Найдите ближайшее место с долготой и широтой
Я работаю над приложением, где мне нужно найти место рядом,
мой веб-сервис получит 2 параметра (десятичная долгота, десятичная широта)
У меня есть таблица, где местоположения сохраняются в базе данных с полями долготы и широты,
Я хочу получить ближайшие местоположения.
Может ли кто-нибудь помочь?
Вот мой код:
var locations = from l in locations
select l
Подробнее об этом:
У меня есть 2 поля (десятичное (18, 2) null) 1 широта, 2 долготы внутри таблицы базы данных,
и у меня есть метод
public List<Locations> GetLocation(decimal? Long, decimal? lat)
{
var Loc = from l in Locations
//// now here is how to get nearest location ? how to query?
//// i have also tried Math.Abs(l.Lat - lat) its giving error about nullable decimal always hence i have seted decimal to nullable or converted to nullable
//// also i have tried where (l.lat - Lat) * (l.lon - Long) this is also giving error about can not convert decimal to bool
return Loc.ToList();
}
Ответы
Ответ 1
Вот решение
var constValue = 57.2957795130823D
var constValue2 = 3958.75586574D;
var searchWithin = 20;
double latitude = ConversionHelper.SafeConvertToDoubleCultureInd(Latitude, 0),
longitude = ConversionHelper.SafeConvertToDoubleCultureInd(Longitude, 0);
var loc = (from l in DB.locations
let temp = Math.Sin(Convert.ToDouble(l.Latitude) / constValue) * Math.Sin(Convert.ToDouble(latitude) / constValue) +
Math.Cos(Convert.ToDouble(l.Latitude) / constValue) *
Math.Cos(Convert.ToDouble(latitude) / constValue) *
Math.Cos((Convert.ToDouble(longitude) / constValue) - (Convert.ToDouble(l.Longitude) / constValue))
let calMiles = (constValue2 * Math.Acos(temp > 1 ? 1 : (temp < -1 ? -1 : temp)))
where (l.Latitude > 0 && l.Longitude > 0)
orderby calMiles
select new location
{
Name = l.name
});
return loc .ToList();
Ответ 2
Сначала вы можете преобразовать данные местоположения в базу данных в System.Device.Location.GeoCoordinate
, а затем использовать LINQ для поиска ближайшего.
var coord = new GeoCoordinate(latitude, longitude);
var nearest = locations.Select(x => new GeoCoordinate(x.Latitude, x.Longitude))
.OrderBy(x => x.GetDistanceTo(coord))
.First();
Ответ 3
У вас есть допустимый диапазон, за пределами которого "удар" не имеет особого значения? Если это так, используйте
from l in locations where ((l.lat - point.lat) * (l.lat - point.lat)) + ((l.lng - point.lng) * (l.lng - point.lng)) < (range * range) select l
то найдите хит с наименьшим квадратом значения расстояния в пределах цикла этих результатов.
Ответ 4
Чтобы прокомментировать комментарий @Fung, если вы используете Entity Framework/LINQ to Entities, если вы попытаетесь использовать метод GeoCoordinate.GetDistanceTo
в запросе LINQ, вы получите сообщение об ошибке NotSupportedException с сообщением:
LINQ to Entities не распознает метод "Double GetDistanceTo (System.Device.Location.GeoCoordinate)", и этот метод не может быть переведен в выражение хранилища.
С Entity Framework версии 5 или 6 альтернативой является использование класса System.Data.Spatial.DbGeography. Например:
DbGeography searchLocation = DbGeography.FromText(String.Format("POINT({0} {1})", longitude, latitude));
var nearbyLocations =
(from location in _context.Locations
where // (Additional filtering criteria here...)
select new
{
LocationID = location.ID,
Address1 = location.Address1,
City = location.City,
State = location.State,
Zip = location.Zip,
Latitude = location.Latitude,
Longitude = location.Longitude,
Distance = searchLocation.Distance(
DbGeography.FromText("POINT(" + location.Longitude + " " + location.Latitude + ")"))
})
.OrderBy(location => location.Distance)
.ToList();
_context
в этом примере - ваш экземпляр экземпляра DbContext, созданный ранее.
Хотя в настоящее время недокументирован в MSDN, единицы, возвращаемые DbGeography.Distance, как представляется, являются метрами. См.: System.Data.Spatial DbGeography. Единицы измерения?
Ответ 5
var objAllListing = (from listing in _listingWithLanguageRepository.GetAll().Where(z => z.IsActive == true)
let distance = 12742 * SqlFunctions.Asin(SqlFunctions.SquareRoot(SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (listing.Listings.Latitude - sourceLatitude)) / 2) * SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (listing.Listings.Latitude - sourceLatitude)) / 2) +
SqlFunctions.Cos((SqlFunctions.Pi() / 180) * sourceLatitude) * SqlFunctions.Cos((SqlFunctions.Pi() / 180) * (listing.Listings.Latitude)) *
SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (listing.Listings.Longitude - sourceLongitude)) / 2) * SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (listing.Listings.Longitude - sourceLongitude)) / 2)))
where distance <= input.Distance
select new ListingFinalResult { ListingDetail = listing, Distance = distance }).ToList();//.Take(5).OrderBy(x => x.distance).ToList();