求向量的角度

求向量的角度简单记录一个计算机图形学方面的算法。即计算 2D 平面中,从点 A 到点 B 形成的向量的夹角。

大家好,欢迎来到IT知识分享网。

简单记录一个计算机图形学方面的算法。即计算 2D 平面中,从点 A 到点 B 形成的向量的夹角。

这算是游戏里面比较底层的算法,一般游戏引擎都会包装好这个方法,如 GMS2 的 point_direction 方法,常用于实现旋转一个物体,比如拨动时钟的指针、人物的武器使用鼠标瞄准敌人。

本文代码使用 JavaScript 实现。

问题描述

求向量的角度

如图,求这里朝上的白色虚线到红线的角度。

我们规定角度区间为 (-180, 180]。当向量朝上的时候,角度为0,向量正朝下时,角度为 180。当然你也可以规定为 [0, 360),只需要在代码得到的角度 angle 的基础上,计算 (angle + 360) % 360 即可。

另外要注意这里的坐标系的 y 轴是朝下的(一般计算机屏幕的坐标系都是y轴朝下的),x 轴朝向为右。

计算

已知中心点 cx、cy,光标的坐标 x,y,求角度。

说到底,求的是向量 a (x – cx, y – cy) 和向量 b (0, -1) 的夹角。这里我们需要用到 点积公式

求向量的角度

我们要求的是角度,于是得到下面公式:

求向量的角度

假设向量 a 为 (x, y), 向量 b 为 (x2, y2),则 a · bx * x2 + y * y2

|a| 指的是向量 a 的模,即向量 a 的 x 和 y 平方和并开方,即 Math.sqrt(x * x + y * y)

通过公式,我们得到了余弦值 cos,然后反余弦 Math.acos(),得到弧度,再进行单位换算得到角度。

function calCos(a, b) {     // 点积     let dotProduct = a[0] * b[0] + a[1] * b[1];     let d = Math.sqrt(a[0] * a[0] + a[1] * a[1]) * Math.sqrt(b[0] * b[0] + b[1] * b[1]);     return dotProduct/d; }
let angle = Math.acos(radian) * 180 / Math.PI; 

我们先看看 余弦函数 和 反余弦函数的示意图:

求向量的角度

由图中的反余弦函数可知,求得的角度范围为 [0, 180]。那 [-180, 0) 的范围如何获取呢?我们还有个办法,就是通过 判断光标的 x 坐标大于还是小于 中心点的 x 坐标 来设置正负,如果大于,角度为正;反之为负。

let angle = Math.acos(radian) * 180 / Math.PI; if (x < cx) angle = -angle;

完整代码

function calAngle(cx, cy, x, y) {     const radian = getCosBy2pt(x, y, cx, cy);     let angle = Math.acos(radian) * 180 / Math.PI;     if (x < cx) angle = -angle;     return angle;     // 计算 点1指点2形成 的向量      function getCosBy2pt(x, y, cx, cy) {         let a = [x - cx, y - cy];         let b = [0, -1];         return calCos(a, b);     }     function calCos(a, b) {         // 点积         let dotProduct = a[0] * b[0] + a[1] * b[1];         let d = Math.sqrt(a[0] * a[0] + a[1] * a[1]) * Math.sqrt(b[0] * b[0] + b[1] * b[1]);         return dotProduct/d;     } }

演示

本人使用 svg 做了一个演示 demo 出来,使用了 svgjs 库。

https://f-star.github.io/my-test/calAngle/

这里你会发现我这里有个 蓝色的弧线 表示了角度经过的路径,是不是很好玩,其实这个弧的绘制也是通过 点积公式 计算出中心点到光标的连线上的一个点的坐标来实现的。有兴趣你可以自己研究一下。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/84261.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信