纯数学问题,今天正好有人询问到,搜索复习几何知识,留此记录。
平面给定三点,计算夹角有三种方法:
1 使用向量计算
关于向量a和b,向量夹角余弦公式
a*b = |a||b|cosTheta
所以
夹角 = acos(a*b) / (|a|*|b|)
两向量的数量积 = a.x*b.x + a.y*b.y
向量的模 = sqrt(x*x+y*y)
在二维下,计算量是最小的一种方法了(节约了sqrt计算),只需要一次acos
例,三个点A(1,1), B(2,1), C(2,2)
AB=(B.x-A.x, B.y-A.y)=(1,0)
AC=(C.x-A.x, C.y-A.y)=(1,1)
cosA = (AB*AC)/(|AB|*|AC|)=1/√2=√2/2, 则夹角BAC=45度
2 余弦定理
cosA = (AB*AB + AC*AC - BC*BC ) / 2*AB*AC
例,三个点A(1,1), B(2,1), C(2,2)
cosA = (1+2-1)/2*1*√2=1/√2=√2/2, 则夹角A=45度
3 单独计算AB和AC的角度
分别求出直线AB, AC的斜率,得到对应的角度,两线角度之差即为夹角,考虑到夹角的方向,顺时钟夹角定为正
AB的角度:atan2(AB.y, AB.x)
AC的角度:atan2(AC.y, AC.x)
计算AB和AC的差
在JavaScript中使用第二种方法实现:
var lengthAB = Math.sqrt( Math.pow(pointA.X - pointB.X, 2) +
Math.pow(pointA.Y - pointB.Y, 2)),
lengthAC = Math.sqrt( Math.pow(pointA.X - pointC.X, 2) +
Math.pow(pointA.Y - pointC.Y, 2)),
lengthBC = Math.sqrt( Math.pow(pointB.X - pointC.X, 2) +
Math.pow(pointB.Y - pointC.Y, 2));
var cosA = (Math.pow(lengthAB, 2) + Math.pow(lengthAC, 2) - Math.pow(lengthBC, 2)) /
(2 * lengthAB * lengthAC);
var angleA = Math.round( Math.acos(cosA) * 180 / Math.PI );
Math反三角函数返回值是弧度,若需要的是角度时还应将弧度转换,如最末行所示。