diff --git a/libs/kimath/include/convert_basic_shapes_to_polygon.h b/libs/kimath/include/convert_basic_shapes_to_polygon.h index dc4491e373..1dca385dbc 100644 --- a/libs/kimath/include/convert_basic_shapes_to_polygon.h +++ b/libs/kimath/include/convert_basic_shapes_to_polygon.h @@ -56,9 +56,11 @@ enum RECT_CHAMFER_POSITIONS : int * @param aRadius is the radius of the circle. * @param aError is the internal units allowed for error approximation. * @param aErrorLoc determines if the approximation error be placed outside or inside the polygon. + * @param aMinSegCount is the min count of segments to approximate. + * Default = 0 to do not force a min count. */ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter, int aRadius, - int aError, ERROR_LOC aErrorLoc ); + int aError, ERROR_LOC aErrorLoc, int aMinSegCount = 0 ); /** * Convert a circle to a polygon, using multiple straight lines. @@ -68,9 +70,11 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter, * @param aRadius is the radius of the circle. * @param aError is the internal units allowed for error in approximation. * @param aErrorLoc determines if the approximation error be placed outside or inside the polygon. + * @param aMinSegCount is the min count of segments to approximate. + * Default = 0 to do not force a min count. */ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, - int aError, ERROR_LOC aErrorLoc ); + int aError, ERROR_LOC aErrorLoc, int aMinSegCount = 0 ); /** @@ -87,9 +91,11 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, i * @param aWidth is the width of the segment. * @param aError is the internal units allowed for error in approximation. * @param aErrorLoc determines if the approximation error be placed outside or inside the polygon. + * @param aMinSegCount is the min count of segments to approximate. + * Default = 0 to do not force a min count. */ void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, - int aWidth, int aError, ERROR_LOC aErrorLoc ); + int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount = 0 ); /** diff --git a/libs/kimath/src/convert_basic_shapes_to_polygon.cpp b/libs/kimath/src/convert_basic_shapes_to_polygon.cpp index 97e6961ba0..426cbc661b 100644 --- a/libs/kimath/src/convert_basic_shapes_to_polygon.cpp +++ b/libs/kimath/src/convert_basic_shapes_to_polygon.cpp @@ -39,10 +39,11 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter, int aRadius, - int aError, ERROR_LOC aErrorLoc ) + int aError, ERROR_LOC aErrorLoc, int aMinSegCount ) { wxPoint corner_position; int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 ); + numSegs = std::max( aMinSegCount, numSegs ); // The shape will be built with a even number of segs. Reason: the horizontal // diameter begins and ends to points on the actual circle, or circle @@ -77,10 +78,11 @@ void TransformCircleToPolygon( SHAPE_LINE_CHAIN& aCornerBuffer, wxPoint aCenter, void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, int aRadius, - int aError, ERROR_LOC aErrorLoc ) + int aError, ERROR_LOC aErrorLoc, int aMinSegCount ) { wxPoint corner_position; int numSegs = GetArcToSegmentCount( aRadius, aError, 360.0 ); + numSegs = std::max( aMinSegCount, numSegs); // The shape will be built with a even number of segs. Reason: the horizontal // diameter begins and ends to points on the actual circle, or circle @@ -121,7 +123,7 @@ void TransformCircleToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aCenter, i void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPoint aEnd, - int aWidth, int aError, ERROR_LOC aErrorLoc ) + int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount ) { // To build the polygonal shape outside the actual shape, we use a bigger // radius to build rounded ends. @@ -130,11 +132,19 @@ void TransformOvalToPolygon( SHAPE_POLY_SET& aCornerBuffer, wxPoint aStart, wxPo // of the segment. int radius = aWidth / 2; int numSegs = GetArcToSegmentCount( radius, aError, 360.0 ); + numSegs = std::max( aMinSegCount, numSegs ); + int delta = 3600 / numSegs; // rotate angle in 0.1 degree - int correction = GetCircleToPolyCorrection( aError ); if( aErrorLoc == ERROR_OUTSIDE ) + { + // The outer radius should be radius+aError + // Recalculate the actual approx error, as it can be smaller than aError + // because numSegs is clamped to a minimal value + int actual_delta_radius = CircleToEndSegmentDeltaRadius( radius, numSegs ); + int correction = GetCircleToPolyCorrection( actual_delta_radius ); radius += correction; + } // end point is the coordinate relative to aStart wxPoint endp = aEnd - aStart; @@ -248,7 +258,13 @@ void TransformRoundRectToPolygon( SHAPE_POLY_SET& aCornerBuffer, const wxSize& a int radius = aCornerRadius; if( aErrorLoc == ERROR_OUTSIDE ) - radius += GetCircleToPolyCorrection( aError ); + { + // The outer radius should be radius+aError + // Recalculate the actual approx error, as it can be smaller than aError + // because numSegs is clamped to a minimal value + int actual_delta_radius = CircleToEndSegmentDeltaRadius( radius, numSegs ); + radius += GetCircleToPolyCorrection( actual_delta_radius ); + } auto genArc = [&]( const wxPoint& aCenter, int aStart, int aEnd )