Calcular a distância entre dois pontos de latitude e longitude? (Fórmula de haversina)

Como posso calcular a distância entre dois pontos especificados por latitude e longitude?

Para esclarecer, eu gostaria da distância em quilômetros; os pontos usam o sistema WGS84 e eu gostaria de entender a precisão relativa das aproximações disponíveis.

Author: Zero, 2008-08-26

30 answers

Esta ligação pode ser útil para si, pois descreve a utilização da Fórmula Haversina para calcular a distância.

Excerto:

Este programa calcula distâncias em grandes círculos entre os dois pontos – isto é, a distância mais curta sobre a superfície da terra – usando o Fórmula "Haversine".

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; // Distance in km
  return d;
}

function deg2rad(deg) {
  return deg * (Math.PI/180)
}
 913
Author: Chuck, 2014-07-31 01:25:14
Eu precisava calcular muitas distâncias entre os pontos do meu projeto, então eu fui em frente e tentei otimizar o código, eu encontrei aqui. Em média, em navegadores diferentes, a minha nova implementação é 2 vezes mais rápida do que a resposta Mais votada.
function distance(lat1, lon1, lat2, lon2) {
  var p = 0.017453292519943295;    // Math.PI / 180
  var c = Math.cos;
  var a = 0.5 - c((lat2 - lat1) * p)/2 + 
          c(lat1 * p) * c(lat2 * p) * 
          (1 - c((lon2 - lon1) * p))/2;

  return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}

Podes brincar com o meu jsPerf e ver os resultados aqui.

Recentemente eu precisava fazer o mesmo em python, então aqui está uma implementação em python:

from math import cos, asin, sqrt
def distance(lat1, lon1, lat2, lon2):
    p = 0.017453292519943295     #Pi/180
    a = 0.5 - cos((lat2 - lat1) * p)/2 + cos(lat1 * p) * cos(lat2 * p) * (1 - cos((lon2 - lon1) * p)) / 2
    return 12742 * asin(sqrt(a)) #2*R*asin...

E para o bem de exaustividade: Haversine em wiki.

 266
Author: Salvador Dali, 2017-04-16 19:45:25

Aqui está uma implementação C#:

static class DistanceAlgorithm
{
    const double PIx = 3.141592653589793;
    const double RADIUS = 6378.16;

    /// <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 * RADIUS;
    }
 58
Author: jaircazarin-old-account, 2016-11-01 09:11:43

Aqui está uma implementação java da fórmula Haversine.

public final static double AVERAGE_RADIUS_OF_EARTH_KM = 6371;
public int calculateDistanceInKilometer(double userLat, double userLng,
  double venueLat, double venueLng) {

    double latDistance = Math.toRadians(userLat - venueLat);
    double lngDistance = Math.toRadians(userLng - venueLng);

    double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
      + Math.cos(Math.toRadians(userLat)) * Math.cos(Math.toRadians(venueLat))
      * Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);

    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    return (int) (Math.round(AVERAGE_RADIUS_OF_EARTH_KM * c));
}
Note que aqui estamos arredondando a resposta para o km mais próximo.
 50
Author: whostolebenfrog, 2016-11-29 09:19:04
Muito obrigado por tudo isto. Eu usei o seguinte código no meu aplicativo iPhone Objective-C:
const double PIx = 3.141592653589793;
const double RADIO = 6371; // Mean radius of Earth in Km

double convertToRadians(double val) {

   return val * PIx / 180;
}

-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

        double dlon = convertToRadians(place2.longitude - place1.longitude);
        double dlat = convertToRadians(place2.latitude - place1.latitude);

        double a = ( pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))) * cos(convertToRadians(place2.latitude)) * pow(sin(dlon / 2), 2);
        double angle = 2 * asin(sqrt(a));

        return angle * RADIO;
}

Latitude E Longitude são decimais. Eu não usei min () para a chamada asin() como as distâncias que eu estou usando são tão pequenas que eles não exigem isso.

Deu respostas incorrectas até eu passar os valores em radianos-agora é praticamente o mesmo que os valores obtidos da aplicação da Apple Map: -)

Actualização Extra:

Se estiver a utilizar iOS4 ou mais tarde, então Apple fornece alguns métodos para fazer isso de modo que a mesma funcionalidade seria alcançada com:

-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

    MKMapPoint  start, finish;


    start = MKMapPointForCoordinate(place1);
    finish = MKMapPointForCoordinate(place2);

    return MKMetersBetweenMapPoints(start, finish) / 1000;
}
 41
