Вы захотите использовать для этого правильную формулу расстояния, если не хотите получать странные результаты:
double CalculateDistance(double lat1, double lon1, double lat2, double lon2)
{
const double R = 6371;
return Math.Acos(
Math.Sin(lat1) * Math.Sin(lat2) +
Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(lon2 - lon1)) * R;
}
Я надеюсь, что это правильная формула, моя математика может быть немного ржавой здесь. Все параметры должны быть в rads, поэтому, если вы берете ввод в градусах, напишите также служебный метод:
double DegToRad(double deg)
{
return deg * Math.PI / 180.0;
}
В любом случае, после этого вы можете определить кратчайшее расстояние как:
Location GetClosestLocation(Location origin)
{
double olatr = DegToRad(origin.Lat);
double olonr = DegToRad(origin.Lon);
return
(from l in locations
let latr = DegToRad(l.Lat)
let lonr = DegToRad(l.Lon)
orderby CalculateDistance(latr, lonr, olatr, olonr))
.FirstOrDefault();
}
Технически это не самое эффективное решение, так как оно должно выполнять сортировку, но нет красивого метода расширения Linq, который бы делал min с проекцией. Если вы хотите этого, вам нужно написать собственный цикл foreach
:
Location GetClosestLocation(Location origin)
{
double olatr = DegToRad(origin.Lat);
double olonr = DegToRad(origin.Lon);
Location closest = null;
double minDistance = double.MaxValue;
foreach (Location l in locations)
{
double latr = DegToRad(l.Lat);
double lonr = DegToRad(l.Lon);
double dist = CalculateDistance(latr, lonr, olatr, olonr));
if (dist < minDistance)
{
minDistance = dist;
closest = l;
}
}
return closest;
}