数学 / 空间向量 · 用坐标与法向量解立体几何 / 空间距离:点线、点面与异面直线 待审核 5 / 5
AP×dd\dfrac{\lvert AP \times d\rvert}{\lvert d\rvert} · APnn\dfrac{\lvert AP \cdot n\rvert}{\lvert n\rvert}

空间距离:点线、点面与异面直线

立体几何里的距离有六七种名目,向量法把它们收成三个公式。三个公式的形状还很像:都是「一个向量与某个方向作积,再除以那个方向的长度」,区别只在作的是叉积还是数量积。

1 · 点到直线的距离

设直线过点 AA、方向向量为 ddPP 是空间中一点。

定理 1.1PP 到该直线的距离为

h=AP×ddh = \frac{\lvert \overrightarrow{AP} \times d \rvert}{\lvert d \rvert}

AP×d\lvert \overrightarrow{AP} \times d \rvert 是以 AP\overrightarrow{AP}dd 为邻边的平行四边形面积,除以底 d\lvert d \rvert 即得高。另一条等价路线是先求投影长度再用勾股定理:

h=AP2(APdd)2h = \sqrt{\lvert \overrightarrow{AP} \rvert^2 - \left(\frac{\overrightarrow{AP} \cdot d}{\lvert d \rvert}\right)^2}

两条路各有用处。叉积那条一步到位;勾股那条会顺带交出投影长度,也就是垂足的位置,画图或求后续的量时用得上。pointLineReport 两个都给,单测则拿它们互相校验,再拿「沿直线密集取样求最小距离」当独立参照。

2 · 点到平面的距离

定理 2.1 平面 α\alpha 过点 AA、法向量为 nnPP 是空间中一点。则

d=APnnd = \frac{\lvert \overrightarrow{AP} \cdot n \rvert}{\lvert n \rvert}

去掉绝对值的那个量 APn/n\overrightarrow{AP} \cdot n / \lvert n \rvert 是带符号的距离,符号说明 PP 落在法向量所指的一侧还是另一侧。判断两点是否在平面同侧只需比较两个符号,不必求交点,pointPlaneReport 把它一并交出。

另外三种距离由这一个公式一并吸收:直线与它平行的平面之间的距离,等于直线上任一点到平面的距离;两个平行平面之间的距离,等于一个平面上任一点到另一个的距离;而球心到切面的距离就是半径。三者都不需要新公式,只需要「任一点」这三个字成立——它成立的前提正是平行。

例 2.1 正方体 ABCDABCD-A1B1C1D1A_1B_1C_1D_1 棱长为 2,AA 在原点。平面 A1BDA_1BD 的法向量由 A1B=(2,0,2)\overrightarrow{A_1B} = (2,0,-2)A1D=(0,2,2)\overrightarrow{A_1D} = (0,2,-2) 叉积得 (4,4,4)(4,4,4),约简为 (1,1,1)(1,1,1)A1A=(0,0,2)\overrightarrow{A_1A} = (0,0,-2),故 d=2/3=1.1547d = 2/\sqrt{3} = 1.1547。点 AA 到直线 B1CB_1C 的距离则是 6=2.4495\sqrt{6} = 2.4495,垂足恰是 B1CB_1C 的中点 (2,1,1)(2,1,1)

3 · 异面直线的距离

两条异面直线有唯一一条公垂线,它们之间的距离就是公垂线段的长。公垂线的方向不必求出来——它就是 d1×d2d_1 \times d_2

定理 3.1 直线 l1l_1AA、方向 d1d_1l2l_2BB、方向 d2d_2,且 d1d_1d2d_2 不平行。则

d=AB(d1×d2)d1×d2d = \frac{\lvert \overrightarrow{AB} \cdot (d_1 \times d_2) \rvert}{\lvert d_1 \times d_2 \rvert}

式子的读法是:把 AB\overrightarrow{AB} 投影到公垂线方向上。这一步同时解释了为什么结果与 AABB 各自取在直线上哪一点无关——沿 d1d_1d2d_2 移动 AABB,改变的分量都与 d1×d2d_1 \times d_2 垂直,投影不变。

公垂线段的两个端点要多解一步。它们由两条垂直条件定出,写成一个二元一次方程组,行列式恰是 d1×d22\lvert d_1 \times d_2 \rvert^2lineLineReport 解出这对最近点是为了把那条线段画出来:距离是一个数,线段要两个点。

图 3-1 · 正方体上的三类距离。可调方位角与俯仰角旋转视图,切换点线距、点面距、异面直线距与平行的一支;读数给出中间量、垂足或最近点对,红色线段即所求的距离。

注 ·AA 到平面 A1BDA_1BD 的距离与异面直线 A1BA_1BB1CB_1C 之间的距离数值相同,都是 1.15471.1547。这不是巧合:B1C(1,1,1)=0\overrightarrow{B_1C} \cdot (1,1,1) = 0 说明 B1CB_1C 平行于平面 A1BDA_1BD,而 A1BA_1B 落在该平面内,故两条异面直线的距离等于 B1CB_1C 上任一点到该平面的距离;点 CC 的带符号距离是 +2/3+2/\sqrt{3},点 AA 的是 2/3-2/\sqrt{3},两点在平面两侧等距。把「异面直线距」化归成「点面距」是常用手法,判据就是那个数量积为零。

4 · 平行是一个奇点

d1d_1d2d_2 平行时 d1×d2=0d_1 \times d_2 = 0,定理 3.1 的分子分母同时为零。这一支不能靠把阈值调小回避,因为距离作为方向的函数在平行处真的不连续。

底面内的两条平行直线 ABABDCDC(正方体棱长 2)相距 2。把 DCDC 的方向从 (1,0,0)(1,0,0) 偏出 ε\varepsilon:两条共面直线一旦不平行就必然相交,于是距离准确地变成 0。ε=102\varepsilon = 10^{-2} 时交点在 x=200x = -200 处,10610^{-6} 时在 x=2×106x = -2 \times 10^6 处,10810^{-8} 时按公式已到 2×108-2 \times 10^8。距离从 2 掉到 0,中间没有过渡。

警示 · 「是否平行」这个判据必须与算距离时用的是同一个量。本系列先前拿定最近点的那个方程组的行列式(即 d1×d22\lvert d_1 \times d_2 \rvert^2)与 10910^{-9} 比,而 shared/geom3d.tslineToLined1×d2\lvert d_1 \times d_2 \rvert 本身与 10910^{-9} 比。两者差一个平方:ε=108\varepsilon = 10^{-8} 时前者只有 101610^{-16},落进平行支报「距离 2」,后者是 10810^{-8},报「相交、距离 0」。同一个构型两个答案,实测撞上后把判据统一到叉积长度上才对齐。

ε=108\varepsilon = 10^{-8} 这一档还暴露出另一件事。d2d2=1+1016d_2 \cdot d_2 = 1 + 10^{-16} 在双精度里就是 1,那个 2×22 \times 2 方程组的行列式随之算出恰好 0,最近点的参数成了 ±\pm\infty;而距离仍是准确的 0,因为它只经过一次叉积。位置比距离敏感得多:距离的相对误差在 101610^{-16} 量级,位置却已经解不出来。lineLineReport 单独标出这一档,让画面知道那条公垂线段画不出来,而不是把 Infinity 送进 SVG。

5 · 参考文献

  1. Distance from a point to a line. Wikipedia. 点线距的向量推导。https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
  2. Distance from a point to a plane. Wikipedia. 点面距与带符号距离。https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_plane
  3. Skew lines. Wikipedia. 异面直线、公垂线与它们之间的距离。https://en.wikipedia.org/wiki/Skew_lines
  4. Line-Line Distance. Wolfram MathWorld. 两直线间距离的公式与平行时的退化。https://mathworld.wolfram.com/Line-LineDistance.html
  5. Lagrange's identity. Wikipedia. 正规方程的行列式恰是叉积长度的平方。https://en.wikipedia.org/wiki/Lagrange%27s_identity