mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-07 13:22:07 -05:00
Improve data-structure for monotonic curves.
This commit is contained in:
parent
4973ea9845
commit
cf4d72f141
1 changed files with 34 additions and 30 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue