1
2 /*
3 * Copyright 2009 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10
11 ////////////////////////////////////////////////////////////////////////////////
12 // This is an implementation of the triangulation algorithm described by Alain
13 // Fournier and Delfin Montuno, in "Triangulating Simple Polygons and Equivalent
14 // Problems", in the ACM Transactions on Graphics, vol. 3, no. 2, April 1984,
15 // pp. 153-174.
16 //
17 // No new vertices are created in the triangulation: triangles are constructed
18 // only from the points in the original polygon, so there is no possibility for
19 // cracks to develop from finite precision arithmetic.
20 ////////////////////////////////////////////////////////////////////////////////
21
22 // TODO:
23 // - RemoveDegenerateTrapezoids() was added to make the code robust, but it
24 // unfortunately introduces T-vertices. Make it robust without T-vertices.
25 // - It should be easy enough to detect whether the outer contour is right- or
26 // left-handed by looking at the top vertex, which is available in the
27 // pre-sort during trapezoidization. Use this information in angleIsConvex()
28 // to allowed either handedness outer contour. In either case, though, holes
29 // need to have the opposite orientation.
30 // - SkTHeapSort was broken, so I wrote a bubble sort so that I could make other
31 // things work. Use SkQSort() instead.
32 // - The ActiveTrapezoid array does a linear search which is O(n) inefficient.
33 // Use SkSearch to implement O(log n) binary search and insertion sort.
34 // - There is no need to use SkTDArray for everything. Use SkAutoTMalloc for
35 // everything else.
36
37 #include "SkTDArray.h"
38 #include "SkGeometry.h"
39 #include "SkTSort.h"
40
41 // This is used to prevent runaway code bugs, and can probably be removed after
42 // the code has been proven robust.
43 #define kMaxCount 1000
44
45 #define DEBUG
46 #ifdef DEBUG
47 //------------------------------------------------------------------------------
48 // Debugging support
49 //------------------------------------------------------------------------------
50
51 #include <cstdio>
52 #include <stdarg.h>
53
54 static int gDebugLevel = 0; // This enables debug reporting.
55
DebugPrintf(const char * format,...)56 static void DebugPrintf(const char *format, ...) {
57 if (gDebugLevel > 0) {
58 va_list ap;
59 va_start(ap, format);
60 vprintf(format, ap);
61 va_end(ap);
62 }
63 }
64
FailureMessage(const char * format,...)65 static void FailureMessage(const char *format, ...) {
66 if (1) {
67 printf("FAILURE: ");
68 va_list ap;
69 va_start(ap, format);
70 vprintf(format, ap);
71 va_end(ap);
72 }
73 }
74 #else // !DEBUG
DebugPrintf(const char * format,...)75 inline void DebugPrintf(const char *format, ...) {}
FailureMessage(const char * format,...)76 inline void FailureMessage(const char *format, ...) {}
77 #endif // DEBUG
78
79
80 // Forward declaration.
81 class Vertex;
82
83
84 //------------------------------------------------------------------------------
85 // The Trapezoid (actually, up to two of them) is embedded into a Vertex, whose
86 // point() provides the top of the Trapezoid, whereas the bottom, and the left
87 // and right edges, are stored in the Trapezoid. The edges are represented by
88 // their tail point; the head is the successive point modulo the number of
89 // points in the polygon. Only the Y coordinate of the top and bottom are
90 // relevant.
91 //------------------------------------------------------------------------------
92 class Trapezoid {
93 public:
left() const94 const Vertex* left() const { return fLeft; }
right() const95 const Vertex* right() const { return fRight; }
bottom() const96 const Vertex* bottom() const { return fBottom; }
left()97 Vertex* left() { return fLeft; }
right()98 Vertex* right() { return fRight; }
bottom()99 Vertex* bottom() { return fBottom; }
setLeft(Vertex * left)100 void setLeft(Vertex *left) { fLeft = left; }
setRight(Vertex * right)101 void setRight(Vertex *right) { fRight = right; }
setBottom(Vertex * bottom)102 void setBottom(Vertex *bottom) { fBottom = bottom; }
nullify()103 void nullify() { setBottom(NULL); }
104
operator <(Trapezoid & t1)105 bool operator<(Trapezoid &t1) { return compare(t1) < 0; }
operator >(Trapezoid & t1)106 bool operator>(Trapezoid &t1) { return compare(t1) > 0; }
107
108 private:
109 Vertex *fLeft, *fRight, *fBottom;
110
111 // These return a number that is less than, equal to, or greater than zero
112 // depending on whether the trapezoid or point is to the left, on, or to the
113 // right.
114 SkScalar compare(const Trapezoid &t1) const;
115 SkScalar compare(const SkPoint &p) const;
116 };
117
118
119 //------------------------------------------------------------------------------
120 // The ActiveTrapezoids are a sorted list containing the currently active
121 // trapezoids, i.e. those that have the top, left, and right, but still need the
122 // bottom. This could use some optimization, to reduce search time from O(n) to
123 // O(log n).
124 //------------------------------------------------------------------------------
125 class ActiveTrapezoids {
126 public:
ActiveTrapezoids()127 ActiveTrapezoids() { fTrapezoids.setCount(0); }
128
count() const129 size_t count() const { return fTrapezoids.count(); }
130
131 // Select an unused trapezoid from the Vertex vt, initialize it with the
132 // left and right edges, and insert it into the sorted list.
133 bool insertNewTrapezoid(Vertex *vt, Vertex *left, Vertex *right);
134
135 // Remove the specified Trapezoids from the active list.
136 void remove(Trapezoid *t);
137
138 // Determine whether the given point lies within any active trapezoid, and
139 // return a pointer to that Trapezoid.
140 bool withinActiveTrapezoid(const SkPoint &pt, Trapezoid **tp);
141
142 // Find an active trapezoid that contains the given edge.
143 Trapezoid* getTrapezoidWithEdge(const Vertex *edge);
144
145 private:
146 // Insert the specified Trapezoid into the sorted list.
147 void insert(Trapezoid *t);
148
149 // The sorted list of active trapezoids. This is O(n), and would benefit
150 // a 2-3 tree o achieve O(log n).
151 SkTDArray<Trapezoid*> fTrapezoids; // Fournier suggests a 2-3 tree instead.
152 };
153
154
155 //------------------------------------------------------------------------------
156 // The Vertex is used to communicate information between the various phases of
157 // triangulation.
158 //------------------------------------------------------------------------------
159 class Vertex {
160 public:
161 enum VertexType { MONOTONE, CONVEX, CONCAVE };
162
163 Trapezoid fTrap0;
164 Trapezoid fTrap1;
165
point() const166 const SkPoint &point() const { return fPoint; }
setPoint(const SkPoint & point)167 void setPoint(const SkPoint &point) { fPoint = point; }
168
169 // The next and previous vertices around the polygon.
next()170 Vertex *next() { return fNext; }
prev()171 Vertex *prev() { return fPrev; }
next() const172 const Vertex *next() const { return fNext; }
prev() const173 const Vertex *prev() const { return fPrev; }
setNext(Vertex * next)174 void setNext(Vertex *next) { fNext = next; }
setPrev(Vertex * prev)175 void setPrev(Vertex *prev) { fPrev = prev; }
176
setDone(bool done)177 void setDone(bool done) { fDone = done; }
done() const178 bool done() const { return fDone; }
179
180 // Trapezoid accessors return non-null for any complete trapezoids.
trapezoids(Trapezoid ** trap0,Trapezoid ** trap1)181 void trapezoids(Trapezoid **trap0, Trapezoid **trap1) {
182 *trap0 = (fTrap0.bottom() != NULL) ? &fTrap0 : NULL;
183 *trap1 = (fTrap1.bottom() != NULL) ? &fTrap1 : NULL;
184 }
185
186 // Eliminate a trapezoid.
nullifyTrapezoid()187 void nullifyTrapezoid() {
188 if (fTrap1.bottom() != NULL) {
189 DebugPrintf("Unexpected non-null second trapezoid.\n");
190 fTrap1.nullify();
191 return;
192 }
193 fTrap0.nullify();
194 }
195
196 // Determine whether the edge specified by this Vertex shares the given top
197 // and bottom.
198 bool shareEdge(Vertex *top, Vertex *bottom);
199
200 // Determines whether the angle specified by { prev, this, next } is convex.
201 // Note that collinear is considered to be convex.
202 bool angleIsConvex();
203
204 // Remove this Vertex from the { prev, next } linked list.
delink()205 void delink() {
206 Vertex *p = prev(),
207 *n = next();
208 p->setNext(n);
209 n->setPrev(p);
210 }
211
212 // Return a number that is less than, equal to, or greater than zero
213 // depending on whether the point is to the left, on, or to the right of the
214 // edge that has this Vertex as a base.
215 SkScalar compare(const SkPoint &pt) const;
216
217 // Classify the vertex, and return its sorted edges.
218 VertexType classify(Vertex **e0, Vertex **e1);
219
220 // This helps determine unimonotonicity.
221 Vertex *diagonal();
222
223 private:
224 SkPoint fPoint;
225 Vertex *fNext;
226 Vertex *fPrev;
227 bool fDone;
228 };
229
230
angleIsConvex()231 bool Vertex::angleIsConvex() {
232 SkPoint vPrev = prev()->point() - point(),
233 vNext = next()->point() - point();
234 // TODO(turk): There might be overflow in fixed-point.
235 return SkPoint::CrossProduct(vNext, vPrev) >= 0;
236 }
237
238
shareEdge(Vertex * top,Vertex * bottom)239 bool Vertex::shareEdge(Vertex *top, Vertex *bottom) {
240 return (((this == top) && (this->next() == bottom)) ||
241 ((this == bottom) && (this->next() == top)));
242 }
243
244
compare(const SkPoint & pt) const245 SkScalar Vertex::compare(const SkPoint &pt) const {
246 SkPoint ve = next()->point() - point(),
247 vp = pt - point();
248 SkScalar d;
249 if (ve.fY == 0) {
250 // Return twice the distance to the center of the horizontal edge.
251 d = ve.fX + pt.fX - next()->point().fX;
252 } else {
253 // Return the distance to the edge, scaled by the edge length.
254 d = SkPoint::CrossProduct(ve, vp);
255 if (ve.fY > 0) d = -d;
256 }
257 return d;
258 }
259
260
compare(const SkPoint & pt) const261 SkScalar Trapezoid::compare(const SkPoint &pt) const {
262 SkScalar d = left()->compare(pt);
263 if (d <= 0)
264 return d; // Left of the left edge.
265 d = right()->compare(pt);
266 if (d >= 0)
267 return d; // Right of the right edge.
268 return 0; // Somewhere between the left and the right edges.
269 }
270
271
272
compare(const Trapezoid & t1) const273 SkScalar Trapezoid::compare(const Trapezoid &t1) const {
274 #if 1
275 SkScalar d = left()->compare(t1.left()->point());
276 if (d == 0)
277 d = right()->compare(t1.right()->point());
278 return d;
279 #else
280 SkScalar dl = left()->compare( t1.left()->point()),
281 dr = right()->compare(t1.right()->point());
282 if (dl < 0 && dr < 0)
283 return dr;
284 if (dl > 0 && dr > 0)
285 return dl;
286 return 0;
287 #endif
288 }
289
290
getTrapezoidWithEdge(const Vertex * edge)291 Trapezoid* ActiveTrapezoids::getTrapezoidWithEdge(const Vertex *edge) {
292 DebugPrintf("Entering getTrapezoidWithEdge(): looking through %d\n",
293 fTrapezoids.count());
294 DebugPrintf("trying to find %p: ", edge);
295 Trapezoid **tp;
296 for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) {
297 SkASSERT(tp != NULL);
298 SkASSERT(*tp != NULL);
299 DebugPrintf("%p and %p, ", (**tp).left(), (**tp).right());
300 if ((**tp).left() == edge || (**tp).right() == edge) {
301 DebugPrintf("\ngetTrapezoidWithEdge found the trapezoid\n");
302 return *tp;
303 }
304 }
305 DebugPrintf("getTrapezoidWithEdge found no trapezoid\n");
306 return NULL;
307 }
308
309
insertNewTrapezoid(Vertex * vt,Vertex * left,Vertex * right)310 bool ActiveTrapezoids::insertNewTrapezoid(Vertex *vt,
311 Vertex *left,
312 Vertex *right) {
313 DebugPrintf("Inserting a trapezoid...");
314 if (vt->fTrap0.left() == NULL && vt->fTrap0.right() == NULL) {
315 vt->fTrap0.setLeft(left);
316 vt->fTrap0.setRight(right);
317 insert(&vt->fTrap0);
318 } else if (vt->fTrap1.left() == NULL && vt->fTrap1.right() == NULL) {
319 DebugPrintf("a second one...");
320 vt->fTrap1.setLeft(left);
321 vt->fTrap1.setRight(right);
322 if (vt->fTrap1 < vt->fTrap0) { // Keep trapezoids sorted.
323 remove(&vt->fTrap0);
324 Trapezoid t = vt->fTrap0;
325 vt->fTrap0 = vt->fTrap1;
326 vt->fTrap1 = t;
327 insert(&vt->fTrap0);
328 }
329 insert(&vt->fTrap1);
330 } else {
331 FailureMessage("More than 2 trapezoids requested for a vertex\n");
332 return false;
333 }
334 DebugPrintf(" done. %d incomplete trapezoids\n", fTrapezoids.count());
335 return true;
336 }
337
338
insert(Trapezoid * t)339 void ActiveTrapezoids::insert(Trapezoid *t) {
340 Trapezoid **tp;
341 for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp)
342 if (**tp > *t)
343 break;
344 fTrapezoids.insert(tp - fTrapezoids.begin(), 1, &t);
345 // SHOULD VERIFY THAT ALL TRAPEZOIDS ARE PROPERLY SORTED
346 }
347
348
remove(Trapezoid * t)349 void ActiveTrapezoids::remove(Trapezoid *t) {
350 DebugPrintf("Removing a trapezoid...");
351 for (Trapezoid **tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) {
352 if (*tp == t) {
353 fTrapezoids.remove(tp - fTrapezoids.begin());
354 DebugPrintf(" done.\n");
355 return;
356 }
357 }
358 DebugPrintf(" Arghh! Panic!\n");
359 SkASSERT(t == 0); // Cannot find t in active trapezoid list.
360 }
361
362
withinActiveTrapezoid(const SkPoint & pt,Trapezoid ** trap)363 bool ActiveTrapezoids::withinActiveTrapezoid(const SkPoint &pt,
364 Trapezoid **trap) {
365 DebugPrintf("Entering withinActiveTrapezoid()\n");
366 // This is where a good search data structure would be helpful.
367 Trapezoid **t;
368 for (t = fTrapezoids.begin(); t < fTrapezoids.end(); ++t) {
369 if ((**t).left()->compare(pt) <= 0) {
370 // The point is to the left of the left edge of this trapezoid.
371 DebugPrintf("withinActiveTrapezoid: Before a trapezoid\n");
372 *trap = *t; // Return the place where a new trapezoid would go.
373 // We have a bug with the sorting -- look through everything.
374 continue;
375 // return false; // Outside all trapezoids, since they are sorted.
376 }
377 // The point is to the right of the left edge of this trapezoid.
378
379 if ((**t).right()->compare(pt) < 0) {
380 // The point is to the left of the right edge.
381 DebugPrintf("withinActiveTrapezoid: Within an Active Trapezoid\n");
382 *trap = *t;
383 return true;
384 }
385 }
386
387 // The point is to the right of all trapezoids.
388 DebugPrintf("withinActiveTrapezoid: After all trapezoids\n");
389 *trap = NULL;
390 return false;
391 }
392
393
diagonal()394 Vertex* Vertex::diagonal() {
395 Vertex *diag = NULL;
396 if (fTrap0.bottom() != NULL) {
397 if (!fTrap0.left() ->shareEdge(this, fTrap0.bottom()) &&
398 !fTrap0.right()->shareEdge(this, fTrap0.bottom())
399 ) {
400 diag = fTrap0.bottom();
401 fTrap0 = fTrap1;
402 fTrap1.nullify();
403 } else if (fTrap1.bottom() != NULL &&
404 !fTrap1.left() ->shareEdge(this, fTrap1.bottom()) &&
405 !fTrap1.right()->shareEdge(this, fTrap1.bottom())
406 ) {
407 diag = fTrap1.bottom();
408 fTrap1.nullify();
409 }
410 }
411 return diag;
412 }
413
414
415 // We use this to sort the edges vertically for a scan-conversion type of
416 // operation.
417 class VertexPtr {
418 public:
419 Vertex *vt;
420 };
421
422
operator <(VertexPtr & v0,VertexPtr & v1)423 bool operator<(VertexPtr &v0, VertexPtr &v1) {
424 // DebugPrintf("< %p %p\n", &v0, &v1);
425 if (v0.vt->point().fY < v1.vt->point().fY) return true;
426 if (v0.vt->point().fY > v1.vt->point().fY) return false;
427 if (v0.vt->point().fX < v1.vt->point().fX) return true;
428 else return false;
429 }
430
431
operator >(VertexPtr & v0,VertexPtr & v1)432 bool operator>(VertexPtr &v0, VertexPtr &v1) {
433 // DebugPrintf("> %p %p\n", &v0, &v1);
434 if (v0.vt->point().fY > v1.vt->point().fY) return true;
435 if (v0.vt->point().fY < v1.vt->point().fY) return false;
436 if (v0.vt->point().fX > v1.vt->point().fX) return true;
437 else return false;
438 }
439
440
SetVertexPoints(size_t numPts,const SkPoint * pt,Vertex * vt)441 static void SetVertexPoints(size_t numPts, const SkPoint *pt, Vertex *vt) {
442 for (; numPts-- != 0; ++pt, ++vt)
443 vt->setPoint(*pt);
444 }
445
446
InitializeVertexTopology(size_t numPts,Vertex * v1)447 static void InitializeVertexTopology(size_t numPts, Vertex *v1) {
448 Vertex *v0 = v1 + numPts - 1, *v_1 = v0 - 1;
449 for (; numPts-- != 0; v_1 = v0, v0 = v1++) {
450 v0->setPrev(v_1);
451 v0->setNext(v1);
452 }
453 }
454
classify(Vertex ** e0,Vertex ** e1)455 Vertex::VertexType Vertex::classify(Vertex **e0, Vertex **e1) {
456 VertexType type;
457 SkPoint vPrev, vNext;
458 vPrev.fX = prev()->point().fX - point().fX;
459 vPrev.fY = prev()->point().fY - point().fY;
460 vNext.fX = next()->point().fX - point().fX;
461 vNext.fY = next()->point().fY - point().fY;
462
463 // This can probably be simplified, but there are enough potential bugs,
464 // we will leave it expanded until all cases are tested appropriately.
465 if (vPrev.fY < 0) {
466 if (vNext.fY > 0) {
467 // Prev comes from above, Next goes below.
468 type = MONOTONE;
469 *e0 = prev();
470 *e1 = this;
471 } else if (vNext.fY < 0) {
472 // The are both above: sort so that e0 is on the left.
473 type = CONCAVE;
474 if (SkPoint::CrossProduct(vPrev, vNext) <= 0) {
475 *e0 = this;
476 *e1 = prev();
477 } else {
478 *e0 = prev();
479 *e1 = this;
480 }
481 } else {
482 DebugPrintf("### py < 0, ny = 0\n");
483 if (vNext.fX < 0) {
484 type = CONCAVE;
485 *e0 = this; // flat to the left
486 *e1 = prev(); // concave on the right
487 } else {
488 type = CONCAVE;
489 *e0 = prev(); // concave to the left
490 *e1 = this; // flat to the right
491 }
492 }
493 } else if (vPrev.fY > 0) {
494 if (vNext.fY < 0) {
495 // Next comes from above, Prev goes below.
496 type = MONOTONE;
497 *e0 = this;
498 *e1 = prev();
499 } else if (vNext.fY > 0) {
500 // They are both below: sort so that e0 is on the left.
501 type = CONVEX;
502 if (SkPoint::CrossProduct(vPrev, vNext) <= 0) {
503 *e0 = prev();
504 *e1 = this;
505 } else {
506 *e0 = this;
507 *e1 = prev();
508 }
509 } else {
510 DebugPrintf("### py > 0, ny = 0\n");
511 if (vNext.fX < 0) {
512 type = MONOTONE;
513 *e0 = this; // flat to the left
514 *e1 = prev(); // convex on the right - try monotone first
515 } else {
516 type = MONOTONE;
517 *e0 = prev(); // convex to the left - try monotone first
518 *e1 = this; // flat to the right
519 }
520 }
521 } else { // vPrev.fY == 0
522 if (vNext.fY < 0) {
523 DebugPrintf("### py = 0, ny < 0\n");
524 if (vPrev.fX < 0) {
525 type = CONCAVE;
526 *e0 = prev(); // flat to the left
527 *e1 = this; // concave on the right
528 } else {
529 type = CONCAVE;
530 *e0 = this; // concave on the left - defer
531 *e1 = prev(); // flat to the right
532 }
533 } else if (vNext.fY > 0) {
534 DebugPrintf("### py = 0, ny > 0\n");
535 if (vPrev.fX < 0) {
536 type = MONOTONE;
537 *e0 = prev(); // flat to the left
538 *e1 = this; // convex on the right - try monotone first
539 } else {
540 type = MONOTONE;
541 *e0 = this; // convex to the left - try monotone first
542 *e1 = prev(); // flat to the right
543 }
544 } else {
545 DebugPrintf("### py = 0, ny = 0\n");
546 // First we try concave, then monotone, then convex.
547 if (vPrev.fX <= vNext.fX) {
548 type = CONCAVE;
549 *e0 = prev(); // flat to the left
550 *e1 = this; // flat to the right
551 } else {
552 type = CONCAVE;
553 *e0 = this; // flat to the left
554 *e1 = prev(); // flat to the right
555 }
556 }
557 }
558 return type;
559 }
560
561
562 #ifdef DEBUG
GetVertexTypeString(Vertex::VertexType type)563 static const char* GetVertexTypeString(Vertex::VertexType type) {
564 const char *typeStr = NULL;
565 switch (type) {
566 case Vertex::MONOTONE:
567 typeStr = "MONOTONE";
568 break;
569 case Vertex::CONCAVE:
570 typeStr = "CONCAVE";
571 break;
572 case Vertex::CONVEX:
573 typeStr = "CONVEX";
574 break;
575 }
576 return typeStr;
577 }
578
579
PrintVertices(size_t numPts,Vertex * vt)580 static void PrintVertices(size_t numPts, Vertex *vt) {
581 DebugPrintf("\nVertices:\n");
582 for (size_t i = 0; i < numPts; i++) {
583 Vertex *e0, *e1;
584 Vertex::VertexType type = vt[i].classify(&e0, &e1);
585 DebugPrintf("%2d: (%.7g, %.7g), prev(%d), next(%d), "
586 "type(%s), left(%d), right(%d)",
587 i, vt[i].point().fX, vt[i].point().fY,
588 vt[i].prev() - vt, vt[i].next() - vt,
589 GetVertexTypeString(type), e0 - vt, e1 - vt);
590 Trapezoid *trap[2];
591 vt[i].trapezoids(trap, trap+1);
592 for (int j = 0; j < 2; ++j) {
593 if (trap[j] != NULL) {
594 DebugPrintf(", trap(L=%d, R=%d, B=%d)",
595 trap[j]->left() - vt,
596 trap[j]->right() - vt,
597 trap[j]->bottom() - vt);
598 }
599 }
600 DebugPrintf("\n");
601 }
602 }
603
604
PrintVertexPtrs(size_t numPts,VertexPtr * vp,Vertex * vtBase)605 static void PrintVertexPtrs(size_t numPts, VertexPtr *vp, Vertex *vtBase) {
606 DebugPrintf("\nSorted Vertices:\n");
607 for (size_t i = 0; i < numPts; i++) {
608 Vertex *e0, *e1;
609 Vertex *vt = vp[i].vt;
610 Vertex::VertexType type = vt->classify(&e0, &e1);
611 DebugPrintf("%2d: %2d: (%.7g, %.7g), prev(%d), next(%d), "
612 "type(%s), left(%d), right(%d)",
613 i, vt - vtBase, vt->point().fX, vt->point().fY,
614 vt->prev() - vtBase, vt->next() - vtBase,
615 GetVertexTypeString(type), e0 - vtBase, e1 - vtBase);
616 Trapezoid *trap[2];
617 vt->trapezoids(trap, trap+1);
618 for (int j = 0; j < 2; ++j) {
619 if (trap[j] != NULL) {
620 DebugPrintf(", trap(L=%d, R=%d, B=%d)",
621 trap[j]->left() - vtBase,
622 trap[j]->right() - vtBase,
623 trap[j]->bottom() - vtBase);
624 }
625 }
626 DebugPrintf("\n");
627 }
628 }
629 #else // !DEBUG
PrintVertices(size_t numPts,Vertex * vt)630 inline void PrintVertices(size_t numPts, Vertex *vt) {}
PrintVertexPtrs(size_t numPts,VertexPtr * vp,Vertex * vtBase)631 inline void PrintVertexPtrs(size_t numPts, VertexPtr *vp, Vertex *vtBase) {}
632 #endif // !DEBUG
633
634
635 // SkTHeapSort is broken, so we use a bubble sort in the meantime.
636 template <typename T>
BubbleSort(T * array,size_t count)637 void BubbleSort(T *array, size_t count) {
638 bool sorted;
639 size_t count_1 = count - 1;
640 do {
641 sorted = true;
642 for (size_t i = 0; i < count_1; ++i) {
643 if (array[i + 1] < array[i]) {
644 T t = array[i];
645 array[i] = array[i + 1];
646 array[i + 1] = t;
647 sorted = false;
648 }
649 }
650 } while (!sorted);
651 }
652
653
654 // Remove zero-height trapezoids.
RemoveDegenerateTrapezoids(size_t numVt,Vertex * vt)655 static void RemoveDegenerateTrapezoids(size_t numVt, Vertex *vt) {
656 for (; numVt-- != 0; vt++) {
657 Trapezoid *traps[2];
658 vt->trapezoids(traps, traps+1);
659 if (traps[1] != NULL &&
660 vt->point().fY >= traps[1]->bottom()->point().fY) {
661 traps[1]->nullify();
662 traps[1] = NULL;
663 }
664 if (traps[0] != NULL &&
665 vt->point().fY >= traps[0]->bottom()->point().fY) {
666 if (traps[1] != NULL) {
667 *traps[0] = *traps[1];
668 traps[1]->nullify();
669 } else {
670 traps[0]->nullify();
671 }
672 }
673 }
674 }
675
676
677 // Enhance the polygon with trapezoids.
ConvertPointsToVertices(size_t numPts,const SkPoint * pts,Vertex * vta)678 bool ConvertPointsToVertices(size_t numPts, const SkPoint *pts, Vertex *vta) {
679 DebugPrintf("ConvertPointsToVertices()\n");
680
681 // Clear everything.
682 DebugPrintf("Zeroing vertices\n");
683 sk_bzero(vta, numPts * sizeof(*vta));
684
685 // Initialize vertices.
686 DebugPrintf("Initializing vertices\n");
687 SetVertexPoints(numPts, pts, vta);
688 InitializeVertexTopology(numPts, vta);
689
690 PrintVertices(numPts, vta);
691
692 SkTDArray<VertexPtr> vtptr;
693 vtptr.setCount(numPts);
694 for (int i = numPts; i-- != 0;)
695 vtptr[i].vt = vta + i;
696 PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
697 DebugPrintf("Sorting vertrap ptr array [%d] %p %p\n", vtptr.count(),
698 &vtptr[0], &vtptr[vtptr.count() - 1]
699 );
700 // SkTHeapSort(vtptr.begin(), vtptr.count());
701 BubbleSort(vtptr.begin(), vtptr.count());
702 DebugPrintf("Done sorting\n");
703 PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
704
705 DebugPrintf("Traversing sorted vertrap ptrs\n");
706 ActiveTrapezoids incompleteTrapezoids;
707 for (VertexPtr *vtpp = vtptr.begin(); vtpp < vtptr.end(); ++vtpp) {
708 DebugPrintf("%d: sorted vertrap %d\n",
709 vtpp - vtptr.begin(), vtpp->vt - vta);
710 Vertex *vt = vtpp->vt;
711 Vertex *e0, *e1;
712 Trapezoid *t;
713 switch (vt->classify(&e0, &e1)) {
714 case Vertex::MONOTONE:
715 monotone:
716 DebugPrintf("MONOTONE %d %d\n", e0 - vta, e1 - vta);
717 // We should find one edge.
718 t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
719 if (t == NULL) { // One of the edges is flat.
720 DebugPrintf("Monotone: cannot find a trapezoid with e0: "
721 "trying convex\n");
722 goto convex;
723 }
724 t->setBottom(vt); // This trapezoid is now complete.
725 incompleteTrapezoids.remove(t);
726
727 if (e0 == t->left()) // Replace the left edge.
728 incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
729 else // Replace the right edge.
730 incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e1);
731 break;
732
733 case Vertex::CONVEX: // Start of a new trapezoid.
734 convex:
735 // We don't expect to find any edges.
736 DebugPrintf("CONVEX %d %d\n", e0 - vta, e1 - vta);
737 if (incompleteTrapezoids.withinActiveTrapezoid(
738 vt->point(), &t)) {
739 // Complete trapezoid.
740 SkASSERT(t != NULL);
741 t->setBottom(vt);
742 incompleteTrapezoids.remove(t);
743 // Introduce two new trapezoids.
744 incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e0);
745 incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
746 } else {
747 // Insert a new trapezoid.
748 incompleteTrapezoids.insertNewTrapezoid(vt, e0, e1);
749 }
750 break;
751
752 case Vertex::CONCAVE: // End of a trapezoid.
753 DebugPrintf("CONCAVE %d %d\n", e0 - vta, e1 - vta);
754 // We should find two edges.
755 t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
756 if (t == NULL) {
757 DebugPrintf("Concave: cannot find a trapezoid with e0: "
758 " trying monotone\n");
759 goto monotone;
760 }
761 SkASSERT(t != NULL);
762 if (e0 == t->left() && e1 == t->right()) {
763 DebugPrintf(
764 "Concave edges belong to the same trapezoid.\n");
765 // Edges belong to the same trapezoid.
766 // Complete trapezoid & transfer it from the active list.
767 t->setBottom(vt);
768 incompleteTrapezoids.remove(t);
769 } else { // Edges belong to different trapezoids
770 DebugPrintf(
771 "Concave edges belong to different trapezoids.\n");
772 // Complete left and right trapezoids.
773 Trapezoid *s = incompleteTrapezoids.getTrapezoidWithEdge(
774 e1);
775 if (s == NULL) {
776 DebugPrintf(
777 "Concave: cannot find a trapezoid with e1: "
778 " trying monotone\n");
779 goto monotone;
780 }
781 t->setBottom(vt);
782 s->setBottom(vt);
783 incompleteTrapezoids.remove(t);
784 incompleteTrapezoids.remove(s);
785
786 // Merge the two trapezoids into one below this vertex.
787 incompleteTrapezoids.insertNewTrapezoid(vt, t->left(),
788 s->right());
789 }
790 break;
791 }
792 }
793
794 RemoveDegenerateTrapezoids(numPts, vta);
795
796 DebugPrintf("Done making trapezoids\n");
797 PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
798
799 size_t k = incompleteTrapezoids.count();
800 if (k > 0) {
801 FailureMessage("%d incomplete trapezoids\n", k);
802 return false;
803 }
804 return true;
805 }
806
807
appendTriangleAtVertex(const Vertex * v,SkTDArray<SkPoint> * triangles)808 inline void appendTriangleAtVertex(const Vertex *v,
809 SkTDArray<SkPoint> *triangles) {
810 SkPoint *p = triangles->append(3);
811 p[0] = v->prev()->point();
812 p[1] = v->point();
813 p[2] = v->next()->point();
814 DebugPrintf(
815 "Appending triangle: { (%.7g, %.7g), (%.7g, %.7g), (%.7g, %.7g) }\n",
816 p[0].fX, p[0].fY,
817 p[1].fX, p[1].fY,
818 p[2].fX, p[2].fY
819 );
820 }
821
822
CountVertices(const Vertex * first,const Vertex * last)823 static size_t CountVertices(const Vertex *first, const Vertex *last) {
824 DebugPrintf("Counting vertices: ");
825 size_t count = 1;
826 for (; first != last; first = first->next()) {
827 ++count;
828 SkASSERT(count <= kMaxCount);
829 if (count >= kMaxCount) {
830 FailureMessage("Vertices do not seem to be in a linked chain\n");
831 break;
832 }
833 }
834 return count;
835 }
836
837
operator <(const SkPoint & p0,const SkPoint & p1)838 bool operator<(const SkPoint &p0, const SkPoint &p1) {
839 if (p0.fY < p1.fY) return true;
840 if (p0.fY > p1.fY) return false;
841 if (p0.fX < p1.fX) return true;
842 else return false;
843 }
844
845
PrintLinkedVertices(size_t n,Vertex * vertices)846 static void PrintLinkedVertices(size_t n, Vertex *vertices) {
847 DebugPrintf("%d vertices:\n", n);
848 Vertex *v;
849 for (v = vertices; n-- != 0; v = v->next())
850 DebugPrintf(" (%.7g, %.7g)\n", v->point().fX, v->point().fY);
851 if (v != vertices)
852 FailureMessage("Vertices are not in a linked chain\n");
853 }
854
855
856 // Triangulate an unimonotone chain.
TriangulateMonotone(Vertex * first,Vertex * last,SkTDArray<SkPoint> * triangles)857 bool TriangulateMonotone(Vertex *first, Vertex *last,
858 SkTDArray<SkPoint> *triangles) {
859 DebugPrintf("TriangulateMonotone()\n");
860
861 size_t numVertices = CountVertices(first, last);
862 if (numVertices == kMaxCount) {
863 FailureMessage("Way too many vertices: %d:\n", numVertices);
864 PrintLinkedVertices(numVertices, first);
865 return false;
866 }
867
868 Vertex *start = first;
869 // First find the point with the smallest Y.
870 DebugPrintf("TriangulateMonotone: finding bottom\n");
871 int count = kMaxCount; // Maximum number of vertices.
872 for (Vertex *v = first->next(); v != first && count-- > 0; v = v->next())
873 if (v->point() < start->point())
874 start = v;
875 if (count <= 0) {
876 FailureMessage("TriangulateMonotone() was given disjoint chain\n");
877 return false; // Something went wrong.
878 }
879
880 // Start at the far end of the long edge.
881 if (start->prev()->point() < start->next()->point())
882 start = start->next();
883
884 Vertex *current = start->next();
885 while (numVertices >= 3) {
886 if (current->angleIsConvex()) {
887 DebugPrintf("Angle %p is convex\n", current);
888 // Print the vertices
889 PrintLinkedVertices(numVertices, start);
890
891 appendTriangleAtVertex(current, triangles);
892 if (triangles->count() > kMaxCount * 3) {
893 FailureMessage("An extraordinarily large number of triangles "
894 "were generated\n");
895 return false;
896 }
897 Vertex *save = current->prev();
898 current->delink();
899 current = (save == start || save == start->prev()) ? start->next()
900 : save;
901 --numVertices;
902 } else {
903 if (numVertices == 3) {
904 FailureMessage("Convexity error in TriangulateMonotone()\n");
905 appendTriangleAtVertex(current, triangles);
906 return false;
907 }
908 DebugPrintf("Angle %p is concave\n", current);
909 current = current->next();
910 }
911 }
912 return true;
913 }
914
915
916 // Split the polygon into sets of unimonotone chains, and eventually call
917 // TriangulateMonotone() to convert them into triangles.
Triangulate(Vertex * first,Vertex * last,SkTDArray<SkPoint> * triangles)918 bool Triangulate(Vertex *first, Vertex *last, SkTDArray<SkPoint> *triangles) {
919 DebugPrintf("Triangulate()\n");
920 Vertex *currentVertex = first;
921 while (!currentVertex->done()) {
922 currentVertex->setDone(true);
923 Vertex *bottomVertex = currentVertex->diagonal();
924 if (bottomVertex != NULL) {
925 Vertex *saveNext = currentVertex->next();
926 Vertex *savePrev = bottomVertex->prev();
927 currentVertex->setNext(bottomVertex);
928 bottomVertex->setPrev(currentVertex);
929 currentVertex->nullifyTrapezoid();
930 bool success = Triangulate(bottomVertex, currentVertex, triangles);
931 currentVertex->setDone(false);
932 bottomVertex->setDone(false);
933 currentVertex->setNext(saveNext);
934 bottomVertex->setPrev(savePrev);
935 bottomVertex->setNext(currentVertex);
936 currentVertex->setPrev(bottomVertex);
937 return Triangulate(currentVertex, bottomVertex, triangles)
938 && success;
939 } else {
940 currentVertex = currentVertex->next();
941 }
942 }
943 return TriangulateMonotone(first, last, triangles);
944 }
945
946
SkConcaveToTriangles(size_t numPts,const SkPoint pts[],SkTDArray<SkPoint> * triangles)947 bool SkConcaveToTriangles(size_t numPts,
948 const SkPoint pts[],
949 SkTDArray<SkPoint> *triangles) {
950 DebugPrintf("SkConcaveToTriangles()\n");
951
952 SkTDArray<Vertex> vertices;
953 vertices.setCount(numPts);
954 if (!ConvertPointsToVertices(numPts, pts, vertices.begin()))
955 return false;
956
957 triangles->setReserve(numPts);
958 triangles->setCount(0);
959 return Triangulate(vertices.begin(), vertices.end() - 1, triangles);
960 }
961