mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Added PolarView rotation using sensors data
This commit is contained in:
1 parent
1824cd8af0
commit
80b62b4658
6 files changed
+249
-221
No files matched your search
@@ -41,6 +41,7 @@ import com.rtbishop.look4sat.data.SatPass
|
||||
import com.rtbishop.look4sat.databinding.FragmentMapViewBinding
|
||||
import com.rtbishop.look4sat.ui.MainActivity
|
||||
import com.rtbishop.look4sat.ui.SharedViewModel
|
||||
import com.rtbishop.look4sat.utility.GeneralUtils
|
||||
import com.rtbishop.look4sat.utility.PassPredictor
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -182,7 +183,7 @@ class MapViewFragment : Fragment(R.layout.fragment_map_view) {
|
||||
val degLon = width / 360f
|
||||
val degLat = height / 180f
|
||||
drawHomeLoc(canvas, degLon, degLat)
|
||||
val currentTime = getDateFor(System.currentTimeMillis())
|
||||
val currentTime = GeneralUtils.getDateFor(System.currentTimeMillis())
|
||||
val orbitalPeriod = (24 * 60 / selectedSat.meanmo).toInt()
|
||||
val positions = predictor.getPositions(currentTime, 60, 0, orbitalPeriod * 3)
|
||||
setTextViewsToSelectedSatPos(positions[0])
|
||||
@@ -215,8 +216,8 @@ class MapViewFragment : Fragment(R.layout.fragment_map_view) {
|
||||
}
|
||||
|
||||
private fun setTextViewsToSelectedSatPos(position: SatPos) {
|
||||
var lon = rad2Deg(position.longitude).toFloat()
|
||||
val lat = rad2Deg(position.latitude).toFloat()
|
||||
var lon = GeneralUtils.rad2Deg(position.longitude).toFloat()
|
||||
val lat = GeneralUtils.rad2Deg(position.latitude).toFloat()
|
||||
val rng = position.range
|
||||
|
||||
if (lon > 180f) lon -= 360f
|
||||
@@ -238,8 +239,8 @@ class MapViewFragment : Fragment(R.layout.fragment_map_view) {
|
||||
var lastLon = 181f
|
||||
|
||||
list.withIndex().forEach { (index, satPos) ->
|
||||
lon = rad2Deg(satPos.longitude).toFloat()
|
||||
lat = rad2Deg(satPos.latitude).toFloat() * -1
|
||||
lon = GeneralUtils.rad2Deg(satPos.longitude).toFloat()
|
||||
lat = GeneralUtils.rad2Deg(satPos.latitude).toFloat() * -1
|
||||
|
||||
if (lon > 180f) lon -= 360f
|
||||
|
||||
@@ -305,8 +306,8 @@ class MapViewFragment : Fragment(R.layout.fragment_map_view) {
|
||||
position: SatPos,
|
||||
name: String
|
||||
) {
|
||||
var lon = rad2Deg(position.longitude).toFloat()
|
||||
val lat = rad2Deg(position.latitude).toFloat() * -1
|
||||
var lon = GeneralUtils.rad2Deg(position.longitude).toFloat()
|
||||
val lat = GeneralUtils.rad2Deg(position.latitude).toFloat() * -1
|
||||
|
||||
if (lon > 180f) lon -= 360f
|
||||
|
||||
@@ -318,13 +319,5 @@ class MapViewFragment : Fragment(R.layout.fragment_map_view) {
|
||||
canvas.drawText(name, cx - rect.width() / 2, cy - txtPaint.textSize, outlinePaint)
|
||||
canvas.drawText(name, cx - rect.width() / 2, cy - txtPaint.textSize, txtPaint)
|
||||
}
|
||||
|
||||
private fun getDateFor(value: Long): Date {
|
||||
return Date(value)
|
||||
}
|
||||
|
||||
private fun rad2Deg(value: Double): Double {
|
||||
return value * 180 / Math.PI
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,18 +20,18 @@
|
||||
package com.rtbishop.look4sat.ui.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Path
|
||||
import android.hardware.Sensor
|
||||
import android.hardware.SensorEvent
|
||||
import android.hardware.SensorEventListener
|
||||
import android.hardware.SensorManager
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.github.amsacode.predict4java.SatPos
|
||||
import com.rtbishop.look4sat.Look4SatApp
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.dagger.ViewModelFactory
|
||||
@@ -41,225 +41,136 @@ import com.rtbishop.look4sat.databinding.FragmentPolarViewBinding
|
||||
import com.rtbishop.look4sat.ui.MainActivity
|
||||
import com.rtbishop.look4sat.ui.SharedViewModel
|
||||
import com.rtbishop.look4sat.ui.adapters.TransmitterAdapter
|
||||
import com.rtbishop.look4sat.ui.views.PolarView
|
||||
import com.rtbishop.look4sat.utility.GeneralUtils
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class PolarViewFragment : Fragment(R.layout.fragment_polar_view) {
|
||||
class PolarViewFragment : Fragment(R.layout.fragment_polar_view), SensorEventListener {
|
||||
|
||||
@Inject
|
||||
lateinit var modelFactory: ViewModelFactory
|
||||
private val args: PolarViewFragmentArgs by navArgs()
|
||||
private lateinit var mainActivity: MainActivity
|
||||
private lateinit var viewModel: SharedViewModel
|
||||
private lateinit var binding: FragmentPolarViewBinding
|
||||
private lateinit var satPass: SatPass
|
||||
private lateinit var polarView: PolarView
|
||||
private lateinit var mainActivity: MainActivity
|
||||
private var transmitterAdapter: TransmitterAdapter = TransmitterAdapter()
|
||||
private lateinit var sensorManager: SensorManager
|
||||
|
||||
private val args: PolarViewFragmentArgs by navArgs()
|
||||
private val transmitterAdapter = TransmitterAdapter()
|
||||
private var lastAccData = FloatArray(3)
|
||||
private var lastMagData = FloatArray(3)
|
||||
private var refreshJob: Job? = null
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val binding = FragmentPolarViewBinding.bind(view)
|
||||
mainActivity = activity as MainActivity
|
||||
binding = FragmentPolarViewBinding.bind(view)
|
||||
(mainActivity.application as Look4SatApp).appComponent.inject(this)
|
||||
viewModel = ViewModelProvider(mainActivity, modelFactory).get(SharedViewModel::class.java)
|
||||
val refreshRate = viewModel.getRefreshRate()
|
||||
|
||||
sensorManager = mainActivity.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
binding.recPolar.apply {
|
||||
layoutManager = LinearLayoutManager(mainActivity)
|
||||
adapter = transmitterAdapter
|
||||
}
|
||||
|
||||
observePasses(refreshRate, binding)
|
||||
observePasses()
|
||||
}
|
||||
|
||||
private fun observePasses(
|
||||
refreshRate: Long,
|
||||
binding: FragmentPolarViewBinding
|
||||
) {
|
||||
viewModel.getPassList()
|
||||
.observe(viewLifecycleOwner, androidx.lifecycle.Observer { result ->
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
satPass = result.data[args.satPassIndex]
|
||||
mainActivity.supportActionBar?.title = satPass.tle.name
|
||||
polarView = PolarView(mainActivity, refreshRate, binding)
|
||||
binding.framePolar.addView(polarView)
|
||||
observeTransmitters(binding)
|
||||
refreshView()
|
||||
}
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER).also { accData ->
|
||||
sensorManager.registerListener(this, accData, SensorManager.SENSOR_DELAY_GAME)
|
||||
}
|
||||
sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD).also { magData ->
|
||||
sensorManager.registerListener(this, magData, SensorManager.SENSOR_DELAY_GAME)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
sensorManager.unregisterListener(this)
|
||||
}
|
||||
|
||||
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
|
||||
|
||||
override fun onSensorChanged(event: SensorEvent?) {
|
||||
event?.let {
|
||||
if (it.sensor.type == Sensor.TYPE_ACCELEROMETER) {
|
||||
filterSensorData(event.values, lastAccData)
|
||||
} else if (it.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) {
|
||||
filterSensorData(event.values, lastMagData)
|
||||
}
|
||||
|
||||
val rotationMatrix = FloatArray(9)
|
||||
if (SensorManager.getRotationMatrix(rotationMatrix, null, lastAccData, lastMagData)) {
|
||||
val orientation = FloatArray(3)
|
||||
SensorManager.getOrientation(rotationMatrix, orientation)
|
||||
val degree = orientation[0] * 57.2957795f
|
||||
polarView.rotation = -degree
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun filterSensorData(input: FloatArray, output: FloatArray) {
|
||||
val filterStep = 0.05f
|
||||
input.indices.forEach { output[it] = output[it] + filterStep * (input[it] - output[it]) }
|
||||
}
|
||||
|
||||
private fun observePasses() {
|
||||
viewModel.getPassList().observe(viewLifecycleOwner, Observer { result ->
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
val refreshRate = viewModel.getRefreshRate()
|
||||
satPass = result.data[args.satPassIndex]
|
||||
mainActivity.supportActionBar?.title = satPass.tle.name
|
||||
polarView = PolarView(mainActivity, satPass)
|
||||
binding.framePolar.addView(polarView)
|
||||
observeTransmitters()
|
||||
refreshText(refreshRate)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun observeTransmitters(binding: FragmentPolarViewBinding) {
|
||||
viewModel.getTransmittersForSat(satPass.tle.catnum)
|
||||
.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
|
||||
if (it.isNotEmpty()) {
|
||||
transmitterAdapter.setList(it)
|
||||
transmitterAdapter.notifyDataSetChanged()
|
||||
binding.recPolar.visibility = View.VISIBLE
|
||||
binding.tvPolarNoTrans.visibility = View.INVISIBLE
|
||||
} else {
|
||||
binding.recPolar.visibility = View.INVISIBLE
|
||||
binding.tvPolarNoTrans.visibility = View.VISIBLE
|
||||
}
|
||||
})
|
||||
private fun observeTransmitters() {
|
||||
viewModel.getTransmittersForSat(satPass.tle.catnum).observe(viewLifecycleOwner, Observer {
|
||||
if (it.isNotEmpty()) {
|
||||
transmitterAdapter.setList(it)
|
||||
transmitterAdapter.notifyDataSetChanged()
|
||||
binding.recPolar.visibility = View.VISIBLE
|
||||
binding.tvPolarNoTrans.visibility = View.INVISIBLE
|
||||
} else {
|
||||
binding.recPolar.visibility = View.INVISIBLE
|
||||
binding.tvPolarNoTrans.visibility = View.VISIBLE
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun refreshView() {
|
||||
val rate = viewModel.getRefreshRate()
|
||||
lifecycleScope.launch {
|
||||
private fun refreshText(rate: Long) {
|
||||
refreshJob?.cancel()
|
||||
refreshJob = null
|
||||
refreshJob = lifecycleScope.launch {
|
||||
while (true) {
|
||||
setPassText()
|
||||
polarView.invalidate()
|
||||
delay(rate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class PolarView(
|
||||
context: Context,
|
||||
private val updateFreq: Long,
|
||||
private val binding: FragmentPolarViewBinding
|
||||
) :
|
||||
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 radarPaint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
color = ContextCompat.getColor(mainActivity, R.color.themeLight)
|
||||
style = Paint.Style.STROKE
|
||||
strokeWidth = scale
|
||||
}
|
||||
private val txtPaint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
color = ContextCompat.getColor(mainActivity, R.color.themeAccent)
|
||||
textSize = txtSize
|
||||
}
|
||||
private val trackPaint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
color = ContextCompat.getColor(mainActivity, R.color.satTrack)
|
||||
style = Paint.Style.STROKE
|
||||
strokeWidth = scale
|
||||
}
|
||||
private val satPaint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
color = ContextCompat.getColor(mainActivity, R.color.themeAccent)
|
||||
style = Paint.Style.FILL
|
||||
}
|
||||
private val path: Path = Path()
|
||||
|
||||
private lateinit var satPos: SatPos
|
||||
private var satPassX = 0f
|
||||
private var satPassY = 0f
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
canvas.translate(radarSize / 2f, radarSize / 2f)
|
||||
setPassText()
|
||||
drawRadarView(canvas)
|
||||
drawRadarText(canvas)
|
||||
if (!satPass.tle.isDeepspace) drawPassTrajectory(canvas)
|
||||
drawSatellite(canvas)
|
||||
}
|
||||
|
||||
private fun setPassText() {
|
||||
satPos = satPass.predictor.getSatPos(Date())
|
||||
binding.tvPolarAz.text =
|
||||
String.format(context.getString(R.string.pat_azimuth), rad2Deg(satPos.azimuth))
|
||||
binding.tvPolarEl.text =
|
||||
String.format(context.getString(R.string.pat_elevation), rad2Deg(satPos.elevation))
|
||||
binding.tvPolarRng.text =
|
||||
String.format(context.getString(R.string.pat_range), satPos.range)
|
||||
binding.tvPolarAlt.text =
|
||||
String.format(context.getString(R.string.pat_altitude), satPos.altitude)
|
||||
}
|
||||
|
||||
private fun drawRadarView(cvs: Canvas) {
|
||||
cvs.drawLine(center - radius, center, center + radius, center, radarPaint)
|
||||
cvs.drawLine(center, center - radius, center, center + radius, radarPaint)
|
||||
cvs.drawCircle(center, center, radius, radarPaint)
|
||||
cvs.drawCircle(center, center, (radius / 3) * 2, radarPaint)
|
||||
cvs.drawCircle(center, center, radius / 3, radarPaint)
|
||||
}
|
||||
|
||||
private fun drawRadarText(cvs: Canvas) {
|
||||
cvs.drawText(
|
||||
context.getString(R.string.polar_north),
|
||||
center - txtSize / 3,
|
||||
center - radius - scale * 2,
|
||||
txtPaint
|
||||
)
|
||||
cvs.drawText(
|
||||
context.getString(R.string.polar_east),
|
||||
center + radius + scale * 2,
|
||||
center + txtSize / 3,
|
||||
txtPaint
|
||||
)
|
||||
cvs.drawText(
|
||||
context.getString(R.string.polar_south),
|
||||
center - txtSize / 3,
|
||||
center + radius + txtSize,
|
||||
txtPaint
|
||||
)
|
||||
cvs.drawText(
|
||||
context.getString(R.string.polar_west),
|
||||
center - radius - txtSize,
|
||||
center + txtSize / 3,
|
||||
txtPaint
|
||||
)
|
||||
cvs.drawText("90°", center + scale, center - scale * 2, txtPaint)
|
||||
cvs.drawText("60°", center + scale, center - (radius / 3) - scale * 2, txtPaint)
|
||||
cvs.drawText("30°", center + scale, center - ((radius / 3) * 2) - scale * 2, txtPaint)
|
||||
}
|
||||
|
||||
private fun drawPassTrajectory(cvs: Canvas) {
|
||||
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 += updateFreq
|
||||
}
|
||||
cvs.drawPath(path, trackPaint)
|
||||
}
|
||||
|
||||
private fun drawSatellite(cvs: Canvas) {
|
||||
satPos = satPass.predictor.getSatPos(Date())
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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 rad2Deg(value: Double): Double {
|
||||
return value * 180 / Math.PI
|
||||
}
|
||||
private fun setPassText() {
|
||||
val satPos = satPass.predictor.getSatPos(Date())
|
||||
val polarAz = mainActivity.getString(R.string.pat_azimuth)
|
||||
val polarEl = mainActivity.getString(R.string.pat_elevation)
|
||||
val polarRng = mainActivity.getString(R.string.pat_range)
|
||||
val polarAlt = mainActivity.getString(R.string.pat_altitude)
|
||||
binding.tvPolarAz.text = String.format(polarAz, GeneralUtils.rad2Deg(satPos.azimuth))
|
||||
binding.tvPolarEl.text = String.format(polarEl, GeneralUtils.rad2Deg(satPos.elevation))
|
||||
binding.tvPolarRng.text = String.format(polarRng, satPos.range)
|
||||
binding.tvPolarAlt.text = String.format(polarAlt, satPos.altitude)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.rtbishop.look4sat.ui.views
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.Paint
|
||||
import android.graphics.Path
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.SatPass
|
||||
import com.rtbishop.look4sat.utility.GeneralUtils
|
||||
|
||||
class PolarView(context: Context) : View(context) {
|
||||
|
||||
constructor(context: Context, satPass: SatPass) : this(context) {
|
||||
pass = satPass
|
||||
}
|
||||
|
||||
private lateinit var pass: SatPass
|
||||
private val polarWidth = resources.displayMetrics.widthPixels
|
||||
private val polarCenter = polarWidth / 2f
|
||||
private val scale = resources.displayMetrics.density
|
||||
private val radius = polarWidth * 0.49f
|
||||
private val txtSize = scale * 15
|
||||
private val path: Path = Path()
|
||||
private val mMatrix = Matrix()
|
||||
var azimuth = 0f
|
||||
|
||||
private val radarPaint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
color = ContextCompat.getColor(context, R.color.themeLight)
|
||||
style = Paint.Style.STROKE
|
||||
strokeWidth = scale
|
||||
}
|
||||
private val txtPaint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
color = ContextCompat.getColor(context, R.color.themeAccent)
|
||||
textSize = txtSize
|
||||
}
|
||||
private val trackPaint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
color = ContextCompat.getColor(context, R.color.satTrack)
|
||||
style = Paint.Style.STROKE
|
||||
strokeWidth = scale
|
||||
}
|
||||
private val satPaint = Paint().apply {
|
||||
isAntiAlias = true
|
||||
color = ContextCompat.getColor(context, R.color.themeAccent)
|
||||
style = Paint.Style.FILL
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
// Log.w("myTag", "$measuredWidth, $measuredHeight")
|
||||
canvas.rotate(-azimuth, polarCenter, polarCenter)
|
||||
canvas.translate(polarCenter, polarCenter)
|
||||
drawRadarView(canvas)
|
||||
drawRadarText(canvas)
|
||||
if (!pass.tle.isDeepspace) {
|
||||
drawPassTrajectory(canvas, pass)
|
||||
}
|
||||
drawSatellite(canvas, pass)
|
||||
}
|
||||
|
||||
private fun drawRadarView(cvs: Canvas) {
|
||||
cvs.drawLine(-radius, 0f, radius, 0f, radarPaint)
|
||||
cvs.drawLine(0f, -radius, 0f, radius, radarPaint)
|
||||
cvs.drawCircle(0f, 0f, radius, radarPaint)
|
||||
cvs.drawCircle(0f, 0f, (radius / 3) * 2, radarPaint)
|
||||
cvs.drawCircle(0f, 0f, radius / 3, radarPaint)
|
||||
}
|
||||
|
||||
private fun drawRadarText(cvs: Canvas) {
|
||||
cvs.drawText("N", scale, -radius + txtSize - scale * 2, txtPaint)
|
||||
cvs.drawText("30°", scale, -((radius / 3) * 2) - scale * 2, txtPaint)
|
||||
cvs.drawText("60°", scale, -(radius / 3) - scale * 2, txtPaint)
|
||||
cvs.drawText("90°", scale, -scale * 2, txtPaint)
|
||||
}
|
||||
|
||||
private fun drawPassTrajectory(cvs: Canvas, satPass: SatPass) {
|
||||
val startTime = satPass.pass.startTime
|
||||
val endTime = satPass.pass.endTime
|
||||
while (startTime.before(endTime)) {
|
||||
val satPos = satPass.predictor.getSatPos(startTime)
|
||||
val x = GeneralUtils.sph2CartX(satPos.azimuth, satPos.elevation, radius.toDouble())
|
||||
val y = GeneralUtils.sph2CartY(satPos.azimuth, satPos.elevation, radius.toDouble())
|
||||
if (startTime.compareTo(satPass.pass.startTime) == 0) {
|
||||
path.moveTo(x, -y)
|
||||
} else {
|
||||
path.lineTo(x, -y)
|
||||
}
|
||||
startTime.time += 15000
|
||||
}
|
||||
cvs.drawPath(path, trackPaint)
|
||||
}
|
||||
|
||||
private fun drawSatellite(cvs: Canvas, satPass: SatPass) {
|
||||
val date = GeneralUtils.getDateFor(System.currentTimeMillis())
|
||||
val satPos = satPass.predictor.getSatPos(date)
|
||||
if (satPos.elevation > 0) {
|
||||
val x = GeneralUtils.sph2CartX(satPos.azimuth, satPos.elevation, radius.toDouble())
|
||||
val y = GeneralUtils.sph2CartY(satPos.azimuth, satPos.elevation, radius.toDouble())
|
||||
cvs.drawCircle(x, -y, txtSize / 3, satPaint)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.rtbishop.look4sat.utility
|
||||
|
||||
import java.util.*
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
object GeneralUtils {
|
||||
|
||||
private const val piDiv2 = Math.PI / 2.0
|
||||
|
||||
fun getDateFor(value: Long): Date {
|
||||
return Date(value)
|
||||
}
|
||||
|
||||
fun rad2Deg(value: Double): Double {
|
||||
return value * 180 / Math.PI
|
||||
}
|
||||
|
||||
fun sph2CartX(azimuth: Double, elevation: Double, r: Double): Float {
|
||||
val radius = r * (piDiv2 - elevation) / piDiv2
|
||||
return (radius * cos(piDiv2 - azimuth)).toFloat()
|
||||
}
|
||||
|
||||
fun sph2CartY(azimuth: Double, elevation: Double, r: Double): Float {
|
||||
val radius = r * (piDiv2 - elevation) / piDiv2
|
||||
return (radius * sin(piDiv2 - azimuth)).toFloat()
|
||||
}
|
||||
}
|
||||
@@ -77,11 +77,6 @@
|
||||
<string name="pass_maxEl">Элевация: %.1f°</string>
|
||||
<string name="pass_los_az">%2d° — КПС</string>
|
||||
|
||||
<string name="polar_north">С</string>
|
||||
<string name="polar_west">З</string>
|
||||
<string name="polar_south">Ю</string>
|
||||
<string name="polar_east">В</string>
|
||||
|
||||
<string name="pat_azimuth">Азимут: %.1f°</string>
|
||||
<string name="pat_elevation">Элевация: %.1f°</string>
|
||||
<string name="pat_latitude">Широта: %.1f°</string>
|
||||
|
||||
@@ -91,18 +91,13 @@
|
||||
<string name="pass_los_az">%2d° — LOS</string>
|
||||
<string name="pass_dateTime" translatable="false">dd MMM @ HH:mm:ss</string>
|
||||
|
||||
<string name="polar_north">N</string>
|
||||
<string name="polar_west">W</string>
|
||||
<string name="polar_south">S</string>
|
||||
<string name="polar_east">E</string>
|
||||
|
||||
<string name="pat_location" translatable="false">%.4f</string>
|
||||
<string name="pat_azimuth">Azimuth: %.1f°</string>
|
||||
<string name="pat_elevation">Elevation: %.1f°</string>
|
||||
<string name="pat_latitude">Latitude: %.1f°</string>
|
||||
<string name="pat_longitude">Longitude: %.1f°</string>
|
||||
<string name="pat_range">Distance: %.0f km</string>
|
||||
<string name="pat_altitude">Altitude: %.0f km</string>
|
||||
<string name="pat_azimuth">Az: %.1f°</string>
|
||||
<string name="pat_elevation">El: %.1f°</string>
|
||||
<string name="pat_latitude">Lat: %.1f°</string>
|
||||
<string name="pat_longitude">Lon: %.1f°</string>
|
||||
<string name="pat_range">Dst: %.0f km</string>
|
||||
<string name="pat_altitude">Alt: %.0f km</string>
|
||||
<string name="pat_timer" translatable="false">%02d:%02d:%02d</string>
|
||||
|
||||
<string name="trans_description" translatable="false">%s</string>
|
||||
|
||||
Reference in new issue
Block a user