|
@@ -78,81 +78,112 @@ THREE.Ray.prototype = {
|
|
|
|
|
|
}(),
|
|
}(),
|
|
|
|
|
|
- distanceSqAndPointToSegment: function ( v0, v1, optionalPointOnLine, optionalPointOnSegment ) {
|
|
|
|
|
|
+ distanceToSegment: function( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
|
|
|
|
|
|
- // from http://www.geometrictools.com/LibMathematics/Distance/Wm5DistLine3Segment3.cpp
|
|
|
|
- // It returns the min distance between the ray (actually... the line) and the segment
|
|
|
|
|
|
+ // from http://www.geometrictools.com/LibMathematics/Distance/Wm5DistRay3Segment3.cpp
|
|
|
|
+ // It returns the min distance between the ray and the segment
|
|
// defined by v0 and v1
|
|
// defined by v0 and v1
|
|
// It can also set two optional targets :
|
|
// It can also set two optional targets :
|
|
- // - The closest point on the ray (...line)
|
|
|
|
|
|
+ // - The closest point on the ray
|
|
// - The closest point on the segment
|
|
// - The closest point on the segment
|
|
|
|
|
|
var segCenter = v0.clone().add( v1 ).multiplyScalar( 0.5 );
|
|
var segCenter = v0.clone().add( v1 ).multiplyScalar( 0.5 );
|
|
var segDir = v1.clone().sub( v0 ).normalize();
|
|
var segDir = v1.clone().sub( v0 ).normalize();
|
|
- var segExtent = v0.distanceTo( v1 ) *0.5;
|
|
|
|
|
|
+ var segExtent = v0.distanceTo( v1 ) * 0.5;
|
|
var diff = this.origin.clone().sub( segCenter );
|
|
var diff = this.origin.clone().sub( segCenter );
|
|
- var a01 = -this.direction.dot( segDir );
|
|
|
|
|
|
+ var a01 = - this.direction.dot( segDir );
|
|
var b0 = diff.dot( this.direction );
|
|
var b0 = diff.dot( this.direction );
|
|
|
|
+ var b1 = - diff.dot( segDir );
|
|
var c = diff.lengthSq();
|
|
var c = diff.lengthSq();
|
|
var det = Math.abs( 1 - a01 * a01 );
|
|
var det = Math.abs( 1 - a01 * a01 );
|
|
- var b1, s0, s1, sqrDist, extDet;
|
|
|
|
|
|
+ var s0, s1, sqrDist, extDet;
|
|
|
|
+ if (det >= 0) {
|
|
|
|
|
|
- if ( det >= 0 ) {
|
|
|
|
|
|
+ // The ray and segment are not parallel.
|
|
|
|
|
|
- // The line and segment are not parallel.
|
|
|
|
-
|
|
|
|
- b1 = -diff.dot( segDir );
|
|
|
|
|
|
+ s0 = a01 * b1 - b0;
|
|
s1 = a01 * b0 - b1;
|
|
s1 = a01 * b0 - b1;
|
|
extDet = segExtent * det;
|
|
extDet = segExtent * det;
|
|
|
|
|
|
- if ( s1 >= -extDet ) {
|
|
|
|
|
|
+ if (s0 >= 0) {
|
|
|
|
+
|
|
|
|
+ if (s1 >= -extDet) {
|
|
|
|
+
|
|
|
|
+ if (s1 <= extDet) {
|
|
|
|
+
|
|
|
|
+ // region 0
|
|
|
|
+ // Minimum at interior points of ray and segment.
|
|
|
|
+
|
|
|
|
+ var invDet = 1 / det;
|
|
|
|
+ s0 *= invDet;
|
|
|
|
+ s1 *= invDet;
|
|
|
|
+ sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
|
|
|
|
|
|
- if ( s1 <= extDet ) {
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- // Two interior points are closest, one on the line and one
|
|
|
|
- // on the segment.
|
|
|
|
|
|
+ // region 1
|
|
|
|
|
|
- var invDet = 1 / det;
|
|
|
|
- s0 = ( a01 * b1 - b0 ) * invDet;
|
|
|
|
- s1 *= invDet;
|
|
|
|
- sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
|
|
|
|
|
|
+ s1 = segExtent;
|
|
|
|
+ s0 = Math.max( 0, - ( a01 * s1 + b0) );
|
|
|
|
+ sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- // The endpoint e1 of the segment and an interior point of
|
|
|
|
- // the line are closest.
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ else {
|
|
|
|
+
|
|
|
|
+ // region 5
|
|
|
|
|
|
- s1 = segExtent;
|
|
|
|
- s0 = - ( a01 * s1 + b0 );
|
|
|
|
|
|
+ s1 = - segExtent;
|
|
|
|
+ s0 = Math.max( 0, - ( a01 * s1 + b0) );
|
|
sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
|
|
sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
- // The end point e0 of the segment and an interior point of the
|
|
|
|
- // line are closest.
|
|
|
|
|
|
+ if ( s1 <= - extDet) {
|
|
|
|
|
|
- s1 = - segExtent;
|
|
|
|
- s0 = - ( a01 * s1 + b0 );
|
|
|
|
- sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
|
|
|
|
|
|
+ // region 4
|
|
|
|
+
|
|
|
|
+ s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
|
|
|
|
+ s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
|
|
|
|
+ sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
|
|
|
|
+
|
|
|
|
+ } else if (s1 <= extDet) {
|
|
|
|
+
|
|
|
|
+ // region 3
|
|
|
|
+
|
|
|
|
+ s0 = 0;
|
|
|
|
+ s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
|
|
|
|
+ sqrDist = s1 * ( s1 + 2 * b1 ) + c;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ // region 2
|
|
|
|
+
|
|
|
|
+ s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
|
|
|
|
+ s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
|
|
|
|
+ sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- // The line and segment are parallel. Choose the closest pair so that
|
|
|
|
- // one point is at segment center.
|
|
|
|
|
|
+ // Ray and segment are parallel.
|
|
|
|
|
|
- s1 = 0;
|
|
|
|
- s0 = - b0;
|
|
|
|
- sqrDist = b0 * s0 + c;
|
|
|
|
|
|
+ s1 = ( a01 > 0 ) ? - segExtent : segExtent;
|
|
|
|
+ s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
|
|
|
|
+ sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- if ( optionalPointOnLine ) {
|
|
|
|
|
|
+ if ( optionalPointOnRay ) {
|
|
|
|
|
|
- optionalPointOnLine.copy( this.direction.clone().multiplyScalar( s0 ).add( this.origin ) );
|
|
|
|
|
|
+ optionalPointOnRay.copy( this.direction.clone().multiplyScalar( s0 ).add( this.origin ) );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|