mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Further changes to MapViewModel.kt, removed bottomNav ripple effect
This commit is contained in:
1 parent
4556d2d975
commit
f055d96e5a
3 files changed
+85
-94
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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<SatPass>()
|
||||
private lateinit var selectedPass: SatPass
|
||||
|
||||
private val _gsp = MutableLiveData(prefsManager.getStationPosition())
|
||||
fun getGSP(): LiveData<GroundStationPosition> = _gsp
|
||||
private val _gsp = MutableLiveData(getStationPosition())
|
||||
fun getGSP(): LiveData<Position> = _gsp
|
||||
|
||||
private val _selectedSat = MutableLiveData<SelectedSat>()
|
||||
fun getSelectedSat(): LiveData<SelectedSat> = _selectedSat
|
||||
@@ -54,70 +56,58 @@ class MapViewModel @ViewModelInject constructor(prefsManager: PrefsManager) : Vi
|
||||
|
||||
fun setPasses(passesList: List<SatPass>) {
|
||||
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<SatPass>) {
|
||||
val passesMap = mutableMapOf<SatPass, Position>()
|
||||
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<GeoPoint>()
|
||||
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<SatPass>): Map<SatPass, Position> =
|
||||
withContext(Dispatchers.Default) {
|
||||
val passesMap = mutableMapOf<SatPass, Position>()
|
||||
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<GeoPoint>()
|
||||
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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in new issue
Block a user