Math 如何将atan2()映射到0-360度

Math 如何将atan2()映射到0-360度,math,quartz-2d,atan2,Math,Quartz 2d,Atan2,atan2(y,x)在180°处存在不连续性,顺时针方向切换为-180°…0° 如何将值的范围映射到0°…360° 这是我的密码: CGSize-deltaPoint=CGSizeMake(endPoint.x-startPoint.x,endPoint.y-startPoint.y); 浮动滑动轴承=atan2f(deltaPoint.height,deltaPoint.width); 我正在计算滑动触摸事件的方向,给定起始点和端点,这两个点都是XY点结构。该代码适用于iPhone,但任何支

atan2(y,x)
在180°处存在不连续性,顺时针方向切换为-180°…0°

如何将值的范围映射到0°…360°

这是我的密码:

CGSize-deltaPoint=CGSizeMake(endPoint.x-startPoint.x,endPoint.y-startPoint.y);
浮动滑动轴承=atan2f(deltaPoint.height,deltaPoint.width);

我正在计算滑动触摸事件的方向,给定
起始点
端点
,这两个点都是XY点结构。该代码适用于iPhone,但任何支持atan2f()的语言都可以。

如果atan2的答案小于0°,只需添加360°。

或者如果您不喜欢分支,只需将两个参数取反,并将答案添加180°

(x > 0 ? x : (2*PI + x)) * 360 / (2*PI)

(向返回值添加180°可以很好地将其置于0-360范围内,但会翻转角度。对两个输入参数求反会将其翻转回来。)

@erikkallen接近但不完全正确

theta_rad = atan2(y,x);
theta_deg = (theta_rad/M_PI*180) + (theta_rad > 0 ? 0 : 360);
这应该在C++中工作:(取决于fmod的实现方式,它可能比条件表达式快或慢)

或者,您可以这样做:

theta_deg = atan2(-y,-x)/M_PI*180 + 180;
因为(x,y)和(-x,-y)的角度相差180度。

@Jason S:您的“fmod”变体在符合标准的实现上不起作用。C标准明确明了(7.12.10.1,“fmod功能”):

如果y不为零,则结果的符号与x相同

因此,

实际上只是对以下内容的冗长重写:

atan2(y,x)/M_PI*180

然而,你的第三个建议是正确的。

我有两个解决方案似乎适用于所有正负x和y的组合

1)滥用atan2()

根据文档,atan2按该顺序获取参数y和x。但是,如果将其反转,则可以执行以下操作:

double radians = std::atan2(x, y);
double degrees = radians * 180 / M_PI;
if (radians < 0)
{
    degrees += 360; 
}
用模求解 一个简单的解决方案,适用于所有情况

degrees = (degrees + 360) % 360;  // +360 for implementations where mod returns negative numbers
解释 阳性:1到180

如果你修改1到180乘360之间的任何正数,你将得到与你输入的完全相同的数字。这里的Mod只是确保这些正数作为相同的值返回

负-180至-1

在此处使用mod将返回180到359度范围内的值

特殊情况:0和360

使用mod意味着返回0,这是一个安全的0-359度解决方案

angle = Math.atan2(x,y)*180/Math.PI;
我已经做了一个将角度定向为0到360度的公式

angle + Math.ceil( -angle / 360 ) * 360;

另一种解决方案是使用定义为以下内容的mod()函数:

函数mod(a,b){返回a-Math.floor(a/b)*b;}

然后,使用以下函数,获得ini(x,y)端点(x,y)点之间的角度。角度以标准化为[0,360]度的角度表示,以360度为北参考

    function angleInDegrees(ini, end) {
        var radian = Math.atan2((end.y - ini.y), (end.x - ini.x));//radian [-PI,PI]
        return mod(radian * 180 / Math.PI + 90, 360);
    }

R包geosphere将计算轴承Rhumb,这是给定原点和东/北距的恒定轴承线。东距和北距必须在矩阵或向量中。风玫瑰的原点为0,0。以下代码似乎很容易解决此问题:

windE<-wind$uasE
windN<-wind$vasN
wind_matrix<-cbind(windE, windN)
wind$wind_dir<-bearingRhumb(c(0,0), wind_matrix)
wind$wind_dir<-round(wind$wind_dir, 0)
windE
这将逆时针从0°-360°返回角度,0°在3点钟。

theta\u rad=Math.Atan2(y,x);
theta_rad = Math.Atan2(y,x);
if(theta_rad < 0)
  theta_rad = theta_rad + 2 * Math.PI;    //if neg., add 2 PI to it
theta_deg = (theta_rad/M_PI*180) ;        //convert from radian to degree

//or
theta_rad = Math.Atan2(y,x);
theta_rad = (theta_rad < 0) ? theta_rad + 2 * Math.PI : theta_rad;
theta_deg = (theta_rad/M_PI*180) ;
if(θu rad<0) θrad=θrad+2*Math.PI//如果为负数,则向其添加2π θ度=(θ弧度/Mπ*180)//从弧度转换为度 //或 θ_rad=数学Atan2(y,x); θrad=(θrad<0)?theta_rad+2*Math.PI:theta_rad; θ度=(θ弧度/Mπ*180);
-1度变成(-1+360)=359度

-179度变成(-179+360)=181度这是我通常做的:

float rads = atan2(y, x);
if (y < 0) rads = M_PI*2.f + rads;
float degrees = rads*180.f/M_PI;
float rads=atan2(y,x);
如果(y<0)rads=M_PI*2.f+rads;
浮动角度=rads*180.f/M_PI;

一个取值范围为0到360度的公式

f(x,y)=180-90*(1+符号(x))*(1-符号(y^2))-45*(2+符号(x))*符号(y)


这里有一些javascript。只需输入x和y值

var angle = (Math.atan2(x,y) * (180/Math.PI) + 360) % 360;

对于x=0的情况,可能也希望x>=0。对于那些不习惯这种表示法的人,并且不需要转换为内置的度:if(x>0){radians=x;}else{radians=2*PI+x;},所以如果小于0,我们只需在结果中添加2PI。或者
(x>=0?x:(2*PI+x))*180/PI
(x
(x<0?2*PI+x:x)*180/PI
谢谢,这正是我想要的。我宁愿修改我的代码以使用非规范化角度(=360),但似乎总有人想要那种虚假的“优化”感觉;这就是为什么我想加上这个。(或者是因为这是绕过我使用的一些临时调试代码的更快的方法吗?嗯)绝对不容易摸索,因为我可以在2年多后同意这一点。因此:向返回值添加180°可以很好地将其置于0-360范围内,但会翻转角度。否定两个输入参数会将其翻转回去。当$x=0$和$y>0$IIR时,可能会出现一些问题注意:发布的更新方法不会返回零度,而是返回略高于0到360.0的值。>[如何从两个位置获取角度][1][1]:此函数非常有效,但“承载度”计算的角度会翻转。例如,45度通常会在第1象限出现,但在第4象限出现。135度通常位于第二象限,但此函数将其返回到第三象限。我可以简单地取函数返回值x,然后从360取反,得到正确的角度值,但是我很想知道为什么会发生这种情况?这与“只需添加2*PI”相同,如果你有这样的一天。只需将代码添加到dave4420所说的:
x=(x<0)?(x+360):x我认为没有必要添加360-1%360仍然是359:)我不认为这在所有语言中都是正确的。在Javascript中-1%360=-1
在Java@pleasemorebacon不对。在某些语言中-1%360是-1。这是我最喜欢的解决方案:)如果我在
double degree = fmodf((atan2(x, y) * (180.0 / M_PI)) + 360, 360);
theta_rad = Math.Atan2(y,x);
if(theta_rad < 0)
  theta_rad = theta_rad + 2 * Math.PI;    //if neg., add 2 PI to it
theta_deg = (theta_rad/M_PI*180) ;        //convert from radian to degree

//or
theta_rad = Math.Atan2(y,x);
theta_rad = (theta_rad < 0) ? theta_rad + 2 * Math.PI : theta_rad;
theta_deg = (theta_rad/M_PI*180) ;
float rads = atan2(y, x);
if (y < 0) rads = M_PI*2.f + rads;
float degrees = rads*180.f/M_PI;
     -(180/pi())*sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
var angle = (Math.atan2(x,y) * (180/Math.PI) + 360) % 360;