Finish arc implementation of m_ThirdPoint for EDGE_MODULEs.

Fixes https://gitlab.com/kicad/code/kicad/issues/5191
This commit is contained in:
Jeff Young 2020-08-15 16:42:18 +01:00
parent 7342532276
commit 6c74658a98
9 changed files with 90 additions and 55 deletions

View File

@ -262,6 +262,7 @@ set( PCBNEW_CLASS_SRCS
array_pad_name_provider.cpp array_pad_name_provider.cpp
build_BOM_from_board.cpp build_BOM_from_board.cpp
cleanup_item.cpp cleanup_item.cpp
convert_drawsegment_list_to_polygon.cpp
cross-probing.cpp cross-probing.cpp
edit.cpp edit.cpp
edit_track_width.cpp edit_track_width.cpp

View File

@ -187,9 +187,10 @@ void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle )
case S_ARC: case S_ARC:
case S_SEGMENT: case S_SEGMENT:
case S_CIRCLE: case S_CIRCLE:
// these can all be done by just rotating the start and end points // these can all be done by just rotating the constituent points
RotatePoint( &m_Start, aRotCentre, aAngle); RotatePoint( &m_Start, aRotCentre, aAngle );
RotatePoint( &m_End, aRotCentre, aAngle); RotatePoint( &m_End, aRotCentre, aAngle );
RotatePoint( &m_ThirdPoint, aRotCentre, aAngle );
break; break;
case S_RECT: case S_RECT:

View File

@ -109,7 +109,7 @@ public:
* sets the angle for arcs, and normalizes it within the range 0 - 360 degrees. * sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
* @param aAngle is tenths of degrees, but will soon be degrees. * @param aAngle is tenths of degrees, but will soon be degrees.
*/ */
void SetAngle( double aAngle ); // encapsulates the transition to degrees virtual void SetAngle( double aAngle ); // encapsulates the transition to degrees
double GetAngle() const { return m_Angle; } double GetAngle() const { return m_Angle; }
void SetType( int aType ) { m_Type = aType; } void SetType( int aType ) { m_Type = aType; }
@ -200,14 +200,18 @@ public:
* to initialize one point of the cicumference * to initialize one point of the cicumference
*/ */
void SetArcStart( const wxPoint& aArcStartPoint ) void SetArcStart( const wxPoint& aArcStartPoint )
{ m_End = aArcStartPoint; } {
m_End = aArcStartPoint;
}
/** /**
* Initialize the start arc point. can be used for circles * Initialize the end arc point. can be used for circles
* to initialize one point of the cicumference * to initialize one point of the cicumference
*/ */
void SetArcEnd( const wxPoint& aArcEndPoint ) void SetArcEnd( const wxPoint& aArcEndPoint )
{ m_ThirdPoint = aArcEndPoint; } {
m_ThirdPoint = aArcEndPoint;
}
/** For arcs and circles: /** For arcs and circles:
*/ */

View File

