PostGIS를 사용하여 도로 교차로 식별


17

도로가 서로 교차하는 곳을 식별하고이 교차로에서 지점을 만들고 교차로를 형성하는 도로의 수를 나열하려고합니다.

여기에 이미지 설명을 입력하십시오

ST_NumPoints 를 사용하여 이를 달성 할 수 있는 방법이 있는지 궁금 하지만, 내가해야 할 일을 알 수는 없습니다. 내가 한 것은 다음 코드를 사용하여 선이 교차하는 지점 테이블을 만드는 것입니다.

CREATE TABLE test_points as
SELECT      
    ST_Intersection(a.geom, b.geom),
    a.gid
FROM
    roads as a,
    roads as b
WHERE
    ST_Touches(a.geom, b.geom);

샘플을 도로에서 실행하면 다음과 같은 점 그리드가 표시됩니다 (도로는 그림으로 표시됨).

여기에 이미지 설명을 입력하십시오

점 중 하나를 검사하면 서로 위에 많은 점이 쌓여 있음을 알 수 있습니다.

여기에 이미지 설명을 입력하십시오

여기의 GID는 도로 ID이지만, 왜 많은 포인트가 있는지 이해할 수 없습니다. 중앙 도로 교차로에서 계산되는 4 개의 지점을 이해할 수 있지만 여기에 12 개의 지점이 있습니다. PostGIS에서이 계산을 수행하는 더 좋은 방법이 있습니까?

답변:


21

그룹화하면 고유 한 포인트 만 가져와야합니다.

CREATE TABLE test_points as
SELECT      
    ST_Intersection(a.geom, b.geom),
    Count(Distinct a.gid)
FROM
    roads as a,
    roads as b
WHERE
    ST_Touches(a.geom, b.geom)
    AND a.gid != b.gid
GROUP BY
    ST_Intersection(a.geom, b.geom)
;

지오메트리로 그룹화하면 지오메트리 자체가 아니라 지오메트리의 bbox로 그룹화됩니다. 그것은 포인트를 다룰 때 중요하지 않습니다. 거의. Bbox는 이론 상으로는 동일하지 않은 두 점을 그룹화 할 수있는 점 자체보다 정밀도가 떨어집니다.
Nicklas Avén

@ NicklasAvén에게 감사합니다. Bbox 비교는 얼마나 정확합니까? 이 사용 사례에 충분할 것으로 기대합니다.
underdark

1
@underdark 감사합니다. 교차하는 줄 수를 계산하는 방법을 알고 있습니까? 나는 몇 가지 조합을 시도했습니다 COUNT()등을 COUNT(ST_Touches(..))하고 COUNT(ST_Intersection(..))있지만 모든 값과 마찬가지로이 작동하지 않습니다 12.
djq

@underdark, 그래도 충분하다. 그래서 나는 "이론"을 썼다. 상자는 float4에 있고 점의 좌표는 배정도입니다. 따라서 상자는 ST_Point (1.000001,1.0) 및 ST_Point (1.000002,1.0)에 대해 동일하게 표시됩니다 (적어도 내 시스템에서는 방금 시도했습니다. to 포인트를 그룹화합니다). 박스와 실제 지오메트리의 차이점은 dev-list에서 한동안 논의되었습니다.
니클라스 아벤

@AlexOs 제안 수정을 참조하십시오 gis.stackexchange.com/a/151277/3195
마틴 F

6

이것은 예상보다 조금 까다 롭습니다. 이는 쌍 이상의 관계를 분석하는 좋은 방법이 없기 때문입니다. 함수에 세 줄을 넣을 수 없으며 모든 줄이 교차하는지 묻습니다.

그러나 적어도 하나의 접근 방식은 먼저 교차점을 찾은 다음 각 교차점에서 몇 개의 도로가 닿아 있는지 확인하는 것입니다 (모두 동일한 쿼리에서 수행 할 수 있음).

도로가 서로 완벽하게 연결되어 있고 교차로를 통과하는 도로가없는 경우 다음과 같은 작업을 수행 할 수 있습니다 (테스트되지 않음) :
잊어 버린 그룹 절로 편집 (아직 테스트되지 않음) :

SELECT distinct_crosspoints.geom as crossing, array_agg(roads.gid), count(*) FROM
  (SELECT DISTINCT (geom) geom FROM 
    (SELECT ST_Intersection(a.geom, b.geom) geom 
     FROM roads a, roads b 
     WHERE ST_Intersects(a.geom, b.geom)
    ) all_crosspoints
   ) distinct_crosspoints
   ,roads 
 WHERE ST_Intersects(distinct_crosspoints.geom, roads.geom)
 GROUP BY distinct_crosspoints.geom;

도로가 제대로 연결되지 않았거나 일부 도로가 교차로를지나 가면 더 복잡합니다.

HTH

니클라스


@Nicklas 안녕하세요.이 기능을 실행할 수 없습니다. 두 가지 내부 조항은 잘 작동합니다. 를 distinct_crosspoints ,roads테이블 이름 ( roads_test)으로 바꿔야 합니까? 나는 그것을 시도했지만 geom모호함에 대한 오류가 발생했습니다 .
djq

1
@celenius, 그룹 조항을 잊어 버려서 죄송합니다. 또한 당신은 여분의 레벨을 구별 할 필요가 없습니다. 교차로에 직접 놓을 수 있습니다. Underdarks answer 아래의 논의에 따라 Distinct는 그룹과 동일한 동작을합니다.
Nicklas Avén

쿼리를 실행하기 위해 distinct_crosspoints.geom을 Nicklas 답변에 추가했습니다. 나를 위해 지금 작동합니다.
Frank

1
 CREATE TABLE test_points as
    SELECT      
        ST_Intersection(a.geom, b.geom),
        Count(Distinct a.gid)
    FROM
        roads as a,
        roads as b
    WHERE
        ST_Touches(a.geom, b.geom)
        AND a.gid < b.gid   /* !!! Changed "!=" for "<"  */
    GROUP BY
        ST_Intersection(a.geom, b.geom)
    ;

선 A (id 1)가 선 B (id 2)를 교차하면 필요한 교차점입니다. 그러나 선 B도 같은 점에서 선 A와 교차합니다. 그러나이 시점은 두 번 필요하지 않습니다. 그래서 내가 a.gid < b.gid 대신 사용 하는 이유a.gid != b.gid

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.