地图上点与多边形的关系判断

大家都知道,点与多边形的关系无非是点在多边形内、点在多边形外、点在多边形的边界上。那么,如何用代码是实现肉眼就能辨别的地理位置关系呢?~


多边形的外包矩形

> 如果一个点不在多边形的外包矩形内,那它肯定不在这个多边形内

射线法判断奇偶数

> 计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则在多边形内

这里写图片描述

  //判断点是否在多边形内:
       function isPointInPolygon(point,polygon){

        //如果是百度的点,用百度已有的方法判断该点是否在多边形的外包矩形内
        if((point instanceof BMap.Point)&&(polygon instanceof BMap.Polygon)){

              var polygonBounds = polygon.getBounds();
              var sw = polygonBounds.getSouthWest(); //西南脚点
              var ne = polygonBounds.getNorthEast(); //东北脚点

              var inRect = point.lng >= sw.lng && point.lng <= ne.lng && point.lat >= sw.lat && point.lat <= ne.lat ;

              if(!inRect){

               return false ; //如果不在外包矩形内,更不会在多边形内。直接返回false 

              }else{


                  var pts = polygon.getPath();//获取多边形的点集合。
                  /**
                  基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则在多边形内
                  */
                  var N = pts.length;
                  var boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
                  var intersectCount = 0;//cross points count of x 
                  var precision = 2e-10; //浮点类型计算时候与0比较时候的容差
                  var p1, p2;//neighbour bound vertices
                  var p = point; //测试点
                  p1 = pts[0];//left vertex 

                  for(var i = 1; i <= N; ++i){//check all rays            

                   if(p.equals(p1)){
                        return boundOrVertex;//p is an vertex
                    }

                   p2 = pts[i % N];//right vertex            

                   if(p.lat < Math.min(p1.lat, p2.lat) || p.lat > Math.max(p1.lat, p2.lat)){//ray is outside of our interests                
                    p1 = p2; 
                    continue;//next ray left point
                   }

                   if(p.lat > Math.min(p1.lat, p2.lat) && p.lat < Math.max(p1.lat, p2.lat)){//ray is crossing over by the algorithm (common part of)
                       if(p.lng <= Math.max(p1.lng, p2.lng)){//x is before of ray                    
                          if(p1.lat == p2.lat && p.lng >= Math.min(p1.lng, p2.lng)){//overlies on a horizontal ray
                             return boundOrVertex;
                    }

                       if(p1.lng == p2.lng){//ray is vertical                        
                         if(p1.lng == p.lng){//overlies on a vertical ray
                            return boundOrVertex;
                          }else{//before ray
                            ++intersectCount;
                          } 
                        }else{//cross point on the left side                        
                       var xinters = (p.lat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) + p1.lng;//cross point of lng                        
                       if(Math.abs(p.lng - xinters) < precision){//overlies on a ray
                            return boundOrVertex;
                        }

                        if(p.lng < xinters){//before ray
                            ++intersectCount;
                        } 
                    }
                 }
                 }else{//special case when ray is crossing through the vertex                

                    if(p.lat == p2.lat && p.lng <= p2.lng){//p crossing over p2                    
                    var p3 = pts[(i+1) % N]; //next vertex                    
                      if(p.lat >= Math.min(p1.lat, p3.lat) && p.lat <= Math.max(p1.lat, p3.lat)){//p.lat lies between p1.lat & p3.lat
                        ++intersectCount;
                      }else{
                        intersectCount += 2;
                     }
                 }
               }            

               p1 = p2;//next ray left point
               }

              if(intersectCount % 2 == 0){//偶数在多边形外
                 return false;
              } else { //奇数在多边形内
                 return true;
               }  

              }
         }
       }

其中3个点的坐标如下:

  var pointA = new BMap.Point(121.333777,31.206659);

  var pointB  = new BMap.Point(121.307313,31.203956);

  var pointC  = new BMap.Point(121.317967,31.224201);

多边形的可参考上一篇计算面积的点集合。

   //调用计算面积的方法
       setTimeout(function(){

        alert("A是否在范围内:"+isPointInPolygon(pointA,polygon) );
        alert("B是否在范围内:"+isPointInPolygon(pointB,polygon) );
        alert("C是否在范围内:"+isPointInPolygon(pointC,polygon) );


       },1000);

这里写图片描述
这里写图片描述

因为在代码里把在多边形上的点默认值为boundOrVertex =true 。所以C点也属于范围内的
这里写图片描述

通过计算点与范围的关系,可以拓展计算范围与范围的交叉重叠计算,在实际业务中很有用喔。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值