本人小白一枚,文章如有问题还请各位大神评论区指出。整体实现是参考SuperMap iClient3D for Cesium的Box裁剪功能源码~
一、主要功能
二、具体实现
1.HTML主要结构
代码如下:
<select v-model="clipMode">
<option value="clip_behind_all_plane">裁剪包围盒内</option>
<option value="clip_behind_any_plane">裁剪包围盒外</option>
</select>
<el-button type="primary" @click="clearbox()">清 除</el-button>
2.javascript
代码如下:
<script setup>
import { ref, watch, onBeforeUnmount } from "vue";
import { ElMessage } from "element-plus";
import { useStore } from "vuex";
const store = useStore();
//组件销毁前为避免和其他功能组件冲突需要根据当前功能的不同激活状态进行清除和卸载
onBeforeUnmount(() => {
if (layers != null) {
for (var i = 0, j = layers.length; i < j; i++) {
layers[i].clearCustomClipBox();
}
if (editorBox) {
editorBox.deactivate();
}
if (handlerBox.activate == true) {
handlerBox.clear();
handlerBox.deactivate();
}
viewer.entities.removeAll();
}
});
var scene = viewer.scene;
let clipMode = ref("clip_behind_all_plane");
let layers = store.state.others.layers3D;
if (layers == null) {
layerLoad();
} else {
// 精准定位
scene.camera.setView({
destination: {
x: -1686231.1976311686,
y: 4995014.670662241,
z: 3590709.954257436,
},
orientation: {
heading: 3.155708783485583,
pitch: -0.15948987026566308,
roll: 6.283185307179586,
},
});
// 设置裁剪线颜色
setAllLayersClipColor();
var boxEntity = undefined;
//交互绘制box
var handlerBox = new Cesium.DrawHandler(viewer, Cesium.DrawMode.Box);
var editorBox;
handlerBox.drawEvt.addEventListener(function (e) {
boxEntity = e.object;
var newDim = boxEntity.box.dimensions.getValue();
var position = boxEntity.position.getValue(0);
var boxOption = {
dimensions: newDim,
position: position,
clipMode: clipMode.value,
heading: 0,
};
//Box编辑器类,用于对box进行编辑
editorBox = new Cesium.BoxEditor(viewer, boxEntity);
editorBox.editEvt.addEventListener(function (e) {
boxEntity.box.dimensions = e.dimensions;
boxEntity.position = e.position;
boxEntity.orientation = e.orientation;
setClipBox();
});
//控制操作Box的entity可见性(0-950米之间可见)
editorBox.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(
0,
950
);
editorBox.activate();
setAllLayersClipOptions(boxOption);
handlerBox.clear();
handlerBox.deactivate();
});
handlerBox.activate();
//监听裁剪模式变化
watch(clipMode, (newval, oldval) => {
setClipBox();
});
}
function setClipBox() {
if (typeof boxEntity == "undefined") {
return;
}
var newDim = boxEntity.box.dimensions.getValue();
var position = boxEntity.position.getValue(0);
var heading = 0;
if (typeof boxEntity.orientation != "undefined") {
let rotationM3 = Cesium.Matrix3.fromQuaternion(
boxEntity.orientation._value,
new Cesium.Matrix3()
);
let localFrame = Cesium.Matrix4.fromRotationTranslation(
rotationM3,
Cesium.Cartesian3.ZERO,
new Cesium.Matrix4()
);
let inverse = Cesium.Matrix4.inverse(
Cesium.Transforms.eastNorthUpToFixedFrame(position),
new Cesium.Matrix4()
);
let hprm = Cesium.Matrix4.multiply(
inverse,
localFrame,
new Cesium.Matrix4()
);
var rotation = Cesium.Matrix4.getMatrix3(hprm, new Cesium.Matrix3());
let hpr = Cesium.HeadingPitchRoll.fromQuaternion(
Cesium.Quaternion.fromRotationMatrix(rotation)
);
heading = hpr.heading;
}
var boxOptions = {
dimensions: newDim,
position: position,
clipMode: clipMode.value,
heading: heading,
};
setAllLayersClipOptions(boxOptions);
}
function setAllLayersClipColor() {
for (var i = 0, j = layers.length; i < j; i++) {
layers[i].clipLineColor = new Cesium.Color(1, 1, 1, 0);
}
}
function setAllLayersClipOptions(boxOptions) {
for (var i = 0, j = layers.length; i < j; i++) {
layers[i].setCustomClipBox(boxOptions);
}
}
//判断模型图层是否加载
function layerLoad() {
ElMessage({
message: "请先添加三维倾斜摄影模型图层!",
type: "warning",
duration: 6000,
showClose: true,
offset: 80,
grouping: true,
});
}
//清除
function clearbox() {
if (layers == null) {
layerLoad();
} else {
for (var i = 0, j = layers.length; i < j; i++) {
layers[i].clearCustomClipBox();
}
editorBox.deactivate();
viewer.entities.removeAll();
handlerBox.clear();
handlerBox.deactivate();
handlerBox.activate();
}
}
</script>