Implement conditional restrictions
This commit is contained in:
parent
64eb00f1d7
commit
f2f84210e7
4 changed files with 122 additions and 47 deletions
|
@ -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 {
|
||||||
|
@ -102,6 +102,14 @@ public class BinaryMapRouteReaderAdapter {
|
||||||
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){
|
||||||
return intValue;
|
return intValue;
|
||||||
|
@ -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(System.currentTimeMillis());
|
i.setTimeInMillis(time);
|
||||||
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.floatValue;
|
return c.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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,6 +438,15 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
|
@ -487,23 +487,45 @@ public class RouteDataObject {
|
||||||
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]);
|
||||||
|
float mx = r.maxSpeed();
|
||||||
|
if (mx > 0) {
|
||||||
if (r.isForward() != 0) {
|
if (r.isForward() != 0) {
|
||||||
if ((r.isForward() == 1) != direction) {
|
if ((r.isForward() == 1) != direction) {
|
||||||
continue;
|
continue;
|
||||||
}
|
} else {
|
||||||
}
|
// priority over default
|
||||||
float mx = r.maxSpeed();
|
|
||||||
if (mx > 0) {
|
|
||||||
maxSpeed = mx;
|
maxSpeed = mx;
|
||||||
// conditional has priority
|
|
||||||
if(r.conditional()) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
maxSpeed = mx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return maxSpeed;
|
return maxSpeed;
|
||||||
|
@ -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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,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
|
||||||
private String defaultRouter = "";
|
private String defaultRouter = "";
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
@ -71,6 +70,8 @@ public class RoutingContext {
|
||||||
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>>();
|
||||||
TLongObjectHashMap<List<RouteDataObject>> tileRoutes = new TLongObjectHashMap<List<RouteDataObject>>();
|
TLongObjectHashMap<List<RouteDataObject>> tileRoutes = new TLongObjectHashMap<List<RouteDataObject>>();
|
||||||
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue