aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/Intersection/CubicToQuadratics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'experimental/Intersection/CubicToQuadratics.cpp')
-rw-r--r--experimental/Intersection/CubicToQuadratics.cpp44
1 files changed, 35 insertions, 9 deletions
diff --git a/experimental/Intersection/CubicToQuadratics.cpp b/experimental/Intersection/CubicToQuadratics.cpp
index 707cfd10ba..5eeaf19c9f 100644
--- a/experimental/Intersection/CubicToQuadratics.cpp
+++ b/experimental/Intersection/CubicToQuadratics.cpp
@@ -48,6 +48,7 @@ http://www.caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
#include "CubicUtilities.h"
#include "CurveIntersection.h"
#include "LineIntersection.h"
+#include "TSearch.h"
const bool AVERAGE_END_POINTS = true; // results in better fitting curves
@@ -147,9 +148,34 @@ void cubic_to_quadratics(const Cubic& cubic, double precision, SkTDArray<double>
if (order < 3) {
return;
}
- double inflectT[2];
+ double inflectT[5];
int inflections = find_cubic_inflections(cubic, inflectT);
SkASSERT(inflections <= 2);
+ if (!ends_are_extrema_in_x_or_y(cubic)) {
+ inflections += find_cubic_max_curvature(cubic, &inflectT[inflections]);
+ SkASSERT(inflections <= 5);
+ }
+ QSort<double>(inflectT, &inflectT[inflections - 1]);
+ // OPTIMIZATION: is this filtering common enough that it needs to be pulled out into its
+ // own subroutine?
+ while (inflections && approximately_less_than_zero(inflectT[0])) {
+ memcpy(inflectT, &inflectT[1], sizeof(inflectT[0]) * --inflections);
+ }
+ int start = 0;
+ do {
+ int next = start + 1;
+ if (next >= inflections) {
+ break;
+ }
+ if (!approximately_equal(inflectT[start], inflectT[next])) {
+ ++start;
+ continue;
+ }
+ memcpy(&inflectT[start], &inflectT[next], sizeof(inflectT[0]) * (--inflections - start));
+ } while (true);
+ while (inflections && approximately_greater_than_one(inflectT[inflections - 1])) {
+ --inflections;
+ }
CubicPair pair;
if (inflections == 1) {
chop_at(cubic, pair, inflectT[0]);
@@ -174,17 +200,17 @@ void cubic_to_quadratics(const Cubic& cubic, double precision, SkTDArray<double>
addTs(pair.second(), precision, inflectT[0], 1, ts);
return;
}
- if (inflections == 2) {
- if (inflectT[0] > inflectT[1]) {
- SkTSwap(inflectT[0], inflectT[1]);
- }
+ if (inflections > 1) {
Cubic part;
sub_divide(cubic, 0, inflectT[0], part);
addTs(part, precision, 0, inflectT[0], ts);
- sub_divide(cubic, inflectT[0], inflectT[1], part);
- addTs(part, precision, inflectT[0], inflectT[1], ts);
- sub_divide(cubic, inflectT[1], 1, part);
- addTs(part, precision, inflectT[1], 1, ts);
+ int last = inflections - 1;
+ for (int idx = 0; idx < last; ++idx) {
+ sub_divide(cubic, inflectT[idx], inflectT[idx + 1], part);
+ addTs(part, precision, inflectT[idx], inflectT[idx + 1], ts);
+ }
+ sub_divide(cubic, inflectT[last], 1, part);
+ addTs(part, precision, inflectT[last], 1, ts);
return;
}
addTs(cubic, precision, 0, 1, ts);