diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapRouteReaderAdapter.java b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapRouteReaderAdapter.java index b99f51b751..59afdedb9a 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapRouteReaderAdapter.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapRouteReaderAdapter.java @@ -28,6 +28,7 @@ import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.TreeSet; import gnu.trove.iterator.TLongObjectIterator; import gnu.trove.list.array.TIntArrayList; @@ -296,12 +297,14 @@ public class BinaryMapRouteReaderAdapter { public Map decodingRules = null; List subregions = new ArrayList(); List basesubregions = new ArrayList(); - List trafficSignalsTags = new ArrayList<>(); - int directionForward = -1; - int directionBackward = -1; - int directionTrafficSignalsForward = -1; - int directionTrafficSignalsBackward = -1; + public int directionForward = -1; + public int directionBackward = -1; + public int directionTrafficSignalsForward = -1; + public int directionTrafficSignalsBackward = -1; + public int trafficSignals = -1; + public int stopSign = -1; + public int giveWaySign = -1; int nameTypeRule = -1; int refTypeRule = -1; @@ -359,8 +362,12 @@ public class BinaryMapRouteReaderAdapter { destinationTypeRule = id; } else if (tags.equals("destination:ref") || tags.equals("destination:ref:forward") || tags.equals("destination:ref:backward")) { destinationRefTypeRule = id; - } else if (tags.equals("highway") && (val.equals("traffic_signals") || val.equals("stop") || val.equals("give_way"))){ - trafficSignalsTags.add(id); + } else if (tags.equals("highway") && val.equals("traffic_signals")){ + 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")){ if (val.equals("forward")) { 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() { for(int i = 0; i < routeEncodingRules.size(); i++) { RouteTypeRule rtr = routeEncodingRules.get(i); diff --git a/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java b/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java index d65ec8f8ee..da56471f6b 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java @@ -357,58 +357,71 @@ public class GeneralRouter implements VehicleRouter { public float defineObstacle(RouteDataObject road, int point, boolean dir) { int[] pointTypes = road.getPointTypes(point); if(pointTypes != null) { - Float obst = getCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes); + Float obst = getCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes, dir); if(obst == null) { - obst = getObjContext(RouteDataObjectAttribute.OBSTACLES).evaluateFloat(road.region, pointTypes, 0); - putCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes, obst); + int[] filteredPointTypes = filterDirectionTags(road, pointTypes, dir); + obst = getObjContext(RouteDataObjectAttribute.OBSTACLES).evaluateFloat(road.region, filteredPointTypes, 0); + putCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes, obst, dir); } return obst; } return 0; } - boolean foundDirRule = false; TIntArrayList filteredRules = new TIntArrayList(); @Override public float defineRoutingObstacle(RouteDataObject road, int point, boolean dir) { int[] pointTypes = road.getPointTypes(point); 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) { - Float obst = getCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes); + Float obst = getCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, dir); if(obst == null) { - obst = getObjContext(RouteDataObjectAttribute.ROUTING_OBSTACLES).evaluateFloat(road.region, pointTypes, 0); - putCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, obst); + int[] filteredPointTypes = filterDirectionTags(road, pointTypes, dir ); + obst = getObjContext(RouteDataObjectAttribute.ROUTING_OBSTACLES).evaluateFloat(road.region, filteredPointTypes, 0); + putCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, obst, dir); } return obst; } 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 public double defineHeightObstacle(RouteDataObject road, short startIndex, short endIndex) { if(!heightObstacles) { @@ -492,16 +505,20 @@ public class GeneralRouter implements VehicleRouter { Float sp = getCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road); if(sp == null) { sp = getObjContext(RouteDataObjectAttribute.ROAD_PRIORITIES).evaluateFloat(road, 1f); - putCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road, sp); + putCache(RouteDataObjectAttribute.ROAD_PRIORITIES, road, sp, false); } return sp; } 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> ch = evalCache[attr.ordinal()]; if (USE_CACHE) { Map rM = ch.get(reg); @@ -509,40 +526,48 @@ public class GeneralRouter implements VehicleRouter { rM = new HashMap(); ch.put(reg, rM); } - rM.put(new IntHolder(types), val); + rM.put(new IntHolder(types, extra), val); } TIMER += System.nanoTime(); } class IntHolder { private final int[] array; - IntHolder(int[] ts) { array = ts; } - @Override public int hashCode() { return Arrays.hashCode(array); } + private final boolean extra; + + 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) { if (array == other) { return true; } if (! (other instanceof IntHolder) ) { return false; } + if (((IntHolder) other).extra != this.extra) { + return false; + } //noinspection unchecked return Arrays.equals(array, ((IntHolder) other).array); } } 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> ch = evalCache[attr.ordinal()]; - TIMER -= System.nanoTime(); +// TIMER -= System.nanoTime(); if (USE_CACHE) { Map rM = ch.get(reg); if (rM == null) { return null; } - Float vl = rM.get(new IntHolder(types)); + Float vl = rM.get(new IntHolder(types, extra)); if(vl != null) { - TIMER += System.nanoTime(); +// TIMER += System.nanoTime(); return vl; } } diff --git a/OsmAnd-java/src/test/resources/.gitignore b/OsmAnd-java/src/test/resources/.gitignore index 079e13cfb2..25b6999248 100644 --- a/OsmAnd-java/src/test/resources/.gitignore +++ b/OsmAnd-java/src/test/resources/.gitignore @@ -2,4 +2,5 @@ /osm_live/*.json *.obf *.osm -phrases.xml \ No newline at end of file +phrases.xml +*.obf.gz