Berechnen Sie die Entfernung zwischen zwei Punkten in Google Maps V3

Antworten:

460

Wenn Sie es selbst berechnen möchten, können Sie die Haversine-Formel verwenden:

var rad = function(x) {
  return x * Math.PI / 180;
};

var getDistance = function(p1, p2) {
  var R = 6378137; // Earth’s mean radius in meter
  var dLat = rad(p2.lat() - p1.lat());
  var dLong = rad(p2.lng() - p1.lng());
  var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) *
    Math.sin(dLong / 2) * Math.sin(dLong / 2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = R * c;
  return d; // returns the distance in meter
};
Mike Williams
quelle
4
Warum schlagen Sie vor, Math.atan2 (Math.sqrt (a), Math.sqrt (1-a)) anstelle des einfachsten Math.asin (Math.sqrt (a)) zu verwenden?
Emanuele Paolini
3
@EmanuelePaolini - Mathematisch gesehen ist atan2 (sqrt (a), sqrt (1-a)) = asin (sqrt (a)) = acos (sqrt (1-a)), aber die atan2-Version bleibt für alle Werte von numerisch besser konditioniert ein.
ChrisV
23
Jungs. Frage. Warum gefällt es Ihnen so gut, 1-Buchstaben-Variablennamen zu verwenden, um Probleme zu lösen, die etwas Vorstellungskraft erfordern, wo ein guter Variablenname hilfreich sein könnte? Nur fragen :)
pie6k
2
Sollte es nicht var R = 6371 sein; für km?
Alexander Fradiani
5
Die Funktionen p1.lat()und setzen p1.lng()voraus, dass Ihre Eingabedaten google.maps.LatLngObjekte sind. Wenn Sie nur Rohdaten wie diese haben {lat: __, lon: __}, würden Sie stattdessen p1.latzum Beispiel verwenden.
Don McCurdy
308

Es scheint tatsächlich eine Methode in GMap3 zu geben. Es ist eine statische Methode des google.maps.geometry.sphericalNamespace.

Es werden zwei LatLngObjekte als Argumente verwendet und ein Standard-Erdradius von 6378137 Metern verwendet, obwohl der Standardradius bei Bedarf mit einem benutzerdefinierten Wert überschrieben werden kann.

Stellen Sie sicher, dass Sie Folgendes angeben:

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&v=3&libraries=geometry"></script>

in deinem Kopfteil.

Der Anruf wird sein:

google.maps.geometry.spherical.computeDistanceBetween (latLngA, latLngB);
Emil Badh
quelle
10
Warum gibt es einen Unterschied von 1% in der Antwort von Googles sphärischem computeDistanceBetween und der Haversine-Distanzformel?
Matt S
7
@RamenRecon Ich bin nicht sicher, aber eine Frage wäre, dass sie unterschiedliche Werte für den Erdradius verwenden.
Emil Badh
11
@RamenRecon ja, Emil ist hier richtig. In der Dokumentation heißt es: Der Standardradius ist der Erdradius von 6378137 Metern. Aber Mike in der Haversine oben nutzt stattdessen 6371 km .
Laszlo
Der obige Link ist jetzt unterbrochen, aber die Erklärung der Methode macht dies nicht zu einem großen Problem.
GChorn
2
@ ABCD.ca Es ist nicht meine Nummer. Diese Frage bezieht sich auf Version 3 der Google Maps Library. Sie haben gefragt, warum sich Ihre Berechnung von ihrer unterscheidet. Das liegt daran, dass sie einen anderen Wert für den Erdradius verwenden als Sie. Die Referenz für die Nummer? developer.google.com/maps/documentation/javascript/… Direkt unter der Überschrift.
Emil Badh
30

Beispiel mit GPS Breite / Länge von 2 Punkten.

var latitude1 = 39.46;
var longitude1 = -0.36;
var latitude2 = 40.40;
var longitude2 = -3.68;

