Flutter Engine
The Flutter Engine
Functions | Variables
PathOpsQuadIntersectionTest.cpp File Reference
#include "include/core/SkTypes.h"
#include "include/private/base/SkDebug.h"
#include "src/base/SkFloatBits.h"
#include "src/pathops/SkIntersections.h"
#include "src/pathops/SkPathOpsDebug.h"
#include "src/pathops/SkPathOpsPoint.h"
#include "src/pathops/SkPathOpsQuad.h"
#include "src/pathops/SkPathOpsTypes.h"
#include "src/pathops/SkReduceOrder.h"
#include "tests/PathOpsQuadIntersectionTestData.h"
#include "tests/PathOpsTestCommon.h"
#include "tests/Test.h"
#include <array>
#include <cstddef>

Go to the source code of this file.

Functions

static void standardTestCases (skiatest::Reporter *reporter)
 
static void oneOffTest1 (skiatest::Reporter *reporter, size_t outer, size_t inner)
 
static void oneOffTests (skiatest::Reporter *reporter)
 
static void coincidentTestOne (skiatest::Reporter *reporter, int test1, int test2)
 
static void coincidentTest (skiatest::Reporter *reporter)
 
static void intersectionFinder (int test1, int test2)
 
static void QuadraticIntersection_IntersectionFinder ()
 
 DEF_TEST (PathOpsQuadIntersectionOneOff, reporter)
 
 DEF_TEST (PathOpsQuadIntersectionCoincidenceOneOff, reporter)
 
 DEF_TEST (PathOpsQuadIntersection, reporter)
 
 DEF_TEST (PathOpsQuadBinaryProfile, reporter)
 

Variables

static const QuadPts testSet []
 
const size_t testSetCount = std::size(testSet)
 
static const QuadPts coincidentTestSet []
 
static const int coincidentTestSetCount = (int) std::size(coincidentTestSet)
 

Function Documentation

◆ coincidentTest()

static void coincidentTest ( skiatest::Reporter reporter)
static

Definition at line 418 of file PathOpsQuadIntersectionTest.cpp.

418 {
419 for (int testIndex = 0; testIndex < coincidentTestSetCount - 1; testIndex += 2) {
420 coincidentTestOne(reporter, testIndex, testIndex + 1);
421 }
422}
reporter
Definition: FontMgrTest.cpp:39
static const int coincidentTestSetCount
static void coincidentTestOne(skiatest::Reporter *reporter, int test1, int test2)

◆ coincidentTestOne()

static void coincidentTestOne ( skiatest::Reporter reporter,
int  test1,
int  test2 
)
static

Definition at line 396 of file PathOpsQuadIntersectionTest.cpp.

396 {
397 const QuadPts& q1 = coincidentTestSet[test1];
398 SkDQuad quad1;
399 quad1.debugSet(q1.fPts);
400 SkASSERT(ValidQuad(quad1));
401 const QuadPts& q2 = coincidentTestSet[test2];
402 SkDQuad quad2;
403 quad2.debugSet(q2.fPts);
404 SkASSERT(ValidQuad(quad2));
405 SkIntersections intersections2;
406 intersections2.intersect(quad1, quad2);
407 REPORTER_ASSERT(reporter, intersections2.debugCoincidentUsed() >= 2);
408 REPORTER_ASSERT(reporter, intersections2.used() >= 2);
409 for (int pt = 0; pt < intersections2.debugCoincidentUsed(); pt += 2) {
410 double tt1 = intersections2[0][pt];
411 double tt2 = intersections2[1][pt];
412 SkDPoint pt1 = quad1.ptAtT(tt1);
413 SkDPoint pt2 = quad2.ptAtT(tt2);
415 }
416}
static const QuadPts coincidentTestSet[]
bool ValidQuad(const SkDQuad &quad)
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
static void test1(skiatest::Reporter *reporter, SkWriter32 *writer)
int intersect(const SkDLine &, const SkDLine &)
int debugCoincidentUsed() const
int used() const
SkDPoint fPts[kPointCount]
bool approximatelyEqual(const SkDPoint &a) const
void debugSet(const SkDPoint *pts)
SkDPoint ptAtT(double t) const

◆ DEF_TEST() [1/4]

DEF_TEST ( PathOpsQuadBinaryProfile  ,
reporter   
)

