本文给出两种距离算法(Haversine formula;Vincenty formula)
1.Haversine formula
本计算式选取地球模型为球模型,以赤道半径为基准,故计算时纬度越高误差会越大,但胜在快速,具体推导公式可自行Google或参考美团技术文档(引:https://tech.meituan.com/lucene-distance.html)
package com.segment.position.calculate;
import com.segment.position.entity.Circle;
import com.segment.position.entity.Point;
import java.text.DecimalFormat;
/**
* Haversine计算式,速度快误差较小,球模型
*/
public class DistanceCalculate
{
private static final double EARTH_RADIUS = 6371e3;
//private static final Logger logger = LoggerFactory.getLogger(DistanceCalculate.class);
/**
* 根据提供的两点经纬度获取两点间距离
*
* @param lat_one
* @param lon_one
* @param lat_two
* @param lon_two
* @return 两点距离
*/
public static double getDistance(Double lat_one, Double lon_one, Double lat_two, Double lon_two)
{
double latOne = RadiansAngleCalculate.toRadians(lat_one);
double latTwo = RadiansAngleCalculate.toRadians(lat_two);
double latDiff = RadiansAngleCalculate.toRadians(lat_two - lat_one);
double lonDiff = RadiansAngleCalculate.toRadians(lon_two - lon_one);
double a = Math.sin(latDiff / 2) * Math.sin(latDiff / 2) + Math.cos(latOne) * Math.cos(latTwo) * Math.sin(lonDiff / 2) * Math.sin(lonDiff / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
DecimalFormat format = new DecimalFormat("0.00");
//logger.info("两点间距离:{" + format.format(EARTH_RADIUS * c) + "米}");
return Double.parseDouble(format.format(EARTH_RADIUS * c));
}
/**
* 计算两点间距离
*
* @param point_one
* @param point_two
* @return
*/
public static double getDistance(Point point_one, Point point_two)
{
//获取点内信息,计算两点距离
return getDistance(point_one.getLatitude(), point_one.getLongitude(), point_two.getLatitude(), point_two.getLongitude());
}
public static double getDistance(Circle circle, Point point)
{
//计算点到圆心的距离
double point_to_center = getDistance(circle.getCenter(), point);
//返回点距圆环的距离(圆内则为负,圆外则为正)
return point_to_center - circle.getRadius();
}
/**
* 根据提供的圆和点信息判断点是否在圆内
*
* @param circle
* @param point
* @return
*/
public static boolean isPointInCircle(Circle circle, Point point)
{
return getDistance(circle, point) < 0;
}
}
package com.segment.position.calculate;
public class RadiansAngleCalculate
{
/**
* 根据提供的角度值,将其转化为弧度
*
* @param angle 角度值
* @return 结果
*/
public static double toRadians(Double angle)
{
double result = 0L;
if (angle != null) {
result = angle * Math.PI / 180;
}
return result;
}
/**
* 根据提供的经纬度,转化为弧度
*
* @param latitude 纬度
* @param longitude 经度
* @return 结果集
*/
public static double[] latitudeLongitudeToRadians(Double latitude, Double longitude)
{
double[] result = new double[