基于shp数据实现obj模型的切割

在GIS中,我们通过shp数据描述空间信息,这些数据通常以点线面的形式,即概括了地物的空间关系也包含地物的属性信息。通过shp数据和无人机影像建模的结合,可以将大范围三维场景的模型进行分割,使之成为一个个独立的单元并且赋予属性信息。

基于shp数据实现obj模型的切割

在三维仿真的场景中,无人机影像的建模是一种快速可靠的对大场景地形三维重现的方式,但是无人机影像的建模无法对单个场景的属性进行分析,如对单个楼层、居民区进行属性分析查询。在GIS中,我们通过shp数据描述空间信息,这些数据通常以点线面的形式,即概括了地物的空间关系也包含地物的属性信息。通过shp数据和无人机影像建模的结合,可以将大范围三维场景的模型进行分割,使之成为一个个独立的单元并且赋予属性信息,本文通过一个小实验来实现shp面对obj模型中某个单个建筑的分割。

3D模型在线预览提供多种低代码平台3D模型在线预览解决方案,实现了将多种3D模型格式无缝集成到低代码业务表单中。这意味着用户可以在不离开低代码平台的情况下,直接查看和操作3D模型,极大地提升了数据可视化的效果和用户交互体验。

数据准备

采用网上公开无人机影像数据,通过contextcapture对影像进行建模,生成倾斜摄影数据和obj模型,本文采用obj模型进行切割。

由于模型场景很大,本文采用截取一个单体建筑的方式来对场景进行裁剪,后期需要裁剪所有建筑,则需要迭代计算并优化效率(黑框全选为需要裁剪的建筑)。

shp数据为建筑面数据

算法思路

由于obj模型包含顶点和纹理,而shp数据基本处于二维平面,那么需要考虑顶点落在shp面数据xy平面内的数据,同时,一个面最少由三个顶点构成,如果一个面的部分在shp范围内,部分在范围外,则需要重新分割,生成新的顶点并构建网格。

obj数据的格式

通常简单的obj数据包含顶点信息,纹理信息,面信息,有的obj还包含一个mtl文件
其中常见的obj数据的组成形式为:

  • 首行:mtllib *.mtl 表示使用哪个mtl文件,以mtllib开头
  • 顶点坐标: v x y z 表示一个顶点的坐标,以v开头
  • 纹理坐标: vt u v 表示一个纹理的坐标,以vt开头
  • 引用的材质:usemtl * 表示引用mtl文件的哪部分纹理,以usemtl开头
  • 面索引:f v_i1/u_i1 v_i2/u_i2 v_i3/u_i3 ,以f开头,分别记录 顶点的序号和纹理的序号,序号从1开始,一个面由三个顶点组成,所以有三个顶点序号和纹理序号

mtl文件的格式

mtl记录了纹理的一些配置信息,主要有:

  • newmtl *: 创建一个材质,材质名为*,对应obj中的usemtl *
  • ka * * *: 环境颜色
  • kd * * *:漫反射颜色
  • d *: 透明度
  • Ns: *: 高光指数
  • illum: * : 光照模型
  • map_kd: *.jpg:纹理图片的名称

以上可以得出一个结论,一个mtl可以创建多个材质,那么在obj的面索引前面,可以多次引入材质信息,这个材质信息下面对应的面索引的顶点和纹理坐标,使用该材质。

解析obj数据

实验采用python语言,通过pywavefront库解析obj模型

  • materials: 记录了材质信息
  • vertices: 一个坐标数组,五个数据一组,前两位表示纹理坐标,后三位表示顶点坐标
  • mtllibs: 模型使用的mtl文件名,以数组形式存储
  • vertices: 顶点坐标数组
  • meshes: 格网列表,表示面数据索引集合

由于每个材质对应了一部分三角格网数据,格网数据对应了相应的顶点和纹理坐标数据,因此在解析数据的时候以材质进行分类,先记录每个材质的相关信息,在根据材质读取对应的顶点坐标和纹理坐标,进行裁剪和划分。

如上所示,首先根据材质读取材质信息,然后检查面的顶点是否在多边形内,如果面的所有顶点都在多边形内,那么只需要保留这个面的顶点和纹理坐标就行;如果面的部分顶点在多边形内,部分不在,则需要进行分割。
由于顶点和纹理信息存储在model_mesh.vertices中,只需要遍历该数据,即可获取对应的顶点坐标和纹理坐标。

进行分割和裁剪面的构建

​ 多边形的构建采用shapely库,由于是对一个shp要素进行裁剪,因此可以直接通过shapely构建一个多边形要素作为该建筑轮廓,实际分割中也可以采取读取shp要素,依次构建的方式。

判断顶点是否在多边形内

检查面的顶点是否都在多边形内,如果都在,则将对应顶点和纹理坐标追加到数组中

如果只有部分顶点在多边形内,则对面进行分割,并将分割的面和纹理追加进数组

面的分割逻辑需要检查每一条边,判断该边是否和多边形有交点,如果有交点,则分别将交点和在多边形内部点追加进数组

由于判断交点和内部点是在xy平面上进行的,因此在计算出交点的同时,需要通过线性插值的方式,计算出该点的Z值以及该点的纹理坐标

在得出分割的点和内部点之后,即可根据这些数据构建新的格网面,此时需要分为两种场景,当内部点只有一个的时候,说明有两个分割点,那么可以构建出一个新的多边形面;当内部点有两个的时候,那么分割点也有两个,那么可以构建出两个格网面

模型的写入

将新的顶点和纹理坐标及面索引重新写入obj同样需要遵守上述的准则,需要写入mtl文件和obj两个文件,同时mtl中所引用的图片得复制到对应的目录下

图片的复制是一个简单的io操作,判断要复制的图片是否存在,然后根据地址进行复制即可

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号