From a79013e7f3e492742377e29343ea95276d4214ca Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Thu, 19 Jan 2017 19:03:59 +0800 Subject: [PATCH] libarea: added CArea::Clip to handle open wires CArea::Clip enables ClipperLib open wire boolean operation as well as other settings (PolyFillType) for closed wires. --- src/Mod/Path/libarea/Area.h | 7 +++ src/Mod/Path/libarea/AreaClipper.cpp | 92 ++++++++++++++++------------ src/Mod/Path/libarea/clipper.hpp | 2 +- 3 files changed, 61 insertions(+), 40 deletions(-) diff --git a/src/Mod/Path/libarea/Area.h b/src/Mod/Path/libarea/Area.h index 224f48327..7a6634ac5 100644 --- a/src/Mod/Path/libarea/Area.h +++ b/src/Mod/Path/libarea/Area.h @@ -99,6 +99,13 @@ public: CAREA_PARAM_DECLARE(short,min_arc_points); CAREA_PARAM_DECLARE(short,max_arc_points); CAREA_PARAM_DECLARE(double,clipper_scale); + + // Following functions is add to operate on possible open curves + void PopulateClipper(ClipperLib::Clipper &c, ClipperLib::PolyType type) const; + void Clip(ClipperLib::ClipType op, + const CArea *a, + ClipperLib::PolyFillType subjFillType = ClipperLib::pftEvenOdd, + ClipperLib::PolyFillType clipFillType = ClipperLib::pftEvenOdd); }; enum eOverlapType diff --git a/src/Mod/Path/libarea/AreaClipper.cpp b/src/Mod/Path/libarea/AreaClipper.cpp index c8c7c7c50..bcb7ccd42 100644 --- a/src/Mod/Path/libarea/AreaClipper.cpp +++ b/src/Mod/Path/libarea/AreaClipper.cpp @@ -298,48 +298,14 @@ static void OffsetSpansWithObrounds(const CArea& area, TPolyPolygon &pp_new, dou } } -static void MakePolyPoly( const CArea& area, TPolyPolygon &pp, bool reverse = true ){ - pp.clear(); - - for(std::list::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++) - { - pts_for_AddVertex.clear(); - const CCurve& curve = *It; - const CVertex* prev_vertex = NULL; - for(std::list::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++) - { - const CVertex& vertex = *It2; - if(prev_vertex)AddVertex(vertex, prev_vertex); - prev_vertex = &vertex; - } - - TPolygon p; - p.resize(pts_for_AddVertex.size()); - if(reverse) - { - std::size_t i = pts_for_AddVertex.size() - 1;// clipper wants them the opposite way to CArea - for(std::list::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i--) - { - p[i] = It->int_point(); - } - } - else - { - unsigned int i = 0; - for(std::list::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i++) - { - p[i] = It->int_point(); - } - } - - pp.push_back(p); - } -} - -static void MakePoly(const CCurve& curve, TPolygon &p) +static void MakePoly(const CCurve& curve, TPolygon &p, bool reverse = false) { pts_for_AddVertex.clear(); const CVertex* prev_vertex = NULL; + + if(!curve.m_vertices.size()) return; + if(!curve.IsClosed()) AddVertex(curve.m_vertices.front(),NULL); + for (std::list::const_iterator It2 = curve.m_vertices.begin(); It2 != curve.m_vertices.end(); It2++) { const CVertex& vertex = *It2; @@ -348,6 +314,15 @@ static void MakePoly(const CCurve& curve, TPolygon &p) } p.resize(pts_for_AddVertex.size()); + if(reverse) + { + std::size_t i = pts_for_AddVertex.size() - 1;// clipper wants them the opposite way to CArea + for(std::list::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i--) + { + p[i] = It->int_point(); + } + } + else { unsigned int i = 0; for (std::list::iterator It = pts_for_AddVertex.begin(); It != pts_for_AddVertex.end(); It++, i++) @@ -357,6 +332,16 @@ static void MakePoly(const CCurve& curve, TPolygon &p) } } +static void MakePolyPoly( const CArea& area, TPolyPolygon &pp, bool reverse = true ){ + pp.clear(); + + for(std::list::const_iterator It = area.m_curves.begin(); It != area.m_curves.end(); It++) + { + pp.push_back(TPolygon()); + MakePoly(*It,pp.back(),reverse); + } +} + static void SetFromResult( CCurve& curve, TPolygon& p, bool reverse = true ) { if(CArea::m_clipper_clean_distance >= Point::tolerance) @@ -481,6 +466,35 @@ void CArea::Offset(double inwards_value) this->Reorder(); } +void CArea::PopulateClipper(Clipper &c, PolyType type) const +{ + for (std::list::const_iterator It = m_curves.begin(); It != m_curves.end(); It++) + { + const CCurve &curve = *It; + bool closed = curve.IsClosed(); + if(type == ptClip && !closed) + continue; + TPolygon p; + MakePoly(curve, p, false); + c.AddPath(p, type, closed); + } +} + +void CArea::Clip(ClipType op, const CArea *a, + PolyFillType subjFillType, + PolyFillType clipFillType) +{ + Clipper c; + c.StrictlySimple(CArea::m_clipper_simple); + PopulateClipper(c,ptSubject); + if(a) a->PopulateClipper(c,ptClip); + PolyTree tree; + c.Execute(op, tree, subjFillType,clipFillType); + TPolyPolygon solution; + PolyTreeToPaths(tree,solution); + SetFromResult(*this, solution); +} + void CArea::OffsetWithClipper(double offset, JoinType joinType/* =jtRound */, EndType endType/* =etOpenRound */, diff --git a/src/Mod/Path/libarea/clipper.hpp b/src/Mod/Path/libarea/clipper.hpp index 15af31e46..b88bffd79 100644 --- a/src/Mod/Path/libarea/clipper.hpp +++ b/src/Mod/Path/libarea/clipper.hpp @@ -44,7 +44,7 @@ //#define use_xyz //use_lines: Enables line clipping. Adds a very minor cost to performance. -//#define use_lines +#define use_lines //use_deprecated: Enables temporary support for the obsolete functions //#define use_deprecated