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