From 5247ce10aba2d5c31b056abafbbbaf6069a969e1 Mon Sep 17 00:00:00 2001 From: "a.kalmakhanov" Date: Thu, 1 Sep 2022 15:11:26 +0900 Subject: [PATCH] Layers are added to place features below or on top of others --- demo/maps/src/jvmMain/kotlin/Main.kt | 3 ++ .../center/sciprog/maps/compose/MapFeature.kt | 36 ++++++++++------ .../sciprog/maps/compose/MapFeatureBuilder.kt | 42 ++++++++++++------- .../center/sciprog/maps/compose/MapViewJvm.kt | 2 +- 4 files changed, 56 insertions(+), 27 deletions(-) diff --git a/demo/maps/src/jvmMain/kotlin/Main.kt b/demo/maps/src/jvmMain/kotlin/Main.kt index 687602c..408208e 100644 --- a/demo/maps/src/jvmMain/kotlin/Main.kt +++ b/demo/maps/src/jvmMain/kotlin/Main.kt @@ -87,11 +87,14 @@ fun App() { centerCoordinates = pointTwo, ) + draw(position = pointThree) { drawLine(start = Offset(-10f, -10f), end = Offset(10f, 10f), color = Color.Red) drawLine(start = Offset(-10f, 10f), end = Offset(10f, -10f), color = Color.Red) } + circle(pointThree, layer = -1, color = Color.Blue) + arc(pointOne, Distance(10.0), 0f, PI) line(pointOne, pointTwo, id = "line") diff --git a/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/MapFeature.kt b/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/MapFeature.kt index 418b25f..e8ac13b 100644 --- a/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/MapFeature.kt +++ b/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/MapFeature.kt @@ -17,7 +17,7 @@ import kotlin.math.floor public interface MapFeature { public val zoomRange: IntRange public fun getBoundingBox(zoom: Double): GmcRectangle? - + public val layer: Int } public interface DraggableMapFeature : MapFeature { @@ -36,6 +36,7 @@ internal val defaultZoomRange = 1..18 */ public class MapFeatureSelector( public val selector: (zoom: Int) -> MapFeature, + override val layer: Int ) : MapFeature { override val zoomRange: IntRange get() = defaultZoomRange @@ -46,6 +47,7 @@ public class MapDrawFeature( public val position: GeodeticMapCoordinates, override val zoomRange: IntRange = defaultZoomRange, public val drawFeature: DrawScope.() -> Unit, + override val layer: Int ) : DraggableMapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle { //TODO add box computation @@ -53,7 +55,7 @@ public class MapDrawFeature( } override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = - MapDrawFeature(newCoordinates, zoomRange, drawFeature) + MapDrawFeature(newCoordinates, zoomRange, drawFeature, layer) } public class MapPointsFeature( @@ -62,6 +64,7 @@ public class MapPointsFeature( public val stroke: Float = 2f, public val color: Color = Color.Red, public val pointMode: PointMode = PointMode.Points, + override val layer: Int ) : MapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle { return GmcRectangle(points.first(), points.last()) @@ -73,14 +76,15 @@ public class MapCircleFeature( override val zoomRange: IntRange = defaultZoomRange, public val size: Float = 5f, public val color: Color = Color.Red, + override val layer: Int ) : DraggableMapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle { val scale = WebMercatorProjection.scaleFactor(zoom) - return GmcRectangle.square(center, (size/scale).radians, (size/scale).radians) + return GmcRectangle.square(center, (size / scale).radians, (size / scale).radians) } override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = - MapCircleFeature(newCoordinates, zoomRange, size, color) + MapCircleFeature(newCoordinates, zoomRange, size, color, layer) } public class MapRectangleFeature( @@ -88,14 +92,15 @@ public class MapRectangleFeature( override val zoomRange: IntRange = defaultZoomRange, public val size: DpSize = DpSize(5.dp, 5.dp), public val color: Color = Color.Red, + override val layer: Int ) : DraggableMapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle { val scale = WebMercatorProjection.scaleFactor(zoom) - return GmcRectangle.square(center, (size.height.value/scale).radians, (size.width.value/scale).radians) + return GmcRectangle.square(center, (size.height.value / scale).radians, (size.width.value / scale).radians) } override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = - MapRectangleFeature(newCoordinates, zoomRange, size, color) + MapRectangleFeature(newCoordinates, zoomRange, size, color, layer) } public class MapLineFeature( @@ -103,6 +108,7 @@ public class MapLineFeature( public val b: GeodeticMapCoordinates, override val zoomRange: IntRange = defaultZoomRange, public val color: Color = Color.Red, + override val layer: Int ) : MapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(a, b) } @@ -113,6 +119,7 @@ public class MapArcFeature( public val endAngle: Float, override val zoomRange: IntRange = defaultZoomRange, public val color: Color = Color.Red, + override val layer: Int ) : MapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle = oval } @@ -122,11 +129,12 @@ public class MapBitmapImageFeature( public val image: ImageBitmap, public val size: IntSize = IntSize(15, 15), override val zoomRange: IntRange = defaultZoomRange, + override val layer: Int ) : DraggableMapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position) override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = - MapBitmapImageFeature(newCoordinates, image, size, zoomRange) + MapBitmapImageFeature(newCoordinates, image, size, zoomRange, layer) } public class MapVectorImageFeature( @@ -134,11 +142,12 @@ public class MapVectorImageFeature( public val painter: Painter, public val size: DpSize, override val zoomRange: IntRange = defaultZoomRange, -) : DraggableMapFeature{ + override val layer: Int +) : DraggableMapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position) override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = - MapVectorImageFeature(newCoordinates,painter, size, zoomRange) + MapVectorImageFeature(newCoordinates, painter, size, zoomRange, layer) } @Composable @@ -147,7 +156,8 @@ public fun MapVectorImageFeature( image: ImageVector, size: DpSize = DpSize(20.dp, 20.dp), zoomRange: IntRange = defaultZoomRange, -): MapVectorImageFeature = MapVectorImageFeature(position, rememberVectorPainter(image), size, zoomRange) + layer: Int +): MapVectorImageFeature = MapVectorImageFeature(position, rememberVectorPainter(image), size, zoomRange, layer) /** * A group of other features @@ -155,6 +165,7 @@ public fun MapVectorImageFeature( public class MapFeatureGroup( public val children: Map, override val zoomRange: IntRange = defaultZoomRange, + override val layer: Int ) : MapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle? = children.values.mapNotNull { it.getBoundingBox(zoom) }.wrapAll() @@ -166,9 +177,10 @@ public class MapTextFeature( override val zoomRange: IntRange = defaultZoomRange, public val color: Color, public val fontConfig: MapTextFeatureFont.() -> Unit, -) : DraggableMapFeature{ + override val layer: Int +) : DraggableMapFeature { override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position) override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = - MapTextFeature(newCoordinates, text, zoomRange, color, fontConfig) + MapTextFeature(newCoordinates, text, zoomRange, color, fontConfig, layer) } diff --git a/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/MapFeatureBuilder.kt b/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/MapFeatureBuilder.kt index 508385c..4fd13c6 100644 --- a/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/MapFeatureBuilder.kt +++ b/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/MapFeatureBuilder.kt @@ -70,8 +70,9 @@ public fun MapFeatureBuilder.circle( size: Float = 5f, color: Color = Color.Red, id: FeatureId? = null, + layer: Int = 0 ): FeatureId = addFeature( - id, MapCircleFeature(center, zoomRange, size, color) + id, MapCircleFeature(center, zoomRange, size, color, layer) ) public fun MapFeatureBuilder.circle( @@ -80,8 +81,9 @@ public fun MapFeatureBuilder.circle( size: Float = 5f, color: Color = Color.Red, id: FeatureId? = null, + layer: Int = 0 ): FeatureId = addFeature( - id, MapCircleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color) + id, MapCircleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color, layer) ) public fun MapFeatureBuilder.rectangle( @@ -90,16 +92,18 @@ public fun MapFeatureBuilder.rectangle( size: DpSize = DpSize(5.dp, 5.dp), color: Color = Color.Red, id: FeatureId? = null, + layer: Int = 0 ): FeatureId = addFeature( - id, MapRectangleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color) + id, MapRectangleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color, layer) ) public fun MapFeatureBuilder.draw( position: Pair, zoomRange: IntRange = defaultZoomRange, id: FeatureId? = null, - drawFeature: DrawScope.() -> Unit, -): FeatureId = addFeature(id, MapDrawFeature(position.toCoordinates(), zoomRange, drawFeature)) + layer: Int = 0, + drawFeature: DrawScope.() -> Unit +): FeatureId = addFeature(id, MapDrawFeature(position.toCoordinates(), zoomRange, drawFeature, layer)) public fun MapFeatureBuilder.line( aCoordinates: Pair, @@ -107,9 +111,10 @@ public fun MapFeatureBuilder.line( zoomRange: IntRange = defaultZoomRange, color: Color = Color.Red, id: FeatureId? = null, + layer: Int = 0 ): FeatureId = addFeature( id, - MapLineFeature(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), zoomRange, color) + MapLineFeature(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), zoomRange, color, layer) ) public fun MapFeatureBuilder.arc( @@ -119,9 +124,10 @@ public fun MapFeatureBuilder.arc( zoomRange: IntRange = defaultZoomRange, color: Color = Color.Red, id: FeatureId? = null, + layer: Int = 0 ): FeatureId = addFeature( id, - MapArcFeature(oval, startAngle.toFloat(), endAngle.toFloat(), zoomRange, color) + MapArcFeature(oval, startAngle.toFloat(), endAngle.toFloat(), zoomRange, color, layer) ) public fun MapFeatureBuilder.arc( @@ -132,6 +138,7 @@ public fun MapFeatureBuilder.arc( zoomRange: IntRange = defaultZoomRange, color: Color = Color.Red, id: FeatureId? = null, + layer: Int = 0 ): FeatureId = addFeature( id, MapArcFeature( @@ -139,7 +146,8 @@ public fun MapFeatureBuilder.arc( startAngle.toFloat(), endAngle.toFloat(), zoomRange, - color + color, + layer ) ) @@ -150,7 +158,9 @@ public fun MapFeatureBuilder.points( color: Color = Color.Red, pointMode: PointMode = PointMode.Points, id: FeatureId? = null, -): FeatureId = addFeature(id, MapPointsFeature(points.map { it.toCoordinates() }, zoomRange, stroke, color, pointMode)) + layer: Int = 0 +): FeatureId = + addFeature(id, MapPointsFeature(points.map { it.toCoordinates() }, zoomRange, stroke, color, pointMode, layer)) @Composable public fun MapFeatureBuilder.image( @@ -159,15 +169,17 @@ public fun MapFeatureBuilder.image( size: DpSize = DpSize(20.dp, 20.dp), zoomRange: IntRange = defaultZoomRange, id: FeatureId? = null, -): FeatureId = addFeature(id, MapVectorImageFeature(position.toCoordinates(), image, size, zoomRange)) + layer: Int = 0 +): FeatureId = addFeature(id, MapVectorImageFeature(position.toCoordinates(), image, size, zoomRange, layer)) public fun MapFeatureBuilder.group( zoomRange: IntRange = defaultZoomRange, id: FeatureId? = null, - builder: MapFeatureBuilder.() -> Unit, + layer: Int = 0, + builder: MapFeatureBuilder.() -> Unit ): FeatureId { val map = MapFeatureBuilderImpl(mutableStateMapOf()).apply(builder).features - val feature = MapFeatureGroup(map, zoomRange) + val feature = MapFeatureGroup(map, zoomRange, layer) return addFeature(id, feature) } @@ -178,7 +190,8 @@ public fun MapFeatureBuilder.text( color: Color = Color.Red, font: MapTextFeatureFont.() -> Unit = { size = 16f }, id: FeatureId? = null, -): FeatureId = addFeature(id, MapTextFeature(position, text, zoomRange, color, font)) + layer: Int = 0 +): FeatureId = addFeature(id, MapTextFeature(position, text, zoomRange, color, font, layer)) public fun MapFeatureBuilder.text( position: Pair, @@ -187,4 +200,5 @@ public fun MapFeatureBuilder.text( color: Color = Color.Red, font: MapTextFeatureFont.() -> Unit = { size = 16f }, id: FeatureId? = null, -): FeatureId = addFeature(id, MapTextFeature(position.toCoordinates(), text, zoomRange, color, font)) + layer: Int = 0 +): FeatureId = addFeature(id, MapTextFeature(position.toCoordinates(), text, zoomRange, color, font, layer)) diff --git a/maps-kt-compose/src/jvmMain/kotlin/center/sciprog/maps/compose/MapViewJvm.kt b/maps-kt-compose/src/jvmMain/kotlin/center/sciprog/maps/compose/MapViewJvm.kt index b9c195d..88654cc 100644 --- a/maps-kt-compose/src/jvmMain/kotlin/center/sciprog/maps/compose/MapViewJvm.kt +++ b/maps-kt-compose/src/jvmMain/kotlin/center/sciprog/maps/compose/MapViewJvm.kt @@ -351,7 +351,7 @@ public actual fun MapView( dstSize = tileSize ) } - features.values.filter { zoom in it.zoomRange }.forEach { feature -> + features.values.filter { zoom in it.zoomRange }.sortedBy { it.layer }.forEach { feature -> drawFeature(zoom, feature) } }