使用多边形列表过滤点列表

Filter list of points using list of Polygons

给定一个点列表和一个多边形列表。您如何 return 列表中任何多边形中的点列表(原始点列表的子集)

我删除了示例 table 中的其他列以简化操作

分Table:

| Longitude| Latitude  |
|----------|-----------|
| 7.07491  | 51.28725  |
| 3.674765 | 51.40205  |
| 6.049105 | 51.86624  |

位置多边形 Table:

|     LineString       |
|----------------------|
| CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-122.20 47.45, -122.81 47.0, -122.942505 46.687131 ...  |
| MULTIPOLYGON (((-110.3086 24.2154, -110.30842 24.2185966, -110.3127...


如果我有来自 LocationPolygons 的行 table 我可以做类似

DECLARE @homeLocation geography;  
SET @homeLocation = (select top 1 GEOGRAPHY::STGeomFromText(LineString, 4326)
FROM LocationPolygon where LocationPolygonId = '123abc')

select Id, Longitude, Latitude, @homeLocation.STContains(geography::Point(Latitude, Longitude, 4326)) 
as IsInLocation from Points PointId in (1, 2, 3,)

这将 return 我想要的格式如下所示。然而,这仅适用于列表中的一个位置

| Id | Longitude| Latitude  | IsInLocation |
|----|----------|-----------|--------------|
| 1  | 7.07491  | 51.28725  | 0            |
| 2  | 3.674765 | 51.40205  | 1            |
| 3  | 6.049105 | 51.86624  | 0            |

如何处理具有多行 LocationPolygon table 的场景?

我想知道

  1. 如果任何点在任何位置多边形中?
  2. 它们位于哪个特定位置的多边形中?或者如果它们位于多个多边形中。

问题2更多的是题外话。有人可以帮忙吗?

更新 #1 回应@Ben-Thul 的回答。

不幸的是,我没有 access/permission 来对原始 table 进行更改,我可以请求访问权限,但不确定是否会提供。所以不确定我是否能够添加列或创建索引。虽然我可以在存储过程中创建临时 tables,但我也许可以用这种方式测试你的解决方案

我偶然发现了如下答案,但有点担心使用交叉连接对性能的影响。

WITH cte AS (     
      select *, (GEOGRAPHY::STGeomFromText(LineString, 4326)).STContains(geography::Point(Latitude, Longitude, 4326)) as IsInALocation  from 
(     
    select Longitude, Latitude from Points nolock  
) a cross join (
    select LineString FROM LocationPolygons nolock 
) b
)

select * from cte where IsInALocation = 1

显然,最好查看查询计划,但我偶然发现的解决方案与您的解决方案基本相同吗?有没有我遗漏的潜在问题。对此表示歉意,但我的 sql 不是很好。

问题 1 应该还不错。首先,一些设置:

alter table dbo.Points add Point as (GEOGRAPHY::Point(Latitude, Longitude, 4326));
create spatial index IX_Point on dbo.Points (Point) with (online = on);

alter table dbo.LocationPolygon add Polygon as (GEOGRAPHY::STGeomFromText(LineString, 4326));
create spatial index IX_Polygon on dbo.LocationPolygon (Polygon) with (online = on);

这将在每个 table 类型的 geography 上创建一个计算列,上面有一个空间索引。

从那里,你应该能够做这样的事情:

select pt.ID, 
   pt.Longitude,
   pt.Latitude,
   coalesce(pg.IsInLocation, 0) as IsInLocation
from Points as pt
outer apply (
   select top(1) 1 as IsInLocation 
   from dbo.LocationPolygon as pg
   where pg.Polygon.STContains(p.Point) = 1
) as pg;

在这里,您正在 select 点 table 的每一行并使用 outer apply 查看是否有任何多边形包含该点。如果有一个(哪个无关紧要),该查询将 return 结果集中的 1 和冒泡备份到驱动 select.

要将其扩展到问题 2,您可以从 outer apply 中删除 top() 并将其 return 来自多边形 table 的 ID 或任何您想要的 ID想。请注意,它会 return 每个包含点的多边形一行,可能会改变结果集的基数!