ドキュメント / コア / 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
矩形の 2 隅。空のときは未設定です。
center
中心。日付変更線をまたぐ矩形でも正しく求まります。
isEmpty
まだ 1 点も入っていないか。
extend(point)
その点を含むように矩形を広げます。経度は短いほうへ広がります。
contains(point)
点が矩形の内側にあるか。
intersects(other)
2 つの矩形が重なるか。タイルや取得範囲の判定に使います。
union(other)
2 つの矩形を両方含む新しい矩形。
expandedByDegrees(lat, lon)
度単位で外側に広げた新しい矩形。メートル単位で広げたいときは Spherical の expandBounds を使います。
toSpan()
緯度差・経度差を GeoPoint の形で返します。
toUrlValue(precision)
"南西,北東" の文字列。既定は小数 6 桁です。
GeoRectBounds · Kotlin
// ルート全体が入る範囲を作ってカメラを合わせる
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), // 東京タワー
    GeoPoint.fromLatLong(35.7101, 139.8107), // スカイツリー
    GeoPoint.fromLatLong(35.6852, 139.7528), // 皇居
)

// 空の範囲から始めて、1 点ずつ広げる
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 は画面の余白(論理ピクセル)。0 だと端の点が縁に張り付く
    if (!bounds.isEmpty) mapViewState.fitBounds(bounds, padding = 64)
}) {
    Text("全部を表示")
}
サンプル動画 · fitBounds で範囲に収める
動画 未撮影複数のマーカーを含む範囲を求め、fitBounds でカメラが寄っていく様子。アニメーションの途中経過が要点です。

関連ページ