7fife-backend/node_modules/sylvester/lib/node-sylvester/line.segment.js

127 lines
4.2 KiB
JavaScript

// Copyright (c) 2011, Chris Umbel, James Coglan
// Line.Segment class - depends on Line and its dependencies.
var Line = require('./line');
var Vector = require('./vector');
Line.Segment = function() {};
Line.Segment.prototype = {
// Returns true iff the line segment is equal to the argument
eql: function(segment) {
return (this.start.eql(segment.start) && this.end.eql(segment.end)) ||
(this.start.eql(segment.end) && this.end.eql(segment.start));
},
// Returns a copy of the line segment
dup: function() {
return Line.Segment.create(this.start, this.end);
},
// Returns the length of the line segment
length: function() {
var A = this.start.elements, B = this.end.elements;
var C1 = B[0] - A[0], C2 = B[1] - A[1], C3 = B[2] - A[2];
return Math.sqrt(C1*C1 + C2*C2 + C3*C3);
},
// Returns the line segment as a vector equal to its
// end point relative to its endpoint
toVector: function() {
var A = this.start.elements, B = this.end.elements;
return Vector.create([B[0] - A[0], B[1] - A[1], B[2] - A[2]]);
},
// Returns the segment's midpoint as a vector
midpoint: function() {
var A = this.start.elements, B = this.end.elements;
return Vector.create([(B[0] + A[0])/2, (B[1] + A[1])/2, (B[2] + A[2])/2]);
},
// Returns the plane that bisects the segment
bisectingPlane: function() {
return Plane.create(this.midpoint(), this.toVector());
},
// Returns the result of translating the line by the given vector/array
translate: function(vector) {
var V = vector.elements || vector;
var S = this.start.elements, E = this.end.elements;
return Line.Segment.create(
[S[0] + V[0], S[1] + V[1], S[2] + (V[2] || 0)],
[E[0] + V[0], E[1] + V[1], E[2] + (V[2] || 0)]
);
},
// Returns true iff the line segment is parallel to the argument. It simply forwards
// the method call onto its line property.
isParallelTo: function(obj) {
return this.line.isParallelTo(obj);
},
// Returns the distance between the argument and the line segment's closest point to the argument
distanceFrom: function(obj) {
var P = this.pointClosestTo(obj);
return (P === null) ? null : P.distanceFrom(obj);
},
// Returns true iff the given point lies on the segment
contains: function(obj) {
if (obj.start && obj.end) { return this.contains(obj.start) && this.contains(obj.end); }
var P = (obj.elements || obj).slice();
if (P.length == 2) { P.push(0); }
if (this.start.eql(P)) { return true; }
var S = this.start.elements;
var V = Vector.create([S[0] - P[0], S[1] - P[1], S[2] - (P[2] || 0)]);
var vect = this.toVector();
return V.isAntiparallelTo(vect) && V.modulus() <= vect.modulus();
},
// Returns true iff the line segment intersects the argument
intersects: function(obj) {
return (this.intersectionWith(obj) !== null);
},
// Returns the unique point of intersection with the argument
intersectionWith: function(obj) {
if (!this.line.intersects(obj)) { return null; }
var P = this.line.intersectionWith(obj);
return (this.contains(P) ? P : null);
},
// Returns the point on the line segment closest to the given object
pointClosestTo: function(obj) {
if (obj.normal) {
// obj is a plane
var V = this.line.intersectionWith(obj);
if (V === null) { return null; }
return this.pointClosestTo(V);
} else {
// obj is a line (segment) or point
var P = this.line.pointClosestTo(obj);
if (P === null) { return null; }
if (this.contains(P)) { return P; }
return (this.line.positionOf(P) < 0 ? this.start : this.end).dup();
}
},
// Set the start and end-points of the segment
setPoints: function(startPoint, endPoint) {
startPoint = Vector.create(startPoint).to3D();
endPoint = Vector.create(endPoint).to3D();
if (startPoint === null || endPoint === null) { return null; }
this.line = Line.create(startPoint, endPoint.subtract(startPoint));
this.start = startPoint;
this.end = endPoint;
return this;
}
};
// Constructor function
Line.Segment.create = function(v1, v2) {
var S = new Line.Segment();
return S.setPoints(v1, v2);
};
module.exports = Line.Segment;