Author: Stephen Watson, 2014-07-31 01:26:41

Esta é uma função PHP simples que irá dar uma aproximação muito Razoável (Abaixo de +/-1% margem de erro).

<?php
function distance($lat1, $lon1, $lat2, $lon2) {

    $pi80 = M_PI / 180;
    $lat1 *= $pi80;
    $lon1 *= $pi80;
    $lat2 *= $pi80;
    $lon2 *= $pi80;

    $r = 6372.797; // mean radius of Earth in km
    $dlat = $lat2 - $lat1;
    $dlon = $lon2 - $lon1;
    $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlon / 2) * sin($dlon / 2);
    $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
    $km = $r * $c;

    //echo '<br/>'.$km;
    return $km;
}
?>
Como já foi dito, a terra não é uma esfera. É como uma bola velha, velha que Mark McGwire decidiu praticar com-está cheia de amolgadelas e solavancos. Os cálculos mais simples (assim) tratam - no como uma esfera.

Diferentes métodos podem ser mais ou menos precisos de acordo com o local onde se encontra neste ovóide irregular e com a distância entre os seus pontos (a mais próximos são os menores da margem de erro absoluta). Quanto mais precisa for a sua expectativa, mais complexa é a matemática.

Para mais informações: a distância geográfica da Wikipédia

 35
Author: tony gil, 2017-06-22 20:33:20
Postei aqui o meu exemplo de trabalho.

Listar todos os pontos da tabela com distância entre um ponto designado (usamos um ponto aleatório - lat:45.20327, comprimento: 23.7806) menos de 50 KM, com latitude e longitude, em MySQL (os campos da tabela são coorden_lat e coorden_long):

Lista de todos os que têm uma distância

SELECT denumire, (6371 * acos( cos( radians(45.20327) ) * cos( radians( coord_lat ) ) * cos( radians( 23.7806 ) - radians(coord_long) ) + sin( radians(45.20327) ) * sin( radians(coord_lat) ) )) AS distanta 
FROM obiective 
WHERE coord_lat<>'' 
    AND coord_long<>'' 
HAVING distanta<50 
ORDER BY distanta desc

O exemplo acima foi testado em MySQL 5.0.95 e 5.5.16 (Linux).

 26
Author: conualfy, 2014-07-31 01:31:00
Nas outras respostas falta uma implementação em r.

Calcular a distância entre dois pontos é bastante simples com a função distm do pacote geosphere:

distm(p1, p2, fun = distHaversine)

Em que:

p1 = longitude/latitude for point(s)
p2 = longitude/latitude for point(s)
# type of distance calculation
fun = distCosine / distHaversine / distVincentySphere / distVincentyEllipsoid 

Como a terra não é perfeitamente esférica, a fórmula Vincenta para elipsóides é provavelmente a melhor maneira de calcular distâncias. Assim, na embalagem geosphere você usa então:

distm(p1, p2, fun = distVincentyEllipsoid)

Claro que não necessariamente. tem que usar geosphere Pacote, Você também pode calcular a distância na base R com uma função:
hav.dist <- function(long1, lat1, long2, lat2) {
  R <- 6371
  diff.long <- (long2 - long1)
  diff.lat <- (lat2 - lat1)
  a <- sin(diff.lat/2)^2 + cos(lat1) * cos(lat2) * sin(diff.long/2)^2
  b <- 2 * asin(pmin(1, sqrt(a))) 
  d = R * b
  return(d)
}
 20
Author: Jaap, 2018-06-15 13:35:00

Você pode usar o build in CLLocationDistance para calcular isto:

CLLocation *location1 = [[CLLocation alloc] initWithLatitude:latitude1 longitude:longitude1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:latitude2 longitude:longitude2];
[self distanceInMetersFromLocation:location1 toLocation:location2]

- (int)distanceInMetersFromLocation:(CLLocation*)location1 toLocation:(CLLocation*)location2 {
    CLLocationDistance distanceInMeters = [location1 distanceFromLocation:location2];
    return distanceInMeters;
}
No seu caso, se quiser quilómetros, divida por 1000.
 7
