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 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 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 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 const Vertex* left() const { return fLeft; } 95 const Vertex* right() const { return fRight; } 96 const Vertex* bottom() const { return fBottom; } 97 Vertex* left() { return fLeft; } 98 Vertex* right() { return fRight; } 99 Vertex* bottom() { return fBottom; } 100 void setLeft(Vertex *left) { fLeft = left; } 101 void setRight(Vertex *right) { fRight = right; } 102 void setBottom(Vertex *bottom) { fBottom = bottom; } 103 void nullify() { setBottom(NULL); } 104 105 bool operator<(Trapezoid &t1) { return compare(t1) < 0; } 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: 127 ActiveTrapezoids() { fTrapezoids.setCount(0); } 128 129 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 const SkPoint &point() const { return fPoint; } 167 void setPoint(const SkPoint &point) { fPoint = point; } 168 169 // The next and previous vertices around the polygon. 170 Vertex *next() { return fNext; } 171 Vertex *prev() { return fPrev; } 172 const Vertex *next() const { return fNext; } 173 const Vertex *prev() const { return fPrev; } 174 void setNext(Vertex *next) { fNext = next; } 175 void setPrev(Vertex *prev) { fPrev = prev; } 176 177 void setDone(bool done) { fDone = done; } 178 bool done() const { return fDone; } 179 180 // Trapezoid accessors return non-null for any complete trapezoids. 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. 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. 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 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 239 bool Vertex::shareEdge(Vertex *top, Vertex *bottom) { 240 return (((this == top) && (this->next() == bottom)) || 241 ((this == bottom) && (this->next() == top))); 242 } 243 244 245 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 261 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 273 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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. 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. 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 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 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 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 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. 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. 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 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