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

来源:互联网 发布:linux u盘挂载乱码 编辑:程序博客网 时间:2024/05/01 13:30

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


多边形的外包矩形

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

射线法判断奇偶数

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

这里写图片描述

  //判断点是否在多边形内:       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 0
原创粉丝点击