V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nnegier
V2EX  ›  程序员

请问高德地图有没有可以判断某个经纬度坐标是否在指定的地理围栏内部的 API?

  •  
  •   nnegier · 2023-07-09 19:58:14 +08:00 · 2582 次点击
    这是一个创建于 377 天前的主题,其中的信息可能已经有所发展或是发生改变。

    找 API 找的太苦了~

    我的地理围栏就是一个经纬坐标点的方圆 500 米。然后需要判断给定的坐标是否在这个围栏内。

    这是高德地图开发相关文档(我没找到 o(╥﹏╥)o ):

    https://lbs.amap.com/api/android-location-sdk/guide/additional-func/local-geofence#s5

    https://lbs.amap.com/demo/sdk/location-geofence#android

    第 1 条附言  ·  2023-07-09 23:07:31 +08:00
    我表述有模糊,不好意思,我是想要找针对地理围栏的 API ,因为有些地理围栏是多边形的。我目前 Demo 确实是方圆 500 米,实际生产很有可能是要用到多边形地理围栏的
    23 条回复    2023-07-11 10:04:20 +08:00
    Endward
        1
    Endward  
       2023-07-09 20:14:19 +08:00
    你直接计算两个坐标点的距离是否大于 500 米不就好了
    shxlxa
        2
    shxlxa  
       2023-07-09 20:55:37 +08:00 via iPhone
    有的,做过这个功能,我明天找一下
    zu1y
        3
    zu1y  
       2023-07-09 22:03:32 +08:00
    直接算就好了呀,网上有详细的公式和代码的
    Melting
        4
    Melting  
       2023-07-09 22:07:20 +08:00
    https://lbs.amap.com/api/webservice/guide/api/geofence_service#t10
    查询设备与附近的围栏交互状态。例如是否在围栏中,是否进出围栏;若未在围栏中,返回最近围栏的信息等。

    有个 web 接口
    nnegier
        5
    nnegier  
    OP
       2023-07-09 23:05:21 +08:00
    @Endward
    @zu1y
    我还是想要更官方一点的针对地理围栏的方法,因为有些地理围栏是多边形的。纯计算距离这个可以 CoordinateConverter.calculateLineDistance
    liplushe
        6
    liplushe  
       2023-07-10 00:07:55 +08:00
    有很多算法都可以实现判断点是否在多边形内,射线交点法、顶点相交法、面积法等等,这些算法有很多公开代码,也不复杂。
    liplushe
        7
    liplushe  
       2023-07-10 00:10:03 +08:00
    需要注意的是,点的坐标分地理坐标系和投影坐标系,单位分别是度和米,计算的时候需要使用正确的坐标系统,这就涉及到了一点 GIS 知识了。
    Arita
        8
    Arita  
       2023-07-10 00:56:11 +08:00
    Turf.js 可以了解一下
    xuanbg
        9
    xuanbg  
       2023-07-10 07:45:52 +08:00
    redis 就有这个功能
    awinds
        10
    awinds  
       2023-07-10 08:24:49 +08:00
    自己用点在边形内算
    xaplux
        11
    xaplux  
       2023-07-10 08:24:52 +08:00
    sayonara7
        12
    sayonara7  
       2023-07-10 08:29:15 +08:00 via iPhone
    anguiao
        13
    anguiao  
       2023-07-10 08:59:56 +08:00   ❤️ 1
    AMap.GeometryUtil.isPointInRing ?不知道是不是你想要的。
    这个页面还有更多几何计算的方法,https://lbs.amap.com/api/javascript-api/reference/math
    然后如果已经有一个覆盖物了,也可以用 getBounds 或 getPath 之类的方法获取边界,然后再判断。
    aken29
        14
    aken29  
       2023-07-10 09:15:08 +08:00
    围栏功能内的 api 没有找到,地图功能的倒是有计算点是否在多边形内(换个思路),
    js 的 https://lbs.amap.com/demo/javascript-api/example/relationship-judgment/point-surface-relation
    android 的 https://lbs.amap.com/api/android-sdk/guide/computing-equipment/calcute-distance-tool 里面有说到“Android 地图 SDK 提供了很多计算方法,包括:计算两点距离、矩形面积、坐标转换、判断点是否圆或者多边形内等等,下面做简单介绍:”中 “判断点是否圆或者多边形内”,安卓应该也有相关 api ,但是我也没有找到🤣
    opengps
        15
    opengps  
       2023-07-10 09:19:53 +08:00
    我记得是有的
    sobev
        16
    sobev  
       2023-07-10 10:07:51 +08:00
    我记得 elasticsearch 是不是有这玩意
    TianQian
        17
    TianQian  
       2023-07-10 10:20:21 +08:00
    高德的矢量图形类基本都包含一个叫做 contains 的方法,用来判断点是否在图形内,不管是否为多边形
    https://lbs.amap.com/api/javascript-api-v2/documentation#polygon
    EspoirBao
        18
    EspoirBao  
       2023-07-10 11:01:57 +08:00
    function isCoordinateInsideFence(latitude1, longitude1, latitude2, longitude2) {
    const earthRadius = 6371000; // 地球半径,单位为米

    // 将经纬度转换为弧度
    const lat1Rad = toRadians(latitude1);
    const lon1Rad = toRadians(longitude1);
    const lat2Rad = toRadians(latitude2);
    const lon2Rad = toRadians(longitude2);

    // 计算两个坐标点之间的距离
    const distance = getDistance(lat1Rad, lon1Rad, lat2Rad, lon2Rad, earthRadius);

    // 判断距离是否小于等于 500 米
    return distance <= 500;
    }

    function toRadians(degrees) {
    return degrees * Math.PI / 180;
    }

    function getDistance(lat1, lon1, lat2, lon2, radius) {
    const dLat = lat2 - lat1;
    const dLon = lon2 - lon1;

    const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(lat1) * Math.cos(lat2) *
    Math.sin(dLon / 2) * Math.sin(dLon / 2);

    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    const distance = radius * c;
    return distance;
    }

    // 测试
    const fenceLatitude = 40.123456; // 围栏中心点的纬度
    const fenceLongitude = -74.123456; // 围栏中心点的经度
    const testLatitude = 40.123; // 测试点的纬度
    const testLongitude = -74.123; // 测试点的经度

    const isInside = isCoordinateInsideFence(
    fenceLatitude,
    fenceLongitude,
    testLatitude,
    testLongitude
    );

    console.log(isInside ? '坐标在围栏内' : '坐标不在围栏内');
    aken29
        19
    aken29  
       2023-07-10 11:44:48 +08:00
    @aken29
    根据 17 楼的提示,找到安卓的文档了,https://a.amap.com/lbs/static/unzip/Android_Map_Doc/index.html ,还是 contains 方法
    xiangyuecn
        20
    xiangyuecn  
       2023-07-10 12:14:14 +08:00
    射线法,不管什么奇形怪状都能计算是不是在内部

    服务器里面的话:
    - 可以用 RTree 对每条边进行索引,然后还是用射线法😂 性能:1 秒判断 10 万+ 个坐标点
    - Java:高性能的省市区坐标数据、边界数据查询工具,Java 开源程序、带 http 查询接口,内存占用低( 1 秒可查 1 万个以上坐标对应的城市信息): https://github.com/xiangyuecn/AreaCity-Query-Geometry

    客户端:依旧是射线法,自己手撸一下,百来行代码,性能一般😂
    sadyx
        21
    sadyx  
       2023-07-10 14:17:47 +08:00
    zibber
        22
    zibber  
       2023-07-10 19:03:29 +08:00
    redis geo
    zgh2hh
        23
    zgh2hh  
       2023-07-11 10:04:20 +08:00
    turfjs
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2370 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 12:17 · PVG 20:17 · LAX 05:17 · JFK 08:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.