wil*_*lc2 91 math atan2 quartz-2d
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);
Run Code Online (Sandbox Code Playgroud)
在给定startPoint和endPoint两个XY点结构的情况下,我正在计算滑动触摸事件的方向.该代码适用于iPhone,但任何支持atan2f()的语言都可以.
感谢您的帮助,包括一般解决方案和代码.
更新:我将erikkallen的答案变成了一个具有漂亮的长变量名的函数,所以我将在6个月后理解它.也许它会帮助其他一些iPhone noob.
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;
}
Run Code Online (Sandbox Code Playgroud)
Lia*_*rth 85
一个捕获所有案例的简单解决方案.
degrees = (degrees + 360) % 360; // +360 for implementations where mod returns negative numbers
Run Code Online (Sandbox Code Playgroud)
正面:1到180
如果您修改1到180之间的任何正数360,您将得到完全相同的数字.这里的Mod只是确保这些正数返回相同的值.
负数:-180到-1
在这里使用mod将返回180和359度范围内的值.
特殊情况:0和360
使用mod意味着返回0,使其成为一个安全的0-359度解决方案.
eri*_*len 55
(x > 0 ? x : (2*PI + x)) * 360 / (2*PI)
Run Code Online (Sandbox Code Playgroud)
aib*_*aib 31
或者,如果您不喜欢分支,只需取消两个参数并将180°添加到答案中.
Jas*_*n S 20
@erikkallen很接近但不太对劲.
theta_rad = atan2(y,x);
theta_deg = (theta_rad/M_PI*180) + (theta_rad > 0 ? 0 : 360);
Run Code Online (Sandbox Code Playgroud)
这应该适用于C++ :(取决于fmod的实现方式,它可能比条件表达式更快或更慢)
theta_deg = fmod(atan2(y,x)/M_PI*180,360);
Run Code Online (Sandbox Code Playgroud)
或者你可以这样做:
theta_deg = atan2(-y,-x)/M_PI*180 + 180;
Run Code Online (Sandbox Code Playgroud)
因为(x,y)和(-x,-y)的角度相差180度.
小智 10
这是一些 JavaScript。只需输入 x 和 y 值。
var angle = (Math.atan2(x,y) * (180/Math.PI) + 360) % 360;
Run Code Online (Sandbox Code Playgroud)
我有两个解决方案似乎适用于正负x和y的所有组合.
1)滥用atan2()
根据文档,atan2按顺序获取参数y和x.但是,如果您反转它们,则可以执行以下操作:
double radians = std::atan2(x, y);
double degrees = radians * 180 / M_PI;
if (radians < 0)
{
degrees += 360;
}
Run Code Online (Sandbox Code Playgroud)
2)正确使用atan2()并在之后进行转换
double degrees = std::atan2(y, x) * 180 / M_PI;
if (degrees > 90)
{
degrees = 450 - degrees;
}
else
{
degrees = 90 - degrees;
}
Run Code Online (Sandbox Code Playgroud)
@Jason S:您的"fmod"变体不适用于符合标准的实现.C标准明确而清晰(7.12.10.1,"fmod函数"):
如果y非零,则结果与x具有相同的符号
从而,
fmod(atan2(y,x)/M_PI*180,360)
Run Code Online (Sandbox Code Playgroud)
实际上只是一个冗长的重写:
atan2(y,x)/M_PI*180
Run Code Online (Sandbox Code Playgroud)
然而,你的第三个建议是现场.
这是我通常的做法:
float rads = atan2(y, x);
if (y < 0) rads = M_PI*2.f + rads;
float degrees = rads*180.f/M_PI;
Run Code Online (Sandbox Code Playgroud)