0%

计算点到线段最短距离---矢量法

计算点到线段最短距离——矢量法

一、思路

矢量算法过程清晰,如果具有一定的空间几何基础,则是解决此类问题时应优先考虑>的方法。当需要计算的数据量很大时,这种方式优势明显。

由于矢量具有方向性,故一些方向的判断直接根据其正负号就可以得知,使得其中的一些问题得以很简单的解决。

根据下图,可以看到,我们只需计算矢量AC)将其与矢量AB做比较即可分出以下结果。
矢量法示意

二、步骤

矢量AP矢量AB的单位向量,即可得到AC的长度值;
APAB
AC的模长与AB的单位向量相乘可以构成AC向量,所以容易得到:
矢量法3
最后,根据其正负以及大小可以判断出三种情况:
矢量法4

三、代码实现

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
30
31
32
33
34
35
class Segment
{
private Point pt1;
private Point pt2;
private double length;
public Segment(Point pt1, Point pt2)
{
this.pt1 = pt1;
this.pt2 = pt2;
double dx = Math.Abs(pt1.X - pt2.X);
double dy = Math.Abs(pt1.Y - pt2.Y);
this.length = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
}
/// <summary>
/// Finding the shortest distance from a point to the line segment by vector method(矢量法)
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
public double Dis2Pt(Point p)
{
//两向量点乘 P:p A:pt1 B:pt2 C:垂足
//矢量法
//不存在垂足C,求与A点距离
double APAB = (pt2.X - pt1.X) * (p.X - pt1.X) + (pt2.Y - pt1.Y) * (p.Y - pt1.Y);
if (APAB <= 0) { return Math.Sqrt(Math.Pow((p.X - pt1.X), 2) + Math.Pow((p.Y - pt1.Y), 2)); }
//不存在垂足C,求与B点距离
double AB2 = Math.Pow(length, 2);
if (APAB >= AB2) { return Math.Sqrt(Math.Pow((p.X - pt2.X), 2) + Math.Pow((p.Y - pt2.Y), 2)); }
//存在垂足C
double r = APAB / AB2;
double Cx = pt1.X + (pt2.X - pt1.X) * r;
double Cy = pt1.Y + (pt2.Y - pt1.Y) * r;
return Math.Sqrt(Math.Pow((p.X - Cx), 2) + Math.Pow((p.Y - Cy), 2));
}
}