我想写一个简洁的代码来计算一个点和任何方向上的任何线段之间的最短距离。据我所知,在许多情况下,最短距离是从点到线段垂直的线,在某些情况下,是连接线段两端点的线(以较小者为准)。
我完成了我的研究并编写了一些代码!结果并不完全正确,您可以在下面的附图中看到,其中红线在每次迭代中根据其长度而变化,并且计算从星到每条线的最短距离以获得距离的分布。正如您在某些线段中看到的那样,应该垂直的最短距离实际上不是。
我编码的方式是使用d=sqrt((xstar-xline)^2+(ystar-yline)^2)
,然后根据xline
最小化它,并考虑每个线段的x端坐标,获取xline
和{{1}然后将星号连接到该行上的那个点,但可以看出它看起来不正确。
任何人都可以通过发布代码或伪代码或算法来帮忙吗?
问题仍未解决!
请考虑附图中的左上角线段:
yline
并且我使用了与答案中提到的完全相同的算法,但由于未将A = [-157.5461 559.9243];
B = [-127.6786 390.5373];
P = [-70 450];
连接到P
,最短距离似乎不正确!
答案 0 :(得分:1)
在我看来,分析解决这个问题要简单得多。让我们来看一个例子。
让我们说你的线段是
y = x + 4, defined for x such that 3 <= x <= 4
,您的观点是(6,3)
通过取线段斜率的负倒数可以很容易地找到垂直线的斜率,所以在这种情况下
y = -x + b
然后求解b
的适当值,使你的线穿过该点,替换该点的x和y值。
(3) = -(6) + b ==> b = 9
y = -x + 9
现在我们想找到你的垂直线和原始线(假设它是无限长的,即使它不是)交叉的点。所以我们将它们设置为彼此相等并求解x。
x + 4 = -x + 9
2x = 5
x = 2.5
因此,他们会在x = 2.5
点交叉。我们知道您的线段仅在x such that 3 <= x <= 4
上定义,因此您知道点和初始线之间的最短连接线在这种情况下不是垂直线,而是一个端点。由于x = 2.5
小于线段的域(x值),因此您知道要选择的端点是具有较低值x的端点。因此,你可以计算通过这两点的线,你似乎知道如何做到目前为止你已经尝试过。
答案 1 :(得分:0)
我们已经知道从点P
到无限线的最短距离是由贯穿P
的无限直线给出的。需要注意的是,我们沿着这条无限线处理线段,并且垂直线交叉可能落在线段之外。让我们从三点的定义开始:
P = [xP yP]; % Point coordinates
A = [xA yA]; % Starting point of line segment
B = [xB yB]; % Ending point of line segment
现在,让我们考虑一下AP
和AB
之间的dot product,以及AP
上AB
的{{3}}是否相同到dot(AP, AB)/|AB|
,两个向量的点积除以AB
的大小。这是位于向量AP
的{{1}}的组件,它为我们提供了AB
与通过P
的无限直线之间的最短距离的点。 A
(即垂直交叉点)。如果我们再次将该组件除以B
的幅度,它将为我们提供一个参数值,该值在点AB
处为0,在点A
处为1。范围B
之外的值表示最短距离出现在线段之外,并且线段上距离[0 1]
的最近点将是段结束点之一。
现在我们可以整理一个算法:
P
vec = B-A; % Vector from A to B
u = vec*(P-A).'/(vec*vec.'); % Parametric value along AB
if (u <= 0) % Perpendicular is outside segment, closest to A
C = A;
elseif (u >= 1) % Perpendicular is outside segment, closest to B
C = B;
else % Closest point is within segment
C = A+u.*vec;
end
将为您提供最接近C
的线段AB
的点。将此计算扩展为以矢量化方式同时处理多个线段,需要对上述代码进行一些修改......
让我们首先定义一个点和一组3个线段用于此示例:
P
现在我们将复制P = [ 1 1];
A = [ 0 0; ... % Starting points (x, y) of segments
-3 3; ...
0 4];
B = [ 2 -2; ... % Ending points (x, y) of segments
-1 1; ...
3 1];
行以匹配P
和A
,重新处理涉及B
的计算以容纳多个段,并转换参数检查索引操作:
u
这会产生P = repmat(P, [size(A, 1) 1]);
vec = B-A;
u = sum(vec.*(P-A), 2)./sum(vec.*vec, 2);
C = A+[u u].*vec;
C(u < 0, :) = A(u < 0, :);
C(u > 1, :) = B(u >1, :);
的以下结果:
C
我们可以将其可视化如下:
C =
0 0
-1 1
2 2