直线的表示。
直线仍然可以用参数方程(点和向量)来表示,并且射线和线段仍然可以看成参数有取值范围限制的直线,并且点到直线的投影和二维情形一样。
点到直线/线段的距离。仍然可以用面积法(注意三维叉积是向量,要用Length函数而不是fabs)。
点P到直线AB的距离:
double DistanceToLine(const Point3 &P, const Point3 &A, const Point3 &B)
{
Vector3 v1, v2;
v1 = B - A;
v2 = P - A;
return Length(Cross(v1, v2)) / Length(v1);
}
点P到线段AB的距离。
double DistanceToSegment(const Point3 &P, const Point3 &A, const Point3 &B)
{
if(A == B)
return Length(P-A);
Vector3 v1, v2, v3;
v1 = B - A;
v2 = P - A;
v3 = P - B;
if(dcmp(Dot(v1, v2)) < 0)
return Length(v2);
else if(dcmp(Dot(v1, v3)) > 0)
return Length(v3);
else
return Length(Cross(v1, v2)) / Length(v1);
}
异面直线的最短距离:
假设两条直线分别为l1=(p1,v1)和l2=(p2,v2),那么最短距离会在某个q1=p1 + sv1 和 q2 = p2 + tv2 上取到,其中q1和q2分别在l1和l2上
且q1q2是这两条异面直线的公垂线。向量q1q2=q2-q1 = p2-p1 + tv2-sv1垂直于v1, 因此Dot(p2-p1+tv2-sv1)=0.分配率:
Dot(p2-p1,v1) + t*Dot(v2,v1)-s*Dot(v1,v1)=0. 根据q1q2垂直于v2还可以得到一个一次方程,联立。
求异面直线p1+su和p2+tv的公垂线对应的s.如果平行/重合,则返回false。
两条直线相交的情况下算出的距离为0,并且返回true。
bool LineDistance3D(const Point3 &P1,const Vector3 &u,const Point3 &P2,const Vector3 &v, double &s)
{
double a, b;
b = Dot(u, u)*Dot(v, v) - Dot(u, v)*Dot(u, v);
if(dcmp(b) == 0)
return false;
a = Dot(u, v)*Dot(v, P1-P2) - Dot(v, v)*Dot(u, P1-P2);
s = a / b;
return true;
}