| 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 |