[GIS] 표준 GML/KML/WMS/WFS에 대한 요약

자주 솔루션에 대한 요구사항으로 표준을 준수하는가… 라는 대응 항목 중 gml, kml, wms, wfs 이 있습니다. 새로운 gis 데이터 서버 개발에 이러한 표준 항목을 준수하기 위한 준비로 해당 항목에 대해 개략적으로 파악할 목적으로 작성한 내용입니다.

GML (Geography Markup Language)
http://www.opengeospatial.org/standards/gml

GML은 지리적 특성을 표현하기 위한 XML 문법입니다. GML은 인터넷에서 지리 데이터 송수신을 위한 개방된 교환 포맷임과 동시에 지리데이터 시스템을 위한 모델링 언어로써 사용됩니다. 문법에 기반한 대부분의 XML과 같이 두 부분으로 나눠져 있습니다.

  1. 문서의 설명 부분
  2. 실제 데이터 부분

GML 문서는 GML 스키마를 사용하여 기술됩니다. 이는 사용자와 개발자에게 포인트, 라인 그리고 폴리곤을 포함하는 일반적인 지리데이터셋을 설명할 수 있도록 합니다. 그러나 GML의 개발자들은 GML의 확장을 특화시키는 커뮤니티 지향적인 어플리케이션 스키마를 정의하기 위한 커뮤니티 작업을 상상합니다. 어플리케이션 스키마를 사용하여 사용자는 일반적인 포인트, 라인, 폴리곤을 길, 고속도로 그리고 다리로써 참조할 수 있습니다. 만약 커뮤니티의 모든 사람이 동일한 스키마를 사용하는 것에 대해 동의한다면 데이터를 쉽게 교환할 수 있으며 도로에 대한 라인을 표시할때 도로로 표시할 수 있게 됩니다.

KML(Keyhole Markup Language)
http://earth.google.com/intl/ko/userguide/v4/ug_kml.html
http://en.wikipedia.org/wiki/Keyhole_Markup_Language

KML은 현재 또는 미래의 웹 기반의 2차원과 3차원 브라우저에서 지리 데이터의 주기와 가시화를 위한 XML 기반의 스키마입니다. KML은 Google 어스, Google 지도 및 기타 응용 프로그램에 표시하기 위해 점, 선, 이미지, 다각형 및 모델과 같은 지형 기능을 모델링하고 저장하기 위한 XML 문법 및 파일 형식입니다. KML을 사용하여 Google 어스 및 Google 지도의 다른 사용자와 장소 및 정보를 공유할 수 있습니다. KML은 구글어스에서 사용하기 위해 개발되어졌으며 원래 이름은 Keyhole Earth Viewer였습니다. Keyhole 사에서 만들어졌으며 이 회사는 2004년에 구글로 인수되었습니다. 현재 KML은 오픈 GIS 컨소시엄의 국제 표준입니다. KML을 표현하고 편집할 수 있는 첫번째 프로그램은 구글어스이며 KML을 지원하는 툴이 다양하게 제공되고 있습니다.

참고 : KMZ 파일은 KML 파일의 압축된 버전입니다.

WMS(Web Map Service)
http://en.wikipedia.org/wiki/Web_Map_Service

WMS는 GIS 데이터베이스의 데이터를 사용하는 지도 서버로부터 생성되어진 지오레퍼런싱된 지도 이미지를 서비스하기 위한 표준 프로토콜입니다. 스펙은 1999년에 오픈 GIS 컨소시엄에서 처음 개발어 공개되었습니다.

WMS는 다양한 요청 타입을 가지고 있으며 WMS 서버는 다음 2가지 요청 타입을 제공해야 합니다.

  1. GetCapabilities : WMS에 대한 인자값과 이용가능한 지도 레이어 목록 반환
  2. GetMap : 해당 인자에 대한 지도 이미지

