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

发布于 2025-01-11 16:00:31 字数 504 浏览 0 评论 0原文

我需要计算我自己的 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 之间的数字?

I need to calculate the angle in degrees between two points for my own Point class, Point a shall be the center point.

Method:

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

Test 1: // returns 45

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

Test 2: // returns -90, expected: 270

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

How can i convert the returned result into a number between 0 and 359?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

木森分化 2025-01-18 16:00:31

您可以添加以下内容:

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;
}

顺便说一下,为什么您不想在这里使用双精度?

you could add the following:

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;
}

by the way, why do you want to not use a double here?

玩物 2025-01-18 16:00:31

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

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

/**
 * 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;
}

I started with johncarls solution, but needed to adjust it to get exactly what I needed.
Mainly, I needed it to rotate clockwise when the angle increased. I also needed 0 degrees to point NORTH. His solution got me close, but I decided to post my solution as well in case it helps anyone else.

I've added some additional comments to help explain my understanding of the function in case you need to make simple modifications.

/**
 * 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;
}
会傲 2025-01-18 16:00:31

基于萨阿德·艾哈迈德的回答,这是一种可用于任意两点的方法。

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;
}

Based on Saad Ahmed's answer, here is a method that can be used for any two points.

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;
}
似狗非友 2025-01-18 16:00:31

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

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

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

他们所做的只是混合 Atan2 的变量顺序,导致它反转旋转程度。

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

Why is everyone complicating this?

The only problem is Math.atan2( x , y)

The corret answer is Math.atan2( y, x)

All they did was mix the variable order for Atan2 causing it to reverse the degree of rotation.

All you had to do was look up the syntax
https://www.google.com/amp/s/www.geeksforgeeks.org/java-lang-math-atan2-java/amp/

骑趴 2025-01-18 16:00:31

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

The javadoc for Math.atan(double) is pretty clear that the returning value can range from -pi/2 to pi/2. So you need to compensate for that return value.

阪姬 2025-01-18 16:00:31

如果您想要从北开始的“方位”度数,那么:

DirectionDegees
North0
North East45
East90
South East135
South180
South West-135
West-95
North West-45

您可以这样做:

public static final double RAD_360_DEG = Math.PI * 360d / 180d;
public static final double RAD_180_DEG = Math.PI * 180d / 180d;
public static final double RAD_90_DEG = Math.PI * 90d / 180d;

/**
 * @return The angle from north from p1 to p2.  Returns (in radians) -180 to 180, with 0 as north.
 */
public static double getAngleBearing(double p1x, double p1y, double p2x, double p2y) {
    double result = Math.atan2(p2y - p1y, p2x - p1x) + RAD_90_DEG;
    
    if (result > RAD_180_DEG) {
        result = result - RAD_360_DEG;
    }
    
    return result;
}

double bearingAngle = Math.toDegrees(getAngleBearing(...));

If you want the "bearing" degrees from north, so:

DirectionDegees
North0
North East45
East90
South East135
South180
South West-135
West-95
North West-45

you can do this:

public static final double RAD_360_DEG = Math.PI * 360d / 180d;
public static final double RAD_180_DEG = Math.PI * 180d / 180d;
public static final double RAD_90_DEG = Math.PI * 90d / 180d;

/**
 * @return The angle from north from p1 to p2.  Returns (in radians) -180 to 180, with 0 as north.
 */
public static double getAngleBearing(double p1x, double p1y, double p2x, double p2y) {
    double result = Math.atan2(p2y - p1y, p2x - p1x) + RAD_90_DEG;
    
    if (result > RAD_180_DEG) {
        result = result - RAD_360_DEG;
    }
    
    return result;
}

double bearingAngle = Math.toDegrees(getAngleBearing(...));
深居我梦 2025-01-18 16:00:31
angle = Math.toDegrees(Math.atan2(target.x - x, target.y - y));

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

angle = angle + Math.ceil( -angle / 360 ) * 360
angle = Math.toDegrees(Math.atan2(target.x - x, target.y - y));

now for orientation of circular values to keep angle between 0 and 359 can be:

angle = angle + Math.ceil( -angle / 360 ) * 360
末蓝 2025-01-18 16:00:31

我的实现:

private double searchAngle(Point posOne, Point posTwo) {
  int sumPos = (posOne.x * posTwo.x) + (posOne.y * posTwo.y);
  double moduleOne = Math.sqrt( (posOne.x * posOne.x) + (posOne.y * posOne.y) );
  double moduleTwo = Math.sqrt( (posTwo.x * posTwo.x) + (posTwo.y * posTwo.y) );

  return Math.toDegrees( Math.acos( sumPos / (Math.abs( moduleOne ) * Math.abs( moduleTwo )) ) );
}

输入:

  • posOne:(x = 50,y = 43)
  • posTwo:(x = 12,y = 42)

输出为

  • 33.35907305958513

(以度为单位)。

my realization:

private double searchAngle(Point posOne, Point posTwo) {
  int sumPos = (posOne.x * posTwo.x) + (posOne.y * posTwo.y);
  double moduleOne = Math.sqrt( (posOne.x * posOne.x) + (posOne.y * posOne.y) );
  double moduleTwo = Math.sqrt( (posTwo.x * posTwo.x) + (posTwo.y * posTwo.y) );

  return Math.toDegrees( Math.acos( sumPos / (Math.abs( moduleOne ) * Math.abs( moduleTwo )) ) );
}

Input:

  • posOne: (x = 50, y = 43)
  • posTwo: (x = 12, y = 42)

Output is

  • 33.35907305958513

in degrees.

儭儭莪哋寶赑 2025-01-18 16:00:31

怎么样:

angle = angle % 360;

What about something like :

angle = angle % 360;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文