求任意点的两条平行线之间的最短距离

时间:2013-04-06 07:52:59

标签: trigonometry vectormath

我需要编写一个可靠的方法来检索以下场景的答案......

给定一个线段AB和一个任意点C,我如何在平行于AB的线上找到通过C点的最近点A? (上面提到的可靠性是指算法能够找到D,同时允许A,B和C的坐标完全是任意的和不可预测的。我已经遇到了一些我无法适应所有的解决方案可能的情况,可悲的是......)

如果下图中显示的数据,我如何可靠地找到D的x,y坐标?

A = <425, 473>
B = <584, 533>
C = <371, 401>
D = <???, ???>

知道AB和CD是平行的,这显然意味着斜率是相同的。

我已经尝试了许多不同的公式无济于事,并且已经持续了好几周。我很难过!

diagram

1 个答案:

答案 0 :(得分:3)

这是一个最小化问题。

通常,N维空间中两点(A和B)之间的欧几里德距离由下式给出     Dist(A,B)= sqrt((A1-B1)^ 2 + ... +(AN-BN)^ 2)

如果你需要找到空间曲线A(t)(嵌入在某个N维空间中的1维物体)和B点之间的最小距离,那么你需要求解这个等式:

d Dist(A(t),B) / dt = 0    // (this is straightforward calculus: we're at either a minimum or maximum when the rate of change is 0)

并根据距离函数测试该组根(t1,t2等)以找出哪一个产生D的最小值。


现在找到以y = mx + b形式通过C的平行线的等式:

m = (Ay - By)/(Ax-Bx)
b = Cy - mCx

让我们以空间曲线的形式写出来,并将其插入第1部分的公式中:

Dist(D(t),A) = sqrt((t-Ax)^2 + (m*t+b-Ay)^2)

采取我们的衍生物:

d Dist(D(t),A)/ dt = d sqrt((t-Ax)^2 + (m*t+b-Ay)^2) / dt 

= (t + (m^2)*t - Ax + m*b - m*Ay)/sqrt(t^2 + (m^2)t^2 - 2*t*Ax + 2*m*t*b - 2*m*t*Ay + (Ax)^2 + (Ay)^2 + b^2 - 2*b*Ay )
= ((1+m^2)*t - Ax + m*b - m*Ay)/sqrt((1+m^2)*(t^2)  + 2*t*(m*b - Ax - m*Ay) + (Ax)^2 + (Ay)^2 + b^2 - 2*b*Ay )

设置此值等于0并求解t得率:     t =(Ax-m * b + m * Ay)/(1 + m ^ 2) 作为唯一的根(您可以通过替换回来并验证所有内容都根据需要取消来自行检查。)

将此值重新插入到我们的空间曲线中会产生以下结果:     d =≤(斧-M * B + M * AY)/(1 + M ^ 2),B + M *(AX-M * B + M * AY)/(1 + M ^ 2)&GT; < / p>

如果您想要A,B,C中的显式解决方案,或者如果您只想要数值解,您可以将其计算为三步过程,则可以插入m和b的表达式:

m = (Ay - By)/(Ax-Bx)
b = Cy - mCx
D=<(Ax-m*b+m*Ay)/(1+m^2),b+m*(Ax-m*b+m*Ay)/(1+m^2)>

这对所有具有平行直线的情况都有效。将其作为数字(而非分析)代码实现时需要注意的一点是:如果线条垂直定向,计算m =(Ay-By)/(Ax-Bx)将导致除以0,这将使您的代码无法工作。你可以按如下方式安装安全阀:

if( Ax == Bx) {
    D = <Cx,Ay>
} else {
    // normal calculation here
}

对于严肃的数值工作,你可能想要在公差方面实现它,而不是由于舍入误差和所有有趣的东西(即abs(Ax-Bx)&lt; epsilon,而不是Ax ==)直接比较BX)