summaryrefslogtreecommitdiffstats
path: root/core/math/geometry_2d.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/math/geometry_2d.cpp')
-rw-r--r--core/math/geometry_2d.cpp111
1 files changed, 53 insertions, 58 deletions
diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp
index 602e95bc13..d60619b27f 100644
--- a/core/math/geometry_2d.cpp
+++ b/core/math/geometry_2d.cpp
@@ -30,12 +30,12 @@
#include "geometry_2d.h"
-#include "thirdparty/misc/clipper.hpp"
+#include "thirdparty/clipper2/include/clipper2/clipper.h"
#include "thirdparty/misc/polypartition.h"
#define STB_RECT_PACK_IMPLEMENTATION
#include "thirdparty/misc/stb_rect_pack.h"
-#define SCALE_FACTOR 100000.0 // Based on CMP_EPSILON.
+#define PRECISION 5 // Based on CMP_EPSILON.
Vector<Vector<Vector2>> Geometry2D::decompose_polygon_in_convex(const Vector<Point2> &polygon) {
Vector<Vector<Vector2>> decomp;
@@ -196,58 +196,59 @@ void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_re
}
Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open) {
- using namespace ClipperLib;
+ using namespace Clipper2Lib;
- ClipType op = ctUnion;
+ ClipType op = ClipType::Union;
switch (p_op) {
case OPERATION_UNION:
- op = ctUnion;
+ op = ClipType::Union;
break;
case OPERATION_DIFFERENCE:
- op = ctDifference;
+ op = ClipType::Difference;
break;
case OPERATION_INTERSECTION:
- op = ctIntersection;
+ op = ClipType::Intersection;
break;
case OPERATION_XOR:
- op = ctXor;
+ op = ClipType::Xor;
break;
}
- Path path_a, path_b;
- // Need to scale points (Clipper's requirement for robust computation).
+ PathD path_a(p_polypath_a.size());
for (int i = 0; i != p_polypath_a.size(); ++i) {
- path_a << IntPoint(p_polypath_a[i].x * (real_t)SCALE_FACTOR, p_polypath_a[i].y * (real_t)SCALE_FACTOR);
+ path_a[i] = PointD(p_polypath_a[i].x, p_polypath_a[i].y);
}
+ PathD path_b(p_polypath_b.size());
for (int i = 0; i != p_polypath_b.size(); ++i) {
- path_b << IntPoint(p_polypath_b[i].x * (real_t)SCALE_FACTOR, p_polypath_b[i].y * (real_t)SCALE_FACTOR);
+ path_b[i] = PointD(p_polypath_b[i].x, p_polypath_b[i].y);
}
- Clipper clp;
- clp.AddPath(path_a, ptSubject, !is_a_open); // Forward compatible with Clipper 10.0.0.
- clp.AddPath(path_b, ptClip, true); // Polylines cannot be set as clip.
- Paths paths;
+ ClipperD clp(PRECISION); // Scale points up internally to attain the desired precision.
+ clp.PreserveCollinear(false); // Remove redundant vertices.
+ if (is_a_open) {
+ clp.AddOpenSubject({ path_a });
+ } else {
+ clp.AddSubject({ path_a });
+ }
+ clp.AddClip({ path_b });
+
+ PathsD paths;
if (is_a_open) {
- PolyTree tree; // Needed to populate polylines.
- clp.Execute(op, tree);
- OpenPathsFromPolyTree(tree, paths);
+ PolyTreeD tree; // Needed to populate polylines.
+ clp.Execute(op, FillRule::EvenOdd, tree, paths);
} else {
- clp.Execute(op, paths); // Works on closed polygons only.
+ clp.Execute(op, FillRule::EvenOdd, paths); // Works on closed polygons only.
}
- // Have to scale points down now.
+
Vector<Vector<Point2>> polypaths;
+ for (PathsD::size_type i = 0; i < paths.size(); ++i) {
+ const PathD &path = paths[i];
- for (Paths::size_type i = 0; i < paths.size(); ++i) {
Vector<Vector2> polypath;
-
- const Path &scaled_path = paths[i];
-
- for (Paths::size_type j = 0; j < scaled_path.size(); ++j) {
- polypath.push_back(Point2(
- static_cast<real_t>(scaled_path[j].X) / (real_t)SCALE_FACTOR,
- static_cast<real_t>(scaled_path[j].Y) / (real_t)SCALE_FACTOR));
+ for (PathsD::size_type j = 0; j < path.size(); ++j) {
+ polypath.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
}
polypaths.push_back(polypath);
}
@@ -255,67 +256,61 @@ Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation
}
Vector<Vector<Point2>> Geometry2D::_polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
- using namespace ClipperLib;
+ using namespace Clipper2Lib;
- JoinType jt = jtSquare;
+ JoinType jt = JoinType::Square;
switch (p_join_type) {
case JOIN_SQUARE:
- jt = jtSquare;
+ jt = JoinType::Square;
break;
case JOIN_ROUND:
- jt = jtRound;
+ jt = JoinType::Round;
break;
case JOIN_MITER:
- jt = jtMiter;
+ jt = JoinType::Miter;
break;
}
- EndType et = etClosedPolygon;
+ EndType et = EndType::Polygon;
switch (p_end_type) {
case END_POLYGON:
- et = etClosedPolygon;
+ et = EndType::Polygon;
break;
case END_JOINED:
- et = etClosedLine;
+ et = EndType::Joined;
break;
case END_BUTT:
- et = etOpenButt;
+ et = EndType::Butt;
break;
case END_SQUARE:
- et = etOpenSquare;
+ et = EndType::Square;
break;
case END_ROUND:
- et = etOpenRound;
+ et = EndType::Round;
break;
}
- ClipperOffset co(2.0, 0.25f * (real_t)SCALE_FACTOR); // Defaults from ClipperOffset.
- Path path;
- // Need to scale points (Clipper's requirement for robust computation).
+ PathD polypath(p_polypath.size());
for (int i = 0; i != p_polypath.size(); ++i) {
- path << IntPoint(p_polypath[i].x * (real_t)SCALE_FACTOR, p_polypath[i].y * (real_t)SCALE_FACTOR);
+ polypath[i] = PointD(p_polypath[i].x, p_polypath[i].y);
}
- co.AddPath(path, jt, et);
- Paths paths;
- co.Execute(paths, p_delta * (real_t)SCALE_FACTOR); // Inflate/deflate.
+ // Inflate/deflate.
+ PathsD paths = InflatePaths({ polypath }, p_delta, jt, et, 2.0, PRECISION, 0.0);
+ // Here the miter_limit = 2.0 and arc_tolerance = 0.0 are Clipper2 defaults,
+ // and the PRECISION is used to scale points up internally, to attain the desired precision.
- // Have to scale points down now.
Vector<Vector<Point2>> polypaths;
+ for (PathsD::size_type i = 0; i < paths.size(); ++i) {
+ const PathD &path = paths[i];
- for (Paths::size_type i = 0; i < paths.size(); ++i) {
- Vector<Vector2> polypath;
-
- const Path &scaled_path = paths[i];
-
- for (Paths::size_type j = 0; j < scaled_path.size(); ++j) {
- polypath.push_back(Point2(
- static_cast<real_t>(scaled_path[j].X) / (real_t)SCALE_FACTOR,
- static_cast<real_t>(scaled_path[j].Y) / (real_t)SCALE_FACTOR));
+ Vector<Vector2> polypath2;
+ for (PathsD::size_type j = 0; j < path.size(); ++j) {
+ polypath2.push_back(Point2(static_cast<real_t>(path[j].x), static_cast<real_t>(path[j].y)));
}
- polypaths.push_back(polypath);
+ polypaths.push_back(polypath2);
}
return polypaths;
}