Layers are added to place features below or on top of others

This commit is contained in:
a.kalmakhanov 2022-09-01 15:11:26 +09:00
parent 491a4e6000
commit 5247ce10ab
4 changed files with 56 additions and 27 deletions

View File

@ -87,11 +87,14 @@ fun App() {
centerCoordinates = pointTwo, centerCoordinates = pointTwo,
) )
draw(position = pointThree) { 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)
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) arc(pointOne, Distance(10.0), 0f, PI)
line(pointOne, pointTwo, id = "line") line(pointOne, pointTwo, id = "line")

View File

@ -17,7 +17,7 @@ import kotlin.math.floor
public interface MapFeature { public interface MapFeature {
public val zoomRange: IntRange public val zoomRange: IntRange
public fun getBoundingBox(zoom: Double): GmcRectangle? public fun getBoundingBox(zoom: Double): GmcRectangle?
public val layer: Int
} }
public interface DraggableMapFeature : MapFeature { public interface DraggableMapFeature : MapFeature {
@ -36,6 +36,7 @@ internal val defaultZoomRange = 1..18
*/ */
public class MapFeatureSelector( public class MapFeatureSelector(
public val selector: (zoom: Int) -> MapFeature, public val selector: (zoom: Int) -> MapFeature,
override val layer: Int
) : MapFeature { ) : MapFeature {
override val zoomRange: IntRange get() = defaultZoomRange override val zoomRange: IntRange get() = defaultZoomRange
@ -46,6 +47,7 @@ public class MapDrawFeature(
public val position: GeodeticMapCoordinates, public val position: GeodeticMapCoordinates,
override val zoomRange: IntRange = defaultZoomRange, override val zoomRange: IntRange = defaultZoomRange,
public val drawFeature: DrawScope.() -> Unit, public val drawFeature: DrawScope.() -> Unit,
override val layer: Int
) : DraggableMapFeature { ) : DraggableMapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle { override fun getBoundingBox(zoom: Double): GmcRectangle {
//TODO add box computation //TODO add box computation
@ -53,7 +55,7 @@ public class MapDrawFeature(
} }
override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature =
MapDrawFeature(newCoordinates, zoomRange, drawFeature) MapDrawFeature(newCoordinates, zoomRange, drawFeature, layer)
} }
public class MapPointsFeature( public class MapPointsFeature(
@ -62,6 +64,7 @@ public class MapPointsFeature(
public val stroke: Float = 2f, public val stroke: Float = 2f,
public val color: Color = Color.Red, public val color: Color = Color.Red,
public val pointMode: PointMode = PointMode.Points, public val pointMode: PointMode = PointMode.Points,
override val layer: Int
) : MapFeature { ) : MapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle { override fun getBoundingBox(zoom: Double): GmcRectangle {
return GmcRectangle(points.first(), points.last()) return GmcRectangle(points.first(), points.last())
@ -73,6 +76,7 @@ public class MapCircleFeature(
override val zoomRange: IntRange = defaultZoomRange, override val zoomRange: IntRange = defaultZoomRange,
public val size: Float = 5f, public val size: Float = 5f,
public val color: Color = Color.Red, public val color: Color = Color.Red,
override val layer: Int
) : DraggableMapFeature { ) : DraggableMapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle { override fun getBoundingBox(zoom: Double): GmcRectangle {
val scale = WebMercatorProjection.scaleFactor(zoom) val scale = WebMercatorProjection.scaleFactor(zoom)
@ -80,7 +84,7 @@ public class MapCircleFeature(
} }
override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature =
MapCircleFeature(newCoordinates, zoomRange, size, color) MapCircleFeature(newCoordinates, zoomRange, size, color, layer)
} }
public class MapRectangleFeature( public class MapRectangleFeature(
@ -88,6 +92,7 @@ public class MapRectangleFeature(
override val zoomRange: IntRange = defaultZoomRange, override val zoomRange: IntRange = defaultZoomRange,
public val size: DpSize = DpSize(5.dp, 5.dp), public val size: DpSize = DpSize(5.dp, 5.dp),
public val color: Color = Color.Red, public val color: Color = Color.Red,
override val layer: Int
) : DraggableMapFeature { ) : DraggableMapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle { override fun getBoundingBox(zoom: Double): GmcRectangle {
val scale = WebMercatorProjection.scaleFactor(zoom) val scale = WebMercatorProjection.scaleFactor(zoom)
@ -95,7 +100,7 @@ public class MapRectangleFeature(
} }
override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature =
MapRectangleFeature(newCoordinates, zoomRange, size, color) MapRectangleFeature(newCoordinates, zoomRange, size, color, layer)
} }
public class MapLineFeature( public class MapLineFeature(
@ -103,6 +108,7 @@ public class MapLineFeature(
public val b: GeodeticMapCoordinates, public val b: GeodeticMapCoordinates,
override val zoomRange: IntRange = defaultZoomRange, override val zoomRange: IntRange = defaultZoomRange,
public val color: Color = Color.Red, public val color: Color = Color.Red,
override val layer: Int
) : MapFeature { ) : MapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(a, b) override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(a, b)
} }
@ -113,6 +119,7 @@ public class MapArcFeature(
public val endAngle: Float, public val endAngle: Float,
override val zoomRange: IntRange = defaultZoomRange, override val zoomRange: IntRange = defaultZoomRange,
public val color: Color = Color.Red, public val color: Color = Color.Red,
override val layer: Int
) : MapFeature { ) : MapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle = oval override fun getBoundingBox(zoom: Double): GmcRectangle = oval
} }
@ -122,11 +129,12 @@ public class MapBitmapImageFeature(
public val image: ImageBitmap, public val image: ImageBitmap,
public val size: IntSize = IntSize(15, 15), public val size: IntSize = IntSize(15, 15),
override val zoomRange: IntRange = defaultZoomRange, override val zoomRange: IntRange = defaultZoomRange,
override val layer: Int
) : DraggableMapFeature { ) : DraggableMapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position) override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position)
override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature =
MapBitmapImageFeature(newCoordinates, image, size, zoomRange) MapBitmapImageFeature(newCoordinates, image, size, zoomRange, layer)
} }
public class MapVectorImageFeature( public class MapVectorImageFeature(
@ -134,11 +142,12 @@ public class MapVectorImageFeature(
public val painter: Painter, public val painter: Painter,
public val size: DpSize, public val size: DpSize,
override val zoomRange: IntRange = defaultZoomRange, override val zoomRange: IntRange = defaultZoomRange,
override val layer: Int
) : DraggableMapFeature { ) : DraggableMapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position) override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position)
override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature =
MapVectorImageFeature(newCoordinates,painter, size, zoomRange) MapVectorImageFeature(newCoordinates, painter, size, zoomRange, layer)
} }
@Composable @Composable
@ -147,7 +156,8 @@ public fun MapVectorImageFeature(
image: ImageVector, image: ImageVector,
size: DpSize = DpSize(20.dp, 20.dp), size: DpSize = DpSize(20.dp, 20.dp),
zoomRange: IntRange = defaultZoomRange, 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 * A group of other features
@ -155,6 +165,7 @@ public fun MapVectorImageFeature(
public class MapFeatureGroup( public class MapFeatureGroup(
public val children: Map<FeatureId, MapFeature>, public val children: Map<FeatureId, MapFeature>,
override val zoomRange: IntRange = defaultZoomRange, override val zoomRange: IntRange = defaultZoomRange,
override val layer: Int
) : MapFeature { ) : MapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle? = override fun getBoundingBox(zoom: Double): GmcRectangle? =
children.values.mapNotNull { it.getBoundingBox(zoom) }.wrapAll() children.values.mapNotNull { it.getBoundingBox(zoom) }.wrapAll()
@ -166,9 +177,10 @@ public class MapTextFeature(
override val zoomRange: IntRange = defaultZoomRange, override val zoomRange: IntRange = defaultZoomRange,
public val color: Color, public val color: Color,
public val fontConfig: MapTextFeatureFont.() -> Unit, public val fontConfig: MapTextFeatureFont.() -> Unit,
override val layer: Int
) : DraggableMapFeature { ) : DraggableMapFeature {
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position) override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position)
override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature = override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature =
MapTextFeature(newCoordinates, text, zoomRange, color, fontConfig) MapTextFeature(newCoordinates, text, zoomRange, color, fontConfig, layer)
} }

