diff --git a/xcsg/clipper_csg/clipper_profile.cpp b/xcsg/clipper_csg/clipper_profile.cpp index 3341466..f56e3ad 100644 --- a/xcsg/clipper_csg/clipper_profile.cpp +++ b/xcsg/clipper_csg/clipper_profile.cpp @@ -34,6 +34,11 @@ void clipper_profile::AddPaths(std::shared_ptr paths) } } +void clipper_profile::AddPath(const ClipperLib::Path& path) +{ + m_paths.push_back(path); +} + std::shared_ptr clipper_profile::polyset() { std::shared_ptr pset(new polyset2d()); @@ -53,17 +58,14 @@ std::shared_ptr clipper_profile::polyset() return pset; } - -void clipper_profile::fill_holes() +void clipper_profile::positive_profiles(std::list>& profiles ) { - // to fill the holes, we simply discard the negative paths - ClipperLib::Paths filled_paths; - filled_paths.reserve(m_paths.size()); for(size_t i=0; i prof = std::make_shared(); + prof->AddPath(m_paths[i]); + profiles.push_back(prof); } } - m_paths = filled_paths; } diff --git a/xcsg/clipper_csg/clipper_profile.h b/xcsg/clipper_csg/clipper_profile.h index 09851e9..e7e38de 100644 --- a/xcsg/clipper_csg/clipper_profile.h +++ b/xcsg/clipper_csg/clipper_profile.h @@ -19,6 +19,7 @@ #include "clipper_csg_config.h" #include "clipper.hpp" #include "polyset2d.h" +#include // A clipper_profile represents the result of successive 2d booleans // It can represent any complex 2d profile, possibly multiple polygons with holes. @@ -37,8 +38,12 @@ class clipper_profile { // return a set of polygons for this profile std::shared_ptr polyset(); - // fill holes in this profile - void fill_holes(); + // split this profile into a number of single contour profiles containing only positive winding order paths + // negative winding order paths are discareded + void positive_profiles(std::list>& profiles ); + +protected: + void AddPath( const ClipperLib::Path& path); private: ClipperLib::Paths m_paths; diff --git a/xcsg/xcsg_factory.cpp b/xcsg/xcsg_factory.cpp index 95af4ba..3b63c7f 100644 --- a/xcsg/xcsg_factory.cpp +++ b/xcsg/xcsg_factory.cpp @@ -70,7 +70,7 @@ xcsg_factory::xcsg_factory() m_shape2d_map.insert(std::make_pair("intersection2d",xcsg_factory::make_intersection2d)); m_shape2d_map.insert(std::make_pair("union2d",xcsg_factory::make_union2d)); m_shape2d_map.insert(std::make_pair("hull2d",xcsg_factory::make_hull2d)); - m_shape2d_map.insert(std::make_pair("fill2d",xcsg_factory::make_hull2d)); + m_shape2d_map.insert(std::make_pair("fill2d",xcsg_factory::make_fill2d)); m_shape2d_map.insert(std::make_pair("offset2d",xcsg_factory::make_offset2d)); } diff --git a/xcsg/xfill2d.cpp b/xcsg/xfill2d.cpp index 343eb94..128041a 100644 --- a/xcsg/xfill2d.cpp +++ b/xcsg/xfill2d.cpp @@ -48,8 +48,16 @@ std::shared_ptr xfill2d ::create_clipper_profile(const carve::m clipper_boolean csg; for(auto i=m_incl.begin(); i!=m_incl.end(); i++) { std::shared_ptr profile = (*i)->create_clipper_profile(t*get_transform()); - profile->fill_holes(); - csg.compute(profile,ClipperLib::ctUnion); + + // split the profile into single path profiles with only positive winding order + std::list> profiles; + profile->positive_profiles(profiles); + + // union the profiles to obtain a single profile again + // the effect is that all holes dissapear, but outer contours remain + for(auto& p : profiles) { + csg.compute(p,ClipperLib::ctUnion); + } } return csg.profile(); }