坐标转换工具为 GIS 和测绘应用提供了一套完整的坐标系统转换功能,涵盖角度格式转换、坐标系统转换、几何变换等核心能力。本模块通过 PySSMath 提供高性能的坐标转换算法,支持从基础的角度格式互转到复杂的坐标系统映射变换。本文档面向高级开发者,详细说明各类坐标转换工具的 API 使用方法和应用场景。 Sources: [PySSMath.py](PySSMath.py#L2700-L2787) ## 角度格式转换 PySSMath 提供了多种角度表示形式之间的转换功能,支持弧度制、十进制度数、度分秒(DMS)格式之间的灵活互转,满足测绘应用中不同角度表示需求。 ### 基础角度转换 | 函数名 | 功能描述 | 参数 | 返回值 | |--------|----------|------|--------| | `degToRadian(deg)` | 十进制度数转弧度 | deg: float | 弧度值 | | `radianToDeg(dRadian)` | 弧度转十进制度数 | dRadian: float | 度数值 | | `degToDms(deg)` | 十进制度数转度分秒 | deg: float | DMS 值 | | `dmsToDeg(dms)` | 度分秒转十进制度数 | dms: float | 度数值 | | `dmsToRadian(dDms)` | 度分秒转弧度 | dDms: float | 弧度值 | | `radianToDms(dRadian)` | 弧度转度分秒 | dRadian: float | DMS 值 | | `dmsToSec(dms)` | 度分秒转秒数 | dms: float | 秒数 | | `secToDms(sec)` | 秒数转度分秒 | sec: float | DMS 值 | ### 角度调整函数 | 函数名 | 功能描述 | 参数说明 | |--------|----------|----------| | `adjustAngle(dRadian)` | 调整弧度值到 [-π, π] 范围 | dRadian: 待调整的弧度值 | | `adjustDmsAngle(dAngle)` | 调整 DMS 角度值 | dAngle: 待调整的 DMS 角度值 | | `adjustDegAngle(dAngle)` | 调整度数值到 [0, 360] 范围 | dAngle: 待调整的度数值 | ### 角度转换示例 ```python import sunvpy.PySSMath as ssMath # 十进制度数转弧度 deg_value = 45.5 rad_value = ssMath.degToRadian(deg_value) print(f"{deg_value}° = {rad_value:.6f} rad") # 弧度转度分秒 dms_value = ssMath.radianToDms(1.5708) print(f"1.5708 rad = {dms_value:.4f} (DMS格式)") # 角度调整到标准范围 adjusted_angle = ssMath.adjustAngle(7.0) # 超出范围的角度 print(f"调整后角度: {adjusted_angle:.6f} rad") ``` Sources: [PySSMath.py](PySSMath.py#L2752-L2767) ## 极坐标与直角坐标转换 极坐标和直角坐标是两种常用的坐标表示方式,适用于不同的应用场景。PySSMath 提供了两者之间的双向转换功能。 ### 坐标转换函数 | 函数名 | 功能描述 | 参数说明 | |--------|----------|----------| | `rightToPolar(x, y)` | 直角坐标转极坐标 | x, y: 直角坐标值,返回 (距离, 方位角) | | `polarToRight(r, angle)` | 极坐标转直角坐标 | r: 距离;angle: 方位角(弧度) | | `getPolar(p1, p2, dist, dRadian)` | 从基点按距离和方位角获取点 | p1: 基点;p2: 参考点;dist: 距离;dRadian: 方位角 | | `getPoint(p1, p2, dist, dRadian)` | 同 getPolar | 参数同 getPolar | ### 极坐标转换示例 ```python import sunvpy.PySSMath as ssMath # 直角坐标转极坐标 x, y = 100.0, 100.0 distance, angle = ssMath.rightToPolar(x, y) print(f"直角坐标 ({x}, {y}) -> 极坐标: 距离={distance:.2f}, 方位角={angle:.6f} rad") # 极坐标转直角坐标 r = 141.42 angle_rad = 0.785398 x_new, y_new = ssMath.polarToRight(r, angle_rad) print(f"极坐标 (r={r}, angle={angle_rad}) -> 直角坐标: ({x_new:.2f}, {y_new:.2f})") # 从基点获取极坐标点 import sunvpy.PySSMath.Point3D as Point3D p1 = Point3D(0, 0, 0) p2 = Point3D(1, 0, 0) new_point = ssMath.getPolar(p1, p2, 100, ssMath.degToRadian(45)) print(f"从原点向东45°方向100米处的点: ({new_point.x():.2f}, {new_point.y():.2f})") ``` Sources: [PySSMath.py](PySSMath.py#L2808-L2815) ## 方位角计算 方位角计算是测绘和导航应用中的核心功能,PySSMath 提供了多种方位角计算方法,支持点对点方位角、角度平分等场景。 ### 方位角计算函数 | 函数名 | 功能描述 | 参数说明 | |--------|----------|----------| | `bearing(x1, y1, x0, y0)` | 计算从点 (x0, y0) 到点 (x1, y1) 的方位角 | 返回弧度值 | | `bearing(p0, p1)` | 计算方位角(使用 Point3D 对象) | p0: 起始点;p1: 目标点 | | `jiaoPingfenFangWei(x1, y1, x0, y0, x2, y2)` | 计算两线段的夹角平分方位角 | (x1,y1)-(x0,y0) 和 (x2,y2)-(x0,y0) 的平分方向 | ### 角度计算函数 | 函数名 | 功能描述 | 返回值 | |--------|----------|--------| | `openAngle(p1, p0, p2)` | 计算 ∠p1p0p2 的夹角 | 弧度值 | | `openAngleDeg(p1, p0, p2)` | 计算夹角(度数) | 度数 | ### 方位角计算示例 ```python import sunvpy.PySSMath as ssMath import sunvpy.PySSMath.Point3D as Point3D # 计算两点间的方位角 x0, y0 = 100.0, 100.0 # 起点 x1, y1 = 200.0, 150.0 # 终点 azimuth_rad = ssMath.bearing(x1, y1, x0, y0) azimuth_deg = ssMath.radianToDeg(azimuth_rad) print(f"从 ({x0}, {y0}) 到 ({x1}, {y1}) 的方位角: {azimuth_deg:.2f}°") # 使用 Point3D 对象计算方位角 p0 = Point3D(100.0, 100.0, 0) p1 = Point3D(200.0, 150.0, 0) azimuth_rad2 = ssMath.bearing(p0, p1) print(f"方位角(弧度): {azimuth_rad2:.6f}") # 计算角度平分方向 # 从 (0,0) 到 (100,0) 和 (0,100) 的夹角平分方向 bisect_angle = ssMath.jiaoPingfenFangWei(100, 0, 0, 0, 0, 100) bisect_deg = ssMath.radianToDeg(bisect_angle) print(f"90°角的平分方位角: {bisect_deg:.2f}°") # 计算三点夹角 p1 = Point3D(0, 100, 0) p_center = Point3D(0, 0, 0) p2 = Point3D(100, 0, 0) angle_rad = ssMath.openAngle(p1, p_center, p2) angle_deg = ssMath.radianToDeg(angle_rad) print(f"夹角 ∠p1-center-p2: {angle_deg:.2f}°") ``` Sources: [PySSMath.py](PySSMath.py#L2789-L2797) ## 几何变换操作 几何变换是坐标转换的重要应用场景,包括旋转、平移、缩放、镜像等基本变换,以及系统坐标旋转、映射变换等高级变换。 ### 二维几何变换 | 函数名 | 功能描述 | 参数说明 | |--------|----------|----------| | `rotate2DList(Points, angle, basePoint)` | 二维点集旋转 | angle: 旋转角(弧度);basePoint: 旋转基点 | | `offset2DList(Points, dx, dy)` | 二维点集平移 | dx, dy: X和Y方向的平移量 | ### 三维几何变换 | 函数名 | 功能描述 | 参数说明 | |--------|----------|----------| | `rotate3DList(*args)` | 三维点集旋转 | 支持多种参数形式(绕轴旋转、绕任意轴旋转) | | `offset3DList(*args)` | 三维点集偏移 | 支持偏移向量或分量形式 | | `zoom3DList(*args)` | 三维点集缩放 | 支持缩放中心和缩放因子 | | `mirror3DList(baseP0, baseP1, Ps)` | 三维点集镜像 | baseP0, baseP1: 镜像轴上的两点;Ps: 待变换点集 | | `extend3DList(Points, dist, bTail)` | 点集延伸 | dist: 延伸距离;bTail: true=尾部延伸,false=头部延伸 | | `smooth3DList(Ps0, fScale, nFlag)` | 点集平滑 | fScale: 平滑系数;nFlag: 平滑方式 | | `mapping3DList(Points, ctrlPoints_old, ctrlPoints_new)` | 点集映射变换 | 基于控制点的仿射变换 | ### 系统坐标变换 | 函数名 | 功能描述 | 参数说明 | |--------|----------|----------| | `sysRotate(Xold, Yold, Xnew, Ynew, X0, Y0, dRadian)` | 系统旋转 | 将旧坐标系旋转至新坐标系 | | `grdbodyRotate(*args)` | 网格体旋转 | 支持多种参数形式 | ### 几何变换示例 ```python import sunvpy.PySSMath as ssMath import sunvpy.PySSMath.POINT3DLIST as POINT3DLIST import sunvpy.PySSMath.Point3D as Point3D # 创建点集 points = POINT3DLIST() points.push_back(Point3D(10, 10, 0)) points.push_back(Point3D(20, 10, 0)) points.push_back(Point3D(20, 20, 0)) # 二维旋转(绕原点旋转90度) basePoint = Point3D(0, 0, 0) angle = ssMath.degToRadian(90) ssMath.rotate2DList(points, angle, basePoint) print("旋转后的点集:") for i in range(points.size()): pt = points.at(i) print(f" 点{i+1}: ({pt.x():.2f}, {pt.y():.2f}, {pt.z():.2f})") # 二维平移 ssMath.offset2DList(points, 5.0, 5.0) print("平移后的点集:") for i in range(points.size()): pt = points.at(i) print(f" 点{i+1}: ({pt.x():.2f}, {pt.y():.2f}, {pt.z():.2f})") # 镜像变换 points2 = POINT3DLIST() points2.push_back(Point3D(10, 10, 0)) points2.push_back(Point3D(30, 10, 0)) points2.push_back(Point3D(30, 30, 0)) baseP0 = Point3D(0, 0, 0) # 镜像轴起点 baseP1 = Point3D(1, 0, 0) # 镜像轴终点(X轴) ssMath.mirror3DList(baseP0, baseP1, points2) print("镜像后的点集:") for i in range(points2.size()): pt = points2.at(i) print(f" 点{i+1}: ({pt.x():.2f}, {pt.y():.2f}, {pt.z():.2f})") ``` Sources: [PySSMath.py](PySSMath.py#L2819-L2840) ## 坐标转换应用场景 ### 测绘坐标转换 ```python import sunvpy.PySSMath as ssMath # 场景1:测量角度转换 # 将测量得到的度分秒格式转换为十进制度数 dms_angle = 30.3045 # 30°30'45" 表示为 30.3045 deg_angle = ssMath.dmsToDeg(dms_angle) rad_angle = ssMath.degToRadian(deg_angle) print(f"测量角度 {dms_angle:.4f} (DMS) = {deg_angle:.6f}° = {rad_angle:.6f} rad") # 场景2:方位角归一化 # 确保方位角在 [0, 2π) 范围内 azimuth = 450.0 # 超出范围的方位角 normalized_deg = ssMath.adjustDegAngle(azimuth) normalized_rad = ssMath.degToRadian(normalized_deg) print(f"归一化方位角: {azimuth}° -> {normalized_deg:.2f}° = {normalized_rad:.6f} rad") # 场景3:极坐标测量转直角坐标 # 从测站向东偏北45°方向测量距离100米 dist = 100.0 azimuth_from_north = ssMath.degToRadian(45) # 从北方向向东 # 注意:测量通常以北方为0°,顺时针为正 # PySSMath的bearing函数可能以东方为0°,需要根据实际情况调整 ``` ### GIS 坐标变换 ```python import sunvpy.PySSMath as ssMath import sunvpy.PySSMath.POINT3DLIST as POINT3DLIST import sunvpy.PySSMath.Point3D as Point3D # 场景1:地图旋转校正 # 将倾斜的地图元素旋转到标准方向 polygon = POINT3DLIST() polygon.push_back(Point3D(100, 100, 0)) polygon.push_back(Point3D(110, 95, 0)) polygon.push_back(Point3D(105, 105, 0)) # 计算需要旋转的角度 angle_correction = ssMath.degToRadian(5) # 逆时针旋转5度 rotation_center = Point3D(100, 100, 0) ssMath.rotate2DList(polygon, angle_correction, rotation_center) # 场景2:坐标系平移 # 将局部坐标系下的坐标转换到全局坐标系 offset_x = 500000.0 # 全局坐标系X偏移量 offset_y = 3000000.0 # 全局坐标系Y偏移量 ssMath.offset2DList(polygon, offset_x, offset_y) # 场景3:比例尺变换 # 应用地图比例尺变换 scale_factor = 1000.0 # 1:1000比例尺 zoom_center = Point3D(500000, 3000000, 0) ssMath.zoom3DList(polygon, scale_factor, scale_factor, scale_factor, zoom_center) ``` ### 工程应用变换 ```python import sunvpy.PySSMath as ssMath import sunvpy.PySSMath.POINT3DLIST as POINT3DLIST import sunvpy.PySSMath.Point3D as Point3D # 场景:基于控制点的坐标映射 # 已知旧坐标系和新坐标系中的控制点对 control_points_old = POINT3DLIST() control_points_old.push_back(Point3D(0, 0, 0)) control_points_old.push_back(Point3D(100, 0, 0)) control_points_old.push_back(Point3D(0, 100, 0)) control_points_new = POINT3DLIST() control_points_new.push_back(Point3D(500000, 3000000, 0)) control_points_new.push_back(Point3D(500100, 3000000, 0)) control_points_new.push_back(Point3D(500000, 3000100, 0)) # 待变换的点集 points_to_transform = POINT3DLIST() points_to_transform.push_back(Point3D(50, 50, 0)) points_to_transform.push_back(Point3D(75, 25, 0)) # 执行映射变换 ssMath.mapping3DList(points_to_transform, control_points_old, control_points_new) print("变换后的点:") for i in range(points_to_transform.size()): pt = points_to_transform.at(i) print(f" 点{i+1}: ({pt.x():.2f}, {pt.y():.2f}, {pt.z():.2f})") ``` Sources: [PySSMath.py](PySSMath.py#L2700-L2900) ## 最佳实践与注意事项 ### 角度单位处理 在进行角度计算时,务必注意角度单位的统一性。PySSMath 的函数默认使用弧度制进行内部计算,但提供了多种角度格式的转换函数。 ```python import sunvpy.PySSMath as ssMath # 推荐:在计算开始时统一转换为弧度制 def calculate_with_angles(deg_angle): rad_angle = ssMath.degToRadian(deg_angle) # 执行计算 result = rad_angle * 2 # 示例计算 # 将结果转换回需要的格式 return ssMath.radianToDeg(result) ``` ### 坐标变换顺序 多个几何变换的执行顺序会影响最终结果。通常建议的顺序为:平移 → 旋转 → 缩放。 ```python import sunvpy.PySSMath as ssMath import sunvpy.PySSMath.POINT3DLIST as POINT3DLIST import sunvpy.PySSMath.Point3D as Point3D points = POINT3DLIST() # ... 添加点 ... # 推荐的变换顺序 ssMath.offset3DList(points, dx, dy, dz) # 1. 先平移 ssMath.rotate3DList(points, angle, axis) # 2. 再旋转 ssMath.zoom3DList(points, sx, sy, sz, center) # 3. 最后缩放 ``` ### 精度控制 在比较坐标和角度时,使用容差而非精确相等。 ```python import sunvpy.PySSMath as ssMath import sunvpy.PySSMath.Point3D as Point3D p1 = Point3D(100.0, 100.0, 0.0) p2 = Point3D(100.0001, 100.0001, 0.0) # 使用带容差的比较 epsilon = 0.001 is_same = ssMath.isSamePoint(p1, p2, epsilon) ``` ## 相关页面 - [数学计算工具](43-shu-xue-ji-suan-gong-ju) - 了解更多数学计算相关的 API - [地理对象类型定义](42-di-li-dui-xiang-lei-xing-ding-yi) - 了解 Point3D 等基础数据结构 - [库概述](1-ku-gai-shu) - 了解 sunvpy 模块的整体架构