Update schemes to match Maps features
This commit is contained in:
parent
6decba8e83
commit
409d749054
@ -10,7 +10,7 @@ val ktorVersion by extra("2.0.3")
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "center.sciprog"
|
group = "center.sciprog"
|
||||||
version = "0.1.0-dev-7"
|
version = "0.1.0-dev-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
ksciencePublish{
|
ksciencePublish{
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import androidx.compose.desktop.ui.tooling.preview.Preview
|
import androidx.compose.desktop.ui.tooling.preview.Preview
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
@ -17,26 +16,17 @@ import kotlinx.coroutines.launch
|
|||||||
@Preview
|
@Preview
|
||||||
fun App() {
|
fun App() {
|
||||||
MaterialTheme {
|
MaterialTheme {
|
||||||
//create a view point
|
|
||||||
val viewPoint = remember {
|
|
||||||
SchemeViewPoint(
|
|
||||||
SchemeCoordinates(0f, 0f),
|
|
||||||
1f
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
|
||||||
SchemeView(
|
SchemeView(
|
||||||
viewPoint,
|
|
||||||
config = SchemeViewConfig(
|
config = SchemeViewConfig(
|
||||||
inferViewBoxFromFeatures = true,
|
|
||||||
onClick = {
|
onClick = {
|
||||||
println("${focus.x}, ${focus.y}")
|
println("${focus.x}, ${focus.y}")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
background(painterResource("middle-earth.jpg"))
|
background(1600f, 1200f) { painterResource("middle-earth.jpg") }
|
||||||
circle(410.52737 to 868.7676, color = Color.Blue)
|
circle(410.52737 to 868.7676, color = Color.Blue)
|
||||||
text(410.52737 to 868.7676, "Shire", color = Color.Blue)
|
text(410.52737 to 868.7676, "Shire", color = Color.Blue)
|
||||||
circle(1132.0881 to 394.99127, color = Color.Red)
|
circle(1132.0881 to 394.99127, color = Color.Red)
|
||||||
|
@ -216,8 +216,9 @@ public actual fun MapView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val painterCache = featuresState.features().values.filterIsInstance<MapVectorImageFeature>()
|
val painterCache = key(featuresState) {
|
||||||
.associateWith { it.painter() }
|
featuresState.features().values.filterIsInstance<MapVectorImageFeature>().associateWith { it.painter() }
|
||||||
|
}
|
||||||
|
|
||||||
Canvas(canvasModifier) {
|
Canvas(canvasModifier) {
|
||||||
fun WebMercatorCoordinates.toOffset(): Offset = Offset(
|
fun WebMercatorCoordinates.toOffset(): Offset = Offset(
|
||||||
|
@ -1,37 +1,54 @@
|
|||||||
package center.sciprog.maps.scheme
|
package center.sciprog.maps.scheme
|
||||||
|
|
||||||
|
import androidx.compose.ui.unit.DpSize
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
data class SchemeCoordinates(val x: Float, val y: Float)
|
data class SchemeCoordinates(val x: Float, val y: Float)
|
||||||
|
|
||||||
data class SchemeCoordinateBox(
|
data class SchemeRectangle(
|
||||||
val a: SchemeCoordinates,
|
val a: SchemeCoordinates,
|
||||||
val b: SchemeCoordinates,
|
val b: SchemeCoordinates,
|
||||||
)
|
)
|
||||||
|
|
||||||
val SchemeCoordinateBox.top get() = max(a.y, b.y)
|
val SchemeRectangle.top get() = max(a.y, b.y)
|
||||||
val SchemeCoordinateBox.bottom get() = min(a.y, b.y)
|
val SchemeRectangle.bottom get() = min(a.y, b.y)
|
||||||
|
|
||||||
val SchemeCoordinateBox.right get() = max(a.x, b.x)
|
val SchemeRectangle.right get() = max(a.x, b.x)
|
||||||
val SchemeCoordinateBox.left get() = min(a.x, b.x)
|
val SchemeRectangle.left get() = min(a.x, b.x)
|
||||||
|
|
||||||
val SchemeCoordinateBox.width get() = abs(a.x - b.x)
|
val SchemeRectangle.width get() = abs(a.x - b.x)
|
||||||
val SchemeCoordinateBox.height get() = abs(a.y - b.y)
|
val SchemeRectangle.height get() = abs(a.y - b.y)
|
||||||
|
|
||||||
val SchemeCoordinateBox.center get() = SchemeCoordinates((a.x + b.x) / 2, (a.y + b.y) / 2)
|
val SchemeRectangle.center get() = SchemeCoordinates((a.x + b.x) / 2, (a.y + b.y) / 2)
|
||||||
|
|
||||||
|
public val SchemeRectangle.topLeft: SchemeCoordinates get() = SchemeCoordinates(top, left)
|
||||||
|
public val SchemeRectangle.bottomRight: SchemeCoordinates get() = SchemeCoordinates(bottom, right)
|
||||||
|
|
||||||
fun Collection<SchemeCoordinateBox>.wrapAll(): SchemeCoordinateBox? {
|
fun Collection<SchemeRectangle>.wrapAll(): SchemeRectangle? {
|
||||||
if (isEmpty()) return null
|
if (isEmpty()) return null
|
||||||
val minX = minOf { it.left }
|
val minX = minOf { it.left }
|
||||||
val maxX = maxOf { it.right }
|
val maxX = maxOf { it.right }
|
||||||
|
|
||||||
val minY = minOf { it.bottom }
|
val minY = minOf { it.bottom }
|
||||||
val maxY = maxOf { it.top }
|
val maxY = maxOf { it.top }
|
||||||
return SchemeCoordinateBox(
|
return SchemeRectangle(
|
||||||
SchemeCoordinates(minX, minY),
|
SchemeCoordinates(minX, minY),
|
||||||
SchemeCoordinates(maxX, maxY)
|
SchemeCoordinates(maxX, maxY)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val defaultCanvasSize = DpSize(512.dp, 512.dp)
|
||||||
|
|
||||||
|
public fun SchemeRectangle.computeViewPoint(
|
||||||
|
canvasSize: DpSize = defaultCanvasSize,
|
||||||
|
): SchemeViewPoint {
|
||||||
|
val scale = min(
|
||||||
|
canvasSize.width.value / width,
|
||||||
|
canvasSize.height.value / height
|
||||||
|
)
|
||||||
|
|
||||||
|
return SchemeViewPoint(center, scale)
|
||||||
}
|
}
|
@ -15,7 +15,7 @@ import center.sciprog.maps.scheme.SchemeFeature.Companion.defaultScaleRange
|
|||||||
internal typealias FloatRange = ClosedFloatingPointRange<Float>
|
internal typealias FloatRange = ClosedFloatingPointRange<Float>
|
||||||
|
|
||||||
sealed class SchemeFeature(val scaleRange: FloatRange) {
|
sealed class SchemeFeature(val scaleRange: FloatRange) {
|
||||||
abstract fun getBoundingBox(scale: Float): SchemeCoordinateBox?
|
abstract fun getBoundingBox(scale: Float): SchemeRectangle?
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val defaultScaleRange = 0f..Float.MAX_VALUE
|
val defaultScaleRange = 0f..Float.MAX_VALUE
|
||||||
@ -23,27 +23,31 @@ sealed class SchemeFeature(val scaleRange: FloatRange) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun Iterable<SchemeFeature>.computeBoundingBox(scale: Float): SchemeCoordinateBox? =
|
fun Iterable<SchemeFeature>.computeBoundingBox(scale: Float): SchemeRectangle? =
|
||||||
mapNotNull { it.getBoundingBox(scale) }.wrapAll()
|
mapNotNull { it.getBoundingBox(scale) }.wrapAll()
|
||||||
|
|
||||||
|
|
||||||
internal fun Pair<Number, Number>.toCoordinates() = SchemeCoordinates(first.toFloat(), second.toFloat())
|
internal fun Pair<Number, Number>.toCoordinates() = SchemeCoordinates(first.toFloat(), second.toFloat())
|
||||||
|
|
||||||
|
interface PainterFeature {
|
||||||
|
val painter: @Composable () -> Painter
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A background image that is bound to scheme coordinates and is scaled together with them
|
* A background image that is bound to scheme coordinates and is scaled together with them
|
||||||
*
|
*
|
||||||
* @param position the size of background in scheme size units. The screen units to scheme units ratio equals scale.
|
* @param rectangle the size of background in scheme size units. The screen units to scheme units ratio equals scale.
|
||||||
*/
|
*/
|
||||||
class SchemeBackgroundFeature(
|
class SchemeBackgroundFeature(
|
||||||
val position: SchemeCoordinateBox,
|
val rectangle: SchemeRectangle,
|
||||||
val painter: Painter,
|
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
) : SchemeFeature(scaleRange) {
|
override val painter: @Composable () -> Painter,
|
||||||
override fun getBoundingBox(scale: Float): SchemeCoordinateBox = position
|
) : SchemeFeature(scaleRange), PainterFeature {
|
||||||
|
override fun getBoundingBox(scale: Float): SchemeRectangle = rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
class SchemeFeatureSelector(val selector: (scale: Float) -> SchemeFeature) : SchemeFeature(defaultScaleRange) {
|
class SchemeFeatureSelector(val selector: (scale: Float) -> SchemeFeature) : SchemeFeature(defaultScaleRange) {
|
||||||
override fun getBoundingBox(scale: Float): SchemeCoordinateBox? = selector(scale).getBoundingBox(scale)
|
override fun getBoundingBox(scale: Float): SchemeRectangle? = selector(scale).getBoundingBox(scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SchemeDrawFeature(
|
class SchemeDrawFeature(
|
||||||
@ -51,7 +55,7 @@ class SchemeDrawFeature(
|
|||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
val drawFeature: DrawScope.() -> Unit,
|
val drawFeature: DrawScope.() -> Unit,
|
||||||
) : SchemeFeature(scaleRange) {
|
) : SchemeFeature(scaleRange) {
|
||||||
override fun getBoundingBox(scale: Float): SchemeCoordinateBox = SchemeCoordinateBox(position, position)
|
override fun getBoundingBox(scale: Float): SchemeRectangle = SchemeRectangle(position, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SchemeCircleFeature(
|
class SchemeCircleFeature(
|
||||||
@ -60,7 +64,7 @@ class SchemeCircleFeature(
|
|||||||
val size: Float = 5f,
|
val size: Float = 5f,
|
||||||
val color: Color = Color.Red,
|
val color: Color = Color.Red,
|
||||||
) : SchemeFeature(scaleRange) {
|
) : SchemeFeature(scaleRange) {
|
||||||
override fun getBoundingBox(scale: Float): SchemeCoordinateBox = SchemeCoordinateBox(center, center)
|
override fun getBoundingBox(scale: Float): SchemeRectangle = SchemeRectangle(center, center)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SchemeLineFeature(
|
class SchemeLineFeature(
|
||||||
@ -69,7 +73,21 @@ class SchemeLineFeature(
|
|||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
val color: Color = Color.Red,
|
val color: Color = Color.Red,
|
||||||
) : SchemeFeature(scaleRange) {
|
) : SchemeFeature(scaleRange) {
|
||||||
override fun getBoundingBox(scale: Float): SchemeCoordinateBox = SchemeCoordinateBox(a, b)
|
override fun getBoundingBox(scale: Float): SchemeRectangle = SchemeRectangle(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param startAngle the angle in radians from parallel downwards for the start of the arc
|
||||||
|
* @param arcLength arc length in radians
|
||||||
|
*/
|
||||||
|
public class SchemeArcFeature(
|
||||||
|
public val oval: SchemeRectangle,
|
||||||
|
public val startAngle: Float,
|
||||||
|
public val arcLength: Float,
|
||||||
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
|
public val color: Color = Color.Red,
|
||||||
|
) : SchemeFeature(scaleRange) {
|
||||||
|
override fun getBoundingBox(scale: Float): SchemeRectangle = oval
|
||||||
}
|
}
|
||||||
|
|
||||||
class SchemeTextFeature(
|
class SchemeTextFeature(
|
||||||
@ -78,7 +96,7 @@ class SchemeTextFeature(
|
|||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
val color: Color = Color.Red,
|
val color: Color = Color.Red,
|
||||||
) : SchemeFeature(scaleRange) {
|
) : SchemeFeature(scaleRange) {
|
||||||
override fun getBoundingBox(scale: Float): SchemeCoordinateBox = SchemeCoordinateBox(position, position)
|
override fun getBoundingBox(scale: Float): SchemeRectangle = SchemeRectangle(position, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SchemeBitmapFeature(
|
class SchemeBitmapFeature(
|
||||||
@ -87,25 +105,24 @@ class SchemeBitmapFeature(
|
|||||||
val size: IntSize = IntSize(15, 15),
|
val size: IntSize = IntSize(15, 15),
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
) : SchemeFeature(scaleRange) {
|
) : SchemeFeature(scaleRange) {
|
||||||
override fun getBoundingBox(scale: Float): SchemeCoordinateBox = SchemeCoordinateBox(position, position)
|
override fun getBoundingBox(scale: Float): SchemeRectangle = SchemeRectangle(position, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
class SchemeImageFeature(
|
class SchemeImageFeature(
|
||||||
val position: SchemeCoordinates,
|
val position: SchemeCoordinates,
|
||||||
val painter: Painter,
|
|
||||||
val size: DpSize,
|
val size: DpSize,
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
) : SchemeFeature(scaleRange) {
|
override val painter: @Composable () -> Painter,
|
||||||
override fun getBoundingBox(scale: Float): SchemeCoordinateBox = SchemeCoordinateBox(position, position)
|
) : SchemeFeature(scaleRange), PainterFeature {
|
||||||
|
override fun getBoundingBox(scale: Float): SchemeRectangle = SchemeRectangle(position, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
fun SchemeImageFeature(
|
||||||
fun SchemeVectorImageFeature(
|
|
||||||
position: SchemeCoordinates,
|
position: SchemeCoordinates,
|
||||||
image: ImageVector,
|
image: ImageVector,
|
||||||
size: DpSize = DpSize(20.dp, 20.dp),
|
size: DpSize = DpSize(20.dp, 20.dp),
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
): SchemeImageFeature = SchemeImageFeature(position, rememberVectorPainter(image), size, scaleRange)
|
): SchemeImageFeature = SchemeImageFeature(position, size, scaleRange) { rememberVectorPainter(image) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A group of other features
|
* A group of other features
|
||||||
@ -114,6 +131,6 @@ class SchemeFeatureGroup(
|
|||||||
val children: Map<FeatureId, SchemeFeature>,
|
val children: Map<FeatureId, SchemeFeature>,
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
) : SchemeFeature(scaleRange) {
|
) : SchemeFeature(scaleRange) {
|
||||||
override fun getBoundingBox(scale: Float): SchemeCoordinateBox? =
|
override fun getBoundingBox(scale: Float): SchemeRectangle? =
|
||||||
children.values.mapNotNull { it.getBoundingBox(scale) }.wrapAll()
|
children.values.mapNotNull { it.getBoundingBox(scale) }.wrapAll()
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package center.sciprog.maps.scheme
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.mutableStateMapOf
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
import androidx.compose.runtime.snapshots.SnapshotStateMap
|
||||||
import androidx.compose.ui.geometry.Size
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.drawscope.DrawScope
|
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
@ -14,55 +13,88 @@ import center.sciprog.maps.scheme.SchemeFeature.Companion.defaultScaleRange
|
|||||||
|
|
||||||
typealias FeatureId = String
|
typealias FeatureId = String
|
||||||
|
|
||||||
interface SchemeFeatureBuilder {
|
|
||||||
fun addFeature(id: FeatureId?, feature: SchemeFeature): FeatureId
|
|
||||||
|
|
||||||
fun build(): SnapshotStateMap<FeatureId, SchemeFeature>
|
public class SchemeFeaturesState internal constructor(
|
||||||
}
|
private val features: MutableMap<FeatureId, SchemeFeature>,
|
||||||
|
private val attributes: MutableMap<FeatureId, SnapshotStateMap<Attribute<out Any?>, in Any?>>,
|
||||||
|
) {
|
||||||
|
public interface Attribute<T>
|
||||||
|
|
||||||
internal class SchemeFeatureBuilderImpl(
|
public fun features(): Map<FeatureId, SchemeFeature> = features
|
||||||
initialFeatures: Map<FeatureId, SchemeFeature>,
|
|
||||||
) : SchemeFeatureBuilder {
|
|
||||||
|
|
||||||
private val content: SnapshotStateMap<FeatureId, SchemeFeature> =
|
|
||||||
mutableStateMapOf<FeatureId, SchemeFeature>().apply {
|
|
||||||
putAll(initialFeatures)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateID(feature: SchemeFeature): FeatureId = "@feature[${feature.hashCode().toUInt()}]"
|
private fun generateID(feature: SchemeFeature): FeatureId = "@feature[${feature.hashCode().toUInt()}]"
|
||||||
|
|
||||||
override fun addFeature(id: FeatureId?, feature: SchemeFeature): FeatureId {
|
public fun addFeature(id: FeatureId?, feature: SchemeFeature): FeatureId {
|
||||||
val safeId = id ?: generateID(feature)
|
val safeId = id ?: generateID(feature)
|
||||||
content[id ?: generateID(feature)] = feature
|
features[id ?: generateID(feature)] = feature
|
||||||
return safeId
|
return safeId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(): SnapshotStateMap<FeatureId, SchemeFeature> = content
|
public fun <T> setAttribute(id: FeatureId, key: Attribute<T>, value: T) {
|
||||||
|
attributes.getOrPut(id) { mutableStateMapOf() }[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
public fun <T> getAttribute(id: FeatureId, key: Attribute<T>): T? =
|
||||||
|
attributes[id]?.get(key)?.let { it as T }
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
public fun <T> findAllWithAttribute(key: Attribute<T>, condition: (T) -> Boolean): Set<FeatureId> {
|
||||||
|
return attributes.filterValues {
|
||||||
|
condition(it[key] as T)
|
||||||
|
}.keys
|
||||||
|
}
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build, but do not remember map feature state
|
||||||
|
*/
|
||||||
|
public fun build(
|
||||||
|
builder: SchemeFeaturesState.() -> Unit = {},
|
||||||
|
): SchemeFeaturesState = SchemeFeaturesState(
|
||||||
|
mutableStateMapOf(),
|
||||||
|
mutableStateMapOf()
|
||||||
|
).apply(builder)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build and remember map feature state
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
public fun remember(
|
||||||
|
builder: SchemeFeaturesState.() -> Unit = {},
|
||||||
|
): SchemeFeaturesState = androidx.compose.runtime.remember(builder) {
|
||||||
|
build(builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SchemeFeatureBuilder.background(
|
fun SchemeFeaturesState.background(
|
||||||
painter: Painter,
|
box: SchemeRectangle,
|
||||||
box: SchemeCoordinateBox,
|
|
||||||
id: FeatureId? = null,
|
id: FeatureId? = null,
|
||||||
|
painter: @Composable () -> Painter,
|
||||||
): FeatureId = addFeature(
|
): FeatureId = addFeature(
|
||||||
id,
|
id,
|
||||||
SchemeBackgroundFeature(box, painter)
|
SchemeBackgroundFeature(box, painter = painter)
|
||||||
)
|
)
|
||||||
|
|
||||||
fun SchemeFeatureBuilder.background(
|
fun SchemeFeaturesState.background(
|
||||||
painter: Painter,
|
width: Float,
|
||||||
size: Size = painter.intrinsicSize,
|
height: Float,
|
||||||
offset: SchemeCoordinates = SchemeCoordinates(0f, 0f),
|
offset: SchemeCoordinates = SchemeCoordinates(0f, 0f),
|
||||||
id: FeatureId? = null,
|
id: FeatureId? = null,
|
||||||
|
painter: @Composable () -> Painter,
|
||||||
): FeatureId {
|
): FeatureId {
|
||||||
val box = SchemeCoordinateBox(
|
val box = SchemeRectangle(
|
||||||
offset,
|
offset,
|
||||||
SchemeCoordinates(size.width + offset.x, size.height + offset.y)
|
SchemeCoordinates(width + offset.x, height + offset.y)
|
||||||
)
|
)
|
||||||
return background(painter, box, id)
|
return background(box, id, painter = painter)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SchemeFeatureBuilder.circle(
|
fun SchemeFeaturesState.circle(
|
||||||
center: SchemeCoordinates,
|
center: SchemeCoordinates,
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
size: Float = 5f,
|
size: Float = 5f,
|
||||||
@ -72,7 +104,7 @@ fun SchemeFeatureBuilder.circle(
|
|||||||
id, SchemeCircleFeature(center, scaleRange, size, color)
|
id, SchemeCircleFeature(center, scaleRange, size, color)
|
||||||
)
|
)
|
||||||
|
|
||||||
fun SchemeFeatureBuilder.circle(
|
fun SchemeFeaturesState.circle(
|
||||||
centerCoordinates: Pair<Number, Number>,
|
centerCoordinates: Pair<Number, Number>,
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
size: Float = 5f,
|
size: Float = 5f,
|
||||||
@ -82,14 +114,14 @@ fun SchemeFeatureBuilder.circle(
|
|||||||
id, SchemeCircleFeature(centerCoordinates.toCoordinates(), scaleRange, size, color)
|
id, SchemeCircleFeature(centerCoordinates.toCoordinates(), scaleRange, size, color)
|
||||||
)
|
)
|
||||||
|
|
||||||
fun SchemeFeatureBuilder.draw(
|
fun SchemeFeaturesState.draw(
|
||||||
position: Pair<Number, Number>,
|
position: Pair<Number, Number>,
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
id: FeatureId? = null,
|
id: FeatureId? = null,
|
||||||
drawFeature: DrawScope.() -> Unit,
|
drawFeature: DrawScope.() -> Unit,
|
||||||
) = addFeature(id, SchemeDrawFeature(position.toCoordinates(), scaleRange, drawFeature))
|
) = addFeature(id, SchemeDrawFeature(position.toCoordinates(), scaleRange, drawFeature))
|
||||||
|
|
||||||
fun SchemeFeatureBuilder.line(
|
fun SchemeFeaturesState.line(
|
||||||
aCoordinates: Pair<Number, Number>,
|
aCoordinates: Pair<Number, Number>,
|
||||||
bCoordinates: Pair<Number, Number>,
|
bCoordinates: Pair<Number, Number>,
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
@ -97,7 +129,7 @@ fun SchemeFeatureBuilder.line(
|
|||||||
id: FeatureId? = null,
|
id: FeatureId? = null,
|
||||||
) = addFeature(id, SchemeLineFeature(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), scaleRange, color))
|
) = addFeature(id, SchemeLineFeature(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), scaleRange, color))
|
||||||
|
|
||||||
fun SchemeFeatureBuilder.text(
|
fun SchemeFeaturesState.text(
|
||||||
position: SchemeCoordinates,
|
position: SchemeCoordinates,
|
||||||
text: String,
|
text: String,
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
@ -105,7 +137,7 @@ fun SchemeFeatureBuilder.text(
|
|||||||
id: FeatureId? = null,
|
id: FeatureId? = null,
|
||||||
) = addFeature(id, SchemeTextFeature(position, text, scaleRange, color))
|
) = addFeature(id, SchemeTextFeature(position, text, scaleRange, color))
|
||||||
|
|
||||||
fun SchemeFeatureBuilder.text(
|
fun SchemeFeaturesState.text(
|
||||||
position: Pair<Number, Number>,
|
position: Pair<Number, Number>,
|
||||||
text: String,
|
text: String,
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
@ -113,21 +145,20 @@ fun SchemeFeatureBuilder.text(
|
|||||||
id: FeatureId? = null,
|
id: FeatureId? = null,
|
||||||
) = addFeature(id, SchemeTextFeature(position.toCoordinates(), text, scaleRange, color))
|
) = addFeature(id, SchemeTextFeature(position.toCoordinates(), text, scaleRange, color))
|
||||||
|
|
||||||
@Composable
|
fun SchemeFeaturesState.image(
|
||||||
fun SchemeFeatureBuilder.image(
|
|
||||||
position: Pair<Number, Number>,
|
position: Pair<Number, Number>,
|
||||||
image: ImageVector,
|
image: ImageVector,
|
||||||
size: DpSize = DpSize(20.dp, 20.dp),
|
size: DpSize = DpSize(20.dp, 20.dp),
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
id: FeatureId? = null,
|
id: FeatureId? = null,
|
||||||
) = addFeature(id, SchemeVectorImageFeature(position.toCoordinates(), image, size, scaleRange))
|
) = addFeature(id, SchemeImageFeature(position.toCoordinates(), image, size, scaleRange))
|
||||||
|
|
||||||
fun SchemeFeatureBuilder.group(
|
fun SchemeFeaturesState.group(
|
||||||
scaleRange: FloatRange = defaultScaleRange,
|
scaleRange: FloatRange = defaultScaleRange,
|
||||||
id: FeatureId? = null,
|
id: FeatureId? = null,
|
||||||
builder: SchemeFeatureBuilder.() -> Unit,
|
builder: SchemeFeaturesState.() -> Unit,
|
||||||
): FeatureId {
|
): FeatureId {
|
||||||
val map = SchemeFeatureBuilderImpl(emptyMap()).apply(builder).build()
|
val groupBuilder = SchemeFeaturesState.build(builder)
|
||||||
val feature = SchemeFeatureGroup(map, scaleRange)
|
val feature = SchemeFeatureGroup(groupBuilder.features(), scaleRange)
|
||||||
return addFeature(id, feature)
|
return addFeature(id, feature)
|
||||||
}
|
}
|
@ -9,11 +9,8 @@ import androidx.compose.ui.ExperimentalComposeUiApi
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.geometry.Rect
|
import androidx.compose.ui.geometry.Rect
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.*
|
||||||
import androidx.compose.ui.graphics.PathEffect
|
|
||||||
import androidx.compose.ui.graphics.drawscope.*
|
import androidx.compose.ui.graphics.drawscope.*
|
||||||
import androidx.compose.ui.graphics.nativeCanvas
|
|
||||||
import androidx.compose.ui.graphics.toArgb
|
|
||||||
import androidx.compose.ui.input.pointer.*
|
import androidx.compose.ui.input.pointer.*
|
||||||
import androidx.compose.ui.unit.DpOffset
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.DpSize
|
import androidx.compose.ui.unit.DpSize
|
||||||
@ -36,40 +33,29 @@ private val logger = KotlinLogging.logger("SchemeView")
|
|||||||
|
|
||||||
data class SchemeViewConfig(
|
data class SchemeViewConfig(
|
||||||
val zoomSpeed: Float = 1f / 3f,
|
val zoomSpeed: Float = 1f / 3f,
|
||||||
val inferViewBoxFromFeatures: Boolean = false,
|
|
||||||
val onClick: SchemeViewPoint.() -> Unit = {},
|
val onClick: SchemeViewPoint.() -> Unit = {},
|
||||||
val onViewChange: SchemeViewPoint.() -> Unit = {},
|
val onViewChange: SchemeViewPoint.() -> Unit = {},
|
||||||
val onSelect: (SchemeCoordinateBox) -> Unit = {},
|
val onSelect: (SchemeRectangle) -> Unit = {},
|
||||||
val zoomOnSelect: Boolean = true,
|
val zoomOnSelect: Boolean = true,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
public fun SchemeView(
|
public fun SchemeView(
|
||||||
computeViewPoint: (canvasSize: DpSize) -> SchemeViewPoint,
|
initialViewPoint: SchemeViewPoint,
|
||||||
features: Map<FeatureId, SchemeFeature>,
|
featuresState: SchemeFeaturesState,
|
||||||
config: SchemeViewConfig = SchemeViewConfig(),
|
config: SchemeViewConfig = SchemeViewConfig(),
|
||||||
modifier: Modifier = Modifier.fillMaxSize(),
|
modifier: Modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
|
var canvasSize by remember { mutableStateOf(defaultCanvasSize) }
|
||||||
|
|
||||||
var canvasSize by remember { mutableStateOf(DpSize(512.dp, 512.dp)) }
|
var viewPoint by remember { mutableStateOf(initialViewPoint) }
|
||||||
|
|
||||||
var viewPointInternal: SchemeViewPoint? by remember {
|
|
||||||
mutableStateOf(null)
|
fun setViewPoint(newViewPoint: SchemeViewPoint) {
|
||||||
|
config.onViewChange(newViewPoint)
|
||||||
|
viewPoint = newViewPoint
|
||||||
}
|
}
|
||||||
|
|
||||||
val viewPoint: SchemeViewPoint by derivedStateOf {
|
|
||||||
viewPointInternal ?: if (config.inferViewBoxFromFeatures) {
|
|
||||||
features.values.computeBoundingBox(1f)?.let { box ->
|
|
||||||
val scale = min(
|
|
||||||
canvasSize.width.value / box.width,
|
|
||||||
canvasSize.height.value / box.height
|
|
||||||
)
|
|
||||||
SchemeViewPoint(box.center, scale)
|
|
||||||
} ?: computeViewPoint(canvasSize)
|
|
||||||
} else {
|
|
||||||
computeViewPoint(canvasSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun DpOffset.toCoordinates(): SchemeCoordinates = SchemeCoordinates(
|
fun DpOffset.toCoordinates(): SchemeCoordinates = SchemeCoordinates(
|
||||||
(x - canvasSize.width / 2).value / viewPoint.scale + viewPoint.focus.x,
|
(x - canvasSize.width / 2).value / viewPoint.scale + viewPoint.focus.x,
|
||||||
@ -104,7 +90,7 @@ public fun SchemeView(
|
|||||||
}
|
}
|
||||||
selectRect?.let { rect ->
|
selectRect?.let { rect ->
|
||||||
//Use selection override if it is defined
|
//Use selection override if it is defined
|
||||||
val box = SchemeCoordinateBox(
|
val box = SchemeRectangle(
|
||||||
rect.topLeft.toDpOffset().toCoordinates(),
|
rect.topLeft.toDpOffset().toCoordinates(),
|
||||||
rect.bottomRight.toDpOffset().toCoordinates()
|
rect.bottomRight.toDpOffset().toCoordinates()
|
||||||
)
|
)
|
||||||
@ -117,8 +103,7 @@ public fun SchemeView(
|
|||||||
|
|
||||||
val newViewPoint = SchemeViewPoint(box.center, newScale)
|
val newViewPoint = SchemeViewPoint(box.center, newScale)
|
||||||
|
|
||||||
config.onViewChange(newViewPoint)
|
setViewPoint(newViewPoint)
|
||||||
viewPointInternal = newViewPoint
|
|
||||||
}
|
}
|
||||||
selectRect = null
|
selectRect = null
|
||||||
}
|
}
|
||||||
@ -132,8 +117,7 @@ public fun SchemeView(
|
|||||||
-dragAmount.x.toDp().value / viewPoint.scale,
|
-dragAmount.x.toDp().value / viewPoint.scale,
|
||||||
dragAmount.y.toDp().value / viewPoint.scale
|
dragAmount.y.toDp().value / viewPoint.scale
|
||||||
)
|
)
|
||||||
config.onViewChange(newViewPoint)
|
setViewPoint(newViewPoint)
|
||||||
viewPointInternal = newViewPoint
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,10 +130,13 @@ public fun SchemeView(
|
|||||||
//compute invariant point of translation
|
//compute invariant point of translation
|
||||||
val invariant = DpOffset(xPos.toDp(), yPos.toDp()).toCoordinates()
|
val invariant = DpOffset(xPos.toDp(), yPos.toDp()).toCoordinates()
|
||||||
val newViewPoint = viewPoint.zoom(-change.scrollDelta.y * config.zoomSpeed, invariant)
|
val newViewPoint = viewPoint.zoom(-change.scrollDelta.y * config.zoomSpeed, invariant)
|
||||||
config.onViewChange(newViewPoint)
|
setViewPoint(newViewPoint)
|
||||||
viewPointInternal = newViewPoint
|
|
||||||
}.fillMaxSize()
|
}.fillMaxSize()
|
||||||
|
|
||||||
|
val painterCache = key(featuresState){
|
||||||
|
featuresState.features().values.filterIsInstance<PainterFeature>().associateWith { it.painter() }
|
||||||
|
}
|
||||||
|
|
||||||
Canvas(canvasModifier) {
|
Canvas(canvasModifier) {
|
||||||
fun SchemeCoordinates.toOffset(): Offset = Offset(
|
fun SchemeCoordinates.toOffset(): Offset = Offset(
|
||||||
(canvasSize.width / 2 + (x.dp - viewPoint.focus.x.dp) * viewPoint.scale).toPx(),
|
(canvasSize.width / 2 + (x.dp - viewPoint.focus.x.dp) * viewPoint.scale).toPx(),
|
||||||
@ -160,36 +147,55 @@ public fun SchemeView(
|
|||||||
fun DrawScope.drawFeature(scale: Float, feature: SchemeFeature) {
|
fun DrawScope.drawFeature(scale: Float, feature: SchemeFeature) {
|
||||||
when (feature) {
|
when (feature) {
|
||||||
is SchemeBackgroundFeature -> {
|
is SchemeBackgroundFeature -> {
|
||||||
val offset = SchemeCoordinates(feature.position.left, feature.position.top).toOffset()
|
val offset = SchemeCoordinates(feature.rectangle.left, feature.rectangle.top).toOffset()
|
||||||
|
|
||||||
val backgroundSize = DpSize(
|
val backgroundSize = DpSize(
|
||||||
(feature.position.width * scale).dp,
|
(feature.rectangle.width * scale).dp,
|
||||||
(feature.position.height * scale).dp
|
(feature.rectangle.height * scale).dp
|
||||||
).toSize()
|
).toSize()
|
||||||
|
|
||||||
translate(offset.x, offset.y) {
|
translate(offset.x, offset.y) {
|
||||||
with(feature.painter) {
|
with(painterCache[feature]!!) {
|
||||||
draw(backgroundSize)
|
draw(backgroundSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is SchemeFeatureSelector -> drawFeature(scale, feature.selector(scale))
|
is SchemeFeatureSelector -> drawFeature(scale, feature.selector(scale))
|
||||||
is SchemeCircleFeature -> drawCircle(
|
is SchemeCircleFeature -> drawCircle(
|
||||||
feature.color,
|
feature.color,
|
||||||
feature.size,
|
feature.size,
|
||||||
center = feature.center.toOffset()
|
center = feature.center.toOffset()
|
||||||
)
|
)
|
||||||
|
|
||||||
is SchemeLineFeature -> drawLine(feature.color, feature.a.toOffset(), feature.b.toOffset())
|
is SchemeLineFeature -> drawLine(feature.color, feature.a.toOffset(), feature.b.toOffset())
|
||||||
|
is SchemeArcFeature -> {
|
||||||
|
val topLeft = feature.oval.topLeft.toOffset()
|
||||||
|
val bottomRight = feature.oval.bottomRight.toOffset()
|
||||||
|
|
||||||
|
val path = Path().apply {
|
||||||
|
addArcRad(
|
||||||
|
Rect(topLeft, bottomRight),
|
||||||
|
feature.startAngle,
|
||||||
|
feature.arcLength
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
drawPath(path, color = feature.color, style = Stroke())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
is SchemeBitmapFeature -> drawImage(feature.image, feature.position.toOffset())
|
is SchemeBitmapFeature -> drawImage(feature.image, feature.position.toOffset())
|
||||||
is SchemeImageFeature -> {
|
is SchemeImageFeature -> {
|
||||||
val offset = feature.position.toOffset()
|
val offset = feature.position.toOffset()
|
||||||
val imageSize = feature.size.toSize()
|
val imageSize = feature.size.toSize()
|
||||||
translate(offset.x - imageSize.width / 2, offset.y - imageSize.height / 2) {
|
translate(offset.x - imageSize.width / 2, offset.y - imageSize.height / 2) {
|
||||||
with(feature.painter) {
|
with(painterCache[feature]!!) {
|
||||||
draw(imageSize)
|
draw(imageSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is SchemeTextFeature -> drawIntoCanvas { canvas ->
|
is SchemeTextFeature -> drawIntoCanvas { canvas ->
|
||||||
val offset = feature.position.toOffset()
|
val offset = feature.position.toOffset()
|
||||||
canvas.nativeCanvas.drawString(
|
canvas.nativeCanvas.drawString(
|
||||||
@ -200,12 +206,14 @@ public fun SchemeView(
|
|||||||
feature.color.toPaint()
|
feature.color.toPaint()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is SchemeDrawFeature -> {
|
is SchemeDrawFeature -> {
|
||||||
val offset = feature.position.toOffset()
|
val offset = feature.position.toOffset()
|
||||||
translate(offset.x, offset.y) {
|
translate(offset.x, offset.y) {
|
||||||
feature.drawFeature(this)
|
feature.drawFeature(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is SchemeFeatureGroup -> {
|
is SchemeFeatureGroup -> {
|
||||||
feature.children.values.forEach {
|
feature.children.values.forEach {
|
||||||
drawFeature(scale, it)
|
drawFeature(scale, it)
|
||||||
@ -219,10 +227,10 @@ public fun SchemeView(
|
|||||||
logger.debug { "Recalculate canvas. Size: $size" }
|
logger.debug { "Recalculate canvas. Size: $size" }
|
||||||
}
|
}
|
||||||
clipRect {
|
clipRect {
|
||||||
features.values.filterIsInstance<SchemeBackgroundFeature>().forEach { background ->
|
featuresState.features().values.filterIsInstance<SchemeBackgroundFeature>().forEach { background ->
|
||||||
drawFeature(viewPoint.scale, background)
|
drawFeature(viewPoint.scale, background)
|
||||||
}
|
}
|
||||||
features.values.filter {
|
featuresState.features().values.filter {
|
||||||
it !is SchemeBackgroundFeature && viewPoint.scale in it.scaleRange
|
it !is SchemeBackgroundFeature && viewPoint.scale in it.scaleRange
|
||||||
}.forEach { feature ->
|
}.forEach { feature ->
|
||||||
drawFeature(viewPoint.scale, feature)
|
drawFeature(viewPoint.scale, feature)
|
||||||
@ -243,20 +251,82 @@ public fun SchemeView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for a Scheme with static features.
|
||||||
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun SchemeView(
|
public fun SchemeView(
|
||||||
initialViewPoint: SchemeViewPoint,
|
initialViewPoint: SchemeViewPoint? = null,
|
||||||
features: Map<FeatureId, SchemeFeature> = emptyMap(),
|
initialRectangle: SchemeRectangle? = null,
|
||||||
|
featureMap: Map<FeatureId, SchemeFeature>,
|
||||||
config: SchemeViewConfig = SchemeViewConfig(),
|
config: SchemeViewConfig = SchemeViewConfig(),
|
||||||
modifier: Modifier = Modifier.fillMaxSize(),
|
modifier: Modifier = Modifier.fillMaxSize(),
|
||||||
buildFeatures: @Composable (SchemeFeatureBuilder.() -> Unit) = {},
|
|
||||||
) {
|
) {
|
||||||
val featuresBuilder = SchemeFeatureBuilderImpl(features)
|
val featuresState = key(featureMap) {
|
||||||
featuresBuilder.buildFeatures()
|
SchemeFeaturesState.build {
|
||||||
|
featureMap.forEach(::addFeature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val viewPointOverride: SchemeViewPoint = remember(initialViewPoint, initialRectangle) {
|
||||||
|
initialViewPoint
|
||||||
|
?: initialRectangle?.computeViewPoint()
|
||||||
|
?: featureMap.values.computeBoundingBox(1f)?.computeViewPoint()
|
||||||
|
?: SchemeViewPoint(SchemeCoordinates(0f, 0f))
|
||||||
|
}
|
||||||
|
|
||||||
|
SchemeView(viewPointOverride, featuresState, config, modifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a map using convenient parameters. If neither [initialViewPoint], noe [initialRectangle] is defined,
|
||||||
|
* use map features to infer view region.
|
||||||
|
* @param initialViewPoint The view point of the map using center and zoom. Is used if provided
|
||||||
|
* @param initialRectangle The rectangle to be used for view point computation. Used if [initialViewPoint] is not defined.
|
||||||
|
* @param buildFeatures - a builder for features
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
public fun SchemeView(
|
||||||
|
initialViewPoint: SchemeViewPoint? = null,
|
||||||
|
initialRectangle: SchemeRectangle? = null,
|
||||||
|
config: SchemeViewConfig = SchemeViewConfig(),
|
||||||
|
modifier: Modifier = Modifier.fillMaxSize(),
|
||||||
|
buildFeatures: SchemeFeaturesState.() -> Unit = {},
|
||||||
|
) {
|
||||||
|
val featureState = SchemeFeaturesState.remember(buildFeatures)
|
||||||
|
|
||||||
|
val features = featureState.features()
|
||||||
|
|
||||||
|
val viewPointOverride: SchemeViewPoint = remember(initialViewPoint, initialRectangle) {
|
||||||
|
initialViewPoint
|
||||||
|
?: initialRectangle?.computeViewPoint()
|
||||||
|
?: features.values.computeBoundingBox(1f)?.computeViewPoint()
|
||||||
|
?: SchemeViewPoint(SchemeCoordinates(0f, 0f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// val featureDrag = DragHandle.withPrimaryButton { _, start, end ->
|
||||||
|
// val zoom = start.zoom
|
||||||
|
// featureState.findAllWithAttribute(DraggableAttribute) { it }.forEach { id ->
|
||||||
|
// val feature = features[id] as? DraggableMapFeature ?: return@forEach
|
||||||
|
// val boundingBox = feature.getBoundingBox(zoom) ?: return@forEach
|
||||||
|
// if (start.focus in boundingBox) {
|
||||||
|
// featureState.addFeature(id, feature.withCoordinates(end.focus))
|
||||||
|
// return@withPrimaryButton false
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return@withPrimaryButton true
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// val newConfig = config.copy(
|
||||||
|
// dragHandle = DragHandle.combine(featureDrag, config.dragHandle)
|
||||||
|
// )
|
||||||
|
|
||||||
SchemeView(
|
SchemeView(
|
||||||
{ initialViewPoint },
|
initialViewPoint = viewPointOverride,
|
||||||
featuresBuilder.build(),
|
featuresState = featureState,
|
||||||
config,
|
config = config,
|
||||||
modifier
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user