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 <vector>
#include <functional>
#include <cstddef>
#include <cstdint>
#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<LocalMinima*>::iterator current_locmin_iter_;
std::vector<Vertex*> vertex_lists_;
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
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<PolyPathD*>::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<PolyPathD*>(childs_[index]);
PolyPathD* operator [] (size_t index)
{
return static_cast<PolyPathD*>(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

View File

@ -15,6 +15,9 @@
#include <algorithm>
#include "clipper2/clipper.engine.h"
#include <cstddef>
#include <cstdint>
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<int64_t>(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<double>(pt3.y + pt1.y) * static_cast<double>(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);