mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2024-12-29 09:22:22 -05:00
Some code refactoring for #1740
This commit is contained in:
parent
a183dc0c0d
commit
46f1aaeca1
3 changed files with 104 additions and 114 deletions
|
@ -2103,9 +2103,9 @@ new function() { // Scope for bezier intersection using fat-line clipping
|
|||
}
|
||||
|
||||
function getIntersections(curves1, curves2, include, matrix1, matrix2,
|
||||
_returnFirst) {
|
||||
var epsilon = Numerical.GEOMETRIC_EPSILON;
|
||||
var self = !curves2;
|
||||
_returnFirst) {
|
||||
var epsilon = /*#=*/Numerical.GEOMETRIC_EPSILON,
|
||||
self = !curves2;
|
||||
if (self)
|
||||
curves2 = curves1;
|
||||
var length1 = curves1.length,
|
||||
|
@ -2115,17 +2115,15 @@ new function() { // Scope for bezier intersection using fat-line clipping
|
|||
locations = [];
|
||||
|
||||
for (var i = 0; i < length1; i++) {
|
||||
var v = curves1[i].getValues(matrix1);
|
||||
values1[i] = v;
|
||||
values1[i] = curves1[i].getValues(matrix1);
|
||||
}
|
||||
if (!self) {
|
||||
for (var i = 0; i < length2; i++) {
|
||||
var v = curves2[i].getValues(matrix2);
|
||||
values2[i] = v;
|
||||
values2[i] = curves2[i].getValues(matrix2);
|
||||
}
|
||||
}
|
||||
var boundsCollisions = CollisionDetection.findCurveBoundsCollisions(
|
||||
values1, self ? null : values2, epsilon);
|
||||
values1, self ? null : values2, epsilon);
|
||||
for (var index1 = 0; index1 < length1; index1++) {
|
||||
var curve1 = curves1[index1],
|
||||
v1 = values1[index1];
|
||||
|
@ -2146,8 +2144,7 @@ new function() { // Scope for bezier intersection using fat-line clipping
|
|||
var curve2 = curves2[index2],
|
||||
v2 = values2[index2];
|
||||
getCurveIntersections(
|
||||
v1, v2, curve1, curve2, locations, include
|
||||
);
|
||||
v1, v2, curve1, curve2, locations, include);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,8 @@
|
|||
* - Boolean operations on self-intersecting Paths items
|
||||
*
|
||||
* @author Harikrishnan Gopalakrishnan <hari.exeption@gmail.com>
|
||||
* @author Jan Boesenberg <development@iconexperience.com>
|
||||
* @author Jan Boesenberg <jan.boesenberg@gmail.com>
|
||||
* @author Juerg Lehni <juerg@scratchdisk.com>
|
||||
* https://hkrish.com/playground/paperjs/booleanStudy.html
|
||||
*/
|
||||
PathItem.inject(new function() {
|
||||
var min = Math.min,
|
||||
|
@ -179,22 +178,22 @@ PathItem.inject(new function() {
|
|||
horCurvesMap[pathId][curve.getIndex()] = collidingCurves;
|
||||
}
|
||||
|
||||
var vertCurveCollisions =
|
||||
var verCurveCollisions =
|
||||
CollisionDetection.findCurveBoundsCollisions(
|
||||
curvesValues, curvesValues, 0, true, true);
|
||||
var vertCurvesMap = {};
|
||||
var verCurvesMap = {};
|
||||
for (var i = 0; i < curves.length; i++) {
|
||||
var curve = curves[i],
|
||||
collidingCurves = [],
|
||||
collisionIndices = vertCurveCollisions[i];
|
||||
collisionIndices = verCurveCollisions[i];
|
||||
if (collisionIndices) {
|
||||
for (var j = 0; j < collisionIndices.length; j++) {
|
||||
collidingCurves.push(curves[collisionIndices[j]]);
|
||||
}
|
||||
}
|
||||
var pathId = curve.getPath().getId();
|
||||
vertCurvesMap[pathId] = vertCurvesMap[pathId] || {};
|
||||
vertCurvesMap[pathId][curve.getIndex()] = collidingCurves;
|
||||
verCurvesMap[pathId] = verCurvesMap[pathId] || {};
|
||||
verCurvesMap[pathId][curve.getIndex()] = collidingCurves;
|
||||
}
|
||||
|
||||
// Propagate the winding contribution. Winding contribution of
|
||||
|
@ -203,14 +202,14 @@ PathItem.inject(new function() {
|
|||
// in all crossings:
|
||||
for (var i = 0, l = crossings.length; i < l; i++) {
|
||||
propagateWinding(crossings[i]._segment, _path1, _path2,
|
||||
horCurvesMap, vertCurvesMap, operator);
|
||||
horCurvesMap, verCurvesMap, operator);
|
||||
}
|
||||
for (var i = 0, l = segments.length; i < l; i++) {
|
||||
var segment = segments[i],
|
||||
inter = segment._intersection;
|
||||
if (!segment._winding) {
|
||||
propagateWinding(segment, _path1, _path2,
|
||||
horCurvesMap, vertCurvesMap, operator);
|
||||
horCurvesMap, verCurvesMap, operator);
|
||||
}
|
||||
// See if all encountered segments in a path are overlaps.
|
||||
if (!(inter && inter._overlap))
|
||||
|
@ -349,28 +348,28 @@ PathItem.inject(new function() {
|
|||
// Now determine the winding for each path, from large to small.
|
||||
for (var i = 0; i < length; i++) {
|
||||
var path1 = sorted[i],
|
||||
indicesI = collisions[i],
|
||||
entry1 = lookup[path1._id],
|
||||
containerWinding = 0;
|
||||
if (indicesI) {
|
||||
var point = null; // interior point, only get it if required
|
||||
for (var j = indicesI.length - 1; j >= 0; j--) {
|
||||
if (indicesI[j] < i) {
|
||||
containerWinding = 0,
|
||||
indices = collisions[i];
|
||||
if (indices) {
|
||||
var point = null; // interior point, only get it if required.
|
||||
for (var j = indices.length - 1; j >= 0; j--) {
|
||||
if (indices[j] < i) {
|
||||
point = point || path1.getInteriorPoint();
|
||||
var path2 = sorted[indicesI[j]];
|
||||
var path2 = sorted[indices[j]];
|
||||
// As we run through the paths from largest to
|
||||
// smallest, for any current path, all potentially
|
||||
// containing paths have already been processed and
|
||||
// their orientation fixed. To achieve correct
|
||||
// orientation of contained paths based on winding,
|
||||
// we have to find one containing path with
|
||||
// different "insideness" and set opposite orientation.
|
||||
// find one containing path with different
|
||||
// "insideness" and set opposite orientation.
|
||||
if (path2.contains(point)) {
|
||||
var entry2 = lookup[path2._id];
|
||||
containerWinding = entry2.winding;
|
||||
entry1.winding += containerWinding;
|
||||
entry1.container = entry2.exclude ?
|
||||
entry2.container : path2;
|
||||
entry1.container = entry2.exclude
|
||||
? entry2.container : path2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -388,8 +387,8 @@ PathItem.inject(new function() {
|
|||
// If the containing path is not excluded, we're done
|
||||
// searching for the orientation defining path.
|
||||
var container = entry1.container;
|
||||
path1.setClockwise(container ? !container.isClockwise()
|
||||
: clockwise);
|
||||
path1.setClockwise(
|
||||
container ? !container.isClockwise() : clockwise);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -793,8 +792,8 @@ PathItem.inject(new function() {
|
|||
};
|
||||
}
|
||||
|
||||
function propagateWinding(segment, path1, path2, horCurveCollisionsMap,
|
||||
vertCurveCollisionsMap, operator) {
|
||||
function propagateWinding(segment, path1, path2, horCurvesMap, verCurvesMap,
|
||||
operator) {
|
||||
// Here we try to determine the most likely winding number contribution
|
||||
// for the curve-chain starting with this segment. Once we have enough
|
||||
// confidence in the winding contribution, we can propagate it until the
|
||||
|
@ -845,9 +844,8 @@ PathItem.inject(new function() {
|
|||
var wind = null;
|
||||
if (operator.subtract && path2) {
|
||||
// Calculate path winding at point depending on operand.
|
||||
var pathWinding = operand === path1
|
||||
? path2._getWinding(pt, dir, true)
|
||||
: path1._getWinding(pt, dir, true);
|
||||
var otherPath = operand === path1 ? path2 : path1,
|
||||
pathWinding = otherPath._getWinding(pt, dir, true);
|
||||
// Check if curve should be omitted.
|
||||
if (operand === path1 && pathWinding.winding ||
|
||||
operand === path2 && !pathWinding.winding) {
|
||||
|
@ -861,12 +859,13 @@ PathItem.inject(new function() {
|
|||
}
|
||||
}
|
||||
}
|
||||
var pathId = path.getId();
|
||||
var curveIndex = curve.getIndex();
|
||||
var hCollisions = horCurveCollisionsMap[pathId][curveIndex];
|
||||
var vCollisions = vertCurveCollisionsMap[pathId][curveIndex];
|
||||
wind = wind ||
|
||||
getWinding(pt, hCollisions, vCollisions, dir, true);
|
||||
if (!wind) {
|
||||
var pathId = path.getId(),
|
||||
curveIndex = curve.getIndex(),
|
||||
curvesH = horCurvesMap[pathId][curveIndex],
|
||||
curvesV = verCurvesMap[pathId][curveIndex];
|
||||
wind = getWinding(pt, curvesH, curvesV, dir, true);
|
||||
}
|
||||
if (wind.quality > winding.quality)
|
||||
winding = wind;
|
||||
break;
|
||||
|
|
|
@ -14,54 +14,51 @@
|
|||
* @name CollisionDetection
|
||||
* @namespace
|
||||
* @private
|
||||
* @author Jan Boesenberg <jan.boesenberg@gmail.com>
|
||||
*/
|
||||
var CollisionDetection = /** @lends CollisionDetection */{
|
||||
|
||||
var CollisionDetection = /** @lends CollisionDetection */{
|
||||
/**
|
||||
* Finds collisions between axis aligned bounding boxes of items.
|
||||
*
|
||||
* This function takes the bounds of all items in the items1 and items2
|
||||
* arrays and calls findBoundsCollisions().
|
||||
*
|
||||
* @param {Array} itemsA Array of curve values for which collisions should
|
||||
* be found.
|
||||
* @param {Array} [itemsA] Array of curve values that the first array should
|
||||
* be compared with. If not provided, collisions between items within
|
||||
* the first arrray will be returned.
|
||||
* @param {Array} items1 Array of items for which collisions should be
|
||||
* found.
|
||||
* @param {Array} [items2] Array of items that the first array should be
|
||||
* compared with. If not provided, collisions between items within
|
||||
* the first array will be returned.
|
||||
* @param {Number} [tolerance] If provided, the tolerance will be added to
|
||||
* all sides of each bounds when checking for collisions.
|
||||
* @param {Boolean} [sweepVertical] If set to true, the sweep is done
|
||||
* along the y axis.
|
||||
* @param {Boolean} [onlySweepAxisCollisionss] If set to true, no collision
|
||||
* checks will be done on the secondary axis.
|
||||
* @returns {Array} Array containing for the bounds at thes same index in
|
||||
* itemsA an array of the indexes of colliding bounds in itemsB
|
||||
*
|
||||
* @author Jan Boesenberg <jan.boesenberg@gmail.com>
|
||||
* @param {Boolean} [sweepVertical] If true, the sweep is performed along
|
||||
* the y-axis.
|
||||
* @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
|
||||
* items1 an array of the indexes of colliding bounds in items2
|
||||
*/
|
||||
findItemBoundsCollisions: function(itemsA, itemsB, tolerance,
|
||||
sweepVertical, onlySweepAxisCollisions) {
|
||||
var boundsArr1 = new Array(itemsA.length),
|
||||
boundsArr2;
|
||||
for (var i = 0; i < boundsArr1.length; i++) {
|
||||
var bounds = itemsA[i].bounds;
|
||||
boundsArr1[i] = [bounds.left, bounds.top, bounds.right,
|
||||
bounds.bottom];
|
||||
findItemBoundsCollisions: function(items1, items2, tolerance,
|
||||
sweepVertical, onlySweepAxisCollisions) {
|
||||
var bounds1 = new Array(items1.length),
|
||||
bounds2;
|
||||
for (var i = 0; i < items1.length; i++) {
|
||||
var bounds = items1[i].bounds;
|
||||
bounds1[i] = [bounds.left, bounds.top, bounds.right, bounds.bottom];
|
||||
}
|
||||
if (itemsB) {
|
||||
if (itemsB === itemsA) {
|
||||
boundsArr2 = boundsArr1;
|
||||
if (items2) {
|
||||
if (items2 === items1) {
|
||||
bounds2 = bounds1;
|
||||
} else {
|
||||
boundsArr2 = new Array(itemsB.length);
|
||||
for (var i = 0; i < boundsArr2.length; i++) {
|
||||
var bounds = itemsB[i].bounds;
|
||||
boundsArr2[i] = [bounds.left, bounds.top, bounds.right,
|
||||
bounds2 = new Array(items2.length);
|
||||
for (var i = 0; i < items2.length; i++) {
|
||||
var bounds = items2[i].bounds;
|
||||
bounds2[i] = [bounds.left, bounds.top, bounds.right,
|
||||
bounds.bottom];
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.findBoundsCollisions(boundsArr1, boundsArr2, tolerance || 0,
|
||||
sweepVertical, onlySweepAxisCollisions);
|
||||
return this.findBoundsCollisions(bounds1, bounds2, tolerance || 0,
|
||||
sweepVertical, onlySweepAxisCollisions);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -80,25 +77,23 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
|||
* curve bounds within the first arrray will be returned.
|
||||
* @param {Number} [tolerance] If provided, the tolerance will be added to
|
||||
* all sides of each bounds when checking for collisions.
|
||||
* @param {Boolean} [sweepVertical] If set to true, the sweep is done
|
||||
* along the y axis.
|
||||
* @param {Boolean} [onlySweepAxisCollisionss] If set to true, no collision
|
||||
* checks will be done on the secondary axis.
|
||||
* @returns {Array} Array containing for the bounds at thes same index in
|
||||
* curveValuesA an array of the indexes of colliding bounds in
|
||||
* curveValuesB
|
||||
*
|
||||
* @author Jan Boesenberg <jan.boesenberg@gmail.com>
|
||||
* @param {Boolean} [sweepVertical] If true, the sweep is performed along
|
||||
* the y-axis.
|
||||
* @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
|
||||
* curveValues1 an array of the indexes of colliding bounds in
|
||||
* curveValues2
|
||||
*/
|
||||
findCurveBoundsCollisions: function(curvesValues1, curvesValues2,
|
||||
tolerance, sweepVertical, onlySweepAxisCollisions) {
|
||||
tolerance, sweepVertical, onlySweepAxisCollisions) {
|
||||
var min = Math.min,
|
||||
max = Math.max,
|
||||
boundsArr1 = new Array(curvesValues1.length),
|
||||
boundsArr2;
|
||||
for (var i = 0; i < boundsArr1.length; i++) {
|
||||
bounds1 = new Array(curvesValues1.length),
|
||||
bounds2;
|
||||
for (var i = 0; i < bounds1.length; i++) {
|
||||
var v1 = curvesValues1[i];
|
||||
boundsArr1[i] = [
|
||||
bounds1[i] = [
|
||||
min(v1[0], v1[2], v1[4], v1[6]),
|
||||
min(v1[1], v1[3], v1[5], v1[7]),
|
||||
max(v1[0], v1[2], v1[4], v1[6]),
|
||||
|
@ -107,12 +102,12 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
|||
}
|
||||
if (curvesValues2) {
|
||||
if (curvesValues2 === curvesValues1) {
|
||||
boundsArr2 = boundsArr1;
|
||||
bounds2 = bounds1;
|
||||
} else {
|
||||
boundsArr2 = new Array(curvesValues2.length);
|
||||
for (var i = 0; i < boundsArr2.length; i++) {
|
||||
bounds2 = new Array(curvesValues2.length);
|
||||
for (var i = 0; i < bounds2.length; i++) {
|
||||
var v2 = curvesValues2[i];
|
||||
boundsArr2[i] = [
|
||||
bounds2[i] = [
|
||||
min(v2[0], v2[2], v2[4], v2[6]),
|
||||
min(v2[1], v2[3], v2[5], v2[7]),
|
||||
max(v2[0], v2[2], v2[4], v2[6]),
|
||||
|
@ -121,8 +116,8 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
|||
}
|
||||
}
|
||||
}
|
||||
return this.findBoundsCollisions(boundsArr1, boundsArr2,
|
||||
tolerance || 0, sweepVertical, onlySweepAxisCollisions);
|
||||
return this.findBoundsCollisions(bounds1, bounds2,
|
||||
tolerance || 0, sweepVertical, onlySweepAxisCollisions);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -135,9 +130,9 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
|||
* Each entry in the bounds arrays must be an array of length 4 with
|
||||
* x0, y0, x1, and y1 as the array elements.
|
||||
*
|
||||
* The returned array has the same length as boundsArr1. Each entry
|
||||
* The returned array has the same length as bounds1. Each entry
|
||||
* contains an array with all indices of overlapping bounds of
|
||||
* boundsArr2 (or boundsArr1 if boundsArr2 is not provided) sorted
|
||||
* bounds2 (or bounds1 if bounds2 is not provided) sorted
|
||||
* in ascending order.
|
||||
*
|
||||
* If the second bounds array parameter is null, collisions between bounds
|
||||
|
@ -145,21 +140,19 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
|||
* returned for each bounds will not contain the bounds' own index.
|
||||
*
|
||||
*
|
||||
* @param {Array} boundsArr1 Array of bounds objects for which collisions
|
||||
* @param {Array} boundsA Array of bounds objects for which collisions
|
||||
* should be found.
|
||||
* @param {Array} [boundsArr2] Array of bounds that the first array should
|
||||
* @param {Array} [boundsB] Array of bounds that the first array should
|
||||
* be compared with. If not provided, collisions between bounds within
|
||||
* the first arrray will be returned.
|
||||
* @param {Number} [tolerance] If provided, the tolerance will be added to
|
||||
* all sides of each bounds when checking for collisions.
|
||||
* @param {Boolean} [sweepVertical] If set to true, the sweep is done
|
||||
* along the y axis.
|
||||
* @param {Boolean} [onlySweepAxisCollisionss] If set to true, no collision
|
||||
* checks will be done on the secondary axis.
|
||||
* @returns {Array} Array containing for the bounds at thes same index in
|
||||
* boundsA an array of the indexes of colliding bounds in boundsB
|
||||
*
|
||||
* @author Jan Boesenberg <jan.boesenberg@gmail.com>
|
||||
* @param {Boolean} [sweepVertical] If true, the sweep is performed along
|
||||
* the y-axis.
|
||||
* @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
|
||||
* boundsA an array of the indexes of colliding bounds in boundsB
|
||||
*/
|
||||
findBoundsCollisions: function(boundsA, boundsB, tolerance,
|
||||
sweepVertical, onlySweepAxisCollisions) {
|
||||
|
@ -176,7 +169,7 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
|||
lo = 0;
|
||||
hi = indices.length;
|
||||
while (lo < hi) {
|
||||
var mid = (hi + lo) >>> 1; // same as Math.floor((hi+lo)/2)
|
||||
var mid = (hi + lo) >>> 1; // Same as Math.floor((hi + lo) / 2)
|
||||
if (allBounds[indices[mid]][coordinate] < coordinateValue) {
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
|
@ -209,8 +202,9 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
|||
for (var i = 0; i < countAll; i++) {
|
||||
var currentIndex = allIndicesByP0[i],
|
||||
currentBounds = allBounds[currentIndex],
|
||||
currentOriginalIndex = self ? currentIndex
|
||||
: currentIndex - countA, // index in boundsA or boundsB array
|
||||
currentOriginalIndex = self // index in boundsA or boundsB
|
||||
? currentIndex
|
||||
: currentIndex - countA,
|
||||
isCurrentA = currentIndex < countA,
|
||||
isCurrentB = self || currentIndex >= countA,
|
||||
currentCollisions = isCurrentA ? [] : null;
|
||||
|
@ -273,13 +267,13 @@ var CollisionDetection = /** @lends CollisionDetection */{
|
|||
if (activeIndicesByP1.length) {
|
||||
var currentP1 = currentBounds[coordP1],
|
||||
insertIndex =
|
||||
binarySearch(activeIndicesByP1, currentP1, coordP1) + 1;
|
||||
binarySearch(activeIndicesByP1, currentP1, coordP1) + 1;
|
||||
activeIndicesByP1.splice(insertIndex, 0, currentIndex);
|
||||
} else {
|
||||
activeIndicesByP1.push(currentIndex);
|
||||
}
|
||||
}
|
||||
// Sort collision indices in ascending order
|
||||
// Sort collision indices in ascending order.
|
||||
for (var i = 0; i < allCollisions.length; i++) {
|
||||
if (allCollisions[i]) {
|
||||
allCollisions[i].sort(function(i1, i2) {
|
||||
|
|
Loading…
Reference in a new issue