cesium-地面裁剪(多个剪切面)

cesium-地面裁剪(多个剪切面)

介绍

我之前的文章介绍过地面裁剪的实现,这里介绍一下裁剪多个面的方式。

Cesium自带的ClippingPlaneCollection只能实现单凸多边形挖除,为了实现多个面的裁切和简单凹多边形,这里我们需要修源码以提供支持。

在github中的问题讨论中已经有人实现了,实现方式需要重新打包源码

具体的详解

image-20220209155938532

image-20220209160228889

实现效果

image-20220209160110399

image-20220209160154294

源码打包

  • 这里我使用的cesium源码版本为:1.79.1下载地址
  • 打包工具使用的是webstorm
  • node.js版本为14.17.5

替换文件

image-20220209160807442

所有替换文件位置都在Source下,可以检索一下替换

image-20220209160837427

使用打包命令打包

npm run build

image-20220209161020569

部署打包代码

image-20220209161220473

可以部署到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;
      }

    },
  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙霸天

你的打赏是我不断创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值