[GIS] PostGIS, 공간데이터 테이블 생성에 대한 SQL

진행하고 있는 프로젝트에서 사용하고 있는 공간 DBMS로 PostGIS를 사용하고 있습니다. 공간 테이블을 직접 만들어어 활용해야할 필요가 있어 찾은 내용을 정리해 봅니다.

고유한 ID 값으로써 fid와 기타 필드로써 name 그리고 Geometry 값에 대한 the_geom이라는 이름의 필드를 가지는 테이블을 생성하는 SQL 문의 예는 다음과 같습니다.

CREATE TABLE "tst_table"(
    fid INTEGER PRIMARY KEY,
    name VARCHAR(64),
    the_geom geometry,

    CONSTRAINT enforce_dims_the_geom CHECK (st_ndims(the_geom) = 2),

    CONSTRAINT enforce_geotype_the_geom CHECK 
            (geometrytype(the_geom) = 'MULTIPOLYGON'::text 
        OR 
            the_geom IS NULL),

    CONSTRAINT enforce_srid_the_geom CHECK (st_srid(the_geom) = (-1))
);

1번 줄에 생성할 테이블 명으로써 tst_Table로 지정했습니다. 2~4번 줄이 앞서 언급한 필드들이구요. 6번 줄은 Geometry에 대한 필드인 the_geom의 차원이 2차원, 즉 X와 Y의 쌍이어야 한다는 제약 조건입니다. 그리고 8번 줄의 제약 조건은 Geometry가 MULTIPOLYGON 타입이며 NULL 일 수 있다는 것 입니다. 그리고 13번 줄은 Geometry의 Spatial Reference ID에 대한 제약 조건입니다.

이제 아래는 앞서 생성한 공간 테이블에 하나의 레코도를 추가하는 SQL 문입니다.

INSERT INTO tst_Table 
 (
    fid, 
    name, 
    the_geom
) 
VALUES 
 (
    0, 
    '테스트', 
    ST_GeomFromText('MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)))', -1)
); 

일반적인 INSERT SQL 문입니다. 단지 주목해야할 줄은 11번입니다. Geometry에 대한 WKT 형식으로 지정했으며 공간참조로 -1을 주었습니다. 이 값은 앞서 공간 테이블을 생성할때 제약 조건과 일치합니다.

[GIS] FingerEyes, 면적, 거리 측정하기

핑거아이즈에서 마우스로 거리와 면적을 측정하는 방법에 대한 설명입니다. 펑거아이즈는 면적과 거리에 대해서도 스냅핑 기능을 적용할 수 있음으로 보다 정확하게 면적과 거리를 측정할 수 있습니다. 예를 들어 지적도를 대상으로 스냅핑을 적용할 경우 면적과 거리를 마우스를 이용해 측정할때 지적도의 도형의 정점이나 선분에 스냅핑되어 지적도를 정확히 참조하여 거리와 면적을 측정할 수 있습니다.

핑거아이즈의 거리와 면적의 측정은 매쉬업 레이어를 대상으로 작동합니다. 그러므로 거리와 면적을 측정하기 위해서는 지도 컴포넌트에 XrMashupLayer 클래스를 통해 매쉬업 레이어를 추가해야 합니다. 아래의 코드는 “mashup”이라는 레이어 고유 식별자를 지정하여 매쉬업 레이어를 추가하는 코드입니다. 레이어 고유 식별자는 임이의 문자열로 지정 가능하며 각 레이어 마다 고유해야 합니다.

var ml:XrMashupLayer = new XrMashupLayer("mashup");
map.layers.addLayer(ml);
map.edit.targetLayer = ml;

보시면, 매쉬업 레이어를 추가한 후에 편집 대상 레이어로써 추가한 매쉬업 레이어를 지정해 줘야 합니다. 면적 측정이나 거리 측정은 마우스를 통한 새로운 폴리곤과 폴리라인을 만들어 내는 작업이므로 간단한 편집 기능으로 분류되기 때문입니다.

이제 거리와 면적을 측정하는 코드에 대해 살펴보겠습니다. 먼저 면적을 측정하기 위한 버튼을 클릭하게 되면 발생하는 클릭 이벤트 처리 함수에 대해 다음처럼 코딩합니다.
private function onAddPolygon(event:MouseEvent):void
{
    map.edit.editMode = true;
    var id:uint = fid++;
    var bOK:Boolean = map.edit.addPolygon(id, true);
    if(!bOK)
    {
        trace("폴리곤 매쉬업 실패");
    }
}

먼저 3번 코드를 통해 맵의 상태를 편집 상태로 지정합니다. 편집 상태가 되면 마우스에 대한 조작은 모두 편집 행위로 간주됩니다. 다시 지도를 확대하고 축소하고 이동하려면 editMode를 false로 지정해 주면 됩니다. 그리고 4번 코드를 통해 고유한 id 값을 하나 만듭니다. fid 변수는 int 타입의 전역 변수로써 계속 1씩 증가해 중복되지 않은 값을 유지합니다. 물론 정말 중복되지 않도록 하려면 필요할 경우 다양한 방법이 적용되어야 할 것입니다. 5번 코드는 폴리곤을 그리라는 코드로써 앞서 만들어 놓은 중복되지 않는 정수값 인자 하나와 true 값 인자가 사용됩니다. 중요한 것이 바로 이 두번째 인자인 true입니다. true값이 지정되면 그래픽 요소를 그릴때 그래픽 요소에 관련된 측정값이 함께 표시됩니다. 여기서는 폴리곤이므로 폴리곤의 면적이 표시됩니다. 아래의 이미지는 면적 측정 버튼을 누른후 마우스 클릭을 통해 면적을 측정하는 화면입니다.

사용자 삽입 이미지
다음은 거리를 측정하는 코드입니다.
private function onAddPolyline(event:MouseEvent):void
{
    map.edit.editMode = true;
    var id:uint = fid++;
    var bOK:Boolean = map.edit.addPolyline(id, true);
    if(!bOK)
    {
        trace("폴리라인 매쉬업 실패");
    }
}

면적 측정과 다른 부분은 5번 코드 뿐입니다. 즉, addPolygon 대신에 거리 측정에 대한 폴리라인인 addPolyline 매서드로 대체되었습니다. 아래의 그림은 거리 측정 버튼을 클릭하고 마우스로 거리를 측정하는 화면입니다.

사용자 삽입 이미지