diff --git a/src/commonMain/kotlin/centre/sciprog/maps/MapViewPoint.kt b/src/commonMain/kotlin/centre/sciprog/maps/MapViewPoint.kt index 3094d1a..c99cfc0 100644 --- a/src/commonMain/kotlin/centre/sciprog/maps/MapViewPoint.kt +++ b/src/commonMain/kotlin/centre/sciprog/maps/MapViewPoint.kt @@ -1,6 +1,8 @@ package centre.sciprog.maps +import kotlin.math.pow import kotlin.math.roundToInt +import kotlin.math.sign /** * Observable position on the map. Includes observation coordinate and [zoom] factor @@ -34,4 +36,13 @@ fun MapViewPoint.move(delta: GeodeticMapCoordinates): MapViewPoint { return MapViewPoint(newCoordinates, zoom) } -fun MapViewPoint.zoom(zoomDelta: Double): MapViewPoint = copy(zoom = (zoom + zoomDelta).coerceIn(2.0, 18.0)) \ No newline at end of file +fun MapViewPoint.zoom(zoomDelta: Double): MapViewPoint = copy(zoom = (zoom + zoomDelta).coerceIn(2.0, 18.0)) + +fun MapViewPoint.zoom(zoomDelta: Double, at: GeodeticMapCoordinates): MapViewPoint { + val difScale = 2.0.pow(-zoomDelta) + val newCenter = GeodeticMapCoordinates.ofRadians( + focus.latitude + (at.latitude - focus.latitude) * difScale, + focus.longitude + (at.longitude - focus.longitude) * difScale + ) + return MapViewPoint(newCenter, (zoom + zoomDelta).coerceIn(2.0, 18.0)) +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt b/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt index 81b8bc1..600ed69 100644 --- a/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt +++ b/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt @@ -70,7 +70,11 @@ actual fun MapView( val (xPos, yPos) = it.changes.first().position onClick(DpOffset(xPos.toDp(), yPos.toDp()).toGeodetic()) }.onPointerEvent(PointerEventType.Scroll) { - viewPoint = viewPoint.zoom(-it.changes.first().scrollDelta.y.toDouble()) + val change = it.changes.first() + val (xPos, yPos) = change.position + //compute invariant point of translation + val at = DpOffset(xPos.toDp(), yPos.toDp()).toGeodetic() + viewPoint = viewPoint.zoom(-change.scrollDelta.y.toDouble(), at) }.pointerInput(Unit) { detectDragGestures { _: PointerInputChange, dragAmount: Offset -> viewPoint = viewPoint.move(-dragAmount.x, +dragAmount.y)