Line 그리기 (DDA 알고리즘)

C언어로 구현된 코드를 C#으로 변경한 코드입니다. 출처는 https://www.geeksforgeeks.org/dda-line-generation-algorithm-computer-graphics/ 입니다.

private void DrawLine(
    int X0, int Y0, int X1, int Y1, 
    XrMapLib.GridCells cells, 
    double Value)
{
    int dx = X1 - X0;
    int dy = Y1 - Y0;

    int steps = Math.Abs(dx) > Math.Abs(dy) ? Math.Abs(dx) : Math.Abs(dy);

    float Xinc = dx / (float)steps;
    float Yinc = dy / (float)steps;

    float X = X0;
    float Y = Y0;
    for (int i = 0; i <= steps; i++)
    {
        cells.SetValue((int)Math.Round(Y), (int)Math.Round(X), Value); 
        X += Xinc; 
        Y += Yinc;
    }
}

그리드 분석에서 특정 지점에 대해 값을 지정하는 방식이 아닌 값을 지정하는 대상을 선(Line)으로 정의하기 위한 코드입니다.

크리깅(Kriging) 공간분석

공간 상에 분포된 값 기반의 보간 방식 중 하나인 크리깅을 기능 단위로 만든 코드를 정리한 글입니다. GIS 엔진은 웹 GIS 컴포넌트인 FingerEyes-Xr를 사용했습니다. 크리깅 알고리즘은 오픈소스 라이브러리인 kriging.js를 사용하였으므로 Leaflet이나 OpenLayers에 대한 API에 익숙한 개발자라면 해당 GIS 컴포넌트로도 크리깅 결과에 대한 효과적인 시각화를 구현할 수 있을 것입니다. 웹 기반에서 수행되지만 별도의 서버가 필요하지 않습니다. 지도는 VWorld의 배경지도를 그대로 이용할 것이며 크리깅을 위한 입력 데이터는 실행시 동적으로 생성할 것이기 때문입니다.

결과를 이미지로 먼저 살펴보면 아래와 같습니다.

0~100까지의 값을 가지는 총 35개의 지점이 있고 특정 영역 안에서 크리깅 분석을 수행해 그 결과를 그라디언트 색상으로 표현하는 것인데요. 먼저 특정 영역에 대한 좌표를 지정하고 지도에 표시하는 코드는 다음과 같습니다.

let psd = new Xr.data.PolygonShapeData([[
    new Xr.PointD(14289447.80, 4437166.67),
    new Xr.PointD(14289920.87, 4437347.65),
    new Xr.PointD(14289963.20, 4437210.07),
    new Xr.PointD(14290033.05, 4437198.42),
    new Xr.PointD(14289981.19, 4436636.45),
    new Xr.PointD(14289942.04, 4436488.28),
    new Xr.PointD(14289879.60, 4436349.64),
    new Xr.PointD(14289733.55, 4436420.55),
    new Xr.PointD(14289717.67, 4436438.54)
]]);

let psr = new Xr.data.PolygonGraphicRow(0, psd);

psr.brushSymbol().opacity(0);
psr.penSymbol().color('#ff0000');

gl.rowSet().add(psr);

0~100까지 난수로 부여된 값을 가지는 총 35개의 지점을 지도에 표시하는 코드는 다음과 같구요.

const x = [
    14289539.88, 14289633.01, 14289713.44, 14289812.93, 14289912.41,
    14289598.08, 14289698.63, 14289809.75, 14289883.83, 14289952.62,
    14289747.31, 14289760.01, 14289779.06, 14289793.88, 14289815.04,
    14289836.21, 14289864.78, 14289920.87, 14289698.63, 14289665.82,
    14289758.95, 14289697.57, 14289771.65, 14289732.49, 14289804.46,
    14289828.8, 14289839.38, 14289853.14, 14289885.95, 14289853.14,
    14289878.54, 14289876.42, 14289942.04, 14289929.34, 14289912.41
];

const y = [
    4437041.79, 4437076.72, 4437109.52, 4437148.68, 4437185.72,
    4436892.57, 4436923.26, 4436970.88, 4436999.46, 4436999.46,
    4436877.75, 4436834.36, 4436785.67, 4436736.99, 4436681.96,
    4436626.92, 4436563.42, 4436512.62, 4436824.83, 4436761.33,
    4436740.17, 4436667.14, 4436638.57, 4436577.18, 4436553.90,
    4436927.49, 4436879.87, 4436834.36, 4436790.97, 4436723.23,
    4436687.25, 4436629.04, 4436890.45, 4436744.40, 4436600.47
];

const t = [];

for (let i = 0; i < x.length; i++) {
    t[i] = Math.random() * 100.0;

    let p = new Xr.PointD(x[i], y[i]);
    let tsd = new Xr.data.TextShapeData({ x: x[i], y: y[i], text: t[i] >> 0 });
    let pgr = new Xr.data.TextGraphicRow(i + 1, tsd);

    gl.rowSet().remove(i + 1);
    gl.rowSet().add(pgr);
}

크리깅을 위한 입력값이 준비되어 있으므로 크리깅 분석을 아래의 코드처럼 수행합니다.

const variogram = kriging.train(t, x, y, "spherical", 0, 100);

이제 크리깅 분석 결과를 지도에 표시하기 위해 GridLayer를 사용하게 되는데, 크리깅 분석 결과 모델을 토대로 모르는 지점에 대한 값도 예측할 수 있으며 이 값들을 토대로 적절하게 색상을 배합하면 됩니다. 이러한 코드는 다음과 같습니다.

gridLyr.reset();

