2009-09-14 19 views

Respuesta

26

La fórmula Haversine asume una tierra esférica. Sin embargo, la forma de la oreja es más compleja. Un modelo de esferoide oblato dará mejores resultados.

Si tal precisión es necesaria, debería utilizar mejor Vincenty inverse formula. Ver http://en.wikipedia.org/wiki/Vincenty's_formulae para más detalles. Utilizándolo, puede obtener una precisión de 0,5 mm para el modelo de esferoides.

No existe una fórmula perfecta, ya que la forma real de la tierra es demasiado compleja para ser expresada por una fórmula. Además, la forma de la Tierra cambia debido a los eventos climáticos (ver http://www.nasa.gov/centers/goddard/earthandsun/earthshape.html), y también cambia con el tiempo debido a la rotación de la tierra.

También debe tener en cuenta que el método anterior no tiene en cuenta las altitudes, y asume un esferoide oblato a nivel del mar.

Edit 10-Jul-2010: Descubrí que hay situaciones excepcionales para las que la fórmula inversa de Vincenty no converge a la precisión declarada. Una mejor idea es usar GeographicLib (ver http://sourceforge.net/projects/geographiclib/) que también es más preciso.

+2

+1 esto atrapó a algunas personas con la guardia baja en un empleador anterior. –

+0

De hecho. Cuando los valores no pueden estar a más de unos pocos metros de distancia, esta pregunta se vuelve mucho más complicada. – PeterAllenWebb

+0

+1 para "la respuesta depende del grado de precisión requerido" – Piskvor

4

¿Está buscando

Haversine formula

La fórmula haversine es una ecuación importante en la navegación, dando distancias de círculo máximo entre dos puntos sobre una esfera de sus longitudes y latitudes Es un caso especial de una fórmula más general en trigonometría esférica, la ley de haversines, que relaciona los lados y ángulos de "triángulos" esféricos.

2

This link tiene toda la información que necesita, ya sea en ella o vinculada.

4

Eche un vistazo a esto .. también tiene un ejemplo de JavaScript.

Find Distance

+0

Muy bueno! buen hallazgo –

9

Aquí hay uno: http://www.movable-type.co.uk/scripts/latlong.html

Uso de fórmula Haversine:

R = earth’s radius (mean radius = 6,371km) 
Δlat = lat2− lat1 
Δlong = long2− long1 
a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2) 
c = 2.atan2(√a, √(1−a)) 
d = R.c 
5

Aplica la fórmula Haversine para encontrar la distancia. Vea el código de C# a continuación para encontrar la distancia entre 2 coordenadas.Mejor aún si quiere decir encontrar una lista de tiendas dentro de un cierto radio, puede aplicar una cláusula WHERE en SQL o un filtro LINQ en C#.

La fórmula aquí está en kilómetros, tendrá que cambiar los números correspondientes y funcionará por millas.

Por ej .: Convertir 6371.392896 a millas.

DECLARE @radiusInKm AS FLOAT 
    DECLARE @lat2Compare AS FLOAT 
    DECLARE @long2Compare AS FLOAT 
    SET @radiusInKm = 5.000 
    SET @lat2Compare = insert_your_lat_to_compare_here 
    SET @long2Compare = insert_you_long_to_compare_here 

    SELECT * FROM insert_your_table_here WITH(NOLOCK) 
    WHERE (6371.392896*2*ATN2(SQRT((sin((radians(GeoLatitude - @lat2Compare))/2) * sin((radians(GeoLatitude - @lat2Compare))/2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2))) 
    , SQRT(1-((sin((radians(GeoLatitude - @lat2Compare))/2) * sin((radians(GeoLatitude - @lat2Compare))/2)) + (cos(radians(GeoLatitude)) * cos(radians(@lat2Compare)) * sin(radians(GeoLongitude - @long2Compare)/2) * sin(radians(GeoLongitude - @long2Compare)/2))) 
    ))) <= @radiusInKm 

Si desea llevar a cabo la fórmula Haversine en C#,

double resultDistance = 0.0; 
    double avgRadiusOfEarth = 6371.392896; //Radius of the earth differ, I'm taking the average. 

    //Haversine formula 
    //distance = R * 2 * aTan2 (square root of A, square root of 1 - A) 
    //     where A = sinus squared (difference in latitude/2) + (cosine of latitude 1 * cosine of latitude 2 * sinus squared (difference in longitude/2)) 
    //     and R = the circumference of the earth 

    double differenceInLat = DegreeToRadian(currentLatitude - latitudeToCompare); 
    double differenceInLong = DegreeToRadian(currentLongitude - longtitudeToCompare); 
    double aInnerFormula = Math.Cos(DegreeToRadian(currentLatitude)) * Math.Cos(DegreeToRadian(latitudeToCompare)) * Math.Sin(differenceInLong/2) * Math.Sin(differenceInLong/2); 
    double aFormula = (Math.Sin((differenceInLat)/2) * Math.Sin((differenceInLat)/2)) + (aInnerFormula); 
    resultDistance = avgRadiusOfEarth * 2 * Math.Atan2(Math.Sqrt(aFormula), Math.Sqrt(1 - aFormula)); 

DegreesToRadian es una función que he creado a medida, su es un simple 1 forro de "Math.PI * angle/180.0

My blog entry - SQL Haversine

-1

simplemente use la fórmula de distancia Sqrt((x2-x1)^2 + (y2-y1)^2)

1

aquí es un violín con la búsqueda de localizaciones/cerca de lugares a largo/lat por determinada IP:

http://jsfiddle.net/bassta/zrgd9qc3/2/

Y aquí es la función que utilizo para calcular la distancia en línea recta:

function distance(lat1, lng1, lat2, lng2) { 
     var radlat1 = Math.PI * lat1/180; 
     var radlat2 = Math.PI * lat2/180; 
     var radlon1 = Math.PI * lng1/180; 
     var radlon2 = Math.PI * lng2/180; 
     var theta = lng1 - lng2; 
     var radtheta = Math.PI * theta/180; 
     var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta); 
     dist = Math.acos(dist); 
     dist = dist * 180/Math.PI; 
     dist = dist * 60 * 1.1515; 

     //Get in in kilometers 
     dist = dist * 1.609344; 

     return dist; 
    } 

