地理空间距离计算

1、球面半正矢公式

来源:维基百科 http://en.wikipedia.org/wiki/Haversine_formula

1.1、代码

public static double distHaversineRAD(double lat1, double lon1, double lat2, double lon2) {
        double hsinX = Math.sin((lon1 - lon2) * 0.5);
        double hsinY = Math.sin((lat1 - lat2) * 0.5);
        double h = hsinY * hsinY +
                (Math.cos(lat1) * Math.cos(lat2) * hsinX * hsinX);
        return 2 * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h)) * 6367000;
    }

1.2、优化

将经纬度坐标转三维坐标减少三角函数计算

经纬度坐标转三维直角坐标系坐标(将地球看成圆):

x = Math.cos(lat) Math.cos(lon);
y = Math.cos(lat) 
Math.sin(lon);
z = Math.sin(lat);

sinAOB≈AOB完全避免三角函数计算

2、其他计算方法

业务场景仅仅是在一个城市范围内进行距离计算,也就是说两个点之间的距离一般不会超过200多千米。由于范围小,可以认为经线和纬线是垂直的。由勾股定理,点间距离可由两点水平距离和垂直距离得到

2.1 代码

public static double distanceSimplify(double lat1, double lng1, double lat2, double lng2, double[] a) {
     double dx = lng1 - lng2; // 经度差值
     double dy = lat1 - lat2; // 纬度差值
     double b = (lat1 + lat2) / 2.0; // 平均纬度
     double Lx = toRadians(dx) * 6367000.0* Math.cos(toRadians(b)); // 东西距离
     double Ly = 6367000.0 * toRadians(dy); // 南北距离
     return Math.sqrt(Lx * Lx + Ly * Ly);  // 用平面的矩形对角距离公式计算总距离
    }
}

2.2 优化

采用多项式来拟合cos三角函数来去掉上面的三角函数cos。

使用org.apache.commons.math3这一数学工具包来进行拟合。中国的纬度范围在10~60之间,即我们将此区间离散成Length份作为我们的训练集。

public static double[] trainPolyFit(int degree, int Length){
    PolynomialCurveFitter polynomialCurveFitter = PolynomialCurveFitter.create(degree);
    double minLat = 10.0; //中国最低纬度
    double maxLat = 60.0; //中国最高纬度
    double interv = (maxLat - minLat) / (double)Length;
    List<WeightedObservedPoint> weightedObservedPoints = new ArrayList<WeightedObservedPoint>();
    for(int i = 0; i < Length; i++) {
        WeightedObservedPoint weightedObservedPoint = new WeightedObservedPoint(1,  minLat + (double)i*interv, Math.cos(toRadians(x[i])));
        weightedObservedPoints.add(weightedObservedPoint); 
    }
    return polynomialCurveFitter.fit(weightedObservedPoints);
}


public static double distanceSimplifyMore(double lat1, double lng1, double lat2, double lng2, double[] a) {
     //1) 计算三个参数
     double dx = lng1 - lng2; // 经度差值
     double dy = lat1 - lat2; // 纬度差值
     double b = (lat1 + lat2) / 2.0; // 平均纬度
     //2) 计算东西方向距离和南北方向距离(单位:米),东西距离采用三阶多项式
     double Lx = (a[3] * b*b*b  + a[2]* b*b  +a[1] * b + a[0] ) * toRadians(dx) * 6367000.0; // 东西距离
     double Ly = 6367000.0 * toRadians(dy); // 南北距离
     //3) 用平面的矩形对角距离公式计算总距离
     return Math.sqrt(Lx * Lx + Ly * Ly);
}
View Code

3、参考资料

1、维基百科 球面距离公式

2、美团点评技术团队 地理空间距离计算优化

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL支持地理空间信息的存储和查询。你可以使用MySQL的地理空间展来处理地理空间数据类型,点、线、多边形等。 要使用理空间功能,你需要确保你的版本支持地理空间扩展。在装MySQL时,需要选择启用地理空间支持,或者在已安装的MySQL上启用地理空间插件。 一旦你的MySQL服务器支持地理空间扩展,你可以创建具有地理空间属性的表,并将地理空间数据存储在其中。下面是一个创建包含地理空间列的表的示例: ```sql CREATE TABLE locations ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), location GEOMETRY ); ``` 在这个例子中,`location`列被定义为`GEOMETRY`类型,用于存储地理空间数据。 要查询地理空间数据,你可以使用一些MySQL提供的函数和操作符。例如,你可以使用 `ST_DISTANCE()` 函数计算两个点之间的距离,使用 `ST_CONTAINS()` 函数判断一个点是否在一个多边形内等等。 以下是一个简单的查询示例,找出距离给定坐标最近的位置: ```sql SELECT id, name, ST_DISTANCE(location, POINT(40.7128, -74.0060)) AS distance FROM locations ORDER BY distance LIMIT 1; ``` 这个查询将返回距离给定坐标(纬度40.7128,经度-74.0060)最近的位置的id、名称和距离。 这只是地理空间功能的简单介绍,MySQL提供了更多的函数和操作符来处理地理空间数据。你可以查阅MySQL官方文档以获得更详细的信息和示例。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值