polygon: Fix missing steiner removal and fracture
When removing steiner points, there is the possibility that the test point is also removed. In this case, it is no longer a member of the linked list and will break the output. The test for re-fracturing a broken polygon can also result in multiple polygons, rather than only 0 or 1. Skipping the extra polygons will result in a limited tesselation. Fixes: lp:1812393 * https://bugs.launchpad.net/kicad/+bug/1812393
This commit is contained in:
parent
e2afe5e1a3
commit
4a68ae4bae
|
@ -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<TRIANGULATED_POLYGON>() );
|
||||
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 )
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue