14 KiB
操作指南:从 CAD 图纸生成 airport_roads.yaml 配置文件
1. 目标与挑战
本指南旨在说明如何使用免费开源的 GIS 软件 QGIS,从机场的 CAD 工程图纸(通常使用局部坐标系)生成包含精确地理坐标(经纬度,WGS84)的 airport_roads.yaml 配置文件,以供应用程序使用。
主要挑战在于将 CAD 的局部坐标系转换为标准的 WGS84 地理坐标系,这需要准确的地理参考信息。
2. 准备工作
在开始之前,请确保你拥有:
- QGIS 软件: 从 QGIS 官网 下载并安装最新稳定版。
- 机场 CAD 图纸:
.dwg或.dxf格式的文件。最好是包含清晰道路中心线的版本。 - 地面控制点 (GCPs - Ground Control Points): 这是最关键的部分! 你需要获取 CAD 图上至少 3-4 个(越多越好,分布越均匀越好)易于识别的点(如建筑角点、跑道端点、特定标记)的精确真实世界地理坐标。坐标可以是:
- 经纬度 (WGS84): 例如
[经度 113.12345, 纬度 22.54321] - 投影坐标: 例如 UTM 坐标,并清楚知道其对应的区域和基准面。
- 获取方式:可能来自现场 GPS 测量、官方测绘数据、高精度卫星地图的比对等。控制点的精度直接决定了最终结果的精度。
- 经纬度 (WGS84): 例如
3. QGIS 安装
访问 QGIS 官网,根据你的操作系统下载并安装 QGIS Desktop。
4. CAD 文件准备(可选但推荐)
为了简化后续操作,建议在 CAD 软件中:
- 清理图纸,只保留必要的图层,尤其是道路中心线图层和用于地理配准的参考点所在图层。
- 确保道路中心线是连接良好的线段 (Polyline)。
- 如果可能,将文件另存为较旧版本的
.dxf格式,有时兼容性更好。
5. 导入 CAD 文件到 QGIS
- 打开 QGIS。
- 通过菜单
图层 (Layer)->添加图层 (Add Layer)->添加矢量图层 (Add Vector Layer...)打开数据源管理器。 - 在
矢量 (Vector)选项卡中,选择文件 (File)类型。 - 点击
源 (Source)旁边的...按钮,浏览并选择你的.dwg或.dxf文件。 - 点击
添加 (Add)。QGIS 可能会询问要导入哪些图层(如果 CAD 文件包含多个图层),选择包含道路中心线和参考点的图层。 - 关闭数据源管理器。你现在应该能在 QGIS 地图中看到 CAD 图纸的内容。此时,它的坐标系还是未知的或局部的。
6. 地理配准 (Georeferencing)
这是将 CAD 局部坐标转换为地理坐标的关键步骤。
- 打开地理配准器: 通过菜单
图层 (Layer)->地理配准器 (Georeferencer...)打开工具。 - 准备并加载要配准的图像:
- 由于地理配准器主要处理栅格图像,你需要先将导入的 CAD 图层视图导出为图像文件。
- 在 QGIS 主窗口,调整视图以清晰显示 CAD 图纸内容和参考点。
- 通过菜单
项目 (Project)->导入/导出 (Import/Export)->导出地图为图像 (Export Map to Image)...。 - 设置合适的范围(例如
地图画布范围或计算自图层-> 选择 CAD 图层),并确保设置一个足够高的分辨率(例如 300 DPI 或更高)以保证后续精确选取控制点。点击保存 (Save),选择文件名(如cad_export.tif)和位置。 - 加载图像到地理配准器: 回到地理配准器窗口,点击工具栏上的
打开栅格 (Open Raster)按钮。在弹出的文件选择窗口中,找到并选择你刚刚导出的图像文件 (cad_export.tif)。
- 添加地面控制点 (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)列可以帮助判断点的精度,残差值越小越好。
- 设置变换参数:
- 点击工具栏上的
变换设置 (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)。
- 点击工具栏上的
- 执行地理配准: 点击工具栏上的
开始地理配准 (Start Georeferencing)按钮(绿色播放图标)。 - 配准完成后,关闭地理配准器。新的、已地理配准的图层会添加到 QGIS 主窗口。你可以通过添加一个在线地图背景(如 OpenStreetMap)来验证配准效果是否准确。
6.5 矢量图层仿射初步变换(推荐)
如果你的CAD道路中心线图层坐标范围与地理底图(如配准后的栅格或OSM)相差极大,建议先用QGIS的"仿射变换"工具将其大致平移、缩放到目标区域:
- 在图层面板中选中你的道路中心线图层(如
roads_centerline)。 - 菜单栏选择
矢量→几何工具→仿射变换(Affine transform)。 - 在弹出的对话框中填写参数(以青岛机场的 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下此参数无效) - 其他参数保持默认
- Translation (x-axis):
- 输出选择"创建临时图层"或指定保存位置。
- 点击"运行",生成大致对齐的新图层。
注意: 仿射变换只做粗略对齐,后续还需精确配准。
6.6 用Vector Bender插件两对点法精确对齐
- 安装并启用Vector Bender插件。
- 创建一条线图层作为Pairs layer(点对图层)或直接使用 Vector Bender 的 Pairs layer 图层,并切换到编辑模式。
- 在Pairs layer中用"添加线要素"工具,分别绘制两条线:
- 每条线的起点为仿射变换后道路图层上的特征点(如交叉口、端点),终点为底图(如配准栅格或OSM)上对应的真实地理位置。
- 推荐选择分布较远、方向不同的两对点。
- 保存并退出编辑模式。
- 打开Vector Bender插件:
- Layer to bend 选择仿射变换后的道路图层
- Pairs layer 选择刚才绘制的点对图层
- 勾选"Change pairs to pins"
- 点击"Run"
- 插件会自动完成平移、缩放、旋转,使两对点完全重合,实现道路图层与底图的精准对齐。
- 检查结果,确认道路几何关系和位置均正确。
注意: 只用两对点即可实现无畸变的仿射对齐,几何关系不会被破坏。
7. 数字化道路中心线(修正版)
重要: 请务必先完成仿射变换和Vector Bender两对点精确对齐,再进行属性补充、导出等后续操作。
- 对齐后的道路中心线图层可直接用于属性补充。
- 如需补充或修改道路,可在该图层上继续编辑。
- 完成后,右键图层 → 导出 → 要素另存为...,选择GeoJSON等格式,确保CRS为WGS84。
7.1 修改字段属性
在QGIS中,可以使用"重构字段"(Refactor fields)工具来修改字段名和数据类型。
7.1.1 修改字段名
-
打开处理工具箱:
- 菜单
处理→工具箱 - 或使用快捷键 Ctrl+Alt+T
- 菜单
-
搜索并打开"重构字段"工具:
- 在搜索框中输入"重构字段"
- 双击打开工具对话框
-
设置参数:
- 在"输入图层"下拉列表中选择要修改的图层
- 在字段映射表中:
- 找到要修改的字段
- 双击"名称"列,输入新的字段名
- 在"输出文件"中设置保存位置
-
点击"运行"执行修改
7.1.2 修改字段数据类型
-
打开"重构字段"工具(步骤同上)
-
设置参数:
- 在"输入图层"下拉列表中选择要修改的图层
- 在字段映射表中:
- 找到要修改的字段
- 双击"类型"列,选择新的数据类型
- 常见类型包括:
- 整数(Integer)
- 小数(Decimal/Real)
- 文本(String)
- 布尔值(Boolean)
- 在"输出文件"中设置保存位置
-
点击"运行"执行修改
7.1.3 批量修改字段值
使用字段计算器可以批量修改某个字段的所有值:
-
确保图层处于编辑模式:
- 右键点击图层
- 选择"切换编辑模式"(Toggle Editing)
-
打开属性表:
- 右键点击图层
- 选择"打开属性表"(Open Attribute Table)
-
使用字段计算器:
- 点击属性表工具栏上的"字段计算器"按钮(计算器图标)
- 在弹出的对话框中:
- 勾选"更新现有字段"(Update existing field)
- 在下拉列表中选择要修改的字段
- 在表达式框中输入新值(例如:
3.80) - 点击"确定"
-
保存修改:
- 检查属性表中的值是否已全部更新
- 点击工具栏上的"保存图层编辑"按钮
- 或右键图层 → "切换编辑模式" → 选择"保存"
注意:
- 如果只想修改特定记录,可以先使用选择工具选择要修改的记录
- 修改前建议先备份数据
- 确保新值的数据类型与字段类型兼容
8. 导出数字化道路为 GeoJSON
GeoJSON 是易于程序处理的格式。
- 在
图层 (Layers)面板中,右键单击roads_centerline图层。 - 选择
导出 (Export)->要素另存为... (Save Features As...)。 - 格式: 选择
GeoJSON。 - 文件名: 指定导出的 GeoJSON 文件名和保存位置,例如
airport_roads.geojson。 - 坐标系 (CRS): 确保选择的是
WGS 84 (EPSG:4326)。 - 导出字段: 确保所有需要的属性字段都被勾选导出。
- 几何图形: 可以设置坐标精度(小数位数),根据需要调整。
- 点击
确定 (OK)。
9. 从 GeoJSON 生成 YAML
现在你有了一个包含所有道路几何和属性的 GeoJSON 文件。你需要编写一个脚本(例如 Python)来将其转换为 airport_roads.yaml 格式。
脚本逻辑概要 (以 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 中细致地完成地理配准和数字化工作。这个过程可能比较耗时,但能确保配置数据的质量。