Docs / Core / GeoPoint & bounds

GeoPoint and bounds

There is exactly one coordinate type in MapConductor: GeoPoint. You never touch a provider LatLng, CLLocationCoordinate2D or LngLat. Rectangular areas are GeoRectBounds, expressed as a south-west and a north-east corner. Both have the same members on all three platforms.

ANDROID
com.mapconductor.core.features
iOS
MapConductorCore
REACT
@mapconductor/js-sdk-core
Platform

01 · GeoPoint

An immutable value holding latitude, longitude and altitude. Altitude is optional and treated as 0 when omitted. Equality and hashing are by content, so a GeoPoint works directly as a map key or in change detection.

Member
Type
Description
latitude
Double
Latitude in degrees, −90…90.
longitude
Double
Longitude in degrees, −180…180.
altitude
Double · 0.0
Altitude in metres; only the 3D providers interpret it.
wrap()
GeoPoint
Returns the point with its longitude wrapped across the date line.
toUrlValue(precision)
String · 6
A “lat,lng” string; six decimal places by default.

There are three ways to build one: the constructor, factories that spell out the coordinate order, and a converter from another coordinate-like value. The easily-swapped lat/lng order is disambiguated by name.

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 and fromLngLat / fromLongLat are aliases of one another — pick whichever matches the naming in your existing code.

02 · Normalising and validity

Coordinates from outside data are often out of range, or carry a longitude past 360°. normalize clamps them into range and isValid tells you whether they were in range to begin with.

normalize()

Bring it into range

Latitude is clamped to −90…90 and longitude is wrapped into −180…180 — a longitude of 200 becomes −160.

isValid()

Check the range

True only when latitude sits in −90…90 and longitude in −180…180. Use it when ingesting data.

Kotlin · extension functions
// GeoPointInterface の拡張関数として提供される
val safe = raw.normalize()
if (!raw.isValid()) return

03 · GeoRectBounds

A rectangle given by its south-west and north-east corners. The idiom is a growing box: feed it points and it expands to enclose them all. A freshly created one is empty, with southWest and northEast unset.

Member
Description
southWest / northEast
The two corners; unset while the box is empty.
center
The centre — computed correctly even for a box straddling the date line.
isEmpty
Whether no point has been added yet.
extend(point)
Grows the box to include the point, expanding across the shorter side in longitude.
contains(point)
Whether a point falls inside.
intersects(other)
Whether two boxes overlap — used for tile and fetch-window decisions.
union(other)
A new box enclosing both.
expandedByDegrees(lat, lon)
A new box padded outwards in degrees. To pad in metres, use expandBounds from the geodesy helpers.
toSpan()
Returns the latitude and longitude deltas, packaged as a GeoPoint.
toUrlValue(precision)
A “sw,ne” string; six decimal places by default.
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 · Where bounds are used

GeoRectBounds shows up all over the API, and it is always the same type — build a box once and reuse it.

fitBounds()

Moves the camera so the whole box fits; padding is screen margin in logical pixels.

GroundImageState

Placing an image on the map is expressed as the bounds it covers.

CameraRestriction · restrictBounds

The box the camera is not allowed to leave (Android and React).

visibleRegion.bounds

The MapCameraPosition delivered by onCameraMove carries the visible box, so you can fetch only the data inside it.

expandBounds()

The metre-based variant; see the geodesy page.

GeoJSON / tiles

intersects drives tile generation and refetch decisions.

What the video shows · 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")
}
Sample video · fitBounds framing a set of points
Video not shot yetComputing the bounds around several markers and letting fitBounds move the camera in. What matters is the motion in between.

Related pages