mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 02:38:43 -05:00
Implement better calculation of tangential angles in CurveLocation#isCrossing()
Relates to #1074
This commit is contained in:
parent
5854c25dd5
commit
4966f6250f
2 changed files with 20 additions and 16 deletions
|
@ -448,22 +448,27 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
|||
: angle > min || angle < max;
|
||||
}
|
||||
|
||||
// Calculate angles for all four tangents at the intersection point,
|
||||
// using values for getTangentAt() that are almost 0 and 1.
|
||||
// NOTE: Even though getTangentAt() has code to support 0 and 1 instead
|
||||
// of tMin and tMax, we still need to use tMin / tMaxx instead, as other
|
||||
// issues emerge from switching to 0 and 1 in edge cases.
|
||||
// NOTE: VectorBoolean has code that slowly shifts these points inwards
|
||||
// Calculate angles for all four tangents at the intersection point.
|
||||
// If the intersection is on an actual segment, step away from it at
|
||||
// equal offsets on each curve, to calculate tangential angles that are
|
||||
// unambiguous. The offset is determined by taking 1/64th of the length
|
||||
// of the shortest of all involved curves. This appears to work well.
|
||||
// NOTE: VectorBoolean has code that slowly shifts these offsets inwards
|
||||
// until the resulting tangents are not ambiguous. Do we need this too?
|
||||
// NOTE: We handle t*Inside here simply by picking t1 / t2 instead of
|
||||
// tMin / tMax. E.g. if t1Inside is true, c1 will be the same as c2,
|
||||
// and the code will doe the right thing.
|
||||
// NOTE: We handle t1 / t2Inside here by getting the tangent at t1 / t2
|
||||
// instead of at this calculated offset.
|
||||
// The incomings tangents v1 & v3 are inverted, so that all angles
|
||||
// are pointing outwards in the right direction from the intersection.
|
||||
var v2 = c2.getTangentAtTime(t1Inside ? t1 : tMin),
|
||||
v1 = (t1Inside ? v2 : c1.getTangentAtTime(tMax)).negate(),
|
||||
v4 = c4.getTangentAtTime(t2Inside ? t2 : tMin),
|
||||
v3 = (t2Inside ? v4 : c3.getTangentAtTime(tMax)).negate(),
|
||||
var lenghts = [];
|
||||
if (!t1Inside)
|
||||
lenghts.push(c1.getLength(), c2.getLength());
|
||||
if (!t2Inside)
|
||||
lenghts.push(c3.getLength(), c4.getLength());
|
||||
var offset = Math.min.apply(null, lenghts) / 64;
|
||||
var v2 = t1Inside ? c2.getTangentAtTime(t1) : c2.getTangentAt(offset),
|
||||
v1 = (t1Inside ? v2 : c1.getTangentAt(-offset)).negate(),
|
||||
v4 = t2Inside ? c4.getTangentAtTime(t2) : c4.getTangentAt(offset),
|
||||
v3 = (t2Inside ? v4 : c3.getTangentAt(-offset)).negate(),
|
||||
// NOTE: For shorter API calls we work with angles in degrees here:
|
||||
a1 = v1.getAngle(),
|
||||
a2 = v2.getAngle(),
|
||||
|
|
|
@ -147,9 +147,8 @@ test('#1066', function() {
|
|||
test('#1074', function() {
|
||||
var path1 = new Path('M349.98644,0c-192.98072,0 -349.98644,157.00255 -349.98644,349.98327c0,35.02687 28.39313,63.42 63.42,63.42c35.02687,0 63.42,-28.39313 63.42,-63.42c0,-123.04114 100.10213,-223.14327 223.14644,-223.14327c35.02687,0 63.42,-28.39313 63.42,-63.42c0,-35.02687 -28.39313,-63.42 -63.42,-63.42z');
|
||||
var path2 = new Path('M349.98644,0c-35.02687,0 -63.42,28.39313 -63.42,63.42c0,35.02687 28.39313,63.42 63.42,63.42c59.25965,0 118.69687,22.57118 158.98443,60.37584c25.54558,23.97593 65.67775,22.6885 89.64417,-2.84756c23.96959,-25.5424 22.69168,-65.67775 -2.84756,-89.64417c-63.21071,-59.31355 -155.09044,-94.72411 -245.78104,-94.72411z');
|
||||
var inters = path1.getIntersections(path2);
|
||||
testIntersection(path1.getIntersections(path2), [
|
||||
{ point: { x: 349.98644, y: 0 }, index: 0, time: 0 },
|
||||
{ point: { x: 349.98644, y: 126.84 } , index: 4, time: 0 }
|
||||
{ point: { x: 349.98644, y: 0 }, index: 0, time: 0, crossing: true },
|
||||
{ point: { x: 349.98644, y: 126.84 } , index: 4, time: 0, crossing: true }
|
||||
]);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue