Cache read arc data for stability
Arcs can be altered by the process of changing from on-disk representation to in-memory representation. Saving back to disk without modifying the arc should not modify the calculated values. This stores a copy of the on-disk representation that is only used to save back to disk in the event that the arc is not modified during editing. Fixes https://gitlab.com/kicad/code/kicad/issues/10442
This commit is contained in:
parent
2200c1319d
commit
cd7141fd10
|
@ -437,6 +437,12 @@ void EDA_SHAPE::SetCenter( const VECTOR2I& aCenter )
|
|||
|
||||
VECTOR2I EDA_SHAPE::GetArcMid() const
|
||||
{
|
||||
// If none of the input data have changed since we loaded the arc,
|
||||
// keep the original mid point data to minimize churn
|
||||
if( m_arcMidData.start == m_start && m_arcMidData.end == m_end
|
||||
&& m_arcMidData.center == m_arcCenter )
|
||||
return m_arcMidData.mid;
|
||||
|
||||
VECTOR2I mid = m_start;
|
||||
RotatePoint( mid, m_arcCenter, -GetArcAngle() / 2.0 );
|
||||
return mid;
|
||||
|
@ -487,19 +493,34 @@ int EDA_SHAPE::GetRadius() const
|
|||
}
|
||||
|
||||
|
||||
void EDA_SHAPE::SetCachedArcData( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd, const VECTOR2I& aCenter )
|
||||
{
|
||||
m_arcMidData.start = aStart;
|
||||
m_arcMidData.end = aEnd;
|
||||
m_arcMidData.center = aCenter;
|
||||
m_arcMidData.mid = aMid;
|
||||
}
|
||||
|
||||
|
||||
void EDA_SHAPE::SetArcGeometry( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd )
|
||||
{
|
||||
m_arcMidData = {};
|
||||
m_start = aStart;
|
||||
m_end = aEnd;
|
||||
m_arcCenter = CalcArcCenter( aStart, aMid, aEnd );
|
||||
VECTOR2I new_mid = GetArcMid();
|
||||
|
||||
m_endsSwapped = false;
|
||||
|
||||
// Watch the ordering here. GetArcMid above needs to be called prior to initializing the
|
||||
// m_arcMidData structure in order to ensure we get the calculated variant, not the cached
|
||||
SetCachedArcData( aStart, aMid, aEnd, m_arcCenter );
|
||||
|
||||
/*
|
||||
* If the input winding doesn't match our internal winding, the calculated midpoint will end
|
||||
* up on the other side of the arc. In this case, we need to flip the start/end points and
|
||||
* flag this change for the system.
|
||||
*/
|
||||
VECTOR2I new_mid = GetArcMid();
|
||||
VECTOR2D dist( new_mid - aMid );
|
||||
VECTOR2D dist2( new_mid - m_arcCenter );
|
||||
|
||||
|
|
|
@ -1000,12 +1000,9 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseArc()
|
|||
}
|
||||
}
|
||||
|
||||
arc->SetStart( startPoint );
|
||||
arc->SetEnd( endPoint );
|
||||
|
||||
if( hasMidPoint )
|
||||
{
|
||||
arc->SetCenter( CalcArcCenter( arc->GetStart(), midPoint, arc->GetEnd() ) );
|
||||
arc->SetArcGeometry( startPoint, midPoint, endPoint);
|
||||
|
||||
#if 1 // This code will be removed if the current code in Eeschema is modified to allow
|
||||
// full support of arcs >= 180 deg without issue.
|
||||
|
@ -1030,6 +1027,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseArc()
|
|||
VECTOR2I new_center = CalcArcCenter( arc->GetStart(), arc->GetEnd(),
|
||||
EDA_ANGLE( 179.5, DEGREES_T ) );
|
||||
arc->SetCenter( new_center );
|
||||
arc->SetCachedArcData( startPoint, midPoint, endPoint, new_center );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1041,9 +1039,8 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseArc()
|
|||
* between LibEdit and PCBNew. Since we now use a common class (EDA_SHAPE) for both we
|
||||
* need to flip one of them. LibEdit drew the short straw.
|
||||
*/
|
||||
VECTOR2I temp = arc->GetStart();
|
||||
arc->SetStart( arc->GetEnd() );
|
||||
arc->SetEnd( temp );
|
||||
arc->SetStart( endPoint );
|
||||
arc->SetEnd( startPoint );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -61,6 +61,15 @@ enum class FILL_T : int
|
|||
};
|
||||
|
||||
|
||||
// Holding struct to keep originating midpoint
|
||||
struct ARC_MID
|
||||
{
|
||||
VECTOR2I mid;
|
||||
VECTOR2I start;
|
||||
VECTOR2I end;
|
||||
VECTOR2I center;
|
||||
};
|
||||
|
||||
class EDA_SHAPE
|
||||
{
|
||||
public:
|
||||
|
@ -193,6 +202,17 @@ public:
|
|||
*/
|
||||
void SetArcGeometry( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd );
|
||||
|
||||
/**
|
||||
* Set the data used for mid point caching. If the controlling points remain constant, then
|
||||
* we keep the midpoint the same as it was when read in. This minimizes VCS churn
|
||||
*
|
||||
* @param aStart Cached start point
|
||||
* @param aMid Cached mid point
|
||||
* @param aEnd Cached end point
|
||||
* @param aCenter Calculated center point using the preceeding three
|
||||
*/
|
||||
void SetCachedArcData( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd, const VECTOR2I& aCenter );
|
||||
|
||||
const std::vector<VECTOR2I>& GetBezierPoints() const { return m_bezierPoints; }
|
||||
|
||||
/**
|
||||
|
@ -314,6 +334,7 @@ protected:
|
|||
VECTOR2I m_end; // Line end point or Circle 3 o'clock point
|
||||
|
||||
VECTOR2I m_arcCenter; // Used only for Arcs: arc end point
|
||||
ARC_MID m_arcMidData; // Used to store originating data
|
||||
|
||||
VECTOR2I m_bezierC1; // Bezier Control Point 1
|
||||
VECTOR2I m_bezierC2; // Bezier Control Point 2
|
||||
|
|
|
@ -178,6 +178,12 @@ void FP_SHAPE::SetCenter0( const VECTOR2I& aCenter )
|
|||
|
||||
VECTOR2I FP_SHAPE::GetArcMid0() const
|
||||
{
|
||||
// If none of the input data have changed since we loaded the arc,
|
||||
// keep the original mid point data to minimize churn
|
||||
if( m_arcMidData_0.start == m_start && m_arcMidData_0.end == m_end
|
||||
&& m_arcMidData_0.center == m_arcCenter )
|
||||
return m_arcMidData_0.mid;
|
||||
|
||||
VECTOR2I mid0 = m_start0;
|
||||
RotatePoint( mid0, m_arcCenter0, -GetArcAngle() / 2.0 );
|
||||
return mid0;
|
||||
|
@ -202,6 +208,11 @@ void FP_SHAPE::SetArcGeometry0( const VECTOR2I& aStart0, const VECTOR2I& aMid0,
|
|||
m_start0 = aStart0;
|
||||
m_end0 = aEnd0;
|
||||
m_arcCenter0 = CalcArcCenter( aStart0, aMid0, aEnd0 );
|
||||
|
||||
m_arcMidData_0.center = m_arcCenter0;
|
||||
m_arcMidData_0.end = m_end0;
|
||||
m_arcMidData_0.mid = aMid0;
|
||||
m_arcMidData_0.start = m_start0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -164,6 +164,8 @@ protected:
|
|||
VECTOR2I m_arcCenter0; ///< Center of arc, relative to footprint origin, orient 0.
|
||||
VECTOR2I m_bezierC1_0; ///< Bezier Control Point 1, relative to footprint origin, orient 0.
|
||||
VECTOR2I m_bezierC2_0; ///< Bezier Control Point 2, relative to footprint origin, orient 0.
|
||||
|
||||
ARC_MID m_arcMidData_0; ///< Originating Arc data, orient 0
|
||||
};
|
||||
|
||||
#endif // FP_SHAPE_H
|
||||
|
|
Loading…
Reference in New Issue