@ -58,6 +58,7 @@ void EDGE_MODULE::SetLocalCoord()
{ {
m_Start0 = m_Start; m_Start0 = m_Start;
m_End0 = m_End; m_End0 = m_End;
m_ThirdPoint0 = m_ThirdPoint;
m_Bezier0_C1 = m_BezierC1; m_Bezier0_C1 = m_BezierC1;
m_Bezier0_C2 = m_BezierC2; m_Bezier0_C2 = m_BezierC2;
return; return;
@ -65,11 +66,13 @@ void EDGE_MODULE::SetLocalCoord()
m_Start0 = m_Start - module->GetPosition(); m_Start0 = m_Start - module->GetPosition();
m_End0 = m_End - module->GetPosition(); m_End0 = m_End - module->GetPosition();
m_ThirdPoint0 = m_ThirdPoint - module->GetPosition();
m_Bezier0_C1 = m_BezierC1 - module->GetPosition(); m_Bezier0_C1 = m_BezierC1 - module->GetPosition();
m_Bezier0_C2 = m_BezierC2 - module->GetPosition(); m_Bezier0_C2 = m_BezierC2 - module->GetPosition();
double angle = module->GetOrientation(); double angle = module->GetOrientation();
RotatePoint( &m_Start0.x, &m_Start0.y, -angle ); RotatePoint( &m_Start0.x, &m_Start0.y, -angle );
RotatePoint( &m_End0.x, &m_End0.y, -angle ); RotatePoint( &m_End0.x, &m_End0.y, -angle );
RotatePoint( &m_ThirdPoint0.x, &m_ThirdPoint0.y, -angle );
RotatePoint( &m_Bezier0_C1.x, &m_Bezier0_C1.y, -angle ); RotatePoint( &m_Bezier0_C1.x, &m_Bezier0_C1.y, -angle );
RotatePoint( &m_Bezier0_C2.x, &m_Bezier0_C2.y, -angle ); RotatePoint( &m_Bezier0_C2.x, &m_Bezier0_C2.y, -angle );
} }
@ -81,6 +84,7 @@ void EDGE_MODULE::SetDrawCoord()
m_Start = m_Start0; m_Start = m_Start0;
m_End = m_End0; m_End = m_End0;
m_ThirdPoint = m_ThirdPoint0;
m_BezierC1 = m_Bezier0_C1; m_BezierC1 = m_Bezier0_C1;
m_BezierC2 = m_Bezier0_C2; m_BezierC2 = m_Bezier0_C2;
@ -88,11 +92,13 @@ void EDGE_MODULE::SetDrawCoord()
{ {
RotatePoint( &m_Start.x, &m_Start.y, module->GetOrientation() ); RotatePoint( &m_Start.x, &m_Start.y, module->GetOrientation() );
RotatePoint( &m_End.x, &m_End.y, module->GetOrientation() ); RotatePoint( &m_End.x, &m_End.y, module->GetOrientation() );
RotatePoint( &m_ThirdPoint.x, &m_ThirdPoint.y, module->GetOrientation() );
RotatePoint( &m_BezierC1.x, &m_BezierC1.y, module->GetOrientation() ); RotatePoint( &m_BezierC1.x, &m_BezierC1.y, module->GetOrientation() );
RotatePoint( &m_BezierC2.x, &m_BezierC2.y, module->GetOrientation() ); RotatePoint( &m_BezierC2.x, &m_BezierC2.y, module->GetOrientation() );
m_Start += module->GetPosition(); m_Start += module->GetPosition();
m_End += module->GetPosition(); m_End += module->GetPosition();
m_ThirdPoint += module->GetPosition();
m_BezierC1 += module->GetPosition(); m_BezierC1 += module->GetPosition();
m_BezierC2 += module->GetPosition(); m_BezierC2 += module->GetPosition();
} }
@ -144,6 +150,17 @@ EDA_ITEM* EDGE_MODULE::Clone() const
} }
void EDGE_MODULE::SetAngle( double aAngle )
{
// Mark as depreciated.
// m_Angle does not define the arc anymore
// m_Angle must be >= -360 and <= +360 degrees
m_Angle = NormalizeAngle360Max( aAngle );
m_ThirdPoint0 = m_End0;
RotatePoint( &m_ThirdPoint0, m_Start0, -m_Angle );
}
void EDGE_MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight ) void EDGE_MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
{ {
wxPoint pt( 0, 0 ); wxPoint pt( 0, 0 );
@ -166,10 +183,12 @@ void EDGE_MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
{ {
MIRROR( m_Start.x, aCentre.x ); MIRROR( m_Start.x, aCentre.x );
MIRROR( m_End.x, aCentre.x ); MIRROR( m_End.x, aCentre.x );
MIRROR( m_ThirdPoint.y, aCentre.x );
MIRROR( m_BezierC1.x, aCentre.x ); MIRROR( m_BezierC1.x, aCentre.x );
MIRROR( m_BezierC2.x, aCentre.x ); MIRROR( m_BezierC2.x, aCentre.x );
MIRROR( m_Start0.x, pt.x ); MIRROR( m_Start0.x, pt.x );
MIRROR( m_End0.x, pt.x ); MIRROR( m_End0.x, pt.x );
MIRROR( m_ThirdPoint0.x, pt.x );
MIRROR( m_Bezier0_C1.x, pt.x ); MIRROR( m_Bezier0_C1.x, pt.x );
MIRROR( m_Bezier0_C2.x, pt.x ); MIRROR( m_Bezier0_C2.x, pt.x );
} }
@ -177,10 +196,12 @@ void EDGE_MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
{ {
MIRROR( m_Start.y, aCentre.y ); MIRROR( m_Start.y, aCentre.y );
MIRROR( m_End.y, aCentre.y ); MIRROR( m_End.y, aCentre.y );
MIRROR( m_ThirdPoint.y, aCentre.y );
MIRROR( m_BezierC1.y, aCentre.y ); MIRROR( m_BezierC1.y, aCentre.y );
MIRROR( m_BezierC2.y, aCentre.y ); MIRROR( m_BezierC2.y, aCentre.y );
MIRROR( m_Start0.y, pt.y ); MIRROR( m_Start0.y, pt.y );
MIRROR( m_End0.y, pt.y ); MIRROR( m_End0.y, pt.y );
MIRROR( m_ThirdPoint0.y, pt.y );
MIRROR( m_Bezier0_C1.y, pt.y ); MIRROR( m_Bezier0_C1.y, pt.y );
MIRROR( m_Bezier0_C2.y, pt.y ); MIRROR( m_Bezier0_C2.y, pt.y );
} }
@ -272,6 +293,7 @@ void EDGE_MODULE::Move( const wxPoint& aMoveVector )
// This is a footprint shape modification. // This is a footprint shape modification.
m_Start0 += aMoveVector; m_Start0 += aMoveVector;
m_End0 += aMoveVector; m_End0 += aMoveVector;
m_ThirdPoint0 += aMoveVector;
m_Bezier0_C1 += aMoveVector; m_Bezier0_C1 += aMoveVector;
m_Bezier0_C2 += aMoveVector; m_Bezier0_C2 += aMoveVector;

View File

@ -72,6 +72,8 @@ public:
return false; return false;
} }
void SetAngle( double aAngle ) override;
/** /**
* Move an edge of the footprint. * Move an edge of the footprint.
* This is a footprint shape modification. * This is a footprint shape modification.
@ -111,6 +113,9 @@ public:
void SetEnd0( const wxPoint& aPoint ) { m_End0 = aPoint; } void SetEnd0( const wxPoint& aPoint ) { m_End0 = aPoint; }
const wxPoint& GetEnd0() const { return m_End0; } const wxPoint& GetEnd0() const { return m_End0; }
void SetThirdPoint0( const wxPoint& aPoint ){ m_ThirdPoint0 = aPoint; }
const wxPoint& GetThirdPoint0() const { return m_ThirdPoint0; }
void SetBezier0_C1( const wxPoint& aPoint ) { m_Bezier0_C1 = aPoint; } void SetBezier0_C1( const wxPoint& aPoint ) { m_Bezier0_C1 = aPoint; }
const wxPoint& GetBezier0_C1() const { return m_Bezier0_C1; } const wxPoint& GetBezier0_C1() const { return m_Bezier0_C1; }
@ -151,6 +156,7 @@ public:
wxPoint m_Start0; ///< Start point or center, relative to module origin, orient 0. wxPoint m_Start0; ///< Start point or center, relative to module origin, orient 0.
wxPoint m_End0; ///< End point, relative to module origin, orient 0. wxPoint m_End0; ///< End point, relative to module origin, orient 0.
wxPoint m_ThirdPoint0; ///< End point for an arc.
wxPoint m_Bezier0_C1; ///< Bezier Control Point 1, relative to module origin, orient 0. wxPoint m_Bezier0_C1; ///< Bezier Control Point 1, relative to module origin, orient 0.
wxPoint m_Bezier0_C2; ///< Bezier Control Point 2, relative to module origin, orient 0. wxPoint m_Bezier0_C2; ///< Bezier Control Point 2, relative to module origin, orient 0.
}; };

View File

@ -178,12 +178,14 @@ static DRAWSEGMENT* findPoint( const wxPoint& aPoint, std::vector< DRAWSEGMENT*
* These closed inner outlines are considered as holes in the main outline * These closed inner outlines are considered as holes in the main outline
* @param aSegList the initial list of drawsegments (only lines, circles and arcs). * @param aSegList the initial list of drawsegments (only lines, circles and arcs).
* @param aPolygons will contain the complex polygon. * @param aPolygons will contain the complex polygon.
* @param aTolerance is the max distance between points that is still accepted as connected (internal units) * @param aTolerance is the max distance between points that is still accepted as connected
* (internal units)
* @param aErrorText is a wxString to return error message. * @param aErrorText is a wxString to return error message.
* @param aErrorLocation is the optional position of the error in the outline * @param aErrorLocation is the optional position of the error in the outline
*/ */
bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons, bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons,
wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation ) wxString* aErrorText, unsigned int aTolerance,
wxPoint* aErrorLocation )
{ {
if( aSegList.size() == 0 ) if( aSegList.size() == 0 )
return true; return true;
@ -225,15 +227,12 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
break; break;
case S_ARC: case S_ARC:
// Freerouter does not yet understand arcs, so approximate
// an arc with a series of short lines and put those
// line segments into the !same! PATH.
{ {
wxPoint pstart = graphic->GetArcStart(); wxPoint pstart = graphic->GetArcStart();
wxPoint center = graphic->GetCenter(); wxPoint center = graphic->GetCenter();
double angle = -graphic->GetAngle(); double angle = -graphic->GetAngle();
double radius = graphic->GetRadius(); double radius = graphic->GetRadius();
int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 ); int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
wxPoint pt; wxPoint pt;
for( int step = 1; step<=steps; ++step ) for( int step = 1; step<=steps; ++step )
@ -273,10 +272,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
{ {
graphic->RebuildBezierToSegmentsPointsList( graphic->GetWidth() ); graphic->RebuildBezierToSegmentsPointsList( graphic->GetWidth() );
for( unsigned int jj = 0; jj < graphic->GetBezierPoints().size(); jj++ ) for( const wxPoint& pt : graphic->GetBezierPoints())
{ {
wxPoint pt = graphic->GetBezierPoints()[jj];
if( pt.x < xmin.x ) if( pt.x < xmin.x )
{ {
xmin = pt; xmin = pt;
@ -288,14 +285,14 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
case S_POLYGON: case S_POLYGON:
{ {
const auto poly = graphic->GetPolyShape(); const SHAPE_POLY_SET poly = graphic->GetPolyShape();
MODULE* module = aSegList[0]->GetParentModule(); MODULE* module = aSegList[0]->GetParentModule();
double orientation = module ? module->GetOrientation() : 0.0; double orientation = module ? module->GetOrientation() : 0.0;
VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 ); VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
for( auto iter = poly.CIterate(); iter; iter++ ) for( auto iter = poly.CIterate(); iter; iter++ )
{ {
auto pt = *iter; VECTOR2I pt = *iter;
RotatePoint( pt, orientation ); RotatePoint( pt, orientation );
pt += offset; pt += offset;
@ -308,6 +305,7 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
} }
} }
break; break;
default: default:
break; break;
} }
@ -358,8 +356,10 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
// Polygon start point. Arbitrarily chosen end of the // Polygon start point. Arbitrarily chosen end of the
// segment and build the poly from here. // segment and build the poly from here.
wxPoint startPt = wxPoint( graphic->GetEnd() ); wxPoint startPt = graphic->GetShape() == S_ARC ? graphic->GetArcEnd()
prevPt = graphic->GetEnd(); : graphic->GetEnd();
prevPt = startPt;
aPolygons.NewOutline(); aPolygons.NewOutline();
aPolygons.Append( prevPt ); aPolygons.Append( prevPt );
@ -374,9 +374,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
{ {
wxPoint nextPt; wxPoint nextPt;
// Use the line segment end point furthest away from // Use the line segment end point furthest away from prevPt as we assume
// prevPt as we assume the other end to be ON prevPt or // the other end to be ON prevPt or very close to it.
// very close to it.
if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) ) if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
nextPt = graphic->GetEnd(); nextPt = graphic->GetEnd();
@ -389,9 +388,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
break; break;
case S_ARC: case S_ARC:
// We do not support arcs in polygons, so approximate // We do not support arcs in polygons, so approximate an arc with a series of
// an arc with a series of short lines and put those // short lines and put those line segments into the !same! PATH.
// line segments into the !same! PATH.
{ {
wxPoint pstart = graphic->GetArcStart(); wxPoint pstart = graphic->GetArcStart();
wxPoint pend = graphic->GetArcEnd(); wxPoint pend = graphic->GetArcEnd();
@ -424,9 +422,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
break; break;
case S_CURVE: case S_CURVE:
// We do not support Bezier curves in polygons, so approximate // We do not support Bezier curves in polygons, so approximate with a series
// with a series of short lines and put those // of short lines and put those line segments into the !same! PATH.
// line segments into the !same! PATH.
{ {
wxPoint nextPt; wxPoint nextPt;
bool reverse = false; bool reverse = false;
@ -584,13 +581,9 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
// very close to it. // very close to it.
if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) ) if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
{
nextPt = graphic->GetEnd(); nextPt = graphic->GetEnd();
}
else else
{
nextPt = graphic->GetStart(); nextPt = graphic->GetStart();
}
prevPt = nextPt; prevPt = nextPt;
aPolygons.Append( prevPt, -1, hole ); aPolygons.Append( prevPt, -1, hole );
@ -660,8 +653,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
} }
else else
{ {
for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ ) for( const wxPoint& pt : graphic->GetBezierPoints())
aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole ); aPolygons.Append( pt, -1, hole );
} }
prevPt = nextPt; prevPt = nextPt;
@ -742,7 +735,7 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
return false; return false;
} }
if( auto pt = seg1.Get().Intersect( seg2.Get(), true ) ) if( boost::optional<VECTOR2I> pt = seg1.Get().Intersect( seg2.Get(), true ) )
{ {
if( aErrorLocation ) if( aErrorLocation )
{ {

View File

@ -1678,9 +1678,12 @@ void LEGACY_PLUGIN::loadMODULE_EDGE( MODULE* aModule )
width = biuParse( data, &data ); width = biuParse( data, &data );
layer = layerParse( data ); layer = layerParse( data );
dwg->SetAngle( angle );
dwg->m_Start0 = wxPoint( start0_x, start0_y ); dwg->m_Start0 = wxPoint( start0_x, start0_y );
dwg->m_End0 = wxPoint( end0_x, end0_y ); dwg->m_End0 = wxPoint( end0_x, end0_y );
// Setting angle will set m_ThirdPoint0, so must be done after setting
// m_Start0 and m_End0
dwg->SetAngle( angle );
} }
break; break;

View File

@ -163,10 +163,13 @@ void PCB_ARC::AddToModule( MODULE* aModule )
EDGE_MODULE* arc = new EDGE_MODULE( aModule, ( IsCircle() ? S_CIRCLE : S_ARC ) ); EDGE_MODULE* arc = new EDGE_MODULE( aModule, ( IsCircle() ? S_CIRCLE : S_ARC ) );
aModule->Add( arc ); aModule->Add( arc );
arc->SetAngle( -m_angle );
arc->m_Start0 = wxPoint( m_positionX, m_positionY ); arc->m_Start0 = wxPoint( m_positionX, m_positionY );
arc->m_End0 = wxPoint( m_startX, m_startY ); arc->m_End0 = wxPoint( m_startX, m_startY );
// Setting angle will set m_ThirdPoint0, so must be done after setting
// m_Start0 and m_End0
arc->SetAngle( -m_angle );
arc->SetWidth( m_width ); arc->SetWidth( m_width );
arc->SetLayer( m_KiCadLayer ); arc->SetLayer( m_KiCadLayer );

View File

@ -2960,6 +2960,8 @@ EDGE_MODULE* PCB_PARSER::parseEDGE_MODULE()
if( token != T_angle ) if( token != T_angle )
Expecting( T_angle ); Expecting( T_angle );
// Setting angle will set m_ThirdPoint0, so must be done after setting
// m_Start0 and m_End0
segment->SetAngle( parseDouble( "segment angle" ) * 10.0 ); segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
NeedRIGHT(); NeedRIGHT();
break; break;