공간 상에 분포된 값 기반의 보간 방식 중 하나인 크리깅을 기능 단위로 만든 코드를 정리한 글입니다. 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 } );
이상으로 잘 만들어진 크리깅 라이브러리를 이용하여 웹 상에서 크리깅 분석을 수행하고 그 분석 결과를 시각화하는 코드에 대해 살펴 보았습니다.