说明
当直线与平面不平行时,它们肯定会有一个交点。
几何
如图,AB 为平面法线,BC 为直线。要求的点 D 为其交点。
首先,我们可以利用前面的知识,先求出点 B 到平面的长度。注意这个距离是有符号的,距离为正时,代表点 B 在平面正方向(即法线正方向),为负时代表点 B 在平面背后。这里我们直接用向量 AB 的长来表示这个距离。
假设BD = x*BC
,x 为需要求的未知数。那么,向量 BD 在法线上的投影长,也是等于点 B 到平面的距离(也就是向量 AB 的长)。
所以,x=||AB|| / BC 在法线上的投影长
。也可以从相似三角形来理解:要求 BD 的长,可以根据 AB 长 ,BE 长,和 BC 的长来得到:
这里也需要注意,BC 在平面法线 AB 上的投影也是有符号的:为正时,代表与法线正方向接近,为负代表与法线反方向接近。所以,我们需要考虑 x 的符号问题:
- 当点 B 在正方向时,投影向量 BE 需要与法线 AB 方向相反;
- 当点 B 在反方向时,投影向量 BE 需要与法线 AB 方向相同;
实际上,BC 向量应该向 BA 向量投影(即法线的相反方向),才能保证最终结果正确。
代码
static func intersectionPoint(line:Line, plane:Plane) -> simd_float3? {
let vector = line.position - plane.position
let distance = dot(vector, normalize(plane.normal))
let dotValue = dot(line.direction, -normalize(plane.normal))
if dotValue < Float.leastNormalMagnitude {
// 平行
return nil
}
let x = distance / dotValue
return line.position + x * line.direction
}