Ermitteln Sie den Abstand zwischen zwei Geopunkten


108

Ich möchte eine App erstellen, die den nächstgelegenen Ort überprüft, an dem sich ein Benutzer befindet. Ich kann den Standort des Benutzers leicht ermitteln und habe bereits eine Liste von Orten mit Längen- und Breitengraden.

Was wäre der beste Weg, um den nächstgelegenen Ort der Liste anhand des aktuellen Benutzerstandorts zu ermitteln?

Ich konnte nichts in den Google-APIs finden.

Antworten:


164
Location loc1 = new Location("");
loc1.setLatitude(lat1);
loc1.setLongitude(lon1);

Location loc2 = new Location("");
loc2.setLatitude(lat2);
loc2.setLongitude(lon2);

float distanceInMeters = loc1.distanceTo(loc2);

Referenz: http://developer.android.com/reference/android/location/Location.html#distanceTo(android.location.Location)


2
Wahrscheinlich langsamer als die Verwendung von Location.DistanceBetween (), da es Location-Objekte verwendet, aber für meine Zwecke sehr gut funktioniert.
ZoltanF

Welche Klasse muss ich für den Standort importieren import android.location.Location;oder welche
Pranav MS

@PranavMS yes android.location.Location;
AndrewS

Ich denke, dass distanceTo die Entfernung zwischen dem ersten und dem letzten Punkt aber in einer rektalen Linie zurückgibt. Wenn Sie also eine andere Richtung von Punkt a nach b einschlagen, wird dies niemals berechnet, da der Pfad unterschiedlich ist. Wenn sich distanceBetween anschließt, können Sie dies tun Speichern Sie jeden Abstand zwischen den erstellten Punkten und erhalten Sie dann mit den endgültigen Parameterergebnissen [] den richtigen Abstand.
Gastón Saillén

122

http://developer.android.com/reference/android/location/Location.html

Schauen Sie in distanceTo oder distanceBetween. Sie können ein Standortobjekt aus einem Breiten- und Längengrad erstellen:

Location location = new Location("");
location.setLatitude(lat);
location.setLongitude(lon);

37
distanceBetween ist eine statische Methode, die 2 Sätze von Lat Long Points verwendet, so dass Sie nicht einmal ein Location-Objekt instanziieren müssen =)
Stan Kurdziel

4
Ich bin sicher, er meinte das für die distanceToMethode.
Laph

Das ist großartig und super hilfreich, aber wofür ist der String-Anbieter im Konstruktor?
Miss.serena

33

Eine ungefähre Lösung (basierend auf einer gleichwinkligen Projektion), viel schneller (es werden nur 1 Trigger und 1 Quadratwurzel benötigt).

Diese Annäherung ist relevant, wenn Ihre Punkte nicht zu weit voneinander entfernt sind. Es wird immer im Vergleich zur tatsächlichen Haversine-Entfernung überschätzt. Beispielsweise wird die tatsächliche Entfernung um nicht mehr als 0,05382% erhöht , wenn der Delta-Breiten- oder Längengrad zwischen Ihren beiden Punkten 4 Dezimalgrad nicht überschreitet .

Die Standardformel (Haversine) ist die exakte (das heißt, sie funktioniert für alle Längen- / Breitengrade auf der Erde), ist jedoch viel langsamer, da sie 7 trigonometrische und 2 Quadratwurzeln benötigt. Wenn Ihre Punkte nicht zu weit voneinander entfernt sind und die absolute Genauigkeit nicht von größter Bedeutung ist, können Sie diese ungefähre Version (gleichwinklig) verwenden, die viel schneller ist, da nur eine trigonometrische und eine Quadratwurzel verwendet werden.

// Approximate Equirectangular -- works if (lat1,lon1) ~ (lat2,lon2)
int R = 6371; // km
double x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
double y = (lat2 - lat1);
double distance = Math.sqrt(x * x + y * y) * R;

Sie können dies weiter optimieren, indem Sie entweder:

  1. Entfernen der Quadratwurzel, wenn Sie einfach den Abstand mit einem anderen vergleichen (in diesem Fall vergleichen Sie beide Quadratabstände);
  2. Berücksichtigen Sie den Kosinus, wenn Sie den Abstand von einem Hauptpunkt zu vielen anderen berechnen (in diesem Fall führen Sie die auf den Hauptpunkt zentrierte gleichwinklige Projektion durch, sodass Sie den Kosinus für alle Vergleiche einmal berechnen können).

Weitere Informationen finden Sie unter: http://www.movable-type.co.uk/scripts/latlong.html

Es gibt eine schöne Referenzimplementierung der Haversine-Formel in mehreren Sprachen unter: http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe


großer Mann Danke. Wenn ich jedoch eine Reihe von Orten um einen Ort in einem Umkreis herum abrufen muss, sollte ich eine while-Schleife verwenden, um jeden Ort mit dem gesuchten zu vergleichen und nur diejenigen zu behalten, die sich im Umkreis befinden?
Themhz

