Oto moja próba, to tylko fragment mojego kodu:
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;
Używam tych formuł, aby uzyskać szerokość i długość geograficzną:
x = Deg + (Min + Sec / 60) / 60)
java
math
latitude-longitude
m4design
źródło
źródło
a
ic
? Czy to są boki trójkąta prostokątnego z tradycyjnych etykieta
,b
ic
?Oto funkcja Java, która oblicza odległość między dwoma długimi i długimi punktami , zamieszczona poniżej, na wypadek, gdyby znowu zniknęła.
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");
źródło
Uwaga: to rozwiązanie działa tylko na krótkie odległości.
Próbowałem użyć opublikowanej formuły dommera dla aplikacji i stwierdziłem, że radziła sobie dobrze na długich dystansach, ale w moich danych użyłem wszystkich bardzo krótkich odległości, a post dommera wypadł bardzo słabo. Potrzebowałem szybkości, a bardziej złożone obliczenia geograficzne działały dobrze, ale były zbyt wolne. Tak więc w przypadku, gdy potrzebujesz prędkości, a wszystkie obliczenia, które wykonujesz, są krótkie (może <100 m lub więcej). Uważam, że to małe przybliżenie działa świetnie. zakłada, że świat jest płaski, więc nie używaj go na duże odległości, działa poprzez przybliżenie odległości jednej szerokości i długości geograficznej na danej szerokości geograficznej i zwrócenie odległości pitagorejskiej w metrach.
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; } }
źródło
Przyszli czytelnicy, którzy natkną się na ten artykuł SOF.
Oczywiście pytanie padło w 2010 r., A teraz jest w 2019 r. Ale pojawia się na początku wyszukiwania w Internecie. Oryginalne pytanie nie pomija korzystania z biblioteki zewnętrznej (kiedy pisałem tę odpowiedź).
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; }
i
<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
Przeczytaj dokumentację o „SloppyMath” przed przystąpieniem do nurkowania!
https://lucene.apache.org/core/8_2_0/core/org/apache/lucene/util/SloppyMath.html
źródło
Oto strona z przykładami javascript do różnych obliczeń sferycznych. Pierwsza na stronie powinna dać Ci to, czego potrzebujesz.
http://www.movable-type.co.uk/scripts/latlong.html
Oto kod 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;
Gdzie „d” utrzyma dystans.
źródło
udzielono wielu świetnych odpowiedzi, jednak znalazłem pewne niedociągnięcia w wydajności, więc pozwól mi zaoferować wersję z myślą o wydajności. Każda stała jest wstępnie obliczana i wprowadzane są zmienne x, y, aby uniknąć podwójnego obliczania tej samej wartości. Mam nadzieję, że to pomoże
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; }
źródło
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); } }
źródło
Nieznacznie ulepszona odpowiedź od @David George:
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); } public static double distanceBetweenLocations(Location l1, Location l2) { if(l1.hasAltitude() && l2.hasAltitude()) { return distance(l1.getLatitude(), l2.getLatitude(), l1.getLongitude(), l2.getLongitude(), l1.getAltitude(), l2.getAltitude()); } return l1.distanceTo(l2); }
Funkcja odległości jest taka sama, ale utworzyłem małą funkcję opakowującą, która przyjmuje 2 obiekty Location . Dzięki temu z funkcji odległości korzystam tylko wtedy, gdy obie lokalizacje faktycznie mają wysokość, bo czasami tak nie jest. Może to prowadzić do dziwnych wyników (jeśli lokalizacja nie zna jej wysokości, zostanie zwrócona 0). W tym przypadku wracam do klasycznej funkcji distanceTo .
źródło
Ten artykuł na Wikipedii zawiera wzory i przykład. Tekst jest w języku niemieckim, ale obliczenia mówią same za siebie.
źródło