본 카테고리의 이전글(PostGIS를 이용한 격자 만들기)에서 사각형 그리드 격자를 만들었습니다. 격자를 제작한 목적은 이전글에서 설명했듯이 특정 데이터셋의 격자별 집계 수행을 통해 분석을 진행하기 위함입니다. 본 게시글을 통해 실제 집계를 설명합니다.

1. 데이터 준비

 

격자는 준비했습니다. 실제 집계의 대상이 되어야 하는 데이터가 필요합니다. 저는 "공공데이터포털(data.go.kr)"에 접근하여 "데이터셋 > 표준데이터"메뉴에서 "전국 CCTV 표준 데이터"를 선택했습니다. CSV형식으로 제공받았기에 실제 PostGIS에 적재하는 전처리 작업이 요구됩니다. 전처리 작업 절차는 아래와 같습니다.

  1. Qgis에서 "쉽표로 구분된 텍스트 레이어 추가" 후 형상을 확인합니다. 이 후 DB연결을 통해 PostGIS에 적재합니다.
  2. Qgis에서 Import된 레이어를 선택한 후 내보내기를 실시하여 Shp 형식으로 저장합니다.
  3. Qgis에서 데이터베이스 연결 후 "파일가져오기"를 실시하여 PostGIS에 적재합니다.
  4. 원본에 위도, 경도 속성이 존재하며, 좌표계는 4326입니다. 필자는 PostGIS에 적재 후 좌표계를 5179로 변환했습니다. 미리 제작된 격자가 5179좌표계이기 때문에 변환했습니다. 
  5. 마지막으로 공간인덱스를 생성합니다.

2. 집계 실행

실제 질의는 아래처럼 단순합니다. SQL의 세부사항을 설명하지는 않겠습니다. 격자개수만큼 박복하며 교차여부를 검사하여 CCTV를 격자별로 개수합니다. 즉 격자 개수가 많으면 많을 수록 실행 성능은 떨어질 수 밖에 없습니다. 집계하고자 하는 대상에 따라 격자크기가 결정되야 합니다.
또한 눈썰미가 있다면 "count()"함수를 대신하여 숫자 필드를 대상으로 sum, median 등 다양한 함수의 적용이 가능합니다. 개수가 아닌 양, 추세 등이 중요한 경우입니다.



CREATE TABLE tempsubtotal AS
SELECT count(*) AS cnt, bound.geom AS geom
FROM temp_20200206020231 bound
LEFT JOIN ms101_20200207020227 counted ON ST_Intersects(bound.geom, counted.geom)
GROUP BY bound.geom;

이 후 Qgis를 통해 PostGIS에 접속하여 새로이 생성된 집계 테이블을 레이어로 추가한 후 보게되면, CCTV가 많을 수록 짙은 빨간색으로 나타나는 것을 볼 수 있습니다. 이는 Qgis의 시각화 속성을 이용한 것으로 고정색이 아닌 특정 컬럼을 대상으로 시각화를 지정한 것 입니다. 

데이터 및 처리는 PostGIS 에서 수행하고, 시각화는 사용자가 가지는 도구를 이용합니다. 아마도 실제 프로젝트에 적용한다면 데이터 처리 영역과 시각화 영역은 특별한 경우를 제외하고 철저히 분리하는 것이 좋습니다. 

3. 맺으며

PostGIS 사랑스럽지 않습니까? DBMS에 SDE(Spatial Data Extension)를 추가하는 것만으로 GIS업무의 많은 부분을 처리할 수 있습니다. 시각화라는 부분을 제외하면 일반적 공공정보화사업에 무리없이 사용될 수 있습니다. 정의도 제대로 못하는 GIS엔진이 정말 필요할까요? 

 

개요

공공개방되는 공간정보에는 건물도 포함됩니다. 건물 데이터는 수치지형도, 건물통합데이터, 도로명주소 건물 등 정보소스가 있습니다. 실제 데이터를 보게되면 건물 형상 등에 차이가 존재합니다. 필자는 단순히 형상이 틀립니다가 아닌 틀린 정도를 수치로 표현하려 합니다. 

본 게시글의 이해를 위하여 Hausdorff Distance에 대한 이해가 필요합니다. Hausdorff Distance는 점으로 이루어진 두 집합(포인트세트) 간의 거리를 결정하는 방법입니다. 두 집합 사이의 근접점에서 떨어진 가장 먼 지점을 찾습니다. 일반적으로 두 점(Point)간의 거리는 최단거리가 정의되는 거리입니다. 그러나 다각형의 경우 모든 점이 최단거리일 수 없습니다.

 

이를 적용하여 개별 공간 객체의 Hausdorff Distance를 구하여 객체 형상의 유사성을 검사할 수 있습니다. 거리 값이 작을수록 건물의 형상은 유사하다라고 정의할 수 있습니다. 

> 바로가기 : Hausdorff Distance (위키피디아)
> 바로가기 : Computing Geometric Similarity

 

본문

1. Hausdorff Distance의 이해

아래의 질의를 실행하여 객체의 좌표를 변경해가며 산출되는 거리를 보면 이해가 쉽습니다.
SELECT ST_HausdorffDistance('MULTIPOINT (0 0, 1 0)'::geometry, 'MULTIPOINT (0 2, 1 2, 2 2)'::geometry);

2. 검사 대상 데이터 준비

QGIS를 이용하여 건물통합 건물과 도로명주소 건물에서 여의도 지역만을 추출하여 4326좌표계로 전환한 후 PostGIS에 적재합니다. 실제 중첩한 형상을 보면 형상이 상당 부분 일치하지 않는 것을 볼 수 있습니다.

 

3. 거리 산출 수행 : ST_HausdorffDistance 함수 실행

수행 과정은 단순합니다. 그저 공간위상관계가 교차(ST_Intersects)하는 객체를 찾아 객체간 거리 산출(ST_HausdorffDistance) 함수를 적용하게 되면 두 건물간의 거리가 산출이 됩니다. 이를 통해 산출된 거리 값이 작을수록 두 건물은 유사한 형상을 가지고 있다라고 정의할 수 있습니다. 

SELECT DISTINCT ON(TEST_BD_1.bd_mgt_sn) TEST_BD_1.bd_mgt_sn, TEST_BD_1.bld_nm, TEST_BD_2.buld_nm, 
    CAST(ST_HausdorffDistance(TEST_BD_1.geom, TEST_BD_2.geom) as numeric) as hdist1
    FROM TEST_BD_1 INNER JOIN TEST_BD_2 ON ST_Intersects(TEST_BD_1.geom, TEST_BD_2.geom)
    ORDER BY TEST_BD_1.bd_mgt_sn, ST_HausdorffDistance(TEST_BD_1.geom, TEST_BD_2.geom);

 

맺음말
저는 단순히 거리만을 산출했습니다. 건물유형 별 산출된 거리의 평균값과 표준편차를 구한다면 전체 수준에서 데이터 유사성 수준을 평가할 수 있습니다. 필자가 전하고자 하는 메시지는 한결같습니다. 공간DBMS의 올바른 활용만으로 가성비좋은 앱을 제작할 수 있습니다.
즐 코딩 하십시오~~
 

 


개요

필자는 흔히 현장에서 GIS엔진이라고 말하는 미들웨어의 도입을 강력히 반대하는 입장입니다. 대부분의 2D GIS 사이트에서 GIS엔진은 성능을 떨어뜨리는 원인이기 때문입니다.
정보시스템은 정보저장 및 조회의 편의를 위하여 DBMS와 함께 동작합니다.(일부 예외는 존재합니다) 꽤 오래전부터 DBMS는 SDE(Spatial Data Extension)를 통해 공간데이터에 특화된 기능 및 함수를 제공합니다. SDE은 강력한 공간분석도구 입니다. 이의 활용을 통해 별도 미들웨어 없이 SQL만으로 Geo Processing을 수행할 수 있고 수행결과는 DBMS에 테이블 형식으로 정의함으로써 데이터 저장구조를 전체 시스템 수준에서 동일하게 가져갈 수 있는 장점이 있습니다.

공개SW인 PostGIS를 이용하여 경계분할을 진행합니다. 별도의 솔루션이 아닌 오직 DBMS가 지원하는 함수만을 이용합니다. 과정별 생성되는 데이터는 Qgis에서 확인했습니다.

