2009-09-14 73 views

Trả lời

26

Công thức Haversine giả định một trái đất hình cầu. Tuy nhiên, hình dạng của tai là phức tạp hơn. Một mô hình hình cầu hình cầu sẽ cho kết quả tốt hơn.

Nếu độ chính xác như vậy là cần thiết, bạn nên sử dụng tốt hơn Công thức nghịch đảo Vincenty. Xem http://en.wikipedia.org/wiki/Vincenty's_formulae để biết chi tiết. Sử dụng nó, bạn có thể nhận được độ chính xác 0.5mm cho mô hình hình cầu.

Không có công thức hoàn hảo, vì hình dạng thật của trái đất quá phức tạp để thể hiện bằng công thức. Hơn nữa, hình dạng của trái đất thay đổi do các biến cố khí hậu (xem http://www.nasa.gov/centers/goddard/earthandsun/earthshape.html), và cũng thay đổi theo thời gian do sự quay của trái đất.

Bạn cũng nên lưu ý rằng phương pháp trên không tính đến độ cao và giả định một hình cầu có kích thước bằng mực nước biển.

Chỉnh sửa 10-Jul-2010: Tôi phát hiện ra rằng có một số trường hợp hiếm hoi mà công thức nghịch đảo của Vincenty không hội tụ với độ chính xác được khai báo. Ý tưởng tốt hơn là sử dụng GeographicLib (xem http://sourceforge.net/projects/geographiclib/) cũng chính xác hơn.

+2

+1 này bắt gặp khá một vài người mất cảnh giác tại một chủ nhân trước đó. –

+0

Thật vậy. Khi các giá trị không thể dài hơn vài mét, câu hỏi này sẽ phức tạp hơn nhiều. – PeterAllenWebb

+0

+1 cho "câu trả lời tùy thuộc vào mức độ chính xác được yêu cầu" – Piskvor

4

Bạn đang tìm kiếm

Haversine formula

Công thức haversine là một phương trình quan trọng trong việc chuyển hướng, đưa ra khoảng cách rất xa vòng tròn giữa hai điểm trên một quả cầu từ kinh độ và họ vĩ độ. Đó là một trường hợp đặc biệt của một công thức tổng quát hơn trong lượng giác cầu, pháp luật của haversines, liên quan các bên và các góc của hình tam giác "hình cầu".

2

This link có tất cả thông tin bạn cần, trên đó hoặc được liên kết.

4

Hãy xem ví dụ này .. cũng có một ví dụ javascript.

Find Distance

+0

Rất tuyệt! tốt đẹp tìm thấy –

9

Dưới đây là một: http://www.movable-type.co.uk/scripts/latlong.html

Sử dụng công thức 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

Áp dụng công thức Haversine để tìm khoảng cách. Xem mã C# dưới đây để tìm khoảng cách giữa 2 tọa độ.Vẫn tốt hơn nếu bạn muốn nói tìm danh sách các cửa hàng trong một bán kính nhất định, bạn có thể áp dụng mệnh đề WHERE trong SQL hoặc bộ lọc LINQ trong C# cho nó.

Công thức ở đây là bằng km, bạn sẽ phải thay đổi số liên quan và nó sẽ làm việc hàng dặm.

ví dụ: Chuyển đổi 6371,392896 để dặm.

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 

Nếu bạn muốn thực hiện công thức Haversine trong 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 là một chức năng tôi tùy chỉnh được tạo ra, nó là 1 lót đơn giản của "Math.PI * angle/180.0

My blog entry - SQL Haversine

-1

chỉ cần sử dụng công thức khoảng cách Sqrt((x2-x1)^2 + (y2-y1)^2)

1

đây là một fiddle với việc tìm kiếm địa điểm/gần địa điểm để dài/lat bởi IP đưa ra:

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

Và đây là chức năng tôi sử dụng để tính toán khoảng cách trong đường thẳng:

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

Trả về khoảng cách tính bằng Kilômét

0

Sau đây là mô-đun (mã hóa trong F90) có chứa ba công thức thảo luận trong các câu trả lời trước. Bạn có thể đặt mô-đun này ở đầu chương trình (trước MAOG CHÍNH) hoặc biên dịch riêng rẽ và bao gồm thư mục mô-đun trong quá trình biên dịch.

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

Tôi đang thực hiện sử dụng SQL query

chọn , (acos (sin (input_lat 0,01745329) * sin (lattitude * 0,01745329) + cos (input_lat * 0,01745329) * cos (lattitude * 0,01745329) * cos ((input_long-longitude) 0.01745329)) 57.29577951) * 69.16 Khi D từ tên_bảng

Các vấn đề liên quan