Author: André Cytryn, 2013-06-26 08:43:46
{[[2]} a haversine é definitivamente uma boa fórmula para provavelmente a maioria dos casos, outras respostas já A incluem por isso eu não vou tomar o espaço. Mas é importante notar que não importa qual fórmula é usada (sim, não apenas uma). Devido à grande variedade de precisão possível, bem como o tempo de computação necessário. A escolha da fórmula requer um pouco mais de pensamento do que uma simples resposta simples. Este post de uma pessoa na nasa, é o melhor que encontrei em discutir o opções

Http://www.cs.nyu.edu/visual/home/proj/tiger/gisfaq.html

Por exemplo, se estiver apenas a ordenar as linhas à distância num raio de 160 km. A fórmula da terra plana será muito mais rápida que a de haversine.

HalfPi = 1.5707963;
R = 3956; /* the radius gives you the measurement unit*/

a = HalfPi - latoriginrad;
b = HalfPi - latdestrad;
u = a * a + b * b;
v = - 2 * a * b * cos(longdestrad - longoriginrad);
c = sqrt(abs(u + v));
return R * c;
Repara que só há um cosseno e uma raiz quadrada. Vs 9 deles na fórmula de Haversine.
 7
Author: Arturo Hernandez, 2013-11-04 16:20:08

Não gosto de adicionar mais uma resposta, mas a API v. 3 do Google maps tem geometria esférica (e muito mais). Depois de converter o seu WGS84 em graus decimais, poderá fazer isto:

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

distance = google.maps.geometry.spherical.computeDistanceBetween(
    new google.maps.LatLng(fromLat, fromLng), 
    new google.maps.LatLng(toLat, toLng));

Nenhuma palavra sobre o quão precisos são os cálculos do Google ou mesmo que modelo é usado (embora ele diga "esférico" em vez de "geóide". A propósito, a distância" linha recta " será obviamente diferente da distância se se viaja na superfície da terra, que é o que todos parecem ser. presumir.

 6
Author: Steven Christenson, 2014-07-20 00:10:07

Poderia haver uma solução mais simples, e mais correta: o perímetro da terra é de 40.000 Km no Equador, cerca de 37.000 no ciclo de Greenwich (ou qualquer longitude). Assim:

pythagoras = function (lat1, lon1, lat2, lon2) {
   function sqr(x) {return x * x;}
   function cosDeg(x) {return Math.cos(x * Math.PI / 180.0);}

   var earthCyclePerimeter = 40000000.0 * cosDeg((lat1 + lat2) / 2.0);
   var dx = (lon1 - lon2) * earthCyclePerimeter / 360.0;
   var dy = 37000000.0 * (lat1 - lat2) / 360.0;

   return Math.sqrt(sqr(dx) + sqr(dy));
};
Concordo que deve ser afinado porque eu mesmo disse que é um elipsóide, por isso o raio a ser multiplicado pelo cosseno varia. Mas é um pouco mais preciso. Em comparação com o Google Maps e reduziu significativamente o erro.
 5
Author: Meymann, 2016-02-10 07:26:41

Aqui está um typescript implementação da fórmula Haversine

static getDistanceFromLatLonInKm(lat1: number, lon1: number, lat2: number, lon2: number): number {
    var deg2Rad = deg => {
        return deg * Math.PI / 180;
    }

    var r = 6371; // Radius of the earth in km
    var dLat = deg2Rad(lat2 - lat1);   
    var dLon = deg2Rad(lon2 - lon1);
    var a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(deg2Rad(lat1)) * Math.cos(deg2Rad(lat2)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = r * c; // Distance in km
    return d;
}
 4
Author: Sel, 2015-12-26 08:13:11
Todas as respostas acima assumem que a terra é uma esfera. No entanto, uma aproximação mais precisa seria a de um esferóide oblato.
a= 6378.137#equitorial radius in km
b= 6356.752#polar radius in km

def Distance(lat1, lons1, lat2, lons2):
    lat1=math.radians(lat1)
    lons1=math.radians(lons1)
    R1=(((((a**2)*math.cos(lat1))**2)+(((b**2)*math.sin(lat1))**2))/((a*math.cos(lat1))**2+(b*math.sin(lat1))**2))**0.5 #radius of earth at lat1
    x1=R*math.cos(lat1)*math.cos(lons1)
    y1=R*math.cos(lat1)*math.sin(lons1)
    z1=R*math.sin(lat1)

    lat2=math.radians(lat2)
    lons2=math.radians(lons2)
    R1=(((((a**2)*math.cos(lat2))**2)+(((b**2)*math.sin(lat2))**2))/((a*math.cos(lat2))**2+(b*math.sin(lat2))**2))**0.5 #radius of earth at lat2
    x2=R*math.cos(lat2)*math.cos(lons2)
    y2=R*math.cos(lat2)*math.sin(lons2)
    z2=R*math.sin(lat2)

    return ((x1-x2)**2+(y1-y2)**2+(z1-z2)**2)**0.5
 4
Author: Keerthana Gopalakrishnan, 2016-06-16 22:25:37

Para calcular a distância entre dois pontos numa esfera, é necessário fazer o cálculo do Grande Círculo.

Existem várias bibliotecas C / C++ para ajudar com a projecção de mapas em MapTools Se precisar de reprojectar as suas distâncias para uma superfície plana. Para isso, você precisará da cadeia de projeção dos vários sistemas de coordenadas.

Poderá também encontrar a MapWindow uma ferramenta útil para visualizar os pontos. Também como seu código aberto é um guia útil para como usar o proj.dll library, que parece ser a principal biblioteca de projeção de código aberto.

 3
Author: , 2008-10-19 01:30:09

Implementação em Python A origem é o centro dos Estados Unidos contíguos.

from haversine import haversine
origin = (39.50, 98.35)
paris = (48.8567, 2.3508)
haversine(origin, paris, miles=True)
Para obter a resposta em quilómetros, basta definir milhas = falsas.
 3
Author: invoketheshell, 2015-07-14 05:52:12

Este programa [em PHP] calcula distâncias entre os dois pontos.

public static function getDistanceOfTwoPoints($source, $dest, $unit='K') {
        $lat1 = $source[0];
        $lon1 = $source[1];
        $lat2 = $dest[0];
        $lon2 = $dest[1];

        $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);
        $miles = $dist * 60 * 1.1515;
        $unit = strtoupper($unit);

        if ($unit == "K") {
            return ($miles * 1.609344);
        }
        else if ($unit == "M")
        {
            return ($miles * 1.609344 * 1000);
        }
        else if ($unit == "N") {
            return ($miles * 0.8684);
        } 
        else {
            return $miles;
        }
    }
 3
Author: Er.Subhendu Kumar Pati, 2017-02-21 07:04:55
Eu condensei o cálculo simplificando a fórmula. Aqui está em Ruby.
include Math
earth_radius_mi = 3959
radians = lambda { |deg| deg * PI / 180 }
coord_radians = lambda { |c| { :lat => radians[c[:lat]], :lng => radians[c[:lng]] } }

# from/to = { :lat => (latitude_in_degrees), :lng => (longitude_in_degrees) }
def haversine_distance(from, to)
  from, to = coord_radians[from], coord_radians[to]
  cosines_product = cos(to[:lat]) * cos(from[:lat]) * cos(from[:lng] - to[:lng])
  sines_product = sin(to[:lat]) * sin(from[:lat])
  return earth_radius_mi * acos(cosines_product + sines_product)
end
 2
Author: Kache, 2013-06-13 02:28:45
Aqui está a implementação de respostas aceita portada para Java, caso alguém precise.
package com.project529.garage.util;


/**
 * Mean radius.
 */
private static double EARTH_RADIUS = 6371;

/**
 * Returns the distance between two sets of latitudes and longitudes in meters.
 * <p/>
 * Based from the following JavaScript SO answer:
 * http://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula,
 * which is based on https://en.wikipedia.org/wiki/Haversine_formula (error rate: ~0.55%).
 */
public double getDistanceBetween(double lat1, double lon1, double lat2, double lon2) {
    double dLat = toRadians(lat2 - lat1);
    double dLon = toRadians(lon2 - lon1);

    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
                    Math.sin(dLon / 2) * Math.sin(dLon / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double d = EARTH_RADIUS * c;

    return d;
}

public double toRadians(double degrees) {
    return degrees * (Math.PI / 180);
}
 2
Author: Eddnav, 2015-10-12 20:59:53

Há aqui um bom exemplo para calcular a distância com o PHP http://www.geodatasource.com/developers/php :

 function distance($lat1, $lon1, $lat2, $lon2, $unit) {

     $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);
     $miles = $dist * 60 * 1.1515;
     $unit = strtoupper($unit);

     if ($unit == "K") {
         return ($miles * 1.609344);
     } else if ($unit == "N") {
          return ($miles * 0.8684);
     } else {
          return $miles;
     }
 }
 1
Author: ayalcinkaya, 2013-01-15 01:48:23
Aqui está a implementação. VB.NET, esta implementação lhe dará o resultado em KM ou milhas com base em um valor Enum que você passa.
Public Enum DistanceType
    Miles
    KiloMeters
End Enum

Public Structure Position
    Public Latitude As Double
    Public Longitude As Double
End Structure

Public Class Haversine

    Public Function Distance(Pos1 As Position,
                             Pos2 As Position,
                             DistType As DistanceType) As Double

        Dim R As Double = If((DistType = DistanceType.Miles), 3960, 6371)

        Dim dLat As Double = Me.toRadian(Pos2.Latitude - Pos1.Latitude)

        Dim dLon As Double = Me.toRadian(Pos2.Longitude - Pos1.Longitude)

        Dim a As Double = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(Me.toRadian(Pos1.Latitude)) * Math.Cos(Me.toRadian(Pos2.Latitude)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)

        Dim c As Double = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)))

        Dim result As Double = R * c

        Return result

    End Function

    Private Function toRadian(val As Double) As Double

        Return (Math.PI / 180) * val

    End Function

