카메라와 투영

네이버 지도 SDK는 기기 화면 건너편의 지도를 카메라로 바라보는 방식으로 지도를 표현합니다. 카메라를 이동, 확대 및 축소, 기울임, 회전시킴으로써 화면에 보이는 지도를 자유자재로 움직일 수 있습니다.

카메라의 위치

카메라의 위치는 카메라가 놓여 있는 대상 지점의 좌표와 줌 레벨, 기울기, 베어링으로 구성됩니다.

대상 지점

target은 카메라가 놓여 있는 대상 지점의 좌표를 나타내는 속성입니다. 대상 지점이 변경되면 지도가 동서남북으로 움직입니다.

대상 지점

줌 레벨

zoom은 카메라의 줌 레벨을 나타내는 속성입니다. 줌 레벨은 지도의 축척을 나타냅니다. 즉, 줌 레벨이 작을수록 지도가 축소되고 클수록 확대됩니다. 줌 레벨이 커지면 지도에 나타나는 정보도 더욱 세밀해집니다.

기울임 각도

tilt는 카메라의 기울임 각도를 나타내는 속성입니다. 카메라는 기울임 각도만큼 지면을 비스듬하게 내려다봅니다. 기울임 각도가 0도이면 카메라가 지면을 수직으로 내려다보며, 각도가 증가하면 카메라의 시선도 점점 수평에 가깝게 기울어집니다. 따라서 기울임 각도가 클수록 더 먼 곳을 볼 수 있게 됩니다. 카메라가 기울어지면 화면에 보이는 지도에 원근감이 적용됩니다. 즉, 화면의 중심을 기준으로 먼 곳은 더 작게 보이고 가까운 곳은 더 크게 보입니다.

기울임 각도

베어링 각도

bearing은 카메라의 베어링 각도를 나타내는 속성입니다. 베어링은 카메라가 바라보는 방위를 의미합니다. 카메라가 정북 방향을 바라볼 때 베어링 각도는 0도이며, 시계 방향으로 값이 증가합니다. 즉, 동쪽을 바라볼 때 90도, 남쪽을 바라볼 때 180도가 됩니다.

베어링 각도

CameraPosition 객체

CameraPosition은 카메라의 위치를 나타내는 클래스입니다. CameraPosition의 모든 속성은 final이므로 생성자로만 지정할 수 있고, 한 번 생성된 객체의 속성은 변경할 수 없습니다.

다음은 CameraPosition 객체를 생성하고 토스트로 각 속성을 출력하는 예제입니다.

CameraPosition cameraPosition = new CameraPosition(
    new LatLng(37.5666102, 126.9783881), // 대상 지점
    16, // 줌 레벨
    20, // 기울임 각도
    180 // 베어링 각도
);

Toast.makeText(context,
    "대상 지점 위도: " + cameraPosition.target.latitude + ", " +
    "대상 지점 경도: " + cameraPosition.target.longitude + ", " +
    "줌 레벨: " + cameraPosition.zoom + ", " +
    "기울임 각도: " + cameraPosition.tilt + ", " +
    "베어링 각도: " + cameraPosition.bearing,
    Toast.LENGTH_SHORT).show();

Java

CameraPosition cameraPosition = new CameraPosition(
    new LatLng(37.5666102, 126.9783881), // 대상 지점
    16, // 줌 레벨
    20, // 기울임 각도
    180 // 베어링 각도
);

Toast.makeText(context,
    "대상 지점 위도: " + cameraPosition.target.latitude + ", " +
    "대상 지점 경도: " + cameraPosition.target.longitude + ", " +
    "줌 레벨: " + cameraPosition.zoom + ", " +
    "기울임 각도: " + cameraPosition.tilt + ", " +
    "베어링 각도: " + cameraPosition.bearing,
    Toast.LENGTH_SHORT).show();

Kotlin

val cameraPosition = CameraPosition(
        LatLng(37.5666102, 126.9783881), // 대상 지점
        16.0, // 줌 레벨
        20.0, // 기울임 각도
        180.0 // 베어링 각도
)

