DuraMap-Xr 소개 및 다운로드

듀라맵은 3.5MB 크기의 단 하나의 dll 파일로 구성되어 있는 매우 작은 크기의 경량 지도 엔진입니다. 꼭 필요한 기능만을 담아 최적화 되어 있으며 빠른 퍼포먼스를 제공합니다. 듀라맵은 GIS 맵엔진으로써 작지만 매운 꼬추라고 할 수 있겠습니다. 프로그래밍이 가능한 분이라면 DuraMap-Xr을 이용하여 GIS 시스템 개발은 물론 공간 데이터를 다양하게 생성하고 가공할 수 있으며 공간분석 알고리즘을 실제로 구현할 수 있는 API를 제공합니다.

DuraMap-Xr은 COM을 지원하는 프로그래밍 언어에서 사용할 수 있는 컴포넌트이며 VB, Delphi, C#, C++을 이용하여 C/S 기반의 어플리케이션을 개발할 수 있으며 HTML과 자바스크립트를 이용하여 웹브라우저에서 운영되는 웹 GIS 시스템을 쉽게 개발할 수 있습니다(하지만 저희는 ActiveX인 듀라맵을 이용하여 웹기반의 시스템 개발을 권장하지 않습니다). DuraMap-Xr은 기본적으로 다음과 같은 큰 범주의 기능을 제공합니다. (자세한 내용에 대해서 각 항목 클릭 가능)

위의 기능은 DuraMap-Xr 맵 엔진을 통해 로컬에 저장된 공간 데이터를 대상으로 수행되는 기능이며 동시에 원격으로 분리된 서버로부터 제공되는 공간 데이터에 대해서도 동일하게 지원됩니다. 공간 데이터 서비스는 GeoService-Xr 공간서버로부터 제공됩니다.

듀라맵에서 항공영상 또는 위성영상(geotiff)을 자체포맷 형태로 표시하고 싶을 경우 변환툴은 다음 url을 통해 다운받으실 수 있습니다.

듀라맵(DuraMap-Xr)과 블랙포인트(BlackPoint-Xr)의 항공영상(위성영상) 자체 포맷 변환툴

DuraMap-Xr은 단일 파일(DuraMap-Xr.dll)로 구성됩니다. 기능을 확장할 수 있는 플러그인 기능 개발을 위한 COM 객체도 이 파일 안에 포함합니다. DuraMap-Xr을 설치하기 위해서는 아래의 URL에서 설치 프로그램을 통해 쉽게 하실 수 있습니다.

DuraMap-Xr 설치자 프로그램   

설치자 프로그램을 사용하지 않고 직접 DuraMap-Xr.dll을 등록하고 설치하기 위해서는 다음과 같은 절차로 할 수 있습니다.

(등록방법 동영상)   

  1. DuraMap-Xr.dll을 다운로드(지오서비스 자료실)받습니다. 
  2. DuraMap-Xr.dll을 원하는 폴더에 저장합니다.
  3. 명령 프롬프트 창을 실행합니다. (비스타 또는 윈7에서는 관리자 권한으로 실행)
  4. 명령 프롬프트 창에서 DuraMap-Xr.dll이 저장된 폴더로 이동합니다.
  5. regsvr32 DuraMap-Xr.dll을 입력하여 등록합니다.

아래의 그림은 명령 프롬프트 창에서 XrMap.dll을 등록하는 화면입니다. (D:\ 드라이브의 DuraMap 폴더에 DuraMap-Xr.dll 복사된 경우의 예)

사용자 삽입 이미지

성공적으로 등록이 되면 다음과 같은 메세지가 표시됩니다.

사용자 삽입 이미지

등록이 완료되면 C# 또는 C++, 델파이, VB나 IE에서 자바 스크립트를 이용하여 DuraMap-Xr을 사용할 수 있습니다. 끝으로 DuraMap-Xr의 API에 대한 튜토리얼은 다음 URL과 같습니다.

DuraMap-Xr 글 검색

