GLSL的Intersect函数如何计算直线起点到两线交点的距离?
结论:这段代码逻辑是正确的,它是2D直线求交的经典高效实现
首先你需要明确,这个函数返回的不是直接的距离值,是第一条直线(lineOne)参数方程的缩放系数t,你可以通过简单换算得到你需要的距离。
运行原理推导
我们可以用参数方程+隐式方程的方法拆解逻辑:
- 把lineOne写成参数方程,直线上任意点可以表示为:
其中P(t) = lineOneStart + t * (lineOneEnd - lineOneStart)t=0对应lineOne起点,t=1对应lineOne终点,t>1或t<0对应直线向两端延伸的部分,你要找的交点就是这个方程里的t值。 - 把lineTwo写成隐式方程:lineTwo的方向向量是
lineTwoEnd - lineTwoStart,代码第一行计算的line2Perp是把这个方向向量逆时针旋转90度得到的line2的法向量,所有落在line2上的点都满足:dot( P - lineTwoStart, line2Perp ) = 0 - 把lineOne的参数方程代入lineTwo的隐式方程,展开求解
t:
这个结果和代码里的返回值完全一致。dot( lineOneStart + t*(lineOneEnd - lineOneStart) - lineTwoStart, line2Perp ) = 0 dot( lineOneStart - lineTwoStart, line2Perp ) + t * dot( lineOneEnd - lineOneStart, line2Perp ) = 0 t = dot( lineTwoStart - lineOneStart, line2Perp ) / dot( lineOneEnd - lineOneStart, line2Perp ) - 代码里的边界判断
abs(line1Proj) < 0.0001是处理平行的情况:如果line1的方向向量和line2的法向量点积为0,说明两条直线平行,没有唯一交点,直接返回0做边界处理。
需求适配
你需要的lineOneStart到交点的距离,只需要把返回的t乘以lineOne方向向量的长度即可:
float t = Intersect(lineOneStart, lineOneEnd, lineTwoStart, lineTwoEnd); float distance = t * length(lineOneEnd - lineOneStart);
误解澄清
你认为第一行逻辑是指向lineTwo起点属于认知偏差,line2Perp只是line2的法向量,是求交推导里的必要中间量,和“指向lineTwo起点”没有关联。
内容的提问来源于stack exchange,提问作者Ryan Peschel
相关产品推荐
相关产品推荐

