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 :
56 0 : static void DebugPrintf(const char *format, ...) {
57 0 : if (gDebugLevel > 0) {
58 : va_list ap;
59 0 : va_start(ap, format);
60 0 : vprintf(format, ap);
61 0 : va_end(ap);
62 : }
63 0 : }
64 :
65 0 : static void FailureMessage(const char *format, ...) {
66 : if (1) {
67 0 : printf("FAILURE: ");
68 : va_list ap;
69 0 : va_start(ap, format);
70 0 : vprintf(format, ap);
71 0 : va_end(ap);
72 : }
73 0 : }
74 : #else // !DEBUG
75 : inline void DebugPrintf(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:
94 0 : const Vertex* left() const { return fLeft; }
95 0 : const Vertex* right() const { return fRight; }
96 : const Vertex* bottom() const { return fBottom; }
97 0 : Vertex* left() { return fLeft; }
98 0 : Vertex* right() { return fRight; }
99 0 : Vertex* bottom() { return fBottom; }
100 0 : void setLeft(Vertex *left) { fLeft = left; }
101 0 : void setRight(Vertex *right) { fRight = right; }
102 0 : void setBottom(Vertex *bottom) { fBottom = bottom; }
103 0 : void nullify() { setBottom(NULL); }
104 :
105 0 : bool operator<(Trapezoid &t1) { return compare(t1) < 0; }
106 0 : 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 0 : class ActiveTrapezoids {
126 : public:
127 0 : ActiveTrapezoids() { fTrapezoids.setCount(0); }
128 :
129 0 : 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 :
166 0 : const SkPoint &point() const { return fPoint; }
167 0 : void setPoint(const SkPoint &point) { fPoint = point; }
168 :
169 : // The next and previous vertices around the polygon.
170 0 : Vertex *next() { return fNext; }
171 0 : Vertex *prev() { return fPrev; }
172 0 : const Vertex *next() const { return fNext; }
173 0 : const Vertex *prev() const { return fPrev; }
174 0 : void setNext(Vertex *next) { fNext = next; }
175 0 : void setPrev(Vertex *prev) { fPrev = prev; }
176 :
177 0 : void setDone(bool done) { fDone = done; }
178 0 : bool done() const { return fDone; }
179 :
180 : // Trapezoid accessors return non-null for any complete trapezoids.
181 0 : void trapezoids(Trapezoid **trap0, Trapezoid **trap1) {
182 0 : *trap0 = (fTrap0.bottom() != NULL) ? &fTrap0 : NULL;
183 0 : *trap1 = (fTrap1.bottom() != NULL) ? &fTrap1 : NULL;
184 0 : }
185 :
186 : // Eliminate a trapezoid.
187 0 : void nullifyTrapezoid() {
188 0 : if (fTrap1.bottom() != NULL) {
189 0 : DebugPrintf("Unexpected non-null second trapezoid.\n");
190 0 : fTrap1.nullify();
191 0 : return;
192 : }
193 0 : 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.
205 0 : void delink() {
206 0 : Vertex *p = prev(),
207 0 : *n = next();
208 0 : p->setNext(n);
209 0 : n->setPrev(p);
210 0 : }
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 :
231 0 : bool Vertex::angleIsConvex() {
232 0 : SkPoint vPrev = prev()->point() - point(),
233 0 : vNext = next()->point() - point();
234 : // TODO(turk): There might be overflow in fixed-point.
235 0 : return SkPoint::CrossProduct(vNext, vPrev) >= 0;
236 : }
237 :
238 :
239 0 : bool Vertex::shareEdge(Vertex *top, Vertex *bottom) {
240 0 : return (((this == top) && (this->next() == bottom)) ||
241 0 : ((this == bottom) && (this->next() == top)));
242 : }
243 :
244 :
245 0 : SkScalar Vertex::compare(const SkPoint &pt) const {
246 0 : SkPoint ve = next()->point() - point(),
247 0 : vp = pt - point();
248 : SkScalar d;
249 0 : if (ve.fY == 0) {
250 : // Return twice the distance to the center of the horizontal edge.
251 0 : d = ve.fX + pt.fX - next()->point().fX;
252 : } else {
253 : // Return the distance to the edge, scaled by the edge length.
254 0 : d = SkPoint::CrossProduct(ve, vp);
255 0 : if (ve.fY > 0) d = -d;
256 : }
257 0 : return d;
258 : }
259 :
260 :
261 0 : SkScalar Trapezoid::compare(const SkPoint &pt) const {
262 0 : SkScalar d = left()->compare(pt);
263 0 : if (d <= 0)
264 0 : return d; // Left of the left edge.
265 0 : d = right()->compare(pt);
266 0 : if (d >= 0)
267 0 : return d; // Right of the right edge.
268 0 : return 0; // Somewhere between the left and the right edges.
269 : }
270 :
271 :
272 :
273 0 : SkScalar Trapezoid::compare(const Trapezoid &t1) const {
274 : #if 1
275 0 : SkScalar d = left()->compare(t1.left()->point());
276 0 : if (d == 0)
277 0 : d = right()->compare(t1.right()->point());
278 0 : 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 :
291 0 : Trapezoid* ActiveTrapezoids::getTrapezoidWithEdge(const Vertex *edge) {
292 : DebugPrintf("Entering getTrapezoidWithEdge(): looking through %d\n",
293 0 : fTrapezoids.count());
294 0 : DebugPrintf("trying to find %p: ", edge);
295 : Trapezoid **tp;
296 0 : for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) {
297 0 : SkASSERT(tp != NULL);
298 0 : SkASSERT(*tp != NULL);
299 0 : DebugPrintf("%p and %p, ", (**tp).left(), (**tp).right());
300 0 : if ((**tp).left() == edge || (**tp).right() == edge) {
301 0 : DebugPrintf("\ngetTrapezoidWithEdge found the trapezoid\n");
302 0 : return *tp;
303 : }
304 : }
305 0 : DebugPrintf("getTrapezoidWithEdge found no trapezoid\n");
306 0 : return NULL;
307 : }
308 :
309 :
310 0 : bool ActiveTrapezoids::insertNewTrapezoid(Vertex *vt,
311 : Vertex *left,
312 : Vertex *right) {
313 0 : DebugPrintf("Inserting a trapezoid...");
314 0 : if (vt->fTrap0.left() == NULL && vt->fTrap0.right() == NULL) {
315 0 : vt->fTrap0.setLeft(left);
316 0 : vt->fTrap0.setRight(right);
317 0 : insert(&vt->fTrap0);
318 0 : } else if (vt->fTrap1.left() == NULL && vt->fTrap1.right() == NULL) {
319 0 : DebugPrintf("a second one...");
320 0 : vt->fTrap1.setLeft(left);
321 0 : vt->fTrap1.setRight(right);
322 0 : if (vt->fTrap1 < vt->fTrap0) { // Keep trapezoids sorted.
323 0 : remove(&vt->fTrap0);
324 0 : Trapezoid t = vt->fTrap0;
325 0 : vt->fTrap0 = vt->fTrap1;
326 0 : vt->fTrap1 = t;
327 0 : insert(&vt->fTrap0);
328 : }
329 0 : insert(&vt->fTrap1);
330 : } else {
331 0 : FailureMessage("More than 2 trapezoids requested for a vertex\n");
332 0 : return false;
333 : }
334 0 : DebugPrintf(" done. %d incomplete trapezoids\n", fTrapezoids.count());
335 0 : return true;
336 : }
337 :
338 :
339 0 : void ActiveTrapezoids::insert(Trapezoid *t) {
340 : Trapezoid **tp;
341 0 : for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp)
342 0 : if (**tp > *t)
343 0 : break;
344 0 : fTrapezoids.insert(tp - fTrapezoids.begin(), 1, &t);
345 : // SHOULD VERIFY THAT ALL TRAPEZOIDS ARE PROPERLY SORTED
346 0 : }
347 :
348 :
349 0 : void ActiveTrapezoids::remove(Trapezoid *t) {
350 0 : DebugPrintf("Removing a trapezoid...");
351 0 : for (Trapezoid **tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) {
352 0 : if (*tp == t) {
353 0 : fTrapezoids.remove(tp - fTrapezoids.begin());
354 0 : DebugPrintf(" done.\n");
355 0 : return;
356 : }
357 : }
358 0 : DebugPrintf(" Arghh! Panic!\n");
359 0 : SkASSERT(t == 0); // Cannot find t in active trapezoid list.
360 : }
361 :
362 :
363 0 : bool ActiveTrapezoids::withinActiveTrapezoid(const SkPoint &pt,
364 : Trapezoid **trap) {
365 0 : DebugPrintf("Entering withinActiveTrapezoid()\n");
366 : // This is where a good search data structure would be helpful.
367 : Trapezoid **t;
368 0 : for (t = fTrapezoids.begin(); t < fTrapezoids.end(); ++t) {
369 0 : if ((**t).left()->compare(pt) <= 0) {
370 : // The point is to the left of the left edge of this trapezoid.
371 0 : DebugPrintf("withinActiveTrapezoid: Before a trapezoid\n");
372 0 : *trap = *t; // Return the place where a new trapezoid would go.
373 : // We have a bug with the sorting -- look through everything.
374 0 : 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 0 : if ((**t).right()->compare(pt) < 0) {
380 : // The point is to the left of the right edge.
381 0 : DebugPrintf("withinActiveTrapezoid: Within an Active Trapezoid\n");
382 0 : *trap = *t;
383 0 : return true;
384 : }
385 : }
386 :
387 : // The point is to the right of all trapezoids.
388 0 : DebugPrintf("withinActiveTrapezoid: After all trapezoids\n");
389 0 : *trap = NULL;
390 0 : return false;
391 : }
392 :
393 :
394 0 : Vertex* Vertex::diagonal() {
395 0 : Vertex *diag = NULL;
396 0 : if (fTrap0.bottom() != NULL) {
397 0 : if (!fTrap0.left() ->shareEdge(this, fTrap0.bottom()) &&
398 0 : !fTrap0.right()->shareEdge(this, fTrap0.bottom())
399 : ) {
400 0 : diag = fTrap0.bottom();
401 0 : fTrap0 = fTrap1;
402 0 : fTrap1.nullify();
403 0 : } else if (fTrap1.bottom() != NULL &&
404 0 : !fTrap1.left() ->shareEdge(this, fTrap1.bottom()) &&
405 0 : !fTrap1.right()->shareEdge(this, fTrap1.bottom())
406 : ) {
407 0 : diag = fTrap1.bottom();
408 0 : fTrap1.nullify();
409 : }
410 : }
411 0 : 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 :
423 0 : bool operator<(VertexPtr &v0, VertexPtr &v1) {
424 : // DebugPrintf("< %p %p\n", &v0, &v1);
425 0 : if (v0.vt->point().fY < v1.vt->point().fY) return true;
426 0 : if (v0.vt->point().fY > v1.vt->point().fY) return false;
427 0 : if (v0.vt->point().fX < v1.vt->point().fX) return true;
428 0 : else return false;
429 : }
430 :
431 :
432 0 : bool operator>(VertexPtr &v0, VertexPtr &v1) {
433 : // DebugPrintf("> %p %p\n", &v0, &v1);
434 0 : if (v0.vt->point().fY > v1.vt->point().fY) return true;
435 0 : if (v0.vt->point().fY < v1.vt->point().fY) return false;
436 0 : if (v0.vt->point().fX > v1.vt->point().fX) return true;
437 0 : else return false;
438 : }
439 :
440 :
441 0 : static void SetVertexPoints(size_t numPts, const SkPoint *pt, Vertex *vt) {
442 0 : for (; numPts-- != 0; ++pt, ++vt)
443 0 : vt->setPoint(*pt);
444 0 : }
445 :
446 :
447 0 : static void InitializeVertexTopology(size_t numPts, Vertex *v1) {
448 0 : Vertex *v0 = v1 + numPts - 1, *v_1 = v0 - 1;
449 0 : for (; numPts-- != 0; v_1 = v0, v0 = v1++) {
450 0 : v0->setPrev(v_1);
451 0 : v0->setNext(v1);
452 : }
453 0 : }
454 :
455 0 : Vertex::VertexType Vertex::classify(Vertex **e0, Vertex **e1) {
456 : VertexType type;
457 : SkPoint vPrev, vNext;
458 0 : vPrev.fX = prev()->point().fX - point().fX;
459 0 : vPrev.fY = prev()->point().fY - point().fY;
460 0 : vNext.fX = next()->point().fX - point().fX;
461 0 : 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 0 : if (vPrev.fY < 0) {
466 0 : if (vNext.fY > 0) {
467 : // Prev comes from above, Next goes below.
468 0 : type = MONOTONE;
469 0 : *e0 = prev();
470 0 : *e1 = this;
471 0 : } else if (vNext.fY < 0) {
472 : // The are both above: sort so that e0 is on the left.
473 0 : type = CONCAVE;
474 0 : if (SkPoint::CrossProduct(vPrev, vNext) <= 0) {
475 0 : *e0 = this;
476 0 : *e1 = prev();
477 : } else {
478 0 : *e0 = prev();
479 0 : *e1 = this;
480 : }
481 : } else {
482 0 : DebugPrintf("### py < 0, ny = 0\n");
483 0 : if (vNext.fX < 0) {
484 0 : type = CONCAVE;
485 0 : *e0 = this; // flat to the left
486 0 : *e1 = prev(); // concave on the right
487 : } else {
488 0 : type = CONCAVE;
489 0 : *e0 = prev(); // concave to the left
490 0 : *e1 = this; // flat to the right
491 : }
492 : }
493 0 : } else if (vPrev.fY > 0) {
494 0 : if (vNext.fY < 0) {
495 : // Next comes from above, Prev goes below.
496 0 : type = MONOTONE;
497 0 : *e0 = this;
498 0 : *e1 = prev();
499 0 : } else if (vNext.fY > 0) {
500 : // They are both below: sort so that e0 is on the left.
501 0 : type = CONVEX;
502 0 : if (SkPoint::CrossProduct(vPrev, vNext) <= 0) {
503 0 : *e0 = prev();
504 0 : *e1 = this;
505 : } else {
506 0 : *e0 = this;
507 0 : *e1 = prev();
508 : }
509 : } else {
510 0 : DebugPrintf("### py > 0, ny = 0\n");
511 0 : if (vNext.fX < 0) {
512 0 : type = MONOTONE;
513 0 : *e0 = this; // flat to the left
514 0 : *e1 = prev(); // convex on the right - try monotone first
515 : } else {
516 0 : type = MONOTONE;
517 0 : *e0 = prev(); // convex to the left - try monotone first
518 0 : *e1 = this; // flat to the right
519 : }
520 : }
521 : } else { // vPrev.fY == 0
522 0 : if (vNext.fY < 0) {
523 0 : DebugPrintf("### py = 0, ny < 0\n");
524 0 : if (vPrev.fX < 0) {
525 0 : type = CONCAVE;
526 0 : *e0 = prev(); // flat to the left
527 0 : *e1 = this; // concave on the right
528 : } else {
529 0 : type = CONCAVE;
530 0 : *e0 = this; // concave on the left - defer
531 0 : *e1 = prev(); // flat to the right
532 : }
533 0 : } else if (vNext.fY > 0) {
534 0 : DebugPrintf("### py = 0, ny > 0\n");
535 0 : if (vPrev.fX < 0) {
536 0 : type = MONOTONE;
537 0 : *e0 = prev(); // flat to the left
538 0 : *e1 = this; // convex on the right - try monotone first
539 : } else {
540 0 : type = MONOTONE;
541 0 : *e0 = this; // convex to the left - try monotone first
542 0 : *e1 = prev(); // flat to the right
543 : }
544 : } else {
545 0 : DebugPrintf("### py = 0, ny = 0\n");
546 : // First we try concave, then monotone, then convex.
547 0 : if (vPrev.fX <= vNext.fX) {
548 0 : type = CONCAVE;
549 0 : *e0 = prev(); // flat to the left
550 0 : *e1 = this; // flat to the right
551 : } else {
552 0 : type = CONCAVE;
553 0 : *e0 = this; // flat to the left
554 0 : *e1 = prev(); // flat to the right
555 : }
556 : }
557 : }
558 0 : return type;
559 : }
560 :
561 :
562 : #ifdef DEBUG
563 0 : static const char* GetVertexTypeString(Vertex::VertexType type) {
564 0 : const char *typeStr = NULL;
565 0 : switch (type) {
566 : case Vertex::MONOTONE:
567 0 : typeStr = "MONOTONE";
568 0 : break;
569 : case Vertex::CONCAVE:
570 0 : typeStr = "CONCAVE";
571 0 : break;
572 : case Vertex::CONVEX:
573 0 : typeStr = "CONVEX";
574 0 : break;
575 : }
576 0 : return typeStr;
577 : }
578 :
579 :
580 0 : static void PrintVertices(size_t numPts, Vertex *vt) {
581 0 : DebugPrintf("\nVertices:\n");
582 0 : for (size_t i = 0; i < numPts; i++) {
583 : Vertex *e0, *e1;
584 0 : 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 0 : i, vt[i].point().fX, vt[i].point().fY,
588 0 : vt[i].prev() - vt, vt[i].next() - vt,
589 0 : GetVertexTypeString(type), e0 - vt, e1 - vt);
590 : Trapezoid *trap[2];
591 0 : vt[i].trapezoids(trap, trap+1);
592 0 : for (int j = 0; j < 2; ++j) {
593 0 : if (trap[j] != NULL) {
594 : DebugPrintf(", trap(L=%d, R=%d, B=%d)",
595 0 : trap[j]->left() - vt,
596 0 : trap[j]->right() - vt,
597 0 : trap[j]->bottom() - vt);
598 : }
599 : }
600 0 : DebugPrintf("\n");
601 : }
602 0 : }
603 :
604 :
605 0 : static void PrintVertexPtrs(size_t numPts, VertexPtr *vp, Vertex *vtBase) {
606 0 : DebugPrintf("\nSorted Vertices:\n");
607 0 : for (size_t i = 0; i < numPts; i++) {
608 : Vertex *e0, *e1;
609 0 : Vertex *vt = vp[i].vt;
610 0 : 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 0 : i, vt - vtBase, vt->point().fX, vt->point().fY,
614 0 : vt->prev() - vtBase, vt->next() - vtBase,
615 0 : GetVertexTypeString(type), e0 - vtBase, e1 - vtBase);
616 : Trapezoid *trap[2];
617 0 : vt->trapezoids(trap, trap+1);
618 0 : for (int j = 0; j < 2; ++j) {
619 0 : if (trap[j] != NULL) {
620 : DebugPrintf(", trap(L=%d, R=%d, B=%d)",
621 0 : trap[j]->left() - vtBase,
622 0 : trap[j]->right() - vtBase,
623 0 : trap[j]->bottom() - vtBase);
624 : }
625 : }
626 0 : DebugPrintf("\n");
627 : }
628 0 : }
629 : #else // !DEBUG
630 : inline void PrintVertices(size_t numPts, Vertex *vt) {}
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>
637 0 : void BubbleSort(T *array, size_t count) {
638 : bool sorted;
639 0 : size_t count_1 = count - 1;
640 0 : do {
641 0 : sorted = true;
642 0 : for (size_t i = 0; i < count_1; ++i) {
643 0 : if (array[i + 1] < array[i]) {
644 0 : T t = array[i];
645 0 : array[i] = array[i + 1];
646 0 : array[i + 1] = t;
647 0 : sorted = false;
648 : }
649 : }
650 : } while (!sorted);
651 0 : }
652 :
653 :
654 : // Remove zero-height trapezoids.
655 0 : static void RemoveDegenerateTrapezoids(size_t numVt, Vertex *vt) {
656 0 : for (; numVt-- != 0; vt++) {
657 : Trapezoid *traps[2];
658 0 : vt->trapezoids(traps, traps+1);
659 0 : if (traps[1] != NULL &&
660 0 : vt->point().fY >= traps[1]->bottom()->point().fY) {
661 0 : traps[1]->nullify();
662 0 : traps[1] = NULL;
663 : }
664 0 : if (traps[0] != NULL &&
665 0 : vt->point().fY >= traps[0]->bottom()->point().fY) {
666 0 : if (traps[1] != NULL) {
667 0 : *traps[0] = *traps[1];
668 0 : traps[1]->nullify();
669 : } else {
670 0 : traps[0]->nullify();
671 : }
672 : }
673 : }
674 0 : }
675 :
676 :
677 : // Enhance the polygon with trapezoids.
678 0 : bool ConvertPointsToVertices(size_t numPts, const SkPoint *pts, Vertex *vta) {
679 0 : DebugPrintf("ConvertPointsToVertices()\n");
680 :
681 : // Clear everything.
682 0 : DebugPrintf("Zeroing vertices\n");
683 0 : sk_bzero(vta, numPts * sizeof(*vta));
684 :
685 : // Initialize vertices.
686 0 : DebugPrintf("Initializing vertices\n");
687 0 : SetVertexPoints(numPts, pts, vta);
688 0 : InitializeVertexTopology(numPts, vta);
689 :
690 0 : PrintVertices(numPts, vta);
691 :
692 0 : SkTDArray<VertexPtr> vtptr;
693 0 : vtptr.setCount(numPts);
694 0 : for (int i = numPts; i-- != 0;)
695 0 : vtptr[i].vt = vta + i;
696 0 : PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
697 : DebugPrintf("Sorting vertrap ptr array [%d] %p %p\n", vtptr.count(),
698 0 : &vtptr[0], &vtptr[vtptr.count() - 1]
699 0 : );
700 : // SkTHeapSort(vtptr.begin(), vtptr.count());
701 0 : BubbleSort(vtptr.begin(), vtptr.count());
702 0 : DebugPrintf("Done sorting\n");
703 0 : PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
704 :
705 0 : DebugPrintf("Traversing sorted vertrap ptrs\n");
706 0 : ActiveTrapezoids incompleteTrapezoids;
707 0 : for (VertexPtr *vtpp = vtptr.begin(); vtpp < vtptr.end(); ++vtpp) {
708 : DebugPrintf("%d: sorted vertrap %d\n",
709 0 : vtpp - vtptr.begin(), vtpp->vt - vta);
710 0 : Vertex *vt = vtpp->vt;
711 : Vertex *e0, *e1;
712 : Trapezoid *t;
713 0 : switch (vt->classify(&e0, &e1)) {
714 : case Vertex::MONOTONE:
715 : monotone:
716 0 : DebugPrintf("MONOTONE %d %d\n", e0 - vta, e1 - vta);
717 : // We should find one edge.
718 0 : t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
719 0 : if (t == NULL) { // One of the edges is flat.
720 : DebugPrintf("Monotone: cannot find a trapezoid with e0: "
721 0 : "trying convex\n");
722 0 : goto convex;
723 : }
724 0 : t->setBottom(vt); // This trapezoid is now complete.
725 0 : incompleteTrapezoids.remove(t);
726 :
727 0 : if (e0 == t->left()) // Replace the left edge.
728 0 : incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
729 : else // Replace the right edge.
730 0 : incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e1);
731 0 : break;
732 :
733 : case Vertex::CONVEX: // Start of a new trapezoid.
734 : convex:
735 : // We don't expect to find any edges.
736 0 : DebugPrintf("CONVEX %d %d\n", e0 - vta, e1 - vta);
737 0 : if (incompleteTrapezoids.withinActiveTrapezoid(
738 0 : vt->point(), &t)) {
739 : // Complete trapezoid.
740 0 : SkASSERT(t != NULL);
741 0 : t->setBottom(vt);
742 0 : incompleteTrapezoids.remove(t);
743 : // Introduce two new trapezoids.
744 0 : incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e0);
745 0 : incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
746 : } else {
747 : // Insert a new trapezoid.
748 0 : incompleteTrapezoids.insertNewTrapezoid(vt, e0, e1);
749 : }
750 0 : break;
751 :
752 : case Vertex::CONCAVE: // End of a trapezoid.
753 0 : DebugPrintf("CONCAVE %d %d\n", e0 - vta, e1 - vta);
754 : // We should find two edges.
755 0 : t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
756 0 : if (t == NULL) {
757 : DebugPrintf("Concave: cannot find a trapezoid with e0: "
758 0 : " trying monotone\n");
759 0 : goto monotone;
760 : }
761 0 : SkASSERT(t != NULL);
762 0 : if (e0 == t->left() && e1 == t->right()) {
763 : DebugPrintf(
764 0 : "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 0 : t->setBottom(vt);
768 0 : incompleteTrapezoids.remove(t);
769 : } else { // Edges belong to different trapezoids
770 : DebugPrintf(
771 0 : "Concave edges belong to different trapezoids.\n");
772 : // Complete left and right trapezoids.
773 : Trapezoid *s = incompleteTrapezoids.getTrapezoidWithEdge(
774 0 : e1);
775 0 : if (s == NULL) {
776 : DebugPrintf(
777 : "Concave: cannot find a trapezoid with e1: "
778 0 : " trying monotone\n");
779 0 : goto monotone;
780 : }
781 0 : t->setBottom(vt);
782 0 : s->setBottom(vt);
783 0 : incompleteTrapezoids.remove(t);
784 0 : incompleteTrapezoids.remove(s);
785 :
786 : // Merge the two trapezoids into one below this vertex.
787 : incompleteTrapezoids.insertNewTrapezoid(vt, t->left(),
788 0 : s->right());
789 : }
790 0 : break;
791 : }
792 : }
793 :
794 0 : RemoveDegenerateTrapezoids(numPts, vta);
795 :
796 0 : DebugPrintf("Done making trapezoids\n");
797 0 : PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
798 :
799 0 : size_t k = incompleteTrapezoids.count();
800 0 : if (k > 0) {
801 0 : FailureMessage("%d incomplete trapezoids\n", k);
802 0 : return false;
803 : }
804 0 : return true;
805 : }
806 :
807 :
808 0 : inline void appendTriangleAtVertex(const Vertex *v,
809 : SkTDArray<SkPoint> *triangles) {
810 0 : SkPoint *p = triangles->append(3);
811 0 : p[0] = v->prev()->point();
812 0 : p[1] = v->point();
813 0 : 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 0 : p[1].fX, p[1].fY,
818 0 : p[2].fX, p[2].fY
819 0 : );
820 0 : }
821 :
822 :
823 0 : static size_t CountVertices(const Vertex *first, const Vertex *last) {
824 0 : DebugPrintf("Counting vertices: ");
825 0 : size_t count = 1;
826 0 : for (; first != last; first = first->next()) {
827 0 : ++count;
828 0 : SkASSERT(count <= kMaxCount);
829 0 : if (count >= kMaxCount) {
830 0 : FailureMessage("Vertices do not seem to be in a linked chain\n");
831 0 : break;
832 : }
833 : }
834 0 : return count;
835 : }
836 :
837 :
838 0 : bool operator<(const SkPoint &p0, const SkPoint &p1) {
839 0 : if (p0.fY < p1.fY) return true;
840 0 : if (p0.fY > p1.fY) return false;
841 0 : if (p0.fX < p1.fX) return true;
842 0 : else return false;
843 : }
844 :
845 :
846 0 : static void PrintLinkedVertices(size_t n, Vertex *vertices) {
847 0 : DebugPrintf("%d vertices:\n", n);
848 : Vertex *v;
849 0 : for (v = vertices; n-- != 0; v = v->next())
850 0 : DebugPrintf(" (%.7g, %.7g)\n", v->point().fX, v->point().fY);
851 0 : if (v != vertices)
852 0 : FailureMessage("Vertices are not in a linked chain\n");
853 0 : }
854 :
855 :
856 : // Triangulate an unimonotone chain.
857 0 : bool TriangulateMonotone(Vertex *first, Vertex *last,
858 : SkTDArray<SkPoint> *triangles) {
859 0 : DebugPrintf("TriangulateMonotone()\n");
860 :
861 0 : size_t numVertices = CountVertices(first, last);
862 0 : if (numVertices == kMaxCount) {
863 0 : FailureMessage("Way too many vertices: %d:\n", numVertices);
864 0 : PrintLinkedVertices(numVertices, first);
865 0 : return false;
866 : }
867 :
868 0 : Vertex *start = first;
869 : // First find the point with the smallest Y.
870 0 : DebugPrintf("TriangulateMonotone: finding bottom\n");
871 0 : int count = kMaxCount; // Maximum number of vertices.
872 0 : for (Vertex *v = first->next(); v != first && count-- > 0; v = v->next())
873 0 : if (v->point() < start->point())
874 0 : start = v;
875 0 : if (count <= 0) {
876 0 : FailureMessage("TriangulateMonotone() was given disjoint chain\n");
877 0 : return false; // Something went wrong.
878 : }
879 :
880 : // Start at the far end of the long edge.
881 0 : if (start->prev()->point() < start->next()->point())
882 0 : start = start->next();
883 :
884 0 : Vertex *current = start->next();
885 0 : while (numVertices >= 3) {
886 0 : if (current->angleIsConvex()) {
887 0 : DebugPrintf("Angle %p is convex\n", current);
888 : // Print the vertices
889 0 : PrintLinkedVertices(numVertices, start);
890 :
891 0 : appendTriangleAtVertex(current, triangles);
892 0 : if (triangles->count() > kMaxCount * 3) {
893 : FailureMessage("An extraordinarily large number of triangles "
894 0 : "were generated\n");
895 0 : return false;
896 : }
897 0 : Vertex *save = current->prev();
898 0 : current->delink();
899 0 : current = (save == start || save == start->prev()) ? start->next()
900 0 : : save;
901 0 : --numVertices;
902 : } else {
903 0 : if (numVertices == 3) {
904 0 : FailureMessage("Convexity error in TriangulateMonotone()\n");
905 0 : appendTriangleAtVertex(current, triangles);
906 0 : return false;
907 : }
908 0 : DebugPrintf("Angle %p is concave\n", current);
909 0 : current = current->next();
910 : }
911 : }
912 0 : return true;
913 : }
914 :
915 :
916 : // Split the polygon into sets of unimonotone chains, and eventually call
917 : // TriangulateMonotone() to convert them into triangles.
918 0 : bool Triangulate(Vertex *first, Vertex *last, SkTDArray<SkPoint> *triangles) {
919 0 : DebugPrintf("Triangulate()\n");
920 0 : Vertex *currentVertex = first;
921 0 : while (!currentVertex->done()) {
922 0 : currentVertex->setDone(true);
923 0 : Vertex *bottomVertex = currentVertex->diagonal();
924 0 : if (bottomVertex != NULL) {
925 0 : Vertex *saveNext = currentVertex->next();
926 0 : Vertex *savePrev = bottomVertex->prev();
927 0 : currentVertex->setNext(bottomVertex);
928 0 : bottomVertex->setPrev(currentVertex);
929 0 : currentVertex->nullifyTrapezoid();
930 0 : bool success = Triangulate(bottomVertex, currentVertex, triangles);
931 0 : currentVertex->setDone(false);
932 0 : bottomVertex->setDone(false);
933 0 : currentVertex->setNext(saveNext);
934 0 : bottomVertex->setPrev(savePrev);
935 0 : bottomVertex->setNext(currentVertex);
936 0 : currentVertex->setPrev(bottomVertex);
937 0 : return Triangulate(currentVertex, bottomVertex, triangles)
938 0 : && success;
939 : } else {
940 0 : currentVertex = currentVertex->next();
941 : }
942 : }
943 0 : return TriangulateMonotone(first, last, triangles);
944 : }
945 :
946 :
947 0 : bool SkConcaveToTriangles(size_t numPts,
948 : const SkPoint pts[],
949 : SkTDArray<SkPoint> *triangles) {
950 0 : DebugPrintf("SkConcaveToTriangles()\n");
951 :
952 0 : SkTDArray<Vertex> vertices;
953 0 : vertices.setCount(numPts);
954 0 : if (!ConvertPointsToVertices(numPts, pts, vertices.begin()))
955 0 : return false;
956 :
957 0 : triangles->setReserve(numPts);
958 0 : triangles->setCount(0);
959 0 : return Triangulate(vertices.begin(), vertices.end() - 1, triangles);
960 : }
|