측정하고자 하는 지점을 클릭했을 경우 지점을 포함한 면적이 폴리곤으로 표시되고, 더블 클릭 했을 경우 면적 측정을 종료합니다.
거리측정 종료 후 다시 다른 지점을 클릭하면 새로운 셋의 측정 결과가 표시됩니다.
위 기능을 구현하는 전체 코드입니다.
functioninit() {Module.Start(window.innerWidth,window.innerHeight);// 카메라 위치 설정Module.getViewCamera().setLocation(newModule.JSVector3D(126.92836647767662,37.52439503321471,1000.0));// 분석 출력 POI 레이어 생성let layerList =newModule.JSLayerList(true);let layer =layerList.createLayer("MEASURE_POI",Module.ELT_3DPOINT);layer.setMaxDistance(20000.0);layer.setSelectable(false);// 면적측정 라인 랜더 옵션 설정Module.getOption().SetAreaMeasurePolygonDepthBuffer(false); // WEBGL GL_DEPTH_TEST 설정// 콜백 함수 설정 지속적으로 사용Module.getOption().callBackAddPoint(addPoint); // 마우스 입력시 발생하는 콜백 성공 시 success 반환 실패 시 실패 오류 반환Module.getOption().callBackCompletePoint(endPoint); // 측정 종료(더블클릭) 시 발생하는 콜백 성공 시 success 반환 실패 시 실패 오류 반환}/* 마우스 상태 변경 */functionsetMouseState(_type){if (_type =="move") {// 지도 이동 마우스 모드 변경Module.XDSetMouseState(Module.MML_MOVE_GRAB); }elseif (_type =="measure") {// 면적 측정 마우스 모드 변경Module.XDSetMouseState(Module.MML_ANALYS_AREA_PLANE); }}let m_mercount =0; // 측정 오브젝트 갯수/* callBackAddPoint에 지정된 함수 [마우스 왼쪽 클릭 시 이벤트 발생]*/functionaddPoint(e) {// e 구성요소// dLon, dLat, dAlt : 면적 중심 좌표(경위 고도)// dArea : 면적 크기 createPOI(newModule.JSVector3D(e.dLon,e.dLat,e.dAlt),"rgba(255, 204, 198, 0.8)",e.dArea,true);}/* callBackCompletePoint에 지정된 함수 [마우스 더블 클릭 시 이벤트 발생]*/functionendPoint(e) {viewListOBjKey(e); m_mercount++;}//=============================================== POI 생성 과정/* 정보 표시 POI */functioncreatePOI(_position, _color, _value, _balloonType) {// 매개 변수// _position : POI 생성 위치// _color : drawIcon 구성 색상// _value : drawIcon 표시 되는 텍스트// _balloonType : drawIcon 표시 되는 모서리 옵션(true : 각진 모서리, false : 둥근 모서리)// POI 아이콘 이미지를 그릴 Canvas 생성var drawCanvas =document.createElement('canvas');// 캔버스 사이즈(이미지 사이즈)drawCanvas.width =100;drawCanvas.height =100;// 아이콘 이미지 데이터 반환let imageData =drawIcon(drawCanvas, _color, _value, _balloonType);let Symbol =Module.getSymbol();let layerList =newModule.JSLayerList(true);let layer =layerList.nameAtLayer("MEASURE_POI");// POI가 존재 하면 삭제 후 생성let key = m_mercount +"_POI";layer.removeAtKey(key);// POI 생성 과정 poi =Module.createPoint(m_mercount +"_POI");poi.setPosition(_position); // 위치 설정poi.setImage(imageData,drawCanvas.width,drawCanvas.height); // 아이콘 설정layer.addObject(poi,0); // POI 레이어 등록}/* 아이콘 이미지 데이터 반환 */functiondrawIcon(_canvas, _color, _value, _balloonType) {// 컨텍스트 반환 및 배경 초기화var ctx =_canvas.getContext('2d'), width =_canvas.width, height =_canvas.height ;ctx.clearRect(0,0, width, height);// 배경 Draw Path 설정 후 텍스트 그리기if (_balloonType) {drawBalloon(ctx, height *0.5, width, height,5, height *0.25, _color);setText(ctx, width *0.5, height *0.2, _value); } else {drawRoundRect(ctx,0, height *0.3, width, height *0.25,5, _color);setText(ctx, width *0.5, height *0.5, _value); }returnctx.getImageData(0,0,_canvas.width,_canvas.height).data;}/* 말풍선 배경 그리기 */functiondrawBalloon(ctx, marginBottom, width, height, barWidth, barHeight, color) {var wCenter = width *0.5, hCenter = height *0.5;// 말풍선 형태의 Draw Path 설정ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(0, height - barHeight - marginBottom);ctx.lineTo(wCenter - barWidth, height - barHeight - marginBottom);ctx.lineTo(wCenter, height - marginBottom);ctx.lineTo(wCenter + barWidth, height - barHeight - marginBottom);ctx.lineTo(width, height - barHeight - marginBottom);ctx.lineTo(width,0);ctx.closePath();// 말풍선 그리기ctx.fillStyle = color;ctx.fill();}/* 둥근 사각형 배경 그리기 */functiondrawRoundRect(ctx, x, y, width, height, radius, color) {if (width <2* radius) radius = width *0.5;if (height <2* radius) radius = height *0.5;ctx.beginPath();ctx.moveTo(x + radius, y);ctx.arcTo(x + width, y, x + width, y + height, radius);ctx.arcTo(x + width, y + height, x, y + height, radius);ctx.arcTo(x, y + height, x, y, radius);ctx.arcTo(x, y, x + width, y, radius);ctx.closePath();// 사각형 그리기ctx.fillStyle = color;ctx.fill();return ctx;}/* 텍스트 그리기 */functionsetText(_ctx, _posX, _posY, _value) {var strText ="";// 텍스트 문자열 설정var strText =setTextComma(_value.toFixed(2)) +'㎡';// 텍스트 스타일 설정_ctx.font ="bold 16px sans-serif";_ctx.textAlign ="center";_ctx.fillStyle ="rgb(0, 0, 0)";// 텍스트 그리기_ctx.fillText(strText, _posX, _posY);}/* 단위 표현 */functionsetTextComma(str) { str =String(str);returnstr.replace(/(\d)(?=(?:\d{3})+(?!\d))/g,'$1,');}//=============================================== 측정 목록 및 삭제 관련functionviewListOBjKey(_key) {let cell =document.getElementById("objList");let li =document.createElement('li');// 측정 객체 리스트 추가( ui )li.id = _keyli.innerHTML ="<a href='#' onclick=\"deleteObject('"+ _key +"');\">"+ _key +"</a>"cell.appendChild(li);}functiondeleteObject(_key) {Module.XDClearAreaObject(_key);let li =document.getElementById(_key);li.remove(); // 선택 <a> 컨트롤러 삭제// 오브젝트 삭제let layerList =newModule.JSLayerList(true);let layer =layerList.nameAtLayer("MEASURE_POI");let list =layer.getObjectKeyList();let key =_key.replace(/[^0-9]/g,'') +"_POI"; // [생성순서]_POI_ 형태로 객체 생성let strlist =list.split(",");strlist.forEach((item, index) => {if (item.indexOf(key) !==-1) {layer.removeAtKey(item) // 키값으로 레이어에 들어간 오브젝트 삭제 } });// 화면 재 갱신Module.XDRenderData();}/* 분석 내용 초기화 */functionclearAnalysis() {// 실행 중인 분석 내용 초기화Module.XDClearAreaMeasurement(); m_mercount =0;// 레이어 삭제let layerList =newModule.JSLayerList(true);let layer =layerList.nameAtLayer("MEASURE_POI");layer.removeAll();// <ui> 모든 노드 삭제let cell =document.getElementById("objList");while ( cell.hasChildNodes() ) { cell.removeChild( cell.firstChild ); }}
이어서 코드의 세부 단계에 대해 알아봅니다.
기능 구현
Global 변수
기능을 구현하기 전 전역으로 사용하는 변수를 선언한 부분입니다.
varGLOBAL= { m_mercount :0// 측정 오브젝트 갯수};
측정 종료 후 데이터를 관리할 수 있도록 측정 오브젝트 수를 관리합니다.
step 1. 레이어 생성
면적측정 Icon 및 면적 값을 가시화할 레이어를 생성합니다.
면적 측정 값을 POI로 출력해야 하므로 레이어 타입은 ELT_3DPOINT으로 설정합니다.
let layerList =newModule.JSLayerList(true);let layer =layerList.createLayer("MEASURE_POI",Module.ELT_3DPOINT);layer.setMaxDistance(20000.0);layer.setSelectable(false);
Module.getOption().callBackAddPoint(addPoint); // 마우스 입력시 발생하는 콜백 성공 시 success 반환 실패 시 실패 오류 반환Module.getOption().callBackCompletePoint(endPoint); // 측정 종료(더블클릭) 시 발생하는 콜백 성공 시 success 반환 실패 시 실패 오류 반환
functionaddPoint(e) {// e 구성요소// dLon, dLat, dAlt : 면적 중심 좌표(경위 고도)// dArea : 면적 크기 createPOI(newModule.JSVector3D(e.dLon,e.dLat,e.dAlt),"rgba(255, 204, 198, 0.8)",e.dArea);}
functioncreatePOI(_position, _color, _value) {// 매개 변수// _position : POI 생성 위치// _color : drawIcon 구성 색상// _value : drawIcon 표시 되는 텍스트// POI 아이콘 이미지를 그릴 Canvas 생성var drawCanvas =document.createElement('canvas');// 캔버스 사이즈(이미지 사이즈)drawCanvas.width =100;drawCanvas.height =100;// 아이콘 이미지 데이터 반환let imageData =drawIcon(drawCanvas, _color, _value);let Symbol =Module.getSymbol();let layerList =newModule.JSLayerList(true);let layer =layerList.nameAtLayer("MEASURE_POI");// POI가 존재 하면 삭제 후 생성let key =GLOBAL.m_mercount +"_POI";layer.removeAtKey(key);// POI 생성 과정 poi =Module.createPoint(GLOBAL.m_mercount +"_POI");poi.setPosition(_position); // 위치 설정poi.setImage(imageData,drawCanvas.width,drawCanvas.height); // 아이콘 설정layer.addObject(poi,0); // POI 레이어 등록}
JSSymbol을 사용하지 않고 간단히 이미지 데이터만을 등록하여 사용하는 방법도 있습니다.
functionclearAnalysis() {// 실행 중인 분석 내용 초기화Module.XDClearAreaMeasurement();GLOBAL.m_mercount =0;// 레이어 삭제let layerList =newModule.JSLayerList(true);let layer =layerList.nameAtLayer("MEASURE_POI");layer.removeAll();}