More refactoring for a328f5b04b

This commit is contained in:
Jürg Lehni 2016-06-16 12:07:38 +02:00
parent e80b2ff043
commit 827abd21b8
2 changed files with 73 additions and 74 deletions

View file

@ -622,6 +622,54 @@ statics: /** @lends Curve */{
];
},
/**
* Splits the specified curve values into segments of curves that are
* monotone in the specified coordinate direction (0: monotone in
* x-direction, 1: monotone in y-direction. If the curve is already
* monotone, an array only containing the original values will be returned.
*/
getMonoCurves: function(v, coord) {
var curves = [];
// #getLength() is a rather expensive operation, therefore we test two
// cheap preconditions first.
if (v[0] === v[6] && v[1] === v[7] && Curve.getLength(v) === 0)
return curves;
var o0 = v[1 - coord],
o1 = v[3 - coord],
o2 = v[5 - coord],
o3 = v[7 - coord];
if ((o0 >= o1) === (o1 >= o2) && (o1 >= o2) === (o2 >= o3)
|| Curve.isStraight(v)) {
// Straight curves and curves with points and control points ordered
// in coordinate direction are guaranteed to be monotone.
curves.push(v);
} else {
var a = 3 * (o1 - o2) - o0 + o3,
b = 2 * (o0 + o2) - 4 * o1,
c = o1 - o0,
tMin = 4e-7,
tMax = 1 - tMin,
roots = [],
n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);
if (n === 0) {
curves.push(v);
} else {
roots.sort();
var t = roots[0],
parts = Curve.subdivide(v, t);
curves.push(parts[0]);
if (n > 1) {
t = (roots[1] - t) / (1 - t);
parts = Curve.subdivide(parts[1], t);
curves.push(parts[0]);
}
curves.push(parts[1]);
}
}
return curves;
},
// Converts from the point coordinates (p1, c1, c2, p2) for one axis to
// the polynomial coefficients and solves the polynomial for val
solveCubic: function (v, coord, val, roots, min, max) {
@ -822,53 +870,6 @@ statics: /** @lends Curve */{
+ t * t * t * v3,
padding);
}
},
/**
* Splits the specified curve values into segments of curves that are
* monotone in the specified coordinate direction (0: monotone in
* x-direction, 1: monotone in y-direction. If the curve is already
* monotone, an array only containing the original values will be returned.
*/
splitToMonoCurves: function(v, coord) {
var vMono = [];
// #getLength() is a rather expensive operation, therefore we test two
// cheap preconditions first.
if (v[0] === v[6] && v[1] === v[7] && Curve.getLength(v) === 0)
return vMono;
var o0 = v[1 - coord],
o1 = v[3 - coord],
o2 = v[5 - coord],
o3 = v[7 - coord];
if ((o0 >= o1) === (o1 >= o2) && (o1 >= o2) === (o2 >= o3)
|| Curve.isStraight(v)) {
// Straight curves and curves with points and control points ordered
// in coordinate direction are guaranteed to be monotone.
vMono.push(v);
} else {
var a = 3 * (o1 - o2) - o0 + o3,
b = 2 * (o0 + o2) - 4 * o1,
c = o1 - o0,
tMin = 4e-7,
tMax = 1 - tMin,
roots = [],
n = Numerical.solveQuadratic(a, b, c, roots, tMin, tMax);
if (n === 0) {
vMono.push(v);
} else {
roots.sort();
var t = roots[0],
parts = Curve.subdivide(v, t);
vMono.push(parts[0]);
if (n > 1) {
t = (roots[1] - t) / (1 - t);
parts = Curve.subdivide(parts[1], t);
vMono.push(parts[0]);
}
vMono.push(parts[1]);
}
}
return vMono;
}
}}, Base.each(
['getBounds', 'getStrokeBounds', 'getHandleBounds'],

View file

@ -452,7 +452,7 @@ PathItem.inject(new function() {
( v[coord] > aAfter && v[2 + coord] > aAfter &&
v[4 + coord] > aAfter && v[6 + coord] > aAfter)
? [v]
: Curve.splitToMonoCurves(v, coord);
: Curve.getMonoCurves(v, coord);
for (var j = 0, m = monoCurves.length; j < m; j++) {
vPrev = addWinding(monoCurves[j], vPrev, point.x, point.y,
windings, isOnPath, coord);
@ -980,44 +980,42 @@ Path.inject(/** @lends Path# */{
var bounds = this.getBounds(),
point = bounds.getCenter(true);
if (!this.contains(point)) {
// Since there is no guarantee that a poly-bezier path contains
// the center of its bounding rectangle, we shoot a ray in
// x direction and select a point between the first consecutive
// intersections of the ray on the left.
// Since there is no guarantee that a poly-bezier path contains the
// center of its bounding rectangle, we shoot a ray in x direction
// and select a point between the first consecutive intersections of
// the ray on the left.
var curves = this.getCurves(),
y = point.y,
intercepts = [],
monoCurves = [];
// Collect values for all y-monotone curves that intersect the ray at y
monoCurves = [],
roots = [],
windingPrev = 0;
// Get values for all y-monotone curves that intersect the ray at y.
for (var i = 0, l = curves.length; i < l; i++) {
var monoVals = Curve.splitToMonoCurves(curves[i].getValues(), 0);
for (var j = 0; j < monoVals.length; j++) {
var values = monoVals[j];
if (y >= values[1] && y <= values[7]
|| y >= values[7] && y <= values[1]) {
var winding = values[1] > values[7] ? 1 : values[1] < values[7] ? -1 : 0;
var monos = Curve.getMonoCurves(curves[i].getValues(), 0);
for (var j = 0, m = monos.length; j < m; j++) {
var v = monos[j];
if (y >= v[1] && y <= v[7] || y >= v[7] && y <= v[1]) {
var winding = v[1] > v[7] ? 1 : v[1] < v[7] ? -1 : 0;
if (winding) {
monoCurves.push({values: values, winding: winding});
monoCurves.push({ values: v, winding: winding });
windingPrev = winding;
}
}
}
}
if (!monoCurves.length) {
// fallback in case no non-horizontal curves were found
// Fallback in case no non-horizontal curves were found.
if (!monoCurves.length)
return point;
}
var windingPrev = monoCurves[monoCurves.length - 1].winding;
for (var i = 0, l = monoCurves.length; i < l; i++) {
var v = monoCurves[i].values;
var winding = monoCurves[i].winding;
var roots = [];
var x = y === v[1] ? v[0]
: y === v[7] ? v[6]
: Curve.solveCubic(v, 1, y, roots, 0, 1) === 1
? Curve.getPoint(v, roots[0]).x
: (v[0] + v[6]) / 2;
//if (y != v[1] || winding != windingPrev)
var v = monoCurves[i].values,
winding = monoCurves[i].winding,
x = y === v[1] ? v[0]
: y === v[7] ? v[6]
: Curve.solveCubic(v, 1, y, roots, 0, 1) === 1
? Curve.getPoint(v, roots[0]).x
: (v[0] + v[6]) / 2;
// if (y != v[1] || winding != windingPrev)
intercepts.push(x);
windingPrev = winding;
}