From c1ef019d3588de5fabc43f7ec9672b4f2f975bfa Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 27 Jan 2026 09:51:54 -0800 Subject: [PATCH] Move splitSelfTouchingOutlines to cacheTriangulation The splitSelfTouchingOutlines call was unconditionally called in Simplify but is only needed during triangulation when dealing with self-touching or self-intersecting polygons. Move the call to cacheTriangulation where it's actually used and remove it from Simplify. Simplify the test to directly check triangulated area against the expected value instead of relying on the simplified polygon as a reference. --- libs/kimath/src/geometry/shape_poly_set.cpp | 5 +++- .../geometry/test_poly_triangulation.cpp | 23 ++++--------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/libs/kimath/src/geometry/shape_poly_set.cpp b/libs/kimath/src/geometry/shape_poly_set.cpp index b6f226b579..41b9ecbdc0 100644 --- a/libs/kimath/src/geometry/shape_poly_set.cpp +++ b/libs/kimath/src/geometry/shape_poly_set.cpp @@ -2175,7 +2175,6 @@ void SHAPE_POLY_SET::splitSelfTouchingOutlines() void SHAPE_POLY_SET::Simplify() { - splitSelfTouchingOutlines(); splitCollinearOutlines(); SHAPE_POLY_SET empty; @@ -3234,7 +3233,10 @@ void SHAPE_POLY_SET::cacheTriangulation( bool aPartition, bool aSimplify, flattened.ClearArcs(); if( flattened.HasHoles() || flattened.IsSelfIntersecting() ) + { + flattened.splitSelfTouchingOutlines(); flattened.Fracture(); + } else if( aSimplify ) flattened.Simplify(); @@ -3260,6 +3262,7 @@ void SHAPE_POLY_SET::cacheTriangulation( bool aPartition, bool aSimplify, SHAPE_POLY_SET tmpSet( *this ); tmpSet.ClearArcs(); + tmpSet.splitSelfTouchingOutlines(); tmpSet.Fracture(); if( !triangulate( tmpSet, -1, m_triangulatedPolys, aHintData ) ) diff --git a/qa/tests/libs/kimath/geometry/test_poly_triangulation.cpp b/qa/tests/libs/kimath/geometry/test_poly_triangulation.cpp index 36abb0ea44..26c336d0a9 100644 --- a/qa/tests/libs/kimath/geometry/test_poly_triangulation.cpp +++ b/qa/tests/libs/kimath/geometry/test_poly_triangulation.cpp @@ -505,29 +505,14 @@ BOOST_AUTO_TEST_CASE( Issue18083_SelfIntersectingPolygonArea ) triangulatedArea += std::abs( tri.Area() ); } - // Calculate expected area by simplifying the polygon first. - // The simplification should split the self-touching polygon into two separate triangles. - SHAPE_POLY_SET simplified; - simplified.AddOutline( outline ); - simplified.Simplify(); - - // After simplification, we should have two separate triangular outlines - BOOST_TEST( simplified.OutlineCount() == 2 ); - - double expectedArea = 0.0; - - for( int ii = 0; ii < simplified.OutlineCount(); ++ii ) - { - expectedArea += std::abs( simplified.Outline( ii ).Area() ); - } - // The expected total area is 49 mm² (14 mm² + 35 mm² for the two triangular lobes) + // Triangle 1: (165,87) - (169,87) - (167,94) = base 4mm, height 7mm = 14 mm² + // Triangle 2: (169,87) - (179,87) - (174,94) = base 10mm, height 7mm = 35 mm² double expectedAreaMmSq = 49.0 * SCALE * SCALE; - BOOST_TEST( std::abs( expectedArea - expectedAreaMmSq ) < expectedAreaMmSq * 0.01 ); // The triangulated area should match the expected area - BOOST_TEST( std::abs( triangulatedArea - expectedArea ) < expectedArea * 0.01, - "Triangulated area should match simplified polygon area" ); + BOOST_TEST( std::abs( triangulatedArea - expectedAreaMmSq ) < expectedAreaMmSq * 0.01, + "Triangulated area should match expected area of 49 mm²" ); } BOOST_AUTO_TEST_CASE( NearlyCollinearVertices )