C#의 스레드(Thread)에서 UI 컨트롤 사용하기

기본적으로 UI를 갖는 컨트롤은 메인 스레드가 아닌 다른 스레드에서 접근될때 충돌(Crash)이 발생합니다. 현재 C/S 기반의 맵엔진인 듀라맵을 서버단에서 사용하고 있으며, 서버에서 여러 개의 스레드에서 UI 컨트롤인 듀라맵에 접근할때 아래와 같은 충돌이 발생합니다.

사용자 삽입 이미지

이에 대한 해결 방안은 델리게이트(Delegate)와 UI 컨트롤을 담는 Form 클래스의 Invoke 매서드를 사용해 해결할 수 있습니다.

예를 들어서 지도 엔진인 듀라맵을 이용해 어떤 지점이 특정 폴리곤에 포함(Contain)하는지에 대한 기능을 수행하고자 할 때를 살펴 보겠습니다.

듀라맵을 이용해 다음과 같은 Contain이라는 새로운 사용자 정의 매서드를 만들었습니다. 이 Contain 매서드의 위치는 어디라도 상관이 없습니다. 중요한 것은, 바로 이 Contain이라는 매서드가 별도의 스레드를 통해 호출된다는 것이고 델리게이트 기법을 사용하지 않는다면 충돌이 발생합니다.

public bool Contain(double X, double Y, int FID)
{
    //UI 컨트롤 사용
}

별도의 스레드에서 문제 없이 위에서 언급한 Contain이라는  매서드를 호출하기 위해서는, Contain 매서드를 직접 호출하지 않고 델리게이트(대리자)를 사용하면 됩니다. 델리게이트를 다음처럼 Contain 매서드가 존재하는 같은 클래스에 선언합니다.

private delegate bool DelegateContain(double X, double Y, int FID);
private DelegateContain delegateContain;

이제 위의 델리게이트와 Contain 매서드를 연결하는 코드는 다음과 같습니다.

delegateContain = new DelegateContain(Contain);

이제 메인 스레드가 아닌 스레드에서 Contain 매서드의 기능을 활용하기 위해서는 Contain에 대한 델리게이트인 delegateContain를 사용하면 됩니다. 즉, 다음처럼…

bool bContain = (bool)form.Invoke(delegateContain, X, Y, FID);

스레드에서 사용하고자 하는 UI 컨트롤이 담긴 폼 객체의 Invoke 매서드를 사용해 delegateContain을 호출하며 Contain 매서드의 인자는 Invoke 매서드를 통해 전달하면 됩니다. Invoke는 가변 인자를 받으므로 인자의 제약이 덜합니다. 또한 Invoke의 반환값은 델리게이트 대상이 되는 함수의 반환값이며 object 타입이므로 Contain 매서드의 반환값으로 형변환하여 사용하면 됩니다.

[GIS] SHP2SQL ㅡ MSSQLServer Version

SHP 파일에 대한 속성정보와 MBR 정보를 MSSQL Server의 DB 테이블에 저장해 주는 SQL문을 생성해 주는 툴입니다. 포인트 SHP 파일은 MBR 정보에 대해서 포인트(X, Y) 값을 저장하고 폴리라인과 폴리곤의 경우 MinX, MinY, MaxX, MaxY 값을 저장해 줍니다.

(주)지오서비스의 공간서버인 GeoService-Xr이 공간 데이터에 대해 MSSQLServer를 지원하게 되면서 부차적인 목적으로 필요하여 만들어진 툴입니다. 이 프로그램은 듀라맵(DuraMap-Xr)을 기반으로 SHP 파일을 처리하므로 듀라맵이 먼저 설치되어 있어야 합니다.

사용자 삽입 이미지
위의 화면에서처럼 속성 데이터에 대해 선택할 수 있습니다. 그리고 테이블을 생성할 CREATE SQL문과 레코드를 입력할 INSERT SQL에 대해서 따로 저장하도록 되어 있습니다. 위의 화면에 대한 실행 결과로써 CREATE SQL 문에 대한 결과는 다음과 같습니다.

