如何根据经纬度按半径搜索?

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。

【讨论】:

以上是关于如何根据经纬度按半径搜索?的主要内容,如果未能解决你的问题,请参考以下文章

如何在经纬度半径范围内的 xml 文件中查找位置

Mysql 之根据经纬度按距离排序

计算半径内的 100 英里

iphone iOS mapkit,按最近点过滤点列表(经度,纬度)

计算两个经纬度之间的距离

用于存储位置数据(经纬度)和搜索的 postgresql 或 Mongodb?