• js 如何判断一个指定的位置点坐标是否落在一个多边形区域内?


    1 场景

      业务场景举例:快递选择收获区域、车辆电子围栏、运动轨迹路线、地理位置信息检测范围和地图等过滤等等。
      比方说地图上有一块区域(抽象成多边形),然后里面每一个位置点(像素点)都有对应的GPS的经纬度坐标值,题目要求的就是判断任意点(用户输入的信息)与多边形的位置关系(是否在里面还是在图形区域外面)。

    1.1 方案

      设:需要判断的目标点为P
      参数
      aLat: P的纬度
      aLon: P的经度
      pointList: 单个多边形区域顶点数组。如果有多个独立区域,则分别调用本方法,只要有一次为ture即表示在区域内。
    在这里插入图片描述

    1.2 理论支持

      目前比较通用的就是射线法和坐标轴法,而我采用的就是X轴射线法。
      判断一个点向左的射线跟一个多边形的交叉点有几个,如果结果为奇数的话那么说明这个点落在多边形中,反之则不在。
      如果从需要判断的点出发的一条射线与该多边形的焦点个数为奇数,则该点在此多边形内,否则该点在此多边形外。(射线不能与多边形顶点相交)

    1.3 编程思路

      该程序的思路是从A点出发向左做一条水平射线(平行于x轴,向X轴的反方向),判断与各边是否有焦点。
    dLon1, dLon2, dLat1, dLat2分别表示边的起点和终点的经度和纬度(x轴和y轴)。
      先判断A点是否在边的两端点d1和d2的水平平行线之间,不在则不可能有交点,继续判断下一条边。
    在之间则说明可能与A点向左的射线有交点,接下来利用几何方法得到A点的水平直线与该边交点的x坐标。
    然后判断交点的x坐标在A点的左侧还是右侧,左侧则总交点数加一,右侧则不在A点左射线上,继续判断下一条边。
      代码讲解: 主要的类有两个↓↓
    一个是坐标点的抽象类(点的坐标位置),另一个是位置关系判断工具类(判断点和多边形的关系)。
      因为坐标描点要涉及到坐标以及小数点的经纬关系,故要用到浮点型运算,也就是要使用到double双精度。而地图涉及到很多个像素点构成的图形区域,故要用到list数组。结果要展示需要用到js代码
    utilofMap.js文件:

    function IsPtInPoly(aLat, aLon, pointList) {
      /* 
      :param aLon: double 经度 
      :param aLat: double 纬度 
      :param pointList: list [{latitude: 22.22, longitude: 113.113}...] 多边形点的顺序需根据顺时针或逆时针,不能乱 
      */
      var iSum = 0  
      var iCount = pointList.length
        
      if(iCount < 3) {
          return false 
      }
      //  待判断的点(x, y) 为已知值
      var y = aLat
      var x = aLon
      for(var i = 0; i < iCount; i++) {
          var y1 = pointList[i].latitude  
          var x1 = pointList[i].longitude
          if(i == iCount - 1) {
              var y2 = pointList[0].latitude
              var x2 = pointList[0].longitude
          } else {
              var y2 = pointList[i + 1].latitude  
              var x2 = pointList[i + 1].longitude
          }
          // 当前边的 2 个端点分别为 已知值(x1, y1), (x2, y2)
          if (((y >= y1) && (y < y2)) || ((y >= y2) && (y < y1))) {
              //  y 界于 y1 和 y2 之间
              //  假设过待判断点(x, y)的水平直线和当前边的交点为(x_intersect, y_intersect),有y_intersect = y
              // 则有(2个相似三角形,公用顶角,宽/宽 = 高/高):|x1 - x2| / |x1 - x_intersect| = |y1 - y2| / |y1 - y|
              if (Math.abs(y1 - y2) > 0) {
                  var x_intersect = x1 - ((x1 - x2) * (y1 - y)) / (y1 - y2);  
                  if(x_intersect < x) {
                      iSum += 1 
                  }
              }
          } 
      }
      if(iSum % 2 != 0) {
          return true  
      }else {
          return false 
      }  
    }
    module.exports = {
      IsPtInPoly: IsPtInPoly,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
  • 相关阅读:
    面试官:hold住了八股和算法,扫码登录应该怎么实现你总不会了吧
    uniapp公用返回组件
    笔试强训第18天
    太全了——用Python操作MySQL的使用教程集锦
    Flutter 高级教程之如何开发iOS Widget小组件展示SQLite本地数据库数据(教程含完整源码)
    Prometheus接入AlterManager配置邮件告警(基于K8S环境部署)
    压力测试-JMeter安装、入门、结果分析
    WoShop多商户直播电商系统APP+小程序+H5全开源无加密商城源码
    【无标题】
    Docker部署Jumpserver堡垒机
  • 原文地址:https://blog.csdn.net/qq_36158551/article/details/133513314