https://generalcoder.tistory.com/3
지난 포스팅에서 카카오 지도와 주소 api를 연동하는 방법을 알아보고 테스트까지 해보았다. 이번시간에는 지도 api에서 얻은 경도와 위도를 가지고 두 점 사이의 거리를 측정하는 방법을 알아보려 한다.
두 점 사이의 거리를 구하기 위해서는 두 가지를 알아야한다.
첫째, 각 점의 위도와 경도를 얻어온다.
둘째, 위도와 경도를 가지고 두 점사이의 거리를 측정할 수 있는 공식을 찾는다.
위도와 경도 구하기
카카오맵은 자체적으로 위도와 경도를 얻어올 수 있는 함수를 제공한다. 카카오 개발자센터 api를 뒤져보다 보니 다음과 같은 함수를 발견했다.
문제는 이 함수를 어느 위치에 넣어야 하는지 였는데 친절하게도 api예제에 주석이 달려있어서 대략적인 위치를 파악하고 테스트 해보았다. 예제 코드를 살펴보니 맵의 중심좌표를 설정하는 부분이 있었는데 내가 원하는 것도 검색위치의 중심좌표였기 때문에 'lat' 과 'lng' 라는 변수를 먼저 선언하고 적절한 위치에 위도, 경도를 받아오는 함수를 사용해 코드를 작성했다. 값을 받아온 후 console에 출력해서 값이 나오는지 확인해보았다.
let lat;//위도 받을 변수
let lng;//경도 받을 변수
async function execPostcode(){
new daum.Postcode({
oncomplete: function(data) {
var addr = data.address; // 최종 주소 변수
// 주소 정보를 해당 필드에 넣는다.
document.getElementById("get-location").value = addr;
// 주소로 상세 정보를 검색
geocoder.addressSearch(data.address, function(results, status) {
// 정상적으로 검색이 완료됐으면
if (status === daum.maps.services.Status.OK) {
var result = results[0]; //첫번째 결과의 값을 활용
// 해당 주소에 대한 좌표를 받아서
var coords = new daum.maps.LatLng(result.y, result.x);
// 지도를 보여준다.
mapContainer.style.display = "block";
map.relayout();
// 지도 중심을 변경한다.
map.setCenter(coords);
const center = map.getCenter();
lat = center.getLat()//=======> 중심좌표의 위도를 받아온다.
lng = center.getLng()//=======> 중심좌표의 경도를 받아온다.
console.log(lat);
console.log(lng);
// 마커를 결과값으로 받은 위치로 옮긴다.
marker.setPosition(coords)
}
});
}
}).open();
}
판교라는 검색어로 주소를 받아오니 맵이 출력되었고 위도와 경도를 차례로 콘솔에 출력해주는 것을 확인했다.
위도와 경도를 지도 api에서 받아오는 첫번째 과제는 해결했다.
위도와 경도로 두 점 사이의 거리 구하기
두번째 과제는 위도와 경도를 갖는 두 점 사이의 거리를 구하는 것이다. 단순 좌표값처럼 생각해서 쉽게 구할 수 있을 줄 알았는데 내가 간과한 문제가 있었다. 일반적인 좌표는 평면상에 놓여진다. 때문에 중학생 수준의 수학능력만 있으면 쉽게 두 점 사이의 거리를 구할 수 있다. 하지만 위도와 경도는 지구라는 구 형태의 구조물 위에 놓여진 위치를 말하기 때문에 두 점 사이의 거리를 구하는 방법은 평면좌표에서 거리구하는 방법과는 달라야한다.
하지만 친절하게도 이미 먼저 공식을 구해놓고 코드로 제시해 놓은 자료들이 있었다. javascript로 표현된 거리 공식은 아래와 같다.
function getDistanceFromLatLonInKm(lat1,lng1,lat2,lng2) {//lat1:위도1, lng1:경도1, lat2:위도2, lat2:경도2
function deg2rad(deg) {
return deg * (Math.PI/180)
}
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lng2-lng1);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}
위 함수는 두 점의 위도와 경도를 매개변수로 넣으면 km단위의 거리를 계산해준다. 지구의 반지름인 6371km를 R이라는 변수로 두고 원의 중심으로부터의 각도를 통해 거리를 구하는 것으로 보인다.
두점 사이의 거리를 검색해보기 위해 직선거리에 있는 두 지점을 선택해서 위도경도를 받아와 보았다. 네이버 지도는 직선거리가 아니라 교통경로를 안내해주기 때문에 최대한 직선거리에 있는 두 지점을 선택했다.
첫번째 지점: 강남역
두번째 지점: 양재역
네이버지도를 통해 찾아본 강남역과 양재역 사이의 거리는 1.3km이다. 지도상으로 직선거리에 있기 때문에 테스트해보기 아주 좋은 상태로 배치되어있었다.
이제 함수로 측정한 두 지점 사이의 거리가 네이버지도의 거리와 일치하는지 테스트를 해보자. 위에 선언한 함수에 파라미터로 넣어줄 위도와 경도를 변수로 선언하고 함수를 호출해준다.
//강남역
const lat1 = 37.49813943152925
const lng1 = 127.02827170358093
//양재역
const lat2 = 37.48390185679575
const lng2 = 127.03450754512691
console.log(getDistanceFromLatLonInKm(lat1,lng1,lat2,lng2));
콘솔에 출력된 결과값은 1.67km로 네이버 지도와 약 300m정도의 오차를 보였다. 이런 차이가 나게 된 이유중 하나는 주소에서 찍힌 좌표가 정확하게 역 좌표와 일치하지 않은 것 때문으로 보인다. 여러 번 테스트해본 결과 km단위로는 대체로 들어맞았다.
m단위의 정밀함을 요구하는 작업에는 사용하기 힘들다는 생각이 들었지만 당근마켓의 동네반경의 게시물을 보여주는 기능처럼 고도의 정밀함을 요구하지 않는 작업에는 쓸만해 보인다.
다음시간에는 이어서 위도와 경도를 가지고 주변 반경에 있는 게시물을 선택적으로 보여주는 코드를 작성해보려 한다.
'만들자' 카테고리의 다른 글
[Javascript]위도 경도로 두 점 사이의 거리 구하기 2 - 지정범위내의 게시물 보여주기 (0) | 2023.11.22 |
---|---|
[Javascript]카카오 지도, 주소api 사용해보기 (0) | 2023.11.16 |
[Firebase] 파이어베이스로 마켓어플 만들어본 후기(Firestore, Storage연동, 인증) (2) | 2023.11.12 |