如何获取两向量的360°夹角?现有代码无法区分90°与270°
向量夹角计算问题的修复方案
问题根源
Math.acos() 的返回范围是 0 到 π(0°~180°),它只能计算两个向量间的最小夹角,无法区分顺时针/逆时针方向。270°和90°的余弦值均为0,因此会返回相同的π/2(1.57)。
修复思路
要获取0到2π(0°~360°)的完整方向夹角,需要结合二维向量叉乘判断方向:
- 叉乘公式:
cross = a.x * b.y - a.y * b.x - 叉乘结果为正:向量b在a的逆时针方向,保留
acos计算的夹角 - 叉乘结果为负:向量b在a的顺时针方向,用
2π - theta得到大于π的夹角 - 叉乘结果为0:两向量共线,直接使用
acos结果即可
修改后的代码
getAngle(a, b) { const dot = a.x * b.x + a.y * b.y; const absA = Math.hypot(a.x, a.y); // 用Math.hypot替代手动开平方,更简洁且避免溢出 const absB = Math.hypot(b.x, b.y); // 处理零向量边界情况 if (absA === 0 || absB === 0) { return 0; } let cosTheta = dot / (absA * absB); // 修正浮点误差导致的cosTheta超出[-1,1]的问题 cosTheta = Math.max(-1, Math.min(1, cosTheta)); let theta = Math.acos(cosTheta); // 通过叉乘判断方向,调整夹角范围 const cross = a.x * b.y - a.y * b.x; if (cross < 0) { theta = 2 * Math.PI - theta; } console.log("force theta:", theta); return theta; }
验证效果
- 90°夹角:叉乘为正,返回π/2(≈1.57)
- 270°夹角:叉乘为负,返回3π/2(≈4.71)
- 180°夹角:叉乘为0,返回π(≈3.14)
内容的提问来源于stack exchange,提问作者whitebear
相关产品推荐
相关产品推荐

