2011-06-16 160 views
85

我正在計算兩個地理座標之間的距離。我正在測試我的應用程序對3-4其他應用程序。當我計算距離時,我的計算結果平均爲3.3英里,而其他應用則爲3.5英里。對於我正在嘗試執行的計算而言,這是一個很大的區別。有沒有好的課程庫用於計算距離?我在C#中計算它是這樣的:計算兩個緯度和經度地理座標之間的距離

public static double Calculate(double sLatitude,double sLongitude, double eLatitude, 
           double eLongitude) 
{ 
    var radiansOverDegrees = (Math.PI/180.0); 

    var sLatitudeRadians = sLatitude * radiansOverDegrees; 
    var sLongitudeRadians = sLongitude * radiansOverDegrees; 
    var eLatitudeRadians = eLatitude * radiansOverDegrees; 
    var eLongitudeRadians = eLongitude * radiansOverDegrees; 

    var dLongitude = eLongitudeRadians - sLongitudeRadians; 
    var dLatitude = eLatitudeRadians - sLatitudeRadians; 

    var result1 = Math.Pow(Math.Sin(dLatitude/2.0), 2.0) + 
        Math.Cos(sLatitudeRadians) * Math.Cos(eLatitudeRadians) * 
        Math.Pow(Math.Sin(dLongitude/2.0), 2.0); 

    // Using 3956 as the number of miles around the earth 
    var result2 = 3956.0 * 2.0 * 
        Math.Atan2(Math.Sqrt(result1), Math.Sqrt(1.0 - result1)); 

    return result2; 
} 

我該做什麼錯?我應該先計算公里數,然後轉換爲英里數嗎?

+1

地球平均半徑= 6,371千米=3958.76英里 – 2011-06-16 02:14:39

+1

http://stackoverflow.com/questions/27928/how-do-i-calculate-distance-between-two-latitude-longitude-points – 2011-06-16 02:19:28

+0

不應該這是對gis.stackexchange.com – 2011-06-16 02:22:25

回答

221

GeoCoordinate類(.NET Framework 4及更高版本)已經有GetDistanceTo方法。

var sCoord = new GeoCoordinate(sLatitude, sLongitude); 
var eCoord = new GeoCoordinate(eLatitude, eLongitude); 

return sCoord.GetDistanceTo(eCoord); 

該距離以米爲單位。

您需要引用System.Device。

+1

+1。好的!! – 2011-06-16 10:02:21

+0

Nigel,你確定DistanceTo方法可以在手機上使用嗎?我認爲它使用了WP7的GeoCoordinate 2.0版本。 – 2011-06-17 05:20:44

+1

我沒有檢查過,設備的GeoCordinate有一個GetDistanceTo方法,這是你所引用的(但不是你上面的)。沒什麼大不了。我要測試一下,看看內置的計算是否更好。謝謝奈傑爾! – 2011-06-17 05:37:49

3

地球平均半徑=6371公里=3958.76英里

而不是使用var我建議你使用double,只是要明確。

10

下面是JavaScript版本球員和加爾斯

function distanceTo(lat1, lon1, lat2, lon2, unit) { 
     var rlat1 = Math.PI * lat1/180 
     var rlat2 = Math.PI * lat2/180 
     var rlon1 = Math.PI * lon1/180 
     var rlon2 = Math.PI * lon2/180 
     var theta = lon1-lon2 
     var rtheta = Math.PI * theta/180 
     var dist = Math.sin(rlat1) * Math.sin(rlat2) + Math.cos(rlat1) * Math.cos(rlat2) * Math.cos(rtheta); 
     dist = Math.acos(dist) 
     dist = dist * 180/Math.PI 
     dist = dist * 60 * 1.1515 
     if (unit=="K") { dist = dist * 1.609344 } 
     if (unit=="N") { dist = dist * 0.8684 } 
     return dist 
} 
0

試試這個:

