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 a1e2af0eac..a305d70204 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapRouteReaderAdapter.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/BinaryMapRouteReaderAdapter.java @@ -73,7 +73,6 @@ public class BinaryMapRouteReaderAdapter { private float floatValue; private int type; private List conditions = null; - private TIntObjectHashMap directions = null; private int forward; public RouteTypeRule() { @@ -166,10 +165,6 @@ public class BinaryMapRouteReaderAdapter { return conditions != null; } - public boolean directional() { - return directions != null; - } - public String getNonConditionalTag() { String tag = getTag(); if(tag != null && tag.endsWith(":conditional")) { @@ -296,12 +291,9 @@ public class BinaryMapRouteReaderAdapter { if (i > 0) { intValue = Integer.parseInt(v.substring(0, i)); } - } else if (t.endsWith("direction") && v!=null) { + } else if (t.endsWith("direction") && v != null) { type = TRAFFIC_SIGNALS; - directions = new TIntObjectHashMap(); - } - } } @@ -311,6 +303,8 @@ public class BinaryMapRouteReaderAdapter { public Map decodingRules = null; List subregions = new ArrayList(); List basesubregions = new ArrayList(); + TIntObjectHashMap trafficSignalsDir = new TIntObjectHashMap(); + List trafficSignalsTags = new ArrayList<>(); int nameTypeRule = -1; int refTypeRule = -1; @@ -369,9 +363,29 @@ 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.endsWith("direction")) { + int d = 0; + if (val.equals("forward")) { + trafficSignalsDir.put(id, 1); + } else if (val.equals("backward")) { + trafficSignalsDir.put(id, -1); + } + } else if (tags.equals("highway") && (val.equals("traffic_signals") || val.equals("stop") || val.equals("give_way"))){ + trafficSignalsTags.add(id); } } + public boolean isTrafficSignalsRule(int ruleId) { + return trafficSignalsTags.contains(ruleId); + } + + public int getTrafficSignalDirection(int ruleId) { + if (trafficSignalsDir.get(ruleId) != null) { + return trafficSignalsDir.get(ruleId); + } + 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/binary/RouteDataObject.java b/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java index eaf670cca1..c5f713cdf6 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java @@ -541,44 +541,6 @@ public class RouteDataObject { } } - // TODO implement - public void processDirectionalTags() { - if (pointTypes != null) { - for (int i = 0; i < pointTypes.length; i++) { - if (pointTypes[i] != null) { - int[] pTypes = pointTypes[i]; - int pSz = pTypes.length; - if (pSz > 0) { - for (int j = 0; j < pSz; j++) { - RouteTypeRule r = region.quickGetEncodingRule(pTypes[j]); - if (r != null && r.directional()) { -// int vl = r.conditionalValue(conditionalTime); -// if (vl != 0) { -// RouteTypeRule rtr = region.quickGetEncodingRule(vl); -// String nonCondTag = rtr.getTag(); -// int ks; -// for (ks = 0; ks < pointTypes[i].length; ks++) { -// RouteTypeRule toReplace = region.quickGetEncodingRule(pointTypes[i][j]); -// if (toReplace != null && toReplace.getTag().contentEquals(nonCondTag)) { -// break; -// } -// } -// if (ks == pTypes.length) { -// int[] ntypes = new int[pTypes.length + 1]; -// System.arraycopy(pTypes, 0, ntypes, 0, pTypes.length); -// pTypes = ntypes; -// } -// pTypes[ks] = vl; -// } - } - } - } - pointTypes[i] = pTypes; - } - } - } - } - public float getMaximumSpeed(boolean direction) { int sz = types.length; float maxSpeed = 0; 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..bf77ed698d 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,8 +354,8 @@ public class GeneralRouter implements VehicleRouter { } @Override - public float defineObstacle(RouteDataObject road, int point) { - int[] pointTypes = road.getPointTypes(point); + public float defineObstacle(RouteDataObject road, int point, boolean dir) { + int[] pointTypes = filterRulesByDirection(road.getPointTypes(point), dir, road); if(pointTypes != null) { Float obst = getCache(RouteDataObjectAttribute.OBSTACLES, road.region, pointTypes); if(obst == null) { @@ -367,11 +368,11 @@ public class GeneralRouter implements VehicleRouter { } @Override - public float defineRoutingObstacle(RouteDataObject road, int point) { - int[] pointTypes = road.getPointTypes(point); - if(pointTypes != null){ + public float defineRoutingObstacle(RouteDataObject road, int point, boolean dir) { + int[] pointTypes = filterRulesByDirection(road.getPointTypes(point), dir, road); + if(pointTypes != null) { Float obst = getCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes); - if(obst == null) { + if(obst == null) { obst = getObjContext(RouteDataObjectAttribute.ROUTING_OBSTACLES).evaluateFloat(road.region, pointTypes, 0); putCache(RouteDataObjectAttribute.ROUTING_OBSTACLES, road.region, pointTypes, obst); } @@ -380,6 +381,38 @@ public class GeneralRouter implements VehicleRouter { return 0; } + @Override + public int[] filterRulesByDirection(int[] pointRules, boolean direction, RouteDataObject route) { + if (pointRules != null) { + TIntArrayList filteredRules = new TIntArrayList(); + boolean foundDirRule = false; + for (int i = 0; i < pointRules.length; i++) { + foundDirRule = false; + if (route.region.isTrafficSignalsRule(pointRules[i])) { + for (int rid : pointRules) { + if (rid != pointRules[i]) { + //possible error if we have two different directions on one point? + int trafficSignalDir = route.region.getTrafficSignalDirection(rid); + if (trafficSignalDir != 0) { + if ((direction && trafficSignalDir > 0) || (!direction && trafficSignalDir < 0)) { + filteredRules.add(pointRules[i]); + } + foundDirRule = true; + } + } + } + if (!foundDirRule) { + filteredRules.add(pointRules[i]); + } + } else if (route.region.getTrafficSignalDirection(pointRules[i]) == 0){ + filteredRules.add(pointRules[i]); + } + } + return filteredRules.size() > 0 ? filteredRules.toArray() : null; + } + return pointRules; + } + @Override public double defineHeightObstacle(RouteDataObject road, short startIndex, short endIndex) { if(!heightObstacles) { 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 14363c39af..379f7b4172 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java @@ -268,7 +268,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/RoutingContext.java b/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java index 44bb6846c2..ed6f451763 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java @@ -309,7 +309,6 @@ public class RoutingContext { } ts.excludedIds.add(ro.getId()); } - ro.processDirectionalTags(); } } } 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..6047e5f561 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,13 +40,18 @@ 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 */ public float defineRoutingSpeed(RouteDataObject road); + /** + * Define if rule should be applied based on movement direction; + */ + public int[] filterRulesByDirection(int[] pointRules, boolean direction, RouteDataObject road); + /** * return real speed in m/s for vehicle for specified road */