WebGL--Vue+openlayers实现绘制多边形并且计算出多边形内有多少物体数量

Vue+openlayers实现绘制多边形并且计算出多边形内有多少物体数量

效果:
在这里插入图片描述
代码:

<!--  -->
<template>
  <div class="querycount">
    <button @click="drawPolygon('Polygon')">
      {{ isDraw ? "点击绘制多边形查询人数" : "取消绘制" }}
    </button>
    <div id="map"></div>
  </div>
</template>

<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
//引入主要组件
// import { Feature, Map, Overlay, View } from "ol";
import { Map, View, Feature } from "ol";
//引入layer
import ImageLayer from "ol/layer/Image";
import VectorLayer from "ol/layer/Vector";
//引入source
import Static from "ol/source/ImageStatic";
import VectorSource from "ol/source/Vector";
//交互
import { Draw } from "ol/interaction";
//其他
import Projection from "ol/proj/Projection";
import { getCenter } from "ol/extent";
import { Point } from "ol/geom";
import { Style, Icon, Stroke, Fill } from "ol/style";
//import { Style, Icon, Text, Fill, Stroke } from "ol/style";
//导入图片
import mapImage from "@/assets/img/map1.jpg"; //底图
import personImg from "@/assets/img/anchor.png";
//引入图形算法工具类turf
import * as turf from "@turf/turf";
export default {
  //import引入的组件需要注入到对象中才能使用
  components: {},
  data() {
    //这里存放数据
    return {
      map: null,
      //贴图
      featureSource: new VectorSource(), //人员贴图的source
      feature: null, //贴图
      features: [], //贴图数组
      //多边形
      polygonLayer: null,
      polygonSource: new VectorSource(),
      isDraw: true,
      draw: null,
      //其他
      persons: [], //人的数据,
      //   polygonPoints: [], //多边形的坐标点,
      areaPerson: [], //多边形区域的人员
    };
  },
  //计算属性 类似于data概念
  computed: {},
  //监控data中的数据变化
  watch: {
    persons(newVal) {
      if (newVal) {
        this.setFeatures();
      }
    },
  },
  //方法集合
  methods: {
    //初始化地图
    initMap() {
      //限制范围
      let extent = [0, 0, 2560, 1920];
      //投影
      let projection = new Projection({
        //SRS 标识符代码,例如EPSG:4326
        code: "xkcd-image",
        //	单位。必需,除非 定义 PROJ4 投影。code
        units: "pixels",
        //SRS 的有效性范围。
        extent: extent,
      });
      //底图Layers
      let mapLayer = new ImageLayer({
        source: new Static({
          url: mapImage,
          projection: projection,
          imageExtent: extent,
        }),
      });
      //图标小人图层Layers
      let featureLayer = new VectorLayer({
        source: this.featureSource,
      });
      //绘制多边形layers
      this.polygonLayer = new VectorLayer({
        source: this.polygonSource,
        style: new Style({
          stroke: new Stroke({
            color: "rgba(255,0,0,0.6)",
            width: 5,
          }),
          fill: new Fill({
            color: "rgba(255,0,0,0.3)",
          }),
        }),
      });
      //创建地图
      this.map = new Map({
        target: "map",
        layers: [mapLayer, featureLayer],
        view: new View({
          //配置投影
          projection: projection,
          //配置中心
          center: getCenter(extent),
          //配置zoom
          zoom: 2,
          //配置最大zoom
          maxZoom: 10,
        }),
      });
      //将多边形Layers添加到map中去
      this.map.addLayer(this.polygonLayer);
    },
    //添加Features
    setFeatures() {
      //创建feature
      this.persons.map((item) => {
        this.feature = new Feature({
          geometry: new Point([item.x, item.y]),
          name: item.name,
        });
        //设置features的样式
        this.feature.setStyle(
          new Style({
            image: new Icon({
              //设置icon的锚,默认是中心[0.5,0.5]
              anchor: [0, 1],
              //设置icon的图片
              src: personImg,
            }),
          })
        );
        //给到features数组
        this.features.push(this.feature);
      });
      //给features添加到feature矢量图层中去
      this.featureSource.addFeatures(this.features);
    },
    //绘制多边形
    drawPolygon(type) {
      if (this.isDraw) {
        this.isDraw = false;
        //添加绘制的实例
        this.draw = new Draw({
          type: type,
          //必须设置source,否则不会保存
          source: this.polygonSource,
        });
        //给地图添加交互
        this.map.addInteraction(this.draw);
        //绘制完成后查询所在区域的人数
        this.draw.on("drawend", this.drawEnd);
      } else {
        this.isDraw = true;
        //清理多边形
        this.polygonSource.clear();
        //移除交互
        this.map.removeInteraction(this.draw);
        // //清空多边形的坐标和区域中的人
        // this.polygonPoints = [];
        this.areaPerson = [];
      }
    },
    //绘制完成后查询所在区域的人数
    drawEnd(e) {
      //获取绘制的几何
      let geo = e.feature.getGeometry();
      let geoType = geo.getType();
      if (geoType == "Polygon") {
        //获取该多边形的坐标点
        let points = geo.getCoordinates();
        //#region
        //*******判断多边形内的点的--------方法一***********
        //将多边形的点添加到数组中
        // points[0].map((item) => {
        //   this.polygonPoints.push({ longitude: item[0], latitude: item[1] });
        // });
        // //判断人员是否在多边形的区域内  Y--将人员添加到区域数组中
        // this.persons.forEach((item) => {
        //   //   let pt = turf.point([item.x, item.y]);
        //   //   //定义一个旗帜表示是否在多边形区域
        //   //   let flag = turf.booleanPointInPolygon(pt, polygonPoints);
        //   let flag = this.isAtRegion(item.x, item.y, this.polygonPoints);
        //   if (flag) {
        //     this.areaPerson.push(item);
        //   }
        // });
        //#endregion
        //**********判断多边形内的点的-------方法二(运用turf.js来计算)************
        let polygonPoints = turf.polygon([points[0]]); //多边形的坐标点
        //判断人员是否在多边形的区域内  Y--将人员添加到区域数组中
        this.persons.forEach((item) => {
          let pt = turf.point([item.x, item.y]); //每一个人员的坐标点
          //定义一个旗帜表示是否在多边形区域
          let flag = turf.booleanPointInPolygon(pt, polygonPoints);
          if (flag) {
            this.areaPerson.push(item);
          }
        });

        //弹窗输出区域内的人数
        alert(`区域内有${this.areaPerson.length}`);
        //移除交互
        this.map.removeInteraction(this.draw);
      }
    },
    //判断是否在多边形区域内的算法 参数:人的经度,人的纬度,多边形的坐标点
    // isAtRegion(lon, lat, polygonPoints) {
    //   let num = 0;
    //   let iCount;
    //   let dLon1, dLon2, dLat1, dLat2, dLon;
    //   if (polygonPoints.length < 3) {
    //     return false;
    //   }
    //   iCount = polygonPoints.length;
    //   for (let i = 0; i < iCount; i++) {
    //     if (i == iCount - 1) {
    //       dLon1 = polygonPoints[i].longitude;
    //       dLat1 = polygonPoints[i].latitude;
    //       dLon2 = polygonPoints[0].longitude;
    //       dLat2 = polygonPoints[0].latitude;
    //     } else {
    //       dLon1 = polygonPoints[i].longitude;
    //       dLat1 = polygonPoints[i].latitude;
    //       dLon2 = polygonPoints[i + 1].longitude;
    //       dLat2 = polygonPoints[i + 1].latitude;
    //     }
    //     if ((lat >= dLat1 && lat < dLat2) || (lat >= dLat2 && lat < dLat1)) {
    //       if (Math.abs(dLat1 - dLat2) > 0) {
    //         dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - lat)) / (dLat1 - dLat2);
    //         if (dLon < lon) num++;
    //       }
    //     }
    //   }
    //   if (num % 2 != 0) return true;
    //   return false;
    // },
  },
  beforeCreate() {}, //生命周期 - 创建之前
  //生命周期 - 创建完成(可以访问当前this实例)
  created() {
    //在此周期给persons添加数据
    this.persons = [
      { id: 1, name: "点-1", x: 497.08, y: 187.88, z: 0 },
      { id: 2, name: "点-2", x: 725.32, y: 565.88, z: 0 },
      { id: 3, name: "点-3", x: 643.24, y: 503.96, z: 0 },
    ];
  },
  beforeMount() {}, //生命周期 - 挂载之前
  //生命周期 - 挂载完成(可以访问DOM元素)
  mounted() {
    //初始化地图
    this.initMap();
  },
  beforeUpdate() {}, //生命周期 - 更新之前
  updated() {}, //生命周期 - 更新之后
  beforeDestroy() {}, //生命周期 - 销毁之前
  destroyed() {}, //生命周期 - 销毁完成
  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
};
</script>
<style scoped>
#map {
  width: 1000px;
  height: 800px;
  border: 1px solid #333;
  margin: 0 auto;
}
button {
  display: block;
  margin: 10px auto;
}
/* #region */
/* #popup {
  width: 200px;
  height: 80px;
  padding: 0 20px;
  border-radius: 5px;
  z-index: 1;
  opacity: 1;
  position: absolute;
  bottom: 0;
  left: 0;
  margin: 0;
  background: rgba(0, 60, 136, 0.7);
  color: white;
  border: 0;
  transition: opacity 100ms ease-in;
} */
/* #endregion */
</style>

注意:
此处用了两种方法来进行点在多边形内的判断
法一:自己写的isAtRegion()函数
法二:使用turf.js来进行算法判断(推荐)
如果使用法二,请删除data中的polygonPoints
methods中的isAtRegion()
再去掉方法一下的代码即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值