fix PAD::TransformShapeWithClearanceToPolygon() incorrect calculation in some cases.

For round rect pads, when the arc error was OUTSIDE, the shape was too big and creates
bad shape for chamfered round rect pads.
For chamfered pads, when the clearance value was not 0, the chamfer was not at the
right place.
This commit is contained in:
jean-pierre charras 2020-11-14 08:50:58 +01:00
parent b996c0d2f5
commit 7265f84358
2 changed files with 73 additions and 15 deletions

View File

@ -192,6 +192,8 @@ void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPo
void TransformRoundRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const wxSize& aSize,
int aCornerRadius, int aError, ERROR_LOC aErrorLoc )
{
SHAPE_POLY_SET outline;
wxPoint centers[4];
wxSize size( aSize / 2 );
@ -228,26 +230,51 @@ void TransformRoundRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const wxSize& a
wxPoint pt( -radius, 0 );
RotatePoint( &pt, angle );
pt += aCenter;
aCornerBuffer.Append( pt.x, pt.y );
outline.Append( pt.x, pt.y );
}
};
aCornerBuffer.NewOutline();
outline.NewOutline();
aCornerBuffer.Append( centers[0] + wxPoint( -radius, 0 ) );
outline.Append( centers[0] + wxPoint( -radius, 0 ) );
genArc( centers[0], 0, 900 );
aCornerBuffer.Append( centers[0] + wxPoint( 0, radius ) );
aCornerBuffer.Append( centers[1] + wxPoint( 0, radius ) );
outline.Append( centers[0] + wxPoint( 0, radius ) );
outline.Append( centers[1] + wxPoint( 0, radius ) );
genArc( centers[1], 900, 1800 );
aCornerBuffer.Append( centers[1] + wxPoint( radius, 0 ) );
aCornerBuffer.Append( centers[2] + wxPoint( radius, 0 ) );
outline.Append( centers[1] + wxPoint( radius, 0 ) );
outline.Append( centers[2] + wxPoint( radius, 0 ) );
genArc( centers[2], 1800, 2700 );
aCornerBuffer.Append( centers[2] + wxPoint( 0, -radius ) );
aCornerBuffer.Append( centers[3] + wxPoint( 0, -radius ) );
outline.Append( centers[2] + wxPoint( 0, -radius ) );
outline.Append( centers[3] + wxPoint( 0, -radius ) );
genArc( centers[3], 2700, 3600 );
aCornerBuffer.Append( centers[3] + wxPoint( -radius, 0 ) );
outline.Append( centers[3] + wxPoint( -radius, 0 ) );
aCornerBuffer.Outline( 0 ).SetClosed( true );
outline.Outline( 0 ).SetClosed( true );
// The created outlines are bigger than the actual outlines, due to the fact
// the corner radius is bigger than the initial value when building a shape outside the
// actual shape.
// However the bounding box shape does not need to be bigger: only rounded corners must
// be modified.
// So clamp the too big shape by the actual bounding box
if( aErrorLoc == ERROR_OUTSIDE )
{
SHAPE_POLY_SET bbox;
bbox.NewOutline();
wxSize bbox_size = aSize/2;
bbox.Append( wxPoint( -bbox_size.x, -bbox_size.y ) );
bbox.Append( wxPoint( bbox_size.x, -bbox_size.y ) );
bbox.Append( wxPoint( bbox_size.x, bbox_size.y ) );
bbox.Append( wxPoint( -bbox_size.x, bbox_size.y ) );
bbox.Outline( 0 ).SetClosed( true );
outline.BooleanIntersection( bbox, SHAPE_POLY_SET::PM_FAST );
// The result is a convex polygon, no need to simplify or fracture.
}
// Add the outline:
aCornerBuffer.Append( outline );
}

View File

@ -641,13 +641,44 @@ void PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
wxSize shapesize( m_size );
bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT;
double chamferRatio = doChamfer ? GetChamferRectRatio() : 0.0;
if( aClearanceValue )
{
radius += aClearanceValue;
shapesize.x += aClearanceValue * 2;
shapesize.y += aClearanceValue * 2;
// The chamfer position (the 45 deg line on corner) must be
// offsetted by aClearanceValue from the base shape chamfer pos
// So we recalculate the chamferRatio to do that
//
// the chamfered shape is square with widet = w, and a corner dist from center
// is w*1.414 / 2 = w*0.707
// the distance from corner to chamfer line is ch = chamfer_size/707
// the distance from center to chamfer line is
// d = w*707 - ch/707
// so we have:
// base shape: d1 = w1*707 - ch1/707 = 0.707 * ( w1 - w1*chamferRatio)
// shape with clearance: d2 = w2*707 - ch2/707 = d1 + aClearanceValue
const double rootsq_2 = 1.41421356237/2;
int d1 = rootsq_2 * std::min( m_size.x, m_size.y ) * ( 1 - GetChamferRectRatio() );
int d2 = d1 + aClearanceValue;
// d2 = 0.707 * w2 * ( 1 - chamferRatio2 )
// 1 - d2 / ( 0.707 * w2 ) = chamferRatio2
chamferRatio = 1.0 - d2 / ( rootsq_2 * std::min( shapesize.x, shapesize.y ) );
// Ensure chamferRatio = 0.0 ... 0.5
if( chamferRatio < 0.0 )
chamferRatio = 0.0;
if( chamferRatio > 0.5 )
chamferRatio = 0.5;
}
SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, radius,
doChamfer ? GetChamferRectRatio() : 0.0,
chamferRatio,
doChamfer ? GetChamferPositions() : 0,
aError, aErrorLoc );