diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java index ef2dae665f..3a708d8534 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java @@ -1,8 +1,11 @@ package net.osmand.router; +import net.osmand.PlatformUtil; import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRulesStorage; +import org.apache.commons.logging.Log; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -10,7 +13,8 @@ import java.util.TreeMap; public class RouteStatistics { - private static final String UNDEFINED_ATTR = "undefined"; + public static final String UNDEFINED_ATTR = "undefined"; + private static final Log log = PlatformUtil.getLog(RouteStatistics.class); private final List route; private final RenderingRulesStorage currentRenderer; @@ -354,7 +358,7 @@ public class RouteStatistics { public String getPropertyName(Boundaries attribute) { int lowerBoundary = Math.round(attribute.getLowerBoundary()); int upperBoundary = Math.round(attribute.getUpperBoundary()); - if (lowerBoundary > Boundaries.MIN_INCLINE) { + if (lowerBoundary >= Boundaries.MIN_DIVIDED_INCLINE) { lowerBoundary++; } return String.format("%d%% ... %d%%", lowerBoundary, upperBoundary); @@ -365,9 +369,15 @@ public class RouteStatistics { int lowerBoundary = Math.round(attribute.getLowerBoundary()); int upperBoundary = Math.round(attribute.getUpperBoundary()); StringBuilder range = new StringBuilder(); - if (lowerBoundary > Boundaries.MIN_INCLINE) { + if (lowerBoundary >= Boundaries.MIN_DIVIDED_INCLINE) { lowerBoundary++; } + if (lowerBoundary < Boundaries.MIN_DIVIDED_INCLINE) { + lowerBoundary = Boundaries.MIN_INCLINE; + } + if (upperBoundary > Boundaries.MAX_DIVIDED_INCLINE) { + upperBoundary = Boundaries.MAX_INCLINE; + } range.append(lowerBoundary); range.append(upperBoundary < 0 ? "_" : "-"); range.append(upperBoundary); @@ -446,14 +456,17 @@ public class RouteStatistics { public static class Incline { - private float inclineValue; + private final float inclineValue; private final float distance; - private final Boundaries boundaries; + private Boundaries boundaries; public Incline(float inclineValue, float distance) { this.inclineValue = inclineValue; this.distance = distance; - this.boundaries = Boundaries.newBoundariesFor(inclineValue); + } + + public void computeBoundaries(float minIncline, float maxIncline) { + this.boundaries = Boundaries.newBoundariesFor(inclineValue, minIncline, maxIncline); } public float getValue() { @@ -505,16 +518,24 @@ public class RouteStatistics { this.lowerBoundary = lowerBoundary; } - public static Boundaries newBoundariesFor(float incline) { + public static Boundaries newBoundariesFor(float incline, float minIncline, float maxIncline) { + int maxRoundedIncline = Math.round(maxIncline); + int minRoundedIncline = Math.round(minIncline); if (incline > MAX_INCLINE) { - return new Boundaries(MAX_INCLINE, MAX_INCLINE - STEP); + return new Boundaries(MAX_INCLINE, MAX_DIVIDED_INCLINE); } if (incline < MIN_INCLINE) { - return new Boundaries(MIN_INCLINE + STEP, MIN_INCLINE); + return new Boundaries(MIN_DIVIDED_INCLINE, MIN_INCLINE); } for (int i = 1; i < NUM; i++) { if (incline >= BOUNDARIES_ARRAY[i - 1] && incline < BOUNDARIES_ARRAY[i]) { - return new Boundaries(BOUNDARIES_ARRAY[i], BOUNDARIES_ARRAY[i - 1]); + if (i == 1) { + return new Boundaries(BOUNDARIES_ARRAY[i], minRoundedIncline); + } else if (i == NUM - 1) { + return new Boundaries(maxRoundedIncline, BOUNDARIES_ARRAY[i - 1]); + } else { + return new Boundaries(BOUNDARIES_ARRAY[i], BOUNDARIES_ARRAY[i - 1]); + } } } return null; diff --git a/OsmAnd/res/layout/route_info_card.xml b/OsmAnd/res/layout/route_info_card.xml index 94e1735f4d..98d3212657 100644 --- a/OsmAnd/res/layout/route_info_card.xml +++ b/OsmAnd/res/layout/route_info_card.xml @@ -53,7 +53,7 @@ + android:layout_height="@dimen/route_info_chart_height" /> 78dp 12dp 27dp + 78dp 78dp diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index 0e28e19383..286f80081a 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -282,6 +282,7 @@ 54dp 8dp 18dp + 52dp 52dp diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index 4fb0e276d1..1491f6378b 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -1226,7 +1226,7 @@ public class GpxUiHelper { chart.setDragEnabled(useGesturesAndScale); chart.setScaleYEnabled(false); chart.setAutoScaleMinMaxEnabled(true); - chart.setDrawBorders(false); + chart.setDrawBorders(true); chart.getDescription().setEnabled(false); chart.setDragDecelerationEnabled(false); @@ -1252,6 +1252,9 @@ public class GpxUiHelper { yr.setDrawAxisLine(false); yr.setDrawGridLines(false); yr.setAxisMinimum(0f); + chart.setMinOffset(0); + chart.setExtraRightOffset(16); + chart.setExtraLeftOffset(16); yl.setTextColor(ContextCompat.getColor(app, nightMode ? R.color.primary_text_dark : R.color.primary_text_light)); yr.setTextColor(ContextCompat.getColor(app, nightMode ? R.color.primary_text_dark : R.color.primary_text_light)); @@ -1266,7 +1269,8 @@ public class GpxUiHelper { @NonNull HorizontalBarChart mChart, @NonNull RouteStatistics.Statistics routeStatistics, @NonNull GPXTrackAnalysis analysis, - boolean useRightAxis) { + boolean useRightAxis, + boolean nightMode) { XAxis xAxis = mChart.getXAxis(); xAxis.setEnabled(false); @@ -1292,9 +1296,10 @@ public class GpxUiHelper { entries.add(new BarEntry(0, stacks)); BarDataSet barDataSet = new BarDataSet(entries, ""); barDataSet.setColors(colors); + barDataSet.setBarBorderColor(ContextCompat.getColor(app, nightMode ? R.color.divider_dark : R.color.divider_light)); BarData dataSet = new BarData(barDataSet); dataSet.setDrawValues(false); - + dataSet.setBarWidth(1); mChart.getAxisRight().setAxisMaximum(dataSet.getYMax()); mChart.getAxisLeft().setAxisMaximum(dataSet.getYMax()); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowRouteInfoDialogFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowRouteInfoDialogFragment.java index e6f1e1ae33..f3309be033 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowRouteInfoDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ShowRouteInfoDialogFragment.java @@ -1662,12 +1662,17 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment implements P } private List createInclinesAndAdd100MetersWith0Incline(List entries) { + float minIncline = 0; + float maxIncline = 0; int size = entries.size(); List inclines = new ArrayList<>(); for (Entry entry : entries) { - Incline incline = new Incline(entry.getY(), entry.getX() * 1000); - inclines.add(incline); + float inclineValue = entry.getY(); + maxIncline = Math.max(inclineValue, maxIncline); + minIncline = Math.min(inclineValue, minIncline); + Incline incline = new Incline(inclineValue, entry.getX() * 1000); + inclines.add(incline); } for (int i = 0; i < 10; i++) { float distance = i * 5; @@ -1678,6 +1683,9 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment implements P float distance = lastDistance * 1000f + i * 5f; inclines.add(new Incline(0f, distance)); } + for (Incline incline : inclines) { + incline.computeBoundaries(minIncline, maxIncline); + } return inclines; } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java index 2f69b8cfa8..3011d1d73a 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java @@ -20,17 +20,26 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.SettingsNavigationActivity; import net.osmand.plus.helpers.GpxUiHelper; -import net.osmand.router.RouteStatistics; +import net.osmand.router.RouteStatistics.Boundaries; +import net.osmand.router.RouteStatistics.RouteSegmentAttribute; +import net.osmand.router.RouteStatistics.StatisticType; +import net.osmand.router.RouteStatistics.Statistics; import net.osmand.util.Algorithms; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; import java.util.Map; +import static net.osmand.router.RouteStatistics.UNDEFINED_ATTR; + public class RouteInfoCard extends BaseCard { - private RouteStatistics.Statistics routeStatistics; + private Statistics routeStatistics; private GPXUtilities.GPXTrackAnalysis analysis; - public RouteInfoCard(MapActivity mapActivity, RouteStatistics.Statistics routeStatistics, GPXUtilities.GPXTrackAnalysis analysis) { + public RouteInfoCard(MapActivity mapActivity, Statistics routeStatistics, GPXUtilities.GPXTrackAnalysis analysis) { super(mapActivity); this.routeStatistics = routeStatistics; this.analysis = analysis; @@ -46,7 +55,7 @@ public class RouteInfoCard extends BaseCard { updateHeader(); final HorizontalBarChart chart = (HorizontalBarChart) view.findViewById(R.id.chart); GpxUiHelper.setupHorizontalGPXChart(app, chart, 5, 10, 10, true, nightMode); - BarData barData = GpxUiHelper.buildStatisticChart(app, chart, routeStatistics, analysis, true); + BarData barData = GpxUiHelper.buildStatisticChart(app, chart, routeStatistics, analysis, true, nightMode); chart.setData(barData); LinearLayout container = view.findViewById(R.id.route_items); attachLegend(container, routeStatistics); @@ -62,23 +71,25 @@ public class RouteInfoCard extends BaseCard { } private String getInfoType() { - if (routeStatistics.getStatisticType() == RouteStatistics.StatisticType.CLASS) { + if (routeStatistics.getStatisticType() == StatisticType.CLASS) { return app.getString(R.string.road_types); - } else if (routeStatistics.getStatisticType() == RouteStatistics.StatisticType.STEEPNESS) { + } else if (routeStatistics.getStatisticType() == StatisticType.STEEPNESS) { return app.getString(R.string.route_steepness_stat_container); - } else if (routeStatistics.getStatisticType() == RouteStatistics.StatisticType.SMOOTHNESS) { + } else if (routeStatistics.getStatisticType() == StatisticType.SMOOTHNESS) { return app.getString(R.string.route_smoothness_stat_container); - } else if (routeStatistics.getStatisticType() == RouteStatistics.StatisticType.SURFACE) { + } else if (routeStatistics.getStatisticType() == StatisticType.SURFACE) { return app.getString(R.string.route_surface_stat_container); } else { return ""; } } - private void attachLegend(ViewGroup container, RouteStatistics.Statistics routeStatistics) { - Map> partition = routeStatistics.getPartition(); - for (E key : partition.keySet()) { - RouteStatistics.RouteSegmentAttribute segment = partition.get(key); + private void attachLegend(ViewGroup container, Statistics routeStatistics) { + Map> partition = routeStatistics.getPartition(); + List list = new ArrayList(partition.keySet()); + sortRouteSegmentAttributes(list); + for (E key : list) { + RouteSegmentAttribute segment = partition.get(key); int color = segment.getColor(); Drawable circle = app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, color); String propertyName = segment.getPropertyName(); @@ -98,7 +109,30 @@ public class RouteInfoCard extends BaseCard { } } - private Spannable getSpanLegend(String title, RouteStatistics.RouteSegmentAttribute segment) { + private void sortRouteSegmentAttributes(List list) { + Collections.sort(list, new Comparator() { + @Override + public int compare(E o1, E o2) { + if (o1 instanceof String && o2 instanceof String) { + String name1 = (String) o1; + String name2 = (String) o2; + + if (name1.equalsIgnoreCase(UNDEFINED_ATTR)) { + return 1; + } + if (name2.equalsIgnoreCase(UNDEFINED_ATTR)) { + return -1; + } + return name1.compareTo(name2); + } else if (o1 instanceof Boundaries && o2 instanceof Boundaries) { + return ((Boundaries) o1).compareTo((Boundaries) o2); + } + return 0; + } + }); + } + + private Spannable getSpanLegend(String title, RouteSegmentAttribute segment) { String formattedDistance = OsmAndFormatter.getFormattedDistance(segment.getDistance(), getMyApplication()); title = Algorithms.capitalizeFirstLetter(title); SpannableStringBuilder spannable = new SpannableStringBuilder(title);