다음은 WMS 서버에서 옵션으로 제공하는 요청 타입입니다.

  1. GetFeatureInfo
  2. DescribeLayer
  3. GetLegendGraphic

WMS는 클라이언트가 인터넷으로부터 접근할 수 있는 지도와 GIS 데이터 포맷을 폭넓게 지원합니다. WMS를 지원하는 주요 상업적인 GIS 및 맵핑 소프트웨어는 다음과 같습니다.

  • Bentley Systems’s GIS products
  • ESRI’s ArcGIS products
  • MapInfo Professional
  • GeoMedia
  • Manifold System
  • Google Earth

또한 WMS를 지원하는 오픈소스 제품군은 다음과 같습니다.

  • Quantum GIS
  • uDig
  • OpenJUMP
  • MapGuide Open Source
  • NASA World Wind
  • GRASS GIS
  • gvSIG
  • OpenLayers

WFS(Web Feature Service)
http://en.wikipedia.org/wiki/Web_Feature_Service

WFS는 플랫폼에 독립적인 호출을 이용하여 웹에서 지리데이터에 대한 피쳐(feature)를 요청할 수 있는 인터페이스를 제공합니다. WMS가 단순히 지도 이미지만을 서비스하는데 반해 WFS는 공간 분석 등과 같은 연산을 위해 필요한 데이터를 서비스 합니다.

WFS의 서비스 기능은 다음과 같습니다.

  1. 공간 또는 비공간 조건에 기반한 피쳐(feature)의 쿼리
  2. 새로운 피쳐 생성
  3. 피쳐 삭제
  4. 피쳐 업데이트

가장 기본적인 WFS 서버는 반드시 공간 또는 비공간 조건에 기반한 피쳐의 쿼리 기능을 지원해야 하며, 트랜젝션 WFS(WFS-T)는 피쳐의 생성과 삭제 그리고 업데이트를 제공합니다.

 

[GIS] 폴리곤 SHP를 KML로 변환하는 툴

폴리곤 SHP를 KML로 변환하는 툴을 요청하는 분이 계셔서 바로 만들어 올립니다. 원래 오늘 정도 만들어 올리려고 했는데… 먼저 필요한 분이 있어서 기쁜 마음에 올려봅니다.

사용자 삽입 이미지

폴리곤 타입의 SHP를 지정하고… 높이 값에 대한 필드를 지정하여 건물과 같은 Feature를 입체감있게 표현할 수 있도록 하였습니다. 높이 값에 어떤 수를 곱할 수 있도록 값을 지정할 수 있도록 하였으니 참고하시구요. 만약 높이값에 대한 필드가 딱히… 없다면 일정한 높이 값을 지정할 수도 있게 하였습니다. 아래는 건물 SHP을 KML로 내보내어 구글어스에서 본 화면입니다. 참고로 SHP 파일의 좌표계는 WGS84 경위도 좌표계를 가지고 있어야 구글어스에서 옳바른 위치가 적용됩니다.

사용자 삽입 이미지
포인트나 폴리라인을 kml로 변환하는 다른 툴보다 상대적으로 사용법이 다소 복잡한데… 이해가 않되시거나 실행이 않되는 분들은 언제든 댓글을 통해 질문 남겨주시기 바랍니다.

[GIS] 폴리라인 SHP을 KML로 변환

폴리라인 타입의 SHP 파일을 KML로 변환할 수 있는 툴입니다. 요즘 부쩍 KML에 대해 관심이 높습니다. OGC에서 표준으로 채택된 포맷인지라…. 활용도도 매우 높을거란 판단에서 인듯 합니다. 잠시 시간을 내어 만들어 보았습니다. 아래는 툴의 실행화면인데…. 사용법은 매우 간단합니다. 폴리라인 타입의 SHP 파일과 저장할 KML 파일 이름을 지정해 주면됩니다.

사용자 삽입 이미지

