mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-08 05:42:07 -05:00
Merge remote-tracking branch 'origin/master' into bool-fix
This commit is contained in:
commit
971268cd72
3 changed files with 55 additions and 38 deletions
|
@ -483,11 +483,11 @@ statics: {
|
||||||
// 3: curvature, 1st derivative & 2nd derivative
|
// 3: curvature, 1st derivative & 2nd derivative
|
||||||
// Prevent tangents and normals of length 0:
|
// Prevent tangents and normals of length 0:
|
||||||
// http://stackoverflow.com/questions/10506868/
|
// http://stackoverflow.com/questions/10506868/
|
||||||
var tMin = /*#=*/ Numerical.TOLERANCE;
|
var tolerance = /*#=*/ Numerical.TOLERANCE;
|
||||||
if (t < tMin && c1x == p1x && c1y == p1y
|
if (t < tolerance && c1x === p1x && c1y === p1y
|
||||||
|| t > 1 - tMin && c2x == p2x && c2y == p2y) {
|
|| t > 1 - tolerance && c2x === p2x && c2y === p2y) {
|
||||||
x = c2x - c1x;
|
x = p2x - p1x;
|
||||||
y = c2y - c1y;
|
y = p2y - p1y;
|
||||||
} else {
|
} else {
|
||||||
// Simply use the derivation of the bezier function for both
|
// Simply use the derivation of the bezier function for both
|
||||||
// the x and y coordinates:
|
// the x and y coordinates:
|
||||||
|
@ -688,7 +688,7 @@ statics: {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_getWinding: function(v, x, y, roots1, roots2) {
|
_getWinding: function(v, prev, x, y, roots1, roots2) {
|
||||||
// Implementation of the crossing number algorithm:
|
// Implementation of the crossing number algorithm:
|
||||||
// http://en.wikipedia.org/wiki/Point_in_polygon
|
// http://en.wikipedia.org/wiki/Point_in_polygon
|
||||||
// Solve the y-axis cubic polynomial for y and count all solutions
|
// Solve the y-axis cubic polynomial for y and count all solutions
|
||||||
|
@ -701,22 +701,22 @@ statics: {
|
||||||
// which is why we need to split them at y extrema, see below.
|
// which is why we need to split them at y extrema, see below.
|
||||||
// Returns 0 if the curve is outside the boundaries and is not to be
|
// Returns 0 if the curve is outside the boundaries and is not to be
|
||||||
// considered.
|
// considered.
|
||||||
function getOrientation(v) {
|
function getDirection(v) {
|
||||||
var y0 = v[1],
|
var y0 = v[1],
|
||||||
y1 = v[7],
|
y1 = v[7],
|
||||||
dir = y0 <= y1 ? 1 : -1;
|
dir = y0 > y1 ? -1 : 1;
|
||||||
// Bounds check: Reverse y0 and y1 if direction is -1, and exclude
|
// Bounds check: Reverse y0 and y1 if direction is -1.
|
||||||
// end points of curves / lines (y1), to not count corners / joints
|
// Include end points, so we can handle them depending on different
|
||||||
// twice.
|
// edge cases.
|
||||||
return dir === 1 && (y < y0 || y >= y1)
|
return dir === 1 && (y < y0 || y > y1)
|
||||||
|| dir === -1 && (y <= y1 || y > y0)
|
|| dir === -1 && (y < y1 || y > y0)
|
||||||
? 0
|
? 0
|
||||||
: dir;
|
: dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Curve.isLinear(v)) {
|
if (Curve.isLinear(v)) {
|
||||||
// Special simplified case for handling lines.
|
// Special simplified case for handling lines.
|
||||||
var dir = getOrientation(v);
|
var dir = getDirection(v);
|
||||||
if (!dir)
|
if (!dir)
|
||||||
return 0;
|
return 0;
|
||||||
var cross = (v[6] - v[0]) * (y - v[1]) - (v[7] - v[1]) * (x - v[0]);
|
var cross = (v[6] - v[0]) * (y - v[1]) - (v[7] - v[1]) * (x - v[0]);
|
||||||
|
@ -759,7 +759,7 @@ statics: {
|
||||||
part[3] = part[1]; // curve2.handle1.y = curve2.point1.y;
|
part[3] = part[1]; // curve2.handle1.y = curve2.point1.y;
|
||||||
if (i < count)
|
if (i < count)
|
||||||
part[5] = rest[1]; // curve1.handle2.y = curve2.point1.y;
|
part[5] = rest[1]; // curve1.handle2.y = curve2.point1.y;
|
||||||
var dir = getOrientation(part);
|
var dir = getDirection(part);
|
||||||
if (!dir)
|
if (!dir)
|
||||||
continue;
|
continue;
|
||||||
// Adjust start and end range depending on if curve was flipped.
|
// Adjust start and end range depending on if curve was flipped.
|
||||||
|
@ -787,8 +787,14 @@ statics: {
|
||||||
px = t2 === 0 ? part[0] : part[6];
|
px = t2 === 0 ? part[0] : part[6];
|
||||||
}
|
}
|
||||||
// See if we're touching a horizontal stationary point by looking at
|
// See if we're touching a horizontal stationary point by looking at
|
||||||
// the tanget's y coordinate.
|
// the tanget's y coordinate. There are two cases 0:
|
||||||
var flat = abs(Curve.evaluate(part, t2, 1).y) < tolerance;
|
// A) The slope is 0, meaning we're touching a stationary
|
||||||
|
// point inside the curve.
|
||||||
|
// B) t2 == 0 and the slope changes between the current and the
|
||||||
|
// previous curve.
|
||||||
|
var slope = Curve.evaluate(part, t2, 1).y,
|
||||||
|
stationary = abs(slope) < tolerance || t2 < tolerance
|
||||||
|
&& Curve.evaluate(prev, 1, 1).y * slope < 0;
|
||||||
// Calculate compare tolerance based on curve orientation (dir), to
|
// Calculate compare tolerance based on curve orientation (dir), to
|
||||||
// add a bit of tolerance when considering points lying on the curve
|
// add a bit of tolerance when considering points lying on the curve
|
||||||
// as inside. But if we're touching a horizontal stationary point,
|
// as inside. But if we're touching a horizontal stationary point,
|
||||||
|
@ -796,18 +802,23 @@ statics: {
|
||||||
// side-ways in tolerance based on orientation. This is needed e.g.
|
// side-ways in tolerance based on orientation. This is needed e.g.
|
||||||
// when touching the bottom tip of a circle.
|
// when touching the bottom tip of a circle.
|
||||||
// Pass 1 for Curve.evaluate() type to calculate tangent
|
// Pass 1 for Curve.evaluate() type to calculate tangent
|
||||||
if (x >= px + (flat ? -tolerance : tolerance * dir)
|
if (x >= px + (stationary ? -tolerance : tolerance * dir)
|
||||||
// When touching a stationary point, only count it if we're
|
// When touching a stationary point, only count it if we're
|
||||||
// actuall on it.
|
// actuall on it.
|
||||||
&& !(flat && (abs(t2) < tolerance && x != part[0]
|
&& !(stationary && (abs(t2) < tolerance
|
||||||
|| abs(t2 - 1) < tolerance && x != part[6]))) {
|
&& abs(x - part[0]) > tolerance
|
||||||
|
|| abs(t2 - 1) < tolerance
|
||||||
|
&& abs(x - part[6]) > tolerance))) {
|
||||||
// If this is a horizontal stationary point, and we're at the
|
// If this is a horizontal stationary point, and we're at the
|
||||||
// end of the curve (or at the beginning of a curve with
|
// end of the curve (or at the beginning of a curve with
|
||||||
// negative direction, as we're not actually flipping them),
|
// negative direction, as we're not actually flipping them),
|
||||||
// flip dir, as the curve is about to change orientation.
|
// flip dir, as the curve is about to change orientation.
|
||||||
winding += flat && abs(t2 - (dir > 0 ? 1 : 0)) < tolerance
|
winding += stationary && abs(t2 - (dir > 0 ? 1 : 0)) < tolerance
|
||||||
? -dir : dir;
|
? -dir : dir;
|
||||||
}
|
}
|
||||||
|
// Point the previous curve to the newly split part, so stationary
|
||||||
|
// points are correctly detected.
|
||||||
|
prev = part;
|
||||||
}
|
}
|
||||||
return winding;
|
return winding;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1711,20 +1711,22 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
// Create a straight closing line for open paths, just like
|
// Create a straight closing line for open paths, just like
|
||||||
// how filling open paths works.
|
// how filling open paths works.
|
||||||
: new Curve(segments[segments.length - 1]._point,
|
: new Curve(segments[segments.length - 1]._point,
|
||||||
segments[0]._point)).getValues();
|
segments[0]._point)).getValues(),
|
||||||
|
previous = last;
|
||||||
for (var i = 0, l = curves.length; i < l; i++) {
|
for (var i = 0, l = curves.length; i < l; i++) {
|
||||||
var vals = curves[i].getValues(),
|
var curve = curves[i].getValues(),
|
||||||
x = vals[0],
|
x = curve[0],
|
||||||
y = vals[1];
|
y = curve[1];
|
||||||
// Filter out curves with 0-length (all 4 points in the same place):
|
// Filter out curves with 0-length (all 4 points in the same place):
|
||||||
if (!(x === vals[2] && y === vals[3] && x === vals[4]
|
if (!(x === curve[2] && y === curve[3] && x === curve[4]
|
||||||
&& y === vals[5] && x === vals[6] && y === vals[7])) {
|
&& y === curve[5] && x === curve[6] && y === curve[7])) {
|
||||||
winding += Curve._getWinding(vals, point.x, point.y,
|
winding += Curve._getWinding(curve, previous, point.x, point.y,
|
||||||
roots1, roots2);
|
roots1, roots2);
|
||||||
|
previous = curve;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
winding += Curve._getWinding(last, point.x, point.y,
|
winding += Curve._getWinding(last, previous, point.x, point.y,
|
||||||
roots1, roots2);
|
roots1, roots2);
|
||||||
}
|
}
|
||||||
return winding;
|
return winding;
|
||||||
|
@ -1784,12 +1786,16 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
|
|
||||||
function isInArea(point) {
|
function isInArea(point) {
|
||||||
var length = area.length,
|
var length = area.length,
|
||||||
|
previous = getAreaCurve(length - 1),
|
||||||
roots1 = [],
|
roots1 = [],
|
||||||
roots2 = [],
|
roots2 = [],
|
||||||
winding = 0;
|
winding = 0;
|
||||||
for (var i = 0; i < length; i++)
|
for (var i = 0; i < length; i++) {
|
||||||
winding += Curve._getWinding(getAreaCurve(i), point.x, point.y,
|
var curve = getAreaCurve(i);
|
||||||
|
winding += Curve._getWinding(curve, previous, point.x, point.y,
|
||||||
roots1, roots2);
|
roots1, roots2);
|
||||||
|
previous = curve;
|
||||||
|
}
|
||||||
return !!winding;
|
return !!winding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,19 +76,19 @@ var Key = new function() {
|
||||||
scope = view && view.isVisible() && view._scope,
|
scope = view && view.isVisible() && view._scope,
|
||||||
tool = scope && scope._tool,
|
tool = scope && scope._tool,
|
||||||
name;
|
name;
|
||||||
|
keyMap[key] = down;
|
||||||
// Detect modifiers and mark them as pressed / released
|
// Detect modifiers and mark them as pressed / released
|
||||||
if (specialKey && (name = Base.camelize(specialKey)) in modifiers)
|
if (specialKey && (name = Base.camelize(specialKey)) in modifiers)
|
||||||
modifiers[name] = down;
|
modifiers[name] = down;
|
||||||
// Use delete instead of setting to false, so keyMap only contains keys
|
|
||||||
// that are currently down, and can easily be emurated over, e.g. in the
|
|
||||||
// window blur event.
|
|
||||||
if (down) {
|
|
||||||
keyMap[key] = true;
|
|
||||||
// Link the keyCode from keydown with the charCode form keypress,
|
// Link the keyCode from keydown with the charCode form keypress,
|
||||||
// so keyup can retrieve the charCode again.
|
// so keyup can retrieve the charCode again.
|
||||||
|
// Use delete instead of setting to null, so charCodeMap only contains
|
||||||
|
// keyCodes that are currently pressed, allowing the use of `keyCode in
|
||||||
|
// charCodeMap` checks and enumeration over pressed keys, e.g. in the
|
||||||
|
// window blur event.
|
||||||
|
if (down) {
|
||||||
charCodeMap[keyCode] = charCode;
|
charCodeMap[keyCode] = charCode;
|
||||||
} else {
|
} else {
|
||||||
delete keyMap[key];
|
|
||||||
delete charCodeMap[keyCode];
|
delete charCodeMap[keyCode];
|
||||||
}
|
}
|
||||||
if (tool && tool.responds(type)) {
|
if (tool && tool.responds(type)) {
|
||||||
|
@ -135,7 +135,7 @@ var Key = new function() {
|
||||||
DomEvent.add(window, {
|
DomEvent.add(window, {
|
||||||
blur: function(event) {
|
blur: function(event) {
|
||||||
// Fire key-up events for all currently pressed keys.
|
// Fire key-up events for all currently pressed keys.
|
||||||
for (var code in keyMap)
|
for (var code in charCodeMap)
|
||||||
handleKey(false, code, charCodeMap[code], event);
|
handleKey(false, code, charCodeMap[code], event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue