S01E04:点到平面的距离

996 阅读2分钟

说明

在 3D 几何中,如果求一个点C到平面的距离?如下图,平面 P 定义为:过 A 点,垂直于向量 AB。也就是说:A 点在平面上,AB 则是平面的法线。

几何

利用几何知识,我们知道从点 C 向平面做垂线,这个线段长度就是点 C 到平面的距离。那么这个垂线的方向是什么,长度又是多少?很显然,垂线的方向就是平面的法线 AB 的方向(或者说相反方向),那么长度就是 AC 向量在法线 AB 上的投影长。 恰好,向量的点积就可以求投影长,前提是 AB 为单位长度的向量。如果 AB 不是单位长度向量呢?只要用normalize方向将其变成单位向量就可以了。

//当 AB 长度为 1 时,点积就代表了 AC 在 AB 上的投影长
dot(AC, AB) = ||AC||*||AB||*cos𝜃

从向量点积的角度讲,计算出的距离可能是负的,意味着点在平面的背面方向,如果只需要数值的话,对结果取绝对值就好了。

代码

//定义平面
struct Plane {
    var position = simd_float3.zero
    var normal = simd_float3.zero
}
static func distanceBetween(point:simd_float3, plane:Plane) -> Float {
    let vector = point - plane.position
    let dotValue = dot(vector, normalize(plane.normal))
    return dotValue
}

平面的其他定义

这里我们在定义平面时,直接使用了点+法线的形式定义,实际中平面也可以由三个点来定义(不共线的三个点)。

那么这种情况下,又该如何呢?其实可以利用叉乘来求出法线: 平面由 A、B、C 三个定义,构造向量 BA、BC,叉乘得到法线 BD,就可以用前面的公式来求其他点到平面的距离了。

还有另一种定义,用矩阵来定义平面,将某个矩阵的 xoy 平面或 xoz 平面做为要定义的平面。要转化成点+法线也非常简单,矩阵的平移分量(运动后的坐标原点)可以当做点,法线则根据定义,如果 xoy 平面则 z 轴就是法线,xoz 平面则 y 轴就是法线。

当然了,在这种情况下,平面的法线方面就需要自己根据情况选择了,如果只是计算距离,那任意选择都是可以的。