Fix Clipper2 build with GCC13

This commit is contained in:
Maciej Lisiewski 2023-05-31 19:01:05 -04:00 committed by Lane.Wei
parent fbe776aaaa
commit 2bca1fc9f3
2 changed files with 93 additions and 88 deletions

View File

@ -17,6 +17,8 @@ constexpr auto CLIPPER2_VERSION = "1.0.6";
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include <functional> #include <functional>
#include <cstddef>
#include <cstdint>
#include "clipper.core.h" #include "clipper.core.h"
namespace Clipper2Lib { namespace Clipper2Lib {
@ -31,19 +33,19 @@ namespace Clipper2Lib {
//Note: all clipping operations except for Difference are commutative. //Note: all clipping operations except for Difference are commutative.
enum class ClipType { None, Intersection, Union, Difference, Xor }; enum class ClipType { None, Intersection, Union, Difference, Xor };
enum class PathType { Subject, Clip }; enum class PathType { Subject, Clip };
enum class VertexFlags : uint32_t { enum class VertexFlags : uint32_t {
None = 0, OpenStart = 1, OpenEnd = 2, LocalMax = 4, LocalMin = 8 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)); 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)); 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 //Important: UP and DOWN here are premised on Y-axis positive down
//displays, which is the orientation used in Clipper's development. //displays, which is the orientation used in Clipper's development.
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
struct Active { struct Active {
Point64 bot; Point64 bot;
Point64 top; Point64 top;
@ -168,7 +170,7 @@ namespace Clipper2Lib {
std::vector<LocalMinima*>::iterator current_locmin_iter_; std::vector<LocalMinima*>::iterator current_locmin_iter_;
std::vector<Vertex*> vertex_lists_; std::vector<Vertex*> vertex_lists_;
std::priority_queue<int64_t> scanline_list_; std::priority_queue<int64_t> scanline_list_;
std::vector<IntersectNode> intersect_nodes_; std::vector<IntersectNode> intersect_nodes_;
std::vector<Joiner*> joiner_list_; //pointers in case of memory reallocs std::vector<Joiner*> joiner_list_; //pointers in case of memory reallocs
void Reset(); void Reset();
void InsertScanline(int64_t y); void InsertScanline(int64_t y);
@ -197,7 +199,7 @@ namespace Clipper2Lib {
void ProcessIntersectList(); void ProcessIntersectList();
void SwapPositionsInAEL(Active& edge1, Active& edge2); void SwapPositionsInAEL(Active& edge1, Active& edge2);
OutPt* AddOutPt(const Active &e, const Point64& pt); 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); const Point64& pt, bool is_new = false);
OutPt* AddLocalMaxPoly(Active &e1, Active &e2, const Point64& pt); OutPt* AddLocalMaxPoly(Active &e1, Active &e2, const Point64& pt);
void DoHorizontal(Active &horz); void DoHorizontal(Active &horz);
@ -254,7 +256,7 @@ namespace Clipper2Lib {
PolyPath* parent_; PolyPath* parent_;
public: public:
PolyPath(PolyPath* parent = nullptr): parent_(parent){} PolyPath(PolyPath* parent = nullptr): parent_(parent){}
virtual ~PolyPath() { Clear(); }; virtual ~PolyPath() { Clear(); };
//https://en.cppreference.com/w/cpp/language/rule_of_three //https://en.cppreference.com/w/cpp/language/rule_of_three
PolyPath(const PolyPath&) = delete; PolyPath(const PolyPath&) = delete;
PolyPath& operator=(const PolyPath&) = delete; PolyPath& operator=(const PolyPath&) = delete;
@ -274,7 +276,7 @@ namespace Clipper2Lib {
const PolyPath* Parent() const { return parent_; } const PolyPath* Parent() const { return parent_; }
bool IsHole() const bool IsHole() const
{ {
const PolyPath* pp = parent_; const PolyPath* pp = parent_;
bool is_hole = pp; bool is_hole = pp;
@ -364,13 +366,13 @@ namespace Clipper2Lib {
PathD polygon_; PathD polygon_;
typedef typename std::vector<PolyPathD*>::const_iterator ppD_itor; typedef typename std::vector<PolyPathD*>::const_iterator ppD_itor;
public: public:
PolyPathD(PolyPathD* parent = nullptr) : PolyPath(parent) PolyPathD(PolyPathD* parent = nullptr) : PolyPath(parent)
{ {
inv_scale_ = parent ? parent->inv_scale_ : 1.0; inv_scale_ = parent ? parent->inv_scale_ : 1.0;
} }
PolyPathD* operator [] (size_t index) PolyPathD* operator [] (size_t index)
{ {
return static_cast<PolyPathD*>(childs_[index]); return static_cast<PolyPathD*>(childs_[index]);
} }
ppD_itor begin() const { return childs_.cbegin(); } ppD_itor begin() const { return childs_.cbegin(); }
ppD_itor end() const { return childs_.cend(); } ppD_itor end() const { return childs_.cend(); }
@ -437,7 +439,7 @@ namespace Clipper2Lib {
return Execute(clip_type, fill_rule, closed_paths, dummy); 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) Paths64& closed_paths, Paths64& open_paths)
{ {
closed_paths.clear(); closed_paths.clear();
@ -509,12 +511,12 @@ namespace Clipper2Lib {
void CheckCallback() void CheckCallback()
{ {
if(zCallback_) 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 // then assign the proxy callback function
ClipperBase::zCallback_ = ClipperBase::zCallback_ =
std::bind(&ClipperD::ZCB, this, std::placeholders::_1, std::bind(&ClipperD::ZCB, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3, std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4, std::placeholders::_5); std::placeholders::_4, std::placeholders::_5);
else else
ClipperBase::zCallback_ = nullptr; ClipperBase::zCallback_ = nullptr;
} }
@ -581,6 +583,6 @@ namespace Clipper2Lib {
}; };
} // namespace } // namespace
#endif // CLIPPER_ENGINE_H #endif // CLIPPER_ENGINE_H

View File

@ -15,6 +15,9 @@
#include <algorithm> #include <algorithm>
#include "clipper2/clipper.engine.h" #include "clipper2/clipper.engine.h"
#include <cstddef>
#include <cstdint>
namespace Clipper2Lib { namespace Clipper2Lib {
static const double FloatingPointTolerance = 1.0e-12; static const double FloatingPointTolerance = 1.0e-12;
@ -94,7 +97,7 @@ namespace Clipper2Lib {
inline bool IsOpenEnd(const Vertex& v) inline bool IsOpenEnd(const Vertex& v)
{ {
return (v.flags & (VertexFlags::OpenStart | VertexFlags::OpenEnd)) != return (v.flags & (VertexFlags::OpenStart | VertexFlags::OpenEnd)) !=
VertexFlags::None; VertexFlags::None;
} }
@ -189,8 +192,8 @@ namespace Clipper2Lib {
} }
inline Point64 GetEndE1ClosestToEndE2( inline Point64 GetEndE1ClosestToEndE2(
const Active& e1, const Active& e2) const Active& e1, const Active& e2)
{ {
double d[] = { double d[] = {
DistanceSqr(e1.bot, e2.bot), DistanceSqr(e1.bot, e2.bot),
DistanceSqr(e1.top, e2.top), DistanceSqr(e1.top, e2.top),
@ -204,7 +207,7 @@ namespace Clipper2Lib {
if (d[i] < d[idx]) idx = i; if (d[i] < d[idx]) idx = i;
if (d[i] == 0) break; if (d[i] == 0) break;
} }
switch (idx) switch (idx)
{ {
case 1: case 2: return e1.top; case 1: case 2: return e1.top;
default: return e1.bot; default: return e1.bot;
@ -214,7 +217,7 @@ namespace Clipper2Lib {
Point64 GetIntersectPoint(const Active& e1, const Active& e2) Point64 GetIntersectPoint(const Active& e1, const Active& e2)
{ {
double b1, b2, q = (e1.dx - e2.dx); 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 return GetEndE1ClosestToEndE2(e1, e2); // ie almost parallel
if (e1.dx == 0) if (e1.dx == 0)
@ -235,7 +238,7 @@ namespace Clipper2Lib {
{ {
b1 = e1.bot.x - e1.bot.y * e1.dx; b1 = e1.bot.x - e1.bot.y * e1.dx;
b2 = e2.bot.x - e2.bot.y * e2.dx; b2 = e2.bot.x - e2.bot.y * e2.dx;
q = (b2 - b1) / q; q = (b2 - b1) / q;
return (abs(e1.dx) < abs(e2.dx)) ? return (abs(e1.dx) < abs(e2.dx)) ?
Point64(static_cast<int64_t>(e1.dx * q + b1), Point64(static_cast<int64_t>(e1.dx * q + b1),
@ -306,7 +309,7 @@ namespace Clipper2Lib {
//PrevPrevVertex: useful to get the (inverted Y-axis) top of the //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) inline Vertex* PrevPrevVertex(const Active& ae)
{ {
if (ae.wind_dx > 0) if (ae.wind_dx > 0)
@ -353,7 +356,7 @@ namespace Clipper2Lib {
while (result->next->pt.y == result->pt.y) result = result->next; while (result->next->pt.y == result->pt.y) result = result->next;
else else
while (result->prev->pt.y == result->pt.y) result = result->prev; 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; return result;
} }
@ -494,7 +497,7 @@ namespace Clipper2Lib {
return result * 0.5; return result * 0.5;
} }
inline double AreaTriangle(const Point64& pt1, inline double AreaTriangle(const Point64& pt1,
const Point64& pt2, const Point64& pt3) const Point64& pt2, const Point64& pt3)
{ {
return (static_cast<double>(pt3.y + pt1.y) * static_cast<double>(pt3.x - pt1.x) + return (static_cast<double>(pt3.y + pt1.y) * static_cast<double>(pt3.x - pt1.x) +
@ -630,7 +633,7 @@ namespace Clipper2Lib {
Clear(); Clear();
} }
void ClipperBase::DeleteEdges(Active*& e) void ClipperBase::DeleteEdges(Active*& e)
{ {
while (e) while (e)
{ {
@ -681,7 +684,7 @@ namespace Clipper2Lib {
void ClipperBase::SetZ(const Active& e1, const Active& e2, Point64& ip) void ClipperBase::SetZ(const Active& e1, const Active& e2, Point64& ip)
{ {
if (!zCallback_) return; 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 // subject vertices before clip vertices in the callback
if (GetPolyType(e1) == PathType::Subject) if (GetPolyType(e1) == PathType::Subject)
{ {
@ -872,19 +875,19 @@ namespace Clipper2Lib {
case FillRule::EvenOdd: case FillRule::EvenOdd:
break; break;
case FillRule::NonZero: case FillRule::NonZero:
if (abs(e.wind_cnt) != 1) return false; if (abs(e.wind_cnt) != 1) return false;
break; break;
case FillRule::Positive: case FillRule::Positive:
if (e.wind_cnt != 1) return false; if (e.wind_cnt != 1) return false;
break; break;
case FillRule::Negative: case FillRule::Negative:
if (e.wind_cnt != -1) return false; if (e.wind_cnt != -1) return false;
break; break;
} }
switch (cliptype_) switch (cliptype_)
{ {
case ClipType::None: case ClipType::None:
return false; return false;
case ClipType::Intersection: case ClipType::Intersection:
switch (fillrule_) switch (fillrule_)
@ -914,17 +917,17 @@ namespace Clipper2Lib {
bool result; bool result;
switch (fillrule_) switch (fillrule_)
{ {
case FillRule::Positive: case FillRule::Positive:
result = (e.wind_cnt2 <= 0); result = (e.wind_cnt2 <= 0);
break; break;
case FillRule::Negative: case FillRule::Negative:
result = (e.wind_cnt2 >= 0); result = (e.wind_cnt2 >= 0);
break; break;
default: default:
result = (e.wind_cnt2 == 0); result = (e.wind_cnt2 == 0);
} }
if (GetPolyType(e) == PathType::Subject) if (GetPolyType(e) == PathType::Subject)
return result; return result;
else else
return !result; return !result;
break; break;
@ -940,15 +943,15 @@ namespace Clipper2Lib {
bool is_in_clip, is_in_subj; bool is_in_clip, is_in_subj;
switch (fillrule_) switch (fillrule_)
{ {
case FillRule::Positive: case FillRule::Positive:
is_in_clip = e.wind_cnt2 > 0; is_in_clip = e.wind_cnt2 > 0;
is_in_subj = e.wind_cnt > 0; is_in_subj = e.wind_cnt > 0;
break; break;
case FillRule::Negative: case FillRule::Negative:
is_in_clip = e.wind_cnt2 < 0; is_in_clip = e.wind_cnt2 < 0;
is_in_subj = e.wind_cnt < 0; is_in_subj = e.wind_cnt < 0;
break; break;
default: default:
is_in_clip = e.wind_cnt2 != 0; is_in_clip = e.wind_cnt2 != 0;
is_in_subj = e.wind_cnt != 0; is_in_subj = e.wind_cnt != 0;
} }
@ -1085,15 +1088,15 @@ namespace Clipper2Lib {
//the direction they're about to turn //the direction they're about to turn
if (!IsMaxima(resident) && (resident.top.y > newcomer.top.y)) if (!IsMaxima(resident) && (resident.top.y > newcomer.top.y))
{ {
return CrossProduct(newcomer.bot, return CrossProduct(newcomer.bot,
resident.top, NextVertex(resident)->pt) <= 0; 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, return CrossProduct(newcomer.bot,
newcomer.top, NextVertex(newcomer)->pt) >= 0; newcomer.top, NextVertex(newcomer)->pt) >= 0;
} }
int64_t y = newcomer.bot.y; int64_t y = newcomer.bot.y;
bool newcomerIsLeft = newcomer.is_left_bound; bool newcomerIsLeft = newcomer.is_left_bound;
@ -1103,7 +1106,7 @@ namespace Clipper2Lib {
else if (resident.is_left_bound != newcomerIsLeft) else if (resident.is_left_bound != newcomerIsLeft)
return newcomerIsLeft; return newcomerIsLeft;
else if (CrossProduct(PrevPrevVertex(resident)->pt, else if (CrossProduct(PrevPrevVertex(resident)->pt,
resident.bot, resident.top) == 0) return true; resident.bot, resident.top) == 0) return true;
else else
//compare turning direction of the alternate bound //compare turning direction of the alternate bound
return (CrossProduct(PrevPrevVertex(resident)->pt, return (CrossProduct(PrevPrevVertex(resident)->pt,
@ -1319,7 +1322,7 @@ namespace Clipper2Lib {
SetSides(*outrec, e1, e2); SetSides(*outrec, e1, e2);
else else
SetSides(*outrec, e2, e1); SetSides(*outrec, e2, e1);
} }
else else
{ {
Active* prevHotEdge = GetPrevHotEdge(e1); Active* prevHotEdge = GetPrevHotEdge(e1);
@ -1335,7 +1338,7 @@ namespace Clipper2Lib {
else else
SetSides(*outrec, e1, e2); SetSides(*outrec, e1, e2);
} }
else else
{ {
outrec->owner = nullptr; outrec->owner = nullptr;
if (is_new) if (is_new)
@ -1344,7 +1347,7 @@ namespace Clipper2Lib {
SetSides(*outrec, e2, e1); SetSides(*outrec, e2, e1);
} }
} }
OutPt* op = new OutPt(pt, outrec); OutPt* op = new OutPt(pt, outrec);
outrec->pts = op; outrec->pts = op;
return op; return op;
@ -1359,7 +1362,7 @@ namespace Clipper2Lib {
SwapFrontBackSides(*e1.outrec); SwapFrontBackSides(*e1.outrec);
else if (IsOpenEnd(e2)) else if (IsOpenEnd(e2))
SwapFrontBackSides(*e2.outrec); SwapFrontBackSides(*e2.outrec);
else else
{ {
succeeded_ = false; succeeded_ = false;
return nullptr; return nullptr;
@ -1369,7 +1372,7 @@ namespace Clipper2Lib {
OutPt* result = AddOutPt(e1, pt); OutPt* result = AddOutPt(e1, pt);
if (e1.outrec == e2.outrec) if (e1.outrec == e2.outrec)
{ {
OutRec& outrec = *e1.outrec; OutRec& outrec = *e1.outrec;
outrec.pts = result; outrec.pts = result;
UncoupleOutRec(e1); UncoupleOutRec(e1);
@ -1523,7 +1526,7 @@ namespace Clipper2Lib {
void ClipperBase::DoSplitOp(OutRec* outrec, OutPt* splitOp) void ClipperBase::DoSplitOp(OutRec* outrec, OutPt* splitOp)
{ {
// splitOp.prev -> splitOp && // splitOp.prev -> splitOp &&
// splitOp.next -> splitOp.next.next are intersecting // splitOp.next -> splitOp.next.next are intersecting
OutPt* prevOp = splitOp->prev; OutPt* prevOp = splitOp->prev;
OutPt* nextNextOp = splitOp->next->next; OutPt* nextNextOp = splitOp->next->next;
@ -1572,7 +1575,7 @@ namespace Clipper2Lib {
SafeDeleteOutPtJoiners(splitOp->next); SafeDeleteOutPtJoiners(splitOp->next);
SafeDeleteOutPtJoiners(splitOp); SafeDeleteOutPtJoiners(splitOp);
if (absArea2 >= 1 && if (absArea2 >= 1 &&
(absArea2 > absArea1 || (area2 > 0) == (area1 > 0))) (absArea2 > absArea1 || (area2 > 0) == (area1 > 0)))
{ {
OutRec* newOutRec = new OutRec(); OutRec* newOutRec = new OutRec();
@ -1762,7 +1765,7 @@ namespace Clipper2Lib {
else result = result->next_in_ael; else result = result->next_in_ael;
} }
result = e->prev_in_ael; result = e->prev_in_ael;
while (result) while (result)
{ {
if (result->local_min == e->local_min) return result; if (result->local_min == e->local_min) return result;
else if (!IsHorizontal(*result) && e->bot != result->bot) return nullptr; else if (!IsHorizontal(*result) && e->bot != result->bot) return nullptr;
@ -1791,14 +1794,14 @@ namespace Clipper2Lib {
edge_c = &e1; edge_c = &e1;
} }
if (abs(edge_c->wind_cnt) != 1) return nullptr; if (abs(edge_c->wind_cnt) != 1) return nullptr;
switch (cliptype_) switch (cliptype_)
{ {
case ClipType::Union: case ClipType::Union:
if (!IsHotEdge(*edge_c)) return nullptr; if (!IsHotEdge(*edge_c)) return nullptr;
break; break;
default: default:
if (edge_c->local_min->polytype == PathType::Subject) if (edge_c->local_min->polytype == PathType::Subject)
return nullptr; return nullptr;
} }
@ -1821,11 +1824,11 @@ namespace Clipper2Lib {
edge_o->outrec = nullptr; edge_o->outrec = nullptr;
return resultOp; return resultOp;
} }
//horizontal edges can pass under open paths at a LocMins //horizontal edges can pass under open paths at a LocMins
else if (pt == edge_o->local_min->vertex->pt && else if (pt == edge_o->local_min->vertex->pt &&
!IsOpenEnd(*edge_o->local_min->vertex)) !IsOpenEnd(*edge_o->local_min->vertex))
{ {
//find the other side of the LocMin and //find the other side of the LocMin and
//if it's 'hot' join up with it ... //if it's 'hot' join up with it ...
Active* e3 = FindEdgeWithMatchingLocMin(edge_o); Active* e3 = FindEdgeWithMatchingLocMin(edge_o);
@ -1833,7 +1836,7 @@ namespace Clipper2Lib {
{ {
edge_o->outrec = e3->outrec; edge_o->outrec = e3->outrec;
if (edge_o->wind_dx > 0) if (edge_o->wind_dx > 0)
SetSides(*e3->outrec, *edge_o, *e3); SetSides(*e3->outrec, *edge_o, *e3);
else else
SetSides(*e3->outrec, *e3, *edge_o); SetSides(*e3->outrec, *e3, *edge_o);
return e3->outrec->pts; return e3->outrec->pts;
@ -1847,7 +1850,7 @@ namespace Clipper2Lib {
//MANAGING CLOSED PATHS FROM HERE ON //MANAGING CLOSED PATHS FROM HERE ON
//UPDATE WINDING COUNTS... //UPDATE WINDING COUNTS...
int old_e1_windcnt, old_e2_windcnt; int old_e1_windcnt, old_e2_windcnt;
@ -1913,7 +1916,7 @@ namespace Clipper2Lib {
{ {
return nullptr; return nullptr;
} }
//NOW PROCESS THE INTERSECTION ... //NOW PROCESS THE INTERSECTION ...
OutPt* resultOp = nullptr; OutPt* resultOp = nullptr;
//if both edges are 'hot' ... //if both edges are 'hot' ...
@ -2282,7 +2285,7 @@ namespace Clipper2Lib {
inline bool HorzIsSpike(const Active& horzEdge) inline bool HorzIsSpike(const Active& horzEdge)
{ {
Point64 nextPt = NextVertex(horzEdge)->pt; 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); (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) //always trim 180 deg. spikes (in closed paths)
//but otherwise break if preserveCollinear = true //but otherwise break if preserveCollinear = true
if (preserveCollinear && 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; break;
horzEdge.vertex_top = NextVertex(horzEdge); horzEdge.vertex_top = NextVertex(horzEdge);
@ -2353,11 +2356,11 @@ namespace Clipper2Lib {
OutPt* op; OutPt* op;
while (true) // loop through consec. horizontal edges while (true) // loop through consec. horizontal edges
{ {
if (horzIsOpen && IsMaxima(horz) && !IsOpenEnd(horz)) if (horzIsOpen && IsMaxima(horz) && !IsOpenEnd(horz))
{ {
vertex_max = GetCurrYMaximaVertex(horz); vertex_max = GetCurrYMaximaVertex(horz);
if (vertex_max) if (vertex_max)
max_pair = GetHorzMaximaPair(horz, vertex_max); max_pair = GetHorzMaximaPair(horz, vertex_max);
} }
@ -2388,7 +2391,7 @@ namespace Clipper2Lib {
//if horzEdge is a maxima, keep going until we reach //if horzEdge is a maxima, keep going until we reach
//its maxima pair, otherwise check for break conditions //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 //otherwise stop when 'ae' is beyond the end of the horizontal line
if ((is_left_to_right && e->curr_x > horz_right) || if ((is_left_to_right && e->curr_x > horz_right) ||
@ -2467,15 +2470,15 @@ namespace Clipper2Lib {
{ {
AddOutPt(horz, horz.top); AddOutPt(horz, horz.top);
if (IsFront(horz)) if (IsFront(horz))
horz.outrec->front_edge = nullptr; horz.outrec->front_edge = nullptr;
else else
horz.outrec->back_edge = nullptr; horz.outrec->back_edge = nullptr;
horz.outrec = nullptr; horz.outrec = nullptr;
} }
DeleteFromAEL(horz); DeleteFromAEL(horz);
return; return;
} }
else if (NextVertex(horz)->pt.y != horz.top.y) else if (NextVertex(horz)->pt.y != horz.top.y)
break; break;
//still more horizontals in bound to process ... //still more horizontals in bound to process ...
@ -2486,7 +2489,7 @@ namespace Clipper2Lib {
if (PreserveCollinear && !horzIsOpen && HorzIsSpike(horz)) if (PreserveCollinear && !horzIsOpen && HorzIsSpike(horz))
TrimHorz(horz, true); TrimHorz(horz, true);
is_left_to_right = is_left_to_right =
ResetHorzDirection(horz, max_pair, horz_left, horz_right); ResetHorzDirection(horz, max_pair, horz_left, horz_right);
} }
@ -2499,7 +2502,7 @@ namespace Clipper2Lib {
else else
op = nullptr; op = nullptr;
if ((horzIsOpen && !IsOpenEnd(horz)) || if ((horzIsOpen && !IsOpenEnd(horz)) ||
(!horzIsOpen && vertex_max != horz.vertex_top)) (!horzIsOpen && vertex_max != horz.vertex_top))
{ {
UpdateEdgeIntoAEL(&horz); // this is the end of an intermediate horiz. UpdateEdgeIntoAEL(&horz); // this is the end of an intermediate horiz.
@ -2516,7 +2519,7 @@ namespace Clipper2Lib {
AddJoin(op2, op); AddJoin(op2, op);
} }
} }
else if (IsHotEdge(horz)) else if (IsHotEdge(horz))
AddLocalMaxPoly(horz, *max_pair, horz.top); AddLocalMaxPoly(horz, *max_pair, horz.top);
else else
{ {
@ -2966,7 +2969,7 @@ namespace Clipper2Lib {
OutRec* outrec = ProcessJoin(j); OutRec* outrec = ProcessJoin(j);
CleanCollinear(outrec); CleanCollinear(outrec);
} }
else else
delete j; delete j;
} }
@ -3015,7 +3018,7 @@ namespace Clipper2Lib {
bool CollinearSegsOverlap(const Point64& seg1a, const Point64& seg1b, bool CollinearSegsOverlap(const Point64& seg1a, const Point64& seg1b,
const Point64& seg2a, const Point64& seg2b) const Point64& seg2a, const Point64& seg2b)
{ {
//precondition: seg1 and seg2 are collinear //precondition: seg1 and seg2 are collinear
if (seg1a.x == seg1b.x) if (seg1a.x == seg1b.x)
{ {
if (seg2a.x != seg1a.x || seg2a.x != seg2b.x) return false; if (seg2a.x != seg1a.x || seg2a.x != seg2b.x) return false;
@ -3146,7 +3149,7 @@ namespace Clipper2Lib {
{ {
or1->pts = op1; or1->pts = op1;
or2->pts = nullptr; or2->pts = nullptr;
if (or1->owner && (!or2->owner || if (or1->owner && (!or2->owner ||
or2->owner->idx < or1->owner->idx)) or2->owner->idx < or1->owner->idx))
or1->owner = or2->owner; or1->owner = or2->owner;
or2->owner = or1; or2->owner = or1;
@ -3156,7 +3159,7 @@ namespace Clipper2Lib {
result = or2; result = or2;
or2->pts = op1; or2->pts = op1;
or1->pts = nullptr; or1->pts = nullptr;
if (or2->owner && (!or1->owner || if (or2->owner && (!or1->owner ||
or1->owner->idx < or2->owner->idx)) or1->owner->idx < or2->owner->idx))
or2->owner = or1->owner; or2->owner = or1->owner;
or1->owner = or2; or1->owner = or2;
@ -3207,7 +3210,7 @@ namespace Clipper2Lib {
{ {
or1->pts = op1; or1->pts = op1;
or2->pts = nullptr; or2->pts = nullptr;
if (or1->owner && (!or2->owner || if (or1->owner && (!or2->owner ||
or2->owner->idx < or1->owner->idx)) or2->owner->idx < or1->owner->idx))
or1->owner = or2->owner; or1->owner = or2->owner;
or2->owner = or1; or2->owner = or1;
@ -3217,9 +3220,9 @@ namespace Clipper2Lib {
result = or2; result = or2;
or2->pts = op1; or2->pts = op1;
or1->pts = nullptr; or1->pts = nullptr;
if (or2->owner && (!or1->owner || if (or2->owner && (!or1->owner ||
or1->owner->idx < or2->owner->idx)) or1->owner->idx < or2->owner->idx))
or2->owner = or1->owner; or2->owner = or1->owner;
or1->owner = or2; or1->owner = or2;
} }
} }
@ -3310,11 +3313,11 @@ namespace Clipper2Lib {
if (pt.y > result.bottom) result.bottom = pt.y; if (pt.y > result.bottom) result.bottom = pt.y;
} }
return result; return result;
} }
bool BuildPath64(OutPt* op, bool reverse, bool isOpen, Path64& path) 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; return false;
path.resize(0); path.resize(0);
@ -3355,9 +3358,9 @@ namespace Clipper2Lib {
if (owner->bounds.IsEmpty()) owner->bounds = GetBounds(owner->path); if (owner->bounds.IsEmpty()) owner->bounds = GetBounds(owner->path);
bool is_inside_owner_bounds = owner->bounds.Contains(outrec->bounds); bool is_inside_owner_bounds = owner->bounds.Contains(outrec->bounds);
// while looking for the correct owner, check the owner's // while looking for the correct owner, check the owner's
// splits **before** checking the owner itself because // splits **before** checking the owner itself because
// splits can occur internally, and checking the owner // splits can occur internally, and checking the owner
// first would miss the inner split's true ownership // first would miss the inner split's true ownership
if (owner->splits) if (owner->splits)
{ {
@ -3388,7 +3391,7 @@ namespace Clipper2Lib {
{ {
if (is_inside_owner_bounds && Path1InsidePath2(outrec, outrec->owner)) if (is_inside_owner_bounds && Path1InsidePath2(outrec, outrec->owner))
return true; return true;
// otherwise keep trying with owner's owner // otherwise keep trying with owner's owner
outrec->owner = outrec->owner->owner; outrec->owner = outrec->owner->owner;
if (!outrec->owner) return true; // true or false if (!outrec->owner) return true; // true or false
is_inside_owner_bounds = outrec->owner->bounds.Contains(outrec->bounds); is_inside_owner_bounds = outrec->owner->bounds.Contains(outrec->bounds);