Как найти расстояние от широты и долготы двух местах?

У меня есть набор широт и долгот мест.

  • как найти расстояние из одного места в другое?
  • есть ли формула ?

12 ответов


формула Гаверсинуса предполагает сферичность Земли. Однако форма Земли более сложная. Сплющенная модель сфероида даст лучшие результаты.

Если такая точность необходима, вам лучше использовать Vincenty обратная формула. См.http://en.wikipedia.org/wiki/Vincenty ' s_formulae для деталей. Используя его, вы можете получить точность 0.5 mm для модели сфероида.

нет совершенной формулы, так как реальная форма земля слишком сложна, чтобы ее можно было выразить формулой. Более того, форма Земли меняется из-за климатических событий (см.http://www.nasa.gov/centers/goddard/earthandsun/earthshape.html), а также изменения с течением времени из-за вращения Земли.

следует также отметить, что метод выше не учитывает высоты и предполагает наличие на уровне моря сплющенного сфероида.

Edit 10-Jul-2010: я узнал, что есть редкие ситуации для которых обратная формула Винценти не сходится к заявленной точности. Лучше использовать GeographicLib (см.http://sourceforge.net/projects/geographiclib/) который также более точен.


вот один: http://www.movable-type.co.uk/scripts/latlong.html

используя формулу 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 

применить формулу Haversine, чтобы найти расстояние. См. код C# ниже, чтобы найти расстояние между 2 координатами. Еще лучше, если вы хотите найти список магазинов, в определенном радиусе, вы могли бы применить WHERE предложение в SQL или фильтр LINQ в C# к нему.

формула здесь в километрах, вам придется изменить соответствующие номера, и она будет работать на мили.

например: преобразовать 6371.392896 в миль.

    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

если вы хотите выполнить формулу Haversine в 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 является функцией я создан, его простой 1 вкладыш"Math.PI * angle / 180.0

запись в моем блоге-SQL Haversine


ищите

формула Гаверсинуса

формула гаверсинуса это уравнение важно в навигации, давая расстояния большого круга между двумя точки На сфере от их долготы и широты. Это частный случай более общей формулы в сферической тригонометрии, закон haversines, relating the sides and углы сферических "треугольников".


взгляните на это.. имеет пример javascript, а также.

Найти Расстояние



этой ссылке имеет всю необходимую информацию, либо на нем, либо по ссылке.


вот скрипка с поиском местоположений / рядом с местоположениями long/lat по заданному IP:

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

и вот функция, которую я использую для вычисления расстояния по прямой:

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;
    }

он возвращает расстояние в километрах


на этой странице вы можете увидеть весь код и формулы, как расстояния местоположений рассчитываются в классе местоположения Android

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.4_r1/android/location/Location.java#Location.computeDistanceAndBearing%28double%2Cdouble%2Cdouble%2Cdouble%2Cfloat[]%29


Ниже приведен модуль (закодированный в f90), содержащий три формулы, рассмотренные в предыдущих ответах. Вы можете либо поставить этот модуль в верхней части вашей программы (перед программой MAIN) или скомпилируйте ее отдельно и включите каталог модуля во время компиляции.

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

Я закончил использовать SQL query

выберите , (acos (sin (input_lat 0.01745329) * sin (lattitude *0.01745329) + cos(input_lat *0.01745329)*cos (lattitude *0.01745329)*cos ((input_long-долгота)0.01745329)) 57.29577951 )* 69.16 как D from имя_таблицы


просто используйте формулу расстояния Sqrt( (x2-x1)^2 + (y2-y1)^2 )