66 lines
2.2 KiB
Kotlin
66 lines
2.2 KiB
Kotlin
package center.sciprog.maps.scheme
|
|
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.remember
|
|
import androidx.compose.ui.unit.Dp
|
|
import androidx.compose.ui.unit.DpOffset
|
|
import androidx.compose.ui.unit.DpRect
|
|
import androidx.compose.ui.unit.dp
|
|
import center.sciprog.maps.features.*
|
|
import kotlin.math.min
|
|
|
|
class XYViewScope(
|
|
config: ViewConfig<XY>,
|
|
) : CoordinateViewScope<XY>(config) {
|
|
override val space: CoordinateSpace<XY>
|
|
get() = XYCoordinateSpace
|
|
|
|
override fun DpOffset.toCoordinates(): XY = XY(
|
|
(x - canvasSize.width / 2).value / viewPoint.zoom + viewPoint.focus.x,
|
|
(canvasSize.height / 2 - y).value / viewPoint.zoom + viewPoint.focus.y
|
|
)
|
|
|
|
override fun XY.toDpOffset(): DpOffset = DpOffset(
|
|
(canvasSize.width / 2 + (x.dp - viewPoint.focus.x.dp) * viewPoint.zoom),
|
|
(canvasSize.height / 2 + (viewPoint.focus.y.dp - y.dp) * viewPoint.zoom)
|
|
)
|
|
|
|
override fun computeViewPoint(rectangle: Rectangle<XY>): ViewPoint<XY> {
|
|
val scale = min(
|
|
canvasSize.width.value / rectangle.width,
|
|
canvasSize.height.value / rectangle.height
|
|
)
|
|
|
|
return XYViewPoint(rectangle.center, scale)
|
|
}
|
|
|
|
override fun ViewPoint<XY>.moveBy(x: Dp, y: Dp): ViewPoint<XY> {
|
|
val newCoordinates = XY(focus.x + x.value / zoom, focus.y + y.value / zoom)
|
|
return XYViewPoint(newCoordinates, zoom)
|
|
}
|
|
|
|
override fun Rectangle<XY>.toDpRect(): DpRect {
|
|
val topLeft = leftTop.toDpOffset()
|
|
val bottomRight = rightBottom.toDpOffset()
|
|
return DpRect(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y)
|
|
}
|
|
|
|
companion object{
|
|
@Composable
|
|
public fun remember(
|
|
config: ViewConfig<XY> = ViewConfig(),
|
|
initialViewPoint: ViewPoint<XY>? = null,
|
|
initialRectangle: Rectangle<XY>? = null,
|
|
): XYViewScope = remember {
|
|
XYViewScope(config).also { mapState->
|
|
if (initialViewPoint != null) {
|
|
mapState.viewPoint = initialViewPoint
|
|
} else if (initialRectangle != null) {
|
|
mapState.viewPoint = mapState.computeViewPoint(initialRectangle)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|