Devuelve la distancia en los kilómetros

0

Siguiendo es el módulo (codificado en f90) que contiene tres fórmulas discutidos en las respuestas anteriores. Puede colocar este módulo en la parte superior de su programa (antes de PROGRAM PRINCIPAL) o compilarlo por separado e incluir el directorio del módulo durante la compilación.

module spherical_dists 
contains 
subroutine haversine_formula(lon1,lat1,lon2,lat2,dist) 
implicit none 
real,intent(in)::lon1,lon2,lat1,lat2 
real,intent(out)::dist 
real,parameter::pi=3.141592,mean_earth_radius=6371.0088 
real::lonr1,lonr2,latr1,latr2 
real::delangl,dellon,dellat,a 
lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.) 
latr1=lat1*(pi/180.);latr2=lat2*(pi/180.) 
dellon=lonr2-lonr1 
dellat=latr2-latr1 
a=(sin(dellat/2))**2+cos(latr1)*cos(latr2)*(sin(dellon/2))**2 
delangl=2*asin(sqrt(a)) !2*asin(sqrt(a)) 
dist=delangl*mean_earth_radius 
end subroutine 
subroutine great_circle_distance(lon1,lat1,lon2,lat2,dist) 
implicit none 
real,intent(in)::lon1,lon2,lat1,lat2 
real,intent(out)::dist 
real,parameter::pi=3.141592,mean_earth_radius=6371.0088 
real::lonr1,lonr2,latr1,latr2 
real::delangl,dellon 
lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.) 
latr1=lat1*(pi/180.);latr2=lat2*(pi/180.) 
dellon=lonr2-lonr1 
delangl=acos(sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon)) 
dist=delangl*mean_earth_radius 
end subroutine 
subroutine vincenty_formula(lon1,lat1,lon2,lat2,dist) 
implicit none 
real,intent(in)::lon1,lon2,lat1,lat2 
real,intent(out)::dist 
real,parameter::pi=3.141592,mean_earth_radius=6371.0088 
real::lonr1,lonr2,latr1,latr2 
real::delangl,dellon,nom,denom 
lonr1=lon1*(pi/180.);lonr2=lon2*(pi/180.) 
latr1=lat1*(pi/180.);latr2=lat2*(pi/180.) 
dellon=lonr2-lonr1 
nom=sqrt((cos(latr2)*sin(dellon))**2. + (cos(latr1)*sin(latr2)-sin(latr1)*cos(latr2)*cos(dellon))**2.) 
denom=sin(latr1)*sin(latr2)+cos(latr1)*cos(latr2)*cos(dellon) 
delangl=atan2(nom,denom) 
dist=delangl*mean_earth_radius 
end subroutine 
end module 
0

ha terminado de usarlo consulta SQL

seleccione , (acos (sin (input_lat 0,01745329) * sen (LAttitude * 0,01745329) + cos (input_lat * 0,01745329) * cos (LAttitude * 0,01745329) * cos ((input_long -longitude) 0.01745329)) 57.29577951) * 69.16 Como D desde table_name

Cuestiones relacionadas