diff --git a/libs/kimath/include/geometry/shape_poly_set.h b/libs/kimath/include/geometry/shape_poly_set.h index f8a7ce7a63..1f16ffd4e9 100644 --- a/libs/kimath/include/geometry/shape_poly_set.h +++ b/libs/kimath/include/geometry/shape_poly_set.h @@ -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 diff --git a/libs/kimath/src/geometry/shape_poly_set.cpp b/libs/kimath/src/geometry/shape_poly_set.cpp index 7fbc3474d7..df50dc280b 100644 --- a/libs/kimath/src/geometry/shape_poly_set.cpp +++ b/libs/kimath/src/geometry/shape_poly_set.cpp @@ -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; diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index b596ab5594..0b7fc4ddc4 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -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 ); }