Ganos BIM数据管理与可视化功能解析
关于Ganos
关于Ganos三维引擎
基于Ganos三维引擎的BIM数据管理分析
业务需求
BIM数据往往以专业格式按文件存储,不利于结合其他二三维数据统一管理、联合查询,需要对其进行结构化拆解,提供业务/空间查询的能力; 基于BIM的三维报建系统逐步推广,要求可以精细化计算设计院生成的BIM模型的相关指标(投影面、体积、碰撞关系等),并与二三维的规划红线进行空间比对; 结构化拆解后的BIM模型依然具备快速可视化的能力,与主流渲染引擎对接高效渲染;
功能介绍
BIM数据导入
boolean ST_ImportIFC(cstring prefix, cstring url, cstring options default ‘{}’);boolean ST_ImportIFC(cstring prefix, bytea content, cstring options default ‘{}’);
返回值 | |
导入成功后会在数据库内生成三张表:
XXX_ifc_geom_elem(几何组件表):存储所有几何对象。
XXX_ifc_material_elem(IFC材质表):存储所有关联的材质对象。
XXX_ifc_elem(IFC部件表):存储所有实际的IFC部件对象及其相关属性。
其中部件表以树状结构进行存储,三张表通过一个project_uuid进行关联。用户可以自行扩展三张表以存储更多业务信息。
三维快显数据创建
boolean ST_As3dTiles(sfmesh sfmesh_object, cstring table_name, cstring options default ‘{}’);返回值
返回值 | 描述 |
true | 导出成功 |
false | 导出失败 |
参数
参数名称 | 描述 |
sfmesh_object | 需要处理的sfmesh对象 |
table_name | 业务表名称 |
options | json 字符串描述处理配置参数 |
XXX(主表):存储该项目的元数据信息。 XXX_tile(瓦片表):存储该项目所有的三维快显数据。 XXX_tileset(tileset.json表):存储该项目对应的tileset.json信息。
Ganos BIM数据管理的技术优势
原生支持BIM数据的存储、计算与可视化,不依赖于任何第三方的BIM/GIS软件,库内使用SQL语句即可操作; 将非结构化的BIM文件解构,保留了BIM数据的语义及各类属性,使其可以与其他空间数据一样进行管理与联合查询; 库内提供三维基础算子进行空间分析,可通过云原生数据库的各项能力进行计算加速,经项目实测三维空间计算能力相较于传统方案有百倍提升; 提供了三维快显能力,库内直接构建BIM的快显瓦片,通过简单的后端服务即可与渲染引擎进行对接,做到视算一体;
功能使用案例
create extension ganos_importer cascade;数据入库
select ST_importIFC('ifc_demo'::cstring, 'OSS://<ak>:<ak_secret>@oss-cn-beijing.aliyuncs-internal.com/ifc/data/Architecture.ifc'::cstring);注意: 公有云实例必须填写internal的endpoint地址
查看BIM的部件信息
SELECT project_uuid, project_name, parent_uuid, uuid, "family", "name", attrs, props_set, ST_AsText("element")FROM ifc_demo_ifc_elem;
查看构件的几何信息
SELECT project_uuid, project_name, geometry_id, ST_AsText(geom_element)FROM ifc_demo_ifc_geom_elem;
查看材质信息
SELECT project_uuid, project_name, material_name, ST_AsText(material_element)FROM ifc_demo_ifc_material_elem;
可以通过 PolarAdmin 以可视化的方式对BIM中的部件进行浏览:
SELECT project_uuid, project_name, parent_uuid, uuid, "family", "name", attrs, props_setFROM ifc_demo_ifc_elemWHERE(((props_set->'Other')::json)->'Type')::text like '%System Panel: %';
空间分析
同样,可以基于空间范围对部件进行查询。 以下示例表示查询所有在三楼的部件,查询的条件是空间范围包含在第三层楼的范围内:
select a.namefrom ifc_demo_ifc_elem a, ifc_demo_ifc_elem bwhere ST_3DIntersects(b."element", a."element") = trueand b."family" = 'IfcBuildingStorey' and b.name = 'Level 3';
可视化展示
创建三维快显格式
select ST_As3DTiles(element, 'ifc_demo_tiles') from ifc_demo_ifc_elem where family='IfcProject';注 :一些IFC不带有空间位置信息,需要手工更新空间范围的锚点,才能在前端正确的位置上进行显示。
Update ifc_demo_tilesSET anchor=ST_SetSrid(ST_MakePoint(120, 30, 0), 4326)WHERE project_id = 'xxxxxxx'
发布服务进行浏览
{"dependencies": {"koa": "^2.14.2","koa-router": "^12.0.0","koa-send": "^5.0.1","pg": "^8.10.0"}}
在本目录下执行npm install安装依赖库。
在同一目录下创建Node.js脚本文件index.js:
const Koa = require('koa');const Send = require('koa-send');const Router = require('koa-router');const router = new Router()const { Pool } = require('pg');const pool = new Pool({ user: <YOUR_USER>, host: <YOUR_HOST>, database: <YOUR_DB_NAME>, port: <YOUR_PORT> });const TABLE_NAME = 'ifc_demo_tiles'const PROJECT_NAME = ''router.get('/', (_) => Send(_, '/index.html'))/* get metadata of current project */router.get('/project', async (ctx) => {const sql = `SELECT (REGEXP_MATCHES(ST_ASTEXT(ST_TRANSFORM(ANCHOR,4326)), 'POINT Z \\((.*?)\\)'))[1] _ANCHOR, PROJECT_ID FROM ${TABLE_NAME} WHERE PROJECT_NAME='${PROJECT_NAME}';`const { rows: [{ _anchor, project_id }] } = await pool.query(sql)const anchor = _anchor.split(' ').map(x => parseFloat(x))const url = `/tileset/${project_id}/${project_id}`ctx.body = { url, anchor }})router.get('/tileset/:project_id/:uid', async (ctx) => {const { params: { project_id, uid } } = ctxconst sql = `SELECT TILESET FROM ${TABLE_NAME}_TILESET WHERE PROJECT_ID=$1::UUID AND UID=$2::UUID;`const { rows: [{ tileset }] } = await pool.query(sql, [project_id, uid])ctx.body = tileset})router.get('/b3dm/:project_id/:uid', async (ctx) => {const { params: { project_id, uid } } = ctxconst sql = `SELECT ST_ASB3DM(TILE) TILE FROM ${TABLE_NAME}_TILE WHERE PROJECT_ID=$1::UUID AND UID=$2::UUID;`const { rows: [{ tile }] } = await pool.query(sql, [project_id, uid])ctx.body = tile})new Koa().use(router.routes()).listen(5500, '0.0.0.0');
在同一目录下创建HTML文件index.html:
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><script src="https://cesium.com/downloads/cesiumjs/releases/1.89/Build/Cesium/Cesium.js"></script><link href="https://cesium.com/downloads/cesiumjs/releases/1.89/Build/Cesium/Widgets/widgets.css" rel="stylesheet"><style>html,body,#cesium_container {width: 100%;height: 100%;margin: 0;padding: 0;overflow: hidden;}</style></head><body><div id="cesium_container"></div><script>Cesium.Ion.defaultAccessToken = <SET_YOUR_OWN_TOKEN_HERE>const disable_opt = ['timeline', 'animation', 'infoBox', 'navigationHelpButton'].reduce((opts, opt) => (opts[opt] = false) || opts, {})const viewer = new Cesium.Viewer('cesium_container', disable_opt)fetch('/project').then(res => res.json()).then(({ anchor, url }) => {const position = Cesium.Cartesian3.fromDegrees(...anchor)const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)const tileset = new Cesium.Cesium3DTileset({ url, modelMatrix })tileset.readyPromise.then(() => viewer.zoomTo(tileset))viewer.scene.primitives.add(tileset)})</script></div></body></html>
在同一目录下执行如下命令启动服务:
node index.js最终前端基于cesium的可视化效果如下所示: