GeoRectBounds
GeoRectBounds representa un área geográfica rectangular definida por dos esquinas: suroeste y noreste. Se utiliza para definir regiones de mapa, límites de imágenes de tipo ground image y para cálculos de viewport.
Constructor
Section titled “Constructor”class GeoRectBounds( southWest: GeoPoint? = null, northEast: GeoPoint? = null)Propiedades
Section titled “Propiedades”Esquinas
Section titled “Esquinas”southWest: GeoPoint?: esquina suroeste (inferior izquierda) del rectángulo.northEast: GeoPoint?: esquina noreste (superior derecha) del rectángulo.isEmpty: Boolean: devuelvetruesi los límites no están definidos.
Propiedades calculadas
Section titled “Propiedades calculadas”center: GeoPoint?: punto central de los límites.toSpan(): GeoPoint?: devuelve el “span” (ancho/alto) como unGeoPointInterface.
Pruebas con puntos y límites
Section titled “Pruebas con puntos y límites”Contiene un punto
Section titled “Contiene un punto”fun contains(point: GeoPointInterface): Boolean
// Usageval bounds = GeoRectBounds( southWest = GeoPoint.fromLatLong(37.7649, -122.4294), northEast = GeoPoint.fromLatLong(37.7849, -122.4094))
val testPoint = GeoPoint.fromLatLong(37.7749, -122.4194)val isInside = bounds.contains(testPoint)
println("Point is inside bounds: $isInside")Intersección de límites
Section titled “Intersección de límites”fun intersects(other: GeoRectBounds): Boolean
// Usageval bounds1 = GeoRectBounds(/* ... */)val bounds2 = GeoRectBounds(/* ... */)
val doIntersect = bounds1.intersects(bounds2)println("Bounds intersect: $doIntersect")Ejemplos prácticos
Section titled “Ejemplos prácticos”Cálculo de límites de viewport
Section titled “Cálculo de límites de viewport”@Composablefun ViewportBoundsExample() { var viewportBounds by remember { mutableStateOf<GeoRectBounds?>(null) }
// Calcular el viewport a partir de los marcadores visibles val markers = remember { listOf( GeoPoint.fromLatLong(37.7749, -122.4194), GeoPoint.fromLatLong(37.7849, -122.4094), GeoPoint.fromLatLong(37.7649, -122.4294), GeoPoint.fromLatLong(37.7949, -122.3994) ) }
LaunchedEffect(markers) { val bounds = GeoRectBounds() markers.forEach { marker -> bounds.extend(marker) } viewportBounds = bounds }
// Sustituye MapView por el proveedor de mapas que prefieras, como GoogleMapView o MapboxMapView MapView(state = mapViewState) { // Show all markers markers.forEach { position -> Marker( position = position, icon = DefaultIcon(fillColor = Color.Blue) ) }
// Show viewport bounds as a polygon viewportBounds?.let { bounds -> if (!bounds.isEmpty) { val sw = bounds.southWest!! val ne = bounds.northEast!!
val boundsPolygon = listOf( sw, GeoPoint.fromLatLong(sw.latitude, ne.longitude), ne, GeoPoint.fromLatLong(ne.latitude, sw.longitude), sw // Close the polygon )
Polygon( points = boundsPolygon, strokeColor = Color.Red, strokeWidth = 2.dp, fillColor = Color.Red.copy(alpha = 0.1f) ) } } }}Carga basada en límites
Section titled “Carga basada en límites”@Composablefun BoundsBasedLoadingExample() { var currentBounds by remember { mutableStateOf<GeoRectBounds?>(null) } var markersInBounds by remember { mutableStateOf<List<GeoPoint>>(emptyList()) }
// Simular todos los marcadores disponibles val allMarkers = remember { List(100) { i -> GeoPoint.fromLatLong( 37.7 + (i % 10) * 0.01, -122.5 + (i / 10) * 0.01 ) } }
// Filter markers based on current bounds LaunchedEffect(currentBounds) { markersInBounds = currentBounds?.let { bounds -> if (bounds.isEmpty) { emptyList() } else { allMarkers.filter { marker -> bounds.contains(marker) } } } ?: emptyList() }
Column { Text("Markers in bounds: ${markersInBounds.size}/${allMarkers.size}")
Button( onClick = { // Simular el establecimiento de los límites del viewport currentBounds = GeoRectBounds( southWest = GeoPoint.fromLatLong(37.7, -122.5), northEast = GeoPoint.fromLatLong(37.75, -122.45) ) } ) { Text("Set Viewport") }
// Sustituye MapView por el proveedor de mapas que prefieras, como GoogleMapView o MapboxMapView MapView(state = mapViewState) { // Show only markers within bounds markersInBounds.forEach { position -> Marker( position = position, icon = DefaultIcon( fillColor = Color.Green, scale = 0.8f ) ) }
// Show current bounds currentBounds?.let { bounds -> if (!bounds.isEmpty) { val sw = bounds.southWest!! val ne = bounds.northEast!!
Polygon( points = listOf( sw, GeoPoint.fromLatLong(sw.latitude, ne.longitude), ne, GeoPoint.fromLatLong(ne.latitude, sw.longitude), sw ), strokeColor = Color.Blue, strokeWidth = 3.dp, fillColor = Color.Blue.copy(alpha = 0.1f) ) } } } }}Editor interactivo de límites
Section titled “Editor interactivo de límites”@Composablefun BoundsEditorExample() { var bounds by remember { mutableStateOf( GeoRectBounds( southWest = GeoPoint.fromLatLong(37.7649, -122.4294), northEast = GeoPoint.fromLatLong(37.7849, -122.4094) ) ) }
val onCornerDrag: (MarkerState) -> Unit = { markerState -> val newPosition = markerState.position when (markerState.extra) { "SW" -> { bounds = GeoRectBounds( southWest = newPosition as GeoPoint, northEast = bounds.northEast ) } "NE" -> { bounds = GeoRectBounds( southWest = bounds.southWest, northEast = newPosition as GeoPoint ) } } }
// Sustituye MapView por el proveedor de mapas que prefieras, como GoogleMapView o MapboxMapView MapView( state = mapViewState ) { // Bounds visualization if (!bounds.isEmpty) { val sw = bounds.southWest!! val ne = bounds.northEast!!
// Bounds rectangle Polygon( points = listOf( sw, GeoPoint.fromLatLong(sw.latitude, ne.longitude), ne, GeoPoint.fromLatLong(ne.latitude, sw.longitude), sw ), strokeColor = Color.Red, fillColor = Color.Red.copy(alpha = 0.2f) )
// Corner markers Marker( position = sw, icon = DefaultIcon( fillColor = Color.Green, label = "SW" ), draggable = true, extra = "SW", onDrag = onCornerDrag )
Marker( position = ne, icon = DefaultIcon( fillColor = Color.Red, label = "NE" ), draggable = true, extra = "NE", onDrag = onCornerDrag ) } }}Manejo especial
Section titled “Manejo especial”Línea internacional de cambio de fecha
Section titled “Línea internacional de cambio de fecha”GeoRectBounds maneja rectángulos que cruzan la línea internacional de cambio de fecha (longitud ±180°):
// Bounds crossing the date lineval pacificBounds = GeoRectBounds( southWest = GeoPoint.fromLatLong(20, 170), // West of date line northEast = GeoPoint.fromLatLong(40, -170) // East of date line)
val pointInPacific = GeoPoint.fromLatLong(30, 175)val containsPoint = pacificBounds.contains(pointInPacific) // trueManejo de límites vacíos
Section titled “Manejo de límites vacíos”val emptyBounds = GeoRectBounds()
println(emptyBounds.isEmpty) // trueprintln(emptyBounds.center) // nullprintln(emptyBounds.toSpan()) // null
// Extending empty boundsemptyBounds.extend(GeoPoint.fromLatLong(37.7749, -122.4194))println(emptyBounds.isEmpty) // falseMétodos utilitarios
Section titled “Métodos utilitarios”Representación de cadena
Section titled “Representación de cadena”// For debuggingval bounds = GeoRectBounds( southWest = GeoPoint.fromLatLong(37.7649, -122.4294), northEast = GeoPoint.fromLatLong(37.7849, -122.4094))
println(bounds.toString())// Output: ((37.7649, -122.4294), (37.7849, -122.4094))Valor de URL
Section titled “Valor de URL”fun toUrlValue(precision: Int = 6): String
// Usage for API callsval urlString = bounds.toUrlValue() // "37.764900,-122.429400,37.784900,-122.409400"val preciseString = bounds.toUrlValue(precision = 8)Comparación de igualdad
Section titled “Comparación de igualdad”fun equalsTo(other: GeoRectBounds): Boolean
// Usoval bounds1 = GeoRectBounds(/* ... */)val bounds2 = GeoRectBounds(/* ... */)
val areEqual = bounds1.equalsTo(bounds2)