[GIS] FingerEyes-Xr, 핑거아이즈로 생성한 밀집도(밀도도)

아래의 이미지는 웹 GIS 엔진인 핑거아이즈(FingerEyes-Xr)로 생성한 밀집도입니다. 흔히 밀집도는 Kernel Density 알고리즘을 사용해 계산됩니다. 알고리즘 명칭에 Density가 사용되어 밀집도라는 용어 대신 밀도도라는 용어가 사용될 수도 있습니다.


위의 밀집도의 대상 데이터는 교통사고 발생 지점입니다. 해외나 국내에서 웹기반의 지도 엔진에서 제공되는 밀집도 분석 결과는 HeatMap이라는 기능에서 사용된 오픈소스를 그대로 적용하거거나 개선해 구현함으로써 그 품질이 떨어집니다.

핑거아이즈는 오픈소스이므로 위의 밀집도 결과 이미지를 생성해 내는 알고리즘에 대한 코드가 제공됩니다. 혹.. 관심이 있으신 분은 해당 소스를 참고하시기 바랍니다. 핑거아이즈의 소스코드는 http://www.gisdeveloper.co.kr/?page_id=3916의 자료실을 통해 누구나 다운로드 받으실 수 있습니다.

[GIS] FingerEyes-Xr, ShapeMapLayer의 포인트에 이미지 심벌 설정

수치지도 데이터를 서비스 받아 화면에 표시하는 레이어인 XrShapeMapLayer는 도형 데이터를 표현하는 다양한 방법을 제공합니다. 단순히는 일괄적인 색상 심벌에서부터, 속성값에 따라 달라지는 다양한 심벌에까지.. 이 포스트는 포인트 타입의 수치지도 데이터에 대해서 이미지 심벌을 지정하는 코드 예입니다.

layer = new XrShapeMapLayer("LAYER_NAME", "http://www.gisdeveloper.co.kr/Xr?layerName=SPTBL");
shpTheme = layer.theme as XrSingleColorTheme;
 
var ImgSym:XrImageMarkerSymbol = new XrImageMarkerSymbol(   
    {borderEnable:false, markerUrl:"http://www.gisdeveloper.co.kr/images/0.png"});

shpTheme.markerSymbol = ImgSym;

map.layers.addLayer(layer);

포인트 타입의 수치지도의 경우 원, 사각형 등과 같은 단순 도형에서부터 위의 글에서처럼 이미지 뿐만 아니라 특수 기호 표시를 위한 텍스트 심벌을 지원합니다.

[ActionScript] GroupingCollection2 클래스를 이용한 그룹핑(Grouping)

플래시빌더 4.7은 언제 정식 출시되나.. 지금 사용하고 있는 4.6의 차트 컴포넌트에 약간의 버그가 있고 4.7에서는 해결되기를 기대해 봅니다. 특히 4.7은 스레드 개념을 지원함으로써 더욱 유연한 개발이 가능할 것으로 기대됩니다. 이 스레드 개념은 HTML5의 Worker 기능에서 많은 힌트를 얻어 이번에 추가한 기능이 아닌가 싶습니다. 여튼………

어떤 데이터가 있다면.. 동일한 값을 가지는 녀석들을 묶는데.. 이렇게 1차적으로 묶인 녀석들에 대해서 또 한번 다른 필드의 동일한 값으로 또 묶어 그룹핑하는데 요긴하게 사용한 클래스입니다. 이 클래스의 존재를 모른체 직접 코드를 한땀.. 한땀.. 땀 한방울.. 땀 두방울 흘리며 코딩했답니다. 물론 지금은 이 클래스를 이용해 기능 개발을 했구요.

var grouping:GroupingCollection2 = new GroupingCollection2();
grouping.source = new ArrayCollection(rows);
grouping.grouping = new Grouping();
grouping.grouping.fields = 
    [ new GroupingField("FIELD1"), new GroupingField("FIELD2") ];
grouping.refresh();

