Skip to content

Commit 6ab3641

Browse files
authored
Clipper2 1.5.3 (#2541)
1 parent b112adc commit 6ab3641

File tree

7 files changed

+232
-124
lines changed

7 files changed

+232
-124
lines changed

3rdparty/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

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

3838
## ConcurrentQueue

3rdparty/clipper2/include/clipper2/clipper.core.h

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*******************************************************************************
22
* Author : Angus Johnson *
3-
* Date : 12 May 2024 *
3+
* Date : 24 March 2025 *
44
* Website : https://www.angusj.com *
5-
* Copyright : Angus Johnson 2010-2024 *
5+
* Copyright : Angus Johnson 2010-2025 *
66
* Purpose : Core Clipper Library structures and functions *
77
* License : https://www.boost.org/LICENSE_1_0.txt *
88
*******************************************************************************/
@@ -248,6 +248,20 @@ namespace Clipper2Lib
248248
template <typename T>
249249
using Paths = std::vector<Path<T>>;
250250

251+
template <typename T, typename T2=T>
252+
Path<T>& operator<<(Path<T>& poly, const Point<T2>& p)
253+
{
254+
poly.emplace_back(p);
255+
return poly;
256+
}
257+
258+
template <typename T>
259+
Paths<T>& operator<<(Paths<T>& polys, const Path<T>& p)
260+
{
261+
polys.emplace_back(p);
262+
return polys;
263+
}
264+
251265
using Path64 = Path<int64_t>;
252266
using PathD = Path<double>;
253267
using Paths64 = std::vector< Path64>;
@@ -685,29 +699,30 @@ namespace Clipper2Lib
685699
return (x > 0) - (x < 0);
686700
}
687701

688-
struct MultiplyUInt64Result
702+
struct UInt128Struct
689703
{
690-
const uint64_t result = 0;
691-
const uint64_t carry = 0;
704+
const uint64_t lo = 0;
705+
const uint64_t hi = 0;
692706

693-
bool operator==(const MultiplyUInt64Result& other) const
707+
bool operator==(const UInt128Struct& other) const
694708
{
695-
return result == other.result && carry == other.carry;
709+
return lo == other.lo && hi == other.hi;
696710
};
697711
};
698712

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

704719
const uint64_t x1 = lo(a) * lo(b);
705720
const uint64_t x2 = hi(a) * lo(b) + hi(x1);
706721
const uint64_t x3 = lo(a) * hi(b) + lo(x2);
707-
const uint64_t result = lo(x3) << 32 | lo(x1);
708-
const uint64_t carry = hi(a) * hi(b) + hi(x2) + hi(x3);
722+
const uint64_t lobits = lo(x3) << 32 | lo(x1);
723+
const uint64_t hibits = hi(a) * hi(b) + hi(x2) + hi(x3);
709724

710-
return { result, carry };
725+
return { lobits, hibits };
711726
}
712727

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

727-
const auto abs_ab = Multiply(abs_a, abs_b);
728-
const auto abs_cd = Multiply(abs_c, abs_d);
742+
const auto ab = Multiply(abs_a, abs_b);
743+
const auto cd = Multiply(abs_c, abs_d);
729744

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

734-
return abs_ab == abs_cd && sign_ab == sign_cd;
749+
return ab == cd && sign_ab == sign_cd;
750+
#endif
751+
}
752+
753+
template <typename T>
754+
inline int CrossProductSign(const Point<T>& pt1, const Point<T>& pt2, const Point<T>& pt3)
755+
{
756+
const auto a = pt2.x - pt1.x;
757+
const auto b = pt3.y - pt2.y;
758+
const auto c = pt2.y - pt1.y;
759+
const auto d = pt3.x - pt2.x;
760+
761+
#if (defined(__clang__) || defined(__GNUC__)) && UINTPTR_MAX >= UINT64_MAX
762+
const auto ab = static_cast<__int128_t>(a) * static_cast<__int128_t>(b);
763+
const auto cd = static_cast<__int128_t>(c) * static_cast<__int128_t>(d);
764+
if (ab > cd) return 1;
765+
else if (ab < cd) return -1;
766+
else return 0;
767+
#else
768+
// nb: unsigned values needed for calculating carry into 'hi'
769+
const auto abs_a = static_cast<uint64_t>(std::abs(a));
770+
const auto abs_b = static_cast<uint64_t>(std::abs(b));
771+
const auto abs_c = static_cast<uint64_t>(std::abs(c));
772+
const auto abs_d = static_cast<uint64_t>(std::abs(d));
773+
774+
const auto ab = Multiply(abs_a, abs_b);
775+
const auto cd = Multiply(abs_c, abs_d);
776+
777+
const auto sign_ab = TriSign(a) * TriSign(b);
778+
const auto sign_cd = TriSign(c) * TriSign(d);
779+
780+
if (sign_ab == sign_cd)
781+
{
782+
int result;
783+
if (ab.hi == cd.hi)
784+
{
785+
if (ab.lo == cd.lo) return 0;
786+
result = (ab.lo > cd.lo) ? 1 : -1;
787+
}
788+
else result = (ab.hi > cd.hi) ? 1 : -1;
789+
return (sign_ab > 0) ? result : -result;
790+
}
791+
return (sign_ab > sign_cd) ? 1 : -1;
735792
#endif
736793
}
737794

3rdparty/clipper2/include/clipper2/clipper.h

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*******************************************************************************
22
* Author : Angus Johnson *
3-
* Date : 27 April 2024 *
3+
* Date : 5 March 2025 *
44
* Website : https://www.angusj.com *
5-
* Copyright : Angus Johnson 2010-2024 *
5+
* Copyright : Angus Johnson 2010-2025 *
66
* Purpose : This module provides a simple interface to the Clipper Library *
77
* License : https://www.boost.org/LICENSE_1_0.txt *
88
*******************************************************************************/
@@ -150,7 +150,7 @@ namespace Clipper2Lib {
150150
if (!delta) return paths;
151151
if (error_code) return PathsD();
152152
const double scale = std::pow(10, precision);
153-
ClipperOffset clip_offset(miter_limit, arc_tolerance);
153+
ClipperOffset clip_offset(miter_limit, arc_tolerance * scale);
154154
clip_offset.AddPaths(ScalePaths<int64_t,double>(paths, scale, error_code), jt, et);
155155
if (error_code) return PathsD();
156156
Paths64 solution;
@@ -351,6 +351,29 @@ namespace Clipper2Lib {
351351
#endif
352352
}
353353

354+
inline size_t GetNext(size_t current, size_t high,
355+
const std::vector<bool>& flags)
356+
{
357+
++current;
358+
while (current <= high && flags[current]) ++current;
359+
if (current <= high) return current;
360+
current = 0;
361+
while (flags[current]) ++current;
362+
return current;
363+
}
364+
365+
inline size_t GetPrior(size_t current, size_t high,
366+
const std::vector<bool>& flags)
367+
{
368+
if (current == 0) current = high;
369+
else --current;
370+
while (current > 0 && flags[current]) --current;
371+
if (!flags[current]) return current;
372+
current = high;
373+
while (flags[current]) --current;
374+
return current;
375+
}
376+
354377
} // end details namespace
355378

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

614-
inline size_t GetNext(size_t current, size_t high,
615-
const std::vector<bool>& flags)
616-
{
617-
++current;
618-
while (current <= high && flags[current]) ++current;
619-
if (current <= high) return current;
620-
current = 0;
621-
while (flags[current]) ++current;
622-
return current;
623-
}
624-
625-
inline size_t GetPrior(size_t current, size_t high,
626-
const std::vector<bool>& flags)
627-
{
628-
if (current == 0) current = high;
629-
else --current;
630-
while (current > 0 && flags[current]) --current;
631-
if (!flags[current]) return current;
632-
current = high;
633-
while (flags[current]) --current;
634-
return current;
635-
}
636-
637637
template <typename T>
638638
inline Path<T> SimplifyPath(const Path<T> &path,
639639
double epsilon, bool isClosedPath = true)
@@ -665,13 +665,13 @@ namespace Clipper2Lib {
665665
start = curr;
666666
do
667667
{
668-
curr = GetNext(curr, high, flags);
668+
curr = details::GetNext(curr, high, flags);
669669
} while (curr != start && distSqr[curr] > epsSqr);
670670
if (curr == start) break;
671671
}
672672

673-
prior = GetPrior(curr, high, flags);
674-
next = GetNext(curr, high, flags);
673+
prior = details::GetPrior(curr, high, flags);
674+
next = details::GetNext(curr, high, flags);
675675
if (next == prior) break;
676676

677677
// flag for removal the smaller of adjacent 'distances'
@@ -680,14 +680,14 @@ namespace Clipper2Lib {
680680
prior2 = prior;
681681
prior = curr;
682682
curr = next;
683-
next = GetNext(next, high, flags);
683+
next = details::GetNext(next, high, flags);
684684
}
685685
else
686-
prior2 = GetPrior(prior, high, flags);
686+
prior2 = details::GetPrior(prior, high, flags);
687687

688688
flags[curr] = true;
689689
curr = next;
690-
next = GetNext(next, high, flags);
690+
next = details::GetNext(next, high, flags);
691691

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

715+
716+
template <typename T>
717+
inline bool Path2ContainsPath1(const Path<T>& path1, const Path<T>& path2)
718+
{
719+
// precondition: paths must not intersect, except for
720+
// transient (and presumed 'micro') path intersections
721+
PointInPolygonResult pip = PointInPolygonResult::IsOn;
722+
for (const Point<T>& pt : path1)
723+
{
724+
switch (PointInPolygon(pt, path2))
725+
{
726+
case PointInPolygonResult::IsOutside:
727+
if (pip == PointInPolygonResult::IsOutside) return false;
728+
pip = PointInPolygonResult::IsOutside;
729+
break;
730+
case PointInPolygonResult::IsInside:
731+
if (pip == PointInPolygonResult::IsInside) return true;
732+
pip = PointInPolygonResult::IsInside;
733+
break;
734+
default:
735+
break;
736+
}
737+
}
738+
if (pip != PointInPolygonResult::IsInside) return false;
739+
// result is likely true but check midpoint
740+
Point<T> mp1 = GetBounds(path1).MidPoint();
741+
return PointInPolygon(mp1, path2) == PointInPolygonResult::IsInside;
742+
}
743+
715744
template <typename T>
716745
inline void RDP(const Path<T> path, std::size_t begin,
717746
std::size_t end, double epsSqrd, std::vector<bool>& flags)

3rdparty/clipper2/include/clipper2/clipper.offset.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class ClipperOffset {
3535
class Group {
3636
public:
3737
Paths64 paths_in;
38-
std::optional<size_t> lowest_path_idx{};
38+
std::optional<size_t> lowest_path_idx{};
3939
bool is_reversed = false;
4040
JoinType join_type;
4141
EndType end_type;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#ifndef CLIPPER_VERSION_H
22
#define CLIPPER_VERSION_H
33

4-
constexpr auto CLIPPER2_VERSION = "1.5.2";
4+
constexpr auto CLIPPER2_VERSION = "1.5.3";
55

66
#endif // CLIPPER_VERSION_H

0 commit comments

Comments
 (0)