计算两点间的距离(java、mysql),根据点计算热力图密度

需求:将点数据封装成mapbox需要的热力图格式返回。
数据格式中需要计算每个点单位范围内的密度,最后想到的思路是每个点都跟其他点计算距离,取半径范围内点的数量作为密度。

确定思路:
1、根据经纬度计算两点的距离,设置半径,计算距离小于此半径的点数量
2、 根据两点经纬度计算距离
3、mysql st_distance()函数

计算地图上两点间的距离

首先看一下大佬的基础理论:https://www.cnblogs.com/ycsfwhh/archive/2010/12/20/1911232.html
得到如下的计算公式

C = sin(MLatA)*sin(MLatB)*cos(MLonA-MLonB) + cos(MLatA)cos(MLatB)
Distance = R
Arccos©*Pi/180

1、Java代码实现
public final class DistanceUtils {
 
    /**
     * 地球半径,单位 km
     */
    private static final double EARTH_RADIUS = 6378.137;
 
    /**
     * 根据经纬度,计算两点间的距离
     *
     * @param longitude1 第一个点的经度
     * @param latitude1  第一个点的纬度
     * @param longitude2 第二个点的经度
     * @param latitude2  第二个点的纬度
     * @return 返回距离 单位千米
     */
    public static double getDistance(double longitude1, double latitude1, double longitude2, double latitude2) {
        // 纬度
        double lat1 = Math.toRadians(latitude1);
        double lat2 = Math.toRadians(latitude2);
        // 经度
        double lng1 = Math.toRadians(longitude1);
        double lng2 = Math.toRadians(longitude2);
        // 纬度之差
        double a = lat1 - lat2;
        // 经度之差
        double b = lng1 - lng2;
        // 计算两点距离的公式
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
                Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2)));
        // 弧长乘地球半径, 返回单位: 千米
        s =  s * EARTH_RADIUS;
        return s;
    }
 
    public static void main(String[] args) {
        double d = getDistance(116.308479, 39.983171, 116.353454, 39.996059);
        System.out.println(d);
    }
}
2、sql实现
/*传入的参数为:纬度 40.0497810000 经度 116.3424590000 经度 ASC升序由近至远 DESC 降序 由远到近 */
SELECT
    *,
    ROUND(
        6378.138 * 2 * ASIN(
            SQRT(
                POW(
                    SIN(
                        (
                            40.0497810000 * PI() / 180 - lat * PI() / 180
                        ) / 2
                    ),
                    2
                ) + COS(40.0497810000 * PI() / 180) * COS(lat * PI() / 180) * POW(
                    SIN(
                        (
                            116.3424590000 * PI() / 180 - lon * PI() / 180
                        ) / 2
                    ),
                    2
                )
            )
        ) * 1000
    ) AS juli
FROM
    customer
ORDER BY
    juli ASC
3、mysql st_distance()函数

st_distance(point(a.longitude,a.latitude),point(b.longitude,b.latitude)) * 111195

最后选择方法3进行热力图计算

表自关联后与每个点匹配,#{dis}为传入半径

select name,mmsi,count(0) as count,lon,lat 
from (
  select a.`name`,a.mmsi,
  (st_distance(point(a.longitude,a.latitude),point(b.longitude,b.latitude)) * 111195) as distance,
  a.longitude as lon,a.latitude as lat
  from (select * from table where create_date = (select create_date from table GROUP BY create_date order by create_date desc limit 1)) a
  inner join (select * from table where create_date = (select create_date from table GROUP BY create_date order by create_date desc limit 1)) b
) c
where distance < #{dis}
group by mmsi;

猜你喜欢

转载自blog.csdn.net/qq_16253859/article/details/122288750
今日推荐