判断地图上的点是否在区域内的方法

// 地图的工具类(使用平台,小程序,h5,pc等)
const EARTHRADIUS = 6370996.81;
const mapUtils = (function() {
    const GeoUtils = function () {

    };

    // ------添加静态方法-------

    /**
     * 判断点是否在矩形内
     * @param {Point} point 点对象
     * @param {bounds} bounds 矩形边界对象(由西南点, 东北点两个点构成)
     * @returns {Boolean} 点在矩形内返回true,否则返回false
     */
    GeoUtils.isPointInRect = function(point, bounds) {
        const sw = bounds.sw; //西南脚点
        const ne = bounds.ne; //东北脚点
        console.log(sw, ne);
        return (point.longitude >= sw.longitude && point.longitude <= ne.longitude && point.latitude >= sw.latitude && point.latitude <= ne.latitude);
    };

    /**
     * 判断点是否多边形内
     * @param {Point} point 点对象
     * @param {Polyline} polygon 多边形对象
     * @returns {Boolean} 点在多边形内返回true,否则返回false
     */
    GeoUtils.isPointInPolygon = function(point, polygon) { debugger;
        // 工具函数
        function equals(p1, p2) {
            return p1 && p2 && p1.latitude == p2.latitude && p1.longitude == p2.longitude;
        }
        //首先判断点是否在多边形的外包矩形内,如果在,则进一步判断,否则返回false
        //  const polygonBounds = polygon.getBounds();
        //  if(!this.isPointInRect(point, polygonBounds)) {
        //      return false;
        //  }
 
        const pts = polygon;//获取多边形点
        
        //下述代码来源:http://paulbourke.net/geometry/insidepoly/,进行了部分修改
        //基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
        //在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
        
        const N = pts.length;
        let boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
        let intersectCount = 0; //cross points count of x 
        const precision = 2e-10; //浮点类型计算时候与0比较时候的容差
        let p1, p2; //neighbour bound vertices
        let p = point; //测试点
        
        p1 = pts[0];//left vertex        
        for(let i = 1; i <= N; ++i) { //check all rays  
            
            // 判断点是否与多边形的点重合
            if(equals(p, p1)) {
                return boundOrVertex;//p is an vertex
            }
            
            p2 = pts[i % N];//right vertex
            // 点与线不想交,进行下次判断            
            if(p.latitude < Math.min(p1.latitude, p2.latitude) || p.latitude > Math.max(p1.latitude, p2.latitude)) { 
                //ray is outside of our interests                
                p1 = p2; 
                continue;//next ray left point
            }
            
            // 点与线相交
            if(p.latitude > Math.min(p1.latitude, p2.latitude) && p.latitude < Math.max(p1.latitude, p2.latitude)) { 
                //ray is crossing over by the algorithm (common part of) (比较横坐标了)
                if(p.longitude <= Math.max(p1.longitude, p2.longitude)) { 
                    //x is before of ray                    
                    if (p1.latitude == p2.latitude && p.longitude >= Math.min(p1.longitude, p2.longitude)) { 
                        //overlies on a horizontal ray(是否覆盖在水平线上)
                        return boundOrVertex;
                    }
                    
                    if (p1.longitude == p2.longitude) { //ray is vertical (线是否垂直)                       
                        if(p1.longitude == p.longitude) { //overlies on a vertical ray
                            return boundOrVertex;
                        }else{ //before ray
                            ++intersectCount;
                        } 
                    } else { //cross point on the left side                        
                        const xinters = (p.latitude - p1.latitude) * (p2.longitude - p1.longitude) / (p2.latitude - p1.latitude) + p1.longitude;//cross point of longitude                        
                        if(Math.abs(p.longitude - xinters) < precision) { //overlies on a ray
                            return boundOrVertex;
                        }
                        
                        if(p.longitude < xinters) { //before ray
                            ++intersectCount;
                        } 
                    }
                }
            }else{ //special case when ray is crossing through the vertex                
                if(p.latitude == p2.latitude && p.longitude <= p2.longitude) { //p crossing over p2                    
                    const p3 = pts[(i+1) % N]; //next vertex                    
                    if(p.latitude >= Math.min(p1.latitude, p3.latitude) && p.latitude <= Math.max(p1.latitude, p3.latitude)) { //p.latitude lies between p1.latitude & p3.latitude
                        ++intersectCount;
                    }else{
                        intersectCount += 2;
                    }
                }
            }            
            p1 = p2;//next ray left point
        }
    
        if(intersectCount % 2 == 0) { //偶数在多边形外
            return false;
        } else { //奇数在多边形内
            return true;
        }            
    };

    /**
     * 将v值限定在a,b之间,经度使用
     */
    function _getLoop(v, a, b){
        while( v > b){
          v -= b - a
        }
        while(v < a){
          v += b - a
        }
        return v;
    }

    /**
     * 将度转化为弧度
     * @param {degree} Number 度     
     * @returns {Number} 弧度
     */
    GeoUtils.degreeToRad =  function(degree){
        return Math.PI * degree/180;    
    }
    
    /**
     * 将弧度转化为度
     * @param {radian} Number 弧度     
     * @returns {Number} 度
     */
    GeoUtils.radToDegree = function(rad){
        return (180 * rad) / Math.PI;       
    }

    /**
     * 计算两点之间的距离,两点坐标必须为经纬度
     * @param {point1} Point 点对象
     * @param {point2} Point 点对象
     * @returns {Number} 两点之间距离,单位为米
     */
    GeoUtils.getDistance = function(point1, point2){

        point1.longitude = _getLoop(point1.longitude, -180, 180);
        point1.latitude = _getRange(point1.latitude, -74, 74);
        point2.longitude = _getLoop(point2.longitude, -180, 180);
        point2.latitude = _getRange(point2.latitude, -74, 74);
        
        var x1, x2, y1, y2;
        x1 = GeoUtils.degreeToRad(point1.longitude);
        y1 = GeoUtils.degreeToRad(point1.latitude);
        x2 = GeoUtils.degreeToRad(point2.longitude);
        y2 = GeoUtils.degreeToRad(point2.latitude);

        return EARTHRADIUS * Math.acos((Math.sin(y1) * Math.sin(y2) + Math.cos(y1) * Math.cos(y2) * Math.cos(x2 - x1)));    
    }
    

    return GeoUtils;
})();// 闭包结束

export default mapUtils;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值