Java 计算由两点定义的线之间的角度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2676719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calculating the angle between the line defined by two points
提问by kingrichard2005
I'm currently developing a simple 2D game for Android. I have a stationary object that's situated in the center of the screen and I'm trying to get that object to rotate and point to the area on the screen that the user touches. I have the constant coordinates that represent the center of the screen and I can get the coordinates of the point that the user taps on. I'm using the formula outlined in this forum: How to get angle between two points?
我目前正在为 Android 开发一个简单的 2D 游戏。我有一个位于屏幕中央的静止物体,我试图让该物体旋转并指向用户触摸的屏幕区域。我有代表屏幕中心的常量坐标,我可以获得用户点击的点的坐标。我正在使用本论坛中概述的公式: 如何获得两点之间的角度?
It says as follows "If you want the the angle between the line defined by these two points and the horizontal axis:
double angle = atan2(y2 - y1, x2 - x1) * 180 / PI;".
I implemented this, but I think the fact the I'm working in screen coordinates is causing a miscalculation, since the Y-coordinate is reversed. I'm not sure if this is the right way to go about it, any other thoughts or suggestions are appreciated.
它说如下“如果你想要这两个点定义的线和水平轴之间的角度:
double angle = atan2(y2 - y1, x2 - x1) * 180 / PI;".
我实现了这一点,但我认为我在屏幕坐标中工作的事实会导致计算错误,因为 Y 坐标是反向的。我不确定这是否是正确的方法,任何其他想法或建议表示赞赏。
采纳答案by Jim Lewis
Assumptions: x
is the horizontal axis, and increases when moving from left to right.
y
is the vertical axis, and increases from bottom to top. (touch_x, touch_y)
is the
point selected by the user. (center_x, center_y)
is the point at the center of the
screen. theta
is measured counter-clockwise from the +x
axis. Then:
假设: x
是水平轴,从左向右移动时增加。
y
是纵轴,从下往上增加。(touch_x, touch_y)
是用户选择的点。(center_x, center_y)
是屏幕中心的点。 theta
从+x
轴逆时针方向测量。然后:
delta_x = touch_x - center_x
delta_y = touch_y - center_y
theta_radians = atan2(delta_y, delta_x)
Edit: you mentioned in a comment that y increases from top to bottom. In that case,
编辑:您在评论中提到 y 从上到下增加。在这种情况下,
delta_y = center_y - touch_y
But it would be more correct to describe this as expressing (touch_x, touch_y)
in polar coordinates relative to (center_x, center_y)
. As ChrisF mentioned,
the idea of taking an "angle between two points" is not well defined.
但是将其描述为(touch_x, touch_y)
以相对于 的极坐标表示会更正确(center_x, center_y)
。正如 ChrisF 所提到的,“两点之间的角度”的想法没有明确定义。
回答by Dave Discoid
Had a need for similar functionality myself, so after much hair pulling I came up with the function below
我自己也需要类似的功能,所以在拉了很多头发之后我想出了下面的功能
/**
* Fetches angle relative to screen centre point
* where 3 O'Clock is 0 and 12 O'Clock is 270 degrees
*
* @param screenPoint
* @return angle in degress from 0-360.
*/
public double getAngle(Point screenPoint) {
double dx = screenPoint.getX() - mCentreX;
// Minus to correct for coord re-mapping
double dy = -(screenPoint.getY() - mCentreY);
double inRads = Math.atan2(dy, dx);
// We need to map to coord system when 0 degree is at 3 O'clock, 270 at 12 O'clock
if (inRads < 0)
inRads = Math.abs(inRads);
else
inRads = 2 * Math.PI - inRads;
return Math.toDegrees(inRads);
}
回答by Golfcabalist
"the origin is at the top-left of the screen and the Y-Coordinate increases going down, while the X-Coordinate increases to the right like normal. I guess my question becomes, do I have to convert the screen coordinates to Cartesian coordinates before applying the above formula?"
“原点在屏幕的左上角,Y 坐标向下增加,而 X 坐标像往常一样向右增加。我想我的问题变成了,我是否必须将屏幕坐标转换为笛卡尔坐标在应用上述公式之前?”
If you were calculating the angle using Cartesian coordinates, and both points were in quadrant 1 (where x>0 and y>0), the situation would be identical to screen pixel coordinates (except for the upside-down-Y thing. If you negate Y to get it right-side up, it becomes quadrant 4...). Converting screen pixel coordinates to Cartesian doesnt really change the angle.
如果您使用笛卡尔坐标计算角度,并且两个点都在象限 1(其中 x>0 和 y>0)中,则情况将与屏幕像素坐标相同(倒置 Y 的东西除外。如果您否定 Y 使其正面朝上,它变成象限 4 ......)。将屏幕像素坐标转换为笛卡尔坐标并不会真正改变角度。
回答by Tigger
A few answers here have tried to explain the "screen" issue where top left
is 0,0
and bottom right
is (positive) screen width, screen height
. Most grids have the Y
axis as positive above X
not below.
这里的一些答案试图解释“屏幕”问题 where top left
is0,0
和bottom right
is (positive) screen width, screen height
。大多数网格的Y
轴为正上方X
而不是下方。
The following method will work with screen values instead of "grid" values. The only difference to the excepted answer is the Y
values are inverted.
以下方法将使用屏幕值而不是“网格”值。与例外答案的唯一区别是Y
值被反转。
/**
* Work out the angle from the x horizontal winding anti-clockwise
* in screen space.
*
* The value returned from the following should be 315.
* <pre>
* x,y -------------
* | 1,1
* | \
* | \
* | 2,2
* </pre>
* @param p1
* @param p2
* @return - a double from 0 to 360
*/
public static double angleOf(PointF p1, PointF p2) {
// NOTE: Remember that most math has the Y axis as positive above the X.
// However, for screens we have Y as positive below. For this reason,
// the Y values are inverted to get the expected results.
final double deltaY = (p1.y - p2.y);
final double deltaX = (p2.x - p1.x);
final double result = Math.toDegrees(Math.atan2(deltaY, deltaX));
return (result < 0) ? (360d + result) : result;
}
回答by quang_tran
with pygame:
与 pygame:
dy = p1.y - p2.y
dX = p2.x - p1.x
rads = atan2(dy,dx)
degs = degrees(rads)
if degs < 0 :
degs +=90
it work for me
它对我有用
回答by j2emanue
in android i did this using kotlin:
在 android 中,我使用 kotlin 做到了这一点:
private fun angleBetweenPoints(a: PointF, b: PointF): Double {
val deltaY = abs(b.y - a.y)
val deltaX = abs(b.x - a.x)
return Math.toDegrees(atan2(deltaY.toDouble(), deltaX.toDouble()))
}