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和端点,无论XY点结构挥动触摸事件的方向。该代码是用于iPhone但支持atan2f(任何语言)都行。

感谢您的帮助球员,同时与一般的解决方法和代码。

更新:我做了erikkallen的答案与漂亮的长变量名的功能,所以我会从现在开始理解它6个月。也许这将帮助其他一些iPhone小白。

float PointPairToBearingDegrees(CGPoint startingPoint, CGPoint endingPoint)
{
    CGPoint originPoint = CGPointMake(endingPoint.x - startingPoint.x, endingPoint.y - startingPoint.y); // get origin point to origin by subtracting end from start
    float bearingRadians = atan2f(originPoint.y, originPoint.x); // get bearing in radians
    float bearingDegrees = bearingRadians * (180.0 / M_PI); // convert to degrees
    bearingDegrees = (bearingDegrees > 0.0 ? bearingDegrees : (360.0 + bearingDegrees)); // correct discontinuity
    return bearingDegrees;
}
有帮助吗?

解决方案

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

其他提示

使用模解决方案

一个简单的解决方案来捕获所有的情况下。

degrees = (degrees + 360) % 360;  // +360 for implementations where mod returns negative numbers

说明

<强> 正:1到180

如果您通过360国防部1和180之间的正数,你会得到你把完全相同的号码。国防部这里只是确保这些正数返回相同的值。

<强> 阴性:-180到-1

使用MOD这里将在180和359度的范围内返回值。

<强> 特殊情况是:0和360

使用模装置,其返回0,使之成为一个安全0-359度的解决方案。

只需添加360°,如果从ATAN2答案是小于0°。

或者,如果你不喜欢的分支,只是否定了两个参数,并添加180°的答案。

(添加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 = fmod(atan2(y,x)/M_PI*180,360);

另外,你可以这样做:

theta_deg = atan2(-y,-x)/M_PI*180 + 180;

因为(X,Y)和(-x,-y)以180度的角度中不同。

我有2个解决方案,似乎对的正和负x和y的所有组合工作。

<强> 1)滥用ATAN2()

据需要ATAN2的顺序参数y和x的文档。不过,如果你扭转他们,你可以做到以下几点:

double radians = std::atan2(x, y);
double degrees = radians * 180 / M_PI;
if (radians < 0)
{
    degrees += 360; 
}

<强> 2)使用ATAN2()正确地和之后转换

double degrees = std::atan2(y, x) * 180 / M_PI;
if (degrees > 90)
{
    degrees = 450 - degrees;
}
else
{
    degrees = 90 - degrees;
}

@Jason S:你的“FMOD”变种不会对符合标准的实施工作。 C标准是明确的和明确的(7.12.10.1 “的FMOD功能”):

  

如果y为非零值,结果具有相同的符号为x

因此,

fmod(atan2(y,x)/M_PI*180,360)

实际上只是一个详细重写:

atan2(y,x)/M_PI*180

您第三项建议,但是,是即期。

这就是我通常做的:

float rads = atan2(y, x);
if (y < 0) rads = M_PI*2.f + rads;
float degrees = rads*180.f/M_PI;
angle = Math.atan2(x,y)*180/Math.PI;

我已经作出了式用于定向角成0到360

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

另一种解决方案是使用 MOD 定义为()函数:

function mod(a, b) {return 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封装地圈将计算bearingRhumb,其是给定的原点和东/北向的恒定方位线。的东向和北向必须在一个矩阵或矢量。对于风玫瑰的原点是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)
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) ;

-1度成为(-1 + 360)= 359度,点击 -179度变为(-179 + 360)= 181度

double degree = fmodf((atan2(x, y) * (180.0 / M_PI)) + 360, 360);

此将从逆时针0°-360°返回度,0°是在3点钟。

一个公式来具有的值的范围从0到360度。

F(X,Y)= 180-90 *(1 +符号(X))*(1-符号(Y ^ 2)) - 45 *(2 +符号(X))*符号(Y)

     -(180/pi())*sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top