문서 / 코어 / GeoPoint와 범위

GeoPoint와 범위(GeoRectBounds)

MapConductor의 좌표 타입은 GeoPoint 하나뿐입니다. 프로바이더마다 다른 LatLng・CLLocationCoordinate2D・LngLat를 만질 필요가 없습니다. 사각형 범위는 GeoRectBounds가 맡으며, 남서와 북동의 2점으로 나타냅니다. 둘 다 3개 플랫폼에서 같은 멤버 구성입니다.

ANDROID
com.mapconductor.core.features
iOS
MapConductorCore
REACT
@mapconductor/js-sdk-core
플랫폼

01 · GeoPoint

위도・경도・고도 3개를 가지는 불변의 값입니다. 고도는 생략할 수 있고, 그 경우 0으로 다룹니다. 동등 비교와 해시는 위경도(와 고도)의 내용으로 정해지므로, 그대로 맵의 키나 차분 판정에 쓸 수 있습니다.

멤버
Type
설명
latitude
Double
위도(도). −90〜90.
longitude
Double
경도(도). −180〜180.
altitude
Double · 0.0
고도(미터). 3D 프로바이더만 해석합니다.
wrap()
GeoPoint
경도를 날짜변경선을 넘어 되돌린 좌표를 반환합니다.
toUrlValue(precision)
String · 6
"위도,경도" 형식의 문자열. 기본은 소수점 6자리입니다.

생성 방법은 3가지입니다. 생성자, 위경도의 순서를 명시하는 팩토리, 그리고 다른 좌표 타입으로부터의 변환입니다. 순서를 헷갈리기 쉬운 경도・위도의 배열은 이름으로 구별할 수 있게 해 두었습니다.

GeoPoint · Kotlin
val tokyo = GeoPoint(35.6812, 139.7671)
val haneda = GeoPoint.fromLatLong(35.548852, 139.784086)
val fromLngLat = GeoPoint.fromLongLat(139.7671, 35.6812)

// GeoPointInterface를 구현한 값이라면 무엇이든
val copied = GeoPoint.from(anyPositionLike)

val url = tokyo.toUrlValue() // "35.681200,139.767100"

fromLatLng과 fromLatLong, fromLngLat과 fromLongLat은 같은 것의 다른 이름입니다. 기존 코드의 명명에 맞춰 고를 수 있습니다.

02 · 정규화와 유효성

외부 데이터의 좌표는 범위를 벗어나 있거나, 경도가 360도를 넘기도 합니다. 범위 안으로 넣는 normalize와, 범위 안인지 확인하는 isValid가 준비되어 있습니다.

normalize()

범위 안으로 넣기

위도는 −90〜90으로 잘라내고, 경도는 −180〜180으로 되돌립니다. 경도 200은 −160이 됩니다.

isValid()

범위 안인지 확인하기

위도가 −90〜90, 경도가 −180〜180 안에 들어 있을 때만 true. 데이터를 가져올 때의 검증에 씁니다.

Kotlin · 확장 함수
// GeoPointInterface의 확장 함수로 제공된다
val safe = raw.normalize()
if (!raw.isValid()) return

03 · GeoRectBounds

남서와 북동의 2점으로 사각형을 나타냅니다. 점을 더해 가면 전체를 감싸는 범위가 자라는 「늘어나는 상자」로 쓰는 것이 기본입니다. 만든 직후에는 비어 있고(isEmpty), southWest와 northEast는 설정되지 않은 상태입니다.

멤버
설명
southWest / northEast
사각형의 두 모서리. 비어 있을 때는 설정되지 않은 상태입니다.
center
중심. 날짜변경선을 넘는 사각형에서도 올바르게 구해집니다.
isEmpty
아직 점이 하나도 들어 있지 않은지.
extend(point)
그 점을 포함하도록 사각형을 넓힙니다. 경도는 짧은 쪽으로 넓어집니다.
contains(point)
점이 사각형의 안쪽에 있는지.
intersects(other)
두 사각형이 겹치는지. 타일이나 취득 범위의 판정에 씁니다.
union(other)
두 사각형을 모두 포함하는 새로운 사각형.
expandedByDegrees(lat, lon)
도 단위로 바깥쪽으로 넓힌 새로운 사각형. 미터 단위로 넓히고 싶을 때는 Spherical의 expandBounds를 씁니다.
toSpan()
위도차・경도차를 GeoPoint의 형태로 반환합니다.
toUrlValue(precision)
"남서,북동" 형식의 문자열. 기본은 소수점 6자리입니다.
GeoRectBounds · Kotlin
// 경로 전체를 담는 bounds를 만들어 카메라를 맞춘다
val bounds = GeoRectBounds()
routePoints.forEach { bounds.extend(it) }

mapViewState.fitBounds(bounds = bounds, padding = 48)

// 표시 범위보다 조금 넓게 가져온다
val fetchArea = bounds.expandedByDegrees(latPad = 0.05, lonPad = 0.05)

04 · 범위의 쓰임새

GeoRectBounds는 API의 여기저기에 나타납니다. 어느 것이나 같은 타입이므로, 한 번 만든 범위는 돌려 쓸 수 있습니다.

fitBounds()

범위 전체가 들어가도록 카메라를 맞춥니다. padding은 화면의 여백(논리 픽셀).

GroundImageState

이미지를 지도에 붙일 때, 붙일 위치를 범위로 지정합니다.

CameraRestriction · restrictBounds

카메라가 나갈 수 없는 범위를 사각형으로 정합니다(Android・React).

visibleRegion.bounds

onCameraMove로 도착하는 MapCameraPosition이 표시 중인 범위를 가집니다. 그 범위의 데이터만 가지러 갈 수 있습니다.

expandBounds()

미터 단위로 넓히는 버전. 지리 계산 페이지를 참조.

GeoJSON / 타일

타일 생성과 재취득의 판단에 intersects를 씁니다.

영상으로 보여 주는 구현 · Android + MapLibreKotlin · Jetpack Compose
val spots = listOf(
    GeoPoint.fromLatLong(35.6586, 139.7454), // Tokyo Tower
    GeoPoint.fromLatLong(35.7101, 139.8107), // Skytree
    GeoPoint.fromLatLong(35.6852, 139.7528), // Imperial Palace
)

// Start from an empty rectangle and widen it one point at a time
val bounds = GeoRectBounds()
spots.forEach { bounds.extend(it) }

MapLibreMapView(state = mapViewState) {
    spots.forEachIndexed { i, point ->
        Marker(MarkerState(id = "spot-$i", position = point))
    }
}

Button(onClick = {
    // padding is screen margin in logical pixels; at 0 the outermost point hugs the edge
    if (!bounds.isEmpty) mapViewState.fitBounds(bounds, padding = 64)
}) {
    Text("Show all")
}
샘플 영상 · fitBounds로 범위에 맞추기
영상 미촬영여러 마커를 포함하는 범위를 구하고, fitBounds로 카메라가 다가가는 모습. 애니메이션의 도중 경과가 요점입니다.

관련 페이지