From 2c6b35dbdf878b9f7666d2df9a1a255babb48467 Mon Sep 17 00:00:00 2001 From: andrekir Date: Sat, 8 Jul 2023 07:11:08 -0300 Subject: [PATCH] fix: revert zoomToNodes removal revert https://github.com/meshtastic/Meshtastic-Android/pull/647/commits/4412a5d5aa6752c9bc1c71084c8570f6efea0df1 --- .../com/geeksville/mesh/ui/map/MapFragment.kt | 18 ++++++++++++++---- .../com/geeksville/mesh/util/LocationUtils.kt | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/map/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/map/MapFragment.kt index 2da68ce52..ad969a502 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/map/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/map/MapFragment.kt @@ -50,11 +50,13 @@ import com.geeksville.mesh.ui.map.components.DownloadButton import com.geeksville.mesh.ui.map.components.EditWaypointDialog import com.geeksville.mesh.ui.map.components.MapStyleButton import com.geeksville.mesh.util.SqlTileWriterExt +import com.geeksville.mesh.util.requiredZoomLevel import com.geeksville.mesh.util.formatAgo import com.geeksville.mesh.waypoint import com.google.accompanist.themeadapter.appcompat.AppCompatTheme import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint +import org.osmdroid.api.IMapController import org.osmdroid.config.Configuration import org.osmdroid.events.MapEventsReceiver import org.osmdroid.events.MapListener @@ -111,6 +113,7 @@ fun MapView(model: UIViewModel = viewModel()) { // constants val defaultMinZoom = 1.5 val defaultMaxZoom = 18.0 + val defaultZoomSpeed = 3000L val prefsName = "org.geeksville.osm.prefs" val mapStyleId = "map_style_id" val nodeLayer = 1 @@ -432,6 +435,16 @@ fun MapView(model: UIViewModel = viewModel()) { // } // } + fun zoomToNodes(controller: IMapController) { + if (nodeMarkers.isNotEmpty()) { + val box = BoundingBox.fromGeoPoints(nodeMarkers.map { it.position }) + val center = GeoPoint(box.centerLatitude, box.centerLongitude) + val maximumZoomLevel = map.tileProvider.tileSource.maximumZoomLevel.toDouble() + val finalZoomLevel = minOf(box.requiredZoomLevel() * 0.8, maximumZoomLevel) + controller.animateTo(center, finalZoomLevel, defaultZoomSpeed) + } else controller.zoomIn() + } + fun loadOnlineTileSourceBase(): ITileSource { val id = mPrefs.getInt(mapStyleId, 1) debug("mapStyleId from prefs: $id") @@ -577,10 +590,7 @@ fun MapView(model: UIViewModel = viewModel()) { map.apply { setTileSource(loadOnlineTileSourceBase()) defaultMapSettings() - if (nodeMarkers.isNotEmpty()) zoomToBoundingBox( - BoundingBox.fromGeoPoints(nodeMarkers.map { it.position }), - false - ) else controller.zoomIn() + zoomToNodes(controller) } }, modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/com/geeksville/mesh/util/LocationUtils.kt b/app/src/main/java/com/geeksville/mesh/util/LocationUtils.kt index 434f9d4de..9fe6ed9f8 100644 --- a/app/src/main/java/com/geeksville/mesh/util/LocationUtils.kt +++ b/app/src/main/java/com/geeksville/mesh/util/LocationUtils.kt @@ -5,10 +5,13 @@ import com.geeksville.mesh.Position import mil.nga.grid.features.Point import mil.nga.mgrs.MGRS import mil.nga.mgrs.utm.UTM +import org.osmdroid.util.BoundingBox +import org.osmdroid.util.GeoPoint import kotlin.math.abs import kotlin.math.acos import kotlin.math.atan2 import kotlin.math.cos +import kotlin.math.log2 import kotlin.math.sin /******************************************************************************* @@ -233,3 +236,18 @@ fun bearing( fun radToBearing(rad: Double): Double { return (Math.toDegrees(rad) + 360) % 360 } + +/** + * Calculates the zoom level required to fit the entire [BoundingBox] inside the map view. + * @return The zoom level as a Double value. + */ +fun BoundingBox.requiredZoomLevel(): Double { + val topLeft = GeoPoint(this.latNorth, this.lonWest) + val bottomRight = GeoPoint(this.latSouth, this.lonEast) + val latLonWidth = topLeft.distanceToAsDouble(GeoPoint(topLeft.latitude, bottomRight.longitude)) + val latLonHeight = topLeft.distanceToAsDouble(GeoPoint(bottomRight.latitude, topLeft.longitude)) + val requiredLatZoom = log2(360.0 / (latLonHeight / 111320)) + val requiredLonZoom = log2(360.0 / (latLonWidth / 111320)) + return maxOf(requiredLatZoom, requiredLonZoom) +} +