Clean up various simplify steps

Adds the option to simplify the output of Clipper ops that remove minor
detours from the output lines.  These detours are not substantive, so
removing them speeds up the rest of the system by removing unimportant
vertices.  This also prevents the introduction of inadvertant concave
points when unioning two, closely-sized rounded shapes
This commit is contained in:
Seth Hillbrand 2023-03-20 16:53:31 -07:00
parent e758391a23
commit 798e13f70d
3 changed files with 42 additions and 10 deletions

View File

@ -1046,6 +1046,12 @@ public:
///< For \a aFastMode meaning, see function booleanOp
void Simplify( POLYGON_MODE aFastMode );
///< Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
///< @param aMaxError Smooths the output such that points less than aMaxError away from the line through
/// the two adjacent points will be removed
void Simplify( size_t aMaxError );
/**
* Convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s).
*
@ -1422,10 +1428,10 @@ private:
void booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET& aShape,
const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode );
void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape );
void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape, size_t aMaxError = 0 );
void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aShape,
const SHAPE_POLY_SET& aOtherShape );
const SHAPE_POLY_SET& aOtherShape, size_t aMaxError = 0 );
/**
* Check whether the point \a aP is inside the \a aSubpolyIndex-th polygon of the polyset. If

View File

@ -721,14 +721,14 @@ void SHAPE_POLY_SET::booleanOp( ClipperLib::ClipType aType, const SHAPE_POLY_SET
}
void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape )
void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape, size_t aMaxError )
{
booleanOp( aType, *this, aOtherShape );
booleanOp( aType, *this, aOtherShape, aMaxError );
}
void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aShape,
const SHAPE_POLY_SET& aOtherShape )
const SHAPE_POLY_SET& aOtherShape, size_t aMaxError )
{
if( ( aShape.OutlineCount() > 1 || aOtherShape.OutlineCount() > 0 )
&& ( aShape.ArcCount() > 0 || aOtherShape.ArcCount() > 0 ) )
@ -765,7 +765,8 @@ void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SE
c.AddSubject( paths );
c.AddClip( clips );
Clipper2Lib::PolyTree64 solution;
Clipper2Lib::Paths64 solution;
Clipper2Lib::PolyTree64 tree;
Clipper2Lib::ZCallback64 callback =
[&]( const Clipper2Lib::Point64 & e1bot, const Clipper2Lib::Point64 & e1top,
@ -828,10 +829,24 @@ void SHAPE_POLY_SET::booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SE
c.SetZCallback( callback ); // register callback
c.Execute( aType, Clipper2Lib::FillRule::NonZero, solution );
if( aMaxError > 0 )
{
c.Execute( aType, Clipper2Lib::FillRule::NonZero, solution );
Clipper2Lib::Paths64 output = Clipper2Lib::SimplifyPaths( solution, aMaxError, false );
Clipper2Lib::Clipper64 c2;
importTree( solution, zValues, arcBuffer );
solution.Clear(); // Free used memory (not done in dtor)
c2.PreserveCollinear = false;
c2.ReverseSolution = false;
c2.AddSubject( output );
c2.Execute( Clipper2Lib::ClipType::Union, Clipper2Lib::FillRule::Positive, tree);
}
else
{
c.Execute( aType, Clipper2Lib::FillRule::NonZero, tree );
}
importTree( tree, zValues, arcBuffer );
tree.Clear(); // Free used memory (not done in dtor)
}
@ -1597,6 +1612,17 @@ void SHAPE_POLY_SET::Unfracture( POLYGON_MODE aFastMode )
}
void SHAPE_POLY_SET::Simplify( size_t aMaxError )
{
SHAPE_POLY_SET empty;
if( ADVANCED_CFG::GetCfg().m_UseClipper2 )
booleanOp( Clipper2Lib::ClipType::Union, empty, aMaxError );
else
booleanOp( ClipperLib::ctUnion, empty, PM_FAST );
}
void SHAPE_POLY_SET::Simplify( POLYGON_MODE aFastMode )
{
SHAPE_POLY_SET empty;

View File

@ -1299,7 +1299,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
}
}
aHoles.Simplify( SHAPE_POLY_SET::PM_FAST );
aHoles.Simplify( m_maxError );
}