点到直线距离的向量计算方法:

    这篇文章没有什么特别的,主要就是针对最近的一些想法进行了尝试,其中需要用到相关的数学知识,在这里进行一下总结避免忘记,实际上点到直线的距离计算在GIS应用中十分广泛,在做线缓冲区分析,面缓冲区分析等应用中都会涉及,在这里我的应用类似于对空间三维直线进行缓冲区分析,获取缓冲区内的点云,针对这个应用首要的就是计算点到空间三维直线的距离,点到平面直线距离公式比较简单,在这里就不多做描述,然而相比于2维直线,三维直线在空间中的描述是通过两个平面相交来实现的,因此距离公式就不是这么明确了,一般来说是通过向量来进行计算。



点到直线距离

    如上图所示,点A和点B为空间直线上两点,C点为直线外一点,点到直线的距离为d,假设垂足为O,则AO为直线外一点C到直线AB的投影长度,假设有向量$\overrightarrow{AC}$ 以及向量$\overrightarrow{AB}$,则AO为向量$\overrightarrow{AC}$到$\overrightarrow{AB}$上的的投影,则计算公式为:
$$
|AO|=|\overrightarrow{AC}|cos(\theta)
$$
    则点到直线的距离为:
$$\begin{aligned}
|CO| &=\sqrt{|AC|^{2}-|AO|^{2}} \
&=\sqrt{|AC|^{2}(1-cos^{2}(\theta))}\
&=|AC|*\sqrt{1-(\frac{\overrightarrow{AB}\cdot\overrightarrow{AC}}{|\overrightarrow{AB}||\overrightarrow{AC}|})}
\end{aligned}$$
    根据以上公式可以求取点到直线的距离,以下为代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
double DistanceComputation::Distance(Point3D pt, Point3D pl1, Point3D pl2,bool segment/*=true*/)
{
Point3D ac,ab;
ac.x=pt.x-pl1.x; ac.y=pt.y-pl1.y; ac.z=pt.z-pl1.z;
ab.x=pl2.x-pl1.x;ab.y=pl2.y-pl1.y;ab.z=pl2.z-pl1.z;

double acDotab = ac.x*ab.x+ac.y*ab.y+ac.z*ab.z;
double dis2_ac = ac.x*ac.x+ac.y*ac.y+ac.z*ac.z;
double dis2_ab = ab.x*ab.x+ab.y*ab.y+ab.z*ab.z;

double d12 = dis2_ac;
double d22 = acDotab*acDotab/dis2_ab;

//if compute the segment
if(segment)
{
if(acDotab/sqrt(dis2_ac)/sqrt(dis2_ab)<0)
{
return Distance(pt,pl1);
}else if(acDotab/sqrt(dis2_ab)>sqrt(dis2_ab)){
return Distance(pt,pl2);
}else{
return sqrt(d12-d22);
}
}
else{
return sqrt(d12-d22);
}
}

点到线段的距离计算

    实际上在计算过程中由于直线无限长,因此在计算过程中会计算到点到直线的距离这样与实际结果不相符,一般来说我们需要计算的是点到线段的距离,因此需要有一个线段约束。根据上图所示,如果点C在点线段AB之间,则∠CAB小于90°,若点C在点A之外则∠CAB大于90°,因此当∠CAB大于90°则点到直线的最近距离为点C到点A的距离。此外,当AC在AB上的投影距离大于线段AC的长度则说明点C在B点之外,则点C到线段的最近距离为点C到点B的距离,添加一个判断则能够计算点到线段的距离。