FingerEyes-Xr의 Hotspot 기능

지도 상에 특정한 지점을 시각적으로 두드러지게 표현하고 싶을 경우 FignerEyes-Xr에서는 Hotspot 기능을 활용할 수 있습니다. 아래는 이러한 Hotspot 기능을 활용하여 원하는 위치를 강조하는 기능에 대한 동영상입니다.

코드는 아래와 같이 간단합니다.

var pt = new Xr.PointD(102033, 231233);
var hotSpot = new Xr.ui.HotSpotControl(id, map, pt);
map.userControls().add(hotSpot);

위의 코드에 덧붙여 만약 사용자가 hotSpot을 클릭하면 지도에서 사라지도록 하는 추가 코드는 아래와 같습니다.

hotSpot.addEventListener("click", 
    function() {
        map.userControls().remove(id);
    }
);

FingerEyes-Xr의 소스코드는 GitHub에서 다운로드 받으실 수 있습니다.

울릉도 지역의 지적도와 건물통합데이터의 좌표계 문제

우리가 GIS를 활용해 무언가를 할 때 공간 데이터들 간의 좌표를 맞춰 레이어 단위로 중첩하여 하나의 지도를 구성한 뒤, 시각적 비교와 다양한 분석을 처리하게 됩니다. 이번에 경상북도 지역 중 내륙과 상당히 멀리 떨어져 있는 울릉도 지역에 대한 좌표계에 상당한 문제가 있다는 것을 파악했습니다. 독도는 더 심각!! -_-; 경상북도의 울릉도를 제외한 다른 지역은 그 좌표계가 매우 정확히 일치하는 것을 볼 때 울릉도 지역에 대한 좌표 불일치는 데이터 구축단계에서 원점 처리에 있어 상당한 문제가 있고, 근본적인 해결을 국가공간정보포털의 운영 주체인 정부 차원에서 조속히 해결해줘야 할 부분으로 생각합니다. 아래는 GRS80 UTM-K 좌표계로 변환하여 지적도와 행정경계를 중첩한 지도입니다.

앞서 언급하였듯이, 을릉도 이외의 다른 경상북도 지역은 GRS80 UTM-K 좌표계로 변환하여 중첩했을 경우 정확히 일치합니다. 제대로 구축된 데이터를 구할 수 있다면 좋았겠지만, 그럴 수 없는 상황에서 이처럼 구축 단계에서 근본적으로 잘못 되어진 공간 데이터의 좌표계를 일치시키는 방법으로 Georeferencing 기능을 활용하는 방법밖에 없었고, Georeferencing 기능을 수행할 수 있는 GDAL의 ogr2ogr.exe 콘솔 프로그램을 사용하고자 하였습니다. 그런데 이 프로그램은 콘솔인지라, 시각적으로 GCP를 잡을 수 없다는 문제가 있습니다. QGIS을 활용해 보려고 하였으나, 관련된 기능에 오류가 발생합니다. QGIS 역시 GDAL의 기능을 그대로 활용하면서 단지 시각적으로 GCP를 잡는 기능을 제공하는 것으로 예상됩니다. 여튼.. ogr2ogr을 통한 Georeferencing 기능을 위해 시각적으로 GCP를 효과적을 취득할 수 있는 툴을 별도로 개발하였고 아래의 화면과 같습니다.

위의 프로그램을 통해 19개의 GCP 좌표를 입력하여 Georeferencing 기능을 수행하여 얻은 결과는 아래와 같습니다.

그러나 이러한 수치지도에 대한 Georeferencing 방식을 활용하여 좌표계 일치하는 방법은 최선의 방법이 아닙니다. Georeferencing은 원래 목적은 항공영상과 같은 이미지를 수치지도에 맵핑시키기 위한 방법입니다. 결과적으로 수치지도를 또 다른 수치지도와 맵핑시키는 Georeferencing 방식은 그 결과면에서 정확도가 매우 떨어집니다. 근본적인 방법은 공간 데이터 구축을 처음부터 올바르게 해서 제공해야 한다는 것입니다. 조속히 관련 기관에서 해결해 주기를 바랄 뿐입니다.

FingerEyes-Xr에서 회전 Label에 대한 반복 표현

선형(Polyline)에 대한 라벨을 표시할 때, 선형의 방향에 따라 회전이 되도록 표시되는데.. 이때 선형이 긴 경우 라벨을 하나만 표시하게 되면 시인성이 떨어지는 경우가 있습니다. 예를 들어 도로명의 표현이 그러한데요. 아래의 화면이 그 예입니다.

선형이 짧은 관망(Network)과 같은 경우에 선형의 중심에 하나의 라벨을 표현해 주는 것이 적합한 반면, 위의 경우처럼 선형이 긴 경우에는 라벨을 일정한 기준에 따라 반복적으로 표현해 줘야 합니다. 아래의 화면이 라벨을 반복적으로 표현해 주는 예입니다.

위처럼 라벨을 일정한 간격마다(Pixel 단위) 반복적으로 표현해주는 FingerEyes-Xr의 코드는 아래와 같습니다.

var label = lyr.label();
label.repeatMode(true).repeatLength(300);
...

라벨의 repeatMode 함수에 true 인자를 전달하여 라벨의 반복을 지정하고, 300px 간격으로 반복되도록 repeatLength 함수에 300 인자를 지정하였습니다.

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를 활용한 A* 알고리즘

실제 도로망은 U턴 제한이나 우회전 제한 등과 같은 회전 제한에 대한 성질과 좌측 및 우측 차로에 대한 방향에 대한 성질을 가집니다. 이러한 성질에 대한 속성값을 가지는 네트워크 데이터는 지능형 교통체계 표준 노드링크 관리시스템(http://nodelink.its.go.kr)에서 제공하고 있습니다.

이 글은 지능형 교통체계 표준 노드링크 관리시스템에서 제공하는 네트워크 DB에 대해 A* 알고리즘을 적용하는 각 단계별 과정에 대한 상태정보를 기록한 자료에 대한 글입니다. A*에 대한 자세한 설명은 기존의 최단 경로 탐색 – A* 알고리즘이라는 글을 참고하시기 바랍니다. 본 글은 A* 알고리즘을 확장하고 응용한 글이므로 반드시 A* 알고리즘을 완전하게 이해하고 있는 상태에서만 의미있게 이해될 수 있는 글이라는 점을 알려드립니다.

해결하고자 하는 네트워크 DB에서의 최적경로에 대한 문제는 아래 그림과 같습니다.

위의 문제에 대해 확장된 A* 알고리즘을 통해 최종적으로 도출된 그 결과는 아래의 그림과 같습니다.

해결하고자 하는 문제와 그 결과 도출을 위한 알고리즘의 각 단계를 정리한 내용은 아래의 pdf 파일에 담겨 있습니다.