【问题标题】:Get angle in terms of 360 degrees获取 360 度的角度
【发布时间】:2015-01-29 23:47:11
【问题描述】:

我想获得一个 360 度的角度...对于我的游戏,我需要知道玩家前进的方向...

这里的代码获得了正确的角度,但仅以 90 度为增量:(意思是,当我点击左上象限时,我得到的角度是 0 到 90 度...左下角是 0 到 -90 度等...)

    var dY = this.pos.y-e.gameY;            //opposite
    var dX = this.pos.x-e.gameX;            //adjacent
    var dist = Math.sqrt((dY*dY)+(dX*dX));  //hypotenuse
    var sin = dY/dist;                      //opposite over hypotenuse
    var radians = Math.asin(sin);
    var degrees = radians*(180/Math.PI);    //convert from radians to degrees
    this.calculatedAngle = degrees;     

如何获得 360 度?


这是另一个例子:前两个代表问题...当我单击左上/下象限时,它会一直从 x 轴绘制一个直角三角形...

我需要它像下面的 2 张图片一样,它一直在周围绘制角度:

【问题讨论】:

  • 您有任何数据可以用来证明您在所有 4 个象限中的计算吗?
  • 您可以使用dydx 的符号来区分象限并相应地为您的结果添加偏移量。
  • @Xotic750 你什么意思?我只是在用户点击的地图上取点(e.gameX 或 e.gameY),然后获取到玩家当前位置的距离。橙子,我也不太明白你的意思
  • 那么你的图表上的原点是 (0, 0) 吗?你所有的价值观都与那个起源有关吗?因此,播放器和点击的示例如 (1, 1)、(-1, 1)、(-1, -1) 和 (1, -1)。 IE。玩家可能在 (1, 1) 并在 (2, 2) 获得点击,或者玩家总是在 (0, 0) 并且点击其他地方?
  • @Xotic750 他们不是。它们只是玩家与屏幕上点击点的坐标。所以玩家可以在(200, 300),点击(400, 500),distX = 200, distY = 200

标签: javascript geometry angle


【解决方案1】:

您可以使用atan2 函数直接从坐标中执行此操作,而无需计算斜边等额外信息,该函数是在 FORTRAN 的早期为与您的情况完全一样的情况而设计的。

注意两件重要的事情:

  1. atan2 函数已创建为自动处理所有可能的情况中的一种情况,并且
  2. 它将输出(-PI, PI]的范围。

两个坐标都是 (0, 0) 的情况是未定义的(当向量的大小为零时所有角度都是等价的),所以在这种情况下我任意将角度设置为零度。而为了得到想要的范围,还需要一些简单的逻辑和加法。

var Vx = this.pos.x - e.gameX;
var Vy = this.pos.y - e.gameY;

var radians;

if (Vx || Vy) {
    radians = Math.atan2(Vy, Vx);
} else {
    radians = 0;
}

if (radians < 0) {
    radians += 2*Math.PI;
}

var degrees = radians * 180 / Math.PI;

this.calculatedAngle = degrees;

根据需要,结果将是为所有情况定义的角度,并且在 [0, 360°) 范围内。

示例

function showDegrees(e, svg) {
	var rectangle = svg.getBoundingClientRect();
	var targetX = (rectangle.left + rectangle.right)/2;
	var targetY = (rectangle.top + rectangle.bottom)/2;
	var Vx = Math.round(e.clientX - targetX);
	var Vy = Math.round(targetY - e.clientY);
	var radians = Math.atan2(Vy, Vx);
	if (radians < 0) radians += 2*Math.PI;
	var degrees = Math.round(radians*180/Math.PI);
	var textBox = document.getElementById('showdegrees');
	textBox.innerHTML = degrees + '&deg;' + ' (' + Vx + ', ' + Vy + ')';
	textBox.setAttribute('x', Math.round(100 + Vx));
	textBox.setAttribute('y', Math.round(100 - Vy));
}
<svg width="200" height="200" viewBox="0 0 200 200" onmousemove="showDegrees(evt, this)">
<text x="0" y="0" fill="red" style="font-size: 12px"  id="showdegrees">Info</text>
<line x1="100" y1="0" x2="100" y2="200" style="stroke: black; stroke-width: 1" />
<line x1="0" y1="100" x2="200" y2="100" style="stroke: black; stroke-width: 1" />
</svg>

【讨论】:

    【解决方案2】:

    试试这个:

    var dY = this.pos.y - e.gameY,          // opposite
        dX = this.pos.x - e.gameX,          // adjacent
        radians = Math.atan(dY/dX);         // wrong, in [-1/2 pi, 1/2 pi]
    if(1/dX < 0) radians += Math.PI;        // fixed, in [-1/2 pi, 3/2 pi]
    if(1/radians < 0) radians += 2*Math.PI; // fixed, in [+0, 2 pi]
    var degrees = radians*180/Math.PI;      // from radians to degrees
    

    解释:

    • 最好用Math.atan 和切线计算弧度。使用 Math.sqrt 计算斜边是很昂贵的。
    • Math.atan 给出了-1/2 pi1/2 pi 之间的角度,即右半圆。要修复它,只需将 pi 相加,以防 dX 为负数。
    • 然后我们得到-1/2 pi3/2 pi 之间的角度。因此,如果它是负数,我们将2 pi 相加,以获得02 pi 之间的角度。
    • 请注意,我们必须将-0 视为否定,以使其正常工作。因此,我们不检查dX &lt; 0radians &lt; 0,而是检查它们的倒数。
    • 请注意,如果dXdY 都是0(或-0),最终结果将为NaN

    【讨论】:

      【解决方案3】:

      您需要使用比 arcsin 更多的信息来解决这个问题。这样做的原因是 arcsin 只会返回介于 -π/2 和 π/2(-90 度和 90 度)之间的值,正如您已经知道的那样。

      所以,要弄清楚另一部分,你需要知道你在哪个象限。

      在象限 2,arcsin 在 90 和 0 之间,实角在 90 和 180 之间。所以如果你在象限 2,180-calculated angle=real angle(180-90=90, 180-0=180).

      在第 3 象限中,arcsin 介于 0 和 -90 之间。实际角度在 180 到 270 之间。同样,180-calculated angle = real angle(180-0=180, 180-(-90)=270).

      在象限 4 中,arcsin 介于 -90 和 0 之间。实际角度介于 270 和 360 之间。所以 360+calculated angle=real angle(360+(-90)=270, 360+0)=360).

      对于象限 1 也是如此,您只是不需要进行转换。 (0+360=360 (equivalent to 0), 90+360=450 (equivalent to 90) ).

      因此,首先确定象限,然后根据该象限应用规则。 对于 (x,y) 坐标,如果 x 为正且 y 为正,则为第 1 象限。如果 x 为负且 y 为正,则为第 2 象限。如果 x 为负且 y 为负,则为第 3 象限. 如果 x 为正而 y 为负,那么你就是第 4 象限。

      所以在你的情况下,到原点的距离是你 (dX,dY) 坐标对,所以应该这样做:

      //your original code...
      var degrees = radians*(180/Math.PI);    //convert from radians to degrees
      
      //then
      
      
      if (dX>=0 and dY>=0)
      {//quadrant 1
      //no transformation, do nothing
      }
      if (dX>=0 and dy<0) 
      { //quadrant 4
      degrees=360+degrees;
      }
      if (dX<0 and dy<0) 
      { //quadrant 3
      degrees=180-degrees;
      }
      if (dX<0 and dy>0) 
      { //quadrant 2
      degrees=180-degrees;
      }
      
      
      this.calculatedAngle = degrees;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多