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

支持更多场景

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

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

点击出建筑楼栋信息

相关推荐
橙子家5 分钟前
浏览器缓存之【身份与会话管理】:Cookies 和 Private state tokens
前端
To_OC1 小时前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
最新资讯动态1 小时前
HDC 2026 | 对话鲸鸿动能:存量时代,品牌如何夺回营销“主动权”?
前端
最新资讯动态1 小时前
游戏出海,从产品走向体系
前端
最新资讯动态1 小时前
20人团队跑出百万DAU、大厂也来抢量:谁在鸿蒙生态跑出加速度
前端
最新资讯动态1 小时前
千万开发者背后,鸿蒙商业化的B面
前端
爱勇宝3 小时前
AI 时代:智商决定起点,情商决定走多远
前端·ai编程
kyriewen3 小时前
用了半年 Claude Code 后,我尝试关掉它写了一周代码——结果比想象中严重
前端·javascript·ai编程
IT_陈寒4 小时前
Vite的静态资源打包让我熬夜到三点,这坑千万别跳
前端·人工智能·后端
山河木马5 小时前
矩阵专题0-webGL中的矩阵
javascript·webgl·计算机图形学