Definition at line 539 of file PathOpsQuadIntersectionTest.cpp.

539 {
541 return;
542 }
543 SkIntersections intersections;
544 for (int x = 0; x < 100; ++x) {
545 int outer = 0;
546 int inner = outer + 1;
547 do {
548 const QuadPts& q1 = testSet[outer];
549 SkDQuad quad1;
550 quad1.debugSet(q1.fPts);
551 const QuadPts& q2 = testSet[inner];
552 SkDQuad quad2;
553 quad2.debugSet(q2.fPts);
554 (void) intersections.intersect(quad1, quad2);
555 REPORTER_ASSERT(reporter, intersections.used() >= 0); // make sure code isn't tossed
556 inner += 2;
557 outer += 2;
558 } while (outer < (int) testSetCount);
559 }
560 for (int x = 0; x < 100; ++x) {
561 for (size_t test = 0; test < quadraticTests_count; ++test) {
562 const QuadPts& q1 = quadraticTests[test][0];
563 const QuadPts& q2 = quadraticTests[test][1];
564 SkDQuad quad1, quad2;
565 quad1.debugSet(q1.fPts);
566 quad2.debugSet(q2.fPts);
567 (void) intersections.intersect(quad1, quad2);
568 REPORTER_ASSERT(reporter, intersections.used() >= 0); // make sure code isn't tossed
569 }
570 }
571}
#define test(name)
const size_t quadraticTests_count
const QuadPts quadraticTests[][2]
static const QuadPts testSet[]
const size_t testSetCount
static bool gVeryVerbose
double x

◆ DEF_TEST() [2/4]

DEF_TEST ( PathOpsQuadIntersection  ,
reporter   
)

Definition at line 532 of file PathOpsQuadIntersectionTest.cpp.

532 {
537}
static void standardTestCases(skiatest::Reporter *reporter)
static void QuadraticIntersection_IntersectionFinder()
static void oneOffTests(skiatest::Reporter *reporter)
static void coincidentTest(skiatest::Reporter *reporter)

◆ DEF_TEST() [3/4]

DEF_TEST ( PathOpsQuadIntersectionCoincidenceOneOff  ,
reporter   
)

Definition at line 528 of file PathOpsQuadIntersectionTest.cpp.

528 {
530}

◆ DEF_TEST() [4/4]

DEF_TEST ( PathOpsQuadIntersectionOneOff  ,
reporter   
)

Definition at line 524 of file PathOpsQuadIntersectionTest.cpp.

524 {
525 oneOffTest1(reporter, 0, 1);
526}
static void oneOffTest1(skiatest::Reporter *reporter, size_t outer, size_t inner)

◆ intersectionFinder()

static void intersectionFinder ( int  test1,
int  test2 
)
static

Definition at line 424 of file PathOpsQuadIntersectionTest.cpp.

