From f055d96e5a51860642804b7cd4dc9a81efa3c377 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Sat, 28 Nov 2020 16:46:11 +0000 Subject: [PATCH] Further changes to MapViewModel.kt, removed bottomNav ripple effect --- .../look4sat/ui/mainScreen/MapFragment.kt | 56 +++----- .../look4sat/ui/mainScreen/MapViewModel.kt | 122 ++++++++++-------- app/src/main/res/layout/activity_main.xml | 1 + 3 files changed, 85 insertions(+), 94 deletions(-) diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/mainScreen/MapFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/mainScreen/MapFragment.kt index 4b782c59..dd176481 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/mainScreen/MapFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/mainScreen/MapFragment.kt @@ -10,7 +10,6 @@ import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels -import com.github.amsacode.predict4java.GroundStationPosition import com.github.amsacode.predict4java.Position import com.rtbishop.look4sat.R import com.rtbishop.look4sat.SharedViewModel @@ -36,23 +35,11 @@ class MapFragment : Fragment(R.layout.fragment_map) { @Inject lateinit var preferences: SharedPreferences private lateinit var binding: FragmentMapBinding - private lateinit var nameFormat: String - private lateinit var qthFormat: String - private lateinit var altFormat: String - private lateinit var distFormat: String - private lateinit var velFormat: String - private lateinit var latLonFormat: String - private lateinit var coverageFormat: String - private val viewModel: MapViewModel by viewModels() + private val mapViewModel: MapViewModel by viewModels() private val sharedViewModel: SharedViewModel by activityViewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setupComponents(view) - setupObservers() - } - - private fun setupComponents(view: View) { Configuration.getInstance().load(requireContext().applicationContext, preferences) binding = FragmentMapBinding.bind(view).apply { mapView.apply { @@ -70,35 +57,29 @@ class MapFragment : Fragment(R.layout.fragment_map) { overlays.addAll(Array(4) { FolderOverlay() }) } } - nameFormat = getString(R.string.pat_osm_idName) - qthFormat = getString(R.string.map_qth) - altFormat = getString(R.string.pat_altitude) - distFormat = getString(R.string.pat_distance) - velFormat = getString(R.string.pat_osm_vel) - latLonFormat = getString(R.string.pat_osm_latLon) - coverageFormat = getString(R.string.map_coverage) + setupObservers() } private fun setupObservers() { - viewModel.getGSP().observe(viewLifecycleOwner, { setupPosOverlay(it) }) + mapViewModel.getGSP().observe(viewLifecycleOwner, { setupPosOverlay(it) }) sharedViewModel.getPasses().observe(viewLifecycleOwner, { if (it is Result.Success && it.data.isNotEmpty()) { - viewModel.setPasses(it.data) - binding.fabPrev.setOnClickListener { viewModel.changeSelection(true) } - binding.fabNext.setOnClickListener { viewModel.changeSelection(false) } + mapViewModel.setPasses(it.data) + binding.fabPrev.setOnClickListener { mapViewModel.scrollSelection(true) } + binding.fabNext.setOnClickListener { mapViewModel.scrollSelection(false) } } }) - viewModel.getSelectedSat().observe(viewLifecycleOwner, { setSelectedSatDetails(it) }) - viewModel.getSatMarkers().observe(viewLifecycleOwner, { setMarkers(it) }) + mapViewModel.getSelectedSat().observe(viewLifecycleOwner, { setSelectedSatDetails(it) }) + mapViewModel.getSatMarkers().observe(viewLifecycleOwner, { setMarkers(it) }) } - private fun setupPosOverlay(gsp: GroundStationPosition) { + private fun setupPosOverlay(osmPos: Position) { binding.apply { Marker(mapView).apply { setInfoWindow(null) setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_map_pos) - position = GeoPoint(gsp.latitude, gsp.longitude) + position = GeoPoint(osmPos.lat, osmPos.lon) mapView.overlays[0] = this mapView.invalidate() } @@ -107,13 +88,14 @@ class MapFragment : Fragment(R.layout.fragment_map) { private fun setSelectedSatDetails(sat: SelectedSat) { binding.apply { - idName.text = String.format(nameFormat, sat.catNum, sat.name) - qthLocator.text = String.format(qthFormat, sat.qthLoc) - altitude.text = String.format(altFormat, sat.altitude) - distance.text = String.format(distFormat, sat.range) - velocity.text = String.format(velFormat, sat.velocity) - latLon.text = String.format(latLonFormat, sat.osmPos.lat, sat.osmPos.lon) - mapCoverage.text = String.format(coverageFormat, sat.coverage) + idName.text = String.format(getString(R.string.pat_osm_idName), sat.catNum, sat.name) + qthLocator.text = String.format(getString(R.string.map_qth), sat.qthLoc) + altitude.text = String.format(getString(R.string.pat_altitude), sat.altitude) + distance.text = String.format(getString(R.string.pat_distance), sat.range) + velocity.text = String.format(getString(R.string.pat_osm_vel), sat.velocity) + latLon.text = + String.format(getString(R.string.pat_osm_latLon), sat.osmPos.lat, sat.osmPos.lon) + mapCoverage.text = String.format(getString(R.string.map_coverage), sat.coverage) mapView.overlays[1] = sat.groundTrack mapView.overlays[2] = sat.footprint mapView.invalidate() @@ -130,7 +112,7 @@ class MapFragment : Fragment(R.layout.fragment_map) { icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_map_sat) position = GeoPoint(it.value.lat, it.value.lon) setOnMarkerClickListener { _, _ -> - viewModel.setSelectedSat(it.key) + mapViewModel.selectSatellite(it.key) return@setOnMarkerClickListener true } markers.add(this) diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/mainScreen/MapViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/ui/mainScreen/MapViewModel.kt index 8562b79f..69034004 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/mainScreen/MapViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/mainScreen/MapViewModel.kt @@ -7,8 +7,8 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.github.amsacode.predict4java.GroundStationPosition import com.github.amsacode.predict4java.Position +import com.github.amsacode.predict4java.SatPos import com.rtbishop.look4sat.data.SatPass import com.rtbishop.look4sat.data.SelectedSat import com.rtbishop.look4sat.utility.PrefsManager @@ -16,6 +16,7 @@ import com.rtbishop.look4sat.utility.Utilities import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.osmdroid.util.GeoPoint import org.osmdroid.views.overlay.FolderOverlay import org.osmdroid.views.overlay.Overlay @@ -25,7 +26,7 @@ import java.util.* import kotlin.math.pow import kotlin.math.sqrt -class MapViewModel @ViewModelInject constructor(prefsManager: PrefsManager) : ViewModel() { +class MapViewModel @ViewModelInject constructor(val prefsManager: PrefsManager) : ViewModel() { private val dateNow = Date() private val trackPaint = Paint().apply { @@ -42,9 +43,10 @@ class MapViewModel @ViewModelInject constructor(prefsManager: PrefsManager) : Vi isAntiAlias = true } private var filteredPasses = listOf() + private lateinit var selectedPass: SatPass - private val _gsp = MutableLiveData(prefsManager.getStationPosition()) - fun getGSP(): LiveData = _gsp + private val _gsp = MutableLiveData(getStationPosition()) + fun getGSP(): LiveData = _gsp private val _selectedSat = MutableLiveData() fun getSelectedSat(): LiveData = _selectedSat @@ -54,70 +56,58 @@ class MapViewModel @ViewModelInject constructor(prefsManager: PrefsManager) : Vi fun setPasses(passesList: List) { filteredPasses = passesList.distinctBy { it.tle } - setSelectedSat(filteredPasses[0]) - calculatePositions(filteredPasses) - } - - fun changeSelection(decrement: Boolean) { - val index = filteredPasses.indexOf(_selectedSat.value?.pass) - if (decrement) { - if (index > 0) setSelectedSat(filteredPasses[index - 1]) - else setSelectedSat(filteredPasses[filteredPasses.size - 1]) - } else { - if (index < filteredPasses.size - 1) setSelectedSat(filteredPasses[index + 1]) - else setSelectedSat(filteredPasses[0]) - } - } - - fun setSelectedSat(pass: SatPass?) { - pass?.let { - viewModelScope.launch(Dispatchers.Default) { - val satPos = pass.predictor.getSatPos(dateNow) - val osmPos = getOsmPosition(satPos.latitude, satPos.longitude, true) - val qthLoc = Utilities.locToQTH(osmPos.lat, osmPos.lon) - val velocity = getSatVelocity(satPos.altitude) - val coverage = satPos.rangeCircleRadiusKm * 2 - val footprint = getSatFootprint(pass) - val track = getSatTrack(pass) - _selectedSat.postValue( - SelectedSat( - pass, pass.tle.catnum, pass.tle.name, satPos.range, - satPos.altitude, velocity, qthLoc, osmPos, coverage, footprint, track - ) - ) - } - } - } - - private fun calculatePositions(passes: List) { - val passesMap = mutableMapOf() + selectedPass = filteredPasses[0] viewModelScope.launch { while (true) { dateNow.time = System.currentTimeMillis() - passes.forEach { - val satPos = it.predictor.getSatPos(dateNow) - passesMap[it] = getOsmPosition(satPos.latitude, satPos.longitude, true) - } - setSelectedSat(_selectedSat.value?.pass) - _satMarkers.postValue(passesMap) + _selectedSat.value = getDataForSelSatellite(selectedPass) + _satMarkers.value = getDataForAllSatellites(filteredPasses) delay(2000) } } } - private fun getSatFootprint(pass: SatPass): Overlay { - val rangePoints = mutableListOf() - pass.predictor.getSatPos(dateNow).rangeCircle.withIndex().forEach { - val osmPos = getOsmPosition(it.value.lat, it.value.lon, false) - rangePoints.add(GeoPoint(osmPos.lat, osmPos.lon)) - } - return Polygon().apply { - fillPaint.set(footprintPaint) - outlinePaint.set(footprintPaint) - points = rangePoints + fun scrollSelection(decrement: Boolean) { + val index = filteredPasses.indexOf(selectedPass) + if (decrement) { + if (index > 0) selectSatellite(filteredPasses[index - 1]) + else selectSatellite(filteredPasses[filteredPasses.size - 1]) + } else { + if (index < filteredPasses.size - 1) selectSatellite(filteredPasses[index + 1]) + else selectSatellite(filteredPasses[0]) } } + fun selectSatellite(satPass: SatPass) { + selectedPass = satPass + viewModelScope.launch { _selectedSat.value = getDataForSelSatellite(selectedPass) } + } + + private suspend fun getDataForSelSatellite(pass: SatPass): SelectedSat = + withContext(Dispatchers.Default) { + val satPos = pass.predictor.getSatPos(dateNow) + val osmPos = getOsmPosition(satPos.latitude, satPos.longitude, true) + val qthLoc = Utilities.locToQTH(osmPos.lat, osmPos.lon) + val velocity = getSatVelocity(satPos.altitude) + val coverage = satPos.rangeCircleRadiusKm * 2 + val footprint = getSatFootprint(satPos) + val track = getSatTrack(pass) + return@withContext SelectedSat( + pass, pass.tle.catnum, pass.tle.name, satPos.range, + satPos.altitude, velocity, qthLoc, osmPos, coverage, footprint, track + ) + } + + private suspend fun getDataForAllSatellites(passes: List): Map = + withContext(Dispatchers.Default) { + val passesMap = mutableMapOf() + passes.forEach { + val satPos = it.predictor.getSatPos(dateNow) + passesMap[it] = getOsmPosition(satPos.latitude, satPos.longitude, true) + } + return@withContext passesMap + } + private fun getSatTrack(pass: SatPass): Overlay { val period = (24 * 60 / pass.tle.meanmo).toInt() val positions = pass.predictor.getPositions(dateNow, 20, 0, period * 3) @@ -147,6 +137,24 @@ class MapViewModel @ViewModelInject constructor(prefsManager: PrefsManager) : Vi return trackOverlay } + private fun getSatFootprint(satPos: SatPos): Overlay { + val rangePoints = mutableListOf() + satPos.rangeCircle.withIndex().forEach { + val osmPos = getOsmPosition(it.value.lat, it.value.lon, false) + rangePoints.add(GeoPoint(osmPos.lat, osmPos.lon)) + } + return Polygon().apply { + fillPaint.set(footprintPaint) + outlinePaint.set(footprintPaint) + points = rangePoints + } + } + + private fun getStationPosition(): Position { + val stationPosition = prefsManager.getStationPosition() + return getOsmPosition(stationPosition.latitude, stationPosition.longitude, false) + } + private fun getSatVelocity(altitude: Double): Double { val earthG = 6.674 * 10.0.pow(-11) val earthM = 5.98 * 10.0.pow(24) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 5003c2f6..8ea3a81e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -21,6 +21,7 @@ android:layout_width="match_parent" android:layout_height="48dp" app:elevation="1dp" + app:itemRippleColor="@android:color/transparent" app:labelVisibilityMode="labeled" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent"