获得360度的角度

时间:2015-01-29 23:47:11

标签: javascript geometry angle

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

enter image description here

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

enter image description here

    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张图片一样,它会不断地绘制角度:

enter image description here

3 个答案:

答案 0 :(得分:3)

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

注意两件重要的事情:

  1. 已创建atan2函数以自动处理多个可能情况中的之外的所有,并且
  2. 它会输出一系列(-PI, PI]
  3. 两个坐标都是(0,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>

答案 1 :(得分: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 < 0radians < 0,而是检查它们的反向。
  • 请注意,如果NaNdX都是dY(或0),则最终结果为-0

答案 2 :(得分:1)

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

因此,要找出另一部分,您需要了解您所在的象限。

enter image description here

在象限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;