End Class
 1
Author: Taiseer Joudeh, 2013-04-02 08:35:43

Aqui está a minha implementação java para a distância de cálculo via graus decimais após alguma pesquisa. Eu usei o raio médio do mundo (a partir da Wikipédia) em km. Se você quer o resultado milhas, então use o raio do mundo em milhas.

public static double distanceLatLong2(double lat1, double lng1, double lat2, double lng2) 
{
  double earthRadius = 6371.0d; // KM: use mile here if you want mile result

  double dLat = toRadian(lat2 - lat1);
  double dLng = toRadian(lng2 - lng1);

  double a = Math.pow(Math.sin(dLat/2), 2)  + 
          Math.cos(toRadian(lat1)) * Math.cos(toRadian(lat2)) * 
          Math.pow(Math.sin(dLng/2), 2);

  double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

  return earthRadius * c; // returns result kilometers
}

public static double toRadian(double degrees) 
{
  return (degrees * Math.PI) / 180.0d;
}
 1
Author: user2881716, 2014-02-12 20:52:42

No Mysql use a seguinte função passar os parâmetros como usar POINT(LONG,LAT)

CREATE FUNCTION `distance`(a POINT, b POINT)
 RETURNS double
    DETERMINISTIC
BEGIN

RETURN

GLength( LineString(( PointFromWKB(a)), (PointFromWKB(b)))) * 100000; -- To Make the distance in meters

