2009-09-14 109 views

回答

26

haversine公式假定地球是一個球形。但是,耳朵的形狀更復雜。扁球模型會給出更好的結果。

如果需要這樣的準確度,您最好使用Vincenty逆公式。 有關詳細信息,請參閱http://en.wikipedia.org/wiki/Vincenty's_formulae。使用它,您可以獲得0.5毫米的球體模型精度。

沒有完美的公式,因爲地球的真實形狀太複雜,無法用公式表達。此外,地球的形狀因氣候事件而變化(見http://www.nasa.gov/centers/goddard/earthandsun/earthshape.html),並且隨着時間的推移也會隨着地球的旋轉而變化。

你還應該注意,上面的方法並沒有考慮到海拔高度,並且假定了一個海平面扁球體。

編輯10-Jul-2010:我發現有很少的情況下Vincenty逆公式不會收斂到聲明的精度。更好的主意是使用GeographicLib(參見http://sourceforge.net/projects/geographiclib/),這也更準確。

+2

+1這引起了前幾位僱主的不安。 – 2009-09-14 16:34:56

+0

確實。當價值不能超過幾米時,這個問題變得更加複雜。 – PeterAllenWebb 2009-09-17 17:45:11

+0

+1爲「答案取決於所需的準確度」 – Piskvor 2010-09-26 16:19:34

4

您是否在尋找

Haversine formula

haversine公式是一個公式 導航重要的是,給二 點之間 大圓距離上的球體從他們 經度和緯度。這是一個 特殊情況下的一個更通用的公式 在球面三角,規則 肌腱,側面和 球形「三角形」的角度。

4

看看這個..也有一個javascript的例子。

Find Distance

+0

非常酷!不錯的發現 – 2010-09-27 16:34:53

9

這裏有一個: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 
5

應用Haversine公式來查找距離。請參閱下面的C#代碼來查找2個座標之間的距離。更好的是,如果你想說在一定範圍內找到商店列表,你可以在SQL中應用WHERE子句或者在C#中應用LINQ過濾器。

這裏的公式是以公里爲單位,你將不得不改變相關的數字,它將以英里爲單位。

例如:將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 

如果你想在C#中執行haversine公式,

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

My blog entry - SQL Haversine

-1

只使用距離公式Sqrt((x2-x1)^2 + (y2-y1)^2)

1

這裏是由給定的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; 
    } 

它返回以公里爲單位的距離

0

以下是包含在以前的答案討論三個公式的模塊(F90編碼的)。你可以把這個模塊放在程序的頂部 (PROGRAM 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 
0

我使用SQL查詢

選擇,(ACOS(罪(做input_lat 0.01745329)*罪(lattitude * 0.01745329)+ COS(input_lat * 0.01745329)* COS(lattitude * 0.01745329) * cos((input_long-longitude)0.01745329)) 57.29577951)* 69.16由表D中的D

相關問題