根据经纬度计算指定范围内或者附近的人(java)

根据经纬度计算指定范围内或者附近的人(java)

前言

最近项目中有一个需求,就是在地图中随便标一个点位,然后根据这个点位显示出附近所选范围内的人员。这里说一下人员的经纬度是app实时上传更新的。说白了就是要根据指定的坐标计算所选半径内的在线人员。

实现

思路:
这个大概有两种方式,各位大佬要是有好的建议还请分享一下。
1、在sql中直接计算出所选经纬度和当前在线的人员的实时经纬度之间的距离,然后再用sql过滤一下这些距离在不在所选的距离范围之内就可以了。比如说:你所选的经纬度为A,人员的经纬度为B,你所选的范围为C,那么就可以这么来理解,先计算出A和B之间的距离,然后比较A和B之间的距离是否小于等于C,如果小于等于C那么B就在A的所选范围内。
2、使用java代码计算出距离然后进行比较。大概思路都一样,就看是用sql计算距离,还是用java代码计算距离。
代码
方式一:
sql:

SELECT
	userid,
	gps,
	times,
	( 
    6371000.393 * acos (
      cos ( radians(34.246876) ) 
      * cos( radians( SUBSTRING_INDEX(gps,',',-1) ) ) 
      * cos( radians( SUBSTRING_INDEX(gps,',',1) )<
计算六边形的经纬度信息可以使用以下公式: 1. 六边形的中心点坐标 (lat, lng): ``` lat = (maxLat + minLat) / 2 lng = (maxLng + minLng) / 2 ``` 2. 六边形的边长 R: ``` R = earthRadius * Math.sqrt(3) / 2 ``` 其中,`earthRadius` 是地球半径,可以取 `6371` 公里。 3. 六边形的顶点坐标 (lat_i, lng_i): ``` lat_i = lat + R * Math.cos(i * 60 * Math.PI / 180) lng_i = lng + R * Math.sin(i * 60 * Math.PI / 180) / Math.cos(lat * Math.PI / 180) ``` 其中,`i` 取值为 `0` 到 `5`,分别对应六边形的六个顶点。 过滤指定覆盖范围内的六边形可以按照以下步骤进行: 1. 计算覆盖范围的边界经纬度信息(最大经度、最小经度、最大纬度、最小纬度)。 2. 根据边界经纬度信息,计算覆盖范围的中心点坐标半径。 3. 对于每个六边形,判断其是否在覆盖范围内。具体方法是,计算六边形中心点与覆盖范围中心点的距离,若距离小于等于覆盖范围半径,则该六边形在覆盖范围内。 完整代码示例: ```java // 计算六边形的经纬度信息 public static double[][] getHexagonLatLng(double lat, double lng, double radius) { double[][] points = new double[6][2]; double R = radius * Math.sqrt(3) / 2; for (int i = 0; i < 6; i++) { double lat_i = lat + R * Math.cos(i * 60 * Math.PI / 180); double lng_i = lng + R * Math.sin(i * 60 * Math.PI / 180) / Math.cos(lat * Math.PI / 180); points[i] = new double[]{lat_i, lng_i}; } return points; } // 过滤指定覆盖范围内的六边形 public static List<double[][]> filterHexagonsByBound(double maxLat, double minLat, double maxLng, double minLng, double radius) { List<double[][]> result = new ArrayList<>(); double lat = (maxLat + minLat) / 2; double lng = (maxLng + minLng) / 2; double R = radius * Math.sqrt(3) / 2; double dLat = (maxLat - minLat) / 2; double dLng = (maxLng - minLng) / 2; double distance = Math.sqrt(dLat * dLat + dLng * dLng); double coverRadius = Math.sqrt(distance * distance + R * R); for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { double lat_i = lat + i * distance; double lng_i = lng + j * distance / Math.cos(lat * Math.PI / 180); double d = getDistance(lat, lng, lat_i, lng_i); if (d <= coverRadius) { result.add(getHexagonLatLng(lat_i, lng_i, radius)); } } } return result; } // 计算两点之间的距离 public static double getDistance(double lat1, double lng1, double lat2, double lng2) { double radLat1 = lat1 * Math.PI / 180; double radLat2 = lat2 * Math.PI / 180; double a = radLat1 - radLat2; double b = lng1 * Math.PI / 180 - lng2 * Math.PI / 180; double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); s = s * 6378.137;// EARTH_RADIUS; s = Math.round(s * 10000) / 10000; return s; } ``` 其中,`getHexagonLatLng` 方法用于计算六边形的经纬度信息,`filterHexagonsByBound` 方法用于过滤指定覆盖范围内的六边形,`getDistance` 方法用于计算两点之间的距离。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值