Sie können, aber das ist ein Brute-Force-Ansatz in O(n). O(1)Verwenden Sie für eine Lösung einen räumlichen 2D-Index, um die potenziellen Übereinstimmungen zu kürzen, bevor Sie die genaue Lösung berechnen. Wir verlassen den Rahmen dieser Frage :)
Laurent Grégoire

Dies ist eine sehr schöne Zusammenfassung der möglichen Optimierungen. Danke! Genau das, wonach ich gesucht habe
Sam Vloeberghs

Ich wollte nur wissen, ob diese Formel für große Entfernungen funktioniert
Sandipan Majhi

Siehe die Antwort, aber kurz gesagt: Nein , es funktioniert nicht für große Entfernungen. Je größer der Abstand zwischen den beiden Punkten ist, desto größer ist der Fehler im Vergleich zu den exakten Haversine- Formeln.
Laurent Grégoire

11

Es gibt einige Methoden, die Sie verwenden können, aber um festzustellen, welche die beste ist, müssen wir zuerst wissen, ob Sie die Höhe des Benutzers sowie die Höhe der anderen Punkte kennen.

Abhängig von der Genauigkeit, nach der Sie suchen, können Sie entweder die Haversine- oder die Vincenty-Formel betrachten ...

Diese Seiten beschreiben die Formeln und bieten für weniger mathematische Neigungen auch eine Erklärung, wie sie in Skripten implementiert werden können!

Haversine-Formel: http://www.movable-type.co.uk/scripts/latlong.html

Vincenty-Formel: http://www.movable-type.co.uk/scripts/latlong-vincenty.html

Wenn Sie Probleme mit einer der Bedeutungen in den Formeln haben, kommentieren Sie einfach und ich werde mein Bestes tun, um sie zu beantworten :)


4

Es gibt zwei Möglichkeiten, um die Entfernung zwischen LatLng zu ermitteln.

public static void distanceBetween (double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)

Sieh dir das an

und zweitens

public float distanceTo (Location dest) wie von praveen beantwortet.


3
private float getDistance(double lat1, double lon1, double lat2, double lon2) {
        float[] distance = new float[2];
        Location.distanceBetween(lat1, lon1, lat2, lon2, distance);
        return distance[0];
    }

1

Verwenden Sie einfach die folgende Methode, übergeben Sie sie lat und long und ermitteln Sie die Entfernung in Metern:

private static double distance_in_meter(final double lat1, final double lon1, final double lat2, final double lon2) {
    double R = 6371000f; // Radius of the earth in m
    double dLat = (lat1 - lat2) * Math.PI / 180f;
    double dLon = (lon1 - lon2) * Math.PI / 180f;
    double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(latlong1.latitude * Math.PI / 180f) * Math.cos(latlong2.latitude * Math.PI / 180f) *
                    Math.sin(dLon/2) * Math.sin(dLon/2);
    double c = 2f * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    double d = R * c;
    return d;
}

2
latlong1 und latlong2 sind nicht definiert
Boy

1
Was ist Latlong1 & Latlong2?
Nisal Malinda Livera

0

Sie können Entfernung und Zeit mit der Google Map API ermitteln. Google Map API

Übergeben Sie einfach heruntergeladenes JSON an diese Methode. Sie erhalten Echtzeitentfernung und -zeit zwischen zwei Latlongs

void parseJSONForDurationAndKMS(String json) throws JSONException {

    Log.d(TAG, "called parseJSONForDurationAndKMS");
    JSONObject jsonObject = new JSONObject(json);
    String distance;
    String duration;
    distance = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("distance").getString("text");
    duration = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("duration").getString("text");

    Log.d(TAG, "distance : " + distance);
    Log.d(TAG, "duration : " + duration);

    distanceBWLats.setText("Distance : " + distance + "\n" + "Duration : " + duration);


}

0

a = sin² (Δφ / 2) + cos φ1 ⋅ cos φ2 ⋅ sin² (Δλ / 2)

c = 2 ⋅ atan2 (√a, √ (1 - a))

Abstand = R ⋅ c

wobei φ der Breitengrad ist, λ der Längengrad ist, R der Erdradius ist (mittlerer Radius = 6.371 km);

Beachten Sie, dass die Winkel im Bogenmaß angegeben werden müssen, um zu Triggerfunktionen zu gelangen!

fun distanceInMeter(firstLocation: Location, secondLocation: Location): Double {
    val earthRadius = 6371000.0
    val deltaLatitudeDegree = (firstLocation.latitude - secondLocation.latitude) * Math.PI / 180f
    val deltaLongitudeDegree = (firstLocation.longitude - secondLocation.longitude) * Math.PI / 180f
    val a = sin(deltaLatitudeDegree / 2).pow(2) +
            cos(firstLocation.latitude * Math.PI / 180f) * cos(secondLocation.latitude * Math.PI / 180f) *
            sin(deltaLongitudeDegree / 2).pow(2)
    val c = 2f * atan2(sqrt(a), sqrt(1 - a))
    return earthRadius * c
}


data class Location(val latitude: Double, val longitude: Double)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.