C++ 来自二维单位向量的角度?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6247153/
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
Angle from 2D unit vector?
提问by jmasterx
Given unit vector 0.5, 0.5 how could I find the angle (its direction),
给定单位向量 0.5, 0.5 我怎么能找到角度(它的方向),
is it
是吗
cos(x) + sin(y)?
cos(x) + sin(y)?
回答by mpenkov
Given y and x, the angle with the x axis is given by:
给定 y 和 x,与 x 轴的角度由下式给出:
atan2(y,x)
With (0.5, 0.5) the angle is:
与 (0.5, 0.5) 的角度是:
radians:
弧度:
In [2]: math.atan2(0.5,0.5)
Out[2]: 0.7853981633974483
degrees:
度数:
In [3]: math.atan2(0.5, 0.5)*180/math.pi
Out[3]: 45.0
回答by Jonathan Grynspan
#include <cmath>
double x = 0.5;
double y = 0.5;
double angleInRadians = std::atan2(y, x);
double angleInDegrees = (angleInRadians / M_PI) * 180.0;
回答by Hi-Angel
Good answers already posted, unfortunately nobody addressed that OP wanted code to calculate the direction, being rather a global angle. Let me fix this.
好的答案已经发布,不幸的是没有人提到 OP 想要代码来计算方向,而是一个全局角度。让我解决这个问题。
atan
(mentioned in other answers)would give you an angle ±0..90°. Afterwards you'd need to figure out which quadrant the vector is in, and modify the angle accordingly; and don't forget the special cases of either x or y equal to zero! Here's a slightly modified code I use:
atan
(在其他答案中提到)会给你一个±0..90°的角度。之后你需要找出向量所在的象限,并相应地修改角度;并且不要忘记 x 或 y 等于零的特殊情况!这是我使用的稍微修改的代码:
#include <cmath>
#include <iostream>
using namespace std;
constexpr int radToDeg(float rad) { return rad*(180/M_PI); }
int vectorAngle(int x, int y) {
if (x == 0) // special cases
return (y > 0)? 90
: (y == 0)? 0
: 270;
else if (y == 0) // special cases
return (x >= 0)? 0
: 180;
int ret = radToDeg(atanf((float)y/x));
if (x < 0 && y < 0) // quadrant Ⅲ
ret = 180 + ret;
else if (x < 0) // quadrant Ⅱ
ret = 180 + ret; // it actually substracts
else if (y < 0) // quadrant Ⅳ
ret = 270 + (90 + ret); // it actually substracts
return ret;
}
int main() {
cout << vectorAngle(1,0) << endl
<< vectorAngle(1,1) << endl
<< vectorAngle(0,1) << endl
<< vectorAngle(-1,1) << endl
<< vectorAngle(-1,0) << endl
<< vectorAngle(-1,-1) << endl
<< vectorAngle(0,-1) << endl
<< vectorAngle(1,-1) << endl
<< endl;
}
$ g++ test2.cpp -o a -g3 -O0 && ./a
0
45
90
135
180
225
270
315
In real code, however, if you use both degrees and radians a lot (e.g. because you're getting an input with degrees, and then C++ functions are using radians), I'd recommend to use wrappers around them to not swap them occasionally (which did happen to me). For the sake of completeness below is a snip of relevant code from my bot for a car game, use it however you like :)
但是,在实际代码中,如果您经常同时使用度数和弧度(例如,因为您获得带有度数的输入,然后 C++ 函数正在使用弧度),我建议您在它们周围使用包装器,不要偶尔交换它们(这确实发生在我身上)。为了完整起见,下面是我的机器人汽车游戏相关代码的片段,您可以随意使用它:)
#include <cmath>
#include <iostream>
using namespace std;
struct Point {
int x, y;
bool operator==(const Point& p) const {
return p.x == x && p.y == y;
}
bool operator!=(const Point& p) const {
return !(p == *this);
}
Point operator+(const Point& rhs) const {
return {x + rhs.x, y + rhs.y};
}
Point operator-(const Point& rhs) const {
return {x - rhs.x, y - rhs.y};
}
void operator+=(const Point& rhs) {
x += rhs.x;
y += rhs.y;
}
friend ostream& operator<<(ostream& os, const Point& p) {
os << "x = " << p.x << ", y = " << p.y;
return os;
}
};
template<typename T>
struct NumWrapper {
T val;
friend ostream& operator<<(ostream& os, const NumWrapper& w) {
os << w.val;
return os;
}
friend istream& operator>>(istream& is, NumWrapper& w) {
is >> w.val;
return is;
}
NumWrapper operator-(const T rhs) const {
return {val - rhs};
}
NumWrapper operator-(const NumWrapper rhs) const {
return {val - rhs.val};
}
NumWrapper operator-() const {
return {-val};
}
NumWrapper operator+(const T rhs) const {
return {val + rhs};
}
NumWrapper operator+(const NumWrapper rhs) const {
return {val + rhs.val};
}
};
using Degree = NumWrapper<int>;
using Radian = NumWrapper<float>;
constexpr Radian degToRad(Degree degree) { return {degree.val*(M_PI/180)}; }
constexpr Radian degToRad(int degree) { return {degree*(M_PI/180)}; }
constexpr Degree radToDeg(Radian rad) { return {rad.val*(180/M_PI)}; }
constexpr Degree radToDeg(float rad) { return {rad*(180/M_PI)}; }
Degree vectorAngle(const Point& vec) {
if (vec.x == 0) // special cases
return (vec.y > 0)? Degree{90}
: (vec.y == 0)? Degree{0}
: Degree{270};
else if (vec.y == 0) // special cases
return (vec.x >= 0)? Degree{0}
: Degree{180};
Degree ret = radToDeg(atanf((float)vec.y/vec.x));
if (vec.x < 0 && vec.y < 0) // quadrant Ⅲ
ret.val = 180 + ret.val;
else if (vec.x < 0) // quadrant Ⅱ
ret.val = 180 + ret.val; // it actually substracts
else if (vec.y < 0) // quadrant Ⅳ
ret.val = 270 + (90 + ret.val); // it actually substracts
return ret;
}
int main() {
cout << vectorAngle({1,0}) << endl
<< vectorAngle({1,1}) << endl
<< vectorAngle({0,1}) << endl
<< vectorAngle({-1,1}) << endl
<< vectorAngle({-1,0}) << endl
<< vectorAngle({-1,-1}) << endl
<< vectorAngle({0,-1}) << endl
<< vectorAngle({1,-1}) << endl
<< endl;
}