【问题标题】:SQL radius searchSQL 半径搜索
【发布时间】:2018-02-20 10:36:22
【问题描述】:

假设我有一个由 5 个纬度/经度点组成的多边形地理区域,例如:-

51.314869, -0.497125
51.255586, 0.237066
51.684476, 0.244771
51.725210, -0.514339
51.314869, -0.497125

然后我从 30 英里的单点(例如 51.728215、-1.209971)进行半径搜索。我希望能够确定该半径搜索是否包含该多边形区域的任何或全部。

我知道 SQL Server 中有一个可用的地理数据类型,如果需要,可以将数据更改为此,如果它更容易解决的话

【问题讨论】:

  • 到目前为止你尝试过什么?可以提供一下已经写好的代码吗?
  • 到目前为止我还没有尝试过任何事情,因为我真的不知道该怎么做。如果它是检查 2 点之间的距离,那么没问题,但我以前从未做过这样的事情

标签: sql sql-server geospatial


【解决方案1】:

以下应该可以解决问题:

declare @g geography =
    geography::STGeomFromText('POLYGON((
        51.314869 -0.497125 ,
        51.255586 0.237066  ,
        51.684476 0.244771  ,
        51.725210 -0.514339 ,
        51.314869 -0.497125 
    ))', 4326);

set @g=@g.ReorientObject();

declare @p geography =
    --geography::Point(-0.497125, 51.314869, 4326);
    geography::STPointFromText('POINT(51.314869 -0.497125)', 4326);

select @g.STIntersects(@p.STBuffer(48280.3))

作为解释,我使用的是 geography 数据类型,就像您的直觉所说的那样应该是可能的。我首先构建一个代表您所在区域的多边形。实际多边形的语法称为 WKT(即众所周知的文本),是地理空间的标准。

下一步是我必须重新定位您的对象。为什么?地理多边形的一个问题是,它们可以根据定义点的顺序定义边界内部或边界外部的区域。在这种情况下,您指定它们的顺序定义了该区域的外部(即整个地球减去一个非常小的四边形),所以我假设您想要考虑该区域的内部(事实证明将是必要的,如下所示)。

接下来,我构造一个点。出于方便,我选择了多边形的一个角。请注意,我提供了两种方法来做到这一点。我个人更喜欢用Point()的方法,不过你也可以用WKT来做!

最后,我测试你的多边形 (@g) 和一个以半径为 30 英里(或 48280.3 米)的点为中心的圆盘之间的交点。测试返回一个布尔值。谈到多边形中点排序的假设,如果您以错误的顺序定义点,则相交测试将对甚至不靠近您的多边形的事物返回 true(因为它几乎定义了整个地球)。乍一看,您可能会认为您可以反转测试(即对 STIntersects() 测试的逻辑否定),但我将把它作为练习留给读者,为什么这不是正确的做法。

【讨论】:

    【解决方案2】:

    您可以通过获取 lat/lon 的最小值和最大值来计算边界框来优化搜索。然后您可以通过与最小/最大纬度/经度进行比较来搜索数据库。最后,您可以通过检查纬度/经度是否在多边形内来过滤剩余的数据。如果你的多边形是凸的,这并不难。您必须将其分解为三角形,并检查纬度/经度是否在其中一个内。

    【讨论】:

      猜你喜欢
      • 2014-09-01
      • 2016-09-06
      • 2014-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 1970-01-01
      • 2016-09-29
      相关资源
      最近更新 更多