2012-11-07 164 views
1

我想查找距離特定地點最近的城市。我已經存儲了一些我想要使用的城市的位置。我有我的位置,但我不知道如何找到離我最近的城市?查找距離特定地點最近的城市

Cities 
New York - Lat 40.714353; Long -74.005973 
Washington - Lat 38.895112; Long -77.036366 
....more cities 

My location 
Philadephia - Lat 39.952335; Long -75.163789 

那麼我應該如何比較座標找到最近的城市呢?我在C#中做計劃,但只知道algorythm的解決方案是enaught我:) 感謝所有幫助

回答

5

你應該用你高中的知識來解決這個問題,您alghorithm是:

最接近= sqrt((lat2 - lat1)^ 2 +(Long2-Long1)^ 2) 現在這給你你的空氣距離。

因此,當您爲數組值進行此操作時,可以使用asort函數來比較哪一個與您最接近。

+0

這是不完全正確。在40°N時,一定的緯度比一個經度的距離更長。請參閱http://en.wikipedia.org/wiki/Longitude#Length_of_a_degree_of_longitude –

+0

@EeroAaltonen我的回答(或者說,我給出的替代方案之一)處理這個問題,但這對於某些目的來說足夠接近,並且更快計算。我唯一的反對意見是不需要的'sqrt',它不會影響相對順序。 –

0

的距離bitween兩個點(X1,Y1)和(x2,y2)的是

d = sqrt((x1 - x2)^2 + (y1 - y2)^2) 

所以在C#中,我們將有:

public City FindNearestCity(double currentLatitude, double currentLogitude, List<City> cities) 
{ 
    Dictionary<City, double> distances = new Dictionary<City, double>(); 
    foreach (City city in cities) 
    { 
     double distance = Math.Sqrt(Math.Pow(city.latitude - currentLatitude, 2) + Math.Pow(city.Longitude - currentLogitude, 2)); 
     distances.Add(city, distance); 
    } 
    double minimumDistance = distances.Min(distance => distance.Value); 
    return distances.First(distance => distance.Value == minimumDistance).Key; 
} 
+2

爲什麼要用'Math.Sqrt'?沒有它的結果仍然會以相同的順序進行。 –

+0

@Jon Hanna你是對的。但用sqrt命名變量比較容易:) –

0

訪問here 你可以找到兩個c#函數使用蠻力和分而治之算法來查找一組給定點中兩個維度中最接近的兩個點。

+0

雖然沒有以任何方式回答問題。 –

2

嚴格來說,你想要使用Haversine formula

然而,儘管你可能在遠北或遠南的地方略微偏出一點,但你也許可以假裝墨卡託投影對距離是準確的,而忽略了地球的曲率。如果你要有很多城市,尤其如此,因爲錯誤更大,其他點來自目標點。因此,你只想用畢達哥拉斯:

relDist = √((xLat - yLat) × (xLat - yLat) + (xLng - yLng) × (xLng - yLng)) 

但因爲你只關心(並且只得到)的相對排序,你可以跳過平方根位,這是最重的步:

relDist = (xLat - yLat) × (xLat - yLat) + (xLng - yLng) × (xLng - yLng) 
如果您將座標存儲爲實際座標的倍數(例如,將紐約(40.664167,-73.938611)存儲爲一對(406642, - ),則可以合理預整型爲整數, 739386)如果你想快速地將大量的地點按照接近指定點的順序排序,這可能是一個很大的提升。

然而,如果你真的關心精度的事實,地球是圓的,面部,隨後下列工具半正矢:

private const double radiusE = 6378135; // Equatorial radius 
private const double radiusP = 6356750; // Polar radius 
private const double radianConv = 180/Math.PI; 
public static double GetDistanceBetweenPoints(double lat1, double long1, double lat2, double long2) 
{ 
    double dLat = (lat2 - lat1)/radianConv; 
    double dLong = (long2 - long1)/radianConv; 
    double a = Math.Sin(dLat/2) * Math.Sin(dLat/2) + Math.Cos(lat2) * Math.Sin(dLong/2) * Math.Sin(dLong/2); 
    return Math.Sqrt((Math.Pow(radiusE * radiusP * Math.Cos(lat1/radianConv), 2))/(Math.Pow(radiusE * Math.Cos(lat1/radianConv), 2) + Math.Pow(radiusP * Math.Sin(lat1/radianConv), 2))) * (2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a))); 
}