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
build_BOM_from_board.cpp
cleanup_item.cpp
convert_drawsegment_list_to_polygon.cpp
cross-probing.cpp
edit.cpp
edit_track_width.cpp

View File

@ -187,9 +187,10 @@ void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle )
case S_ARC:
case S_SEGMENT:
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_End, aRotCentre, aAngle );
RotatePoint( &m_ThirdPoint, aRotCentre, aAngle );
break;
case S_RECT:

View File

@ -109,7 +109,7 @@ public:
* 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.
*/
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; }
void SetType( int aType ) { m_Type = aType; }
@ -200,14 +200,18 @@ public:
* to initialize one point of the cicumference
*/
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
*/
void SetArcEnd( const wxPoint& aArcEndPoint )
{ m_ThirdPoint = aArcEndPoint; }
{
m_ThirdPoint = aArcEndPoint;
}
/** For arcs and circles:
*/

View File

@ -58,6 +58,7 @@ void EDGE_MODULE::SetLocalCoord()
{
m_Start0 = m_Start;
m_End0 = m_End;
m_ThirdPoint0 = m_ThirdPoint;
m_Bezier0_C1 = m_BezierC1;
m_Bezier0_C2 = m_BezierC2;
return;
@ -65,11 +66,13 @@ void EDGE_MODULE::SetLocalCoord()
m_Start0 = m_Start - module->GetPosition();
m_End0 = m_End - module->GetPosition();
m_ThirdPoint0 = m_ThirdPoint - module->GetPosition();
m_Bezier0_C1 = m_BezierC1 - module->GetPosition();
m_Bezier0_C2 = m_BezierC2 - module->GetPosition();
double angle = module->GetOrientation();
RotatePoint( &m_Start0.x, &m_Start0.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_C2.x, &m_Bezier0_C2.y, -angle );
}
@ -81,6 +84,7 @@ void EDGE_MODULE::SetDrawCoord()
m_Start = m_Start0;
m_End = m_End0;
m_ThirdPoint = m_ThirdPoint0;
m_BezierC1 = m_Bezier0_C1;
m_BezierC2 = m_Bezier0_C2;
@ -88,11 +92,13 @@ void EDGE_MODULE::SetDrawCoord()
{
RotatePoint( &m_Start.x, &m_Start.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_BezierC2.x, &m_BezierC2.y, module->GetOrientation() );
m_Start += module->GetPosition();
m_End += module->GetPosition();
m_ThirdPoint += module->GetPosition();
m_BezierC1 += 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 )
{
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_End.x, aCentre.x );
MIRROR( m_ThirdPoint.y, aCentre.x );
MIRROR( m_BezierC1.x, aCentre.x );
MIRROR( m_BezierC2.x, aCentre.x );
MIRROR( m_Start0.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_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_End.y, aCentre.y );
MIRROR( m_ThirdPoint.y, aCentre.y );
MIRROR( m_BezierC1.y, aCentre.y );
MIRROR( m_BezierC2.y, aCentre.y );
MIRROR( m_Start0.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_C2.y, pt.y );
}
@ -272,6 +293,7 @@ void EDGE_MODULE::Move( const wxPoint& aMoveVector )
// This is a footprint shape modification.
m_Start0 += aMoveVector;
m_End0 += aMoveVector;
m_ThirdPoint0 += aMoveVector;
m_Bezier0_C1 += aMoveVector;
m_Bezier0_C2 += aMoveVector;

View File

