Map(WEB)

VWorld의 WMS, WFS 기능 구현

별동산 2025. 3. 27. 10:28
반응형

아래 브이월드 서비스 개발 교육 자료를 참고해서

브이월드 서비스 개발 교육(3차시).pdf
2.79MB

 
 
VWorld의 WFS 오픈 API를 이용해 클릭한 지점의 주소, 지목, 면적 등을 추출하는 프로그램을 만들어봤습니다.

교재대로 만드니 불편한 점이 있어서 몇 군데는 수정했습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>VWorld WebGl 3D API 3.0 Sample</title>
    <script type="text/javascript" src="https://map.vworld.kr/js/webglMapInit.js.do?version=3.0&apiKey=개인인증키"></script>
    <style type="text/css">
		#wrap .buttons { position:absolute;top:5px;left:62%;z-index:1000;padding:5px; }
		#wrap .buttons .control-btn {padding:0;margin:0; }
	
		.search { position:absolute;z-index:1000;top:20px;left:10px; }
		.search #address { width:150px;height:20px;line-height:20px;border:solid 1px #555;padding:5px;font-size:15px;box-sizing:content-box; }
		.search #submit { height:30px;line-height:30px;padding:0 10px;font-size:15px;border:solid 1px #555;border-radius:3px;cursor:pointer;box-sizing:content-box; }	
		
        table{
            border-collapse: separate;
            border-spacing: 0;
            text-align: left;
            line-height: 1.5;
            border-top: 1px solid #ccc;
            border-left: 1px solid #ccc;
            margin: 20px 10px;
        }
        table th{
            width: 150px;
            padding: 10px;
            font-weight: bold;
            vertical-align: top;
            border-right: 1px solid #ccc;
            border-bottom: 1px solid #ccc;
            border-top: 1px solid #fff;
            border-left: 1px solid #fff;
            background: #eee;
        }
        table td{
            padding: 10px;
            vertical-align: top;
            border-right: 1px solid #ccc;
            border-bottom: 1px solid #ccc;
        }
    </style>
</head>
<body>

    <div style="display: flex;">
        <div style="float: left; width:100%;">
            <div id="vmap" style="width: 100%;height: 80vh";">

			</div>
        </div>
    </div>

<div id="wrap">
	<div class="search" style="">
		<input id="address" name="address" type="text" placeholder="정자동 178-1" />
		<input id='submit' type="button" value="검색" />
	</div> 