사용자 삽입 이미지
그리고 INSERT SQL 문에 대한 결과는 다음과 같습니다.

사용자 삽입 이미지
실행 파일과 소스 파일은 아래의 경로를 통해 다운로드 받으시기 바랍니다. 비록 이 툴은 MSSQL Server에 대한 SQL문을 생성하지만 다른 DBMS의 경우 소스코드를 약간 변경하여 다른 DBMS에 맞는 SQL 구문을 얻을 수 있습니다.

[GIS] 공간 데이터 좌표 변환툴 – XrProjection

이 툴에 대한 최신 버전은 XrProjection v3.1 을 통해 다운로드 받아 사용하시기 바랍니다.

개발자 피드백

  • EPSG900913(구글좌표계)를 지원합니다. 구글좌표계는 WGS84 타원체를 사용하므로 WGS84 타원체가 아닌 좌표계 간의 변환에서는 반드시 변환 파라메터를 지정하셔야 합니다 ㅡ 2013/07/23
  • WGS80 타원체의 경위도에 대한 Bessel 타원체/GRS80 타원체의 경위도에 대한 상호 좌표변환은 반드시 변환 파라메터 사용 여부를 체크해야 옳바르게 변환됩니다 ㅡ 2013/05/30
  • 행안부 새주소 좌표계(UTM-K)와 관련된 좌표계 변환 정확도 문제 제거하였습니다 ㅡ 2013/03/22
  • WGS84 타원체에서 다른 좌표계로의 변환 정확도 문제를 제거하였습니다 ㅡ 2012/10/28

공간 데이터에 대한 좌표 변환툴입니다. SHP 파일에 대한 좌표 변환과 폴더에 저장된 모든 파일에 대한 좌표 변환 그리고 좌표 하나에 대한 좌표 변환 끝으로 Degree와 DMS 간의 변환 기능을 제공합니다. 이와 함께 좌표 변환에 사용되는 3 파라메터와 7 파라메터를 지정할 수도 있습니다.

각 기능에 대한 UI는 탭으로 독립되어 있어서 사용하기에 쉽고 직관적입니다. 이 프로그램에 대한 소스 코드와 실행 파일을 별도로 분리하여 아래 링크를 통해 다운로드 받을 수 있습니다. 이 프로그램은

듀라맵과 .NET 2.0 프레임워크를 사용합니다.

먼저 좌표변환시 사용할 3 파라메터 또는 7 파라메터를 지정하는 UI입니다. 실제 업무에서 있어서 특별한 경우가 아니라면 이 파라메터의 지정은 하지 않으며 공간 데이터를 제공하는 곳에서 특별한 언급이 있는 경우에 사용하시기 바랍니다.

사용자 삽입 이미지
다음은 하나의 SHP 파일에 대한 좌표 변환 기능입니다. 변환하고자 하는 SHP 파일과 변환하고자 하는 SHP 파일의 원래 좌표계를 지정하고 변환되어 저장 출력될 SHP 파일과 변환될 좌표계를 지정하면 됩니다.

사용자 삽입 이미지
다음은 폴더 단위로 좌표변환을 하는 기능입니다. 지정한 폴더에 저장된 모든 SHP 파일이 좌표 변환되어 원하는 출력 폴더로 저장됩니다. 많은 SHP 파일을 한번에 좌표 변환할때 유용하게 사용할 수 있는 기능입니다.

사용자 삽입 이미지
다음은 하나의 좌표에 대한 변환 기능입니다. 하나의 좌표의 변환만을 해보거나 좌표 변환 기능을 테스트해 볼 때 유용한 기능입니다.

사용자 삽입 이미지
끝으로 하나의 Degree(도) 단위 값의 각도를 DMS(Degree, Minute, Second)의 3개의 값으로 분리하거나 이와 반대로 변환해 주는 기능입니다.

사용자 삽입 이미지
이 프로그램은 맵엔진인 듀라맵을 이용해 개발되었습니다. 실행을 위해 먼저 듀라맵을 시스템에 등록하셔야 합니다. 듀라맵에 대한 소개는 다음 UR을 통해 살펴보시기 바랍니다.

[GIS] BlackPoint-Xr, 네트워크를 통한 공간 데이터 서비스

안드로이드(Android) GIS 엔진인 블랙포인트에서 네트워크를 통해 항공영상이나 수치지도를 받아 지도로 표시하는 기능에 대한 샘플 코드를 정리해 봅니다. 먼저 항공영상에 대한 레이어를 추가한느 코드는 다음과 같습니다.

ILayer aerial = new TileImageLayer(
    "aerial", 
    "http://222.237.78.28:8080/tiles/a", 
    false);

layerMan.addLayer(aerial);

TileImageLayer 클래스의 생성자 함수의 첫번째 인자는 레이어의 식별자이고 두번째는 항공영상지도를 받아올 인터넷 URL입니다. 세번째는 파일에서 항공영상을 처리하는 것이 아니므로 false를 지정합니다. 다음은 수치지도를 표시하는 코드 예입니다.

ShapeLayer jibun = new ShapeLayer(
    "jibun", 
    "http://222.237.78.28:8080/Xr?layerName=jj");

layerMan.addLayer(jibun);

ShapeLayer 클래스의 생성자 함수의 첫번째 인자는 레이어의 식별자이고 두번째는 수치지도를 받아올 인터넷 URL입니다.

안드로이드 GIS 엔진인 블랙포인트는 공간 데이터를 SD 카드를 통한 로컬 방식과 네트워크를 통해 받아 사용 방식에 대해서 모두 동일한 TileImageLayer와 ShapeLayer를 사용함으로써 라벨이나 속성, 좌표 등의 정보를 얻어오고 사용하는 방식이 동일합니다. 다음은 위의 예제에서 추가한 항공영상과 수치지도를 추가한 화면입니다.

[GIS] FingerEyes-Xr, TMS(OSGeo Spec) 지원

핑거아이즈가 OSGeo 스펙인 TMS를 지원합니다. TMS는 타일맵 형태의 맵 서비스로 오픈스트리트, 다음, 네이버, 지오서비스의 지도 서비스에서 따르는 맵 서비스 형태입니다. 핑거아이즈에서  TMS를 지원함으로써 사용자가 원하는 다양한 배경지도를 쉽게 활용할 수 있습니다. 다음은 네이버에서 제공하는 배경지도를 핑거아이즈에서 레이어로 추가한 화면입니다.

사용자 삽입 이미지
TMS를 활용하기 위해서는 최소한 다음과 같은 메타데이터(Metadata)를 알고 있어야 합니다.

  • 1픽셀에 대한 지도단위 길이
  • 타일맵 이미지 요청 URL
  • MBR(Boundray)
  • 타일맵 이미지 크기(256×256 등)
  • 타일맵 이미지 형식(PNG/JPEG/GIF 등)

다음은 핑거아이즈에서 네이버의 지도를 TMS를 통해 레이어로 추가하는 코드입니다.

var lyr:IXrLayer = new XrTMSLayer(
  "basemap", 
  [
    "http://onetile1.map.naver.net/get/18/0/0/${z}/${x}/${y}/bl_vc_bg/ol_vc_an",
    "http://onetile2.map.naver.net/get/18/0/0/${z}/${x}/${y}/bl_vc_bg/ol_vc_an",
    "http://onetile3.map.naver.net/get/18/0/0/${z}/${x}/${y}/bl_vc_bg/ol_vc_an",
    "http://onetile4.map.naver.net/get/18/0/0/${z}/${x}/${y}/bl_vc_bg/ol_vc_an"
  ],     
  [2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5, 0.25],
  new XrExtent(90112, 1192896, 1990673, 2761664)
);
    
map.layers.addLayer(lyr);

참고로 TMS를 지원 사이트에서 지도 데이터를 업데이트 하면서 metadata가 자주 변경될 수 있습니다.