Cleaned up the MapFragment.kt, changed satTrack color

pull/49/head
Arty Bishop 2020-10-28 21:38:20 +00:00
rodzic ca92f8581e
commit b7f7f0b477
4 zmienionych plików z 97 dodań i 161 usunięć

Wyświetl plik

@ -1,11 +0,0 @@
package com.rtbishop.look4sat.data
import org.osmdroid.api.IGeoPoint
import org.osmdroid.views.overlay.OverlayItem
data class SatItem(
val name: String,
val description: String,
val position: IGeoPoint,
val pass: SatPass
) : OverlayItem(name, description, position)

Wyświetl plik

@ -4,20 +4,17 @@ import android.graphics.Color
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.Paint
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import com.github.amsacode.predict4java.GroundStationPosition
import com.github.amsacode.predict4java.Position
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.SharedViewModel
import com.rtbishop.look4sat.data.Result
import com.rtbishop.look4sat.data.SatItem
import com.rtbishop.look4sat.data.SatPass
import com.rtbishop.look4sat.databinding.FragmentMapBinding
import com.rtbishop.look4sat.utility.PrefsManager
@ -27,7 +24,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.osmdroid.config.Configuration
import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase
import org.osmdroid.tileprovider.tilesource.ITileSource
import org.osmdroid.tileprovider.tilesource.TileSourcePolicy
import org.osmdroid.tileprovider.tilesource.XYTileSource
import org.osmdroid.util.BoundingBox
@ -45,43 +42,27 @@ class MapFragment : Fragment(R.layout.fragment_map) {
@Inject
lateinit var prefsManager: PrefsManager
private lateinit var mainActivity: FragmentActivity
private lateinit var binding: FragmentMapBinding
private lateinit var trackPaint: Paint
private lateinit var footprintPaint: Paint
private lateinit var selectedPass: SatPass
private val dateNow = Date(System.currentTimeMillis())
private val dateNow = Date()
private val viewModel: SharedViewModel by activityViewModels()
private var iconPos: Drawable? = null
private var iconSat: Drawable? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentMapBinding.bind(view)
mainActivity = requireActivity()
val prefs = PreferenceManager.getDefaultSharedPreferences(mainActivity.applicationContext)
Configuration.getInstance().load(mainActivity.applicationContext, prefs)
trackPaint = Paint().apply {
strokeWidth = 2f
style = Paint.Style.STROKE
color = ContextCompat.getColor(mainActivity, R.color.satTrack)
strokeCap = Paint.Cap.ROUND
strokeJoin = Paint.Join.ROUND
isAntiAlias = true
}
footprintPaint = Paint().apply {
style = Paint.Style.FILL_AND_STROKE
color = ContextCompat.getColor(mainActivity, R.color.satFootprint)
isAntiAlias = true
}
setupMapView()
setupPosOverlay(prefsManager.getStationPosition())
setupPosOverlay()
setupObservers()
}
private fun setupMapView() {
Configuration.getInstance()
.load(requireContext().applicationContext, prefsManager.preferences)
val filter = getColorFilter(ContextCompat.getColor(requireContext(), R.color.satTrack))
binding.mapView.apply {
setMultiTouchControls(true)
setTileSource(getWikimediaTileSource())
@ -89,36 +70,52 @@ class MapFragment : Fragment(R.layout.fragment_map) {
maxZoomLevel = 6.0
controller.setZoom(3.0)
zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
isHorizontalMapRepetitionEnabled = false
isVerticalMapRepetitionEnabled = false
overlayManager.tilesOverlay.loadingBackgroundColor = Color.TRANSPARENT
overlayManager.tilesOverlay.loadingLineColor = Color.TRANSPARENT
overlayManager.tilesOverlay.setColorFilter(filter)
setScrollableAreaLimitDouble(BoundingBox(85.05, 180.0, -85.05, -180.0))
// apply filter
val tilesFilter = getColorFilter(Color.parseColor("#D50000"))
overlayManager.tilesOverlay.setColorFilter(tilesFilter)
// add overlays: 0 - GSP, 1 - SatTrack, 2 - SatFootprint, 3 - SatIcons
val layers = listOf(FolderOverlay(), FolderOverlay(), FolderOverlay(), FolderOverlay())
overlays.addAll(layers)
}
trackPaint = Paint().apply {
strokeWidth = 2f
style = Paint.Style.STROKE
color = ContextCompat.getColor(requireContext(), R.color.satTrack)
strokeCap = Paint.Cap.ROUND
strokeJoin = Paint.Join.ROUND
isAntiAlias = true
}
footprintPaint = Paint().apply {
style = Paint.Style.FILL_AND_STROKE
color = ContextCompat.getColor(requireContext(), R.color.satFootprint)
isAntiAlias = true
}
iconPos = ContextCompat.getDrawable(requireContext(), R.drawable.ic_map_pos)
iconSat = ContextCompat.getDrawable(requireContext(), R.drawable.ic_map_sat)
}
private fun getWikimediaTileSource(): OnlineTileSourceBase {
return XYTileSource(
"wikimedia",
2,
6,
256,
".png",
arrayOf("https://maps.wikimedia.org/osm-intl/"),
resources.getString(R.string.map_copyright),
TileSourcePolicy(
1, TileSourcePolicy.FLAG_NO_BULK and TileSourcePolicy.FLAG_NO_PREVENTIVE and
TileSourcePolicy.FLAG_USER_AGENT_MEANINGFUL and TileSourcePolicy.FLAG_USER_AGENT_NORMALIZED
)
private fun getWikimediaTileSource(): ITileSource {
val copyright = resources.getString(R.string.map_copyright)
val sources = arrayOf("https://maps.wikimedia.org/osm-intl/")
val policy = TileSourcePolicy(
1, TileSourcePolicy.FLAG_NO_BULK and TileSourcePolicy.FLAG_NO_PREVENTIVE and
TileSourcePolicy.FLAG_USER_AGENT_MEANINGFUL and TileSourcePolicy.FLAG_USER_AGENT_NORMALIZED
)
return XYTileSource("wikimedia", 2, 6, 256, ".png", sources, copyright, policy)
}
private fun setupPosOverlay() {
val gsp = prefsManager.getStationPosition()
Marker(binding.mapView).apply {
setInfoWindow(null)
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
icon = iconPos
position = GeoPoint(gsp.latitude, gsp.longitude)
binding.mapView.overlays[0] = this
binding.mapView.invalidate()
}
}
private fun setupObservers() {
@ -133,63 +130,39 @@ class MapFragment : Fragment(R.layout.fragment_map) {
})
}
private fun setupPosOverlay(gsp: GroundStationPosition) {
Marker(binding.mapView).apply {
setInfoWindow(null)
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_map_pos, mainActivity.theme)
position = GeoPoint(gsp.latitude, gsp.longitude)
binding.mapView.overlays[0] = this
binding.mapView.invalidate()
}
}
private fun setupSatOverlay(passList: List<SatPass>) {
lifecycleScope.launch {
while (true) {
dateNow.time = System.currentTimeMillis()
binding.mapView.overlays[3] = getSatIcons(passList)
binding.mapView.overlays[3] = getSatMarkers(passList)
binding.mapView.overlays[2] = getSatFootprint(selectedPass)
setSatInfo(selectedPass)
binding.mapView.invalidate()
delay(3000)
delay(2000)
}
}
}
private suspend fun getSatIcons(passList: List<SatPass>): Overlay =
private suspend fun getSatMarkers(passList: List<SatPass>): Overlay =
withContext(Dispatchers.Default) {
val icon =
ResourcesCompat.getDrawable(resources, R.drawable.ic_map_sat, mainActivity.theme)
val items = mutableListOf<SatItem>()
passList.forEach {
val satPos = it.predictor.getSatPos(dateNow)
var lat = Math.toDegrees(satPos.latitude)
if (lat > 85.05) lat = 85.05
else if (lat < -85.05) lat = -85.05
var lon = Math.toDegrees(satPos.longitude)
if (lon > 180.0) lon -= 360.0
SatItem(it.tle.name, it.tle.name, GeoPoint(lat, lon), it).apply {
markerHotspot = OverlayItem.HotspotPlace.CENTER
val items = FolderOverlay()
passList.forEach { satPass ->
val satPos = satPass.predictor.getSatPos(dateNow)
val osmPos = getOsmPosition(satPos.latitude, satPos.longitude, true)
Marker(binding.mapView).apply {
setInfoWindow(null)
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
icon = iconSat
position = GeoPoint(osmPos.lat, osmPos.lon)
setOnMarkerClickListener { _, _ ->
selectedPass = satPass
setSatDetails(satPass)
true
}
items.add(this)
}
}
val listener = object : ItemizedIconOverlay.OnItemGestureListener<SatItem> {
override fun onItemLongPress(index: Int, item: SatItem): Boolean {
return true
}
override fun onItemSingleTapUp(index: Int, item: SatItem): Boolean {
selectedPass = item.pass
setSatDetails(item.pass)
return true
}
}
return@withContext ItemizedIconOverlay(items, icon, listener, mainActivity)
return@withContext items
}
private fun setSatDetails(satPass: SatPass) {
@ -201,31 +174,17 @@ class MapFragment : Fragment(R.layout.fragment_map) {
private fun setSatInfo(satPass: SatPass) {
val satPos = satPass.predictor.getSatPos(dateNow)
var satLat = Math.toDegrees(satPos.latitude)
if (satLat > 85.05) satLat = 85.05
else if (satLat < -85.05) satLat = -85.05
var satLon = Math.toDegrees(satPos.longitude)
if (satLon > 180f) satLon -= 360f
binding.idName.text =
String.format(
mainActivity.getString(R.string.pat_osm_idName),
satPass.tle.catnum,
satPass.tle.name
)
binding.altitude.text =
String.format(mainActivity.getString(R.string.pat_altitude), satPos.altitude)
binding.distance.text =
String.format(mainActivity.getString(R.string.pat_distance), satPos.range)
binding.velocity.text =
String.format(
mainActivity.getString(R.string.pat_osm_vel),
getSatVelocity(satPos.altitude)
)
binding.latLon.text =
String.format(mainActivity.getString(R.string.pat_osm_latLon), satLat, satLon)
val osmPos = getOsmPosition(satPos.latitude, satPos.longitude, true)
val catNum = satPass.tle.catnum
val name = satPass.tle.name
val satVelocity = getSatVelocity(satPos.altitude)
binding.apply {
idName.text = String.format(getString(R.string.pat_osm_idName), catNum, name)
altitude.text = String.format(getString(R.string.pat_altitude), satPos.altitude)
distance.text = String.format(getString(R.string.pat_distance), satPos.range)
velocity.text = String.format(getString(R.string.pat_osm_vel), satVelocity)
latLon.text = String.format(getString(R.string.pat_osm_latLon), osmPos.lat, osmPos.lon)
}
}
private fun getSatVelocity(satAlt: Double): Double {
@ -240,17 +199,11 @@ class MapFragment : Fragment(R.layout.fragment_map) {
val positions = pass.predictor.getPositions(dateNow, 20, 0, period * 3)
val trackOverlay = FolderOverlay()
val trackPoints = mutableListOf<GeoPoint>()
var oldLon = 0.0
positions.forEach {
var newLat = Math.toDegrees(it.latitude)
if (newLat > 85.05) newLat = 85.05
else if (newLat < -85.05) newLat = -85.05
var newLon = Math.toDegrees(it.longitude)
if (newLon > 180.0) newLon -= 360.0
if (oldLon < -170.0 && newLon > 170.0 || oldLon > 170.0 && newLon < -170.0) {
val osmPos = getOsmPosition(it.latitude, it.longitude, true)
if (oldLon < -170.0 && osmPos.lon > 170.0 || oldLon > 170.0 && osmPos.lon < -170.0) {
val currentPoints = mutableListOf<GeoPoint>()
currentPoints.addAll(trackPoints)
Polyline().apply {
@ -260,8 +213,8 @@ class MapFragment : Fragment(R.layout.fragment_map) {
}
trackPoints.clear()
}
oldLon = newLon
trackPoints.add(GeoPoint(newLat, newLon))
oldLon = osmPos.lon
trackPoints.add(GeoPoint(osmPos.lat, osmPos.lon))
}
Polyline().apply {
@ -269,7 +222,6 @@ class MapFragment : Fragment(R.layout.fragment_map) {
setPoints(trackPoints)
trackOverlay.add(this)
}
return trackOverlay
}
@ -279,18 +231,12 @@ class MapFragment : Fragment(R.layout.fragment_map) {
var zeroPoint = GeoPoint(0.0, 0.0)
rangeCircle.withIndex().forEach {
var lat = it.value.lat
if (lat > 85.05) lat = 85.05
else if (lat < -85.05) lat = -85.05
var lon = it.value.lon
if (lon > 180.0) lon -= 360.0
if (it.index == 0) zeroPoint = GeoPoint(lat, lon)
rangePoints.add(GeoPoint(lat, lon))
val osmPos = getOsmPosition(it.value.lat, it.value.lon, false)
if (it.index == 0) zeroPoint = GeoPoint(osmPos.lat, osmPos.lon)
rangePoints.add(GeoPoint(osmPos.lat, osmPos.lon))
}
rangePoints.add(zeroPoint)
rangePoints.add(zeroPoint)
return Polygon().apply {
fillPaint.set(footprintPaint)
outlinePaint.set(footprintPaint)
@ -302,7 +248,6 @@ class MapFragment : Fragment(R.layout.fragment_map) {
val newR = Color.red(targetColor) / 255f
val newG = Color.green(targetColor) / 255f
val newB = Color.blue(targetColor) / 255f
val negativeMatrix = ColorMatrix(
floatArrayOf(
-1f, 0f, 0f, 0f, 255f,
@ -311,7 +256,6 @@ class MapFragment : Fragment(R.layout.fragment_map) {
0f, 0f, 0f, 1f, 0f
)
)
val tintedMatrix = ColorMatrix(
floatArrayOf(
newR, newG, newB, 0f, 0f,
@ -320,18 +264,21 @@ class MapFragment : Fragment(R.layout.fragment_map) {
0f, 0f, 0f, 0f, 255f
)
)
tintedMatrix.preConcat(negativeMatrix)
return ColorMatrixColorFilter(tintedMatrix)
}
override fun onPause() {
binding.mapView.onPause()
super.onPause()
}
override fun onResume() {
super.onResume()
binding.mapView.onResume()
private fun getOsmPosition(lat: Double, lon: Double, inRadians: Boolean): Position {
return if (inRadians) {
var osmLat = Math.toDegrees(lat)
var osmLon = Math.toDegrees(lon)
if (osmLat > 85.05) osmLat = 85.05 else if (osmLat < -85.05) osmLat = -85.05
if (osmLon > 180f) osmLon -= 360f
Position(osmLat, osmLon)
} else {
val osmLat = if (lat > 85.05) 85.05 else if (lat < -85.05) -85.05 else lat
val osmLon = if (lon > 180.0) lon - 360.0 else lon
Position(osmLat, osmLon)
}
}
}

Wyświetl plik

@ -26,7 +26,7 @@ import com.github.amsacode.predict4java.GroundStationPosition
import com.rtbishop.look4sat.data.PassPrefs
import javax.inject.Inject
class PrefsManager @Inject constructor(private val preferences: SharedPreferences) {
class PrefsManager @Inject constructor(val preferences: SharedPreferences) {
companion object {
const val keyLatitude = "latitude"
const val keyLongitude = "longitude"

Wyświetl plik

@ -26,7 +26,7 @@
<color name="greyDivider">#808080</color>
<color name="greySurface">#1e1e1e</color>
<!-- map colors -->
<color name="satTrack">#B00020</color>
<color name="satTrack">#D50000</color>
<color name="satFootprint">#26FFE082</color>
<color name="mapInfoLayout">#66000000</color>
</resources>