【问题标题】:Java: Calculating the angle between two points in degreesJava:以度为单位计算两点之间的角度
【发布时间】: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)之间的角度?

标签: java point angle degrees


【解决方案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/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多