Better calculation of polygon clearance area of oval pads.

Fixes: lp:1665582
https://bugs.launchpad.net/kicad/+bug/1665582
This commit is contained in:
jean-pierre charras 2018-01-20 20:44:04 +01:00
parent 1db14d44b7
commit 6dd398bd6f
1 changed files with 50 additions and 13 deletions

View File

@ -68,34 +68,45 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
wxPoint aStart, wxPoint aEnd, int aWidth, wxPoint aStart, wxPoint aEnd, int aWidth,
int aCircleToSegmentsCount, double aCorrectionFactor ) int aCircleToSegmentsCount, double aCorrectionFactor )
{ {
// To build the polygonal shape outside the actual shape, we use a bigger
// radius to build rounded ends.
// However, the width of the segment is too big.
// so, later, we will clamp the polygonal shape with the bounding box
// of the segment.
int radius = aWidth / 2; int radius = aWidth / 2;
wxPoint endp = aEnd - aStart; // end point coordinate for the same segment starting at (0,0) radius = radius * aCorrectionFactor; // make segments outside the circles
// end point is the coordinate relative to aStart
wxPoint endp = aEnd - aStart;
wxPoint startp = aStart; wxPoint startp = aStart;
wxPoint corner; wxPoint corner;
VECTOR2I polypoint; SHAPE_POLY_SET polyshape;
SHAPE_LINE_CHAIN polyshape;
radius = radius * aCorrectionFactor; polyshape.NewOutline();
// normalize the position in order to have endp.x >= 0; // normalize the position in order to have endp.x >= 0
// it makes calculations more easy to understand
if( endp.x < 0 ) if( endp.x < 0 )
{ {
endp = aStart - aEnd; endp = aStart - aEnd;
startp = aEnd; startp = aEnd;
} }
// delta_angle is in rd // delta_angle is in radian
double delta_angle = atan2( (double)endp.y, (double)endp.x ); double delta_angle = atan2( (double)endp.y, (double)endp.x );
int seg_len = KiROUND( EuclideanNorm( endp ) ); int seg_len = KiROUND( EuclideanNorm( endp ) );
int delta = 3600 / aCircleToSegmentsCount; // rot angle in 0.1 degree double delta = 3600 / aCircleToSegmentsCount; // rot angle in 0.1 degree
// Compute the outlines of the segment, and creates a polygon // Compute the outlines of the segment, and creates a polygon
// Note: the polygonal shape is built from the equivalent horizontal
// segment starting ar 0,0, and ending at seg_len,0
// add right rounded end: // add right rounded end:
for( int ii = 0; ii < 1800; ii += delta ) for( int ii = 0; ii < aCircleToSegmentsCount/2; ii++ )
{ {
corner = wxPoint( 0, radius ); corner = wxPoint( 0, radius );
RotatePoint( &corner, ii ); RotatePoint( &corner, delta*ii );
corner.x += seg_len; corner.x += seg_len;
polyshape.Append( corner.x, corner.y ); polyshape.Append( corner.x, corner.y );
} }
@ -105,23 +116,49 @@ void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
polyshape.Append( corner.x, corner.y ); polyshape.Append( corner.x, corner.y );
// add left rounded end: // add left rounded end:
for( int ii = 0; ii < 1800; ii += delta ) for( int ii = 0; ii < aCircleToSegmentsCount/2; ii++ )
{ {
corner = wxPoint( 0, -radius ); corner = wxPoint( 0, -radius );
RotatePoint( &corner, ii ); RotatePoint( &corner, delta*ii );
polyshape.Append( corner.x, corner.y ); polyshape.Append( corner.x, corner.y );
} }
// Finish arc: // Finish arc:
corner = wxPoint( 0, radius ); corner = wxPoint( 0, radius );
polyshape.Append( corner.x, corner.y ); polyshape.Append( corner.x, corner.y );
polyshape.SetClosed( true );
// Now, clamp the polygonal shape (too big) with the segment bounding box
// the polygonal shape bbox equivalent to the segment has a too big height,
// and the right width
if( aCorrectionFactor > 1.0 )
{
SHAPE_POLY_SET bbox;
bbox.NewOutline();
// Build the bbox (a horizontal rectangle).
int halfwidth = aWidth / 2; // Use the exact segment width for the bbox height
corner.x = -radius - 2; // use a bbox width slightly bigger to avoid
// creating useless corner at segment ends
corner.y = halfwidth;
bbox.Append( corner.x, corner.y );
corner.y = -halfwidth;
bbox.Append( corner.x, corner.y );
corner.x = radius + seg_len + 2;
bbox.Append( corner.x, corner.y );
corner.y = halfwidth;
bbox.Append( corner.x, corner.y );
// Now, clamp the shape
polyshape.BooleanIntersection( bbox, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
// Note the final polygon is a simple, convex polygon with no hole
// due to the shape of initial polygons
}
// Rotate and move the polygon to its right location // Rotate and move the polygon to its right location
polyshape.Rotate( delta_angle, VECTOR2I( 0, 0 ) ); polyshape.Rotate( delta_angle, VECTOR2I( 0, 0 ) );
polyshape.Move( startp ); polyshape.Move( startp );
aCornerBuffer.AddOutline( polyshape);
aCornerBuffer.Append( polyshape);
} }
/* Returns the centers of the rounded corners of a rect. /* Returns the centers of the rounded corners of a rect.