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.
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")
}