373 lines
13 KiB
Markdown
373 lines
13 KiB
Markdown
坐标转换工具为 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 模块的整体架构 |