From 7a715eb9319073889706a4c83741b2c08b47ca69 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sat, 18 Aug 2012 02:34:02 +0200 Subject: [PATCH] Introduce specialization technique for routing. Support avoid features and short way feature --- .../net/osmand/router/RouterTestsSuite.java | 2 +- .../src/net/osmand/router/GeneralRouter.java | 19 +++++ .../osmand/router/RoutingConfiguration.java | 70 ++++++++++++++----- .../src/net/osmand/router/routing.xml | 31 +++++--- .../osmand/swing/DataExtractionSettings.java | 2 +- .../src/net/osmand/swing/MapRouterLayer.java | 3 +- .../swing/OsmExtractionPreferencesDialog.java | 2 +- .../osmand/plus/routing/RouteProvider.java | 21 +++++- .../osmand/plus/routing/RoutingHelper.java | 4 +- 9 files changed, 119 insertions(+), 35 deletions(-) diff --git a/DataExtractionOSM/src-tests/net/osmand/router/RouterTestsSuite.java b/DataExtractionOSM/src-tests/net/osmand/router/RouterTestsSuite.java index 7ce543387e..f9d6659ef1 100644 --- a/DataExtractionOSM/src-tests/net/osmand/router/RouterTestsSuite.java +++ b/DataExtractionOSM/src-tests/net/osmand/router/RouterTestsSuite.java @@ -159,7 +159,7 @@ public class RouterTestsSuite { System.err.println("\n\n!! Skipped test case '" + testDescription + "' because 'best_percent' attribute is not specified \n\n" ); return; } - RoutingContext ctx = new RoutingContext(config.build(vehicle, true)); + RoutingContext ctx = new RoutingContext(config.build(vehicle)); String skip = testCase.getAttribute("skip_comment"); if (skip != null && skip.length() > 0) { System.err.println("\n\n!! Skipped test case '" + testDescription + "' because '" + skip + "'\n\n" ); diff --git a/DataExtractionOSM/src/net/osmand/router/GeneralRouter.java b/DataExtractionOSM/src/net/osmand/router/GeneralRouter.java index 5dc1c9e7f5..94c19126b8 100644 --- a/DataExtractionOSM/src/net/osmand/router/GeneralRouter.java +++ b/DataExtractionOSM/src/net/osmand/router/GeneralRouter.java @@ -1,5 +1,6 @@ package net.osmand.router; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; @@ -11,6 +12,9 @@ import net.osmand.router.BinaryRoutePlanner.RouteSegment; 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_UNPAVED = "avoid_unpaved"; Map highwaySpeed ; Map highwayPriorities ; @@ -266,12 +270,27 @@ public class GeneralRouter extends VehicleRouter { } return 0; } + + private void specialize(String specializationTag, Map m){ + ArrayList ks = new ArrayList(m.keySet()); + for(String s : ks){ + if(s.startsWith(specializationTag +":")) { + m.put(s.substring((specializationTag +":").length()), m.get(s)); + } + } + } @Override public GeneralRouter specialization(String specializationTag) { GeneralRouter gr = new GeneralRouter(this); + gr.specialize(specializationTag, gr.highwayFuturePriorities); + gr.specialize(specializationTag, gr.highwayPriorities); + gr.specialize(specializationTag, gr.highwaySpeed); + gr.specialize(specializationTag, gr.avoid); + gr.specialize(specializationTag, gr.obstacles); return gr; } } + diff --git a/DataExtractionOSM/src/net/osmand/router/RoutingConfiguration.java b/DataExtractionOSM/src/net/osmand/router/RoutingConfiguration.java index 333b6fb30f..0ce953e0b2 100644 --- a/DataExtractionOSM/src/net/osmand/router/RoutingConfiguration.java +++ b/DataExtractionOSM/src/net/osmand/router/RoutingConfiguration.java @@ -53,10 +53,10 @@ public class RoutingConfiguration { private Map routers = new LinkedHashMap(); private Map attributes = new LinkedHashMap(); - public RoutingConfiguration build(String router, boolean useShortestWay) { - return build(router, useShortestWay, null); + public RoutingConfiguration build(String router, String... specialization) { + return build(router, null, specialization); } - public RoutingConfiguration build(String router, boolean useShortestWay, Double direction) { + public RoutingConfiguration build(String router, Double direction, String... specialization) { if (!routers.containsKey(router)) { router = defaultRouter; } @@ -79,8 +79,10 @@ public class RoutingConfiguration { return i; } i.router = routers.get(router); - if(useShortestWay) { - i.router = i.router.specialization(GeneralRouter.USE_SHORTEST_WAY); + if(specialization != null) { + for(String s : specialization) { + i.router = i.router.specialization(s); + } } i.routerName = router; return i; @@ -138,17 +140,20 @@ public class RoutingConfiguration { DefaultHandler handler = new DefaultHandler() { String currentSelectedRouter = null; GeneralRouter currentRouter = null; + String previousKey = null; + String previousTag = null; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { String name = parser.isNamespaceAware() ? localName : qName; if("osmand_routing_config".equals(name)) { config.defaultRouter = attributes.getValue("defaultProfile"); } else if("attribute".equals(name)) { - String key = attributes.getValue("name"); - if(currentSelectedRouter != null) { - key = currentSelectedRouter +"$"+key; + previousKey = attributes.getValue("name"); + previousTag = name; + if (currentSelectedRouter != null) { + previousKey = currentSelectedRouter + "$" + previousKey; } - config.attributes.put(key, attributes.getValue("value")); + config.attributes.put(previousKey, attributes.getValue("value")); } else if("routingProfile".equals(name)) { currentSelectedRouter = attributes.getValue("name"); Map attrs = new LinkedHashMap(); @@ -157,26 +162,55 @@ public class RoutingConfiguration { } currentRouter = new GeneralRouter(GeneralRouterProfile.valueOf(attributes.getValue("baseProfile").toUpperCase()), attrs); config.routers.put(currentSelectedRouter, currentRouter); + } else if ("specialization".equals(name)) { + String in = attributes.getValue("input"); + if (previousKey != null) { + String k = in + ":" + previousKey; + if (attributes.getValue("penalty") != null) { + currentRouter.obstacles.put(k, parseSilentDouble(attributes.getValue("penalty"), 0)); + } + if (attributes.getValue("priority") != null) { + currentRouter.highwayPriorities.put(k, parseSilentDouble(attributes.getValue("priority"), 0)); + } + if (attributes.getValue("dynamicPriority") != null) { + currentRouter.highwayFuturePriorities.put(k, parseSilentDouble(attributes.getValue("dynamicPriority"), 0)); + } + if (attributes.getValue("speed") != null) { + currentRouter.highwaySpeed.put(k, parseSilentDouble(attributes.getValue("speed"), 0)); + } + if ("avoid".equals(previousTag)) { + double priority = parseSilentDouble(attributes.getValue("decreasedPriority"), 0); + if (priority == 0) { + currentRouter.avoid.put(k, priority); + } else { + currentRouter.highwayPriorities.put(k, priority); + } + } + } + } else if("road".equals(name)) { - String key = attributes.getValue("tag") +"$" + attributes.getValue("value"); - currentRouter.highwayPriorities.put(key, parseSilentDouble(attributes.getValue("priority"), + previousTag = name; + previousKey = attributes.getValue("tag") +"$" + attributes.getValue("value"); + currentRouter.highwayPriorities.put(previousKey, parseSilentDouble(attributes.getValue("priority"), 1)); - currentRouter.highwayFuturePriorities.put(key, parseSilentDouble(attributes.getValue("dynamicPriority"), + currentRouter.highwayFuturePriorities.put(previousKey, parseSilentDouble(attributes.getValue("dynamicPriority"), 1)); - currentRouter.highwaySpeed.put(key, parseSilentDouble(attributes.getValue("speed"), + currentRouter.highwaySpeed.put(previousKey, parseSilentDouble(attributes.getValue("speed"), 10)); } else if("obstacle".equals(name)) { - String key = attributes.getValue("tag") + "$" + attributes.getValue("value"); - currentRouter.obstacles.put(key, parseSilentDouble(attributes.getValue("penalty"), + previousTag = name; + previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value"); + currentRouter.obstacles.put(previousKey, parseSilentDouble(attributes.getValue("penalty"), 0)); } else if("avoid".equals(name)) { - String key = attributes.getValue("tag") + "$" + attributes.getValue("value"); + previousTag = name; + previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value"); double priority = parseSilentDouble(attributes.getValue("decreasedPriority"), 0); if(priority == 0) { - currentRouter.avoid.put(key, priority); + currentRouter.avoid.put(previousKey, priority); } else { - currentRouter.highwayPriorities.put(key, priority); + currentRouter.highwayPriorities.put(previousKey, priority); } } } diff --git a/DataExtractionOSM/src/net/osmand/router/routing.xml b/DataExtractionOSM/src/net/osmand/router/routing.xml index af1332bbd8..093ff935d2 100644 --- a/DataExtractionOSM/src/net/osmand/router/routing.xml +++ b/DataExtractionOSM/src/net/osmand/router/routing.xml @@ -59,22 +59,35 @@ - + + + - + + + - + + + - + + + - + + + + - + + + - + @@ -89,7 +102,9 @@ - + + + diff --git a/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java b/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java index 552a08959f..508c05ffb2 100644 --- a/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java +++ b/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java @@ -160,7 +160,7 @@ public class DataExtractionSettings { public String getRouteMode(){ - return preferences.get("routeMode", "car"); + return preferences.get("routeMode", "car,short_way"); } public void setRouteMode(String mode){ diff --git a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java index fa38442785..5673a0dbac 100644 --- a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java +++ b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java @@ -597,8 +597,9 @@ public class MapRouterLayer implements MapPanelLayer { rs[it++] = new BinaryMapIndexReader(raf, false); } String m = DataExtractionSettings.getSettings().getRouteMode(); + String[] props = m.split("\\,"); BinaryRoutePlanner router = new BinaryRoutePlanner(NativeSwingRendering.getDefaultFromSettings(), rs); - RoutingConfiguration config = builder.build(m, true); + RoutingConfiguration config = builder.build(props[0], props); RoutingContext ctx = new RoutingContext(config); ctx.previouslyCalculatedRoute = previousRoute; log.info("Use " + config.routerName + "mode for routing"); diff --git a/DataExtractionOSM/src/net/osmand/swing/OsmExtractionPreferencesDialog.java b/DataExtractionOSM/src/net/osmand/swing/OsmExtractionPreferencesDialog.java index b6dc5a4628..995e9dcfbd 100644 --- a/DataExtractionOSM/src/net/osmand/swing/OsmExtractionPreferencesDialog.java +++ b/DataExtractionOSM/src/net/osmand/swing/OsmExtractionPreferencesDialog.java @@ -140,7 +140,7 @@ public class OsmExtractionPreferencesDialog extends JDialog { constr.gridy = gridY++; l.setConstraints(nativeFilesDirectory, constr); - label = new JLabel("Routing mode (car/bicycle/pedestrian) : "); + label = new JLabel("Routing (car|bicycle|pedestrian,[short_way],[avoid_ferries]...) : "); panel.add(label); constr = new GridBagConstraints(); constr.ipadx = 5; diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index f78995659e..507c88bce3 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -37,6 +37,7 @@ import net.osmand.plus.activities.ApplicationMode; import net.osmand.plus.render.NativeOsmandLibrary; import net.osmand.router.BinaryRoutePlanner; import net.osmand.router.BinaryRoutePlanner.RouteSegment; +import net.osmand.router.GeneralRouter; import net.osmand.router.GeneralRouter.GeneralRouterProfile; import net.osmand.router.Interruptable; import net.osmand.router.RouteSegmentResult; @@ -167,7 +168,7 @@ public class RouteProvider { if(previousToRecalculate != null) { originalRoute = previousToRecalculate.getOriginalRoute(); } - res = findVectorMapsRoute(start, end, mode, fast, (OsmandApplication)ctx.getApplicationContext(), originalRoute, leftSide, interruptable); + res = findVectorMapsRoute(start, end, mode, (OsmandApplication)ctx.getApplicationContext(), originalRoute, leftSide, interruptable); } else { res = findCloudMadeRoute(start, end, mode, ctx, fast, leftSide); } @@ -307,7 +308,7 @@ public class RouteProvider { return new RouteCalculationResult(res, null, start, end, null, ctx, leftSide, true); } - protected RouteCalculationResult findVectorMapsRoute(Location start, LatLon end, ApplicationMode mode, boolean fast, OsmandApplication app, + protected RouteCalculationResult findVectorMapsRoute(Location start, LatLon end, ApplicationMode mode, OsmandApplication app, List previousRoute, boolean leftSide, Interruptable interruptable) throws IOException { BinaryMapIndexReader[] files = app.getResourceManager().getRoutingMapFiles(); @@ -332,7 +333,21 @@ public class RouteProvider { } else { p = GeneralRouterProfile.CAR; } - RoutingContext ctx = new RoutingContext(config.build(p.name().toLowerCase(), !fast, start.hasBearing() ? start.getBearing() / 180d * Math.PI : null)); + List specs = new ArrayList(); + if (!app.getSettings().FAST_ROUTE_MODE.get()) { + specs.add(GeneralRouter.USE_SHORTEST_WAY); + } + if(app.getSettings().AVOID_FERRIES.get()){ + specs.add(GeneralRouter.AVOID_FERRIES); + } + if(app.getSettings().AVOID_TOLL_ROADS.get()){ + specs.add(GeneralRouter.AVOID_TOLL); + } + if(app.getSettings().AVOID_UNPAVED_ROADS.get()){ + specs.add(GeneralRouter.AVOID_UNPAVED); + } + String[] specialization = specs.toArray(new String[specs.size()]); + RoutingContext ctx = new RoutingContext(config.build(p.name().toLowerCase(), start.hasBearing() ? start.getBearing() / 180d * Math.PI : null, specialization)); ctx.interruptable = interruptable; ctx.previouslyCalculatedRoute = previousRoute; RouteSegment st= router.findRouteSegment(start.getLatitude(), start.getLongitude(), ctx); diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java index 26eec93beb..61da89f246 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java @@ -539,7 +539,6 @@ public class RoutingHelper { private final GPXRouteParams gpxRoute; private final RouteCalculationResult previousRoute; private RouteService service; - private boolean fastRoute; private boolean interrupted = false; public RouteRecalculationThread(String name, @@ -550,7 +549,7 @@ public class RoutingHelper { this.gpxRoute = gpxRoute; this.previousRoute = previousRoute; service = settings.ROUTER_SERVICE.get(); - fastRoute = settings.FAST_ROUTE_MODE.get(); + } public void stopCalculation(){ @@ -565,6 +564,7 @@ public class RoutingHelper { @Override public void run() { boolean leftSide = settings.LEFT_SIDE_NAVIGATION.get(); + boolean fastRoute = settings.FAST_ROUTE_MODE.get(); RouteCalculationResult res = provider.calculateRouteImpl(start, end, mode, service, context, gpxRoute, previousRoute, fastRoute, leftSide, this); if (interrupted) {