Skip to content

Commit

Permalink
Use map layer management for radar compass
Browse files Browse the repository at this point in the history
  • Loading branch information
kylecorry31 committed Sep 4, 2023
1 parent c9ff4d6 commit cb4eea7
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,7 @@ import com.kylecorry.trail_sense.navigation.infrastructure.Navigator
import com.kylecorry.trail_sense.navigation.infrastructure.share.LocationCopy
import com.kylecorry.trail_sense.navigation.infrastructure.share.LocationGeoSender
import com.kylecorry.trail_sense.navigation.infrastructure.share.LocationSharesheet
import com.kylecorry.trail_sense.navigation.paths.domain.Path
import com.kylecorry.trail_sense.navigation.paths.infrastructure.PathLoader
import com.kylecorry.trail_sense.navigation.paths.infrastructure.persistence.PathService
import com.kylecorry.trail_sense.navigation.paths.ui.asMappable
import com.kylecorry.trail_sense.navigation.ui.data.UpdateAstronomyLayerCommand
import com.kylecorry.trail_sense.navigation.ui.data.UpdateTideLayerCommand
import com.kylecorry.trail_sense.navigation.ui.errors.NavigatorUserErrors
import com.kylecorry.trail_sense.navigation.ui.layers.*
import com.kylecorry.trail_sense.navigation.ui.layers.compass.BeaconCompassLayer
Expand All @@ -73,8 +68,12 @@ import com.kylecorry.trail_sense.shared.permissions.alertNoCameraPermission
import com.kylecorry.trail_sense.shared.permissions.requestCamera
import com.kylecorry.trail_sense.shared.preferences.PreferencesSubsystem
import com.kylecorry.trail_sense.shared.sensors.SensorService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import com.kylecorry.trail_sense.tools.maps.infrastructure.layers.ILayerManager
import com.kylecorry.trail_sense.tools.maps.infrastructure.layers.MultiLayerManager
import com.kylecorry.trail_sense.tools.maps.infrastructure.layers.MyAccuracyLayerManager
import com.kylecorry.trail_sense.tools.maps.infrastructure.layers.MyLocationLayerManager
import com.kylecorry.trail_sense.tools.maps.infrastructure.layers.PathLayerManager
import com.kylecorry.trail_sense.tools.maps.infrastructure.layers.TideLayerManager
import java.time.Duration
import java.time.Instant
import java.util.*
Expand Down Expand Up @@ -102,7 +101,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
private lateinit var navController: NavController

private val beaconRepo by lazy { BeaconRepo.getInstance(requireContext()) }
private val pathService by lazy { PathService.getInstance(requireContext()) }

private val sensorService by lazy { SensorService(requireContext()) }
private val cache by lazy { PreferencesSubsystem.getInstance(requireContext()).preferences }
Expand All @@ -111,7 +109,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
private val formatService by lazy { FormatService.getInstance(requireContext()) }

private var beacons: Collection<Beacon> = listOf()
private var paths: List<Path> = emptyList()
private var nearbyBeacons: List<Beacon> = listOf()

private var destination: Beacon? = null
Expand All @@ -135,12 +132,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
private lateinit var diagnostics: List<IDiagnostic>

// Data commands
private val updateTideLayerCommand by lazy {
UpdateTideLayerCommand(
requireContext(),
tideLayer
)
}
private val updateAstronomyLayerCommand by lazy {
UpdateAstronomyLayerCommand(
astronomyCompassLayer,
Expand All @@ -154,16 +145,14 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {

private var lastOrientation: DeviceOrientation.Orientation? = null

private val pathLoader by lazy { PathLoader(pathService) }

private val loadPathRunner = CoroutineQueueRunner()
private val loadBeaconsRunner = CoroutineQueueRunner()

private val pathLayer = PathLayer()
private val beaconLayer = BeaconLayer()
private val myLocationLayer = MyLocationLayer()
private val myAccuracyLayer = MyAccuracyLayer()
private val tideLayer = TideLayer()
private var layerManager: ILayerManager? = null

// Compass layers
private val beaconCompassLayer = BeaconCompassLayer()
Expand All @@ -179,6 +168,7 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
private val nearbyCount by lazy { userPrefs.navigation.numberOfVisibleBeacons }
private val nearbyDistance
get() = userPrefs.navigation.maxBeaconDistance
private var lastNearbyDistance: Float? = null
private val useRadarCompass by lazy { userPrefs.navigation.useRadarCompass }
private val lockScreenPresence by lazy { userPrefs.navigation.lockScreenPresence }
private val styleChooser by lazy { CompassStyleChooser(userPrefs.navigation, hasCompass) }
Expand All @@ -194,7 +184,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
}
}


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val beaconId = arguments?.getLong("destination") ?: 0L
Expand Down Expand Up @@ -239,7 +228,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {

// Initialize layers
beaconLayer.setOutlineColor(Resources.color(requireContext(), R.color.colorSecondary))
myAccuracyLayer.setColors(AppColor.Orange.color, Color.TRANSPARENT, 25)
binding.radarCompass.setLayers(
listOf(
pathLayer,
Expand Down Expand Up @@ -288,16 +276,9 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
updateNearbyBeacons()
}

observeFlow(pathService.getPaths()) {
onIO {
paths = it.filter { path -> path.style.visible }
updateCompassPaths(true)
}
}

navController = findNavController()

observe(compass) { }
observe(compass) {}
observe(orientation) { onOrientationUpdate() }
observe(altimeter) { }
observe(gps) { onLocationUpdate() }
Expand Down Expand Up @@ -480,7 +461,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
return@inBackground
}

updateTideLayerCommand.execute()
updateAstronomyLayerCommand.execute()
astronomyDataLoaded = true
}
Expand All @@ -490,6 +470,21 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
super.onResume()
lastOrientation = null

layerManager = MultiLayerManager(
listOf(
PathLayerManager(requireContext(), pathLayer),
MyAccuracyLayerManager(myAccuracyLayer, AppColor.Orange.color, 25),
MyLocationLayerManager(myLocationLayer, Color.WHITE),
TideLayerManager(requireContext(), tideLayer)
)
)
if (useRadarCompass) {
layerManager?.start()
}

// Populate the last known location
layerManager?.onLocationChanged(gps.location, gps.horizontalAccuracy)

// Resume navigation
inBackground {
destination = navigator.getDestination()
Expand All @@ -513,10 +508,11 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {

override fun onPause() {
super.onPause()
loadPathRunner.cancel()
loadBeaconsRunner.cancel()
sightingCompass?.stop()
errors.reset()
layerManager?.stop()
layerManager = null
}

private fun updateNearbyBeacons() {
Expand Down Expand Up @@ -635,6 +631,8 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
Distance.meters(altimeter.altitude).convertTo(baseDistanceUnits)
)

layerManager?.onBearingChanged(compass.bearing)

// Compass
listOf<ICompassView>(
binding.roundCompass,
Expand All @@ -646,11 +644,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
it.compassCenter = gps.location
}

// This gets set with the other compass layers as well, but also set it here to keep it up to date since this changes more often
myLocationLayer.setLocation(gps.location)
myLocationLayer.setAzimuth(compass.bearing)
myAccuracyLayer.setLocation(gps.location, gps.horizontalAccuracy)

// Location
binding.navigationTitle.subtitle.text = formatService.formatLocation(gps.location)

Expand Down Expand Up @@ -679,10 +672,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
)
}

myLocationLayer.setAzimuth(compass.bearing)
myLocationLayer.setLocation(gps.location)
myAccuracyLayer.setLocation(gps.location, gps.horizontalAccuracy)

// Update beacon layers
beaconLayer.setBeacons(nearbyBeacons)
beaconCompassLayer.setBeacons(nearbyBeacons)
Expand All @@ -700,48 +689,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
}
}

