From 307e42eac282b73e0dcfdfa754b3e5e254c9e103 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 19 Jul 2022 10:12:52 +0300 Subject: [PATCH] Add feature group --- .../sciprog/maps/compose/FeatureBuilder.kt | 12 +++++++++++- .../centre/sciprog/maps/compose/MapFeature.kt | 18 ++++++++++++++---- .../centre/sciprog/maps/compose/MapViewJvm.kt | 8 +++++++- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/maps-kt-compose/src/commonMain/kotlin/centre/sciprog/maps/compose/FeatureBuilder.kt b/maps-kt-compose/src/commonMain/kotlin/centre/sciprog/maps/compose/FeatureBuilder.kt index cb49c4c..2457de9 100644 --- a/maps-kt-compose/src/commonMain/kotlin/centre/sciprog/maps/compose/FeatureBuilder.kt +++ b/maps-kt-compose/src/commonMain/kotlin/centre/sciprog/maps/compose/FeatureBuilder.kt @@ -74,4 +74,14 @@ fun FeatureBuilder.image( size: Size = Size(20f, 20f), zoomRange: IntRange = defaultZoomRange, id: FeatureId? = null, -) = addFeature(id, MapVectorImageFeature(position.toCoordinates(), image, size, zoomRange)) \ No newline at end of file +) = addFeature(id, MapVectorImageFeature(position.toCoordinates(), image, size, zoomRange)) + +fun FeatureBuilder.group( + zoomRange: IntRange = defaultZoomRange, + id: FeatureId? = null, + builder: FeatureBuilder.() -> Unit, +): FeatureId { + val map = MapFeatureBuilder(emptyMap()).apply(builder).build() + val feature = MapFeatureGroup(map, zoomRange) + return addFeature(id, feature) +} \ No newline at end of file diff --git a/maps-kt-compose/src/commonMain/kotlin/centre/sciprog/maps/compose/MapFeature.kt b/maps-kt-compose/src/commonMain/kotlin/centre/sciprog/maps/compose/MapFeature.kt index 2b8dd02..e4cb1bc 100644 --- a/maps-kt-compose/src/commonMain/kotlin/centre/sciprog/maps/compose/MapFeature.kt +++ b/maps-kt-compose/src/commonMain/kotlin/centre/sciprog/maps/compose/MapFeature.kt @@ -16,10 +16,11 @@ import centre.sciprog.maps.wrapAll //TODO replace zoom range with zoom-based representation change sealed class MapFeature(val zoomRange: IntRange) { - abstract fun getBoundingBox(zoom: Int): GmcBox + abstract fun getBoundingBox(zoom: Int): GmcBox? } -fun Iterable.computeBoundingBox(zoom: Int): GmcBox? = map { it.getBoundingBox(zoom) }.wrapAll() +fun Iterable.computeBoundingBox(zoom: Int): GmcBox? = + mapNotNull { it.getBoundingBox(zoom) }.wrapAll() internal fun Pair.toCoordinates() = GeodeticMapCoordinates.ofDegrees(first, second) @@ -29,7 +30,7 @@ internal val defaultZoomRange = 1..18 * A feature that decides what to show depending on the zoom value (it could change size of shape) */ class MapFeatureSelector(val selector: (zoom: Int) -> MapFeature) : MapFeature(defaultZoomRange) { - override fun getBoundingBox(zoom: Int): GmcBox = selector(zoom).getBoundingBox(zoom) + override fun getBoundingBox(zoom: Int): GmcBox? = selector(zoom).getBoundingBox(zoom) } class MapDrawFeature( @@ -79,7 +80,6 @@ class MapBitmapImageFeature( override fun getBoundingBox(zoom: Int): GmcBox = GmcBox(position, position) } - class MapVectorImageFeature( val position: GeodeticMapCoordinates, val painter: Painter, @@ -96,3 +96,13 @@ fun MapVectorImageFeature( size: Size = Size(20f, 20f), zoomRange: IntRange = defaultZoomRange, ): MapVectorImageFeature = MapVectorImageFeature(position, rememberVectorPainter(image), size, zoomRange) + +/** + * A group of other features + */ +class MapFeatureGroup( + val children: Map, + zoomRange: IntRange = defaultZoomRange, +) : MapFeature(zoomRange) { + override fun getBoundingBox(zoom: Int): GmcBox? = children.values.mapNotNull { it.getBoundingBox(zoom) }.wrapAll() +} diff --git a/maps-kt-compose/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt b/maps-kt-compose/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt index 9312dfe..0621513 100644 --- a/maps-kt-compose/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt +++ b/maps-kt-compose/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt @@ -48,7 +48,7 @@ private val logger = KotlinLogging.logger("MapView") /** * A component that renders map and provides basic map manipulation capabilities */ -@OptIn(ExperimentalComposeUiApi::class) + @Composable actual fun MapView( mapTileProvider: MapTileProvider, @@ -102,6 +102,7 @@ actual fun MapView( // Selection rectangle. If null - no selection var selectRect by remember { mutableStateOf(null) } + @OptIn(ExperimentalComposeUiApi::class) val canvasModifier = modifier.pointerInput(Unit) { forEachGesture { awaitPointerEventScope { @@ -240,6 +241,11 @@ actual fun MapView( val offset = feature.position.toOffset() feature.drawFeature(this, offset) } + is MapFeatureGroup -> { + feature.children.values.forEach { + drawFeature(zoom, it) + } + } } }