From 2bca1fc9f35fadee9f4f950791d822709d49bf0f Mon Sep 17 00:00:00 2001 From: Maciej Lisiewski Date: Wed, 31 May 2023 19:01:05 -0400 Subject: [PATCH] Fix Clipper2 build with GCC13 --- .../include/clipper2/clipper.engine.h | 36 +++-- .../Clipper2Lib/src/clipper.engine.cpp | 145 +++++++++--------- 2 files changed, 93 insertions(+), 88 deletions(-) diff --git a/src/clipper2/Clipper2Lib/include/clipper2/clipper.engine.h b/src/clipper2/Clipper2Lib/include/clipper2/clipper.engine.h index 34e216ac5..67383f213 100644 --- a/src/clipper2/Clipper2Lib/include/clipper2/clipper.engine.h +++ b/src/clipper2/Clipper2Lib/include/clipper2/clipper.engine.h @@ -17,6 +17,8 @@ constexpr auto CLIPPER2_VERSION = "1.0.6"; #include #include #include +#include +#include #include "clipper.core.h" namespace Clipper2Lib { @@ -31,19 +33,19 @@ namespace Clipper2Lib { //Note: all clipping operations except for Difference are commutative. enum class ClipType { None, Intersection, Union, Difference, Xor }; - + enum class PathType { Subject, Clip }; enum class VertexFlags : uint32_t { None = 0, OpenStart = 1, OpenEnd = 2, LocalMax = 4, LocalMin = 8 }; - constexpr enum VertexFlags operator &(enum VertexFlags a, enum VertexFlags b) + constexpr enum VertexFlags operator &(enum VertexFlags a, enum VertexFlags b) { return (enum VertexFlags)(uint32_t(a) & uint32_t(b)); } - constexpr enum VertexFlags operator |(enum VertexFlags a, enum VertexFlags b) + constexpr enum VertexFlags operator |(enum VertexFlags a, enum VertexFlags b) { return (enum VertexFlags)(uint32_t(a) | uint32_t(b)); } @@ -97,7 +99,7 @@ namespace Clipper2Lib { //Important: UP and DOWN here are premised on Y-axis positive down //displays, which is the orientation used in Clipper's development. /////////////////////////////////////////////////////////////////// - + struct Active { Point64 bot; Point64 top; @@ -168,7 +170,7 @@ namespace Clipper2Lib { std::vector::iterator current_locmin_iter_; std::vector vertex_lists_; std::priority_queue scanline_list_; - std::vector intersect_nodes_; + std::vector intersect_nodes_; std::vector joiner_list_; //pointers in case of memory reallocs void Reset(); void InsertScanline(int64_t y); @@ -197,7 +199,7 @@ namespace Clipper2Lib { void ProcessIntersectList(); void SwapPositionsInAEL(Active& edge1, Active& edge2); OutPt* AddOutPt(const Active &e, const Point64& pt); - OutPt* AddLocalMinPoly(Active &e1, Active &e2, + OutPt* AddLocalMinPoly(Active &e1, Active &e2, const Point64& pt, bool is_new = false); OutPt* AddLocalMaxPoly(Active &e1, Active &e2, const Point64& pt); void DoHorizontal(Active &horz); @@ -254,7 +256,7 @@ namespace Clipper2Lib { PolyPath* parent_; public: PolyPath(PolyPath* parent = nullptr): parent_(parent){} - virtual ~PolyPath() { Clear(); }; + virtual ~PolyPath() { Clear(); }; //https://en.cppreference.com/w/cpp/language/rule_of_three PolyPath(const PolyPath&) = delete; PolyPath& operator=(const PolyPath&) = delete; @@ -274,7 +276,7 @@ namespace Clipper2Lib { const PolyPath* Parent() const { return parent_; } - bool IsHole() const + bool IsHole() const { const PolyPath* pp = parent_; bool is_hole = pp; @@ -364,13 +366,13 @@ namespace Clipper2Lib { PathD polygon_; typedef typename std::vector::const_iterator ppD_itor; public: - PolyPathD(PolyPathD* parent = nullptr) : PolyPath(parent) + PolyPathD(PolyPathD* parent = nullptr) : PolyPath(parent) { inv_scale_ = parent ? parent->inv_scale_ : 1.0; } - PolyPathD* operator [] (size_t index) - { - return static_cast(childs_[index]); + PolyPathD* operator [] (size_t index) + { + return static_cast(childs_[index]); } ppD_itor begin() const { return childs_.cbegin(); } ppD_itor end() const { return childs_.cend(); } @@ -437,7 +439,7 @@ namespace Clipper2Lib { return Execute(clip_type, fill_rule, closed_paths, dummy); } - bool Execute(ClipType clip_type, FillRule fill_rule, + bool Execute(ClipType clip_type, FillRule fill_rule, Paths64& closed_paths, Paths64& open_paths) { closed_paths.clear(); @@ -509,12 +511,12 @@ namespace Clipper2Lib { void CheckCallback() { if(zCallback_) - // if the user defined float point callback has been assigned + // if the user defined float point callback has been assigned // then assign the proxy callback function - ClipperBase::zCallback_ = + ClipperBase::zCallback_ = std::bind(&ClipperD::ZCB, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, - std::placeholders::_4, std::placeholders::_5); + std::placeholders::_4, std::placeholders::_5); else ClipperBase::zCallback_ = nullptr; } @@ -581,6 +583,6 @@ namespace Clipper2Lib { }; -} // namespace +} // namespace #endif // CLIPPER_ENGINE_H diff --git a/src/clipper2/Clipper2Lib/src/clipper.engine.cpp b/src/clipper2/Clipper2Lib/src/clipper.engine.cpp index 0c0d47f37..069b52392 100644 --- a/src/clipper2/Clipper2Lib/src/clipper.engine.cpp +++ b/src/clipper2/Clipper2Lib/src/clipper.engine.cpp @@ -15,6 +15,9 @@ #include #include "clipper2/clipper.engine.h" +#include +#include + namespace Clipper2Lib { static const double FloatingPointTolerance = 1.0e-12; @@ -94,7 +97,7 @@ namespace Clipper2Lib { inline bool IsOpenEnd(const Vertex& v) { - return (v.flags & (VertexFlags::OpenStart | VertexFlags::OpenEnd)) != + return (v.flags & (VertexFlags::OpenStart | VertexFlags::OpenEnd)) != VertexFlags::None; } @@ -189,8 +192,8 @@ namespace Clipper2Lib { } inline Point64 GetEndE1ClosestToEndE2( - const Active& e1, const Active& e2) - { + const Active& e1, const Active& e2) + { double d[] = { DistanceSqr(e1.bot, e2.bot), DistanceSqr(e1.top, e2.top), @@ -204,7 +207,7 @@ namespace Clipper2Lib { if (d[i] < d[idx]) idx = i; if (d[i] == 0) break; } - switch (idx) + switch (idx) { case 1: case 2: return e1.top; default: return e1.bot; @@ -214,7 +217,7 @@ namespace Clipper2Lib { Point64 GetIntersectPoint(const Active& e1, const Active& e2) { double b1, b2, q = (e1.dx - e2.dx); - if (std::abs(q) < 1e-5) // 1e-5 is a rough empirical limit + if (std::abs(q) < 1e-5) // 1e-5 is a rough empirical limit return GetEndE1ClosestToEndE2(e1, e2); // ie almost parallel if (e1.dx == 0) @@ -235,7 +238,7 @@ namespace Clipper2Lib { { b1 = e1.bot.x - e1.bot.y * e1.dx; b2 = e2.bot.x - e2.bot.y * e2.dx; - + q = (b2 - b1) / q; return (abs(e1.dx) < abs(e2.dx)) ? Point64(static_cast(e1.dx * q + b1), @@ -306,7 +309,7 @@ namespace Clipper2Lib { //PrevPrevVertex: useful to get the (inverted Y-axis) top of the - //alternate edge (ie left or right bound) during edge insertion. + //alternate edge (ie left or right bound) during edge insertion. inline Vertex* PrevPrevVertex(const Active& ae) { if (ae.wind_dx > 0) @@ -353,7 +356,7 @@ namespace Clipper2Lib { while (result->next->pt.y == result->pt.y) result = result->next; else while (result->prev->pt.y == result->pt.y) result = result->prev; - if (!IsMaxima(*result)) result = nullptr; // not a maxima + if (!IsMaxima(*result)) result = nullptr; // not a maxima return result; } @@ -494,7 +497,7 @@ namespace Clipper2Lib { return result * 0.5; } - inline double AreaTriangle(const Point64& pt1, + inline double AreaTriangle(const Point64& pt1, const Point64& pt2, const Point64& pt3) { return (static_cast(pt3.y + pt1.y) * static_cast(pt3.x - pt1.x) + @@ -630,7 +633,7 @@ namespace Clipper2Lib { Clear(); } - void ClipperBase::DeleteEdges(Active*& e) + void ClipperBase::DeleteEdges(Active*& e) { while (e) { @@ -681,7 +684,7 @@ namespace Clipper2Lib { void ClipperBase::SetZ(const Active& e1, const Active& e2, Point64& ip) { if (!zCallback_) return; - // prioritize subject over clip vertices by passing + // prioritize subject over clip vertices by passing // subject vertices before clip vertices in the callback if (GetPolyType(e1) == PathType::Subject) { @@ -872,19 +875,19 @@ namespace Clipper2Lib { case FillRule::EvenOdd: break; case FillRule::NonZero: - if (abs(e.wind_cnt) != 1) return false; + if (abs(e.wind_cnt) != 1) return false; break; case FillRule::Positive: - if (e.wind_cnt != 1) return false; + if (e.wind_cnt != 1) return false; break; case FillRule::Negative: - if (e.wind_cnt != -1) return false; + if (e.wind_cnt != -1) return false; break; } switch (cliptype_) { - case ClipType::None: + case ClipType::None: return false; case ClipType::Intersection: switch (fillrule_) @@ -914,17 +917,17 @@ namespace Clipper2Lib { bool result; switch (fillrule_) { - case FillRule::Positive: - result = (e.wind_cnt2 <= 0); + case FillRule::Positive: + result = (e.wind_cnt2 <= 0); break; case FillRule::Negative: - result = (e.wind_cnt2 >= 0); + result = (e.wind_cnt2 >= 0); break; - default: + default: result = (e.wind_cnt2 == 0); } if (GetPolyType(e) == PathType::Subject) - return result; + return result; else return !result; break; @@ -940,15 +943,15 @@ namespace Clipper2Lib { bool is_in_clip, is_in_subj; switch (fillrule_) { - case FillRule::Positive: - is_in_clip = e.wind_cnt2 > 0; + case FillRule::Positive: + is_in_clip = e.wind_cnt2 > 0; is_in_subj = e.wind_cnt > 0; break; - case FillRule::Negative: - is_in_clip = e.wind_cnt2 < 0; + case FillRule::Negative: + is_in_clip = e.wind_cnt2 < 0; is_in_subj = e.wind_cnt < 0; break; - default: + default: is_in_clip = e.wind_cnt2 != 0; is_in_subj = e.wind_cnt != 0; } @@ -1085,15 +1088,15 @@ namespace Clipper2Lib { //the direction they're about to turn if (!IsMaxima(resident) && (resident.top.y > newcomer.top.y)) { - return CrossProduct(newcomer.bot, + return CrossProduct(newcomer.bot, resident.top, NextVertex(resident)->pt) <= 0; } - else if (!IsMaxima(newcomer) && (newcomer.top.y > resident.top.y)) + else if (!IsMaxima(newcomer) && (newcomer.top.y > resident.top.y)) { return CrossProduct(newcomer.bot, newcomer.top, NextVertex(newcomer)->pt) >= 0; } - + int64_t y = newcomer.bot.y; bool newcomerIsLeft = newcomer.is_left_bound; @@ -1103,7 +1106,7 @@ namespace Clipper2Lib { else if (resident.is_left_bound != newcomerIsLeft) return newcomerIsLeft; else if (CrossProduct(PrevPrevVertex(resident)->pt, - resident.bot, resident.top) == 0) return true; + resident.bot, resident.top) == 0) return true; else //compare turning direction of the alternate bound return (CrossProduct(PrevPrevVertex(resident)->pt, @@ -1319,7 +1322,7 @@ namespace Clipper2Lib { SetSides(*outrec, e1, e2); else SetSides(*outrec, e2, e1); - } + } else { Active* prevHotEdge = GetPrevHotEdge(e1); @@ -1335,7 +1338,7 @@ namespace Clipper2Lib { else SetSides(*outrec, e1, e2); } - else + else { outrec->owner = nullptr; if (is_new) @@ -1344,7 +1347,7 @@ namespace Clipper2Lib { SetSides(*outrec, e2, e1); } } - + OutPt* op = new OutPt(pt, outrec); outrec->pts = op; return op; @@ -1359,7 +1362,7 @@ namespace Clipper2Lib { SwapFrontBackSides(*e1.outrec); else if (IsOpenEnd(e2)) SwapFrontBackSides(*e2.outrec); - else + else { succeeded_ = false; return nullptr; @@ -1369,7 +1372,7 @@ namespace Clipper2Lib { OutPt* result = AddOutPt(e1, pt); if (e1.outrec == e2.outrec) { - OutRec& outrec = *e1.outrec; + OutRec& outrec = *e1.outrec; outrec.pts = result; UncoupleOutRec(e1); @@ -1523,7 +1526,7 @@ namespace Clipper2Lib { void ClipperBase::DoSplitOp(OutRec* outrec, OutPt* splitOp) { - // splitOp.prev -> splitOp && + // splitOp.prev -> splitOp && // splitOp.next -> splitOp.next.next are intersecting OutPt* prevOp = splitOp->prev; OutPt* nextNextOp = splitOp->next->next; @@ -1572,7 +1575,7 @@ namespace Clipper2Lib { SafeDeleteOutPtJoiners(splitOp->next); SafeDeleteOutPtJoiners(splitOp); - if (absArea2 >= 1 && + if (absArea2 >= 1 && (absArea2 > absArea1 || (area2 > 0) == (area1 > 0))) { OutRec* newOutRec = new OutRec(); @@ -1762,7 +1765,7 @@ namespace Clipper2Lib { else result = result->next_in_ael; } result = e->prev_in_ael; - while (result) + while (result) { if (result->local_min == e->local_min) return result; else if (!IsHorizontal(*result) && e->bot != result->bot) return nullptr; @@ -1791,14 +1794,14 @@ namespace Clipper2Lib { edge_c = &e1; } - if (abs(edge_c->wind_cnt) != 1) return nullptr; + if (abs(edge_c->wind_cnt) != 1) return nullptr; switch (cliptype_) { - case ClipType::Union: - if (!IsHotEdge(*edge_c)) return nullptr; + case ClipType::Union: + if (!IsHotEdge(*edge_c)) return nullptr; break; - default: - if (edge_c->local_min->polytype == PathType::Subject) + default: + if (edge_c->local_min->polytype == PathType::Subject) return nullptr; } @@ -1821,11 +1824,11 @@ namespace Clipper2Lib { edge_o->outrec = nullptr; return resultOp; } - + //horizontal edges can pass under open paths at a LocMins else if (pt == edge_o->local_min->vertex->pt && !IsOpenEnd(*edge_o->local_min->vertex)) - { + { //find the other side of the LocMin and //if it's 'hot' join up with it ... Active* e3 = FindEdgeWithMatchingLocMin(edge_o); @@ -1833,7 +1836,7 @@ namespace Clipper2Lib { { edge_o->outrec = e3->outrec; if (edge_o->wind_dx > 0) - SetSides(*e3->outrec, *edge_o, *e3); + SetSides(*e3->outrec, *edge_o, *e3); else SetSides(*e3->outrec, *e3, *edge_o); return e3->outrec->pts; @@ -1847,7 +1850,7 @@ namespace Clipper2Lib { //MANAGING CLOSED PATHS FROM HERE ON - + //UPDATE WINDING COUNTS... int old_e1_windcnt, old_e2_windcnt; @@ -1913,7 +1916,7 @@ namespace Clipper2Lib { { return nullptr; } - + //NOW PROCESS THE INTERSECTION ... OutPt* resultOp = nullptr; //if both edges are 'hot' ... @@ -2282,7 +2285,7 @@ namespace Clipper2Lib { inline bool HorzIsSpike(const Active& horzEdge) { Point64 nextPt = NextVertex(horzEdge)->pt; - return (nextPt.y == horzEdge.bot.y) && + return (nextPt.y == horzEdge.bot.y) && (horzEdge.bot.x < horzEdge.top.x) != (horzEdge.top.x < nextPt.x); } @@ -2295,7 +2298,7 @@ namespace Clipper2Lib { //always trim 180 deg. spikes (in closed paths) //but otherwise break if preserveCollinear = true if (preserveCollinear && - ((pt.x < horzEdge.top.x) != (horzEdge.bot.x < horzEdge.top.x))) + ((pt.x < horzEdge.top.x) != (horzEdge.bot.x < horzEdge.top.x))) break; horzEdge.vertex_top = NextVertex(horzEdge); @@ -2353,11 +2356,11 @@ namespace Clipper2Lib { OutPt* op; while (true) // loop through consec. horizontal edges - { + { if (horzIsOpen && IsMaxima(horz) && !IsOpenEnd(horz)) { vertex_max = GetCurrYMaximaVertex(horz); - if (vertex_max) + if (vertex_max) max_pair = GetHorzMaximaPair(horz, vertex_max); } @@ -2388,7 +2391,7 @@ namespace Clipper2Lib { //if horzEdge is a maxima, keep going until we reach //its maxima pair, otherwise check for break conditions - if (vertex_max != horz.vertex_top || IsOpenEnd(horz)) + if (vertex_max != horz.vertex_top || IsOpenEnd(horz)) { //otherwise stop when 'ae' is beyond the end of the horizontal line if ((is_left_to_right && e->curr_x > horz_right) || @@ -2467,15 +2470,15 @@ namespace Clipper2Lib { { AddOutPt(horz, horz.top); if (IsFront(horz)) - horz.outrec->front_edge = nullptr; + horz.outrec->front_edge = nullptr; else horz.outrec->back_edge = nullptr; horz.outrec = nullptr; } - DeleteFromAEL(horz); + DeleteFromAEL(horz); return; } - else if (NextVertex(horz)->pt.y != horz.top.y) + else if (NextVertex(horz)->pt.y != horz.top.y) break; //still more horizontals in bound to process ... @@ -2486,7 +2489,7 @@ namespace Clipper2Lib { if (PreserveCollinear && !horzIsOpen && HorzIsSpike(horz)) TrimHorz(horz, true); - is_left_to_right = + is_left_to_right = ResetHorzDirection(horz, max_pair, horz_left, horz_right); } @@ -2499,7 +2502,7 @@ namespace Clipper2Lib { else op = nullptr; - if ((horzIsOpen && !IsOpenEnd(horz)) || + if ((horzIsOpen && !IsOpenEnd(horz)) || (!horzIsOpen && vertex_max != horz.vertex_top)) { UpdateEdgeIntoAEL(&horz); // this is the end of an intermediate horiz. @@ -2516,7 +2519,7 @@ namespace Clipper2Lib { AddJoin(op2, op); } } - else if (IsHotEdge(horz)) + else if (IsHotEdge(horz)) AddLocalMaxPoly(horz, *max_pair, horz.top); else { @@ -2966,7 +2969,7 @@ namespace Clipper2Lib { OutRec* outrec = ProcessJoin(j); CleanCollinear(outrec); } - else + else delete j; } @@ -3015,7 +3018,7 @@ namespace Clipper2Lib { bool CollinearSegsOverlap(const Point64& seg1a, const Point64& seg1b, const Point64& seg2a, const Point64& seg2b) { - //precondition: seg1 and seg2 are collinear + //precondition: seg1 and seg2 are collinear if (seg1a.x == seg1b.x) { if (seg2a.x != seg1a.x || seg2a.x != seg2b.x) return false; @@ -3146,7 +3149,7 @@ namespace Clipper2Lib { { or1->pts = op1; or2->pts = nullptr; - if (or1->owner && (!or2->owner || + if (or1->owner && (!or2->owner || or2->owner->idx < or1->owner->idx)) or1->owner = or2->owner; or2->owner = or1; @@ -3156,7 +3159,7 @@ namespace Clipper2Lib { result = or2; or2->pts = op1; or1->pts = nullptr; - if (or2->owner && (!or1->owner || + if (or2->owner && (!or1->owner || or1->owner->idx < or2->owner->idx)) or2->owner = or1->owner; or1->owner = or2; @@ -3207,7 +3210,7 @@ namespace Clipper2Lib { { or1->pts = op1; or2->pts = nullptr; - if (or1->owner && (!or2->owner || + if (or1->owner && (!or2->owner || or2->owner->idx < or1->owner->idx)) or1->owner = or2->owner; or2->owner = or1; @@ -3217,9 +3220,9 @@ namespace Clipper2Lib { result = or2; or2->pts = op1; or1->pts = nullptr; - if (or2->owner && (!or1->owner || + if (or2->owner && (!or1->owner || or1->owner->idx < or2->owner->idx)) - or2->owner = or1->owner; + or2->owner = or1->owner; or1->owner = or2; } } @@ -3310,11 +3313,11 @@ namespace Clipper2Lib { if (pt.y > result.bottom) result.bottom = pt.y; } return result; - } + } bool BuildPath64(OutPt* op, bool reverse, bool isOpen, Path64& path) { - if (op->next == op || (!isOpen && op->next == op->prev)) + if (op->next == op || (!isOpen && op->next == op->prev)) return false; path.resize(0); @@ -3355,9 +3358,9 @@ namespace Clipper2Lib { if (owner->bounds.IsEmpty()) owner->bounds = GetBounds(owner->path); bool is_inside_owner_bounds = owner->bounds.Contains(outrec->bounds); - // while looking for the correct owner, check the owner's - // splits **before** checking the owner itself because - // splits can occur internally, and checking the owner + // while looking for the correct owner, check the owner's + // splits **before** checking the owner itself because + // splits can occur internally, and checking the owner // first would miss the inner split's true ownership if (owner->splits) { @@ -3388,7 +3391,7 @@ namespace Clipper2Lib { { if (is_inside_owner_bounds && Path1InsidePath2(outrec, outrec->owner)) return true; - // otherwise keep trying with owner's owner + // otherwise keep trying with owner's owner outrec->owner = outrec->owner->owner; if (!outrec->owner) return true; // true or false is_inside_owner_bounds = outrec->owner->bounds.Contains(outrec->bounds);