• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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