Improve Path#getArea() and #isClockwise()

This commit is contained in:
Jürg Lehni 2015-09-18 17:27:29 +02:00
parent 17356637ac
commit 85311cfb29

View file

@ -151,7 +151,8 @@ var Path = PathItem.extend(/** @lends Path# */{
parent._currentPath = undefined; parent._currentPath = undefined;
// Clockwise state becomes undefined as soon as geometry changes. // Clockwise state becomes undefined as soon as geometry changes.
// Also clear cached mono curves used for winding calculations. // Also clear cached mono curves used for winding calculations.
this._length = this._clockwise = this._monoCurves = undefined; this._length = this._area = this._clockwise = this._monoCurves =
undefined;
if (flags & /*#=*/ChangeFlag.SEGMENTS) { if (flags & /*#=*/ChangeFlag.SEGMENTS) {
this._version++; // See CurveLocation this._version++; // See CurveLocation
} else if (this._curves) { } else if (this._curves) {
@ -806,10 +807,11 @@ var Path = PathItem.extend(/** @lends Path# */{
*/ */
getLength: function() { getLength: function() {
if (this._length == null) { if (this._length == null) {
var curves = this.getCurves(); var curves = this.getCurves(),
this._length = 0; length = 0;
for (var i = 0, l = curves.length; i < l; i++) for (var i = 0, l = curves.length; i < l; i++)
this._length += curves[i].getLength(); length += curves[i].getLength();
this._length = length;
} }
return this._length; return this._length;
}, },
@ -822,11 +824,50 @@ var Path = PathItem.extend(/** @lends Path# */{
* @bean * @bean
*/ */
getArea: function() { getArea: function() {
var curves = this.getCurves(); if (this._area == null) {
var area = 0; var segments = this._segments,
for (var i = 0, l = curves.length; i < l; i++) count = segments.length,
area += curves[i].getArea(); last = count - 1,
return area; area = 0;
for (var i = 0, l = this._closed ? count : last; i < l; i++) {
area += Curve.getArea(Curve.getValues(
segments[i], segments[i < last ? i + 1 : 0]));
}
this._area = area;
}
return this._area;
},
/**
* Specifies whether the path is oriented clock-wise.
*
* @type Boolean
* @bean
*/
isClockwise: function() {
if (this._clockwise !== undefined)
return this._clockwise;
var segments = this._segments,
count = segments.length,
last = count - 1,
sum = 0;
// TODO: Check if this works correctly for all open paths.
for (var i = 0, l = this._closed ? count : last; i < l; i++) {
sum += Curve.getEdgeSum(Curve.getValues(
segments[i], segments[i < last ? i + 1 : 0]));
}
return sum > 0;
},
setClockwise: function(clockwise) {
// Only revers the path if its clockwise orientation is not the same
// as what it is now demanded to be.
// On-the-fly conversion to boolean:
if (this.isClockwise() != (clockwise = !!clockwise))
this.reverse();
// Reverse only flips _clockwise state if it was already set, so let's
// always set this here now.
this._clockwise = clockwise;
}, },
/** /**
@ -1223,29 +1264,6 @@ var Path = PathItem.extend(/** @lends Path# */{
return null; return null;
}, },
/**
* Specifies whether the path is oriented clock-wise.
*
* @type Boolean
* @bean
*/
isClockwise: function() {
if (this._clockwise !== undefined)
return this._clockwise;
return Path.isClockwise(this._segments);
},
setClockwise: function(clockwise) {
// Only revers the path if its clockwise orientation is not the same
// as what it is now demanded to be.
// On-the-fly conversion to boolean:
if (this.isClockwise() != (clockwise = !!clockwise))
this.reverse();
// Reverse only flips _clockwise state if it was already set, so let's
// always set this here now.
this._clockwise = clockwise;
},
/** /**
* Reverses the orientation of the path, by reversing all its segments. * Reverses the orientation of the path, by reversing all its segments.
*/ */
@ -2684,21 +2702,6 @@ new function() { // PostScript-style drawing commands
// Mess with indentation in order to get more line-space below: // Mess with indentation in order to get more line-space below:
statics: { statics: {
/**
* Determines whether the segments describe a path in clockwise or counter-
* clockwise orientation.
*
* @private
*/
isClockwise: function(segments) {
var sum = 0;
// TODO: Check if this works correctly for all open paths.
for (var i = 0, l = segments.length; i < l; i++)
sum += Curve.getEdgeSum(Curve.getValues(
segments[i], segments[i + 1 < l ? i + 1 : 0]));
return sum > 0;
},
/** /**
* Returns the bounding rectangle of the item excluding stroke width. * Returns the bounding rectangle of the item excluding stroke width.
* *