如何基于经纬度的半径搜索
本文关键字:搜索 何基于 经纬度 | 更新日期: 2023-09-27 18:17:26
我想显示基于指定半径的经纬度的数据。
的例子:
我有一条记录,纬度55.0628,经度-162.3056,没有指定状态。
如何使用entity to 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
我将尽可能接近实际数据执行查询(这可能意味着绕过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;
要知道一个目的地在一个给定的更大的区域内,你不仅需要有大区域中一个点的坐标,还需要有映射出它的整个边界的坐标。
如果你有这些数据,它就变成了多边形中的点问题。我发现光线追踪在SQL和c#中都很容易实现,所以这是一个很好的函数,你可以让linq感知,尽管我只做了Linq2SQL而不是Linq2Entities。
如果你只有中心点的坐标,你可以用STDistance
找到最近的中心点。然而,这很容易将靠近较大国家边界的位置误认为是较小国家的位置,因为它比较大国家更靠近较小国家的中心。
如果你这样做,但你没有使用SQL 2008(所以没有STDistance),你可以通过在((lat1 - lat2) * (lat1 - lat2)) + ((lng1 - lng2) * (lng1 - lng2))
上排序得到一个粗略的近似值。这给出了相对距离,就好像世界真的是一个矩形,就像墨卡托投影所显示的那样。距离赤道越远,不准确性就越差,所以对于美国各州来说,这可能还可以忍受,但对于加拿大各省来说,这就不合适了。
正确和最快的方法是从邮政编码的纵向配对开始,找到给定距离(半径)的东、西、北、南点。点击此链接获取相关公式。然后使用这些点从数据库中获取邮政编码;比如:
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操作。