Don't whack original pad shape when converting to custom.
Rectangles and circles convert easily, but a chamfered rectangle (for instance) needs more careful handling.
This commit is contained in:
parent
fe1e835471
commit
b779715996
|
@ -65,7 +65,7 @@ namespace KIGFX
|
||||||
class PAD_CS_PRIMITIVE
|
class PAD_CS_PRIMITIVE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
STROKE_T m_Shape; /// S_SEGMENT, S_ARC, S_CIRCLE, S_POLYGON only (same as DRAWSEGMENT)
|
STROKE_T m_Shape; /// S_SEGMENT, S_RECT, S_ARC, S_CIRCLE, S_POLYGON only (same as DRAWSEGMENT)
|
||||||
int m_Thickness; /// thickness of segment or outline
|
int m_Thickness; /// thickness of segment or outline
|
||||||
/// For filled S_CIRCLE shape, thickness = 0.
|
/// For filled S_CIRCLE shape, thickness = 0.
|
||||||
// if thickness is not = 0 S_CIRCLE shape is a ring
|
// if thickness is not = 0 S_CIRCLE shape is a ring
|
||||||
|
|
|
@ -1538,6 +1538,13 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
|
||||||
FormatInternalUnits( primitive.m_Thickness ).c_str() );
|
FormatInternalUnits( primitive.m_Thickness ).c_str() );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case S_RECT:
|
||||||
|
m_out->Print( nested_level, "(gr_rect (start %s) (end %s) (width %s))",
|
||||||
|
FormatInternalUnits( primitive.m_Start ).c_str(),
|
||||||
|
FormatInternalUnits( primitive.m_End ).c_str(),
|
||||||
|
FormatInternalUnits( primitive.m_Thickness ).c_str() );
|
||||||
|
break;
|
||||||
|
|
||||||
case S_ARC: // Arc with rounded ends
|
case S_ARC: // Arc with rounded ends
|
||||||
m_out->Print( nested_level, "(gr_arc (start %s) (end %s) (angle %s) (width %s))",
|
m_out->Print( nested_level, "(gr_arc (start %s) (end %s) (angle %s) (width %s))",
|
||||||
FormatInternalUnits( primitive.m_Start ).c_str(),
|
FormatInternalUnits( primitive.m_Start ).c_str(),
|
||||||
|
|
|
@ -83,9 +83,7 @@ void PAD_CS_PRIMITIVE::Move( wxPoint aMoveVector )
|
||||||
m_Ctrl2 += aMoveVector;
|
m_Ctrl2 += aMoveVector;
|
||||||
|
|
||||||
for( auto& corner : m_Poly )
|
for( auto& corner : m_Poly )
|
||||||
{
|
|
||||||
corner += aMoveVector;
|
corner += aMoveVector;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,6 +99,25 @@ void PAD_CS_PRIMITIVE::Rotate( const wxPoint& aRotCentre, double aAngle )
|
||||||
RotatePoint( &m_End, aRotCentre, aAngle );
|
RotatePoint( &m_End, aRotCentre, aAngle );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case S_RECT:
|
||||||
|
if( KiROUND( aAngle ) % 900 == 0 )
|
||||||
|
{
|
||||||
|
RotatePoint( &m_Start, aRotCentre, aAngle );
|
||||||
|
RotatePoint( &m_End, aRotCentre, aAngle );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert non-cartesian-rotated rect to a diamond
|
||||||
|
m_Shape = S_POLYGON;
|
||||||
|
|
||||||
|
m_Poly.clear();
|
||||||
|
m_Poly.emplace_back( m_Start );
|
||||||
|
m_Poly.emplace_back( m_End.x, m_Start.y );
|
||||||
|
m_Poly.emplace_back( m_End );
|
||||||
|
m_Poly.emplace_back( m_Start.x, m_End.y );
|
||||||
|
|
||||||
|
KI_FALLTHROUGH;
|
||||||
|
|
||||||
case S_POLYGON:
|
case S_POLYGON:
|
||||||
for( auto& pt : m_Poly )
|
for( auto& pt : m_Poly )
|
||||||
RotatePoint( &pt, aRotCentre, aAngle );
|
RotatePoint( &pt, aRotCentre, aAngle );
|
||||||
|
@ -112,10 +129,8 @@ void PAD_CS_PRIMITIVE::Rotate( const wxPoint& aRotCentre, double aAngle )
|
||||||
RotatePoint( &m_End, aRotCentre, aAngle );
|
RotatePoint( &m_End, aRotCentre, aAngle );
|
||||||
RotatePoint( &m_Ctrl1, aRotCentre, aAngle );
|
RotatePoint( &m_Ctrl1, aRotCentre, aAngle );
|
||||||
RotatePoint( &m_Ctrl2, aRotCentre, aAngle );
|
RotatePoint( &m_Ctrl2, aRotCentre, aAngle );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_RECT:
|
|
||||||
default:
|
default:
|
||||||
// un-handled edge transform
|
// un-handled edge transform
|
||||||
wxASSERT_MSG( false, wxT( "PAD_CS_PRIMITIVE::Rotate not implemented for "
|
wxASSERT_MSG( false, wxT( "PAD_CS_PRIMITIVE::Rotate not implemented for "
|
||||||
|
@ -146,8 +161,8 @@ void D_PAD::AddPrimitivePoly( const SHAPE_POLY_SET& aPoly, int aThickness, bool
|
||||||
AddPrimitivePoly( points, aThickness, aMergePrimitives );
|
AddPrimitivePoly( points, aThickness, aMergePrimitives );
|
||||||
}
|
}
|
||||||
|
|
||||||
void D_PAD::AddPrimitivePoly(
|
void D_PAD::AddPrimitivePoly( const std::vector<wxPoint>& aPoly, int aThickness,
|
||||||
const std::vector<wxPoint>& aPoly, int aThickness, bool aMergePrimitives )
|
bool aMergePrimitives )
|
||||||
{
|
{
|
||||||
PAD_CS_PRIMITIVE shape( S_POLYGON );
|
PAD_CS_PRIMITIVE shape( S_POLYGON );
|
||||||
shape.m_Poly = aPoly;
|
shape.m_Poly = aPoly;
|
||||||
|
@ -159,8 +174,8 @@ void D_PAD::AddPrimitivePoly(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D_PAD::AddPrimitiveSegment(
|
void D_PAD::AddPrimitiveSegment( wxPoint aStart, wxPoint aEnd, int aThickness,
|
||||||
wxPoint aStart, wxPoint aEnd, int aThickness, bool aMergePrimitives )
|
bool aMergePrimitives )
|
||||||
{
|
{
|
||||||
PAD_CS_PRIMITIVE shape( S_SEGMENT );
|
PAD_CS_PRIMITIVE shape( S_SEGMENT );
|
||||||
shape.m_Start = aStart;
|
shape.m_Start = aStart;
|
||||||
|
@ -173,8 +188,8 @@ void D_PAD::AddPrimitiveSegment(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D_PAD::AddPrimitiveArc(
|
void D_PAD::AddPrimitiveArc( wxPoint aCenter, wxPoint aStart, int aArcAngle, int aThickness,
|
||||||
wxPoint aCenter, wxPoint aStart, int aArcAngle, int aThickness, bool aMergePrimitives )
|
bool aMergePrimitives )
|
||||||
{
|
{
|
||||||
PAD_CS_PRIMITIVE shape( S_ARC );
|
PAD_CS_PRIMITIVE shape( S_ARC );
|
||||||
shape.m_Start = aCenter;
|
shape.m_Start = aCenter;
|
||||||
|
@ -189,7 +204,7 @@ void D_PAD::AddPrimitiveArc(
|
||||||
|
|
||||||
|
|
||||||
void D_PAD::AddPrimitiveCurve( wxPoint aStart, wxPoint aEnd, wxPoint aCtrl1, wxPoint aCtrl2,
|
void D_PAD::AddPrimitiveCurve( wxPoint aStart, wxPoint aEnd, wxPoint aCtrl1, wxPoint aCtrl2,
|
||||||
int aThickness, bool aMergePrimitives )
|
int aThickness, bool aMergePrimitives )
|
||||||
{
|
{
|
||||||
PAD_CS_PRIMITIVE shape( S_CURVE );
|
PAD_CS_PRIMITIVE shape( S_CURVE );
|
||||||
shape.m_Start = aStart;
|
shape.m_Start = aStart;
|
||||||
|
@ -204,8 +219,8 @@ void D_PAD::AddPrimitiveCurve( wxPoint aStart, wxPoint aEnd, wxPoint aCtrl1, wxP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D_PAD::AddPrimitiveCircle(
|
void D_PAD::AddPrimitiveCircle( wxPoint aCenter, int aRadius, int aThickness,
|
||||||
wxPoint aCenter, int aRadius, int aThickness, bool aMergePrimitives )
|
bool aMergePrimitives )
|
||||||
{
|
{
|
||||||
PAD_CS_PRIMITIVE shape( S_CIRCLE );
|
PAD_CS_PRIMITIVE shape( S_CIRCLE );
|
||||||
shape.m_Start = aCenter;
|
shape.m_Start = aCenter;
|
||||||
|
@ -253,10 +268,8 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET aux_polyset;
|
SHAPE_POLY_SET aux_polyset;
|
||||||
|
|
||||||
for( unsigned cnt = 0; cnt < m_basicShapes.size(); ++cnt )
|
for( PAD_CS_PRIMITIVE& bshape : m_basicShapes )
|
||||||
{
|
{
|
||||||
const PAD_CS_PRIMITIVE& bshape = m_basicShapes[cnt];
|
|
||||||
|
|
||||||
switch( bshape.m_Shape )
|
switch( bshape.m_Shape )
|
||||||
{
|
{
|
||||||
case S_CURVE:
|
case S_CURVE:
|
||||||
|
@ -276,32 +289,42 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError )
|
||||||
|
|
||||||
case S_SEGMENT: // usual segment : line with rounded ends
|
case S_SEGMENT: // usual segment : line with rounded ends
|
||||||
{
|
{
|
||||||
TransformSegmentToPolygon(
|
TransformSegmentToPolygon( aux_polyset, bshape.m_Start, bshape.m_End, aError,
|
||||||
aux_polyset, bshape.m_Start, bshape.m_End, aError, bshape.m_Thickness );
|
bshape.m_Thickness );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case S_ARC: // Arc with rounded ends
|
case S_ARC: // Arc with rounded ends
|
||||||
{
|
{
|
||||||
TransformArcToPolygon( aux_polyset, bshape.m_Start, bshape.m_End, bshape.m_ArcAngle,
|
TransformArcToPolygon( aux_polyset, bshape.m_Start, bshape.m_End, bshape.m_ArcAngle,
|
||||||
aError, bshape.m_Thickness );
|
aError, bshape.m_Thickness );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case S_CIRCLE: // ring or circle
|
case S_CIRCLE: // ring or circle
|
||||||
{
|
{
|
||||||
if( bshape.m_Thickness ) // ring
|
if( bshape.m_Thickness ) // ring
|
||||||
TransformRingToPolygon(
|
TransformRingToPolygon( aux_polyset, bshape.m_Start, bshape.m_Radius, aError,
|
||||||
aux_polyset, bshape.m_Start, bshape.m_Radius, aError, bshape.m_Thickness );
|
bshape.m_Thickness );
|
||||||
else // Filled circle
|
else // Filled circle
|
||||||
TransformCircleToPolygon( aux_polyset, bshape.m_Start, bshape.m_Radius, aError );
|
TransformCircleToPolygon( aux_polyset, bshape.m_Start, bshape.m_Radius, aError );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case S_RECT:
|
||||||
|
bshape.m_Poly.clear();
|
||||||
|
bshape.m_Poly.emplace_back( bshape.m_Start );
|
||||||
|
bshape.m_Poly.emplace_back( bshape.m_End.x, bshape.m_Start.y );
|
||||||
|
bshape.m_Poly.emplace_back( bshape.m_End );
|
||||||
|
bshape.m_Poly.emplace_back( bshape.m_Start.x, bshape.m_End.y );
|
||||||
|
|
||||||
|
KI_FALLTHROUGH;
|
||||||
|
|
||||||
case S_POLYGON: // polygon
|
case S_POLYGON: // polygon
|
||||||
|
{
|
||||||
if( bshape.m_Poly.size() < 2 )
|
if( bshape.m_Poly.size() < 2 )
|
||||||
break; // Malformed polygon.
|
break; // Malformed polygon.
|
||||||
{
|
|
||||||
// Insert the polygon:
|
// Insert the polygon:
|
||||||
const std::vector< wxPoint>& poly = bshape.m_Poly;
|
const std::vector< wxPoint>& poly = bshape.m_Poly;
|
||||||
aux_polyset.NewOutline();
|
aux_polyset.NewOutline();
|
||||||
|
@ -311,24 +334,29 @@ bool D_PAD::buildCustomPadPolygon( SHAPE_POLY_SET* aMergedPolygon, int aError )
|
||||||
SHAPE_POLY_SET polyset;
|
SHAPE_POLY_SET polyset;
|
||||||
polyset.NewOutline();
|
polyset.NewOutline();
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < poly.size(); ii++ )
|
for( const wxPoint& pt : poly )
|
||||||
{
|
polyset.Append( pt.x, pt.y );
|
||||||
polyset.Append( poly[ii].x, poly[ii].y );
|
|
||||||
}
|
|
||||||
|
|
||||||
int numSegs = std::max(
|
int numSegs = std::max( GetArcToSegmentCount( bshape.m_Thickness / 2, aError, 360.0 ), 6 );
|
||||||
GetArcToSegmentCount( bshape.m_Thickness / 2, aError, 360.0 ), 6 );
|
|
||||||
polyset.Inflate( bshape.m_Thickness / 2, numSegs );
|
polyset.Inflate( bshape.m_Thickness / 2, numSegs );
|
||||||
|
|
||||||
aux_polyset.Append( polyset );
|
aux_polyset.Append( polyset );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
for( unsigned ii = 0; ii < poly.size(); ii++ )
|
{
|
||||||
aux_polyset.Append( poly[ii].x, poly[ii].y );
|
for( const wxPoint& pt : poly )
|
||||||
|
aux_polyset.Append( pt.x, pt.y );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( bshape.m_Shape == S_RECT )
|
||||||
|
bshape.m_Poly.clear();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
// un-handled primitive
|
||||||
|
wxASSERT_MSG( false, wxT( "D_PAD::buildCustomPadPolygon not implemented for "
|
||||||
|
+ BOARD_ITEM::ShowShape( bshape.m_Shape ) ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -390,8 +418,9 @@ bool D_PAD::MergePrimitivesAsPolygon( SHAPE_POLY_SET* aMergedPolygon )
|
||||||
return aMergedPolygon->OutlineCount() <= 1;
|
return aMergedPolygon->OutlineCount() <= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D_PAD::CustomShapeAsPolygonToBoardPosition( SHAPE_POLY_SET * aMergedPolygon,
|
void D_PAD::CustomShapeAsPolygonToBoardPosition( SHAPE_POLY_SET * aMergedPolygon,
|
||||||
wxPoint aPosition, double aRotation ) const
|
wxPoint aPosition, double aRotation ) const
|
||||||
{
|
{
|
||||||
if( aMergedPolygon->OutlineCount() == 0 )
|
if( aMergedPolygon->OutlineCount() == 0 )
|
||||||
return;
|
return;
|
||||||
|
@ -402,6 +431,7 @@ void D_PAD::CustomShapeAsPolygonToBoardPosition( SHAPE_POLY_SET * aMergedPolygon
|
||||||
aMergedPolygon->Move( VECTOR2I( aPosition ) );
|
aMergedPolygon->Move( VECTOR2I( aPosition ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos )
|
bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos )
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET poly;
|
SHAPE_POLY_SET poly;
|
||||||
|
@ -430,9 +460,9 @@ bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos )
|
||||||
stepsX = std::max(minSteps, std::min( maxSteps, stepsX ) );
|
stepsX = std::max(minSteps, std::min( maxSteps, stepsX ) );
|
||||||
stepsY = std::max(minSteps, std::min( maxSteps, stepsY ) );
|
stepsY = std::max(minSteps, std::min( maxSteps, stepsY ) );
|
||||||
|
|
||||||
auto center = bbox.Centre();
|
VECTOR2I center = bbox.Centre();
|
||||||
|
|
||||||
auto minDist = std::numeric_limits<int64_t>::max();
|
int64_t minDist = std::numeric_limits<int64_t>::max();
|
||||||
int64_t minDistEdge;
|
int64_t minDistEdge;
|
||||||
|
|
||||||
if( GetAnchorPadShape() == PAD_SHAPE_CIRCLE )
|
if( GetAnchorPadShape() == PAD_SHAPE_CIRCLE )
|
||||||
|
@ -446,22 +476,23 @@ bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos )
|
||||||
|
|
||||||
OPT<VECTOR2I> bestAnchor( []()->OPT<VECTOR2I> { return NULLOPT; }() );
|
OPT<VECTOR2I> bestAnchor( []()->OPT<VECTOR2I> { return NULLOPT; }() );
|
||||||
|
|
||||||
for ( int y = 0; y < stepsY ; y++ )
|
for( int y = 0; y < stepsY ; y++ )
|
||||||
{
|
{
|
||||||
for ( int x = 0; x < stepsX; x++ )
|
for( int x = 0; x < stepsX; x++ )
|
||||||
{
|
{
|
||||||
VECTOR2I p = bbox.GetPosition();
|
VECTOR2I p = bbox.GetPosition();
|
||||||
p.x += rescale( x, bbox.GetWidth(), (stepsX - 1) );
|
p.x += rescale( x, bbox.GetWidth(), (stepsX - 1) );
|
||||||
p.y += rescale( y, bbox.GetHeight(), (stepsY - 1) );
|
p.y += rescale( y, bbox.GetHeight(), (stepsY - 1) );
|
||||||
|
|
||||||
if ( poly.Contains(p) )
|
if( poly.Contains(p) )
|
||||||
{
|
{
|
||||||
|
|
||||||
auto dist = (center - p).EuclideanNorm();
|
int dist = (center - p).EuclideanNorm();
|
||||||
auto distEdge = poly.COutline(0).Distance( p, true );
|
int distEdge = poly.COutline(0).Distance( p, true );
|
||||||
if ( distEdge >= minDistEdge )
|
|
||||||
|
if( distEdge >= minDistEdge )
|
||||||
{
|
{
|
||||||
if ( dist < minDist )
|
if( dist < minDist )
|
||||||
{
|
{
|
||||||
bestAnchor = p;
|
bestAnchor = p;
|
||||||
minDist = dist;
|
minDist = dist;
|
||||||
|
@ -471,7 +502,7 @@ bool D_PAD::GetBestAnchorPosition( VECTOR2I& aPos )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bestAnchor )
|
if( bestAnchor )
|
||||||
{
|
{
|
||||||
aPos = *bestAnchor;
|
aPos = *bestAnchor;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -466,7 +466,7 @@ int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
||||||
shape.m_Ctrl2 = em->GetBezControl2();
|
shape.m_Ctrl2 = em->GetBezControl2();
|
||||||
shape.m_Poly = em->BuildPolyPointsList();
|
shape.m_Poly = em->BuildPolyPointsList();
|
||||||
|
|
||||||
shapes.push_back(shape);
|
shapes.push_back( shape );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -501,19 +501,49 @@ int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double refOrientation = 0.0;
|
double deltaAngle = 0.0;
|
||||||
|
|
||||||
if( refPad )
|
if( refPad && refPad->GetShape() == PAD_SHAPE_CUSTOM )
|
||||||
|
{
|
||||||
|
// it's already a pad anchor
|
||||||
|
}
|
||||||
|
else if( refPad )
|
||||||
{
|
{
|
||||||
pad.reset( static_cast<D_PAD*>( refPad->Clone() ) );
|
pad.reset( static_cast<D_PAD*>( refPad->Clone() ) );
|
||||||
|
|
||||||
if( refPad->GetShape() == PAD_SHAPE_RECT )
|
if( refPad->GetShape() == PAD_SHAPE_RECT )
|
||||||
|
{
|
||||||
pad->SetAnchorPadShape( PAD_SHAPE_RECT );
|
pad->SetAnchorPadShape( PAD_SHAPE_RECT );
|
||||||
|
deltaAngle = 0.0;
|
||||||
|
}
|
||||||
|
else if( refPad->GetShape() == PAD_SHAPE_CIRCLE )
|
||||||
|
{
|
||||||
|
pad->SetAnchorPadShape( PAD_SHAPE_CIRCLE );
|
||||||
|
deltaAngle = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Create a new minimally-sized circular anchor and convert existing pad
|
||||||
|
// to a polygon primitive
|
||||||
|
pad->SetAnchorPadShape( PAD_SHAPE_CIRCLE );
|
||||||
|
int r = refPad->GetDrillSize().x + Millimeter2iu( 0.2 );
|
||||||
|
pad->SetSize( wxSize( r, r ) );
|
||||||
|
pad->SetOffset( wxPoint( 0, 0 ) );
|
||||||
|
|
||||||
// ignore the pad offset for the moment. Makes more trouble than it's worth.
|
SHAPE_POLY_SET existingOutline;
|
||||||
pad->SetOffset( wxPoint( 0, 0 ) );
|
int maxError = board()->GetDesignSettings().m_MaxError;
|
||||||
refOrientation = pad->GetOrientation();
|
refPad->TransformShapeWithClearanceToPolygon( existingOutline, 0, maxError );
|
||||||
pad->SetOrientation( 0.0 );
|
|
||||||
|
PAD_CS_PRIMITIVE shape( S_POLYGON );
|
||||||
|
|
||||||
|
for( auto ii = existingOutline.Iterate(); ii; ii++ )
|
||||||
|
shape.m_Poly.emplace_back( ii->x, ii->y );
|
||||||
|
|
||||||
|
shapes.push_back( shape );
|
||||||
|
|
||||||
|
deltaAngle = refPad->GetOrientation();
|
||||||
|
pad->SetOrientation( 0.0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -562,7 +592,7 @@ int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
||||||
for( auto& shape : shapes )
|
for( auto& shape : shapes )
|
||||||
{
|
{
|
||||||
shape.Move( wxPoint( -anchor->x, -anchor->y ) );
|
shape.Move( wxPoint( -anchor->x, -anchor->y ) );
|
||||||
shape.Rotate( wxPoint( 0, 0 ), -refOrientation );
|
shape.Rotate( wxPoint( 0, 0 ), -deltaAngle );
|
||||||
}
|
}
|
||||||
|
|
||||||
pad->SetPosition( wxPoint( anchor->x, anchor->y ) );
|
pad->SetPosition( wxPoint( anchor->x, anchor->y ) );
|
||||||
|
@ -570,7 +600,7 @@ int FOOTPRINT_EDITOR_TOOLS::CreatePadFromShapes( const TOOL_EVENT& aEvent )
|
||||||
pad->ClearFlags();
|
pad->ClearFlags();
|
||||||
|
|
||||||
bool result = pad->MergePrimitivesAsPolygon();
|
bool result = pad->MergePrimitivesAsPolygon();
|
||||||
pad->Rotate( wxPoint( anchor->x, anchor->y ), refOrientation );
|
pad->Rotate( wxPoint( anchor->x, anchor->y ), deltaAngle );
|
||||||
|
|
||||||
if( !result )
|
if( !result )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue