GeoService-Xr과 FingerEyes-Xr의 On-The-Fly-Projection 적용하기

다양한 좌표계가 존재하므로, 사용자마다 자신이 가지고 있는 공간 데이터마다 서로 다른 좌표계를 적용하고 있습니다. 이러한 서로 다른 좌표계의 공간 데이터를 DBMS에 Import할때, 좌표계를 명시해 주고, 이를 사용하는 클라이언트 단에서는 서로 다른 좌표계를 하나의 기준 좌표계로 변환하여 사용하게 됩니다. 그래야 레이어로써의 여러개의 지도가 하나의 지도로 중첩됩니다.

GeoService-Xr과 FingerEyes-Xr에서도 서로 다른 좌표계에 대해 동적으로 좌표계를 변환해 단일 좌표계로 변환해 레이어를 중첩해 주는 On-The-Fly-Projection 기능을 제공합니다. 이를 위해서는 서버인 GeoService-Xr 과 클라이언트인 FingerEyes-Xr에서 간단한 설정이 필요한데요. 이 내용을 정리해 봅니다.

먼저 서버인 GeoService-Xr에서는 DBMS에 저장된 공간 데이터를 GeoData라는 단위로 관리하는데, 이 GeoData를 정의하는 xml 파일의 내용에 EPSG를 설정할 수 있습니다. 아래의 예와 같습니다.


    parcel
    muan_db://public."parcel"
    5186



    link
    network://public."link"
    5179

위의 내용은 parcel이라는 GeoData의 좌표계는 EPSG:5186이고, link라는 GeoData의 좌표계는 EPSG:5179라는 것을 명확히 하고 있습니다.

다음은 클라이언트 단의 코드인데요. 클라이언트 단에서 공통 좌표로 사용하고자 하는 좌표계를 아래처럼 지정하면 됩니다.

map.EPSG(5186);

위의 코드에 의해 클라이언트 단에서 사용하는 단일 좌표계는 EPSG:5186으로써, 만약 서버 단에서 이와 다른 좌표계의 데이터가 오면 이를 EPSG:5186으로 변환하도록 합니다. (명확히는 서버단에서 좌표계 변환을 수행함)

아래의 그림은 서로 다른 좌표계를 가지는 parcel(지적도로 EPSG:5186)와 link(네트워크 링크로 EPSG:5179)가 하나의 단일 좌표계(EPSG:5186)으로 변환되어 정확히 그 위치가 일치되는 것을 보여주고 있습니다.

도로명주소DB의 도로중심선을 활용한 최단거리 기능 소개

도로명주소DB에는 도로중심선이 있습니다. 예전에 도로중심선을 네트워크 DB로 가공하는 글을 포스팅한 적이 있었는데요. 찾으시는 분을 위해 주소를 정리하면 아래와 같습니다.

도로중심선만으로 네트워크 데이터 구축하기 ㅡ 1/3
도로중심선만으로 네트워크 데이터 구축하기 ㅡ 2/3
도로중심선만으로 네트워크 데이터 구축하기 ㅡ 3/3

아울러 이러한 네트워크 DB를 이용하는 알고리즘 중에 하나인 최단경로를 탐색하는 A*에 대해 정리하는 글은 아래와 같습니다.

최단 경로 탐색 – A* 알고리즘

이러한 과거의 작업 내용을 토대로 두 지점간의 최단 경로를 분석해 그 결과를 제공하는 서비스를 개발하였고, 기능에 대한 실행이 아래의 동영상입니다.

사실, 도로명주소DB의 도로중심선만으로 길찾기 서비스를 개발하는 것은 충분하지만, 길찾기 서비스의 품질으로써 도로중심선은 추가적인 보완이 필요합니다. 도보용으로는 적당하지만, 차량용과 같이 보다 더 나은 서비스 개발을 위해서는 나라에서 제공하는 표준 노드/링크 데이터를 활용하는 것을 권장합니다. 그럼에도 도로명주소DB의 도로중심선을 이용한 최단 경로를 개발한 이유는 상수관, 하수관, 가스관, 전력선, 통신선 등과 같은 설비들의 관망 해석에 대한 기반 기술 마련입니다. 이러한 관망은 최단경로라는 의미보다는 어떤 조건을 만족하는 관망을 탐색하여야 하는데, 어떠한 조건에 대한 과제를 “최단거리”라고 정한 것 뿐입니다. A*라는 알고리즘을 이해하고 구현함으로써 이를 응용하고 확장해 어떠한 조건에서의 관망이라도 탐색할 수 있습니다.

FingerEyes-Xr, 공간 데이터에 대한 Custom Draw (사용자 정의 그리기)

