如何计算两条相交直线的反弹端点?已有交点代码求反射点坐标公式
两条相交直线反弹端点计算方法
我们默认line1为入射运动轨迹,(x1,y1)为入射起始点,(x2,y2)为无碰撞时的目标点;line2为碰撞边界,反弹端点指的是轨迹碰到line2的交点后,按反射定律运动相同长度对应的终点。
计算步骤
- 第一步:调用你已实现的
intersection函数,获取两条线段的交点P(x,y),如果返回平行、无相交等错误,不需要计算反弹 - 第二步:计算边界line2的单位法向量
- 先求line2的方向向量:
dir_x = x4 - x3,dir_y = y4 - y3(使用你代码中已经反转后的y坐标计算) - 计算法向量:
normal_x = -dir_y,normal_y = dir_x - 法向量单位化:
len = Math.sqrt(normal_x**2 + normal_y**2),unit_normal_x = normal_x / len,unit_normal_y = normal_y / len
- 先求line2的方向向量:
- 第三步:计算入射向量,即从交点指向原轨迹终点的向量:
v_x = x2 - x,v_y = y2 - y - 第四步:按反射公式计算反射向量:
- 先求入射向量和单位法向量的点积:
dot = v_x * unit_normal_x + v_y * unit_normal_y - 反射向量:
reflect_x = v_x - 2 * dot * unit_normal_x,reflect_y = v_y - 2 * dot * unit_normal_y
- 先求入射向量和单位法向量的点积:
- 第五步:计算反弹端点坐标:
rx = x + reflect_x,ry = y + reflect_y,如果需要转回网页原生坐标,将ry *= -1即可
兼容现有逻辑的实现代码
// 入参和intersection函数保持一致,默认line1为入射轨迹,line2为碰撞边界 export function getReflectionEnd(line1, line2) { // 调用现有方法求交点 const intersect = intersection(line1, line2); if (typeof intersect === 'string') return intersect; const {x, y} = intersect; // 复用intersection里已经反转后的坐标 const [, , x2, y2] = line1; // 入射轨迹的原终点 const [x3, y3, x4, y4] = line2; // 碰撞边界的两个端点 // 计算边界的单位法向量 const dirX = x4 - x3; const dirY = y4 - y3; const normalX = -dirY; const normalY = dirX; const normalLen = Math.hypot(normalX, normalY); const unitNormalX = normalX / normalLen; const unitNormalY = normalY / normalLen; // 入射向量 const vX = x2 - x; const vY = y2 - y; // 计算反射向量 const dot = vX * unitNormalX + vY * unitNormalY; const reflectX = vX - 2 * dot * unitNormalX; const reflectY = vY - 2 * dot * unitNormalY; // 反弹端点坐标(反转y轴适配网页坐标) const rx = x + reflectX; const ry = (y + reflectY) * -1; return {x: rx, y: ry}; }
注意事项
- 如果计算出的反射方向不符合预期,说明法向量方向取反了,将
normalX = dirY、normalY = -dirX即可修正 - 如果需要将line2作为入射轨迹、line1作为碰撞边界,只需要交换两个入参的位置,同时调整取对应轨迹的原终点即可
- 上述计算已经适配了你现有代码中网页坐标y轴反转的逻辑,直接调用即可

内容的提问来源于stack exchange,提问作者allenhwkim
相关产品推荐
相关产品推荐

