diff --git a/common/convert_basic_shapes_to_polygon.cpp b/common/convert_basic_shapes_to_polygon.cpp index f3a4652468..ba58fab398 100644 --- a/common/convert_basic_shapes_to_polygon.cpp +++ b/common/convert_basic_shapes_to_polygon.cpp @@ -64,6 +64,66 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, } } +void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + wxPoint aStart, wxPoint aEnd, int aWidth, + int aCircleToSegmentsCount, double aCorrectionFactor ) +{ + int radius = aWidth / 2; + wxPoint endp = aEnd - aStart; // end point coordinate for the same segment starting at (0,0) + wxPoint startp = aStart; + wxPoint corner; + VECTOR2I polypoint; + SHAPE_LINE_CHAIN polyshape; + + radius = radius * aCorrectionFactor; + + // normalize the position in order to have endp.x >= 0; + if( endp.x < 0 ) + { + endp = aStart - aEnd; + startp = aEnd; + } + + // delta_angle is in rd + double delta_angle = atan2( (double)endp.y, (double)endp.x ); + int seg_len = KiROUND( EuclideanNorm( endp ) ); + + int delta = 3600 / aCircleToSegmentsCount; // rot angle in 0.1 degree + + // Compute the outlines of the segment, and creates a polygon + // add right rounded end: + for( int ii = 0; ii < 1800; ii += delta ) + { + corner = wxPoint( 0, radius ); + RotatePoint( &corner, ii ); + corner.x += seg_len; + polyshape.Append( corner.x, corner.y ); + } + + // Finish arc: + corner = wxPoint( seg_len, -radius ); + polyshape.Append( corner.x, corner.y ); + + // add left rounded end: + for( int ii = 0; ii < 1800; ii += delta ) + { + corner = wxPoint( 0, -radius ); + RotatePoint( &corner, ii ); + polyshape.Append( corner.x, corner.y ); + } + + // Finish arc: + corner = wxPoint( 0, radius ); + polyshape.Append( corner.x, corner.y ); + polyshape.SetClosed( true ); + + // Rotate and move the polygon to its right location + polyshape.Rotate( delta_angle, VECTOR2I( 0, 0 ) ); + polyshape.Move( startp ); + + aCornerBuffer.AddOutline( polyshape); +} + /* Returns the centers of the rounded corners of a rect. */ void GetRoundRectCornerCenters( wxPoint aCenters[4], int aRadius, diff --git a/include/convert_basic_shapes_to_polygon.h b/include/convert_basic_shapes_to_polygon.h index f8190f84fb..eac92db8d3 100644 --- a/include/convert_basic_shapes_to_polygon.h +++ b/include/convert_basic_shapes_to_polygon.h @@ -50,6 +50,29 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, int aCircleToSegmentsCount ); + +/** + * convert a oblong shape to a polygon, using multiple segments + * It is similar to TransformRoundedEndsSegmentToPolygon, but the polygon + * is outside the actual oblong shape (a segment with rounded ends) + * It is suitable to create oblong clearance areas. + * because multiple segments create a smaller area than the circle, the + * radius of the circle to approximate must be bigger ( radius*aCorrectionFactor) + * to create segments outside the circle. + * @param aCornerBuffer = a buffer to store the polygon + * @param aStart = the first point of the segment + * @param aEnd = the second point of the segment + * @param aWidth = the width of the segment + * @param aCircleToSegmentsCount = the number of segments to approximate a circle + * @param aCorrectionFactor = the coefficient to have segments outside the circle + * if aCorrectionFactor = 1.0, the shape will be the same as + * TransformRoundedEndsSegmentToPolygon + */ +void TransformOvalClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, + wxPoint aStart, wxPoint aEnd, int aWidth, + int aCircleToSegmentsCount, double aCorrectionFactor ); + + /** * Helper function GetRoundRectCornerCenters * Has meaning only for rounded rect diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp index cd83c4309e..8533242205 100644 --- a/pcbnew/board_items_to_polygon_shape_transform.cpp +++ b/pcbnew/board_items_to_polygon_shape_transform.cpp @@ -651,13 +651,11 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint shape_offset; if( dy > dx ) // Oval pad X/Y ratio for choosing translation axis { - dy = KiROUND( dy * aCorrectionFactor ); shape_offset.y = dy - dx; width = dx * 2; } else //if( dy <= dx ) { - dx = KiROUND( dx * aCorrectionFactor ); shape_offset.x = dy - dx; width = dy * 2; } @@ -665,8 +663,8 @@ void D_PAD::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, RotatePoint( &shape_offset, angle ); wxPoint start = padShapePos - shape_offset; wxPoint end = padShapePos + shape_offset; - TransformRoundedEndsSegmentToPolygon( aCornerBuffer, start, end, - aCircleToSegmentsCount, width ); + TransformOvalClearanceToPolygon( aCornerBuffer, start, end, width, + aCircleToSegmentsCount, aCorrectionFactor ); } break; diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 88b058ef96..4c86c641df 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -900,12 +900,13 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con { case PAD_SHAPE_CIRCLE: return arect.IntersectsCircle( GetPosition(), GetBoundingRadius() ); + case PAD_SHAPE_RECT: shapeRect.SetOrigin( shapePos ); shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 ); return arect.Intersects( shapeRect, m_Orient ); - case PAD_SHAPE_OVAL: + case PAD_SHAPE_OVAL: // Circlular test if dimensions are equal if( m_Size.x == m_Size.y ) return arect.IntersectsCircle( shapePos, GetBoundingRadius() ); @@ -953,6 +954,7 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con } break; + case PAD_SHAPE_TRAPEZOID: /* Trapezoid intersection tests: * A) Any points of rect inside trapezoid @@ -996,8 +998,8 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con } return false; - } + case PAD_SHAPE_ROUNDRECT: /* RoundRect intersection can be broken up into simple tests: * a) Test intersection of horizontal rect @@ -1053,6 +1055,7 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con } break; + default: break; }