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:以度为单位计算两点之间的角度的主要内容,如果未能解决你的问题,请参考以下文章