public double getDistance(GeoCoordinate p1, GeoCoordinate p2) 
    { 
     double d = p1.Latitude * 0.017453292519943295; 
     double num3 = p1.Longitude * 0.017453292519943295; 
     double num4 = p2.Latitude * 0.017453292519943295; 
     double num5 = p2.Longitude * 0.017453292519943295; 
     double num6 = num5 - num3; 
     double num7 = num4 - d; 
     double num8 = Math.Pow(Math.Sin(num7/2.0), 2.0) + ((Math.Cos(d) * Math.Cos(num4)) * Math.Pow(Math.Sin(num6/2.0), 2.0)); 
     double num9 = 2.0 * Math.Atan2(Math.Sqrt(num8), Math.Sqrt(1.0 - num8)); 
     return (6376500.0 * num9); 
    } 
2

基於艾略特伍德的功能,這個C函數是工作...

#define SIM_Degree_to_Radian(x) ((float)x * 0.017453292F) 
#define SIM_PI_VALUE       (3.14159265359) 

float GPS_Distance(float lat1, float lon1, float lat2, float lon2) 
{ 
    float theta; 
    float dist; 

    theta = lon1 - lon2; 

    lat1 = SIM_Degree_to_Radian(lat1); 
    lat2 = SIM_Degree_to_Radian(lat2); 
    theta = SIM_Degree_to_Radian(theta); 

    dist = (sin(lat1) * sin(lat2)) + (cos(lat1) * cos(lat2) * cos(theta)); 
    dist = acos(dist); 

// dist = dist * 180.0/SIM_PI_VALUE; 
// dist = dist * 60.0 * 1.1515; 
// /* Convert to km */ 
// dist = dist * 1.609344; 

    dist *= 6370.693486F; 

    return (dist); 
} 

您可以將其更改爲double。它以km爲單位返回值。

70

getDistance的是最好的解決辦法,但在很多情況下,我們不能使用這個方法(如通用的應用程序)的算法

  • 計算之間的距離 coorindates:

    public static double DistanceTo(double lat1, double lon1, double lat2, double lon2, char unit = 'K') 
    { 
        double rlat1 = Math.PI*lat1/180; 
        double rlat2 = Math.PI*lat2/180; 
        double theta = lon1 - lon2; 
        double rtheta = Math.PI*theta/180; 
        double dist = 
         Math.Sin(rlat1)*Math.Sin(rlat2) + Math.Cos(rlat1)* 
         Math.Cos(rlat2)*Math.Cos(rtheta); 
        dist = Math.Acos(dist); 
        dist = dist*180/Math.PI; 
        dist = dist*60*1.1515; 
    
        switch (unit) 
        { 
         case 'K': //Kilometers -> default 
          return dist*1.609344; 
         case 'N': //Nautical Miles 
          return dist*0.8684; 
         case 'M': //Miles 
          return dist; 
        } 
    
        return dist; 
    } 
    
  • 真實世界的C#實現,這使得使用擴展方法的

    用法:

    var distance = new Coordinates(48.672309, 15.695585) 
           .DistanceTo(
            new Coordinates(48.237867, 16.389477), 
            UnitOfLength.Kilometers 
           ); 
    

    實現:

    public class Coordinates 
    { 
        public double Latitude { get; private set; } 
        public double Longitude { get; private set; } 
    
        public Coordinates(double latitude, double longitude) 
        { 
         Latitude = latitude; 
         Longitude = longitude; 
        } 
    } 
    public static class CoordinatesDistanceExtensions 
    { 
        public static double DistanceTo(this Coordinates baseCoordinates, Coordinates targetCoordinates) 
        { 
         return DistanceTo(baseCoordinates, targetCoordinates, UnitOfLength.Kilometers); 
        } 
    
        public static double DistanceTo(this Coordinates baseCoordinates, Coordinates targetCoordinates, UnitOfLength unitOfLength) 
        { 
         var baseRad = Math.PI * baseCoordinates.Latitude/180; 
         var targetRad = Math.PI * targetCoordinates.Latitude/ 180; 
         var theta = baseCoordinates.Longitude - targetCoordinates.Longitude; 
         var thetaRad = Math.PI * theta/180; 
    
         double dist = 
          Math.Sin(baseRad) * Math.Sin(targetRad) + Math.Cos(baseRad) * 
          Math.Cos(targetRad) * Math.Cos(thetaRad); 
         dist = Math.Acos(dist); 
    
         dist = dist * 180/Math.PI; 
         dist = dist * 60 * 1.1515; 
    
         return unitOfLength.ConvertFromMiles(dist); 
        } 
    } 
    
    public class UnitOfLength 
    { 
        public static UnitOfLength Kilometers = new UnitOfLength(1.609344); 
        public static UnitOfLength NauticalMiles = new UnitOfLength(0.8684); 
        public static UnitOfLength Miles = new UnitOfLength(1); 
    
        private readonly double _fromMilesFactor; 
    
        private UnitOfLength(double fromMilesFactor) 
        { 
         _fromMilesFactor = fromMilesFactor; 
        } 
    
        public double ConvertFromMiles(double input) 
        { 
         return input*_fromMilesFactor; 
        } 
    } 
    
