void CubicCoincidence_Test() { // split large quadratic // upscale quadratics to cubics // compare original, parts, to see if the are coincident for (size_t index = firstCubicCoincidenceTest; index < quadratics_count; ++index) { const Quadratic& test = quadratics[index]; QuadraticPair split; chop_at(test, split, 0.5); Quadratic midThird; sub_divide(test, 1.0/3, 2.0/3, midThird); Cubic whole, first, second, mid; quad_to_cubic(test, whole); quad_to_cubic(split.first(), first); quad_to_cubic(split.second(), second); quad_to_cubic(midThird, mid); if (!implicit_matches(whole, first)) { printf("%s-1 %d\n", __FUNCTION__, (int)index); } if (!implicit_matches(whole, second)) { printf("%s-2 %d\n", __FUNCTION__, (int)index); } if (!implicit_matches(mid, first)) { printf("%s-3 %d\n", __FUNCTION__, (int)index); } if (!implicit_matches(mid, second)) { printf("%s-4 %d\n", __FUNCTION__, (int)index); } if (!implicit_matches(first, second)) { printf("%s-5 %d\n", __FUNCTION__, (int)index); } } }
bool intersect(const Quadratic& q1, const Quadratic& q2, Intersections& i) { if (implicit_matches(q1, q2)) { // FIXME: compute T values // compute the intersections of the ends to find the coincident span bool useVertical = fabs(q1[0].x - q1[2].x) < fabs(q1[0].y - q1[2].y); double t; if ((t = axialIntersect(q1, q2[0], useVertical)) >= 0) { i.addCoincident(t, 0); } if ((t = axialIntersect(q1, q2[2], useVertical)) >= 0) { i.addCoincident(t, 1); } useVertical = fabs(q2[0].x - q2[2].x) < fabs(q2[0].y - q2[2].y); if ((t = axialIntersect(q2, q1[0], useVertical)) >= 0) { i.addCoincident(0, t); } if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) { i.addCoincident(1, t); } assert(i.fCoincidentUsed <= 2); return i.fCoincidentUsed > 0; } QuadraticIntersections q(q1, q2, i); bool result = q.intersect(); // FIXME: partial coincidence detection is currently poor. For now, try // to fix up the data after the fact. In the future, revisit the error // term to try to avoid this kind of result in the first place. if (i.fUsed && i.fCoincidentUsed) { hackToFixPartialCoincidence(q1, q2, i); } return result; }
void CubicParameterization_Test() { for (size_t index = firstCubicParameterizationTest; index < cubics_count; ++index) { for (size_t inner = 0; inner < 4; inner += 3) { if (!point_on_parameterized_curve(cubics[index], cubics[index][inner])) { printf("%s [%zu,%zu] 1 parameterization failed\n", __FUNCTION__, index, inner); } if (!point_on_parameterized_curve(cubics[index], cubics[index ^ 1][inner])) { printf("%s [%zu,%zu] 2 parameterization failed\n", __FUNCTION__, index, inner); } } if (!implicit_matches(cubics[index], cubics[index ^ 1])) { printf("%s %d\n", __FUNCTION__, (int)index); } } }
void CubicIntersection_Test() { for (size_t index = firstCubicIntersectionTest; index < tests_count; ++index) { const Cubic& cubic1 = tests[index][0]; const Cubic& cubic2 = tests[index][1]; Cubic reduce1, reduce2; int order1 = reduceOrder(cubic1, reduce1, kReduceOrder_NoQuadraticsAllowed); int order2 = reduceOrder(cubic2, reduce2, kReduceOrder_NoQuadraticsAllowed); if (order1 < 4) { printf("%s [%d] cubic1 order=%d\n", __FUNCTION__, (int) index, order1); continue; } if (order2 < 4) { printf("%s [%d] cubic2 order=%d\n", __FUNCTION__, (int) index, order2); continue; } if (implicit_matches(reduce1, reduce2)) { printf("%s [%d] coincident\n", __FUNCTION__, (int) index); continue; } Intersections tIntersections; intersect(reduce1, reduce2, tIntersections); if (!tIntersections.intersected()) { printf("%s [%d] no intersection\n", __FUNCTION__, (int) index); continue; } for (int pt = 0; pt < tIntersections.used(); ++pt) { double tt1 = tIntersections.fT[0][pt]; double tx1, ty1; xy_at_t(cubic1, tt1, tx1, ty1); double tt2 = tIntersections.fT[1][pt]; double tx2, ty2; xy_at_t(cubic2, tt2, tx2, ty2); if (!AlmostEqualUlps(tx1, tx2)) { printf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n", __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2); } if (!AlmostEqualUlps(ty1, ty2)) { printf("%s [%d,%d] y!= t1=%g (%g,%g) t2=%g (%g,%g)\n", __FUNCTION__, (int)index, pt, tt1, tx1, ty1, tt2, tx2, ty2); } } } }