var distance = google.maps.geometry.spherical.computeDistanceBetween(new google.maps.LatLng(latitude1, longitude1), new google.maps.LatLng(latitude2, longitude2));       
joan16v
quelle
3
Entfernungsergebnisse werden in Metern angegeben.
joan16v
1
@ joan16v wie man google.maps.geometry in node.js benötigt. Ich möchte den obigen Code in node.js verwenden. Welches Modul soll ich installieren und welche Dateien soll ich benötigen?
Kisor
15

Fügen Sie dies einfach am Anfang Ihres JavaScript-Codes hinzu:

google.maps.LatLng.prototype.distanceFrom = function(latlng) {
  var lat = [this.lat(), latlng.lat()]
  var lng = [this.lng(), latlng.lng()]
  var R = 6378137;
  var dLat = (lat[1]-lat[0]) * Math.PI / 180;
  var dLng = (lng[1]-lng[0]) * Math.PI / 180;
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
  Math.cos(lat[0] * Math.PI / 180 ) * Math.cos(lat[1] * Math.PI / 180 ) *
  Math.sin(dLng/2) * Math.sin(dLng/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;
  return Math.round(d);
}

und dann verwenden Sie die Funktion wie folgt:

var loc1 = new GLatLng(52.5773139, 1.3712427);
var loc2 = new GLatLng(52.4788314, 1.7577444);
var dist = loc2.distanceFrom(loc1);
alert(dist/1000);
Plamen Todorov
quelle
Hervorragende Lösung, aber ich möchte wissen, in welchen Einheiten das Ergebnis zurückgegeben wird. Ich habe 3.013 .. ist das in Meilen, km?
Gowthami Gattineni
Der zurückgegebene Wert ist in Metern. Daher gibt dist / 1000 den Wert in km an.
Praveen Janakarajan
13
//p1 and p2 are google.maps.LatLng(x,y) objects

function calcDistance(p1, p2) {
          var d = (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2);
          console.log(d);              
}
Aishwat Singh
quelle
3
Das ist die beste Antwort. Warum eine Funktion hinzufügen, wenn Google API bereits über die Funktionen verfügt
felixfbecker
Gibt es eine Java-Variante für diese API? Ich konnte es nach langem Suchen nicht finden.
Sanketh
@felixfbecker, da Sie möglicherweise in einer Umgebung arbeiten, in der Sie die Google Maps-API nicht in ein scriptTag einfügen und diese Methoden aufrufen können. Wie reaktionsgeboren.
Nnanyielugo
11

Hier ist die c # -Implementierung dieses Forums

 public class DistanceAlgorithm
{
    const double PIx = 3.141592653589793;
    const double RADIO = 6378.16;

    /// <summary>
    /// This class cannot be instantiated.
    /// </summary>
    private DistanceAlgorithm() { }

    /// <summary>
    /// Convert degrees to Radians
    /// </summary>
    /// <param name="x">Degrees</param>
    /// <returns>The equivalent in radians</returns>
    public static double Radians(double x)
    {
        return x * PIx / 180;
    }

    /// <summary>
    /// Calculate the distance between two places.
    /// </summary>
    /// <param name="lon1"></param>
    /// <param name="lat1"></param>
    /// <param name="lon2"></param>
    /// <param name="lat2"></param>
    /// <returns></returns>
    public static double DistanceBetweenPlaces(
        double lon1,
        double lat1,
        double lon2,
        double lat2)
    {
        double dlon =  Radians(lon2 - lon1);
        double dlat =  Radians(lat2 - lat1);

        double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
        double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
        return (angle * RADIO) * 0.62137;//distance in miles
    }

}    
Naveed Ahmad
quelle
5
Dies gilt nicht für die ursprüngliche Frage, wie dies in Google Maps zu tun ist.
Niklas Wulff
Es gibt keine eingebaute Funktion zum direkten Berechnen der Entfernung. Sie müssen Verzeichnisdienste für zwei Punkte verwenden und die Entfernung aus dem zurückgegebenen XML / JSON extrahieren.
Naveed Ahmad
1
Mein Kommentar war die Tatsache, dass es besser gewesen wäre, eine Lösung in Javascript bereitzustellen, da der Thread-Starter nicht sagte, ob er / sie PHP, .net oder statisches HTML verwendet.
Niklas Wulff
11

Mit Google können Sie es tun , um die Verwendung von sphärischen api , google.maps.geometry.spherical.computeDistanceBetween (latLngA, latLngB);.

Wenn die Genauigkeit einer sphärischen Projektion oder einer Haversine-Lösung für Sie jedoch nicht genau genug ist (z. B. wenn Sie sich in der Nähe des Pols befinden oder größere Entfernungen berechnen), sollten Sie eine andere Bibliothek verwenden.

Die meisten Informationen zu diesem Thema habe ich hier auf Wikipedia gefunden .

Ein Trick, um festzustellen, ob die Genauigkeit eines bestimmten Algorithmus angemessen ist, besteht darin, den maximalen und minimalen Radius der Erde auszufüllen und festzustellen, ob der Unterschied Probleme für Ihren Anwendungsfall verursachen kann. Viele weitere Details finden Sie in diesem Artikel

Am Ende wird die Google API oder Haversine den meisten Zwecken ohne Probleme dienen.

iwein
quelle
9

Mit PHP können Sie die Entfernung mit dieser einfachen Funktion berechnen:

// um den Abstand zwischen zwei lat & lon zu berechnen

Funktion berechne_Distanz ($ lat1, $ lon1, $ lat2, $ lon2, $ unit = 'N') 
{ 
  $ theta = $ lon1 - $ lon2; 
  $ dist = sin (deg2rad ($ lat1)) * sin (deg2rad ($ lat2)) + cos (deg2rad ($ lat1)) * cos (deg2rad ($ lat2)) * cos (deg2rad ($ theta)); 
  $ dist = acos ($ dist); 
  $ dist = rad2deg ($ dist); 
  $ Meilen = $ dist * 60 * 1,1515;
  $ unit = strtoupper ($ unit);

  if ($ unit == "K") {
    Rückgabe ($ Meilen * 1,609344); 
  } else if ($ unit == "N") {
      Rückkehr ($ Meilen * 0,8684);
    } else {
        $ Meilen zurückgeben;
      }}
}}