성의없이.. 막 코드로 시작합니다. rows가 그룹핑할 배열(Array)입니다. 이 배열의 요소는 FIELD1과 FIELD2라는 이름의 속성값이 있습니다. 일단 FIELD1에 대해 동일한 요소들을 한번 묶고.. 다시 이렇게 묶인 그룹들을 대상으로 FIELD2로 또 한번 묶습니다.

결과적으로 그룹핑된 컬렉션은 grouping 객체(위의 코드 참조)의 getRoot 매서드를 통해 얻습니다. getRoot()의 결과에 대한 클래스 타입은, 배열을 대상으로 그룹핑 했으므로 ArrayCollection 타입입니다.

그룹핑되기 이전에는 단순한 1차원 배열이였던 것이 GroupingCollection2 클래스를 통해 그룹핑되면 3차원 배열이 됩니다. 이 3차원으로 재가공된 배열(실제로는 ArrayCollection 클래스 타입)의 원소들을 하나 하나 참조해야할 때가 있습니다. 설명하기엔 무척….. 염병같고……………. 걍 코드.. 예제 코드 나갑니다. ;-|

var groupingRows:ArrayCollection = grouping.getRoot() as ArrayCollection;
var driverNameAndCarNumber:Object = new Object();
for(i=0; i{
    var D1:Object = groupingRows.getItemAt(i);
    D1["iconIndex"] = 0;
     
    var carName:String = D1.GroupLabel;
    var D2:ArrayCollection = D1.children as ArrayCollection; 

    for(var j:int=0; j    {
        var item:Object = D2.getItemAt(j);
        var driverName:String = item.GroupLabel;
        item["iconIndex"] = 1;
      
        var D3:ArrayCollection = item.children as ArrayCollection;
        for(var k:int=0; k        {
            var lastItem:Object = D3.getItemAt(k);
            lastItem["iconIndex"] = 2;
        }
      
        var sortField:SortField = new SortField();
        sortField.name = "GroupLabel";
        var sort:Sort = new Sort();
        sort.fields = [sortField];
        D3.sort = sort;
        D3.refresh();
    }
}

이 코드는 그룹핑된 내부의 요소드를 또 다시 정렬해줌과 동시에 아이콘 적용을 위해 아이콘 인덱스 번호를 넣어주는 코드입니다. 시간이 지난후에 이 코드를 보고 제 스스로 이해할 수 있다면… 과연 그럴 수 있을까.. 싶습니다.,

[ActionScript] 날짜로 요일 계산하기

아래의 getDay 함수는 액션스크립트로 구성된 요일을 계산해 반환하는 함수입니다. 이 getDay 함수의 파라메터는 날짜로써 년(예:2012), 월(1 ~ 12), 일(1 ~ 31)입니다.

private function getDay(year:int, month:int, day:int):String
{
    const dayStrings:Object = {
        0:"일요일",
        1:"월요일",
        2:"화요일",
        3:"수요일",
        4:"목요일",
        5:"금요일",
        6:"토요일"
    };
    
    if (month == 1 || month == 2) year--;
    month = (month + 9) % 12 + 1;
    var y:int = year % 100;
    var century:int = year / 100;
    var week:int = ((13 * month - 1) / 5 
        + day + y + y / 4 + century / 4 - 2 * century) % 7;
    if (week < 0) week = (week + 7) % 7;

    return dayStrings[week];
}

이처럼 날짜로부터 요일을 계산하는 함수를 직접 작성해 사용할 수 있지만 다음처럼 액션스크립트에서 이미 제공하고 있는 Date 클래스를 사용해 보다 간단히 요일을 계산할 수 있습니다.

 const dayStrings:Object = {
        0:"일요일",
        1:"월요일",
        2:"화요일",
        3:"수요일",
        4:"목요일",
        5:"금요일",
        6:"토요일"
    };
     
    var d:Date = new Date(2012, 10-1, 4);
    Alert.show(dayStrings[d.day]);

여기서 주의해야할 점은 월(Month)은 1부터 시작하지 않고 0부터 시작한다는 것입니다. 그래서 11번 코드에서 지정한 (10-1)은 9월이 아니라 10월을 의미합니다.