카페에 어떤 분의 질문에 답변 글로 올린 글인데 블로그로 옮겨왔습니다.
경도, 위도 (GPS 정보 따위)를 알고 있을 때, 그것을 지도 이미지 상의 어떤 위치에
매핑을 하기 위해서는
일단
1) 사용하시려고하는 소스, 즉 맵타일 이미지가 어떤 기준을 가지고 만들어졌느냐?
2) 그리고 어떤 도법에 의해서 그려진 지도인가?
를 아셔야 합니다.
버추얼 어스(이하 VE)를 예로 들어 설명해 보겠습니다.
- VE 맵타일 하나는 256 pixel x 256 pixel로 이루어져 있습니다.
- VE 맵 중심점은 위도 0도, 경도 0도입니다.
현재 화면의 지도상태를 ZoomStep 2단계라고 가정하면, 지도이미지는 4x4의 타일로 구성되어 있습니다.
(VE의 ZoomStep 1단계는 세계지도를 2x2의 타일로 표현한 것입니다. VE는 19단계의 ZoomStep을 지원합니다.)
이때 전체 맵 크기는 가로, 세로 256 pixel * 4 = 1024 pixel 입니다.
간단히 생각해 보면.
가로 1024pixel을 경도 360도( -180(=서경180) ~ 180(=동경180)로 나눠쓰고 있고,
세로 1024pixel을 위도 180도(90 (북반구) ~ -90 (남반구))로 나눠쓰고 있다고 생각할 수 있습니다.
이 지도 위에 인천 공항의 위치를 점으로 찍으려면 어떻게 하면 될까요?
먼저, 인천 공항의 경도와 위도를 알아야 합니다.
경도는 126도 36분 30초 입니다.
(편의를 위해 '도' 단위로 나타내겠습니다. 126 + 36 * 1/60 + 30 * 1/3600 = 126.6083도)
위도는 37도 28분 20초 입니다.
(편의를 위해 '도' 단위로 나타내겠습니다. 37 + 28 * 1/60 + 20 * 1/3600 = 37.4722도)
또, 지도의 중심이 경도 0, 위도 0 이고,
지도의 왼쪽이 경도 -180, 오른쪽이 180
지도의 위쪽이 위도 90, 아래쪽이 -90이라는 조건에 의해,
변환식은 아래와 같을 것입니다.
위 공식에 따라서 계산을 해보면,
X = 872.130275555556 pixel = 872 (소수점 이하 반올림)
Y = 298.824817777778 pixel = 299 (소수점 이하 반올림)
하지만 간과하면 안 되는 점이 하나 있습니다.
아까도 말씀드렸듯이 어떤 도법으로 그려진 것인지가 중요합니다.
- VE는 메르카토르 도법으로 그려진 지도 입니다.
여기서 새로 고려해야만 하는 사실은 지도이미지가 실제로는 위도 85.05도 ~ -85.05도까지의 범위를 그려놓은 것이라는 점입니다.
즉, 지도이미지 상의 좌표(512, 0)는 경도 0도 위도 85.05도 입니다.
게다가 Y방향으로는 선형관계(Linear)를 갖지 않습니다.
변환식의 수정이 필요하겠죠?
변환식을 수정하고 재계산 해보시면 다른 값이 나올 것입니다.
변환식이 어떻게 바뀌어야 하는지는,
자세한 내용은 http://gilverlight.net/2693를 참조하십시오.
이 정도 생각해 보시면,
어떤 타일이 얼마만큼의 경도, 위도 범위를 표현하는지,
LeftTop(경도1, 위도1), RightBottom(경도2, 위도2)
어떤 지점(경도, 위도)이 어떤 타일 위에 존재하는지 계산하는 것은 쉬울 것입니다.
지도이미지 상 좌표가 X = 872, Y = 299라고 가정하면
왼쪽 맨위의 맵타일이 (0, 0)의 인덱스를 갖는 2차원 배열로 가정해서 생각해보면,
아래와 같이 인덱스를 구할 수 있을 겁니다.
XIndex = Math.Floor( X / 단위 맵타일 폭 )
YIndex = Math.Floor( Y / 단위 맵타일 높이 )
Math.Floor(872 / 256) = 3
Math.Floor(299 / 256) = 1
(3, 1)에 해당하는 맵타일 위가 되겠군요.
Tag : GIS, gps, maps.live.com, Windows Live, 메르카토르도법, 버추얼어스
more..
Tag : maps.live.com, Virtual Earth, 버추얼어스, 웹서비스
Virtual Earth의 지도 이미지들을 이용한 실버라이트 어플리케이션을 만들기 위해서
요즘 한참 공부하고 있습니다.
며칠 전에는 어느 정도 구현이 끝나서, 서울을 화면에 띄워 보려고,
경도 127도(E), 위도 37도 3분 을 입력했더니, 한반도 북부가 화면 중심에 뜨는 겁니다.
위도를 20도 정도로 입력을 했더니, 그제서야 서울이 보이는 겁니다.
엥? 왜이럴까?
지도 이미지 상에서의 위치가 위도와 정비례 한다고 가정하고 구현했기 때문에 맞지가 않는 거였습니다.
구글링으로 Virtual Earth가 사용한 도법이 'mercator projection'이라는 것을 알아냈습니다.
Wiki에서 찾은 자료로 이 문제를 해결할 수 있었습니다.
원문 : http://en.wikipedia.org/wiki/Mercator_projection
중간의 계산은 생략하고,
지도의 수직적 위치 y와 위도 φ (파이) 사이에는 다음과 같은 관계가 있습니다.
y = ln(tan(φ) + sec(φ)) .... (1)
φ = tan-¹(sinh(y)) .... (2)
(1)번 식을 C# 코드로 표현하면, 아래와 같습니다.
dLatitude : 위도 [단위 : 도]
dRad : 위도 [단위 : Radian]
(2)번 식은 아래와 같습니다.
dLatitude : 위도 [단위 : 도]
dRad : 위도 [단위 : Radian]
이때 알아두셔야 할 점은 위도가 90나 -90일 때는 엄청나게 큰 dVerticalPosition 값을 가지게 되어,
90일 때는 Infinity(무한대), -90일 때는 -Infinity(-무한대)를 가지게 됩니다.
따라서 어느 정도 제한이 있어야 하는데요.
위도의 최대 값은 y value가 π 값을 가질 때인,
dVerticalPosition = +/- 85.0511287798066로 한다고 합니다.
버추얼어스에서 보여주는 지도의 꼭대기 부분은 위도가 90도가 아니라
85.0511287798066도 였던 것입니다.
위에서 계산한 dVerticalPosition(π ~ -π)은 다음과 같이 사용할 수 있습니다.
지도 이미지 높이가 MAP_HEIGHT라 가정하면
dPosY : MAP_HEIGHT의 높이를 갖는 지도 이미지 상의 Y좌표
결론적으로 위 공식들을 적용하니 위도/경도를 입력했을 때 정확하게 그 위치를
화면 중앙에 위치시킬 수 있었습니다.
한편, 각도와 Radian 변환은 다음과 같이 하시면 됩니다.
Tag : maps.live.com, Silverlight, 버추얼어스, 실버라이트