模型单体化效果是指,点击模型中的某个楼栋,弹出楼栋信息或楼栋扫光高亮。
常见自制模型单体化方法
这是一个常见的高频问题。常用的自制模型单体化有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页面,点击场景中某个建筑,显示高亮。

支持更多场景
基于地形的建筑白模自动化贴图 + 单体化

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

点击出建筑楼栋信息

完