mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-29 09:22:22 -05:00
Some more optimizations for #1740
This commit is contained in:
parent
c82e5d41f7
commit
a9ebe475e0
3 changed files with 58 additions and 72 deletions
|
@ -2123,7 +2123,7 @@ new function() { // Scope for bezier intersection using fat-line clipping
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var boundsCollisions = CollisionDetection.findCurveBoundsCollisions(
|
var boundsCollisions = CollisionDetection.findCurveBoundsCollisions(
|
||||||
values1, self ? null : values2, epsilon);
|
values1, values2, epsilon);
|
||||||
for (var index1 = 0; index1 < length1; index1++) {
|
for (var index1 = 0; index1 < length1; index1++) {
|
||||||
var curve1 = curves1[index1],
|
var curve1 = curves1[index1],
|
||||||
v1 = values1[index1];
|
v1 = values1[index1];
|
||||||
|
|
|
@ -139,7 +139,7 @@ PathItem.inject(new function() {
|
||||||
curves = [],
|
curves = [],
|
||||||
paths;
|
paths;
|
||||||
|
|
||||||
function collect(paths) {
|
function collectPaths(paths) {
|
||||||
for (var i = 0, l = paths.length; i < l; i++) {
|
for (var i = 0, l = paths.length; i < l; i++) {
|
||||||
var path = paths[i];
|
var path = paths[i];
|
||||||
Base.push(segments, path._segments);
|
Base.push(segments, path._segments);
|
||||||
|
@ -150,50 +150,35 @@ PathItem.inject(new function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCurves(indices) {
|
||||||
|
var list = [];
|
||||||
|
for (var i = 0, l = indices && indices.length; i < l; i++) {
|
||||||
|
list.push(curves[indices[i]]);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
if (crossings.length) {
|
if (crossings.length) {
|
||||||
// Collect all segments and curves of both involved operands.
|
// Collect all segments and curves of both involved operands.
|
||||||
collect(paths1);
|
collectPaths(paths1);
|
||||||
if (paths2)
|
if (paths2)
|
||||||
collect(paths2);
|
collectPaths(paths2);
|
||||||
|
|
||||||
var curvesValues = new Array(curves.length);
|
var curvesValues = new Array(curves.length);
|
||||||
for (var i = 0, l = curves.length; i < l; i++) {
|
for (var i = 0, l = curves.length; i < l; i++) {
|
||||||
curvesValues[i] = curves[i].getValues();
|
curvesValues[i] = curves[i].getValues();
|
||||||
}
|
}
|
||||||
var horCurveCollisions =
|
var curveCollisions = CollisionDetection.findCurveBoundsCollisions(
|
||||||
CollisionDetection.findCurveBoundsCollisions(
|
curvesValues, curvesValues, 0, true);
|
||||||
curvesValues, curvesValues, 0, false, true);
|
var curveCollisionsMap = {};
|
||||||
var horCurvesMap = {};
|
|
||||||
for (var i = 0; i < curves.length; i++) {
|
for (var i = 0; i < curves.length; i++) {
|
||||||
var curve = curves[i],
|
var curve = curves[i],
|
||||||
collidingCurves = [],
|
id = curve._path._id,
|
||||||
collisionIndices = horCurveCollisions[i];
|
map = curveCollisionsMap[id] = curveCollisionsMap[id] || {};
|
||||||
if (collisionIndices) {
|
map[curve.getIndex()] = {
|
||||||
for (var j = 0; j < collisionIndices.length; j++) {
|
hor: getCurves(curveCollisions[i].hor),
|
||||||
collidingCurves.push(curves[collisionIndices[j]]);
|
ver: getCurves(curveCollisions[i].ver)
|
||||||
}
|
};
|
||||||
}
|
|
||||||
var pathId = curve.getPath().getId();
|
|
||||||
horCurvesMap[pathId] = horCurvesMap[pathId] || {};
|
|
||||||
horCurvesMap[pathId][curve.getIndex()] = collidingCurves;
|
|
||||||
}
|
|
||||||
|
|
||||||
var verCurveCollisions =
|
|
||||||
CollisionDetection.findCurveBoundsCollisions(
|
|
||||||
curvesValues, curvesValues, 0, true, true);
|
|
||||||
var verCurvesMap = {};
|
|
||||||
for (var i = 0; i < curves.length; i++) {
|
|
||||||
var curve = curves[i],
|
|
||||||
collidingCurves = [],
|
|
||||||
collisionIndices = verCurveCollisions[i];
|
|
||||||
if (collisionIndices) {
|
|
||||||
for (var j = 0; j < collisionIndices.length; j++) {
|
|
||||||
collidingCurves.push(curves[collisionIndices[j]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var pathId = curve.getPath().getId();
|
|
||||||
verCurvesMap[pathId] = verCurvesMap[pathId] || {};
|
|
||||||
verCurvesMap[pathId][curve.getIndex()] = collidingCurves;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propagate the winding contribution. Winding contribution of
|
// Propagate the winding contribution. Winding contribution of
|
||||||
|
@ -202,14 +187,14 @@ PathItem.inject(new function() {
|
||||||
// in all crossings:
|
// in all crossings:
|
||||||
for (var i = 0, l = crossings.length; i < l; i++) {
|
for (var i = 0, l = crossings.length; i < l; i++) {
|
||||||
propagateWinding(crossings[i]._segment, _path1, _path2,
|
propagateWinding(crossings[i]._segment, _path1, _path2,
|
||||||
horCurvesMap, verCurvesMap, operator);
|
curveCollisionsMap, operator);
|
||||||
}
|
}
|
||||||
for (var i = 0, l = segments.length; i < l; i++) {
|
for (var i = 0, l = segments.length; i < l; i++) {
|
||||||
var segment = segments[i],
|
var segment = segments[i],
|
||||||
inter = segment._intersection;
|
inter = segment._intersection;
|
||||||
if (!segment._winding) {
|
if (!segment._winding) {
|
||||||
propagateWinding(segment, _path1, _path2,
|
propagateWinding(segment, _path1, _path2,
|
||||||
horCurvesMap, verCurvesMap, operator);
|
curveCollisionsMap, operator);
|
||||||
}
|
}
|
||||||
// See if all encountered segments in a path are overlaps.
|
// See if all encountered segments in a path are overlaps.
|
||||||
if (!(inter && inter._overlap))
|
if (!(inter && inter._overlap))
|
||||||
|
@ -533,16 +518,9 @@ PathItem.inject(new function() {
|
||||||
*
|
*
|
||||||
* @param {Point} point the location for which to determine the winding
|
* @param {Point} point the location for which to determine the winding
|
||||||
* contribution
|
* contribution
|
||||||
* @param {Curve[]} curvesH The curves that describe the shape against which
|
* @param {Curve[]} curves The curves that describe the shape against which
|
||||||
* to check, as returned by {@link Path#curves} or
|
* to check, as returned by {@link Path#curves} or
|
||||||
* {@link CompoundPath#curves}. This only has to contain those curves
|
* {@link CompoundPath#curves}.
|
||||||
* that can be crossed by a horizontal line through the point to be
|
|
||||||
* checked.
|
|
||||||
* @param {Curve[]} curvesV The curves that describe the shape against which
|
|
||||||
* to check, as returned by {@link Path#curves} or
|
|
||||||
* {@link CompoundPath#curves}. This only has to contain those curves
|
|
||||||
* that can be crossed by a vertical line through the point to be
|
|
||||||
* checked.
|
|
||||||
* @param {Boolean} [dir=false] the direction in which to determine the
|
* @param {Boolean} [dir=false] the direction in which to determine the
|
||||||
* winding contribution, `false`: in x-direction, `true`: in y-direction
|
* winding contribution, `false`: in x-direction, `true`: in y-direction
|
||||||
* @param {Boolean} [closed=false] determines how areas should be closed
|
* @param {Boolean} [closed=false] determines how areas should be closed
|
||||||
|
@ -555,8 +533,14 @@ PathItem.inject(new function() {
|
||||||
* well as an indication whether the point was situated on the contour
|
* well as an indication whether the point was situated on the contour
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function getWinding(point, curvesH, curvesV, dir, closed, dontFlip) {
|
function getWinding(point, curves, dir, closed, dontFlip) {
|
||||||
var curves = !dir ? curvesV : curvesH;
|
// `curves` can either be an array of curves, or an object containing of
|
||||||
|
// the form `{ hor: [], ver: [] }` (see `curveCollisionsMap`), with each
|
||||||
|
// key / value pair holding only those curves that can be crossed by a
|
||||||
|
// horizontal / vertical line through the point to be checked.
|
||||||
|
var curvesList = Array.isArray(curves)
|
||||||
|
? curves
|
||||||
|
: curves[dir ? 'hor' : 'ver'];
|
||||||
// Determine the index of the abscissa and ordinate values in the curve
|
// Determine the index of the abscissa and ordinate values in the curve
|
||||||
// values arrays, based on the direction:
|
// values arrays, based on the direction:
|
||||||
var ia = dir ? 1 : 0, // the abscissa index
|
var ia = dir ? 1 : 0, // the abscissa index
|
||||||
|
@ -671,7 +655,7 @@ PathItem.inject(new function() {
|
||||||
// again with flipped direction and return that result instead.
|
// again with flipped direction and return that result instead.
|
||||||
return !dontFlip && a > paL && a < paR
|
return !dontFlip && a > paL && a < paR
|
||||||
&& Curve.getTangent(v, t)[dir ? 'x' : 'y'] === 0
|
&& Curve.getTangent(v, t)[dir ? 'x' : 'y'] === 0
|
||||||
&& getWinding(point, curvesH, curvesV, !dir, closed, true);
|
&& getWinding(point, curves, !dir, closed, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCurve(v) {
|
function handleCurve(v) {
|
||||||
|
@ -702,12 +686,12 @@ PathItem.inject(new function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0, l = curves.length; i < l; i++) {
|
for (var i = 0, l = curvesList.length; i < l; i++) {
|
||||||
var curve = curves[i],
|
var curve = curvesList[i],
|
||||||
path = curve._path,
|
path = curve._path,
|
||||||
v = curve.getValues(),
|
v = curve.getValues(),
|
||||||
res;
|
res;
|
||||||
if (!i || curves[i - 1]._path !== path) {
|
if (!i || curvesList[i - 1]._path !== path) {
|
||||||
// We're on a new (sub-)path, so we need to determine values of
|
// We're on a new (sub-)path, so we need to determine values of
|
||||||
// the last non-horizontal curve on this path.
|
// the last non-horizontal curve on this path.
|
||||||
vPrev = null;
|
vPrev = null;
|
||||||
|
@ -751,7 +735,7 @@ PathItem.inject(new function() {
|
||||||
if (res = handleCurve(v))
|
if (res = handleCurve(v))
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if (i + 1 === l || curves[i + 1]._path !== path) {
|
if (i + 1 === l || curvesList[i + 1]._path !== path) {
|
||||||
// We're at the last curve of the current (sub-)path. If a
|
// We're at the last curve of the current (sub-)path. If a
|
||||||
// closing curve was calculated at the beginning of it, handle
|
// closing curve was calculated at the beginning of it, handle
|
||||||
// it now to treat the path as closed:
|
// it now to treat the path as closed:
|
||||||
|
@ -792,7 +776,7 @@ PathItem.inject(new function() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function propagateWinding(segment, path1, path2, horCurvesMap, verCurvesMap,
|
function propagateWinding(segment, path1, path2, curveCollisionsMap,
|
||||||
operator) {
|
operator) {
|
||||||
// Here we try to determine the most likely winding number contribution
|
// Here we try to determine the most likely winding number contribution
|
||||||
// for the curve-chain starting with this segment. Once we have enough
|
// for the curve-chain starting with this segment. Once we have enough
|
||||||
|
@ -859,13 +843,9 @@ PathItem.inject(new function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!wind) {
|
wind = wind || getWinding(
|
||||||
var pathId = path.getId(),
|
pt, curveCollisionsMap[path._id][curve.getIndex()],
|
||||||
curveIndex = curve.getIndex(),
|
dir, true);
|
||||||
curvesH = horCurvesMap[pathId][curveIndex],
|
|
||||||
curvesV = verCurvesMap[pathId][curveIndex];
|
|
||||||
wind = getWinding(pt, curvesH, curvesV, dir, true);
|
|
||||||
}
|
|
||||||
if (wind.quality > winding.quality)
|
if (wind.quality > winding.quality)
|
||||||
winding = wind;
|
winding = wind;
|
||||||
break;
|
break;
|
||||||
|
@ -1141,8 +1121,7 @@ PathItem.inject(new function() {
|
||||||
* @return {Number} the winding number
|
* @return {Number} the winding number
|
||||||
*/
|
*/
|
||||||
_getWinding: function(point, dir, closed) {
|
_getWinding: function(point, dir, closed) {
|
||||||
var curves = this.getCurves();
|
return getWinding(point, this.getCurves(), dir, closed);
|
||||||
return getWinding(point, curves, curves, dir, closed);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -66,15 +66,12 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
||||||
* bounds within the first arrray will be returned.
|
* bounds within the first arrray will be returned.
|
||||||
* @param {Number} [tolerance] If provided, the tolerance will be added to
|
* @param {Number} [tolerance] If provided, the tolerance will be added to
|
||||||
* all sides of each bounds when checking for collisions.
|
* all sides of each bounds when checking for collisions.
|
||||||
* @param {Boolean} [sweepVertical] If true, the sweep is performed along
|
* @param {Boolean} [bothAxis] If true, the sweep is performed along both
|
||||||
* the y-axis.
|
* axis, and the results include collisions for both: `{ hor, ver }`.
|
||||||
* @param {Boolean} [onlySweepAxisCollisions] If true, no collision checks
|
|
||||||
* will be done on the secondary axis.
|
|
||||||
* @returns {Array} Array containing for the bounds at the same index in
|
* @returns {Array} Array containing for the bounds at the same index in
|
||||||
* curves1 an array of the indexes of colliding bounds in curves2
|
* curves1 an array of the indexes of colliding bounds in curves2
|
||||||
*/
|
*/
|
||||||
findCurveBoundsCollisions: function(curves1, curves2,
|
findCurveBoundsCollisions: function(curves1, curves2, tolerance, bothAxis) {
|
||||||
tolerance, sweepVertical, onlySweepAxisCollisions) {
|
|
||||||
function getBounds(curves) {
|
function getBounds(curves) {
|
||||||
var min = Math.min,
|
var min = Math.min,
|
||||||
max = Math.max,
|
max = Math.max,
|
||||||
|
@ -95,8 +92,18 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
||||||
bounds2 = !curves2 || curves2 === curves1
|
bounds2 = !curves2 || curves2 === curves1
|
||||||
? bounds1
|
? bounds1
|
||||||
: getBounds(curves2);
|
: getBounds(curves2);
|
||||||
return this.findBoundsCollisions(bounds1, bounds2,
|
if (bothAxis) {
|
||||||
tolerance || 0, sweepVertical, onlySweepAxisCollisions);
|
var hor = this.findBoundsCollisions(
|
||||||
|
bounds1, bounds2, tolerance || 0, false, true),
|
||||||
|
ver = this.findBoundsCollisions(
|
||||||
|
bounds1, bounds2, tolerance || 0, true, true),
|
||||||
|
list = [];
|
||||||
|
for (var i = 0, l = hor.length; i < l; i++) {
|
||||||
|
list[i] = { hor: hor[i], ver: ver[i] };
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
return this.findBoundsCollisions(bounds1, bounds2, tolerance || 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue