kopia lustrzana https://github.com/rt-bishop/Look4Sat
Got rid of SatNotFoundExceptions in WorldMapFragment. Minor refactoring.
rodzic
f9438eb5f7
commit
80430df1cd
|
@ -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"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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'
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
|
@ -1,2 +1,2 @@
|
||||||
include ':app'
|
include ':app'
|
||||||
rootProject.name='LookingSat'
|
rootProject.name='Look4Sat'
|
||||||
|
|
Ładowanie…
Reference in New Issue