Update triangulation

Allow for overlapping points in input polygon.  This is relatively
common on a grid and should be used as potential split points to shave
additional ears

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16933

(cherry picked from commit 745c52c2b7)
This commit is contained in:
Seth Hillbrand 2024-02-12 15:19:01 -08:00
parent a6210da126
commit f3566a987d
2 changed files with 50 additions and 2 deletions

View File

@ -56,6 +56,8 @@
#include <math/box2.h>
#include <math/vector2d.h>
#define TRIANGULATE_TRACE "triangulate"
class PolygonTriangulation
{
public:
@ -578,6 +580,46 @@ private:
{
Vertex* origPoly = start;
// Our first attempts to split the polygon will be at overlapping points.
// These are natural split points and we only need to switch the loop directions
// to generate two new loops. Since they are overlapping, we are do not
// need to create a new segment to disconnect the two loops.
do
{
Vertex* nextZ = origPoly->nextZ;
if( nextZ && *nextZ == *origPoly )
{
std::swap( origPoly->next, nextZ->next );
origPoly->next->prev = origPoly;
nextZ->next->prev = nextZ;
origPoly->updateList();
nextZ->updateList();
return earcutList( origPoly ) && earcutList( nextZ );
}
Vertex* prevZ = origPoly->prevZ;
if( prevZ && *prevZ == *origPoly )
{
std::swap( origPoly->next, prevZ->next );
origPoly->next->prev = origPoly;
prevZ->next->prev = prevZ;
origPoly->updateList();
prevZ->updateList();
return earcutList( origPoly ) && earcutList( prevZ );
}
origPoly = origPoly->next;
} while ( origPoly != start );
// If we've made it through the split algorithm and we still haven't found a
// set of overlapping points, we need to create a new segment to split the polygon
// into two separate polygons. We do this by finding the two vertices that form
// a valid line (does not cross the existing polygon)
do
{
Vertex* marker = origPoly->next->next;

View File

@ -2815,7 +2815,10 @@ void SHAPE_POLY_SET::CacheTriangulation( bool aPartition, bool aSimplify )
// This pushes the triangulation for all polys in partitions
// to be referenced to the ii-th polygon
m_triangulationValid &= triangulate( partitions, ii , m_triangulatedPolys );
if( !triangulate( partitions, ii , m_triangulatedPolys ) )
{
wxLogTrace( TRIANGULATE_TRACE, "Failed to triangulate partitioned polygon %d", ii );
}
}
}
else
@ -2826,7 +2829,10 @@ void SHAPE_POLY_SET::CacheTriangulation( bool aPartition, bool aSimplify )
tmpSet.Fracture( PM_FAST );
m_triangulationValid = triangulate( tmpSet, -1, m_triangulatedPolys );
if( !triangulate( tmpSet, -1, m_triangulatedPolys ) )
{
wxLogTrace( TRIANGULATE_TRACE, "Failed to triangulate polygon" );
}
}
if( m_triangulationValid )