공간 데이터는 위치 데이터와 속성 데이터의 조합입니다. 단순히 공간 데이터를 일괄적으로 원하는 색상이나, 아이콘 등으로 표현할 수 있지만 각각의 공간 데이터에 대한 속성 데이터를 활용하여 다양한 형태로 그리고자 할 때가 있습니다. 예를 들어 아래와 같은 공간 데이터 테이블이 있다고 합시다.

위의 테이블에서 images는 서버 측에 저장된 이미지 파일명에 대한 리스트이고, tags는 이미지에 대한 해시태그 성격의 값입니다. 그리고 the_geom은 좌표 데이터입니다. 이 3개의 값을 이용해 특정 위치에 이미지와 해시태그를 표현하고자 할 때, 클라이언트 GIS 엔진인 FingerEyes-Xr의 어떤 API를 활용해 구현할 수 있는지 정리해 봅니다. 먼저 아래는 위의 3개의 속성값을 이용해 실제로 구현된 결과에 대한 화면입니다.

FingerEyes-Xr에서는 공간 데이터를 그릴 때, 특히 포인트 데이터에 대해서 다음처럼 표현하고자 하는 마커 심벌을 지정할 수 있습니다.

var customSym = new GeoHashTagMarkerSymbol();
layer.theme().markerSymbol(customSym);

즉, 공간 데이터를 그리는 방식을 지정하는 GeoHashTagMarkerSymbol 클래스를 정의해 생성한 후, 공간 데이터에 대한 레이어의 Theme에 대해 MarkerSymbol로써 지정하면 됩니다. 바로 이 GeoHashTagMarkerSymbol의 Javascript의 구현은 아래와 같습니다.

GeoHashTagMarkerSymbol = Xr.Class({
    requires: [Xr.symbol.IMarkerSymbol],

    construct: function () { },

    methods: {
        /* SVG Element */ create: function (/* PointD */ point, 
            /* AttributeRow */ attrRow, /* CoordMapper */ coordMapper) { 
            var vp = coordMapper.W2V(point);
            var vpx = vp.x, vpy = vp.y;

            var tags = attrRow.valueAsString(0); // tags 필드의 값
            var imageFile = attrRow.valueAsString(1); // images 필드의 값
            var w = this.wSize(), h = this.hSize();
            var g = document.createElementNS(xmlns, "g");

            var image = document.createElementNS(xmlns, "image");
            image.setAttribute("x", vpx - w / 2);
            image.setAttribute("y", vpy - w / 2);
            image.setAttribute("width", w);
            image.setAttribute("height", w);
            image.setAttributeNS("http://www.w3.org/1999/xlink", "href", imageFile);

            g.appendChild(image);

            var textStroke = document.createElementNS(xmlns, "text");
            textStroke.setAttribute("x", vpx);
            textStroke.setAttribute("y", vpy + h / 2 - 6);
            textStroke.setAttribute("text-anchor", "middle");
            textStroke.setAttribute("stroke", "black");
            textStroke.textContent = tags;
            g.appendChild(textStroke);

            return g;
        },

        /* number */ wSize: function () { 
            return this._width;
        },

        /* number */ hSize: function () {
            return this._height;
        },
    }
});

2번 코드에서처럼 Xr.symbol.IMarkerSymbol 인터페이스를 구현하겠다고 명시하고, 4번 코드의 생성자에서 필요로 값을 미리 정의해 두며, 10번 코드의 create에서 지도 상에 표현할 SVG 요소를 생성해 반환합니다. 40번과 44번 코드의 wSize, hSize 함수를 통해 심벌의 크기를 정하게 됩니다.

FingerEyes-Xr의 그래픽 요소에 타이틀(텍스트) 달기

FingerEyes-Xr은 사용자가 마우스를 이용해 자유롭게 다양한 그래픽 요소를 지도에 스케치할 수 있습니다. 사용자가 스케치한 그래픽 요소에 원하는 텍스트 추가로 붙여주는 코드에 대해 정리합니다. 먼저 아래는 사용자가 마우스로 그린 그래픽 요소에 대해 특정 텍스트를 추가한 화면입니다.

코드 예시는 아래와 같습니다.

var gl = /* 그래픽 레이어 */
var id = /* 그래픽 요소의 ID */
var row = gl.row(id);

row.titleText("타이틀에 대한 텍스트");
row.titleFontSymbol() // 타이틀 텍스트에 대한 폰트 스타일
    .size(24).color('#f1c40f').strokeColor('#000000');

쉽죠? 쉬우니 관련 글 정리도 쉽네요..