From 18bc70d4fa7453c1191fc446327d1e24d5defe6d Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Sun, 16 Jan 2022 02:31:26 -0600 Subject: Set zoom limits of mapControl by converting zoom levels to Mapnik scale denominators --- .../TrackerMap/android/map/MapFragment.kt | 46 ++++++++++++++++++---- .../mx/trackermap/TrackerMap/utils/MapCalculus.kt | 31 +++++++++++++++ 2 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/MapCalculus.kt diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt index 4a63e65..9fa37c9 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt @@ -18,6 +18,7 @@ import mil.nga.sf.wkt.GeometryReader import java.io.File import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.client.models.Geofence +import mx.trackermap.TrackerMap.utils.MapCalculus import mx.trackermap.TrackerMap.utils.MarkerType typealias MarkerCallback = (Int?) -> Unit @@ -60,7 +61,10 @@ class MapFragment : GlobeMapFragment() { if (tileInfo == null) { val layer = resources.getStringArray(R.array.maps_streets_tile_url) val tmpInfo = RemoteTileInfoNew(layer[0], layer[1].toInt(), layer[2].toInt()) - tileInfo = makeTileInfo(layer[0], tmpInfo) + tileInfo = tileInfoSetCacheDir(layer[0], tmpInfo) + tileInfo?.let { + setZoomLimits(it.minZoom, it.maxZoom) + } } val params = SamplingParams() @@ -77,7 +81,16 @@ class MapFragment : GlobeMapFragment() { val latitude = 23.191 val longitude = -100.36 - focusOn(latitude, longitude, zoom = 0.4, animated = false) + focusOn(latitude, longitude, height = 0.4, animated = false) + } + + override fun mapDidStopMoving( + mapControl: MapController?, + corners: Array?, + userMotion: Boolean + ) { + super.mapDidStopMoving(mapControl, corners, userMotion) + Log.d("MapFragment", "Height: ${mapControl?.height}") } override fun userDidSelect( @@ -221,7 +234,8 @@ class MapFragment : GlobeMapFragment() { mbr.expandByFraction(0.1) mapControl.addPostSurfaceRunnable { - val zoom = mapControl.findHeightToViewBounds(mbr, mbr.middle()) + val zoom = mapControl.zoomLimitMax.coerceAtLeast( + mapControl.findHeightToViewBounds(mbr, mbr.middle())) mapControl.setPositionGeo(mbr.middle(), zoom) } } @@ -301,17 +315,19 @@ class MapFragment : GlobeMapFragment() { )) } - fun focusOn(latitude: Double, longitude: Double, zoom: Double = 0.00009, animated: Boolean = true) { + fun focusOn(latitude: Double, longitude: Double, height: Double = 0.00009, animated: Boolean = true) { val lat = latitude * Math.PI / 180 val lon = longitude * Math.PI / 180 + // Ensure height is equal or higher than bottom limit + val z = mapControl.zoomLimitMin.coerceAtLeast(height) if (animated) { - mapControl.animatePositionGeo(lon, lat, zoom, 0.2) + mapControl.animatePositionGeo(lon, lat, z, 0.2) } else { - mapControl.setPositionGeo(lon, lat, zoom) + mapControl.setPositionGeo(lon, lat, z) } } - private fun makeTileInfo(url: String, tileInfo: TileInfoNew): TileInfoNew? { + private fun tileInfoSetCacheDir(url: String, tileInfo: TileInfoNew): TileInfoNew? { return context?.let { val cacheDirName = url.toByteArray(Charsets.UTF_8).md5().hex val cacheDirMap = File(it.cacheDir, cacheDirName) @@ -323,11 +339,25 @@ class MapFragment : GlobeMapFragment() { } } + private fun setZoomLimits(minZoom: Int, maxZoom: Int) { + mapControl?.setZoomLimits( + mapControl.heightForMapScale( + MapCalculus.zoomLevelToScale(maxZoom) + ?: MapCalculus.zoomLevelToScale(20)!! + ), + mapControl.heightForMapScale( + MapCalculus.zoomLevelToScale(minZoom) + ?: MapCalculus.zoomLevelToScale(1)!! + ) + ) + } + fun updateTileInfo(url: String, tileInfo: TileInfoNew) { context?.let { - this.tileInfo = makeTileInfo(url, tileInfo) + this.tileInfo = tileInfoSetCacheDir(url, tileInfo) this.tileInfo?.let { loader?.changeTileInfo(it) + setZoomLimits(tileInfo.minZoom, tileInfo.maxZoom) } } } diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/MapCalculus.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/MapCalculus.kt new file mode 100644 index 0000000..8c58179 --- /dev/null +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/MapCalculus.kt @@ -0,0 +1,31 @@ +package mx.trackermap.TrackerMap.utils + +class MapCalculus { + companion object { + // Source: https://github.com/openstreetmap/mapnik-stylesheets/blob/master/zoom-to-scale.txt + fun zoomLevelToScale(zoom: Int): Double? = + when (zoom) { + 1 -> 279541132.014 + 2 -> 139770566.007 + 3 -> 69885283.0036 + 4 -> 34942641.5018 + 5 -> 17471320.7509 + 6 -> 8735660.37545 + 7 -> 4367830.18772 + 8 -> 2183915.09386 + 9 -> 1091957.54693 + 10 -> 545978.773466 + 11 -> 272989.386733 + 12 -> 136494.693366 + 13 -> 68247.3466832 + 14 -> 34123.6733416 + 15 -> 17061.8366708 + 16 -> 8530.9183354 + 17 -> 4265.4591677 + 18 -> 2132.72958385 + 19 -> 1000.0 // made up + 20 -> 500.0 // made up + else -> null + } + } +} \ No newline at end of file -- cgit v1.2.3