Java 使用纬度经度计算两点之间的距离?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3694380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calculating distance between two points, using latitude longitude?
提问by m4design
Here's my try, it's just a snippet of my code:
这是我的尝试,它只是我的代码片段:
final double RADIUS = 6371.01;
double temp = Math.cos(Math.toRadians(latA))
* Math.cos(Math.toRadians(latB))
* Math.cos(Math.toRadians((latB) - (latA)))
+ Math.sin(Math.toRadians(latA))
* Math.sin(Math.toRadians(latB));
return temp * RADIUS * Math.PI / 180;
I am using this formulae to get the latitude and longitude:
我使用这个公式来获取纬度和经度:
x = Deg + (Min + Sec / 60) / 60)
采纳答案by David George
The Java code given by Dommer above gives slightly incorrect results but the small errors add up if you are processing say a GPS track. Here is an implementation of the Haversine method in Java which also takes into account height differences between two points.
上面 Dommer 给出的 Java 代码给出了稍微不正确的结果,但是如果你正在处理一个 GPS 轨迹,这些小错误就会累积起来。这是Java中Haversine方法的实现,它也考虑了两点之间的高度差异。
/**
* Calculate distance between two points in latitude and longitude taking
* into account height difference. If you are not interested in height
* difference pass 0.0. Uses Haversine method as its base.
*
* lat1, lon1 Start point lat2, lon2 End point el1 Start altitude in meters
* el2 End altitude in meters
* @returns Distance in Meters
*/
public static double distance(double lat1, double lat2, double lon1,
double lon2, double el1, double el2) {
final int R = 6371; // Radius of the earth
double latDistance = Math.toRadians(lat2 - lat1);
double lonDistance = Math.toRadians(lon2 - lon1);
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
+ Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
* Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double distance = R * c * 1000; // convert to meters
double height = el1 - el2;
distance = Math.pow(distance, 2) + Math.pow(height, 2);
return Math.sqrt(distance);
}
回答by dommer
Here's a Java function that calculates the distance between two lat/long points.
这是一个计算两个纬度/经度点之间距离的Java 函数。
Edit
编辑
I found another reference to the code.
我找到了另一个对代码的引用。
And, posted below, just in case it disappears again.
并且,张贴在下面,以防万一它再次消失。
private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == 'K') {
dist = dist * 1.609344;
} else if (unit == 'N') {
dist = dist * 0.8684;
}
return (dist);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts decimal degrees to radians :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:: This function converts radians to decimal degrees :*/
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'M') + " Miles\n");
System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'K') + " Kilometers\n");
System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'N') + " Nautical Miles\n");
回答by Chris Taylor
Here is a page with javascript examples for various spherical calculations. The very first one on the page should give you what you need.
这是一个页面,其中包含用于各种球面计算的 javascript 示例。页面上的第一个应该给你你需要的东西。
http://www.movable-type.co.uk/scripts/latlong.html
http://www.movable-type.co.uk/scripts/latlong.html
Here is the Javascript code
这是Javascript代码
var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
Where 'd' will hold the distance.
'd' 将保持距离。
回答by zellus
回答by zahmde
Note: this solution only works for short distances.
注意:此解决方案仅适用于短距离。
I tried to use dommer's posted formula for an application and found it did well for long distances but in my data I was using all very short distances, and dommer's post did very poorly. I needed speed, and the more complex geo calcs worked well but were too slow. So, in the case that you need speed and all the calculations you're making are short (maybe < 100m or so). I found this little approximation to work great. it assumes the world is flat mind you, so don't use it for long distances, it works by approximating the distance of a single Latitude and Longitude at the given Latitude and returning the Pythagorean distance in meters.
我尝试在应用程序中使用 dommer 的张贴公式,发现它在长距离上表现良好,但在我的数据中,我使用了所有非常短的距离,而 dommer 的张贴效果很差。我需要速度,更复杂的地理计算效果很好,但速度太慢。因此,如果您需要速度并且您所做的所有计算都很短(可能 < 100m 左右)。我发现这个小近似效果很好。它假设世界是平坦的,所以不要长距离使用它,它的工作原理是在给定的纬度上近似单个纬度和经度的距离并返回以米为单位的毕达哥拉斯距离。
public class FlatEarthDist {
//returns distance in meters
public static double distance(double lat1, double lng1,
double lat2, double lng2){
double a = (lat1-lat2)*FlatEarthDist.distPerLat(lat1);
double b = (lng1-lng2)*FlatEarthDist.distPerLng(lat1);
return Math.sqrt(a*a+b*b);
}
private static double distPerLng(double lat){
return 0.0003121092*Math.pow(lat, 4)
+0.0101182384*Math.pow(lat, 3)
-17.2385140059*lat*lat
+5.5485277537*lat+111301.967182595;
}
private static double distPerLat(double lat){
return -0.000000487305676*Math.pow(lat, 4)
-0.0033668574*Math.pow(lat, 3)
+0.4601181791*lat*lat
-1.4558127346*lat+110579.25662316;
}
}
回答by MAnoj Sarnaik
package distanceAlgorithm;
public class CalDistance {
public static void main(String[] args) {
// TODO Auto-generated method stub
CalDistance obj=new CalDistance();
/*obj.distance(38.898556, -77.037852, 38.897147, -77.043934);*/
System.out.println(obj.distance(38.898556, -77.037852, 38.897147, -77.043934, "M") + " Miles\n");
System.out.println(obj.distance(38.898556, -77.037852, 38.897147, -77.043934, "K") + " Kilometers\n");
System.out.println(obj.distance(32.9697, -96.80322, 29.46786, -98.53506, "N") + " Nautical Miles\n");
}
public double distance(double lat1, double lon1, double lat2, double lon2, String sr) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (sr.equals("K")) {
dist = dist * 1.609344;
} else if (sr.equals("N")) {
dist = dist * 0.8684;
}
return (dist);
}
public double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
public double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
}
回答by granadaCoder
Future readers who stumble upon this SOF article.
偶然发现这篇 SOF 文章的未来读者。
Obviously, the question was asked in 2010 and its now 2019. But it comes up early in an internet search. The original question does not discount use of third-party-library (when I wrote this answer).
显然,这个问题是在 2010 年提出的,现在是 2019 年。但它在互联网搜索中很早就出现了。原始问题不打折第三方库的使用(当我写这个答案时)。
public double calculateDistanceInMeters(double lat1, double long1, double lat2,
double long2) {
double dist = org.apache.lucene.util.SloppyMath.haversinMeters(lat1, long1, lat2, long2);
return dist;
}
and
和
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-spatial</artifactId>
<version>8.2.0</version>
</dependency>
https://mvnrepository.com/artifact/org.apache.lucene/lucene-spatial/8.2.0
https://mvnrepository.com/artifact/org.apache.lucene/lucene-spatial/8.2.0
Please read documentation about "SloppyMath" before diving in!
请在开始之前阅读有关“SloppyMath”的文档!
https://lucene.apache.org/core/8_2_0/core/org/apache/lucene/util/SloppyMath.html
https://lucene.apache.org/core/8_2_0/core/org/apache/lucene/util/SloppyMath.html
回答by Stan Sokolov
was a lot of great answers provided however I found some performance shortcomings, so let me offer a version with performance in mind. Every constant is precalculated and x,y variables are introduced to avoid calculating the same value twice. Hope it helps
提供了很多很棒的答案,但是我发现了一些性能缺陷,所以让我提供一个考虑到性能的版本。每个常数都是预先计算好的,并且引入了 x,y 变量以避免两次计算相同的值。希望能帮助到你
private static final double r2d = 180.0D / 3.141592653589793D;
private static final double d2r = 3.141592653589793D / 180.0D;
private static final double d2km = 111189.57696D * r2d;
public static double meters(double lt1, double ln1, double lt2, double ln2) {
final double x = lt1 * d2r;
final double y = lt2 * d2r;
return Math.acos( Math.sin(x) * Math.sin(y) + Math.cos(x) * Math.cos(y) * Math.cos(d2r * (ln1 - ln2))) * d2km;
}