OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #include "PathOpsCubicIntersectionTestData.h" | 7 #include "PathOpsCubicIntersectionTestData.h" |
8 #include "PathOpsTestCommon.h" | 8 #include "PathOpsTestCommon.h" |
9 #include "SkIntersections.h" | 9 #include "SkIntersections.h" |
10 #include "SkPathOpsRect.h" | 10 #include "SkPathOpsRect.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 double tt1 = tIntersections[0][pt]; | 54 double tt1 = tIntersections[0][pt]; |
55 SkDPoint xy1 = cubic1.ptAtT(tt1); | 55 SkDPoint xy1 = cubic1.ptAtT(tt1); |
56 double tt2 = tIntersections[1][pt]; | 56 double tt2 = tIntersections[1][pt]; |
57 SkDPoint xy2 = cubic2.ptAtT(tt2); | 57 SkDPoint xy2 = cubic2.ptAtT(tt2); |
58 if (!xy1.approximatelyEqual(xy2)) { | 58 if (!xy1.approximatelyEqual(xy2)) { |
59 SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n", | 59 SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n", |
60 __FUNCTION__, (int)index, pt, tt1, xy1.fX, xy1.fY, tt2, xy2.
fX, xy2.fY); | 60 __FUNCTION__, (int)index, pt, tt1, xy1.fX, xy1.fY, tt2, xy2.
fX, xy2.fY); |
61 } | 61 } |
62 REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2)); | 62 REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2)); |
63 } | 63 } |
| 64 reporter->bumpTestCount(); |
64 } | 65 } |
65 } | 66 } |
66 | 67 |
67 static const SkDCubic testSet[] = { | 68 static const SkDCubic testSet[] = { |
68 // FIXME: uncommenting these two will cause this to fail | 69 // FIXME: uncommenting these two will cause this to fail |
69 // this results in two curves very nearly but not exactly coincident | 70 // this results in two curves very nearly but not exactly coincident |
70 #if 0 | 71 #if 0 |
71 {{{67.426548091427676, 37.993772624988935}, {23.483695892376684, 90.476863174921
306}, | 72 {{{67.426548091427676, 37.993772624988935}, {23.483695892376684, 90.476863174921
306}, |
72 {35.597065061143162, 79.872482633158796}, {75.38634169631932, 18.244890038
969412}}}, | 73 {35.597065061143162, 79.872482633158796}, {75.38634169631932, 18.244890038
969412}}}, |
73 {{{67.4265481, 37.9937726}, {23.4836959, 90.4768632}, {35.5970651, 79.8724826}, | 74 {{{67.4265481, 37.9937726}, {23.4836959, 90.4768632}, {35.5970651, 79.8724826}, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 | 157 |
157 {{{18.1312339, 31.6473732}, {95.5711034, 63.5350219}, {92.3283165, 62.0158945}, | 158 {{{18.1312339, 31.6473732}, {95.5711034, 63.5350219}, {92.3283165, 62.0158945}, |
158 {18.5656052, 32.1268808}}}, | 159 {18.5656052, 32.1268808}}}, |
159 {{{97.402018, 35.7169972}, {33.1127443, 25.8935163}, {1.13970027, 54.9424981}, | 160 {{{97.402018, 35.7169972}, {33.1127443, 25.8935163}, {1.13970027, 54.9424981}, |
160 {56.4860195, 60.529264}}}, | 161 {56.4860195, 60.529264}}}, |
161 }; | 162 }; |
162 | 163 |
163 const size_t testSetCount = SK_ARRAY_COUNT(testSet); | 164 const size_t testSetCount = SK_ARRAY_COUNT(testSet); |
164 | 165 |
165 static const SkDCubic newTestSet[] = { | 166 static const SkDCubic newTestSet[] = { |
166 {{{134, 11414}, {131.990234375, 11414}, {130.32666015625, 11415.482421875}, {130
.04275512695312, 11417.4130859375}}}, | 167 #if 0 // FIXME: asserts coincidence, not working yet |
| 168 {{{195, 785}, {124.30755615234375, 785}, {67, 841.85986328125}, {67, 912}}}, |
| 169 {{{67, 913}, {67, 842.30755615234375}, {123.85984039306641, 785}, {194, 785}}}, |
| 170 #endif |
| 171 |
| 172 {{{399,657}, {399,661.970581}, {403.029449,666}, {408,666}}}, |
| 173 {{{406,666}, {402.686279,666}, {400,663.313721}, {400,660}}}, |
| 174 |
| 175 {{{0,5}, {3,5}, {3,0}, {3,2}}}, |
| 176 {{{0,3}, {2,3}, {5,0}, {5,3}}}, |
| 177 |
167 {{{132, 11419}, {130.89543151855469, 11419}, {130, 11418.1044921875}, {130, 1141
7}}}, | 178 {{{132, 11419}, {130.89543151855469, 11419}, {130, 11418.1044921875}, {130, 1141
7}}}, |
168 | 179 |
169 {{{3, 4}, {1, 5}, {4, 3}, {6, 4}}}, | 180 {{{3, 4}, {1, 5}, {4, 3}, {6, 4}}}, |
170 {{{3, 4}, {4, 6}, {4, 3}, {5, 1}}}, | 181 {{{3, 4}, {4, 6}, {4, 3}, {5, 1}}}, |
171 | 182 |
172 {{{130.04275512695312, 11417.413085937500 }, | 183 {{{130.04275512695312, 11417.413085937500 }, |
173 {130.23312377929687, 11418.319335937500 }, | 184 {130.23312377929687, 11418.319335937500 }, |
174 {131.03707885742187, 11419.000000000000 }, | 185 {131.03707885742187, 11419.000000000000 }, |
175 {132.00000000000000, 11419.000000000000 }}}, | 186 {132.00000000000000, 11419.000000000000 }}}, |
176 | 187 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 | 287 |
277 {{{0, 6}, {1, 2}, {1, 0}, {1, 0}}}, | 288 {{{0, 6}, {1, 2}, {1, 0}, {1, 0}}}, |
278 {{{0, 1}, {0, 1}, {6, 0}, {2, 1}}}, | 289 {{{0, 1}, {0, 1}, {6, 0}, {2, 1}}}, |
279 | 290 |
280 {{{0, 2}, {0, 1}, {3, 0}, {1, 0}}}, | 291 {{{0, 2}, {0, 1}, {3, 0}, {1, 0}}}, |
281 {{{0, 3}, {0, 1}, {2, 0}, {1, 0}}}, | 292 {{{0, 3}, {0, 1}, {2, 0}, {1, 0}}}, |
282 }; | 293 }; |
283 | 294 |
284 const size_t newTestSetCount = SK_ARRAY_COUNT(newTestSet); | 295 const size_t newTestSetCount = SK_ARRAY_COUNT(newTestSet); |
285 | 296 |
286 static void oneOff(skiatest::Reporter* reporter, const SkDCubic& cubic1, const S
kDCubic& cubic2) { | 297 static void oneOff(skiatest::Reporter* reporter, const SkDCubic& cubic1, const S
kDCubic& cubic2, |
| 298 bool coin) { |
287 SkASSERT(ValidCubic(cubic1)); | 299 SkASSERT(ValidCubic(cubic1)); |
288 SkASSERT(ValidCubic(cubic2)); | 300 SkASSERT(ValidCubic(cubic2)); |
289 #if ONE_OFF_DEBUG | 301 #if ONE_OFF_DEBUG |
290 SkDebugf("computed quadratics given\n"); | 302 SkDebugf("computed quadratics given\n"); |
291 SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n"
, | 303 SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n"
, |
292 cubic1[0].fX, cubic1[0].fY, cubic1[1].fX, cubic1[1].fY, | 304 cubic1[0].fX, cubic1[0].fY, cubic1[1].fX, cubic1[1].fY, |
293 cubic1[2].fX, cubic1[2].fY, cubic1[3].fX, cubic1[3].fY); | 305 cubic1[2].fX, cubic1[2].fY, cubic1[3].fX, cubic1[3].fY); |
294 SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n"
, | 306 SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n"
, |
295 cubic2[0].fX, cubic2[0].fY, cubic2[1].fX, cubic2[1].fY, | 307 cubic2[0].fX, cubic2[0].fY, cubic2[1].fX, cubic2[1].fY, |
296 cubic2[2].fX, cubic2[2].fY, cubic2[3].fX, cubic2[3].fY); | 308 cubic2[2].fX, cubic2[2].fY, cubic2[3].fX, cubic2[3].fY); |
(...skipping 13 matching lines...) Expand all Loading... |
310 #if ONE_OFF_DEBUG | 322 #if ONE_OFF_DEBUG |
311 SkDebugf("computed quadratics set 2\n"); | 323 SkDebugf("computed quadratics set 2\n"); |
312 for (int index = 0; index < quads2.count(); ++index) { | 324 for (int index = 0; index < quads2.count(); ++index) { |
313 const SkDQuad& q = quads2[index]; | 325 const SkDQuad& q = quads2[index]; |
314 SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].fX,
q[0].fY, | 326 SkDebugf(" {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].fX,
q[0].fY, |
315 q[1].fX, q[1].fY, q[2].fX, q[2].fY); | 327 q[1].fX, q[1].fY, q[2].fX, q[2].fY); |
316 } | 328 } |
317 #endif | 329 #endif |
318 SkIntersections intersections; | 330 SkIntersections intersections; |
319 intersections.intersect(cubic1, cubic2); | 331 intersections.intersect(cubic1, cubic2); |
| 332 REPORTER_ASSERT(reporter, !coin || intersections.used() == 2); |
320 double tt1, tt2; | 333 double tt1, tt2; |
321 SkDPoint xy1, xy2; | 334 SkDPoint xy1, xy2; |
322 for (int pt3 = 0; pt3 < intersections.used(); ++pt3) { | 335 for (int pt3 = 0; pt3 < intersections.used(); ++pt3) { |
323 tt1 = intersections[0][pt3]; | 336 tt1 = intersections[0][pt3]; |
324 xy1 = cubic1.ptAtT(tt1); | 337 xy1 = cubic1.ptAtT(tt1); |
325 tt2 = intersections[1][pt3]; | 338 tt2 = intersections[1][pt3]; |
326 xy2 = cubic2.ptAtT(tt2); | 339 xy2 = cubic2.ptAtT(tt2); |
327 const SkDPoint& iPt = intersections.pt(pt3); | 340 const SkDPoint& iPt = intersections.pt(pt3); |
328 #if ONE_OFF_DEBUG | 341 #if ONE_OFF_DEBUG |
329 SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1
.9g\n", | 342 SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1
.9g\n", |
330 __FUNCTION__, tt1, xy1.fX, xy1.fY, iPt.fX, | 343 __FUNCTION__, tt1, xy1.fX, xy1.fY, iPt.fX, |
331 iPt.fY, xy2.fX, xy2.fY, tt2); | 344 iPt.fY, xy2.fX, xy2.fY, tt2); |
332 #endif | 345 #endif |
333 REPORTER_ASSERT(reporter, xy1.approximatelyEqual(iPt)); | 346 REPORTER_ASSERT(reporter, xy1.approximatelyEqual(iPt)); |
334 REPORTER_ASSERT(reporter, xy2.approximatelyEqual(iPt)); | 347 REPORTER_ASSERT(reporter, xy2.approximatelyEqual(iPt)); |
335 REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2)); | 348 REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2)); |
336 } | 349 } |
| 350 reporter->bumpTestCount(); |
337 } | 351 } |
338 | 352 |
339 static void oneOff(skiatest::Reporter* reporter, int outer, int inner) { | 353 static void oneOff(skiatest::Reporter* reporter, int outer, int inner) { |
340 const SkDCubic& cubic1 = testSet[outer]; | 354 const SkDCubic& cubic1 = testSet[outer]; |
341 const SkDCubic& cubic2 = testSet[inner]; | 355 const SkDCubic& cubic2 = testSet[inner]; |
342 oneOff(reporter, cubic1, cubic2); | 356 oneOff(reporter, cubic1, cubic2, false); |
343 } | 357 } |
344 | 358 |
345 static void newOneOff(skiatest::Reporter* reporter, int outer, int inner) { | 359 static void newOneOff(skiatest::Reporter* reporter, int outer, int inner) { |
346 const SkDCubic& cubic1 = newTestSet[outer]; | 360 const SkDCubic& cubic1 = newTestSet[outer]; |
347 const SkDCubic& cubic2 = newTestSet[inner]; | 361 const SkDCubic& cubic2 = newTestSet[inner]; |
348 oneOff(reporter, cubic1, cubic2); | 362 oneOff(reporter, cubic1, cubic2, false); |
349 } | 363 } |
350 | 364 |
351 static void oneOffTests(skiatest::Reporter* reporter) { | 365 static void oneOffTests(skiatest::Reporter* reporter) { |
352 for (size_t outer = 0; outer < testSetCount - 1; ++outer) { | 366 for (size_t outer = 0; outer < testSetCount - 1; ++outer) { |
353 for (size_t inner = outer + 1; inner < testSetCount; ++inner) { | 367 for (size_t inner = outer + 1; inner < testSetCount; ++inner) { |
354 oneOff(reporter, outer, inner); | 368 oneOff(reporter, outer, inner); |
355 } | 369 } |
356 } | 370 } |
357 for (size_t outer = 0; outer < newTestSetCount - 1; ++outer) { | 371 for (size_t outer = 0; outer < newTestSetCount - 1; ++outer) { |
358 for (size_t inner = outer + 1; inner < newTestSetCount; ++inner) { | 372 for (size_t inner = outer + 1; inner < newTestSetCount; ++inner) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 #endif | 419 #endif |
406 REPORTER_ASSERT(reporter, 0); | 420 REPORTER_ASSERT(reporter, 0); |
407 } | 421 } |
408 for (int pt = 0; pt < intersections2.used(); ++pt) { | 422 for (int pt = 0; pt < intersections2.used(); ++pt) { |
409 double tt1 = intersections2[0][pt]; | 423 double tt1 = intersections2[0][pt]; |
410 SkDPoint xy1 = cubic1.ptAtT(tt1); | 424 SkDPoint xy1 = cubic1.ptAtT(tt1); |
411 double tt2 = intersections2[1][pt]; | 425 double tt2 = intersections2[1][pt]; |
412 SkDPoint xy2 = cubic2.ptAtT(tt2); | 426 SkDPoint xy2 = cubic2.ptAtT(tt2); |
413 REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2)); | 427 REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2)); |
414 } | 428 } |
| 429 reporter->bumpTestCount(); |
415 } | 430 } |
416 } | 431 } |
417 | 432 |
418 static void intersectionFinder(int index0, int index1, double t1Seed, double t2S
eed, | 433 static void intersectionFinder(int index0, int index1, double t1Seed, double t2S
eed, |
419 double t1Step, double t2Step) { | 434 double t1Step, double t2Step) { |
420 const SkDCubic& cubic1 = newTestSet[index0]; | 435 const SkDCubic& cubic1 = newTestSet[index0]; |
421 const SkDCubic& cubic2 = newTestSet[index1]; | 436 const SkDCubic& cubic2 = newTestSet[index1]; |
422 SkDPoint t1[3], t2[3]; | 437 SkDPoint t1[3], t2[3]; |
423 bool toggle = true; | 438 bool toggle = true; |
424 do { | 439 do { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 SkDebugf("\n"); | 567 SkDebugf("\n"); |
553 #endif | 568 #endif |
554 SkIntersections i; | 569 SkIntersections i; |
555 int result = i.intersect(cubic); | 570 int result = i.intersect(cubic); |
556 REPORTER_ASSERT(reporter, result == 1); | 571 REPORTER_ASSERT(reporter, result == 1); |
557 REPORTER_ASSERT(reporter, i.used() == 1); | 572 REPORTER_ASSERT(reporter, i.used() == 1); |
558 REPORTER_ASSERT(reporter, !approximately_equal(i[0][0], i[1][0])); | 573 REPORTER_ASSERT(reporter, !approximately_equal(i[0][0], i[1][0])); |
559 SkDPoint pt1 = cubic.ptAtT(i[0][0]); | 574 SkDPoint pt1 = cubic.ptAtT(i[0][0]); |
560 SkDPoint pt2 = cubic.ptAtT(i[1][0]); | 575 SkDPoint pt2 = cubic.ptAtT(i[1][0]); |
561 REPORTER_ASSERT(reporter, pt1.approximatelyEqual(pt2)); | 576 REPORTER_ASSERT(reporter, pt1.approximatelyEqual(pt2)); |
| 577 reporter->bumpTestCount(); |
562 } | 578 } |
563 | 579 |
564 static void cubicIntersectionSelfTest(skiatest::Reporter* reporter) { | 580 static void cubicIntersectionSelfTest(skiatest::Reporter* reporter) { |
565 size_t firstFail = 0; | 581 size_t firstFail = 0; |
566 for (size_t index = firstFail; index < selfSetCount; ++index) { | 582 for (size_t index = firstFail; index < selfSetCount; ++index) { |
567 selfOneOff(reporter, index); | 583 selfOneOff(reporter, index); |
568 } | 584 } |
569 } | 585 } |
570 | 586 |
| 587 static const SkDCubic coinSet[] = { |
| 588 {{{317, 711}, {322.52285766601562, 711}, {327, 715.4771728515625}, {327, 721
}}}, |
| 589 {{{324.07107543945312, 713.928955078125}, {324.4051513671875, 714.2630004882
8125}, |
| 590 {324.71566772460937, 714.62060546875}, {325, 714.9990234375}}}, |
| 591 |
| 592 {{{2, 3}, {0, 4}, {3, 2}, {5, 3}}}, |
| 593 {{{2, 3}, {0, 4}, {3, 2}, {5, 3}}}, |
| 594 }; |
| 595 |
| 596 size_t coinSetCount = SK_ARRAY_COUNT(coinSet); |
| 597 |
| 598 static void coinOneOff(skiatest::Reporter* reporter, int index) { |
| 599 const SkDCubic& cubic1 = coinSet[index]; |
| 600 const SkDCubic& cubic2 = coinSet[index + 1]; |
| 601 oneOff(reporter, cubic1, cubic2, true); |
| 602 } |
| 603 |
| 604 static void cubicIntersectionCoinTest(skiatest::Reporter* reporter) { |
| 605 size_t firstFail = 0; |
| 606 for (size_t index = firstFail; index < coinSetCount; index += 2) { |
| 607 coinOneOff(reporter, index); |
| 608 } |
| 609 } |
| 610 |
| 611 static void PathOpsCubicCoinOneOffTest(skiatest::Reporter* reporter) { |
| 612 coinOneOff(reporter, 0); |
| 613 } |
| 614 |
571 static void PathOpsCubicIntersectionOneOffTest(skiatest::Reporter* reporter) { | 615 static void PathOpsCubicIntersectionOneOffTest(skiatest::Reporter* reporter) { |
572 newOneOff(reporter, 0, 1); | 616 newOneOff(reporter, 0, 1); |
573 } | 617 } |
574 | 618 |
575 static void PathOpsCubicSelfOneOffTest(skiatest::Reporter* reporter) { | 619 static void PathOpsCubicSelfOneOffTest(skiatest::Reporter* reporter) { |
576 selfOneOff(reporter, 0); | 620 selfOneOff(reporter, 0); |
577 } | 621 } |
578 | 622 |
579 static void PathOpsCubicIntersectionTest(skiatest::Reporter* reporter) { | 623 static void PathOpsCubicIntersectionTest(skiatest::Reporter* reporter) { |
580 oneOffTests(reporter); | 624 oneOffTests(reporter); |
581 cubicIntersectionSelfTest(reporter); | 625 cubicIntersectionSelfTest(reporter); |
| 626 cubicIntersectionCoinTest(reporter); |
582 standardTestCases(reporter); | 627 standardTestCases(reporter); |
583 if (false) CubicIntersection_IntersectionFinder(); | 628 if (false) CubicIntersection_IntersectionFinder(); |
584 if (false) CubicIntersection_RandTest(reporter); | 629 if (false) CubicIntersection_RandTest(reporter); |
585 } | 630 } |
586 | 631 |
587 #include "TestClassDef.h" | 632 #include "TestClassDef.h" |
588 DEFINE_TESTCLASS_SHORT(PathOpsCubicIntersectionTest) | 633 DEFINE_TESTCLASS_SHORT(PathOpsCubicIntersectionTest) |
589 | 634 |
590 DEFINE_TESTCLASS_SHORT(PathOpsCubicIntersectionOneOffTest) | 635 DEFINE_TESTCLASS_SHORT(PathOpsCubicIntersectionOneOffTest) |
591 | 636 |
592 DEFINE_TESTCLASS_SHORT(PathOpsCubicSelfOneOffTest) | 637 DEFINE_TESTCLASS_SHORT(PathOpsCubicSelfOneOffTest) |
| 638 |
| 639 DEFINE_TESTCLASS_SHORT(PathOpsCubicCoinOneOffTest) |
OLD | NEW |