Java:以度为单位计算两点之间的角度

Posted

技术标签:

【中文标题】Java:以度为单位计算两点之间的角度【英文标题】:Java: Calculating the angle between two points in degrees 【发布时间】:2012-04-15 18:00:41 【问题描述】:

我需要为自己的 Point 类计算两点之间的角度,点 a 应为中心点。

方法:

public float getAngle(Point target) 
    return (float) Math.toDegrees(Math.atan2(target.x - x, target.y - y));

测试 1: // 返回 45

Point a = new Point(0, 0);
    System.out.println(a.getAngle(new Point(1, 1)));

测试 2:// 返回 -90,预期:270

Point a = new Point(0, 0);
    System.out.println(a.getAngle(new Point(-1, 0)));

如何将返回的结果转换为 0 到 359 之间的数字?

【问题讨论】:

刚刚注意到atan2的参数顺序相反:必须是atan2(y, x) 我不知道出了什么问题,但是我的订单可以正常工作,相反的顺序不会。 只能测量三点之间的角度。您可能会认为 (0, 0)(min(x1,x2), min(y1,y2)) 是其中一个点,但您不能在两点之间画一个角度。 @Peter Lawrey Point a 代表中心。所以我的意思是中心点和线a到新点(x,y)的角度。还是没有这个意义? 所以你的意思是(0, 0)(1, 0)(0,0)(x, y)之间的角度? 【参考方案1】:

您可以添加以下内容:

public float getAngle(Point target) 
    float angle = (float) Math.toDegrees(Math.atan2(target.y - y, target.x - x));

    if(angle < 0)
        angle += 360;
    

    return angle;

对了,你为什么不想在这里使用双精度数?

【讨论】:

由于角度只会在瞬间低于 0,我认为没有理由在这里使用 while 循环。 我在一个游戏帧中调用了这个方法数百次。我想我的性能更高一点,但精度更低,而且我也不需要额外的数字。 哦,如果您在游戏中处理这些数字,-90 和 270 在增量方向方面将被视为完全相同。 您不必检查它是否 >= 360。这永远不会发生,因为 atan2 返回一个介于 +/- pi/2 之间的值。 @johncarl 应该是 tan2(deltay/deltax)【参考方案2】:

Math.atan(double) 的 javadoc 非常清楚,返回值的范围可以从 -pi/2 到 pi/2。所以你需要补偿那个返回值。

【讨论】:

【参考方案3】:

我从 johncarls 解决方案开始,但需要对其进行调整以得到我所需要的。 主要是,当角度增加时,我需要它顺时针旋转。我还需要 0 度来指向 NORTH。他的解决方案让我很接近,但我决定也发布我的解决方案,以防它帮助其他人。

我添加了一些额外的 cmets 来帮助解释我对函数的理解,以防您需要进行简单的修改。

/**
 * Calculates the angle from centerPt to targetPt in degrees.
 * The return should range from [0,360), rotating CLOCKWISE, 
 * 0 and 360 degrees represents NORTH,
 * 90 degrees represents EAST, etc...
 *
 * Assumes all points are in the same coordinate space.  If they are not, 
 * you will need to call SwingUtilities.convertPointToScreen or equivalent 
 * on all arguments before passing them  to this function.
 *
 * @param centerPt   Point we are rotating around.
 * @param targetPt   Point we want to calcuate the angle to.  
 * @return angle in degrees.  This is the angle from centerPt to targetPt.
 */
public static double calcRotationAngleInDegrees(Point centerPt, Point targetPt)

    // calculate the angle theta from the deltaY and deltaX values
    // (atan2 returns radians values from [-PI,PI])
    // 0 currently points EAST.  
    // NOTE: By preserving Y and X param order to atan2,  we are expecting 
    // a CLOCKWISE angle direction.  
    double theta = Math.atan2(targetPt.y - centerPt.y, targetPt.x - centerPt.x);

    // rotate the theta angle clockwise by 90 degrees 
    // (this makes 0 point NORTH)
    // NOTE: adding to an angle rotates it clockwise.  
    // subtracting would rotate it counter-clockwise
    theta += Math.PI/2.0;

    // convert from radians to degrees
    // this will give you an angle from [0->270],[-180,0]
    double angle = Math.toDegrees(theta);

    // convert to positive range [0-360)
    // since we want to prevent negative angles, adjust them now.
    // we can assume that atan2 will not return a negative value
    // greater than one partial rotation
    if (angle < 0) 
        angle += 360;
    

    return angle;

【讨论】:

在将弧度值转换为度数之前,与其将 Pi/2(一个不精确的近似值)添加到弧度值上,不如在将其转换为度数后添加 90 更有意义。 你也可以为弧度做这个吗? 编辑: 没关系 - 你只需删除Math.toDegrees 调用。 这里我也建议 return (angle + 360) % 360;【参考方案4】:

类似的东西呢:

angle = angle % 360;

【讨论】:

但是..我们没有te角!【参考方案5】:
angle = Math.toDegrees(Math.atan2(target.x - x, target.y - y));

现在圆形值的方向保持角度在 0 到 359 之间可以是:

angle = angle + Math.ceil( -angle / 360 ) * 360

【讨论】:

我觉得应该是Math.atan2(target.y - y, target.x - x),所以先是y分量而不是x分量。【参考方案6】:

基于Saad Ahmed's answer,这里有一个方法,可以任意两点使用。

public static double calculateAngle(double x1, double y1, double x2, double y2)

    double angle = Math.toDegrees(Math.atan2(x2 - x1, y2 - y1));
    // Keep angle between 0 and 360
    angle = angle + Math.ceil( -angle / 360 ) * 360;

    return angle;

【讨论】:

这不是通用方法 @FrankK 我删除了“通用”作为描述符【参考方案7】:

为什么每个人都把事情复杂化了?

唯一的问题是 Math.atan2( x , y)

正确答案是 Math.atan2(y, x)

他们所做的只是混合 Atan2 的可变顺序,使其反转旋转度数。

您所要做的就是查找语法 https://www.google.com/amp/s/www.geeksforgeeks.org/java-lang-math-atan2-java/amp/

【讨论】:

以上是关于Java:以度为单位计算两点之间的角度的主要内容,如果未能解决你的问题,请参考以下文章

如何获得两个 POI 之间的角度?

给定一个以度为单位的角度,我如何使用 x 和 y 找到行进线的逻辑? (数学困境)

如何计算两个角度测量值的差异? [重复]

使用位置查找运动转角

逆正弦、余弦和正切的代码

用坐标、长度、宽度和角度计算矩形的中心