From 8a473250b6647bcffc7586cd61666531c7f142b9 Mon Sep 17 00:00:00 2001 From: evgenij27 Date: Fri, 2 Nov 2018 18:33:33 +0200 Subject: [PATCH] move enums to top level, fix errors in incline stats calculation --- .../java/net/osmand/router/RoadClass.java | 27 ++ .../java/net/osmand/router/RoadSurface.java | 40 +++ .../net/osmand/router/RouteSegmentResult.java | 26 +- .../net/osmand/router/RouteStatistic.java | 13 + .../net/osmand/router/RouteStatistics.java | 328 +++++++++--------- 5 files changed, 267 insertions(+), 167 deletions(-) create mode 100644 OsmAnd-java/src/main/java/net/osmand/router/RoadClass.java create mode 100644 OsmAnd-java/src/main/java/net/osmand/router/RoadSurface.java create mode 100644 OsmAnd-java/src/main/java/net/osmand/router/RouteStatistic.java diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoadClass.java b/OsmAnd-java/src/main/java/net/osmand/router/RoadClass.java new file mode 100644 index 0000000000..be73795816 --- /dev/null +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoadClass.java @@ -0,0 +1,27 @@ +package net.osmand.router; + +import java.util.Arrays; +import java.util.Set; +import java.util.TreeSet; + +public enum RoadClass { + MOTORWAY("motorway", "motorway_link"), + STATE_ROAD("trunk", "trunk_link", "primary", "primary_link"), + ROAD("secondary", "secondary_link", "tertiary", "tertiary_link", "unclassified"), + STREET("residential", "living_street"), + SERVICE("service"), + TRACK("track", "road"), + FOOTWAY("footway"), + PATH("path"), + CYCLE_WAY("cycleway"); + + final Set roadClasses = new TreeSet<>(); + + RoadClass(String... classes) { + roadClasses.addAll(Arrays.asList(classes)); + } + + boolean contains(String roadClass) { + return roadClasses.contains(roadClass); + } +} diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoadSurface.java b/OsmAnd-java/src/main/java/net/osmand/router/RoadSurface.java new file mode 100644 index 0000000000..98878ea0fa --- /dev/null +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoadSurface.java @@ -0,0 +1,40 @@ +package net.osmand.router; + +import java.util.Arrays; +import java.util.Set; +import java.util.TreeSet; + +public enum RoadSurface { + PAVED("paved"), + UNPAVED("unpaved"), + ASPHALT("asphalt"), + CONCRETE("concrete"), + COMPACTED("compacted"), + GRAVEL("gravel"), + FINE_GRAVEL("fine_gravel"), + PAVING_STONES("paving_stones"), + SETT("sett"), + COBBLESTONE("cobblestone"), + PEBBLESTONE("pebblestone"), + STONE("stone"), + METAL("metal"), + GROUND("ground", "mud"), + WOOD("wood"), + GRASS_PAVER("grass_paver"), + GRASS("grass"), + SAND("sand"), + SALT("salt"), + SNOW("snow"), + ICE("ice"), + CLAY("clay"); + + final Set surfaces = new TreeSet<>(); + + RoadSurface(String... surfaces) { + this.surfaces.addAll(Arrays.asList(surfaces)); + } + + boolean contains(String surface) { + return surfaces.contains(surface); + } +} diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java index 7403e7ee81..6a014ad5fe 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteSegmentResult.java @@ -2,6 +2,7 @@ package net.osmand.router; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -43,19 +44,28 @@ public class RouteSegmentResult { int st = Math.min(startPointIndex, endPointIndex); int end = Math.max(startPointIndex, endPointIndex); float[] res = new float[(end - st + 1) * 2]; - for (int k = 0; k < res.length / 2; k++) { - int ind = reverse ? (2 * (end - k)) : (2 * (k + st)); - if (k == 0) { - res[2 * k] = 0; - } else { - if(ind < pf.length) { + if (reverse) { + for (int k = 1; k <= res.length / 2; k++) { + int ind = (2 * (end--)); + if (ind < pf.length && k < res.length / 2) { res[2 * k] = pf[ind]; } + if (ind < pf.length) { + res[2 * (k - 1) + 1] = pf[ind + 1]; + } } - if(ind < pf.length) { - res[2 * k + 1] = pf[ind + 1]; + } else { + for (int k = 0; k < res.length / 2; k++) { + int ind = (2 * (st + k)); + if (k > 0 && ind < pf.length) { + res[2 * k] = pf[ind]; + } + if (ind < pf.length) { + res[2 * k + 1] = pf[ind + 1]; + } } } + return res; } diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistic.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistic.java new file mode 100644 index 0000000000..add5e32475 --- /dev/null +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistic.java @@ -0,0 +1,13 @@ +package net.osmand.router; + +import java.util.List; +import java.util.Map; + +public interface RouteStatistic { + + float getTotalDistance(); + + List getElements(); + + Map getPartition(); +} 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 a3f1ef83f4..8b1f6717c5 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java @@ -6,47 +6,34 @@ public class RouteStatistics { private static final String UNDEFINED = "undefined"; - private final RouteStatisticComputer routeSurfaceStatisticComputer; - private final RouteStatisticComputer routeSmoothnessStatisticComputer; - private final RouteStatisticComputer routeClassStatisticComputer; - private final RouteStatisticComputer routeSteepnessStatisticComputer; + private final List route; - - private RouteStatistics(RouteStatisticComputer routeSurfaceStatisticComputer, - RouteStatisticComputer routeSmoothnessStatisticComputer, - RouteStatisticComputer routeClassStatisticComputer, - RouteStatisticComputer routeSteepnessStatisticComputer) { - this.routeSurfaceStatisticComputer = routeSurfaceStatisticComputer; - this.routeSmoothnessStatisticComputer = routeSmoothnessStatisticComputer; - this.routeClassStatisticComputer = routeClassStatisticComputer; - this.routeSteepnessStatisticComputer = routeSteepnessStatisticComputer; + private RouteStatistics(List route) { + this.route = route; } public static RouteStatistics newRouteStatistic(List route) { - RouteStatisticComputer routeSurfaceStatisticComputer = new RouteSegmentSurfaceStatisticComputer(route); - RouteStatisticComputer routeSmoothnessStatisticComputer = new RouteSegmentSmoothnessStatisticComputer(route); - RouteStatisticComputer routeClassStatisticComputer = new RouteSegmentClassStatisticComputer(route); - RouteStatisticComputer routeSteepnessStatisticComputer = new RouteSegmentSteepnessStatisticComputer(route); - return new RouteStatistics(routeSurfaceStatisticComputer, - routeSmoothnessStatisticComputer, - routeClassStatisticComputer, - routeSteepnessStatisticComputer); + return new RouteStatistics(route); } - public List getRouteSurfaceStatistic() { - return routeSurfaceStatisticComputer.computeStatistic(); + public RouteStatistic getRouteSurfaceStatistic() { + RouteStatisticComputer statisticComputer = new RouteSurfaceStatisticComputer(route); + return statisticComputer.computeStatistic(); } - public List getRouteSmoothnessStatistic() { - return routeSmoothnessStatisticComputer.computeStatistic(); + public RouteStatistic getRouteSmoothnessStatistic() { + RouteStatisticComputer statisticComputer = new RouteSmoothnessStatisticComputer(route); + return statisticComputer.computeStatistic(); } - public List getRouteClassStatistic() { - return routeClassStatisticComputer.computeStatistic(); + public RouteStatistic getRouteClassStatistic() { + RouteStatisticComputer statisticComputer = new RouteClassStatisticComputer(route); + return statisticComputer.computeStatistic(); } - public List getRouteSteepnessStatistic() { - return routeSteepnessStatisticComputer.computeStatistic(); + public RouteStatistic getRouteSteepnessStatistic() { + RouteStatisticComputer statisticComputer = new RouteSteepnessStatisticComputer(route); + return statisticComputer.computeStatistic(); } @@ -58,13 +45,35 @@ public class RouteStatistics { this.route = new ArrayList<>(route); } - public List getRoute() { + private Map makePartition(List routeAttributes) { + Map partition = new HashMap<>(); + for (RouteSegmentAttribute attribute : routeAttributes) { + String key = attribute.getAttribute(); + RouteSegmentAttribute pattr = partition.get(key); + if (pattr == null) { + pattr = new RouteSegmentAttribute(attribute.getIndex(), attribute.getAttribute()); + partition.put(key, pattr); + } + pattr.incrementDistanceBy(attribute.getDistance()); + } + return partition; + } + + private float computeTotalDistance(List attributes) { + float distance = 0f; + for (RouteSegmentAttribute attribute : attributes) { + distance += attribute.getDistance(); + } + return distance; + } + + protected List getRoute() { return route; } - protected List computeStatistic() { + protected List processRoute() { int index = 0; - List routeSurfaces = new ArrayList<>(); + List routes = new ArrayList<>(); String prev = null; for (RouteSegmentResult segment : getRoute()) { String current = getAttribute(segment); @@ -74,23 +83,61 @@ public class RouteStatistics { if (prev != null && !prev.equals(current)) { index++; } - if (index >= routeSurfaces.size()) { - routeSurfaces.add(new RouteSegmentAttribute(index, current)); + if (index >= routes.size()) { + routes.add(new RouteSegmentAttribute(index, current)); } - RouteSegmentAttribute surface = routeSurfaces.get(index); + RouteSegmentAttribute surface = routes.get(index); surface.incrementDistanceBy(segment.getDistance()); prev = current; } - return routeSurfaces; + return routes; + } + + public RouteStatistic computeStatistic() { + List routeAttributes = processRoute(); + Map partition = makePartition(routeAttributes); + float totalDistance = computeTotalDistance(routeAttributes); + return new RouteStatisticImpl(routeAttributes, partition, totalDistance); } public abstract String getAttribute(RouteSegmentResult segment); + private static class RouteStatisticImpl implements RouteStatistic { + + private final List elements; + private final Map partition; + private final float totalDistance; + + public RouteStatisticImpl(List elements, + Map partition, + float totalDistance) { + this.elements = elements; + this.partition = partition; + this.totalDistance = totalDistance; + } + + @Override + public float getTotalDistance() { + return totalDistance; + } + + @Override + public List getElements() { + return new ArrayList<>(elements); + } + + @Override + public Map getPartition() { + return new HashMap<>(partition); + } + } } - private static class RouteSegmentSurfaceStatisticComputer extends RouteStatisticComputer { - public RouteSegmentSurfaceStatisticComputer(List route) { + + private static class RouteSurfaceStatisticComputer extends RouteStatisticComputer { + + public RouteSurfaceStatisticComputer(List route) { super(route); } @@ -109,9 +156,9 @@ public class RouteStatistics { } } - private static class RouteSegmentSmoothnessStatisticComputer extends RouteStatisticComputer { + private static class RouteSmoothnessStatisticComputer extends RouteStatisticComputer { - public RouteSegmentSmoothnessStatisticComputer(List route) { + public RouteSmoothnessStatisticComputer(List route) { super(route); } @@ -121,9 +168,10 @@ public class RouteStatistics { } } - private static class RouteSegmentClassStatisticComputer extends RouteStatisticComputer { - public RouteSegmentClassStatisticComputer(List route) { + private static class RouteClassStatisticComputer extends RouteStatisticComputer { + + public RouteClassStatisticComputer(List route) { super(route); } @@ -142,28 +190,31 @@ public class RouteStatistics { } } - private static class RouteSegmentSteepnessStatisticComputer extends RouteStatisticComputer { - public RouteSegmentSteepnessStatisticComputer(List route) { + private static class RouteSteepnessStatisticComputer extends RouteStatisticComputer { + + public RouteSteepnessStatisticComputer(List route) { super(route); } - @Override - public String getAttribute(RouteSegmentResult segment) { - return null; + private float computeIncline(float prevHeight, float currHeight, float distance) { + float incline = (currHeight - prevHeight) / distance; + if (incline > 30f || incline < -30f) { + throw new IllegalArgumentException("Invalid incline " + incline); + } + if (Float.isInfinite(incline) || Float.isNaN(incline)) { + incline = 0f; + } + return incline * 100; } - @Override - public List computeStatistic() { - List routeInclines = new ArrayList<>(); - int inclineIndex = 0; + private List computeSegmentInclines() { + List inclines = new ArrayList<>(); for (RouteSegmentResult segment : getRoute()) { float[] heights = segment.getHeightValues(); if (heights.length == 0) { - RouteSegmentIncline routeIncline = new RouteSegmentIncline(inclineIndex++); - routeIncline.mayJoin(0); - routeIncline.incrementDistanceBy(segment.getDistance()); - routeInclines.add(routeIncline); + Incline incline = new Incline(0, segment.getDistance()); + inclines.add(incline); continue; } for (int index = 1; index < heights.length / 2; index++) { @@ -173,35 +224,42 @@ public class RouteStatistics { float prevHeight = heights[prevHeightIndex]; float currHeight = heights[currHeightIndex]; float distanceBetweenHeights = heights[distanceBetweenHeightsIndex]; - float incline = computeIncline(prevHeight, currHeight, distanceBetweenHeights); - - if (inclineIndex >= routeInclines.size()) { - routeInclines.add(new RouteSegmentIncline(inclineIndex)); - } - - RouteSegmentIncline routeIncline = (RouteSegmentIncline) routeInclines.get(inclineIndex); - - if (routeIncline.mayJoin(incline)) { - routeIncline.addIncline(incline); - routeIncline.incrementDistanceBy(distanceBetweenHeights); - } else { - inclineIndex++; - } + float computedIncline = computeIncline(prevHeight, currHeight, distanceBetweenHeights); + Incline incline = new Incline(computedIncline, distanceBetweenHeights); + inclines.add(incline); } } + return inclines; + } + + @Override + public List processRoute() { + List routeInclines = new ArrayList<>(); + int index = 0; + String prev = null; + for (Incline incline : computeSegmentInclines()) { + String current = incline.getBoundariesAsString(); + if (prev != null && !prev.equals(current)) { + index++; + } + if (index >= routeInclines.size()) { + routeInclines.add(new RouteSegmentAttribute(index, current)); + } + RouteSegmentAttribute routeIncline = routeInclines.get(index); + routeIncline.incrementDistanceBy(incline.getDistance()); + prev = current; + } return routeInclines; } - private float computeIncline(float prevHeight, float currHeight, float distance) { - float incline = (currHeight - prevHeight) / distance; - if (Float.isInfinite(incline) || Float.isNaN(incline)) { - incline = 0f; - } - return incline * 100; + @Override + public String getAttribute(RouteSegmentResult segment) { + return null; } } + public static class RouteSegmentAttribute { private final int index; @@ -241,7 +299,9 @@ public class RouteStatistics { } } - public static class RouteSegmentIncline extends RouteSegmentAttribute { + + + private static class Incline { private static final float MAX_INCLINE = 30; private static final float MIN_INCLINE = -30; @@ -257,15 +317,6 @@ public class RouteStatistics { } } - private final List inclines = new ArrayList<>(); - private float upperBoundary; - private float lowerBoundary; - private float middlePoint; - - public RouteSegmentIncline(int index) { - super(index,"incline"); - } - private void determineBoundaries(float incline) { for (int pos = 1; pos < INTERVALS.length; pos++) { float lower = INTERVALS[pos - 1]; @@ -279,6 +330,22 @@ public class RouteStatistics { } } + private float upperBoundary; + private float lowerBoundary; + private float middlePoint; + + private final float inclineValue; + private final float distance; + + public Incline(float inclineValue, float distance) { + this.inclineValue = inclineValue; + this.distance = distance; + determineBoundaries(inclineValue); + if (upperBoundary == lowerBoundary) { + throw new IllegalArgumentException("Invalid boundaries"); + } + } + public float getUpperBoundary() { return upperBoundary; } @@ -287,88 +354,31 @@ public class RouteStatistics { return lowerBoundary; } - public boolean mayJoin(float incline) { - if (lowerBoundary == upperBoundary) { - determineBoundaries(incline); - } - return incline >= lowerBoundary && incline < upperBoundary; - } - - public void addIncline(float incline) { - inclines.add(incline); - } - public float getMiddlePoint() { - return this.middlePoint; + return middlePoint; + } + + public float getValue() { + return inclineValue; + } + + public float getDistance() { + return distance; + } + + public String getBoundariesAsString() { + return String.format("%.2f|%.2f", getLowerBoundary(), getUpperBoundary()); } @Override public String toString() { - return "RouteSegmentIncline{" + - "index=" + getIndex() + - ", distance=" + getDistance() + - ", inclines=" + inclines + - ", upperBoundary=" + upperBoundary + + return "Incline{" + + "upperBoundary=" + upperBoundary + ", lowerBoundary=" + lowerBoundary + ", middlePoint=" + middlePoint + + ", incline=" + inclineValue + + ", distance=" + distance + '}'; } } - - public enum RoadSurface { - PAVED("paved"), - UNPAVED("unpaved"), - ASPHALT("asphalt"), - CONCRETE("concrete"), - COMPACTED("compacted"), - GRAVEL("gravel"), - FINE_GRAVEL("fine_gravel"), - PAVING_STONES("paving_stones"), - SETT("sett"), - COBBLESTONE("cobblestone"), - PEBBLESTONE("pebblestone"), - STONE("stone"), - METAL("metal"), - GROUND("ground", "mud"), - WOOD("wood"), - GRASS_PAVER("grass_paver"), - GRASS("grass"), - SAND("sand"), - SALT("salt"), - SNOW("snow"), - ICE("ice"), - CLAY("clay"); - - final Set surfaces = new TreeSet<>(); - - RoadSurface(String... surfaces) { - this.surfaces.addAll(Arrays.asList(surfaces)); - } - - boolean contains(String surface) { - return surfaces.contains(surface); - } - } - - public enum RoadClass { - MOTORWAY("motorway", "motorway_link"), - STATE_ROAD("trunk", "trunk_link", "primary", "primary_link"), - ROAD("secondary", "secondary_link", "tertiary", "tertiary_link", "unclassified"), - STREET("residential", "living_street"), - SERVICE("service"), - TRACK("track", "road"), - FOOTWAY("footway"), - PATH("path"), - CYCLE_WAY("cycleway"); - - final Set roadClasses = new TreeSet<>(); - - RoadClass(String... classes) { - roadClasses.addAll(Arrays.asList(classes)); - } - - boolean contains(String roadClass) { - return roadClasses.contains(roadClass); - } - } }