static void oneOffTest() { const Quadratic& quad1 = testSet[0]; const Quadratic& quad2 = testSet[1]; double minT = 0; double maxT = 1; bezier_clip(quad1, quad2, minT, maxT); }
static void oneAtEndTest() { const Quadratic& quad1 = testSet[2]; const Quadratic& quad2 = testSet[3]; double minT = 0; double maxT = 1; bezier_clip(quad1, quad2, minT, maxT); }
bool intersect() { double minT1, minT2, maxT1, maxT2; if (!bezier_clip(quad2, quad1, minT1, maxT1)) { return false; } if (!bezier_clip(quad1, quad2, minT2, maxT2)) { return false; } int split; if (maxT1 - minT1 < maxT2 - minT2) { intersections.swap(); minT2 = 0; maxT2 = 1; split = maxT1 - minT1 > tClipLimit; } else { minT1 = 0; maxT1 = 1; split = (maxT2 - minT2 > tClipLimit) << 1; } return chop(minT1, maxT1, minT2, maxT2, split); }
static void standardTestCases() { for (size_t index = 0; index < quadraticTests_count; ++index) { const Quadratic& quad1 = quadraticTests[index][0]; const Quadratic& quad2 = quadraticTests[index][1]; Quadratic reduce1, reduce2; int order1 = reduceOrder(quad1, reduce1); int order2 = reduceOrder(quad2, reduce2); if (order1 < 3) { printf("%s [%d] quad1 order=%d\n", __FUNCTION__, (int)index, order1); } if (order2 < 3) { printf("%s [%d] quad2 order=%d\n", __FUNCTION__, (int)index, order2); } if (order1 == 3 && order2 == 3) { double minT = 0; double maxT = 1; bezier_clip(reduce1, reduce2, minT, maxT); } } }
void CubicBezierClip_Test() { for (size_t index = 0; 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, kReduceOrder_TreatAsFill); int order2 = reduceOrder(cubic2, reduce2, kReduceOrder_NoQuadraticsAllowed, kReduceOrder_TreatAsFill); if (order1 < 4) { SkDebugf("%s [%d] cubic1 order=%d\n", __FUNCTION__, (int) index, order1); } if (order2 < 4) { SkDebugf("%s [%d] cubic2 order=%d\n", __FUNCTION__, (int) index, order2); } if (order1 == 4 && order2 == 4) { double minT = 0; double maxT = 1; bezier_clip(reduce1, reduce2, minT, maxT); } } }
bool intersect(double minT1, double maxT1, double minT2, double maxT2) { bool t1IsLine = maxT1 - minT1 <= quad1Divisions; bool t2IsLine = maxT2 - minT2 <= quad2Divisions; if (t1IsLine | t2IsLine) { return intersectAsLine(minT1, maxT1, minT2, maxT2, t1IsLine, t2IsLine); } Quadratic smaller, larger; // FIXME: carry last subdivide and reduceOrder result with quad sub_divide(quad1, minT1, maxT1, intersections.swapped() ? larger : smaller); sub_divide(quad2, minT2, maxT2, intersections.swapped() ? smaller : larger); double minT, maxT; if (!bezier_clip(smaller, larger, minT, maxT)) { if (approximately_equal(minT, maxT)) { double smallT, largeT; _Point q2pt, q1pt; if (intersections.swapped()) { largeT = interp(minT2, maxT2, minT); xy_at_t(quad2, largeT, q2pt.x, q2pt.y); xy_at_t(quad1, minT1, q1pt.x, q1pt.y); if (AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)) { smallT = minT1; } else { xy_at_t(quad1, maxT1, q1pt.x, q1pt.y); // FIXME: debug code assert(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)); smallT = maxT1; } } else { smallT = interp(minT1, maxT1, minT); xy_at_t(quad1, smallT, q1pt.x, q1pt.y); xy_at_t(quad2, minT2, q2pt.x, q2pt.y); if (AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)) { largeT = minT2; } else { xy_at_t(quad2, maxT2, q2pt.x, q2pt.y); // FIXME: debug code assert(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)); largeT = maxT2; } } intersections.add(smallT, largeT); return true; } return false; } int split; if (intersections.swapped()) { double newMinT1 = interp(minT1, maxT1, minT); double newMaxT1 = interp(minT1, maxT1, maxT); split = (newMaxT1 - newMinT1 > (maxT1 - minT1) * tClipLimit) << 1; #define VERBOSE 0 #if VERBOSE printf("%s d=%d s=%d new1=(%g,%g) old1=(%g,%g) split=%d\n", __FUNCTION__, depth, splits, newMinT1, newMaxT1, minT1, maxT1, split); #endif minT1 = newMinT1; maxT1 = newMaxT1; } else { double newMinT2 = interp(minT2, maxT2, minT); double newMaxT2 = interp(minT2, maxT2, maxT); split = newMaxT2 - newMinT2 > (maxT2 - minT2) * tClipLimit; #if VERBOSE printf("%s d=%d s=%d new2=(%g,%g) old2=(%g,%g) split=%d\n", __FUNCTION__, depth, splits, newMinT2, newMaxT2, minT2, maxT2, split); #endif minT2 = newMinT2; maxT2 = newMaxT2; } return chop(minT1, maxT1, minT2, maxT2, split); }
bool intersect(double minT1, double maxT1, double minT2, double maxT2) { Quadratic smaller, larger; // FIXME: carry last subdivide and reduceOrder result with quad sub_divide(quad1, minT1, maxT1, intersections.swapped() ? larger : smaller); sub_divide(quad2, minT2, maxT2, intersections.swapped() ? smaller : larger); Quadratic smallResult; if (reduceOrder(smaller, smallResult) <= 2) { Quadratic largeResult; if (reduceOrder(larger, largeResult) <= 2) { double smallT[2], largeT[2]; const _Line& smallLine = (const _Line&) smallResult; const _Line& largeLine = (const _Line&) largeResult; // FIXME: this doesn't detect or deal with coincident lines if (!::intersect(smallLine, largeLine, smallT, largeT)) { return false; } if (intersections.swapped()) { smallT[0] = interp(minT2, maxT2, smallT[0]); largeT[0] = interp(minT1, maxT1, largeT[0]); } else { smallT[0] = interp(minT1, maxT1, smallT[0]); largeT[0] = interp(minT2, maxT2, largeT[0]); } intersections.add(smallT[0], largeT[0]); return true; } } double minT, maxT; if (!bezier_clip(smaller, larger, minT, maxT)) { if (minT == maxT) { if (intersections.swapped()) { minT1 = (minT1 + maxT1) / 2; minT2 = interp(minT2, maxT2, minT); } else { minT1 = interp(minT1, maxT1, minT); minT2 = (minT2 + maxT2) / 2; } intersections.add(minT1, minT2); return true; } return false; } int split; if (intersections.swapped()) { double newMinT1 = interp(minT1, maxT1, minT); double newMaxT1 = interp(minT1, maxT1, maxT); split = (newMaxT1 - newMinT1 > (maxT1 - minT1) * tClipLimit) << 1; #define VERBOSE 0 #if VERBOSE printf("%s d=%d s=%d new1=(%g,%g) old1=(%g,%g) split=%d\n", __FUNCTION__, depth, splits, newMinT1, newMaxT1, minT1, maxT1, split); #endif minT1 = newMinT1; maxT1 = newMaxT1; } else { double newMinT2 = interp(minT2, maxT2, minT); double newMaxT2 = interp(minT2, maxT2, maxT); split = newMaxT2 - newMinT2 > (maxT2 - minT2) * tClipLimit; #define VERBOSE 0 #if VERBOSE printf("%s d=%d s=%d new2=(%g,%g) old2=(%g,%g) split=%d\n", __FUNCTION__, depth, splits, newMinT2, newMaxT2, minT2, maxT2, split); #endif minT2 = newMinT2; maxT2 = newMaxT2; } return chop(minT1, maxT1, minT2, maxT2, split); }