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 e195c42d42..3cfc80806f 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/GeneralRouter.java @@ -90,7 +90,8 @@ public class GeneralRouter implements VehicleRouter { CAR, PEDESTRIAN, BICYCLE, - BOAT + BOAT, + PUBLIC_TRANSPORT } @@ -224,7 +225,7 @@ public class GeneralRouter implements VehicleRouter { return impassableRoads.toArray(); } - private int registerTagValueAttribute(String tag, String value) { + public int registerTagValueAttribute(String tag, String value) { String key = tag +"$"+value; if(universalRules.containsKey(key)) { return universalRules.get(key); @@ -617,6 +618,14 @@ public class GeneralRouter implements VehicleRouter { return ((Number)o).intValue(); } + public int evaluateInt(BitSet rawTypes, int defValue) { + Object o = evaluate(rawTypes); + if(!(o instanceof Number)){ + return defValue; + } + return ((Number)o).intValue(); + } + public float evaluateFloat(RouteDataObject ro, float defValue) { Object o = evaluate(ro); if(!(o instanceof Number)) { @@ -633,6 +642,14 @@ public class GeneralRouter implements VehicleRouter { return ((Number)o).floatValue(); } + public float evaluateFloat(BitSet rawTypes, float defValue) { + Object o = evaluate(rawTypes); + if(!(o instanceof Number)){ + return defValue; + } + return ((Number)o).floatValue(); + } + private BitSet convert(RouteRegion reg, int[] types) { BitSet b = new BitSet(universalRules.size()); Map map = regionConvert.get(reg); diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoutingConfiguration.java b/OsmAnd-java/src/main/java/net/osmand/router/RoutingConfiguration.java index e3271c2378..d3d73dd828 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutingConfiguration.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutingConfiguration.java @@ -136,7 +136,7 @@ public class RoutingConfiguration { } } - private static int parseSilentInt(String t, int v) { + public static int parseSilentInt(String t, int v) { if (t == null || t.length() == 0) { return v; } @@ -144,7 +144,7 @@ public class RoutingConfiguration { } - private static float parseSilentFloat(String t, float v) { + public static float parseSilentFloat(String t, float v) { if (t == null || t.length() == 0) { return v; } @@ -217,8 +217,8 @@ public class RoutingConfiguration { String valueDescriptions = parser.getAttributeValue("", "valueDescriptions"); String[] strValues = values.split(","); Double[] vls = new Double[strValues.length]; - for(int i =0; i< vls.length; i++) { - vls[i] =Double.parseDouble(strValues[i].trim()); + for (int i = 0; i < vls.length; i++) { + vls[i] = Double.parseDouble(strValues[i].trim()); } currentRouter.registerNumericParameter(id, name, description, vls , valueDescriptions.split(",")); diff --git a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java index 4aad77d9f2..d99eab1e5b 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java @@ -79,6 +79,10 @@ public class TransportRoutePlanner { double minDist = 0; double travelDist = 0; double travelTime = 0; + final float routeTravelSpeed = ctx.cfg.getSpeedByRouteType(segment.road.getType()); + if(routeTravelSpeed == 0) { + continue; + } TransportStop prevStop = segment.getStop(segment.segStart); List sgms = new ArrayList(); for (int ind = 1 + segment.segStart; ind < segment.getLength(); ind++) { @@ -96,7 +100,7 @@ public class TransportRoutePlanner { int interval = sc.avgStopIntervals.get(ind - 1); travelTime += interval * 10; } else { - travelTime += ctx.cfg.stopTime + segmentDist / ctx.cfg.travelSpeed; + travelTime += ctx.cfg.stopTime + segmentDist / routeTravelSpeed; } if(segment.distFromStart + travelTime > finishTime + ctx.cfg.finishTimeSeconds) { break; @@ -118,7 +122,7 @@ public class TransportRoutePlanner { nextSegment.parentTravelTime = travelTime; nextSegment.parentTravelDist = travelDist; double walkTime = nextSegment.walkDist / ctx.cfg.walkSpeed - + (ctx.cfg.getChangeTime()); + + ctx.cfg.getChangeTime() + ctx.cfg.getBoardingTime(); nextSegment.distFromStart = segment.distFromStart + travelTime + walkTime; if(ctx.cfg.useSchedule) { int tm = (sgm.departureTime - ctx.cfg.scheduleTimeOfDay) * 10; @@ -181,7 +185,7 @@ public class TransportRoutePlanner { ctx.calculationProgress.distanceFromEnd = 0; ctx.calculationProgress.reverseSegmentQueueSize = 0; ctx.calculationProgress.directSegmentQueueSize = 0; - float speed = (float) ctx.cfg.travelSpeed + 1; // assume + float speed = (float) ctx.cfg.defaultTravelSpeed + 1; // assume ctx.calculationProgress.totalEstimatedDistance = (float) (MapUtils.getDistance(start, end) / speed); } } @@ -226,7 +230,7 @@ public class TransportRoutePlanner { sg.walkDist = p.parentRoute.walkDist; sg.walkTime = sg.walkDist / ctx.cfg.walkSpeed; sg.depTime = p.departureTime; - sg.travelInaccurateDist = p.parentTravelDist; + sg.travelDistApproximate = p.parentTravelDist; sg.travelTime = p.parentTravelTime; route.segments.add(0, sg); } @@ -294,7 +298,7 @@ public class TransportRoutePlanner { private static final int DISPLAY_SEGMENT_IND = 0; public TransportRoute route; public double walkTime; - public double travelInaccurateDist; + public double travelDistApproximate; public double travelTime; public int start; public int end; @@ -322,6 +326,10 @@ public class TransportRoutePlanner { return -1; } + public double getTravelTime() { + return travelTime; + } + public TransportStop getStart() { return route.getForwardStops().get(start); } @@ -478,18 +486,21 @@ public class TransportRoutePlanner { } public double getTravelTime() { - if(cfg.useSchedule) { - int t = 0; - for(TransportRouteResultSegment s : segments) { + double t = 0; + for (TransportRouteResultSegment s : segments) { + if (cfg.useSchedule) { TransportSchedule sts = s.route.getSchedule(); for (int k = s.start; k < s.end; k++) { t += sts.getAvgStopIntervals()[k] * 10; } + } else { + if (t > 0) { + t += cfg.getBoardingTime(); + } + t += s.getTravelTime(); } - return t; } - return getTravelDist() / cfg.travelSpeed + cfg.stopTime * getStops() + - cfg.getChangeTime() * getChanges(); + return t; } public double getWalkTime() { diff --git a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java index a046021ee2..7c7e447cad 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutingConfiguration.java @@ -1,5 +1,14 @@ package net.osmand.router; +import java.util.BitSet; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import net.osmand.router.GeneralRouter.RouteAttributeContext; +import net.osmand.router.GeneralRouter.RouteDataObjectAttribute; + public class TransportRoutingConfiguration { public static final String KEY = "public_transport"; @@ -10,52 +19,94 @@ public class TransportRoutingConfiguration { public int walkChangeRadius = 300; - public double walkSpeed = 3.6 / 3.6; // m/s - - public double travelSpeed = 36 / 3.6; // m/s - - public int stopTime = 30; - - public int changeTime = 300; - - public int maxNumberOfChanges = 5; + public int maxNumberOfChanges = 4; public int finishTimeSeconds = 1200; public int maxRouteTime = 60 * 60 * 10; // 10 hours - public boolean useSchedule; + public GeneralRouter router; + // cache values from router for fast access + public float walkSpeed = (float) (3.6 / 3.6); // m/s + public float defaultTravelSpeed = (float) (60 / 3.6); // m/s + public int stopTime = 30; + public int changeTime = 180; + public int boardingTime = 180; + public boolean useSchedule; // 10 seconds based public int scheduleTimeOfDay = 12 * 60 * 6; // 12:00 - 60*6*12 - public int scheduleMaxTime = 50 * 6; // TODO not appropriate variable, should be dynamic - - public int scheduleMinChangeTime = 180; // 3 min - // day since 2000 public int scheduleDayNumber; + + private Map rawTypes = new HashMap(); + private Map speed = new TreeMap(); + + + public float getSpeedByRouteType(String routeType) { + Float sl = speed.get(routeType); + if(sl == null) { + RouteAttributeContext spds = router.getObjContext(RouteDataObjectAttribute.ROAD_SPEED); + sl = spds.evaluateFloat(getRawBitset("route", routeType), defaultTravelSpeed); + speed.put(routeType, sl); + } + return sl.floatValue(); + } + + private int getRawType(String tg, String vl) { + String key = tg + "$"+vl; + if(!rawTypes.containsKey(key)) { + int at = router.registerTagValueAttribute(tg, vl); + rawTypes.put(key, at); + } + return rawTypes.get(key); + } + + private BitSet getRawBitset(String tg, String vl) { + BitSet bs = new BitSet(); + bs.set(getRawType(tg, vl)); + return bs; + } public int getChangeTime() { - return useSchedule ? scheduleMinChangeTime : changeTime; + return useSchedule ? 0 : changeTime; + } + + public int getBoardingTime() { + return boardingTime; } public TransportRoutingConfiguration(RoutingConfiguration.Builder builder) { - GeneralRouter router = builder == null ? null : builder.getRouter("public_transport"); - if(router != null) { + this(builder, Collections.emptyMap()); + } + + public TransportRoutingConfiguration(RoutingConfiguration.Builder builder, Map params) { + GeneralRouter prouter = builder == null ? null : builder.getRouter("public_transport"); + if(prouter != null) { + this.router = prouter.build(params); walkRadius = router.getIntAttribute("walkRadius", walkRadius); - walkChangeRadius = router.getIntAttribute("walkChangeRadius", walkRadius); + walkChangeRadius = router.getIntAttribute("walkChangeRadius", walkChangeRadius); ZOOM_TO_LOAD_TILES = router.getIntAttribute("zoomToLoadTiles", ZOOM_TO_LOAD_TILES); maxNumberOfChanges = router.getIntAttribute("maxNumberOfChanges", maxNumberOfChanges); maxRouteTime = router.getIntAttribute("maxRouteTime", maxRouteTime); finishTimeSeconds = router.getIntAttribute("delayForAlternativesRoutes", finishTimeSeconds); + String mn = params.get("max_num_changes"); + maxNumberOfChanges = RoutingConfiguration.parseSilentInt(mn, maxNumberOfChanges); + + walkSpeed = router.getFloatAttribute("minDefaultSpeed", this.walkSpeed * 3.6f) / 3.6f; + defaultTravelSpeed = router.getFloatAttribute("maxDefaultSpeed", this.defaultTravelSpeed * 3.6f) / 3.6f; + + RouteAttributeContext obstacles = router.getObjContext(RouteDataObjectAttribute.ROUTING_OBSTACLES); + stopTime = obstacles.evaluateInt(getRawBitset("time", "stop"), stopTime); + changeTime = obstacles.evaluateInt(getRawBitset("time", "change"), changeTime); + boardingTime = obstacles.evaluateInt(getRawBitset("time", "boarding"), boardingTime); + + RouteAttributeContext spds = router.getObjContext(RouteDataObjectAttribute.ROAD_SPEED); + walkSpeed = spds.evaluateFloat(getRawBitset("route", "walk"), walkSpeed); + - travelSpeed = router.getFloatAttribute("defaultTravelSpeed", (float) travelSpeed); - walkSpeed = router.getFloatAttribute("defaultWalkSpeed", (float) walkSpeed); - stopTime = router.getIntAttribute("defaultStopTime", stopTime); - changeTime = router.getIntAttribute("defaultChangeTime", changeTime); - scheduleMinChangeTime = router.getIntAttribute("defaultScheduleChangeTime", changeTime); } }