Расчет расстояния между двумя географическими координатами широты и долготы
Я вычисления расстояния между двумя географические координаты. Я тестирую свое приложение против 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;
}
что я могу делать неправильно? Должен ли я рассчитать его в км сначала, а потом конвертировать в мили?
10 ответов:
The GeoCoordinate класс (.NET Framework 4 и выше) уже имеет
GetDistanceToметод.var sCoord = new GeoCoordinate(sLatitude, sLongitude); var eCoord = new GeoCoordinate(eLatitude, eLongitude); return sCoord.GetDistanceTo(eCoord);расстояние в метрах.
вам нужна справочная система.Устройство.
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#, который использует
вот версия JavaScript guys and gals
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 }
для тех, кто использует Xamarin и не имеет доступа к классу GeoCoordinate, вы можете использовать класс местоположения 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); }
средний радиус Земли = 6,371 км = 3958,76 миль
а не использовать
varЯ предлагаю вам использоватьdouble, просто чтобы быть явными.
основываясь на функции Эллиота Вуда, эта функция 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 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;
и вот, для тех, кого все еще не устраивает, оригинальный код из .NET-фреймворков
GeoCoordinateкласс, преобразованный в автономный метод:public double GetDistance(double longitude, double latitude, double otherLongitude, double otherLatitude) { var d1 = latitude * (Math.PI / 180.0); var num1 = longitude * (Math.PI / 180.0); var d2 = otherLatitude * (Math.PI / 180.0); var num2 = otherLongitude * (Math.PI / 180.0) - num1; var d3 = Math.Pow(Math.Sin((d2 - d1) / 2.0), 2.0) + Math.Cos(d1) * Math.Cos(d2) * Math.Pow(Math.Sin(num2 / 2.0), 2.0); return 6376500.0 * (2.0 * Math.Atan2(Math.Sqrt(d3), Math.Sqrt(1.0 - d3))); }
попробуйте это:
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); }
можно использовать
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);удачи
Comments