Speed up Line class by removing internal dependance on Point.

This commit is contained in:
Jürg Lehni 2013-05-26 16:58:34 -07:00
parent c9a669ae37
commit f771233d37

View file

@ -24,11 +24,25 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* @param {Point} point2 * @param {Point} point2
* @param {Boolean} [asVector=false] * @param {Boolean} [asVector=false]
*/ */
initialize: function(point1, point2, asVector) { initialize: function(arg0, arg1, arg2, arg3, arg4) {
this.point = Point.read(arguments); var asVector = false;
this.vector = Point.read(arguments); if (arguments.length >= 4) {
if (!Base.read(arguments)) this._px = arg0;
this.vector = this.vector.subtract(this.point); this._py = arg1;
this._vx = arg2;
this._vy = arg3;
asVector = arg4;
} else {
this._px = arg0.x;
this._py = arg0.y;
this._vx = arg1.x;
this._vy = arg1.y;
asVector = arg2;
}
if (!asVector) {
this._vx -= this._px;
this._vy -= this._py;
}
}, },
/** /**
@ -37,6 +51,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* @name Line#point * @name Line#point
* @type Point * @type Point
*/ */
getPoint: function() {
return Point.create(this._px, this._py);
},
/** /**
* The vector of the line * The vector of the line
@ -44,6 +61,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* @name Line#vector * @name Line#vector
* @type Point * @type Point
*/ */
getVector: function() {
return Point.create(this._vx, this._vy);
},
/** /**
* @param {Line} line * @param {Line} line
@ -52,11 +72,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* if the two lines are colinear, or {@code null} if they don't intersect. * if the two lines are colinear, or {@code null} if they don't intersect.
*/ */
intersect: function(line, isInfinite) { intersect: function(line, isInfinite) {
var p1 = this.point, return Line.intersect(
v1 = this.vector, this._px, this._py, this._vx, this._vy,
p2 = line.point, line._px, line._py, line._vx, line._vy,
v2 = line.vector;
return Line.intersect(p1.x, p1.y, v1.x, v1.y, p2.x, p2.y, v2.x, v2.y,
true, isInfinite); true, isInfinite);
}, },
@ -66,31 +84,9 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* @return {Number} * @return {Number}
*/ */
getSide: function(point) { getSide: function(point) {
point = Point.read(arguments); return Line.getSide(
var v1 = this.vector, this._px, this._py, this._vx, this._vy,
v2 = point.subtract(this.point), point.x, point.y, true);
ccw = v2.cross(v1);
if (ccw === 0) {
ccw = v2.dot(v1);
if (ccw > 0) {
ccw = v2.subtract(v1).dot(v1);
if (ccw < 0)
ccw = 0;
}
}
return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
},
// DOCS: document Line#getSignedDistance(point)
/**
* @param {Point} point
* @return {Number}
*/
getSignedDistance: function(point) {
var m = this.vector.y / this.vector.x, // slope
b = this.point.y - (m * this.point.x); // y offset
// Distance to the linear equation
return (point.y - (m * point.x) - b) / Math.sqrt(m * m + 1);
}, },
// DOCS: document Line#getDistance(point) // DOCS: document Line#getDistance(point)
@ -99,34 +95,70 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
* @return {Number} * @return {Number}
*/ */
getDistance: function(point) { getDistance: function(point) {
return Math.abs(this.getSignedDistance(point)); return Math.abs(Line.getSignedDistance(
this._px, this._py, this._vx, this._vy,
point.x, point.y, true));
}, },
statics: /** @lends Line */{ statics: /** @lends Line */{
intersect: function(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, asVectors, intersect: function(apx, apy, avx, avy, bpx, bpy, bvx, bvy, asVector,
isInfinite) { isInfinite) {
// Convert 2nd points to vectors if they are not specified as such. // Convert 2nd points to vectors if they are not specified as such.
if (!asVectors) { if (!asVector) {
ax2 -= ax1; avx -= apx;
ay2 -= ay1; avy -= apy;
bx2 -= bx1; bvx -= bpx;
by2 -= by1; bvy -= bpy;
} }
var cross = by2 * ax2 - bx2 * ay2; var cross = bvy * avx - bvx * avy;
// Avoid divisions by 0, and errors when getting too close to 0 // Avoid divisions by 0, and errors when getting too close to 0
if (!Numerical.isZero(cross)) { if (!Numerical.isZero(cross)) {
var dx = ax1 - bx1, var dx = apx - bpx,
dy = ay1 - by1, dy = apy - bpy,
ta = (bx2 * dy - by2 * dx) / cross, ta = (bvx * dy - bvy * dx) / cross,
tb = (ax2 * dy - ay2 * dx) / cross; tb = (avx * dy - avy * dx) / cross;
// Check the ranges of t parameters if the line is not allowed // Check the ranges of t parameters if the line is not allowed
// to extend beyond the definition points. // to extend beyond the definition points.
if ((isInfinite || 0 <= ta && ta <= 1) if ((isInfinite || 0 <= ta && ta <= 1)
&& (isInfinite || 0 <= tb && tb <= 1)) && (isInfinite || 0 <= tb && tb <= 1))
return Point.create( return Point.create(
ax1 + ta * ax2, apx + ta * avx,
ay1 + ta * ay2); apy + ta * avy);
} }
},
getSide: function(px, py, vx, vy, x, y, asVector) {
if (!asVector) {
vx -= px;
vy -= py;
}
var vx = x - px,
vy = y - py,
ccw = vx * vy - vy * vx; // ccw = v2.cross(v1);
if (ccw === 0) {
ccw = vx * vx + vy * vy; // ccw = v2.dot(v1);
if (ccw > 0) {
// ccw = v2.subtract(v1).dot(v1);
vx -= vx;
vy -= vy;
ccw = vx * vx + vy * vy;
if (ccw < 0)
ccw = 0;
}
}
return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
},
getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
if (!asVector) {
vx -= px;
vy -= py;
}
// Cache these values since they're used heavily in fatline code
var m = vy / vx, // slope
b = py - m * px; // y offset
// Distance to the linear equation
return (y - (m * x) - b) / Math.sqrt(m * m + 1);
} }
} }
}); });