cesium-地面裁剪(多个剪切面)
介绍
我之前的文章介绍过地面裁剪的实现,这里介绍一下裁剪多个面的方式。
Cesium自带的ClippingPlaneCollection
只能实现单凸多边形挖除,为了实现多个面的裁切和简单凹多边形,这里我们需要修源码以提供支持。
在github中的问题讨论中已经有人实现了,实现方式需要重新打包源码
实现效果
源码打包
- 这里我使用的cesium源码版本为:1.79.1下载地址
- 打包工具使用的是webstorm
- node.js版本为14.17.5
替换文件
所有替换文件位置都在Source下,可以检索一下替换
使用打包命令打包
npm run build
部署打包代码
可以部署到nginx、apache等服务器上
完整代码
这里使用vue实现
<template>
<div class="home">
<el-row type="flex" :gutter="20">
<el-col :span="24">
<div class="grid-content bg-purple">
<el-breadcrumb separator="/">
<el-breadcrumb-item>cesium</el-breadcrumb-item>
<el-breadcrumb-item>裁剪功能</el-breadcrumb-item>
<el-breadcrumb-item>地形多裁剪</el-breadcrumb-item>
</el-breadcrumb>
</div>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="24">
<div class="grid-content bg-purple" >
<cesiumComponent id="cesium" ref="refCesium"/>
</div>
</el-col>
</el-row>
<el-row type="flex" :gutter="20">
<el-col :span="24">
<div class="grid-content bg-purple">
<el-button type="primary" @click="addDem()">复位</el-button>
<el-button type="primary" @click="clippings()">裁剪</el-button>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import cesiumComponent from '../cesium.vue'
export default {
name: "clipping_many",
data() {
return {
_viewer: undefined,
polygonOne: [
[
87.27401733398438,
29.61763959537609
],
[
87.24723815917969,
29.586594438725495
],
[
87.25410461425781,
29.542398322601738
],
[
87.29187011718749,
29.52208551698379
],
[
87.34336853027344,
29.52507295013191
],
[
87.35916137695312,
29.580623120820174
],
[
87.33100891113281,
29.6194303704904
],
[
87.27401733398438,
29.61763959537609
]
],
polygonTwo: [
[
87.50747680664062,
29.558526173207785
],
[
87.43572235107422,
29.52507295013191
],
[
87.45014190673828,
29.452154410825624
],
[
87.53837585449219,
29.449762750751052
],
[
87.5497055053711,
29.50266505164239
],
[
87.50747680664062,
29.558526173207785
]
],
isClipping: false
};
},
components: {
cesiumComponent
},
mounted() {
this.init();
},
methods: {
init() {
this.$refs.refCesium.initMap();
this._viewer = this.$refs.refCesium._viewer;
this.addDem();
},
addDem() {
let that = this;
that._viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
url: '**/dem/ASTGTM_N29E087D'
});
that._viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(87.42919921875, 28.700224692776988, 67863.0),
orientation: {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-45.0),
roll: 0.0
}
});
},
clippings() {
let that = this;
let clippingPlanes1 = this.createClippingPlane(this.polygonOne);
let clippingPlanes2 = this.createClippingPlane(this.polygonTwo);
let clippingPlaneCollection1 = new Cesium.ClippingPlaneCollection({
planes: clippingPlanes1,
});
let clippingPlaneCollection2 = new Cesium.ClippingPlaneCollection({
planes: clippingPlanes2,
});
if(!that.isClipping){
that._viewer.scene.globe.depthTestAgainstTerrain = true;
that._viewer.scene.globe.multiClippingPlanes = new Cesium.MultiClippingPlaneCollection({
collections: [clippingPlaneCollection1, clippingPlaneCollection2],
edgeWidth: 1,
edgeColor: Cesium.Color.WHITE,
});
that.isClipping=true;
}else {
that._viewer.scene.globe.multiClippingPlanes =null;
that.isClipping=false;
}
},
/**
* 根据多边形数组创建裁切面
* @param points_ 多边形数组集合
* @returns {[]} 返回裁切面数组
*/
createClippingPlane(points_) {
let points = [];
for (let i = 0; i < points_.length - 1; i++) {
points.push(Cesium.Cartesian3.fromDegrees(points_[i][0], points_[i][1]))
}
let pointsLength = points.length;
let clippingPlanes = []; // 存储ClippingPlane集合
for (let i = 0; i < pointsLength; ++i) {
let nextIndex = (i + 1) % pointsLength;
let midpoint = Cesium.Cartesian3.add(points[i], points[nextIndex], new Cesium.Cartesian3());
midpoint = Cesium.Cartesian3.multiplyByScalar(midpoint, 0.5, midpoint);
let up = Cesium.Cartesian3.normalize(midpoint, new Cesium.Cartesian3());
let right = Cesium.Cartesian3.subtract(points[nextIndex], midpoint, new Cesium.Cartesian3());
right = Cesium.Cartesian3.normalize(right, right);
let normal = Cesium.Cartesian3.cross(right, up, new Cesium.Cartesian3());
normal = Cesium.Cartesian3.normalize(normal, normal);
let originCenteredPlane = new Cesium.Plane(normal, 0.0);
let distance = Cesium.Plane.getPointDistance(originCenteredPlane, midpoint);
clippingPlanes.push(new Cesium.ClippingPlane(normal, distance));
}
return clippingPlanes;
}
},
created() {
},
}
</script>
<style scoped>
.home {
height: 100%;
margin: 0;
padding: 0;
overflow-y:auto;
overflow-x:hidden;
}
.el-breadcrumb {
margin: 10px;
font-size: 15px;
}
#cesium{
max-height: 500px;
}
</style>
核心代码
创建裁切面
/**
* 根据多边形数组创建裁切面
* @param points_ 多边形数组集合
* @returns {[]} 返回裁切面数组
*/
createClippingPlane(points_) {
let points = [];
for (let i = 0; i < points_.length - 1; i++) {
points.push(Cesium.Cartesian3.fromDegrees(points_[i][0], points_[i][1]))
}
let pointsLength = points.length;
let clippingPlanes = []; // 存储ClippingPlane集合
for (let i = 0; i < pointsLength; ++i) {
let nextIndex = (i + 1) % pointsLength;
let midpoint = Cesium.Cartesian3.add(points[i], points[nextIndex], new Cesium.Cartesian3());
midpoint = Cesium.Cartesian3.multiplyByScalar(midpoint, 0.5, midpoint);
let up = Cesium.Cartesian3.normalize(midpoint, new Cesium.Cartesian3());
let right = Cesium.Cartesian3.subtract(points[nextIndex], midpoint, new Cesium.Cartesian3());
right = Cesium.Cartesian3.normalize(right, right);
let normal = Cesium.Cartesian3.cross(right, up, new Cesium.Cartesian3());
normal = Cesium.Cartesian3.normalize(normal, normal);
let originCenteredPlane = new Cesium.Plane(normal, 0.0);
let distance = Cesium.Plane.getPointDistance(originCenteredPlane, midpoint);
clippingPlanes.push(new Cesium.ClippingPlane(normal, distance));
}
return clippingPlanes;
}
裁剪代码
clippings() {
let that = this;
let clippingPlanes1 = this.createClippingPlane(this.polygonOne);
let clippingPlanes2 = this.createClippingPlane(this.polygonTwo);
let clippingPlaneCollection1 = new Cesium.ClippingPlaneCollection({
planes: clippingPlanes1,
});
let clippingPlaneCollection2 = new Cesium.ClippingPlaneCollection({
planes: clippingPlanes2,
});
if(!that.isClipping){
that._viewer.scene.globe.depthTestAgainstTerrain = true;
that._viewer.scene.globe.multiClippingPlanes = new Cesium.MultiClippingPlaneCollection({
collections: [clippingPlaneCollection1, clippingPlaneCollection2],
edgeWidth: 1,
edgeColor: Cesium.Color.WHITE,
});
that.isClipping=true;
}else {
that._viewer.scene.globe.multiClippingPlanes =null;
that.isClipping=false;
}
},