// Funktion endet hier
Ravinder Singh
quelle
2
Es gibt eine Bedingung in der Funktion, dass, wenn Sie das Gerät so passieren K, Sie die Entfernung in km erhalten. Prüfen Sie.
Toter Mann
Diese Funktion funktioniert sehr gut und gibt die Entfernung vom Sternort zu allen Orten an. Kann es auf eine Weise durchqueren, dass es zuerst den ersten nächstgelegenen Ort findet und als Quelle oder Startpunkt fungiert und dann den nächstgelegenen, aber nicht den ersten Quellort usw. findet?
Waheed ur Rehman
8

OFFLINE-LÖSUNG - Haversine-Algorithmus

In Javascript

var _eQuatorialEarthRadius = 6378.1370;
var _d2r = (Math.PI / 180.0);

function HaversineInM(lat1, long1, lat2, long2)
{
    return (1000.0 * HaversineInKM(lat1, long1, lat2, long2));
}

function HaversineInKM(lat1, long1, lat2, long2)
{
    var dlong = (long2 - long1) * _d2r;
    var dlat = (lat2 - lat1) * _d2r;
    var a = Math.pow(Math.sin(dlat / 2.0), 2.0) + Math.cos(lat1 * _d2r) * Math.cos(lat2 * _d2r) * Math.pow(Math.sin(dlong / 2.0), 2.0);
    var c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1.0 - a));
    var d = _eQuatorialEarthRadius * c;

    return d;
}

var meLat = -33.922982;
var meLong = 151.083853;


