15.Boost.Geometry 坐标系统详解

1. cs::cartesian ------ 笛卡尔坐标系(直角坐标系)

原始描述翻译

定义笛卡尔(或称矩形)坐标系,其中点由两个、三个或更多维度的坐标表示,通常(但不总是)记作 x, y, z。

扩展说明

笛卡尔坐标系是最基础、最常用的坐标系统,适用于平面或欧几里得空间中的几何计算。在二维情形下,一个点由横坐标 x 和纵坐标 y 唯一确定;在三维情形下,增加高度坐标 z。该坐标系假设空间是平坦的(即无曲率),因此适用于局部区域的地图投影、工程建模、计算机图形学等场景。Boost.Geometry 中的许多算法(如距离、面积、交集等)默认基于笛卡尔坐标系实现,因其计算效率高且数学形式简洁。

适用场景

  • 城市地图、CAD 设计、2D 游戏引擎
  • 小范围平面距离、面积、交集等计算

C++ 示例:计算两点间距离与多边形面积

cpp 复制代码
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>

namespace bg = boost::geometry;

int main() {
    // 使用笛卡尔坐标系的 2D 点(默认即为 cartesian)
    using point = bg::model::d2::point_xy<double>;
    using polygon = bg::model::polygon<point>;

    point p1(0.0, 0.0);
    point p2(3.0, 4.0);

    double dist = bg::distance(p1, p2);
    std::cout << "笛卡尔距离: " << dist << " (应为 5.0)\n";

    // 构建一个正方形
    polygon poly;
    bg::exterior_ring(poly).assign({
        {0, 0}, {0, 2}, {2, 2}, {2, 0}, {0, 0}
    });

    double area = bg::area(poly);
    std::cout << "笛卡尔面积: " << area << " (应为 4.0)\n";

    return 0;
}

2. cs::geographic ------ 地理坐标系

原始描述翻译

定义地理坐标系,其中点由两个角度表示,通常称为纬度/经度(lat/long)、经度/纬度(lo/la)或 φ/λ(phi/lambda)。

扩展说明

地理坐标系用于在地球椭球体(或近似球体)表面定位点,使用**纬度(Latitude) 经度(Longitude)两个角度参数。纬度范围为 -90° 到 +90°(南纬到北纬),经度范围为 -180° 到 +180°(西经到东经)。Boost.Geometry 支持以 度(degree)弧度(radian)**为单位输入角度。

地理坐标系本身不包含投影信息,因此不能直接用于平面距离或面积计算------必须通过大地测量算法(如 Vincenty、Andoyer)或先投影到平面坐标系(如 UTM)再处理。Boost.Geometry 内置了对球面或椭球面距离、方位角等的高精度支持。

适用场景

  • GPS 轨迹分析、全球导航、GIS 系统
  • 需要高精度大地测量距离(如 Vincenty 算法)

C++ 示例:计算两个城市间的球面距离(WGS84 椭球)

cpp 复制代码
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>

namespace bg = boost::geometry;
namespace cs = bg::cs;

// 定义地理坐标系下的点(角度单位:度)
using point_geo = bg::model::point<double, 2, cs::geographic<bg::degree>>;

int main() {
    // 北京 (39.9°N, 116.4°E) 与 上海 (31.2°N, 121.5°E)
    point_geo beijing(116.4, 39.9);
    point_geo shanghai(121.5, 31.2);

    // 使用默认策略(Andoyer 近似,适用于球面)
    double dist_meters = bg::distance(beijing, shanghai);
    std::cout << "北京到上海距离(近似): " << dist_meters / 1000.0 << " km\n";

    // 使用更精确的策略(需指定椭球)
    bg::srs::spheroid<double> wgs84(6378137.0, 6356752.3142451793);
    bg::strategy::distance::geographic<bg::strategy::vincenty> vincenty(wgs84);
    double dist_vincenty = bg::distance(beijing, shanghai, vincenty);
    std::cout << "Vincenty 精确距离: " << dist_vincenty / 1000.0 << " km\n";

    return 0;
}

3. cs::spherical ------ 球面坐标系(极坐标形式)

原始描述翻译

定义球面坐标系,其中点由两个角度和一个可选半径表示,通常记作 r, θ, φ(半径、极角、方位角)。

扩展说明

这是数学和物理学中常见的球坐标系(Spherical Polar Coordinates) 。在 Boost.Geometry 的上下文中,通常用于单位球面上的点表示(即 r = 1 固定),仅用两个角度描述方向:

  • θ(theta):极角(polar angle),从正 z 轴(北极)向下测量,范围 [0, π] 弧度(0°~180°);
  • φ(phi):方位角(azimuthal angle),在 xy 平面内从正 x 轴逆时针测量,范围 [0, 2π) 弧度(0°~360°)。

