blob: 24c0ffe03a9daaccc82d4ff15fe3db871528fb65 [file] [log] [blame]
caryclark@google.com6d0032a2013-01-04 19:41:13 +00001#include "CubicIntersection_TestData.h"
2#include "CubicUtilities.h"
3#include "Intersection_Tests.h"
4#include "QuadraticIntersection_TestData.h"
5#include "TestUtilities.h"
6
caryclark@google.comd68bc302013-01-07 13:17:18 +00007static double calcPrecision(const Cubic& cubic) {
8 _Rect dRect;
9 dRect.setBounds(cubic);
10 double width = dRect.right - dRect.left;
11 double height = dRect.bottom - dRect.top;
12 return (width > height ? width : height) / 256;
13}
14
15static void test(const Cubic(& cubics)[], const char* name, int firstTest, size_t testCount) {
16 SkTDArray<Quadratic> quads;
17 for (size_t index = firstTest; index < testCount; ++index) {
18 const Cubic& cubic = cubics[index];
19 double precision = calcPrecision(cubic);
20 cubic_to_quadratics(cubic, precision, quads);
21 if (quads.count() != 1) {
22 printf("%s [%d] cubic to quadratics failed count=%d\n", name, (int) index,
23 quads.count());
24 }
25 }
26}
27
28static void test(const Quadratic(& quadTests)[], const char* name, int firstTest, size_t testCount) {
29 SkTDArray<Quadratic> quads;
30 for (size_t index = firstTest; index < testCount; ++index) {
31 const Quadratic& quad = quadTests[index];
32 Cubic cubic;
33 quad_to_cubic(quad, cubic);
34 double precision = calcPrecision(cubic);
35 cubic_to_quadratics(cubic, precision, quads);
36 if (quads.count() != 1) {
37 printf("%s [%d] cubic to quadratics failed count=%d\n", name, (int) index,
38 quads.count());
39 }
40 }
41}
42
43static void testC(const Cubic(& cubics)[], const char* name, int firstTest, size_t testCount) {
44 SkTDArray<Quadratic> quads;
45 // test if computed line end points are valid
46 for (size_t index = firstTest; index < testCount; ++index) {
47 const Cubic& cubic = cubics[index];
48 double precision = calcPrecision(cubic);
49 int order = cubic_to_quadratics(cubic, precision, quads);
50 assert(order != 4);
51 if (order < 3) {
52 continue;
53 }
54 if (!AlmostEqualUlps(cubic[0].x, quads[0][0].x)
55 || !AlmostEqualUlps(cubic[0].y, quads[0][0].y)) {
56 printf("[%d] unmatched start\n", (int) index);
57 }
58 int last = quads.count() - 1;
59 if (!AlmostEqualUlps(cubic[3].x, quads[last][2].x)
60 || !AlmostEqualUlps(cubic[3].y, quads[last][2].y)) {
61 printf("[%d] unmatched end\n", (int) index);
62 }
63 }
64}
65
66static void testC(const Cubic(& cubics)[][2], const char* name, int firstTest, size_t testCount) {
67 SkTDArray<Quadratic> quads;
68 for (size_t index = firstTest; index < testCount; ++index) {
69 for (int idx2 = 0; idx2 < 2; ++idx2) {
70 const Cubic& cubic = cubics[index][idx2];
71 double precision = calcPrecision(cubic);
72 int order = cubic_to_quadratics(cubic, precision, quads);
73 assert(order != 4);
74 if (order < 3) {
75 continue;
76 }
77 if (!AlmostEqualUlps(cubic[0].x, quads[0][0].x)
78 || !AlmostEqualUlps(cubic[0].y, quads[0][0].y)) {
79 printf("[%d][%d] unmatched start\n", (int) index, idx2);
80 }
81 int last = quads.count() - 1;
82 if (!AlmostEqualUlps(cubic[3].x, quads[last][2].x)
83 || !AlmostEqualUlps(cubic[3].y, quads[last][2].y)) {
84 printf("[%d][%d] unmatched end\n", (int) index, idx2);
85 }
86 }
87 }
88}
89
caryclark@google.com6d0032a2013-01-04 19:41:13 +000090void CubicToQuadratics_Test() {
caryclark@google.com6d0032a2013-01-04 19:41:13 +000091 enum {
92 RunAll,
93 RunPointDegenerates,
94 RunNotPointDegenerates,
95 RunLines,
96 RunNotLines,
97 RunModEpsilonLines,
98 RunLessEpsilonLines,
99 RunNegEpsilonLines,
100 RunQuadraticLines,
101 RunQuadraticModLines,
102 RunComputedLines,
caryclark@google.comd68bc302013-01-07 13:17:18 +0000103 RunComputedTests,
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000104 RunNone
105 } run = RunAll;
106 int firstTestIndex = 0;
107#if 0
108 run = RunComputedLines;
109 firstTestIndex = 18;
110#endif
111 int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : INT_MAX;
112 int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : INT_MAX;
113 int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : INT_MAX;
114 int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : INT_MAX;
115 int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : INT_MAX;
116 int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : INT_MAX;
117 int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : INT_MAX;
118 int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : INT_MAX;
119 int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : INT_MAX;
120 int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : INT_MAX;
caryclark@google.comd68bc302013-01-07 13:17:18 +0000121 int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests ? firstTestIndex : INT_MAX;
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000122
caryclark@google.comd68bc302013-01-07 13:17:18 +0000123 test(pointDegenerates, "pointDegenerates", firstPointDegeneratesTest, pointDegenerates_count);
124 test(notPointDegenerates, "notPointDegenerates", firstNotPointDegeneratesTest, notPointDegenerates_count);
125 test(lines, "lines", firstLinesTest, lines_count);
126 test(notLines, "notLines", firstNotLinesTest, notLines_count);
127 test(modEpsilonLines, "modEpsilonLines", firstModEpsilonTest, modEpsilonLines_count);
128 test(lessEpsilonLines, "lessEpsilonLines", firstLessEpsilonTest, lessEpsilonLines_count);
129 test(negEpsilonLines, "negEpsilonLines", firstNegEpsilonTest, negEpsilonLines_count);
130 test(quadraticLines, "quadraticLines", firstQuadraticLineTest, quadraticLines_count);
131 test(quadraticModEpsilonLines, "quadraticModEpsilonLines", firstQuadraticModLineTest,
132 quadraticModEpsilonLines_count);
133 testC(lines, "computed lines", firstComputedLinesTest, lines_count);
134 testC(tests, "computed tests", firstComputedCubicsTest, tests_count);
135 printf("%s end\n", __FUNCTION__);
136}
137
138static Cubic locals[] = {
139 {{
140 60.776536520932126,
141 71.249307306133829
142 }, {
skia.committer@gmail.com4e8ef332013-01-08 02:01:29 +0000143 87.107894191103014,
caryclark@google.comd68bc302013-01-07 13:17:18 +0000144 22.377669868235323
145 }, {
skia.committer@gmail.com4e8ef332013-01-08 02:01:29 +0000146 1.4974754310666936,
caryclark@google.comd68bc302013-01-07 13:17:18 +0000147 68.069569937917208
148 }, {
skia.committer@gmail.com4e8ef332013-01-08 02:01:29 +0000149 45.261946574441133,
caryclark@google.comd68bc302013-01-07 13:17:18 +0000150 17.536076632112298
151 }}
152};
153
154static size_t localsCount = sizeof(locals) / sizeof(locals[0]);
155
156void CubicsToQuadratics_RandTest() {
157 for (size_t x = 0; x < localsCount; ++x) {
158 const Cubic& cubic = locals[x];
159 SkTDArray<Quadratic> quads;
160 double precision = calcPrecision(cubic);
161 cubic_to_quadratics(cubic, precision, quads);
162 }
163 srand(0);
164 const int arrayMax = 1000;
165 const int tests = 1000000;
166 int quadDist[arrayMax];
167 bzero(quadDist, sizeof(quadDist));
168 for (int x = 0; x < tests; ++x) {
169 Cubic cubic;
170 for (int i = 0; i < 4; ++i) {
171 cubic[i].x = (double) rand() / RAND_MAX * 100;
172 cubic[i].y = (double) rand() / RAND_MAX * 100;
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000173 }
caryclark@google.comd68bc302013-01-07 13:17:18 +0000174 SkTDArray<Quadratic> quads;
175 double precision = calcPrecision(cubic);
176 cubic_to_quadratics(cubic, precision, quads);
177 assert(quads.count() < arrayMax);
178 quadDist[quads.count()]++;
179 }
180 for (int x = 0; x < arrayMax; ++x) {
181 if (!quadDist[x]) {
182 continue;
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000183 }
caryclark@google.comd68bc302013-01-07 13:17:18 +0000184 printf("%d 1.9%g%%\n", x, (double) quadDist[x] / tests * 100);
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000185 }
186}