Java、SQLServer 根據經緯度計算距離
阿新 • • 發佈:2019-02-19
Java
public class DistanceUtils {
//經度校驗正則表示式
private static final String longitudePattern= "^[\\-\\+]?0(\\.\\d{0,7}){0,1}|(0?\\d{1,2}\\.\\d{0,7}|1[0-7]?\\d\\.\\d{0,7}|180\\.0{0,7})$";
//緯度校驗正則表示式
private static final String latitudePattern = "^[\\-\\+]?0(\\.\\d{0,7}){0,1}|([0-8]?\\d{1}\\.\\d{0,7}|90\\.0{0,7})$" ;
//地球半徑
private static final double EARTH_RADIUS = 6378137;
//計算弧度
private static double rad(double d) {
return d * Math.PI / 180.0;
}
//計算兩個經緯度間的距離
public static double calculateDistance(double lat1, double lng1, double lat2, double lng2) {
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
double a = radLat1 - radLat2;
double b = rad(lng1) - rad(lng2);
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 * EARTH_RADIUS;
s = Math.round(s * 10000 ) / 10000;
return s;
}
//計算兩個經緯度間的距離
public static double calculateDistance(Point point1, Point point2) {
double radLat1 = rad(point1.getLatitude());
double radLat2 = rad(point2.getLatitude());
double a = radLat1 - radLat2;
double b = rad(point1.getLongitude()) - rad(point2.getLongitude());
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 * EARTH_RADIUS;
s = Math.round(s * 10000) / 10000;
return s;
}
//校驗經緯度
public static void valid(String latitude, String longitude) {
if (Strings.isNullOrEmpty(latitude) || Strings.isNullOrEmpty(longitude)) {
throw new Exception("經緯度不能為空");
}
if (!longitude.matches(longitudePattern)) {
throw new Exception("緯度不合法");
}
if (!latitude.matches(latitudePattern)) {
throw new Exception("經度不合法");
}
}
//用於封裝經緯度
public static class Point {
private double latitude;
private double longitude;
private Point(String latitude, String longitude) {
this.latitude = Double.valueOf(latitude);
this.longitude = Double.valueOf(longitude);
}
private Point(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
public static Point build(String latitude, String longitude) {
return new Point(latitude, longitude);
}
public static Point build(double latitude, double longitude) {
return new Point(latitude, longitude);
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
@Override
public String toString() {
return "latitude is -->"+latitude +" longitude is -->"+longitude;
}
}
}
SQLServer
CREATE FUNCTION [dbo].[fnGetDistance](@LatBegin REAL, @LngBegin REAL, @LatEnd REAL, @LngEnd REAL) RETURNS FLOAT
AS
BEGIN
--距離(千米)
DECLARE @Distance REAL
DECLARE @EARTH_RADIUS REAL
SET @EARTH_RADIUS = 6378.137
DECLARE @RadLatBegin REAL,@RadLatEnd REAL,@RadLatDiff REAL,@RadLngDiff REAL
SET @RadLatBegin = @LatBegin *PI()/180.0
SET @RadLatEnd = @LatEnd *PI()/180.0
SET @RadLatDiff = @RadLatBegin - @RadLatEnd
SET @RadLngDiff = @LngBegin *PI()/180.0 - @LngEnd *PI()/180.0
SET @Distance = 2 *ASIN(SQRT(POWER(SIN(@RadLatDiff/2), 2)+COS(@RadLatBegin)*COS(@RadLatEnd)*POWER(SIN(@RadLngDiff/2), 2)))
SET @Distance = @Distance * @EARTH_RADIUS
--SET @Distance = Round(@Distance * 10000) / 10000
RETURN @Distance
END
使用方法
dbo.fnGetDistance(%s,%s,latitude,longitude) as distance
替換佔位符,第一個引數是緯度、第二個引數是經度