또한 DuraMap-Xr에 대한 질문과 개선점에 대한 건의는 hjkim@geoservice.co.kr로 메일 주시기기 바랍니다.

[GIS] DuraMap, 듀라맵 3.1.0.1 버전업

듀라맵이 3.1.0.1로 버전업 되었습니다. 추가된 기능 2가지와 해결된 오류입니다. 먼저 해결된 오류는 윈도우즈 XP에서 편집시 잦은 다운현상을 해결하였습니다. 이 문제에 대한 이유는 XP와 비스타(Windows 7 포함)에서 동기화 객체인 CriticalSection의 작동에 차이가 발생하는 것에 원인이 있었습니다. 그리고 추가된 기능 2가지는 다음과 같습니다. 첫번째로 사용자가 정의한 도형을 포인트 심벌로 사용할 수 있게 되었습니다. 그리고 두번째는 폴리곤의 라벨 표시에서 항상 폴리곤 위에 표시되도록 개선함으로써 라벨의 가시성을 향상시켰습니다.

먼저 사용자 정의 도형을 포인트 심벌로 지정하는 기능은 추후 CAD 데이터를 완벽하게 지원하기 위한 기능으로 CAD에서는 포인트에 대해 Block Symbol 기능과 유사합니다. 이 기능은 추후 CAD 데이터(DXF 파일)을 지원하는 기능을 추가할때 이 기능이 유용하게 사용될 예정입니다.

사용자 삽입 이미지
그리고 라벨 표시에서 항상 폴리곤 위에 표시되도록 개선한 기능은.. 기존에 폴리곤의 라벨은 항상 도형의 무게중심점(Centroid)를 기준으로 라벨을 표시하도록 하였으나 가끔 폴리곤 밖으로 라벨이 표시되는 현상이 발생하여 항상 도형 안에 라벨이 표시되도록 한 기능입니다. 위의 이미지에서 첫번째는 일반적인 도형의 무게중심점 위치에 라벨을 표시하도록 한 이미지이고 두번째가 이번에 새롭게 개선된 라벨 표시에 대한 이미지입니다.

추가된 새로운 기능에 대한 API 사용방법에 대해서는 추후 별도의 글을 통해 소개드리도록 하겠습니다.

SimpleSHP v0.1

SimpleSHP는 ESRI에서 정의한 SHP와 DBF 파일을 처리하기 위한 자바 클래스 모음입니다. 이 라이브러리는 사용하기 쉬우며 가볍고 매우 단순한 구조를 갖습니다. 아래의 UML은 SHP 파일 Access에 대한 Class Diagram 입니다.

사용자 삽입 이미지

SHP 파일에 대한 Access에 대한 예제 코드는 아래와 같습니다.

AccessSHP access = new AccessSHP("filename.shp");
RowSetSHP rowSet = access.getRowSet();
int rowCount = rowSet.getRowCount();
try {
    for(int fid=0; fid < rotCount; fid++) {
        RowSHP row = rowSet.getRow(fid+1);
        if(row.load()) {
            System.out.println(row.getFID());
            Geometry geom = row.getGeometry();
            System.out.println(geom.getEnvelopeInternal().toString());
            row.unload();
        }
    }

    access.release();
} catch (IOException e) {
    e.printStackTrace();
}  

사용자 삽입 이미지

DBF 파일에 대한 Access에 대한 예제 코드는 아래와 같습니다.

AccessDBF access = new AccessDBF("filename.dbf");
RowSetDBF rowSet = access.getRowSet();
int rowCount = rowSet.getRowCount();
try {
    for(int fid=0; fid < rowCount; ++fid) {       
        RowDBF row = rowSet.getRow(fid+1);
        if(row.load()) {
            System.out.println(row.getFID());
            FieldSet fieldSet = access.getFieldSet();
            for(int iField=0; iField                Field field = fieldSet.getField(iField);
                System.out.println(field.getFieldName() 
                    + ": " + row.getValueAsString(iField));
            }
  
            row.unload();
        }

        access.release();
    }
} catch (IOException e) {
    e.printStackTrace();
}  

