如何根据经纬度按半径搜索?
Posted
技术标签:
【中文标题】如何根据经纬度按半径搜索?【英文标题】:How to search by radius based on latitude and longitude? 【发布时间】:2011-12-11 22:06:49 【问题描述】:我想以指定半径显示基于纬度和经度的数据。
例子:
我有一个纬度 55.0628 和经度 -162.3056 的记录,没有指定状态。
如何使用实体 linq 仅显示一种状态内的记录?
如果我有佛罗里达州只显示佛罗里达州内的记录。
Table Data
id item latitude longitude
1 townhome 55.0628 -162.3056
Table postal codes
id state city latitude longitude
1 alaska Akutan 54.143 -165.7854
2 Alabama Huntsville 34.7448 -86.6704
【问题讨论】:
您的数据不足以提供准确的结果,但您可以计算到每个城市的距离并选择距离最近的城市。 【参考方案1】:我会尽可能接近实际数据执行查询(这可能意味着绕过 LINQ 并调用存储过程)。
这是我用来计算两个位置之间距离的 SQL 用户定义函数。它利用了 SQL Server 2008 中引入的新地理功能。
CREATE FUNCTION [dbo].[GetDistanceBetween]
(
@Lat1 float,
@Long1 float,
@Lat2 float,
@Long2 float
)
RETURNS float
AS
BEGIN
DECLARE @RetVal float;
SET @RetVal = ( SELECT geography::Point(@Lat1, @Long1, 4326).STDistance(geography::Point(@Lat2, @Long2, 4326)) / 1609.344 );
RETURN @RetVal;
END
函数以英里为单位返回距离,并且根据我的经验非常快(这显然取决于您需要进行多少比较)。
你可以使用类似这样的方式来调用它:
DECLARE @StartingLatitude FLOAT, @StartingLongitude FLOAT;
DECLARE @MaxDistance FLOAT = 50;
SELECT * FROM PostalCodes
WHERE dbo.GetDistanceBetween(@StartingLatitude, @StartingLongitude, latitude, longitude) <= @MaxDistance;
【讨论】:
这很有趣,请您解释一下查询。 @max 此处的答案提供了更多详细信息:***.com/questions/15628794/…。这仍然是一个有效的答案,但您可以通过从框搜索开始,然后使用半径搜索对其进行修剪来进一步优化它。【参考方案2】:要知道目的地在给定的较大区域内,您不仅需要拥有较大区域中某个点的坐标,还需要绘制出整个边界的坐标。
如果你有这些数据,那就是Point in Polygon 的问题了。我发现光线追踪在 SQL 和 C# 中都非常容易实现,因此可以将它作为一种让 Linq 感知的函数,尽管我只使用了 Linq2SQL 而不是 Linq2Entities。
如果您只有中心点的坐标,您可以使用STDistance
找到最近的此类点。但是,这很容易将较大州边界附近的位置误识别为较小州,因为它比较大州更靠近较小州的中心。
如果你这样做,但你没有使用 SQL 2008(所以没有 STDistance),你可以通过在((lat1 - lat2) * (lat1 - lat2)) + ((lng1 - lng2) * (lng1 - lng2))
上订购来获得粗略的近似值。这给出了相对距离,就好像世界真的像墨卡托投影所暗示的那样是一个矩形。点距赤道越远,误差越严重,因此对于美国各州来说可能几乎可以容忍,但对于加拿大各省来说就不行了。
【讨论】:
【参考方案3】:正确且最快的方法是从您的经纬度对邮政编码开始,然后找到给定距离(半径)的东、西、北和南点。关注this link 获取相关公式。然后使用这些点从数据库中获取邮政编码;类似:
select *
from zipcodes
where
lat >= South
and lat <= North
and lon >= West
and lon <= East
-- and state = 'FL' -- use it optionally
现在,在由东、北、西和南点(作为线)定义的正方形内的所有 zip 记录继续进行距离计算(使用 Tim 的代码)并仅保留半径内的记录。 (如果正方形中的所有点都有记录,那么大约 22% 将超出半径)。 显然,如果你使用 CTE,你将只用一个查询来执行整个 sql。
【讨论】:
以上是关于如何根据经纬度按半径搜索?的主要内容,如果未能解决你的问题,请参考以下文章