天下之事,必先处之难,而后易之。

经纬度距离等相关计算的不同语言实现

因为最近在研究一款基于位置的附近应用,所以需要用到经纬度距离计算做排名因素。

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版的不知道放哪个站点上发布了,现在重新发布一个多语言版的。

posted @   boonya  阅读(14)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
历史上的今天:
2022-10-11 Android中软键盘常见的问题
我有佳人隔窗而居,今有伊人明月之畔。
轻歌柔情冰壶之浣,涓涓清流梦入云端。
美人如娇温雅悠婉,目遇赏阅适而自欣。
百草层叠疏而有致,此情此思怀彼佳人。
念所思之唯心叩之,踽踽彳亍寤寐思之。
行云如风逝而复归,佳人一去莫知可回?
深闺冷瘦独自徘徊,处处明灯影还如只。
推窗见月疑是归人,阑珊灯火托手思忖。
庐居闲客而好品茗,斟茶徐徐漫漫生烟。

我有佳人在水之畔,瓮载渔舟浣纱归还。
明月相照月色还低,浅近芦苇深深如钿。
庐山秋月如美人衣,画堂春阁香气靡靡。
秋意幽笃残粉摇曳,轻轻如诉画中蝴蝶。
泾水潺潺取尔浇园,暮色黄昏如沐佳人。
青丝撩弄长裙翩翩,彩蝶飞舞执子手腕。
香带丝缕缓缓在肩,柔美体肤寸寸爱怜。
如水之殇美玉成欢,我有佳人清新如兰。
伊人在水我在一边,远远相望不可亵玩。

点击右上角即可分享
微信分享提示