Python:建筑物底面shp数据拉升白膜obj

用到的库:triangle库,用于构建约束三角网

整个拉起白膜过程为:

1、获取shp底面数点数据(这里需要注意geopandas读取面数据首尾点为一样的,所以构建三角网以及构建约束边的时候需要去除这个重复点)

2、底面数据Z值加上建筑物高度为顶面点数据

3、对底面点数据约束构网,底面边数据即为约束边,同理顶面数据构网结果与底面一致,故加上相应值即可

4、对侧面进行构网,侧面为多个矩形组成,矩形可以划分为两个三角形

5、输出文件

整个过程可以根据需求从属性表中添加其他数据,比如建筑物层数,建筑物高度,建筑物底面高度等,这些高度都可以作为建筑物高度或者建筑物底面的高度

import geopandas as gpd
import numpy as np
from shapely.geometry import Polygon
import triangle  # 用于三角化

# 读取shp文件
shapefile_path = r'E:\data\building.shp'
gdf = gpd.read_file(shapefile_path)

buildingHeight = 18

# 存储OBJ文件的内容
obj_content = []

# 生成OBJ文件头部
obj_content.append("# Generated OBJ file\n")

# 用于记录顶点索引的计数器
vertex_counter = 1


def polygon_to_triangles(polygon):
    # 将Shapely的多边形转换为triangle库能处理的格式
    coords = np.array(polygon.exterior.coords[:-1])

    # 定义三角化的边界约束
    edges = []
    for i in range(len(coords) - 1):
        edges.append([i, i + 1])
    # 闭合边界
    edges.append([len(coords) - 1, 0])

    # 将边界约束转化为 numpy 数组
    edges = np.array(edges)

    # 定义三角化的边界约束
    constraints = {'segments': edges}

    # 三角化
    triangulation = triangle.triangulate({'vertices': coords, 'segments': constraints['segments']}, '-p')
    return triangulation


for idx, row in gdf.iterrows():
    geom = row.geometry
    if isinstance(geom, Polygon):
        triangulation = polygon_to_triangles(geom)
        coords = np.array(geom.exterior.coords[:-1])
        height = row['MEAN']

        # 添加底面顶点
        for coord in coords:
            obj_content.append(f"v {coord[0]} {coord[1]} {height}\n")

        # 添加顶部顶点
        for coord in coords:
            obj_content.append(f"v {coord[0]} {coord[1]} {height + buildingHeight}\n")

        num_vertices = len(coords)
        num_triangles = len(triangulation['triangles'])

        # 添加底面三角形
        for triangle_indices in triangulation['triangles']:
            obj_content.append("f " + " ".join([str(i + vertex_counter) for i in triangle_indices]) + "\n")

        # 添加顶部三角形
        offset = num_vertices
        for triangle_indices in triangulation['triangles']:
            obj_content.append("f " + " ".join([str(i + vertex_counter + offset) for i in triangle_indices]) + "\n")

        # 添加侧面三角形
        for triangle_indices in triangulation['triangles']:
            base_triangle = [vertex_counter + i for i in triangle_indices]
            top_triangle = [vertex_counter + i + offset for i in triangle_indices]
            obj_content.append(f"f {base_triangle[0]} {base_triangle[1]} {top_triangle[1]}\n")
            obj_content.append(f"f {base_triangle[0]} {top_triangle[1]} {top_triangle[0]}\n")
            obj_content.append(f"f {base_triangle[1]} {base_triangle[2]} {top_triangle[2]}\n")
            obj_content.append(f"f {base_triangle[1]} {top_triangle[2]} {top_triangle[1]}\n")
            obj_content.append(f"f {base_triangle[2]} {base_triangle[0]} {top_triangle[0]}\n")
            obj_content.append(f"f {base_triangle[2]} {top_triangle[0]} {top_triangle[2]}\n")

        vertex_counter += num_vertices * 2

# 保存OBJ文件
with open('buildings.obj', 'w') as f:
    f.writelines(obj_content)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值