7.6小学期基础语法记录
atan2 反正切值
在 C++ 中,atan2 是一个数学函数,定义在头文件 <cmath> 中,用于计算 两个参数(y, x)所确定的角度的反正切值,也就是极坐标中的角度 θ(以弧度为单位):
#include <cmath>
#include <iostream>
int main() {
double y = 1.0;
double x = 1.0;
double angle = std::atan2(y, x); // 返回弧度
std::cout << "Angle in radians: " << angle << std::endl;
std::cout << "Angle in degrees: " << angle * 180.0 / M_PI << std::endl;
return 0;
}
🔍 atan2(y, x) 的含义
它计算的是:
\[\theta = \tan^{-1}\left(\frac{y}{x}\right)
\]
但不同于单独的 atan(y/x),atan2 考虑了 x 与 y 的符号,从而能够确定 θ 所在的象限。返回值范围为:
\[(-\pi, \pi]
\]
即:
- 第一象限:
atan2(正, 正)→ [0, π/2) - 第二象限:
atan2(正, 负)→ (π/2, π] - 第三象限:
atan2(负, 负)→ (-π, -π/2] - 第四象限:
atan2(负, 正)→ (-π/2, 0)
✅ 函数原型
double atan2(double y, double x); // double 类型
float atan2f(float y, float x); // float 类型
long double atan2l(long double y, long double x); // long double 类型
🌟 使用场景举例
1. 极坐标角度计算
double x = 3, y = 4;
double theta = atan2(y, x); // 弧度:约 0.927(53度)
2. 二维向量方向
struct Point {
double x, y;
};
double angle_between(const Point& a, const Point& b) {
return atan2(b.y - a.y, b.x - a.x); // 从 a 到 b 的方向
}
3. 转为角度(单位为度)
double radians = atan2(y, x);
double degrees = radians * 180.0 / M_PI;
⚠️ 注意事项
atan2(0, 0)是未定义行为,可能返回 0,也可能触发异常。atan2(y, x)会比atan(y/x)更安全和准确,尤其在x == 0时能正确处理。- 弧度单位很常见,在需要用度数输出时需手动转换。
应用场景
非常好,那我们就从“实用角度”深入扩展 atan2(y, x) 在 C++ 中的典型应用场景,包括:
🧭 1. 机器人 / 移动系统中的朝向计算
✅ 任务:
给定一个机器人当前位置
(x1, y1),和目标点(x2, y2),计算机器人应该朝哪个方向移动。
double get_heading(double x1, double y1, double x2, double y2) {
return atan2(y2 - y1, x2 - x1); // 返回弧度方向角
}
👉 如果你使用 ROS2、OpenCV、SLAM,这个函数会非常常见,用于计算机器人的 朝向(heading)或偏航角(yaw)。
🧠 2. 角度归一化与方位判断
atan2 返回的是 (-π, π],但有时我们需要角度落在 [0, 2π) 或 [0°, 360°)。
double normalize_angle_rad(double angle) {
if (angle < 0)
angle += 2 * M_PI;
return angle;
}
double normalize_angle_deg(double angle) {
if (angle < 0)
angle += 360;
return angle;
}
🖼️ 3. 图像处理中的旋转角度检测(OpenCV 相关)
在图像识别中,atan2 常用于:
- 矩形的主方向角度
- 边缘方向
- 特征点朝向
例如计算两个点之间的连线角度:
cv::Point2f a(10, 10), b(30, 40);
double angle = atan2(b.y - a.y, b.x - a.x);
double degrees = angle * 180 / CV_PI; // OpenCV 中用 CV_PI
🎯 4. 游戏/图形开发中的角度控制
在 2D 游戏或图形中,atan2 可用于:
- 人物朝向鼠标
- 子弹发射角度
- 精灵旋转
struct Vec2 {
double x, y;
};
double get_rotation_angle(Vec2 origin, Vec2 target) {
return atan2(target.y - origin.y, target.x - origin.x);
}
🔁 5. 向量夹角计算
若已知两个向量 v1 = (x1, y1) 和 v2 = (x2, y2),可用:
double angle_between_vectors(double x1, double y1, double x2, double y2) {
double dot = x1 * x2 + y1 * y2;
double det = x1 * y2 - y1 * x2;
return atan2(det, dot); // 返回两个向量的夹角(有方向)
}
✔️ 优点:比 acos(dot/(|a||b|)) 更稳定,不怕除 0 或精度丢失。
❗ 错误案例解析:为什么不能用 atan(y/x) 替代
假设:
double x = -1, y = 1;
std::cout << atan(y / x); // -0.785398(第四象限)
std::cout << atan2(y, x); // 2.35619(第二象限)
🧨 错误结果:使用 atan(y/x) 会将所有角度强行压缩进 (-π/2, π/2) 区间,不考虑象限,破坏方向性。
✅ 总结笔记
| 内容 | 说明 |
|---|---|
| 函数定义 | atan2(y, x) 计算 (y,x) 极坐标方向角,单位为弧度 |
| 返回范围 | (-π, π],考虑象限 |
| 常见用途 | 机器人航向、图像角度检测、2D游戏朝向、向量方向 |
与 atan(y/x) 区别 |
atan2 可判断象限,atan 不可 |
| 度数转换 | angle * 180.0 / M_PI |
| 角度归一化 | 需加 2π 或 360° 后取模 |
| ⚠️ 注意 | atan2(0, 0) 未定义;避免直接用 atan(y/x) 代替 |

浙公网安备 33010602011771号