mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-03 19:45:44 -05:00
Improve handling of straight closing curves in open path checks.
This commit is contained in:
parent
e643338422
commit
aee9a3190d
4 changed files with 32 additions and 39 deletions
|
@ -251,11 +251,11 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
|
||||||
* @bean
|
* @bean
|
||||||
* @type Number
|
* @type Number
|
||||||
*/
|
*/
|
||||||
getArea: function(_closed) {
|
getArea: function() {
|
||||||
var children = this._children,
|
var children = this._children,
|
||||||
area = 0;
|
area = 0;
|
||||||
for (var i = 0, l = children.length; i < l; i++)
|
for (var i = 0, l = children.length; i < l; i++)
|
||||||
area += children[i].getArea(_closed);
|
area += children[i].getArea();
|
||||||
return area;
|
return area;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -577,17 +577,21 @@ var Curve = Base.extend(/** @lends Curve# */{
|
||||||
},
|
},
|
||||||
|
|
||||||
statics: /** @lends Curve */{
|
statics: /** @lends Curve */{
|
||||||
getValues: function(segment1, segment2, matrix) {
|
getValues: function(segment1, segment2, matrix, straight) {
|
||||||
var p1 = segment1._point,
|
var p1 = segment1._point,
|
||||||
h1 = segment1._handleOut,
|
h1 = segment1._handleOut,
|
||||||
h2 = segment2._handleIn,
|
h2 = segment2._handleIn,
|
||||||
p2 = segment2._point,
|
p2 = segment2._point,
|
||||||
values = [
|
x1 = p1.x, y1 = p1.y,
|
||||||
p1._x, p1._y,
|
x2 = p2.x, y2 = p2.y,
|
||||||
p1._x + h1._x, p1._y + h1._y,
|
values = straight
|
||||||
p2._x + h2._x, p2._y + h2._y,
|
? [ x1, y1, x1, y1, x2, y2, x2, y2 ]
|
||||||
p2._x, p2._y
|
: [
|
||||||
];
|
x1, y1,
|
||||||
|
x1 + h1._x, y1 + h1._y,
|
||||||
|
x2 + h2._x, y2 + h2._y,
|
||||||
|
x2, y2
|
||||||
|
];
|
||||||
if (matrix)
|
if (matrix)
|
||||||
matrix._transformCoordinates(values, values, 4);
|
matrix._transformCoordinates(values, values, 4);
|
||||||
return values;
|
return values;
|
||||||
|
|
|
@ -828,29 +828,23 @@ var Path = PathItem.extend(/** @lends Path# */{
|
||||||
* @bean
|
* @bean
|
||||||
* @type Number
|
* @type Number
|
||||||
*/
|
*/
|
||||||
getArea: function(_closed) {
|
getArea: function() {
|
||||||
// Cache the area for the open path, and the the final curve separately,
|
var area = this._area;
|
||||||
// so open and closed area can be returned at almost no additional cost.
|
if (area == null) {
|
||||||
var closed = Base.pick(_closed, this._closed),
|
|
||||||
cached = this._area;
|
|
||||||
if (cached == null) {
|
|
||||||
var segments = this._segments,
|
var segments = this._segments,
|
||||||
sum = 0,
|
closed = this._closed;
|
||||||
close = 0;
|
area = 0;
|
||||||
for (var i = 0, l = segments.length; i < l; i++) {
|
for (var i = 0, l = segments.length; i < l; i++) {
|
||||||
var next = i + 1,
|
var last = i + 1 === l;
|
||||||
last = next >= l,
|
area += Curve.getArea(Curve.getValues(
|
||||||
area = Curve.getArea(Curve.getValues(
|
segments[i], segments[last ? 0 : i + 1],
|
||||||
segments[i], segments[last ? 0 : i + 1]));
|
// If this is the last curve and the last is not closed,
|
||||||
if (last) {
|
// connect with a straight curve and ignore the handles.
|
||||||
close = area;
|
null, last && !closed));
|
||||||
} else {
|
|
||||||
sum += area;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cached = this._area = [sum, close];
|
this._area = area;
|
||||||
}
|
}
|
||||||
return cached[0] + (closed ? cached[1] : 0);
|
return area;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -95,7 +95,7 @@ PathItem.inject(new function() {
|
||||||
// Give both paths the same orientation except for subtraction
|
// Give both paths the same orientation except for subtraction
|
||||||
// and exclusion, where we need them at opposite orientation.
|
// and exclusion, where we need them at opposite orientation.
|
||||||
if (_path2 && (operator.subtract || operator.exclude)
|
if (_path2 && (operator.subtract || operator.exclude)
|
||||||
^ (_path2.isClockwise(true) ^ _path1.isClockwise(true)))
|
^ (_path2.isClockwise() ^ _path1.isClockwise()))
|
||||||
_path2.reverse();
|
_path2.reverse();
|
||||||
// Split curves at crossings on both paths. Note that for self-
|
// Split curves at crossings on both paths. Note that for self-
|
||||||
// intersection, path2 is null and getIntersections() handles it.
|
// intersection, path2 is null and getIntersections() handles it.
|
||||||
|
@ -510,15 +510,10 @@ PathItem.inject(new function() {
|
||||||
// - `true`: Connect with a curve that takes the segment handles
|
// - `true`: Connect with a curve that takes the segment handles
|
||||||
// into account, just like how closed paths behave.
|
// into account, just like how closed paths behave.
|
||||||
if (!path._closed) {
|
if (!path._closed) {
|
||||||
var s1 = path.getLastCurve().getSegment2(),
|
vClose = Curve.getValues(
|
||||||
s2 = curve.getSegment1(),
|
path.getLastCurve().getSegment2(),
|
||||||
p1 = s1._point,
|
curve.getSegment1(),
|
||||||
p2 = s2._point,
|
null, !closed);
|
||||||
x1 = p1._x, y1 = p1._y,
|
|
||||||
x2 = p2._x, y2 = p2._y;
|
|
||||||
vClose = closed
|
|
||||||
? Curve.getValues(s1, s2)
|
|
||||||
: [x1, y1, x1, y1, x2, y2, x2, y2];
|
|
||||||
// This closing curve is a potential candidate for the last
|
// This closing curve is a potential candidate for the last
|
||||||
// non-horizontal curve.
|
// non-horizontal curve.
|
||||||
if (vClose[io] !== vClose[io + 6]) {
|
if (vClose[io] !== vClose[io + 6]) {
|
||||||
|
@ -850,7 +845,7 @@ PathItem.inject(new function() {
|
||||||
// close to each other that they are considered the same
|
// close to each other that they are considered the same
|
||||||
// location, but the winding calculation still produces a valid
|
// location, but the winding calculation still produces a valid
|
||||||
// number due to their slight differences producing a tiny area.
|
// number due to their slight differences producing a tiny area.
|
||||||
var area = path.getArea(true);
|
var area = path.getArea();
|
||||||
if (abs(area) >= /*#=*/Numerical.GEOMETRIC_EPSILON) {
|
if (abs(area) >= /*#=*/Numerical.GEOMETRIC_EPSILON) {
|
||||||
// This path wasn't finished and is hence invalid.
|
// This path wasn't finished and is hence invalid.
|
||||||
// Report the error to the console for the time being.
|
// Report the error to the console for the time being.
|
||||||
|
|
Loading…
Reference in a new issue