clipper2 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +165 -0
  4. data/examples/larb_transform.rb +17 -0
  5. data/examples/rugl_mesh.rb +33 -0
  6. data/examples/svg_boolean.rb +28 -0
  7. data/ext/clipper2/CMakeLists.txt +27 -0
  8. data/ext/clipper2/clipper2_native.cpp +2 -0
  9. data/ext/clipper2/extconf.rb +27 -0
  10. data/ext/clipper2/generate_bindings.rb +73 -0
  11. data/ext/clipper2/memory_check.cpp +48 -0
  12. data/ext/clipper2/vendor/LICENSE +23 -0
  13. data/ext/clipper2/vendor/UPSTREAM.md +11 -0
  14. data/ext/clipper2/vendor/include/clipper2/clipper.core.h +1159 -0
  15. data/ext/clipper2/vendor/include/clipper2/clipper.engine.h +635 -0
  16. data/ext/clipper2/vendor/include/clipper2/clipper.export.h +851 -0
  17. data/ext/clipper2/vendor/include/clipper2/clipper.h +796 -0
  18. data/ext/clipper2/vendor/include/clipper2/clipper.minkowski.h +117 -0
  19. data/ext/clipper2/vendor/include/clipper2/clipper.offset.h +125 -0
  20. data/ext/clipper2/vendor/include/clipper2/clipper.rectclip.h +80 -0
  21. data/ext/clipper2/vendor/include/clipper2/clipper.triangulation.h +27 -0
  22. data/ext/clipper2/vendor/include/clipper2/clipper.version.h +6 -0
  23. data/ext/clipper2/vendor/src/clipper.engine.cpp +3152 -0
  24. data/ext/clipper2/vendor/src/clipper.offset.cpp +661 -0
  25. data/ext/clipper2/vendor/src/clipper.rectclip.cpp +1027 -0
  26. data/ext/clipper2/vendor/src/clipper.triangulation.cpp +1221 -0
  27. data/lib/clipper2/api.rb +45 -0
  28. data/lib/clipper2/c_paths64.rb +80 -0
  29. data/lib/clipper2/earcut/engine.rb +191 -0
  30. data/lib/clipper2/earcut/geometry.rb +100 -0
  31. data/lib/clipper2/earcut/node.rb +18 -0
  32. data/lib/clipper2/earcut/ring.rb +94 -0
  33. data/lib/clipper2/earcut.rb +18 -0
  34. data/lib/clipper2/errors.rb +19 -0
  35. data/lib/clipper2/generated.rb +62 -0
  36. data/lib/clipper2/native.rb +38 -0
  37. data/lib/clipper2/native_memory.rb +64 -0
  38. data/lib/clipper2/operations.rb +206 -0
  39. data/lib/clipper2/path.rb +171 -0
  40. data/lib/clipper2/path_simplifier.rb +61 -0
  41. data/lib/clipper2/paths.rb +130 -0
  42. data/lib/clipper2/quantizer.rb +48 -0
  43. data/lib/clipper2/triangulation.rb +103 -0
  44. data/lib/clipper2/version.rb +5 -0
  45. data/lib/clipper2.rb +34 -0
  46. data/licenses/CLIPPER2-BSL-1.0.txt +23 -0
  47. data/licenses/EARCUT-ISC.txt +15 -0
  48. metadata +113 -0
