Files
sunvpy-docs/docs/content/44-zuo-biao-zhuan-huan-gong-ju.md

373 lines
13 KiB
Markdown
Raw Permalink Normal View History

2026-04-10 13:47:53 +08:00
坐标转换工具为 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 模块的整体架构