만약 폴리라인 타입이 아닌 폴리곤 SHP을 지정했을 경우에도 폴리곤이 아닌 폴리라인으로 내보내집니다. 하지만 포인트의 경우 그 결과가 어떻게 될지 모르겠습니다. 좌표계는 구글어스에서 사용하는 WGS84 경위도 좌표계로 저장된 SHP 파일일 경우에 제대로 구글어스에서 중첩됩니다. 아래는 위의 툴로 내보낸 SHP 파일을 구글어스에서 함께 표현한 화면입니다.

사용자 삽입 이미지
혹… 필요로 하시는 분들에게 도움이 되셨으면 좋겠습니다.

[GIS] SHP를 Point Type의 KML로 변환

포인트, 폴리라인, 폴리곤에 대한 SHP를 KML 포맷으로 변환할 수 있는 유틸리티입니다. 선택 기능으로써 SHP의 속성값을 라벨로 표시할 수 있는 기능도 제공됩니다. SHP 파일의 좌표계는 WGS84 경위도 좌표계여야 합니다.

사용자 삽입 이미지

위의 프로그램으로 SHP 파일을 KML로 내보내 구글어스에서 살펴본 화면은 아래와 같습니다. 처음 화면은 기본 화면이며 두번째 화면이 변환된 KML과 함께 표현한 것입니다.

사용자 삽입 이미지
사용자 삽입 이미지
참고로… 이 툴은 오픈소스인 ShapeLib를 이용해 SHP 파일의 도형 정보와 속성 정보를 읽어 만들었습니다. ShapeLib는 http://cafe.naver.com/gisdev에서 자세한 사용법을 알 수 있으니 SHP 파일을 처리할 필요가 있으신 분은 한번 참조해 보시기 바랍니다.

참고로… 이 프로그램을 만들면서 찾은 정보입니다. 먼저 Visual C++ 2005 이상에서 MFC 대화창 기반의 어플리케이션 개발 시에 XP 테마를 적용하기 위해서는 다음 코드를 임의의 헤더 파일이나 소스 파일에 포함해야 합니다.

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")

그리고 KML 파일의 내용은 utf-8로 인코딩되어야 하며 C/C++에서 ansi 문자셋를 utf-8 문자셋으로 변환하기 위해 사용한 코드는 아래와 같습니다.

void CPoint2KmlDlg::SaveAsUTF8(FILE *pFile, char *pszCode)
{
    int  nLength, nLength2;
    BSTR bstrCode; 
    char *pszUTFCode = NULL;

    nLength = MultiByteToWideChar(CP_ACP, 0, pszCode, 
        lstrlen(pszCode), NULL, NULL); 
    bstrCode = SysAllocStringLen(NULL, nLength); 
    MultiByteToWideChar(CP_ACP, 0, pszCode, lstrlen(pszCode), bstrCode, nLength);

    nLength2 = WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, pszUTFCode, 
        0, NULL, NULL); 
    pszUTFCode = (char*)malloc(nLength2+1); 
    WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, pszUTFCode, 
        nLength2, NULL, NULL); 

    fprintf(pFile, "%s", pszUTFCode);

    SysFreeString(bstrCode);
    free(pszUTFCode);
}

첫번째 인자는 출력할 파일의 핸들이며 두번째는 널문자로 끝나는 ansi 문자 배열을 넘겨주게 되면 utf-8로 변환되어 저장됩니다. 위의 코드의 출처는 http://skorea.tistory.com/43 입니다.

[C++] XML 파서, CMarkup

XML 데이터를 쓰고 읽기 위해서 인터넷을 검색하던 차에 속도를 강점으로 내세우면서 STL 만을 사용하여 플랫폼 이식에도 뛰어난 오픈소스를 찾았는데요. 바로 CMarkup 입니다. 다운로드 사이트는 http://www.firstobject.com/ 이구요. 사용해 보니 XML의 charset도 지원하여 더욱 믿음이 가는 오픈소스였습니다. XML을 처리할 일이 있다면 한번 사용해 보시기 바랍니다.