Toast.makeText(this,
        "대상 지점 위도: ${cameraPosition.target.latitude}, " +
        "대상 지점 경도: ${cameraPosition.target.longitude}, " +
        "줌 레벨: ${cameraPosition.zoom}, " +
        "기울임 각도: ${cameraPosition.tilt}, " +
        "베어링 각도: ${cameraPosition.bearing}",
        Toast.LENGTH_SHORT).show()

CameraPosition 객체를 생성할 때 기울임 각도와 베어링 각도는 생략할 수 있습니다. 생략할 경우 0으로 지정됩니다.

다음은 대상 지점과 줌 레벨만을 지정해 CameraPosition 객체를 생성하는 예제입니다.

CameraPosition cameraPosition =
    new CameraPosition(new LatLng(37.5666102, 126.9783881), 16);

Java

CameraPosition cameraPosition =
    new CameraPosition(new LatLng(37.5666102, 126.9783881), 16);

Kotlin

val cameraPosition = CameraPosition(LatLng(37.5666102, 126.9783881), 16.0)

뷰와 카메라

카메라는 기본적으로 지도 뷰의 중심에 위치합니다. 그러나 콘텐츠 패딩이 지정되면 카메라의 위치에 영향을 미칩니다.

카메라의 현재 위치

NaverMap.getCameraPosition()을 호출하면 카메라의 현재 위치를 얻을 수 있습니다.

다음은 카메라의 현재 위치를 얻는 예제입니다.

CameraPosition cameraPosition = naverMap.getCameraPosition();

Java

CameraPosition cameraPosition = naverMap.getCameraPosition();

Kotlin

val cameraPosition = naverMap.cameraPosition

콘텐츠 패딩

NaverMap.setContentPadding()을 호출하면 콘텐츠 패딩을 지정할 수 있습니다. 다음 그림과 같이 UI 요소가 지도의 일부를 덮을 경우, 카메라는 지도 뷰의 중심에 위치하므로 실제로 보이는 지도의 중심과 카메라의 위치가 불일치하게 됩니다.

지도 중심 불일치

이 경우 UI 요소에 가려진 영역을 콘텐츠 패딩으로 지정할 수 있습니다. 콘텐츠 패딩을 지정하면 카메라는 콘텐츠 패딩을 제외한 영역의 중심에 위치하게 됩니다.

콘텐츠 패딩 적용

다음은 아래쪽 콘텐츠 패딩을 200픽셀로 지정하는 예제입니다.

naverMap.setContentPadding(0, 0, 0, 200);

Java

naverMap.setContentPadding(0, 0, 0, 200);

Kotlin

naverMap.setContentPadding(0, 0, 0, 200)

콘텐츠 패딩을 변경하더라도 눈에 보이는 지도에는 변화가 일어나지 않습니다. 그러나 카메라가 위치할 지도의 중심이 변경되므로 카메라의 위치도 변경됩니다.

투영

화면은 왼쪽 위를 기준점으로 삼는 픽셀 단위 좌표계를 사용하고, 지도는 지리적 위경도 좌표계를 사용합니다. Projection 클래스의 메서드를 사용하면 화면 좌표와 지도 좌표를 서로 변환할 수 있습니다. Projection 클래스의 인스턴스는 직접 생성할 수 없고 NaverMap.getProjection()을 호출해 가져와야 합니다.

다음은 Projection 클래스의 인스턴스를 얻는 예제입니다.

Projection projection = naverMap.getProjection();

Java

Projection projection = naverMap.getProjection();

Kotlin

val projection = naverMap.projection

화면 좌표와 지도 좌표 간 변환

fromScreenLocation()을 사용하면 화면 좌표를 지도 좌표로, toScreenLocation()을 사용하면 지도 좌표를 화면 좌표로 변환할 수 있습니다.

다음은 화면의 (100, 100) 지점을 지도 좌표로 변환하는 예제입니다.

LatLng coord = projection.fromScreenLocation(new PointF(100, 100));

Java

LatLng coord = projection.fromScreenLocation(new PointF(100, 100));

Kotlin

val coord = projection.fromScreenLocation(PointF(100f, 100f))