버전 이력
           1.  v0.1 2011/05/20 최초 배포

라이브러리 소스코드 다운로드

상세 문서 URL

http://www.gisdeveloper.co.kr/download/simpleshp

외부 참조 라이브러리

JTS(Java Topology Suite, http://www.vividsolutions.com/jts/jtshome.htm)

[GIS] FingerEyes, 차트 표시하기(차트 레이어 추가)

핑거아이즈에 대한 마지막 API 사용 실습 튜토리얼로써 공간상에 의미있게 분포되어 있는 수치데이터를 차트로 표현하는 기능에 대해 살펴보겠습니다. 이 글에 대한 최종 결과에 대한 실행은 아래와 같습니다. 각 집계구에 나이대별 인구수를 파이차트로 표현하는 예입니다.

사용자 삽입 이미지실행 결과 보기 및 소스코드 다운로드

위의 실행 결과를 살펴보면 어플리케이션에 대한 UI는 총 3개입니다. 차트표시라는 버튼, 범례표시라는 버튼 그리고 맵 컴포넌트입니다. 이 UI를 구성하기 위해 먼저 MXML Application을 추가하고 UI 구성을 위한 MXML에 다음과 같은 코드를 추가합니다.


    
        
        
    

맵 컴포넌트에 대한 네임스페이스를 xr로 잡고 있는데 이 네임스페이스가 유효하기 위해서는 Application 태그쪽에 다음과 같은 네임스페이스 속성이 필요합니다.


다시 UI 구성을 위한 코드를 살펴보면.. 맵 컴포넌트의 id를 map으로 주어 다른 코드부에서 참조할 수 있게 했으며 차트표시 버튼의 이벤트는 onChartClick 핸들러 함수에 할당했고 범례표시는 onLegendClick 핸들러 함수에 할당했습니다. 이 두개의 핸들러 함수에 집중하기 전에 먼저 배경이 되는 지도 레이어를 구성하는 코드를 살펴보겠습니다. 지도 레이어 준비는 어플리케이션의 initialize 이벤트가 적당하며 여기서는 onInit 핸들러 함수에 이 이벤트를 할당했습니다.

protected function onInit(event:FlexEvent):void
{
    var lyr:XrTileMapLayer = new XrTileMapLayer("basemap", 
        "http://www.geoservice.co.kr/tilemap1");
    map.layers.addLayer(lyr);
    
    map.viewControls.scaleLevels = 
    [
        3000000, 1800000, 800000, 460000, 250000, 
        110000, 50000, 25000, 14000, 7500, 3500, 2000
    ];
    map.moveMap(new XrCoordinate(317782, 544590));
    map.viewControls.scaleLevel = 11;
    
    var lyr2:XrShapeMapLayer = new XrShapeMapLayer("population", 
        "http://www.geoservice.co.kr:8080/Xr?layerName=population_polygon");
    lyr2.theme.properties = 
    {
        fillColor:0xff000000, fillAlpha:0.01, 
        lineThickness:2.0, lineAlpha:1.0, lineColor:0xff5522
    };
    lyr2.requestAttributeAlways = true;
    lyr2.visibleByLevel = true;
    lyr2.fromVisibleLevel = 10;
    lyr2.toVisibleLevel = 11;
    map.layers.addLayer(lyr2);
    
    addChartLayer();
}

3~5번 코드는 배경도로써 타일맵 레이어를 추가하는 코드이고 7~13번 코드는 어플리케이션이 시작할때 초기 지도뷰를 설정하는 코드이며 15~26번 코드는 차트 데이터를 위한 Shape 지도 레이어를 추가하는 코드입니다. 17~21번 코드는 Shape 지도 레이어의 그리기 심벌을 지정하는 코드이고 22번 코드는 통계 데이터에 대한 속성값을 할당 서버로부터 가져오라는 의미입니다. 그리고 23~25번 코드는 해당 Shape 맵 레이어가 사용자에게 보여지는 레벨을 10~11단계 사이에서만 보여지도록 하겠다는 의미입니다. 끝으로 28번 코드는 사용자 정의함수로 여기에 차트 표시를 위한 차트 레이어 추가를 위한 함수입니다. addChartLayer 함수를 살펴보겠습니다.

private function addChartLayer():void
{
    var chartLyr:XrChartLayer = new XrChartLayer("chart", null);
    chartLyr.defines.stroke.color = 0xffffff;
    chartLyr.defines.stroke.thickness = 2;
    
    var fillSym1:XrFillSymbol = new XrFillSymbol({fillColor:0xff1111});
    var fillSym2:XrFillSymbol = new XrFillSymbol({fillColor:0xff4444});
    var fillSym3:XrFillSymbol = new XrFillSymbol({fillColor:0xff8888});
    var fillSym4:XrFillSymbol = new XrFillSymbol({fillColor:0xffbbbb});
    var fillSym5:XrFillSymbol = new XrFillSymbol({fillColor:0xffdddd});
    var fillSym6:XrFillSymbol = new XrFillSymbol({fillColor:0x11ff11});
    var fillSym7:XrFillSymbol = new XrFillSymbol({fillColor:0x44ff44});
    var fillSym8:XrFillSymbol = new XrFillSymbol({fillColor:0x88ff88});
    var fillSym9:XrFillSymbol = new XrFillSymbol({fillColor:0xccffcc});
    var fillSym10:XrFillSymbol = new XrFillSymbol({fillColor:0x1111ff});
    var fillSym11:XrFillSymbol = new XrFillSymbol({fillColor:0x4444ff});
    var fillSym12:XrFillSymbol = new XrFillSymbol({fillColor:0x8888ff});
    var fillSym13:XrFillSymbol = new XrFillSymbol({fillColor:0xbbbbff});
    var fillSym14:XrFillSymbol = new XrFillSymbol({fillColor:0xddddff});
    
    chartLyr.defines.add("4세 이하", fillSym1);
    chartLyr.defines.add("5~9세", fillSym2);
    chartLyr.defines.add("10~14세 이하", fillSym3);
    chartLyr.defines.add("15~19세 이하", fillSym4);
    chartLyr.defines.add("20~24세 이하", fillSym5);
    chartLyr.defines.add("25~29세 이하", fillSym6);
    chartLyr.defines.add("30~34세 이하", fillSym7);
    chartLyr.defines.add("35~39세 이하", fillSym8);
    chartLyr.defines.add("40~44세 이하", fillSym9);
    chartLyr.defines.add("44~49세 이하", fillSym10);
    chartLyr.defines.add("50~54세 이하", fillSym11);
    chartLyr.defines.add("55~59세 이하", fillSym12);    
    chartLyr.defines.add("60~64세 이하", fillSym13);
    chartLyr.defines.add("65세 이상", fillSym14);
    
    map.layers.addLayer(chartLyr);    
}

3번코드가 차트 레이어를 생성하는 코드입니다. 그리고 4~5번 코드는 차트 레이어를 그릴때 외곽선에 대한 심벌입니다. 그리고 7~20번은 차트를 그릴때 사용하는 채움심벌을 위한 것으로 총 14개를 생성하고 있습니다. 왜 14개인가 하면… 22~35번 코드를 살펴보면 쉽게 이해할 수 있습니다. 우리는 파이차트를 그릴 것인데.. 이 차트를 구성하는 각 항목이 총 14개이고.. 나이대별(4세 이하, 5~9세 등등) 항목으로 구성하게 됩니다. 각 항목에 대해 앞서 생성해 놓은 채움심벌을 각각 지정해 놓고 있습니다. 이러한 설정이 적동된 차트레이어를 37번 코드를 통해 레이어로써 추가해 놓습니다. 이제 차트 레이어까지 추가되어 차트를 구성하기 위한 준비가 끝났군요! 다음으로 차트표시 버튼에 대한 이벤트 코드를 살펴봄으로써 차트를 어떻게 표현하는지 알아보겠습니다!

protected function onChartClick(event:MouseEvent):void
{
    var chartLyr:XrChartLayer = map.layers.getLayer("chart") as XrChartLayer;
    if(chartLyr == null) return;
    chartLyr.items.clear();
    
    var shpLyr:XrShapeMapLayer = 
        map.layers.getLayer("population") as XrShapeMapLayer;
    if(shpLyr != null)
    {
        var shpRows:Object = shpLyr.shapeSet.rows;
        for(var key:String in shpRows)   
        {    
            var shp:XrShape = shpRows[key] as XrShape; 
            var centroid:XrCoordinate = shp.centroid;
            if(shp != null)
            {
                var fid:int = shp.fid;
                var row:XrAttribute = shpLyr.attributeSet.rows[fid] as XrAttribute;
                if(row != null)
                {
                    var fs:XrFieldSet = shpLyr.attributeSet.fieldSet;
                    var A00_01:int = fs.getFieldIndex("A00_01");
                    var A00_02:int = fs.getFieldIndex("A00_02");
                    var A00_03:int = fs.getFieldIndex("A00_03");
                    var A00_04:int = fs.getFieldIndex("A00_04");
                    var A00_05:int = fs.getFieldIndex("A00_05");
                    var A00_06:int = fs.getFieldIndex("A00_06");
                    var A00_07:int = fs.getFieldIndex("A00_07");
                    var A00_08:int = fs.getFieldIndex("A00_08");
                    var A00_09:int = fs.getFieldIndex("A00_09");
                    var A00_10:int = fs.getFieldIndex("A00_10");
                    var A00_11:int = fs.getFieldIndex("A00_11");
                    var A00_12:int = fs.getFieldIndex("A00_12");
                    var A00_13:int = fs.getFieldIndex("A00_13");
                    var A00_14:int = fs.getFieldIndex("A00_14");  

                    var A00_01_value:Number = row.getValueAsDouble(A00_01);
                    var A00_02_value:Number = row.getValueAsDouble(A00_02);
                    var A00_03_value:Number = row.getValueAsDouble(A00_03);
                    var A00_04_value:Number = row.getValueAsDouble(A00_04);
                    var A00_05_value:Number = row.getValueAsDouble(A00_05);
                    var A00_06_value:Number = row.getValueAsDouble(A00_06);
                    var A00_07_value:Number = row.getValueAsDouble(A00_07);
                    var A00_08_value:Number = row.getValueAsDouble(A00_08);
                    var A00_09_value:Number = row.getValueAsDouble(A00_09);
                    var A00_10_value:Number = row.getValueAsDouble(A00_10);
                    var A00_11_value:Number = row.getValueAsDouble(A00_11);
                    var A00_12_value:Number = row.getValueAsDouble(A00_12);
                    var A00_13_value:Number = row.getValueAsDouble(A00_13);
                    var A00_14_value:Number = row.getValueAsDouble(A00_14);
        
                    chartLyr.items.add(new XrChartItem(null, 
                    [
                        A00_01_value, A00_02_value, A00_03_value, A00_04_value, 
                        A00_05_value, A00_06_value, A00_07_value, A00_08_value, 
                        A00_09_value, A00_10_value, A00_11_value, A00_12_value,
                        A00_13_value, A00_14_value
                    ], centroid));
                } 
            }
        }
     
        if(!chartLyr.items.build())
        {
             trace("Chart Building Error!");
        }
     
        map.update(false);
    }
}

코드가 상당히 긴편인데요. 실제로 참조하는 속성값이 14개나 되기때문에 길어보일뿐입니다. 하나 하나 살펴보면 단순합니다. 먼저 3번코드는 앞서 추가한 차트 레이어를 구합니다. 그리고 5번 코드를 통해 기존의 차트 데이터를 깨끗하게 지움니다. 이렇게 지우니 매번 버튼을 누를때마다 새롭게 차트를 구성할 수 있게 됩니다. 7번 코드는 차트를 구성하기 위한 수치 데이터를 참조할 Shape 맵 레이어를 구합니다. 12번 코드에 대한 반복문을 통해 Shape 맵 레이어를 구성하는 모든 도형에 대한 중심점(15번 코드)와 이 도형의 fid를 통해 얻은 속성값(19번 코드)를 통해 차트를 구성하게 됩니다. 참고로 앞서 모든 도형이라고 언급했으나 실제로는 화면상에 표시되는 도형입니다. 화면 밖의 표시되지 않은 도형은 해당사항이 없습니다. 23~36번 코드가 앞서 언급한 총 14개의 통계값을 읽기 위한 필드 인덱스를 구하는 코드들이고 실제 통계 데이터를 가져오는 코드는 38~51번 코드들입니다. 이렇게 구한 통계 값들을 53번 코드를 통해 지정하여 차트의 아이템으로써 도형의 중심점 좌표와 함께 추가해 줍니다. 최종적으로 차트 아이템들이 추가 완료되면 64번 코드를 통해 새롭게 재구성해 줘야 합니다. 이 재구성이 완료되면 차트가 화면상에 짠~ 하고 표시됩니다. 이제 이 차트 레이어에 대한 범례 구성을 위한 범례표시 버튼에 대해 이벤트 코드에 대해 살펴보겠습니다.

protected function onLegendClick(event:MouseEvent):void
{
    var legend:XrLegend = new XrLegend("legend");
    
    var vbox:XrVAlignLegendItemGroup = new XrVAlignLegendItemGroup();
    legend.content = vbox;
    
    var fontSym_title:XrFontSymbol = 
        new XrFontSymbol({fontName:"HY견고딕", fontSize:15});
    var text_title:XrTextLegendItem = 
        new XrTextLegendItem("차트 범례", fontSym_title);
    text_title.centerAlign = true;
    text_title.fillParentWidth = true;
    vbox.addItem(text_title);
    
    var lineSym_bar:XrLineSymbol = 
        new XrLineSymbol({lineColor:0x000000, lineThickness:1});
    var bar:XrBarLegendItem = new XrBarLegendItem(true, lineSym_bar);
    vbox.addItem(bar);
    
    var fontSym_Content:XrFontSymbol = 
        new XrFontSymbol(
            {fontName:"맑은 고딕", bold:true, fontSize:9, fontColor:0x000000}
        );
    var chartLyr:XrChartLayer = map.layers.getLayer("chart") as XrChartLayer;
    var chartLgd:XrPieChartLegendItem = 
        new XrPieChartLegendItem(chartLyr, 100, 100, fontSym_Content);
    chartLgd.marginLeft = 75;
    chartLgd.marginRight = 75;
    chartLgd.marginTop = 20;
    chartLgd.marginBottom = 20;
    vbox.addItem(chartLgd);
    
    legend.position.horizontalAlignment=XrRelativePosition.HORIZONTAL_ALIGN_LEFT;
    legend.position.verticalAlignment=XrRelativePosition.VERTICAL_ALIGN_BOTTOM;

    map.legends.addLegend(legend);
}  

차트 레이어에 대한 범례 구성은 듀라맵의 레이아웃 구성 기법에 유사합니다. 이에 대한 자세한 내용은

DuraMap-Xr, 통계 데이터를 이용한 주제도 작성을 참고하시기 바랍니다. 다른 점은 차트 레이어에 대해 특별하게 제공되는 범례 구성 항목으로써 XrPieChartLegendItem이 있으며 이 항목을 차트레이어와 연계하여 쉽게 차트 범례를 구성할 수 있습니다.

이상으로 Xr 솔루션 중 RIA 기반의  GIS 솔루션을 담당하는 핑거아이즈에 대한 기본적인 API 사용법에 대한 포스팅을 마무리 하도록 하겠습니다.