import os
from qgis.core import (
QgsVectorLayer,
QgsFeature,
QgsWkbTypes,
QgsVectorFileWriter
)
LAYER_TYPE = {
"Point": (QgsWkbTypes.Point, QgsWkbTypes.PointGeometry),
"MultiPoint": (QgsWkbTypes.MultiPoint, QgsWkbTypes.PointGeometry),
"MultiPoint25D": (QgsWkbTypes.MultiPoint25D, QgsWkbTypes.PointGeometry),
"LineString": (QgsWkbTypes.LineString, QgsWkbTypes.LineGeometry),
"MultiLineString": (QgsWkbTypes.MultiLineString, QgsWkbTypes.LineGeometry),
"Polygon": (QgsWkbTypes.Polygon, QgsWkbTypes.PolygonGeometry),
"MultiPolygon": (QgsWkbTypes.MultiPolygon, QgsWkbTypes.PolygonGeometry),
}
# 解析 S57 图层信息的函数
def extract_s57_layer_info(s57layers: list[str]) -> list[tuple]:
extracted_info = []
# 内部的解析函数
def parse_layer_info(layer_info):
# 以 "!!::!!" 分割字符串
parts = layer_info.split('!!::!!')
# 提取序号、图层名称、几何类型
sublayer_id = parts[0] # 序号
sublayer_name = parts[1] # 图层名称
feature_count = parts[2] # 要素数量
geometry_type = parts[3] # 几何类型
return sublayer_id, sublayer_name, feature_count, geometry_type
# 遍历所有图层,解析并存储信息
for layer in s57layers:
extracted_info.append(parse_layer_info(layer))
return extracted_info
def main(s57_file, output_folder):
# 确保输出文件夹存在
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 加载 S57 文件为 OGR 数据源
layer = QgsVectorLayer(s57_file, "S57 Layer", "ogr")
if not layer.isValid():
print(f"S57 文件 '{s57_file}' 无法加载为图层")
return
# 加载 S57 文件的所有子图层
sublayers = layer.dataProvider().subLayers()
sublayers_info = extract_s57_layer_info(sublayers)
for sublayer_info in sublayers_info:
sublayer_id, sublayer_name, feature_count, geometry_type = sublayer_info
# 跳过没有几何类型的图层
if geometry_type == "None":
continue
# 构建子图层的 URI
sublayer_uri = f"{s57_file}|layername={sublayer_name}"
sublayer = QgsVectorLayer(sublayer_uri, sublayer_name, "ogr")
if sublayer.isValid():
# 创建一个新的图层用于存储要素
output_file = os.path.join(output_folder, f"{sublayer_name}_{geometry_type}.shp")
fields = sublayer.fields() # 保持子图层的字段
crs = sublayer.crs() # 保留子图层的 CRS(坐标参考系)
# 创建一个新的空矢量图层用于存储要素
layer_option = LAYER_TYPE.get(geometry_type)
if layer_option is None:
print(f"不支持的类型:{geometry_type}")
continue
layer_writer = QgsVectorFileWriter(
output_file, "UTF-8", fields, layer_option[0], crs, "ESRI Shapefile"
)
if layer_writer.hasError() != QgsVectorFileWriter.NoError:
print(f"创建Shapefile失败: {layer_writer.hasError()}")
return
# 遍历所有要素,筛选出点要素
for feature in sublayer.getFeatures():
geometry = feature.geometry()
if geometry.type() == layer_option[1]: # 判断是否为对应类型
new_feature = QgsFeature()
new_feature.setGeometry(geometry)
new_feature.setAttributes(feature.attributes()) # 保留原始属性
layer_writer.addFeature(new_feature)
# 完成写入
del layer_writer # 确保写入成功并关闭文件
print(f"要素成功导出为 '{output_file}'")
else:
print(f"子图层 '{sublayer_name}-{geometry_type}' 转换失败")
print("End...")
if __name__ == '__main__':
# S57 文件路径
s57_file = r"F:\Python学习\pyqgis\data\s57\C1515435.000"
# 输出文件夹路径
output_folder = r"F:\Python学习\pyqgis\data\test"
main(s57_file, output_folder)