Merge pull request #7317 from osmandapp/GpxStatisticImprovements

Fix #7054
This commit is contained in:
vshcherb 2019-07-23 15:25:19 +02:00 committed by GitHub
commit ad50979f2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 217 additions and 14 deletions

View file

@ -159,12 +159,16 @@ public class GPXUtilities {
public float distance;
public int time;
public float elevation;
public boolean firstPoint = false;
public boolean lastPoint = false;
}
public static class Speed {
public float distance;
public int time;
public float speed;
public boolean firstPoint = false;
public boolean lastPoint = false;
}
public static class WptPt extends GPXExtensions {
@ -355,15 +359,19 @@ public class GPXUtilities {
public static class GPXTrackAnalysis {
public float totalDistance = 0;
public float totalDistanceWithoutGaps = 0;
public int totalTracks = 0;
public long startTime = Long.MAX_VALUE;
public long endTime = Long.MIN_VALUE;
public long timeSpan = 0;
public long timeSpanWithoutGaps = 0;
//Next few lines for Issue 3222 heuristic testing only
//public long timeMoving0 = 0;
//public float totalDistanceMoving0 = 0;
public long timeMoving = 0;
public long timeMovingWithoutGaps = 0;
public float totalDistanceMoving = 0;
public float totalDistanceMovingWithoutGaps = 0;
public double diffElevationUp = 0;
public double diffElevationDown = 0;
@ -432,6 +440,10 @@ public class GPXUtilities {
long startTimeOfSingleSegment = 0;
long endTimeOfSingleSegment = 0;
float distanceOfSingleSegment = 0;
float distanceMovingOfSingleSegment = 0;
long timeMovingOfSingleSegment = 0;
float totalElevation = 0;
int elevationPoints = 0;
int speedCount = 0;
@ -479,7 +491,7 @@ public class GPXUtilities {
endTimeOfSingleSegment = time;
}
if (startTimeOfSingleSegment != 0 && endTimeOfSingleSegment != 0) {
timeSpan += endTimeOfSingleSegment - startTimeOfSingleSegment;
timeSpanWithoutGaps += endTimeOfSingleSegment - startTimeOfSingleSegment;
startTimeOfSingleSegment = 0;
endTimeOfSingleSegment = 0;
}
@ -627,6 +639,10 @@ public class GPXUtilities {
if ((speed > 0) && (calculations[0] > 0.1 / 1000f * (point.time - prev.time)) && point.time != 0 && prev.time != 0) {
timeMoving = timeMoving + (point.time - prev.time);
totalDistanceMoving += calculations[0];
if (s.segment.generalSegment && !point.firstPoint) {
timeMovingOfSingleSegment += point.time - prev.time;
distanceMovingOfSingleSegment += calculations[0];
}
}
//Next few lines for Issue 3222 heuristic testing only
@ -658,6 +674,27 @@ public class GPXUtilities {
if (!hasSpeedData && speed1.speed > 0 && totalDistance > 0) {
hasSpeedData = true;
}
if (s.segment.generalSegment) {
distanceOfSingleSegment += calculations[0];
if (point.firstPoint) {
distanceOfSingleSegment = 0;
timeMovingOfSingleSegment = 0;
distanceMovingOfSingleSegment = 0;
if (j > 0) {
elevation1.firstPoint = true;
speed1.firstPoint = true;
}
}
if (point.lastPoint) {
totalDistanceWithoutGaps += distanceOfSingleSegment;
timeMovingWithoutGaps += timeMovingOfSingleSegment;
totalDistanceMovingWithoutGaps += distanceMovingOfSingleSegment;
if (j < numberOfPoints - 1) {
elevation1.lastPoint = true;
speed1.lastPoint = true;
}
}
}
}
}
if (totalDistance < 0) {

View file

@ -18,6 +18,35 @@
android:layout_height="150dp"
android:layout_gravity="center_vertical"/>
<LinearLayout
android:id="@+id/gpx_join_gaps_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/card_row_min_height"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/gpx_join_gaps_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:text="@string/gpx_join_gaps"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular" />
<android.support.v7.widget.SwitchCompat
android:id="@+id/gpx_join_gaps_switch"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding" />
</LinearLayout>
<LinearLayout
android:id="@+id/average_range"
android:layout_width="match_parent"

View file

@ -18,6 +18,35 @@
android:layout_height="150dp"
android:layout_gravity="center_vertical"/>
<LinearLayout
android:id="@+id/gpx_join_gaps_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/card_row_min_height"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/gpx_join_gaps_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:text="@string/gpx_join_gaps"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular" />
<android.support.v7.widget.SwitchCompat
android:id="@+id/gpx_join_gaps_switch"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding" />
</LinearLayout>
<LinearLayout
android:id="@+id/distance_time_span"
android:layout_width="match_parent"

View file

@ -18,6 +18,35 @@
android:layout_height="150dp"
android:layout_gravity="center_vertical"/>
<LinearLayout
android:id="@+id/gpx_join_gaps_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/card_row_min_height"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/gpx_join_gaps_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:text="@string/gpx_join_gaps"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular" />
<android.support.v7.widget.SwitchCompat
android:id="@+id/gpx_join_gaps_switch"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding" />
</LinearLayout>
<LinearLayout
android:id="@+id/average_max"
android:layout_width="match_parent"

View file

@ -11,6 +11,7 @@
Thx - Hardy
-->
<string name="gpx_join_gaps">Join gaps</string>
<string name="app_mode_camper">Camper</string>
<string name="app_mode_campervan">Campervan</string>
<string name="rendering_attr_showLez_description">Show Low Emission zones on the map. Does not affect routing.</string>

View file

@ -197,6 +197,7 @@ public class GpxSelectionHelper {
d = t.name + " " + d;
}
group.setDescription(d);
group.setGeneralTrack(true);
processGroupTrack(app, group);
return group;
}
@ -215,6 +216,7 @@ public class GpxSelectionHelper {
d = t.name + " " + d;
}
group.setDescription(d);
group.setGeneralTrack(t.generalTrack);
processGroupTrack(app, group);
return group;
}
@ -771,6 +773,7 @@ public class GpxSelectionHelper {
private double splitDistance = -1;
private int splitTime = -1;
private int color;
private boolean generalTrack;
public GpxDisplayGroup(GPXFile gpx) {
this.gpx = gpx;
@ -878,6 +881,14 @@ public class GpxSelectionHelper {
public void setColor(int color) {
this.color = color;
}
public boolean isGeneralTrack() {
return generalTrack;
}
public void setGeneralTrack(boolean generalTrack) {
this.generalTrack = generalTrack;
}
}
public static class GpxDisplayItem {
@ -903,5 +914,9 @@ public class GpxSelectionHelper {
public Matrix chartMatrix;
public float chartHighlightPos = -1f;
public boolean isGeneralTrack() {
return group != null && group.isGeneralTrack();
}
}
}

View file

@ -1164,7 +1164,7 @@ public class GpxUiHelper {
}
private static List<Entry> calculateElevationArray(GPXTrackAnalysis analysis, GPXDataSetAxisType axisType,
float divX, float convEle) {
float divX, float convEle, boolean useGeneralTrackPoints) {
List<Entry> values = new ArrayList<>();
List<Elevation> elevationData = analysis.elevationData;
float nextX = 0;
@ -1207,6 +1207,9 @@ public class GpxUiHelper {
}
hasSameY = false;
}
if (useGeneralTrackPoints && e.firstPoint && lastEntry != null) {
values.add(new Entry(nextX, lastEntry.getY()));
}
prevElevOrig = e.elevation;
prevElev = elev;
nextY = elev * convEle;
@ -1352,7 +1355,7 @@ public class GpxUiHelper {
}
});
List<Entry> values = calculateElevationArray(analysis, axisType, divX, convEle);
List<Entry> values = calculateElevationArray(analysis, axisType, divX, convEle, true);
OrderedLineDataSet dataSet = new OrderedLineDataSet(values, "", GPXDataSetType.ALTITUDE, axisType);
dataSet.priority = (float) (analysis.avgElevation - analysis.minElevation) * convEle;
@ -1483,7 +1486,13 @@ public class GpxUiHelper {
if (nextY < 0 || Float.isInfinite(nextY)) {
nextY = 0;
}
if (s.firstPoint) {
values.add(new Entry(nextX, 0));
}
values.add(new Entry(nextX, nextY));
if (s.lastPoint) {
values.add(new Entry(nextX, 0));
}
}
}
@ -1602,7 +1611,7 @@ public class GpxUiHelper {
List<Entry> values;
if (eleValues == null) {
values = calculateElevationArray(analysis, GPXDataSetAxisType.DISTANCE, 1f, 1f);
values = calculateElevationArray(analysis, GPXDataSetAxisType.DISTANCE, 1f, 1f, false);
} else {
values = new ArrayList<>(eleValues.size());
for (Entry e : eleValues) {

View file

@ -16,6 +16,7 @@ import android.support.v4.view.MenuItemCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.SwitchCompat;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
@ -60,6 +61,7 @@ import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.base.OsmAndListFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
@ -91,6 +93,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
private boolean updateEnable;
private boolean chartClicked;
private boolean joinGapsEnabled;
private IconPopupMenu generalPopupMenu;
private IconPopupMenu altitudePopupMenu;
@ -455,7 +458,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
dataSets.add(elevationDataSet);
}
if (analysis.hasElevationData) {
List<Entry> eleValues = elevationDataSet != null ? elevationDataSet.getValues() : null;
List<Entry> eleValues = elevationDataSet != null && !gpxItem.isGeneralTrack() ? elevationDataSet.getValues() : null;
OrderedLineDataSet slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart,
analysis, GPXDataSetAxisType.DISTANCE, eleValues, true, true);
if (slopeDataSet != null) {
@ -713,11 +716,17 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
((ImageView) view.findViewById(R.id.end_time_icon))
.setImageDrawable(ic.getThemedIcon(R.drawable.ic_action_time_end));
((TextView) view.findViewById(R.id.distance_text))
.setText(OsmAndFormatter.getFormattedDistance(analysis.totalDistance, app));
((TextView) view.findViewById(R.id.duration_text))
.setText(Algorithms.formatDuration((int) (analysis.timeSpan / 1000), app.accessibilityEnabled()));
final SwitchCompat joinGapsSwitch = (SwitchCompat) view.findViewById(R.id.gpx_join_gaps_switch);
joinGapsSwitch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
joinGapsEnabled = joinGapsSwitch.isChecked();
for (int i = 0; i < getCount(); i++) {
View view = getViewAtPosition(i);
updateJoinGapsInfo(view, i);
}
}
});
if (analysis.timeSpan > 0) {
DateFormat tf = SimpleDateFormat.getTimeInstance(DateFormat.SHORT);
DateFormat df = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM);
@ -738,6 +747,7 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
view.findViewById(R.id.start_end_time).setVisibility(View.GONE);
}
updateJoinGapsInfo(view, position);
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -844,12 +854,24 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
((TextView) view.findViewById(R.id.ascent_text)).setText(asc);
((TextView) view.findViewById(R.id.descent_text)).setText(desc);
final SwitchCompat joinGapsSwitch = (SwitchCompat) view.findViewById(R.id.gpx_join_gaps_switch);
joinGapsSwitch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
joinGapsEnabled = joinGapsSwitch.isChecked();
for (int i = 0; i < getCount(); i++) {
View view = getViewAtPosition(i);
updateJoinGapsInfo(view, i);
}
}
});
} else {
chart.setVisibility(View.GONE);
view.findViewById(R.id.average_range).setVisibility(View.GONE);
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
view.findViewById(R.id.ascent_descent).setVisibility(View.GONE);
}
updateJoinGapsInfo(view, position);
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -938,17 +960,25 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
((TextView) view.findViewById(R.id.average_text)).setText(avg);
((TextView) view.findViewById(R.id.max_text)).setText(max);
((TextView) view.findViewById(R.id.time_moving_text))
.setText(Algorithms.formatDuration((int) (analysis.timeMoving / 1000), app.accessibilityEnabled()));
((TextView) view.findViewById(R.id.distance_text))
.setText(OsmAndFormatter.getFormattedDistance(analysis.totalDistanceMoving, app));
final SwitchCompat joinGapsSwitch = (SwitchCompat) view.findViewById(R.id.gpx_join_gaps_switch);
joinGapsSwitch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
joinGapsEnabled = joinGapsSwitch.isChecked();
for (int i = 0; i < getCount(); i++) {
View view = getViewAtPosition(i);
updateJoinGapsInfo(view, i);
}
}
});
} else {
chart.setVisibility(View.GONE);
view.findViewById(R.id.average_max).setVisibility(View.GONE);
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
view.findViewById(R.id.time_distance).setVisibility(View.GONE);
}
updateJoinGapsInfo(view, position);
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -1110,6 +1140,30 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit
}
}
void updateJoinGapsInfo(View view, int position) {
if (view != null) {
GPXTrackAnalysis analysis = gpxItem.analysis;
AndroidUiHelper.updateVisibility(view.findViewById(R.id.gpx_join_gaps_container), gpxItem.isGeneralTrack() && analysis != null);
((SwitchCompat) view.findViewById(R.id.gpx_join_gaps_switch)).setChecked(joinGapsEnabled);
if (analysis != null) {
GPXTabItemType tabType = tabTypes[position];
if (tabType.equals(GPXTabItemType.GPX_TAB_ITEM_GENERAL)) {
float totalDistance = joinGapsEnabled && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
float timeSpan = joinGapsEnabled && gpxItem.isGeneralTrack() ? analysis.timeSpanWithoutGaps : analysis.timeSpan;
((TextView) view.findViewById(R.id.distance_text)).setText(OsmAndFormatter.getFormattedDistance(totalDistance, app));
((TextView) view.findViewById(R.id.duration_text)).setText(Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()));
} else if (tabType.equals(GPXTabItemType.GPX_TAB_ITEM_SPEED)) {
long timeMoving = joinGapsEnabled && gpxItem.isGeneralTrack() ? analysis.timeMovingWithoutGaps : analysis.timeMoving;
float totalDistanceMoving = joinGapsEnabled && gpxItem.isGeneralTrack() ? analysis.totalDistanceMovingWithoutGaps : analysis.totalDistanceMoving;
((TextView) view.findViewById(R.id.time_moving_text)).setText(Algorithms.formatDuration((int) (timeMoving / 1000), app.accessibilityEnabled()));
((TextView) view.findViewById(R.id.distance_text)).setText(OsmAndFormatter.getFormattedDistance(totalDistanceMoving, app));
}
}
}
}
void updateChart(LineChart chart) {
if (chart != null && !chart.isEmpty()) {
if (gpxItem.chartMatrix != null) {