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 
22 #include <stdio.h>
23 #include <string.h>
24 #include <math.h>
25 
26 #include "triangulator.h"
27 
28 
29 #define TRIANGULATOR_VERTEXTYPE_REGULAR 0
30 #define TRIANGULATOR_VERTEXTYPE_START 1
31 #define TRIANGULATOR_VERTEXTYPE_END 2
32 #define TRIANGULATOR_VERTEXTYPE_SPLIT 3
33 #define TRIANGULATOR_VERTEXTYPE_MERGE 4
34 
TriangulatorPoly()35 TriangulatorPoly::TriangulatorPoly() {
36 	hole = false;
37 	numpoints = 0;
38 	points = NULL;
39 }
40 
~TriangulatorPoly()41 TriangulatorPoly::~TriangulatorPoly() {
42 	if(points) delete [] points;
43 }
44 
Clear()45 void TriangulatorPoly::Clear() {
46 	if(points) delete [] points;
47 	hole = false;
48 	numpoints = 0;
49 	points = NULL;
50 }
51 
Init(long numpoints)52 void TriangulatorPoly::Init(long numpoints) {
53 	Clear();
54 	this->numpoints = numpoints;
55 	points = new Vector2[numpoints];
56 }
57 
Triangle(Vector2 & p1,Vector2 & p2,Vector2 & p3)58 void TriangulatorPoly::Triangle(Vector2 &p1, Vector2 &p2, Vector2 &p3) {
59 	Init(3);
60 	points[0] = p1;
61 	points[1] = p2;
62 	points[2] = p3;
63 }
64 
TriangulatorPoly(const TriangulatorPoly & src)65 TriangulatorPoly::TriangulatorPoly(const TriangulatorPoly &src) {
66 	hole = src.hole;
67 	numpoints = src.numpoints;
68 	points = new Vector2[numpoints];
69 	memcpy(points, src.points, numpoints*sizeof(Vector2));
70 }
71 
operator =(const TriangulatorPoly & src)72 TriangulatorPoly& TriangulatorPoly::operator=(const TriangulatorPoly &src) {
73 	Clear();
74 	hole = src.hole;
75 	numpoints = src.numpoints;
76 	points = new Vector2[numpoints];
77 	memcpy(points, src.points, numpoints*sizeof(Vector2));
78 	return *this;
79 }
80 
GetOrientation()81 int TriangulatorPoly::GetOrientation() {
82 	long i1,i2;
83 	real_t area = 0;
84 	for(i1=0; i1<numpoints; i1++) {
85 		i2 = i1+1;
86 		if(i2 == numpoints) i2 = 0;
87 		area += points[i1].x * points[i2].y - points[i1].y * points[i2].x;
88 	}
89 	if(area>0) return TRIANGULATOR_CCW;
90 	if(area<0) return TRIANGULATOR_CW;
91 	return 0;
92 }
93 
SetOrientation(int orientation)94 void TriangulatorPoly::SetOrientation(int orientation) {
95 	int polyorientation = GetOrientation();
96 	if(polyorientation&&(polyorientation!=orientation)) {
97 		Invert();
98 	}
99 }
100 
Invert()101 void TriangulatorPoly::Invert() {
102 	long i;
103 	Vector2 *invpoints;
104 
105 	invpoints = new Vector2[numpoints];
106 	for(i=0;i<numpoints;i++) {
107 		invpoints[i] = points[numpoints-i-1];
108 	}
109 
110 	delete [] points;
111 	points = invpoints;
112 }
113 
Normalize(const Vector2 & p)114 Vector2 TriangulatorPartition::Normalize(const Vector2 &p) {
115 	Vector2 r;
116 	real_t n = sqrt(p.x*p.x + p.y*p.y);
117 	if(n!=0) {
118 		r = p/n;
119 	} else {
120 		r.x = 0;
121 		r.y = 0;
122 	}
123 	return r;
124 }
125 
Distance(const Vector2 & p1,const Vector2 & p2)126 real_t TriangulatorPartition::Distance(const Vector2 &p1, const Vector2 &p2) {
127 	real_t dx,dy;
128 	dx = p2.x - p1.x;
129 	dy = p2.y - p1.y;
130 	return(sqrt(dx*dx + dy*dy));
131 }
132 
133 //checks if two lines intersect
Intersects(Vector2 & p11,Vector2 & p12,Vector2 & p21,Vector2 & p22)134 int TriangulatorPartition::Intersects(Vector2 &p11, Vector2 &p12, Vector2 &p21, Vector2 &p22) {
135 	if((p11.x == p21.x)&&(p11.y == p21.y)) return 0;
136 	if((p11.x == p22.x)&&(p11.y == p22.y)) return 0;
137 	if((p12.x == p21.x)&&(p12.y == p21.y)) return 0;
138 	if((p12.x == p22.x)&&(p12.y == p22.y)) return 0;
139 
140 	Vector2 v1ort,v2ort,v;
141 	real_t dot11,dot12,dot21,dot22;
142 
143 	v1ort.x = p12.y-p11.y;
144 	v1ort.y = p11.x-p12.x;
145 
146 	v2ort.x = p22.y-p21.y;
147 	v2ort.y = p21.x-p22.x;
148 
149 	v = p21-p11;
150 	dot21 = v.x*v1ort.x + v.y*v1ort.y;
151 	v = p22-p11;
152 	dot22 = v.x*v1ort.x + v.y*v1ort.y;
153 
154 	v = p11-p21;
155 	dot11 = v.x*v2ort.x + v.y*v2ort.y;
156 	v = p12-p21;
157 	dot12 = v.x*v2ort.x + v.y*v2ort.y;
158 
159 	if(dot11*dot12>0) return 0;
160 	if(dot21*dot22>0) return 0;
161 
162 	return 1;
163 }
164 
165 //removes holes from inpolys by merging them with non-holes
RemoveHoles(List<TriangulatorPoly> * inpolys,List<TriangulatorPoly> * outpolys)166 int TriangulatorPartition::RemoveHoles(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *outpolys) {
167 	List<TriangulatorPoly> polys;
168 	List<TriangulatorPoly>::Element *holeiter,*polyiter,*iter,*iter2;
169 	long i,i2,holepointindex,polypointindex;
170 	Vector2 holepoint,polypoint,bestpolypoint;
171 	Vector2 linep1,linep2;
172 	Vector2 v1,v2;
173 	TriangulatorPoly newpoly;
174 	bool hasholes;
175 	bool pointvisible;
176 	bool pointfound;
177 
178 	//check for trivial case (no holes)
179 	hasholes = false;
180 	for(iter = inpolys->front(); iter; iter=iter->next()) {
181 		if(iter->get().IsHole()) {
182 			hasholes = true;
183 			break;
184 		}
185 	}
186 	if(!hasholes) {
187 		for(iter = inpolys->front(); iter; iter=iter->next()) {
188 			outpolys->push_back(iter->get());
189 		}
190 		return 1;
191 	}
192 
193 	polys = *inpolys;
194 
195 	while(1) {
196 		//find the hole point with the largest x
197 		hasholes = false;
198 		for(iter = polys.front(); iter; iter=iter->next()) {
199 			if(!iter->get().IsHole()) continue;
200 
201 			if(!hasholes) {
202 				hasholes = true;
203 				holeiter = iter;
204 				holepointindex = 0;
205 			}
206 
207 			for(i=0; i < iter->get().GetNumPoints(); i++) {
208 				if(iter->get().GetPoint(i).x > holeiter->get().GetPoint(holepointindex).x) {
209 					holeiter = iter;
210 					holepointindex = i;
211 				}
212 			}
213 		}
214 		if(!hasholes) break;
215 		holepoint = holeiter->get().GetPoint(holepointindex);
216 
217 		pointfound = false;
218 		for(iter = polys.front(); iter; iter=iter->next()) {
219 			if(iter->get().IsHole()) continue;
220 			for(i=0; i < iter->get().GetNumPoints(); i++) {
221 				if(iter->get().GetPoint(i).x <= holepoint.x) continue;
222 				if(!InCone(iter->get().GetPoint((i+iter->get().GetNumPoints()-1)%(iter->get().GetNumPoints())),
223 					   iter->get().GetPoint(i),
224 					   iter->get().GetPoint((i+1)%(iter->get().GetNumPoints())),
225 					   holepoint))
226 					continue;
227 				polypoint = iter->get().GetPoint(i);
228 				if(pointfound) {
229 					v1 = Normalize(polypoint-holepoint);
230 					v2 = Normalize(bestpolypoint-holepoint);
231 					if(v2.x > v1.x) continue;
232 				}
233 				pointvisible = true;
234 				for(iter2 = polys.front(); iter2; iter2=iter2->next()) {
235 					if(iter2->get().IsHole()) continue;
236 					for(i2=0; i2 < iter2->get().GetNumPoints(); i2++) {
237 						linep1 = iter2->get().GetPoint(i2);
238 						linep2 = iter2->get().GetPoint((i2+1)%(iter2->get().GetNumPoints()));
239 						if(Intersects(holepoint,polypoint,linep1,linep2)) {
240 							pointvisible = false;
241 							break;
242 						}
243 					}
244 					if(!pointvisible) break;
245 				}
246 				if(pointvisible) {
247 					pointfound = true;
248 					bestpolypoint = polypoint;
249 					polyiter = iter;
250 					polypointindex = i;
251 				}
252 			}
253 		}
254 
255 		if(!pointfound) return 0;
256 
257 		newpoly.Init(holeiter->get().GetNumPoints() + polyiter->get().GetNumPoints() + 2);
258 		i2 = 0;
259 		for(i=0;i<=polypointindex;i++) {
260 			newpoly[i2] = polyiter->get().GetPoint(i);
261 			i2++;
262 		}
263 		for(i=0;i<=holeiter->get().GetNumPoints();i++) {
264 			newpoly[i2] = holeiter->get().GetPoint((i+holepointindex)%holeiter->get().GetNumPoints());
265 			i2++;
266 		}
267 		for(i=polypointindex;i<polyiter->get().GetNumPoints();i++) {
268 			newpoly[i2] = polyiter->get().GetPoint(i);
269 			i2++;
270 		}
271 
272 		polys.erase(holeiter);
273 		polys.erase(polyiter);
274 		polys.push_back(newpoly);
275 	}
276 
277 	for(iter = polys.front(); iter; iter=iter->next()) {
278 		outpolys->push_back(iter->get());
279 	}
280 
281 	return 1;
282 }
283 
IsConvex(Vector2 & p1,Vector2 & p2,Vector2 & p3)284 bool TriangulatorPartition::IsConvex(Vector2& p1, Vector2& p2, Vector2& p3) {
285 	real_t tmp;
286 	tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y);
287 	if(tmp>0) return 1;
288 	else return 0;
289 }
290 
IsReflex(Vector2 & p1,Vector2 & p2,Vector2 & p3)291 bool TriangulatorPartition::IsReflex(Vector2& p1, Vector2& p2, Vector2& p3) {
292 	real_t tmp;
293 	tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y);
294 	if(tmp<0) return 1;
295 	else return 0;
296 }
297 
IsInside(Vector2 & p1,Vector2 & p2,Vector2 & p3,Vector2 & p)298 bool TriangulatorPartition::IsInside(Vector2& p1, Vector2& p2, Vector2& p3, Vector2 &p) {
299 	if(IsConvex(p1,p,p2)) return false;
300 	if(IsConvex(p2,p,p3)) return false;
301 	if(IsConvex(p3,p,p1)) return false;
302 	return true;
303 }
304 
InCone(Vector2 & p1,Vector2 & p2,Vector2 & p3,Vector2 & p)305 bool TriangulatorPartition::InCone(Vector2 &p1, Vector2 &p2, Vector2 &p3, Vector2 &p) {
306 	bool convex;
307 
308 	convex = IsConvex(p1,p2,p3);
309 
310 	if(convex) {
311 		if(!IsConvex(p1,p2,p)) return false;
312 		if(!IsConvex(p2,p3,p)) return false;
313 		return true;
314 	} else {
315 		if(IsConvex(p1,p2,p)) return true;
316 		if(IsConvex(p2,p3,p)) return true;
317 		return false;
318 	}
319 }
320 
InCone(PartitionVertex * v,Vector2 & p)321 bool TriangulatorPartition::InCone(PartitionVertex *v, Vector2 &p) {
322 	Vector2 p1,p2,p3;
323 
324 	p1 = v->previous->p;
325 	p2 = v->p;
326 	p3 = v->next->p;
327 
328 	return InCone(p1,p2,p3,p);
329 }
330 
UpdateVertexReflexity(PartitionVertex * v)331 void TriangulatorPartition::UpdateVertexReflexity(PartitionVertex *v) {
332 	PartitionVertex *v1,*v3;
333 	v1 = v->previous;
334 	v3 = v->next;
335 	v->isConvex = !IsReflex(v1->p,v->p,v3->p);
336 }
337 
UpdateVertex(PartitionVertex * v,PartitionVertex * vertices,long numvertices)338 void TriangulatorPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) {
339 	long i;
340 	PartitionVertex *v1,*v3;
341 	Vector2 vec1,vec3;
342 
343 	v1 = v->previous;
344 	v3 = v->next;
345 
346 	v->isConvex = IsConvex(v1->p,v->p,v3->p);
347 
348 	vec1 = Normalize(v1->p - v->p);
349 	vec3 = Normalize(v3->p - v->p);
350 	v->angle = vec1.x*vec3.x + vec1.y*vec3.y;
351 
352 	if(v->isConvex) {
353 		v->isEar = true;
354 		for(i=0;i<numvertices;i++) {
355 			if((vertices[i].p.x==v->p.x)&&(vertices[i].p.y==v->p.y)) continue;
356 			if((vertices[i].p.x==v1->p.x)&&(vertices[i].p.y==v1->p.y)) continue;
357 			if((vertices[i].p.x==v3->p.x)&&(vertices[i].p.y==v3->p.y)) continue;
358 			if(IsInside(v1->p,v->p,v3->p,vertices[i].p)) {
359 				v->isEar = false;
360 				break;
361 			}
362 		}
363 	} else {
364 		v->isEar = false;
365 	}
366 }
367 
368 //triangulation by ear removal
Triangulate_EC(TriangulatorPoly * poly,List<TriangulatorPoly> * triangles)369 int TriangulatorPartition::Triangulate_EC(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
370 	long numvertices;
371 	PartitionVertex *vertices;
372 	PartitionVertex *ear;
373 	TriangulatorPoly triangle;
374 	long i,j;
375 	bool earfound;
376 
377 	if(poly->GetNumPoints() < 3) return 0;
378 	if(poly->GetNumPoints() == 3) {
379 		triangles->push_back(*poly);
380 		return 1;
381 	}
382 
383 	numvertices = poly->GetNumPoints();
384 
385 	vertices = new PartitionVertex[numvertices];
386 	for(i=0;i<numvertices;i++) {
387 		vertices[i].isActive = true;
388 		vertices[i].p = poly->GetPoint(i);
389 		if(i==(numvertices-1)) vertices[i].next=&(vertices[0]);
390 		else vertices[i].next=&(vertices[i+1]);
391 		if(i==0) vertices[i].previous = &(vertices[numvertices-1]);
392 		else vertices[i].previous = &(vertices[i-1]);
393 	}
394 	for(i=0;i<numvertices;i++) {
395 		UpdateVertex(&vertices[i],vertices,numvertices);
396 	}
397 
398 	for(i=0;i<numvertices-3;i++) {
399 		earfound = false;
400 		//find the most extruded ear
401 		for(j=0;j<numvertices;j++) {
402 			if(!vertices[j].isActive) continue;
403 			if(!vertices[j].isEar) continue;
404 			if(!earfound) {
405 				earfound = true;
406 				ear = &(vertices[j]);
407 			} else {
408 				if(vertices[j].angle > ear->angle) {
409 					ear = &(vertices[j]);
410 				}
411 			}
412 		}
413 		if(!earfound) {
414 			delete [] vertices;
415 			return 0;
416 		}
417 
418 		triangle.Triangle(ear->previous->p,ear->p,ear->next->p);
419 		triangles->push_back(triangle);
420 
421 		ear->isActive = false;
422 		ear->previous->next = ear->next;
423 		ear->next->previous = ear->previous;
424 
425 		if(i==numvertices-4) break;
426 
427 		UpdateVertex(ear->previous,vertices,numvertices);
428 		UpdateVertex(ear->next,vertices,numvertices);
429 	}
430 	for(i=0;i<numvertices;i++) {
431 		if(vertices[i].isActive) {
432 			triangle.Triangle(vertices[i].previous->p,vertices[i].p,vertices[i].next->p);
433 			triangles->push_back(triangle);
434 			break;
435 		}
436 	}
437 
438 	delete [] vertices;
439 
440 	return 1;
441 }
442 
Triangulate_EC(List<TriangulatorPoly> * inpolys,List<TriangulatorPoly> * triangles)443 int TriangulatorPartition::Triangulate_EC(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) {
444 	List<TriangulatorPoly> outpolys;
445 	List<TriangulatorPoly>::Element*iter;
446 
447 	if(!RemoveHoles(inpolys,&outpolys)) return 0;
448 	for(iter=outpolys.front();iter;iter=iter->next()) {
449 		if(!Triangulate_EC(&(iter->get()),triangles)) return 0;
450 	}
451 	return 1;
452 }
453 
ConvexPartition_HM(TriangulatorPoly * poly,List<TriangulatorPoly> * parts)454 int TriangulatorPartition::ConvexPartition_HM(TriangulatorPoly *poly, List<TriangulatorPoly> *parts) {
455 	List<TriangulatorPoly> triangles;
456 	List<TriangulatorPoly>::Element *iter1,*iter2;
457 	TriangulatorPoly *poly1,*poly2;
458 	TriangulatorPoly newpoly;
459 	Vector2 d1,d2,p1,p2,p3;
460 	long i11,i12,i21,i22,i13,i23,j,k;
461 	bool isdiagonal;
462 	long numreflex;
463 
464 	//check if the poly is already convex
465 	numreflex = 0;
466 	for(i11=0;i11<poly->GetNumPoints();i11++) {
467 		if(i11==0) i12 = poly->GetNumPoints()-1;
468 		else i12=i11-1;
469 		if(i11==(poly->GetNumPoints()-1)) i13=0;
470 		else i13=i11+1;
471 		if(IsReflex(poly->GetPoint(i12),poly->GetPoint(i11),poly->GetPoint(i13))) {
472 			numreflex = 1;
473 			break;
474 		}
475 	}
476 	if(numreflex == 0) {
477 		parts->push_back(*poly);
478 		return 1;
479 	}
480 
481 	if(!Triangulate_EC(poly,&triangles)) return 0;
482 
483 	for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) {
484 		poly1 = &(iter1->get());
485 		for(i11=0;i11<poly1->GetNumPoints();i11++) {
486 			d1 = poly1->GetPoint(i11);
487 			i12 = (i11+1)%(poly1->GetNumPoints());
488 			d2 = poly1->GetPoint(i12);
489 
490 			isdiagonal = false;
491 			for(iter2 = iter1; iter2 ; iter2=iter2->next()) {
492 				if(iter1 == iter2) continue;
493 				poly2 = &(iter2->get());
494 
495 				for(i21=0;i21<poly2->GetNumPoints();i21++) {
496 					if((d2.x != poly2->GetPoint(i21).x)||(d2.y != poly2->GetPoint(i21).y)) continue;
497 					i22 = (i21+1)%(poly2->GetNumPoints());
498 					if((d1.x != poly2->GetPoint(i22).x)||(d1.y != poly2->GetPoint(i22).y)) continue;
499 					isdiagonal = true;
500 					break;
501 				}
502 				if(isdiagonal) break;
503 			}
504 
505 			if(!isdiagonal) continue;
506 
507 			p2 = poly1->GetPoint(i11);
508 			if(i11 == 0) i13 = poly1->GetNumPoints()-1;
509 			else i13 = i11-1;
510 			p1 = poly1->GetPoint(i13);
511 			if(i22 == (poly2->GetNumPoints()-1)) i23 = 0;
512 			else i23 = i22+1;
513 			p3 = poly2->GetPoint(i23);
514 
515 			if(!IsConvex(p1,p2,p3)) continue;
516 
517 			p2 = poly1->GetPoint(i12);
518 			if(i12 == (poly1->GetNumPoints()-1)) i13 = 0;
519 			else i13 = i12+1;
520 			p3 = poly1->GetPoint(i13);
521 			if(i21 == 0) i23 = poly2->GetNumPoints()-1;
522 			else i23 = i21-1;
523 			p1 = poly2->GetPoint(i23);
524 
525 			if(!IsConvex(p1,p2,p3)) continue;
526 
527 			newpoly.Init(poly1->GetNumPoints()+poly2->GetNumPoints()-2);
528 			k = 0;
529 			for(j=i12;j!=i11;j=(j+1)%(poly1->GetNumPoints())) {
530 				newpoly[k] = poly1->GetPoint(j);
531 				k++;
532 			}
533 			for(j=i22;j!=i21;j=(j+1)%(poly2->GetNumPoints())) {
534 				newpoly[k] = poly2->GetPoint(j);
535 				k++;
536 			}
537 
538 			triangles.erase(iter2);
539 			iter1->get() = newpoly;
540 			poly1 = &(iter1->get());
541 			i11 = -1;
542 
543 			continue;
544 		}
545 	}
546 
547 	for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) {
548 		parts->push_back(iter1->get());
549 	}
550 
551 	return 1;
552 }
553 
ConvexPartition_HM(List<TriangulatorPoly> * inpolys,List<TriangulatorPoly> * parts)554 int TriangulatorPartition::ConvexPartition_HM(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *parts) {
555 	List<TriangulatorPoly> outpolys;
556 	List<TriangulatorPoly>::Element* iter;
557 
558 	if(!RemoveHoles(inpolys,&outpolys)) return 0;
559 	for(iter=outpolys.front();iter;iter=iter->next()) {
560 		if(!ConvexPartition_HM(&(iter->get()),parts)) return 0;
561 	}
562 	return 1;
563 }
564 
565 //minimum-weight polygon triangulation by dynamic programming
566 //O(n^3) time complexity
567 //O(n^2) space complexity
Triangulate_OPT(TriangulatorPoly * poly,List<TriangulatorPoly> * triangles)568 int TriangulatorPartition::Triangulate_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
569 	long i,j,k,gap,n;
570 	DPState **dpstates;
571 	Vector2 p1,p2,p3,p4;
572 	long bestvertex;
573 	real_t weight,minweight,d1,d2;
574 	Diagonal diagonal,newdiagonal;
575 	List<Diagonal> diagonals;
576 	TriangulatorPoly triangle;
577 	int ret = 1;
578 
579 	n = poly->GetNumPoints();
580 	dpstates = new DPState *[n];
581 	for(i=1;i<n;i++) {
582 		dpstates[i] = new DPState[i];
583 	}
584 
585 	//init states and visibility
586 	for(i=0;i<(n-1);i++) {
587 		p1 = poly->GetPoint(i);
588 		for(j=i+1;j<n;j++) {
589 			dpstates[j][i].visible = true;
590 			dpstates[j][i].weight = 0;
591 			dpstates[j][i].bestvertex = -1;
592 			if(j!=(i+1)) {
593 				p2 = poly->GetPoint(j);
594 
595 				//visibility check
596 				if(i==0) p3 = poly->GetPoint(n-1);
597 				else p3 = poly->GetPoint(i-1);
598 				if(i==(n-1)) p4 = poly->GetPoint(0);
599 				else p4 = poly->GetPoint(i+1);
600 				if(!InCone(p3,p1,p4,p2)) {
601 					dpstates[j][i].visible = false;
602 					continue;
603 				}
604 
605 				if(j==0) p3 = poly->GetPoint(n-1);
606 				else p3 = poly->GetPoint(j-1);
607 				if(j==(n-1)) p4 = poly->GetPoint(0);
608 				else p4 = poly->GetPoint(j+1);
609 				if(!InCone(p3,p2,p4,p1)) {
610 					dpstates[j][i].visible = false;
611 					continue;
612 				}
613 
614 				for(k=0;k<n;k++) {
615 					p3 = poly->GetPoint(k);
616 					if(k==(n-1)) p4 = poly->GetPoint(0);
617 					else p4 = poly->GetPoint(k+1);
618 					if(Intersects(p1,p2,p3,p4)) {
619 						dpstates[j][i].visible = false;
620 						break;
621 					}
622 				}
623 			}
624 		}
625 	}
626 	dpstates[n-1][0].visible = true;
627 	dpstates[n-1][0].weight = 0;
628 	dpstates[n-1][0].bestvertex = -1;
629 
630 	for(gap = 2; gap<n; gap++) {
631 		for(i=0; i<(n-gap); i++) {
632 			j = i+gap;
633 			if(!dpstates[j][i].visible) continue;
634 			bestvertex = -1;
635 			for(k=(i+1);k<j;k++) {
636 				if(!dpstates[k][i].visible) continue;
637 				if(!dpstates[j][k].visible) continue;
638 
639 				if(k<=(i+1)) d1=0;
640 				else d1 = Distance(poly->GetPoint(i),poly->GetPoint(k));
641 				if(j<=(k+1)) d2=0;
642 				else d2 = Distance(poly->GetPoint(k),poly->GetPoint(j));
643 
644 				weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2;
645 
646 				if((bestvertex == -1)||(weight<minweight)) {
647 					bestvertex = k;
648 					minweight = weight;
649 				}
650 			}
651 			if(bestvertex == -1) {
652 				for(i=1;i<n;i++) {
653 					delete [] dpstates[i];
654 				}
655 				delete [] dpstates;
656 
657 				return 0;
658 			}
659 
660 			dpstates[j][i].bestvertex = bestvertex;
661 			dpstates[j][i].weight = minweight;
662 		}
663 	}
664 
665 	newdiagonal.index1 = 0;
666 	newdiagonal.index2 = n-1;
667 	diagonals.push_back(newdiagonal);
668 	while(!diagonals.empty()) {
669 		diagonal = (diagonals.front()->get());
670 		diagonals.pop_front();
671 		bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex;
672 		if(bestvertex == -1) {
673 			ret = 0;
674 			break;
675 		}
676 		triangle.Triangle(poly->GetPoint(diagonal.index1),poly->GetPoint(bestvertex),poly->GetPoint(diagonal.index2));
677 		triangles->push_back(triangle);
678 		if(bestvertex > (diagonal.index1+1)) {
679 			newdiagonal.index1 = diagonal.index1;
680 			newdiagonal.index2 = bestvertex;
681 			diagonals.push_back(newdiagonal);
682 		}
683 		if(diagonal.index2 > (bestvertex+1)) {
684 			newdiagonal.index1 = bestvertex;
685 			newdiagonal.index2 = diagonal.index2;
686 			diagonals.push_back(newdiagonal);
687 		}
688 	}
689 
690 	for(i=1;i<n;i++) {
691 		delete [] dpstates[i];
692 	}
693 	delete [] dpstates;
694 
695 	return ret;
696 }
697 
UpdateState(long a,long b,long w,long i,long j,DPState2 ** dpstates)698 void TriangulatorPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) {
699 	Diagonal newdiagonal;
700 	List<Diagonal> *pairs;
701 	long w2;
702 
703 	w2 = dpstates[a][b].weight;
704 	if(w>w2) return;
705 
706 	pairs = &(dpstates[a][b].pairs);
707 	newdiagonal.index1 = i;
708 	newdiagonal.index2 = j;
709 
710 	if(w<w2) {
711 		pairs->clear();
712 		pairs->push_front(newdiagonal);
713 		dpstates[a][b].weight = w;
714 	} else {
715 		if((!pairs->empty())&&(i <= pairs->front()->get().index1)) return;
716 		while((!pairs->empty())&&(pairs->front()->get().index2 >= j)) pairs->pop_front();
717 		pairs->push_front(newdiagonal);
718 	}
719 }
720 
TypeA(long i,long j,long k,PartitionVertex * vertices,DPState2 ** dpstates)721 void TriangulatorPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
722 	List<Diagonal> *pairs;
723 	List<Diagonal>::Element *iter,*lastiter;
724 	long top;
725 	long w;
726 
727 	if(!dpstates[i][j].visible) return;
728 	top = j;
729 	w = dpstates[i][j].weight;
730 	if(k-j > 1) {
731 		if (!dpstates[j][k].visible) return;
732 		w += dpstates[j][k].weight + 1;
733 	}
734 	if(j-i > 1) {
735 		pairs = &(dpstates[i][j].pairs);
736 		iter = NULL;
737 		lastiter = NULL;
738 		while(iter!=pairs->front()) {
739 			if (!iter)
740 				iter=pairs->back();
741 			else
742 				iter=iter->prev();
743 
744 			if(!IsReflex(vertices[iter->get().index2].p,vertices[j].p,vertices[k].p)) lastiter = iter;
745 			else break;
746 		}
747 		if(lastiter == NULL) w++;
748 		else {
749 			if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->get().index1].p)) w++;
750 			else top = lastiter->get().index1;
751 		}
752 	}
753 	UpdateState(i,k,w,top,j,dpstates);
754 }
755 
TypeB(long i,long j,long k,PartitionVertex * vertices,DPState2 ** dpstates)756 void TriangulatorPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) {
757 	List<Diagonal> *pairs;
758 	List<Diagonal>::Element* iter,*lastiter;
759 	long top;
760 	long w;
761 
762 	if(!dpstates[j][k].visible) return;
763 	top = j;
764 	w = dpstates[j][k].weight;
765 
766 	if (j-i > 1) {
767 		if (!dpstates[i][j].visible) return;
768 		w += dpstates[i][j].weight + 1;
769 	}
770 	if (k-j > 1) {
771 		pairs = &(dpstates[j][k].pairs);
772 
773 		iter = pairs->front();
774 		if((!pairs->empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p))) {
775 			lastiter = iter;
776 			while(iter!=NULL) {
777 				if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p)) {
778 					lastiter = iter;
779 					iter=iter->next();
780 				}
781 				else break;
782 			}
783 			if(IsReflex(vertices[lastiter->get().index2].p,vertices[k].p,vertices[i].p)) w++;
784 			else top = lastiter->get().index2;
785 		} else w++;
786 	}
787 	UpdateState(i,k,w,j,top,dpstates);
788 }
789 
ConvexPartition_OPT(TriangulatorPoly * poly,List<TriangulatorPoly> * parts)790 int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *parts) {
791 	Vector2 p1,p2,p3,p4;
792 	PartitionVertex *vertices;
793 	DPState2 **dpstates;
794 	long i,j,k,n,gap;
795 	List<Diagonal> diagonals,diagonals2;
796 	Diagonal diagonal,newdiagonal;
797 	List<Diagonal> *pairs,*pairs2;
798 	List<Diagonal>::Element* iter,*iter2;
799 	int ret;
800 	TriangulatorPoly newpoly;
801 	List<long> indices;
802 	List<long>::Element* iiter;
803 	bool ijreal,jkreal;
804 
805 	n = poly->GetNumPoints();
806 	vertices = new PartitionVertex[n];
807 
808 	dpstates = new DPState2 *[n];
809 	for(i=0;i<n;i++) {
810 		dpstates[i] = new DPState2[n];
811 	}
812 
813 	//init vertex information
814 	for(i=0;i<n;i++) {
815 		vertices[i].p = poly->GetPoint(i);
816 		vertices[i].isActive = true;
817 		if(i==0) vertices[i].previous = &(vertices[n-1]);
818 		else vertices[i].previous = &(vertices[i-1]);
819 		if(i==(poly->GetNumPoints()-1)) vertices[i].next = &(vertices[0]);
820 		else vertices[i].next = &(vertices[i+1]);
821 	}
822 	for(i=1;i<n;i++) {
823 		UpdateVertexReflexity(&(vertices[i]));
824 	}
825 
826 	//init states and visibility
827 	for(i=0;i<(n-1);i++) {
828 		p1 = poly->GetPoint(i);
829 		for(j=i+1;j<n;j++) {
830 			dpstates[i][j].visible = true;
831 			if(j==i+1) {
832 				dpstates[i][j].weight = 0;
833 			} else {
834 				dpstates[i][j].weight = 2147483647;
835 			}
836 			if(j!=(i+1)) {
837 				p2 = poly->GetPoint(j);
838 
839 				//visibility check
840 				if(!InCone(&vertices[i],p2)) {
841 					dpstates[i][j].visible = false;
842 					continue;
843 				}
844 				if(!InCone(&vertices[j],p1)) {
845 					dpstates[i][j].visible = false;
846 					continue;
847 				}
848 
849 				for(k=0;k<n;k++) {
850 					p3 = poly->GetPoint(k);
851 					if(k==(n-1)) p4 = poly->GetPoint(0);
852 					else p4 = poly->GetPoint(k+1);
853 					if(Intersects(p1,p2,p3,p4)) {
854 						dpstates[i][j].visible = false;
855 						break;
856 					}
857 				}
858 			}
859 		}
860 	}
861 	for(i=0;i<(n-2);i++) {
862 		j = i+2;
863 		if(dpstates[i][j].visible) {
864 			dpstates[i][j].weight = 0;
865 			newdiagonal.index1 = i+1;
866 			newdiagonal.index2 = i+1;
867 			dpstates[i][j].pairs.push_back(newdiagonal);
868 		}
869 	}
870 
871 	dpstates[0][n-1].visible = true;
872 	vertices[0].isConvex = false; //by convention
873 
874 	for(gap=3; gap<n; gap++) {
875 		for(i=0;i<n-gap;i++) {
876 			if(vertices[i].isConvex) continue;
877 			k = i+gap;
878 			if(dpstates[i][k].visible) {
879 				if(!vertices[k].isConvex) {
880 					for(j=i+1;j<k;j++) TypeA(i,j,k,vertices,dpstates);
881 				} else {
882 					for(j=i+1;j<(k-1);j++) {
883 						if(vertices[j].isConvex) continue;
884 						TypeA(i,j,k,vertices,dpstates);
885 					}
886 					TypeA(i,k-1,k,vertices,dpstates);
887 				}
888 			}
889 		}
890 		for(k=gap;k<n;k++) {
891 			if(vertices[k].isConvex) continue;
892 			i = k-gap;
893 			if((vertices[i].isConvex)&&(dpstates[i][k].visible)) {
894 				TypeB(i,i+1,k,vertices,dpstates);
895 				for(j=i+2;j<k;j++) {
896 					if(vertices[j].isConvex) continue;
897 					TypeB(i,j,k,vertices,dpstates);
898 				}
899 			}
900 		}
901 	}
902 
903 
904 	//recover solution
905 	ret = 1;
906 	newdiagonal.index1 = 0;
907 	newdiagonal.index2 = n-1;
908 	diagonals.push_front(newdiagonal);
909 	while(!diagonals.empty()) {
910 		diagonal = (diagonals.front()->get());
911 		diagonals.pop_front();
912 		if((diagonal.index2 - diagonal.index1) <=1) continue;
913 		pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
914 		if(pairs->empty()) {
915 			ret = 0;
916 			break;
917 		}
918 		if(!vertices[diagonal.index1].isConvex) {
919 			iter = pairs->back();
920 
921 			j = iter->get().index2;
922 			newdiagonal.index1 = j;
923 			newdiagonal.index2 = diagonal.index2;
924 			diagonals.push_front(newdiagonal);
925 			if((j - diagonal.index1)>1) {
926 				if(iter->get().index1 != iter->get().index2) {
927 					pairs2 = &(dpstates[diagonal.index1][j].pairs);
928 					while(1) {
929 						if(pairs2->empty()) {
930 							ret = 0;
931 							break;
932 						}
933 						iter2 = pairs2->back();
934 
935 						if(iter->get().index1 != iter2->get().index1) pairs2->pop_back();
936 						else break;
937 					}
938 					if(ret == 0) break;
939 				}
940 				newdiagonal.index1 = diagonal.index1;
941 				newdiagonal.index2 = j;
942 				diagonals.push_front(newdiagonal);
943 			}
944 		} else {
945 			iter = pairs->front();
946 			j = iter->get().index1;
947 			newdiagonal.index1 = diagonal.index1;
948 			newdiagonal.index2 = j;
949 			diagonals.push_front(newdiagonal);
950 			if((diagonal.index2 - j) > 1) {
951 				if(iter->get().index1 != iter->get().index2) {
952 					pairs2 = &(dpstates[j][diagonal.index2].pairs);
953 					while(1) {
954 						if(pairs2->empty()) {
955 							ret = 0;
956 							break;
957 						}
958 						iter2 = pairs2->front();
959 						if(iter->get().index2 != iter2->get().index2) pairs2->pop_front();
960 						else break;
961 					}
962 					if(ret == 0) break;
963 				}
964 				newdiagonal.index1 = j;
965 				newdiagonal.index2 = diagonal.index2;
966 				diagonals.push_front(newdiagonal);
967 			}
968 		}
969 	}
970 
971 	if(ret == 0) {
972 		for(i=0;i<n;i++) {
973 			delete [] dpstates[i];
974 		}
975 		delete [] dpstates;
976 		delete [] vertices;
977 
978 		return ret;
979 	}
980 
981 	newdiagonal.index1 = 0;
982 	newdiagonal.index2 = n-1;
983 	diagonals.push_front(newdiagonal);
984 	while(!diagonals.empty()) {
985 		diagonal = (diagonals.front())->get();
986 		diagonals.pop_front();
987 		if((diagonal.index2 - diagonal.index1) <= 1) continue;
988 
989 		indices.clear();
990 		diagonals2.clear();
991 		indices.push_back(diagonal.index1);
992 		indices.push_back(diagonal.index2);
993 		diagonals2.push_front(diagonal);
994 
995 		while(!diagonals2.empty()) {
996 			diagonal = (diagonals2.front()->get());
997 			diagonals2.pop_front();
998 			if((diagonal.index2 - diagonal.index1) <= 1) continue;
999 			ijreal = true;
1000 			jkreal = true;
1001 			pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs);
1002 			if(!vertices[diagonal.index1].isConvex) {
1003 				iter = pairs->back();
1004 				j = iter->get().index2;
1005 				if(iter->get().index1 != iter->get().index2) ijreal = false;
1006 			} else {
1007 				iter = pairs->front();
1008 				j = iter->get().index1;
1009 				if(iter->get().index1 != iter->get().index2) jkreal = false;
1010 			}
1011 
1012 			newdiagonal.index1 = diagonal.index1;
1013 			newdiagonal.index2 = j;
1014 			if(ijreal) {
1015 				diagonals.push_back(newdiagonal);
1016 			} else {
1017 				diagonals2.push_back(newdiagonal);
1018 			}
1019 
1020 			newdiagonal.index1 = j;
1021 			newdiagonal.index2 = diagonal.index2;
1022 			if(jkreal) {
1023 				diagonals.push_back(newdiagonal);
1024 			} else {
1025 				diagonals2.push_back(newdiagonal);
1026 			}
1027 
1028 			indices.push_back(j);
1029 		}
1030 
1031 		indices.sort();
1032 		newpoly.Init((long)indices.size());
1033 		k=0;
1034 		for(iiter = indices.front();iiter;iiter=iiter->next()) {
1035 			newpoly[k] = vertices[iiter->get()].p;
1036 			k++;
1037 		}
1038 		parts->push_back(newpoly);
1039 	}
1040 
1041 	for(i=0;i<n;i++) {
1042 		delete [] dpstates[i];
1043 	}
1044 	delete [] dpstates;
1045 	delete [] vertices;
1046 
1047 	return ret;
1048 }
1049 
1050 //triangulates a set of polygons by first partitioning them into monotone polygons
1051 //O(n*log(n)) time complexity, O(n) space complexity
1052 //the algorithm used here is outlined in the book
1053 //"Computational Geometry: Algorithms and Applications"
1054 //by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars
MonotonePartition(List<TriangulatorPoly> * inpolys,List<TriangulatorPoly> * monotonePolys)1055 int TriangulatorPartition::MonotonePartition(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *monotonePolys) {
1056 	List<TriangulatorPoly>::Element *iter;
1057 	MonotoneVertex *vertices;
1058 	long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices;
1059 	long polystartindex, polyendindex;
1060 	TriangulatorPoly *poly;
1061 	MonotoneVertex *v,*v2,*vprev,*vnext;
1062 	ScanLineEdge newedge;
1063 	bool error = false;
1064 
1065 	numvertices = 0;
1066 	for(iter = inpolys->front(); iter ; iter=iter->next()) {
1067 		numvertices += iter->get().GetNumPoints();
1068 	}
1069 
1070 	maxnumvertices = numvertices*3;
1071 	vertices = new MonotoneVertex[maxnumvertices];
1072 	newnumvertices = numvertices;
1073 
1074 	polystartindex = 0;
1075 	for(iter = inpolys->front(); iter ; iter=iter->next()) {
1076 		poly = &(iter->get());
1077 		polyendindex = polystartindex + poly->GetNumPoints()-1;
1078 		for(i=0;i<poly->GetNumPoints();i++) {
1079 			vertices[i+polystartindex].p = poly->GetPoint(i);
1080 			if(i==0) vertices[i+polystartindex].previous = polyendindex;
1081 			else vertices[i+polystartindex].previous = i+polystartindex-1;
1082 			if(i==(poly->GetNumPoints()-1)) vertices[i+polystartindex].next = polystartindex;
1083 			else vertices[i+polystartindex].next = i+polystartindex+1;
1084 		}
1085 		polystartindex = polyendindex+1;
1086 	}
1087 
1088 	//construct the priority queue
1089 	long *priority = new long [numvertices];
1090 	for(i=0;i<numvertices;i++) priority[i] = i;
1091 	SortArray<long,VertexSorter> sorter;
1092 	sorter.compare.vertices=vertices;
1093 	sorter.sort(priority,numvertices);
1094 
1095 	//determine vertex types
1096 	char *vertextypes = new char[maxnumvertices];
1097 	for(i=0;i<numvertices;i++) {
1098 		v = &(vertices[i]);
1099 		vprev = &(vertices[v->previous]);
1100 		vnext = &(vertices[v->next]);
1101 
1102 		if(Below(vprev->p,v->p)&&Below(vnext->p,v->p)) {
1103 			if(IsConvex(vnext->p,vprev->p,v->p)) {
1104 				vertextypes[i] = TRIANGULATOR_VERTEXTYPE_START;
1105 			} else {
1106 				vertextypes[i] = TRIANGULATOR_VERTEXTYPE_SPLIT;
1107 			}
1108 		} else if(Below(v->p,vprev->p)&&Below(v->p,vnext->p)) {
1109 			if(IsConvex(vnext->p,vprev->p,v->p))
1110 			{
1111 				vertextypes[i] = TRIANGULATOR_VERTEXTYPE_END;
1112 			} else {
1113 				vertextypes[i] = TRIANGULATOR_VERTEXTYPE_MERGE;
1114 			}
1115 		} else {
1116 			vertextypes[i] = TRIANGULATOR_VERTEXTYPE_REGULAR;
1117 		}
1118 	}
1119 
1120 	//helpers
1121 	long *helpers = new long[maxnumvertices];
1122 
1123 	//binary search tree that holds edges intersecting the scanline
1124 	//note that while set doesn't actually have to be implemented as a tree
1125 	//complexity requirements for operations are the same as for the balanced binary search tree
1126 	Set<ScanLineEdge> edgeTree;
1127 	//store iterators to the edge tree elements
1128 	//this makes deleting existing edges much faster
1129 	Set<ScanLineEdge>::Element **edgeTreeIterators,*edgeIter;
1130 	edgeTreeIterators = new Set<ScanLineEdge>::Element*[maxnumvertices];
1131 //	Pair<Set<ScanLineEdge>::Element*,bool> edgeTreeRet;
1132 	for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = NULL;
1133 
1134 	//for each vertex
1135 	for(i=0;i<numvertices;i++) {
1136 		vindex = priority[i];
1137 		v = &(vertices[vindex]);
1138 		vindex2 = vindex;
1139 		v2 = v;
1140 
1141 		//depending on the vertex type, do the appropriate action
1142 		//comments in the following sections are copied from "Computational Geometry: Algorithms and Applications"
1143 		switch(vertextypes[vindex]) {
1144 			case TRIANGULATOR_VERTEXTYPE_START:
1145 				//Insert ei in T and set helper(ei) to vi.
1146 				newedge.p1 = v->p;
1147 				newedge.p2 = vertices[v->next].p;
1148 				newedge.index = vindex;
1149 				edgeTreeIterators[vindex] = edgeTree.insert(newedge);
1150 				helpers[vindex] = vindex;
1151 				break;
1152 
1153 			case TRIANGULATOR_VERTEXTYPE_END:
1154 				//if helper(ei-1) is a merge vertex
1155 				if(vertextypes[helpers[v->previous]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
1156 					//Insert the diagonal connecting vi to helper(ei-1) in D.
1157 					AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
1158 							vertextypes, edgeTreeIterators, &edgeTree, helpers);
1159 				}
1160 				//Delete ei-1 from T
1161 				edgeTree.erase(edgeTreeIterators[v->previous]);
1162 				break;
1163 
1164 			case TRIANGULATOR_VERTEXTYPE_SPLIT:
1165 				//Search in T to find the edge e j directly left of vi.
1166 				newedge.p1 = v->p;
1167 				newedge.p2 = v->p;
1168 				edgeIter = edgeTree.lower_bound(newedge);
1169 				if(edgeIter == edgeTree.front()) {
1170 					error = true;
1171 					break;
1172 				}
1173 				edgeIter=edgeIter->prev();
1174 				//Insert the diagonal connecting vi to helper(ej) in D.
1175 				AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->get().index],
1176 						vertextypes, edgeTreeIterators, &edgeTree, helpers);
1177 				vindex2 = newnumvertices-2;
1178 				v2 = &(vertices[vindex2]);
1179 				//helper(e j)�vi
1180 				helpers[edgeIter->get().index] = vindex;
1181 				//Insert ei in T and set helper(ei) to vi.
1182 				newedge.p1 = v2->p;
1183 				newedge.p2 = vertices[v2->next].p;
1184 				newedge.index = vindex2;
1185 
1186 				edgeTreeIterators[vindex2] = edgeTree.insert(newedge);
1187 				helpers[vindex2] = vindex2;
1188 				break;
1189 
1190 			case TRIANGULATOR_VERTEXTYPE_MERGE:
1191 				//if helper(ei-1) is a merge vertex
1192 				if(vertextypes[helpers[v->previous]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
1193 					//Insert the diagonal connecting vi to helper(ei-1) in D.
1194 					AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
1195 							vertextypes, edgeTreeIterators, &edgeTree, helpers);
1196 					vindex2 = newnumvertices-2;
1197 					v2 = &(vertices[vindex2]);
1198 				}
1199 				//Delete ei-1 from T.
1200 				edgeTree.erase(edgeTreeIterators[v->previous]);
1201 				//Search in T to find the edge e j directly left of vi.
1202 				newedge.p1 = v->p;
1203 				newedge.p2 = v->p;
1204 				edgeIter = edgeTree.lower_bound(newedge);
1205 				if(edgeIter == edgeTree.front()) {
1206 					error = true;
1207 					break;
1208 				}
1209 				edgeIter=edgeIter->prev();
1210 				//if helper(ej) is a merge vertex
1211 				if(vertextypes[helpers[edgeIter->get().index]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
1212 					//Insert the diagonal connecting vi to helper(e j) in D.
1213 					AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->get().index],
1214 							vertextypes, edgeTreeIterators, &edgeTree, helpers);
1215 				}
1216 				//helper(e j)�vi
1217 				helpers[edgeIter->get().index] = vindex2;
1218 				break;
1219 
1220 			case TRIANGULATOR_VERTEXTYPE_REGULAR:
1221 				//if the interior of P lies to the right of vi
1222 				if(Below(v->p,vertices[v->previous].p)) {
1223 					//if helper(ei-1) is a merge vertex
1224 					if(vertextypes[helpers[v->previous]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
1225 						//Insert the diagonal connecting vi to helper(ei-1) in D.
1226 						AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous],
1227 								vertextypes, edgeTreeIterators, &edgeTree, helpers);
1228 						vindex2 = newnumvertices-2;
1229 						v2 = &(vertices[vindex2]);
1230 					}
1231 					//Delete ei-1 from T.
1232 					edgeTree.erase(edgeTreeIterators[v->previous]);
1233 					//Insert ei in T and set helper(ei) to vi.
1234 					newedge.p1 = v2->p;
1235 					newedge.p2 = vertices[v2->next].p;
1236 					newedge.index = vindex2;
1237 					edgeTreeIterators[vindex2] = edgeTree.insert(newedge);
1238 					helpers[vindex2] = vindex;
1239 				} else {
1240 					//Search in T to find the edge ej directly left of vi.
1241 					newedge.p1 = v->p;
1242 					newedge.p2 = v->p;
1243 					edgeIter = edgeTree.lower_bound(newedge);
1244 					if(edgeIter == edgeTree.front()) {
1245 						error = true;
1246 						break;
1247 					}
1248 					edgeIter=edgeIter->prev();
1249 					//if helper(ej) is a merge vertex
1250 					if(vertextypes[helpers[edgeIter->get().index]]==TRIANGULATOR_VERTEXTYPE_MERGE) {
1251 						//Insert the diagonal connecting vi to helper(e j) in D.
1252 						AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->get().index],
1253 								vertextypes, edgeTreeIterators, &edgeTree, helpers);
1254 					}
1255 					//helper(e j)�vi
1256 					helpers[edgeIter->get().index] = vindex;
1257 				}
1258 				break;
1259 		}
1260 
1261 		if(error) break;
1262 	}
1263 
1264 	char *used = new char[newnumvertices];
1265 	memset(used,0,newnumvertices*sizeof(char));
1266 
1267 	if(!error) {
1268 		//return result
1269 		long size;
1270 		TriangulatorPoly mpoly;
1271 		for(i=0;i<newnumvertices;i++) {
1272 			if(used[i]) continue;
1273 			v = &(vertices[i]);
1274 			vnext = &(vertices[v->next]);
1275 			size = 1;
1276 			while(vnext!=v) {
1277 				vnext = &(vertices[vnext->next]);
1278 				size++;
1279 			}
1280 			mpoly.Init(size);
1281 			v = &(vertices[i]);
1282 			mpoly[0] = v->p;
1283 			vnext = &(vertices[v->next]);
1284 			size = 1;
1285 			used[i] = 1;
1286 			used[v->next] = 1;
1287 			while(vnext!=v) {
1288 				mpoly[size] = vnext->p;
1289 				used[vnext->next] = 1;
1290 				vnext = &(vertices[vnext->next]);
1291 				size++;
1292 			}
1293 			monotonePolys->push_back(mpoly);
1294 		}
1295 	}
1296 
1297 	//cleanup
1298 	delete [] vertices;
1299 	delete [] priority;
1300 	delete [] vertextypes;
1301 	delete [] edgeTreeIterators;
1302 	delete [] helpers;
1303 	delete [] used;
1304 
1305 	if(error) {
1306 		return 0;
1307 	} else {
1308 		return 1;
1309 	}
1310 }
1311 
1312 //adds a diagonal to the doubly-connected list of vertices
AddDiagonal(MonotoneVertex * vertices,long * numvertices,long index1,long index2,char * vertextypes,Set<ScanLineEdge>::Element ** edgeTreeIterators,Set<ScanLineEdge> * edgeTree,long * helpers)1313 void TriangulatorPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
1314 					char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
1315 					Set<ScanLineEdge> *edgeTree, long *helpers)
1316 {
1317 	long newindex1,newindex2;
1318 
1319 	newindex1 = *numvertices;
1320 	(*numvertices)++;
1321 	newindex2 = *numvertices;
1322 	(*numvertices)++;
1323 
1324 	vertices[newindex1].p = vertices[index1].p;
1325 	vertices[newindex2].p = vertices[index2].p;
1326 
1327 	vertices[newindex2].next = vertices[index2].next;
1328 	vertices[newindex1].next = vertices[index1].next;
1329 
1330 	vertices[vertices[index2].next].previous = newindex2;
1331 	vertices[vertices[index1].next].previous = newindex1;
1332 
1333 	vertices[index1].next = newindex2;
1334 	vertices[newindex2].previous = index1;
1335 
1336 	vertices[index2].next = newindex1;
1337 	vertices[newindex1].previous = index2;
1338 
1339 	//update all relevant structures
1340 	vertextypes[newindex1] = vertextypes[index1];
1341 	edgeTreeIterators[newindex1] = edgeTreeIterators[index1];
1342 	helpers[newindex1] = helpers[index1];
1343 	if(edgeTreeIterators[newindex1] != NULL)
1344 		edgeTreeIterators[newindex1]->get().index = newindex1;
1345 	vertextypes[newindex2] = vertextypes[index2];
1346 	edgeTreeIterators[newindex2] = edgeTreeIterators[index2];
1347 	helpers[newindex2] = helpers[index2];
1348 	if(edgeTreeIterators[newindex2] != NULL)
1349 		edgeTreeIterators[newindex2]->get().index = newindex2;
1350 }
1351 
Below(Vector2 & p1,Vector2 & p2)1352 bool TriangulatorPartition::Below(Vector2 &p1, Vector2 &p2) {
1353 	if(p1.y < p2.y) return true;
1354 	else if(p1.y == p2.y) {
1355 		if(p1.x < p2.x) return true;
1356 	}
1357 	return false;
1358 }
1359 
1360 
1361 
1362 
1363 
1364 //sorts in the falling order of y values, if y is equal, x is used instead
operator ()(long index1,long index2) const1365 bool TriangulatorPartition::VertexSorter::operator() (long index1, long index2) const {
1366 	if(vertices[index1].p.y > vertices[index2].p.y) return true;
1367 	else if(vertices[index1].p.y == vertices[index2].p.y) {
1368 		if(vertices[index1].p.x > vertices[index2].p.x) return true;
1369 	}
1370 	return false;
1371 }
1372 
IsConvex(const Vector2 & p1,const Vector2 & p2,const Vector2 & p3) const1373 bool TriangulatorPartition::ScanLineEdge::IsConvex(const Vector2& p1, const Vector2& p2, const Vector2& p3) const {
1374 	real_t tmp;
1375 	tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y);
1376 	if(tmp>0) return 1;
1377 	else return 0;
1378 }
1379 
operator <(const ScanLineEdge & other) const1380 bool TriangulatorPartition::ScanLineEdge::operator < (const ScanLineEdge & other) const {
1381 	if(other.p1.y == other.p2.y) {
1382 		if(p1.y == p2.y) {
1383 			if(p1.y < other.p1.y) return true;
1384 			else return false;
1385 		}
1386 		if(IsConvex(p1,p2,other.p1)) return true;
1387 		else return false;
1388 	} else if(p1.y == p2.y) {
1389 		if(IsConvex(other.p1,other.p2,p1)) return false;
1390 		else return true;
1391 	} else if(p1.y < other.p1.y) {
1392 		if(IsConvex(other.p1,other.p2,p1)) return false;
1393 		else return true;
1394 	} else {
1395 		if(IsConvex(p1,p2,other.p1)) return true;
1396 		else return false;
1397 	}
1398 }
1399 
1400 //triangulates monotone polygon
1401 //O(n) time, O(n) space complexity
TriangulateMonotone(TriangulatorPoly * inPoly,List<TriangulatorPoly> * triangles)1402 int TriangulatorPartition::TriangulateMonotone(TriangulatorPoly *inPoly, List<TriangulatorPoly> *triangles) {
1403 	long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex;
1404 	Vector2 *points;
1405 	long numpoints;
1406 	TriangulatorPoly triangle;
1407 
1408 	numpoints = inPoly->GetNumPoints();
1409 	points = inPoly->GetPoints();
1410 
1411 	//trivial calses
1412 	if(numpoints < 3) return 0;
1413 	if(numpoints == 3) {
1414 		triangles->push_back(*inPoly);
1415 	}
1416 
1417 	topindex = 0; bottomindex=0;
1418 	for(i=1;i<numpoints;i++) {
1419 		if(Below(points[i],points[bottomindex])) bottomindex = i;
1420 		if(Below(points[topindex],points[i])) topindex = i;
1421 	}
1422 
1423 	//check if the poly is really monotone
1424 	i = topindex;
1425 	while(i!=bottomindex) {
1426 		i2 = i+1; if(i2>=numpoints) i2 = 0;
1427 		if(!Below(points[i2],points[i])) return 0;
1428 		i = i2;
1429 	}
1430 	i = bottomindex;
1431 	while(i!=topindex) {
1432 		i2 = i+1; if(i2>=numpoints) i2 = 0;
1433 		if(!Below(points[i],points[i2])) return 0;
1434 		i = i2;
1435 	}
1436 
1437 	char *vertextypes = new char[numpoints];
1438 	long *priority = new long[numpoints];
1439 
1440 	//merge left and right vertex chains
1441 	priority[0] = topindex;
1442 	vertextypes[topindex] = 0;
1443 	leftindex = topindex+1; if(leftindex>=numpoints) leftindex = 0;
1444 	rightindex = topindex-1; if(rightindex<0) rightindex = numpoints-1;
1445 	for(i=1;i<(numpoints-1);i++) {
1446 		if(leftindex==bottomindex) {
1447 			priority[i] = rightindex;
1448 			rightindex--; if(rightindex<0) rightindex = numpoints-1;
1449 			vertextypes[priority[i]] = -1;
1450 		} else if(rightindex==bottomindex) {
1451 			priority[i] = leftindex;
1452 			leftindex++;  if(leftindex>=numpoints) leftindex = 0;
1453 			vertextypes[priority[i]] = 1;
1454 		} else {
1455 			if(Below(points[leftindex],points[rightindex])) {
1456 				priority[i] = rightindex;
1457 				rightindex--; if(rightindex<0) rightindex = numpoints-1;
1458 				vertextypes[priority[i]] = -1;
1459 			} else {
1460 				priority[i] = leftindex;
1461 				leftindex++;  if(leftindex>=numpoints) leftindex = 0;
1462 				vertextypes[priority[i]] = 1;
1463 			}
1464 		}
1465 	}
1466 	priority[i] = bottomindex;
1467 	vertextypes[bottomindex] = 0;
1468 
1469 	long *stack = new long[numpoints];
1470 	long stackptr = 0;
1471 
1472 	stack[0] = priority[0];
1473 	stack[1] = priority[1];
1474 	stackptr = 2;
1475 
1476 	//for each vertex from top to bottom trim as many triangles as possible
1477 	for(i=2;i<(numpoints-1);i++) {
1478 		vindex = priority[i];
1479 		if(vertextypes[vindex]!=vertextypes[stack[stackptr-1]]) {
1480 			for(j=0;j<(stackptr-1);j++) {
1481 				if(vertextypes[vindex]==1) {
1482 					triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
1483 				} else {
1484 					triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
1485 				}
1486 				triangles->push_back(triangle);
1487 			}
1488 			stack[0] = priority[i-1];
1489 			stack[1] = priority[i];
1490 			stackptr = 2;
1491 		} else {
1492 			stackptr--;
1493 			while(stackptr>0) {
1494 				if(vertextypes[vindex]==1) {
1495 					if(IsConvex(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]])) {
1496 						triangle.Triangle(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]]);
1497 						triangles->push_back(triangle);
1498 						stackptr--;
1499 					} else {
1500 						break;
1501 					}
1502 				} else {
1503 					if(IsConvex(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]])) {
1504 						triangle.Triangle(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]]);
1505 						triangles->push_back(triangle);
1506 						stackptr--;
1507 					} else {
1508 						break;
1509 					}
1510 				}
1511 			}
1512 			stackptr++;
1513 			stack[stackptr] = vindex;
1514 			stackptr++;
1515 		}
1516 	}
1517 	vindex = priority[i];
1518 	for(j=0;j<(stackptr-1);j++) {
1519 		if(vertextypes[stack[j+1]]==1) {
1520 			triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]);
1521 		} else {
1522 			triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]);
1523 		}
1524 		triangles->push_back(triangle);
1525 	}
1526 
1527 	delete [] priority;
1528 	delete [] vertextypes;
1529 	delete [] stack;
1530 
1531 	return 1;
1532 }
1533 
Triangulate_MONO(List<TriangulatorPoly> * inpolys,List<TriangulatorPoly> * triangles)1534 int TriangulatorPartition::Triangulate_MONO(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) {
1535 	List<TriangulatorPoly> monotone;
1536 	List<TriangulatorPoly>::Element* iter;
1537 
1538 	if(!MonotonePartition(inpolys,&monotone)) return 0;
1539 	for(iter = monotone.front(); iter;iter=iter->next()) {
1540 		if(!TriangulateMonotone(&(iter->get()),triangles)) return 0;
1541 	}
1542 	return 1;
1543 }
1544 
Triangulate_MONO(TriangulatorPoly * poly,List<TriangulatorPoly> * triangles)1545 int TriangulatorPartition::Triangulate_MONO(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) {
1546 	List<TriangulatorPoly> polys;
1547 	polys.push_back(*poly);
1548 
1549 	return Triangulate_MONO(&polys, triangles);
1550 }
1551