QDAirPortBackend0122/doc/guide/cad_to_yaml_guide.md
2026-01-22 13:19:47 +08:00

276 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 操作指南:从 CAD 图纸生成 airport_roads.yaml 配置文件
## 1. 目标与挑战
本指南旨在说明如何使用免费开源的 GIS 软件 QGIS从机场的 CAD 工程图纸通常使用局部坐标系生成包含精确地理坐标经纬度WGS84`airport_roads.yaml` 配置文件,以供应用程序使用。
主要挑战在于将 CAD 的局部坐标系转换为标准的 WGS84 地理坐标系,这需要准确的地理参考信息。
## 2. 准备工作
在开始之前,请确保你拥有:
* **QGIS 软件**: 从 [QGIS 官网](https://qgis.org/) 下载并安装最新稳定版。
* **机场 CAD 图纸**: `.dwg``.dxf` 格式的文件。最好是包含清晰道路中心线的版本。
* **地面控制点 (GCPs - Ground Control Points)**: **这是最关键的部分!** 你需要获取 CAD 图上至少 3-4 个(越多越好,分布越均匀越好)易于识别的点(如建筑角点、跑道端点、特定标记)的**精确真实世界地理坐标**。坐标可以是:
* **经纬度 (WGS84)**: 例如 `[经度 113.12345, 纬度 22.54321]`
* **投影坐标**: 例如 UTM 坐标,并清楚知道其对应的区域和基准面。
* 获取方式:可能来自现场 GPS 测量、官方测绘数据、高精度卫星地图的比对等。**控制点的精度直接决定了最终结果的精度。**
## 3. QGIS 安装
访问 [QGIS 官网](https://qgis.org/),根据你的操作系统下载并安装 QGIS Desktop。
## 4. CAD 文件准备(可选但推荐)
为了简化后续操作,建议在 CAD 软件中:
* 清理图纸,只保留必要的图层,尤其是**道路中心线**图层和用于**地理配准的参考点**所在图层。
* 确保道路中心线是连接良好的线段 (Polyline)。
* 如果可能,将文件另存为较旧版本的 `.dxf` 格式,有时兼容性更好。
## 5. 导入 CAD 文件到 QGIS
1. 打开 QGIS。
2. 通过菜单 `图层 (Layer)` -> `添加图层 (Add Layer)` -> `添加矢量图层 (Add Vector Layer...)` 打开数据源管理器。
3.`矢量 (Vector)` 选项卡中,选择 `文件 (File)` 类型。
4. 点击 `源 (Source)` 旁边的 `...` 按钮,浏览并选择你的 `.dwg``.dxf` 文件。
5. 点击 `添加 (Add)`。QGIS 可能会询问要导入哪些图层(如果 CAD 文件包含多个图层),选择包含道路中心线和参考点的图层。
6. 关闭数据源管理器。你现在应该能在 QGIS 地图中看到 CAD 图纸的内容。此时,它的坐标系还是未知的或局部的。
## 6. 地理配准 (Georeferencing)
这是将 CAD 局部坐标转换为地理坐标的关键步骤。
1. **打开地理配准器**: 通过菜单 `图层 (Layer)` -> `地理配准器 (Georeferencer...)` 打开工具。
2. **准备并加载要配准的图像**:
* 由于地理配准器主要处理栅格图像,你需要先将导入的 CAD 图层视图导出为图像文件。
* 在 QGIS 主窗口,调整视图以清晰显示 CAD 图纸内容和参考点。
* 通过菜单 `项目 (Project)` -> `导入/导出 (Import/Export)` -> `导出地图为图像 (Export Map to Image)...`
* 设置合适的范围(例如 `地图画布范围``计算自图层` -> 选择 CAD 图层),并确保设置一个**足够高的分辨率**(例如 300 DPI 或更高)以保证后续精确选取控制点。点击 `保存 (Save)`,选择文件名(如 `cad_export.tif`)和位置。
* **加载图像到地理配准器**: 回到地理配准器窗口,点击工具栏上的 `打开栅格 (Open Raster)` 按钮。在弹出的文件选择窗口中,找到并选择你刚刚导出的图像文件 (`cad_export.tif`)。
3. **添加地面控制点 (GCPs)**:
* 在地理配准器地图窗口中,找到你的第一个已知控制点(例如,某个建筑的角点)。
* 使用工具栏上的 `添加点 (Add Point)` 工具,在图上精确点击该点。
* 会弹出一个 `输入地图坐标 (Enter map coordinates)` 的对话框。**不要输入** X/Y 坐标(那是源坐标,让 QGIS 自动获取),而是点击 `来自地图画布 (From map canvas)`(如果你的控制点在另一地图层可见)或**手动输入该点的真实世界坐标**(经度 Longitude 对应 X纬度 Latitude 对应 Y。**确保输入的是 WGS84 经纬度坐标!** 点击 `确定 (OK)`
* 该控制点会出现在下方的 GCP 表中。
* 重复此过程,为所有已知的控制点添加映射关系(至少 3 个,推荐 4 个以上分布均匀。GCP 表中的 `dX`, `dY``残差 (Residual)` 列可以帮助判断点的精度,残差值越小越好。
4. **设置变换参数**:
* 点击工具栏上的 `变换设置 (Transformation settings)` 按钮(黄色齿轮图标)。
* **变换类型 (Transformation type)**: 根据控制点数量和分布选择。`线性 (Linear)` 适用于只有少数点或简单变换;`Helmert`能做平移、旋转等变换。 `多项式1/2/3 (Polynomial 1/2/3)` 能处理更复杂的形变,但可能会导致变形过大。`薄板样条 (Thin Plate Spline)` 适用于需要局部精确变形的情况。线性和 Helmert 都不改变地图本身形状。这里选择`Helmert`。
* **重采样方法 (Resampling method)**: 如果是基于栅格配准,选 `最近邻 (Nearest neighbour)`
* **目标坐标系 (Target CRS)**: **极其重要!** 点击 `选择 CRS (Select CRS)` 按钮,搜索并选择 `WGS 84` (其 EPSG 代码通常是 **4326**)。
* **输出栅格 (Output raster)**: 指定配准后文件的保存位置和名称。建议保存为 GeoPackage (`.gpkg`) 或 GeoTIFF (`.tif`) 格式。
* 勾选 `完成后在 QGIS 中加载 (Load in QGIS when done)`
* 点击 `确定 (OK)`
5. **执行地理配准**: 点击工具栏上的 `开始地理配准 (Start Georeferencing)` 按钮(绿色播放图标)。
6. 配准完成后,关闭地理配准器。新的、已地理配准的图层会添加到 QGIS 主窗口。你可以通过添加一个在线地图背景(如 OpenStreetMap来验证配准效果是否准确。
## 6.5 矢量图层仿射初步变换(推荐)
如果你的CAD道路中心线图层坐标范围与地理底图如配准后的栅格或OSM相差极大建议先用QGIS的"仿射变换"工具将其大致平移、缩放到目标区域:
1. 在图层面板中选中你的道路中心线图层(如`roads_centerline`)。
2. 菜单栏选择 `矢量``几何工具``仿射变换`Affine transform
3. 在弹出的对话框中填写参数(以青岛机场的 CAD 图纸为例):
- Translation (x-axis)`119.98`(经度方向平移,单位度)
- Translation (y-axis)`36.24`(纬度方向平移,单位度)
- Scale factor (x-axis)`0.00001`
- Scale factor (y-axis)`0.00001`
- Rotation around z-axis保持`0.0`EPSG:4326下此参数无效
- 其他参数保持默认
4. 输出选择"创建临时图层"或指定保存位置。
5. 点击"运行",生成大致对齐的新图层。
> **注意:** 仿射变换只做粗略对齐,后续还需精确配准。
## 6.6 用Vector Bender插件两对点法精确对齐
1. 安装并启用Vector Bender插件。
2. 创建一条线图层作为Pairs layer点对图层或直接使用 Vector Bender 的 Pairs layer 图层,并切换到编辑模式。
3. 在Pairs layer中用"添加线要素"工具,分别绘制两条线:
- 每条线的起点为仿射变换后道路图层上的特征点如交叉口、端点终点为底图如配准栅格或OSM上对应的真实地理位置。
- 推荐选择分布较远、方向不同的两对点。
4. 保存并退出编辑模式。
5. 打开Vector Bender插件
- Layer to bend 选择仿射变换后的道路图层
- Pairs layer 选择刚才绘制的点对图层
- 勾选"Change pairs to pins"
- 点击"Run"
6. 插件会自动完成平移、缩放、旋转,使两对点完全重合,实现道路图层与底图的精准对齐。
7. 检查结果,确认道路几何关系和位置均正确。
> **注意:** 只用两对点即可实现无畸变的仿射对齐,几何关系不会被破坏。
## 7. 数字化道路中心线(修正版)
> **重要:** 请务必先完成仿射变换和Vector Bender两对点精确对齐再进行属性补充、导出等后续操作。
1. 对齐后的道路中心线图层可直接用于属性补充。
2. 如需补充或修改道路,可在该图层上继续编辑。
3. 完成后,右键图层 → 导出 → 要素另存为...选择GeoJSON等格式确保CRS为WGS84。
## 7.1 修改字段属性
在QGIS中可以使用"重构字段"Refactor fields工具来修改字段名和数据类型。
### 7.1.1 修改字段名
1. 打开处理工具箱:
- 菜单 `处理``工具箱`
- 或使用快捷键 Ctrl+Alt+T
2. 搜索并打开"重构字段"工具:
- 在搜索框中输入"重构字段"
- 双击打开工具对话框
3. 设置参数:
- 在"输入图层"下拉列表中选择要修改的图层
- 在字段映射表中:
- 找到要修改的字段
- 双击"名称"列,输入新的字段名
- 在"输出文件"中设置保存位置
4. 点击"运行"执行修改
### 7.1.2 修改字段数据类型
1. 打开"重构字段"工具(步骤同上)
2. 设置参数:
- 在"输入图层"下拉列表中选择要修改的图层
- 在字段映射表中:
- 找到要修改的字段
- 双击"类型"列,选择新的数据类型
- 常见类型包括:
- 整数Integer
- 小数Decimal/Real
- 文本String
- 布尔值Boolean
- 在"输出文件"中设置保存位置
3. 点击"运行"执行修改
### 7.1.3 批量修改字段值
使用字段计算器可以批量修改某个字段的所有值:
1. 确保图层处于编辑模式:
- 右键点击图层
- 选择"切换编辑模式"Toggle Editing
2. 打开属性表:
- 右键点击图层
- 选择"打开属性表"Open Attribute Table
3. 使用字段计算器:
- 点击属性表工具栏上的"字段计算器"按钮(计算器图标)
- 在弹出的对话框中:
- 勾选"更新现有字段"Update existing field
- 在下拉列表中选择要修改的字段
- 在表达式框中输入新值(例如:`3.80`
- 点击"确定"
4. 保存修改:
- 检查属性表中的值是否已全部更新
- 点击工具栏上的"保存图层编辑"按钮
- 或右键图层 → "切换编辑模式" → 选择"保存"
> **注意:**
> - 如果只想修改特定记录,可以先使用选择工具选择要修改的记录
> - 修改前建议先备份数据
> - 确保新值的数据类型与字段类型兼容
## 8. 导出数字化道路为 GeoJSON
GeoJSON 是易于程序处理的格式。
1.`图层 (Layers)` 面板中,右键单击 `roads_centerline` 图层。
2. 选择 `导出 (Export)` -> `要素另存为... (Save Features As...)`
3. **格式**: 选择 `GeoJSON`
4. **文件名**: 指定导出的 GeoJSON 文件名和保存位置,例如 `airport_roads.geojson`
5. **坐标系 (CRS)**: 确保选择的是 `WGS 84 (EPSG:4326)`
6. **导出字段**: 确保所有需要的属性字段都被勾选导出。
7. **几何图形**: 可以设置坐标精度(小数位数),根据需要调整。
8. 点击 `确定 (OK)`
## 9. 从 GeoJSON 生成 YAML
现在你有了一个包含所有道路几何和属性的 GeoJSON 文件。你需要编写一个脚本(例如 Python来将其转换为 `airport_roads.yaml` 格式。
**脚本逻辑概要 (以 Python 为例):**
```python
import json
import yaml # 需要安装 PyYAML: pip install pyyaml
geojson_file = 'airport_roads.geojson'
yaml_file = 'src/main/resources/config/airport_roads.yaml' # 目标路径
output_data = {
'airport_code': 'XYZ', # 或者从其他地方获取
'roads': []
}
with open(geojson_file, 'r', encoding='utf-8') as f:
geojson_data = json.load(f)
for feature in geojson_data['features']:
props = feature['properties']
coords = feature['geometry']['coordinates']
road_entry = {
'id': props.get('road_id'),
'name': props.get('name'),
'geometry': {
'type': 'LineString',
'coordinates': coords # GeoJSON 的坐标列表可以直接用
},
'width': {
'value': props.get('width_value'),
'unit': props.get('width_unit', 'm')
},
'speed_limit': {
'value': props.get('speed_limit_value'),
'unit': props.get('speed_limit_unit', 'km/h')
},
'directionality': props.get('directionality'),
# ... 其他字段类似处理 ...
# 注意处理 None 或缺失值,以及数据类型转换
'prohibited': bool(props.get('prohibited', False)), # 示例:处理布尔值
# height_limit, width_limit 需要判断值是否存在再添加
# related_zones 可能需要特殊处理,例如如果 GeoJSON 里是逗号分隔字符串,这里要转成列表
}
# 添加可选字段
if props.get('height_limit_value') is not None:
road_entry['height_limit'] = {
'value': props.get('height_limit_value'),
'unit': props.get('height_limit_unit', 'm')
}
if props.get('width_limit_value') is not None:
road_entry['width_limit'] = {
'value': props.get('width_limit_value'),
'unit': props.get('width_limit_unit', 'm')
}
if props.get('related_zones'):
# 假设 related_zones 在 QGIS 中是以逗号分隔的字符串输入的
related_zones_list = [zone.strip() for zone in props.get('related_zones').split(',')]
road_entry['related_zones'] = related_zones_list
output_data['roads'].append(road_entry)
# 写入 YAML 文件
with open(yaml_file, 'w', encoding='utf-8') as f:
yaml.dump(output_data, f, allow_unicode=True, default_flow_style=False, sort_keys=False)
print(f"YAML 文件已生成: {yaml_file}")
```
你需要根据你在 QGIS 中定义的实际字段名和数据类型来调整脚本。
## 10. 总结
通过以上步骤,你可以将 CAD 图纸中的道路信息转换为包含精确地理坐标的 YAML 配置文件。关键在于获取准确的地面控制点 (GCPs) 以及在 QGIS 中细致地完成地理配准和数字化工作。这个过程可能比较耗时,但能确保配置数据的质量。