END;
 1
Author: shanavascet, 2014-05-28 08:59:44
function getDistanceFromLatLonInKm(position1, position2) {
    "use strict";
    var deg2rad = function (deg) { return deg * (Math.PI / 180); },
        R = 6371,
        dLat = deg2rad(position2.lat - position1.lat),
        dLng = deg2rad(position2.lng - position1.lng),
        a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
            + Math.cos(deg2rad(position1.lat))
            * Math.cos(deg2rad(position1.lat))
            * Math.sin(dLng / 2) * Math.sin(dLng / 2),
        c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c;
}

console.log(getDistanceFromLatLonInKm(
    {lat: 48.7931459, lng: 1.9483572},
    {lat: 48.827167, lng: 2.2459745}
));
 1
Author: Raphael C, 2015-04-29 14:22:25

Aqui está um exemplo em postgres sql (em km, para a versão miles, substitua 1.609344 pela versão 0.8684)

CREATE OR REPLACE FUNCTION public.geodistance(alat float, alng float, blat  

float, blng  float)
  RETURNS float AS
$BODY$
DECLARE
    v_distance float;
BEGIN

    v_distance = asin( sqrt(
            sin(radians(blat-alat)/2)^2 
                + (
                    (sin(radians(blng-alng)/2)^2) *
                    cos(radians(alat)) *
                    cos(radians(blat))
                )
          )
        ) * cast('7926.3352' as float) * cast('1.609344' as float) ;


    RETURN v_distance;
END 
$BODY$
language plpgsql VOLATILE SECURITY DEFINER;
alter function geodistance(alat float, alng float, blat float, blng float)
owner to postgres;
 1
Author: fisc, 2016-12-21 07:34:02
Como foi referido, um cálculo preciso deve ter em conta que a terra não é uma esfera perfeita. Aqui estão algumas comparações dos vários algoritmos oferecidos aqui:
geoDistance(50,5,58,3)
Haversine: 899 km
Maymenn: 833 km
Keerthana: 897 km
google.maps.geometry.spherical.computeDistanceBetween(): 900 km