+0

你能提供用於這個微積分的公式嗎,或者可以提供一些關於什麼線的評論?我需要改變的是什麼,直接得到以Km爲單位的距離而不是轉換成英里? – AlbertFM 2018-01-08 14:50:41

+0

他是繼[此頁](https://www.movable-type.co.uk/scripts/latlong.html) – 2018-02-15 12:32:52

+0

感謝一個很好的解決方案,我現在可以在我的桌面應用程序中使用它。 – CodeIt 2018-03-02 15:59:53

2

計算緯度和經度點之間的距離...

 double Lat1 = Convert.ToDouble(latitude); 
     double Long1 = Convert.ToDouble(longitude); 

     double Lat2 = 30.678; 
     double Long2 = 45.786; 
     double circumference = 40000.0; // Earth's circumference at the equator in km 
     double distance = 0.0; 
     double latitude1Rad = DegreesToRadians(Lat1); 
     double latititude2Rad = DegreesToRadians(Lat2); 
     double longitude1Rad = DegreesToRadians(Long1); 
     double longitude2Rad = DegreesToRadians(Long2); 
     double logitudeDiff = Math.Abs(longitude1Rad - longitude2Rad); 
     if (logitudeDiff > Math.PI) 
     { 
      logitudeDiff = 2.0 * Math.PI - logitudeDiff; 
     } 
     double angleCalculation = 
      Math.Acos(
       Math.Sin(latititude2Rad) * Math.Sin(latitude1Rad) + 
       Math.Cos(latititude2Rad) * Math.Cos(latitude1Rad) * Math.Cos(logitudeDiff)); 
     distance = circumference * angleCalculation/(2.0 * Math.PI); 
     return distance; 
0

您可以使用System.device.Location

System.device.Location.GeoCoordinate gc = new System.device.Location.GeoCoordinate(){ 
Latitude = yourLatitudePt1, 
Longitude = yourLongitudePt1 
}; 

System.device.Location.GeoCoordinate gc2 = new System.device.Location.GeoCoordinate(){ 
Latitude = yourLatitudePt2, 
Longitude = yourLongitudePt2 
}; 

Double distance = gc2.getDistanceTo(gc); 

好運

3

對於那些誰正在使用Xamarin並沒有進入會有地理座標類,你可以使用Android的位置類,而不是:

public static double GetDistanceBetweenCoordinates (double lat1, double lng1, double lat2, double lng2) { 
      var coords1 = new Location (""); 
      coords1.Latitude = lat1; 
      coords1.Longitude = lng1; 
      var coords2 = new Location (""); 
      coords2.Latitude = lat2; 
      coords2.Longitude = lng2; 
      return coords1.DistanceTo (coords2); 
     } 
相關問題