@@ -0,0 +1,117 @@
1
+ /*******************************************************************************
2
+ * Author : Angus Johnson *
3
+ * Date : 1 November 2023 *
4
+ * Website : https://www.angusj.com *
5
+ * Copyright : Angus Johnson 2010-2023 *
6
+ * Purpose : Minkowski Sum and Difference *
7
+ * License : https://www.boost.org/LICENSE_1_0.txt *
8
+ *******************************************************************************/
9
+
10
+ #ifndef CLIPPER_MINKOWSKI_H
11
+ #define CLIPPER_MINKOWSKI_H
12
+
13
+ #include "clipper2/clipper.core.h"
14
+
15
+ namespace Clipper2Lib
16
+ {
17
+
18
+ namespace detail
19
+ {
20
+ inline Paths64 Minkowski(const Path64& pattern, const Path64& path, bool isSum, bool isClosed)
21
+ {
22
+ size_t delta = isClosed ? 0 : 1;
23
+ size_t patLen = pattern.size(), pathLen = path.size();
24
+ if (patLen == 0 || pathLen == 0) return Paths64();
25
+ Paths64 tmp;
26
+ tmp.reserve(pathLen);
27
+
28
+ if (isSum)
29
+ {
30
+ for (const Point64& p : path)
31
+ {
32
+ Path64 path2(pattern.size());
33
+ std::transform(pattern.cbegin(), pattern.cend(),
34
+ path2.begin(), [p](const Point64& pt2) {return p + pt2; });
35
+ tmp.emplace_back(std::move(path2));
36
+ }
37
+ }
38
+ else
39
+ {
40
+ for (const Point64& p : path)
41
+ {
42
+ Path64 path2(pattern.size());
43
+ std::transform(pattern.cbegin(), pattern.cend(),
44
+ path2.begin(), [p](const Point64& pt2) {return p - pt2; });
45
+ tmp.emplace_back(std::move(path2));
46
+ }
47
+ }
48
+
49
+ Paths64 result;
50
+ result.reserve((pathLen - delta) * patLen);
51
+ size_t g = isClosed ? pathLen - 1 : 0;
52
+ for (size_t h = patLen - 1, i = delta; i < pathLen; ++i)
53
+ {
54
+ for (size_t j = 0; j < patLen; j++)
55
+ {
56
+ Path64 quad;
57
+ quad.reserve(4);
58
+ {
59
+ quad.emplace_back(tmp[g][h]);
60
+ quad.emplace_back(tmp[i][h]);
61
+ quad.emplace_back(tmp[i][j]);
62
+ quad.emplace_back(tmp[g][j]);
63
+ }
64
+ if (!IsPositive(quad))
65
+ std::reverse(quad.begin(), quad.end());
66
+ result.emplace_back(std::move(quad));
67
+ h = j;
68
+ }
69
+ g = i;
70
+ }
71
+ return result;
72
+ }
73
+
74
+ inline Paths64 Union(const Paths64& subjects, FillRule fillrule)
75
+ {
76
+ Paths64 result;
77
+ Clipper64 clipper;
78
+ clipper.AddSubject(subjects);
79
+ clipper.Execute(ClipType::Union, fillrule, result);
80
+ return result;
81
+ }
82
+
83
+ } // namespace internal
84
+
85
+ inline Paths64 MinkowskiSum(const Path64& pattern, const Path64& path, bool isClosed)
86
+ {
87
+ return detail::Union(detail::Minkowski(pattern, path, true, isClosed), FillRule::NonZero);
88
+ }
89
+
90
+ inline PathsD MinkowskiSum(const PathD& pattern, const PathD& path, bool isClosed, int decimalPlaces = 2)
91
+ {
92
+ int error_code = 0;
93
+ double scale = pow(10, decimalPlaces);
94
+ Path64 pat64 = ScalePath<int64_t, double>(pattern, scale, error_code);
95
+ Path64 path64 = ScalePath<int64_t, double>(path, scale, error_code);
96
+ Paths64 tmp = detail::Union(detail::Minkowski(pat64, path64, true, isClosed), FillRule::NonZero);
97
+ return ScalePaths<double, int64_t>(tmp, 1 / scale, error_code);
98
+ }
99
+
100
+ inline Paths64 MinkowskiDiff(const Path64& pattern, const Path64& path, bool isClosed)
101
+ {
102
+ return detail::Union(detail::Minkowski(pattern, path, false, isClosed), FillRule::NonZero);
103
+ }
104
+
105
+ inline PathsD MinkowskiDiff(const PathD& pattern, const PathD& path, bool isClosed, int decimalPlaces = 2)
106
+ {
107
+ int error_code = 0;
108
+ double scale = pow(10, decimalPlaces);
109
+ Path64 pat64 = ScalePath<int64_t, double>(pattern, scale, error_code);
110
+ Path64 path64 = ScalePath<int64_t, double>(path, scale, error_code);
111
+ Paths64 tmp = detail::Union(detail::Minkowski(pat64, path64, false, isClosed), FillRule::NonZero);
112
+ return ScalePaths<double, int64_t>(tmp, 1 / scale, error_code);
113
+ }
114
+
115
+ } // Clipper2Lib namespace
116
+
117
+ #endif // CLIPPER_MINKOWSKI_H
@@ -0,0 +1,125 @@
1
+ /*******************************************************************************
2
+ * Author : Angus Johnson *
3
+ * Date : 22 January 2025 *
4
+ * Website : https://www.angusj.com *
5
+ * Copyright : Angus Johnson 2010-2025 *
6
+ * Purpose : Path Offset (Inflate/Shrink) *
7
+ * License : https://www.boost.org/LICENSE_1_0.txt *
8
+ *******************************************************************************/
9
+
10
+ #ifndef CLIPPER_OFFSET_H_
11
+ #define CLIPPER_OFFSET_H_
12
+
13
+ #include "clipper.core.h"
14
+ #include "clipper.engine.h"
15
+ #include <optional>
16
+
17
+ namespace Clipper2Lib {
18
+
19
+ enum class JoinType { Square, Bevel, Round, Miter };
20
+ //Square : Joins are 'squared' at exactly the offset distance (more complex code)
21
+ //Bevel : Similar to Square, but the offset distance varies with angle (simple code & faster)
22
+
23
+ enum class EndType {Polygon, Joined, Butt, Square, Round};
24
+ //Butt : offsets both sides of a path, with square blunt ends
25
+ //Square : offsets both sides of a path, with square extended ends
26
+ //Round : offsets both sides of a path, with round extended ends
27
+ //Joined : offsets both sides of a path, with joined ends
28
+ //Polygon: offsets only one side of a closed path
29
+
30
+ typedef std::function<double(const Path64& path, const PathD& path_normals, size_t curr_idx, size_t prev_idx)> DeltaCallback64;
31
+
32
+ class ClipperOffset {
33
+ private:
34
+
35
+ class Group {
36
+ public:
37
+ Paths64 paths_in;
38
+ std::optional<size_t> lowest_path_idx{};
39
+ bool is_reversed = false;
40
+ JoinType join_type;
41
+ EndType end_type;
42
+ Group(const Paths64& _paths, JoinType _join_type, EndType _end_type);
43
+ };
44
+
45
+ int error_code_ = 0;
46
+ double delta_ = 0.0;
47
+ double group_delta_ = 0.0;
48
+ double temp_lim_ = 0.0;
49
+ double steps_per_rad_ = 0.0;
50
+ double step_sin_ = 0.0;
51
+ double step_cos_ = 0.0;
52
+ PathD norms;
53
+ Path64 path_out;
54
+ Paths64* solution = nullptr;
55
+ PolyTree64* solution_tree = nullptr;
56
+ std::vector<Group> groups_;
57
+ JoinType join_type_ = JoinType::Bevel;
58
+ EndType end_type_ = EndType::Polygon;
59
+
60
+ double miter_limit_ = 0.0;
61
+ double arc_tolerance_ = 0.0;
62
+ bool preserve_collinear_ = false;
63
+ bool reverse_solution_ = false;
64
+
65
+ #ifdef USINGZ
66
+ ZCallback64 zCallback64_ = nullptr;
67
+ void ZCB(const Point64& bot1, const Point64& top1,
68
+ const Point64& bot2, const Point64& top2, Point64& ip);
69
+ #endif
70
+ DeltaCallback64 deltaCallback64_ = nullptr;
71
+ size_t CalcSolutionCapacity();
72
+ bool CheckReverseOrientation();
73
+ void DoBevel(const Path64& path, size_t j, size_t k);
74
+ void DoSquare(const Path64& path, size_t j, size_t k);
75
+ void DoMiter(const Path64& path, size_t j, size_t k, double cos_a);
76
+ void DoRound(const Path64& path, size_t j, size_t k, double angle);
77
+ void BuildNormals(const Path64& path);
78
+ void OffsetPolygon(Group& group, const Path64& path);
79
+ void OffsetOpenJoined(Group& group, const Path64& path);
80
+ void OffsetOpenPath(Group& group, const Path64& path);
81
+ void OffsetPoint(Group& group, const Path64& path, size_t j, size_t k);
82
+ void DoGroupOffset(Group &group);
83
+ void ExecuteInternal(double delta);
84
+ public:
85
+ explicit ClipperOffset(double miter_limit = 2.0,
86
+ double arc_tolerance = 0.0,
87
+ bool preserve_collinear = false,
88
+ bool reverse_solution = false) :
89
+ miter_limit_(miter_limit), arc_tolerance_(arc_tolerance),
90
+ preserve_collinear_(preserve_collinear),
91
+ reverse_solution_(reverse_solution) { }
92
+
93
+ ~ClipperOffset() { Clear(); }
94
+
95
+ int ErrorCode() const { return error_code_; }
96
+ void AddPath(const Path64& path, JoinType jt_, EndType et_);
97
+ void AddPaths(const Paths64& paths, JoinType jt_, EndType et_);
98
+ void Clear() { groups_.clear(); norms.clear(); }
99
+
100
+ void Execute(double delta, Paths64& sols_64);
101
+ void Execute(double delta, PolyTree64& polytree);
102
+ void Execute(DeltaCallback64 delta_cb, Paths64& paths);
103
+
104
+ double MiterLimit() const { return miter_limit_; }
105
+ void MiterLimit(double miter_limit) { miter_limit_ = miter_limit; }
106
+
107
+ //ArcTolerance: needed for rounded offsets (See offset_triginometry2.svg)
108
+ double ArcTolerance() const { return arc_tolerance_; }
109
+ void ArcTolerance(double arc_tolerance) { arc_tolerance_ = arc_tolerance; }
110
+
111
+ bool PreserveCollinear() const { return preserve_collinear_; }
112
+ void PreserveCollinear(bool preserve_collinear){preserve_collinear_ = preserve_collinear;}
113
+
114
+ bool ReverseSolution() const { return reverse_solution_; }
115
+ void ReverseSolution(bool reverse_solution) {reverse_solution_ = reverse_solution;}
116
+
117
+ #ifdef USINGZ
118
+ void SetZCallback(ZCallback64 cb) { zCallback64_ = cb; }
119
+ #endif
120
+ void SetDeltaCallback(DeltaCallback64 cb) { deltaCallback64_ = cb; }
121
+
122
+ };
123
+
124
+ }
125
+ #endif /* CLIPPER_OFFSET_H_ */
@@ -0,0 +1,80 @@
1
+ /*******************************************************************************
2
+ * Author : Angus Johnson *
3
+ * Date : 5 July 2024 *
4
+ * Website : https://www.angusj.com *
5
+ * Copyright : Angus Johnson 2010-2024 *
6
+ * Purpose : FAST rectangular clipping *
7
+ * License : https://www.boost.org/LICENSE_1_0.txt *
8
+ *******************************************************************************/
9
+
10
+ #ifndef CLIPPER_RECTCLIP_H
11
+ #define CLIPPER_RECTCLIP_H
12
+
13
+ #include "clipper2/clipper.core.h"
14
+ #include <queue>
15
+
16
+ namespace Clipper2Lib
17
+ {
18
+
19
+ // Location: the order is important here, see StartLocsIsClockwise()
20
+ enum class Location { Left, Top, Right, Bottom, Inside };
21
+
22
+ class OutPt2;
23
+ typedef std::vector<OutPt2*> OutPt2List;
24
+
25
+ class OutPt2 {
26
+ public:
27
+ Point64 pt;
28
+ size_t owner_idx = 0;
29
+ OutPt2List* edge = nullptr;
30
+ OutPt2* next = nullptr;
31
+ OutPt2* prev = nullptr;
32
+ };
33
+
34
+ //------------------------------------------------------------------------------
35
+ // RectClip64
36
+ //------------------------------------------------------------------------------
37
+
38
+ class RectClip64 {
39
+ private:
40
+ void ExecuteInternal(const Path64& path);
41
+ Path64 GetPath(OutPt2*& op);
42
+ protected:
43
+ const Rect64 rect_;
44
+ const Path64 rect_as_path_;
45
+ const Point64 rect_mp_;
46
+ Rect64 path_bounds_;
47
+ std::deque<OutPt2> op_container_;
48
+ OutPt2List results_; // each path can be broken into multiples
49
+ OutPt2List edges_[8]; // clockwise and counter-clockwise
50
+ std::vector<Location> start_locs_;
51
+ void CheckEdges();
52
+ void TidyEdges(size_t idx, OutPt2List& cw, OutPt2List& ccw);
53
+ void GetNextLocation(const Path64& path,
54
+ Location& loc, size_t& i, size_t highI);
55
+ OutPt2* Add(Point64 pt, bool start_new = false);
56
+ void AddCorner(Location prev, Location curr);
57
+ void AddCorner(Location& loc, bool isClockwise);
58
+ public:
59
+ explicit RectClip64(const Rect64& rect) :
60
+ rect_(rect),
61
+ rect_as_path_(rect.AsPath()),
62
+ rect_mp_(rect.MidPoint()) {}
63
+ Paths64 Execute(const Paths64& paths);
64
+ };
65
+
66
+ //------------------------------------------------------------------------------
67
+ // RectClipLines64
68
+ //------------------------------------------------------------------------------
69
+
70
+ class RectClipLines64 : public RectClip64 {
71
+ private:
72
+ void ExecuteInternal(const Path64& path);
73
+ Path64 GetPath(OutPt2*& op);
74
+ public:
75
+ explicit RectClipLines64(const Rect64& rect) : RectClip64(rect) {}
76
+ Paths64 Execute(const Paths64& paths);
77
+ };
78
+
79
+ } // Clipper2Lib namespace
80
+ #endif // CLIPPER_RECTCLIP_H
@@ -0,0 +1,27 @@
1
+ /*******************************************************************************
2
+ * Author : Angus Johnson *
3
+ * Date : 6 December 2025 *
4
+ * Release : BETA RELEASE *
5
+ * Website : https://www.angusj.com *
6
+ * Copyright : Angus Johnson 2010-2025 *
7
+ * Purpose : Delaunay Triangulation *
8
+ * License : https://www.boost.org/LICENSE_1_0.txt *
9
+ *******************************************************************************/
10
+
11
+ #ifndef CLIPPER_TRIANGULATION_H
12
+ #define CLIPPER_TRIANGULATION_H
13
+
14
+ #include <stack>
15
+ #include "clipper2/clipper.core.h"
16
+
17
+ namespace Clipper2Lib
18
+ {
19
+
20
+ enum class TriangulateResult { success, fail, no_polygons, paths_intersect };
21
+
22
+ // Triangulate - this function will not accept intesecting paths
23
+ TriangulateResult Triangulate(const Paths64& pp, Paths64& solution, bool useDelaunay = true);
24
+ TriangulateResult Triangulate(const PathsD& pp, int decPlaces, PathsD& solution, bool useDelaunay = true);
25
+
26
+ } // Clipper2Lib namespace
27
+ #endif // CLIPPER_TRIANGULATION_H
@@ -0,0 +1,6 @@
1
+ #ifndef CLIPPER_VERSION_H
2
+ #define CLIPPER_VERSION_H
3
+
4
+ constexpr auto CLIPPER2_VERSION = "2.0.1";
5
+
6
+ #endif // CLIPPER_VERSION_H