본 글에서는 "보로노이다이어그램"을 이용하여 경계를 나누어 각각이 동일 면적에 근접하도록 분할하는 기법을 설명합니다. 이해를 위해 "보로노이 다이어그램"을 이해하셔야 합니다.

> 보로노이다이어그램 1 : 위키피디아
> 보로노이다이어그램 2 : 네이버캐스트

또한 K-Means 알고리즘에 대한 기반 지식 또한 요구됩니다.

> K-평균 알고리즘 : 위키피디아
> K-평균 군집화 : 티스토리(untitledblog)

이하 기술되는 SQL의 실행을 위하여 PostGIS의 GEOS 버전이 2.3.0 이상 이어야 합니다. 아래의 질의를 통해 PostGIS의 버전을 확인하고, 만일 기준을 충족하지 않을 경우 PostGIS를 업그레이드 하십시오. 간단한 설치 명령어만으로 쉽게 업그레이드 할 수 있습니다. 별도 설명하지 않겠습니다.

 select postgis_full_version();
POSTGIS="2.4.6 r17068" PGSQL="96" GEOS="3.7.0-CAPI-1.11.0 673b9939" SFCGAL="1.2.2" PROJ="Rel. 4.9.3, 15 August 2016" GDAL="GDAL 1.11.4, released 2016/01/25" LIBXML="2.9.1" LIBJSON="0.11" RASTER

 

본문

본 게시글에서 사용하는 PostGIS 함수는 다음과 같습니다. 상세 설명은 공식 사이트의 도큐먼트를 참조하십시오.(필독)

경계 분할 시행

1. 경계준비 : 시도경계 테이블에서 서울시 경계만을 추출한 별도 테이블 생성 (생략가능 과정)
CREATE TABLE seoul AS
    SELECT * FROM ngii_cdm_4326 WHERE bjcd = '1100000000';

2. 서울 경계 내에 존재하는 랜덤 포인트 셋 생성 : 포인트 개수가 많을 수록 최종 생성되는 분할 경계의 면적은 동일 값에 수렴
CREATE TABLE seoul_pts AS
    SELECT (ST_Dump(ST_GeneratePoints(geom, 10000))).geom AS geom FROM seoul WHERE bjcd = '1100000000';

3. K-Means 알고리즘을 이용한 군집화
CREATE TABLE seoul_pts_clustered AS
    SELECT ST_ClusterKMeans(geom, 10) over () AS cluster_id, geom FROM seoul_pts;

4. 클러스터 별 중심점 생성
CREATE TABLE seoul_pts_clustered_center AS
    SELECT cluster_id, ST_Centroid(ST_collect(geom)) AS geom FROM seoul_pts_clustered
    GROUP BY cluster_id;

5. 중심점을 기준으로 보로노이 다각형 생성
CREATE TABLE seoul_voronoi AS
    SELECT (ST_Dump(ST_VoronoiPolygons(ST_collect(geom)))).geom AS geom FROM seoul_pts_clustered_center;

6. 서울 경계와 보로노이 경계의 폐합 폴리곤 경계 생성
CREATE TABLE seoul_divided_result AS
    SELECT ST_Intersection(a.geom, b.geom) AS geom FROM seoul a
    CROSS JOIN seoul_voronoi b;

 

마치며

본 블로그의 카테고리 중 "꿀팁-PostGIS"가 상대적으로 빈약했습니다. 카테고리의 빈부격차를 줄이고자 임의의 시나리오를 만들어 게시글을 작성했습니다. 하지만 전하고자하는 메시지는 명확합니다.

공개SW가 보여주는 기능 및 성능은 필자를 많이 놀라게 합니다. 본 게시글에서 설명한 류의 Geo-Processing을 수행해야 한다면 저는 Shell Script를 만들어서 이를 호출하는 것으로 개발 코드를 많이 줄일 것 같습니다. 기능을 이행하는 수단은 한가지가 아니겠지만 가장 좋은 것은 이미 존재하여 검증된 것을 잘쓰는 것입니다. PostGIS는 이미 시장에서 검증되어 기술성숙도가 높은 공개SW입니다.

GIS엔진, 오라클이라는 굴레만 벗어난다면 가성비 좋은 아주 훌륭한 앱을 제작할 수 있습니다.

+ Recent posts