Skip to content

Clipper2 1.5.3 #2541

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 3rdparty/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

## Clipper2
- [![Upstream](https://img.shields.io/github/v/tag/AngusJohnson/Clipper2?label=Upstream)](https://github.com/AngusJohnson/Clipper2)
- Version: 1.5.2
- Version: 1.5.3
- License: BSL-1.0

## ConcurrentQueue
Expand Down
85 changes: 71 additions & 14 deletions 3rdparty/clipper2/include/clipper2/clipper.core.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 12 May 2024 *
* Date : 24 March 2025 *
* Website : https://www.angusj.com *
* Copyright : Angus Johnson 2010-2024 *
* Copyright : Angus Johnson 2010-2025 *
* Purpose : Core Clipper Library structures and functions *
* License : https://www.boost.org/LICENSE_1_0.txt *
*******************************************************************************/
Expand Down Expand Up @@ -248,6 +248,20 @@ namespace Clipper2Lib
template <typename T>
using Paths = std::vector<Path<T>>;

template <typename T, typename T2=T>
Path<T>& operator<<(Path<T>& poly, const Point<T2>& p)
{
poly.emplace_back(p);
return poly;
}

template <typename T>
Paths<T>& operator<<(Paths<T>& polys, const Path<T>& p)
{
polys.emplace_back(p);
return polys;
}

using Path64 = Path<int64_t>;
using PathD = Path<double>;
using Paths64 = std::vector< Path64>;
Expand Down Expand Up @@ -685,29 +699,30 @@ namespace Clipper2Lib
return (x > 0) - (x < 0);
}

struct MultiplyUInt64Result
struct UInt128Struct
{
const uint64_t result = 0;
const uint64_t carry = 0;
const uint64_t lo = 0;
const uint64_t hi = 0;

bool operator==(const MultiplyUInt64Result& other) const
bool operator==(const UInt128Struct& other) const
{
return result == other.result && carry == other.carry;
return lo == other.lo && hi == other.hi;
};
};

inline MultiplyUInt64Result Multiply(uint64_t a, uint64_t b) // #834, #835
inline UInt128Struct Multiply(uint64_t a, uint64_t b) // #834, #835
{
// note to self - lamba expressions follow
const auto lo = [](uint64_t x) { return x & 0xFFFFFFFF; };
const auto hi = [](uint64_t x) { return x >> 32; };

const uint64_t x1 = lo(a) * lo(b);
const uint64_t x2 = hi(a) * lo(b) + hi(x1);
const uint64_t x3 = lo(a) * hi(b) + lo(x2);
const uint64_t result = lo(x3) << 32 | lo(x1);
const uint64_t carry = hi(a) * hi(b) + hi(x2) + hi(x3);
const uint64_t lobits = lo(x3) << 32 | lo(x1);
const uint64_t hibits = hi(a) * hi(b) + hi(x2) + hi(x3);

return { result, carry };
return { lobits, hibits };
}

// returns true if (and only if) a * b == c * d
Expand All @@ -724,14 +739,56 @@ namespace Clipper2Lib
const auto abs_c = static_cast<uint64_t>(std::abs(c));
const auto abs_d = static_cast<uint64_t>(std::abs(d));

const auto abs_ab = Multiply(abs_a, abs_b);
const auto abs_cd = Multiply(abs_c, abs_d);
const auto ab = Multiply(abs_a, abs_b);
const auto cd = Multiply(abs_c, abs_d);

// nb: it's important to differentiate 0 values here from other values
const auto sign_ab = TriSign(a) * TriSign(b);
const auto sign_cd = TriSign(c) * TriSign(d);

return abs_ab == abs_cd && sign_ab == sign_cd;
return ab == cd && sign_ab == sign_cd;
#endif
}

template <typename T>
inline int CrossProductSign(const Point<T>& pt1, const Point<T>& pt2, const Point<T>& pt3)
{
const auto a = pt2.x - pt1.x;
const auto b = pt3.y - pt2.y;
const auto c = pt2.y - pt1.y;
const auto d = pt3.x - pt2.x;

#if (defined(__clang__) || defined(__GNUC__)) && UINTPTR_MAX >= UINT64_MAX
const auto ab = static_cast<__int128_t>(a) * static_cast<__int128_t>(b);
const auto cd = static_cast<__int128_t>(c) * static_cast<__int128_t>(d);
if (ab > cd) return 1;
else if (ab < cd) return -1;
else return 0;
#else
// nb: unsigned values needed for calculating carry into 'hi'
const auto abs_a = static_cast<uint64_t>(std::abs(a));
const auto abs_b = static_cast<uint64_t>(std::abs(b));
const auto abs_c = static_cast<uint64_t>(std::abs(c));
const auto abs_d = static_cast<uint64_t>(std::abs(d));

const auto ab = Multiply(abs_a, abs_b);
const auto cd = Multiply(abs_c, abs_d);

const auto sign_ab = TriSign(a) * TriSign(b);
const auto sign_cd = TriSign(c) * TriSign(d);

if (sign_ab == sign_cd)
{
int result;
if (ab.hi == cd.hi)
{
if (ab.lo == cd.lo) return 0;
result = (ab.lo > cd.lo) ? 1 : -1;
}
else result = (ab.hi > cd.hi) ? 1 : -1;
return (sign_ab > 0) ? result : -result;
}
return (sign_ab > sign_cd) ? 1 : -1;
#endif
}

