SQL Server-より大きなポリゴン内にネストされているすべてのポリゴンを選択します


9

これは一見シンプルなSQL Serverのジオメトリの質問で、すぐに使えるソリューションがあると思っていましたが、見つけることができません。

私の意図は、別のテーブルからのより大きなポリゴン内にネストされた(含まれている)ポリゴンを持つ1つのテーブル内のすべてのレコードを選択することです。私は期待する機能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'

編集:

1つの提案は、省略STIntersectionSTIntersectsて次のようにのみ使用することでした。

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関数の結果


含むポリゴンで最小限のバッファを作成してから、STContainsまたはを使用することもできSTWithinます。本当に良いハックではありませんが、あなたが望む結果を得るでしょう。もう1つのオプションは、交差領域とポリゴン領域を比較してSTIntersectsを実行することです。
MickyT 2016

私は...比較エリアに取り組んで始めたが、比較ジオメトリがなどなど、数に面積に換算してウサギの穴に入った
DPSSpatial

回答:


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と同じトポロジから派生していないためだと思います。これは、予想した結果から逸脱する理由を説明しています。同じトポロジを共有する2つのテーブルを使用してSTWithinの使用をテストしましたが、バッファは必要ありませんでした。
user1185790

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の領域だけが必要な場合(つまり、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の境界と一致することはできません。「Contains」にも同じことが言えます。

これらの定義により、aのポリゴンのうち実際にb内にあるポリゴンの数は...?

内にあるaのポリゴンを選択する前にbをバッファーしますか?または、ネガティブバッファーを実行しますか?

ここでの正確な答えが何であるかわかりません...


これは後に私はかなりのものではありません、なぜ完全な説明のための編集を参照してください
user1185790

私はあなたが何をしようとしているのか
わかり
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.