Python自动化处理断面高程数据

本文摘要: 提出一个基于Python的自动化流程,用于沿断面线每1米间隔生成断面点并提取高程数据。首先读取断面线矢量数据(shp)和DEM栅格数据(tif),进行坐标转换和几何校验。核心算法包含:1)沿断面线按整数长度采样;2)坐标投影转换;3)DEM高程值提取。程序输出包含坐标、里程和高程的shp文件及结构化Excel表格。关键处理包括:线要素方向标准化、坐标边界检查、异常值处理等。该方案实现了从空间数据到断面特征的自动化提取,适用于水文分析、地形测量等领域,代码具备完整错误处理机制。

一、ai交流过程:现在给你一个断面线数据,“95-102E-断面线.shp”,如图1所示。

属性如图2所示。

再给你一个“105E-0.2m-dem.tif”,如图3所示。

现在想让你沿着断面线从左向右,每1m间隔生成一个断面点(注:左端点为起点,如果该断面线的长度不是整数,假设是n+a(其中n是断面长度整数部分,a是小数部分)那么最后一小段(即小数部分a)不要了。即终点为长度为n位置的点)。然后每条断面线都进行这样的操作。生成所有的断面点后,需要提取所有点位的x,y,里程值,高程值(值提取至点操作)。生成的excel文件格式如图4所示(所有生成的点需在一个excel文件里面):

能用python实现这个过程吗?

二、最终代码:

import geopandas as gpd
import rasterio
from shapely.geometry import Point, LineString
import numpy as np
import os
from pyproj import Transformer
import pandas as pd

# 1. 读取断面线数据
line_shp_path = r"D:\0617test\0620\96-102E-唐家村断面线\96-102E-断面线.shp"

# 验证文件路径是否存在
if not os.path.exists(line_shp_path):
    raise FileNotFoundError(f"错误: 未找到断面线文件 '{line_shp_path}'")

# 读取断面线数据并添加异常处理
try:
    line_gdf = gpd.read_file(line_shp_path)
    print(f"成功读取断面线数据: {len(line_gdf)} 条记录")
    print(f"数据坐标系: {line_gdf.crs}")

    # 检查是否有几何列
    if 'geometry' not in line_gdf.columns:
        raise ValueError("错误: 数据中不包含几何列 'geometry'")

    # 验证是否为线要素
    geom_types = line_gdf.geometry.geom_type.unique()
    if not all(geom in ['LineString', 'MultiLineString'] for geom in geom_types):
        print(f"警告: 数据中包含非线要素类型: {geom_types}")

except Exception as e:
    print(f"读取断面线数据失败: {e}")
    raise

# 2. 读取 DEM 数据
dem_path = r"D:\0617test\0620\唐家村.tif"

# 验证 DEM 文件路径
if not os.path.exists(dem_path):
    raise FileNotFoundError(f"错误: 未找到 DEM 文件 '{dem_path}'")

try:
    with rasterio.open(dem_path) as dem_ds:
        dem_transform = dem_ds.transform
        dem_arr = dem_ds.read(1)
        dem_crs = dem_ds.crs
        print(f"成功读取 DEM 数据,尺寸: {dem_arr.shape}")
        print(f"DEM 坐标系: {dem_crs}")

except Exception as e:
    print(f"读取 DEM 数据失败: {e}")
    raise

# 创建坐标转换器:从断面线坐标系(EPSG:4543)转换到DEM坐标系
transformer = Transformer.from_crs("EPSG:4543", dem_crs, always_xy=True)


# 3. 定义函数:沿断面线生成指定间隔的点并提取高程
def generate_section_points(line_geom, interval=1):
    """
    沿断面线生成指定间隔的点,提取坐标、里程和高程
    :param line_geom: 断面线的 shapely LineString 几何对象(已确保左→右方向)
    :param interval: 采样间隔,单位米(需保证线要素坐标是投影坐标,单位为米)
    :return: 包含点几何、里程、x、y、高程的列表
    """
    # 计算线长度
    line_length = line_geom.length
    # 确定最大整数里程(去掉小数部分,如长度 10.9 → 取 10)
    max_integer_length = int(line_length)
    # 生成采样里程列表(从 0 到 max_integer_length,步长 interval)
    mileages = np.arange(0, max_integer_length+1, interval)

    points_data = []
    for mile in mileages:
        # 在断面上按里程插值点(从左端点开始)
        point = line_geom.interpolate(mile)
        x, y = point.x, point.y

        # 将点坐标从断面线坐标系(EPSG:4543)转换到DEM坐标系
        x_proj, y_proj = transformer.transform(x, y)

        # 从 DEM 提取高程
        # 转换为行列号(使用投影后的坐标)
        row, col = rasterio.transform.rowcol(dem_transform, x_proj, y_proj)

        # 检查行列号是否在DEM范围内
        if 0 <= row < dem_arr.shape[0] and 0 <= col < dem_arr.shape[1]:
            elevation = dem_arr[row, col]
        else:
            elevation = None  # 点在 DEM 范围外时设为 None

        points_data.append({
            "geometry": Point(x_proj, y_proj),  # 使用投影后的坐标创建点
            "section_na": "",  # 用于存储 DMName 字段值
            "section_id": "",  # 用于存储 Id 字段值
            "POINT_X": x_proj,  # 存储投影后的X坐标
            "POINT_Y": y_proj,  # 存储投影后的Y坐标
            "distance": mile,
            "elevation": elevation
        })
    return points_data


