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 048eb706fb..64d6f7cdf7 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapRouteReaderAdapter.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapRouteReaderAdapter.java @@ -1,9 +1,25 @@ package net.osmand.binary; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; + import com.google.protobuf.CodedInputStream; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.WireFormat; +import gnu.trove.iterator.TLongObjectIterator; +import gnu.trove.list.array.TIntArrayList; +import gnu.trove.list.array.TLongArrayList; +import gnu.trove.map.hash.TIntObjectHashMap; +import gnu.trove.map.hash.TLongObjectHashMap; import net.osmand.PlatformUtil; import net.osmand.ResultMatcher; import net.osmand.binary.BinaryMapIndexReader.SearchRequest; @@ -18,23 +34,6 @@ import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; import net.osmand.util.OpeningHoursParser; -import org.apache.commons.logging.Log; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import gnu.trove.iterator.TLongObjectIterator; -import gnu.trove.list.array.TIntArrayList; -import gnu.trove.list.array.TLongArrayList; -import gnu.trove.map.hash.TIntObjectHashMap; -import gnu.trove.map.hash.TLongObjectHashMap; - public class BinaryMapRouteReaderAdapter { protected static final Log LOG = PlatformUtil.getLog(BinaryMapRouteReaderAdapter.class); private static final int SHIFT_COORDINATES = 4; @@ -172,7 +171,7 @@ public class BinaryMapRouteReaderAdapter { } return tag; } - + public int onewayDirection(){ if(type == ONEWAY){ return intValue; @@ -297,6 +296,14 @@ public class BinaryMapRouteReaderAdapter { List subregions = new ArrayList(); List basesubregions = new ArrayList(); + 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; int destinationTypeRule = -1; @@ -353,9 +360,28 @@ 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")){ + 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; + } else if (val.equals("backward")) { + directionTrafficSignalsBackward = id; + } + } else if (tags.equals("direction")) { + if (val.equals("forward")) { + directionForward = id; + } else if (val.equals("backward")) { + directionBackward = id; + } } } + 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/binary/RouteDataObject.java b/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java index 807561e66d..c5f713cdf6 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java @@ -1054,6 +1054,4 @@ public class RouteDataObject { } restrictionsVia[k] = viaWay; } - - } diff --git a/OsmAnd-java/src/main/java/net/osmand/router/BinaryRoutePlanner.java b/OsmAnd-java/src/main/java/net/osmand/router/BinaryRoutePlanner.java index 6bffd147a7..154d31928e 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/BinaryRoutePlanner.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/BinaryRoutePlanner.java @@ -442,7 +442,8 @@ public class BinaryRoutePlanner { segmentDist += squareRootDist(x, y, prevx, prevy); // 2.1 calculate possible obstacle plus time - double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentPoint); + + double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentPoint, (dir && !reverseWaySearch)); if (obstacle < 0) { directionAllowed = false; continue; 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 b3f2660646..be42f432d6 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import gnu.trove.list.array.TIntArrayList; import gnu.trove.set.hash.TLongHashSet; public class GeneralRouter implements VehicleRouter { @@ -353,33 +354,74 @@ public class GeneralRouter implements VehicleRouter { } @Override - public float defineObstacle(RouteDataObject road, int point) { + 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; } + TIntArrayList filteredRules = new TIntArrayList(); + @Override - public float defineRoutingObstacle(RouteDataObject road, int point) { + public float defineRoutingObstacle(RouteDataObject road, int point, boolean dir) { int[] pointTypes = road.getPointTypes(point); - if(pointTypes != null){ - Float obst = getCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes); - if(obst == null) { - obst = getObjContext(RouteDataObjectAttribute.ROUTING_OBSTACLES).evaluateFloat(road.region, pointTypes, 0); - putCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, obst); + if (pointTypes != null) { + + } + if(pointTypes != null) { + Float obst = getCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, dir); + if(obst == null) { + 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) { @@ -463,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); @@ -480,40 +526,56 @@ 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); } - @Override public boolean equals(Object other) { - if (array == other) { return true; } - if (! (other instanceof IntHolder) ) { - return false; - } - //noinspection unchecked - return Arrays.equals(array, ((IntHolder) other).array); - } + private final int[] 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/main/java/net/osmand/router/RouteResultPreparation.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java index 205e4d505a..1ee7865634 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java @@ -270,7 +270,7 @@ public class RouteResultPreparation { double d = measuredDist(road.getPoint31XTile(j), road.getPoint31YTile(j), road.getPoint31XTile(next), road.getPoint31YTile(next)); distance += d; - double obstacle = ctx.getRouter().defineObstacle(road, j); + double obstacle = ctx.getRouter().defineObstacle(road, j, plus); if (obstacle < 0) { obstacle = 0; } diff --git a/OsmAnd-java/src/main/java/net/osmand/router/VehicleRouter.java b/OsmAnd-java/src/main/java/net/osmand/router/VehicleRouter.java index 6797de0848..e8757b1486 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/VehicleRouter.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/VehicleRouter.java @@ -30,7 +30,7 @@ public interface VehicleRouter { /** * return delay in seconds (0 no obstacles) */ - public float defineObstacle(RouteDataObject road, int point); + public float defineObstacle(RouteDataObject road, int point, boolean dir); /** * return delay in seconds for height obstacles @@ -40,7 +40,7 @@ public interface VehicleRouter { /** * return delay in seconds (0 no obstacles) */ - public float defineRoutingObstacle(RouteDataObject road, int point); + public float defineRoutingObstacle(RouteDataObject road, int point, boolean dir); /** * return routing speed in m/s for vehicle for specified road diff --git a/OsmAnd-java/src/test/resources/.gitignore b/OsmAnd-java/src/test/resources/.gitignore index f80b76e485..842b6c97f5 100644 --- a/OsmAnd-java/src/test/resources/.gitignore +++ b/OsmAnd-java/src/test/resources/.gitignore @@ -3,4 +3,5 @@ /search/* *.obf *.osm -phrases.xml \ No newline at end of file +phrases.xml +*.obf.gz