Implement conditional restrictions

This commit is contained in:
Victor Shcherb 2019-07-21 13:54:46 +02:00
parent 64eb00f1d7
commit f2f84210e7
4 changed files with 122 additions and 47 deletions

View file

@ -41,7 +41,7 @@ public class BinaryMapRouteReaderAdapter {
private static class RouteTypeCondition { private static class RouteTypeCondition {
String condition = ""; String condition = "";
OpeningHoursParser.OpeningHours hours = null; OpeningHoursParser.OpeningHours hours = null;
float floatValue; String value;
} }
public static class RouteTypeRule { public static class RouteTypeRule {
@ -85,7 +85,7 @@ public class BinaryMapRouteReaderAdapter {
public String getTag() { public String getTag() {
return t; return t;
} }
public String getValue(){ public String getValue(){
return v; return v;
} }
@ -101,6 +101,14 @@ public class BinaryMapRouteReaderAdapter {
public boolean conditional() { public boolean conditional() {
return conditions != null; return conditions != null;
} }
public String getNonConditionalTag() {
String tag = getTag();
if(tag != null && tag.endsWith(":conditional")) {
tag = tag.substring(0, tag.length() - ":conditional".length());
}
return tag;
}
public int onewayDirection(){ public int onewayDirection(){
if(type == ONEWAY){ if(type == ONEWAY){
@ -109,17 +117,21 @@ public class BinaryMapRouteReaderAdapter {
return 0; return 0;
} }
public float maxSpeed(){ public String conditionalValue(long time) {
if(type == MAXSPEED){ if (conditional()) {
if(conditions != null) { Calendar i = Calendar.getInstance();
Calendar i = Calendar.getInstance(); i.setTimeInMillis(time);
i.setTimeInMillis(System.currentTimeMillis()); for (RouteTypeCondition c : conditions) {
for(RouteTypeCondition c : conditions) { if (c.hours != null && c.hours.isOpenedForTime(i)) {
if(c.hours != null && c.hours.isOpenedForTime(i)) { return c.value;
return c.floatValue;
}
} }
} }
}
return null;
}
public float maxSpeed(){
if(type == MAXSPEED){
return floatValue; return floatValue;
} }
return -1; return -1;
@ -159,16 +171,14 @@ public class BinaryMapRouteReaderAdapter {
type = ROUNDABOUT; type = ROUNDABOUT;
} else if(t.equalsIgnoreCase("highway") && v != null){ } else if(t.equalsIgnoreCase("highway") && v != null){
type = HIGHWAY_TYPE; type = HIGHWAY_TYPE;
} else if(t.startsWith("access") && v != null){ } else if(t.endsWith(":conditional") && v != null){
type = ACCESS;
} else if(t.equalsIgnoreCase("maxspeed:conditional") && v != null){
conditions = new ArrayList<RouteTypeCondition>(); conditions = new ArrayList<RouteTypeCondition>();
String[] cts = v.split(";"); String[] cts = v.split(";");
for(String c : cts) { for(String c : cts) {
int ch = c.indexOf('@'); int ch = c.indexOf('@');
if (ch > 0) { if (ch > 0) {
RouteTypeCondition cond = new RouteTypeCondition(); RouteTypeCondition cond = new RouteTypeCondition();
cond.floatValue = RouteDataObject.parseSpeed(c.substring(0, ch), 0); cond.value = c.substring(0, ch).trim();
cond.condition = c.substring(ch + 1).trim(); cond.condition = c.substring(ch + 1).trim();
if (cond.condition.startsWith("(")) { if (cond.condition.startsWith("(")) {
cond.condition = cond.condition.substring(1, cond.condition.length()).trim(); cond.condition = cond.condition.substring(1, cond.condition.length()).trim();
@ -180,7 +190,18 @@ public class BinaryMapRouteReaderAdapter {
conditions.add(cond); conditions.add(cond);
} }
} }
type = MAXSPEED; // we don't set type for condtiional so they are not used directly
// if(t.startsWith("maxspeed")) {
// type = MAXSPEED;
// } else if(t.startsWith("oneway")) {
// type = ONEWAY;
// } else if(t.startsWith("lanes")) {
// type = LANES;
// } else if(t.startsWith("access")) {
// type = ACCESS;
// }
} else if(t.startsWith("access") && v != null){
type = ACCESS;
} else if(t.equalsIgnoreCase("maxspeed") && v != null){ } else if(t.equalsIgnoreCase("maxspeed") && v != null){
type = MAXSPEED; type = MAXSPEED;
floatValue = RouteDataObject.parseSpeed(v, 0); floatValue = RouteDataObject.parseSpeed(v, 0);
@ -265,6 +286,21 @@ public class BinaryMapRouteReaderAdapter {
} }
} }
public void completeRouteEncodingRules() {
for(int i = 0; i < routeEncodingRules.size(); i++) {
RouteTypeRule rtr = routeEncodingRules.get(i);
if(rtr != null && rtr.conditional()) {
String tag = rtr.getNonConditionalTag();
for(RouteTypeCondition c : rtr.conditions ) {
if(tag != null && c.value != null) {
findOrCreateRouteType(tag, c.value);
}
}
}
}
}
public List<RouteSubregion> getSubregions(){ public List<RouteSubregion> getSubregions(){
return subregions; return subregions;
} }
@ -336,14 +372,8 @@ public class BinaryMapRouteReaderAdapter {
rdo.types = new int[o.types.length]; rdo.types = new int[o.types.length];
for (int i = 0; i < o.types.length; i++) { for (int i = 0; i < o.types.length; i++) {
RouteTypeRule tp = o.region.routeEncodingRules.get(o.types[i]); RouteTypeRule tp = o.region.routeEncodingRules.get(o.types[i]);
int ruleId = searchRouteEncodingRule(tp.getTag(), tp.getValue()); int ruleId = findOrCreateRouteType(tp.getTag(), tp.getValue());
if(ruleId != -1) { rdo.types[i] = ruleId;
rdo.types[i] = ruleId;
} else {
ruleId = routeEncodingRules.size() ;
initRouteEncodingRule(ruleId, tp.getTag(), tp.getValue());
rdo.types[i] = ruleId;
}
} }
} }
if (o.pointTypes != null) { if (o.pointTypes != null) {
@ -408,7 +438,16 @@ public class BinaryMapRouteReaderAdapter {
} }
public int findOrCreateRouteType(String tag, String value) {
int ruleId = searchRouteEncodingRule(tag, value);
if(ruleId == -1) {
ruleId = routeEncodingRules.size() ;
initRouteEncodingRule(ruleId, tag, value);
}
return ruleId;
}
} }
// Used in C++ // Used in C++
@ -484,6 +523,7 @@ public class BinaryMapRouteReaderAdapter {
int tag = WireFormat.getTagFieldNumber(t); int tag = WireFormat.getTagFieldNumber(t);
switch (tag) { switch (tag) {
case 0: case 0:
region.completeRouteEncodingRules();
return; return;
case OsmandOdb.OsmAndRoutingIndex.NAME_FIELD_NUMBER : case OsmandOdb.OsmAndRoutingIndex.NAME_FIELD_NUMBER :
region.name = codedIS.readString(); region.name = codedIS.readString();

View file

@ -486,27 +486,49 @@ public class RouteDataObject {
public int[] getTypes() { public int[] getTypes() {
return types; return types;
} }
public void processConditionalTags(long conditionalTime) {
int sz = types.length;
for (int i = 0; i < sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]);
if (r != null && r.conditional()) {
String vl = r.conditionalValue(conditionalTime);
if(vl != null) {
String nonCondTag = r.getNonConditionalTag();
int tp = region.findOrCreateRouteType(nonCondTag, vl);
for(int ks = 0; ks < types.length; ks++) {
RouteTypeRule toReplace = region.quickGetEncodingRule(types[ks]);
if(toReplace != null && toReplace.getTag().equals(nonCondTag)) {
types[ks] = tp;
break;
}
}
}
}
}
}
public float getMaximumSpeed(boolean direction){ public float getMaximumSpeed(boolean direction) {
int sz = types.length; int sz = types.length;
float maxSpeed = 0; float maxSpeed = 0;
for (int i = 0; i < sz; i++) { for (int i = 0; i < sz; i++) {
RouteTypeRule r = region.quickGetEncodingRule(types[i]); RouteTypeRule r = region.quickGetEncodingRule(types[i]);
if(r.isForward() != 0) {
if((r.isForward() == 1) != direction) {
continue;
}
}
float mx = r.maxSpeed(); float mx = r.maxSpeed();
if (mx > 0) { if (mx > 0) {
maxSpeed = mx; if (r.isForward() != 0) {
// conditional has priority if ((r.isForward() == 1) != direction) {
if(r.conditional()) { continue;
break; } else {
// priority over default
maxSpeed = mx;
break;
}
} else {
maxSpeed = mx;
} }
} }
} }
return maxSpeed ; return maxSpeed;
} }
public static float parseSpeed(String v, float def) { public static float parseSpeed(String v, float def) {
@ -671,6 +693,12 @@ public class RouteDataObject {
return r.getValue(); return r.getValue();
} }
} }
for(int i = 0; i < nameIds.length; i++) {
RouteTypeRule r = region.quickGetEncodingRule(nameIds[i]);
if (r.getTag().equals(tag)) {
return names.get(nameIds[i]);
}
}
return null; return null;
} }
@ -898,4 +926,6 @@ public class RouteDataObject {
} }
} }

View file

@ -46,6 +46,9 @@ public class RoutingConfiguration {
// 1.5 Recalculate distance help // 1.5 Recalculate distance help
public float recalculateDistance = 20000f; public float recalculateDistance = 20000f;
// 1.6 Timestamp to calculate route using conditional tags and temporal restrictions
public long dateToCalculateRoute;
public static class Builder { public static class Builder {
// Design time storage // Design time storage

View file

@ -1,12 +1,6 @@
package net.osmand.router; package net.osmand.router;
import gnu.trove.iterator.TIntObjectIterator;
import gnu.trove.iterator.TLongIterator;
import gnu.trove.map.TLongObjectMap;
import gnu.trove.map.hash.TLongObjectHashMap;
import gnu.trove.set.hash.TLongHashSet;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -18,6 +12,13 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import gnu.trove.iterator.TIntObjectIterator;
import gnu.trove.iterator.TLongIterator;
import gnu.trove.map.TLongObjectMap;
import gnu.trove.map.hash.TLongObjectHashMap;
import gnu.trove.set.hash.TLongHashSet;
import net.osmand.NativeLibrary; import net.osmand.NativeLibrary;
import net.osmand.NativeLibrary.NativeRouteSearchResult; import net.osmand.NativeLibrary.NativeRouteSearchResult;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
@ -32,8 +33,6 @@ import net.osmand.router.BinaryRoutePlanner.RouteSegment;
import net.osmand.router.BinaryRoutePlanner.RouteSegmentVisitor; import net.osmand.router.BinaryRoutePlanner.RouteSegmentVisitor;
import net.osmand.router.RoutePlannerFrontEnd.RouteCalculationMode; import net.osmand.router.RoutePlannerFrontEnd.RouteCalculationMode;
import org.apache.commons.logging.Log;
public class RoutingContext { public class RoutingContext {
@ -70,6 +69,8 @@ public class RoutingContext {
public boolean leftSideNavigation; public boolean leftSideNavigation;
public List<RouteSegmentResult> previouslyCalculatedRoute; public List<RouteSegmentResult> previouslyCalculatedRoute;
public PrecalculatedRouteDirection precalculatedRouteDirection; public PrecalculatedRouteDirection precalculatedRouteDirection;
public long conditionalTime = 0;
// 2. Routing memory cache (big objects) // 2. Routing memory cache (big objects)
TLongObjectHashMap<List<RoutingSubregionTile>> indexedSubregions = new TLongObjectHashMap<List<RoutingSubregionTile>>(); TLongObjectHashMap<List<RoutingSubregionTile>> indexedSubregions = new TLongObjectHashMap<List<RoutingSubregionTile>>();
@ -110,8 +111,6 @@ public class RoutingContext {
public FinalRouteSegment finalRouteSegment; public FinalRouteSegment finalRouteSegment;
RoutingContext(RoutingContext cp) { RoutingContext(RoutingContext cp) {
this.config = cp.config; this.config = cp.config;
this.map.putAll(cp.map); this.map.putAll(cp.map);
@ -316,12 +315,15 @@ public class RoutingContext {
BinaryMapIndexReader reader = reverseMap.get(ts.subregion.routeReg); BinaryMapIndexReader reader = reverseMap.get(ts.subregion.routeReg);
ts.setLoadedNonNative(); ts.setLoadedNonNative();
List<RouteDataObject> res = reader.loadRouteIndexData(ts.subregion); List<RouteDataObject> res = reader.loadRouteIndexData(ts.subregion);
// System.out.println(ts.subregion.shiftToData + " " + res);
if(toLoad != null) { if(toLoad != null) {
toLoad.addAll(res); toLoad.addAll(res);
} else { } else {
for(RouteDataObject ro : res){ for(RouteDataObject ro : res){
if(ro != null) { if(ro != null) {
if(conditionalTime != 0) {
ro.processConditionalTags(conditionalTime);
}
if(config.router.acceptLine(ro)) { if(config.router.acceptLine(ro)) {
if(excludeNotAllowed != null && !excludeNotAllowed.contains(ro.getId())) { if(excludeNotAllowed != null && !excludeNotAllowed.contains(ro.getId())) {
ts.add(ro); ts.add(ro);