path-intersection
Advanced tools
Comparing version 2.0.0 to 2.0.1
@@ -9,2 +9,9 @@ # Changelog | ||
## 2.0.1 | ||
* `FIX`: handle path segments with length smaller than five pixel ([`f733e90f`](https://github.com/bpmn-io/path-intersection/commit/f733e90f5fd5251ca103f82d48cf84f5cf4d3ffc)) | ||
* `FIX`: compensate rounding error ([`6433915d`](https://github.com/bpmn-io/path-intersection/commit/6433915d11d6ddab3942c240fe6adf090bc3ca06)) | ||
* `CHORE`: slightly increase duplicate filtering accuracy ([`f37c0567`](https://github.com/bpmn-io/path-intersection/commit/f37c05672a9cfd413b032c4f9dd5a8e54a780541)) | ||
* `CHORE`: various code cleanups | ||
## 2.0.0 | ||
@@ -11,0 +18,0 @@ |
160
intersect.js
'use strict'; | ||
/** | ||
* This file contains portions that got extraced from Snap.svg (licensed Apache-2.0). | ||
* This file contains source code adapted from Snap.svg (licensed Apache-2.0). | ||
* | ||
@@ -156,7 +156,4 @@ * @see https://github.com/adobe-webplatform/Snap.svg/blob/master/src/path.js | ||
function box(x, y, width, height) { | ||
if (x == null) { | ||
x = y = width = height = 0; | ||
} | ||
if (y == null) { | ||
if (arguments.length === 1) { | ||
y = x.y; | ||
@@ -204,37 +201,19 @@ width = x.width; | ||
x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x, | ||
y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y, | ||
mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x), | ||
my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y), | ||
nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x), | ||
ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y), | ||
ax = t1 * p1x + t * c1x, | ||
ay = t1 * p1y + t * c1y, | ||
cx = t1 * c2x + t * p2x, | ||
cy = t1 * c2y + t * p2y, | ||
alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI); | ||
y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y; | ||
return { | ||
x: x, | ||
y: y, | ||
m: { x: mx, y: my }, | ||
n: { x: nx, y: ny }, | ||
start: { x: ax, y: ay }, | ||
end: { x: cx, y: cy }, | ||
alpha: alpha | ||
x: fixError(x), | ||
y: fixError(y) | ||
}; | ||
} | ||
function bezierBBox(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { | ||
function bezierBBox(points) { | ||
if (!is(p1x, 'array')) { | ||
p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y]; | ||
} | ||
var bbox = curveBBox.apply(null, points); | ||
var bbox = curveBBox.apply(null, p1x); | ||
return box( | ||
bbox.min.x, | ||
bbox.min.y, | ||
bbox.max.x - bbox.min.x, | ||
bbox.max.y - bbox.min.y | ||
bbox.x0, | ||
bbox.y0, | ||
bbox.x1 - bbox.x0, | ||
bbox.y1 - bbox.y0 | ||
); | ||
@@ -319,4 +298,4 @@ } | ||
var px = nx / denominator, | ||
py = ny / denominator, | ||
var px = fixError(nx / denominator), | ||
py = fixError(ny / denominator), | ||
px2 = +px.toFixed(2), | ||
@@ -341,2 +320,6 @@ py2 = +py.toFixed(2); | ||
function fixError(number) { | ||
return Math.round(number * 100000000000) / 100000000000; | ||
} | ||
function findBezierIntersections(bez1, bez2, justCount) { | ||
@@ -352,4 +335,4 @@ var bbox1 = bezierBBox(bez1), | ||
l2 = bezlen.apply(0, bez2), | ||
n1 = ~~(l1 / 5), | ||
n2 = ~~(l2 / 5), | ||
n1 = ~~(l1 / 5) || 1, | ||
n2 = ~~(l2 / 5) || 1, | ||
dots1 = [], | ||
@@ -379,11 +362,13 @@ dots2 = [], | ||
cj = abs(dj1.x - dj.x) < .01 ? 'y' : 'x', | ||
is = intersectLines(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y); | ||
is = intersectLines(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y), | ||
key; | ||
if (is) { | ||
key = is.x.toFixed(9) + '#' + is.y.toFixed(9); | ||
if (xy[is.x.toFixed(0)] == is.y.toFixed(0)) { | ||
if (xy[key]) { | ||
continue; | ||
} | ||
xy[is.x.toFixed(0)] = is.y.toFixed(0); | ||
xy[key] = true; | ||
@@ -830,19 +815,21 @@ var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t), | ||
return { | ||
min: { x: mmin.apply(0, bounds[0]), y: mmin.apply(0, bounds[1]) }, | ||
max: { x: mmax.apply(0, bounds[0]), y: mmax.apply(0, bounds[1]) } | ||
x0: mmin.apply(0, bounds[0]), | ||
y0: mmin.apply(0, bounds[1]), | ||
x1: mmax.apply(0, bounds[0]), | ||
y1: mmax.apply(0, bounds[1]) | ||
}; | ||
} | ||
function pathToCurve(path, path2) { | ||
var pth = !path2 && paths(path); | ||
function pathToCurve(path) { | ||
if (!path2 && pth.curve) { | ||
var pth = paths(path); | ||
// return cached curve, if existing | ||
if (pth.curve) { | ||
return pathClone(pth.curve); | ||
} | ||
var p = pathToAbsolute(path), | ||
p2 = path2 && pathToAbsolute(path2), | ||
var curvedPath = pathToAbsolute(path), | ||
attrs = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null }, | ||
attrs2 = { x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null }, | ||
processPath = function(path, d, pcom) { | ||
processPath = function(path, d, pathCommand) { | ||
var nx, ny; | ||
@@ -865,3 +852,3 @@ | ||
case 'S': | ||
if (pcom == 'C' || pcom == 'S') { | ||
if (pathCommand == 'C' || pathCommand == 'S') { | ||
// In 'S' case we have to take into account, if the previous command is C/S. | ||
@@ -881,3 +868,3 @@ nx = d.x * 2 - d.bx; | ||
case 'T': | ||
if (pcom == 'Q' || pcom == 'T') { | ||
if (pathCommand == 'Q' || pathCommand == 'T') { | ||
// In 'T' case we have to take into account, if the previous command is Q/T. | ||
@@ -925,4 +912,3 @@ d.qx = d.x * 2 - d.qx; | ||
while (pi.length) { | ||
pcoms1[i] = 'A'; // if created multiple C:s, their original seg is saved | ||
p2 && (pcoms2[i] = 'A'); // the same as above | ||
pathCommands[i] = 'A'; // if created multiple C:s, their original seg is saved | ||
pp.splice(i++, 0, ['C'].concat(pi.splice(0, 6))); | ||
@@ -932,64 +918,29 @@ } | ||
pp.splice(i, 1); | ||
ii = mmax(p.length, p2 && p2.length || 0); | ||
ii = curvedPath.length; | ||
} | ||
}, | ||
fixM = function(path1, path2, a1, a2, i) { | ||
if (path1 && path2 && path1[i][0] == 'M' && path2[i][0] != 'M') { | ||
path2.splice(i, 0, ['M', a2.x, a2.y]); | ||
a1.bx = 0; | ||
a1.by = 0; | ||
a1.x = path1[i][1]; | ||
a1.y = path1[i][2]; | ||
ii = mmax(p.length, p2 && p2.length || 0); | ||
} | ||
}, | ||
pcoms1 = [], // path commands of original path p | ||
pcoms2 = [], // path commands of original path p2 | ||
pathCommands = [], // path commands of original path p | ||
pfirst = '', // temporary holder for original path command | ||
pcom = ''; // holder for previous path command of original path | ||
pathCommand = ''; // holder for previous path command of original path | ||
for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) { | ||
p[i] && (pfirst = p[i][0]); // save current path command | ||
for (var i = 0, ii = curvedPath.length; i < ii; i++) { | ||
curvedPath[i] && (pfirst = curvedPath[i][0]); // save current path command | ||
if (pfirst != 'C') // C is not saved yet, because it may be result of conversion | ||
{ | ||
pcoms1[i] = pfirst; // Save current path command | ||
i && (pcom = pcoms1[i - 1]); // Get previous path command pcom | ||
pathCommands[i] = pfirst; // Save current path command | ||
i && (pathCommand = pathCommands[i - 1]); // Get previous path command pathCommand | ||
} | ||
p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath | ||
curvedPath[i] = processPath(curvedPath[i], attrs, pathCommand); // Previous path command is inputted to processPath | ||
if (pcoms1[i] != 'A' && pfirst == 'C') pcoms1[i] = 'C'; // A is the only command | ||
if (pathCommands[i] != 'A' && pfirst == 'C') pathCommands[i] = 'C'; // A is the only command | ||
// which may produce multiple C:s | ||
// so we have to make sure that C is also C in original path | ||
fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1 | ||
fixArc(curvedPath, i); // fixArc adds also the right amount of A:s to pathCommands | ||
if (p2) { // the same procedures is done to p2 | ||
p2[i] && (pfirst = p2[i][0]); | ||
var seg = curvedPath[i], | ||
seglen = seg.length; | ||
if (pfirst != 'C') { | ||
pcoms2[i] = pfirst; | ||
i && (pcom = pcoms2[i - 1]); | ||
} | ||
p2[i] = processPath(p2[i], attrs2, pcom); | ||
if (pcoms2[i] != 'A' && pfirst == 'C') { | ||
pcoms2[i] = 'C'; | ||
} | ||
fixArc(p2, i); | ||
} | ||
fixM(p, p2, attrs, attrs2, i); | ||
fixM(p2, p, attrs2, attrs, i); | ||
var seg = p[i], | ||
seg2 = p2 && p2[i], | ||
seglen = seg.length, | ||
seg2len = p2 && seg2.length; | ||
attrs.x = seg[seglen - 2]; | ||
@@ -999,15 +950,10 @@ attrs.y = seg[seglen - 1]; | ||
attrs.by = toFloat(seg[seglen - 3]) || attrs.y; | ||
attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x); | ||
attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y); | ||
attrs2.x = p2 && seg2[seg2len - 2]; | ||
attrs2.y = p2 && seg2[seg2len - 1]; | ||
} | ||
if (!p2) { | ||
pth.curve = pathClone(p); | ||
} | ||
// cache curve | ||
pth.curve = pathClone(curvedPath); | ||
return p2 ? [p, p2] : p; | ||
return curvedPath; | ||
} | ||
module.exports = findPathIntersections; |
{ | ||
"name": "path-intersection", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"description": "Computes the intersection between two SVG paths", | ||
@@ -28,3 +28,2 @@ "main": "intersect.js", | ||
"devDependencies": { | ||
"browserify": "^16.2.0", | ||
"chai": "^4.1.2", | ||
@@ -35,3 +34,2 @@ "domify": "^1.4.0", | ||
"karma": "^1.7.1", | ||
"karma-browserify": "^5.2.0", | ||
"karma-chrome-launcher": "^2.2.0", | ||
@@ -43,2 +41,3 @@ "karma-firefox-launcher": "^1.1.0", | ||
"karma-spec-reporter": "0.0.31", | ||
"karma-webpack": "^4.0.2", | ||
"mocha": "^5.1.1", | ||
@@ -49,4 +48,4 @@ "npm-run-all": "^4.1.2", | ||
"sinon-chai": "^3.0.0", | ||
"watchify": "^3.11.0" | ||
"webpack": "^4.41.2" | ||
} | ||
} |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
18
0
30643
857