Replace Clipper1 library by Clipper2 library
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user