2022-07-23 10:58:16 +03:00
|
|
|
package center.sciprog.maps.compose
|
2022-07-11 09:36:43 +03:00
|
|
|
|
|
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
2022-09-14 15:09:02 +03:00
|
|
|
import androidx.compose.runtime.Composable
|
|
|
|
import androidx.compose.runtime.key
|
|
|
|
import androidx.compose.runtime.remember
|
2022-07-11 09:36:43 +03:00
|
|
|
import androidx.compose.ui.Modifier
|
2022-07-14 20:19:57 +03:00
|
|
|
import androidx.compose.ui.unit.DpSize
|
2022-09-13 20:30:49 +03:00
|
|
|
import androidx.compose.ui.unit.dp
|
2022-12-23 22:16:16 +03:00
|
|
|
import center.sciprog.maps.coordinates.Gmc
|
|
|
|
import center.sciprog.maps.features.*
|
2022-07-14 20:19:57 +03:00
|
|
|
import kotlin.math.PI
|
|
|
|
import kotlin.math.log2
|
|
|
|
import kotlin.math.min
|
2022-07-11 09:36:43 +03:00
|
|
|
|
2022-07-13 11:36:02 +03:00
|
|
|
|
2022-07-11 09:36:43 +03:00
|
|
|
@Composable
|
2022-07-23 13:49:47 +03:00
|
|
|
public expect fun MapView(
|
2022-07-11 09:36:43 +03:00
|
|
|
mapTileProvider: MapTileProvider,
|
2022-09-13 18:27:57 +03:00
|
|
|
initialViewPoint: MapViewPoint,
|
2022-12-26 17:44:01 +03:00
|
|
|
featuresState: FeatureCollection<Gmc>,
|
2022-12-24 22:59:33 +03:00
|
|
|
config: ViewConfig<Gmc> = ViewConfig(),
|
2022-07-11 18:32:36 +03:00
|
|
|
modifier: Modifier = Modifier.fillMaxSize(),
|
|
|
|
)
|
|
|
|
|
2022-09-14 15:09:02 +03:00
|
|
|
internal val defaultCanvasSize = DpSize(512.dp, 512.dp)
|
2022-09-09 21:16:54 +03:00
|
|
|
|
2022-12-23 22:16:16 +03:00
|
|
|
public fun Rectangle<Gmc>.computeViewPoint(
|
2022-09-09 21:16:54 +03:00
|
|
|
mapTileProvider: MapTileProvider,
|
2022-09-14 15:09:02 +03:00
|
|
|
canvasSize: DpSize = defaultCanvasSize,
|
2022-09-13 13:44:38 +03:00
|
|
|
): MapViewPoint {
|
2022-09-09 21:16:54 +03:00
|
|
|
val zoom = log2(
|
|
|
|
min(
|
|
|
|
canvasSize.width.value / longitudeDelta.radians.value,
|
|
|
|
canvasSize.height.value / latitudeDelta.radians.value
|
|
|
|
) * PI / mapTileProvider.tileSize
|
|
|
|
)
|
2022-12-25 14:33:31 +03:00
|
|
|
return MapViewPoint(center, zoom.toFloat())
|
2022-09-09 21:16:54 +03:00
|
|
|
}
|
|
|
|
|
2022-09-14 15:09:02 +03:00
|
|
|
/**
|
|
|
|
* A builder for a Map with static features.
|
|
|
|
*/
|
|
|
|
@Composable
|
|
|
|
public fun MapView(
|
|
|
|
mapTileProvider: MapTileProvider,
|
|
|
|
initialViewPoint: MapViewPoint? = null,
|
2022-12-25 14:33:31 +03:00
|
|
|
initialRectangle: Rectangle<Gmc>? = null,
|
2022-12-09 22:21:24 +03:00
|
|
|
featureMap: Map<FeatureId<*>, MapFeature>,
|
2022-12-24 22:59:33 +03:00
|
|
|
config: ViewConfig<Gmc> = ViewConfig(),
|
2022-09-14 15:09:02 +03:00
|
|
|
modifier: Modifier = Modifier.fillMaxSize(),
|
|
|
|
) {
|
|
|
|
val featuresState = key(featureMap) {
|
2022-12-26 17:44:01 +03:00
|
|
|
FeatureCollection.build(GmcCoordinateSpace) {
|
2022-12-09 22:21:24 +03:00
|
|
|
featureMap.forEach { feature(it.key.id, it.value) }
|
2022-09-14 15:09:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
val viewPointOverride: MapViewPoint = remember(initialViewPoint, initialRectangle) {
|
|
|
|
initialViewPoint
|
|
|
|
?: initialRectangle?.computeViewPoint(mapTileProvider)
|
2022-12-25 14:33:31 +03:00
|
|
|
?: featureMap.values.computeBoundingBox(GmcCoordinateSpace, 1f)?.computeViewPoint(mapTileProvider)
|
2022-09-14 15:09:02 +03:00
|
|
|
?: MapViewPoint.globe
|
|
|
|
}
|
|
|
|
|
|
|
|
MapView(mapTileProvider, viewPointOverride, featuresState, config, modifier)
|
|
|
|
}
|
2022-09-13 20:30:49 +03:00
|
|
|
|
2022-09-13 13:44:38 +03:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2022-07-11 18:32:36 +03:00
|
|
|
@Composable
|
2022-07-23 13:49:47 +03:00
|
|
|
public fun MapView(
|
2022-07-14 20:19:57 +03:00
|
|
|
mapTileProvider: MapTileProvider,
|
2022-09-09 21:16:54 +03:00
|
|
|
initialViewPoint: MapViewPoint? = null,
|
2022-12-25 14:33:31 +03:00
|
|
|
initialRectangle: Rectangle<Gmc>? = null,
|
2022-12-24 22:59:33 +03:00
|
|
|
config: ViewConfig<Gmc> = ViewConfig(),
|
2022-07-14 20:19:57 +03:00
|
|
|
modifier: Modifier = Modifier.fillMaxSize(),
|
2022-12-26 17:44:01 +03:00
|
|
|
buildFeatures: FeatureCollection<Gmc>.() -> Unit = {},
|
2022-09-14 15:09:02 +03:00
|
|
|
) {
|
2022-12-26 17:44:01 +03:00
|
|
|
val featureState = FeatureCollection.remember(GmcCoordinateSpace, buildFeatures)
|
2022-09-13 18:27:57 +03:00
|
|
|
|
2022-09-14 12:11:15 +03:00
|
|
|
val viewPointOverride: MapViewPoint = remember(initialViewPoint, initialRectangle) {
|
2022-09-13 20:30:49 +03:00
|
|
|
initialViewPoint
|
2022-09-14 15:09:02 +03:00
|
|
|
?: initialRectangle?.computeViewPoint(mapTileProvider)
|
2022-12-26 11:19:08 +03:00
|
|
|
?: featureState.features.values.computeBoundingBox(GmcCoordinateSpace, 1f)
|
|
|
|
?.computeViewPoint(mapTileProvider)
|
2022-09-13 20:30:49 +03:00
|
|
|
?: MapViewPoint.globe
|
|
|
|
}
|
2022-09-13 18:27:57 +03:00
|
|
|
|
2022-12-26 11:19:08 +03:00
|
|
|
val featureDrag: DragHandle<Gmc> = DragHandle.withPrimaryButton { event, start, end ->
|
2022-11-28 07:56:15 +03:00
|
|
|
featureState.forEachWithAttribute(DraggableAttribute) { _, handle ->
|
2022-12-26 11:19:08 +03:00
|
|
|
@Suppress("UNCHECKED_CAST")
|
|
|
|
(handle as DragHandle<Gmc>)
|
|
|
|
.handle(event, start, end)
|
|
|
|
.takeIf { !it.handleNext }
|
|
|
|
?.let {
|
|
|
|
//we expect it already have no bypass
|
|
|
|
return@withPrimaryButton it
|
|
|
|
}
|
2022-09-13 18:27:57 +03:00
|
|
|
}
|
2022-12-26 11:19:08 +03:00
|
|
|
//bypass
|
|
|
|
DragResult(end)
|
2022-08-31 22:48:52 +03:00
|
|
|
}
|
|
|
|
|
2022-09-13 20:30:49 +03:00
|
|
|
|
2022-09-14 15:09:02 +03:00
|
|
|
val newConfig = config.copy(
|
|
|
|
dragHandle = DragHandle.combine(featureDrag, config.dragHandle)
|
|
|
|
)
|
2022-09-13 20:30:49 +03:00
|
|
|
|
2022-09-13 18:27:57 +03:00
|
|
|
MapView(
|
|
|
|
mapTileProvider = mapTileProvider,
|
|
|
|
initialViewPoint = viewPointOverride,
|
2022-09-14 15:09:02 +03:00
|
|
|
featuresState = featureState,
|
2022-09-13 18:27:57 +03:00
|
|
|
config = newConfig,
|
|
|
|
modifier = modifier,
|
|
|
|
)
|
|
|
|
}
|