Fix routing

This commit is contained in:
Victor Shcherb 2020-06-24 11:14:45 +02:00
parent 13910d284d
commit 3030c73f8a
3 changed files with 82 additions and 62 deletions

View file

@ -28,6 +28,7 @@ import java.util.Comparator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeSet;
import gnu.trove.iterator.TLongObjectIterator; import gnu.trove.iterator.TLongObjectIterator;
import gnu.trove.list.array.TIntArrayList; import gnu.trove.list.array.TIntArrayList;
@ -296,12 +297,14 @@ public class BinaryMapRouteReaderAdapter {
public Map<String, Integer> decodingRules = null; public Map<String, Integer> decodingRules = null;
List<RouteSubregion> subregions = new ArrayList<RouteSubregion>(); List<RouteSubregion> subregions = new ArrayList<RouteSubregion>();
List<RouteSubregion> basesubregions = new ArrayList<RouteSubregion>(); List<RouteSubregion> basesubregions = new ArrayList<RouteSubregion>();
List<Integer> trafficSignalsTags = new ArrayList<>();
int directionForward = -1; public int directionForward = -1;
int directionBackward = -1; public int directionBackward = -1;
int directionTrafficSignalsForward = -1; public int directionTrafficSignalsForward = -1;
int directionTrafficSignalsBackward = -1; public int directionTrafficSignalsBackward = -1;
public int trafficSignals = -1;
public int stopSign = -1;
public int giveWaySign = -1;
int nameTypeRule = -1; int nameTypeRule = -1;
int refTypeRule = -1; int refTypeRule = -1;
@ -359,8 +362,12 @@ public class BinaryMapRouteReaderAdapter {
destinationTypeRule = id; destinationTypeRule = id;
} else if (tags.equals("destination:ref") || tags.equals("destination:ref:forward") || tags.equals("destination:ref:backward")) { } else if (tags.equals("destination:ref") || tags.equals("destination:ref:forward") || tags.equals("destination:ref:backward")) {
destinationRefTypeRule = id; destinationRefTypeRule = id;
} else if (tags.equals("highway") && (val.equals("traffic_signals") || val.equals("stop") || val.equals("give_way"))){ } else if (tags.equals("highway") && val.equals("traffic_signals")){
trafficSignalsTags.add(id); trafficSignals = id;
} else if (tags.equals("highway") && val.equals("stop")){
stopSign = id;
} else if (tags.equals("highway") && val.equals("give_way")){
giveWaySign = id;
} else if (tags.equals("traffic_signals:direction")){ } else if (tags.equals("traffic_signals:direction")){
if (val.equals("forward")) { if (val.equals("forward")) {
directionTrafficSignalsForward = id; directionTrafficSignalsForward = id;
@ -376,20 +383,7 @@ public class BinaryMapRouteReaderAdapter {
} }
} }
public boolean isTrafficSignalsRule(int ruleId) {
return trafficSignalsTags.contains(ruleId);
}
public int getTrafficSignalDirection(int ruleId) {
if (ruleId == directionForward || ruleId == directionTrafficSignalsForward) {
return 1;
} else if (ruleId == directionBackward || ruleId == directionTrafficSignalsBackward) {
return -1;
} else {
return 0;
}
}
public void completeRouteEncodingRules() { public void completeRouteEncodingRules() {
for(int i = 0; i < routeEncodingRules.size(); i++) { for(int i = 0; i < routeEncodingRules.size(); i++) {
RouteTypeRule rtr = routeEncodingRules.get(i); RouteTypeRule rtr = routeEncodingRules.get(i);

View file

@ -357,58 +357,71 @@ public class GeneralRouter implements VehicleRouter {
public float defineObstacle(RouteDataObject road, int point, boolean dir) { public float defineObstacle(RouteDataObject road, int point, boolean dir) {
int[] pointTypes = road.getPointTypes(point); int[] pointTypes = road.getPointTypes(point);
if(pointTypes != null) { if(pointTypes != null) {
Float obst = getCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes); Float obst = getCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes, dir);
if(obst == null) { if(obst == null) {
obst = getObjContext(RouteDataObjectAttribute.OBSTACLES).evaluateFloat(road.region, pointTypes, 0); int[] filteredPointTypes = filterDirectionTags(road, pointTypes, dir);
putCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes, obst); obst = getObjContext(RouteDataObjectAttribute.OBSTACLES).evaluateFloat(road.region, filteredPointTypes, 0);
putCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes, obst, dir);
} }
return obst; return obst;
} }
return 0; return 0;
} }
boolean foundDirRule = false;
TIntArrayList filteredRules = new TIntArrayList(); TIntArrayList filteredRules = new TIntArrayList();
@Override @Override
public float defineRoutingObstacle(RouteDataObject road, int point, boolean dir) { public float defineRoutingObstacle(RouteDataObject road, int point, boolean dir) {
int[] pointTypes = road.getPointTypes(point); int[] pointTypes = road.getPointTypes(point);
if (pointTypes != null) { if (pointTypes != null) {
filteredRules.clear();
for (int i = 0; i < pointTypes.length; i++) {
foundDirRule = false;
if (road.region.isTrafficSignalsRule(pointTypes[i])) {
for (int rid : pointTypes) {
if (rid != pointTypes[i]) {
int trafficSignalDir = road.region.getTrafficSignalDirection(rid);
if (trafficSignalDir != 0) {
if ((dir && trafficSignalDir > 0) || (!dir && trafficSignalDir < 0)) {
filteredRules.add(pointTypes[i]);
}
foundDirRule = true;
}
}
}
if (!foundDirRule) {
filteredRules.add(pointTypes[i]);
}
} else if (road.region.getTrafficSignalDirection(pointTypes[i]) == 0) {
filteredRules.add(pointTypes[i]);
}
}
pointTypes = filteredRules.size() > 0 ? filteredRules.toArray() : null;
} }
if(pointTypes != null) { if(pointTypes != null) {
Float obst = getCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes); Float obst = getCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, dir);
if(obst == null) { if(obst == null) {
obst = getObjContext(RouteDataObjectAttribute.ROUTING_OBSTACLES).evaluateFloat(road.region, pointTypes, 0); int[] filteredPointTypes = filterDirectionTags(road, pointTypes, dir );
putCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, obst); obst = getObjContext(RouteDataObjectAttribute.ROUTING_OBSTACLES).evaluateFloat(road.region, filteredPointTypes, 0);
putCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, obst, dir);
} }
return obst; return obst;
} }
return 0; return 0;
} }
private int[] filterDirectionTags(RouteDataObject road, int[] pointTypes, boolean dir) {
int wayOppositeDirection = dir ? -1 : 1;
int direction = 0;
int tdirection = 0;
for (int i = 0; i < pointTypes.length; i++) {
if (pointTypes[i] == road.region.directionBackward) {
direction = -1;
} else if(pointTypes[i] == road.region.directionForward) {
direction = 1;
} else if (pointTypes[i] == road.region.directionTrafficSignalsBackward) {
tdirection = -1;
} else if(pointTypes[i] == road.region.directionTrafficSignalsForward) {
tdirection = 1;
}
}
if (direction != 0 || tdirection != 0) {
TIntArrayList filteredRules = new TIntArrayList();
for (int i = 0; i < pointTypes.length; i++) {
boolean skip = false;
if ((pointTypes[i] == road.region.stopSign || pointTypes[i] == road.region.giveWaySign)
&& direction == wayOppositeDirection) {
skip = true;
} else if (pointTypes[i] == road.region.trafficSignals && direction == wayOppositeDirection) {
skip = true;
}
if (!skip) {
filteredRules.add(pointTypes[i]);
}
}
return filteredRules.toArray();
}
return pointTypes;
}
@Override @Override
public double defineHeightObstacle(RouteDataObject road, short startIndex, short endIndex) { public double defineHeightObstacle(RouteDataObject road, short startIndex, short endIndex) {
if(!heightObstacles) { if(!heightObstacles) {
@ -492,16 +505,20 @@ public class GeneralRouter implements VehicleRouter {
Float sp = getCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road); Float sp = getCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road);
if(sp == null) { if(sp == null) {
sp = getObjContext(RouteDataObjectAttribute.ROAD_PRIORITIES).evaluateFloat(road, 1f); sp = getObjContext(RouteDataObjectAttribute.ROAD_PRIORITIES).evaluateFloat(road, 1f);
putCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road, sp); putCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road, sp, false);
} }
return sp; return sp;
} }
private void putCache(RouteDataObjectAttribute attr, RouteDataObject road, Float val) { private void putCache(RouteDataObjectAttribute attr, RouteDataObject road, Float val) {
putCache(attr, road.region, road.types, val); putCache(attr, road.region, road.types, val, false);
} }
private void putCache(RouteDataObjectAttribute attr, RouteRegion reg, int[] types, Float val) { private void putCache(RouteDataObjectAttribute attr, RouteDataObject road, Float val, boolean extra) {
putCache(attr, road.region, road.types, val, extra);
}
private void putCache(RouteDataObjectAttribute attr, RouteRegion reg, int[] types, Float val, boolean extra) {
Map<RouteRegion, Map<IntHolder, Float>> ch = evalCache[attr.ordinal()]; Map<RouteRegion, Map<IntHolder, Float>> ch = evalCache[attr.ordinal()];
if (USE_CACHE) { if (USE_CACHE) {
Map<IntHolder, Float> rM = ch.get(reg); Map<IntHolder, Float> rM = ch.get(reg);
@ -509,40 +526,48 @@ public class GeneralRouter implements VehicleRouter {
rM = new HashMap<IntHolder, Float>(); rM = new HashMap<IntHolder, Float>();
ch.put(reg, rM); ch.put(reg, rM);
} }
rM.put(new IntHolder(types), val); rM.put(new IntHolder(types, extra), val);
} }
TIMER += System.nanoTime(); TIMER += System.nanoTime();
} }
class IntHolder { class IntHolder {
private final int[] array; private final int[] array;
IntHolder(int[] ts) { array = ts; } private final boolean extra;
@Override public int hashCode() { return Arrays.hashCode(array); }
IntHolder(int[] ts, boolean extra) {
array = ts;
this.extra = extra;
}
@Override public int hashCode() { return Arrays.hashCode(array) + (extra ? 1 : 0) ; }
@Override public boolean equals(Object other) { @Override public boolean equals(Object other) {
if (array == other) { return true; } if (array == other) { return true; }
if (! (other instanceof IntHolder) ) { if (! (other instanceof IntHolder) ) {
return false; return false;
} }
if (((IntHolder) other).extra != this.extra) {
return false;
}
//noinspection unchecked //noinspection unchecked
return Arrays.equals(array, ((IntHolder) other).array); return Arrays.equals(array, ((IntHolder) other).array);
} }
} }
private Float getCache(RouteDataObjectAttribute attr, RouteDataObject road) { private Float getCache(RouteDataObjectAttribute attr, RouteDataObject road) {
return getCache(attr, road.region, road.types); return getCache(attr, road.region, road.types, false);
} }
private Float getCache(RouteDataObjectAttribute attr, RouteRegion reg, int[] types) { private Float getCache(RouteDataObjectAttribute attr, RouteRegion reg, int[] types, boolean extra) {
Map<RouteRegion, Map<IntHolder, Float>> ch = evalCache[attr.ordinal()]; Map<RouteRegion, Map<IntHolder, Float>> ch = evalCache[attr.ordinal()];
TIMER -= System.nanoTime(); // TIMER -= System.nanoTime();
if (USE_CACHE) { if (USE_CACHE) {
Map<IntHolder, Float> rM = ch.get(reg); Map<IntHolder, Float> rM = ch.get(reg);
if (rM == null) { if (rM == null) {
return null; return null;
} }
Float vl = rM.get(new IntHolder(types)); Float vl = rM.get(new IntHolder(types, extra));
if(vl != null) { if(vl != null) {
TIMER += System.nanoTime(); // TIMER += System.nanoTime();
return vl; return vl;
} }
} }

View file

@ -2,4 +2,5 @@
/osm_live/*.json /osm_live/*.json
*.obf *.obf
*.osm *.osm
phrases.xml phrases.xml
*.obf.gz