如何将 atan2() 映射到 0-360 度
atan2(y, x)
在 180° 处存在不连续性,顺时针方向切换到 -180°..0°。
如何将值范围映射到 0°..360°?
这是我的代码:
CGSize deltaPoint = CGSizeMake(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
float swipeBearing = atan2f(deltaPoint.height, deltaPoint.width);
我正在根据给定的 startPoint
和 endPoint
(两个 XY 点结构)计算滑动触摸事件的方向。该代码适用于 iPhone,但任何支持 atan2f()
的语言都可以。
atan2(y, x)
has that discontinuity at 180° where it switches to -180°..0° going clockwise.
How do I map the range of values to 0°..360°?
here is my code:
CGSize deltaPoint = CGSizeMake(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
float swipeBearing = atan2f(deltaPoint.height, deltaPoint.width);
I'm calculating the direction of a swiping touch event given the startPoint
and endPoint
, both XY point structs. The code is for the iPhone but any language that supports atan2f()
will do.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
使用 Modulo 的解决方案
捕获所有情况的简单解决方案。
说明
正数:1 到 180
如果将 1 到 180 之间的任何正数除以 360,您将得到与输入的数字完全相同的数。这里的 Mod 只是确保这些正数数字作为相同的值返回。
负数:-180 到 -1
此处使用 mod 将返回 180 到 359 度范围内的值。
特殊情况:0 和 360
使用 mod 意味着返回 0,这使其成为安全的 0-359 度解决方案。
Solution using Modulo
A simple solution that catches all cases.
Explanation
Positive: 1 to 180
If you mod any positive number between 1 and 180 by 360, you will get the exact same number you put in. Mod here just ensures these positive numbers are returned as the same value.
Negative: -180 to -1
Using mod here will return values in the range of 180 and 359 degrees.
Special cases: 0 and 360
Using mod means that 0 is returned, making this a safe 0-359 degrees solution.
如果 atan2 的答案小于 0°,则添加 360°。
Add 360° if the answer from atan2 is less than 0°.
或者,如果您不喜欢分支,请将两个参数取反并将答案添加 180°。
(向返回值添加 180° 使其很好地处于 0-360 范围内,但会翻转角度。对两个输入参数求反会将其翻转回来。)
Or if you don't like branching, negate the two parameters and add 180° to the answer.
(Adding 180° to the return value puts it nicely in the 0-360 range, but flips the angle. Negating both input parameters flips it back.)
@erikkallen 很接近,但不太正确。
这应该在 C++ 中有效:(取决于 fmod 的实现方式,它可能比条件表达式更快或更慢)
或者您可以这样做:
因为 (x,y) 和 (-x,-y) 的角度相差 180度。
@erikkallen is close but not quite right.
This should work in C++: (depending on how fmod is implemented, it may be faster or slower than the conditional expression)
Alternatively you could do this:
since (x,y) and (-x,-y) differ in angles by 180 degrees.
我有 2 个解决方案似乎适用于正负 x 和 y 的所有组合。
1)滥用atan2()
根据文档,atan2 按顺序接受参数 y 和 x。但是,如果您反转它们,您可以执行以下操作:
2)正确使用 atan2() 并随后进行转换
I have 2 solutions that seem to work for all combinations of positive and negative x and y.
1) Abuse atan2()
According to the docs atan2 takes parameters y and x in that order. However if you reverse them you can do the following:
2) Use atan2() correctly and convert afterwards
@Jason S:您的“fmod”变体将无法在符合标准的实现上工作。 C 标准明确且清晰(7.12.10.1,“fmod 函数”):
因此,
实际上只是对以下内容的详细重写:
然而,您的第三个建议是正确的。
@Jason S: your "fmod" variant will not work on a standards-compliant implementation. The C standard is explicit and clear (7.12.10.1, "the fmod functions"):
thus,
is actually just a verbose rewriting of:
Your third suggestion, however, is spot on.
这是一些 JavaScript。只需输入 x 和 y 值。
Here's some javascript. Just input x and y values.
这就是我通常做的事情:
This is what I normally do:
另一种解决方案是使用 mod() 函数,定义为:
function mod(a, b) {return a - Math.floor (a / b) * b;}
然后,通过以下函数,获得 ini(x,y) 和 end(x,y) 点之间的角度。该角度以标准化为 [0, 360] 度的度数表示。和北参考 360 度。
An alternative solution is to use the mod () function defined as:
function mod(a, b) {return a - Math.floor (a / b) * b;}
Then, with the following function, the angle between ini(x,y) and end(x,y) points is obtained. The angle is expressed in degrees normalized to [0, 360] deg. and North referencing 360 deg.
我制定了一个公式,将定向角度设置为 0 到 360
I have made a Formula for orienting angle into 0 to 360
这将逆时针返回 0°-360° 的度数,0° 位于 3 点钟方向。
This will return degree from 0°-360° counter-clockwise, 0° is at 3 o'clock.
值范围为 0 到 360 度的公式。
f(x,y)=180-90*(1+符号(x))* (1-符号(y^2))-45*(2+符号(x))*符号(y)
A formula to have the range of values from 0 to 360 degrees.
f(x,y)=180-90*(1+sign(x))* (1-sign(y^2))-45*(2+sign(x))*sign(y)
R包geosphere将计算bearingRhumb,这是给定原点和东距/北距的恒定方位线。东距和北距必须位于矩阵或向量中。风玫瑰图的原点是 0,0。下面的代码似乎可以轻松解决该问题:
The R packages geosphere will calculate bearingRhumb, which is a constant bearing line given an origin point and easting/northing. The easting and northing must be in a matrix or vector. The origin point for a wind rose is 0,0. The following code seems to readily resolve the issue:
-1 度变为 (-1 + 360) = 359 度
-179 度变为 (-179 + 360) = 181 度
-1 deg becomes (-1 + 360) = 359 deg
-179 deg becomes (-179 + 360) = 181 deg
对于您的应用程序,我怀疑您不需要精确的度数,而更喜欢更近似的罗盘角度,例如 16 个方向中的 1 个?如果是这样,那么这段代码就避免了 atan 问题,并且确实完全避免了浮点。它是为视频游戏编写的,因此使用 8 位和 16 位整数:
For your application I suspect you don't need exact degrees and would prefer a more approximate compass angle, eg 1 of 16 directions? If so then this code avoids atan issues and indeed avoids floating point altogether. It was written for a video game so uses 8 bit and 16 bit integers: