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 함수의 결과


포함하는 다각형에서 최소 버퍼를 시도한 다음 STContains또는 을 사용할 수 있습니다 STWithin. 실제로 좋은 해킹은 아니지만 원하는 결과를 얻을 수 있습니다. 다른 옵션은 교차 영역과 다각형 영역을 비교하여 STIntersects를 수행하는 것입니다.
MickyT

면적 비교 작업을 시작했지만 형상을 숫자 등으로 변환 한 등을 비교하여 토끼 구멍에 들어
갔습니다

답변:


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

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 ...?

따라서 안에있는 다각형을 선택하기 전에 b를 버퍼링 하시겠습니까? 아니면 음수 버퍼를 사용합니까?

정확한 답변이 무엇인지 잘 모르겠습니다 ...


왜 이것이 내가 뒤 따르지 않았는 지에 대한 자세한 설명은 편집을 참조하십시오.
user1185790

나는 당신이 무엇을하려고하는지 ... 지금 무언가에 대해 작업하고 있습니다 ...
DPSSpatial
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.