2018-10-26 18:07:14 +02:00
|
|
|
package net.osmand.router;
|
|
|
|
|
2019-03-01 12:35:59 +01:00
|
|
|
import java.util.ArrayList;
|
2019-07-08 01:22:41 +02:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Comparator;
|
|
|
|
import java.util.LinkedHashMap;
|
2019-03-01 12:35:59 +01:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.TreeMap;
|
2018-10-26 18:07:14 +02:00
|
|
|
|
2019-07-08 00:13:37 +02:00
|
|
|
import net.osmand.binary.BinaryMapRouteReaderAdapter;
|
|
|
|
import net.osmand.binary.RouteDataObject;
|
|
|
|
import net.osmand.render.RenderingRuleSearchRequest;
|
|
|
|
import net.osmand.render.RenderingRulesStorage;
|
|
|
|
|
2019-07-07 18:30:01 +02:00
|
|
|
public class RouteStatisticsHelper {
|
2018-10-26 18:07:14 +02:00
|
|
|
|
2019-03-15 18:12:50 +01:00
|
|
|
public static final String UNDEFINED_ATTR = "undefined";
|
2019-07-08 11:39:43 +02:00
|
|
|
public static final String ROUTE_INFO_PREFIX = "routeInfo_";
|
2019-07-07 23:13:36 +02:00
|
|
|
private static final double H_STEP = 5;
|
|
|
|
private static final double H_SLOPE_APPROX = 100;
|
2019-07-08 00:13:37 +02:00
|
|
|
private static final int MIN_INCLINE = -101;
|
2019-07-07 23:13:36 +02:00
|
|
|
private static final int MIN_DIVIDED_INCLINE = -20;
|
|
|
|
private static final int MAX_INCLINE = 100;
|
|
|
|
private static final int MAX_DIVIDED_INCLINE = 20;
|
|
|
|
private static final int STEP = 4;
|
|
|
|
private static final int[] BOUNDARIES_ARRAY;
|
2019-07-08 00:13:37 +02:00
|
|
|
private static final String[] BOUNDARIES_CLASS;
|
2019-07-07 23:13:36 +02:00
|
|
|
|
|
|
|
static {
|
2019-07-08 00:13:37 +02:00
|
|
|
int NUM = ((MAX_DIVIDED_INCLINE - MIN_DIVIDED_INCLINE) / STEP) + 3;
|
2019-07-07 23:13:36 +02:00
|
|
|
BOUNDARIES_ARRAY = new int[NUM];
|
2019-07-08 00:13:37 +02:00
|
|
|
BOUNDARIES_CLASS = new String[NUM];
|
2019-07-07 23:13:36 +02:00
|
|
|
BOUNDARIES_ARRAY[0] = MIN_INCLINE;
|
2019-07-08 00:13:37 +02:00
|
|
|
BOUNDARIES_CLASS[0] = "steepness=" + (MIN_INCLINE + 1) + "_" + MIN_DIVIDED_INCLINE;
|
2019-07-07 23:13:36 +02:00
|
|
|
for (int i = 1; i < NUM - 1; i++) {
|
|
|
|
BOUNDARIES_ARRAY[i] = MIN_DIVIDED_INCLINE + (i - 1) * STEP;
|
2019-07-08 00:37:20 +02:00
|
|
|
BOUNDARIES_CLASS[i] = "steepness=" + (BOUNDARIES_ARRAY[i - 1] + 1) + "_" + BOUNDARIES_ARRAY[i];
|
2019-07-07 23:13:36 +02:00
|
|
|
}
|
|
|
|
BOUNDARIES_ARRAY[NUM - 1] = MAX_INCLINE;
|
2019-07-08 00:13:37 +02:00
|
|
|
BOUNDARIES_CLASS[NUM - 1] = "steepness="+MAX_DIVIDED_INCLINE+"_"+MAX_INCLINE;
|
2019-07-07 23:13:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static class RouteStatistics {
|
|
|
|
public final List<RouteSegmentAttribute> elements;
|
|
|
|
public final Map<String, RouteSegmentAttribute> partition;
|
|
|
|
public final float totalDistance;
|
2019-07-08 00:47:57 +02:00
|
|
|
public final String name;
|
2019-07-07 23:13:36 +02:00
|
|
|
|
2019-07-08 00:47:57 +02:00
|
|
|
private RouteStatistics(String name, List<RouteSegmentAttribute> elements,
|
2019-07-07 23:13:36 +02:00
|
|
|
Map<String, RouteSegmentAttribute> partition,
|
|
|
|
float totalDistance) {
|
2019-07-08 11:39:43 +02:00
|
|
|
this.name = name.startsWith(ROUTE_INFO_PREFIX) ? name.substring(ROUTE_INFO_PREFIX.length()) : name;
|
2019-07-07 23:13:36 +02:00
|
|
|
this.elements = elements;
|
|
|
|
this.partition = partition;
|
|
|
|
this.totalDistance = totalDistance;
|
|
|
|
}
|
2019-07-08 00:47:57 +02:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
StringBuilder s = new StringBuilder("Statistic '").append(name).append("':");
|
|
|
|
for (RouteSegmentAttribute a : elements) {
|
2019-07-08 01:22:41 +02:00
|
|
|
s.append(String.format(" %.0fm %s,", a.distance, a.getUserPropertyName()));
|
2019-07-08 00:47:57 +02:00
|
|
|
}
|
|
|
|
s.append("\n Partition: ").append(partition);
|
|
|
|
return s.toString();
|
|
|
|
}
|
2019-07-07 23:13:36 +02:00
|
|
|
}
|
2019-07-08 00:47:57 +02:00
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
|
|
|
|
private static class RouteSegmentWithIncline {
|
|
|
|
RouteDataObject obj;
|
|
|
|
float dist;
|
|
|
|
float h;
|
|
|
|
float[] interpolatedHeightByStep;
|
|
|
|
float[] slopeByStep;
|
2019-07-08 00:13:37 +02:00
|
|
|
String[] slopeClass;
|
|
|
|
String[] slopeClassUserString;
|
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
}
|
2019-03-07 18:02:41 +01:00
|
|
|
|
2019-07-07 18:30:01 +02:00
|
|
|
public static List<RouteStatistics> calculateRouteStatistic(List<RouteSegmentResult> route, RenderingRulesStorage currentRenderer,
|
|
|
|
RenderingRulesStorage defaultRenderer, RenderingRuleSearchRequest currentSearchRequest,
|
|
|
|
RenderingRuleSearchRequest defaultSearchRequest) {
|
2019-07-07 23:13:36 +02:00
|
|
|
List<RouteSegmentWithIncline> routeSegmentWithInclines = calculateInclineRouteSegments(route);
|
|
|
|
List<String> attributeNames = new ArrayList<>();
|
2019-07-08 00:37:20 +02:00
|
|
|
if (currentRenderer != null) {
|
|
|
|
for (String s : currentRenderer.getRenderingAttributeNames()) {
|
2019-07-08 11:39:43 +02:00
|
|
|
if (s.startsWith(ROUTE_INFO_PREFIX)) {
|
2019-07-08 00:37:20 +02:00
|
|
|
attributeNames.add(s);
|
|
|
|
}
|
2019-07-07 23:13:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(attributeNames.isEmpty()) {
|
|
|
|
for (String s : defaultRenderer.getRenderingAttributeNames()) {
|
2019-07-08 11:39:43 +02:00
|
|
|
if (s.startsWith(ROUTE_INFO_PREFIX)) {
|
2019-07-07 23:13:36 +02:00
|
|
|
attributeNames.add(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-07 18:02:41 +01:00
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
// "steepnessColor", "surfaceColor", "roadClassColor", "smoothnessColor"
|
|
|
|
// steepness=-19_-16
|
|
|
|
List<RouteStatistics> result = new ArrayList<>();
|
|
|
|
for(String attributeName : attributeNames) {
|
2019-07-07 19:43:13 +02:00
|
|
|
RouteStatisticComputer statisticComputer =
|
2019-07-07 23:13:36 +02:00
|
|
|
new RouteStatisticComputer(currentRenderer, defaultRenderer, currentSearchRequest, defaultSearchRequest);
|
|
|
|
result.add(statisticComputer.computeStatistic(routeSegmentWithInclines, attributeName));
|
2019-07-07 18:30:01 +02:00
|
|
|
}
|
2019-03-07 18:02:41 +01:00
|
|
|
|
2019-07-07 18:30:01 +02:00
|
|
|
return result;
|
2019-03-07 18:02:41 +01:00
|
|
|
}
|
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
private static List<RouteSegmentWithIncline> calculateInclineRouteSegments(List<RouteSegmentResult> route) {
|
|
|
|
List<RouteSegmentWithIncline> input = new ArrayList<>();
|
|
|
|
float prevHeight = 0;
|
|
|
|
int totalArrayHeightsLength = 0;
|
|
|
|
for(RouteSegmentResult r : route) {
|
|
|
|
float[] heightValues = r.getHeightValues();
|
|
|
|
RouteSegmentWithIncline incl = new RouteSegmentWithIncline();
|
|
|
|
incl.dist = r.getDistance();
|
|
|
|
incl.obj = r.getObject();
|
|
|
|
input.add(incl);
|
|
|
|
float prevH = prevHeight;
|
|
|
|
int indStep = 0;
|
|
|
|
if(incl.dist > H_STEP) {
|
2019-07-08 00:13:37 +02:00
|
|
|
// for 10.1 meters 3 points (0, 5, 10)
|
|
|
|
incl.interpolatedHeightByStep = new float[(int) ((incl.dist) / H_STEP) + 1];
|
2019-07-07 23:13:36 +02:00
|
|
|
totalArrayHeightsLength += incl.interpolatedHeightByStep.length;
|
|
|
|
}
|
|
|
|
if(heightValues != null && heightValues.length > 0) {
|
|
|
|
int indH = 2;
|
|
|
|
float distCum = 0;
|
|
|
|
prevH = heightValues[1];
|
|
|
|
incl.h = prevH ;
|
2019-07-08 00:37:20 +02:00
|
|
|
if(incl.interpolatedHeightByStep != null && incl.interpolatedHeightByStep.length > indStep) {
|
2019-07-08 00:13:37 +02:00
|
|
|
incl.interpolatedHeightByStep[indStep++] = prevH;
|
|
|
|
}
|
2019-07-08 00:37:20 +02:00
|
|
|
while(incl.interpolatedHeightByStep != null &&
|
|
|
|
indStep < incl.interpolatedHeightByStep.length && indH < heightValues.length) {
|
2019-07-07 23:13:36 +02:00
|
|
|
float dist = heightValues[indH] + distCum;
|
2019-07-08 00:13:37 +02:00
|
|
|
if(dist > indStep * H_STEP) {
|
2019-07-07 23:13:36 +02:00
|
|
|
if(dist == distCum) {
|
|
|
|
incl.interpolatedHeightByStep[indStep] = prevH;
|
|
|
|
} else {
|
|
|
|
incl.interpolatedHeightByStep[indStep] = (float) (prevH +
|
2019-07-08 00:13:37 +02:00
|
|
|
(indStep * H_STEP - distCum) *
|
2019-07-07 23:13:36 +02:00
|
|
|
(heightValues[indH + 1] - prevH) / (dist - distCum));
|
|
|
|
}
|
|
|
|
indStep++;
|
|
|
|
} else {
|
|
|
|
distCum = dist;
|
|
|
|
prevH = heightValues[indH + 1];
|
|
|
|
indH += 2;
|
|
|
|
}
|
|
|
|
}
|
2019-07-07 19:31:38 +02:00
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
} else {
|
|
|
|
incl.h = prevH;
|
|
|
|
}
|
2019-07-08 00:37:20 +02:00
|
|
|
while(incl.interpolatedHeightByStep != null &&
|
|
|
|
indStep < incl.interpolatedHeightByStep.length) {
|
2019-07-07 23:13:36 +02:00
|
|
|
incl.interpolatedHeightByStep[indStep++] = prevH;
|
|
|
|
}
|
|
|
|
prevHeight = prevH;
|
|
|
|
}
|
|
|
|
int slopeSmoothShift = (int) (H_SLOPE_APPROX / (2 * H_STEP));
|
|
|
|
float[] heightArray = new float[totalArrayHeightsLength];
|
|
|
|
int iter = 0;
|
|
|
|
for(int i = 0; i < input.size(); i ++) {
|
|
|
|
RouteSegmentWithIncline rswi = input.get(i);
|
|
|
|
for(int k = 0; rswi.interpolatedHeightByStep != null &&
|
|
|
|
k < rswi.interpolatedHeightByStep.length; k++) {
|
|
|
|
heightArray[iter++] = rswi.interpolatedHeightByStep[k];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
iter = 0;
|
2019-07-08 00:13:37 +02:00
|
|
|
int minSlope = Integer.MAX_VALUE;
|
|
|
|
int maxSlope = Integer.MIN_VALUE;
|
2019-07-07 23:13:36 +02:00
|
|
|
for(int i = 0; i < input.size(); i ++) {
|
|
|
|
RouteSegmentWithIncline rswi = input.get(i);
|
|
|
|
if(rswi.interpolatedHeightByStep != null) {
|
|
|
|
rswi.slopeByStep = new float[rswi.interpolatedHeightByStep.length];
|
|
|
|
for (int k = 0; k < rswi.slopeByStep.length; k++) {
|
|
|
|
if (iter > slopeSmoothShift && iter + slopeSmoothShift < heightArray.length) {
|
2019-07-08 00:13:37 +02:00
|
|
|
double slope = (heightArray[iter + slopeSmoothShift] - heightArray[iter - slopeSmoothShift]) * 100
|
|
|
|
/ H_SLOPE_APPROX;
|
|
|
|
rswi.slopeByStep[k] = (float) slope;
|
|
|
|
minSlope = Math.min((int) slope, minSlope);
|
|
|
|
maxSlope = Math.max((int) slope, maxSlope);
|
|
|
|
|
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
}
|
|
|
|
iter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-07-08 00:13:37 +02:00
|
|
|
String[] classFormattedStrings = new String[BOUNDARIES_ARRAY.length];
|
|
|
|
classFormattedStrings[0] = formatSlopeString(minSlope, MIN_DIVIDED_INCLINE);
|
|
|
|
classFormattedStrings[1] = formatSlopeString(minSlope, MIN_DIVIDED_INCLINE);
|
|
|
|
classFormattedStrings[BOUNDARIES_ARRAY.length - 1] = formatSlopeString(MAX_DIVIDED_INCLINE, maxSlope);
|
|
|
|
for (int k = 2; k < BOUNDARIES_ARRAY.length - 1; k++) {
|
|
|
|
classFormattedStrings[k] = formatSlopeString(BOUNDARIES_ARRAY[k - 1], BOUNDARIES_ARRAY[k]);
|
|
|
|
}
|
|
|
|
for(int i = 0; i < input.size(); i ++) {
|
|
|
|
RouteSegmentWithIncline rswi = input.get(i);
|
|
|
|
if(rswi.slopeByStep != null) {
|
|
|
|
rswi.slopeClass = new String[rswi.slopeByStep.length];
|
|
|
|
rswi.slopeClassUserString = new String[rswi.slopeByStep.length];
|
|
|
|
for (int t = 0; t < rswi.slopeClass.length; t++) {
|
|
|
|
|
2019-07-08 00:37:20 +02:00
|
|
|
for (int k = 0; k < BOUNDARIES_ARRAY.length; k++) {
|
2019-07-08 00:13:37 +02:00
|
|
|
if (rswi.slopeByStep[t] <= BOUNDARIES_ARRAY[k] || k == BOUNDARIES_ARRAY.length - 1) {
|
2019-07-08 00:37:20 +02:00
|
|
|
rswi.slopeClass[t] = BOUNDARIES_CLASS[k];
|
|
|
|
rswi.slopeClassUserString[t] = classFormattedStrings[k];
|
2019-07-08 00:13:37 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// end of break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-07-07 23:13:36 +02:00
|
|
|
return input;
|
2019-07-07 19:31:38 +02:00
|
|
|
}
|
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
|
2019-07-08 00:13:37 +02:00
|
|
|
private static String formatSlopeString(int slope, int next) {
|
|
|
|
return String.format("%d%% .. %d%%", slope, next);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-07 19:43:13 +02:00
|
|
|
private static class RouteStatisticComputer {
|
2019-03-07 18:02:41 +01:00
|
|
|
|
2019-03-14 17:32:54 +01:00
|
|
|
final RenderingRulesStorage currentRenderer;
|
|
|
|
final RenderingRulesStorage defaultRenderer;
|
|
|
|
final RenderingRuleSearchRequest currentRenderingRuleSearchRequest;
|
|
|
|
final RenderingRuleSearchRequest defaultRenderingRuleSearchRequest;
|
2019-03-07 18:02:41 +01:00
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
RouteStatisticComputer(RenderingRulesStorage currentRenderer, RenderingRulesStorage defaultRenderer,
|
2019-07-07 18:30:01 +02:00
|
|
|
RenderingRuleSearchRequest currentRenderingRuleSearchRequest, RenderingRuleSearchRequest defaultRenderingRuleSearchRequest) {
|
2019-03-12 10:29:10 +01:00
|
|
|
this.currentRenderer = currentRenderer;
|
|
|
|
this.defaultRenderer = defaultRenderer;
|
2019-03-14 17:32:54 +01:00
|
|
|
this.currentRenderingRuleSearchRequest = currentRenderingRuleSearchRequest;
|
|
|
|
this.defaultRenderingRuleSearchRequest = defaultRenderingRuleSearchRequest;
|
2019-03-07 18:02:41 +01:00
|
|
|
}
|
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
|
|
|
|
public RouteStatistics computeStatistic(List<RouteSegmentWithIncline> route, String attribute) {
|
|
|
|
List<RouteSegmentAttribute> routeAttributes = processRoute(route, attribute);
|
|
|
|
Map<String, RouteSegmentAttribute> partition = makePartition(routeAttributes);
|
|
|
|
float totalDistance = computeTotalDistance(routeAttributes);
|
2019-07-08 00:47:57 +02:00
|
|
|
return new RouteStatistics(attribute, routeAttributes, partition, totalDistance);
|
2019-07-07 23:13:36 +02:00
|
|
|
}
|
|
|
|
|
2019-07-07 19:43:13 +02:00
|
|
|
Map<String, RouteSegmentAttribute> makePartition(List<RouteSegmentAttribute> routeAttributes) {
|
2019-07-08 08:53:12 +02:00
|
|
|
final Map<String, RouteSegmentAttribute> partition = new TreeMap<>();
|
2019-07-07 19:43:13 +02:00
|
|
|
for (RouteSegmentAttribute attribute : routeAttributes) {
|
2019-07-08 11:47:58 +02:00
|
|
|
RouteSegmentAttribute attr = partition.get(attribute.getUserPropertyName());
|
2019-07-07 19:43:13 +02:00
|
|
|
if (attr == null) {
|
|
|
|
attr = new RouteSegmentAttribute(attribute);
|
2019-07-08 11:47:58 +02:00
|
|
|
partition.put(attribute.getUserPropertyName(), attr);
|
2019-03-07 18:02:41 +01:00
|
|
|
}
|
2019-07-07 19:43:13 +02:00
|
|
|
attr.incrementDistanceBy(attribute.getDistance());
|
2019-03-07 18:02:41 +01:00
|
|
|
}
|
2019-07-08 01:22:41 +02:00
|
|
|
List<String> keys = new ArrayList<String>(partition.keySet());
|
|
|
|
Collections.sort(keys, new Comparator<String>() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int compare(String o1, String o2) {
|
2019-07-08 11:40:48 +02:00
|
|
|
if (o1.equalsIgnoreCase(UNDEFINED_ATTR)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (o2.equalsIgnoreCase(UNDEFINED_ATTR)) {
|
|
|
|
return -1;
|
|
|
|
}
|
2019-07-08 01:22:41 +02:00
|
|
|
return -Float.compare(partition.get(o1).getDistance(), partition.get(o2).getDistance());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Map<String, RouteSegmentAttribute> sorted = new LinkedHashMap<String, RouteStatisticsHelper.RouteSegmentAttribute>();
|
2019-07-08 11:47:58 +02:00
|
|
|
for (String k : keys) {
|
2019-07-08 01:22:41 +02:00
|
|
|
sorted.put(k, partition.get(k));
|
|
|
|
}
|
|
|
|
|
|
|
|
return sorted;
|
2019-03-07 18:02:41 +01:00
|
|
|
}
|
|
|
|
|
2019-07-07 19:43:13 +02:00
|
|
|
private float computeTotalDistance(List<RouteSegmentAttribute> attributes) {
|
2019-03-07 18:02:41 +01:00
|
|
|
float distance = 0f;
|
|
|
|
for (RouteSegmentAttribute attribute : attributes) {
|
|
|
|
distance += attribute.getDistance();
|
|
|
|
}
|
|
|
|
return distance;
|
|
|
|
}
|
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
protected List<RouteSegmentAttribute> processRoute(List<RouteSegmentWithIncline> route, String attribute) {
|
2019-07-07 19:31:38 +02:00
|
|
|
List<RouteSegmentAttribute> routes = new ArrayList<>();
|
2019-07-07 23:13:36 +02:00
|
|
|
RouteSegmentAttribute prev = null;
|
|
|
|
for (RouteSegmentWithIncline segment : route) {
|
2019-07-08 00:13:37 +02:00
|
|
|
if(segment.slopeClass == null || segment.slopeClass.length == 0) {
|
|
|
|
RouteSegmentAttribute current = classifySegment(attribute, null, segment);
|
|
|
|
current.distance = segment.dist;
|
|
|
|
if (prev != null && prev.getPropertyName() != null &&
|
2019-07-07 23:13:36 +02:00
|
|
|
prev.getPropertyName().equals(current.getPropertyName())) {
|
2019-07-08 00:13:37 +02:00
|
|
|
prev.incrementDistanceBy(current.distance);
|
|
|
|
} else {
|
|
|
|
routes.add(current);
|
|
|
|
prev = current;
|
|
|
|
}
|
2019-07-07 23:13:36 +02:00
|
|
|
} else {
|
2019-07-08 00:13:37 +02:00
|
|
|
for(int i = 0; i < segment.slopeClass.length; i++) {
|
|
|
|
float d = (float) (i == 0 ? (segment.dist - H_STEP * (segment.slopeClass.length - 1)) : H_STEP);
|
|
|
|
if(i > 0 && segment.slopeClass[i].equals(segment.slopeClass[i - 1])) {
|
|
|
|
prev.incrementDistanceBy(d);
|
|
|
|
} else {
|
|
|
|
RouteSegmentAttribute current = classifySegment(attribute,
|
|
|
|
segment.slopeClass[i], segment);
|
|
|
|
current.distance = d;
|
|
|
|
if (prev != null && prev.getPropertyName() != null &&
|
|
|
|
prev.getPropertyName().equals(current.getPropertyName())) {
|
|
|
|
prev.incrementDistanceBy(current.distance);
|
|
|
|
} else {
|
2019-07-08 01:22:41 +02:00
|
|
|
if(segment.slopeClass[i].endsWith(current.propertyName)) {
|
|
|
|
current.setUserPropertyName(segment.slopeClassUserString[i]);
|
|
|
|
}
|
2019-07-08 00:13:37 +02:00
|
|
|
routes.add(current);
|
|
|
|
prev = current;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-07 18:02:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return routes;
|
|
|
|
}
|
|
|
|
|
2019-07-07 19:43:13 +02:00
|
|
|
|
2019-07-08 00:13:37 +02:00
|
|
|
public RouteSegmentAttribute classifySegment(String attribute, String slopeClass, RouteSegmentWithIncline segment) {
|
2019-07-07 23:13:36 +02:00
|
|
|
RouteSegmentAttribute res = new RouteSegmentAttribute(UNDEFINED_ATTR, 0);
|
2019-07-08 00:37:20 +02:00
|
|
|
RenderingRuleSearchRequest currentRequest =
|
|
|
|
currentRenderer == null ? null : new RenderingRuleSearchRequest(currentRenderingRuleSearchRequest);
|
|
|
|
if (currentRenderer != null && searchRenderingAttribute(attribute, currentRenderer, currentRequest, segment, slopeClass)) {
|
2019-07-07 23:13:36 +02:00
|
|
|
res = new RouteSegmentAttribute(currentRequest.getStringPropertyValue(currentRenderer.PROPS.R_ATTR_STRING_VALUE),
|
|
|
|
currentRequest.getIntPropertyValue(currentRenderer.PROPS.R_ATTR_COLOR_VALUE));
|
2019-03-12 10:29:10 +01:00
|
|
|
} else {
|
2019-07-07 23:13:36 +02:00
|
|
|
RenderingRuleSearchRequest defaultRequest = new RenderingRuleSearchRequest(defaultRenderingRuleSearchRequest);
|
2019-07-08 00:13:37 +02:00
|
|
|
if (searchRenderingAttribute(attribute, defaultRenderer, defaultRequest, segment, slopeClass)) {
|
2019-07-08 01:22:41 +02:00
|
|
|
res = new RouteSegmentAttribute(
|
|
|
|
defaultRequest.getStringPropertyValue(defaultRenderer.PROPS.R_ATTR_STRING_VALUE),
|
2019-07-07 23:13:36 +02:00
|
|
|
defaultRequest.getIntPropertyValue(defaultRenderer.PROPS.R_ATTR_COLOR_VALUE));
|
2019-03-12 10:29:10 +01:00
|
|
|
}
|
|
|
|
}
|
2019-07-07 19:31:38 +02:00
|
|
|
return res;
|
2019-03-12 10:29:10 +01:00
|
|
|
}
|
2019-03-07 18:02:41 +01:00
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
protected boolean searchRenderingAttribute(String attribute,
|
2019-07-08 00:13:37 +02:00
|
|
|
RenderingRulesStorage rrs, RenderingRuleSearchRequest req, RouteSegmentWithIncline segment,
|
|
|
|
String slopeClass) {
|
2019-07-07 19:31:38 +02:00
|
|
|
//String additional = attrName + "=" + attribute;
|
2019-07-07 23:13:36 +02:00
|
|
|
RouteDataObject obj = segment.obj;
|
2019-07-07 19:31:38 +02:00
|
|
|
int[] tps = obj.getTypes();
|
2019-07-08 01:30:33 +02:00
|
|
|
String additional = slopeClass != null ? (slopeClass + ";") : "";
|
2019-07-07 19:58:44 +02:00
|
|
|
for (int k = 0; k < tps.length; k++) {
|
2019-07-07 19:31:38 +02:00
|
|
|
BinaryMapRouteReaderAdapter.RouteTypeRule tp = obj.region.quickGetEncodingRule(tps[k]);
|
2019-07-07 19:58:44 +02:00
|
|
|
if (tp.getTag().equals("highway") || tp.getTag().equals("route") ||
|
2019-07-07 19:31:38 +02:00
|
|
|
tp.getTag().equals("railway") || tp.getTag().equals("aeroway") || tp.getTag().equals("aerialway")) {
|
|
|
|
req.setStringFilter(rrs.PROPS.R_TAG, tp.getTag());
|
2019-07-08 00:47:57 +02:00
|
|
|
req.setStringFilter(rrs.PROPS.R_VALUE, tp.getValue());
|
2019-07-07 19:31:38 +02:00
|
|
|
} else {
|
2019-07-08 01:30:33 +02:00
|
|
|
additional += tp.getTag() + "=" + tp.getValue() + ";";
|
2019-07-07 19:31:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
req.setStringFilter(rrs.PROPS.R_ADDITIONAL, additional);
|
2019-07-07 23:13:36 +02:00
|
|
|
return req.searchRenderingAttribute(attribute);
|
2019-03-12 10:29:10 +01:00
|
|
|
|
2019-07-07 19:31:38 +02:00
|
|
|
}
|
2019-03-07 18:02:41 +01:00
|
|
|
}
|
2019-07-07 19:31:38 +02:00
|
|
|
public static class RouteSegmentAttribute {
|
2019-03-07 18:02:41 +01:00
|
|
|
|
|
|
|
private final int color;
|
|
|
|
private final String propertyName;
|
|
|
|
private float distance;
|
2019-07-08 01:22:41 +02:00
|
|
|
private String userPropertyName;
|
2019-03-07 18:02:41 +01:00
|
|
|
|
2019-07-07 23:13:36 +02:00
|
|
|
RouteSegmentAttribute(String propertyName, int color) {
|
2019-07-08 00:47:57 +02:00
|
|
|
this.propertyName = propertyName == null ? UNDEFINED_ATTR : propertyName;
|
2019-03-07 18:02:41 +01:00
|
|
|
this.color = color;
|
|
|
|
}
|
|
|
|
|
2019-07-07 19:31:38 +02:00
|
|
|
RouteSegmentAttribute(RouteSegmentAttribute segmentAttribute) {
|
2019-03-07 18:02:41 +01:00
|
|
|
this.propertyName = segmentAttribute.getPropertyName();
|
|
|
|
this.color = segmentAttribute.getColor();
|
2019-07-08 01:22:41 +02:00
|
|
|
this.userPropertyName = segmentAttribute.userPropertyName;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getUserPropertyName() {
|
|
|
|
return userPropertyName == null ? propertyName : userPropertyName;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setUserPropertyName(String userPropertyName) {
|
|
|
|
this.userPropertyName = userPropertyName;
|
2019-03-07 18:02:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public float getDistance() {
|
|
|
|
return distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void incrementDistanceBy(float distance) {
|
|
|
|
this.distance += distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getPropertyName() {
|
|
|
|
return propertyName;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getColor() {
|
|
|
|
return color;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
2019-07-08 01:22:41 +02:00
|
|
|
return String.format("%s - %.0f m %d", getUserPropertyName(), getDistance(), getColor());
|
2019-03-01 12:35:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-07 18:02:41 +01:00
|
|
|
}
|