424 {
425 const QuadPts& q1 = testSet[test1];
426 const QuadPts& q2 = testSet[test2];
427 SkDQuad quad1, quad2;
428 quad1.debugSet(q1.fPts);
429 quad2.debugSet(q2.fPts);
430 double t1Seed = 0.5;
431 double t2Seed = 0.8;
432 double t1Step = 0.1;
433 double t2Step = 0.1;
434 SkDPoint t1[3], t2[3];
435 bool toggle = true;
436 do {
437 t1[0] = quad1.ptAtT(t1Seed - t1Step);
438 t1[1] = quad1.ptAtT(t1Seed);
439 t1[2] = quad1.ptAtT(t1Seed + t1Step);
440 t2[0] = quad2.ptAtT(t2Seed - t2Step);
441 t2[1] = quad2.ptAtT(t2Seed);
442 t2[2] = quad2.ptAtT(t2Seed + t2Step);
443 double dist[3][3];
444 dist[1][1] = t1[1].distance(t2[1]);
445 int best_i = 1, best_j = 1;
446 for (int i = 0; i < 3; ++i) {
447 for (int j = 0; j < 3; ++j) {
448 if (i == 1 && j == 1) {
449 continue;
450 }
451 dist[i][j] = t1[i].distance(t2[j]);
452 if (dist[best_i][best_j] > dist[i][j]) {
453 best_i = i;
454 best_j = j;
455 }
456 }
457 }
458 if (best_i == 0) {
459 t1Seed -= t1Step;
460 } else if (best_i == 2) {
461 t1Seed += t1Step;
462 }
463 if (best_j == 0) {
464 t2Seed -= t2Step;
465 } else if (best_j == 2) {
466 t2Seed += t2Step;
467 }
468 if (best_i == 1 && best_j == 1) {
469 if ((toggle ^= true)) {
470 t1Step /= 2;
471 } else {
472 t2Step /= 2;
473 }
474 }
475 } while (!t1[1].approximatelyEqual(t2[1]));
476 t1Step = t2Step = 0.1;
477 double t10 = t1Seed - t1Step * 2;
478 double t12 = t1Seed + t1Step * 2;
479 double t20 = t2Seed - t2Step * 2;
480 double t22 = t2Seed + t2Step * 2;
482 while (!approximately_zero(t1Step)) {
483 test = quad1.ptAtT(t10);
484 t10 += t1[1].approximatelyEqual(test) ? -t1Step : t1Step;
485 t1Step /= 2;
486 }
487 t1Step = 0.1;
488 while (!approximately_zero(t1Step)) {
489 test = quad1.ptAtT(t12);
490 t12 -= t1[1].approximatelyEqual(test) ? -t1Step : t1Step;
491 t1Step /= 2;
492 }
493 while (!approximately_zero(t2Step)) {
494 test = quad2.ptAtT(t20);
495 t20 += t2[1].approximatelyEqual(test) ? -t2Step : t2Step;
496 t2Step /= 2;
497 }
498 t2Step = 0.1;
499 while (!approximately_zero(t2Step)) {
500 test = quad2.ptAtT(t22);
501 t22 -= t2[1].approximatelyEqual(test) ? -t2Step : t2Step;
502 t2Step /= 2;
503 }
504#if ONE_OFF_DEBUG
505 SkDebugf("%s t1=(%1.9g<%1.9g<%1.9g) t2=(%1.9g<%1.9g<%1.9g)\n", __FUNCTION__,
506 t10, t1Seed, t12, t20, t2Seed, t22);
507 SkDPoint p10 = quad1.ptAtT(t10);
508 SkDPoint p1Seed = quad1.ptAtT(t1Seed);
509 SkDPoint p12 = quad1.ptAtT(t12);
510 SkDebugf("%s p1=(%1.9g,%1.9g)<(%1.9g,%1.9g)<(%1.9g,%1.9g)\n", __FUNCTION__,
511 p10.fX, p10.fY, p1Seed.fX, p1Seed.fY, p12.fX, p12.fY);
512 SkDPoint p20 = quad2.ptAtT(t20);
513 SkDPoint p2Seed = quad2.ptAtT(t2Seed);
514 SkDPoint p22 = quad2.ptAtT(t22);
515 SkDebugf("%s p2=(%1.9g,%1.9g)<(%1.9g,%1.9g)<(%1.9g,%1.9g)\n", __FUNCTION__,
516 p20.fX, p20.fY, p2Seed.fX, p2Seed.fY, p22.fX, p22.fY);
517#endif
518}
static bool approximately_zero(double x)
Definition: SkCubics.cpp:153
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
double distance(const SkDPoint &a) const

◆ oneOffTest1()

static void oneOffTest1 ( skiatest::Reporter reporter,
size_t  outer,
size_t  inner 
)
static

Definition at line 344 of file PathOpsQuadIntersectionTest.cpp.

344 {
345 const QuadPts& q1 = testSet[outer];
346 SkDQuad quad1;
347 quad1.debugSet(q1.fPts);
348 SkASSERT(ValidQuad(quad1));
349 const QuadPts& q2 = testSet[inner];
350 SkDQuad quad2;
351 quad2.debugSet(q2.fPts);
352 SkASSERT(ValidQuad(quad2));
353 SkIntersections intersections;
354 intersections.intersect(quad1, quad2);
355 for (int pt = 0; pt < intersections.used(); ++pt) {
356 double tt1 = intersections[0][pt];
357 SkDPoint xy1 = quad1.ptAtT(tt1);
358 double tt2 = intersections[1][pt];
359 SkDPoint xy2 = quad2.ptAtT(tt2);
360 if (!xy1.approximatelyEqual(xy2)) {
361 SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
362 __FUNCTION__, static_cast<int>(outer), static_cast<int>(inner),
363 tt1, xy1.fX, xy1.fY, tt2, xy2.fX, xy2.fY);
365 }
366#if ONE_OFF_DEBUG
367 SkDebugf("%s [%d][%d] t1=%1.9g (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
368 outer, inner, tt1, xy1.fX, xy1.fY, tt2);
369#endif
370 }
371}

◆ oneOffTests()

static void oneOffTests ( skiatest::Reporter reporter)
static

Definition at line 373 of file PathOpsQuadIntersectionTest.cpp.

373 {
374 for (size_t outer = 0; outer < testSetCount - 1; ++outer) {
375 for (size_t inner = outer + 1; inner < testSetCount; ++inner) {
376 oneOffTest1(reporter, outer, inner);
377 }
378 }
379}

◆ QuadraticIntersection_IntersectionFinder()

static void QuadraticIntersection_IntersectionFinder ( )
static

Definition at line 520 of file PathOpsQuadIntersectionTest.cpp.

520 {
521 intersectionFinder(0, 1);
522}
static void intersectionFinder(int test1, int test2)

◆ standardTestCases()

static void standardTestCases ( skiatest::Reporter reporter)
static

Definition at line 23 of file PathOpsQuadIntersectionTest.cpp.

23 {
24 bool showSkipped = false;
25 for (size_t index = 0; index < quadraticTests_count; ++index) {
26 const QuadPts& q1 = quadraticTests[index][0];
27 SkDQuad quad1;
28 quad1.debugSet(q1.fPts);
29 SkASSERT(ValidQuad(quad1));
30 const QuadPts& q2 = quadraticTests[index][1];
31 SkDQuad quad2;
32 quad2.debugSet(q2.fPts);
33 SkASSERT(ValidQuad(quad2));
34 SkReduceOrder reduce1, reduce2;
35 int order1 = reduce1.reduce(quad1);
36 int order2 = reduce2.reduce(quad2);
37 if (order1 < 3) {
38 if (showSkipped) {
39 SkDebugf("[%d] quad1 order=%d\n", static_cast<int>(index), order1);
40 }
41 }
42 if (order2 < 3) {
43 if (showSkipped) {
44 SkDebugf("[%d] quad2 order=%d\n", static_cast<int>(index), order2);
45 }
46 }
47 if (order1 == 3 && order2 == 3) {
48 SkIntersections intersections;
49 intersections.intersect(quad1, quad2);
50 if (intersections.used() > 0) {
51 for (int pt = 0; pt < intersections.used(); ++pt) {
52 double tt1 = intersections[0][pt];
53 SkDPoint xy1 = quad1.ptAtT(tt1);
54 double tt2 = intersections[1][pt];
55 SkDPoint xy2 = quad2.ptAtT(tt2);
56 if (!xy1.approximatelyEqual(xy2)) {
57 SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
58 __FUNCTION__, static_cast<int>(index), pt, tt1, xy1.fX, xy1.fY,
59 tt2, xy2.fX, xy2.fY);
61 }
62 }
63 }
64 }
65 }
66}
int reduce(const SkDCubic &cubic, Quadratics)

Variable Documentation

◆ coincidentTestSet

const QuadPts coincidentTestSet[]
static
Initial value:
= {
{{{4914.9990234375, 1523}, {4942.75146484375, 1523}, {4962.375, 1542.6239013671875}}},
{{{4962.3759765625, 1542.6239013671875}, {4942.75244140625, 1523}, {4915, 1523}}},
{{{369.850525, 145.675964}, {382.362915, 121.29287}, {406.211273, 121.29287}}},
{{{369.850525, 145.675964}, {382.362915, 121.29287}, {406.211273, 121.29287}}},
{{{8, 8}, {10, 10}, {8, -10}}},
{{{8, -10}, {10, 10}, {8, 8}}},
}

Definition at line 381 of file PathOpsQuadIntersectionTest.cpp.

◆ coincidentTestSetCount

const int coincidentTestSetCount = (int) std::size(coincidentTestSet)
static

Definition at line 394 of file PathOpsQuadIntersectionTest.cpp.

◆ testSet

const QuadPts testSet[]
static

Definition at line 68 of file PathOpsQuadIntersectionTest.cpp.

◆ testSetCount

const size_t testSetCount = std::size(testSet)

Definition at line 342 of file PathOpsQuadIntersectionTest.cpp.