var result1 = HaversineInKM(meLat, meLong, -32.236457779983745, 148.69094705162837);
var result2 = HaversineInKM(meLat, meLong, -33.609020205923713, 150.77061469270831);

C #

using System;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");

        var meLat = -33.922982;
        double meLong = 151.083853;


        var result1 = HaversineInM(meLat, meLong, -32.236457779983745, 148.69094705162837);
        var result2 = HaversineInM(meLat, meLong, -33.609020205923713, 150.77061469270831);

        Console.WriteLine(result1);
        Console.WriteLine(result2);
    }

    static double _eQuatorialEarthRadius = 6378.1370D;
    static double _d2r = (Math.PI / 180D);

    private static int HaversineInM(double lat1, double long1, double lat2, double long2)
    {
        return (int)(1000D * HaversineInKM(lat1, long1, lat2, long2));
    }

    private static  double HaversineInKM(double lat1, double long1, double lat2, double long2)
    {
        double dlong = (long2 - long1) * _d2r;
        double dlat = (lat2 - lat1) * _d2r;
        double a = Math.Pow(Math.Sin(dlat / 2D), 2D) + Math.Cos(lat1 * _d2r) * Math.Cos(lat2 * _d2r) * Math.Pow(Math.Sin(dlong / 2D), 2D);
        double c = 2D * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1D - a));
        double d = _eQuatorialEarthRadius * c;

        return d;
    }
}

Referenz: https://en.wikipedia.org/wiki/Great-circle_distance

MarceloBarbosa
quelle
3

Musste es tun ... Das Action-Skript so

//just make sure you pass a number to the function because it would accept you mother in law...
public var rad = function(x:*) {return x*Math.PI/180;}

protected  function distHaversine(p1:Object, p2:Object):Number {
    var R:int = 6371; // earth's mean radius in km
    var dLat:Number = rad(p2.lat() - p1.lat());
    var dLong:Number = rad(p2.lng() - p1.lng());

    var a:Number = Math.sin(dLat/2) * Math.sin(dLat/2) +
                Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
    var c:Number = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d:Number = R * c;

    return d;
}
Netcfmx
quelle
3

In meinem Fall war es am besten, dies in SQL Server zu berechnen, da ich den aktuellen Standort übernehmen und dann nach allen Postleitzahlen in einer bestimmten Entfernung vom aktuellen Standort suchen wollte. Ich hatte auch eine Datenbank, die eine Liste der Postleitzahlen und ihrer Lat-Longs enthielt. Prost

--will return the radius for a given number
create function getRad(@variable float)--function to return rad
returns float
as
begin
declare @retval float 
select @retval=(@variable * PI()/180)
--print @retval
return @retval
end
go

--calc distance
--drop function dbo.getDistance
create function getDistance(@cLat float,@cLong float, @tLat float, @tLong float)
returns float
as
begin
declare @emr float
declare @dLat float
declare @dLong float
declare @a float
declare @distance float
declare @c float

set @emr = 6371--earth mean 
set @dLat = dbo.getRad(@tLat - @cLat);
set @dLong = dbo.getRad(@tLong - @cLong);
set @a = sin(@dLat/2)*sin(@dLat/2)+cos(dbo.getRad(@cLat))*cos(dbo.getRad(@tLat))*sin(@dLong/2)*sin(@dLong/2);
set @c = 2*atn2(sqrt(@a),sqrt(1-@a))
set @distance = @emr*@c;
set @distance = @distance * 0.621371 -- i needed it in miles
--print @distance
return @distance;
end 
go


