triangulator.h
1 //Copyright (C) 2011 by Ivan Fratric
2 //
3 //Permission is hereby granted, free of charge, to any person obtaining a copy
4 //of this software and associated documentation files (the "Software"), to deal
5 //in the Software without restriction, including without limitation the rights
6 //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 //copies of the Software, and to permit persons to whom the Software is
8 //furnished to do so, subject to the following conditions:
9 //
10 //The above copyright notice and this permission notice shall be included in
11 //all copies or substantial portions of the Software.
12 //
13 //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 //THE SOFTWARE.
20 
21 #ifndef TRIANGULATOR_H
22 #define TRIANGULATOR_H
23 
24 #include "math_2d.h"
25 #include "list.h"
26 #include "set.h"
27 //2D point structure
28 
29 
30 #define TRIANGULATOR_CCW 1
31 #define TRIANGULATOR_CW -1
32 //Polygon implemented as an array of points with a 'hole' flag
34 protected:
35 
36 
37 
38  Vector2 *points;
39  long numpoints;
40  bool hole;
41 
42 public:
43 
44  //constructors/destructors
47 
49  TriangulatorPoly& operator=(const TriangulatorPoly &src);
50 
51  //getters and setters
52  long GetNumPoints() {
53  return numpoints;
54  }
55 
56  bool IsHole() {
57  return hole;
58  }
59 
60  void SetHole(bool hole) {
61  this->hole = hole;
62  }
63 
64  Vector2 &GetPoint(long i) {
65  return points[i];
66  }
67 
68  Vector2 *GetPoints() {
69  return points;
70  }
71 
72  Vector2& operator[] (int i) {
73  return points[i];
74  }
75 
76  //clears the polygon points
77  void Clear();
78 
79  //inits the polygon with numpoints vertices
80  void Init(long numpoints);
81 
82  //creates a triangle with points p1,p2,p3
83  void Triangle(Vector2 &p1, Vector2 &p2, Vector2 &p3);
84 
85  //inverts the orfer of vertices
86  void Invert();
87 
88  //returns the orientation of the polygon
89  //possible values:
90  // Triangulator_CCW : polygon vertices are in counter-clockwise order
91  // Triangulator_CW : polygon vertices are in clockwise order
92  // 0 : the polygon has no (measurable) area
93  int GetOrientation();
94 
95  //sets the polygon orientation
96  //orientation can be
97  // Triangulator_CCW : sets vertices in counter-clockwise order
98  // Triangulator_CW : sets vertices in clockwise order
99  void SetOrientation(int orientation);
100 };
101 
103 protected:
105  bool isActive;
106  bool isConvex;
107  bool isEar;
108 
109  Vector2 p;
110  real_t angle;
111  PartitionVertex *previous;
112  PartitionVertex *next;
113  };
114 
115  struct MonotoneVertex {
116  Vector2 p;
117  long previous;
118  long next;
119  };
120 
121  struct VertexSorter{
122  mutable MonotoneVertex *vertices;
123  bool operator() (long index1, long index2) const;
124  };
125 
126  struct Diagonal {
127  long index1;
128  long index2;
129  };
130 
131  //dynamic programming state for minimum-weight triangulation
132  struct DPState {
133  bool visible;
134  real_t weight;
135  long bestvertex;
136  };
137 
138  //dynamic programming state for convex partitioning
139  struct DPState2 {
140  bool visible;
141  long weight;
142  List<Diagonal> pairs;
143  };
144 
145  //edge that intersects the scanline
146  struct ScanLineEdge {
147  mutable long index;
148  Vector2 p1;
149  Vector2 p2;
150 
151  //determines if the edge is to the left of another edge
152  bool operator< (const ScanLineEdge & other) const;
153 
154  bool IsConvex(const Vector2& p1, const Vector2& p2, const Vector2& p3) const;
155  };
156 
157  //standard helper functions
158  bool IsConvex(Vector2& p1, Vector2& p2, Vector2& p3);
159  bool IsReflex(Vector2& p1, Vector2& p2, Vector2& p3);
160  bool IsInside(Vector2& p1, Vector2& p2, Vector2& p3, Vector2 &p);
161 
162  bool InCone(Vector2 &p1, Vector2 &p2, Vector2 &p3, Vector2 &p);
163  bool InCone(PartitionVertex *v, Vector2 &p);
164 
165  int Intersects(Vector2 &p11, Vector2 &p12, Vector2 &p21, Vector2 &p22);
166 
167  Vector2 Normalize(const Vector2 &p);
168  real_t Distance(const Vector2 &p1, const Vector2 &p2);
169 
170  //helper functions for Triangulate_EC
171  void UpdateVertexReflexity(PartitionVertex *v);
172  void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices);
173 
174  //helper functions for ConvexPartition_OPT
175  void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates);
176  void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
177  void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
178 
179  //helper functions for MonotonePartition
180  bool Below(Vector2 &p1, Vector2 &p2);
181  void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
182  char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
183  Set<ScanLineEdge> *edgeTree, long *helpers);
184 
185  //triangulates a monotone polygon, used in Triangulate_MONO
186  int TriangulateMonotone(TriangulatorPoly *inPoly, List<TriangulatorPoly> *triangles);
187 
188 public:
189 
190  //simple heuristic procedure for removing holes from a list of polygons
191  //works by creating a diagonal from the rightmost hole vertex to some visible vertex
192  //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
193  //space complexity: O(n)
194  //params:
195  // inpolys : a list of polygons that can contain holes
196  // vertices of all non-hole polys have to be in counter-clockwise order
197  // vertices of all hole polys have to be in clockwise order
198  // outpolys : a list of polygons without holes
199  //returns 1 on success, 0 on failure
200  int RemoveHoles(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *outpolys);
201 
202  //triangulates a polygon by ear clipping
203  //time complexity O(n^2), n is the number of vertices
204  //space complexity: O(n)
205  //params:
206  // poly : an input polygon to be triangulated
207  // vertices have to be in counter-clockwise order
208  // triangles : a list of triangles (result)
209  //returns 1 on success, 0 on failure
210  int Triangulate_EC(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles);
211 
212  //triangulates a list of polygons that may contain holes by ear clipping algorithm
213  //first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon
214  //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
215  //space complexity: O(n)
216  //params:
217  // inpolys : a list of polygons to be triangulated (can contain holes)
218  // vertices of all non-hole polys have to be in counter-clockwise order
219  // vertices of all hole polys have to be in clockwise order
220  // triangles : a list of triangles (result)
221  //returns 1 on success, 0 on failure
222  int Triangulate_EC(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles);
223 
224  //creates an optimal polygon triangulation in terms of minimal edge length
225  //time complexity: O(n^3), n is the number of vertices
226  //space complexity: O(n^2)
227  //params:
228  // poly : an input polygon to be triangulated
229  // vertices have to be in counter-clockwise order
230  // triangles : a list of triangles (result)
231  //returns 1 on success, 0 on failure
232  int Triangulate_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles);
233 
234  //triangulates a polygons by firstly partitioning it into monotone polygons
235  //time complexity: O(n*log(n)), n is the number of vertices
236  //space complexity: O(n)
237  //params:
238  // poly : an input polygon to be triangulated
239  // vertices have to be in counter-clockwise order
240  // triangles : a list of triangles (result)
241  //returns 1 on success, 0 on failure
242  int Triangulate_MONO(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles);
243 
244  //triangulates a list of polygons by firstly partitioning them into monotone polygons
245  //time complexity: O(n*log(n)), n is the number of vertices
246  //space complexity: O(n)
247  //params:
248  // inpolys : a list of polygons to be triangulated (can contain holes)
249  // vertices of all non-hole polys have to be in counter-clockwise order
250  // vertices of all hole polys have to be in clockwise order
251  // triangles : a list of triangles (result)
252  //returns 1 on success, 0 on failure
253  int Triangulate_MONO(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles);
254 
255  //creates a monotone partition of a list of polygons that can contain holes
256  //time complexity: O(n*log(n)), n is the number of vertices
257  //space complexity: O(n)
258  //params:
259  // inpolys : a list of polygons to be triangulated (can contain holes)
260  // vertices of all non-hole polys have to be in counter-clockwise order
261  // vertices of all hole polys have to be in clockwise order
262  // monotonePolys : a list of monotone polygons (result)
263  //returns 1 on success, 0 on failure
264  int MonotonePartition(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *monotonePolys);
265 
266  //partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm
267  //the algorithm gives at most four times the number of parts as the optimal algorithm
268  //however, in practice it works much better than that and often gives optimal partition
269  //uses triangulation obtained by ear clipping as intermediate result
270  //time complexity O(n^2), n is the number of vertices
271  //space complexity: O(n)
272  //params:
273  // poly : an input polygon to be partitioned
274  // vertices have to be in counter-clockwise order
275  // parts : resulting list of convex polygons
276  //returns 1 on success, 0 on failure
277  int ConvexPartition_HM(TriangulatorPoly *poly, List<TriangulatorPoly> *parts);
278 
279  //partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm
280  //the algorithm gives at most four times the number of parts as the optimal algorithm
281  //however, in practice it works much better than that and often gives optimal partition
282  //uses triangulation obtained by ear clipping as intermediate result
283  //time complexity O(n^2), n is the number of vertices
284  //space complexity: O(n)
285  //params:
286  // inpolys : an input list of polygons to be partitioned
287  // vertices of all non-hole polys have to be in counter-clockwise order
288  // vertices of all hole polys have to be in clockwise order
289  // parts : resulting list of convex polygons
290  //returns 1 on success, 0 on failure
291  int ConvexPartition_HM(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *parts);
292 
293  //optimal convex partitioning (in terms of number of resulting convex polygons)
294  //using the Keil-Snoeyink algorithm
295  //M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998
296  //time complexity O(n^3), n is the number of vertices
297  //space complexity: O(n^3)
298  // poly : an input polygon to be partitioned
299  // vertices have to be in counter-clockwise order
300  // parts : resulting list of convex polygons
301  //returns 1 on success, 0 on failure
302  int ConvexPartition_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *parts);
303 };
304 
305 
306 #endif
Definition: triangulator.h:126
Definition: set.h:55
Definition: triangulator.h:132
Definition: triangulator.h:146
Definition: set.h:44
Definition: triangulator.h:33
Definition: triangulator.h:139
Definition: triangulator.h:104
Definition: triangulator.h:121
Definition: list.h:44
Definition: triangulator.h:102
Definition: triangulator.h:115
Definition: math_2d.h:65