private fun updateCompassPaths(reload: Boolean = false) {
inBackground {
loadPathRunner.skipIfRunning {

if (!useRadarCompass) {
return@skipIfRunning
}

val mappablePaths = onIO {
val loadGeofence = Geofence(
gps.location,
Distance.meters(nearbyDistance + 10)
)
val load = CoordinateBounds.from(loadGeofence)

val unloadGeofence =
loadGeofence.copy(radius = Distance.meters(loadGeofence.radius.distance + 1000))
val unload = CoordinateBounds.from(unloadGeofence)

pathLoader.update(paths, load, unload, reload)

val mappablePaths =
pathLoader.getPointsWithBacktrack(requireContext()).mapNotNull {
val path =
paths.firstOrNull { p -> p.id == it.key } ?: return@mapNotNull null
it.value.asMappable(requireContext(), path)
}

mappablePaths
}

withContext(Dispatchers.Main) {
if (isBound) {
pathLayer.setPaths(mappablePaths)
}
}
}
}


}

private fun getPosition(): Position {
return Position(
gps.location,
Expand Down Expand Up @@ -796,15 +743,23 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
}

private fun onLocationUpdate() {
layerManager?.onLocationChanged(gps.location, gps.horizontalAccuracy)

updateNearbyBeacons()
updateDeclination()

if (!astronomyDataLoaded) {
updateAstronomyData()
}

if (paths.any()) {
updateCompassPaths()
if (useRadarCompass && lastNearbyDistance != nearbyDistance) {
lastNearbyDistance = nearbyDistance
val loadGeofence = Geofence(
gps.location,
Distance.meters(nearbyDistance + 10)
)
val bounds = CoordinateBounds.from(loadGeofence)
layerManager?.onBoundsChanged(bounds)
}
}

Expand All @@ -824,7 +779,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
}
}


private fun updateNavigationButton() {
if (destination != null) {
binding.beaconBtn.setImageResource(R.drawable.ic_cancel)
Expand All @@ -839,16 +793,15 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
updateNavigationButton()
}

companion object {
const val LAST_DEST_BEARING = "last_dest_bearing"
const val CACHE_CAMERA_ZOOM = "sighting_compass_camera_zoom"
}

override fun generateBinding(
layoutInflater: LayoutInflater,
container: ViewGroup?
): ActivityNavigatorBinding {
return ActivityNavigatorBinding.inflate(layoutInflater, container, false)
}

companion object {
const val LAST_DEST_BEARING = "last_dest_bearing"
const val CACHE_CAMERA_ZOOM = "sighting_compass_camera_zoom"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import com.kylecorry.sol.units.Coordinate

class MultiLayerManager(private val managers: List<ILayerManager>) : ILayerManager {

private var lastBounds: CoordinateBounds? = null

override fun start() {
managers.forEach { it.start() }
}
Expand All @@ -15,6 +17,10 @@ class MultiLayerManager(private val managers: List<ILayerManager>) : ILayerManag
}

override fun onBoundsChanged(bounds: CoordinateBounds?) {
if (bounds == lastBounds) {
return
}
lastBounds = bounds
managers.forEach {
it.onBoundsChanged(bounds)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class PathLayerManager(private val context: Context, private val layer: PathLaye
private suspend fun loadPaths(reload: Boolean) = onDefault {
if (reload || !loaded) {
val bounds = bounds ?: return@onDefault
// TODO: Make unload bounds larger than load bounds
pathLoader.update(paths, bounds, bounds, true)
loaded = true
}
Expand Down

0 comments on commit cb4eea7

Please sign in to comment.