vuejs+cesium实现落图覆盖率(求落图交集、并集以及面积)

1、主要实现目标:计算所有落图的并集与目标位置的交集面积占目标位置总面积的百分比。

2、主要实现过程:计算所有落图的并集以及目标位置的交集需借助npm包martinez-polygon-clipping。

 ①npm安装martinez-polygon-clipping:npm install martinez-polygon-clipping;
 ②.vue文件引入:const martinez = require('martinez-polygon-clipping');
 ③求并集方法:martinez.union(a,b);
 ④求交集方法:martinez.intersection(a,b);
 ⑤求面积:需要将wgs84坐标转成弧度坐标计算。

3、求并集

 主要情况:①只有一个落图,那此时并集为该落图的点的集合;
      ②有两个落图时,那并集为两个落图并集的点的集合;
      ③大于两个落图时,那并集为:第一个落图与第二个落图求的并集再和第三个落图求的并集的点的集合,以此类推;

 具体代码实现:

    let unionData = [];//并集 --  点的集合
    let selectData = [];//落图 -- 点的集合
              if( selectData.length === 1){
                     unionData = selectData;
    }else if(selectData.length === 2){
      unionData = martinez.union(selectData[0],selectData[1]);
    }else if(selectData.length >2){
      unionData = selectData[0];
      selectData.map((item)=>{
        unionData = martinez.union(item,unionData);
      })
    }

4、求交集

 具体代码实现:

    let intersectionData = [];//交集 -- 点的集合
    let targetPositionData = [];//目标位置 -- 点的集合
    intersectionData = martinez.intersection(unionData[0],targetPositionData);

5、求面积

 计算一组坐标组成多边形的面积:

     getPositionsArea:(positions) {
                  let result = 0
                  if (positions) {
                      let h = 0
                      let ellipsoid = Cesium.Ellipsoid.WGS84
                      for (let i = 1; i < positions.length; i++) {
                          let oel = ellipsoid.cartographicToCartesian(
                              this.transformWGS84ToCartographic(positions[i - 1])
                          )
                          let el = ellipsoid.cartographicToCartesian(
                              this.transformWGS84ToCartographic(positions[i])
                          )
                          h += oel.x * el.y - el.x * oel.y
                      }
                      result = Math.abs(h).toFixed(2)
                  }
                  return result
             }
     //wgs84坐标转换成Cartographic 弧度坐标
    transformWGS84ToCartographic: function (position) {
                  return position ?
                      Cesium.Cartographic.fromDegrees(
                          position.lng || position.lon,
                          position.lat,
                          position.alt
                      ) :
                      Cesium.Cartographic.ZERO
             }
 点的集合的数据结构:①一个多边形(三维数组):[[[116.14949273,39.98831936],...,[116.14949273,39.98831936]]];
           ②多个多边形(四维数组):[[[[116.14949273,39.98831936],...,[116.14949273,39.98831936]]]];
 计算面积时需要将三维数组或者四维数组转换成含有lng、lat、alt属性的数组对象,具体代码实现:
    calculateArea(list,type){
          let that = this;
          let area = 0;
             list.map((item)=>{
              let zhuanhuanData = [];
              item.map((list)=>{
                  that.$set(list,'lng',list[0]);
                  that.$set(list,'lat',list[1]);
                  that.$set(list,'alt',0);
                  zhuanhuanData.push(list);
              })
                area = area + Number(that.getPositionsArea(zhuanhuanData));
           })
         return area
      }
6、完整代码
  
  getCoverageRateData(seletObj){
    //seletObj为选中的落图数据
        let selectData = [];
        let unionData = [];
        let intersectionData = [];
        if(seletObj.length > 0){
          seletObj.map((item)=>{
            selectData.push(JSON.parse(item.geom).coordinates)
          })
          if(selectData && (selectData.length == 1)){
              unionData = selectData;
          }else if(selectData.length == 2){
              unionData = martinez.union(selectData[0],selectData[1]);
          }else if(selectData.length >2){
              unionData = selectData[0];
              selectData.map((item)=>{
                unionData = martinez.union(item,unionData);
              })
          }
     //this.queryParams.geom为目标位置数据
          intersectionData = martinez.intersection(unionData[0],JSON.parse(this.queryParams.geom).coordinates);
    //dropPlotArea -- 落图与目标位置交集的面积
          let dropPlotArea= this.calculateArea(JSON.parse(this.queryParams.geom).coordinates,this.computeAnArray(JSON.parse(this.queryParams.geom).coordinates));
    //targetLocationArea -- 目标位置面积
          let targetLocationArea = this.calculateArea(intersectionData,this.computeAnArray(intersectionData));
    //覆盖率
          let coverageRate = ((targetLocationArea/dropPlotArea)*100).toFixed(2);
       }
    },
  //判断是几维数组
  computeAnArray(arr) {
        var list = [];
        var num = 0;
        for (var i = 0; i < arr.length; i++) {
          if (arr[i] instanceof Array) {
            for (var j = 0; j < arr[i].length; j++) {
              list.push(arr[i][j]);
            }
          }
        }
        if (list.length) {
          num = 1
          num += this.computeAnArray(list)
        }
        return num;
     },
  //计算面积(此方法待优化)
      calculateArea(list,type){
        let that = this;
        let area = 0;
        if(type == 2){
          list.map((item)=>{
            let zhuanhuanData1 = [];
            item.map((list)=>{
              that.$set(list,'lng',list[0]);
              that.$set(list,'lat',list[1]);
              that.$set(list,'alt',0);
              zhuanhuanData1.push(list);
            })
            area = area + Number(that.getPositionsArea(zhuanhuanData1));
          })
        }else{
          list.map((item)=>{
            let zhuanhuanData1 = [];
            item.map((list)=>{
              list.map((value)=>{
                that.$set(value,'lng',value[0]);
                that.$set(value,'lat',value[1]);
                that.$set(value,'alt',0);
                zhuanhuanData1.push(value);
              })
            })
            area = area + Number(that.getPositionsArea(zhuanhuanData1));
          })
        }
        return area
    },
  getPositionsArea:(positions) {
                let result = 0
                if (positions) {
                    let h = 0
                    let ellipsoid = Cesium.Ellipsoid.WGS84
                    for (let i = 1; i < positions.length; i++) {
                         let oel = ellipsoid.cartographicToCartesian(
                             this.transformWGS84ToCartographic(positions[i - 1])
                         )
                         let el = ellipsoid.cartographicToCartesian(
                             this.transformWGS84ToCartographic(positions[i])
                         )
                         h += oel.x * el.y - el.x * oel.y
                     }
                    result = Math.abs(h).toFixed(2)
                 }
                 return result
            },
   //wgs84坐标转换成Cartographic 弧度坐标
   transformWGS84ToCartographic: function (position) {
                 return position ?
                      Cesium.Cartographic.fromDegrees(
                          position.lng || position.lon,
                          position.lat,
                          position.alt
                      ) :
                      Cesium.Cartographic.ZERO
            },


 
posted @ 2023-05-11 14:26  我爱敲代码0000  阅读(302)  评论(0编辑  收藏  举报