Tmap API를 활용한 폴리곤 내 마커 포함 여부 확인

Enzo·2023년 1월 15일
4
post-thumbnail

서론

모빌리티 도메인을 개발하는 회사를 다니며 구현했던 로직들 중 기억에 남는 것들을 정리하려한다.
내가 했던 삽질들을 다른 사람들은 하지 않기를 바라는 마음으로 공유한다.

Tmap API를 확인해보면 '폴리곤' 이라는 다각형을 그리는 API를 제공한다.
https://tmapapi.sktelecom.com/main.html#webv2/sample/webSample84

하지만 해당 API를 사용해서는 구역 내 마커의 포함 여부를 확인할 수 없다.
왜냐하면 폴리곤을 그릴 때 생성되는 객체와 폴리곤 내 좌표를 확인할 수 있는 객체가 다르기 때문이다.

도대체 왜 이렇게 만드는건데

API는 아래의 링크를 참조하자

폴리곤을 그리는 API : Tmapv2.extension.Drawing
https://tmapapi.sktelecom.com/main.html#webv2/docs/WebDocs.extension_Drawing
폴리곤 내 좌표 포함여부 API : Tmapv2.Polygon
https://tmapapi.sktelecom.com/main.html#webv2/docs/WebDocs.Polygon


구현방법

현재 만들고자 하는 기능은 우회하여 구현해야한다. 방법은 2가지가 있다.

  1. 폴리곤을 그리는 API를 통해 폴리곤을 그리다가 우클릭을 통해 폴리곤을 다 그린 순간 꼭짓점의 좌표를 통해 새로운 폴리곤 그리기
  2. 면적을 구할 수 있는 API가 존재한다. 해당 API도 폴리곤을 그리는 API와 비슷하게 동작한다. 구할 면적을 그리다가 우클릭을 통해 면적을 다 그린 순간 꼭짓점의 좌표를 통해 새로운 폴리곤 그리기

Tmap은 레스터 형식의 맵(Tmapv2)과 벡터 형식의 맵(Tmapv3)을 제공한다. 하지만 이번 로직의 구현을 위해서는 레스터 형식의 맵을 사용해야 한다.
벡터 형식의 경우 폴리곤을 그리는 API를 제공하지 않기 때문이다.


이론은 이쯤하고 직접 구현해보자!

  1. 객체를 선택하여 map을 생성하고 구역과 폴리곤을 그리는 버튼을 구현

index.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>simpleMap</title>
<script src="https://apis.openapi.sk.com/tmap/jsv2?version=1&appKey=생성한 AppKey"></script>
<script src="index.js"></script>
<link rel="stylesheet" href="index.css">

</head>
<body onload="initTmap()">
	<div id="map_div">
		<div class="map_act_btn_wrap clear_box" style="position: absolute;z-index: 1;padding-left: 10px;">
            <button onClick="drawMeasure()">면적 그리기</button>
            <button onClick="drawPolygon()">폴리곤 그리기</button>
        </div>
	</div>
</body>
</html>

index.js

let map = null;
let drawingObject = null;
let measureObject = null;
let markerArray = [];

function initTmap(){
    // map 생성
    map = new Tmapv2.Map("map_div", {
        center : new Tmapv2.LatLng(37.57220450, 126.99532028), // 지도 초기 좌표
        width : "100%", // 지도의 넓이
        height : "100vh", // 지도의 높이
        zoom : 16	// 지도의 줌레벨
    });

    // 더미 마커 생성
    for(let i=0; i<10; i++){
        for(let j=0; j<10; j++){
            let lat = 37.56520450 + (0.002 * i);
            let lon = 126.98602028 + (0.002 * j);

            let marker = new Tmapv2.Marker({
                position: new Tmapv2.LatLng(lat, lon),
                iconHTML: '<div id="icon" style="background:black"></div>',
                iconSize: new Tmapv2.Size(10, 10),
                zIndex: 200,
                map: map
            });

            // 마커 정보 저장
            markerArray.push(marker);
        }
    }

    // map 우클릭
    map.addListener('contextmenu', ()=>{
        if(true){
            console.log('--- measureObject ---');
            console.log(measureObject);
            console.log(measureObject._data.pointArray);
            console.log('--- polygonObject ---');
            console.log(drawingObject);
            console.log(drawingObject._data.shapeArray[0]);

            setTimeout(()=>{
                console.log(drawingObject._data.shapeArray[0]._shape_data.path);
            }, 1);
        }
    });
};

// 면적 그리기
function drawMeasure(){
    measureObject = new Tmapv2.extension.MeasureArea({
            map: map
    });
};

// 폴리곤 그리기
function drawPolygon(){
    drawingObject = new Tmapv2.extension.Drawing(
        {
            map:map, // 지도 객체
            strokeWeight: 4, // 테두리 두께
            strokeColor:"blue", // 테두리 색상
            strokeOpacity:1, // 테두리 투명도
            fillColor:"red", // 도형 내부 색상
            fillOpacity:0.2 // 도형 내부 투명도
        }
    );
    drawingObject.drawPolygon();
};

drawPolygon, drawMeasure API는 우클릭 시 현재 그리는 면적 또는 폴리곤을 종료하는 동작을 수행한다. map 객체에 우클릭 시 해당 객체들의 정보를 콘솔로 찍어보도록 하자

위와 같이 해당 객체의 정보를 볼 수 있다. 각 객체 아래에 존재하는 정보는 LatLng 객체를 저장하는 곳을 찾아놓은 것이다.
polygonObject의 경우 바로 객체를 찍어볼 경우 값을 받아오지 못했다.
1ms를 기다렸다가 콘솔을 찍어보는 로직을 추가한 이유이다. 폴리곤을 그리는 API를 사용하여 꼭짓점의 정보를 가져오려면 위와 같이 동작시켜야 하는 것 같다.

polygon API에서는 꼭짓점의 정보를 Tmap에서 제공하는 LatLng 객체로 전달해야만 한다.
현재 콘솔로 나오는 객체는 LatLng 객체이므로 따로 객체를 생성할 필요는 없다.

LatLng 객체에 대한 API 정보는 아래 링크를 참조하자
https://tmapapi.sktelecom.com/main.html#webv2/docs/WebDocs.LatLng

이제 위와 같이 받아온 정보를 통해 새롭게 polygon을 그린 뒤 contains 메서드를 사용하면 마커가 해당 구역에 포함되는지 확인할 수 있다.


index.js 내 우클릭 이벤트

// map 우클릭
map.addListener('contextmenu', ()=>{
  // 랜덤 색상
  let randomColor = "#" + Math.round(Math.random() * 0xffffff).toString(16);

  // 폴리곤 생성
  let polygon = new Tmapv2.Polygon({	
    paths: [measureObject._data.pointArray], // 면적 객체의 꼭짓점 배열
    fillColor: randomColor,	// 랜덤 내부 색상
    map: map	// 지도 객체
  });

  // 폴리곤 내 마커 판별
  for(let i=0; i<markerArray.length; i++){
    if(polygon.contains(markerArray[i].getPosition())){
      markerArray[i].setIconHTML('<div id="icon" style="background:'+randomColor+'"></div>');
    }
  }
});

최종 결과

짜잔!

구역 객체의 정보를 통해 랜덤한 배경색의 폴리곤을 생성한 뒤 마커가 포함되면 마커의 배경색을 폴리곤의 동일한 색상으로 변경하도록 동작한다.

0개의 댓글