|
@@ -1,16 +1,16 @@
|
|
|
/*******************************************************************************
|
|
|
* Author : Angus Johnson *
|
|
|
-* Date : 14 May 2024 *
|
|
|
-* Website : http://www.angusj.com *
|
|
|
-* Copyright : Angus Johnson 2010-2024 *
|
|
|
+* Date : 24 January 2025 *
|
|
|
+* Website : https://www.angusj.com *
|
|
|
+* Copyright : Angus Johnson 2010-2025 *
|
|
|
* Purpose : This module exports the Clipper2 Library (ie DLL/so) *
|
|
|
-* License : http://www.boost.org/LICENSE_1_0.txt *
|
|
|
+* License : https://www.boost.org/LICENSE_1_0.txt *
|
|
|
*******************************************************************************/
|
|
|
|
|
|
|
|
|
/*
|
|
|
Boolean clipping:
|
|
|
- cliptype: None=0, Intersection=1, Union=2, Difference=3, Xor=4
|
|
|
+ cliptype: NoClip=0, Intersection=1, Union=2, Difference=3, Xor=4
|
|
|
fillrule: EvenOdd=0, NonZero=1, Positive=2, Negative=3
|
|
|
|
|
|
Polygon offsetting (inflate/deflate):
|
|
@@ -19,73 +19,104 @@
|
|
|
|
|
|
The path structures used extensively in other parts of this library are all
|
|
|
based on std::vector classes. Since C++ classes can't be accessed by other
|
|
|
-languages, these paths are converted into very simple array data structures
|
|
|
-(of either int64_t for CPath64 or double for CPathD) that can be parsed by
|
|
|
-just about any programming language.
|
|
|
+languages, these paths are exported here as very simple array structures
|
|
|
+(either of int64_t or double) that can be parsed by just about any
|
|
|
+programming language.
|
|
|
+
|
|
|
+These 2D paths are defined by series of x and y coordinates together with an
|
|
|
+optional user-defined 'z' value (see Z-values below). Hence, a vertex refers
|
|
|
+to a single x and y coordinate (+/- a user-defined value). Data structures
|
|
|
+have names with suffixes that indicate the array type (either int64_t or
|
|
|
+double). For example, the data structure CPath64 contains an array of int64_t
|
|
|
+values, whereas the data structure CPathD contains an array of double.
|
|
|
+Where documentation omits the type suffix (eg CPath), it is referring to an
|
|
|
+array whose data type could be either int64_t or double.
|
|
|
+
|
|
|
+For conciseness, the following letters are used in the diagrams below:
|
|
|
+N: Number of vertices in a given path
|
|
|
+C: Count (ie number) of paths (or PolyPaths) in the structure
|
|
|
+A: Number of elements in an array
|
|
|
+
|
|
|
|
|
|
CPath64 and CPathD:
|
|
|
-These are arrays of consecutive x and y path coordinates preceeded by
|
|
|
-a pair of values containing the path's length (N) and a 0 value.
|
|
|
-__________________________________
|
|
|
-|counter|coord1|coord2|...|coordN|
|
|
|
-|N, 0 |x1, y1|x2, y2|...|xN, yN|
|
|
|
-__________________________________
|
|
|
+These are arrays of either int64_t or double values. Apart from
|
|
|
+the first two elements, these arrays are a series of vertices
|
|
|
+that together define a path. The very first element contains the
|
|
|
+number of vertices (N) in the path, while second element should
|
|
|
+contain a 0 value.
|
|
|
+_______________________________________________________________
|
|
|
+| counters | vertex1 | vertex2 | ... | vertexN |
|
|
|
+| N, 0 | x1, y1, (z1) | x2, y2, (z2) | ... | xN, yN, (zN) |
|
|
|
+---------------------------------------------------------------
|
|
|
+
|
|
|
|
|
|
CPaths64 and CPathsD:
|
|
|
-These are also arrays containing any number of consecutive CPath64 or
|
|
|
-CPathD structures. But preceeding these consecutive paths, there is pair of
|
|
|
-values that contain the total length of the array structure (A) and the
|
|
|
-number of CPath64 or CPathD it contains (C). The space these structures will
|
|
|
-occupy in memory = A * sizeof(int64_t) or A * sizeof(double) respectively.
|
|
|
-_______________________________
|
|
|
-|counter|path1|path2|...|pathC|
|
|
|
-|A , C | |
|
|
|
-_______________________________
|
|
|
+These are also arrays of either int64_t or double values that
|
|
|
+contain any number of consecutive CPath structures. However,
|
|
|
+preceding the first path is a pair of values. The first value
|
|
|
+contains the length of the entire array structure (A), and the
|
|
|
+second contains the number (ie count) of contained paths (C).
|
|
|
+ Memory allocation for CPaths64 = A * sizeof(int64_t)
|
|
|
+ Memory allocation for CPathsD = A * sizeof(double)
|
|
|
+__________________________________________
|
|
|
+| counters | path1 | path2 | ... | pathC |
|
|
|
+| A, C | | | ... | |
|
|
|
+------------------------------------------
|
|
|
+
|
|
|
|
|
|
CPolytree64 and CPolytreeD:
|
|
|
-These are also arrays consisting of CPolyPath structures that represent
|
|
|
-individual paths in a tree structure. However, the very first (ie top)
|
|
|
-CPolyPath is just the tree container that doesn't have a path. And because
|
|
|
-of that, its structure will be very slightly different from the remaining
|
|
|
-CPolyPath. This difference will be discussed below.
|
|
|
+The entire polytree structure is an array of int64_t or double. The
|
|
|
+first element in the array indicates the array's total length (A).
|
|
|
+The second element indicates the number (C) of CPolyPath structures
|
|
|
+that are the TOP LEVEL CPolyPath in the polytree, and these top
|
|
|
+level CPolyPath immediately follow these first two array elements.
|
|
|
+These top level CPolyPath structures may, in turn, contain nested
|
|
|
+CPolyPath children, and these collectively make a tree structure.
|
|
|
+_________________________________________________________
|
|
|
+| counters | CPolyPath1 | CPolyPath2 | ... | CPolyPathC |
|
|
|
+| A, C | | | ... | |
|
|
|
+---------------------------------------------------------
|
|
|
|
|
|
-CPolyPath64 and CPolyPathD:
|
|
|
-These are simple arrays consisting of a series of path coordinates followed
|
|
|
-by any number of child (ie nested) CPolyPath. Preceeding these are two values
|
|
|
-indicating the length of the path (N) and the number of child CPolyPath (C).
|
|
|
-____________________________________________________________
|
|
|
-|counter|coord1|coord2|...|coordN| child1|child2|...|childC|
|
|
|
-|N , C |x1, y1|x2, y2|...|xN, yN| |
|
|
|
-____________________________________________________________
|
|
|
-
|
|
|
-As mentioned above, the very first CPolyPath structure is just a container
|
|
|
-that owns (both directly and indirectly) every other CPolyPath in the tree.
|
|
|
-Since this first CPolyPath has no path, instead of a path length, its very
|
|
|
-first value will contain the total length of the CPolytree array (not its
|
|
|
-total bytes length).
|
|
|
-
|
|
|
-Again, all theses exported structures (CPaths64, CPathsD, CPolyTree64 &
|
|
|
-CPolyTreeD) are arrays of either type int64_t or double, and the first
|
|
|
-value in these arrays will always be the length of that array.
|
|
|
-
|
|
|
-These array structures are allocated in heap memory which will eventually
|
|
|
-need to be released. However, since applications dynamically linking to
|
|
|
-these functions may use different memory managers, the only safe way to
|
|
|
-free up this memory is to use the exported DisposeArray64 and
|
|
|
-DisposeArrayD functions (see below).
|
|
|
-*/
|
|
|
|
|
|
+CPolyPath64 and CPolyPathD:
|
|
|
+These array structures consist of a pair of counter values followed by a
|
|
|
+series of polygon vertices and a series of nested CPolyPath children.
|
|
|
+The first counter values indicates the number of vertices in the
|
|
|
+polygon (N), and the second counter indicates the CPolyPath child count (C).
|
|
|
+_____________________________________________________________________________
|
|
|
+|cntrs |vertex1 |vertex2 |...|vertexN |child1|child2|...|childC|
|
|
|
+|N, C |x1, y1, (z1)| x2, y2, (z2)|...|xN, yN, (zN)| | |...| |
|
|
|
+-----------------------------------------------------------------------------
|
|
|
+
|
|
|
+
|
|
|
+DisposeArray64 & DisposeArrayD:
|
|
|
+All array structures are allocated in heap memory which will eventually
|
|
|
+need to be released. However, since applications linking to these DLL
|
|
|
+functions may use different memory managers, the only safe way to release
|
|
|
+this memory is to use the exported DisposeArray functions.
|
|
|
+
|
|
|
+
|
|
|
+(Optional) Z-Values:
|
|
|
+Structures will only contain user-defined z-values when the USINGZ
|
|
|
+pre-processor identifier is used. The library does not assign z-values
|
|
|
+because this field is intended for users to assign custom values to vertices.
|
|
|
+Z-values in input paths (subject and clip) will be copied to solution paths.
|
|
|
+New vertices at path intersections will generate a callback event that allows
|
|
|
+users to assign z-values at these new vertices. The user's callback function
|
|
|
+must conform with the DLLZCallback definition and be registered with the
|
|
|
+DLL via SetZCallback. To assist the user in assigning z-values, the library
|
|
|
+passes in the callback function the new intersection point together with
|
|
|
+the four vertices that define the two segments that are intersecting.
|
|
|
|
|
|
+*/
|
|
|
#ifndef CLIPPER2_EXPORT_H
|
|
|
#define CLIPPER2_EXPORT_H
|
|
|
|
|
|
-#include <cstdlib>
|
|
|
-#include <vector>
|
|
|
-
|
|
|
#include "clipper2/clipper.core.h"
|
|
|
#include "clipper2/clipper.engine.h"
|
|
|
#include "clipper2/clipper.offset.h"
|
|
|
#include "clipper2/clipper.rectclip.h"
|
|
|
+#include <cstdlib>
|
|
|
|
|
|
namespace Clipper2Lib {
|
|
|
|
|
@@ -127,6 +158,12 @@ inline Rect<T> CRectToRect(const CRect<T>& rect)
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+template <typename T1, typename T2>
|
|
|
+inline T1 Reinterpret(T2 value) {
|
|
|
+ return *reinterpret_cast<T1*>(&value);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
#ifdef _WIN32
|
|
|
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
|
|
|
#else
|
|
@@ -178,11 +215,22 @@ EXTERN_DLL_EXPORT CPaths64 InflatePaths64(const CPaths64 paths,
|
|
|
double delta, uint8_t jointype, uint8_t endtype,
|
|
|
double miter_limit = 2.0, double arc_tolerance = 0.0,
|
|
|
bool reverse_solution = false);
|
|
|
+
|
|
|
EXTERN_DLL_EXPORT CPathsD InflatePathsD(const CPathsD paths,
|
|
|
double delta, uint8_t jointype, uint8_t endtype,
|
|
|
int precision = 2, double miter_limit = 2.0,
|
|
|
double arc_tolerance = 0.0, bool reverse_solution = false);
|
|
|
|
|
|
+EXTERN_DLL_EXPORT CPaths64 InflatePath64(const CPath64 path,
|
|
|
+ double delta, uint8_t jointype, uint8_t endtype,
|
|
|
+ double miter_limit = 2.0, double arc_tolerance = 0.0,
|
|
|
+ bool reverse_solution = false);
|
|
|
+
|
|
|
+EXTERN_DLL_EXPORT CPathsD InflatePathD(const CPathD path,
|
|
|
+ double delta, uint8_t jointype, uint8_t endtype,
|
|
|
+ int precision = 2, double miter_limit = 2.0,
|
|
|
+ double arc_tolerance = 0.0, bool reverse_solution = false);
|
|
|
+
|
|
|
// RectClip & RectClipLines:
|
|
|
EXTERN_DLL_EXPORT CPaths64 RectClip64(const CRect64& rect,
|
|
|
const CPaths64 paths);
|
|
@@ -197,6 +245,15 @@ EXTERN_DLL_EXPORT CPathsD RectClipLinesD(const CRectD& rect,
|
|
|
// INTERNAL FUNCTIONS
|
|
|
//////////////////////////////////////////////////////
|
|
|
|
|
|
+#ifdef USINGZ
|
|
|
+ZCallback64 dllCallback64 = nullptr;
|
|
|
+ZCallbackD dllCallbackD = nullptr;
|
|
|
+
|
|
|
+constexpr int EXPORT_VERTEX_DIMENSIONALITY = 3;
|
|
|
+#else
|
|
|
+constexpr int EXPORT_VERTEX_DIMENSIONALITY = 2;
|
|
|
+#endif
|
|
|
+
|
|
|
template <typename T>
|
|
|
static void GetPathCountAndCPathsArrayLen(const Paths<T>& paths,
|
|
|
size_t& cnt, size_t& array_len)
|
|
@@ -206,30 +263,47 @@ static void GetPathCountAndCPathsArrayLen(const Paths<T>& paths,
|
|
|
for (const Path<T>& path : paths)
|
|
|
if (path.size())
|
|
|
{
|
|
|
- array_len += path.size() * 2 + 2;
|
|
|
+ array_len += path.size() * EXPORT_VERTEX_DIMENSIONALITY + 2;
|
|
|
++cnt;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static size_t GetPolyPath64ArrayLen(const PolyPath64& pp)
|
|
|
+static size_t GetPolyPathArrayLen64(const PolyPath64& pp)
|
|
|
+{
|
|
|
+ size_t result = 2; // poly_length + child_count
|
|
|
+ result += pp.Polygon().size() * EXPORT_VERTEX_DIMENSIONALITY;
|
|
|
+ //plus nested children :)
|
|
|
+ for (size_t i = 0; i < pp.Count(); ++i)
|
|
|
+ result += GetPolyPathArrayLen64(*pp[i]);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static size_t GetPolyPathArrayLenD(const PolyPathD& pp)
|
|
|
{
|
|
|
size_t result = 2; // poly_length + child_count
|
|
|
- result += pp.Polygon().size() * 2;
|
|
|
+ result += pp.Polygon().size() * EXPORT_VERTEX_DIMENSIONALITY;
|
|
|
//plus nested children :)
|
|
|
for (size_t i = 0; i < pp.Count(); ++i)
|
|
|
- result += GetPolyPath64ArrayLen(*pp[i]);
|
|
|
+ result += GetPolyPathArrayLenD(*pp[i]);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-static void GetPolytreeCountAndCStorageSize(const PolyTree64& tree,
|
|
|
+static void GetPolytreeCountAndCStorageSize64(const PolyTree64& tree,
|
|
|
+ size_t& cnt, size_t& array_len)
|
|
|
+{
|
|
|
+ cnt = tree.Count(); // nb: top level count only
|
|
|
+ array_len = GetPolyPathArrayLen64(tree);
|
|
|
+}
|
|
|
+
|
|
|
+static void GetPolytreeCountAndCStorageSizeD(const PolyTreeD& tree,
|
|
|
size_t& cnt, size_t& array_len)
|
|
|
{
|
|
|
cnt = tree.Count(); // nb: top level count only
|
|
|
- array_len = GetPolyPath64ArrayLen(tree);
|
|
|
+ array_len = GetPolyPathArrayLenD(tree);
|
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
|
-static T* CreateCPaths(const Paths<T>& paths)
|
|
|
+static T* CreateCPathsFromPathsT(const Paths<T>& paths)
|
|
|
{
|
|
|
size_t cnt = 0, array_len = 0;
|
|
|
GetPathCountAndCPathsArrayLen(paths, cnt, array_len);
|
|
@@ -245,11 +319,38 @@ static T* CreateCPaths(const Paths<T>& paths)
|
|
|
{
|
|
|
*v++ = pt.x;
|
|
|
*v++ = pt.y;
|
|
|
+#ifdef USINGZ
|
|
|
+ *v++ = Reinterpret<T>(pt.z);
|
|
|
+#endif
|
|
|
}
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+CPathsD CreateCPathsDFromPathsD(const PathsD& paths)
|
|
|
+{
|
|
|
+ if (!paths.size()) return nullptr;
|
|
|
+ size_t cnt, array_len;
|
|
|
+ GetPathCountAndCPathsArrayLen(paths, cnt, array_len);
|
|
|
+ CPathsD result = new double[array_len], v = result;
|
|
|
+ *v++ = (double)array_len;
|
|
|
+ *v++ = (double)cnt;
|
|
|
+ for (const PathD& path : paths)
|
|
|
+ {
|
|
|
+ if (!path.size()) continue;
|
|
|
+ *v = (double)path.size();
|
|
|
+ ++v; *v++ = 0;
|
|
|
+ for (const PointD& pt : path)
|
|
|
+ {
|
|
|
+ *v++ = pt.x;
|
|
|
+ *v++ = pt.y;
|
|
|
+#ifdef USINGZ
|
|
|
+ * v++ = Reinterpret<double>(pt.z);
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
|
|
|
CPathsD CreateCPathsDFromPaths64(const Paths64& paths, double scale)
|
|
|
{
|
|
@@ -268,13 +369,16 @@ CPathsD CreateCPathsDFromPaths64(const Paths64& paths, double scale)
|
|
|
{
|
|
|
*v++ = pt.x * scale;
|
|
|
*v++ = pt.y * scale;
|
|
|
+#ifdef USINGZ
|
|
|
+ *v++ = Reinterpret<double>(pt.z);
|
|
|
+#endif
|
|
|
}
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
|
-static Path<T> ConvertCPath(T* path)
|
|
|
+static Path<T> ConvertCPathToPathT(T* path)
|
|
|
{
|
|
|
Path<T> result;
|
|
|
if (!path) return result;
|
|
@@ -284,14 +388,19 @@ static Path<T> ConvertCPath(T* path)
|
|
|
result.reserve(cnt);
|
|
|
for (size_t j = 0; j < cnt; ++j)
|
|
|
{
|
|
|
- T x = *v++, y = *v++;
|
|
|
- result.push_back(Point<T>(x, y));
|
|
|
+ T x = *v++, y = *v++;
|
|
|
+#ifdef USINGZ
|
|
|
+ z_type z = Reinterpret<z_type>(*v++);
|
|
|
+ result.emplace_back(x, y, z);
|
|
|
+#else
|
|
|
+ result.emplace_back(x, y);
|
|
|
+#endif
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
|
-static Paths<T> ConvertCPaths(T* paths)
|
|
|
+static Paths<T> ConvertCPathsToPathsT(T* paths)
|
|
|
{
|
|
|
Paths<T> result;
|
|
|
if (!paths) return result;
|
|
@@ -301,19 +410,45 @@ static Paths<T> ConvertCPaths(T* paths)
|
|
|
for (size_t i = 0; i < cnt; ++i)
|
|
|
{
|
|
|
size_t cnt2 = static_cast<size_t>(*v);
|
|
|
- v += 2;
|
|
|
+ v += 2;
|
|
|
Path<T> path;
|
|
|
path.reserve(cnt2);
|
|
|
for (size_t j = 0; j < cnt2; ++j)
|
|
|
{
|
|
|
T x = *v++, y = *v++;
|
|
|
- path.push_back(Point<T>(x, y));
|
|
|
+#ifdef USINGZ
|
|
|
+ z_type z = Reinterpret<z_type>(*v++);
|
|
|
+ path.emplace_back(x, y, z);
|
|
|
+#else
|
|
|
+ path.emplace_back(x, y);
|
|
|
+#endif
|
|
|
}
|
|
|
- result.push_back(path);
|
|
|
+ result.emplace_back(std::move(path));
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+static Path64 ConvertCPathDToPath64WithScale(const CPathD path, double scale)
|
|
|
+{
|
|
|
+ Path64 result;
|
|
|
+ if (!path) return result;
|
|
|
+ double* v = path;
|
|
|
+ size_t cnt = static_cast<size_t>(*v);
|
|
|
+ v += 2; // skip 0 value
|
|
|
+ result.reserve(cnt);
|
|
|
+ for (size_t j = 0; j < cnt; ++j)
|
|
|
+ {
|
|
|
+ double x = *v++ * scale;
|
|
|
+ double y = *v++ * scale;
|
|
|
+#ifdef USINGZ
|
|
|
+ z_type z = Reinterpret<z_type>(*v++);
|
|
|
+ result.emplace_back(x, y, z);
|
|
|
+#else
|
|
|
+ result.emplace_back(x, y);
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
|
|
|
static Paths64 ConvertCPathsDToPaths64(const CPathsD paths, double scale)
|
|
|
{
|
|
@@ -333,42 +468,78 @@ static Paths64 ConvertCPathsDToPaths64(const CPathsD paths, double scale)
|
|
|
{
|
|
|
double x = *v++ * scale;
|
|
|
double y = *v++ * scale;
|
|
|
- path.push_back(Point64(x, y));
|
|
|
+#ifdef USINGZ
|
|
|
+ z_type z = Reinterpret<z_type>(*v++);
|
|
|
+ path.emplace_back(x, y, z);
|
|
|
+#else
|
|
|
+ path.emplace_back(x, y);
|
|
|
+#endif
|
|
|
}
|
|
|
- result.push_back(path);
|
|
|
+ result.emplace_back(std::move(path));
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-template <typename T>
|
|
|
-static void CreateCPolyPath(const PolyPath64* pp, T*& v, T scale)
|
|
|
+static void CreateCPolyPath64(const PolyPath64* pp, int64_t*& v)
|
|
|
{
|
|
|
- *v++ = static_cast<T>(pp->Polygon().size());
|
|
|
- *v++ = static_cast<T>(pp->Count());
|
|
|
+ *v++ = static_cast<int64_t>(pp->Polygon().size());
|
|
|
+ *v++ = static_cast<int64_t>(pp->Count());
|
|
|
for (const Point64& pt : pp->Polygon())
|
|
|
{
|
|
|
- *v++ = static_cast<T>(pt.x * scale);
|
|
|
- *v++ = static_cast<T>(pt.y * scale);
|
|
|
+ *v++ = pt.x;
|
|
|
+ *v++ = pt.y;
|
|
|
+#ifdef USINGZ
|
|
|
+ * v++ = Reinterpret<int64_t>(pt.z); // raw memory copy
|
|
|
+#endif
|
|
|
}
|
|
|
for (size_t i = 0; i < pp->Count(); ++i)
|
|
|
- CreateCPolyPath(pp->Child(i), v, scale);
|
|
|
+ CreateCPolyPath64(pp->Child(i), v);
|
|
|
}
|
|
|
|
|
|
-template <typename T>
|
|
|
-static T* CreateCPolyTree(const PolyTree64& tree, T scale)
|
|
|
+static void CreateCPolyPathD(const PolyPathD* pp, double*& v)
|
|
|
+{
|
|
|
+ *v++ = static_cast<double>(pp->Polygon().size());
|
|
|
+ *v++ = static_cast<double>(pp->Count());
|
|
|
+ for (const PointD& pt : pp->Polygon())
|
|
|
+ {
|
|
|
+ *v++ = pt.x;
|
|
|
+ *v++ = pt.y;
|
|
|
+#ifdef USINGZ
|
|
|
+ * v++ = Reinterpret<double>(pt.z); // raw memory copy
|
|
|
+#endif
|
|
|
+ }
|
|
|
+ for (size_t i = 0; i < pp->Count(); ++i)
|
|
|
+ CreateCPolyPathD(pp->Child(i), v);
|
|
|
+}
|
|
|
+
|
|
|
+static int64_t* CreateCPolyTree64(const PolyTree64& tree)
|
|
|
{
|
|
|
- if (scale == 0) scale = 1;
|
|
|
size_t cnt, array_len;
|
|
|
- GetPolytreeCountAndCStorageSize(tree, cnt, array_len);
|
|
|
+ GetPolytreeCountAndCStorageSize64(tree, cnt, array_len);
|
|
|
if (!cnt) return nullptr;
|
|
|
// allocate storage
|
|
|
- T* result = new T[array_len];
|
|
|
- T* v = result;
|
|
|
+ int64_t* result = new int64_t[array_len];
|
|
|
+ int64_t* v = result;
|
|
|
+ *v++ = static_cast<int64_t>(array_len);
|
|
|
+ *v++ = static_cast<int64_t>(tree.Count());
|
|
|
+ for (size_t i = 0; i < tree.Count(); ++i)
|
|
|
+ CreateCPolyPath64(tree.Child(i), v);
|
|
|
+ return result;
|
|
|
+}
|
|
|
|
|
|
- *v++ = static_cast<T>(array_len);
|
|
|
- *v++ = static_cast<T>(tree.Count());
|
|
|
+static double* CreateCPolyTreeD(const PolyTreeD& tree)
|
|
|
+{
|
|
|
+ double scale = std::log10(tree.Scale());
|
|
|
+ size_t cnt, array_len;
|
|
|
+ GetPolytreeCountAndCStorageSizeD(tree, cnt, array_len);
|
|
|
+ if (!cnt) return nullptr;
|
|
|
+ // allocate storage
|
|
|
+ double* result = new double[array_len];
|
|
|
+ double* v = result;
|
|
|
+ *v++ = static_cast<double>(array_len);
|
|
|
+ *v++ = static_cast<double>(tree.Count());
|
|
|
for (size_t i = 0; i < tree.Count(); ++i)
|
|
|
- CreateCPolyPath(tree.Child(i), v, scale);
|
|
|
+ CreateCPolyPathD(tree.Child(i), v);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
@@ -391,20 +562,24 @@ EXTERN_DLL_EXPORT int BooleanOp64(uint8_t cliptype,
|
|
|
if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3;
|
|
|
|
|
|
Paths64 sub, sub_open, clp, sol, sol_open;
|
|
|
- sub = ConvertCPaths(subjects);
|
|
|
- sub_open = ConvertCPaths(subjects_open);
|
|
|
- clp = ConvertCPaths(clips);
|
|
|
+ sub = ConvertCPathsToPathsT(subjects);
|
|
|
+ sub_open = ConvertCPathsToPathsT(subjects_open);
|
|
|
+ clp = ConvertCPathsToPathsT(clips);
|
|
|
|
|
|
Clipper64 clipper;
|
|
|
clipper.PreserveCollinear(preserve_collinear);
|
|
|
clipper.ReverseSolution(reverse_solution);
|
|
|
+#ifdef USINGZ
|
|
|
+ if (dllCallback64)
|
|
|
+ clipper.SetZCallback(dllCallback64);
|
|
|
+#endif
|
|
|
if (sub.size() > 0) clipper.AddSubject(sub);
|
|
|
if (sub_open.size() > 0) clipper.AddOpenSubject(sub_open);
|
|
|
if (clp.size() > 0) clipper.AddClip(clp);
|
|
|
if (!clipper.Execute(ClipType(cliptype), FillRule(fillrule), sol, sol_open))
|
|
|
return -1; // clipping bug - should never happen :)
|
|
|
- solution = CreateCPaths(sol);
|
|
|
- solution_open = CreateCPaths(sol_open);
|
|
|
+ solution = CreateCPathsFromPathsT(sol);
|
|
|
+ solution_open = CreateCPathsFromPathsT(sol_open);
|
|
|
return 0; //success !!
|
|
|
}
|
|
|
|
|
@@ -417,22 +592,26 @@ EXTERN_DLL_EXPORT int BooleanOp_PolyTree64(uint8_t cliptype,
|
|
|
if (cliptype > static_cast<uint8_t>(ClipType::Xor)) return -4;
|
|
|
if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3;
|
|
|
Paths64 sub, sub_open, clp, sol_open;
|
|
|
- sub = ConvertCPaths(subjects);
|
|
|
- sub_open = ConvertCPaths(subjects_open);
|
|
|
- clp = ConvertCPaths(clips);
|
|
|
+ sub = ConvertCPathsToPathsT(subjects);
|
|
|
+ sub_open = ConvertCPathsToPathsT(subjects_open);
|
|
|
+ clp = ConvertCPathsToPathsT(clips);
|
|
|
|
|
|
PolyTree64 tree;
|
|
|
Clipper64 clipper;
|
|
|
clipper.PreserveCollinear(preserve_collinear);
|
|
|
clipper.ReverseSolution(reverse_solution);
|
|
|
+#ifdef USINGZ
|
|
|
+ if (dllCallback64)
|
|
|
+ clipper.SetZCallback(dllCallback64);
|
|
|
+#endif
|
|
|
if (sub.size() > 0) clipper.AddSubject(sub);
|
|
|
if (sub_open.size() > 0) clipper.AddOpenSubject(sub_open);
|
|
|
if (clp.size() > 0) clipper.AddClip(clp);
|
|
|
if (!clipper.Execute(ClipType(cliptype), FillRule(fillrule), tree, sol_open))
|
|
|
return -1; // clipping bug - should never happen :)
|
|
|
|
|
|
- sol_tree = CreateCPolyTree(tree, (int64_t)1);
|
|
|
- solution_open = CreateCPaths(sol_open);
|
|
|
+ sol_tree = CreateCPolyTree64(tree);
|
|
|
+ solution_open = CreateCPathsFromPathsT(sol_open);
|
|
|
return 0; //success !!
|
|
|
}
|
|
|
|
|
@@ -445,23 +624,27 @@ EXTERN_DLL_EXPORT int BooleanOpD(uint8_t cliptype,
|
|
|
if (precision < -8 || precision > 8) return -5;
|
|
|
if (cliptype > static_cast<uint8_t>(ClipType::Xor)) return -4;
|
|
|
if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3;
|
|
|
- const double scale = std::pow(10, precision);
|
|
|
+ //const double scale = std::pow(10, precision);
|
|
|
|
|
|
- Paths64 sub, sub_open, clp, sol, sol_open;
|
|
|
- sub = ConvertCPathsDToPaths64(subjects, scale);
|
|
|
- sub_open = ConvertCPathsDToPaths64(subjects_open, scale);
|
|
|
- clp = ConvertCPathsDToPaths64(clips, scale);
|
|
|
+ PathsD sub, sub_open, clp, sol, sol_open;
|
|
|
+ sub = ConvertCPathsToPathsT(subjects);
|
|
|
+ sub_open = ConvertCPathsToPathsT(subjects_open);
|
|
|
+ clp = ConvertCPathsToPathsT(clips);
|
|
|
|
|
|
- Clipper64 clipper;
|
|
|
+ ClipperD clipper(precision);
|
|
|
clipper.PreserveCollinear(preserve_collinear);
|
|
|
clipper.ReverseSolution(reverse_solution);
|
|
|
+#ifdef USINGZ
|
|
|
+ if (dllCallbackD)
|
|
|
+ clipper.SetZCallback(dllCallbackD);
|
|
|
+#endif
|
|
|
if (sub.size() > 0) clipper.AddSubject(sub);
|
|
|
if (sub_open.size() > 0) clipper.AddOpenSubject(sub_open);
|
|
|
if (clp.size() > 0) clipper.AddClip(clp);
|
|
|
if (!clipper.Execute(ClipType(cliptype),
|
|
|
FillRule(fillrule), sol, sol_open)) return -1;
|
|
|
- solution = CreateCPathsDFromPaths64(sol, 1 / scale);
|
|
|
- solution_open = CreateCPathsDFromPaths64(sol_open, 1 / scale);
|
|
|
+ solution = CreateCPathsDFromPathsD(sol);
|
|
|
+ solution_open = CreateCPathsDFromPathsD(sol_open);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -474,27 +657,30 @@ EXTERN_DLL_EXPORT int BooleanOp_PolyTreeD(uint8_t cliptype,
|
|
|
if (precision < -8 || precision > 8) return -5;
|
|
|
if (cliptype > static_cast<uint8_t>(ClipType::Xor)) return -4;
|
|
|
if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3;
|
|
|
-
|
|
|
- double scale = std::pow(10, precision);
|
|
|
+ //double scale = std::pow(10, precision);
|
|
|
|
|
|
int err = 0;
|
|
|
- Paths64 sub, sub_open, clp, sol_open;
|
|
|
- sub = ConvertCPathsDToPaths64(subjects, scale);
|
|
|
- sub_open = ConvertCPathsDToPaths64(subjects_open, scale);
|
|
|
- clp = ConvertCPathsDToPaths64(clips, scale);
|
|
|
+ PathsD sub, sub_open, clp, sol_open;
|
|
|
+ sub = ConvertCPathsToPathsT(subjects);
|
|
|
+ sub_open = ConvertCPathsToPathsT(subjects_open);
|
|
|
+ clp = ConvertCPathsToPathsT(clips);
|
|
|
|
|
|
- PolyTree64 tree;
|
|
|
- Clipper64 clipper;
|
|
|
+ PolyTreeD tree;
|
|
|
+ ClipperD clipper(precision);
|
|
|
clipper.PreserveCollinear(preserve_collinear);
|
|
|
clipper.ReverseSolution(reverse_solution);
|
|
|
+#ifdef USINGZ
|
|
|
+ if (dllCallbackD)
|
|
|
+ clipper.SetZCallback(dllCallbackD);
|
|
|
+#endif
|
|
|
if (sub.size() > 0) clipper.AddSubject(sub);
|
|
|
if (sub_open.size() > 0) clipper.AddOpenSubject(sub_open);
|
|
|
if (clp.size() > 0) clipper.AddClip(clp);
|
|
|
if (!clipper.Execute(ClipType(cliptype), FillRule(fillrule), tree, sol_open))
|
|
|
return -1; // clipping bug - should never happen :)
|
|
|
|
|
|
- solution = CreateCPolyTree(tree, 1/scale);
|
|
|
- solution_open = CreateCPathsDFromPaths64(sol_open, 1 / scale);
|
|
|
+ solution = CreateCPolyTreeD(tree);
|
|
|
+ solution_open = CreateCPathsDFromPathsD(sol_open);
|
|
|
return 0; //success !!
|
|
|
}
|
|
|
|
|
@@ -503,13 +689,13 @@ EXTERN_DLL_EXPORT CPaths64 InflatePaths64(const CPaths64 paths,
|
|
|
double arc_tolerance, bool reverse_solution)
|
|
|
{
|
|
|
Paths64 pp;
|
|
|
- pp = ConvertCPaths(paths);
|
|
|
+ pp = ConvertCPathsToPathsT(paths);
|
|
|
ClipperOffset clip_offset( miter_limit,
|
|
|
arc_tolerance, reverse_solution);
|
|
|
clip_offset.AddPaths(pp, JoinType(jointype), EndType(endtype));
|
|
|
Paths64 result;
|
|
|
clip_offset.Execute(delta, result);
|
|
|
- return CreateCPaths(result);
|
|
|
+ return CreateCPathsFromPathsT(result);
|
|
|
}
|
|
|
|
|
|
EXTERN_DLL_EXPORT CPathsD InflatePathsD(const CPathsD paths,
|
|
@@ -525,18 +711,49 @@ EXTERN_DLL_EXPORT CPathsD InflatePathsD(const CPathsD paths,
|
|
|
clip_offset.AddPaths(pp, JoinType(jointype), EndType(endtype));
|
|
|
Paths64 result;
|
|
|
clip_offset.Execute(delta * scale, result);
|
|
|
-
|
|
|
return CreateCPathsDFromPaths64(result, 1 / scale);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+EXTERN_DLL_EXPORT CPaths64 InflatePath64(const CPath64 path,
|
|
|
+ double delta, uint8_t jointype, uint8_t endtype, double miter_limit,
|
|
|
+ double arc_tolerance, bool reverse_solution)
|
|
|
+{
|
|
|
+ Path64 pp;
|
|
|
+ pp = ConvertCPathToPathT(path);
|
|
|
+ ClipperOffset clip_offset(miter_limit,
|
|
|
+ arc_tolerance, reverse_solution);
|
|
|
+ clip_offset.AddPath(pp, JoinType(jointype), EndType(endtype));
|
|
|
+ Paths64 result;
|
|
|
+ clip_offset.Execute(delta, result);
|
|
|
+ return CreateCPathsFromPathsT(result);
|
|
|
+}
|
|
|
+
|
|
|
+EXTERN_DLL_EXPORT CPathsD InflatePathD(const CPathD path,
|
|
|
+ double delta, uint8_t jointype, uint8_t endtype,
|
|
|
+ int precision, double miter_limit,
|
|
|
+ double arc_tolerance, bool reverse_solution)
|
|
|
+{
|
|
|
+ if (precision < -8 || precision > 8 || !path) return nullptr;
|
|
|
+
|
|
|
+ const double scale = std::pow(10, precision);
|
|
|
+ ClipperOffset clip_offset(miter_limit, arc_tolerance, reverse_solution);
|
|
|
+ Path64 pp = ConvertCPathDToPath64WithScale(path, scale);
|
|
|
+ clip_offset.AddPath(pp, JoinType(jointype), EndType(endtype));
|
|
|
+ Paths64 result;
|
|
|
+ clip_offset.Execute(delta * scale, result);
|
|
|
+
|
|
|
+ return CreateCPathsDFromPaths64(result, 1 / scale);
|
|
|
+}
|
|
|
+
|
|
|
EXTERN_DLL_EXPORT CPaths64 RectClip64(const CRect64& rect, const CPaths64 paths)
|
|
|
{
|
|
|
if (CRectIsEmpty(rect) || !paths) return nullptr;
|
|
|
Rect64 r64 = CRectToRect(rect);
|
|
|
class RectClip64 rc(r64);
|
|
|
- Paths64 pp = ConvertCPaths(paths);
|
|
|
+ Paths64 pp = ConvertCPathsToPathsT(paths);
|
|
|
Paths64 result = rc.Execute(pp);
|
|
|
- return CreateCPaths(result);
|
|
|
+ return CreateCPathsFromPathsT(result);
|
|
|
}
|
|
|
|
|
|
EXTERN_DLL_EXPORT CPathsD RectClipD(const CRectD& rect, const CPathsD paths, int precision)
|
|
@@ -560,9 +777,9 @@ EXTERN_DLL_EXPORT CPaths64 RectClipLines64(const CRect64& rect,
|
|
|
if (CRectIsEmpty(rect) || !paths) return nullptr;
|
|
|
Rect64 r = CRectToRect(rect);
|
|
|
class RectClipLines64 rcl (r);
|
|
|
- Paths64 pp = ConvertCPaths(paths);
|
|
|
+ Paths64 pp = ConvertCPathsToPathsT(paths);
|
|
|
Paths64 result = rcl.Execute(pp);
|
|
|
- return CreateCPaths(result);
|
|
|
+ return CreateCPathsFromPathsT(result);
|
|
|
}
|
|
|
|
|
|
EXTERN_DLL_EXPORT CPathsD RectClipLinesD(const CRectD& rect,
|
|
@@ -581,20 +798,35 @@ EXTERN_DLL_EXPORT CPathsD RectClipLinesD(const CRectD& rect,
|
|
|
|
|
|
EXTERN_DLL_EXPORT CPaths64 MinkowskiSum64(const CPath64& cpattern, const CPath64& cpath, bool is_closed)
|
|
|
{
|
|
|
- Path64 path = ConvertCPath(cpath);
|
|
|
- Path64 pattern = ConvertCPath(cpattern);
|
|
|
+ Path64 path = ConvertCPathToPathT(cpath);
|
|
|
+ Path64 pattern = ConvertCPathToPathT(cpattern);
|
|
|
Paths64 solution = MinkowskiSum(pattern, path, is_closed);
|
|
|
- return CreateCPaths(solution);
|
|
|
+ return CreateCPathsFromPathsT(solution);
|
|
|
}
|
|
|
|
|
|
EXTERN_DLL_EXPORT CPaths64 MinkowskiDiff64(const CPath64& cpattern, const CPath64& cpath, bool is_closed)
|
|
|
{
|
|
|
- Path64 path = ConvertCPath(cpath);
|
|
|
- Path64 pattern = ConvertCPath(cpattern);
|
|
|
+ Path64 path = ConvertCPathToPathT(cpath);
|
|
|
+ Path64 pattern = ConvertCPathToPathT(cpattern);
|
|
|
Paths64 solution = MinkowskiDiff(pattern, path, is_closed);
|
|
|
- return CreateCPaths(solution);
|
|
|
+ return CreateCPathsFromPathsT(solution);
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef USINGZ
|
|
|
+typedef void (*DLLZCallback64)(const Point64& e1bot, const Point64& e1top, const Point64& e2bot, const Point64& e2top, Point64& pt);
|
|
|
+typedef void (*DLLZCallbackD)(const PointD& e1bot, const PointD& e1top, const PointD& e2bot, const PointD& e2top, PointD& pt);
|
|
|
+
|
|
|
+EXTERN_DLL_EXPORT void SetZCallback64(DLLZCallback64 callback)
|
|
|
+{
|
|
|
+ dllCallback64 = callback;
|
|
|
}
|
|
|
|
|
|
-} // end Clipper2Lib namespace
|
|
|
+EXTERN_DLL_EXPORT void SetZCallbackD(DLLZCallbackD callback)
|
|
|
+{
|
|
|
+ dllCallbackD = callback;
|
|
|
+}
|
|
|
|
|
|
+#endif
|
|
|
+
|
|
|
+}
|
|
|
#endif // CLIPPER2_EXPORT_H
|