diff --git a/common/geometry/shape_poly_set.cpp b/common/geometry/shape_poly_set.cpp index 3dd21d32aa..4bb1ea1b59 100644 --- a/common/geometry/shape_poly_set.cpp +++ b/common/geometry/shape_poly_set.cpp @@ -1871,27 +1871,23 @@ void SHAPE_POLY_SET::CacheTriangulation() m_triangulatedPolys.clear(); m_triangulationValid = true; - for( int i = 0; i < tmpSet.OutlineCount(); i++ ) + while( tmpSet.OutlineCount() > 0 ) { m_triangulatedPolys.push_back( std::make_unique() ); PolygonTriangulation tess( *m_triangulatedPolys.back() ); // If the tesselation fails, we re-fracture the polygon, which will // first simplify the system before fracturing and removing the holes - if( !tess.TesselatePolygon( tmpSet.Polygon( i ).front() ) ) + // This may result in multiple, disjoint polygons. + if( !tess.TesselatePolygon( tmpSet.Polygon( 0 ).front() ) ) { tmpSet.Fracture( PM_FAST ); - - // After fracturing, we may have zero or one polygon - // Check for zero polygons before tesselating and break regardless - if( !tmpSet.OutlineCount() || !tess.TesselatePolygon( tmpSet.Polygon( i ).front() ) ) - { - m_triangulatedPolys.pop_back(); - m_triangulationValid = false; - } - - break; + m_triangulationValid = false; + continue; } + + tmpSet.DeletePolygon( 0 ); + m_triangulationValid = true; } if( m_triangulationValid ) diff --git a/include/geometry/polygon_triangulation.h b/include/geometry/polygon_triangulation.h index b419b45c6f..c1c0dbfdf7 100644 --- a/include/geometry/polygon_triangulation.h +++ b/include/geometry/polygon_triangulation.h @@ -263,9 +263,9 @@ private: * as the NULL triangles are inserted as Steiner points to improve the * triangulation regularity of polygons */ - bool removeNullTriangles( Vertex* aStart ) + Vertex* removeNullTriangles( Vertex* aStart ) { - bool retval = false; + Vertex* retval = nullptr; Vertex* p = aStart->next; while( p != aStart ) @@ -274,7 +274,7 @@ private: { p = p->prev; p->next->remove(); - retval = true; + retval = aStart; if( p == p->next ) break; @@ -286,8 +286,8 @@ private: // here we do the final check for this as a Steiner point if( area( aStart->prev, aStart, aStart->next ) == 0.0 ) { + retval = p->next; p->remove(); - retval = true; } return retval; @@ -433,8 +433,13 @@ private: if( aPoint == stop ) { // First, try to remove the remaining steiner points - if( removeNullTriangles( aPoint ) ) + // If aPoint is a steiner, we need to re-assign both the start and stop points + if( auto newPoint = removeNullTriangles( aPoint ) ) + { + aPoint = newPoint; + stop = newPoint; continue; + } // If we don't have any NULL triangles left, cut the polygon in two and try again splitPolygon( aPoint );