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;

⚠️ 注意事项

  1. atan2(0, 0) 是未定义行为,可能返回 0,也可能触发异常。
  2. atan2(y, x) 会比 atan(y/x) 更安全和准确,尤其在 x == 0 时能正确处理。
  3. 弧度单位很常见,在需要用度数输出时需手动转换。

应用场景

非常好,那我们就从“实用角度”深入扩展 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
角度归一化 需加 360° 后取模
⚠️ 注意 atan2(0, 0) 未定义;避免直接用 atan(y/x) 代替

posted @ 2025-07-06 20:14  十八Eigh18n  阅读(28)  评论(0)    收藏  举报