두 개의 GeoCoordinates 사이의 거리를 계산하고 있습니다. 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;
}
내가 뭘 잘못하고 있니? 먼저 km 단위로 계산 한 다음 마일로 변환해야합니까?
답변
정보 좌표 클래스 (.NET 프레임 워크 4 이상) 이미이 GetDistanceTo
방법을.
var sCoord = new GeoCoordinate(sLatitude, sLongitude);
var eCoord = new GeoCoordinate(eLatitude, eLongitude);
return sCoord.GetDistanceTo(eCoord);
거리는 미터입니다.
System.Device를 참조해야합니다.
답변
GetDistance가 가장 좋은 솔루션 이지만 대부분의 경우이 방법 (예 : Universal App)을 사용할 수 없습니다
-
코디네이션 사이 의 거리 를 계산하기 위한 알고리즘의 의사 코드 :
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; }
-
확장 메서드를 사용하는 Real World 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; } }
답변
그리고 여전히 만족스럽지 않은 사람들을 위해 .NET-Frameworks 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)));
}
답변
다음은 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
}
답변
Xamarin을 사용하고 있고 GeoCoordinate 클래스에 액세스 할 수없는 사용자는 대신 Android Location 클래스를 사용할 수 있습니다.
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);
}
답변
이 기능을 사용할 수 있습니다 :
출처 : https://www.geodatasource.com/developers/c-sharp
private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
if ((lat1 == lat2) && (lon1 == lon2)) {
return 0;
}
else {
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == 'K') {
dist = dist * 1.609344;
} else if (unit == 'N') {
dist = dist * 0.8684;
}
return (dist);
}
}
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:: This function converts decimal degrees to radians :::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//:: This function converts radians to decimal degrees :::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
private double rad2deg(double rad) {
return (rad / Math.PI * 180.0);
}
Console.WriteLine(distance(32.9697, -96.80322, 29.46786, -98.53506, "M"));
Console.WriteLine(distance(32.9697, -96.80322, 29.46786, -98.53506, "K"));
Console.WriteLine(distance(32.9697, -96.80322, 29.46786, -98.53506, "N"));
답변
이 플랫폼을위한 이 라이브러리 GeoCoordinate 가 있습니다 :
- 단 핵증
- .NET 4.5
- .NET 코어
- 윈도우 폰 8.x
- 범용 Windows 플랫폼
- Xamarin iOS
- Xamarin 안드로이드
NuGet을 통해 설치가 완료됩니다.
PM> 설치 패키지 지리 좌표
용법
GeoCoordinate pin1 = new GeoCoordinate(lat, lng);
GeoCoordinate pin2 = new GeoCoordinate(lat, lng);
double distanceBetween = pin1.GetDistanceTo(pin2);
두 좌표 사이의 거리 ( 미터) 입니다.