Expand Down
93 changes: 61 additions & 32 deletions 3rdparty/clipper2/include/clipper2/clipper.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 27 April 2024 *
* Date : 5 March 2025 *
* Website : https://www.angusj.com *
* Copyright : Angus Johnson 2010-2024 *
* Copyright : Angus Johnson 2010-2025 *
* Purpose : This module provides a simple interface to the Clipper Library *
* License : https://www.boost.org/LICENSE_1_0.txt *
*******************************************************************************/
Expand Down Expand Up @@ -150,7 +150,7 @@ namespace Clipper2Lib {
if (!delta) return paths;
if (error_code) return PathsD();
const double scale = std::pow(10, precision);
ClipperOffset clip_offset(miter_limit, arc_tolerance);
ClipperOffset clip_offset(miter_limit, arc_tolerance * scale);
clip_offset.AddPaths(ScalePaths<int64_t,double>(paths, scale, error_code), jt, et);
if (error_code) return PathsD();
Paths64 solution;
Expand Down Expand Up @@ -351,6 +351,29 @@ namespace Clipper2Lib {
#endif
}

inline size_t GetNext(size_t current, size_t high,
const std::vector<bool>& flags)
{
++current;
while (current <= high && flags[current]) ++current;
if (current <= high) return current;
current = 0;
while (flags[current]) ++current;
return current;
}

inline size_t GetPrior(size_t current, size_t high,
const std::vector<bool>& flags)
{
if (current == 0) current = high;
else --current;
while (current > 0 && flags[current]) --current;
if (!flags[current]) return current;
current = high;
while (flags[current]) --current;
return current;
}

} // end details namespace

inline std::ostream& operator<< (std::ostream& os, const PolyTree64& pp)
Expand Down Expand Up @@ -611,29 +634,6 @@ namespace Clipper2Lib {
return result;
}

inline size_t GetNext(size_t current, size_t high,
const std::vector<bool>& flags)
{
++current;
while (current <= high && flags[current]) ++current;
if (current <= high) return current;
current = 0;
while (flags[current]) ++current;
return current;
}

inline size_t GetPrior(size_t current, size_t high,
const std::vector<bool>& flags)
{
if (current == 0) current = high;
else --current;
while (current > 0 && flags[current]) --current;
if (!flags[current]) return current;
current = high;
while (flags[current]) --current;
return current;
}

template <typename T>
inline Path<T> SimplifyPath(const Path<T> &path,
double epsilon, bool isClosedPath = true)
Expand Down Expand Up @@ -665,13 +665,13 @@ namespace Clipper2Lib {
start = curr;
do
{
curr = GetNext(curr, high, flags);
curr = details::GetNext(curr, high, flags);
} while (curr != start && distSqr[curr] > epsSqr);
if (curr == start) break;
}

prior = GetPrior(curr, high, flags);
next = GetNext(curr, high, flags);
prior = details::GetPrior(curr, high, flags);
next = details::GetNext(curr, high, flags);
if (next == prior) break;

// flag for removal the smaller of adjacent 'distances'
Expand All @@ -680,14 +680,14 @@ namespace Clipper2Lib {
prior2 = prior;
prior = curr;
curr = next;
next = GetNext(next, high, flags);
next = details::GetNext(next, high, flags);
}
else
prior2 = GetPrior(prior, high, flags);
prior2 = details::GetPrior(prior, high, flags);

flags[curr] = true;
curr = next;
next = GetNext(next, high, flags);
next = details::GetNext(next, high, flags);

if (isClosedPath || ((curr != high) && (curr != 0)))
distSqr[curr] = PerpendicDistFromLineSqrd(path[curr], path[prior], path[next]);
Expand All @@ -712,6 +712,35 @@ namespace Clipper2Lib {
return result;
}


template <typename T>
inline bool Path2ContainsPath1(const Path<T>& path1, const Path<T>& path2)
{
// precondition: paths must not intersect, except for
// transient (and presumed 'micro') path intersections
PointInPolygonResult pip = PointInPolygonResult::IsOn;
for (const Point<T>& pt : path1)
{
switch (PointInPolygon(pt, path2))
{
case PointInPolygonResult::IsOutside:
if (pip == PointInPolygonResult::IsOutside) return false;
pip = PointInPolygonResult::IsOutside;
break;
case PointInPolygonResult::IsInside:
if (pip == PointInPolygonResult::IsInside) return true;
pip = PointInPolygonResult::IsInside;
break;
default:
break;
}
}
if (pip != PointInPolygonResult::IsInside) return false;
// result is likely true but check midpoint
Point<T> mp1 = GetBounds(path1).MidPoint();
return PointInPolygon(mp1, path2) == PointInPolygonResult::IsInside;
}

template <typename T>
inline void RDP(const Path<T> path, std::size_t begin,
std::size_t end, double epsSqrd, std::vector<bool>& flags)
Expand Down
2 changes: 1 addition & 1 deletion 3rdparty/clipper2/include/clipper2/clipper.offset.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ClipperOffset {
class Group {
public:
Paths64 paths_in;
std::optional<size_t> lowest_path_idx{};
std::optional<size_t> lowest_path_idx{};
bool is_reversed = false;
JoinType join_type;
EndType end_type;
Expand Down
2 changes: 1 addition & 1 deletion 3rdparty/clipper2/include/clipper2/clipper.version.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#ifndef CLIPPER_VERSION_H
#define CLIPPER_VERSION_H

constexpr auto CLIPPER2_VERSION = "1.5.2";
constexpr auto CLIPPER2_VERSION = "1.5.3";

#endif // CLIPPER_VERSION_H
Loading