aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIván Ávalos <avalos@disroot.org>2022-01-11 04:12:45 -0600
committerIván Ávalos <avalos@disroot.org>2022-01-11 04:12:45 -0600
commit8878254a4a3af9d15262fd2553c7b2db0a7bd8bc (patch)
tree4918c7ad01bf2c74bf5492f3c443408c733b0ab6
parent7629861e4e2b7e52b93f817426cb940c8f075b59 (diff)
downloadetbsa-trackermap-mobile-8878254a4a3af9d15262fd2553c7b2db0a7bd8bc.tar.gz
etbsa-trackermap-mobile-8878254a4a3af9d15262fd2553c7b2db0a7bd8bc.tar.bz2
etbsa-trackermap-mobile-8878254a4a3af9d15262fd2553c7b2db0a7bd8bc.zip
Implemented polygon geofences
-rw-r--r--androidApp/build.gradle.kts1
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt4
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt92
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt4
-rw-r--r--androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt14
5 files changed, 98 insertions, 17 deletions
diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts
index 5736c84..22d894a 100644
--- a/androidApp/build.gradle.kts
+++ b/androidApp/build.gradle.kts
@@ -38,5 +38,6 @@ dependencies {
implementation("io.ktor:ktor-client-serialization:1.6.6")
implementation("com.github.zerobranch:SwipeLayout:1.3.1")
implementation("com.github.addisonElliott:SegmentedButton:3.1.9")
+ implementation("mil.nga.sf:sf-wkt:1.0.1")
implementation(group = "", name = "WhirlyGlobeMaply", ext = "aar")
} \ No newline at end of file
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
index b701990..43f879d 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt
@@ -17,7 +17,6 @@ import mx.trackermap.TrackerMap.android.databinding.UnitDetailsReportsBinding
import mx.trackermap.TrackerMap.android.details.UnitDetailsAdapter
import mx.trackermap.TrackerMap.android.map.MapFragment
import mx.trackermap.TrackerMap.android.map.MarkerTransformations
-import mx.trackermap.TrackerMap.client.models.Event
import mx.trackermap.TrackerMap.client.models.EventInformation
import mx.trackermap.TrackerMap.client.models.Position
import mx.trackermap.TrackerMap.client.models.Stop
@@ -119,8 +118,9 @@ class UnitReportsFragment : Fragment() {
)
}
- unitReportsViewModel.geofences.observe(this) { geofences ->
+ unitReportsViewModel.geofences.observe(viewLifecycleOwner) { geofences ->
Log.d("UnitReportsFragment", "Success $geofences")
+ reportsMapFragment.displayGeofences(geofences.values.toTypedArray())
}
}
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt
index 41cfd50..fa0a56e 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt
@@ -10,8 +10,12 @@ import android.view.ViewGroup
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.toBitmap
import com.mousebird.maply.*
+import mil.nga.sf.Polygon
+import mil.nga.sf.util.SFException
+import mil.nga.sf.wkt.GeometryReader
import java.io.File
import mx.trackermap.TrackerMap.android.R
+import mx.trackermap.TrackerMap.client.models.Geofence
import mx.trackermap.TrackerMap.utils.MarkerType
typealias MarkerCallback = (Int?) -> Unit
@@ -28,6 +32,7 @@ class MapFragment : GlobeMapFragment() {
var markerCallback: MarkerCallback? = null
private val objects = mutableListOf<ComponentObject>()
+ private val geofenceObjects = mutableListOf<ComponentObject>()
override fun chooseDisplayType(): MapDisplayType {
return MapDisplayType.Map
@@ -95,12 +100,20 @@ class MapFragment : GlobeMapFragment() {
markerCallback?.let { it(null) }
}
- private fun clear() {
- mapControl.removeObjects(
- objects,
- ThreadMode.ThreadAny
- )
- objects.clear()
+ private fun clear(geofences: Boolean = false) {
+ if (geofences) {
+ mapControl.removeObjects(
+ geofenceObjects,
+ ThreadMode.ThreadAny
+ )
+ geofenceObjects.clear()
+ } else {
+ mapControl.removeObjects(
+ objects,
+ ThreadMode.ThreadAny
+ )
+ objects.clear()
+ }
}
fun display(markers: Array<Marker>, isReport: Boolean) {
@@ -108,6 +121,15 @@ class MapFragment : GlobeMapFragment() {
clear()
+ val points = markers.map { marker ->
+ Point2d.FromDegrees(marker.longitude, marker.latitude)
+ }.toTypedArray()
+
+ val vectorInfo = VectorInfo()
+ vectorInfo.setColor(Color.GREEN)
+ vectorInfo.setLineWidth(20.0f)
+
+ /* Draw markers for positions */
val screenMarkers = markers.mapIndexed { i, marker ->
val screenMarker = ScreenMarker()
val markerSize = Point2d(144.0, 144.0)
@@ -133,19 +155,11 @@ class MapFragment : GlobeMapFragment() {
ThreadMode.ThreadAny
))
- val points = markers.map { marker ->
- Point2d.FromDegrees(marker.longitude, marker.latitude)
- }.toTypedArray()
-
- // Draw polyline for report
+ /* Draw polyline for report */
if (isReport && markers.isNotEmpty()) {
val vector = VectorObject()
vector.addAreal(points)
- val vectorInfo = VectorInfo()
- vectorInfo.setColor(Color.GREEN)
- vectorInfo.setLineWidth(25.0f)
-
objects.add(mapControl.addVector(
vector,
vectorInfo,
@@ -168,6 +182,54 @@ class MapFragment : GlobeMapFragment() {
}
}
+ fun displayGeofences(geofences: Array<Geofence>) {
+ Log.d("MapFragment", "Displaying geofences")
+
+ clear(true)
+
+ val vectorInfoGeofence = VectorInfo()
+ vectorInfoGeofence.setColor(Color.BLUE)
+ vectorInfoGeofence.setLineWidth(10.0f)
+
+ val shapes = mutableListOf<Shape>()
+ val vectors = mutableListOf<VectorObject>()
+
+ geofences.forEach { geofence ->
+ geofence.area?.let { area ->
+ Log.d("MainFragment", "Geofence ${geofence.name} = ${geofence.area}")
+ try {
+ val geometry = GeometryReader.readGeometry(area)
+ if (!geometry.isEmpty) {
+ when (geometry) {
+ is Polygon -> {
+ val vector = VectorObject()
+ vector.addAreal(geometry.exteriorRing.points.map {
+ Point2d.FromDegrees(it.y, it.x)
+ }.toTypedArray())
+
+ vectors.add(vector)
+ }
+ }
+ }
+ } catch (e: SFException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ geofenceObjects.add(mapControl.addShapes(
+ shapes,
+ ShapeInfo(),
+ ThreadMode.ThreadAny
+ ))
+
+ geofenceObjects.add(mapControl.addVectors(
+ vectors,
+ vectorInfoGeofence,
+ ThreadMode.ThreadAny
+ ))
+ }
+
fun focusOn(latitude: Double, longitude: Double, zoom: Double = 0.0000144, animated: Boolean = true) {
val lat = latitude * Math.PI / 180
val lon = longitude * Math.PI / 180
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt
index 3c34abb..4f98a96 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt
@@ -124,6 +124,10 @@ class UnitMapFragment : Fragment() {
unitsMapFragment.focusOn(unit.position!!.latitude!!, unit.position!!.longitude!!)
}
}
+
+ unitsViewModel.geofences.observe(viewLifecycleOwner) { geofences ->
+ unitsMapFragment.displayGeofences(geofences.values.toTypedArray())
+ }
}
private fun itemAction(unit: UnitInformation, action: Action) {
diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt
index ca05736..c0dc7c6 100644
--- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt
+++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt
@@ -5,7 +5,9 @@ import androidx.lifecycle.*
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
+import mx.trackermap.TrackerMap.client.models.Geofence
import mx.trackermap.TrackerMap.client.models.UnitInformation
+import mx.trackermap.TrackerMap.controllers.GeofencesController
import mx.trackermap.TrackerMap.controllers.UnitsController
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
@@ -20,22 +22,28 @@ class UnitsViewModel(
}
private val unitsController: UnitsController by inject()
+ private val geofenceController: GeofencesController by inject()
private var _searchQuery = savedStateHandle.getLiveData("searchQuery", "")
private var _unitsDisplayMode = MutableLiveData(UnitsDisplayMode.LIST)
private var _units = MutableLiveData<List<UnitInformation>>()
private var _selectedUnit = MutableLiveData<UnitInformation?>()
+ private var _geofences = MutableLiveData<Map<Int, Geofence>>()
val searchQuery: LiveData<String> get() = _searchQuery
val unitsDisplayMode: LiveData<UnitsDisplayMode> get() = _unitsDisplayMode
val units: LiveData<List<UnitInformation>> get() = _units
val selectedUnit: LiveData<UnitInformation?> get() = _selectedUnit
+ val geofences: LiveData<Map<Int, Geofence>> get() = _geofences
init {
Log.d("UnitsViewModel", "Initializing Units View Model")
viewModelScope.launch {
setupObservers()
}
+ viewModelScope.launch {
+ setupGeofenceObserver()
+ }
}
private suspend fun setupObservers() {
@@ -45,6 +53,12 @@ class UnitsViewModel(
}
}
+ private suspend fun setupGeofenceObserver() {
+ geofenceController.geofencesFlow.collect {
+ this._geofences.postValue(it)
+ }
+ }
+
fun selectUnit(unit: UnitInformation) {
Log.d("UnitsViewModel", "Selecting unit ${unit.device.name}")
_selectedUnit.postValue(unit)