OLD | NEW |
| (Empty) |
1 #include "CubicIntersection_TestData.h" | |
2 #include "CubicUtilities.h" | |
3 #include "Intersection_Tests.h" | |
4 #include "QuadraticIntersection_TestData.h" | |
5 #include "TestUtilities.h" | |
6 #include "SkGeometry.h" | |
7 | |
8 static void test(const Cubic* cubics, const char* name, int firstTest, size_t te
stCount) { | |
9 SkTDArray<Quadratic> quads; | |
10 for (size_t index = firstTest; index < testCount; ++index) { | |
11 const Cubic& cubic = cubics[index]; | |
12 double precision = calcPrecision(cubic); | |
13 (void) cubic_to_quadratics(cubic, precision, quads); | |
14 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 | |
21 static void test(const Quadratic* quadTests, const char* name, int firstTest, si
ze_t testCount) { | |
22 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); | |
28 (void) cubic_to_quadratics(cubic, precision, quads); | |
29 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 | |
36 static void testC(const Cubic* cubics, const char* name, int firstTest, size_t t
estCount) { | |
37 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 SkASSERT(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 | |
59 static void testC(const Cubic(* cubics)[2], const char* name, int firstTest, siz
e_t testCount) { | |
60 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); | |
66 SkASSERT(order != 4); | |
67 if (order < 3) { | |
68 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 | |
83 void CubicToQuadratics_Test() { | |
84 enum { | |
85 RunAll, | |
86 RunPointDegenerates, | |
87 RunNotPointDegenerates, | |
88 RunLines, | |
89 RunNotLines, | |
90 RunModEpsilonLines, | |
91 RunLessEpsilonLines, | |
92 RunNegEpsilonLines, | |
93 RunQuadraticLines, | |
94 RunQuadraticModLines, | |
95 RunComputedLines, | |
96 RunComputedTests, | |
97 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 == RunPointDegenerat
es ? firstTestIndex : SK_MaxS32; | |
105 int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDeg
enerates ? firstTestIndex : SK_MaxS32; | |
106 int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex :
SK_MaxS32; | |
107 int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIn
dex : SK_MaxS32; | |
108 int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? fi
rstTestIndex : SK_MaxS32; | |
109 int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ?
firstTestIndex : SK_MaxS32; | |
110 int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? fi
rstTestIndex : SK_MaxS32; | |
111 int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ?
firstTestIndex : SK_MaxS32; | |
112 int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLi
nes ? firstTestIndex : SK_MaxS32; | |
113 int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? f
irstTestIndex : SK_MaxS32; | |
114 int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests ?
firstTestIndex : SK_MaxS32; | |
115 | |
116 test(pointDegenerates, "pointDegenerates", firstPointDegeneratesTest, pointD
egenerates_count); | |
117 test(notPointDegenerates, "notPointDegenerates", firstNotPointDegeneratesTes
t, notPointDegenerates_count); | |
118 test(lines, "lines", firstLinesTest, lines_count); | |
119 test(notLines, "notLines", firstNotLinesTest, notLines_count); | |
120 test(modEpsilonLines, "modEpsilonLines", firstModEpsilonTest, modEpsilonLine
s_count); | |
121 test(lessEpsilonLines, "lessEpsilonLines", firstLessEpsilonTest, lessEpsilon
Lines_count); | |
122 test(negEpsilonLines, "negEpsilonLines", firstNegEpsilonTest, negEpsilonLine
s_count); | |
123 test(quadraticLines, "quadraticLines", firstQuadraticLineTest, quadraticLine
s_count); | |
124 test(quadraticModEpsilonLines, "quadraticModEpsilonLines", firstQuadraticMod
LineTest, | |
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 | |
131 static Cubic locals[] = { | |
132 {{0, 1}, {1.9274705288631189e-19, 1.0000000000000002}, {0.0017190297609673323, 0
.99828097023903239}, | |
133 {0.0053709083094631276, 0.99505672974365911}}, | |
134 | |
135 {{14.5975863, 41.632436}, {16.3518929, 26.2639684}, {18.5165519, 7.68775139}, {
8.03767257, 89.1628526}}, | |
136 {{69.7292014, 38.6877352}, {24.7648688, 23.1501713}, {84.9283191, 90.2588441},
{80.392774, 61.3533852}}, | |
137 {{ | |
138 60.776536520932126, | |
139 71.249307306133829 | |
140 }, { | |
141 87.107894191103014, | |
142 22.377669868235323 | |
143 }, { | |
144 1.4974754310666936, | |
145 68.069569937917208 | |
146 }, { | |
147 45.261946574441133, | |
148 17.536076632112298 | |
149 }}, | |
150 }; | |
151 | |
152 static size_t localsCount = sizeof(locals) / sizeof(locals[0]); | |
153 | |
154 #define DEBUG_CRASH 0 | |
155 #define TEST_AVERAGE_END_POINTS 0 // must take const off to test | |
156 extern const bool AVERAGE_END_POINTS; | |
157 | |
158 static void oneOff(size_t x) { | |
159 const Cubic& cubic = locals[x]; | |
160 const SkPoint skcubic[4] = {{(float) cubic[0].x, (float) cubic[0].y}, | |
161 {(float) cubic[1].x, (float) cubic[1].y}, {(float) cubic[2].x, (floa
t) cubic[2].y}, | |
162 {(float) cubic[3].x, (float) cubic[3].y}}; | |
163 SkScalar skinflect[2]; | |
164 int skin = SkFindCubicInflections(skcubic, skinflect); | |
165 SkDebugf("%s %d %1.9g\n", __FUNCTION__, skin, skinflect[0]); | |
166 SkTDArray<Quadratic> quads; | |
167 double precision = calcPrecision(cubic); | |
168 (void) cubic_to_quadratics(cubic, precision, quads); | |
169 SkDebugf("%s quads=%d\n", __FUNCTION__, quads.count()); | |
170 } | |
171 | |
172 void CubicsToQuadratics_OneOffTests() { | |
173 for (size_t x = 0; x < localsCount; ++x) { | |
174 oneOff(x); | |
175 } | |
176 } | |
177 | |
178 void CubicsToQuadratics_OneOffTest() { | |
179 oneOff(0); | |
180 } | |
181 | |
182 void CubicsToQuadratics_RandTest() { | |
183 srand(0); | |
184 const int arrayMax = 8; | |
185 const int sampleMax = 10; | |
186 const int tests = 1000000; // 10000000; | |
187 int quadDist[arrayMax]; | |
188 bzero(quadDist, sizeof(quadDist)); | |
189 Cubic samples[arrayMax][sampleMax]; | |
190 int sampleCount[arrayMax]; | |
191 bzero(sampleCount, sizeof(sampleCount)); | |
192 for (int x = 0; x < tests; ++x) { | |
193 Cubic cubic; | |
194 for (int i = 0; i < 4; ++i) { | |
195 cubic[i].x = (double) rand() / RAND_MAX * 100; | |
196 cubic[i].y = (double) rand() / RAND_MAX * 100; | |
197 } | |
198 #if DEBUG_CRASH | |
199 char str[1024]; | |
200 sprintf(str, "{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %
1.9g}},\n", | |
201 cubic[0].x, cubic[0].y, cubic[1].x, cubic[1].y, cubic[2].x, cub
ic[2].y, | |
202 cubic[3].x, cubic[3].y); | |
203 #endif | |
204 SkTDArray<Quadratic> quads; | |
205 double precision = calcPrecision(cubic); | |
206 (void) cubic_to_quadratics(cubic, precision, quads); | |
207 int count = quads.count(); | |
208 SkASSERT(count > 0); | |
209 SkASSERT(--count < arrayMax); | |
210 quadDist[count]++; | |
211 int sCount = sampleCount[count]; | |
212 if (sCount < sampleMax) { | |
213 memcpy(samples[count][sCount], cubic, sizeof(Cubic)); | |
214 sampleCount[count]++; | |
215 } | |
216 } | |
217 for (int x = 0; x < arrayMax; ++x) { | |
218 if (!quadDist[x]) { | |
219 continue; | |
220 } | |
221 SkDebugf("%d %1.9g%%\n", x + 1, (double) quadDist[x] / tests * 100); | |
222 } | |
223 SkDebugf("\n"); | |
224 for (int x = 0; x < arrayMax; ++x) { | |
225 for (int y = 0; y < sampleCount[x]; ++y) { | |
226 #if TEST_AVERAGE_END_POINTS | |
227 for (int w = 0; w < 2; ++w) { | |
228 AVERAGE_END_POINTS = w; | |
229 #else | |
230 int w = 0; | |
231 #endif | |
232 SkDebugf("<div id=\"cubic%dx%d%s\">\n", x + 1, y, w ? "x" : ""); | |
233 const Cubic& cubic = samples[x][y]; | |
234 SkDebugf("{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9
g, %1.9g}},\n", | |
235 cubic[0].x, cubic[0].y, cubic[1].x, cubic[1].y, cubic[2].x,
cubic[2].y, | |
236 cubic[3].x, cubic[3].y); | |
237 SkTDArray<Quadratic> quads; | |
238 double precision = calcPrecision(cubic); | |
239 (void) cubic_to_quadratics(cubic, precision, quads); | |
240 for (int z = 0; z < quads.count(); ++z) { | |
241 const Quadratic& quad = quads[z]; | |
242 SkDebugf("{{%1.9g, %1.9g}, {%1.9g, %1.9g}, {%1.9g, %1.9g}},\
n", | |
243 quad[0].x, quad[0].y, quad[1].x, quad[1].y, quad[2].x,
quad[2].y); | |
244 } | |
245 SkDebugf("</div>\n\n"); | |
246 #if TEST_AVERAGE_END_POINTS | |
247 } | |
248 #endif | |
249 } | |
250 } | |
251 SkDebugf("</div>\n\n"); | |
252 SkDebugf("<script type=\"text/javascript\">\n\n"); | |
253 SkDebugf("var testDivs = [\n"); | |
254 for (int x = 0; x < arrayMax; ++x) { | |
255 for (int y = 0; y < sampleCount[x]; ++y) { | |
256 #if TEST_AVERAGE_END_POINTS | |
257 for (int w = 0; w < 2; ++w) { | |
258 #else | |
259 int w = 0; | |
260 #endif | |
261 SkDebugf(" cubic%dx%d%s,\n", x + 1, y, w ? "x" : ""); | |
262 #if TEST_AVERAGE_END_POINTS | |
263 } | |
264 #endif | |
265 } | |
266 } | |
267 SkDebugf("\n\n\n"); | |
268 SkDebugf("%s end\n", __FUNCTION__); | |
269 } | |
OLD | NEW |