大规模建筑自动贴图+单体化效果,cesium脚本

模型单体化效果是指,点击模型中的某个楼栋,弹出楼栋信息或楼栋扫光高亮。

常见自制模型单体化方法

这是一个常见的高频问题。常用的自制模型单体化有2种方法

1、在模型层面把分组设计好。你如1栋,2栋,3栋等。点击分组模型得到模型分组名,根据分组名请求api得到单体化信息。

2、从自制模型制作gis白模。点击模型后,根据点击点找白模轮廓。

导出的的贴图模型如何单体化?

用户说使用Geobuilding将建筑白模导出成贴图模型。模型有了,白模也有了。领导说要点击建筑物出信息,如何实现单体化交互效果呢?

现在的情形和上面第2种方法是有不同的。

一个是模型gltf->白模geojson. 这里的geojson一定能包含住模型 (上面说的第2种)

一个是白模->模型gltf,这里的模型不一定和白模重合。

为什么不会重合?因为模型内部是局部坐标体系,不是经纬度坐标。 那么如何实现点击模型中某个楼栋,实现单体化交互效果。不会再基于模型二次生产白模geojson吧?当然不用

峰回路转,cesium端的实践

cesium端点击模型后,有世界坐标。根据模型矩阵可转换为模型内部坐标。根据原始模型构建算法,得到点击的相对经纬度。然后拿着经纬度去找轮廓,最后弹出建筑信息或高亮。

该方法集成在了导出的demo html文件中,可作为js插件直接使用。 js插件包含模型全量加载、动态加载、模型扫光、点击单体化。支持cesium低版本和高版本使用。 点击事件代码如下:

javascript 复制代码
const handler = new Cesium.ScreenSpaceEventHandler(_this.viewer.scene.canvas);
            handler.setInputAction(async function(click) {
                const pickedObject = _this.viewer.scene.pick(click.position);
                if(Cesium.defined(pickedObject) && pickedObject['id']&&pickedObject['id']['geojson']){
                    //点击了单体化围墙
                    alert(JSON.stringify(pickedObject['id']['geojson']))
                }else if (Cesium.defined(pickedObject) && pickedObject.primitive.userData['pick2']) {
                    const worldPoint = _this.viewer.scene.pickPosition(click.position);
                    if (Cesium.defined(worldPoint)) {

                        //1、获取模型点击的经纬度和高度。
                        var modellnglat = _this.gltfInstance.GetClickLnglat(_this.viewer, worldPoint, pickedObject)
                        /*
                            2、查询点所在的轮廓。
                            !!!演示文件通过前端来查询点在轮廓内。!!!实际应用中需通过后端查询,避免GIS数据泄漏!
                            内置属性解释
                            https://i1.hdslb.com/bfs/article/55509bc62ca58bb6a8463819342258cd98081c25.png@1192w.avif
                            如果一个建筑体包含多个gis轮廓数据。在Geobuilding软件内对建筑体的gis数据【选择框】-打组。打组后这些gis数据有相同的属性值groupid
                            根据groupid可找到关联数据
                         */
                        let geojson = await (await fetch('geojson/' + pickedObject.primitive.userData.geojson)).text();
                        let result = geojson.split("\n").map(function(r) {return JSON.parse(r);});
                        var hitgeo;
                        for (let i = 0; i < result.length; i++) {
                            if (turf.booleanPointInPolygon(turf.point([modellnglat.lng, modellnglat.lat]), result[i], {ignoreBoundary: false})){
                                var demheight = result[i].properties.demheight;
                                var clickheight = modellnglat.height - demheight;
                                if(clickheight>= result[i].properties.pfh*result[i].properties.minfloor && clickheight<= result[i].properties.pfh*result[i].properties.minfloor + (result[i].properties.wfh*result[i].properties.floor)){
                                    hitgeo = result[i]
                                    break;
                                }
                            }
                        }
                        if(!hitgeo) {
                            console.log("没有找到轮廓")
                            return;
                        }

                        //原始geojson数据
                        //alert(JSON.stringify(hitgeo))

                        //3、对hitgeo并进行偏移转换(相对于模型)。
                        hitgeo = _this.gltfInstance.TransFeature(hitgeo, pickedObject);

                        //4、将geojson转换成cesium世界坐标,添加单体化高亮围墙。
                        var wallpos = turf.buffer(hitgeo, 1, {
                            units: "meters"
                        }).geometry.coordinates[0].map(function(z) {
                            return Cesium.Cartesian3.fromDegrees(z[0], z[1], hitgeo.properties.gltfbheight)
                        })

                        if (wall) wall.remove();
                        wall = new WallObject.FlowWall(_this.viewer,wallpos,{
                                copyright:'geobuilding',
                                wallHeight: hitgeo.properties.wfh*hitgeo.properties.floor,
                                wallColor: Cesium.Color.fromCssColorString('rgba(0, 255, 26, 0.3)'),
                                duration: 1000,
                                materialType: 3,
                            }
                        );
                        wall.flowWallEntity.geojson = hitgeo;
                    }else {
                        console.log('无法获取点击点的世界坐标');
                    }
                }else {
                    console.log('未点击到带有 pick2 的模型');
                }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

下面操作一遍看下效果。

首先选择导出模型

选择批量贴图方案,这里选择 实景风贴图

导出后有demo文件。模型信息.txt中本机浏览地址。

打开导出的demo页面,点击场景中某个建筑,显示高亮。

支持更多场景

基于地形的建筑白模自动化贴图 + 单体化

基于分层的单体化点击操作

点击出建筑楼栋信息

完

相关推荐
excel3 小时前
Marked 与 Markdown 有什么区别?该怎么选?
前端
ZhengEnCi3 小时前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
Da Da 泓3 小时前
五子棋 Web 端测试用例报告
前端·网络·websocket·网络协议·测试用例·项目
秋天的怀念_David4 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Pniubi4 小时前
力扣283移动零(双指针法)
算法·leetcode·职场和发展
hhb_6184 小时前
大模型落地三重优化实战
人工智能·算法·机器学习
云和数据.ChenGuang4 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
zxcvb1534 小时前
远程查看本地文档:一条轻量 Web 文件服务的工程化链路
前端·远程查看文档
niucloud-admin4 小时前
NIUCLOUD PHP SAAS上门家政使用文档:城市管理
java·前端·php
程序员大阳5 小时前
副队长JavaScript教程(50)-DOM:网页开发的起点
javascript·dom·es·节点·概念·document·关系