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