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.
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.
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.
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"
let tokyo = GeoPoint(latitude: 35.6812, longitude: 139.7671) let haneda = GeoPoint.fromLatLong(latitude: 35.548852, longitude: 139.784086) let fromLngLat = GeoPoint.fromLongLat(longitude: 139.7671, latitude: 35.6812) // GeoPointProtocol に準拠する任意の値から let copied = GeoPoint.from(position: anyPositionLike) let url = tokyo.toUrlValue() // "35.681200,139.767100"
import { createGeoPoint, fromLatLng, fromLngLat, GeoPoint } from '@mapconductor/js-sdk-core';
const tokyo = createGeoPoint({ latitude: 35.6812, longitude: 139.7671 });
const haneda = fromLatLng({ latitude: 35.548852, longitude: 139.784086 });
const fromLngLatPoint = fromLngLat({ longitude: 139.7671, latitude: 35.6812 });
// 名前空間からも同じものが引ける
const same = GeoPoint.fromLatLong({ latitude: 35.6812, longitude: 139.7671 });
const url = tokyo.toUrlValue(6); // "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.
Bring it into range
Latitude is clamped to −90…90 and longitude is wrapped into −180…180 — a longitude of 200 becomes −160.
Check the range
True only when latitude sits in −90…90 and longitude in −180…180. Use it when ingesting data.
// GeoPointInterface の拡張関数として提供される val safe = raw.normalize() if (!raw.isValid()) return
let safe = raw.normalize()
guard raw.isValid() else { return }const 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.
// ルート全体が入る範囲を作ってカメラを合わせる
val bounds = GeoRectBounds()
routePoints.forEach { bounds.extend(it) }
mapViewState.fitBounds(bounds = bounds, padding = 48)
// 表示範囲より少し広めに取得する
val fetchArea = bounds.expandedByDegrees(latPad = 0.05, lonPad = 0.05)let bounds = GeoRectBounds()
routePoints.forEach { bounds.extend(point: $0) }
mapState.fitBounds(bounds: bounds, padding: 48)
let fetchArea = bounds.expandedByDegrees(latPad: 0.05, lonPad: 0.05)import { createGeoRectBounds } from '@mapconductor/js-sdk-core';
const bounds = createGeoRectBounds();
routePoints.forEach(p => bounds.extend(p));
mapViewState.fitBounds(bounds, 48);
const fetchArea = bounds.expandedByDegrees(0.05, 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.
Moves the camera so the whole box fits; padding is screen margin in logical pixels.
Placing an image on the map is expressed as the bounds it covers.
The box the camera is not allowed to leave (Android and React).
The MapCameraPosition delivered by onCameraMove carries the visible box, so you can fetch only the data inside it.
The metre-based variant; see the geodesy page.
intersects drives tile generation and refetch decisions.
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")
}