geoDistance(50,5,-58,-3)
Haversine: 12030 km
Maymenn: 11135 km
Keerthana: 10310 km
google.maps.geometry.spherical.computeDistanceBetween(): 12044 km

geoDistance(.05,.005,.058,.003)
Haversine: 0.9169 km
Maymenn: 0.851723 km
Keerthana: 0.917964 km
google.maps.geometry.spherical.computeDistanceBetween(): 0.917964 km

geoDistance(.05,80,.058,80.3)
Haversine: 33.37 km
Maymenn: 33.34 km
Keerthana: 33.40767 km
google.maps.geometry.spherical.computeDistanceBetween(): 33.40770 km

Em pequenas distâncias, o algoritmo de Keerthana parece coincidir com o do Google Maps. O Google Maps não parece seguir qualquer algoritmo simples, sugerindo que ele pode ser o método mais preciso aqui.

De qualquer forma, aqui está uma implementação Javascript do Keerthana algoritmo:
function geoDistance(lat1, lng1, lat2, lng2){
    const a = 6378.137; // equitorial radius in km
    const b = 6356.752; // polar radius in km

    var sq = x => (x*x);
    var sqr = x => Math.sqrt(x);
    var cos = x => Math.cos(x);
    var sin = x => Math.sin(x);
    var radius = lat => sqr((sq(a*a*cos(lat))+sq(b*b*sin(lat)))/(sq(a*cos(lat))+sq(b*sin(lat))));

    lat1 = lat1 * Math.PI / 180;
    lng1 = lng1 * Math.PI / 180;
    lat2 = lat2 * Math.PI / 180;
    lng2 = lng2 * Math.PI / 180;

    var R1 = radius(lat1);
    var x1 = R1*cos(lat1)*cos(lng1);
    var y1 = R1*cos(lat1)*sin(lng1);
    var z1 = R1*sin(lat1);

    var R2 = radius(lat2);
    var x2 = R2*cos(lat2)*cos(lng2);
    var y2 = R2*cos(lat2)*sin(lng2);
    var z2 = R2*sin(lat2);

    return sqr(sq(x1-x2)+sq(y1-y2)+sq(z1-z2));
}
 1
Author: Chong Lip Phang, 2018-04-19 09:14:27

Aqui está uma função javascript simples que pode ser útil a partir deste link .. de alguma forma relacionados, mas estamos usando Google earth javascript plugin em vez de mapas

function getApproximateDistanceUnits(point1, point2) {

    var xs = 0;
    var ys = 0;

    xs = point2.getX() - point1.getX();
    xs = xs * xs;

    ys = point2.getY() - point1.getY();
    ys = ys * ys;

    return Math.sqrt(xs + ys);
}

As unidades tho não estão à distância, mas em termos de proporção em relação às suas coordenadas. Existem outros cálculos relacionados que você pode substituir para a função getApproximateDistanceUnits link aqui

Então eu uso Esta função para ver se uma latitude está dentro do raio

function isMapPlacemarkInRadius(point1, point2, radi) {
    if (point1 && point2) {
        return getApproximateDistanceUnits(point1, point2) <= radi;
    } else {
        return 0;
    }
}

O ponto pode ser definido como

 $$.getPoint = function(lati, longi) {
        var location = {
            x: 0,
            y: 0,
            getX: function() { return location.x; },
            getY: function() { return location.y; }
        };
        location.x = lati;
        location.y = longi;

        return location;
    };
Então você pode fazer a sua coisa para ver se um ponto está dentro de uma região com um raio diz:
 //put it on the map if within the range of a specified radi assuming 100,000,000 units
        var iconpoint = Map.getPoint(pp.latitude, pp.longitude);
        var centerpoint = Map.getPoint(Settings.CenterLatitude, Settings.CenterLongitude);

        //approx ~200 units to show only half of the globe from the default center radius
        if (isMapPlacemarkInRadius(centerpoint, iconpoint, 120)) {
            addPlacemark(pp.latitude, pp.longitude, pp.name);
        }
        else {
            otherSidePlacemarks.push({
                latitude: pp.latitude,
                longitude: pp.longitude,
                name: pp.name
            });

        }
 0
Author: bherto39, 2012-10-17 09:12:48
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2,units) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; 
  var miles = d / 1.609344; 

if ( units == 'km' ) {  
return d; 
 } else {
return miles;
}}
A solução do Chuck, válida para quilómetros também.
 0
Author: MPaulo, 2013-11-08 06:34:35
//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;
    }
 0
Author: borchvm, 2014-06-27 17:41:41