blob: 843833f92fedb74c9e4478e8fa089b84aab3c52c [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"
caryclark@google.com73ca6242013-01-17 21:02:47 +00006#include "SkGeometry.h"
caryclark@google.com6d0032a2013-01-04 19:41:13 +00007
caryclark@google.com73ca6242013-01-17 21:02:47 +00008static void test(const Cubic* cubics, const char* name, int firstTest, size_t testCount) {
caryclark@google.comd68bc302013-01-07 13:17:18 +00009 SkTDArray<Quadratic> quads;
10 for (size_t index = firstTest; index < testCount; ++index) {
11 const Cubic& cubic = cubics[index];
12 double precision = calcPrecision(cubic);
caryclark@google.com73ca6242013-01-17 21:02:47 +000013 (void) cubic_to_quadratics(cubic, precision, quads);
caryclark@google.comd68bc302013-01-07 13:17:18 +000014 if (quads.count() != 1) {
15 printf("%s [%d] cubic to quadratics failed count=%d\n", name, (int) index,
16 quads.count());
17 }
18 }
19}
20
caryclark@google.com73ca6242013-01-17 21:02:47 +000021static void test(const Quadratic* quadTests, const char* name, int firstTest, size_t testCount) {
caryclark@google.comd68bc302013-01-07 13:17:18 +000022 SkTDArray<Quadratic> quads;
23 for (size_t index = firstTest; index < testCount; ++index) {
24 const Quadratic& quad = quadTests[index];
25 Cubic cubic;
26 quad_to_cubic(quad, cubic);
27 double precision = calcPrecision(cubic);
caryclark@google.com73ca6242013-01-17 21:02:47 +000028 (void) cubic_to_quadratics(cubic, precision, quads);
caryclark@google.comd68bc302013-01-07 13:17:18 +000029 if (quads.count() != 1) {
30 printf("%s [%d] cubic to quadratics failed count=%d\n", name, (int) index,
31 quads.count());
32 }
33 }
34}
35
caryclark@google.com73ca6242013-01-17 21:02:47 +000036static void testC(const Cubic* cubics, const char* name, int firstTest, size_t testCount) {
caryclark@google.comd68bc302013-01-07 13:17:18 +000037 SkTDArray<Quadratic> quads;
38 // test if computed line end points are valid
39 for (size_t index = firstTest; index < testCount; ++index) {
40 const Cubic& cubic = cubics[index];
41 double precision = calcPrecision(cubic);
42 int order = cubic_to_quadratics(cubic, precision, quads);
43 assert(order != 4);
44 if (order < 3) {
45 continue;
46 }
47 if (!AlmostEqualUlps(cubic[0].x, quads[0][0].x)
48 || !AlmostEqualUlps(cubic[0].y, quads[0][0].y)) {
49 printf("[%d] unmatched start\n", (int) index);
50 }
51 int last = quads.count() - 1;
52 if (!AlmostEqualUlps(cubic[3].x, quads[last][2].x)
53 || !AlmostEqualUlps(cubic[3].y, quads[last][2].y)) {
54 printf("[%d] unmatched end\n", (int) index);
55 }
56 }
57}
58
caryclark@google.com73ca6242013-01-17 21:02:47 +000059static void testC(const Cubic(* cubics)[2], const char* name, int firstTest, size_t testCount) {
caryclark@google.comd68bc302013-01-07 13:17:18 +000060 SkTDArray<Quadratic> quads;
61 for (size_t index = firstTest; index < testCount; ++index) {
62 for (int idx2 = 0; idx2 < 2; ++idx2) {
63 const Cubic& cubic = cubics[index][idx2];
64 double precision = calcPrecision(cubic);
65 int order = cubic_to_quadratics(cubic, precision, quads);
caryclark@google.com73ca6242013-01-17 21:02:47 +000066 assert(order != 4);
67 if (order < 3) {
caryclark@google.comd68bc302013-01-07 13:17:18 +000068 continue;
69 }
70 if (!AlmostEqualUlps(cubic[0].x, quads[0][0].x)
71 || !AlmostEqualUlps(cubic[0].y, quads[0][0].y)) {
72 printf("[%d][%d] unmatched start\n", (int) index, idx2);
73 }
74 int last = quads.count() - 1;
75 if (!AlmostEqualUlps(cubic[3].x, quads[last][2].x)
76 || !AlmostEqualUlps(cubic[3].y, quads[last][2].y)) {
77 printf("[%d][%d] unmatched end\n", (int) index, idx2);
78 }
79 }
80 }
81}
82
caryclark@google.com6d0032a2013-01-04 19:41:13 +000083void CubicToQuadratics_Test() {
caryclark@google.com6d0032a2013-01-04 19:41:13 +000084 enum {
85 RunAll,
86 RunPointDegenerates,
87 RunNotPointDegenerates,
88 RunLines,
89 RunNotLines,
90 RunModEpsilonLines,
91 RunLessEpsilonLines,
92 RunNegEpsilonLines,
93 RunQuadraticLines,
94 RunQuadraticModLines,
95 RunComputedLines,
caryclark@google.comd68bc302013-01-07 13:17:18 +000096 RunComputedTests,
caryclark@google.com6d0032a2013-01-04 19:41:13 +000097 RunNone
98 } run = RunAll;
99 int firstTestIndex = 0;
100#if 0
101 run = RunComputedLines;
102 firstTestIndex = 18;
103#endif
104 int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : INT_MAX;
105 int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : INT_MAX;
106 int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : INT_MAX;
107 int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : INT_MAX;
108 int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : INT_MAX;
109 int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : INT_MAX;
110 int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : INT_MAX;
111 int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : INT_MAX;
112 int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : INT_MAX;
113 int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : INT_MAX;
caryclark@google.comd68bc302013-01-07 13:17:18 +0000114 int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests ? firstTestIndex : INT_MAX;
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000115
caryclark@google.comd68bc302013-01-07 13:17:18 +0000116 test(pointDegenerates, "pointDegenerates", firstPointDegeneratesTest, pointDegenerates_count);
117 test(notPointDegenerates, "notPointDegenerates", firstNotPointDegeneratesTest, notPointDegenerates_count);
118 test(lines, "lines", firstLinesTest, lines_count);
119 test(notLines, "notLines", firstNotLinesTest, notLines_count);
120 test(modEpsilonLines, "modEpsilonLines", firstModEpsilonTest, modEpsilonLines_count);
121 test(lessEpsilonLines, "lessEpsilonLines", firstLessEpsilonTest, lessEpsilonLines_count);
122 test(negEpsilonLines, "negEpsilonLines", firstNegEpsilonTest, negEpsilonLines_count);
123 test(quadraticLines, "quadraticLines", firstQuadraticLineTest, quadraticLines_count);
124 test(quadraticModEpsilonLines, "quadraticModEpsilonLines", firstQuadraticModLineTest,
125 quadraticModEpsilonLines_count);
126 testC(lines, "computed lines", firstComputedLinesTest, lines_count);
127 testC(tests, "computed tests", firstComputedCubicsTest, tests_count);
128 printf("%s end\n", __FUNCTION__);
129}
130
131static Cubic locals[] = {
caryclark@google.com73ca6242013-01-17 21:02:47 +0000132 {{14.5975863, 41.632436}, {16.3518929, 26.2639684}, {18.5165519, 7.68775139}, {8.03767257, 89.1628526}},
133 {{69.7292014, 38.6877352}, {24.7648688, 23.1501713}, {84.9283191, 90.2588441}, {80.392774, 61.3533852}},
caryclark@google.comd68bc302013-01-07 13:17:18 +0000134 {{
135 60.776536520932126,
136 71.249307306133829
137 }, {
skia.committer@gmail.com4e8ef332013-01-08 02:01:29 +0000138 87.107894191103014,
caryclark@google.comd68bc302013-01-07 13:17:18 +0000139 22.377669868235323
140 }, {
skia.committer@gmail.com4e8ef332013-01-08 02:01:29 +0000141 1.4974754310666936,
caryclark@google.comd68bc302013-01-07 13:17:18 +0000142 68.069569937917208
143 }, {
skia.committer@gmail.com4e8ef332013-01-08 02:01:29 +0000144 45.261946574441133,
caryclark@google.comd68bc302013-01-07 13:17:18 +0000145 17.536076632112298
caryclark@google.com73ca6242013-01-17 21:02:47 +0000146 }},
caryclark@google.comd68bc302013-01-07 13:17:18 +0000147};
148
149static size_t localsCount = sizeof(locals) / sizeof(locals[0]);
150
caryclark@google.com73ca6242013-01-17 21:02:47 +0000151#define DEBUG_CRASH 0
152#define TEST_AVERAGE_END_POINTS 0 // must take const off to test
153extern const bool AVERAGE_END_POINTS;
154
caryclark@google.comd68bc302013-01-07 13:17:18 +0000155void CubicsToQuadratics_RandTest() {
156 for (size_t x = 0; x < localsCount; ++x) {
157 const Cubic& cubic = locals[x];
caryclark@google.com73ca6242013-01-17 21:02:47 +0000158 const SkPoint skcubic[4] = {{(float) cubic[0].x, (float) cubic[0].y},
159 {(float) cubic[1].x, (float) cubic[1].y}, {(float) cubic[2].x, (float) cubic[2].y},
160 {(float) cubic[3].x, (float) cubic[3].y}};
161 SkScalar skinflect[2];
162 int skin = SkFindCubicInflections(skcubic, skinflect);
163 SkDebugf("%s %d %1.9g\n", __FUNCTION__, skin, skinflect[0]);
caryclark@google.comd68bc302013-01-07 13:17:18 +0000164 SkTDArray<Quadratic> quads;
165 double precision = calcPrecision(cubic);
caryclark@google.com73ca6242013-01-17 21:02:47 +0000166 (void) cubic_to_quadratics(cubic, precision, quads);
167 SkDebugf("%s quads=%d\n", __FUNCTION__, quads.count());
caryclark@google.comd68bc302013-01-07 13:17:18 +0000168 }
169 srand(0);
caryclark@google.com73ca6242013-01-17 21:02:47 +0000170 const int arrayMax = 8;
171 const int sampleMax = 10;
172 const int tests = 1000000; // 10000000;
caryclark@google.comd68bc302013-01-07 13:17:18 +0000173 int quadDist[arrayMax];
174 bzero(quadDist, sizeof(quadDist));
caryclark@google.com73ca6242013-01-17 21:02:47 +0000175 Cubic samples[arrayMax][sampleMax];
176 int sampleCount[arrayMax];
177 bzero(sampleCount, sizeof(sampleCount));
caryclark@google.comd68bc302013-01-07 13:17:18 +0000178 for (int x = 0; x < tests; ++x) {
179 Cubic cubic;
180 for (int i = 0; i < 4; ++i) {
181 cubic[i].x = (double) rand() / RAND_MAX * 100;
182 cubic[i].y = (double) rand() / RAND_MAX * 100;
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000183 }
caryclark@google.com73ca6242013-01-17 21:02:47 +0000184 #if DEBUG_CRASH
185 char str[1024];
186 sprintf(str, "{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n",
187 cubic[0].x, cubic[0].y, cubic[1].x, cubic[1].y, cubic[2].x, cubic[2].y,
188 cubic[3].x, cubic[3].y);
189 #endif
caryclark@google.comd68bc302013-01-07 13:17:18 +0000190 SkTDArray<Quadratic> quads;
191 double precision = calcPrecision(cubic);
caryclark@google.com73ca6242013-01-17 21:02:47 +0000192 (void) cubic_to_quadratics(cubic, precision, quads);
193 int count = quads.count();
194 assert(count > 0);
195 assert(--count < arrayMax);
196 quadDist[count]++;
197 int sCount = sampleCount[count];
198 if (sCount < sampleMax) {
199 memcpy(samples[count][sCount], cubic, sizeof(Cubic));
200 sampleCount[count]++;
201 }
caryclark@google.comd68bc302013-01-07 13:17:18 +0000202 }
203 for (int x = 0; x < arrayMax; ++x) {
204 if (!quadDist[x]) {
205 continue;
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000206 }
caryclark@google.com73ca6242013-01-17 21:02:47 +0000207 SkDebugf("%d %1.9g%%\n", x + 1, (double) quadDist[x] / tests * 100);
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000208 }
caryclark@google.com73ca6242013-01-17 21:02:47 +0000209 SkDebugf("\n");
210 for (int x = 0; x < arrayMax; ++x) {
211 for (int y = 0; y < sampleCount[x]; ++y) {
212#if TEST_AVERAGE_END_POINTS
213 for (int w = 0; w < 2; ++w) {
214 AVERAGE_END_POINTS = w;
215#else
216 int w = 0;
217#endif
218 SkDebugf("<div id=\"cubic%dx%d%s\">\n", x + 1, y, w ? "x" : "");
219 const Cubic& cubic = samples[x][y];
220 SkDebugf("{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n",
221 cubic[0].x, cubic[0].y, cubic[1].x, cubic[1].y, cubic[2].x, cubic[2].y,
222 cubic[3].x, cubic[3].y);
223 SkTDArray<Quadratic> quads;
224 double precision = calcPrecision(cubic);
225 (void) cubic_to_quadratics(cubic, precision, quads);
226 for (int z = 0; z < quads.count(); ++z) {
227 const Quadratic& quad = quads[z];
228 SkDebugf("{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\n",
229 quad[0].x, quad[0].y, quad[1].x, quad[1].y, quad[2].x, quad[2].y);
230 }
231 SkDebugf("</div>\n\n");
232#if TEST_AVERAGE_END_POINTS
233 }
234#endif
235 }
236 }
237 SkDebugf("</div>\n\n");
238 SkDebugf("<script type=\"text/javascript\">\n\n");
239 SkDebugf("var testDivs = [\n");
240 for (int x = 0; x < arrayMax; ++x) {
241 for (int y = 0; y < sampleCount[x]; ++y) {
242#if TEST_AVERAGE_END_POINTS
243 for (int w = 0; w < 2; ++w) {
244#else
245 int w = 0;
246#endif
247 SkDebugf(" cubic%dx%d%s,\n", x + 1, y, w ? "x" : "");
248#if TEST_AVERAGE_END_POINTS
249 }
250#endif
251 }
252 }
253 SkDebugf("\n\n\n");
254 SkDebugf("%s end\n", __FUNCTION__);
caryclark@google.com6d0032a2013-01-04 19:41:13 +0000255}