다음은 지도의 (37.5666102, 126.9783881) 지점을 화면 좌표로 변환하는 예제입니다.

PointF point = projection.toScreenLocation(new LatLng(37.5666102, 126.9783881));

Java

PointF point = projection.toScreenLocation(new LatLng(37.5666102, 126.9783881));

Kotlin

val point = projection.toScreenLocation(LatLng(37.5666102, 126.9783881))

축척

지도는 3차원인 지구의 표면을 2차원으로 표현하는 것이므로 왜곡이 발생합니다. 네이버 지도 SDK는 웹 메르카토르 투영법을 사용해 지구 구체를 평면으로 표현하기 때문에 줌 레벨뿐만 아니라 위도에 따라서도 축척이 달라집니다. getMetersPerPixel() 또는 getMetersPerDp()를 사용하면 현재 카메라가 위치한 지점의 축척을 각각 미터/픽셀, 미터/DP 단위로 얻을 수 있습니다.

다음은 현재 카메라가 위치한 지점의 축척을 얻는 예제입니다.

double metersPerPixel = projection.getMetersPerPixel(); // 미터/픽셀 단위
double metersPerDp = projection.getMetersPerDp();       // 미터/DP 단위

Java

double metersPerPixel = projection.getMetersPerPixel(); // 미터/픽셀 단위
double metersPerDp = projection.getMetersPerDp();       // 미터/DP 단위

Kotlin

val metersPerPixel = projection.metersPerPixel // 미터/픽셀 단위
val metersPerDp = projection.metersPerDp       // 미터/DP 단위

getMetersPerPixel(latitude, zoom) 또는 getMetersPerDp(latitude, zoom)를 사용하면 현재 카메라의 위치와 무관하게 특정한 위도와 줌 레벨에서의 축척을 구할 수 있습니다. 특히 getMetersPerDp는 스태틱 메서드이므로 지도 객체를 생성하지 않아도 사용할 수 있습니다.

다음은 다양한 위도와 줌 레벨에서의 축척을 구하는 예제입니다.

// 적도, 줌 레벨 10
double metersPerPixel1 = projection.getMetersPerPixel(0, 10);

// 위도 35도, 줌 레벨 10: 적도보다 축척이 커짐
double metersPerPixel2 = projection.getMetersPerPixel(35, 10);

// 위도 35도, 줌 레벨 14: 줌 레벨 10보다 축척이 커짐
double metersPerPixel3 = projection.getMetersPerPixel(35, 14);

// 적도, 줌 레벨 10, 미터/DP 단위
// 스태틱 메서드이므로 인스턴스 필요 없음
double metersPerDp1 = Projection.getMetersPerDp(0, 10);

Java

// 적도, 줌 레벨 10
double metersPerPixel1 = projection.getMetersPerPixel(0, 10);

// 위도 35도, 줌 레벨 10: 적도보다 축척이 커짐
double metersPerPixel2 = projection.getMetersPerPixel(35, 10);

// 위도 35도, 줌 레벨 14: 줌 레벨 10보다 축척이 커짐
double metersPerPixel3 = projection.getMetersPerPixel(35, 14);

// 적도, 줌 레벨 10, 미터/DP 단위
// 스태틱 메서드이므로 인스턴스 필요 없음
double metersPerDp1 = Projection.getMetersPerDp(0, 10);

Kotlin

// 적도, 줌 레벨 10
val metersPerPixel1 = projection.getMetersPerPixel(0.0, 10.0)

// 위도 35도, 줌 레벨 10: 적도보다 축척이 커짐
val metersPerPixel2 = projection.getMetersPerPixel(35.0, 10.0)

// 위도 35도, 줌 레벨 14: 줌 레벨 10보다 축척이 커짐
val metersPerPixel3 = projection.getMetersPerPixel(35.0, 14.0)

// 적도, 줌 레벨 10, 미터/DP 단위
// 스태틱 메서드이므로 인스턴스 필요 없음
val metersPerDp1 = Projection.getMetersPerDp(0, 10)

results matching ""

    No results matching ""