美文网首页
javascript下的地理围栏算法

javascript下的地理围栏算法

作者: alex很累 | 来源:发表于2022-06-08 22:59 被阅读0次

概述

最近遇到一个小问题:给定一个GPS坐标,判断是否在一个多边形区域内;查阅了一些资料,简单做一下记录。

算法(javascript)

ALon、ALat为需要判断的坐标点的经纬度,APoints为多边形顶点经纬度集合。

function isPtInPoly(ALon, ALat, APoints){
    var iSum = 0, iCount;
    var dLon1, dLon2, dLat1, dLat2, dLon;
    if (APoints.length < 3) {
        return false;
    }
    iCount = APoints.length;
    for (var i = 0; i < iCount; i++) {
        if (i == iCount - 1) {
            dLon1 = APoints[i].longitude;
            dLat1 = APoints[i].latitude;
            dLon2 = APoints[0].longitude;
            dLat2 = APoints[0].latitude;
        } else {
            dLon1 = APoints[i].longitude;
            dLat1 = APoints[i].latitude;
            dLon2 = APoints[i + 1].longitude;
            dLat2 = APoints[i + 1].latitude;
        }
        //以下语句判断A点是否在边的两端点的水平平行线之间,在则可能有交点,开始判断交点是否在左射线上
        if (((ALat >= dLat1) && (ALat < dLat2)) || ((ALat >= dLat2) && (ALat < dLat1))) {
            if (Math.abs(dLat1 - dLat2) > 0) {
                //得到 A点向左射线与边的交点的x坐标:
                dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - ALat)) / (dLat1 - dLat2);
                if (dLon < ALon)
                    iSum++;
            }
        }
    }
    if (iSum % 2 != 0) {
        return true
    }
    return false
}

验证

借用高德地图进行验证:

  1. 进入高德地图某示例页面
  2. 将以下的代码复制到右侧的源代码编辑器中;
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <style>
    html,
    body,
    #container {
      width: 100%;
      height: 100%;
    }
    </style>
    <title>多边形的绘制和编辑</title>
    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
    <script src="https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值&plugin=AMap.PolyEditor"></script>
    <script src="https://a.amap.com/jsapi_demos/static/demo-center/js/demoutils.js"></script>
</head>
<body>
<div id="container"></div>
<div class="input-card" style="width: 120px">
   <button class="btn" onclick="polyEditor.open()" style="margin-bottom: 5px">开始编辑</button> 
   <button class="btn" onclick="polyEditor.close()">结束编辑</button> 
</div>
<script type="text/javascript">  
    // 绘制地图
    var map = new AMap.Map("container", {
       center: [120.73462,31.264536],
       zoom: 16
    });
    // 多边形的几个顶点
    var APoints = [
        {'longitude': 120.7391550000, 'latitude': 31.2677060000},
        {'longitude': 120.7280560000, 'latitude': 31.2640830000},
        {'longitude': 120.7280270000, 'latitude': 31.2604840000},
        {'longitude': 120.7404800000, 'latitude': 31.2644850000}
    ]
    // 用多边形的几个顶点画多边形,数据和上面的那个是一样的
    var path = [
        [120.7391550000, 31.2677060000],
        [120.7280560000, 31.2640830000],
        [120.7280270000, 31.2604840000],
        [120.7404800000, 31.2644850000],
        [120.7391550000, 31.2677060000]
    ]
    var polyline = new AMap.Polyline({
        path: path,
        strokeColor: 'red'
    })
    map.add(polyline)
  
   // 设置点击事件,用于验证算法
    map.on('click', function(e) {
        alert(isPtInPoly(e.lnglat.getLng(),  e.lnglat.getLat(), APoints))
    });
  
    function isPtInPoly(ALon, ALat, APoints){
        var iSum = 0, iCount;
        var dLon1, dLon2, dLat1, dLat2, dLon;
        if (APoints.length < 3) {
            return false;
        }
        iCount = APoints.length;
        for (var i = 0; i < iCount; i++) {
            if (i == iCount - 1) {
                dLon1 = APoints[i].longitude;
                dLat1 = APoints[i].latitude;
                dLon2 = APoints[0].longitude;
                dLat2 = APoints[0].latitude;
            } else {
                dLon1 = APoints[i].longitude;
                dLat1 = APoints[i].latitude;
                dLon2 = APoints[i + 1].longitude;
                dLat2 = APoints[i + 1].latitude;
            }
            //以下语句判断A点是否在边的两端点的水平平行线之间,在则可能有交点,开始判断交点是否在左射线上
            if (((ALat >= dLat1) && (ALat < dLat2)) || ((ALat >= dLat2) && (ALat < dLat1))) {
                if (Math.abs(dLat1 - dLat2) > 0) {
                    //得到 A点向左射线与边的交点的x坐标:
                    dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - ALat)) / (dLat1 - dLat2);
                    if (dLon < ALon)
                        iSum++;
                }
            }
        }
        if (iSum % 2 != 0) {
            return true
        }
        return false
    }
</script>
</body>
</html>
  1. 然后,就可以在图上点击自由测试。


    测试1
    测试2

参考资料

  1. 如何判断一个指定的位置点坐标(GPS上的经纬度)是否落在一个多边形区域内?

相关文章

网友评论

      本文标题:javascript下的地理围栏算法

      本文链接:https://www.haomeiwen.com/subject/uvspmrtx.html