</div>
	<!--
    <div style="float: left; width: 40%;">
        <header>
            <table id="wlayerList">
                <tr>
                    <th>건물 레이어 On/Off</th>
                    <td><input type="checkbox" onclick="checkLayer(this, 'facility_build')" checked="checked"></td> 
                </tr>
                <tr>
                    <th>WMS LX맵(편집지적도) 레이어</th>
                    <td><input type="button" value="WMS/WFS 조회" onclick="wmsSample();"/></td>
                </tr>
            </table>
        </header>
    </div> -->
    <div style="height: 700px; padding: 20px;">
        <form id="wfsForm">
            <input type = "hidden" name="key" value="개인인증키">
			<input type = "hidden" name="domain" value="도메인">
            <input type = "hidden" name="SERVICE" value="WFS">
            <input type = "hidden" name="version" value="1.1.0">
            <input type = "hidden" name="request" value="GetFeature">
            <input type = "hidden" name="TYPENAME" value="lt_c_landinfobasemap">
            <input type = "hidden" name="OUTPUT" value="text/javascript">
            <input type = "hidden" name="SRSNAME" value="EPSG:4326">
            <input type = "hidden" name="BBOX" value="">
        </form>
        <div>
            <!--<span><b>* 선택한 LX맵(편집지적도 WFS) *</b></span>-->
            <div id="resultDiv"></div>
        </div>
    </div>
	

    <script>
		let xhr=new XMLHttpRequest();
        let map;
		let chk;
        let options = {
            mapId: "vmap",
            initPosition: new vw.CameraPosition(
				// 세번째 값이 z(높이)를 조절하여 배율 설정 대체
                new vw.CoordZ(126.92775802528264, 37.52501881993892, 300),
                new vw.Direction(0, -90, 0)
            ),
        logo: true,
        navigation: true
        };

        map = new vw.Map();
        map.setOption(options);
        map.start();
		
		window.onload = function() {
			wmsSample(); // 페이지 로드 시 자동 실행
		};

        let checkLayer = function(c, name) {
            if ($(c).is(":checked")==false) {
                map.getLayerElement(name).hide();
            } else {
                map.getLayerElement(name).show();
            }
        }

        // LX맵(연속지적도) WMS
        function wmsSample() {
            let wmsLayer = new vw.Layers();
            wmsSource = new vw.source.TileWMS();
            wmsSource.setUrl("https://api.vworld.kr/req/wms?Key=8A75386F-EF29-320D-992A-CB341A0FE2A5&");
            wmsSource.setParams("tilesize=256");
            wmsSource.setLayers("lt_c_landinfobasemap");
            wmsSource.setStyles("lt_c_landinfobasemap");
            wmsSource.setFormat("image/png");
            let wmsTile = new vw.layer.Tile(wmsSource);
            wmsLayer.add(wmsTile);

			chk = 1;
			//console.log('5:' + chk);
			
			map.onClick.addEventListener(wfsEvent);
            
        }

		
		
        let getBuffer = function(x, y) {
            position= map.getCurrentPosition().position;
            let z = position.z;
            let m = 1/(111000/z*1.48*50);
            let h = 1/(111000/z*1.85*50);
			//console.log('3:' + z + ',' + m + ',' + h);
            return [m,h];
        }

        //LX 맵 편집지적도 ) WFS
        let wfsEvent = function(windowPosition , ecefPosition , cartographic , featureInfo , event ) {
            let mh = getBuffer(cartographic.longitudeDD, cartographic.latitudeDD);
            let min = [cartographic.longitudeDD- mh[0], cartographic.latitudeDD- mh[1]];
            let max = [cartographic.longitudeDD+ mh[0], cartographic.latitudeDD+ mh[1]];
            let box = min[0] + "," +  min[1]  + "," + max[0]  + "," + max[1];
            $('#wfsForm > [name=BBOX]').val(box);
			//console.log('0:' + min[0]+','+max[1]);
			
			$.ajax({
            type: "get",
            url: "https://api.vworld.kr/req/wfs",
            data: $('#wfsForm').serialize(),
            dataType: 'jsonp',
            async: false,
            jsonpCallback: "parseResponse",
            success: function(data) {
                if(data.totalFeatures == 0) {
                    alert("검색 결과가 없습니다.");
                } else {
					//console.log('4:' + chk);
                    if (chk != 0) {
                        var data = data.features[0].properties;
						//console.log('1:' + data[0]);
                        let resultHtml = ""; 
                        //<b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;❤️ 선택 필지 ❤️</b>

                        resultHtml+="<li>주   소 : " +data.sido_nm + " " + data.sgg_nm + " " + data.emd_nm ;
						if (data.ri_nm){
							resultHtml+=" " + data.ri_nm;
						}                        
						resultHtml+=" " + data.jibun.slice(0, data.jibun.length - 1) + "</li>";
					
                        resultHtml+="<li>지  목 : " + data.jimok + "(" + data.jibun.slice(data.jibun.length - 1) + ")</li>";resultHtml+="<li>면  적 : " + data.parea.toLocaleString() + "㎡</li>";
                        resultHtml+="<li>소유구분 : " + data.owner_nm + "</li>";
						resultHtml+="<li>필지번호(pnu) : " + data.pnu + "</li>";
						
						$('#resultDiv').html(resultHtml);
                    }
                }
            },
			error: function(xhr, stat, err) {}
        })
        }


    </script>
</body>
</html>

 
WMS는 Web Map Service, WFS는 Web Feature Service의 약자입니다.
 
만들고 나서 여의도가 초기 화면이라  여러 군데를 돌아다니면서 면적을 알아보는데 13-25(옥상이 흰색인 건물)의 면적이 18.43㎡로 터무니없이 작습니다(정확한 면적은 12,248㎡).

vworld 3D 맵
브이월드 오픈 API로 만든 3D 지도

 
그래서 VWorld에 물어보니 오류가 있다고 합니다.

 
답답한 순간이 많이 있지만, 더욱더 발전해 나가겠지요.

반응형