const minX = psr.MBR().minX;
const maxX = psr.MBR().maxX;
const minY = psr.MBR().minY;
const maxY = psr.MBR().maxY;

for (let x = minX; x < maxX; x += cellRes) {
    for (let y = minY; y < maxY; y += cellRes) {
        const v = kriging.predict(x, y, variogram);
        gridLyr.value(x, y, v);
    }
}

let clrTbl = new Xr.ColorTable(6);
                    
clrTbl.set(5, 225, 228, 177, 230);
clrTbl.set(4, 190, 208, 122, 230);
clrTbl.set(3, 152, 193, 99, 230);
clrTbl.set(2, 97, 168, 93, 230);
clrTbl.set(1, 46, 146, 85, 230);
clrTbl.set(0, 20, 102, 59, 230);

if (clrTbl.build()) {
    gridLyr.updateByColorTable(clrTbl, psd);
    map.update();
}

GridLayer에 대한 변수는 gridLyr이며 크리깅 보간을 통해 gridLayer 내부의 전체 셀값들이 업데이트됩니다. updateByColorTable 함수를 통해 표현할 색상과 원하는 경계 이외의 셀은 투명하게 잘리게 됩니다. 원하는 경계는 psd라는 변수로 지정하고 있는데 이 psd는 앞서 생성한 특정 영역에 대한 그래픽 요소 객체입니다. 참고로 gridLyr 객체의 생성 코드는 다음과 같습니다.

let cellRes = 1;
let gridLyr = new Xr.layers.GridLayer("grid",
    {
        mbr: psr.MBR(),
        resolution: cellRes
    }
);

이상으로 잘 만들어진 크리깅 라이브러리를 이용하여 웹 상에서 크리깅 분석을 수행하고 그 분석 결과를 시각화하는 코드에 대해 살펴 보았습니다.

VWorld에서 제공하는 지적도를 WFS로 사용하기

VWorld는 다양한 주제도를 전국 단위로 OpenAPI로 제공합니다. WMS와 WFS 등의 방식으로 제공하는데요. VWorld의 지적도를 WFS 방식으로 사용하는 내용을 정리해 봅니다. 먼저 최종 결과는 다음과 같습니다.

VWorld에서 제공하는 지적도에 대한 WFS 방식으로 레이어를 추가하는 코드는 다음과 같습니다.

let parcLyr = new Xr.layers.WFSLayer(
    "wfs_parc",
    {
        proxy: "http://www.gisdeveloper.co.kr:8080/Xr",
        url: "http://api.vworld.kr/req/wfs",
        typename: "lp_pa_cbnd_bubun",
        key: "##09##85-1##3-3##5-A##6-####6##C####",
        domain: "http://localhost:56612"
    }
);
lm.add(parcLyr);

WFS 방식의 장점은 공간 데이터를 좌표값으로 받아와 클라이언트에서 직접 그릴 수 있다는 점입니다. 즉, 다양한 심벌을 자유롭게 지정할 수 있습니다. 그에 대한 코드는 아래와 같습니다.

let parcTheme = parcLyr.theme();
let parcPen = parcTheme.penSymbol();
let parcBrush = parcTheme.brushSymbol();

parcPen.color('#ffff00').width(1);
parcBrush.opacity(0);

WFS 방식의 또 다른 장점은 속성 데이터를 함께 제공한다는 것인데요. 이 속성 데이터를 이용하여 원하는 텍스트 심벌을 사용하여 레벨을 표현할 수 있습니다. 해당하는 코드는 이래와 같습니다.

let label = parcLyr.label();
label.enable(true);
label.formatter().fieldName("jibun");

let labelTheme = label.theme();
labelTheme.symbol().strokeColor("#000000").strokeWidth(2).size(12).fontFamily('맑은 고딕').color("#ffffff");

VWorld에서 제공하는 WFS 방식을 통한 지도 레이어는 매우 활용도가 높습니다. 즉, 전국범위의 공간 데이터를 좌표와 속성 데이터를 그대로 받아 원하는 형태로 자유롭고 다양하게 사용할 수 있기 때문입니다. 하지만 VWorld에서 제공하는 WFS 방식은 WMS 방식 보다 제공되는 지도의 종류 수가 적습니다. 예를 들어 건물 레이어의 경우 WMS로는 제공하지만 WFS로는 제공하지 않습니다. VWorld의 OpenAPI를 통해 지적도처럼 건물도 WFS 방식으로 제공되어 활용할 수 있었으면 좋겠습니다.

모바일 NexGen 관리자

모바일 NexGen 관리자는 단말기를 통해 편집한 공간 데이터와 수집한 현장 데이터를 사용자 PC에 내려 받을 수 있는 프로그램입니다. 아래는 모바일 넥스젠과 관리자 프로그램 간의 업무 흐름에 대한 도식도입니다.

단말기를 사용자 PC의 USB에 연결하여 바로 데이터를 내려받을 수 있으며, 편집된 공간 데이터는 SHP 파일 형식으로 저장할 수 있으며, 수집한 위치 기반 현장 데이터에 대해서는 그 목적에 맞게 SHP, CSV, 이미지, 동영상 파일들로 저장됩니다.

모바일 넥스젠 앱이 설치된 단말기에서 공간 데이터를 편집하는 기능에 대한 소개는 다음 URL을 통해 살펴볼 수 있습니다.

모바일 넥스젠의 공간 데이터 편집

또한 현장에서 다양한 데이터를 수집하는 기능에 대한 소개는 다음 URL을 통해 살펴볼 수 있습니다.

모바일 넥스젠의 현장 데이터 수집