추후 이 오픈소스를 다시 사용할 때를 대비하여 사용 방법을 정리해 정리차원에서 올려봅니다.

컴파일 시 주의할 사항은… CMarkup은 MFC의 CString와 STL의 string에 대한 문자열 타입을 사용하며 기본적으로 CString을 사용합니다. 플랫폼에 독립적인 구성을 위해서 STL을 사용하는것이 좋기 때문에 전처리에서 MARKUP_STL를 정의해줘야 합니다. 이 전처리 정의는 프로젝트의 속성 페이지에서 해줌으로써 전역적으로 적용되도록 해야 합니다. 아래의 코드는 XML을 쓰는 예제 코드입니다. 윈도우즈 계열의 개발툴인 VS2008로 작성했습니다.

#include "stdafx.h"
#include "../Markup.h"

int _tmain(int argc, _TCHAR* argv[])
{
    CMarkup xml;

    xml.AddElem( "ORDER" );
    xml.AddChildElem( "ITEM" );
    xml.IntoElem();
    xml.AddAttrib("type", "A");
    xml.AddChildElem( "SN", "132487A-J" );
    xml.AddChildElem( "NAME", "crank casing" );
    xml.AddChildElem( "QTY", "1" );
    xml.OutOfElem();

    xml.AddChildElem( "ITEM" );
    xml.IntoElem();
    xml.AddAttrib("type", "C");
    xml.AddChildElem( "SN", "434417F-Y" );
    xml.AddChildElem( "NAME", "kully casing" );
    xml.AddChildElem( "QTY", "2" );
    xml.OutOfElem();

    std::string csXML = xml.GetDoc();

    printf("%s", csXML.c_str());

    return 0;
}

결과는 다음과 같습니다.

사용자 삽입 이미지
AddElement를 통해 엘리먼트를 만들고, 해당 엘리먼트의 자식을 추가하기 위해 AddChildElem을 사용하거나 먼저 IntoElem을 호출한 후 다시 AddElement를 사용합니다.

이제 반대로 위와 같은 XML 데이터를 읽어 보도록 하겠습니다. 먼저 위의 결과를 파일로 저장해 놓고 그 파일을 읽어 데이터를 추출하는 예제를 들어 보겠습니다. 예를 들어… 아이템(ITEM)의 이름(NAME)과 수량(QTY)을 읽어 보도록 하겠습니다. 위의 XML 문자열의 경우 아이템의 개수는 총2개이므로 2개가 검색될 것입니다. 다음이 이 예제와 부합되는 코드입니다.

CMarkup xml;
xml.Load("d:/data.xml");

while ( xml.FindChildElem("ITEM") )
{
    xml.IntoElem();

    xml.FindChildElem( "NAME" );
    std::string csSN = xml.GetChildData();
    xml.FindChildElem( "QTY" );
    int nQty = atoi(xml.GetChildData().c_str());

    xml.OutOfElem();

    printf("%s, %d\n", csSN.c_str(), nQty);
}

먼저 XML 데이터를 가지고 있는 파일을 Load 매서드를 이용해 읽습니다. 다시 반복문을 사용하여 루트 엘리먼트의 자식 ITEM 엘리먼트를 검색하기 위해 FindChildElem을 사용합니다. 그러면 해당되는 자식 엘리먼트가 추출됩니다. 해당되는 자식 엘리먼트의 자식 엘리먼트를 읽기 위해 IntoElem() 함수를 사용한 뒤에 원하는 엘리먼트(NAME, QTY)를 검색하기 위해 FindChildElem을 호출하고 실제로 값을 읽기 위해서 GetChildData 매서드를 호출합니다. 다 읽은 후 OutOfElem()을 호출합니다. 결과는 아래와 같습니다.

사용자 삽입 이미지