简介
本文将介绍如何使用Cesium计算模型的包围盒中心点,我们将详细解释实现的原理,并提供相应的代码示例。
实现思路
方法一
通过CesiumCesium3DTileset
加载模型后,直接通过boundingVolume
拿到模型的中心点即可
javascript
const tileset = await Cesium.Cesium3DTileset.fromUrl(url, {
skipLevelOfDetail: true,
baseScreenSpaceError: 1024,
skipScreenSpaceErrorFactor: 16,
skipLevels: 1,
immediatelyLoadDesiredLevelOfDetail: false,
loadSiblings: false,
cullWithChildrenBounds: true,
});
const root = tileset.root;
const boundingVolume = root.boundingVolume;
const modelCenter = boundingVolume.boundingSphere.center;
const halfAxes = boundingVolume.boundingVolume.halfAxes;
const wgs84Cartographic =
Cesium.Cartographic.fromCartesian(modelCenter);
const lon = Cesium.Math.toDegrees(wgs84Cartographic.longitude);
const lat = Cesium.Math.toDegrees(wgs84Cartographic.latitude);
const height = wgs84Cartographic.height;
dataObj.lon = lon;
dataObj.lat = lat;
dataObj.height = height;
viewer.entities.add({
position: modelCenter,
point: {
pixelSize: 20,
color: Cesium.Color.YELLOW,
},
});
方法二
这个是网上的方法,然后我把计算模型方向及旋转角度的方法也加到里面去了,懒得删了,就丢一起吧
{% link Cesium 解析3DTile的包围盒中心点坐标,WebGiser,https://www.jianshu.com/p/6cd91d922920 %}
javascript
// 解析包围盒中心点坐标,以及计算模型的方向旋转角度
fetch(url)
.then((res) => res.json())
.then((response) => {
console.log("response", response);
let root = response.root;
let boundingVolume = root.boundingVolume;
let modelCenter;
if (boundingVolume.hasOwnProperty("box")) {
let x = boundingVolume.box[0];
let y = boundingVolume.box[1];
let z = boundingVolume.box[2];
let w = 1;
modelCenter = new Cesium.Cartesian4(x, y, z, w);
} else if (boundingVolume.hasOwnProperty("region")) {
let x = (boundingVolume.region[0] + boundingVolume.region[2]) / 2;
let y = (boundingVolume.region[1] + boundingVolume.region[3]) / 2;
let z = (boundingVolume.region[4] + boundingVolume.region[5]) / 2;
let cartographic = new Cesium.Cartographic(x, y, z);
let wgs84Cartesian3 = Cesium.Cartographic.toCartesian(cartographic);
modelCenter = new Cesium.Cartesian4(
wgs84Cartesian3.x,
wgs84Cartesian3.y,
wgs84Cartesian3.z,
1
);
} else if (boundingVolume.hasOwnProperty("sphere")) {
let x = boundingVolume.sphere[0];
let y = boundingVolume.sphere[1];
let z = boundingVolume.sphere[2];
let w = 1;
modelCenter = new Cesium.Cartesian4(x, y, z, w);
}
// 是否有转换矩阵
if (root.hasOwnProperty("transform")) {
let transform = root.transform;
let matrix4 = Cesium.Matrix4.fromColumnMajorArray(transform);
let wgs84Cartesian4 = Cesium.Matrix4.multiplyByVector(
matrix4,
modelCenter,
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;
dataObj.lon = lon;
dataObj.lat = lat;
dataObj.height = height;
gui.add(dataObj, "lon", dataObj.lon);
gui.add(dataObj, "lat", dataObj.lat);
gui.add(dataObj, "height", dataObj.height);
//-----------------计算模型欧拉角----------------
const m1 = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Matrix4.getTranslation(
tileset.root.transform,
new Cesium.Cartesian3()
),
Cesium.Ellipsoid.WGS84,
new Cesium.Matrix4()
);
const m3 = Cesium.Matrix4.multiply(
Cesium.Matrix4.inverse(m1, new Cesium.Matrix4()),
tileset.root.transform,
new Cesium.Matrix4()
);
const mat3 = Cesium.Matrix4.getMatrix3(m3, new Cesium.Matrix3());
const q = Cesium.Quaternion.fromRotationMatrix(mat3);
const hpr = Cesium.HeadingPitchRoll.fromQuaternion(q);
// 获取模型的heading、pitch、roll
const heading = Cesium.Math.toDegrees(hpr.heading);
const pitch = Cesium.Math.toDegrees(hpr.pitch);
const roll = Cesium.Math.toDegrees(hpr.roll);
dataObj.heading = heading;
dataObj.pitch = pitch;
dataObj.roll = roll;
gui.add(dataObj, "heading", dataObj.heading);
gui.add(dataObj, "pitch", dataObj.pitch);
gui.add(dataObj, "roll", dataObj.roll);
console.log('dataObj',dataObj)
//-----------------计算模型欧拉角----------------
} else {
let wgs84Cartographic =
Cesium.Cartographic.fromCartesian(modelCenter);
let lon = Cesium.Math.toDegrees(wgs84Cartographic.longitude);
let lat = Cesium.Math.toDegrees(wgs84Cartographic.latitude);
let height = wgs84Cartographic.height;
dataObj.lon = lon;
dataObj.lat = lat;
dataObj.height = height;
gui.add(dataObj, "lon", dataObj.lon);
gui.add(dataObj, "lat", dataObj.lat);
gui.add(dataObj, "height", dataObj.height);
}
});
实现效果
效果如下图所示