zpf 1 год назад
Родитель
Сommit
70ae67639f

+ 150 - 0
src/components/TerrainAnalysis/TerrainCutFillAnalysis/CutFillAnalysis.js

@@ -0,0 +1,150 @@
+
+export default class CutFillAnalysis {
+  constructor(viewer, precision) {
+    if (!viewer) throw new Error("no viewer object!");
+    this.viewer = viewer;
+    this.maxHeigh = -1000000;
+    this.eName = "三角面";
+
+  }
+  createPolygonGeo(points) {
+    //计算网格粒度-精度
+    let granularity = Math.PI / Math.pow(2, 11);
+    granularity = granularity / this.precision;
+
+    let polygonGeometry = new Cesium.PolygonGeometry.fromPositions({
+      positions: points,
+      vertexFormat: Cesium.PerInstanceColorAppearance.FLAT_VERTEX_FORMAT,
+      granularity: granularity,
+    });
+    //创建自定义平面几何体
+    this.geom = new Cesium.PolygonGeometry.createGeometry(polygonGeometry);
+  }
+  VolumeAnalysis(points, height, extrudedHeight) {
+    this.createPolygonGeo(points);
+
+    let cutArea = 0,
+      cutVolume = 0,
+      fillArea = 0,
+      fillVolume = 0,
+      noArea = 0;
+    const indices = this.geom.indices; //获取顶点索引数据
+    const positions = this.geom.attributes.position.values;
+    for (let index = 0; index < indices.length; index += 3) {
+
+      const pos0 = this.returnPosition(positions, indices[index]);
+      const pos1 = this.returnPosition(positions, indices[index + 1]);
+      const pos2 = this.returnPosition(positions, indices[index + 2]);
+      // this.viewer.entities.add({
+      //   name: this.eName,
+      //   polygon: {
+      //     show:false,
+      //     hierarchy: [pos0.heightPos, pos1.heightPos, pos2.heightPos],
+      //     // perPositionHeight:
+      //     //为true时,height将失去作用,extrudedHeight则从地表计算高度作为多边形的高;
+      //     // 为false时,height将从地表计算高度,多边形就会有离地高度,extrudedHeight = height+你想要的多边形高度。例:假如你想创建一个距离地表500米的多边形,它的高度为100,height:500,extrudedHeight:500+100
+      //     perPositionHeight: true,
+      //     material: Cesium.Color.fromRandom({
+      //       alpha: 0.8
+      //     }),
+      //     // height: this.height,
+      //     extrudedHeight: this.extrudedHeight,
+      //     outline: true,
+      //     outlineColor: Cesium.Color.BLACK,
+      //   },
+      // });
+      //水平状态下三角形面积
+      const area = this.computeArea4Triangle(
+        pos0.noHeightPos,
+        pos1.noHeightPos,
+        pos2.noHeightPos
+      );
+      //计算三个点的均高
+      const height = (pos0.height + pos1.height + pos2.height) / 3;
+      if (height < extrudedHeight) {
+        // 需要填方的部分
+        fillArea += area;
+        const volume = area * (extrudedHeight - height);
+        fillVolume += volume;
+      } else if (height == extrudedHeight) {
+        noArea += area;
+      } else {
+        // 需要挖方的部分
+        cutArea += area;
+        const volume = area * (height - extrudedHeight);
+        cutVolume += volume;
+      }
+    }
+    const allArea = cutArea + fillArea + noArea;
+    this.result = {
+      allArea,
+      cutArea,
+      cutVolume,
+      fillArea,
+      fillVolume,
+      noArea,
+    };
+    return cutVolume;
+  }
+
+  computeCentroid4Polygon(positions) {
+    let x = [],
+      y = [];
+    let allX = 0,
+      allY = 0;
+    for (let i = 0; i < positions.length; i++) {
+      let cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
+      allX += cartographic.longitude;
+      allY += cartographic.latitude;
+      x.push(cartographic.longitude);
+      y.push(cartographic.latitude);
+    }
+    let centroidx = allX / positions.length;
+    let centroidy = allY / positions.length;
+    const Cartographic = new Cesium.Cartographic(centroidx, centroidy);
+    return Cesium.Cartesian3.fromRadians(
+      Cartographic.longitude,
+      Cartographic.latitude,
+      this.maxHeigh + 30
+    );
+  }
+  /**
+   * 海伦公式求取三角形面积
+   * @param {*} pos1
+   * @param {*} pos2
+   * @param {*} pos3
+   * @returns 三角形面积㎡
+   */
+  computeArea4Triangle(pos1, pos2, pos3) {
+    let a = Cesium.Cartesian3.distance(pos1, pos2);
+    let b = Cesium.Cartesian3.distance(pos2, pos3);
+    let c = Cesium.Cartesian3.distance(pos3, pos1);
+    let S = (a + b + c) / 2;
+    return Math.sqrt(S * (S - a) * (S - b) * (S - c));
+  }
+  returnPosition(positions, index) {
+    let cartesian = new Cesium.Cartesian3(
+      positions[index * 3],
+      positions[index * 3 + 1],
+      positions[index * 3 + 2]
+    );
+    let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
+    let height = this.viewer.scene.globe.getHeight(cartographic);
+    if (height > this.maxHeigh) {
+      this.maxHeigh = height;
+    }
+    return {
+      heightPos: Cesium.Cartesian3.fromRadians(
+        cartographic.longitude,
+        cartographic.latitude,
+        height
+      ),
+      noHeightPos: Cesium.Cartesian3.fromRadians(
+        cartographic.longitude,
+        cartographic.latitude,
+        0
+      ),
+      height: height,
+    };
+  }
+}

