使用qgis.core模块快速转换s57数据

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)

posted @ 2024-10-23 17:18  槑孒  阅读(19)  评论(0编辑  收藏  举报