From 3f8cada334e373371a995eaac156b73e9b288ae9 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Thu, 3 Feb 2022 19:38:54 +0000 Subject: [PATCH] Fix some issues with new polygonization of arcs and arc collision test. Test should not be testing against the polygonization error; if done correctly that should all be on the correct side of the shape. Use an epsilon instead (I chose polygonization error / 10, but the value isn't terribly important). Fixes https://gitlab.com/kicad/code/kicad/issues/10724 --- .../src/convert_basic_shapes_to_polygon.cpp | 21 ++++++++++++------- qa/libs/kimath/geometry/test_shape_arc.cpp | 11 ++++------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/libs/kimath/src/convert_basic_shapes_to_polygon.cpp b/libs/kimath/src/convert_basic_shapes_to_polygon.cpp index be5fb26f3e..a9eab4ff39 100644 --- a/libs/kimath/src/convert_basic_shapes_to_polygon.cpp +++ b/libs/kimath/src/convert_basic_shapes_to_polygon.cpp @@ -583,6 +583,14 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aStar EDA_ANGLE arc_angle_start = arc.GetStartAngle(); EDA_ANGLE arc_angle = arc.GetCentralAngle(); EDA_ANGLE arc_angle_end = arc_angle_start + arc_angle; + EDA_ANGLE sweep = arc_angle < ANGLE_0 ? -ANGLE_180 : ANGLE_180; + + if( arc_angle < ANGLE_0 ) + { + std::swap( arc_angle_start, arc_angle_end ); + arc = SHAPE_ARC( aEnd, aMid, aStart, aWidth ); + arc_angle = -arc_angle; + } int radial_offset = arc.GetWidth() / 2; int arc_outer_radius = arc.GetRadius() + radial_offset; @@ -596,27 +604,24 @@ void TransformArcToPolygon( SHAPE_POLY_SET& aCornerBuffer, const VECTOR2I& aStar SHAPE_LINE_CHAIN& outline = polyshape.Outline( 0 ); // Starting end - ConvertArcToPolyline( outline, arc.GetP0(), radial_offset, -arc_angle_start, ANGLE_180, aError, - aErrorLoc ); + ConvertArcToPolyline( outline, arc.GetP0(), radial_offset, arc_angle_start - ANGLE_180, + ANGLE_180, aError, aErrorLoc ); // Outside edge ConvertArcToPolyline( outline, arc.GetCenter(), arc_outer_radius, arc_angle_start, arc_angle, aError, errorLocOuter ); // Other end - ConvertArcToPolyline( outline, arc.GetP1(), radial_offset, -arc_angle_end, ANGLE_180, aError, + ConvertArcToPolyline( outline, arc.GetP1(), radial_offset, arc_angle_end, ANGLE_180, aError, aErrorLoc ); // Inside edge if( arc_inner_radius > 0 ) { - ConvertArcToPolyline( outline, arc.GetCenter(), arc_inner_radius, arc_angle_end, -arc_angle, - aError, errorLocInner ); + ConvertArcToPolyline( outline, arc.GetCenter(), arc_inner_radius, arc_angle_end, + -arc_angle, aError, errorLocInner ); } - // Required. Otherwise Clipper has fits with duplicate points generating winding artefacts. - polyshape.Simplify( SHAPE_POLY_SET::PM_FAST ); - aCornerBuffer.Append( polyshape ); } diff --git a/qa/libs/kimath/geometry/test_shape_arc.cpp b/qa/libs/kimath/geometry/test_shape_arc.cpp index 32e94b5dcb..161c69a5f3 100644 --- a/qa/libs/kimath/geometry/test_shape_arc.cpp +++ b/qa/libs/kimath/geometry/test_shape_arc.cpp @@ -886,7 +886,7 @@ BOOST_AUTO_TEST_CASE( CollideArcToShapeLineChain ) BOOST_AUTO_TEST_CASE( CollideArcToPolygonApproximation ) { SHAPE_ARC arc( VECTOR2I( 73843527, 74355869 ), VECTOR2I( 71713528, 72965869 ), - EDA_ANGLE( -76.36664803, DEGREES_T ), 2000000 ); + EDA_ANGLE( -76.36664803, DEGREES_T ), 1000000 ); // Create a polyset approximation from the arc - error outside (simulating the zone filler) SHAPE_POLY_SET arcBuffer; @@ -917,14 +917,11 @@ BOOST_AUTO_TEST_CASE( CollideArcToPolygonApproximation ) int actual = 0; VECTOR2I location; + int epsilon = polygonApproximationError / 10; - int clearanceReduced = clearance - polygonApproximationError; + BOOST_CHECK_EQUAL( zoneFill.Collide( &arc, clearance + epsilon, &actual, &location ), true ); - BOOST_CHECK_EQUAL( zoneFill.Collide( &arc, clearanceReduced, &actual, &location ), false ); - - BOOST_CHECK_EQUAL( zoneFill.Collide( &arc, clearance * 2, &actual, &location ), true ); - - BOOST_CHECK( KI_TEST::IsWithin( actual, clearance, polygonApproximationError ) ); + BOOST_CHECK_EQUAL( zoneFill.Collide( &arc, clearance - epsilon, &actual, &location ), false ); }