Implemented RadarView to show the selected pass trajectory and the current sat position if overhead

pull/30/head
Arty Bishop 2019-11-28 10:43:04 +00:00
rodzic 6f4ab63b4a
commit e88b78d4c6
1 zmienionych plików z 119 dodań i 0 usunięć

Wyświetl plik

@ -1,5 +1,7 @@
package com.rtbishop.lookingsat.ui
import android.content.Context
import android.graphics.*
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -7,14 +9,23 @@ import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import com.github.amsacode.predict4java.SatPos
import com.rtbishop.lookingsat.R
import com.rtbishop.lookingsat.repo.SatPass
import java.util.*
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import kotlin.math.cos
import kotlin.math.sin
class RadarFragment : Fragment() {
private lateinit var satPass: SatPass
private lateinit var radarView: RadarView
private lateinit var radarSkyFrame: FrameLayout
private lateinit var radarRecycler: RecyclerView
private val service = Executors.newSingleThreadScheduledExecutor()
private val delay = 5000L
override fun onCreateView(
inflater: LayoutInflater,
@ -29,5 +40,113 @@ class RadarFragment : Fragment() {
satPass = arguments?.get("satPass") as SatPass
radarSkyFrame = view.findViewById(R.id.radar_sky_frame)
radarRecycler = view.findViewById(R.id.radar_recycler)
radarView = RadarView(activity as MainActivity)
radarSkyFrame.addView(radarView)
service.scheduleAtFixedRate({ radarView.invalidate() }, delay, delay, TimeUnit.MILLISECONDS)
}
inner class RadarView(context: Context) : View(context) {
private val radarSize = resources.displayMetrics.widthPixels
private val scale = resources.displayMetrics.density
private val startTime = satPass.pass.startTime
private val endTime = satPass.pass.endTime
private val radius = radarSize * 0.45f
private val piDiv2 = Math.PI / 2.0
private val txtSize = scale * 15
private val center = 0f
private val bmp: Bitmap = Bitmap.createBitmap(radarSize, radarSize, Bitmap.Config.ARGB_8888)
private val mtrx: Matrix = Matrix().apply {
postTranslate(radarSize / 2f, radarSize / 2f)
}
private val cvs: Canvas = Canvas().apply {
setBitmap(bmp)
setMatrix(mtrx)
}
private val linePaint = Paint().apply {
isAntiAlias = true
color = Color.parseColor("#C0C0C0")
style = Paint.Style.STROKE
strokeWidth = scale
}
private val txtPaint = Paint().apply {
isAntiAlias = true
color = Color.parseColor("#FFE082")
textSize = txtSize
}
private val passPaint = Paint().apply {
isAntiAlias = true
color = Color.RED
style = Paint.Style.STROKE
strokeWidth = scale
}
private val satPaint = Paint().apply {
isAntiAlias = true
color = Color.parseColor("#FFE082")
style = Paint.Style.FILL
}
private val path: Path = Path()
override fun onDraw(canvas: Canvas) {
var satPos: SatPos
var satPassX: Float
var satPassY: Float
bmp.eraseColor(Color.TRANSPARENT)
cvs.drawLine(center - radius, center, center + radius, center, linePaint)
cvs.drawLine(center, center - radius, center, center + radius, linePaint)
cvs.drawCircle(center, center, radius, linePaint)
cvs.drawCircle(center, center, (radius / 3) * 2, linePaint)
cvs.drawCircle(center, center, radius / 3, linePaint)
cvs.drawText("N", center - txtSize / 3, center - radius - scale * 2, txtPaint)
cvs.drawText("E", center + radius + scale * 2, center + txtSize / 3, txtPaint)
cvs.drawText("S", center - txtSize / 3, center + radius + txtSize, txtPaint)
cvs.drawText("W", center - radius - txtSize, center + txtSize / 3, txtPaint)
cvs.drawText("", center + scale, center - scale * 2, txtPaint)
cvs.drawText("30°", center + scale, center - (radius / 3) - scale * 2, txtPaint)
cvs.drawText("60°", center + scale, center - ((radius / 3) * 2) - scale * 2, txtPaint)
while (startTime.before(endTime)) {
satPos = satPass.predictor.getSatPos(startTime)
satPassX = center + sph2CartX(satPos.azimuth, satPos.elevation, radius.toDouble())
satPassY = center - sph2CartY(satPos.azimuth, satPos.elevation, radius.toDouble())
if (startTime.compareTo(satPass.pass.startTime) == 0) {
path.moveTo(satPassX, satPassY)
} else {
path.lineTo(satPassX, satPassY)
}
startTime.time += delay
}
cvs.drawPath(path, passPaint)
satPos = satPass.predictor.getSatPos(getCurrentDate())
if (satPos.elevation > 0) {
cvs.drawCircle(
center + sph2CartX(satPos.azimuth, satPos.elevation, radius.toDouble()),
center - sph2CartY(satPos.azimuth, satPos.elevation, radius.toDouble()),
txtSize / 3, satPaint
)
}
canvas.drawBitmap(bmp, left.toFloat(), top.toFloat(), null)
}
private fun sph2CartX(azimuth: Double, elevation: Double, r: Double): Float {
val radius = r * (piDiv2 - elevation) / piDiv2
return (radius * cos(piDiv2 - azimuth)).toFloat()
}
private fun sph2CartY(azimuth: Double, elevation: Double, r: Double): Float {
val radius = r * (piDiv2 - elevation) / piDiv2
return (radius * sin(piDiv2 - azimuth)).toFloat()
}
private fun getCurrentDate(): Date {
return Date()
}
}
}