198 lines
12 KiB
Markdown
198 lines
12 KiB
Markdown
# 操作指南:从 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)` 旁边的 `...` 按钮,浏览并选择你的 `.dxf` 或 `.dwg` 文件。
|
||
5. 点击 `添加 (Add)`。QGIS 可能会询问要导入哪些图层(如果 CAD 文件包含多个图层),选择包含道路中心线和参考点的图层。
|
||
6. 关闭数据源管理器。你现在应该能在 QGIS 地图中看到 CAD 图纸的内容。此时,它的坐标系还是未知的或局部的。
|
||
|
||
## 6. 地理配准 (Georeferencing)
|
||
|
||
这是将 CAD 局部坐标转换为地理坐标的关键步骤。
|
||
|
||
1. **打开地理配准器**: 通过菜单 `图层 (Layer)` -> `地理配准器 (Georeferencer...)` 打开工具。
|
||
2. **加载 CAD 图层**: 在地理配准器窗口中,点击 `打开栅格 (Open Raster)` 按钮(虽然 CAD 是矢量,但通常在此工具中作为背景加载)。选择你刚刚导入到 QGIS 主窗口中的 CAD 图层。(如果无法直接加载矢量,可能需要先将 CAD 图层导出为图像格式如 TIFF,再加载该图像进行配准,但这会损失矢量特性,优先尝试直接加载)。
|
||
* *备选方案*:如果直接加载 CAD 困难,可以在 QGIS 主窗口将 CAD 图层导出为高分辨率图像(`项目` -> `导入/导出` -> `导出地图为图像`),然后在地理配准器中加载该图像。
|
||
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)` 适用于需要局部精确变形的情况。可以先尝试 `多项式 1` 或 `2`。
|
||
* **重采样方法 (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)来验证配准效果是否准确。
|
||
|
||
## 7. 数字化道路中心线
|
||
|
||
现在,以地理配准后的图层为底图,绘制道路中心线并添加属性。
|
||
|
||
1. **创建新图层**:
|
||
* 菜单 `图层 (Layer)` -> `创建图层 (Create Layer)` -> `新建 GeoPackage 图层 (New GeoPackage Layer...)` (推荐) 或 `新建 Shapefile 图层 (New Shapefile Layer...)`。
|
||
* **文件名**: 指定保存位置和文件名,例如 `airport_roads.gpkg`。
|
||
* **图层名称**: 例如 `roads_centerline`。
|
||
* **几何图形类型**: 选择 `线串 (LineString)` 或 `多段线 (MultiLineString)`。
|
||
* **坐标系**: **必须选择 WGS 84 (EPSG:4326)**。
|
||
* **定义属性字段**: 在 `新建字段 (New Field)` 部分,根据 `airport_roads.yaml` 的结构添加所需的字段。例如:
|
||
* `road_id` (类型: 文本 Text/String)
|
||
* `name` (类型: 文本 Text/String)
|
||
* `width_value` (类型: 十进制数 Decimal/Real)
|
||
* `width_unit` (类型: 文本 Text/String, 默认值可设为 'm')
|
||
* `speed_limit_value` (类型: 整数 Integer 或 十进制数 Decimal)
|
||
* `speed_limit_unit` (类型: 文本 Text/String, 默认值可设为 'km/h')
|
||
* `directionality` (类型: 文本 Text/String)
|
||
* `prohibited` (类型: 布尔 Boolean 或 整数 Integer 0/1)
|
||
* `height_limit_value` (类型: 十进制数 Decimal)
|
||
* `height_limit_unit` (类型: 文本 Text/String, 默认值 'm')
|
||
* `width_limit_value` (类型: 十进制数 Decimal)
|
||
* `width_limit_unit` (类型: 文本 Text/String, 默认值 'm')
|
||
* `related_zones` (类型: 文本 Text/String, 用于存储关联区域 ID 列表,可能需要后续处理)
|
||
* 点击 `添加到字段列表 (Add to Fields List)` 添加每个字段。
|
||
* 点击 `确定 (OK)` 创建图层。
|
||
2. **开始编辑**:
|
||
* 在 `图层 (Layers)` 面板中选中新建的 `roads_centerline` 图层。
|
||
* 点击工具栏上的 `切换编辑模式 (Toggle Editing)` 按钮(铅笔图标)。
|
||
* 点击 `添加线要素 (Add Line Feature)` 按钮(带绿色加号的线图标)。
|
||
3. **绘制道路**:
|
||
* 将鼠标移动到地理配准后的底图上,沿着一条道路的中心线开始点击。
|
||
* **左键单击** 添加顶点。对于**曲线**,需要**密集地添加顶点**来近似。
|
||
* 完成一条道路的绘制后,**右键单击** 结束绘制。
|
||
4. **填充属性**:
|
||
* 右键单击结束绘制后,会弹出一个属性表单窗口。
|
||
* 为刚刚绘制的道路填入对应的属性值(`road_id`, `name`, `width_value` 等)。
|
||
* 点击 `确定 (OK)`。
|
||
* 重复步骤 3 和 4,绘制并录入所有需要的道路。
|
||
5. **保存编辑**: 完成绘制后,再次点击 `切换编辑模式 (Toggle Editing)` 按钮,并在提示时选择 `保存 (Save)`。
|
||
|
||
## 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 中细致地完成地理配准和数字化工作。这个过程可能比较耗时,但能确保配置数据的质量。 |