Fit chart to the map view (track details)
This commit is contained in:
parent
6af7b1aeb3
commit
4fc57fd04c
4 changed files with 183 additions and 54 deletions
|
@ -337,6 +337,7 @@ public class GPXUtilities {
|
||||||
channelBottom = channelBase;
|
channelBottom = channelBase;
|
||||||
channelThres = channelThresMin;
|
channelThres = channelThresMin;
|
||||||
|
|
||||||
|
float segmentDistance = 0f;
|
||||||
metricEnd += s.metricEnd;
|
metricEnd += s.metricEnd;
|
||||||
secondaryMetricEnd += s.secondaryMetricEnd;
|
secondaryMetricEnd += s.secondaryMetricEnd;
|
||||||
points += numberOfPoints;
|
points += numberOfPoints;
|
||||||
|
@ -448,7 +449,8 @@ public class GPXUtilities {
|
||||||
// a little more exact, also seems slightly faster:
|
// a little more exact, also seems slightly faster:
|
||||||
net.osmand.Location.distanceBetween(prev.lat, prev.lon, point.lat, point.lon, calculations);
|
net.osmand.Location.distanceBetween(prev.lat, prev.lon, point.lat, point.lon, calculations);
|
||||||
totalDistance += calculations[0];
|
totalDistance += calculations[0];
|
||||||
point.distance = totalDistance;
|
segmentDistance += calculations[0];
|
||||||
|
point.distance = segmentDistance;
|
||||||
timeDiff = (int)((point.time - prev.time) / 1000);
|
timeDiff = (int)((point.time - prev.time) / 1000);
|
||||||
|
|
||||||
// Motion detection:
|
// Motion detection:
|
||||||
|
|
|
@ -10,15 +10,20 @@ import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.github.mikephil.charting.charts.LineChart;
|
import com.github.mikephil.charting.charts.LineChart;
|
||||||
|
import com.github.mikephil.charting.data.Entry;
|
||||||
import com.github.mikephil.charting.data.LineData;
|
import com.github.mikephil.charting.data.LineData;
|
||||||
import com.github.mikephil.charting.highlight.Highlight;
|
import com.github.mikephil.charting.highlight.Highlight;
|
||||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||||
import com.github.mikephil.charting.listener.ChartTouchListener;
|
import com.github.mikephil.charting.listener.ChartTouchListener;
|
||||||
import com.github.mikephil.charting.listener.OnChartGestureListener;
|
import com.github.mikephil.charting.listener.OnChartGestureListener;
|
||||||
|
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
|
||||||
|
|
||||||
import net.osmand.data.LatLon;
|
import net.osmand.data.LatLon;
|
||||||
|
import net.osmand.data.QuadRect;
|
||||||
|
import net.osmand.data.RotatedTileBox;
|
||||||
import net.osmand.plus.GPXUtilities;
|
import net.osmand.plus.GPXUtilities;
|
||||||
import net.osmand.plus.GPXUtilities.GPXTrackAnalysis;
|
import net.osmand.plus.GPXUtilities.GPXTrackAnalysis;
|
||||||
|
import net.osmand.plus.GPXUtilities.TrkSegment;
|
||||||
import net.osmand.plus.GPXUtilities.WptPt;
|
import net.osmand.plus.GPXUtilities.WptPt;
|
||||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||||
import net.osmand.plus.IconsCache;
|
import net.osmand.plus.IconsCache;
|
||||||
|
@ -43,6 +48,7 @@ public class TrackDetailsMenu {
|
||||||
private MapActivity mapActivity;
|
private MapActivity mapActivity;
|
||||||
private GpxDisplayItem gpxItem;
|
private GpxDisplayItem gpxItem;
|
||||||
private TrackDetailsBarController toolbarController;
|
private TrackDetailsBarController toolbarController;
|
||||||
|
private TrkSegment segment;
|
||||||
|
|
||||||
private static boolean VISIBLE;
|
private static boolean VISIBLE;
|
||||||
|
|
||||||
|
@ -99,6 +105,7 @@ public class TrackDetailsMenu {
|
||||||
if (fragmentRef != null) {
|
if (fragmentRef != null) {
|
||||||
fragmentRef.get().dismiss();
|
fragmentRef.get().dismiss();
|
||||||
} else {
|
} else {
|
||||||
|
segment = null;
|
||||||
VISIBLE = false;
|
VISIBLE = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,31 +136,19 @@ public class TrackDetailsMenu {
|
||||||
mapActivity.getMapLayers().getMapInfoLayer().setSelectedPointLatLon(null);
|
mapActivity.getMapLayers().getMapInfoLayer().setSelectedPointLatLon(null);
|
||||||
mapActivity.getMapView().setMapPositionX(0);
|
mapActivity.getMapView().setMapPositionX(0);
|
||||||
mapActivity.getMapView().refreshMap();
|
mapActivity.getMapView().refreshMap();
|
||||||
|
segment = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateInfo(final View main) {
|
public void updateInfo(final View main) {
|
||||||
updateView(main);
|
updateView(main);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateView(final View parentView) {
|
private TrkSegment getTrackSegment(LineChart chart) {
|
||||||
final LineChart chart = (LineChart) parentView.findViewById(R.id.chart);
|
if (segment == null) {
|
||||||
chart.setOnChartGestureListener(new OnChartGestureListener() {
|
|
||||||
@Override
|
|
||||||
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
|
|
||||||
gpxItem.chartMatrix = new Matrix(chart.getViewPortHandler().getMatrixTouch());
|
|
||||||
Highlight[] highlights = chart.getHighlighted();
|
|
||||||
if (highlights != null && highlights.length > 0) {
|
|
||||||
gpxItem.chartHighlightPos = highlights[0].getX();
|
|
||||||
|
|
||||||
List<ILineDataSet> ds = chart.getLineData().getDataSets();
|
List<ILineDataSet> ds = chart.getLineData().getDataSets();
|
||||||
if (ds != null && ds.size() > 0) {
|
if (ds != null && ds.size() > 0) {
|
||||||
GPXUtilities.TrkSegment segment = null;
|
|
||||||
for (GPXUtilities.Track t : gpxItem.group.getGpx().tracks) {
|
for (GPXUtilities.Track t : gpxItem.group.getGpx().tracks) {
|
||||||
for (GPXUtilities.TrkSegment s : t.segments) {
|
for (TrkSegment s : t.segments) {
|
||||||
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
|
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
|
||||||
segment = s;
|
segment = s;
|
||||||
break;
|
break;
|
||||||
|
@ -163,11 +158,19 @@ public class TrackDetailsMenu {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (segment != null) {
|
}
|
||||||
|
}
|
||||||
|
return segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
private WptPt getPoint(LineChart chart, float pos) {
|
||||||
WptPt wpt = null;
|
WptPt wpt = null;
|
||||||
|
List<ILineDataSet> ds = chart.getLineData().getDataSets();
|
||||||
|
if (ds != null && ds.size() > 0) {
|
||||||
|
TrkSegment segment = getTrackSegment(chart);
|
||||||
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
|
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
|
||||||
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) {
|
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) {
|
||||||
float time = gpxItem.chartHighlightPos * 1000;
|
float time = pos * 1000;
|
||||||
for (WptPt p : segment.points) {
|
for (WptPt p : segment.points) {
|
||||||
if (p.time - gpxItem.analysis.startTime >= time) {
|
if (p.time - gpxItem.analysis.startTime >= time) {
|
||||||
wpt = p;
|
wpt = p;
|
||||||
|
@ -175,7 +178,7 @@ public class TrackDetailsMenu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
float distance = gpxItem.chartHighlightPos * dataSet.getDivX();
|
float distance = pos * dataSet.getDivX();
|
||||||
for (WptPt p : segment.points) {
|
for (WptPt p : segment.points) {
|
||||||
if (p.distance >= distance) {
|
if (p.distance >= distance) {
|
||||||
wpt = p;
|
wpt = p;
|
||||||
|
@ -183,19 +186,123 @@ public class TrackDetailsMenu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return wpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private QuadRect getRect(LineChart chart, float startPos, float endPos) {
|
||||||
|
double left = 0, right = 0;
|
||||||
|
double top = 0, bottom = 0;
|
||||||
|
List<ILineDataSet> ds = chart.getLineData().getDataSets();
|
||||||
|
if (ds != null && ds.size() > 0) {
|
||||||
|
TrkSegment segment = getTrackSegment(chart);
|
||||||
|
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
|
||||||
|
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) {
|
||||||
|
float startTime = startPos * 1000;
|
||||||
|
float endTime = endPos * 1000;
|
||||||
|
for (WptPt p : segment.points) {
|
||||||
|
if (p.time - gpxItem.analysis.startTime >= startTime &&
|
||||||
|
p.time - gpxItem.analysis.startTime <= endTime) {
|
||||||
|
if (left == 0 && right == 0) {
|
||||||
|
left = p.getLongitude();
|
||||||
|
right = p.getLongitude();
|
||||||
|
top = p.getLatitude();
|
||||||
|
bottom = p.getLatitude();
|
||||||
|
} else {
|
||||||
|
left = Math.min(left, p.getLongitude());
|
||||||
|
right = Math.max(right, p.getLongitude());
|
||||||
|
top = Math.max(top, p.getLatitude());
|
||||||
|
bottom = Math.min(bottom, p.getLatitude());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
float startDistance = startPos * dataSet.getDivX();
|
||||||
|
float endDistance = endPos * dataSet.getDivX();
|
||||||
|
for (WptPt p : segment.points) {
|
||||||
|
if (p.distance >= startDistance && p.distance <= endDistance) {
|
||||||
|
if (left == 0 && right == 0) {
|
||||||
|
left = p.getLongitude();
|
||||||
|
right = p.getLongitude();
|
||||||
|
top = p.getLatitude();
|
||||||
|
bottom = p.getLatitude();
|
||||||
|
} else {
|
||||||
|
left = Math.min(left, p.getLongitude());
|
||||||
|
right = Math.max(right, p.getLongitude());
|
||||||
|
top = Math.max(top, p.getLatitude());
|
||||||
|
bottom = Math.min(bottom, p.getLatitude());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new QuadRect(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fitTrackOnMap(LineChart chart) {
|
||||||
|
QuadRect rect = getRect(chart, chart.getLowestVisibleX(), chart.getHighestVisibleX());
|
||||||
|
if (rect != null) {
|
||||||
|
RotatedTileBox tb = mapActivity.getMapView().getCurrentRotatedTileBox().copy();
|
||||||
|
int tileBoxWidthPx = 0;
|
||||||
|
int tileBoxHeightPx = 0;
|
||||||
|
|
||||||
|
WeakReference<TrackDetailsMenuFragment> fragmentRef = findMenuFragment();
|
||||||
|
if (fragmentRef != null) {
|
||||||
|
TrackDetailsMenuFragment f = fragmentRef.get();
|
||||||
|
boolean portrait = AndroidUiHelper.isOrientationPortrait(mapActivity);
|
||||||
|
if (!portrait) {
|
||||||
|
tileBoxWidthPx = tb.getPixWidth() - f.getWidth();
|
||||||
|
} else {
|
||||||
|
tileBoxHeightPx = tb.getPixHeight() - f.getHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapActivity.getMapView().fitRectToMap(rect.left, rect.right, rect.top, rect.bottom,
|
||||||
|
tileBoxWidthPx, tileBoxHeightPx, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void refreshChart(LineChart chart) {
|
||||||
|
gpxItem.chartMatrix = new Matrix(chart.getViewPortHandler().getMatrixTouch());
|
||||||
|
Highlight[] highlights = chart.getHighlighted();
|
||||||
|
if (highlights != null && highlights.length > 0) {
|
||||||
|
gpxItem.chartHighlightPos = highlights[0].getX();
|
||||||
|
WptPt wpt = getPoint(chart, gpxItem.chartHighlightPos);
|
||||||
if (wpt != null) {
|
if (wpt != null) {
|
||||||
if (gpxItem.route) {
|
if (gpxItem.route) {
|
||||||
mapActivity.getMapLayers().getMapInfoLayer().setSelectedPointLatLon(new LatLon(wpt.lat, wpt.lon));
|
mapActivity.getMapLayers().getMapInfoLayer().setSelectedPointLatLon(new LatLon(wpt.lat, wpt.lon));
|
||||||
} else {
|
} else {
|
||||||
mapActivity.getMapLayers().getGpxLayer().setSelectedPointLatLon(new LatLon(wpt.lat, wpt.lon));
|
mapActivity.getMapLayers().getGpxLayer().setSelectedPointLatLon(new LatLon(wpt.lat, wpt.lon));
|
||||||
}
|
}
|
||||||
mapActivity.setMapLocation(wpt.lat, wpt.lon);
|
//mapActivity.setMapLocation(wpt.lat, wpt.lon);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gpxItem.chartHighlightPos = -1;
|
gpxItem.chartHighlightPos = -1;
|
||||||
}
|
}
|
||||||
|
fitTrackOnMap(chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateView(final View parentView) {
|
||||||
|
final LineChart chart = (LineChart) parentView.findViewById(R.id.chart);
|
||||||
|
chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onValueSelected(Entry e, Highlight h) {
|
||||||
|
refreshChart(chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
chart.setOnChartGestureListener(new OnChartGestureListener() {
|
||||||
|
@Override
|
||||||
|
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
|
||||||
|
refreshChart(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -343,6 +450,8 @@ public class TrackDetailsMenu {
|
||||||
xAxis.setBackgroundResource(0);
|
xAxis.setBackgroundResource(0);
|
||||||
xAxisArrow.setVisibility(View.GONE);
|
xAxisArrow.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshChart(chart);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateChart(LineChart chart) {
|
private void updateChart(LineChart chart) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package net.osmand.plus.mapcontextmenu.other;
|
package net.osmand.plus.mapcontextmenu.other;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
|
@ -7,6 +8,7 @@ import android.support.v4.app.FragmentManager;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewTreeObserver;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -61,6 +63,22 @@ public class TrackDetailsMenuFragment extends Fragment {
|
||||||
|
|
||||||
updateInfo();
|
updateInfo();
|
||||||
|
|
||||||
|
ViewTreeObserver vto = mainView.getViewTreeObserver();
|
||||||
|
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGlobalLayout() {
|
||||||
|
|
||||||
|
ViewTreeObserver obs = mainView.getViewTreeObserver();
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||||
|
obs.removeOnGlobalLayoutListener(this);
|
||||||
|
} else {
|
||||||
|
obs.removeGlobalOnLayoutListener(this);
|
||||||
|
}
|
||||||
|
updateInfo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -636,7 +636,7 @@ public class MapControlsLayer extends OsmandMapLayer {
|
||||||
boolean trackDialogOpened = TrackDetailsMenu.isVisible();
|
boolean trackDialogOpened = TrackDetailsMenu.isVisible();
|
||||||
boolean showRouteCalculationControls = routePlanningMode ||
|
boolean showRouteCalculationControls = routePlanningMode ||
|
||||||
((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode);
|
((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode);
|
||||||
updateMyLocation(rh, routeDialogOpened);
|
updateMyLocation(rh, routeDialogOpened || trackDialogOpened);
|
||||||
boolean showButtons = (showRouteCalculationControls || !routeFollowingMode)
|
boolean showButtons = (showRouteCalculationControls || !routeFollowingMode)
|
||||||
&& !isInChangeMarkerPositionMode() && !isInGpxDetailsMode();
|
&& !isInChangeMarkerPositionMode() && !isInGpxDetailsMode();
|
||||||
//routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_gabout_dark : R.drawable.map_directions);
|
//routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_gabout_dark : R.drawable.map_directions);
|
||||||
|
|
Loading…
Reference in a new issue