--get all zipcodes within 2 miles, the hardcoded #'s would be passed in by C#
select *
from cityzips a where dbo.getDistance(29.76,-95.38,a.lat,a.long) <3
order by zipcode
user2004796
quelle
Ich bin mir nicht sicher, ob dies für eine clientseitige Verwendung effizient ist.
Nizar B.
Vielleicht keine Front-End-Lösung, aber definitiv das, wonach ich gesucht habe. Vielen Dank.
st_stefanov
3
//JAVA
    public Double getDistanceBetweenTwoPoints(Double latitude1, Double longitude1, Double latitude2, Double longitude2) {
    final int RADIUS_EARTH = 6371;

    double dLat = getRad(latitude2 - latitude1);
    double dLong = getRad(longitude2 - longitude1);

    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(getRad(latitude1)) * Math.cos(getRad(latitude2)) * Math.sin(dLong / 2) * Math.sin(dLong / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return (RADIUS_EARTH * c) * 1000;
    }

    private Double getRad(Double x) {
    return x * Math.PI / 180;
    }
borchvm
quelle
1

Mit dem Google Distance Matrix-Dienst ist das ganz einfach

Der erste Schritt besteht darin, den Distance Matrix-Dienst über die Google API-Konsole zu aktivieren. Es gibt Entfernungen zwischen einer Reihe von Orten zurück. Und wenden Sie diese einfache Funktion an

function initMap() {
        var bounds = new google.maps.LatLngBounds;
        var markersArray = [];

        var origin1 = {lat:23.0203, lng: 72.5562};
        //var origin2 = 'Ahmedabad, India';
        var destinationA = {lat:23.0436503, lng: 72.55008939999993};
        //var destinationB = {lat: 23.2156, lng: 72.6369};

        var destinationIcon = 'https://chart.googleapis.com/chart?' +
            'chst=d_map_pin_letter&chld=D|FF0000|000000';
        var originIcon = 'https://chart.googleapis.com/chart?' +
            'chst=d_map_pin_letter&chld=O|FFFF00|000000';
        var map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: 55.53, lng: 9.4},
          zoom: 10
        });
        var geocoder = new google.maps.Geocoder;

        var service = new google.maps.DistanceMatrixService;
        service.getDistanceMatrix({
          origins: [origin1],
          destinations: [destinationA],
          travelMode: 'DRIVING',
          unitSystem: google.maps.UnitSystem.METRIC,
          avoidHighways: false,
          avoidTolls: false
        }, function(response, status) {
          if (status !== 'OK') {
            alert('Error was: ' + status);
          } else {
            var originList = response.originAddresses;
            var destinationList = response.destinationAddresses;
            var outputDiv = document.getElementById('output');
            outputDiv.innerHTML = '';
            deleteMarkers(markersArray);

            var showGeocodedAddressOnMap = function(asDestination) {
              var icon = asDestination ? destinationIcon : originIcon;
              return function(results, status) {
                if (status === 'OK') {
                  map.fitBounds(bounds.extend(results[0].geometry.location));
                  markersArray.push(new google.maps.Marker({
                    map: map,
                    position: results[0].geometry.location,
                    icon: icon
                  }));
                } else {
                  alert('Geocode was not successful due to: ' + status);
                }
              };
            };

            for (var i = 0; i < originList.length; i++) {
              var results = response.rows[i].elements;
              geocoder.geocode({'address': originList[i]},
                  showGeocodedAddressOnMap(false));
              for (var j = 0; j < results.length; j++) {
                geocoder.geocode({'address': destinationList[j]},
                    showGeocodedAddressOnMap(true));
                //outputDiv.innerHTML += originList[i] + ' to ' + destinationList[j] + ': ' + results[j].distance.text + ' in ' +                    results[j].duration.text + '<br>';
                outputDiv.innerHTML += results[j].distance.text + '<br>';
              }
            }

          }
        });
      }

Wobei origin1 Ihr Standort und destinationA der Zielstandort ist. Sie können über zwei oder mehr Daten hinzufügen.

Rad Vollständige Dokumentation mit einem Beispiel

