前(fei)言(hua):
最近搞“考勤系统”其中有个“考勤打卡不能超过设置打卡地点多少m需求”,查询帖子,参照相关帖子,做个笔记,方便以后使用。
先上测试结果吧:
比网上多数看不懂的算法要准确一些,虽然依然跟百度地图上的测量结果稍有出入,不过已经足够应付一般的需求了~
思路:
1. 地球本身是个不规则的球体,这里将其看着一个规制球体
2. 半径取平均值:6371.393千米
3. 计算公式采用“球面距离公式”:S=R·arccos[cosβ1cosβ2cos(α1-α2)+sinβ1sinβ2]
4. 对公式的理解:设需要求距离的两点为A、B,球心为O。可以分解成3步:
① cosβ1cosβ2cos(α1-α2)+sinβ1sinβ2——求∠AOB的余弦值,这里是难点,得到这部分公式的推导过程比较复杂;
② arccos[∠AOB的余弦值]——求∠AOB的反余弦值,值域为[0,π],本质是 ∠AOB角度 / 180° * π;
③ R·∠AOB的反余弦值,等价于 R·∠AOB角度 / 180° * π,这里集合弧长公式很好理解
注意:
1. 经纬度,在本质上是角度
2. Java中的Math类提供的sin和con方法的参数是弧度,而不是角度
3. 公式里面的“arccos”是反余弦算法,在Math类中为acos()方法
package com.chinacoal.microservice.util.tool;
import java.awt.geom.Point2D;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @author sc
* @version V1.0
* @createTime 2020/6/26 17:21
* @description
*/
public class LocationUtils {
// 平均半径,单位:m
private static final double EARTH_RADIUS = 6371393;
/**
* 通过AB点经纬度获取距离 整数
* @param pointA A点(经,纬)
* @param pointB B点(经,纬)
* @return 距离(单位:米)