New attributes
This commit is contained in:
parent
8451cc3aa1
commit
0d9efadcb8
@ -20,7 +20,7 @@ public interface MapFeature {
|
|||||||
|
|
||||||
public val zoomRange: IntRange
|
public val zoomRange: IntRange
|
||||||
|
|
||||||
public val attributes: AttributeMap
|
public var attributes: AttributeMap
|
||||||
|
|
||||||
public fun getBoundingBox(zoom: Double): GmcRectangle?
|
public fun getBoundingBox(zoom: Double): GmcRectangle?
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ internal val defaultZoomRange = 1..18
|
|||||||
* A feature that decides what to show depending on the zoom value (it could change size of shape)
|
* A feature that decides what to show depending on the zoom value (it could change size of shape)
|
||||||
*/
|
*/
|
||||||
public class MapFeatureSelector(
|
public class MapFeatureSelector(
|
||||||
override val attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
public val selector: (zoom: Int) -> MapFeature,
|
public val selector: (zoom: Int) -> MapFeature,
|
||||||
) : MapFeature {
|
) : MapFeature {
|
||||||
override val zoomRange: IntRange get() = defaultZoomRange
|
override val zoomRange: IntRange get() = defaultZoomRange
|
||||||
@ -58,7 +58,7 @@ public class MapFeatureSelector(
|
|||||||
public class MapDrawFeature(
|
public class MapDrawFeature(
|
||||||
public val position: GeodeticMapCoordinates,
|
public val position: GeodeticMapCoordinates,
|
||||||
override val zoomRange: IntRange = defaultZoomRange,
|
override val zoomRange: IntRange = defaultZoomRange,
|
||||||
override val attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
public val drawFeature: DrawScope.() -> Unit,
|
public val drawFeature: DrawScope.() -> Unit,
|
||||||
) : DraggableMapFeature {
|
) : DraggableMapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle {
|
override fun getBoundingBox(zoom: Double): GmcRectangle {
|
||||||
@ -77,7 +77,7 @@ public class MapPathFeature(
|
|||||||
public val style: DrawStyle = Fill,
|
public val style: DrawStyle = Fill,
|
||||||
public val targetRect: Rect = path.getBounds(),
|
public val targetRect: Rect = path.getBounds(),
|
||||||
override val zoomRange: IntRange = defaultZoomRange,
|
override val zoomRange: IntRange = defaultZoomRange,
|
||||||
override val attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableMapFeature {
|
) : DraggableMapFeature {
|
||||||
override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature =
|
override fun withCoordinates(newCoordinates: GeodeticMapCoordinates): MapFeature =
|
||||||
MapPathFeature(rectangle.moveTo(newCoordinates), path, brush, style, targetRect, zoomRange)
|
MapPathFeature(rectangle.moveTo(newCoordinates), path, brush, style, targetRect, zoomRange)
|
||||||
@ -92,7 +92,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 attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : MapFeature {
|
) : MapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(points.first(), points.last())
|
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(points.first(), points.last())
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ public data 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 attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableMapFeature {
|
) : DraggableMapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle {
|
override fun getBoundingBox(zoom: Double): GmcRectangle {
|
||||||
val scale = WebMercatorProjection.scaleFactor(zoom)
|
val scale = WebMercatorProjection.scaleFactor(zoom)
|
||||||
@ -118,7 +118,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 attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableMapFeature {
|
) : DraggableMapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle {
|
override fun getBoundingBox(zoom: Double): GmcRectangle {
|
||||||
val scale = WebMercatorProjection.scaleFactor(zoom)
|
val scale = WebMercatorProjection.scaleFactor(zoom)
|
||||||
@ -134,7 +134,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 attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : SelectableMapFeature {
|
) : SelectableMapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(a, b)
|
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(a, b)
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ public class MapArcFeature(
|
|||||||
public val arcLength: Angle,
|
public val arcLength: Angle,
|
||||||
override val zoomRange: IntRange = defaultZoomRange,
|
override val zoomRange: IntRange = defaultZoomRange,
|
||||||
public val color: Color = Color.Red,
|
public val color: Color = Color.Red,
|
||||||
override val attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableMapFeature {
|
) : DraggableMapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle = oval
|
override fun getBoundingBox(zoom: Double): GmcRectangle = oval
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ 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 attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableMapFeature {
|
) : DraggableMapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position)
|
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position)
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ public class MapVectorImageFeature(
|
|||||||
public val image: ImageVector,
|
public val image: ImageVector,
|
||||||
public val size: DpSize = DpSize(20.dp, 20.dp),
|
public val size: DpSize = DpSize(20.dp, 20.dp),
|
||||||
override val zoomRange: IntRange = defaultZoomRange,
|
override val zoomRange: IntRange = defaultZoomRange,
|
||||||
override val attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : DraggableMapFeature {
|
) : DraggableMapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position)
|
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position)
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ public class 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 attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
) : 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()
|
||||||
@ -207,7 +207,7 @@ public class MapTextFeature(
|
|||||||
public val text: String,
|
public val text: String,
|
||||||
override val zoomRange: IntRange = defaultZoomRange,
|
override val zoomRange: IntRange = defaultZoomRange,
|
||||||
public val color: Color = Color.Black,
|
public val color: Color = Color.Black,
|
||||||
override val attributes: AttributeMap = AttributeMap(),
|
override var attributes: AttributeMap = AttributeMap(),
|
||||||
public val fontConfig: MapTextFeatureFont.() -> Unit,
|
public val fontConfig: MapTextFeatureFont.() -> Unit,
|
||||||
) : DraggableMapFeature {
|
) : DraggableMapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position)
|
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(position, position)
|
||||||
|
@ -18,10 +18,11 @@ import kotlinx.coroutines.launch
|
|||||||
@JvmInline
|
@JvmInline
|
||||||
public value class FeatureId<out MapFeature>(public val id: String)
|
public value class FeatureId<out MapFeature>(public val id: String)
|
||||||
|
|
||||||
public class MapFeaturesState internal constructor(
|
public class MapFeaturesState {
|
||||||
private val featureMap: MutableMap<String, MapFeature>,
|
|
||||||
//@PublishedApi internal val attributeMap: MutableMap<String, SnapshotStateMap<Attribute<out Any?>, in Any?>>,
|
@PublishedApi
|
||||||
) {
|
internal val featureMap: MutableMap<String, MapFeature> = mutableStateMapOf()
|
||||||
|
|
||||||
//TODO use context receiver for that
|
//TODO use context receiver for that
|
||||||
public fun FeatureId<DraggableMapFeature>.draggable(
|
public fun FeatureId<DraggableMapFeature>.draggable(
|
||||||
//TODO add constraints
|
//TODO add constraints
|
||||||
@ -61,7 +62,8 @@ public class MapFeaturesState internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun features(): Map<FeatureId<*>, MapFeature> = featureMap.mapKeys { FeatureId<MapFeature>(it.key) }
|
public val features: Map<FeatureId<*>, MapFeature>
|
||||||
|
get() = featureMap.mapKeys { FeatureId<MapFeature>(it.key) }
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
public fun <T : MapFeature> getFeature(id: FeatureId<T>): T = featureMap[id.id] as T
|
public fun <T : MapFeature> getFeature(id: FeatureId<T>): T = featureMap[id.id] as T
|
||||||
@ -77,18 +79,14 @@ public class MapFeaturesState internal constructor(
|
|||||||
|
|
||||||
public fun <T : MapFeature> feature(id: FeatureId<T>?, feature: T): FeatureId<T> = feature(id?.id, feature)
|
public fun <T : MapFeature> feature(id: FeatureId<T>?, feature: T): FeatureId<T> = feature(id?.id, feature)
|
||||||
|
|
||||||
public fun <T> setAttribute(id: FeatureId<*>, key: MapFeature.Attribute<T>, value: T) {
|
public fun <T> setAttribute(id: FeatureId<MapFeature>, key: MapFeature.Attribute<T>, value: T?) {
|
||||||
feature(id,getFeature(id).at)
|
getFeature(id).attributes.setAttribute(key, value)
|
||||||
attributeMap.getOrPut(id.id) { mutableStateMapOf() }[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun removeAttribute(id: FeatureId<*>, key: MapFeature.Attribute<*>) {
|
|
||||||
attributeMap[id.id]?.remove(key)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
public fun <T> getAttribute(id: FeatureId<*>, key: MapFeature.Attribute<T>): T? =
|
public fun <T> getAttribute(id: FeatureId<MapFeature>, key: MapFeature.Attribute<T>): T? =
|
||||||
attributeMap[id.id]?.get(key)?.let { it as T }
|
getFeature(id).attributes[key]
|
||||||
|
|
||||||
|
|
||||||
// @Suppress("UNCHECKED_CAST")
|
// @Suppress("UNCHECKED_CAST")
|
||||||
// public fun <T> findAllWithAttribute(key: Attribute<T>, condition: (T) -> Boolean): Set<FeatureId> {
|
// public fun <T> findAllWithAttribute(key: Attribute<T>, condition: (T) -> Boolean): Set<FeatureId> {
|
||||||
@ -101,10 +99,9 @@ public class MapFeaturesState internal constructor(
|
|||||||
key: MapFeature.Attribute<T>,
|
key: MapFeature.Attribute<T>,
|
||||||
block: (id: FeatureId<*>, attributeValue: T) -> Unit,
|
block: (id: FeatureId<*>, attributeValue: T) -> Unit,
|
||||||
) {
|
) {
|
||||||
attributeMap.forEach { (id, attributeMap) ->
|
featureMap.forEach { (id, feature) ->
|
||||||
attributeMap[key]?.let {
|
feature.attributes[key]?.let {
|
||||||
@Suppress("UNCHECKED_CAST")
|
block(FeatureId<MapFeature>(id), it)
|
||||||
block(FeatureId<MapFeature>(id), it as T)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,10 +113,7 @@ public class MapFeaturesState internal constructor(
|
|||||||
*/
|
*/
|
||||||
public fun build(
|
public fun build(
|
||||||
builder: MapFeaturesState.() -> Unit = {},
|
builder: MapFeaturesState.() -> Unit = {},
|
||||||
): MapFeaturesState = MapFeaturesState(
|
): MapFeaturesState = MapFeaturesState().apply(builder)
|
||||||
mutableStateMapOf(),
|
|
||||||
mutableStateMapOf()
|
|
||||||
).apply(builder)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build and remember map feature state
|
* Build and remember map feature state
|
||||||
@ -178,8 +172,8 @@ public fun MapFeaturesState.draw(
|
|||||||
position: Pair<Double, Double>,
|
position: Pair<Double, Double>,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
id: String? = null,
|
id: String? = null,
|
||||||
drawFeature: DrawScope.() -> Unit,
|
draw: DrawScope.() -> Unit,
|
||||||
): FeatureId<MapDrawFeature> = feature(id, MapDrawFeature(position.toCoordinates(), zoomRange, drawFeature))
|
): FeatureId<MapDrawFeature> = feature(id, MapDrawFeature(position.toCoordinates(), zoomRange, drawFeature = draw))
|
||||||
|
|
||||||
public fun MapFeaturesState.line(
|
public fun MapFeaturesState.line(
|
||||||
aCoordinates: Gmc,
|
aCoordinates: Gmc,
|
||||||
@ -278,10 +272,7 @@ public fun MapFeaturesState.group(
|
|||||||
id: String? = null,
|
id: String? = null,
|
||||||
builder: MapFeaturesState.() -> Unit,
|
builder: MapFeaturesState.() -> Unit,
|
||||||
): FeatureId<MapFeatureGroup> {
|
): FeatureId<MapFeatureGroup> {
|
||||||
val map = MapFeaturesState(
|
val map = MapFeaturesState().apply(builder).features
|
||||||
mutableStateMapOf(),
|
|
||||||
mutableStateMapOf()
|
|
||||||
).apply(builder).features()
|
|
||||||
val feature = MapFeatureGroup(map, zoomRange)
|
val feature = MapFeatureGroup(map, zoomRange)
|
||||||
return feature(id, feature)
|
return feature(id, feature)
|
||||||
}
|
}
|
||||||
@ -293,7 +284,10 @@ public fun MapFeaturesState.text(
|
|||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
||||||
id: String? = null,
|
id: String? = null,
|
||||||
): FeatureId<MapTextFeature> = feature(id, MapTextFeature(position, text, zoomRange, color, font))
|
): FeatureId<MapTextFeature> = feature(
|
||||||
|
id,
|
||||||
|
MapTextFeature(position, text, zoomRange, color, fontConfig = font)
|
||||||
|
)
|
||||||
|
|
||||||
public fun MapFeaturesState.text(
|
public fun MapFeaturesState.text(
|
||||||
position: Pair<Double, Double>,
|
position: Pair<Double, Double>,
|
||||||
@ -302,4 +296,7 @@ public fun MapFeaturesState.text(
|
|||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
||||||
id: String? = null,
|
id: String? = null,
|
||||||
): FeatureId<MapTextFeature> = feature(id, MapTextFeature(position.toCoordinates(), text, zoomRange, color, font))
|
): FeatureId<MapTextFeature> = feature(
|
||||||
|
id,
|
||||||
|
MapTextFeature(position.toCoordinates(), text, zoomRange, color, fontConfig = font)
|
||||||
|
)
|
||||||
|
@ -136,12 +136,10 @@ public fun MapView(
|
|||||||
) {
|
) {
|
||||||
val featureState = MapFeaturesState.remember(buildFeatures)
|
val featureState = MapFeaturesState.remember(buildFeatures)
|
||||||
|
|
||||||
val features = featureState.features()
|
|
||||||
|
|
||||||
val viewPointOverride: MapViewPoint = remember(initialViewPoint, initialRectangle) {
|
val viewPointOverride: MapViewPoint = remember(initialViewPoint, initialRectangle) {
|
||||||
initialViewPoint
|
initialViewPoint
|
||||||
?: initialRectangle?.computeViewPoint(mapTileProvider)
|
?: initialRectangle?.computeViewPoint(mapTileProvider)
|
||||||
?: features.values.computeBoundingBox(1.0)?.computeViewPoint(mapTileProvider)
|
?: featureState.features.values.computeBoundingBox(1.0)?.computeViewPoint(mapTileProvider)
|
||||||
?: MapViewPoint.globe
|
?: MapViewPoint.globe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package center.sciprog.maps.compose
|
package center.sciprog.maps.compose
|
||||||
|
|
||||||
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
public object DraggableAttribute : MapFeature.Attribute<DragHandle>
|
public object DraggableAttribute : MapFeature.Attribute<DragHandle>
|
||||||
@ -8,16 +9,35 @@ public object VisibleAttribute : MapFeature.Attribute<Boolean>
|
|||||||
|
|
||||||
public object ColorAttribute : MapFeature.Attribute<Color>
|
public object ColorAttribute : MapFeature.Attribute<Color>
|
||||||
|
|
||||||
@JvmInline
|
public class AttributeMap {
|
||||||
public value class AttributeMap internal constructor(private val map: Map<MapFeature.Attribute<*>, *>) {
|
public val map: MutableMap<MapFeature.Attribute<*>, Any> = mutableStateMapOf()
|
||||||
|
|
||||||
public fun <T, A : MapFeature.Attribute<T>> withAttribute(
|
public fun <T, A : MapFeature.Attribute<T>> setAttribute(
|
||||||
attribute: A,
|
attribute: A,
|
||||||
value: T,
|
attrValue: T?,
|
||||||
): AttributeMap = AttributeMap(map + (attribute to value))
|
) {
|
||||||
|
if (attrValue == null) {
|
||||||
|
map.remove(attribute)
|
||||||
|
} else {
|
||||||
|
map[attribute] = attrValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
public operator fun <T> get(attribute: MapFeature.Attribute<T>): T? = map[attribute] as? T
|
public operator fun <T> get(attribute: MapFeature.Attribute<T>): T? = map[attribute] as? T
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as AttributeMap
|
||||||
|
|
||||||
|
if (map != other.map) return false
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun AttributeMap(): AttributeMap = AttributeMap(emptyMap<MapFeature.Attribute<*>, Any?>())
|
override fun hashCode(): Int = map.hashCode()
|
||||||
|
|
||||||
|
override fun toString(): String = "AttributeMap(value=${map.entries})"
|
||||||
|
}
|
@ -214,7 +214,7 @@ public actual fun MapView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val painterCache = key(featuresState) {
|
val painterCache = key(featuresState) {
|
||||||
featuresState.features().values.filterIsInstance<MapVectorImageFeature>().associateWith { it.painter() }
|
featuresState.features.values.filterIsInstance<MapVectorImageFeature>().associateWith { it.painter() }
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas(canvasModifier) {
|
Canvas(canvasModifier) {
|
||||||
@ -349,7 +349,7 @@ public actual fun MapView(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
featuresState.features().values.filter { zoom in it.zoomRange }.forEach { feature ->
|
featuresState.features.values.filter { zoom in it.zoomRange }.forEach { feature ->
|
||||||
drawFeature(zoom, feature)
|
drawFeature(zoom, feature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user