经纬度距离等相关计算的不同语言实现
因为最近在研究一款基于位置的附近应用,所以需要用到经纬度距离计算做排名因素。
1.根据经纬度、半径计算距离 最大最小经纬度
public class LatLonUtil {
private static final double PI = 3.14159265; // 圆周率
private static final double EARTH_RADIUS = 6378137;
private static final double RAD = Math.PI / 180.0;
// @see
// The circumference of the earth is 24,901 miles.
// 24,901/360 = 69.17 miles / degree
/**
* @param raidus
* 单位:米 return minLat,minLng,maxLat,maxLng
*/
public static double[] getAround(double lat, double lon, int raidus) {
Double latitude = lat;
Double longitude = lon;
Double degree = (24901 * 1609) / 360.0;
double raidusMile = raidus;
Double dpmLat = 1 / degree;
Double radiusLat = dpmLat * raidusMile;
Double minLat = latitude - radiusLat;
Double maxLat = latitude + radiusLat;
Double mpdLng = degree * Math.cos(latitude * (PI / 180));
Double dpmLng = 1 / mpdLng;
Double radiusLng = dpmLng * raidusMile;
Double minLng = longitude - radiusLng;
Double maxLng = longitude + radiusLng;
// System.out.println("["+minLat+","+minLng+","+maxLat+","+maxLng+"]");
return new double[] { minLat, minLng, maxLat, maxLng };
}
/**
* 根据两点间经纬度坐标(double值),计算两点间距离,单位为米
* @param lng1
* @param lat1
* @param lng2
* @param lat2
* @return
*/
public static double getDistance(double lng1, double lat1, double lng2,
double lat2) {
double radLat1 = lat1 * RAD;
double radLat2 = lat2 * RAD;
double a = radLat1 - radLat2;
double b = (lng1 - lng2) * RAD;
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 main(String[] args) {
Double lat1 = 34.264648;
Double lon1 = 108.952736;
int radius = 1000;
// [34.25566276027792,108.94186385411045,34.27363323972208,108.96360814588955]
getAround(lat1, lon1, radius);
// 911717.0 34.264648,108.952736,39.904549,116.407288
double dis = getDistance(108.952736, 34.264648, 116.407288, 39.904549);
System.out.println(dis);
}
}
2.两个经纬度点之间的距离
PHP:
<?php
define('EARTH_RADIUS', 6378.137);//地球半径,假设地球是规则的球体
define('PI', 3.1415926);
/**
* 计算两组经纬度坐标 之间的距离
* params :lat1 纬度1; lng1 经度1; lat2 纬度2; lng2 经度2; len_type (1:m or 2:km);
* return m or km
*/
function GetDistance($lat1, $lng1, $lat2, $lng2, $len_type = 1, $decimal = 2)
{
$radLat1 = $lat1 * PI ()/ 180.0; //PI()圆周率
$radLat2 = $lat2 * PI() / 180.0;
$a = $radLat1 - $radLat2;
$b = ($lng1 * PI() / 180.0) - ($lng2 * PI() / 180.0);
$s = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
$s = $s * EARTH_RADIUS;
$s = round($s * 1000);
if ($len_type --> 1)
{
$s /= 1000;
}
return round($s, $decimal);
}
echo GetDistance(38.0822841,114.4774532,38.0882967,114.4776678, 1);//输出距离/米
?>
Java:
/**
* 计算地球上任意两点(经纬度)距离
*
* @param long1
* 第一点经度
* @param lat1
* 第一点纬度
* @param long2
* 第二点经度
* @param lat2
* 第二点纬度
* @return 返回距离 单位:米
*/
public static double Distance(double long1, double lat1, double long2,
double lat2) {
double a, b, R;
R = 6378137; // 地球半径
lat1 = lat1 * Math.PI / 180.0;
lat2 = lat2 * Math.PI / 180.0;
a = lat1 - lat2;
b = (long1 - long2) * Math.PI / 180.0;
double d;
double sa2, sb2;
sa2 = Math.sin(a / 2.0);
sb2 = Math.sin(b / 2.0);
d = 2
* R
* Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1)
* Math.cos(lat2) * sb2 * sb2));
return d;
}
Sql Server:
CREATE FUNCTION [f_GetDistance]
(
@GPSLng DECIMAL(12,6),
@GPSLat DECIMAL(12,6),
@Lng DECIMAL(12,6),
@Lat DECIMAL(12,6)
)
RETURNS DECIMAL(12,4)
AS
BEGIN
DECLARE @result DECIMAL(12,4)
SELECT @result = 6378137.0*ACOS(SIN(@GPSLat/180*PI())*SIN(@Lat/180*PI())+COS(@GPSLat/180*PI())*COS(@Lat/180*PI())*COS((@GPSLng-@Lng)/180*PI()))
RETURN @result
END
GO
JS:
function toRad(d) { return d * Math.PI / 180; }
function calculateDistance(lngSrc, latSrc, lngDst, latDst) {
EARTH_RADIUS = 6378137;
//alert(lngSrc+" "+latSrc+" "+lngDst+" "+latDst)
radLngSrc = toRad(lngSrc);
radLngDst = toRad(lngDst);
lngDiff = radLngSrc - radLngDst;
radLatSrc = toRad(latSrc);
radLatDst = toRad(latDst);
latDiff = radLatSrc - radLatDst;
s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(latDiff/2), 2) +
Math.cos(radLatSrc) * Math.cos(radLatDst) * Math.pow(Math.sin(lngDiff/2),2)));
s = s * EARTH_RADIUS;
return Math.round(s);
}
function getDistanceText(distance) {
distanceText = "";
if (distance <= 100)
{
//53 0.053km 53m <100m
distanceText = "<100m";
}
else if (distance < 1000)
{
//532 0.532km 532m
distanceText = distance + "m";
}
else if (distance < 10000) {
//1532 1.532km
distance = distance/1000;
distanceText = distance.toString().substr(0, distance.toString().indexOf('\.')+2)+"km";
} else if (distance < 100000)
{
//11532 11.532km
distance = distance/1000;
distanceText = distance.toString().substr(0, distance.toString().indexOf('\.')+2)+"km";
}
else {
//111532 111.532km >100km
distanceText = ">100km";
}
return distanceText;
}
3.地图工具
package utils;
import java.text.DecimalFormat;
/**
* 地图工具
* @author lwg 2015-11-05
*
*/
public class MapUtil {
/**
* 返回**.**KM
* @param lon1 第一点经度
* @param lat1 第一点纬度
* @param lon2 第二点经度
* @param lat2 第二点纬度
* @return
*/
public static String getStrDistance(String lon1, String lat1, String lon2, String lat2) {
return getStrDistance(MapUtil.Distance(lon1, lat1, lon2, lat2));
}
/**
* 返回**.**KM
* @param distance 距离
* @return
*/
public static String getStrDistance(double distance) {
if(distance<100){
return "0.01KM";
}
DecimalFormat df=new DecimalFormat("#.##");
return df.format(distance/1000d)+"KM";
}
/**
* 计算地球上任意两点(经纬度)距离
* @param coordinate1 第一点(经度lng,纬度lat)
* @param coordinate2 第二点(经度lng,纬度lat)
* @return
*/
public static double Distance(String coordinate1, String coordinate2) {
String log_lat1[] = coordinate1.split(",");
String gg_lon1 = log_lat1[0];
String gg_lat1 = log_lat1[1];
String log_lat2[] = coordinate2.split(",");
String gg_lon2 = log_lat2[0];
String gg_lat2 = log_lat2[1];
return Distance(gg_lon1, gg_lat1, gg_lon2, gg_lat2);
}
/**
* 计算地球上任意两点(经纬度)距离
* @param lng1 第一点经度
* @param lat1 第一点纬度
* @param lng2 第二点经度
* @param lat2 第二点纬度
* @return
*/
public static double Distance(String lon1, String lat1, String lon2, String lat2) {
return Distance(Double.parseDouble(lon1), Double.parseDouble(lat1), Double.parseDouble(lon2), Double.parseDouble(lat2));
}
/**
* 计算地球上任意两点(经纬度)距离
*
* @param long1 第一点经度
* @param lat1 第一点纬度
* @param long2 第二点经度
* @param lat2 第二点纬度
* @return 返回距离 单位:米
*/
public static double Distance(double long1, double lat1, double long2, double lat2) {
double a, b, R;
R = 6378137; // 地球半径
lat1 = lat1 * Math.PI / 180.0;
lat2 = lat2 * Math.PI / 180.0;
a = lat1 - lat2;
b = (long1 - long2) * Math.PI / 180.0;
double d;
double sa2, sb2;
sa2 = Math.sin(a / 2.0);
sb2 = Math.sin(b / 2.0);
d = 2 * R * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math.cos(lat2) * sb2 * sb2));
return d;
}
public static void main(String[] args) {
System.out.println("正确:"+Distance("121.41128,31.170049", "121.411693,31.169045"));
System.out.println("错误:"+Distance("31.170049,121.41128", "31.169045,121.411693"));
System.out.println(getStrDistance(987654321));
}
}
有些是借鉴PHP和Java的实现,之前我曾经写过Java版的不知道放哪个站点上发布了,现在重新发布一个多语言版的。
纸上得来终觉浅,绝知此事要躬行。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
2022-10-11 Android中软键盘常见的问题