C# 用经度和纬度查找最近的位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12835851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find closest location with longitude and latitude
提问by Ashfaq Ahmed
I am working on a application where I need to get nearby location, my web service will receive 2 parameters (decimal longitude, decimal latitude )
我正在开发一个需要获取附近位置的应用程序,我的 Web 服务将接收 2 个参数(十进制经度、十进制纬度)
I have a table where the locations are saved in database with longitude and latitude fields,
我有一个表,其中的位置保存在具有经度和纬度字段的数据库中,
I want to retrieve the nearest locations.
我想检索最近的位置。
Can anyone help?
任何人都可以帮忙吗?
Here is my code:
这是我的代码:
var locations = from l in locations
select l
Here are further details about this : i have a 2 fields (decimal(18, 2) null) 1 latitude, 2 longitude inside a database table,
以下是有关此的更多详细信息:我在数据库表中有 2 个字段(decimal(18, 2) null)1 个纬度,2 个经度,
and i have a method
我有一个方法
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();
}
采纳答案by Ashfaq Ahmed
Here is Solution
这是解决方案
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();
回答by Kirk B.
Do you have a valid range, outside of which the "hit" is not really relevant? If so, use
你有一个有效的范围,在这个范围之外“命中”并不真正相关?如果是这样,请使用
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
then find the hit with the smallest squared distance value within a loop of those results.
然后在这些结果的循环中找到具有最小平方距离值的命中。
回答by Fung
You could first convert the location data in database to System.Device.Location.GeoCoordinate, then use LINQ to find the nearest one.
您可以先将数据库中的位置数据转换为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();
回答by Jon Schneider
To elaborate on the comment by @Fung, if you are using Entity Framework / LINQ to Entities, if you try to use the GeoCoordinate.GetDistanceTomethod in a LINQ query, you'll get a runtime NotSupportedException with the message:
为了详细说明@Fung 的评论,如果您使用的是实体框架/LINQ to Entities,如果您尝试GeoCoordinate.GetDistanceTo在 LINQ 查询中使用该方法,您将收到带有消息的运行时 NotSupportedException:
LINQ to Entities does not recognize the method 'Double GetDistanceTo(System.Device.Location.GeoCoordinate)' method, and this method cannot be translated into a store expression.
LINQ to Entities 无法识别“Double GetDistanceTo(System.Device.Location.GeoCoordinate)”方法,并且此方法无法转换为商店表达式。
With Entity Framework version 5 or 6, an alternative is to use the System.Data.Spatial.DbGeographyclass. For example:
对于实体框架版本 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();
_contextin this example is your previously-instantiated DbContext instance.
_context在此示例中是您之前实例化的 DbContext 实例。
Although it's currently undocumented in MSDN, the units returned by the DbGeography.Distancemethod appear to be meters. See: System.Data.Spatial DbGeography.Distance units?
虽然它目前在 MSDN 中没有记录,但DbGeography.Distance方法返回的单位似乎是米。请参阅:System.Data.Spatial DbGeography.Distance 单位?
回答by Rajesh-Systematix
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();
回答by maeneak
A netcore friendly solution. Refactor as needed.
一个网核友好的解决方案。根据需要重构。
public static System.Drawing.PointF getClosestPoint(System.Drawing.PointF[] points, System.Drawing.PointF query) {
return points.OrderBy(x => distance(query, x)).First();
}
public static double distance(System.Drawing.PointF pt1, System.Drawing.PointF pt2) {
return Math.Sqrt((pt2.Y - pt1.Y) * (pt2.Y - pt1.Y) + (pt2.X - pt1.X) * (pt2.X - pt1.X));
}

