long press on map recording zooms it to bounding box #60

master
y20k 2019-08-12 15:23:48 +02:00
parent 1683dc64e0
commit 7402f872be
No known key found for this signature in database
GPG Key ID: 824D4259F41FAFF6
7 changed files with 156 additions and 107 deletions

View File

@ -24,6 +24,8 @@ import android.content.IntentFilter;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@ -48,10 +50,12 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import org.osmdroid.api.IMapController;
import org.osmdroid.events.MapEventsReceiver;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.ItemizedIconOverlay;
import org.osmdroid.views.overlay.MapEventsOverlay;
import org.osmdroid.views.overlay.TilesOverlay;
import org.osmdroid.views.overlay.compass.CompassOverlay;
import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider;
@ -75,7 +79,7 @@ import java.util.Locale;
/**
* MainActivityTrackFragment class
*/
public class MainActivityTrackFragment extends Fragment implements AdapterView.OnItemSelectedListener, TrackbookKeys {
public class MainActivityTrackFragment extends Fragment implements AdapterView.OnItemSelectedListener, MapEventsReceiver, TrackbookKeys {
/* Define log tag */
private static final String LOG_TAG = MainActivityTrackFragment.class.getSimpleName();
@ -268,6 +272,10 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
attachTapListenerToStatisticsSheet();
}
// enable additional gestures
MapEventsOverlay OverlayEventos = new MapEventsOverlay(this);
mMapView.getOverlays().add(OverlayEventos);
return mRootView;
}
@ -365,6 +373,25 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
}
@Override
public boolean singleTapConfirmedHelper(GeoPoint p) {
return false;
}
@Override
public boolean longPressHelper(GeoPoint p) {
if (mTrack != null) {
// vibrate 50 milliseconds
Vibrator vibrator = (Vibrator) mActivity.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(50);
// zoom to bounding box (= edge coordinates of map)
mMapView.zoomToBoundingBox(mTrack.getBoundingBox(), true);
}
return true;
}
/* Displays map and statistics for track */
private void displayTrack() {
GeoPoint position;
@ -405,7 +432,6 @@ public class MainActivityTrackFragment extends Fragment implements AdapterView.O
// draw track on map
drawTrackOverlay(mTrack);
} else {
position = new GeoPoint(DEFAULT_LATITUDE, DEFAULT_LONGITUDE);
}

View File

