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文件:

javascript 复制代码
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,
};
相关推荐
开发者小天8 分钟前
React中的componentWillUnmount 使用
前端·javascript·vue.js·react.js
sunly_12 分钟前
Flutter:视频预览功能
javascript·flutter·音视频
mjhcsp24 分钟前
C++ 递推与递归:两种算法思想的深度解析与实战
开发语言·c++·算法
m0_7482480236 分钟前
《详解 C++ Date 类的设计与实现:从运算符重载到功能测试》
java·开发语言·c++·算法
杰克尼1 小时前
vue_day04
前端·javascript·vue.js
我命由我123451 小时前
Java 并发编程 - Delay(Delayed 概述、Delayed 实现、Delayed 使用、Delay 缓存实现、Delayed 延迟获取数据实现)
java·开发语言·后端·缓存·java-ee·intellij-idea·intellij idea
HLJ洛神千羽1 小时前
C++程序设计实验(黑龙江大学)
开发语言·c++·软件工程
kyle~1 小时前
算法数学---差分数组(Difference Array)
java·开发语言·算法
曹牧1 小时前
C#:三元运算符
开发语言·c#
Jonathan Star2 小时前
MediaPipe 在Python中实现人体运动识别,最常用且高效的方案是结合**姿态估计**(提取人体关键点)和**动作分类**(识别具体运动)
开发语言·python·分类