Got rid of SatNotFoundExceptions in WorldMapFragment. Minor refactoring.

pull/30/head
Arty Bishop 2020-01-04 18:13:58 +00:00
rodzic f9438eb5f7
commit 80430df1cd
5 zmienionych plików z 68 dodań i 50 usunięć

Wyświetl plik

@ -22,7 +22,6 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: "androidx.navigation.safeargs.kotlin" apply plugin: "androidx.navigation.safeargs.kotlin"
apply plugin: 'com.google.android.gms.oss-licenses-plugin'
android { android {
compileSdkVersion 29 compileSdkVersion 29
@ -92,7 +91,4 @@ dependencies {
testImplementation "junit:junit:$junit" testImplementation "junit:junit:$junit"
androidTestImplementation "androidx.test:runner:$runner" androidTestImplementation "androidx.test:runner:$runner"
androidTestImplementation "androidx.test.espresso:espresso-core:$espresso" androidTestImplementation "androidx.test.espresso:espresso-core:$espresso"
// licences
implementation "com.google.android.gms:play-services-oss-licenses:$licences"
} }

Wyświetl plik

@ -34,28 +34,30 @@ import com.github.amsacode.predict4java.*
import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.rtbishop.look4sat.MainViewModel import com.rtbishop.look4sat.MainViewModel
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.repo.SatPass
import java.util.* import java.util.*
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.math.abs import kotlin.math.abs
class WorldMapFragment : Fragment() { class WorldMapFragment : Fragment() {
private val service = Executors.newSingleThreadScheduledExecutor() private lateinit var service: ScheduledExecutorService
private lateinit var mainActivity: MainActivity
private lateinit var viewModel: MainViewModel private lateinit var viewModel: MainViewModel
private lateinit var trackView: TrackView
private lateinit var mapFrame: FrameLayout private lateinit var mapFrame: FrameLayout
private lateinit var fab: FloatingActionButton private lateinit var fab: FloatingActionButton
private lateinit var trackView: TrackView
private lateinit var predictor: PassPredictor private lateinit var predictor: PassPredictor
private lateinit var mainActivity: MainActivity
private lateinit var selectedSat: TLE private lateinit var selectedSat: TLE
private lateinit var tleMainList: List<TLE>
private lateinit var tleSelection: MutableList<Int>
private lateinit var gsp: GroundStationPosition private lateinit var gsp: GroundStationPosition
private lateinit var satPassList: List<SatPass>
private var checkedItem = 0 private var checkedItem = 0
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
service = Executors.newSingleThreadScheduledExecutor()
mainActivity = activity as MainActivity mainActivity = activity as MainActivity
viewModel = ViewModelProvider(mainActivity).get(MainViewModel::class.java) viewModel = ViewModelProvider(mainActivity).get(MainViewModel::class.java)
} }
@ -81,14 +83,15 @@ class WorldMapFragment : Fragment() {
private fun setupComponents() { private fun setupComponents() {
val delay = viewModel.delay val delay = viewModel.delay
tleMainList = viewModel.tleMainList gsp = viewModel.gsp.value ?: GroundStationPosition(0.0, 0.0, 0.0)
tleSelection = viewModel.tleSelection satPassList = viewModel.passSatList.value ?: emptyList()
gsp = viewModel.gsp.value!!
if (tleMainList.isNotEmpty() && tleSelection.isNotEmpty()) { if (satPassList.isNotEmpty()) {
fab.setOnClickListener { showSelectSatDialog(tleMainList, tleSelection) } satPassList = satPassList.distinctBy { it.tle }
selectedSat = tleMainList[tleSelection[0]] satPassList = satPassList.sortedBy { it.tle.name }
predictor = PassPredictor(selectedSat, viewModel.gsp.value) fab.setOnClickListener { showSelectSatDialog(satPassList) }
selectedSat = satPassList.first().tle
predictor = satPassList.first().predictor
trackView = TrackView(mainActivity) trackView = TrackView(mainActivity)
mapFrame.addView(trackView) mapFrame.addView(trackView)
service.scheduleAtFixedRate( service.scheduleAtFixedRate(
@ -108,19 +111,19 @@ class WorldMapFragment : Fragment() {
} }
} }
private fun showSelectSatDialog(tleMainList: List<TLE>, selectionList: MutableList<Int>) { private fun showSelectSatDialog(list: List<SatPass>) {
val tleNameArray = arrayOfNulls<String>(selectionList.size).apply { val tleArray = arrayOfNulls<String>(list.size).apply {
selectionList.withIndex().forEach { (index, selection) -> list.withIndex().forEach {
this[index] = tleMainList[selection].name this[it.index] = it.value.tle.name
} }
} }
val builder = AlertDialog.Builder(mainActivity) val builder = AlertDialog.Builder(mainActivity)
builder.setTitle(getString(R.string.dialog_show_track)) builder.setTitle(getString(R.string.dialog_show_track))
.setSingleChoiceItems(tleNameArray, checkedItem) { dialog, which -> .setSingleChoiceItems(tleArray, checkedItem) { dialog, which ->
checkedItem = which checkedItem = which
selectedSat = tleMainList[selectionList[which]] selectedSat = list[which].tle
predictor = PassPredictor(selectedSat, gsp) predictor = list[which].predictor
trackView.invalidate() trackView.invalidate()
dialog.dismiss() dialog.dismiss()
} }
@ -164,24 +167,22 @@ class WorldMapFragment : Fragment() {
val degLon = width / 360f val degLon = width / 360f
val degLat = height / 180f val degLat = height / 180f
drawHomeLoc(canvas, degLon, degLat) drawHomeLoc(canvas, degLon, degLat)
val currentTime = getDateFor(System.currentTimeMillis()) val currentTime = getDateFor(System.currentTimeMillis())
val orbitalPeriod = (24 * 60 / selectedSat.meanmo).toInt() val orbitalPeriod = (24 * 60 / selectedSat.meanmo).toInt()
val satPosList = predictor.getPositions(currentTime, 60, 0, orbitalPeriod * 3) val positions = predictor.getPositions(currentTime, 60, 0, orbitalPeriod * 3)
drawGroundTrack(canvas, degLon, degLat, satPosList) drawGroundTrack(canvas, degLon, degLat, positions)
satPassList.forEach {
tleSelection.forEach { drawSat(canvas, degLon, degLat, it.tle, it.predictor, currentTime)
drawSat(it, currentTime, canvas, degLon, degLat)
} }
} }
private fun drawHomeLoc(cvs: Canvas, degLon: Float, degLat: Float) { private fun drawHomeLoc(canvas: Canvas, degLon: Float, degLat: Float) {
val lon = gsp.longitude.toFloat() val lon = gsp.longitude.toFloat()
val lat = gsp.latitude.toFloat() * -1 val lat = gsp.latitude.toFloat() * -1
val cx = lon * degLon val cx = lon * degLon
val cy = lat * degLat val cy = lat * degLat
cvs.drawCircle(cx, cy, scale * 2, txtPaint) canvas.drawCircle(cx, cy, scale * 2, txtPaint)
cvs.drawText( canvas.drawText(
context.getString(R.string.map_gsp), context.getString(R.string.map_gsp),
cx - txtPaint.textSize, cx - txtPaint.textSize,
cy - txtPaint.textSize, cy - txtPaint.textSize,
@ -189,7 +190,12 @@ class WorldMapFragment : Fragment() {
) )
} }
private fun drawGroundTrack(cvs: Canvas, degLon: Float, degLat: Float, list: List<SatPos>) { private fun drawGroundTrack(
canvas: Canvas,
degLon: Float,
degLat: Float,
list: List<SatPos>
) {
val path = Path() val path = Path()
var lon: Float var lon: Float
var lat: Float var lat: Float
@ -209,19 +215,29 @@ class WorldMapFragment : Fragment() {
lastLon = lon lastLon = lon
} }
cvs.drawPath(path, groundTrackPaint) canvas.drawPath(path, groundTrackPaint)
} }
private fun drawSat(index: Int, date: Date, canvas: Canvas, degLon: Float, degLat: Float) { private fun drawSat(
val tle = tleMainList[index] canvas: Canvas,
val predictor = PassPredictor(tle, gsp) degLon: Float,
degLat: Float,
tle: TLE,
predictor: PassPredictor,
date: Date
) {
val satPosNow = predictor.getSatPos(date) val satPosNow = predictor.getSatPos(date)
val footprintPosList = satPosNow.rangeCircle val footprintPosList = satPosNow.rangeCircle
drawFootprint(canvas, degLon, degLat, footprintPosList) drawFootprint(canvas, degLon, degLat, footprintPosList)
drawName(canvas, degLon, degLat, satPosNow, tle.name) drawName(canvas, degLon, degLat, satPosNow, tle.name)
} }
private fun drawFootprint(cvs: Canvas, degLon: Float, degLat: Float, list: List<Position>) { private fun drawFootprint(
canvas: Canvas,
degLon: Float,
degLat: Float,
list: List<Position>
) {
val path = Path() val path = Path()
var lon: Float var lon: Float
var lat: Float var lat: Float
@ -241,19 +257,28 @@ class WorldMapFragment : Fragment() {
lastLon = lon lastLon = lon
} }
cvs.drawPath(path, footprintPaint) canvas.drawPath(path, footprintPaint)
} }
private fun drawName(cvs: Canvas, degLon: Float, degLat: Float, pos: SatPos, name: String) { private fun drawName(
var lon = rad2Deg(pos.longitude).toFloat() canvas: Canvas,
val lat = rad2Deg(pos.latitude).toFloat() * -1 degLon: Float,
degLat: Float,
position: SatPos,
name: String
) {
var lon = rad2Deg(position.longitude).toFloat()
val lat = rad2Deg(position.latitude).toFloat() * -1
if (lon > 180f) lon -= 360f if (lon > 180f) lon -= 360f
val cx = lon * degLon val cx = lon * degLon
val cy = lat * degLat val cy = lat * degLat
cvs.drawCircle(cx, cy, scale * 2, txtPaint)
canvas.drawCircle(cx, cy, scale * 2, txtPaint)
txtPaint.getTextBounds(name, 0, name.length, rect) txtPaint.getTextBounds(name, 0, name.length, rect)
cvs.drawText(name, cx - rect.width() / 2, cy - txtPaint.textSize, outlinePaint) canvas.drawText(name, cx - rect.width() / 2, cy - txtPaint.textSize, outlinePaint)
cvs.drawText(name, cx - rect.width() / 2, cy - txtPaint.textSize, txtPaint) canvas.drawText(name, cx - rect.width() / 2, cy - txtPaint.textSize, txtPaint)
} }
private fun getDateFor(value: Long): Date { private fun getDateFor(value: Long): Date {

Wyświetl plik

@ -68,6 +68,4 @@ ext {
junit = "4.12" junit = "4.12"
runner = '1.1.1' runner = '1.1.1'
espresso = '3.2.0' espresso = '3.2.0'
licences = '17.0.0'
} }

Wyświetl plik

@ -18,5 +18,4 @@ android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX # Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete": # Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official kotlin.code.style=official
kapt.incremental.apt=true

Wyświetl plik

@ -1,2 +1,2 @@
include ':app' include ':app'
rootProject.name='LookingSat' rootProject.name='Look4Sat'