+ 18 - 4
src/components/TerrainAnalysis/TerrainCutFillAnalysis/TerrainCutFillAnalysis.vue

@@ -18,14 +18,17 @@
 
 <script>
 //这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
-
+import CutFillAnalysis from "./CutFillAnalysis.js"
+let cutFillAnalysis = null;
 export default {
   name: "TerrainCutFillAnalysis",
   components: {},
   data() {
 
     return {
-      input: '', sharedState: store.state, height: 300, result: null,
+      input: '', sharedState: store.state,
+      height: 300,
+      result: null,
       handler_Cut_fill: new Cesium.DrawHandler(viewer, Cesium.DrawMode.Polygon, 0)
     };
   },
@@ -79,6 +82,9 @@ export default {
           return;
         };
         var array = [].concat(result.object.positions);
+
+        let cutVolume = cutFillAnalysis.VolumeAnalysis(array, that.height, that.height);
+        that.result = cutVolume;
         tooltip.setVisible(false);
         var positions = [];
         for (var i = 0, len = array.length; i < len; i++) {
@@ -86,6 +92,7 @@ export default {
           var longitude = Cesium.Math.toDegrees(cartographic.longitude);
           var latitude = Cesium.Math.toDegrees(cartographic.latitude);
           var h = cartographic.height;
+
           if (positions.indexOf(longitude) == -1 && positions.indexOf(latitude) == -1) {
             positions.push(longitude);
             positions.push(latitude);
@@ -96,9 +103,10 @@ export default {
         viewer.scene.globe.addExcavationRegion({
           name: 'ggg',
           position: positions,
-          height: 500,
+          height: that.height,
           transparent: false
         });
+
         that.handler_Cut_fill.polygon.show = false;
         that.handler_Cut_fill.polyline.show = false;
         that.handler_Cut_fill.deactivate();
@@ -127,7 +135,13 @@ export default {
 
   }, //生命周期 - 创建完成(可以访问当前this实例)
   beforeMount() { }, //生命周期 - 挂载之前
-  mounted() { }, //生命周期 - 挂在完成
+  mounted() {
+
+    cutFillAnalysis = new CutFillAnalysis(
+      viewer,
+      80,
+    );
+  }, //生命周期 - 挂在完成
   beforeUpdate() { }, //生命周期 - 更新之前
   updated() { }, //生命周期 - 更新之后
   beforeDestroy() { }, //生命周期 - 销毁之前