赞
踩
本文记录如何从3DTile数据的tileset.json文件中,解析出包围盒的中心点坐标以及计算出包围盒的整个包围盒范围的几何平面。
在3DTile数据结构中,boundingVolume(边界范围)属性表当前节点瓦片的空间范围,3dtile的包围盒有三种类型(包围盒box、地理包围区域region或者包围球sphere表示),结构如下:
//外包盒"box": 由12个数字组成数组,前三个元素定义了中心点坐标(x,y,z),其次的三个元素(索引3,4,5)定义了x轴方向半长,然后的三个元素(索引6,7,8)定义了y轴方向和半长,最后的三个元素(索引9,10,11)定义了z轴方向和半长。 "boundingVolume": { "box": [ 430.902023580973, -99.8402685155161, 12.3579940963537, 5853.91565477883, 0, 0, 0, 5796.49705122272, 0, 0, 0, 8.63334992714226 ] } // 外包边界 "region": 由六个数字组成的数组进行定义。分别为[西,南,东,北,最小高度,最大高度],采用的地理参考系,经纬度是WGS84基准下的弧度制单位,高度的单位为米 "boundingVolume": { "region": [ -1.3197209591796106, 0.6988424218, -1.3196390408203893, 0.6989055782, 0, 88 ] } // 外包球"sphere": 外包球由四个数字组成的数组定义,前三个元素定义了球体中心的x,y,z坐标,最后一个定义了球体的半径。 "boundingVolume": { "sphere": [ 0, 0, 10, 141.4214 ] }
通过boundingVolume数据结构及其说明,我们就可以通过Cesium来解析出包围盒的中心点及其包围盒范围的几何平面(由于项目需求只需要获取平面范围,因此这里只记录二维平面范围生成方式:包围盒box、地理包围区域region对应生成矩形polygon、包围球sphere对应生成圆形circle)。
const viewer = new Cesium.Viewer("cesiumContainer", { shadows: true, }); // 加载3DTile function addTiles(){ var tileset = await Cesium.Cesium3DTileset.fromUrl( "http://192.168.1.xx:8080/3dtiles/test/tileset.json", { enableDebugWireframe: true, } ); viewer.scene.primitives.add(tileset); } // 解析数据并计算中心点和外包范围平面,json为请求tileset.json文件得到的数据对象 function calc3DTileBox(json) { let root = json.root; let geometry = null; let center = null; let boundingVolume = root.boundingVolume; if (boundingVolume.hasOwnProperty("box")) { // 中心点 center = new Cesium.Cartesian4( boundingVolume.box[0], boundingVolume.box[1], boundingVolume.box[2], 1 ); center = toDegrees(center,root.transform); // 左上 let leftTop = new Cesium.Cartesian4( boundingVolume.box[0]-boundingVolume.box[3], boundingVolume.box[1]+boundingVolume.box[7], boundingVolume.box[2], 1 ); // 左下 leftTop = toDegrees(leftTop,root.transform); let leftButtom = new Cesium.Cartesian4( boundingVolume.box[0]-boundingVolume.box[3], boundingVolume.box[1]-boundingVolume.box[7], boundingVolume.box[2], 1 ); // 右上 leftButtom = toDegrees(leftButtom,root.transform); let rightButtom = new Cesium.Cartesian4( boundingVolume.box[0]+boundingVolume.box[3], boundingVolume.box[1]-boundingVolume.box[7], boundingVolume.box[2], 1 ); // 右下 rightButtom = toDegrees(rightButtom,root.transform); let rightTop = new Cesium.Cartesian4( boundingVolume.box[0]+boundingVolume.box[3], boundingVolume.box[1]+boundingVolume.box[7], boundingVolume.box[2], 1 ); // 右上 rightTop = toDegrees(rightTop,root.transform); // 使用turf工具生成polygon geometry = turf.polygon([[leftTop, leftButtom, rightButtom, rightTop, leftTop]]); } else if (boundingVolume.hasOwnProperty("region")) { // 中心点 let centerGraphic = new Cesium.Cartographic( (boundingVolume.region[0] + boundingVolume.region[2]) / 2, (boundingVolume.region[1] + boundingVolume.region[3]) / 2, (boundingVolume.region[4] + boundingVolume.region[5]) / 2 ); let centerCartesian = Cesium.Cartographic.toCartesian(centerGraphic); center = new Cesium.Cartesian4(centerCartesian.x, centerCartesian.y, centerCartesian.z, 1); center = toDegrees(center,root.transform); // 左上 let leftTopGraphic = new Cesium.Cartographic( boundingVolume.region[0], boundingVolume.region[3], (boundingVolume.region[4] + boundingVolume.region[5]) / 2 ); let leftTopCartesian = Cesium.Cartographic.toCartesian(leftTopGraphic); let leftTop = new Cesium.Cartesian4(leftTopCartesian.x, leftTopCartesian.y, leftTopCartesian.z, 1); leftTop = toDegrees(leftTop,root.transform); // 左下 let leftButtomGraphic = new Cesium.Cartographic( boundingVolume.region[0], boundingVolume.region[1], (boundingVolume.region[4] + boundingVolume.region[5]) / 2 ); let leftButtomCartesian = Cesium.Cartographic.toCartesian(leftButtomGraphic); let leftButtom = new Cesium.Cartesian4(leftButtomCartesian.x, leftButtomCartesian.y, leftButtomCartesian.z, 1); leftButtom = toDegrees(leftButtom,root.transform); // 右下 let rightButtomGraphic = new Cesium.Cartographic( boundingVolume.region[2], boundingVolume.region[1], (boundingVolume.region[4] + boundingVolume.region[5]) / 2 ); let rightButtomCartesian = Cesium.Cartographic.toCartesian(rightButtomGraphic); let rightButtom = new Cesium.Cartesian4(rightButtomCartesian.x, rightButtomCartesian.y, rightButtomCartesian.z, 1); rightButtom = toDegrees(rightButtom,root.transform); // 右上 let rightTopGraphic = new Cesium.Cartographic( boundingVolume.region[2], boundingVolume.region[3], (boundingVolume.region[4] + boundingVolume.region[5]) / 2 ); let rightTopCartesian = Cesium.Cartographic.toCartesian(rightTopGraphic); let rightTop = new Cesium.Cartesian4(rightTopCartesian.x, rightTopCartesian.y, rightTopCartesian.z, 1); rightTop = toDegrees(rightTop,root.transform); // 使用turf工具生成polygon geometry = turf.polygon([[leftTop, leftButtom, rightButtom, rightTop, leftTop]]); } else if (boundingVolume.hasOwnProperty("sphere")) { center = new Cesium.Cartesian4( boundingVolume.sphere[0], boundingVolume.sphere[1], boundingVolume.sphere[2], 1 ); center = toDegrees(center,root.transform); var radius = boundingVolume.sphere[3]; var options = {units: 'meters'}; // 使用turf工具生成circle geometry = turf.circle(center, radius, options); } return { center:center, geometry:geometry }; } /** * 笛卡尔点转换经纬度,这里根据需要只取平面坐标 * @param {Object} point * @param {Object} transform */ function toDegrees(point,transform){ let result = null; // 是否有转换矩阵 if (transform) { let matrix4 = Cesium.Matrix4.fromColumnMajorArray(transform); let wgs84Cartesian4 = Cesium.Matrix4.multiplyByVector(matrix4, point, new Cesium.Cartesian4()); let wgs84Cartesian3 = Cesium.Cartesian3.fromCartesian4(wgs84Cartesian4); let wgs84Cartographic = Cesium.Cartographic.fromCartesian(wgs84Cartesian3); let lon = Cesium.Math.toDegrees(wgs84Cartographic.longitude); let lat = Cesium.Math.toDegrees(wgs84Cartographic.latitude); let height = wgs84Cartographic.height; result = [lon,lat] } else { let wgs84Cartographic = Cesium.Cartographic.fromCartesian(point); let lon = Cesium.Math.toDegrees(wgs84Cartographic.longitude); let lat = Cesium.Math.toDegrees(wgs84Cartographic.latitude); let height = wgs84Cartographic.height; result = [lon,lat] } return result; }
3DTile加载效果
通过计算得到的外包区域(box)polygon几何,蓝色透明部分
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。