TarangP
quelle
1
  /**
   * Calculates the haversine distance between point A, and B.
   * @param {number[]} latlngA [lat, lng] point A
   * @param {number[]} latlngB [lat, lng] point B
   * @param {boolean} isMiles If we are using miles, else km.
   */
  function haversineDistance(latlngA, latlngB, isMiles) {
    const squared = x => x * x;
    const toRad = x => (x * Math.PI) / 180;
    const R = 6371; // Earth’s mean radius in km

    const dLat = toRad(latlngB[0] - latlngA[0]);
    const dLon = toRad(latlngB[1] - latlngA[1]);

    const dLatSin = squared(Math.sin(dLat / 2));
    const dLonSin = squared(Math.sin(dLon / 2));

    const a = dLatSin +
              (Math.cos(toRad(latlngA[0])) * Math.cos(toRad(latlngB[0])) * dLonSin);
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    let distance = R * c;

    if (isMiles) distance /= 1.609344;

    return distance;
  }

Ich habe eine Online-Version gefunden, die zu 80% richtig ist, aber den falschen Parameter eingesteckt hat und bei der Verwendung der Eingaben inkonsistent ist. Diese Version hat dies vollständig behoben

Bleistiftcheck
quelle
0

Um die Entfernung in Google Maps zu berechnen, können Sie die Wegbeschreibungs-API verwenden. Das wird einer der einfachsten Wege sein, dies zu tun. Um Daten von Google Server abzurufen, können Sie Retrofit oder Volley verwenden. Beides hat seinen eigenen Vorteil. Schauen Sie sich den folgenden Code an, in dem ich ihn nachgerüstet habe:

private void build_retrofit_and_get_response(String type) {

    String url = "https://maps.googleapis.com/maps/";

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    RetrofitMaps service = retrofit.create(RetrofitMaps.class);

    Call<Example> call = service.getDistanceDuration("metric", origin.latitude + "," + origin.longitude,dest.latitude + "," + dest.longitude, type);

    call.enqueue(new Callback<Example>() {
        @Override
        public void onResponse(Response<Example> response, Retrofit retrofit) {

            try {
                //Remove previous line from map
                if (line != null) {
                    line.remove();
                }
                // This loop will go through all the results and add marker on each location.
                for (int i = 0; i < response.body().getRoutes().size(); i++) {
                    String distance = response.body().getRoutes().get(i).getLegs().get(i).getDistance().getText();
                    String time = response.body().getRoutes().get(i).getLegs().get(i).getDuration().getText();
                    ShowDistanceDuration.setText("Distance:" + distance + ", Duration:" + time);
                    String encodedString = response.body().getRoutes().get(0).getOverviewPolyline().getPoints();
                    List<LatLng> list = decodePoly(encodedString);
                    line = mMap.addPolyline(new PolylineOptions()
                                    .addAll(list)
                                    .width(20)
                                    .color(Color.RED)
                                    .geodesic(true)
                    );
                }
            } catch (Exception e) {
                Log.d("onResponse", "There is an error");
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Throwable t) {
            Log.d("onFailure", t.toString());
        }
    });

}

Oben ist der Funktionscode build_retrofit_and_get_response zur Berechnung der Entfernung angegeben. Unten finden Sie die entsprechende Nachrüstschnittstelle:

package com.androidtutorialpoint.googlemapsdistancecalculator;


import com.androidtutorialpoint.googlemapsdistancecalculator.POJO.Example;

import retrofit.Call;
import retrofit.http.GET;
import retrofit.http.Query;

public interface RetrofitMaps {


/*
 * Retrofit get annotation with our URL
 * And our method that will return us details of student.
 */
@GET("api/directions/json?key=AIzaSyC22GfkHu9FdgT9SwdCWMwKX1a4aohGifM")
Call<Example> getDistanceDuration(@Query("units") String units, @Query("origin") String origin, @Query("destination") String destination, @Query("mode") String mode);

}}

Ich hoffe das erklärt deine Anfrage. Alles Gute :)

Quelle: Google Maps Entfernungsrechner

Navneet Goel
quelle
Nein, dies berechnet die Reisedistanz (auf Straßen usw.), nicht die geodätische Punkt-zu-Punkt-Entfernung.
Yarin