SQL Server-选择嵌套在较大多边形内的所有多边形


9

这是一个看似简单的SQL Server几何问题,我以为可以使用一种即用型的解决方案,但是我找不到运气。

我的目的是选择一个表中具有多边形的所有记录,这些记录嵌套(包含)在另一个表的较大多边形中。我有预期的功能STWithinSTContains也有需要提供的解决方案,但是不幸的是,它们都只识别嵌套在较大多边形中的内部多边形,而不识别那些接触较大多边形边界的嵌套多边形。例如参见图片。STWithin和STContains函数的结果

满足我的需求的另一个选择是STIntersection。但是,此函数的问题在于它仅返回几何列!我想获取记录ID。有没有人对如何做到这一点有何建议?

STWithin

select a.bg10 from
gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STWithin(b.shape) = 1
where b.mktname = 'Loop'

STContains

select a.bg10 from
gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on b.shape.STContains(a.shape) = 1
where b.mktname = 'Loop'

STIntersection

select a.shape.STIntersection(b.shape)
from gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STIntersects(b.shape) = 1
where b.mktname = 'Loop'

编辑:

一种建议是STIntersection仅省略和使用STIntersects以下内容:

STIntersects

select a.bg10
from gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STIntersects(b.shape) = 1
where b.mktname = 'Loop'

这种方法的问题在于,STIntersects似乎选择了内部或外部的所有多边形并触摸了较大的多边形,而不仅仅是严格地在内部。例如参见图片。STIntersects函数的结果


您可以尝试在包含的多边形上做一个最小的缓冲区,然后使用STContainsSTWithin。这并不是一个很好的技巧,但可以为您带来所需的结果。另一种选择是通过比较“相交”区域和“多边形”区域来进行STIntersects。
MickyT '16

我开始比较却得到了与比较几何形状的兔子洞的地区工作转化为区域号码,等等...
DPSSpatial

Answers:


8

理论上,您执行的查询应返回您尚未返回的多边形。这使我怀疑您可能会遇到SQL Server空间数据类型具有的浮点错误问题。因此,我对以最小数量缓冲边界多边形的评论。
因此,类似下面的内容应该可以获得所需的结果。

SELECT a.bg10 
FROM gis.usa_10_block_group a
    JOIN gis.usa_10_mkt_definition b
        ON a.shape.STWithin(b.shape.STBuffer(0.0001)) = 1
WHERE b.mktname = 'Loop'

这是一些空间方法的预期行为的快速示例。

SELECT Geometry::STGeomFromText(WKT,0), Description
    , Geometry::STGeomFromText('POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))',0).STIntersects(Geometry::STGeomFromText(WKT,0)) Intersects
    , Geometry::STGeomFromText('POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))',0).STContains(Geometry::STGeomFromText(WKT,0)) Contained
    , Geometry::STGeomFromText('POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))',0).STOverlaps(Geometry::STGeomFromText(WKT,0)) Overlaps
    , Geometry::STGeomFromText('POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))',0).STTouches(Geometry::STGeomFromText(WKT,0)) Touches
FROM (VALUES
    ('POLYGON((0 0, 20 0, 20 20, 0 20, 0 0))'            ,'Interior corner')
    ,('POLYGON((90 90, 100 90, 100 100, 90 100, 90 90))' ,'Interior corner')
    ,('POLYGON((20 20, 40 20, 40 40, 20 40, 20 20))'     ,'Interior')
    ,('POLYGON((50 0, 70 0, 70 20, 50 20, 50 0))'        ,'Interior edge')
    ,('POLYGON((50 80, 70 80, 70 100, 50 100, 50 80))'   ,'Interior edge')
    ,('POLYGON((80 50, 100 50, 100 70, 80 70, 80 50))'   ,'Interior edge')
    ,('POLYGON((90 0, 110 0, 110 20, 90 20, 90 0))'      ,'Overlap')
    ,('POLYGON((100 50, 120 50, 120 70, 100 70, 100 50))','Exterior edge')
    )P(WKT,Description)
UNION ALL 
SELECT Geometry::STGeomFromText('POLYGON((0 0, 100 0, 100 100, 0 100, 0 0))',0),'Bounding Area',null,null,null,null

结果

Description     Intersects Contained Overlaps Touches
--------------- ---------- --------- -------- -------
Interior corner 1          1         0        0
Interior corner 1          1         0        0
Interior        1          1         0        0
Interior edge   1          1         0        0
Interior edge   1          1         0        0
Interior edge   1          1         0        0
Overlap         1          0         1        0
Exterior edge   1          0         0        1
Bounding Area   NULL       NULL      NULL     NULL

这很棒!我不得不将缓冲区大小减小到0.001,但是这个概念起作用了。我怀疑问题在于gis.usa_10_mkt_definition表的几何形状不是与gis.usa_10_block_group相同的拓扑派生的,这解释了为什么它偏离了您提到的预期结果的原因。我使用两个共享相同拓扑的表测试了STWithin的使用,并且不需要缓冲区。
user1185790 '16

2

相交查询应如下所示(假设您希望从“ a”取回所有记录):

select a.* --get all columns from table 'a'
from gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STIntersects(b.shape) = 1
where b.mktname = 'Loop'

如果只需要与b相交的区域(即将a裁剪为b),则可以添加STIntersection

select a.bg10
, a.STIntersection(b.geom) --clipped geometry from a against b
    from gis.usa_10_block_group a
    join gis.usa_10_mkt_definition b
    on a.shape.STIntersects(b.shape) = 1
    where b.mktname = 'Loop'

但这还不能让您获得b内的多边形...

这种类型的多边形对多边形的边界和一致性非常有力-为了在“范围内”,a的边界不能与b的边界一致-“包含”也是如此。

根据这些定义,a中实际上有多少个多边形在b ...中?

那么,要在选择a内的多边形之前先缓冲b吗?还是对a做负缓冲?

不知道这里的确切答案是什么...


请参阅编辑以获取完整解释,为什么这不是我想要的
user1185790

我知道您要尝试做的事...现在正在做某事...
DPSSpatial
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.