Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: src/pathops/SkDQuadIntersection.cpp

Issue 23542056: path ops work in progress (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: verbose + mutex around file number access Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/pathops/SkDQuadImplicit.cpp ('k') | src/pathops/SkDQuadLineIntersection.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Another approach is to start with the implicit form of one curve and solve 1 // Another approach is to start with the implicit form of one curve and solve
2 // (seek implicit coefficients in QuadraticParameter.cpp 2 // (seek implicit coefficients in QuadraticParameter.cpp
3 // by substituting in the parametric form of the other. 3 // by substituting in the parametric form of the other.
4 // The downside of this approach is that early rejects are difficult to come by. 4 // The downside of this approach is that early rejects are difficult to come by.
5 // http://planetmath.org/encyclopedia/GaloisTheoreticDerivationOfTheQuarticFormu la.html#step 5 // http://planetmath.org/encyclopedia/GaloisTheoreticDerivationOfTheQuarticFormu la.html#step
6 6
7 7
8 #include "SkDQuadImplicit.h" 8 #include "SkDQuadImplicit.h"
9 #include "SkIntersections.h" 9 #include "SkIntersections.h"
10 #include "SkPathOpsLine.h" 10 #include "SkPathOpsLine.h"
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 if (roots == 0) { 132 if (roots == 0) {
133 if (subDivide) { 133 if (subDivide) {
134 *subDivide = true; 134 *subDivide = true;
135 } 135 }
136 return true; 136 return true;
137 } 137 }
138 if (roots == 2) { 138 if (roots == 2) {
139 return false; 139 return false;
140 } 140 }
141 SkDPoint pt2 = q1.ptAtT(rootTs[0][0]); 141 SkDPoint pt2 = q1.ptAtT(rootTs[0][0]);
142 if (!pt2.approximatelyEqualHalf(mid)) { 142 if (!pt2.approximatelyEqual(mid)) {
143 return false; 143 return false;
144 } 144 }
145 i->insertSwap(rootTs[0][0], tMid, pt2); 145 i->insertSwap(rootTs[0][0], tMid, pt2);
146 return true; 146 return true;
147 } 147 }
148 148
149 static bool is_linear_inner(const SkDQuad& q1, double t1s, double t1e, const SkD Quad& q2, 149 static bool is_linear_inner(const SkDQuad& q1, double t1s, double t1e, const SkD Quad& q2,
150 double t2s, double t2e, SkIntersections* i, bool* su bDivide) { 150 double t2s, double t2e, SkIntersections* i, bool* su bDivide) {
151 SkDQuad hull = q1.subDivide(t1s, t1e); 151 SkDQuad hull = q1.subDivide(t1s, t1e);
152 SkDLine line = {{hull[2], hull[0]}}; 152 SkDLine line = {{hull[2], hull[0]}};
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 static bool is_linear(const SkDQuad& q1, const SkDQuad& q2, SkIntersections* i) { 242 static bool is_linear(const SkDQuad& q1, const SkDQuad& q2, SkIntersections* i) {
243 double measure = flat_measure(q1); 243 double measure = flat_measure(q1);
244 // OPTIMIZE: (get rid of sqrt) use approximately_zero 244 // OPTIMIZE: (get rid of sqrt) use approximately_zero
245 if (!approximately_zero_sqrt(measure)) { 245 if (!approximately_zero_sqrt(measure)) {
246 return false; 246 return false;
247 } 247 }
248 return is_linear_inner(q1, 0, 1, q2, 0, 1, i, NULL); 248 return is_linear_inner(q1, 0, 1, q2, 0, 1, i, NULL);
249 } 249 }
250 250
251 // FIXME: if flat measure is sufficiently large, then probably the quartic solut ion failed 251 // FIXME: if flat measure is sufficiently large, then probably the quartic solut ion failed
252 static void relaxed_is_linear(const SkDQuad& q1, const SkDQuad& q2, SkIntersecti ons* i) { 252 // avoid imprecision incurred with chopAt
253 double m1 = flat_measure(q1); 253 static void relaxed_is_linear(const SkDQuad* q1, double s1, double e1, const SkD Quad* q2,
254 double m2 = flat_measure(q2); 254 double s2, double e2, SkIntersections* i) {
255 #if DEBUG_FLAT_QUADS 255 double m1 = flat_measure(*q1);
256 double min = SkTMin(m1, m2); 256 double m2 = flat_measure(*q2);
257 if (min > 5) { 257 i->reset();
258 SkDebugf("%s maybe not flat enough.. %1.9g\n", __FUNCTION__, min); 258 const SkDQuad* rounder, *flatter;
259 double sf, midf, ef, sr, er;
260 if (m2 < m1) {
261 rounder = q1;
262 sr = s1;
263 er = e1;
264 flatter = q2;
265 sf = s2;
266 midf = (s2 + e2) / 2;
267 ef = e2;
268 } else {
269 rounder = q2;
270 sr = s2;
271 er = e2;
272 flatter = q1;
273 sf = s1;
274 midf = (s1 + e1) / 2;
275 ef = e1;
259 } 276 }
260 #endif
261 i->reset();
262 const SkDQuad& rounder = m2 < m1 ? q1 : q2;
263 const SkDQuad& flatter = m2 < m1 ? q2 : q1;
264 bool subDivide = false; 277 bool subDivide = false;
265 is_linear_inner(flatter, 0, 1, rounder, 0, 1, i, &subDivide); 278 is_linear_inner(*flatter, sf, ef, *rounder, sr, er, i, &subDivide);
266 if (subDivide) { 279 if (subDivide) {
267 SkDQuadPair pair = flatter.chopAt(0.5); 280 relaxed_is_linear(flatter, sf, midf, rounder, sr, er, i);
268 SkIntersections firstI, secondI; 281 relaxed_is_linear(flatter, midf, ef, rounder, sr, er, i);
269 relaxed_is_linear(pair.first(), rounder, &firstI);
270 for (int index = 0; index < firstI.used(); ++index) {
271 i->insert(firstI[0][index] * 0.5, firstI[1][index], firstI.pt(index) );
272 }
273 relaxed_is_linear(pair.second(), rounder, &secondI);
274 for (int index = 0; index < secondI.used(); ++index) {
275 i->insert(0.5 + secondI[0][index] * 0.5, secondI[1][index], secondI. pt(index));
276 }
277 } 282 }
278 if (m2 < m1) { 283 if (m2 < m1) {
279 i->swapPts(); 284 i->swapPts();
280 } 285 }
281 } 286 }
282 287
283 // each time through the loop, this computes values it had from the last loop 288 // each time through the loop, this computes values it had from the last loop
284 // if i == j == 1, the center values are still good 289 // if i == j == 1, the center values are still good
285 // otherwise, for i != 1 or j != 1, four of the values are still good 290 // otherwise, for i != 1 or j != 1, four of the values are still good
286 // and if i == 1 ^ j == 1, an additional value is good 291 // and if i == 1 ^ j == 1, an additional value is good
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 } 376 }
372 SkDLine tmpLine; 377 SkDLine tmpLine;
373 int testTIndex = testT << 1; 378 int testTIndex = testT << 1;
374 tmpLine[0] = tmpLine[1] = q2[testTIndex]; 379 tmpLine[0] = tmpLine[1] = q2[testTIndex];
375 tmpLine[1].fX += q2[1].fY - q2[testTIndex].fY; 380 tmpLine[1].fX += q2[1].fY - q2[testTIndex].fY;
376 tmpLine[1].fY -= q2[1].fX - q2[testTIndex].fX; 381 tmpLine[1].fY -= q2[1].fX - q2[testTIndex].fX;
377 SkIntersections impTs; 382 SkIntersections impTs;
378 impTs.intersectRay(q1, tmpLine); 383 impTs.intersectRay(q1, tmpLine);
379 for (int index = 0; index < impTs.used(); ++index) { 384 for (int index = 0; index < impTs.used(); ++index) {
380 SkDPoint realPt = impTs.pt(index); 385 SkDPoint realPt = impTs.pt(index);
381 if (!tmpLine[0].approximatelyEqualHalf(realPt)) { 386 if (!tmpLine[0].approximatelyEqual(realPt)) {
382 continue; 387 continue;
383 } 388 }
384 if (swap) { 389 if (swap) {
385 i->insert(testT, impTs[0][index], tmpLine[0]); 390 i->insert(testT, impTs[0][index], tmpLine[0]);
386 } else { 391 } else {
387 i->insert(impTs[0][index], testT, tmpLine[0]); 392 i->insert(impTs[0][index], testT, tmpLine[0]);
388 } 393 }
389 } 394 }
390 } 395 }
391 396
392 int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) { 397 int SkIntersections::intersect(const SkDQuad& q1, const SkDQuad& q2) {
398 fMax = 4;
393 // if the quads share an end point, check to see if they overlap 399 // if the quads share an end point, check to see if they overlap
394 for (int i1 = 0; i1 < 3; i1 += 2) { 400 for (int i1 = 0; i1 < 3; i1 += 2) {
395 for (int i2 = 0; i2 < 3; i2 += 2) { 401 for (int i2 = 0; i2 < 3; i2 += 2) {
396 if (q1[i1] == q2[i2]) { 402 if (q1[i1] == q2[i2]) {
397 insert(i1 >> 1, i2 >> 1, q1[i1]); 403 insert(i1 >> 1, i2 >> 1, q1[i1]);
398 } 404 }
399 } 405 }
400 } 406 }
401 if (fAllowNear || true) { // FIXME ? cubic/cubic intersection fails withou t (cubicOp67u) 407 if (fAllowNear || true) { // FIXME ? cubic/cubic intersection fails withou t (cubicOp67u)
402 for (int i1 = 0; i1 < 3; i1 += 2) { 408 for (int i1 = 0; i1 < 3; i1 += 2) {
403 for (int i2 = 0; i2 < 3; i2 += 2) { 409 for (int i2 = 0; i2 < 3; i2 += 2) {
404 if (q1[i1] != q2[i2] && q1[i1].approximatelyEqualHalf(q2[i2])) { 410 if (q1[i1] != q2[i2] && q1[i1].approximatelyEqual(q2[i2])) {
405 insertNear(i1 >> 1, i2 >> 1, q1[i1]); 411 insertNear(i1 >> 1, i2 >> 1, q1[i1]);
406 } 412 }
407 } 413 }
408 } 414 }
409 } 415 }
410 SkASSERT(fUsed < 3); 416 SkASSERT(fUsed < 3);
411 if (only_end_pts_in_common(q1, q2)) { 417 if (only_end_pts_in_common(q1, q2)) {
412 return fUsed; 418 return fUsed;
413 } 419 }
414 if (only_end_pts_in_common(q2, q1)) { 420 if (only_end_pts_in_common(q2, q1)) {
415 return fUsed; 421 return fUsed;
416 } 422 }
417 // see if either quad is really a line 423 // see if either quad is really a line
418 // FIXME: figure out why reduce step didn't find this earlier 424 // FIXME: figure out why reduce step didn't find this earlier
419 if (is_linear(q1, q2, this)) { 425 if (is_linear(q1, q2, this)) {
420 return fUsed; 426 return fUsed;
421 } 427 }
422 SkIntersections swapped; 428 SkIntersections swapped;
429 swapped.setMax(fMax);
423 if (is_linear(q2, q1, &swapped)) { 430 if (is_linear(q2, q1, &swapped)) {
424 swapped.swapPts(); 431 swapped.swapPts();
425 set(swapped); 432 set(swapped);
426 return fUsed; 433 return fUsed;
427 } 434 }
428 SkIntersections copyI(*this); 435 SkIntersections copyI(*this);
429 lookNearEnd(q1, q2, 0, *this, false, &copyI); 436 lookNearEnd(q1, q2, 0, *this, false, &copyI);
430 lookNearEnd(q1, q2, 1, *this, false, &copyI); 437 lookNearEnd(q1, q2, 1, *this, false, &copyI);
431 lookNearEnd(q2, q1, 0, *this, true, &copyI); 438 lookNearEnd(q2, q1, 0, *this, true, &copyI);
432 lookNearEnd(q2, q1, 1, *this, true, &copyI); 439 lookNearEnd(q2, q1, 1, *this, true, &copyI);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 double roots2[4]; 484 double roots2[4];
478 int rootCount2 = findRoots(i1, q2, roots2, useCubic, flip2, 0); 485 int rootCount2 = findRoots(i1, q2, roots2, useCubic, flip2, 0);
479 double roots2Copy[4]; 486 double roots2Copy[4];
480 int r2Count = addValidRoots(roots2, rootCount2, roots2Copy); 487 int r2Count = addValidRoots(roots2, rootCount2, roots2Copy);
481 SkDPoint pts2[4]; 488 SkDPoint pts2[4];
482 for (index = 0; index < r2Count; ++index) { 489 for (index = 0; index < r2Count; ++index) {
483 pts2[index] = q2.ptAtT(roots2Copy[index]); 490 pts2[index] = q2.ptAtT(roots2Copy[index]);
484 } 491 }
485 if (r1Count == r2Count && r1Count <= 1) { 492 if (r1Count == r2Count && r1Count <= 1) {
486 if (r1Count == 1) { 493 if (r1Count == 1) {
487 if (pts1[0].approximatelyEqualHalf(pts2[0])) { 494 if (pts1[0].approximatelyEqual(pts2[0])) {
488 insert(roots1Copy[0], roots2Copy[0], pts1[0]); 495 insert(roots1Copy[0], roots2Copy[0], pts1[0]);
489 } else if (pts1[0].moreRoughlyEqual(pts2[0])) { 496 } else if (pts1[0].moreRoughlyEqual(pts2[0])) {
490 // experiment: try to find intersection by chasing t 497 // experiment: try to find intersection by chasing t
491 rootCount = findRoots(i2, q1, roots1, useCubic, flip1, 0); 498 rootCount = findRoots(i2, q1, roots1, useCubic, flip1, 0);
492 (void) addValidRoots(roots1, rootCount, roots1Copy); 499 (void) addValidRoots(roots1, rootCount, roots1Copy);
493 rootCount2 = findRoots(i1, q2, roots2, useCubic, flip2, 0); 500 rootCount2 = findRoots(i1, q2, roots2, useCubic, flip2, 0);
494 (void) addValidRoots(roots2, rootCount2, roots2Copy); 501 (void) addValidRoots(roots2, rootCount2, roots2Copy);
495 if (binary_search(q1, q2, roots1Copy, roots2Copy, pts1)) { 502 if (binary_search(q1, q2, roots1Copy, roots2Copy, pts1)) {
496 insert(roots1Copy[0], roots2Copy[0], pts1[0]); 503 insert(roots1Copy[0], roots2Copy[0], pts1[0]);
497 } 504 }
498 } 505 }
499 } 506 }
500 return fUsed; 507 return fUsed;
501 } 508 }
502 int closest[4]; 509 int closest[4];
503 double dist[4]; 510 double dist[4];
504 bool foundSomething = false; 511 bool foundSomething = false;
505 for (index = 0; index < r1Count; ++index) { 512 for (index = 0; index < r1Count; ++index) {
506 dist[index] = DBL_MAX; 513 dist[index] = DBL_MAX;
507 closest[index] = -1; 514 closest[index] = -1;
508 for (int ndex2 = 0; ndex2 < r2Count; ++ndex2) { 515 for (int ndex2 = 0; ndex2 < r2Count; ++ndex2) {
509 if (!pts2[ndex2].approximatelyEqualHalf(pts1[index])) { 516 if (!pts2[ndex2].approximatelyEqual(pts1[index])) {
510 continue; 517 continue;
511 } 518 }
512 double dx = pts2[ndex2].fX - pts1[index].fX; 519 double dx = pts2[ndex2].fX - pts1[index].fX;
513 double dy = pts2[ndex2].fY - pts1[index].fY; 520 double dy = pts2[ndex2].fY - pts1[index].fY;
514 double distance = dx * dx + dy * dy; 521 double distance = dx * dx + dy * dy;
515 if (dist[index] <= distance) { 522 if (dist[index] <= distance) {
516 continue; 523 continue;
517 } 524 }
518 for (int outer = 0; outer < index; ++outer) { 525 for (int outer = 0; outer < index; ++outer) {
519 if (closest[outer] != ndex2) { 526 if (closest[outer] != ndex2) {
520 continue; 527 continue;
521 } 528 }
522 if (dist[outer] < distance) { 529 if (dist[outer] < distance) {
523 goto next; 530 goto next;
524 } 531 }
525 closest[outer] = -1; 532 closest[outer] = -1;
526 } 533 }
527 dist[index] = distance; 534 dist[index] = distance;
528 closest[index] = ndex2; 535 closest[index] = ndex2;
529 foundSomething = true; 536 foundSomething = true;
530 next: 537 next:
531 ; 538 ;
532 } 539 }
533 } 540 }
534 if (r1Count && r2Count && !foundSomething) { 541 if (r1Count && r2Count && !foundSomething) {
535 relaxed_is_linear(q1, q2, this); 542 relaxed_is_linear(&q1, 0, 1, &q2, 0, 1, this);
536 return fUsed; 543 return fUsed;
537 } 544 }
538 int used = 0; 545 int used = 0;
539 do { 546 do {
540 double lowest = DBL_MAX; 547 double lowest = DBL_MAX;
541 int lowestIndex = -1; 548 int lowestIndex = -1;
542 for (index = 0; index < r1Count; ++index) { 549 for (index = 0; index < r1Count; ++index) {
543 if (closest[index] < 0) { 550 if (closest[index] < 0) {
544 continue; 551 continue;
545 } 552 }
546 if (roots1Copy[index] < lowest) { 553 if (roots1Copy[index] < lowest) {
547 lowestIndex = index; 554 lowestIndex = index;
548 lowest = roots1Copy[index]; 555 lowest = roots1Copy[index];
549 } 556 }
550 } 557 }
551 if (lowestIndex < 0) { 558 if (lowestIndex < 0) {
552 break; 559 break;
553 } 560 }
554 insert(roots1Copy[lowestIndex], roots2Copy[closest[lowestIndex]], 561 insert(roots1Copy[lowestIndex], roots2Copy[closest[lowestIndex]],
555 pts1[lowestIndex]); 562 pts1[lowestIndex]);
556 closest[lowestIndex] = -1; 563 closest[lowestIndex] = -1;
557 } while (++used < r1Count); 564 } while (++used < r1Count);
558 return fUsed; 565 return fUsed;
559 } 566 }
OLDNEW
« no previous file with comments | « src/pathops/SkDQuadImplicit.cpp ('k') | src/pathops/SkDQuadLineIntersection.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698