mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 02:38:43 -05:00
parent
a6933e5b2b
commit
f6233a5028
3 changed files with 54 additions and 30 deletions
|
@ -537,11 +537,12 @@ PathItem.inject(new function() {
|
||||||
qualityEpsilon = 1e-6,
|
qualityEpsilon = 1e-6,
|
||||||
paL = pa - windingEpsilon,
|
paL = pa - windingEpsilon,
|
||||||
paR = pa + windingEpsilon,
|
paR = pa + windingEpsilon,
|
||||||
windingL = 0,
|
winding,
|
||||||
windingR = 0,
|
windings = [],
|
||||||
onPath = false,
|
onPath = false,
|
||||||
quality = 1,
|
quality = 1,
|
||||||
roots = [],
|
roots = [],
|
||||||
|
prevOwner,
|
||||||
vPrev,
|
vPrev,
|
||||||
vClose;
|
vClose;
|
||||||
|
|
||||||
|
@ -586,15 +587,15 @@ PathItem.inject(new function() {
|
||||||
a = t === 0 ? a0
|
a = t === 0 ? a0
|
||||||
: t === 1 ? a3
|
: t === 1 ? a3
|
||||||
: Curve.getPoint(v, t)[dir ? 'y' : 'x'],
|
: Curve.getPoint(v, t)[dir ? 'y' : 'x'],
|
||||||
winding = o0 > o3 ? 1 : -1,
|
wind = o0 > o3 ? 1 : -1,
|
||||||
windingPrev = vPrev[io] > vPrev[io + 6] ? 1 : -1,
|
windPrev = vPrev[io] > vPrev[io + 6] ? 1 : -1,
|
||||||
a3Prev = vPrev[ia + 6];
|
a3Prev = vPrev[ia + 6];
|
||||||
if (po !== o0) {
|
if (po !== o0) {
|
||||||
// Standard case, curve is not crossed at its starting point.
|
// Standard case, curve is not crossed at its starting point.
|
||||||
if (a < paL) {
|
if (a < paL) {
|
||||||
windingL += winding;
|
winding.l += wind;
|
||||||
} else if (a > paR) {
|
} else if (a > paR) {
|
||||||
windingR += winding;
|
winding.r += wind;
|
||||||
} else {
|
} else {
|
||||||
onPath = true;
|
onPath = true;
|
||||||
}
|
}
|
||||||
|
@ -605,13 +606,13 @@ PathItem.inject(new function() {
|
||||||
if (a > pa - qualityEpsilon && a < pa + qualityEpsilon)
|
if (a > pa - qualityEpsilon && a < pa + qualityEpsilon)
|
||||||
quality /= 2;
|
quality /= 2;
|
||||||
} else {
|
} else {
|
||||||
if (winding !== windingPrev) {
|
if (wind !== windPrev) {
|
||||||
// Curve is crossed at starting point and winding changes
|
// Curve is crossed at starting point and winding changes
|
||||||
// from previous curve. Cancel winding from previous curve.
|
// from previous curve. Cancel winding from previous curve.
|
||||||
if (a0 < paL) {
|
if (a0 < paL) {
|
||||||
windingL += winding;
|
winding.l += wind;
|
||||||
} else if (a0 > paR) {
|
} else if (a0 > paR) {
|
||||||
windingR += winding;
|
winding.r += wind;
|
||||||
}
|
}
|
||||||
} else if (a0 != a3Prev) {
|
} else if (a0 != a3Prev) {
|
||||||
// Handle a horizontal curve between the current and
|
// Handle a horizontal curve between the current and
|
||||||
|
@ -619,11 +620,11 @@ PathItem.inject(new function() {
|
||||||
// #1261#issuecomment-282726147 for a detailed explanation:
|
// #1261#issuecomment-282726147 for a detailed explanation:
|
||||||
if (a3Prev < paR && a > paR) {
|
if (a3Prev < paR && a > paR) {
|
||||||
// Right winding was not added before, so add it now.
|
// Right winding was not added before, so add it now.
|
||||||
windingR += winding;
|
winding.r += wind;
|
||||||
onPath = true;
|
onPath = true;
|
||||||
} else if (a3Prev > paL && a < paL) {
|
} else if (a3Prev > paL && a < paL) {
|
||||||
// Left winding was not added before, so add it now.
|
// Left winding was not added before, so add it now.
|
||||||
windingL += winding;
|
winding.l += wind;
|
||||||
onPath = true;
|
onPath = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -675,6 +676,14 @@ PathItem.inject(new function() {
|
||||||
v = curve.getValues(),
|
v = curve.getValues(),
|
||||||
res;
|
res;
|
||||||
if (!i || curves[i - 1]._path !== path) {
|
if (!i || curves[i - 1]._path !== path) {
|
||||||
|
var parent = path._parent,
|
||||||
|
owner = parent instanceof CompoundPath ? parent : path;
|
||||||
|
if (owner !== prevOwner) {
|
||||||
|
windings.push(winding = {
|
||||||
|
l: 0, r: 0, rule: owner.getFillRule()
|
||||||
|
});
|
||||||
|
prevOwner = owner;
|
||||||
|
}
|
||||||
// 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;
|
||||||
|
@ -729,8 +738,27 @@ PathItem.inject(new function() {
|
||||||
}
|
}
|
||||||
// Use the unsigned winding contributions when determining which areas
|
// Use the unsigned winding contributions when determining which areas
|
||||||
// are part of the boolean result.
|
// are part of the boolean result.
|
||||||
|
var windingL = 0,
|
||||||
|
windingR = 0;
|
||||||
|
for (var i = 0; i < windings.length; i++) {
|
||||||
|
var winding = windings[i],
|
||||||
|
l = winding.l,
|
||||||
|
r = winding.r;
|
||||||
|
if (winding.rule === 'evenodd') {
|
||||||
|
l = l & 1;
|
||||||
|
r = r & 1;
|
||||||
|
} else {
|
||||||
|
l = l ? 1 : 0;
|
||||||
|
r = r ? 1 : 0;
|
||||||
|
// l = l < 0 ? -1 : l > 0 ? 1 : 0;
|
||||||
|
// r = r < 0 ? -1 : r > 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
windingL += l;
|
||||||
|
windingR += r;
|
||||||
|
}
|
||||||
windingL = abs(windingL);
|
windingL = abs(windingL);
|
||||||
windingR = abs(windingR);
|
windingR = abs(windingR);
|
||||||
|
console.log(JSON.stringify(windings), windingL, windingR);
|
||||||
// Return the calculated winding contributions along with a quality
|
// Return the calculated winding contributions along with a quality
|
||||||
// value indicating how reliable the value really is.
|
// value indicating how reliable the value really is.
|
||||||
return {
|
return {
|
||||||
|
@ -775,6 +803,7 @@ PathItem.inject(new function() {
|
||||||
var curve = entry.curve,
|
var curve = entry.curve,
|
||||||
path = curve._path,
|
path = curve._path,
|
||||||
parent = path._parent,
|
parent = path._parent,
|
||||||
|
operand = parent instanceof CompoundPath ? parent : path,
|
||||||
t = Numerical.clamp(curve.getTimeAt(length), tMin, tMax),
|
t = Numerical.clamp(curve.getTimeAt(length), tMin, tMax),
|
||||||
pt = curve.getPointAtTime(t),
|
pt = curve.getPointAtTime(t),
|
||||||
// Determine the direction in which to check the winding
|
// Determine the direction in which to check the winding
|
||||||
|
@ -783,15 +812,13 @@ PathItem.inject(new function() {
|
||||||
// than 45°, cast the ray vertically, else horizontally.
|
// than 45°, cast the ray vertically, else horizontally.
|
||||||
dir = abs(curve.getTangentAtTime(t).normalize().y)
|
dir = abs(curve.getTangentAtTime(t).normalize().y)
|
||||||
< Math.SQRT1_2 ? 1 : 0;
|
< Math.SQRT1_2 ? 1 : 0;
|
||||||
if (parent instanceof CompoundPath)
|
|
||||||
path = parent;
|
|
||||||
// While subtracting, we need to omit this curve if it is
|
// While subtracting, we need to omit this curve if it is
|
||||||
// contributing to the second operand and is outside the
|
// contributing to the second operand and is outside the
|
||||||
// first operand.
|
// first operand.
|
||||||
var wind = !(operator.subtract && path2 && (
|
var wind = !(operator.subtract && path2 && (
|
||||||
path === path1 &&
|
operand === path1 &&
|
||||||
path2._getWinding(pt, dir, true).winding ||
|
path2._getWinding(pt, dir, true).winding ||
|
||||||
path === path2 &&
|
operand === path2 &&
|
||||||
!path1._getWinding(pt, dir, true).winding))
|
!path1._getWinding(pt, dir, true).winding))
|
||||||
? getWinding(pt, curves, dir, true)
|
? getWinding(pt, curves, dir, true)
|
||||||
: windingZero;
|
: windingZero;
|
||||||
|
|
|
@ -275,9 +275,7 @@ var PathItem = Item.extend(/** @lends PathItem# */{
|
||||||
: {};
|
: {};
|
||||||
// See #1116#issuecomment-243794824 for an explanation of the
|
// See #1116#issuecomment-243794824 for an explanation of the
|
||||||
// winding.onPath check here.
|
// winding.onPath check here.
|
||||||
return winding.onPath || !!(this.getFillRule() === 'evenodd'
|
return !!(winding.winding || winding.onPath);
|
||||||
? winding.windingL & 1 || winding.windingR & 1
|
|
||||||
: winding.winding);
|
|
||||||
/*#*/ } // !__options.nativeContains && __options.booleanOperations
|
/*#*/ } // !__options.nativeContains && __options.booleanOperations
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -405,20 +405,19 @@ test('#870', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('#875', function() {
|
test('#875', function() {
|
||||||
var p1 = new Path({
|
var path1 = new Path.Circle({
|
||||||
segments: [
|
center: [165, 400],
|
||||||
[158.7, 389.3, 0, 0, -4.95, 4.95],
|
radius: 15,
|
||||||
[158.7, 407.2, -4.95, -4.95, 4.95, 4.95],
|
clockwise: false
|
||||||
[176.6, 407.2, -4.95, 4.95, 4.95, -4.95],
|
});
|
||||||
[176.6, 389.3, 4.95, 4.95, -4.95, -4.95],
|
var path2 = new Path.Circle({
|
||||||
[158.7, 389.3, 4.95, -4.95, 0, 0]
|
center: [260, 320],
|
||||||
],
|
radius: 100,
|
||||||
closed: true
|
clockwise: true
|
||||||
});
|
});
|
||||||
var p2 = new Path.Circle(260, 320, 100);
|
|
||||||
|
|
||||||
compareBoolean(function() { return p1.subtract(p2); },
|
compareBoolean(function() { return path1.subtract(path2); },
|
||||||
'M158.7,407.2c4.95,4.95 12.95,4.95 17.9,0c4.95,-4.95 4.95,-12.95 0,-17.9c-4.95,-4.95 -12.95,-4.95 -17.9,0c-4.95,4.95 -4.95,12.95 0,17.9z');
|
'M165,415c8.28427,0 15,-6.71573 15,-15c0,-8.28427 -6.71573,-15 -15,-15c-8.28427,0 -15,6.71573 -15,15c0,8.28427 6.71573,15 15,15z');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('#877', function() {
|
test('#877', function() {
|
||||||
|
|
Loading…
Reference in a new issue