Improve data-structure for monotonic curves.

This commit is contained in:
Jürg Lehni 2014-02-21 10:07:27 +01:00
parent 4973ea9845
commit cf4d72f141

View file

@ -270,10 +270,10 @@ PathItem.inject(new function() {
// Find the closest top and bottom intercepts for the same vertical // Find the closest top and bottom intercepts for the same vertical
// line. // line.
for (var i = 0, l = curves.length; i < l; i++) { for (var i = 0, l = curves.length; i < l; i++) {
v = curves[i]; var values = curves[i].values;
if (Curve.solveCubic(v, 0, x, roots, 0, 1) > 0) { if (Curve.solveCubic(values, 0, x, roots, 0, 1) > 0) {
for (var j = roots.length - 1; j >= 0; j--) { for (var j = roots.length - 1; j >= 0; j--) {
var y0 = Curve.evaluate(v, roots[j], 0).y; var y0 = Curve.evaluate(values, roots[j], 0).y;
if (y0 < yBefore && y0 > yTop) { if (y0 < yBefore && y0 > yTop) {
yTop = y0; yTop = y0;
} else if (y0 > yAfter && y0 < yBottom) { } else if (y0 > yAfter && y0 < yBottom) {
@ -296,25 +296,25 @@ PathItem.inject(new function() {
// Find the winding number for right side of the curve, inclusive of // Find the winding number for right side of the curve, inclusive of
// the curve itself, while tracing along its +-x direction. // the curve itself, while tracing along its +-x direction.
for (var i = 0, l = curves.length; i < l; i++) { for (var i = 0, l = curves.length; i < l; i++) {
var v = curves[i]; var curve = curves[i],
if (Curve.solveCubic(v, 1, y, roots, 0, 1 - TOLERANCE) === 1) { values = curve.values;
if (Curve.solveCubic(values, 1, y, roots, 0, 1 - TOLERANCE)
=== 1) {
var t = roots[0], var t = roots[0],
x0 = Curve.evaluate(v, t, 0).x, x0 = Curve.evaluate(values, t, 0).x,
slope = Curve.evaluate(v, t, 1).y; slope = Curve.evaluate(values, t, 1).y;
// Take care of cases where the curve and the preceeding // Take care of cases where the curve and the preceeding
// curve merely touches the ray towards +-x direction, but // curve merely touches the ray towards +-x direction, but
// proceeds to the same side of the ray. This essentially is // proceeds to the same side of the ray. This essentially is
// not a crossing. // not a crossing.
// NOTE: The previous curve is stored at v[9], see if (abs(slope) < TOLERANCE && !Curve.isLinear(values)
// Path#_getMonoCurves() for details. || t < TOLERANCE && slope * Curve.evaluate(
if (abs(slope) < TOLERANCE && !Curve.isLinear(v) curve.previous.values, t, 1).y < 0) {
|| t < TOLERANCE
&& slope * Curve.evaluate(v[9], t, 1).y < 0) {
// TODO: Handle stationary points here! // TODO: Handle stationary points here!
} else if (x0 <= xBefore) { } else if (x0 <= xBefore) {
windLeft += v[8]; windLeft += curve.winding;
} else if (x0 >= xAfter) { } else if (x0 >= xAfter) {
windRight += v[8]; windRight += curve.winding;
} }
} }
} }
@ -528,20 +528,22 @@ Path.inject(/** @lends Path# */{
// Insert curve values into a cached array // Insert curve values into a cached array
function insertCurve(v) { function insertCurve(v) {
var y0 = v[1], var y0 = v[1],
y1 = v[7]; y1 = v[7],
// Add the winding direction to the end of the curve values. curve = {
v[8] = y0 === y1 values: v,
? 0 // Horizontal winding: y0 === y1
: y0 > y1 ? 0 // Horizontal
? -1 // Decreasing : y0 > y1
: 1; // Increasing ? -1 // Decreasing
// Add a reference to neighboring curves : 1, // Increasing
if (prevCurve) { // Add a reference to neighboring curves.
v[9] = prevCurve; previous: prevCurve,
prevCurve[10] = v; next: null // Always set it for hidden class optimization.
} };
monoCurves.push(v); if (prevCurve)
prevCurve = v; prevCurve.next = curve;
monoCurves.push(curve);
prevCurve = curve;
} }
// Handle bezier curves. We need to chop them into smaller curves with // Handle bezier curves. We need to chop them into smaller curves with
@ -608,8 +610,10 @@ Path.inject(/** @lends Path# */{
handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]); handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]);
} }
// Link first and last curves // Link first and last curves
monoCurves[0][9] = prevCurve = monoCurves[monoCurves.length - 1]; var first = monoCurves[0],
prevCurve[10] = monoCurves[0]; last = monoCurves[monoCurves.length - 1];
first.previous = last;
last.next = first;
} }
return monoCurves; return monoCurves;
} }