package net.osmand.router; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; import net.osmand.binary.RouteDataObject; import net.osmand.router.BinaryRoutePlanner.RouteSegment; import net.osmand.util.MapUtils; public class GeneralRouter extends VehicleRouter { public static final String USE_SHORTEST_WAY = "short_way"; public static final String AVOID_FERRIES = "avoid_ferries"; public static final String AVOID_TOLL = "avoid_toll"; public static final String AVOID_MOTORWAY = "avoid_motorway"; public static final String AVOID_UNPAVED = "avoid_unpaved"; public static final String PREFER_MOTORWAYS = "prefer_motorway"; public Map highwaySpeed ; public Map highwayPriorities ; public Map avoid ; public Map obstacles; public Map routingObstacles; public Map attributes; private GeneralRouterProfile profile; // cached values private boolean restrictionsAware = true; private float leftTurn; private float roundaboutTurn; private float rightTurn; private boolean onewayAware = true; private boolean followSpeedLimitations = true; private float minDefaultSpeed = 10; private float maxDefaultSpeed = 10; public enum GeneralRouterProfile { CAR, PEDESTRIAN, BICYCLE } public GeneralRouter(GeneralRouterProfile profile, Map attributes) { this.attributes = new LinkedHashMap(attributes); this.profile = profile; highwaySpeed = new LinkedHashMap(); highwayPriorities = new LinkedHashMap(); avoid = new LinkedHashMap(); obstacles = new LinkedHashMap(); routingObstacles = new LinkedHashMap(); Iterator> e = attributes.entrySet().iterator(); while(e.hasNext()){ Entry next = e.next(); addAttribute(next.getKey(), next.getValue()); } } public GeneralRouter(GeneralRouter pr, Map attributes) { this.highwaySpeed = new LinkedHashMap(pr.highwaySpeed); this.highwayPriorities = new LinkedHashMap(pr.highwayPriorities); this.avoid = new LinkedHashMap(pr.avoid); this.obstacles = new LinkedHashMap(pr.obstacles); this.routingObstacles = new LinkedHashMap(pr.routingObstacles); this.attributes = new LinkedHashMap(); this.profile = pr.profile; Iterator> e = attributes.entrySet().iterator(); while(e.hasNext()){ Entry next = e.next(); addAttribute(next.getKey(), next.getValue()); } } public void addAttribute(String k, String v) { attributes.put(k, v); if(k.equals("restrictionsAware")) { restrictionsAware = parseSilentBoolean(v, restrictionsAware); } else if(k.equals("onewayAware")) { onewayAware = parseSilentBoolean(v, onewayAware); } else if(k.equals("followSpeedLimitations")) { followSpeedLimitations = parseSilentBoolean(v, followSpeedLimitations); } else if(k.equals("leftTurn")) { leftTurn = parseSilentFloat(v, leftTurn); } else if(k.equals("rightTurn")) { rightTurn = parseSilentFloat(v, rightTurn); } else if(k.equals("roundaboutTurn")) { roundaboutTurn = parseSilentFloat(v, roundaboutTurn); } else if(k.equals("minDefaultSpeed")) { minDefaultSpeed = parseSilentFloat(v, minDefaultSpeed * 3.6f) / 3.6f; } else if(k.equals("maxDefaultSpeed")) { maxDefaultSpeed = parseSilentFloat(v, maxDefaultSpeed * 3.6f) / 3.6f; } } @Override public boolean acceptLine(RouteDataObject way) { int[] types = way.getTypes(); RouteRegion reg = way.region; return acceptLine(types, reg); } public boolean acceptLine(int[] types, RouteRegion reg) { if(!highwaySpeed.containsKey(RouteDataObject.getHighway(types, reg))) { boolean accepted = false; for (int i = 0; i < types.length; i++) { RouteTypeRule r = reg.quickGetEncodingRule(types[i]); Float sp = highwaySpeed.get(r.getTag()+"$"+r.getValue()); if(sp != null){ if(sp > 0) { accepted = true; } break; } } if(!accepted) { return false; } } for(int i=0; i 0) { return m; } } Float value = null; for (int i = 0; i < road.types.length; i++) { RouteTypeRule r = road.region.quickGetEncodingRule(road.types[i]); if(highwaySpeed.containsKey(r.getTag()+"$"+r.getValue())){ value = highwaySpeed.get(r.getTag()+"$"+r.getValue()); break; } } if (value == null) { return getMinDefaultSpeed(); } return value / 3.6f; } @Override public float defineSpeedPriority(RouteDataObject road) { float priority = 1; for (int i = 0; i < road.types.length; i++) { RouteTypeRule r = road.region.quickGetEncodingRule(road.types[i]); if(highwayPriorities.containsKey(r.getTag()+"$"+r.getValue())){ priority *= highwayPriorities.get(r.getTag()+"$"+r.getValue()); } } return priority; } @Override public float getMinDefaultSpeed() { return minDefaultSpeed; } @Override public float getMaxDefaultSpeed() { return maxDefaultSpeed ; } public double getLeftTurn() { return leftTurn; } public double getRightTurn() { return rightTurn; } public double getRoundaboutTurn() { return roundaboutTurn; } @Override public double calculateTurnTime(RouteSegment segment, int segmentEnd, RouteSegment prev, int prevSegmentEnd) { int[] pt = prev.getRoad().getPointTypes(prevSegmentEnd); if(pt != null) { RouteRegion reg = prev.getRoad().region; for(int i=0; i 0 && !prev.getRoad().roundabout() && segment.getRoad().roundabout()) { return rt; } if (getLeftTurn() > 0 || getRightTurn() > 0) { double a1 = segment.getRoad().directionRoute(segment.getSegmentStart(), segment.getSegmentStart() < segmentEnd); double a2 = prev.getRoad().directionRoute(prevSegmentEnd, prevSegmentEnd < prev.getSegmentStart()); double diff = Math.abs(MapUtils.alignAngleDifference(a1 - a2 - Math.PI)); // more like UT if (diff > 2 * Math.PI / 3) { return getLeftTurn(); } else if (diff > Math.PI / 2) { return getRightTurn(); } return 0; } return 0; } private void specialize(String specializationTag, Map m){ ArrayList ks = new ArrayList(m.keySet()); for(String s : ks){ if(s.startsWith(specializationTag +":")) { String tagName = s.substring((specializationTag +":").length()); m.put(tagName, m.get(s)); } } } @Override public GeneralRouter specifyParameter(String specializationTag) { Map attrs = new LinkedHashMap(attributes); for(String s : attributes.keySet()){ if(s.startsWith(specializationTag +":")) { String tagName = s.substring((specializationTag +":").length()); attrs.put(tagName, attributes.get(s)); } } GeneralRouter gr = new GeneralRouter(this, attrs); gr.specialize(specializationTag, gr.highwayPriorities); gr.specialize(specializationTag, gr.highwaySpeed); gr.specialize(specializationTag, gr.avoid); gr.specialize(specializationTag, gr.obstacles); gr.specialize(specializationTag, gr.routingObstacles); gr.specialize(specializationTag, gr.attributes); return gr; } @Override public boolean containsAttribute(String attribute) { return attributes.containsKey(attribute); } @Override public String getAttribute(String attribute) { return attributes.get(attribute); } }