Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/misc/polypartition.h
9898 views
1
/*************************************************************************/
2
/* Copyright (c) 2011-2021 Ivan Fratric and contributors. */
3
/* */
4
/* Permission is hereby granted, free of charge, to any person obtaining */
5
/* a copy of this software and associated documentation files (the */
6
/* "Software"), to deal in the Software without restriction, including */
7
/* without limitation the rights to use, copy, modify, merge, publish, */
8
/* distribute, sublicense, and/or sell copies of the Software, and to */
9
/* permit persons to whom the Software is furnished to do so, subject to */
10
/* the following conditions: */
11
/* */
12
/* The above copyright notice and this permission notice shall be */
13
/* included in all copies or substantial portions of the Software. */
14
/* */
15
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
16
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
17
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
18
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
19
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
20
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
21
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
/*************************************************************************/
23
24
#ifndef POLYPARTITION_H
25
#define POLYPARTITION_H
26
27
#include "core/math/vector2.h"
28
#include "core/templates/list.h"
29
#include "core/templates/rb_set.h"
30
31
typedef double tppl_float;
32
33
enum TPPLOrientation {
34
TPPL_ORIENTATION_CW = -1,
35
TPPL_ORIENTATION_NONE = 0,
36
TPPL_ORIENTATION_CCW = 1,
37
};
38
39
enum TPPLVertexType {
40
TPPL_VERTEXTYPE_REGULAR = 0,
41
TPPL_VERTEXTYPE_START = 1,
42
TPPL_VERTEXTYPE_END = 2,
43
TPPL_VERTEXTYPE_SPLIT = 3,
44
TPPL_VERTEXTYPE_MERGE = 4,
45
};
46
47
// 2D point structure.
48
typedef Vector2 TPPLPoint;
49
50
// Polygon implemented as an array of points with a "hole" flag.
51
class TPPLPoly {
52
protected:
53
TPPLPoint *points;
54
long numpoints;
55
bool hole;
56
57
public:
58
// Constructors and destructors.
59
TPPLPoly();
60
~TPPLPoly();
61
62
TPPLPoly(const TPPLPoly &src);
63
TPPLPoly &operator=(const TPPLPoly &src);
64
65
// Getters and setters.
66
long GetNumPoints() const {
67
return numpoints;
68
}
69
70
bool IsHole() const {
71
return hole;
72
}
73
74
void SetHole(bool p_hole) {
75
this->hole = p_hole;
76
}
77
78
TPPLPoint &GetPoint(long i) {
79
return points[i];
80
}
81
82
const TPPLPoint &GetPoint(long i) const {
83
return points[i];
84
}
85
86
TPPLPoint *GetPoints() {
87
return points;
88
}
89
90
TPPLPoint &operator[](int i) {
91
return points[i];
92
}
93
94
const TPPLPoint &operator[](int i) const {
95
return points[i];
96
}
97
98
// Clears the polygon points.
99
void Clear();
100
101
// Inits the polygon with numpoints vertices.
102
void Init(long numpoints);
103
104
// Creates a triangle with points p1, p2, and p3.
105
void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
106
107
// Inverts the orfer of vertices.
108
void Invert();
109
110
// Returns the orientation of the polygon.
111
// Possible values:
112
// TPPL_ORIENTATION_CCW: Polygon vertices are in counter-clockwise order.
113
// TPPL_ORIENTATION_CW: Polygon vertices are in clockwise order.
114
// TPPL_ORIENTATION_NONE: The polygon has no (measurable) area.
115
TPPLOrientation GetOrientation() const;
116
117
// Sets the polygon orientation.
118
// Possible values:
119
// TPPL_ORIENTATION_CCW: Sets vertices in counter-clockwise order.
120
// TPPL_ORIENTATION_CW: Sets vertices in clockwise order.
121
// TPPL_ORIENTATION_NONE: Reverses the orientation of the vertices if there
122
// is one, otherwise does nothing (if orientation is already NONE).
123
void SetOrientation(TPPLOrientation orientation);
124
125
// Checks whether a polygon is valid or not.
126
inline bool Valid() const { return this->numpoints >= 3; }
127
};
128
129
#ifdef TPPL_ALLOCATOR
130
typedef List<TPPLPoly, TPPL_ALLOCATOR(TPPLPoly)> TPPLPolyList;
131
#else
132
typedef List<TPPLPoly> TPPLPolyList;
133
#endif
134
135
class TPPLPartition {
136
protected:
137
struct PartitionVertex {
138
bool isActive;
139
bool isConvex;
140
bool isEar;
141
142
TPPLPoint p;
143
tppl_float angle;
144
PartitionVertex *previous;
145
PartitionVertex *next;
146
147
PartitionVertex();
148
};
149
150
struct MonotoneVertex {
151
TPPLPoint p;
152
long previous;
153
long next;
154
};
155
156
class VertexSorter {
157
MonotoneVertex *vertices;
158
159
public:
160
VertexSorter(MonotoneVertex *v) :
161
vertices(v) {}
162
bool operator()(long index1, long index2);
163
};
164
165
struct Diagonal {
166
long index1;
167
long index2;
168
};
169
170
#ifdef TPPL_ALLOCATOR
171
typedef List<Diagonal, TPPL_ALLOCATOR(Diagonal)> DiagonalList;
172
#else
173
typedef List<Diagonal> DiagonalList;
174
#endif
175
176
// Dynamic programming state for minimum-weight triangulation.
177
struct DPState {
178
bool visible;
179
tppl_float weight;
180
long bestvertex;
181
};
182
183
// Dynamic programming state for convex partitioning.
184
struct DPState2 {
185
bool visible;
186
long weight;
187
DiagonalList pairs;
188
};
189
190
// Edge that intersects the scanline.
191
struct ScanLineEdge {
192
mutable long index;
193
TPPLPoint p1;
194
TPPLPoint p2;
195
196
// Determines if the edge is to the left of another edge.
197
bool operator<(const ScanLineEdge &other) const;
198
199
bool IsConvex(const TPPLPoint &p1, const TPPLPoint &p2, const TPPLPoint &p3) const;
200
};
201
202
// Standard helper functions.
203
bool IsConvex(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
204
bool IsReflex(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
205
bool IsInside(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p);
206
207
bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p);
208
bool InCone(PartitionVertex *v, TPPLPoint &p);
209
210
int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22);
211
212
TPPLPoint Normalize(const TPPLPoint &p);
213
tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2);
214
215
// Helper functions for Triangulate_EC.
216
void UpdateVertexReflexity(PartitionVertex *v);
217
void UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices);
218
219
// Helper functions for ConvexPartition_OPT.
220
void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates);
221
void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
222
void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
223
224
// Helper functions for MonotonePartition.
225
bool Below(TPPLPoint &p1, TPPLPoint &p2);
226
void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
227
TPPLVertexType *vertextypes, RBSet<ScanLineEdge>::Element **edgeTreeIterators,
228
RBSet<ScanLineEdge> *edgeTree, long *helpers);
229
230
// Triangulates a monotone polygon, used in Triangulate_MONO.
231
int TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles);
232
233
public:
234
// Simple heuristic procedure for removing holes from a list of polygons.
235
// It works by creating a diagonal from the right-most hole vertex
236
// to some other visible vertex.
237
// Time complexity: O(h*(n^2)), h is the # of holes, n is the # of vertices.
238
// Space complexity: O(n)
239
// params:
240
// inpolys:
241
// A list of polygons that can contain holes.
242
// Vertices of all non-hole polys have to be in counter-clockwise order.
243
// Vertices of all hole polys have to be in clockwise order.
244
// outpolys:
245
// A list of polygons without holes.
246
// Returns 1 on success, 0 on failure.
247
int RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys);
248
249
// Triangulates a polygon by ear clipping.
250
// Time complexity: O(n^2), n is the number of vertices.
251
// Space complexity: O(n)
252
// params:
253
// poly:
254
// An input polygon to be triangulated.
255
// Vertices have to be in counter-clockwise order.
256
// triangles:
257
// A list of triangles (result).
258
// Returns 1 on success, 0 on failure.
259
int Triangulate_EC(TPPLPoly *poly, TPPLPolyList *triangles);
260
261
// Triangulates a list of polygons that may contain holes by ear clipping
262
// algorithm. It first calls RemoveHoles to get rid of the holes, and then
263
// calls Triangulate_EC for each resulting polygon.
264
// Time complexity: O(h*(n^2)), h is the # of holes, n is the # of vertices.
265
// Space complexity: O(n)
266
// params:
267
// inpolys:
268
// A list of polygons to be triangulated (can contain holes).
269
// Vertices of all non-hole polys have to be in counter-clockwise order.
270
// Vertices of all hole polys have to be in clockwise order.
271
// triangles:
272
// A list of triangles (result).
273
// Returns 1 on success, 0 on failure.
274
int Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles);
275
276
// Creates an optimal polygon triangulation in terms of minimal edge length.
277
// Time complexity: O(n^3), n is the number of vertices
278
// Space complexity: O(n^2)
279
// params:
280
// poly:
281
// An input polygon to be triangulated.
282
// Vertices have to be in counter-clockwise order.
283
// triangles:
284
// A list of triangles (result).
285
// Returns 1 on success, 0 on failure.
286
int Triangulate_OPT(TPPLPoly *poly, TPPLPolyList *triangles);
287
288
// Triangulates a polygon by first partitioning it into monotone polygons.
289
// Time complexity: O(n*log(n)), n is the number of vertices.
290
// Space complexity: O(n)
291
// params:
292
// poly:
293
// An input polygon to be triangulated.
294
// Vertices have to be in counter-clockwise order.
295
// triangles:
296
// A list of triangles (result).
297
// Returns 1 on success, 0 on failure.
298
int Triangulate_MONO(TPPLPoly *poly, TPPLPolyList *triangles);
299
300
// Triangulates a list of polygons by first
301
// partitioning them into monotone polygons.
302
// Time complexity: O(n*log(n)), n is the number of vertices.
303
// Space complexity: O(n)
304
// params:
305
// inpolys:
306
// A list of polygons to be triangulated (can contain holes).
307
// Vertices of all non-hole polys have to be in counter-clockwise order.
308
// Vertices of all hole polys have to be in clockwise order.
309
// triangles:
310
// A list of triangles (result).
311
// Returns 1 on success, 0 on failure.
312
int Triangulate_MONO(TPPLPolyList *inpolys, TPPLPolyList *triangles);
313
314
// Creates a monotone partition of a list of polygons that
315
// can contain holes. Triangulates a set of polygons by
316
// first partitioning them into monotone polygons.
317
// Time complexity: O(n*log(n)), n is the number of vertices.
318
// Space complexity: O(n)
319
// params:
320
// inpolys:
321
// A list of polygons to be triangulated (can contain holes).
322
// Vertices of all non-hole polys have to be in counter-clockwise order.
323
// Vertices of all hole polys have to be in clockwise order.
324
// monotonePolys:
325
// A list of monotone polygons (result).
326
// Returns 1 on success, 0 on failure.
327
int MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monotonePolys);
328
329
// Partitions a polygon into convex polygons by using the
330
// Hertel-Mehlhorn algorithm. The algorithm gives at most four times
331
// the number of parts as the optimal algorithm, however, in practice
332
// it works much better than that and often gives optimal partition.
333
// It uses triangulation obtained by ear clipping as intermediate result.
334
// Time complexity O(n^2), n is the number of vertices.
335
// Space complexity: O(n)
336
// params:
337
// poly:
338
// An input polygon to be partitioned.
339
// Vertices have to be in counter-clockwise order.
340
// parts:
341
// Resulting list of convex polygons.
342
// Returns 1 on success, 0 on failure.
343
int ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts);
344
345
// Partitions a list of polygons into convex parts by using the
346
// Hertel-Mehlhorn algorithm. The algorithm gives at most four times
347
// the number of parts as the optimal algorithm, however, in practice
348
// it works much better than that and often gives optimal partition.
349
// It uses triangulation obtained by ear clipping as intermediate result.
350
// Time complexity O(n^2), n is the number of vertices.
351
// Space complexity: O(n)
352
// params:
353
// inpolys:
354
// An input list of polygons to be partitioned. Vertices of
355
// all non-hole polys have to be in counter-clockwise order.
356
// Vertices of all hole polys have to be in clockwise order.
357
// parts:
358
// Resulting list of convex polygons.
359
// Returns 1 on success, 0 on failure.
360
int ConvexPartition_HM(TPPLPolyList *inpolys, TPPLPolyList *parts);
361
362
// Optimal convex partitioning (in terms of number of resulting
363
// convex polygons) using the Keil-Snoeyink algorithm.
364
// For reference, see M. Keil, J. Snoeyink, "On the time bound for
365
// convex decomposition of simple polygons", 1998.
366
// Time complexity O(n^3), n is the number of vertices.
367
// Space complexity: O(n^3)
368
// params:
369
// poly:
370
// An input polygon to be partitioned.
371
// Vertices have to be in counter-clockwise order.
372
// parts:
373
// Resulting list of convex polygons.
374
// Returns 1 on success, 0 on failure.
375
int ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts);
376
};
377
378
#endif
379
380