Pcbnew: better approximation of arcs by polygons for pads having a very small size.

Especially, small round rect pads have a ugly shape because the number of segments is
small and the 90 deg arcs are not very well approximated.
The minimal seg count for 90 deg arcs is now 4 (16 segm/circle) for pads.

Fixes: lp:1833005
https://bugs.launchpad.net/kicad/+bug/1833005
This commit is contained in:
jean-pierre charras 2019-06-17 17:26:15 +02:00
parent 1f35ec5521
commit 8085899d0a
3 changed files with 25 additions and 12 deletions

View File

@ -228,7 +228,7 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
const wxPoint& aPosition, const wxSize& aSize,
double aRotation, int aCornerRadius,
double aChamferRatio, int aChamferCorners,
int aError )
int aApproxErrorMax, int aMinSegPerCircleCount )
{
// Build the basic shape in orientation 0.0, position 0,0 for chamfered corners
// or in actual position/orientation for round rect only
@ -243,7 +243,8 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
for( int ii = 0; ii < 4; ++ii )
outline.Append( corners[ii].x, corners[ii].y );
int numSegs = std::max( GetArcToSegmentCount( aCornerRadius, aError, 360.0 ), 6 );
int numSegs = std::max( GetArcToSegmentCount( aCornerRadius, aApproxErrorMax, 360.0 ),
aMinSegPerCircleCount );
outline.Inflate( aCornerRadius, numSegs );
if( aChamferCorners == RECT_NO_CHAMFER ) // no chamfer

View File

@ -117,13 +117,17 @@ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius,
* 4 = BOTTOM_LEFT
* 8 = BOTTOM_RIGHT
* One can have more than one chamfered corner by ORing the corner identifers
* @param aError = the IU allowed for error in approximation
* @param aApproxErrorMax = the IU allowed for error in approximation
* @param aMinSegPerCircleCount = the minimal segments per circle count in approximation
* (aApproxErrorMax can generate must more seg count than aMinSegPerCircleCount)
* To allow a reasonable good shape even for very small shapes, the min count is 16
* (must be a multiple of 4 becauseusually arcs are 90 deg.
*/
void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
const wxPoint& aPosition, const wxSize& aSize,
double aRotation, int aCornerRadius,
double aChamferRatio, int aChamferCorners,
int aError );
int aApproxErrorMax, int aMinSegPerCircleCount = 16 );
/**
* Function TransformRoundedEndsSegmentToPolygon

View File

@ -572,6 +572,10 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
{
wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." );
// minimal segment count to approximate a circle to create the polygonal pad shape
// This minimal value is mainly for very small pads, like SM0402.
// Most of time pads are using the segment count given by aError value.
const int pad_min_seg_per_circle_count = 16;
double angle = m_Orient;
int dx = (m_Size.x / 2) + aClearanceValue;
int dy = (m_Size.y / 2) + aClearanceValue;
@ -625,7 +629,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
outline.Append( corners[ii].x, corners[ii].y );
}
int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ), 6 );
int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ),
pad_min_seg_per_circle_count );
double correction = GetCircletoPolyCorrectionFactor( numSegs );
int rounding_radius = KiROUND( aClearanceValue * correction );
@ -639,7 +644,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
case PAD_SHAPE_ROUNDRECT:
{
int radius = GetRoundRectCornerRadius() + aClearanceValue;
int numSegs = std::max( GetArcToSegmentCount( radius, aError, 360.0 ), 6 );
int numSegs = std::max( GetArcToSegmentCount( radius, aError, 360.0 ),
pad_min_seg_per_circle_count );
double correction = GetCircletoPolyCorrectionFactor( numSegs );
int clearance = KiROUND( aClearanceValue * correction );
int rounding_radius = KiROUND( radius * correction );
@ -660,7 +666,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
case PAD_SHAPE_CUSTOM:
{
int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ), 6 );
int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ),
pad_min_seg_per_circle_count );
double correction = GetCircletoPolyCorrectionFactor( numSegs );
int clearance = KiROUND( aClearanceValue * correction );
SHAPE_POLY_SET outline; // Will contain the corners in board coordinates
@ -844,7 +851,8 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer,
// The pattern roughtly is a 90 deg arc pie
std::vector <wxPoint> corners_buffer;
int numSegs = std::max( GetArcToSegmentCount( dx + aThermalGap, aError, 360.0 ), 6 );
int numSegs = std::max( GetArcToSegmentCount( dx + aThermalGap, aError, 360.0 ),
8 );
double correction = GetCircletoPolyCorrectionFactor( numSegs );
double delta = 3600.0 / numSegs;