@ -72,6 +72,8 @@ public:
return false;
}
void SetAngle( double aAngle ) override;
/**
* Move an edge of the footprint.
* This is a footprint shape modification.
@ -111,6 +113,9 @@ public:
void SetEnd0( const wxPoint& aPoint ) { m_End0 = aPoint; }
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; }
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_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_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
* @param aSegList the initial list of drawsegments (only lines, circles and arcs).
* @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 aErrorLocation is the optional position of the error in the outline
*/
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 )
return true;
@ -225,15 +227,12 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
break;
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 center = graphic->GetCenter();
double angle = -graphic->GetAngle();
double radius = graphic->GetRadius();
int steps = GetArcToSegmentCount( radius, ARC_LOW_DEF, angle / 10.0 );
int steps = GetArcToSegmentCount( radius, aTolerance, angle / 10.0 );
wxPoint pt;
for( int step = 1; step<=steps; ++step )
@ -273,10 +272,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
{
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 )
{
xmin = pt;
@ -288,14 +285,14 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
case S_POLYGON:
{
const auto poly = graphic->GetPolyShape();
const SHAPE_POLY_SET poly = graphic->GetPolyShape();
MODULE* module = aSegList[0]->GetParentModule();
double orientation = module ? module->GetOrientation() : 0.0;
VECTOR2I offset = module ? module->GetPosition() : VECTOR2I( 0, 0 );
for( auto iter = poly.CIterate(); iter; iter++ )
{
auto pt = *iter;
VECTOR2I pt = *iter;
RotatePoint( pt, orientation );
pt += offset;
@ -308,6 +305,7 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
}
}
break;
default:
break;
}
@ -358,8 +356,10 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
// Polygon start point. Arbitrarily chosen end of the
// segment and build the poly from here.
wxPoint startPt = wxPoint( graphic->GetEnd() );
prevPt = graphic->GetEnd();
wxPoint startPt = graphic->GetShape() == S_ARC ? graphic->GetArcEnd()
: graphic->GetEnd();
prevPt = startPt;
aPolygons.NewOutline();
aPolygons.Append( prevPt );
@ -374,9 +374,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
{
wxPoint nextPt;
// Use the line segment end point furthest away from
// prevPt as we assume the other end to be ON prevPt or
// very close to it.
// Use the line segment end point furthest away from prevPt as we assume
// the other end to be ON prevPt or very close to it.
if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
nextPt = graphic->GetEnd();
@ -389,9 +388,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
break;
case S_ARC:
// We do not support arcs in polygons, so approximate
// an arc with a series of short lines and put those
// line segments into the !same! PATH.
// We do not support arcs in polygons, so approximate an arc with a series of
// short lines and put those line segments into the !same! PATH.
{
wxPoint pstart = graphic->GetArcStart();
wxPoint pend = graphic->GetArcEnd();
@ -424,9 +422,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
break;
case S_CURVE:
// We do not support Bezier curves in polygons, so approximate
// with a series of short lines and put those
// line segments into the !same! PATH.
// We do not support Bezier curves in polygons, so approximate with a series
// of short lines and put those line segments into the !same! PATH.
{
wxPoint nextPt;
bool reverse = false;
@ -584,13 +581,9 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
// very close to it.
if( close_st( prevPt, graphic->GetStart(), graphic->GetEnd() ) )
{
nextPt = graphic->GetEnd();
}
else
{
nextPt = graphic->GetStart();
}
prevPt = nextPt;
aPolygons.Append( prevPt, -1, hole );
@ -660,8 +653,8 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
}
else
{
for( size_t jj = 0; jj < graphic->GetBezierPoints().size(); jj++ )
aPolygons.Append( graphic->GetBezierPoints()[jj], -1, hole );
for( const wxPoint& pt : graphic->GetBezierPoints())
aPolygons.Append( pt, -1, hole );
}
prevPt = nextPt;
@ -742,7 +735,7 @@ bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SE
return false;
}
if( auto pt = seg1.Get().Intersect( seg2.Get(), true ) )
if( boost::optional<VECTOR2I> pt = seg1.Get().Intersect( seg2.Get(), true ) )
{
if( aErrorLocation )
{

View File

@ -1678,9 +1678,12 @@ void LEGACY_PLUGIN::loadMODULE_EDGE( MODULE* aModule )
width = biuParse( data, &data );
layer = layerParse( data );
dwg->SetAngle( angle );
dwg->m_Start0 = wxPoint( start0_x, start0_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;

View File

@ -163,10 +163,13 @@ void PCB_ARC::AddToModule( MODULE* aModule )
EDGE_MODULE* arc = new EDGE_MODULE( aModule, ( IsCircle() ? S_CIRCLE : S_ARC ) );
aModule->Add( arc );
arc->SetAngle( -m_angle );
arc->m_Start0 = wxPoint( m_positionX, m_positionY );
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->SetLayer( m_KiCadLayer );

View File

@ -2960,6 +2960,8 @@ EDGE_MODULE* PCB_PARSER::parseEDGE_MODULE()
if( token != 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 );
NeedRIGHT();
break;