Replace Clipper1 library by Clipper2 library
This commit is contained in:
parent
4a0160241f
commit
8a28f816d0
8 changed files with 82 additions and 5332 deletions
|
@ -360,12 +360,6 @@ Copyright: 1998-2010, Gilles Vollant
|
|||
2009-2010, Mathias Svensson
|
||||
License: Zlib
|
||||
|
||||
Files: ./thirdparty/misc/clipper.cpp
|
||||
./thirdparty/misc/clipper.hpp
|
||||
Comment: Clipper
|
||||
Copyright: 2010-2017, Angus Johnson
|
||||
License: BSL-1.0
|
||||
|
||||
Files: ./thirdparty/misc/cubemap_coeffs.h
|
||||
Comment: Fast Filtering of Reflection Probes
|
||||
Copyright: 2016, Activision Publishing, Inc.
|
||||
|
|
|
@ -61,7 +61,6 @@ thirdparty_misc_sources = [
|
|||
# C++ sources
|
||||
"pcg.cpp",
|
||||
"polypartition.cpp",
|
||||
"clipper.cpp",
|
||||
"smolv.cpp",
|
||||
]
|
||||
thirdparty_misc_sources = [thirdparty_misc_dir + file for file in thirdparty_misc_sources]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,9 @@
|
|||
#include "scene/gui/menu_button.h"
|
||||
#include "scene/gui/panel.h"
|
||||
#include "scene/gui/view_panner.h"
|
||||
#include "thirdparty/misc/clipper.hpp"
|
||||
#include "thirdparty/clipper2/include/clipper2/clipper.h"
|
||||
|
||||
#define PRECISION 1
|
||||
|
||||
void Sprite2DEditor::_node_removed(Node *p_node) {
|
||||
if (p_node == node) {
|
||||
|
@ -59,58 +61,39 @@ void Sprite2DEditor::edit(Sprite2D *p_sprite) {
|
|||
node = p_sprite;
|
||||
}
|
||||
|
||||
#define PRECISION 10.0
|
||||
|
||||
Vector<Vector2> expand(const Vector<Vector2> &points, const Rect2i &rect, float epsilon = 2.0) {
|
||||
int size = points.size();
|
||||
ERR_FAIL_COND_V(size < 2, Vector<Vector2>());
|
||||
|
||||
ClipperLib::Path subj;
|
||||
ClipperLib::PolyTree solution;
|
||||
ClipperLib::PolyTree out;
|
||||
|
||||
Clipper2Lib::PathD subj(points.size());
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
subj << ClipperLib::IntPoint(points[i].x * PRECISION, points[i].y * PRECISION);
|
||||
}
|
||||
ClipperLib::ClipperOffset co;
|
||||
co.AddPath(subj, ClipperLib::jtMiter, ClipperLib::etClosedPolygon);
|
||||
co.Execute(solution, epsilon * PRECISION);
|
||||
|
||||
ClipperLib::PolyNode *p = solution.GetFirst();
|
||||
|
||||
ERR_FAIL_NULL_V(p, points);
|
||||
|
||||
while (p->IsHole()) {
|
||||
p = p->GetNext();
|
||||
subj[i] = Clipper2Lib::PointD(points[i].x, points[i].y);
|
||||
}
|
||||
|
||||
//turn the result into simply polygon (AKA, fix overlap)
|
||||
Clipper2Lib::PathsD solution = Clipper2Lib::InflatePaths({ subj }, epsilon, Clipper2Lib::JoinType::Miter, Clipper2Lib::EndType::Polygon, 2.0, PRECISION, 0.0);
|
||||
// Here the miter_limit = 2.0 and arc_tolerance = 0.0 are Clipper2 defaults,
|
||||
// and PRECISION is used to scale points up internally, to attain the desired precision.
|
||||
|
||||
//clamp into the specified rect
|
||||
ClipperLib::Clipper cl;
|
||||
cl.StrictlySimple(true);
|
||||
cl.AddPath(p->Contour, ClipperLib::ptSubject, true);
|
||||
//create the clipping rect
|
||||
ClipperLib::Path clamp;
|
||||
clamp.push_back(ClipperLib::IntPoint(0, 0));
|
||||
clamp.push_back(ClipperLib::IntPoint(rect.size.width * PRECISION, 0));
|
||||
clamp.push_back(ClipperLib::IntPoint(rect.size.width * PRECISION, rect.size.height * PRECISION));
|
||||
clamp.push_back(ClipperLib::IntPoint(0, rect.size.height * PRECISION));
|
||||
cl.AddPath(clamp, ClipperLib::ptClip, true);
|
||||
cl.Execute(ClipperLib::ctIntersection, out);
|
||||
ERR_FAIL_COND_V(solution.size() == 0, points);
|
||||
|
||||
// Clamp into the specified rect.
|
||||
Clipper2Lib::RectD clamp(rect.position.x,
|
||||
rect.position.y,
|
||||
rect.position.x + rect.size.width,
|
||||
rect.position.y + rect.size.height);
|
||||
Clipper2Lib::PathsD out = Clipper2Lib::RectClip(clamp, solution[0], PRECISION);
|
||||
// Here PRECISION is used to scale points up internally, to attain the desired precision.
|
||||
|
||||
ERR_FAIL_COND_V(out.size() == 0, points);
|
||||
|
||||
const Clipper2Lib::PathD &p2 = out[0];
|
||||
|
||||
Vector<Vector2> outPoints;
|
||||
ClipperLib::PolyNode *p2 = out.GetFirst();
|
||||
ERR_FAIL_NULL_V(p2, points);
|
||||
|
||||
while (p2->IsHole()) {
|
||||
p2 = p2->GetNext();
|
||||
}
|
||||
|
||||
int lasti = p2->Contour.size() - 1;
|
||||
Vector2 prev = Vector2(p2->Contour[lasti].X / PRECISION, p2->Contour[lasti].Y / PRECISION);
|
||||
for (uint64_t i = 0; i < p2->Contour.size(); i++) {
|
||||
Vector2 cur = Vector2(p2->Contour[i].X / PRECISION, p2->Contour[i].Y / PRECISION);
|
||||
int lasti = p2.size() - 1;
|
||||
Vector2 prev = Vector2(p2[lasti].x, p2[lasti].y);
|
||||
for (uint64_t i = 0; i < p2.size(); i++) {
|
||||
Vector2 cur = Vector2(p2[i].x, p2[i].y);
|
||||
if (cur.distance_to(prev) > 0.5) {
|
||||
outPoints.push_back(cur);
|
||||
prev = cur;
|
||||
|
|
|
@ -711,12 +711,12 @@ TEST_CASE("[Geometry2D] Clip polyline with polygon") {
|
|||
r = Geometry2D::clip_polyline_with_polygon(l, p);
|
||||
REQUIRE_MESSAGE(r.size() == 2, "There should be 2 resulting clipped lines.");
|
||||
REQUIRE_MESSAGE(r[0].size() == 3, "The resulting clipped line should have 3 vertices.");
|
||||
CHECK(r[0][0].is_equal_approx(Vector2(160, 320)));
|
||||
CHECK(r[0][0].is_equal_approx(Vector2(121.412682, 225.038757)));
|
||||
CHECK(r[0][1].is_equal_approx(Vector2(122, 250)));
|
||||
CHECK(r[0][2].is_equal_approx(Vector2(121.412682, 225.038757)));
|
||||
CHECK(r[0][2].is_equal_approx(Vector2(160, 320)));
|
||||
REQUIRE_MESSAGE(r[1].size() == 2, "The resulting clipped line should have 2 vertices.");
|
||||
CHECK(r[1][0].is_equal_approx(Vector2(53.07737, 116.143021)));
|
||||
CHECK(r[1][1].is_equal_approx(Vector2(55, 70)));
|
||||
CHECK(r[1][0].is_equal_approx(Vector2(55, 70)));
|
||||
CHECK(r[1][1].is_equal_approx(Vector2(53.07737, 116.143021)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
4661
thirdparty/misc/clipper.cpp
vendored
4661
thirdparty/misc/clipper.cpp
vendored
File diff suppressed because it is too large
Load diff
406
thirdparty/misc/clipper.hpp
vendored
406
thirdparty/misc/clipper.hpp
vendored
|
@ -1,406 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* *
|
||||
* Author : Angus Johnson *
|
||||
* Version : 6.4.2 *
|
||||
* Date : 27 February 2017 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2017 *
|
||||
* *
|
||||
* License: *
|
||||
* Use, modification & distribution is subject to Boost Software License Ver 1. *
|
||||
* http://www.boost.org/LICENSE_1_0.txt *
|
||||
* *
|
||||
* Attributions: *
|
||||
* The code in this library is an extension of Bala Vatti's clipping algorithm: *
|
||||
* "A generic solution to polygon clipping" *
|
||||
* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
|
||||
* http://portal.acm.org/citation.cfm?id=129906 *
|
||||
* *
|
||||
* Computer graphics and geometric modeling: implementation and algorithms *
|
||||
* By Max K. Agoston *
|
||||
* Springer; 1 edition (January 4, 2005) *
|
||||
* http://books.google.com/books?q=vatti+clipping+agoston *
|
||||
* *
|
||||
* See also: *
|
||||
* "Polygon Offsetting by Computing Winding Numbers" *
|
||||
* Paper no. DETC2005-85513 pp. 565-575 *
|
||||
* ASME 2005 International Design Engineering Technical Conferences *
|
||||
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
|
||||
* September 24-28, 2005 , Long Beach, California, USA *
|
||||
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef clipper_hpp
|
||||
#define clipper_hpp
|
||||
|
||||
#define CLIPPER_VERSION "6.4.2"
|
||||
|
||||
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
|
||||
//improve performance but coordinate values are limited to the range +/- 46340
|
||||
//#define use_int32
|
||||
|
||||
//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
|
||||
//#define use_xyz
|
||||
|
||||
//use_lines: Enables line clipping. Adds a very minor cost to performance.
|
||||
#define use_lines
|
||||
|
||||
//use_deprecated: Enables temporary support for the obsolete functions
|
||||
//#define use_deprecated
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ostream>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
|
||||
namespace ClipperLib {
|
||||
|
||||
enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
|
||||
enum PolyType { ptSubject, ptClip };
|
||||
//By far the most widely used winding rules for polygon filling are
|
||||
//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
|
||||
//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
|
||||
//see http://glprogramming.com/red/chapter11.html
|
||||
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
|
||||
|
||||
#ifdef use_int32
|
||||
typedef int cInt;
|
||||
static cInt const loRange = 0x7FFF;
|
||||
static cInt const hiRange = 0x7FFF;
|
||||
#else
|
||||
typedef signed long long cInt;
|
||||
static cInt const loRange = 0x3FFFFFFF;
|
||||
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
||||
typedef signed long long long64; //used by Int128 class
|
||||
typedef unsigned long long ulong64;
|
||||
|
||||
#endif
|
||||
|
||||
struct IntPoint {
|
||||
cInt X;
|
||||
cInt Y;
|
||||
#ifdef use_xyz
|
||||
cInt Z;
|
||||
IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
|
||||
#else
|
||||
IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
|
||||
#endif
|
||||
|
||||
friend inline bool operator== (const IntPoint& a, const IntPoint& b)
|
||||
{
|
||||
return a.X == b.X && a.Y == b.Y;
|
||||
}
|
||||
friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
|
||||
{
|
||||
return a.X != b.X || a.Y != b.Y;
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
typedef std::vector< IntPoint > Path;
|
||||
typedef std::vector< Path > Paths;
|
||||
|
||||
inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
|
||||
inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, const IntPoint &p);
|
||||
std::ostream& operator <<(std::ostream &s, const Path &p);
|
||||
std::ostream& operator <<(std::ostream &s, const Paths &p);
|
||||
|
||||
struct DoublePoint
|
||||
{
|
||||
double X;
|
||||
double Y;
|
||||
DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
|
||||
DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef use_xyz
|
||||
typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
|
||||
#endif
|
||||
|
||||
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
|
||||
enum JoinType {jtSquare, jtRound, jtMiter};
|
||||
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
|
||||
|
||||
class PolyNode;
|
||||
typedef std::vector< PolyNode* > PolyNodes;
|
||||
|
||||
class PolyNode
|
||||
{
|
||||
public:
|
||||
PolyNode();
|
||||
virtual ~PolyNode(){};
|
||||
Path Contour;
|
||||
PolyNodes Childs;
|
||||
PolyNode* Parent;
|
||||
PolyNode* GetNext() const;
|
||||
bool IsHole() const;
|
||||
bool IsOpen() const;
|
||||
int ChildCount() const;
|
||||
private:
|
||||
//PolyNode& operator =(PolyNode& other);
|
||||
unsigned Index; //node index in Parent.Childs
|
||||
bool m_IsOpen;
|
||||
JoinType m_jointype;
|
||||
EndType m_endtype;
|
||||
PolyNode* GetNextSiblingUp() const;
|
||||
void AddChild(PolyNode& child);
|
||||
friend class Clipper; //to access Index
|
||||
friend class ClipperOffset;
|
||||
};
|
||||
|
||||
class PolyTree: public PolyNode
|
||||
{
|
||||
public:
|
||||
~PolyTree(){ Clear(); };
|
||||
PolyNode* GetFirst() const;
|
||||
void Clear();
|
||||
int Total() const;
|
||||
private:
|
||||
//PolyTree& operator =(PolyTree& other);
|
||||
PolyNodes AllNodes;
|
||||
friend class Clipper; //to access AllNodes
|
||||
};
|
||||
|
||||
bool Orientation(const Path &poly);
|
||||
double Area(const Path &poly);
|
||||
int PointInPolygon(const IntPoint &pt, const Path &path);
|
||||
|
||||
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
|
||||
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
|
||||
|
||||
void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
|
||||
void CleanPolygon(Path& poly, double distance = 1.415);
|
||||
void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
|
||||
void CleanPolygons(Paths& polys, double distance = 1.415);
|
||||
|
||||
void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
|
||||
void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed);
|
||||
void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
|
||||
|
||||
void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
|
||||
void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
|
||||
void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
|
||||
|
||||
void ReversePath(Path& p);
|
||||
void ReversePaths(Paths& p);
|
||||
|
||||
struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
|
||||
|
||||
//enums that are used internally ...
|
||||
enum EdgeSide { esLeft = 1, esRight = 2};
|
||||
|
||||
//forward declarations (for stuff used internally) ...
|
||||
struct TEdge;
|
||||
struct IntersectNode;
|
||||
struct LocalMinimum;
|
||||
struct OutPt;
|
||||
struct OutRec;
|
||||
struct Join;
|
||||
|
||||
typedef std::vector < OutRec* > PolyOutList;
|
||||
typedef std::vector < TEdge* > EdgeList;
|
||||
typedef std::vector < Join* > JoinList;
|
||||
typedef std::vector < IntersectNode* > IntersectList;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//ClipperBase is the ancestor to the Clipper class. It should not be
|
||||
//instantiated directly. This class simply abstracts the conversion of sets of
|
||||
//polygon coordinates into edge objects that are stored in a LocalMinima list.
|
||||
class ClipperBase
|
||||
{
|
||||
public:
|
||||
ClipperBase();
|
||||
virtual ~ClipperBase();
|
||||
virtual bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
|
||||
bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
|
||||
virtual void Clear();
|
||||
IntRect GetBounds();
|
||||
bool PreserveCollinear() {return m_PreserveCollinear;};
|
||||
void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
|
||||
protected:
|
||||
void DisposeLocalMinimaList();
|
||||
TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
|
||||
virtual void Reset();
|
||||
TEdge* ProcessBound(TEdge* E, bool IsClockwise);
|
||||
void InsertScanbeam(const cInt Y);
|
||||
bool PopScanbeam(cInt &Y);
|
||||
bool LocalMinimaPending();
|
||||
bool PopLocalMinima(cInt Y, const LocalMinimum *&locMin);
|
||||
OutRec* CreateOutRec();
|
||||
void DisposeAllOutRecs();
|
||||
void DisposeOutRec(PolyOutList::size_type index);
|
||||
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
|
||||
void DeleteFromAEL(TEdge *e);
|
||||
void UpdateEdgeIntoAEL(TEdge *&e);
|
||||
|
||||
typedef std::vector<LocalMinimum> MinimaList;
|
||||
MinimaList::iterator m_CurrentLM;
|
||||
MinimaList m_MinimaList;
|
||||
|
||||
bool m_UseFullRange;
|
||||
EdgeList m_edges;
|
||||
bool m_PreserveCollinear;
|
||||
bool m_HasOpenPaths;
|
||||
PolyOutList m_PolyOuts;
|
||||
TEdge *m_ActiveEdges;
|
||||
|
||||
typedef std::priority_queue<cInt> ScanbeamList;
|
||||
ScanbeamList m_Scanbeam;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class Clipper : public virtual ClipperBase
|
||||
{
|
||||
public:
|
||||
Clipper(int initOptions = 0);
|
||||
bool Execute(ClipType clipType,
|
||||
Paths &solution,
|
||||
PolyFillType fillType = pftEvenOdd);
|
||||
bool Execute(ClipType clipType,
|
||||
Paths &solution,
|
||||
PolyFillType subjFillType,
|
||||
PolyFillType clipFillType);
|
||||
bool Execute(ClipType clipType,
|
||||
PolyTree &polytree,
|
||||
PolyFillType fillType = pftEvenOdd);
|
||||
bool Execute(ClipType clipType,
|
||||
PolyTree &polytree,
|
||||
PolyFillType subjFillType,
|
||||
PolyFillType clipFillType);
|
||||
bool ReverseSolution() { return m_ReverseOutput; };
|
||||
void ReverseSolution(bool value) {m_ReverseOutput = value;};
|
||||
bool StrictlySimple() {return m_StrictSimple;};
|
||||
void StrictlySimple(bool value) {m_StrictSimple = value;};
|
||||
//set the callback function for z value filling on intersections (otherwise Z is 0)
|
||||
#ifdef use_xyz
|
||||
void ZFillFunction(ZFillCallback zFillFunc);
|
||||
#endif
|
||||
protected:
|
||||
virtual bool ExecuteInternal();
|
||||
private:
|
||||
JoinList m_Joins;
|
||||
JoinList m_GhostJoins;
|
||||
IntersectList m_IntersectList;
|
||||
ClipType m_ClipType;
|
||||
typedef std::list<cInt> MaximaList;
|
||||
MaximaList m_Maxima;
|
||||
TEdge *m_SortedEdges;
|
||||
bool m_ExecuteLocked;
|
||||
PolyFillType m_ClipFillType;
|
||||
PolyFillType m_SubjFillType;
|
||||
bool m_ReverseOutput;
|
||||
bool m_UsingPolyTree;
|
||||
bool m_StrictSimple;
|
||||
#ifdef use_xyz
|
||||
ZFillCallback m_ZFill; //custom callback
|
||||
#endif
|
||||
void SetWindingCount(TEdge& edge);
|
||||
bool IsEvenOddFillType(const TEdge& edge) const;
|
||||
bool IsEvenOddAltFillType(const TEdge& edge) const;
|
||||
void InsertLocalMinimaIntoAEL(const cInt botY);
|
||||
void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
|
||||
void AddEdgeToSEL(TEdge *edge);
|
||||
bool PopEdgeFromSEL(TEdge *&edge);
|
||||
void CopyAELToSEL();
|
||||
void DeleteFromSEL(TEdge *e);
|
||||
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
|
||||
bool IsContributing(const TEdge& edge) const;
|
||||
bool IsTopHorz(const cInt XPos);
|
||||
void DoMaxima(TEdge *e);
|
||||
void ProcessHorizontals();
|
||||
void ProcessHorizontal(TEdge *horzEdge);
|
||||
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||
OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
|
||||
OutRec* GetOutRec(int idx);
|
||||
void AppendPolygon(TEdge *e1, TEdge *e2);
|
||||
void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
|
||||
OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
|
||||
OutPt* GetLastOutPt(TEdge *e);
|
||||
bool ProcessIntersections(const cInt topY);
|
||||
void BuildIntersectList(const cInt topY);
|
||||
void ProcessIntersectList();
|
||||
void ProcessEdgesAtTopOfScanbeam(const cInt topY);
|
||||
void BuildResult(Paths& polys);
|
||||
void BuildResult2(PolyTree& polytree);
|
||||
void SetHoleState(TEdge *e, OutRec *outrec);
|
||||
void DisposeIntersectNodes();
|
||||
bool FixupIntersectionOrder();
|
||||
void FixupOutPolygon(OutRec &outrec);
|
||||
void FixupOutPolyline(OutRec &outrec);
|
||||
bool IsHole(TEdge *e);
|
||||
bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
|
||||
void FixHoleLinkage(OutRec &outrec);
|
||||
void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
|
||||
void ClearJoins();
|
||||
void ClearGhostJoins();
|
||||
void AddGhostJoin(OutPt *op, const IntPoint offPt);
|
||||
bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
|
||||
void JoinCommonEdges();
|
||||
void DoSimplePolygons();
|
||||
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
|
||||
void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
|
||||
#ifdef use_xyz
|
||||
void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
|
||||
#endif
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ClipperOffset
|
||||
{
|
||||
public:
|
||||
ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
|
||||
~ClipperOffset();
|
||||
void AddPath(const Path& path, JoinType joinType, EndType endType);
|
||||
void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
|
||||
void Execute(Paths& solution, double delta);
|
||||
void Execute(PolyTree& solution, double delta);
|
||||
void Clear();
|
||||
double MiterLimit;
|
||||
double ArcTolerance;
|
||||
private:
|
||||
Paths m_destPolys;
|
||||
Path m_srcPoly;
|
||||
Path m_destPoly;
|
||||
std::vector<DoublePoint> m_normals;
|
||||
double m_delta, m_sinA, m_sin, m_cos;
|
||||
double m_miterLim, m_StepsPerRad;
|
||||
IntPoint m_lowest;
|
||||
PolyNode m_polyNodes;
|
||||
|
||||
void FixOrientations();
|
||||
void DoOffset(double delta);
|
||||
void OffsetPoint(int j, int& k, JoinType jointype);
|
||||
void DoSquare(int j, int k);
|
||||
void DoMiter(int j, int k, double r);
|
||||
void DoRound(int j, int k);
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class clipperException : public std::exception
|
||||
{
|
||||
public:
|
||||
clipperException(const char* description): m_descr(description) {}
|
||||
virtual ~clipperException() throw() {}
|
||||
virtual const char* what() const throw() {return m_descr.c_str();}
|
||||
private:
|
||||
std::string m_descr;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} //ClipperLib namespace
|
||||
|
||||
#endif //clipper_hpp
|
||||
|
||||
|
154
thirdparty/misc/patches/clipper-exceptions.patch
vendored
154
thirdparty/misc/patches/clipper-exceptions.patch
vendored
|
@ -1,154 +0,0 @@
|
|||
diff --git a/thirdparty/misc/clipper.cpp b/thirdparty/misc/clipper.cpp
|
||||
index 8c3a59c4ca..c67045d113 100644
|
||||
--- a/thirdparty/misc/clipper.cpp
|
||||
+++ b/thirdparty/misc/clipper.cpp
|
||||
@@ -48,6 +48,38 @@
|
||||
#include <ostream>
|
||||
#include <functional>
|
||||
|
||||
+//Explicitly disables exceptions handling for target platform
|
||||
+//#define CLIPPER_NOEXCEPTION
|
||||
+
|
||||
+#define CLIPPER_THROW(exception) std::abort()
|
||||
+#define CLIPPER_TRY if(true)
|
||||
+#define CLIPPER_CATCH(exception) if(false)
|
||||
+
|
||||
+#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
|
||||
+ #ifndef CLIPPER_NOEXCEPTION
|
||||
+ #undef CLIPPER_THROW
|
||||
+ #define CLIPPER_THROW(exception) throw exception
|
||||
+ #undef CLIPPER_TRY
|
||||
+ #define CLIPPER_TRY try
|
||||
+ #undef CLIPPER_CATCH
|
||||
+ #define CLIPPER_CATCH(exception) catch(exception)
|
||||
+ #endif
|
||||
+#endif
|
||||
+
|
||||
+//Optionally allows to override exception macros
|
||||
+#if defined(CLIPPER_THROW_USER)
|
||||
+ #undef CLIPPER_THROW
|
||||
+ #define CLIPPER_THROW CLIPPER_THROW_USER
|
||||
+#endif
|
||||
+#if defined(CLIPPER_TRY_USER)
|
||||
+ #undef CLIPPER_TRY
|
||||
+ #define CLIPPER_TRY CLIPPER_TRY_USER
|
||||
+#endif
|
||||
+#if defined(CLIPPER_CATCH_USER)
|
||||
+ #undef CLIPPER_CATCH
|
||||
+ #define CLIPPER_CATCH CLIPPER_CATCH_USER
|
||||
+#endif
|
||||
+
|
||||
namespace ClipperLib {
|
||||
|
||||
static double const pi = 3.141592653589793238;
|
||||
@@ -898,7 +930,7 @@ void RangeTest(const IntPoint& Pt, bool& useFullRange)
|
||||
if (useFullRange)
|
||||
{
|
||||
if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange)
|
||||
- throw clipperException("Coordinate outside allowed range");
|
||||
+ CLIPPER_THROW(clipperException("Coordinate outside allowed range"));
|
||||
}
|
||||
else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange)
|
||||
{
|
||||
@@ -1046,10 +1078,10 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||
{
|
||||
#ifdef use_lines
|
||||
if (!Closed && PolyTyp == ptClip)
|
||||
- throw clipperException("AddPath: Open paths must be subject.");
|
||||
+ CLIPPER_THROW(clipperException("AddPath: Open paths must be subject."));
|
||||
#else
|
||||
if (!Closed)
|
||||
- throw clipperException("AddPath: Open paths have been disabled.");
|
||||
+ CLIPPER_THROW(clipperException("AddPath: Open paths have been disabled."));
|
||||
#endif
|
||||
|
||||
int highI = (int)pg.size() -1;
|
||||
@@ -1062,7 +1094,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||
|
||||
bool IsFlat = true;
|
||||
//1. Basic (first) edge initialization ...
|
||||
- try
|
||||
+ CLIPPER_TRY
|
||||
{
|
||||
edges[1].Curr = pg[1];
|
||||
RangeTest(pg[0], m_UseFullRange);
|
||||
@@ -1075,10 +1107,10 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
|
||||
InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]);
|
||||
}
|
||||
}
|
||||
- catch(...)
|
||||
+ CLIPPER_CATCH(...)
|
||||
{
|
||||
delete [] edges;
|
||||
- throw; //range test fails
|
||||
+ CLIPPER_THROW(); //range test fails
|
||||
}
|
||||
TEdge *eStart = &edges[0];
|
||||
|
||||
@@ -1442,7 +1474,7 @@ void ClipperBase::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2)
|
||||
void ClipperBase::UpdateEdgeIntoAEL(TEdge *&e)
|
||||
{
|
||||
if (!e->NextInLML)
|
||||
- throw clipperException("UpdateEdgeIntoAEL: invalid call");
|
||||
+ CLIPPER_THROW(clipperException("UpdateEdgeIntoAEL: invalid call"));
|
||||
|
||||
e->NextInLML->OutIdx = e->OutIdx;
|
||||
TEdge* AelPrev = e->PrevInAEL;
|
||||
@@ -1510,7 +1542,7 @@ bool Clipper::Execute(ClipType clipType, Paths &solution,
|
||||
{
|
||||
if( m_ExecuteLocked ) return false;
|
||||
if (m_HasOpenPaths)
|
||||
- throw clipperException("Error: PolyTree struct is needed for open path clipping.");
|
||||
+ CLIPPER_THROW(clipperException("Error: PolyTree struct is needed for open path clipping."));
|
||||
m_ExecuteLocked = true;
|
||||
solution.resize(0);
|
||||
m_SubjFillType = subjFillType;
|
||||
@@ -1560,7 +1592,7 @@ void Clipper::FixHoleLinkage(OutRec &outrec)
|
||||
bool Clipper::ExecuteInternal()
|
||||
{
|
||||
bool succeeded = true;
|
||||
- try {
|
||||
+ CLIPPER_TRY {
|
||||
Reset();
|
||||
m_Maxima = MaximaList();
|
||||
m_SortedEdges = 0;
|
||||
@@ -1583,7 +1615,7 @@ bool Clipper::ExecuteInternal()
|
||||
InsertLocalMinimaIntoAEL(botY);
|
||||
}
|
||||
}
|
||||
- catch(...)
|
||||
+ CLIPPER_CATCH(...)
|
||||
{
|
||||
succeeded = false;
|
||||
}
|
||||
@@ -2827,18 +2859,18 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge)
|
||||
bool Clipper::ProcessIntersections(const cInt topY)
|
||||
{
|
||||
if( !m_ActiveEdges ) return true;
|
||||
- try {
|
||||
+ CLIPPER_TRY {
|
||||
BuildIntersectList(topY);
|
||||
size_t IlSize = m_IntersectList.size();
|
||||
if (IlSize == 0) return true;
|
||||
if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList();
|
||||
else return false;
|
||||
}
|
||||
- catch(...)
|
||||
+ CLIPPER_CATCH(...)
|
||||
{
|
||||
m_SortedEdges = 0;
|
||||
DisposeIntersectNodes();
|
||||
- throw clipperException("ProcessIntersections error");
|
||||
+ CLIPPER_THROW(clipperException("ProcessIntersections error"));
|
||||
}
|
||||
m_SortedEdges = 0;
|
||||
return true;
|
||||
@@ -3002,7 +3034,7 @@ void Clipper::DoMaxima(TEdge *e)
|
||||
DeleteFromAEL(eMaxPair);
|
||||
}
|
||||
#endif
|
||||
- else throw clipperException("DoMaxima error");
|
||||
+ else CLIPPER_THROW(clipperException("DoMaxima error"));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in a new issue