diff --git a/libs/kimath/include/geometry/shape_poly_set.h b/libs/kimath/include/geometry/shape_poly_set.h index 1cd9cd056b..4c9c7e40ec 100644 --- a/libs/kimath/include/geometry/shape_poly_set.h +++ b/libs/kimath/include/geometry/shape_poly_set.h @@ -1350,6 +1350,16 @@ public: */ bool IsVertexInHole( int aGlobalIdx ); + /** + * Build a SHAPE_POLY_SET from a bunch of outlines in provided in random order. + * + * @param aPath set of closed outlines forming the polygon. Positive orientation = outline, negative = hole + * @param aReverseOrientation inverts the sign of the orientation of aPaths (so negative = outline) + * @param aEvenOdd forces the even-off fill rule (default is non zero) + * @return the constructed poly set + */ + static const SHAPE_POLY_SET BuildPolysetFromOrientedPaths( const std::vector& aPaths, bool aReverseOrientation = false, bool aEvenOdd = false ); + private: void fractureSingle( POLYGON& paths ); void unfractureSingle ( POLYGON& path ); diff --git a/libs/kimath/src/geometry/shape_poly_set.cpp b/libs/kimath/src/geometry/shape_poly_set.cpp index 6b41e7b984..c67f56db7b 100644 --- a/libs/kimath/src/geometry/shape_poly_set.cpp +++ b/libs/kimath/src/geometry/shape_poly_set.cpp @@ -2524,3 +2524,55 @@ SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRIANGULATED_POLYGON() SHAPE_POLY_SET::TRIANGULATED_POLYGON::~TRIANGULATED_POLYGON() { } + + +const SHAPE_POLY_SET +SHAPE_POLY_SET::BuildPolysetFromOrientedPaths( const std::vector& aPaths, + bool aReverseOrientation, bool aEvenOdd ) +{ + ClipperLib::Clipper clipper; + ClipperLib::PolyTree tree; + + // fixme: do we need aReverseOrientation? + + for( const SHAPE_LINE_CHAIN& path : aPaths ) + { + ClipperLib::Path lc; + + for( int i = 0; i < path.PointCount(); i++ ) + { + lc.emplace_back( path.CPoint( i ).x, path.CPoint( i ).y ); + } + + clipper.AddPath( lc, ClipperLib::ptSubject, true ); + } + + clipper.StrictlySimple( true ); + clipper.Execute( ClipperLib::ctUnion, tree, + aEvenOdd ? ClipperLib::pftEvenOdd : ClipperLib::pftNonZero, + ClipperLib::pftNonZero ); + SHAPE_POLY_SET result; + + for( ClipperLib::PolyNode* n = tree.GetFirst(); n; n = n->GetNext() ) + { + if( !n->IsHole() ) + { + int outl = result.NewOutline(); + + for( unsigned int i = 0; i < n->Contour.size(); i++ ) + result.Outline( outl ).Append( n->Contour[i].X, n->Contour[i].Y ); + + for( unsigned int i = 0; i < n->Childs.size(); i++ ) + { + int outh = result.NewHole( outl ); + for( unsigned int j = 0; j < n->Childs[i]->Contour.size(); j++ ) + { + result.Hole( outl, outh ) + .Append( n->Childs[i]->Contour[j].X, n->Childs[i]->Contour[j].Y ); + } + } + } + } + + return result; +}