@ -54,36 +54,11 @@ public class Track implements TrackbookKeys, Parcelable {
private double mMinAltitude;
private double mPositiveElevation;
private double mNegativeElevation;
private BoundingBox mBoundingBox;
private BoundingBox boundingBox;
/**
* Create a {@code BoundingBox} for the collection of
* {@code WayPoint}s, so that it would be possible to fit the map in
* such box and see the whole {@code Track} in the map without
* manual zooming.
*
* It computes the {@code BoundingBox} only once since it's possibly
* useless to compute it everytime.
*
* @return {@code BoundingBox} containing all {@code Waypoint}s
*/
public BoundingBox getBoundingBox() {
if (null == boundingBox) {
final ArrayList<GeoPoint> geoPoints = new ArrayList<>(mWayPoints.size());
for (final WayPoint aWayPoint : mWayPoints) {
final GeoPoint aGeoPoint = new GeoPoint(aWayPoint.getLocation());
geoPoints.add(aGeoPoint);
}
boundingBox = BoundingBox.fromGeoPoints(geoPoints);
}
return boundingBox;
}
/* Generic Constructor */
public Track(int trackFormatVersion, List<WayPoint> wayPoints, float trackLength, long duration, float stepCount, Date recordingStart, Date recordingStop, double maxAltitude, double minAltitude, double positiveElevation, double negativeElevation) {
public Track(int trackFormatVersion, List<WayPoint> wayPoints, float trackLength, long duration, float stepCount, Date recordingStart, Date recordingStop, double maxAltitude, double minAltitude, double positiveElevation, double negativeElevation, BoundingBox boundingBox) {
mTrackFormatVersion = trackFormatVersion;
mWayPoints = wayPoints;
mTrackLength = trackLength;
@ -95,12 +70,13 @@ public class Track implements TrackbookKeys, Parcelable {
mMinAltitude = minAltitude;
mPositiveElevation = positiveElevation;
mNegativeElevation = negativeElevation;
mBoundingBox = boundingBox;
}
/* Copy Constructor */
public Track(Track track) {
this(track.getTrackFormatVersion(), track.getWayPoints(), track.getTrackLength(), track.getTrackDuration(), track.getStepCount(), track.getRecordingStart(), track.getRecordingStop(), track.getMaxAltitude(), track.getMinAltitude(), track.getPositiveElevation(), track.getNegativeElevation());
this(track.getTrackFormatVersion(), track.getWayPoints(), track.getTrackLength(), track.getTrackDuration(), track.getStepCount(), track.getRecordingStart(), track.getRecordingStop(), track.getMaxAltitude(), track.getMinAltitude(), track.getPositiveElevation(), track.getNegativeElevation(), track.getBoundingBox());
}
@ -117,6 +93,7 @@ public class Track implements TrackbookKeys, Parcelable {
mMinAltitude = 0f;
mPositiveElevation = 0f;
mNegativeElevation = 0f;
mBoundingBox = new BoundingBox();
}
@ -231,6 +208,12 @@ public class Track implements TrackbookKeys, Parcelable {
}
/* Setter for this track's BoundingBox - a data structure describing the edge coordinates of a track */
public void setBoundingBox(BoundingBox boundingBox) {
mBoundingBox = boundingBox;
}
/* Getter for file/track format version */
public int getTrackFormatVersion() {
return mTrackFormatVersion;
@ -302,6 +285,10 @@ public class Track implements TrackbookKeys, Parcelable {
}
/* Getter for this track's BoundingBox - a data structure describing the edge coordinates of a track */
public BoundingBox getBoundingBox() { return mBoundingBox; }
/* Getter recorded distance */
public Double getTrackDistance() {
int size = mWayPoints.size();

View File

@ -17,7 +17,9 @@
package org.y20k.trackbook.core;
import org.osmdroid.util.BoundingBox;
import org.y20k.trackbook.helpers.LogHelper;
import org.y20k.trackbook.helpers.MapHelper;
import java.util.Date;
import java.util.List;
@ -44,10 +46,11 @@ public class TrackBuilder {
private final double mMinAltitude;
private final double mPositiveElevation;
private final double mNegativeElevation;
private BoundingBox mBoundingBox;
/* Generic Constructor */
public TrackBuilder(int trackFormatVersion, List<WayPoint> wayPoints, float trackLength, long duration, float stepCount, Date recordingStart, Date recordingStop, double maxAltitude, double minAltitude, double positiveElevation, double negativeElevation) {
public TrackBuilder(int trackFormatVersion, List<WayPoint> wayPoints, float trackLength, long duration, float stepCount, Date recordingStart, Date recordingStop, double maxAltitude, double minAltitude, double positiveElevation, double negativeElevation, BoundingBox boundingBox) {
mTrackFormatVersion = trackFormatVersion;
mWayPoints = wayPoints;
mTrackLength = trackLength;
@ -59,6 +62,7 @@ public class TrackBuilder {
mMinAltitude = minAltitude;
mPositiveElevation = positiveElevation;
mNegativeElevation = negativeElevation;
mBoundingBox = boundingBox;
}
@ -67,10 +71,13 @@ public class TrackBuilder {
switch (mTrackFormatVersion) {
case 1:
// file format version 1 - does not have elevation data stored
return new Track(mTrackFormatVersion, mWayPoints, mTrackLength, mDuration, mStepCount, mRecordingStart, mRecordingStop, 0f, 0f, 0f, 0f);
return new Track(mTrackFormatVersion, mWayPoints, mTrackLength, mDuration, mStepCount, mRecordingStart, mRecordingStop, 0f, 0f, 0f, 0f, new BoundingBox());
case 2:
// file format version 2 (current version)
return new Track(mTrackFormatVersion, mWayPoints, mTrackLength, mDuration, mStepCount, mRecordingStart, mRecordingStop, mMaxAltitude, mMinAltitude, mPositiveElevation, mNegativeElevation);
// file format version 2 - does not have edge coordinates stored
return new Track(mTrackFormatVersion, mWayPoints, mTrackLength, mDuration, mStepCount, mRecordingStart, mRecordingStop, mMaxAltitude, mMinAltitude, mPositiveElevation, mNegativeElevation, MapHelper.calculateBoundingBox(mWayPoints));
case 3:
// file format version 3 (current version)
return new Track(mTrackFormatVersion, mWayPoints, mTrackLength, mDuration, mStepCount, mRecordingStart, mRecordingStop, mMaxAltitude, mMinAltitude, mPositiveElevation, mNegativeElevation, new BoundingBox());
default:
LogHelper.e(LOG_TAG, "Unknown file format version: " + mTrackFormatVersion);
return null;

View File

@ -21,6 +21,7 @@ import android.graphics.drawable.Drawable;
import android.location.Location;
import android.widget.Toast;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.overlay.ItemizedIconOverlay;
import org.osmdroid.views.overlay.OverlayItem;
@ -33,12 +34,14 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
/**
* MapHelper class
*/
public final class MapHelper {
public final class MapHelper implements TrackbookKeys {
/* Define log tag */
private static final String LOG_TAG = MapHelper.class.getSimpleName();
@ -181,4 +184,92 @@ public final class MapHelper {
return new OverlayItem(title, description, position);
}
/**
* Create a {@code BoundingBox} for the collection of
* {@code WayPoint}s, so that it would be possible to fit the map in
* such box and see the whole {@code Track} in the map without
* manual zooming.
*
* @return {@code BoundingBox} containing all {@code Waypoint}s
*/
public static BoundingBox calculateBoundingBox(List<WayPoint> wayPoints) {
final ArrayList<GeoPoint> geoPoints = new ArrayList<>(wayPoints.size());
for (final WayPoint aWayPoint : wayPoints) {
final GeoPoint aGeoPoint = new GeoPoint(aWayPoint.getLocation());
geoPoints.add(aGeoPoint);
}
return BoundingBox.fromGeoPoints(geoPoints);
}
/* Calculates positive and negative elevation of track */
public static Track calculateElevation(@Nullable Track track) {
double maxAltitude = 0;
double minAltitude = 0;
double positiveElevation = 0;
double negativeElevation = 0;
if (track != null && track.getWayPoints().size() > 0) {
double previousLocationAltitude;
double currentLocationAltitude;
long previousTimeStamp;
long currentTimeStamp;
// initial values for max height and min height - first waypoint
maxAltitude = track.getWayPointLocation(0).getAltitude();
minAltitude = maxAltitude;
// apply filter & smooth data
// track = smoothTrack(track, 15f, 35f);
// iterate over track
for (int i = 1; i < track.getWayPoints().size(); i++ ) {
// get time difference
previousTimeStamp = track.getWayPointLocation(i -1).getTime();
currentTimeStamp = track.getWayPointLocation(i).getTime();
double timeDiff = (currentTimeStamp - previousTimeStamp);
// factor is bigger than 1 if the time stamp difference is larger than the movement recording interval (usually 15 seconds)
double timeDiffFactor = timeDiff / FIFTEEN_SECONDS_IN_MILLISECONDS;
// height of previous and current waypoints
previousLocationAltitude = track.getWayPointLocation(i -1).getAltitude();
currentLocationAltitude = track.getWayPointLocation(i).getAltitude();
// check for new min and max heights
if (currentLocationAltitude > maxAltitude) {
maxAltitude = currentLocationAltitude;
}
if (minAltitude == 0 || currentLocationAltitude < minAltitude) {
minAltitude = currentLocationAltitude;
}
// get elevation difference and sum it up
double altitudeDiff = currentLocationAltitude - previousLocationAltitude;
if (altitudeDiff > 0 && altitudeDiff < MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationAltitude != 0) {
positiveElevation = positiveElevation + altitudeDiff;
}
if (altitudeDiff < 0 && altitudeDiff > -MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationAltitude != 0) {
negativeElevation = negativeElevation + altitudeDiff;
}
}
// store elevation data in track
track.setMaxAltitude(maxAltitude);
track.setMinAltitude(minAltitude);
track.setPositiveElevation(positiveElevation);
track.setNegativeElevation(negativeElevation);
}
return track;
}
}

View File

@ -103,18 +103,20 @@ public class StorageHelper implements TrackbookKeys {
}
if (mFolder != null && mFolder.exists() && mFolder.isDirectory() && mFolder.canWrite() && recordingStart != null && track != null) {
// calculate elevation and store it in track
track = calculateElevation(track);
// create file object
// create file object and calculate bounding box and elevation, if necessary
String fileName;
if (fileType == FILE_TEMP_TRACK) {
// case: temp file
// get the temp file name
fileName = FILE_NAME_TEMP + FILE_TYPE_TRACKBOOK_EXTENSION;
} else {
// case: regular file
// build a regular file name
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US);
fileName = dateFormat.format(recordingStart) + FILE_TYPE_TRACKBOOK_EXTENSION;
// calculate elevation and store it in track
track = MapHelper.calculateElevation(track);
// calculate bounding box and store it in track
track.setBoundingBox(MapHelper.calculateBoundingBox(track.getWayPoints()));
}
File file = new File(mFolder.toString() + "/" + fileName);
@ -360,70 +362,6 @@ public class StorageHelper implements TrackbookKeys {
}
/* Calculates positive and negative elevation of track */
private Track calculateElevation(@Nullable Track track) {
double maxAltitude = 0;
double minAltitude = 0;
double positiveElevation = 0;
double negativeElevation = 0;
if (track != null && track.getWayPoints().size() > 0) {
double previousLocationAltitude;
double currentLocationAltitude;
long previousTimeStamp;
long currentTimeStamp;
// initial values for max height and min height - first waypoint
maxAltitude = track.getWayPointLocation(0).getAltitude();
minAltitude = maxAltitude;
// apply filter & smooth data
// track = smoothTrack(track, 15f, 35f);
// iterate over track
for (int i = 1; i < track.getWayPoints().size(); i++ ) {
// get time difference
previousTimeStamp = track.getWayPointLocation(i -1).getTime();
currentTimeStamp = track.getWayPointLocation(i).getTime();
double timeDiff = (currentTimeStamp - previousTimeStamp);
// factor is bigger than 1 if the time stamp difference is larger than the movement recording interval (usually 15 seconds)
double timeDiffFactor = timeDiff / FIFTEEN_SECONDS_IN_MILLISECONDS;
// height of previous and current waypoints
previousLocationAltitude = track.getWayPointLocation(i -1).getAltitude();
currentLocationAltitude = track.getWayPointLocation(i).getAltitude();
// check for new min and max heights
if (currentLocationAltitude > maxAltitude) {
maxAltitude = currentLocationAltitude;
}
if (minAltitude == 0 || currentLocationAltitude < minAltitude) {
minAltitude = currentLocationAltitude;
}
// get elevation difference and sum it up
double altitudeDiff = currentLocationAltitude - previousLocationAltitude;
if (altitudeDiff > 0 && altitudeDiff < MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationAltitude != 0) {
positiveElevation = positiveElevation + altitudeDiff;
}
if (altitudeDiff < 0 && altitudeDiff > -MEASUREMENT_ERROR_THRESHOLD * timeDiffFactor && currentLocationAltitude != 0) {
negativeElevation = negativeElevation + altitudeDiff;
}
}
// store elevation data in track
track.setMaxAltitude(maxAltitude);
track.setMinAltitude(minAltitude);
track.setPositiveElevation(positiveElevation);
track.setNegativeElevation(negativeElevation);
}
return track;
}
/* Tries to smooth the elevation data using a low pass filter */
private Track smoothTrack(Track input, float dt, float rc) {

View File

@ -113,7 +113,7 @@ public interface TrackbookKeys {
String NOTIFICATION_CHANEL_ID_RECORDING_CHANNEL ="notificationChannelIdRecordingChannel";
/* MISC */
int CURRENT_TRACK_FORMAT_VERSION = 2; // incremental version number to prevent issues in case the Track format evolves
int CURRENT_TRACK_FORMAT_VERSION = 3; // incremental version number to prevent issues in case the Track format evolves
double DEFAULT_LATITUDE = 71.172500; // latitude Nordkapp, Norway
double DEFAULT_LONGITUDE = 25.784444; // longitude Nordkapp, Norway
int MEASUREMENT_ERROR_THRESHOLD = 10; // altitude changes of 10 meter or more (per 15 seconds) are being discarded

View File

@ -24,8 +24,8 @@ allprojects {
project.ext {
applicationId = 'org.y20k.trackbook'
versionCode = 36
versionName = '1.2.2'
versionCode = 37
versionName = '1.2.3'
compileSdkVersion = 28
targetSdkVersion = 27