我正在寻找一个JavaScript的三维公式,可以计算点到直线的距离。该公式也可以用其他的编程语言来实现。其中,P为一个点,A和B是直线上的两个点。
P=(4,2,1);
A=(1,0,1);
B=(1,2,0);
P=(4,2,1);
A=(1,0,1);
B=(1,2,0);
点 P
到线 (A
, V
) 的最近点是线 (X
, P
) 的交点,其中线 (X
, P
) 垂直于线 (A
, B
)。
如果一条线由两个点 A
和 B
定义,则可以计算出表示该线方向的 单位向量 D
(请注意,单位向量的长度为1):
D = normalize(B-A);
V = P - O;
可以通过点积计算从O
到交点(最近点)X
的距离d
。
一般来说,两个向量的点积等于两个向量长度的乘积与它们夹角的余弦值。
dot( A, B ) == | A | * | B | * cos( angle_A_B )
由于 D
是单位向量,向量 V
和 D
的点积等于线段 (O
, D
) 与向量 V
之间夹角的余弦值,乘以向量 V
的模长:
d = dot(V, D);
交点X
可以通过将点O
沿着线(D
)移动距离d
来计算:
X = O + D * d;
因此,交点的公式为:
O ... any point on the line
D ... unit vector which points in the direction of the line
P ... the "Point"
X = O + D * dot(P-O, D);
计算线段 A
、B
和点 P
的交点如下:
D = normalize(B-A);
X = A + D * dot(P-A, D);
三维笛卡尔坐标系的点积可以表示为:
dot(A, B) = Ax*Bx + Ay*By + Az*Bz
可以通过以下方式计算归一化向量(单位向量):
len(A) = sqrt(Ax*Ax + Ay*Ay + Az*Az)
notrmalize(A) = A / len(A)
var P=[4,2,1];
var A=[1,0,1];
var B=[1,2,0];
var AB = [B[0]-A[0], B[1]-A[1], B[2]-A[2]];
var lenAB = Math.sqrt(AB[0]*AB[0] + AB[1]*AB[1] + AB[2]*AB[2]);
var D = [AB[0]/lenAB, AB[1]/lenAB, AB[2]/lenAB];
var AP = [P[0]-A[0], P[1]-A[1], P[2]-A[2]];
var d = D[0]*AP[0] + D[1]*AP[1] + D[2]*AP[2];
var X = [A[0] + d * D[0], A[1] + d * D[1], A[2] + d * D[2]];
使用 Three.js - Vector3
很容易实现此操作,该库定义了向量运算的操作,如 add
、sub
、dot
和 normalize
:
var P = new THREE.Vector3( 4, 2, 1 );
var A = new THREE.Vector3( 1, 0, 1 );
var B = new THREE.Vector3( 1, 2, 0 );
var D = B.clone().sub( A ).normalize();
var d = P.clone().sub( A ).dot( D );
var X = A.clone().add( D.clone().multiplyScalar( d ) );
Line3
的类,可以为你完成这个计算。var line = new THREE.Line3(); // create once and reuse
var P = new THREE.Vector3(); // ditto
var A = new THREE.Vector3();
var B = new THREE.Vector3();
var C = new THREE.Vector3();
P.set( 4, 2, 1 );
A.set( 1, 0, 1 );
B.set( 1, 2, 0 );
// calculate C, the closest point on the (infinite) line AB
line.set( A, B ).closestPointToPoint( P, false, C );
var distance = P.distanceTo( C );
console.log( distance );
three.js r.97
P=new THREE.Vector3(4,2,1);
A=new THREE.Vector3(1,0,1);
B=new THREE.Vector3(1,2,0);
Normal=B.clone ().sub (A).normalize ()
Distance = Normal.multiplyScalar (P.sub (A).dot (Normal)).add (A).sub (P).length ()