当前位置:   article > 正文

使用Cesium 解析3DTile数据的包围盒中心点坐标并生成包围盒的平面矩形_3dtiles+cesium根据坐标点框选区域

3dtiles+cesium根据坐标点框选区域
目标

本文记录如何从3DTile数据的tileset.json文件中,解析出包围盒的中心点坐标以及计算出包围盒的整个包围盒范围的几何平面。

boundingVolume数据结构

在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
  ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

通过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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
效果

3DTile加载效果
在这里插入图片描述
通过计算得到的外包区域(box)polygon几何,蓝色透明部分
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/99717
推荐阅读
相关标签
  

闽ICP备14008679号