# 4. 遍历所有断面线,统一方向(左→右)后生成断面点,并赋值对应字段
all_points = []
for idx, row in line_gdf.iterrows():
    line_geom = row["geometry"]

    # 获取断面线的 Id 和 DMName 字段值
    line_id = row.get("Id")
    line_dm_name = row.get("DMName")

    # 处理 LineString:反转方向,确保左→右
    if isinstance(line_geom, LineString):
        # 反转坐标顺序,让起点变为左端点
        # reversed_coords = list(reversed(line_geom.coords))
        reversed_coords = line_geom.coords
        reversed_line = LineString(reversed_coords)
        section_points = generate_section_points(reversed_line, interval=1)

    # 处理 MultiLineString:逐个 LineString 反转方向
    elif isinstance(line_geom, MultiLineString):
        section_points = []
        for line_part in line_geom.geoms:
            if isinstance(line_part, LineString):
                reversed_coords = list(reversed(line_part.coords))
                reversed_line = LineString(reversed_coords)
                section_points.extend(generate_section_points(reversed_line, interval=1))

    else:
        print(f"警告: 第 {idx} 行不是线要素,跳过")
        continue

    # 根据线数据属性为断面名称(section_na)、断面序号(section_id)赋值
    for p in section_points:
        p["section_na"] = line_dm_name
        p["section_id"] = line_id
    all_points.extend(section_points)

print(f"共生成 {len(all_points)} 个断面点")

# 5. 将所有点数据转换为 GeoDataFrame
if not all_points:
    raise ValueError("错误: 未生成任何断面点,请检查断面线数据")

# 使用DEM的坐标系
points_gdf = gpd.GeoDataFrame(all_points, crs=dem_crs)

# 6. 保存为 shp 文件
output_shp_path = "D:/0617test/0620/section_points.shp"
try:
    points_gdf.to_file(output_shp_path)
    print(f"成功保存断面点数据到: {output_shp_path}")
except Exception as e:
    print(f"保存断面点数据失败: {e}")
    raise
shp_path = output_shp_path
# 替换为实际生成的 shp 文件路径
# 替换为要保存的 excel 文件路径
excel_output_path = "D:/0617test/0620/唐家村.xlsx"

# 读取 shp 文件
gdf = gpd.read_file(shp_path)

# 构造目标 DataFrame 的字段列表
target_columns = [
    "断面名称", "断面序号", "POINT_X", "POINT_Y", "距离", "高程",
    "点类型标记", "断面类型", "left_roughness", "river_roughness",
    "right_roughness", "sigma_s", "slope"
]

# 准备要写入 Excel 的数据列表
data = []
for idx, row in gdf.iterrows():
    row_data = {
        "断面名称": row["section_na"],
        "断面序号": row["section_id"],
        "POINT_X": row["POINT_X"],
        "POINT_Y": row["POINT_Y"],
        "距离": row["distance"],
        "高程": row["elevation"],
        # 其他字段先填充为空字符串,可根据实际需求调整
        "点类型标记": "",
        "断面类型": "",
        "left_roughness": "",
        "river_roughness": "",
        "right_roughness": "",
        "sigma_s": "",
        "slope": ""
    }
    data.append(row_data)

# 创建 DataFrame
result_df = pd.DataFrame(data, columns=target_columns)

# 保存为 Excel 文件
result_df.to_excel(excel_output_path, index=False)
print(f"成功生成 Excel 文件:{excel_output_path}")

 

 

内容概要:本文详细探讨了基于阻尼连续可调减振器(CDC)的半主动悬架系统的控制策略。首先建立了CDC减振器的动力学模型,验证了其阻尼特性,并通过实验确认了模型的准确性。接着,搭建了1/4车辆悬架模型,分析了不同阻尼系数对悬架性能的影响。随后,引入了PID、自适应模糊PID和模糊-PID并联三种控制策略,通过仿真比较它们的性能提升效果。研究表明,模糊-PID并联控制能最优地提升悬架综合性能,在平顺性和稳定性间取得最佳平衡。此外,还深入分析了CDC减振器的特性,优化了控制策略,并进行了系统级验证。 适用人群:从事汽车工程、机械工程及相关领域的研究人员和技术人员,尤其是对车辆悬架系统和控制策略感兴趣的读者。 使用场景及目标:①适用于研究和开发基于CDC减振器的半主动悬架系统的工程师;②帮助理解不同控制策略(如PID、模糊PID、模糊-PID并联)在悬架系统中的应用及其性能差异;③为优化车辆行驶舒适性和稳定性提供理论依据和技术支持。 其他说明:本文不仅提供了详细的数学模型和仿真代码,还通过实验数据验证了模型的准确性。对于希望深入了解CDC减振器工作原理及其控制策略的读者来说,本文是一份极具价的参考资料。同时,文中还介绍了多种控制策略的具体实现方法及其优缺,为后续的研究和实际应用提供了有益的借鉴。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值