View File

@ -70,8 +70,9 @@ public fun MapFeatureBuilder.circle(
size: Float = 5f, size: Float = 5f,
color: Color = Color.Red, color: Color = Color.Red,
id: FeatureId? = null, id: FeatureId? = null,
layer: Int = 0
): FeatureId = addFeature( ): FeatureId = addFeature(
id, MapCircleFeature(center, zoomRange, size, color) id, MapCircleFeature(center, zoomRange, size, color, layer)
) )
public fun MapFeatureBuilder.circle( public fun MapFeatureBuilder.circle(
@ -80,8 +81,9 @@ public fun MapFeatureBuilder.circle(
size: Float = 5f, size: Float = 5f,
color: Color = Color.Red, color: Color = Color.Red,
id: FeatureId? = null, id: FeatureId? = null,
layer: Int = 0
): FeatureId = addFeature( ): FeatureId = addFeature(
id, MapCircleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color) id, MapCircleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color, layer)
) )
public fun MapFeatureBuilder.rectangle( public fun MapFeatureBuilder.rectangle(
@ -90,16 +92,18 @@ public fun MapFeatureBuilder.rectangle(
size: DpSize = DpSize(5.dp, 5.dp), size: DpSize = DpSize(5.dp, 5.dp),
color: Color = Color.Red, color: Color = Color.Red,
id: FeatureId? = null, id: FeatureId? = null,
layer: Int = 0
): FeatureId = addFeature( ): FeatureId = addFeature(
id, MapRectangleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color) id, MapRectangleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color, layer)
) )
public fun MapFeatureBuilder.draw( public fun MapFeatureBuilder.draw(
position: Pair<Double, Double>, position: Pair<Double, Double>,
zoomRange: IntRange = defaultZoomRange, zoomRange: IntRange = defaultZoomRange,
id: FeatureId? = null, id: FeatureId? = null,
drawFeature: DrawScope.() -> Unit, layer: Int = 0,
): FeatureId = addFeature(id, MapDrawFeature(position.toCoordinates(), zoomRange, drawFeature)) drawFeature: DrawScope.() -> Unit
): FeatureId = addFeature(id, MapDrawFeature(position.toCoordinates(), zoomRange, drawFeature, layer))
public fun MapFeatureBuilder.line( public fun MapFeatureBuilder.line(
aCoordinates: Pair<Double, Double>, aCoordinates: Pair<Double, Double>,
@ -107,9 +111,10 @@ public fun MapFeatureBuilder.line(
zoomRange: IntRange = defaultZoomRange, zoomRange: IntRange = defaultZoomRange,
color: Color = Color.Red, color: Color = Color.Red,
id: FeatureId? = null, id: FeatureId? = null,
layer: Int = 0
): FeatureId = addFeature( ): FeatureId = addFeature(
id, id,
MapLineFeature(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), zoomRange, color) MapLineFeature(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), zoomRange, color, layer)
) )
public fun MapFeatureBuilder.arc( public fun MapFeatureBuilder.arc(
@ -119,9 +124,10 @@ public fun MapFeatureBuilder.arc(
zoomRange: IntRange = defaultZoomRange, zoomRange: IntRange = defaultZoomRange,
color: Color = Color.Red, color: Color = Color.Red,
id: FeatureId? = null, id: FeatureId? = null,
layer: Int = 0
): FeatureId = addFeature( ): FeatureId = addFeature(
id, id,
MapArcFeature(oval, startAngle.toFloat(), endAngle.toFloat(), zoomRange, color) MapArcFeature(oval, startAngle.toFloat(), endAngle.toFloat(), zoomRange, color, layer)
) )
public fun MapFeatureBuilder.arc( public fun MapFeatureBuilder.arc(
@ -132,6 +138,7 @@ public fun MapFeatureBuilder.arc(
zoomRange: IntRange = defaultZoomRange, zoomRange: IntRange = defaultZoomRange,
color: Color = Color.Red, color: Color = Color.Red,
id: FeatureId? = null, id: FeatureId? = null,
layer: Int = 0
): FeatureId = addFeature( ): FeatureId = addFeature(
id, id,
MapArcFeature( MapArcFeature(
@ -139,7 +146,8 @@ public fun MapFeatureBuilder.arc(
startAngle.toFloat(), startAngle.toFloat(),
endAngle.toFloat(), endAngle.toFloat(),
zoomRange, zoomRange,
color color,
layer
) )
) )
@ -150,7 +158,9 @@ public fun MapFeatureBuilder.points(
color: Color = Color.Red, color: Color = Color.Red,
pointMode: PointMode = PointMode.Points, pointMode: PointMode = PointMode.Points,
id: FeatureId? = null, 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 @Composable
public fun MapFeatureBuilder.image( public fun MapFeatureBuilder.image(
@ -159,15 +169,17 @@ public fun MapFeatureBuilder.image(
size: DpSize = DpSize(20.dp, 20.dp), size: DpSize = DpSize(20.dp, 20.dp),
zoomRange: IntRange = defaultZoomRange, zoomRange: IntRange = defaultZoomRange,
id: FeatureId? = null, 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( public fun MapFeatureBuilder.group(
zoomRange: IntRange = defaultZoomRange, zoomRange: IntRange = defaultZoomRange,
id: FeatureId? = null, id: FeatureId? = null,
builder: MapFeatureBuilder.() -> Unit, layer: Int = 0,
builder: MapFeatureBuilder.() -> Unit
): FeatureId { ): FeatureId {
val map = MapFeatureBuilderImpl(mutableStateMapOf()).apply(builder).features val map = MapFeatureBuilderImpl(mutableStateMapOf()).apply(builder).features
val feature = MapFeatureGroup(map, zoomRange) val feature = MapFeatureGroup(map, zoomRange, layer)
return addFeature(id, feature) return addFeature(id, feature)
} }
@ -178,7 +190,8 @@ public fun MapFeatureBuilder.text(
color: Color = Color.Red, color: Color = Color.Red,
font: MapTextFeatureFont.() -> Unit = { size = 16f }, font: MapTextFeatureFont.() -> Unit = { size = 16f },
id: FeatureId? = null, 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( public fun MapFeatureBuilder.text(
position: Pair<Double, Double>, position: Pair<Double, Double>,
@ -187,4 +200,5 @@ public fun MapFeatureBuilder.text(
color: Color = Color.Red, color: Color = Color.Red,
font: MapTextFeatureFont.() -> Unit = { size = 16f }, font: MapTextFeatureFont.() -> Unit = { size = 16f },
id: FeatureId? = null, 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))

View File

@ -351,7 +351,7 @@ public actual fun MapView(
dstSize = tileSize 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) drawFeature(zoom, feature)
} }
} }