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:
parent
1f35ec5521
commit
8085899d0a
|
@ -228,7 +228,7 @@ void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||||
const wxPoint& aPosition, const wxSize& aSize,
|
const wxPoint& aPosition, const wxSize& aSize,
|
||||||
double aRotation, int aCornerRadius,
|
double aRotation, int aCornerRadius,
|
||||||
double aChamferRatio, int aChamferCorners,
|
double aChamferRatio, int aChamferCorners,
|
||||||
int aError )
|
int aApproxErrorMax, int aMinSegPerCircleCount )
|
||||||
{
|
{
|
||||||
// Build the basic shape in orientation 0.0, position 0,0 for chamfered corners
|
// Build the basic shape in orientation 0.0, position 0,0 for chamfered corners
|
||||||
// or in actual position/orientation for round rect only
|
// 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 )
|
for( int ii = 0; ii < 4; ++ii )
|
||||||
outline.Append( corners[ii].x, corners[ii].y );
|
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 );
|
outline.Inflate( aCornerRadius, numSegs );
|
||||||
|
|
||||||
if( aChamferCorners == RECT_NO_CHAMFER ) // no chamfer
|
if( aChamferCorners == RECT_NO_CHAMFER ) // no chamfer
|
||||||
|
|
|
@ -117,13 +117,17 @@ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius,
|
||||||
* 4 = BOTTOM_LEFT
|
* 4 = BOTTOM_LEFT
|
||||||
* 8 = BOTTOM_RIGHT
|
* 8 = BOTTOM_RIGHT
|
||||||
* One can have more than one chamfered corner by ORing the corner identifers
|
* 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,
|
void TransformRoundChamferedRectToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||||
const wxPoint& aPosition, const wxSize& aSize,
|
const wxPoint& aPosition, const wxSize& aSize,
|
||||||
double aRotation, int aCornerRadius,
|
double aRotation, int aCornerRadius,
|
||||||
double aChamferRatio, int aChamferCorners,
|
double aChamferRatio, int aChamferCorners,
|
||||||
int aError );
|
int aApproxErrorMax, int aMinSegPerCircleCount = 16 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function TransformRoundedEndsSegmentToPolygon
|
* Function TransformRoundedEndsSegmentToPolygon
|
||||||
|
|
|
@ -572,6 +572,10 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
|
||||||
{
|
{
|
||||||
wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." );
|
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;
|
double angle = m_Orient;
|
||||||
int dx = (m_Size.x / 2) + aClearanceValue;
|
int dx = (m_Size.x / 2) + aClearanceValue;
|
||||||
int dy = (m_Size.y / 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 );
|
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 );
|
double correction = GetCircletoPolyCorrectionFactor( numSegs );
|
||||||
|
|
||||||
int rounding_radius = KiROUND( aClearanceValue * correction );
|
int rounding_radius = KiROUND( aClearanceValue * correction );
|
||||||
|
@ -639,7 +644,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
|
||||||
case PAD_SHAPE_ROUNDRECT:
|
case PAD_SHAPE_ROUNDRECT:
|
||||||
{
|
{
|
||||||
int radius = GetRoundRectCornerRadius() + aClearanceValue;
|
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 );
|
double correction = GetCircletoPolyCorrectionFactor( numSegs );
|
||||||
int clearance = KiROUND( aClearanceValue * correction );
|
int clearance = KiROUND( aClearanceValue * correction );
|
||||||
int rounding_radius = KiROUND( radius * correction );
|
int rounding_radius = KiROUND( radius * correction );
|
||||||
|
@ -660,7 +666,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon(
|
||||||
|
|
||||||
case PAD_SHAPE_CUSTOM:
|
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 );
|
double correction = GetCircletoPolyCorrectionFactor( numSegs );
|
||||||
int clearance = KiROUND( aClearanceValue * correction );
|
int clearance = KiROUND( aClearanceValue * correction );
|
||||||
SHAPE_POLY_SET outline; // Will contain the corners in board coordinates
|
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
|
// The pattern roughtly is a 90 deg arc pie
|
||||||
std::vector <wxPoint> corners_buffer;
|
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 correction = GetCircletoPolyCorrectionFactor( numSegs );
|
||||||
double delta = 3600.0 / numSegs;
|
double delta = 3600.0 / numSegs;
|
||||||
|
|
||||||
|
@ -902,7 +910,7 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||||
for( unsigned ii = 0; ii < corners_buffer.size(); ii++ )
|
for( unsigned ii = 0; ii < corners_buffer.size(); ii++ )
|
||||||
{
|
{
|
||||||
corner = corners_buffer[ii];
|
corner = corners_buffer[ii];
|
||||||
RotatePoint( &corner, th_angle + angle_pad ); // Rotate by segment angle and pad orientation
|
RotatePoint( &corner, th_angle + angle_pad ); // Rotate by segment angle and pad orientation
|
||||||
corner += padShapePos;
|
corner += padShapePos;
|
||||||
aCornerBuffer.Append( corner.x, corner.y );
|
aCornerBuffer.Append( corner.x, corner.y );
|
||||||
}
|
}
|
||||||
|
@ -915,10 +923,10 @@ void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||||
case PAD_SHAPE_OVAL:
|
case PAD_SHAPE_OVAL:
|
||||||
{
|
{
|
||||||
// Oval pad support along the lines of round and rectangular pads
|
// Oval pad support along the lines of round and rectangular pads
|
||||||
std::vector <wxPoint> corners_buffer; // Polygon buffer as vector
|
std::vector <wxPoint> corners_buffer; // Polygon buffer as vector
|
||||||
|
|
||||||
dx = (aPad.GetSize().x / 2) + aThermalGap; // Cutout radius x
|
dx = (aPad.GetSize().x / 2) + aThermalGap; // Cutout radius x
|
||||||
dy = (aPad.GetSize().y / 2) + aThermalGap; // Cutout radius y
|
dy = (aPad.GetSize().y / 2) + aThermalGap; // Cutout radius y
|
||||||
|
|
||||||
wxPoint shape_offset;
|
wxPoint shape_offset;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue