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 分钟前
39.网络流入门
开发语言·网络·c++·算法
前端君16 分钟前
实现最大异步并发执行队列
javascript
未来之窗软件服务1 小时前
幽冥大陆(二)RDIFSDK 接口文档:布草洗涤厂高效运营的技术桥梁C#—东方仙盟
开发语言·c#·rdif·仙盟创梦ide·东方仙盟
小冯记录编程1 小时前
C++指针陷阱:高效背后的致命危险
开发语言·c++·visual studio
1uther1 小时前
Unity核心概念⑨:Screen
开发语言·游戏·unity·c#·游戏引擎
知识分享小能手2 小时前
React学习教程,从入门到精通,React 组件核心语法知识点详解(类组件体系)(19)
前端·javascript·vue.js·学习·react.js·react·anti-design-vue
C_Liu_2 小时前
C++:类和对象(下)
开发语言·c++
coderxiaohan2 小时前
【C++】类和对象1
java·开发语言·c++
阿幸软件杂货间2 小时前
Office转PDF转换器v1.0.py
开发语言·pdf·c#
蚂蚁RichLab前端团队2 小时前
🚀🚀🚀 RichLab - 花呗前端团队招贤纳士 - 【转岗/内推/社招】
前端·javascript·人工智能