Further map setup

This commit is contained in:
Arty Bishop committed 2020-09-19 20:19:41 +01:00
1 parent 8c56c31b8c
commit 4346cedbdc
2 files changed
+245 -125

No files matched your search

@@ -1,14 +1,16 @@
package com.rtbishop.look4sat.ui.fragments
import android.graphics.Color
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.view.View
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import com.github.amsacode.predict4java.GroundStationPosition
import com.github.amsacode.predict4java.SatPos
import com.rtbishop.look4sat.Look4SatApp
@@ -19,22 +21,21 @@ import com.rtbishop.look4sat.data.SatPass
import com.rtbishop.look4sat.databinding.FragmentMapOsmBinding
import com.rtbishop.look4sat.ui.MainActivity
import com.rtbishop.look4sat.ui.SharedViewModel
import com.rtbishop.look4sat.utility.GeneralUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.mapsforge.map.rendertheme.XmlRenderTheme
import org.mapsforge.map.rendertheme.XmlRenderThemeMenuCallback
import org.osmdroid.mapsforge.MapsForgeTileProvider
import org.osmdroid.mapsforge.MapsForgeTileSource
import org.osmdroid.tileprovider.util.SimpleRegisterReceiver
import kotlinx.coroutines.withContext
import org.osmdroid.config.Configuration
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.BoundingBox
import org.osmdroid.util.GeoPoint
import org.osmdroid.views.overlay.Marker
import org.osmdroid.views.overlay.Polygon
import org.osmdroid.views.overlay.Polyline
import org.osmdroid.views.CustomZoomButtonsController
import org.osmdroid.views.overlay.*
import org.osmdroid.views.overlay.compass.CompassOverlay
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider
import java.io.File
import java.io.InputStream
import org.osmdroid.views.overlay.gridlines.LatLonGridlineOverlay2
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay
import java.util.*
import javax.inject.Inject
@@ -45,8 +46,6 @@ class MapOsmFragment : Fragment(R.layout.fragment_map_osm) {
private lateinit var mainActivity: MainActivity
private lateinit var viewModel: SharedViewModel
private lateinit var binding: FragmentMapOsmBinding
private var satPassList = emptyList<SatPass>()
private var gsp = GroundStationPosition(0.0, 0.0, 0.0)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -55,108 +54,241 @@ class MapOsmFragment : Fragment(R.layout.fragment_map_osm) {
(mainActivity.application as Look4SatApp).appComponent.inject(this)
viewModel = ViewModelProvider(mainActivity, modelFactory).get(SharedViewModel::class.java)
val prefs = PreferenceManager.getDefaultSharedPreferences(mainActivity.applicationContext)
Configuration.getInstance().load(mainActivity.applicationContext, prefs)
setupMapView()
setupObservers()
}
private fun setupObservers() {
viewModel.getGSP().observe(viewLifecycleOwner, Observer { result ->
when (result) {
is Result.Success -> gsp = result.data
}
})
viewModel.getPassList().observe(viewLifecycleOwner, Observer { result ->
when (result) {
is Result.Success -> {
satPassList = result.data
setupMapWithAdapter()
}
}
})
}
inner class MyRenderTheme : XmlRenderTheme {
override fun getRenderThemeAsStream(): InputStream {
return resources.openRawResource(R.raw.customrender)
}
override fun getMenuCallback(): XmlRenderThemeMenuCallback? {
return null
}
override fun getRelativePathPrefix(): String {
return ""
}
override fun setMenuCallback(menuCallback: XmlRenderThemeMenuCallback) {}
}
private fun setupMapWithAdapter() {
val mapsArray = arrayOf(File(Environment.getExternalStorageDirectory(), "world.map"))
val tileSource = MapsForgeTileSource.createFromFiles(mapsArray, MyRenderTheme(), null)
val registerReceiver = SimpleRegisterReceiver(mainActivity.applicationContext)
val tileProvider = MapsForgeTileProvider(registerReceiver, tileSource, null)
binding.mapView.tileProvider = tileProvider
private fun setupMapView() {
binding.mapView.apply {
setTileSource(TileSourceFactory.MAPNIK)
// General settings
// isHorizontalMapRepetitionEnabled = false
// isVerticalMapRepetitionEnabled = false
overlayManager.tilesOverlay.loadingBackgroundColor = Color.TRANSPARENT
overlayManager.tilesOverlay.loadingLineColor = Color.TRANSPARENT
minZoomLevel = 3.00
maxZoomLevel = 8.00
controller.setZoom(5.0)
val startPoint = GeoPoint(gsp.latitude, gsp.longitude)
controller.setCenter(startPoint)
val startMarker = Marker(binding.mapView)
startMarker.position = startPoint
startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
startMarker.title = "Ground Station Position"
overlays.add(startMarker)
var dateNow = Date(System.currentTimeMillis())
val selectedSat = satPassList[3]
val orbitalPeriod = (24 * 60 / selectedSat.tle.meanmo).toInt()
var positions = selectedSat.predictor.getPositions(dateNow, 60, 0, orbitalPeriod * 3)
drawGroundTrack(positions)
Log.d("myTag", selectedSat.tle.name)
val compassOverlay = CompassOverlay(
context,
InternalCompassOrientationProvider(context),
binding.mapView
)
compassOverlay.enableCompass()
overlays.add(compassOverlay)
// Zoom settings
minZoomLevel = 2.5
maxZoomLevel = 6.5
controller.setZoom(minZoomLevel)
// controller.setCenter(GeoPoint(0.0, 0.0))
setMultiTouchControls(true)
setScrollableAreaLimitLatitude(85.0, -85.0, 0)
zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
lifecycleScope.launch {
while (true) {
delay(3000)
dateNow = Date(System.currentTimeMillis())
positions =
selectedSat.predictor.getPositions(dateNow, 60, 0, orbitalPeriod * 3)
drawPosition(GeoPoint(positions[0].latitude, positions[0].longitude))
binding.mapView.invalidate()
// Scroll limits
// setScrollableAreaLimitLatitude(85.0, -85.0, 0)
// setScrollableAreaLimitLongitude(-180.0, 180.0, 0)
setScrollableAreaLimitDouble(BoundingBox(85.0, 180.0, -85.0, -180.0))
addLocationOverlay()
addMapScaleBarOverlay()
addSomeIcons()
addColorFilter()
}
}
private fun setupObservers() {
viewModel.getGSP().observe(viewLifecycleOwner, Observer { stationPosition ->
when (stationPosition) {
is Result.Success -> {
// setUserLocation(stationPosition.data)
}
}
})
viewModel.getPassList().observe(viewLifecycleOwner, Observer { satPasses ->
when (satPasses) {
is Result.Success -> {
val filteredPasses = satPasses.data.distinctBy { it.tle }
// setupSatOverlay(filteredPasses)
}
}
})
}
private fun setUserLocation(position: GroundStationPosition) {
val startPoint = GeoPoint(position.latitude, position.longitude)
Marker(binding.mapView).apply {
this.position = startPoint
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
title = "Ground Station Position"
}
}
private fun addCompassOverlay() {
val overlay =
CompassOverlay(context, InternalCompassOrientationProvider(context), binding.mapView)
overlay.enableCompass()
binding.mapView.overlays.add(overlay)
}
private fun addLocationOverlay() {
val overlay = MyLocationNewOverlay(GpsMyLocationProvider(mainActivity), binding.mapView)
overlay.enableMyLocation()
binding.mapView.overlays.add(overlay)
}
private fun addGridLineOverlay() {
val overlay = LatLonGridlineOverlay2()
binding.mapView.overlays.add(overlay)
}
private fun addMapScaleBarOverlay() {
val dm = mainActivity.resources.displayMetrics
val overlay = ScaleBarOverlay(binding.mapView).apply {
setCentred(true)
setScaleBarOffset(dm.widthPixels / 2, 10)
}
binding.mapView.overlays.add(overlay)
}
private fun addMiniMap() {
val dm = mainActivity.resources.displayMetrics
val overlay =
MinimapOverlay(mainActivity, binding.mapView.tileRequestCompleteHandler).apply {
width = dm.widthPixels / 5
height = dm.heightPixels / 5
}
binding.mapView.overlays.add(overlay)
}
private fun addSomeIcons() {
val items = mutableListOf<OverlayItem>()
items.add(OverlayItem("Title", "Description", GeoPoint(0.0, 0.0)))
val listener = object : ItemizedIconOverlay.OnItemGestureListener<OverlayItem> {
override fun onItemLongPress(index: Int, item: OverlayItem?): Boolean {
return true
}
override fun onItemSingleTapUp(index: Int, item: OverlayItem?): Boolean {
Log.d("myTag", "${item?.title}")
return true
}
}
val overlay = ItemizedIconOverlay(mainActivity, items, listener)
binding.mapView.overlays.add(overlay)
}
private fun addColorFilter() {
val negativeArray = floatArrayOf(
-1.0f, .0f, .0f, .0f, 255.0f,
.0f, -1.0f, .0f, .0f, 255.0f,
.0f, .0f, -1.0f, .0f, 255.0f,
.0f, .0f, .0f, 1.0f, .0f
)
val negativeMatrix = ColorMatrix(negativeArray)
val destinationColor = Color.parseColor("#FF2A2A2A")
val lr = (255.0f - Color.red(destinationColor)) / 255.0f
val lg = (255.0f - Color.green(destinationColor)) / 255.0f
val lb = (255.0f - Color.blue(destinationColor)) / 255.0f
val grayScaleArray = floatArrayOf(
lr, lg, lb, 0f, 0f, //
lr, lg, lb, 0f, 0f, //
lr, lg, lb, 0f, 0f, //
0f, 0f, 0f, 0f, 255f //
)
val grayScaleMatrix = ColorMatrix(grayScaleArray)
grayScaleMatrix.preConcat(negativeMatrix)
val dr = Color.red(destinationColor)
val dg = Color.green(destinationColor)
val db = Color.blue(destinationColor)
val drf = dr / 255f
val dgf = dg / 255f
val dbf = db / 255f
val tintArray = floatArrayOf(
drf, 0f, 0f, 0f, 0f, //
0f, dgf, 0f, 0f, 0f, //
0f, 0f, dbf, 0f, 0f, //
0f, 0f, 0f, 1f, 0f //
)
val tintMatrix = ColorMatrix(tintArray)
tintMatrix.preConcat(grayScaleMatrix)
val lDest = drf * lr + dgf * lg + dbf * lb
val scale = 1f - lDest
val translate = 1 - scale * 0.5f
val scaleArray = floatArrayOf(
scale, 0f, 0f, 0f, dr * translate, //
0f, scale, 0f, 0f, dg * translate, //
0f, 0f, scale, 0f, db * translate, //
0f, 0f, 0f, 1f, 0f
)
val scaleMatrix = ColorMatrix(scaleArray)
scaleMatrix.preConcat(tintMatrix)
val filter = ColorMatrixColorFilter(scaleMatrix)
binding.mapView.overlayManager.tilesOverlay.setColorFilter(filter)
}
private fun setupSatOverlay(passList: List<SatPass>) {
lifecycleScope.launch {
while (true) {
// val markers = showSatIcons(data)
// satLayer.removeAllItems()
// satLayer.addItems(markers)
delay(1000)
}
}
}
private suspend fun drawGroundTrack(data: List<SatPass>) {
withContext(Dispatchers.IO) {
data[1].apply {
val dateNow = Date(System.currentTimeMillis())
val period = (24 * 60 / this.tle.meanmo).toInt()
val positions = this.predictor.getPositions(dateNow, 15, 0, period)
positions.forEach {
val lat = Math.toDegrees(it.latitude)
var lon = Math.toDegrees(it.longitude)
// Log.d("myTag", "$lat, $lon")
if (lon > 180.0) {
// path.addPoint(GeoPoint(lat, 180.0))
lon -= 360.0
}
Log.d("myTag", "$lat, $lon")
}
}
// binding.mapView.map().layers().add(path)
// binding.mapView.map().render()
}
}
private fun drawGroundTrack(list: List<SatPos>) {
val groundTrack = Polyline(binding.mapView)
val trackPoints = mutableListOf<GeoPoint>()
list.forEach {
val lat = Math.toDegrees(it.latitude) * -1
var lon = Math.toDegrees(it.longitude)
if (lon > 180.0) lon -= 360.0
trackPoints.add(GeoPoint(lat, lon))
}
groundTrack.setPoints(trackPoints)
groundTrack.setDensityMultiplier(0.5f)
binding.mapView.overlays.add(groundTrack)
binding.mapView.invalidate()
}
private fun drawPosition(position: GeoPoint) {
val satPosition = Polygon(binding.mapView)
val trackPoints = mutableListOf<GeoPoint>()
Log.d("myTag", "${position.latitude}, ${position.longitude}")
val lat = GeneralUtils.rad2Deg(position.latitude)
var lon = GeneralUtils.rad2Deg(position.longitude)
val lat = Math.toDegrees(position.latitude)
var lon = Math.toDegrees(position.longitude)
if (lon > 180.0) lon -= 360.0
trackPoints.add(GeoPoint(lat, lon))
@@ -166,43 +298,31 @@ class MapOsmFragment : Fragment(R.layout.fragment_map_osm) {
startMarker.title = "Sat Position"
binding.mapView.overlays.add(startMarker)
Log.d("myTag", "$lat, $lon")
binding.mapView.overlays.add(satPosition)
satPosition.points = trackPoints
binding.mapView.invalidate()
}
private fun drawGroundTrack(list: List<SatPos>) {
val groundTrack = Polyline(binding.mapView)
val trackPoints = mutableListOf<GeoPoint>()
var lat = 0.0
var lon = 0.0
Log.d("myTag", "${list[1].latitude}, ${list[1].longitude}")
list.forEach {
lat = GeneralUtils.rad2Deg(it.latitude) * -1
lon = GeneralUtils.rad2Deg(it.longitude)
if (lon > 180.0) lon -= 360.0
trackPoints.add(GeoPoint(lat, lon))
private suspend fun showSatIcons(data: List<SatPass>) {
withContext(Dispatchers.Default) {
val dateNow = Date(System.currentTimeMillis())
data.forEach {
val satPos = it.predictor.getSatPos(dateNow)
val lat = Math.toDegrees(satPos.latitude)
var lon = Math.toDegrees(satPos.longitude)
if (lon > 180) lon -= 360
Log.d("myTag", "${it.tle.name}, $lat, $lon")
}
}
}
Log.d("myTag", "$lat, $lon")
groundTrack.setPoints(trackPoints)
groundTrack.setDensityMultiplier(0.5f)
binding.mapView.overlays.add(groundTrack)
binding.mapView.invalidate()
override fun onPause() {
binding.mapView.onPause()
super.onPause()
}
override fun onResume() {
super.onResume()
binding.mapView.onResume()
}
override fun onPause() {
super.onPause()
binding.mapView.onPause()
}
}
+2 -2
View File
@@ -18,13 +18,13 @@
*/
buildscript {
ext.gradle_version = '4.0.0'
ext.gradle_version = '4.0.1'
ext.gradle_plugin_version = '1.3.72'
ext.material_version = '1.1.0'
ext.app_compat_version = '1.1.0'
ext.support_lib_version = '1.0.0'
ext.constraint_layout_version = '1.1.3'
ext.ktx_version = '1.3.0'
ext.ktx_version = '1.3.1'
ext.preference_version = '1.1.1'
ext.navigation_version = '2.3.0'
ext.lifecycle_version = '2.2.0'