大规模建筑自动贴图+单体化效果,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页面,点击场景中某个建筑,显示高亮。

支持更多场景

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

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

点击出建筑楼栋信息

相关推荐
不会就选b1 小时前
算法日常・每日刷题--<贪心>14
算法
AlienZHOU2 小时前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
mmmmath_34 小时前
LeetCode.541.反转字符串II
数据结构·算法·leetcode
Navigator_Z4 小时前
LeetCode //MySQL - 1251. Average Selling Price
c语言·算法·leetcode
Captaincc5 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
醇氧5 小时前
MySQL 8.0 系统表损坏与引擎转换故障排查实战
数据结构·算法
大熊背6 小时前
《Color constancy by characterization of illumination chromaticity》之色度色域最大化算法(二)
算法·白平衡·色度·色温
钓鱼的肝6 小时前
梳理(1-5)
c++·经验分享·笔记·算法·青少年编程
HZZD_HZZD6 小时前
CSDN_批发市场水电漏损归因算法LAM的原理与落地
嵌入式硬件·物联网·算法