use SimpleFastPointOverlay for the track overlay (see #96)

master
y20k 2021-03-15 17:43:31 +01:00
parent c193e8a475
commit 1c70fe1b5e
No known key found for this signature in database
GPG Key ID: 824D4259F41FAFF6
6 changed files with 117 additions and 76 deletions

View File

@ -181,11 +181,11 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
/* Overrides onMarkerTapped from MarkerListener */
override fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) {
super.onMarkerTapped(latitude, longitude, displayStartEndMarker)
override fun onMarkerTapped(latitude: Double, longitude: Double) {
super.onMarkerTapped(latitude, longitude)
if (bound) {
track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude)
layout.overlayCurrentTrack(track, trackingState, displayStartEndMarker)
layout.overlayCurrentTrack(track, trackingState)
trackerService.track = track
}
}
@ -320,7 +320,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
trackingState = trackerService.trackingState
// update location and track
layout.markCurrentPosition(currentBestLocation, trackingState)
layout.overlayCurrentTrack(track, trackingState, displayStartEndMarker = false)
layout.overlayCurrentTrack(track, trackingState)
// center map, if it had not been dragged/zoomed before
if (!layout.userInteraction) { layout.centerMap(currentBestLocation, true)}
// show error snackbar if necessary

View File

@ -162,11 +162,11 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi
/* Overrides onMarkerTapped from MarkerListener */
override fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) {
super.onMarkerTapped(latitude, longitude, displayStartEndMarker)
override fun onMarkerTapped(latitude: Double, longitude: Double) {
super.onMarkerTapped(latitude, longitude)
// update track display
track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude)
layout.updateTrackOverlay(track, displayStartEndMarker)
layout.updateTrackOverlay(track)
// save track
GlobalScope.launch {
FileHelper.saveTrackSuspended(track, true)

View File

@ -476,7 +476,6 @@ class TrackerService: Service(), CoroutineScope, SensorEventListener {
if (now.time - lastSave.time > Keys.SAVE_TEMP_TRACK_INTERVAL) {
lastSave = now
GlobalScope.launch { FileHelper.saveTempTrackSuspended(this@TrackerService, track) }
LogHelper.e(TAG, "TEMP SAVE: $lastSave")
}
}
// update notification

View File

@ -19,14 +19,20 @@ package org.y20k.trackbook.helpers
import android.content.Context
import android.graphics.Paint
import android.graphics.drawable.Drawable
import android.location.Location
import android.os.Vibrator
import android.widget.Toast
import androidx.core.content.ContextCompat
import org.osmdroid.api.IGeoPoint
import org.osmdroid.util.GeoPoint
import org.osmdroid.views.overlay.ItemizedIconOverlay
import org.osmdroid.views.overlay.OverlayItem
import org.osmdroid.views.overlay.simplefastpoint.LabelledGeoPoint
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlayOptions
import org.osmdroid.views.overlay.simplefastpoint.SimplePointTheme
import org.y20k.trackbook.Keys
import org.y20k.trackbook.R
import org.y20k.trackbook.core.Track
@ -44,7 +50,7 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
/* Interface used to communicate back to activity/fragment */
interface MarkerListener {
fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) {
fun onMarkerTapped(latitude: Double, longitude: Double) {
}
}
@ -83,70 +89,86 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
overlayItems.add(overlayItem)
// create and return overlay for current position
return createOverlay(context, overlayItems, enableStarring = false, displayStartEndMarker = false)
return createOverlay(context, overlayItems, enableStarring = false)
}
/* Creates icon overlay for track */
fun createTrackOverlay(context: Context, track: Track, trackingState: Int, displayStartEndMarker: Boolean = false): ItemizedIconOverlay<OverlayItem> {
fun createTrackOverlay(context: Context, track: Track, trackingState: Int): SimpleFastPointOverlay {
// get marker color
val color = if (trackingState == Keys.STATE_TRACKING_ACTIVE) context.getColor(R.color.trackbook_red)
else context.getColor(R.color.trackbook_blue)
// gather points for overlay
val points: MutableList<IGeoPoint> = mutableListOf()
track.wayPoints.forEach { wayPoint ->
val label: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(wayPoint.time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(wayPoint.accuracy)} (${wayPoint.provider})"
// only add normal points
if (!wayPoint.starred && !wayPoint.isStopOver) {
points.add(LabelledGeoPoint(wayPoint.latitude, wayPoint.longitude, wayPoint.altitude, label))
}
}
val pointTheme: SimplePointTheme = SimplePointTheme(points, false)
// set styling for overlay
val style: Paint = Paint()
style.style = Paint.Style.FILL
style.color = color
val scalingFactor: Float = UiHelper.getDensityScalingFactor(context)
val overlayOptions: SimpleFastPointOverlayOptions = SimpleFastPointOverlayOptions.getDefaultStyle()
.setAlgorithm(SimpleFastPointOverlayOptions.RenderingAlgorithm.MAXIMUM_OPTIMIZATION)
.setSymbol(SimpleFastPointOverlayOptions.Shape.CIRCLE)
.setPointStyle(style)
.setRadius(6F * scalingFactor) // radius is set in px - scaling factor makes that display density independent (= dp)
.setIsClickable(true)
// .setCellSize(15) // Sets the grid cell size used for indexing, in pixels. Larger cells result in faster rendering speed, but worse fidelity. Default is 10 pixels, for large datasets (>10k points), use 15.
// create and return overlay
val overlay: SimpleFastPointOverlay = SimpleFastPointOverlay(pointTheme, overlayOptions)
overlay.setOnClickListener(object : SimpleFastPointOverlay.OnClickListener {
override fun onClick(points: SimpleFastPointOverlay.PointAdapter?, point: Int?) {
if (points != null && point != null) {
val markerPoint: IGeoPoint = points.get(point)
markerListener.onMarkerTapped(markerPoint.latitude, markerPoint.longitude)
}
}
})
return overlay
}
/* Creates overlay containing start, stop, stopover and starred markers for track */
fun createSpecialMakersTrackOverlay(context: Context, track: Track, trackingState: Int, displayStartEndMarker: Boolean = false): ItemizedIconOverlay<OverlayItem> {
val overlayItems: ArrayList<OverlayItem> = ArrayList<OverlayItem>()
val wayPoints: MutableList<WayPoint> = track.wayPoints
val maxIndex: Int = wayPoints.size - 1
val trackingActive: Boolean = trackingState == Keys.STATE_TRACKING_ACTIVE
val maxIndex: Int = track.wayPoints.size - 1
when (trackingState) {
// CASE: Recording is active
Keys.STATE_TRACKING_ACTIVE -> {
wayPoints.forEach { wayPoint: WayPoint ->
// get drawable
val newMarker: Drawable
if (wayPoint.starred) {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_star_red_24dp)!!
track.wayPoints.forEachIndexed { index: Int, wayPoint: WayPoint ->
var overlayItem: OverlayItem? = null
if (!trackingActive && index == 0 && displayStartEndMarker && wayPoint.starred) {
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_starred_blue_48dp)!!)
} else if (!trackingActive && index == 0 && displayStartEndMarker && !wayPoint.starred) {
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_blue_48dp)!!)
} else if (!trackingActive && index == maxIndex && displayStartEndMarker && wayPoint.starred) {
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_starred_blue_48dp)!!)
} else if (!trackingActive && index == maxIndex && displayStartEndMarker && !wayPoint.starred) {
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_blue_48dp)!!)
} else if (!trackingActive && wayPoint.starred) {
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_star_blue_24dp)!!)
} else if (trackingActive && wayPoint.starred) {
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_star_red_24dp)!!)
} else if (wayPoint.isStopOver) {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!!
} else {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_red_24dp)!!
}
// create overlay item and add to list of overlay items
val overlayItem: OverlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
overlayItem.setMarker(newMarker)
overlayItems.add(overlayItem)
}
}
// CASE: Recording is paused/stopped
else -> {
wayPoints.forEachIndexed { index: Int, wayPoint: WayPoint ->
// get drawable
val newMarker: Drawable
if (displayStartEndMarker && index == 0) {
if (wayPoint.starred) {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_starred_blue_48dp)!!
} else {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_blue_48dp)!!
}
} else if (displayStartEndMarker && index == maxIndex) {
if (wayPoint.starred) {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_starred_blue_48dp)!!
} else {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_blue_48dp)!!
}
}
else if (wayPoint.starred) {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_star_blue_24dp)!!
} else if (wayPoint.isStopOver) {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!!
} else {
newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_blue_24dp)!!
}
// create overlay item and add to list of overlay items
val overlayItem: OverlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
overlayItem.setMarker(newMarker)
overlayItems.add(overlayItem)
}
overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time)
overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!!)
}
// add overlay item, if it was created
if (overlayItem != null) overlayItems.add(overlayItem)
}
// create and return overlay for current position
return createOverlay(context, overlayItems, enableStarring = true, displayStartEndMarker = displayStartEndMarker)
return createOverlay(context, overlayItems, enableStarring = true)
}
@ -163,12 +185,12 @@ class MapOverlayHelper (private var markerListener: MarkerListener) {
/* Creates an overlay */
private fun createOverlay(context: Context, overlayItems: ArrayList<OverlayItem>, enableStarring: Boolean, displayStartEndMarker: Boolean): ItemizedIconOverlay<OverlayItem> {
private fun createOverlay(context: Context, overlayItems: ArrayList<OverlayItem>, enableStarring: Boolean): ItemizedIconOverlay<OverlayItem> {
return ItemizedIconOverlay<OverlayItem>(context, overlayItems,
object : ItemizedIconOverlay.OnItemGestureListener<OverlayItem> {
override fun onItemSingleTapUp(index: Int, item: OverlayItem): Boolean {
if (enableStarring) {
markerListener.onMarkerTapped(item.point.latitude, item.point.longitude, displayStartEndMarker)
markerListener.onMarkerTapped(item.point.latitude, item.point.longitude)
return true
} else {
return false

View File

@ -41,6 +41,7 @@ import org.osmdroid.views.overlay.OverlayItem
import org.osmdroid.views.overlay.TilesOverlay
import org.osmdroid.views.overlay.compass.CompassOverlay
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
import org.y20k.trackbook.Keys
import org.y20k.trackbook.R
import org.y20k.trackbook.core.Track
@ -67,7 +68,8 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
val resumeButton: FloatingActionButton
var userInteraction: Boolean = false
private var currentPositionOverlay: ItemizedIconOverlay<OverlayItem>
private var currentTrackOverlay: ItemizedIconOverlay<OverlayItem>?
private var currentTrackOverlay: SimpleFastPointOverlay?
private var currentTrackSpecialMarkerOverlay: ItemizedIconOverlay<OverlayItem>?
private var locationErrorBar: Snackbar
private var controller: IMapController
private var zoomLevel: Double
@ -112,8 +114,9 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
mapView.overlays.add(currentPositionOverlay)
centerMap(startLocation)
// initialize track overlay
// initialize track overlays
currentTrackOverlay = null
currentTrackSpecialMarkerOverlay = null
// initialize recording button state
updateRecordingButton(trackingState)
@ -162,13 +165,19 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar
/* Overlay current track on map */
fun overlayCurrentTrack(track: Track, trackingState: Int, displayStartEndMarker: Boolean) {
fun overlayCurrentTrack(track: Track, trackingState: Int) {
if (currentTrackOverlay != null) {
mapView.overlays.remove(currentTrackOverlay)
}
if (currentTrackSpecialMarkerOverlay != null) {
mapView.overlays.remove(currentTrackSpecialMarkerOverlay)
}
if (track.wayPoints.isNotEmpty()) {
currentTrackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, trackingState, displayStartEndMarker)
val mapOverlayHelper: MapOverlayHelper = MapOverlayHelper(markerListener)
currentTrackOverlay = mapOverlayHelper.createTrackOverlay(context, track, trackingState)
currentTrackSpecialMarkerOverlay = mapOverlayHelper.createSpecialMakersTrackOverlay(context, track, trackingState)
mapView.overlays.add(currentTrackOverlay)
mapView.overlays.add(currentTrackSpecialMarkerOverlay)
}
}

View File

@ -45,6 +45,7 @@ import org.osmdroid.views.overlay.OverlayItem
import org.osmdroid.views.overlay.TilesOverlay
import org.osmdroid.views.overlay.compass.CompassOverlay
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
import org.y20k.trackbook.Keys
import org.y20k.trackbook.R
import org.y20k.trackbook.core.Track
@ -68,7 +69,8 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
val editButton: ImageButton
val trackNameView: MaterialTextView
private val mapView: MapView
private var trackOverlay: ItemizedIconOverlay<OverlayItem>?
private var trackSpecialMarkersOverlay: ItemizedIconOverlay<OverlayItem>?
private var trackOverlay: SimpleFastPointOverlay?
private var controller: IMapController
private var zoomLevel: Double
private val statisticsSheetBehavior: BottomSheetBehavior<View>
@ -146,9 +148,12 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
mapView.overlays.add(compassOverlay)
// create map overlay
trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true)
val mapOverlayHelper: MapOverlayHelper = MapOverlayHelper(markerListener)
trackOverlay = mapOverlayHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT)
trackSpecialMarkersOverlay = mapOverlayHelper.createSpecialMakersTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true)
if (track.wayPoints.isNotEmpty()) {
mapView.overlays.add(trackOverlay)
mapView.overlays.add(trackSpecialMarkersOverlay)
}
// set up and show statistics sheet
@ -168,14 +173,20 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
/* Updates map overlay */
fun updateTrackOverlay(newTrack: Track, displayStartEndMarker: Boolean) {
fun updateTrackOverlay(newTrack: Track) {
track = newTrack
if (trackOverlay != null) {
mapView.overlays.remove(trackOverlay)
}
if (trackSpecialMarkersOverlay != null) {
mapView.overlays.remove(trackSpecialMarkersOverlay)
}
if (track.wayPoints.isNotEmpty()) {
trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker)
val mapOverlayHelper: MapOverlayHelper = MapOverlayHelper(markerListener)
trackOverlay = mapOverlayHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT)
trackSpecialMarkersOverlay = mapOverlayHelper.createSpecialMakersTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true)
mapView.overlays.add(trackOverlay)
mapView.overlays.add(trackSpecialMarkersOverlay)
}
}