过P做MN的垂线,垂足为Q,若Q在线段MN以内(包括与点M点N重合),则最短距离为垂线段长度,若垂足在MN以外,则最短距离为PM,PN中的较小者。(若P与MN共线,垂线长度为零,同样适用)
所以可由 Q位置判断
一、代数法
若Q在线段MN上 则
∣
M
Q
∣
+
∣
Q
N
∣
=
∣
M
N
∣
\lvert MQ \rvert + |QN| = |MN|
∣MQ∣+∣QN∣=∣MN∣
或不开方的
∣
M
Q
∣
2
+
∣
Q
N
∣
2
≤
∣
M
N
∣
2
\lvert MQ \rvert ^2 + |QN|^2 \leq |MN|^2
∣MQ∣2+∣QN∣2≤∣MN∣2
所以最小距离可表示为
{
∣
P
Q
∣
|
M
Q
∣
+
∣
Q
N
∣
=
∣
M
N
∣
M
I
N
(
∣
P
N
∣
,
∣
P
M
∣
)
∣
M
Q
∣
+
∣
Q
N
∣
>
∣
M
N
∣
\left\{ \begin{array}{lcr} \lvert PQ \rvert & & \text |MQ | + |QN| = |MN| \\\\ MIN(|PN|,|PM|) & & \lvert MQ \rvert + |QN| \gt |MN| \end{array} \right.
⎩
⎨
⎧∣PQ∣MIN(∣PN∣,∣PM∣)|MQ∣+∣QN∣=∣MN∣∣MQ∣+∣QN∣>∣MN∣
或
{
∣
P
Q
∣
|
M
Q
∣
2
+
∣
Q
N
∣
2
≤
∣
M
N
∣
2
M
I
N
(
∣
P
N
∣
,
∣
P
M
∣
)
∣
M
Q
∣
2
+
∣
Q
N
∣
2
>
∣
M
N
∣
2
\left\{ \begin{array}{lcr} \lvert PQ \rvert & & \text |MQ | ^2 + |QN|^2 \leq |MN|^2 \\\\ MIN(|PN|,|PM|) & & \lvert MQ \rvert ^2 + |QN|^2 \gt |MN|^2 \end{array} \right.
⎩
⎨
⎧∣PQ∣MIN(∣PN∣,∣PM∣)|MQ∣2+∣QN∣2≤∣MN∣2∣MQ∣2+∣QN∣2>∣MN∣2
计算垂足
∠
b
=
∠
a
+
90
°
\angle b = \angle a + 90\degree
∠b=∠a+90°
tan
(
b
)
=
tan
(
a
+
π
2
)
=
−
cot
(
a
)
\tan(b) = \tan (a + \frac {\pi}{2} ) = - \cot(a)
tan(b)=tan(a+2π)=−cot(a)
MN斜率为k PQ斜率为 -1/k
{ y q − y p x q − x p = − 1 k y = k x + b \left\{ \begin{array}{lcr} \frac { y_q - y_p} { x_q - x_p} = -\frac {1}{k} \\\\ y= kx + b & & \end{array} \right. ⎩ ⎨ ⎧xq−xpyq−yp=−k1y=kx+b
点Q在MN上求解
{ x q = x p + k y p − k b 1 + k 2 y q = k x p + k 2 y p + b 1 + k 2 \left\{ \begin{array}{lcr} x_q = \frac { x_p + k y_p - kb}{ 1 + k^2}\\\\ y_q = \frac { k x_p + k^2 y_p + b}{ 1 + k^2} \\ \end{array} \right. ⎩ ⎨ ⎧xq=1+k2xp+kyp−kbyq=1+k2kxp+k2yp+b
其中
{
b
=
y
m
−
y
n
−
y
m
x
n
−
x
m
x
m
=
x
n
y
m
−
x
m
y
n
x
n
−
x
m
k
=
y
n
−
y
m
x
n
−
x
m
\left\{ \begin{array}{lcr} b = y _m - \frac { y_n - y_m} { x_n - x_m} x_m = \frac { x_ny_m - x_m y_n} { x_n - x_m} & & \\\\ k = \frac { y_n - y_m} { x_n - x_m} & & \end{array} \right.
⎩
⎨
⎧b=ym−xn−xmyn−ymxm=xn−xmxnym−xmynk=xn−xmyn−ym
代入 M N P 坐标 可算出 垂足坐标
水平与坚直另分一种情况直接求解
二、向量法
M
N
→
˙
M
P
→
=
∣
M
N
∣
∣
M
P
∣
c
o
s
α
\quad \overrightarrow {MN} \dot \quad \overrightarrow {MP} = \lvert MN\rvert\; \lvert MP \rvert \; cos \; \alpha
MN˙MP=∣MN∣∣MP∣cosα
∠
P
M
N
>
90
°
\angle PMN > 90 \degree
∠PMN>90° 点积结果为负
∠
P
M
N
=
90
°
\angle PMN = 90 \degree
∠PMN=90° 点积结果为零
∠
P
M
N
<
90
°
\angle PMN < 90 \degree
∠PMN<90° 点积结果为正
∣
M
P
∣
c
o
s
α
=
M
N
→
˙
M
P
→
∣
M
N
∣
\lvert MP \rvert \; cos \; \alpha = \frac {\quad \overrightarrow {MN} \dot \quad \overrightarrow {MP} } { \lvert MN\rvert }
∣MP∣cosα=∣MN∣MN˙MP
结果为MQ的长度 带符号 另比一次
∣ M P ∣ c o s α ∣ M N ∣ = M N → ˙ M P → ∣ M N ∣ 2 \frac { \lvert MP \rvert \; cos \; \alpha}{ \lvert MN\rvert } = \frac {\quad \overrightarrow {MN} \dot \quad \overrightarrow {MP} } { \lvert MN\rvert ^2 } ∣MN∣∣MP∣cosα=∣MN∣2MN˙MP
结果为MQ与MN长度比带符号 设为
λ
\lambda
λ
若Q在线段MN上 则
0
≤
λ
≤
1
0 \leq \lambda \leq 1
0≤λ≤1
其它情况Q在线段外
垂足坐标
x
q
=
λ
(
x
n
−
x
m
)
+
x
m
y
q
=
λ
(
y
n
−
y
m
)
+
y
m
x_q = \lambda (x_n-x_m)+x_m \; \; \\\\ y_q =\lambda (y_n-y_m)+y_m
xq=λ(xn−xm)+xmyq=λ(yn−ym)+ym
typedef double real;
typedef struct {
real x;
real y;
} PT;
real dist(PT* a, PT* b, PT* c,PT* foot)
{
real ab = length(a,b);
if (ab < EPS){
return length(a,c);
}
real lambda = dot(a,b,a,c)/(ab*ab);
real dx = b->x - a->x;
real dy = b->y - a->y;
foot->x = lambda*dx + a->x;
foot->y = lambda*dy + a->y;
if( lambda >= 0 && lambda <= 1) {
return length(c,foot); // or cross(a,b,a,c)/ab;
}else {
real ac = length(a,c);
real bc = length(b,c);
return MIN(ac,bc);
}
}