注意:此系统中,θ = 0 对应北极,θ = π/2 对应赤道,θ = π 对应南极。这与地理坐标系中"纬度从赤道起算"不同。

适用场景

  • 天体物理方向、3D 图形光照、雷达波束建模

C++ 示例:计算单位球面上两点间的大圆距离

cpp 复制代码
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>

namespace bg = boost::geometry;
namespace cs = bg::cs;

// 使用弧度单位的球面坐标(theta, phi)
using point_sph = bg::model::point<double, 2, cs::spherical<bg::radian>>;

int main() {
    // 北极点:θ=0, φ任意
    point_sph north_pole(0.0, 0.0);
    // 赤道上某点:θ=π/2, φ=0
    point_sph equator(1.5708, 0.0); // ≈ π/2

    // 球面距离(单位球,结果为弧度)
    double angular_dist = bg::distance(north_pole, equator);
    std::cout << "球面角距离(弧度): " << angular_dist << "\n";
    std::cout << "对应弧长(单位球): " << angular_dist << "\n"; // 半径=1

    return 0;
}

4. cs::spherical_equatorial ------ 球面赤道坐标系

原始描述翻译

该坐标系类似于地理坐标系,纬度从赤道(0°)向上增至极点(90°),与球面(极)坐标系相反。常用于天文学和 GIS(但也存在地理坐标系)。

扩展说明

这是一种以赤道为基准的球面角度系统,结构上非常接近地理坐标系:

  • 第一个角度为纬度(Latitude),从赤道(0°)向北(+90°)或向南(-90°)测量;
  • 第二个角度为经度(Longitude),从本初子午线向东或向西测量。

关键区别在于:虽然形式类似 geographic,但 spherical_equatorial 明确假设地球为完美球体 (而非椭球体),且主要用于天文学中的赤道坐标系统 (如赤经/赤纬,但此处简化为角度对)。在 Boost.Geometry 中,它与 geographic 的主要差异在于内部算法假设geographic 可支持椭球模型,而 spherical_equatorial 始终按球面处理。

适用场景

  • 天文赤道坐标、教学演示、快速球面近似计算

C++ 示例:计算两点间球面距离(单位球)

cpp 复制代码
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>

namespace bg = boost::geometry;
namespace cs = bg::cs;

// 使用度为单位的赤道球面坐标(lat, lon)
using point_eq = bg::model::point<double, 2, cs::spherical_equatorial<bg::degree>>;

int main() {
    // 纽约 (40.7°N, 74.0°W) 与 伦敦 (51.5°N, 0.1°W)
    point_eq ny(-74.0, 40.7);   // 注意:经度在前!
    point_eq london(-0.1, 51.5);

    // 默认使用 haversine 公式(球面)
    double dist_rad = bg::distance(ny, london);
    double earth_radius_km = 6371.0;
    std::cout << "纽约-伦敦距离(球面近似): "
              << dist_rad * earth_radius_km << " km\n";

    return 0;
}

5. 坐标系对比总结

坐标系类型 维度 参数 单位 地球模型 典型用途
cartesian 2D/3D x, y (, z) 长度(米等) 平面(无曲率) 局部地图、工程设计
geographic 2D 纬度, 经度 角度(° 或 rad) 椭球(可选球) GPS、全球定位
spherical 2D(方向) 极角 θ, 方位角 φ 角度 单位球 物理、3D 图形
spherical_equatorial 2D 纬度, 经度 角度 完美球体 天文、简化 GIS

使用建议

  • 若处理真实地球上的位置 (如来自 GPS 的数据),优先使用 cs::geographic,并配合 WGS84 椭球参数。
  • 若进行小范围平面计算 (如城市内路径规划),可将地理坐标投影为 cs::cartesian(如使用 UTM 投影)。
  • 若仅需方向或单位球面上的点 (如卫星指向、星空模拟),可选用 cs::sphericalcs::spherical_equatorial,根据纬度定义习惯选择后者。
相关推荐
AD钙奶-lalala2 小时前
Android编译C++代码步骤详解
android·开发语言·c++
rhett. li2 小时前
FreeBSD系统中使用clang/clang++编译Skia源码的方法
c++·ui·用户界面
_风华ts3 小时前
C++函数指针
c++·函数指针
威桑3 小时前
解决 Qt6 程序 在Linux 环境下无法输入中文的问题
linux·c++·qt
浅念-3 小时前
C++ :类和对象(4)
c语言·开发语言·c++·经验分享·笔记·学习·算法
shentuyu木木木(森)3 小时前
栈与队列基础
c++··队列
yuuki2332333 小时前
【C++】模拟实现 AVL树
java·c++·算法
蜡笔小马4 小时前
20.Boost.Geometry 中常用空间算法详解:crosses、densify、difference 与离散距离度量
c++·算法·boost
Mr YiRan4 小时前
C++语言学习之面向对象
java·c++·学习