坐标系下粒子与线段碰撞的反射角求解问题
解决粒子与线段碰撞后的反射角计算问题
原方法失效的核心原因
- 你用
numpy.arctan2(vy-uy, vx-ux)算出的是线段从u到v的走向角度,但反射计算需要的是线段的法线方向——线段有两个相反的法线方向,选反了直接导致反射角完全错误 - 直接用角度差
Δθ = θuv - θ推导反射角,没考虑粒子是从线段哪一侧入射,再加上角度的周期性(比如超过π或低于-π),很容易出现符号或数值异常
正确计算步骤
1. 先算线段的方向向量和法向量
先得到线段u-v的方向向量:
dx = vx - ux dy = vy - uy
再生成两个垂直于线段的单位法向量(对应线段的两侧):
# 左侧法线(垂直于线段u→v方向向左) nx1 = -dy ny1 = dx # 右侧法线(垂直于线段u→v方向向右) nx2 = dy ny2 = -dx # 归一化法向量(保证后续点积计算准确) norm = numpy.sqrt(nx1**2 + ny1**2) nx1, ny1 = nx1/norm, ny1/norm nx2, ny2 = nx2/norm, ny2/norm
2. 生成粒子入射方向的单位向量
从入射角度θ转换为向量形式:
vx_inc = numpy.cos(θ) vy_inc = numpy.sin(θ)
3. 选对正确的法线方向
判断粒子从线段哪一侧入射:入射方向与指向粒子所在侧的法线点积为负(因为法线指向线段外侧,入射方向是从外侧撞向线段)
dot1 = vx_inc * nx1 + vy_inc * ny1 dot2 = vx_inc * nx2 + vy_inc * ny2 # 选点积为负的法线 nx, ny = (nx1, ny1) if dot1 < 0 else (nx2, ny2)
4. 计算反射方向向量
用标准反射公式:反射向量 = 入射向量 - 2*(入射向量·法线向量)*法线向量
dot_inc_n = vx_inc * nx + vy_inc * ny vx_ref = vx_inc - 2 * dot_inc_n * nx vy_ref = vy_inc - 2 * dot_inc_n * ny
5. 转换为反射角
最后用arctan2得到相对于x轴的反射角:
θ_reflected = numpy.arctan2(vy_ref, vx_ref)
如果需要把角度范围从[-π, π]转成[0, 2π],可以加一步:
θ_reflected = numpy.mod(θ_reflected, 2*numpy.pi)
关键提醒
反射定律的核心是入射角等于反射角(相对于法线),不是相对于线段本身——这是原方法最容易踩的坑,一定要基于法线方向计算,而不是线段的走向角度。
内容的提问来源于stack exchange,提问作者smuecke
相关产品推荐
相关产品推荐

