Вычислить расстояние между двумя точками, используя широту и долготу?
Вот моя попытка, это просто фрагмент моего кода:
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;
Я использую эту формулу, чтобы получить широту и долготу:
x = Deg + (Min + Sec / 60) / 60)
Ответы
Ответ 1
Код Java, приведенный выше в Dommer, дает немного неправильные результаты, но небольшие ошибки складываются, если вы обрабатываете, скажем, GPS-трек. Вот реализация метода Haversine в Java, который также учитывает разницу высот между двумя точками.
/**
* 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);
}
Ответ 2
Здесь Java-функция, которая вычисляет расстояние между двумя точками lat/long.
Edit
Я нашел другую ссылку на код.
И, вывешивается ниже, на случай, если он снова исчезнет.
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");
Ответ 3
Примечание: это решение работает только на короткие расстояния.
Я попытался использовать формулу dommer для приложения и нашел, что это хорошо работает на большие расстояния, но в моих данных я использовал все очень короткие расстояния, а почта dommer делала очень плохо. Мне нужна была скорость, и более сложные гео-калькулы работали хорошо, но были слишком медленными. Таким образом, в случае, если вам нужна скорость, и все вычисления, которые вы делаете, коротки (возможно, менее 100 м или около того). Я нашел, что это небольшое приближение отлично работает. он предполагает, что мир плоский, вы не используете его, поэтому не используйте его на больших расстояниях, он работает, приближая расстояние до одной широты и долготы в заданной широте и возвращая расстояние Пифагора в метрах.
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;
}
}
Ответ 4
Вот страница с примерами javascript для различных сферических вычислений. Самый первый на странице должен предоставить вам то, что вам нужно.
http://www.movable-type.co.uk/scripts/latlong.html
Вот код 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;
Где 'd' будет удерживать расстояние.
Ответ 5
Будущие читатели, которые наткнулись на эту статью SOF.
Очевидно, этот вопрос был задан в 2010 году, а сейчас - в 2019 году.
Но это приходит рано в поиске в Интернете. Оригинальный вопрос не исключает использование сторонней библиотеки (когда я писал этот ответ).
public double calculateDistanceEncapsulated(double lat1, double long1, double lat2,
double long2) {
double dist = org.apache.lucene.util.SloppyMath.haversinMeters(lat1, long1, lat2, long2);
return dist;
}
и
<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
Пожалуйста, прочитайте документацию о "SloppyMath", прежде чем погрузиться в!
https://lucene.apache.org/core/8_2_0/core/org/apache/lucene/util/SloppyMath.html
Ответ 6
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);
}
}
Ответ 7
В этой статье приведены формулы и пример. Текст находится на немецком языке, но расчеты говорят сами за себя.
Ответ 8
Реализация Java в соответствии с формулой Haversine
final double EARTH_RADIUS = 6371.0 //km value
double distance = Math.pow(Math.sin((latPointRad - latMapZoneRad) / 2.0), 2)
+ Math.cos(latMapZoneRad) * Math.cos(latPointRad)
* Math.pow(Math.sin((lngPointRad - lngMapZoneRad) / 2.0), 2);
distance = 2.0 * EARTH_RADIUS * Math.asin(Math.sqrt(distance));
Ответ 9
Было получено много хороших ответов, однако я обнаружил некоторые недостатки в производительности, поэтому позвольте мне предложить версию с учетом производительности. Каждая константа предварительно рассчитывается, и вводятся переменные 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;
}