0

我想编写一个简洁的代码来计算点与任何方向上的任何线段之间的最短距离。我知道在许多情况下,最短距离是从点到线段的垂直线,在某些情况下,是连接线段两端点的线(以较小者为准)。

我已经完成了研究并编写了一些代码!结果并不完全正确,如下图所示,其中红线在每次迭代中的长度都会发生变化,并且计算从星到每条线的最短距离,以获得距离的分布。正如您所看到的,对于某些线段,应该垂直的最短距离实际上并非如此。

我编码的方式是使用d=sqrt((xstar-xline)^2+(ystar-yline)^2)然后最小化它,xline并考虑每个线段的x端坐标,获取xline然后yline将星连接到线上的那个点,但是可以看出它看起来不正确.

任何人都可以通过发布代码或伪代码或算法来提供帮助吗?

在此处输入图像描述

问题还没有解决!

请考虑附图中的左上角线段:

A = [-157.5461    559.9243];
B = [-127.6786    390.5373];
P = [-70          450];

而且我使用了与答案中提到的完全相同的算法,但最短距离似乎仍然不正确,因为它没有连接PB

4

2 回答 2

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 值较低的端点。因此,您可以只计算通过这两个点的线,从目前为止的尝试来看,您似乎知道该怎么做。

于 2017-05-16T03:15:52.153 回答
0

推导:

我们已经知道,从一点P到无限线的最短距离由穿过 的无限线的垂线给出P。需要注意的是,我们正在处理沿着这条无限线的线段,并且垂直线交叉可能落在线段之外。让我们从三点的定义开始:

P = [xP yP];  % Point coordinates
A = [xA yA];  % Starting point of line segment
B = [xB yB];  % Ending point of line segment

现在,让我们考虑向量和之间的点积,并且 on 的标量投影等于,两个向量的点积除以 的大小。这是沿向量的分量,并给出了我们与穿过和的无限线之间距离最短的点(即垂直交点)。如果我们再次将该分量除以它的大小,我们将得到一个参数值,即在 point 为 0,在 point 为1 。超出范围的值APABAPABdot(AP, AB)/|AB|ABAPABPABABAB[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最接近的点P。将此计算扩展到以矢量化方式同时处理多个线段将需要对上述代码进行一些修改......

矢量化解决方案:

让我们首先定义一个点和一组 3 条线段用于此示例:

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以匹配AB,重新进行计算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

我们可以将其可视化如下:

plot([A(:,1) B(:,1)].', [A(:,2) B(:,2)].', 'r', 'LineWidth', 2);
hold on;
axis equal;
plot(P(1, 1), P(1, 2), 'bo', 'MarkerSize', 16);
plot([P(:,1) C(:,1)].', [P(:,2) C(:,2)].', 'm--');

在此处输入图像描述

于 2017-05-16T04:53:33.337 回答