diff --git a/DataExtractionOSM/src/net/osmand/NativeLibrary.java b/DataExtractionOSM/src/net/osmand/NativeLibrary.java index 67d3036eca..3f0de5ea30 100644 --- a/DataExtractionOSM/src/net/osmand/NativeLibrary.java +++ b/DataExtractionOSM/src/net/osmand/NativeLibrary.java @@ -1,13 +1,23 @@ package net.osmand; +import gnu.trove.list.array.TIntArrayList; + import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion; import net.osmand.binary.RouteDataObject; import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRulesStorage; +import net.osmand.router.GeneralRouter; import net.osmand.router.RouteSegmentResult; +import net.osmand.router.RoutingConfiguration; public class NativeLibrary { @@ -99,8 +109,32 @@ public class NativeLibrary { return closeBinaryMapFile(filePath); } - public RouteSegmentResult[] testRoutingInternal(int sx31, int sy31, int ex31, int ey31) { - return testRouting(sx31, sy31, ex31, ey31); + public RouteSegmentResult[] runNativeRouting(int sx31, int sy31, int ex31, int ey31, RoutingConfiguration config) { + TIntArrayList state = new TIntArrayList(); + List keys = new ArrayList(); + List values = new ArrayList(); + GeneralRouter r = (GeneralRouter) config.router; + fillObjects(state, keys, values, 0, r.highwaySpeed); + fillObjects(state, keys, values, 1, r.highwayPriorities); + fillObjects(state, keys, values, 2, r.avoid); + fillObjects(state, keys, values, 3, r.obstacles); + fillObjects(state, keys, values, 4, r.routingObstacles); + LinkedHashMap attrs = new LinkedHashMap(config.attributes); + attrs.putAll(r.attributes); + fillObjects(state, keys, values, 5, attrs); + + return nativeRouting(new int[]{sx31, sy31, ex31, ey31}, state.toArray(), keys.toArray(new String[keys.size()]), + values.toArray(new String[values.size()])); + } + + public void fillObjects(TIntArrayList state, List keys, List values, int s, Map map) { + Iterator> it = map.entrySet().iterator(); + while(it.hasNext()) { + Entry n = it.next(); + state.add(s); + keys.add(n.getKey()); + values.add(n.getValue()+""); + } } @@ -122,7 +156,7 @@ public class NativeLibrary { protected static native RouteDataObject[] getRouteDataObjects(RouteRegion reg, long rs, int x31, int y31); - protected static native RouteSegmentResult[] testRouting(int sx31, int sy31, int ex31, int ey31); + protected static native RouteSegmentResult[] nativeRouting(int[] coordinates, int[] state, String[] keyConfig, String[] valueConfig); protected static native void deleteSearchResult(long searchResultHandle); diff --git a/DataExtractionOSM/src/net/osmand/router/GeneralRouter.java b/DataExtractionOSM/src/net/osmand/router/GeneralRouter.java index e2a0e4651e..e9d4004f62 100644 --- a/DataExtractionOSM/src/net/osmand/router/GeneralRouter.java +++ b/DataExtractionOSM/src/net/osmand/router/GeneralRouter.java @@ -1,8 +1,10 @@ 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.RouteDataObject; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; @@ -17,26 +19,25 @@ public class GeneralRouter extends VehicleRouter { public static final String AVOID_MOTORWAY = "avoid_motorway"; public static final String AVOID_UNPAVED = "avoid_unpaved"; - Map highwaySpeed ; - Map highwayPriorities ; - Map highwayFuturePriorities ; - Map avoid ; - Map obstacles; - Map routingObstacles; - Map attributes; + 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; - private Float leftTurn; - private Float roundaboutTurn; - private Float rightTurn; - private Boolean onewayAware; - private Boolean followSpeedLimitations; - private Float minDefaultSpeed; - private Float maxDefaultSpeed; + 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, @@ -49,21 +50,51 @@ public class GeneralRouter extends VehicleRouter { this.profile = profile; highwaySpeed = new LinkedHashMap(); highwayPriorities = new LinkedHashMap(); - highwayFuturePriorities = 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) { this.highwaySpeed = new LinkedHashMap(pr.highwaySpeed); this.highwayPriorities = new LinkedHashMap(pr.highwayPriorities); - this.highwayFuturePriorities = new LinkedHashMap(pr.highwayFuturePriorities); this.avoid = new LinkedHashMap(pr.avoid); this.obstacles = new LinkedHashMap(pr.obstacles); this.routingObstacles = new LinkedHashMap(pr.routingObstacles); this.attributes = new LinkedHashMap(pr.attributes); this.profile = pr.profile; + Iterator> e = pr.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 @@ -105,9 +136,6 @@ public class GeneralRouter extends VehicleRouter { @Override public boolean restrictionsAware() { - if(restrictionsAware == null) { - restrictionsAware = parseSilentBoolean(attributes.get("restrictionsAware"), true); - } return restrictionsAware; } @@ -156,9 +184,6 @@ public class GeneralRouter extends VehicleRouter { } public boolean isOnewayAware() { - if(onewayAware == null) { - onewayAware = parseSilentBoolean(attributes.get("onewayAware"), true); - } return onewayAware; } @@ -170,23 +195,9 @@ public class GeneralRouter extends VehicleRouter { return super.isOneWay(road); } - @Override - public float getFutureRoadPriority(RouteDataObject road) { - float priority = 1; - for (int i = 0; i < road.types.length; i++) { - RouteTypeRule r = road.region.quickGetEncodingRule(road.types[i]); - if(highwayFuturePriorities.containsKey(r.getTag()+"$"+r.getValue())){ - priority = highwayFuturePriorities.get(r.getTag()+"$"+r.getValue()); - break; - } - } - return priority; - } + public boolean isFollowSpeedLimitations(){ - if(followSpeedLimitations == null){ - followSpeedLimitations = parseSilentBoolean(attributes.get("followSpeedLimitations"), true); - } return followSpeedLimitations; } @@ -241,38 +252,23 @@ public class GeneralRouter extends VehicleRouter { @Override public float getMinDefaultSpeed() { - if(minDefaultSpeed == null ){ - minDefaultSpeed = parseSilentFloat(attributes.get("minDefaultSpeed"), 10); - } - return minDefaultSpeed / 3.6f; + return minDefaultSpeed; } @Override public float getMaxDefaultSpeed() { - if(maxDefaultSpeed == null ){ - maxDefaultSpeed = parseSilentFloat(attributes.get("maxDefaultSpeed"), 10); - } - return maxDefaultSpeed / 3.6f; + return maxDefaultSpeed ; } public double getLeftTurn() { - if(leftTurn == null) { - leftTurn = parseSilentFloat(attributes.get("leftTurn"), 0); - } return leftTurn; } public double getRightTurn() { - if(rightTurn == null) { - rightTurn = parseSilentFloat(attributes.get("rightTurn"), 0); - } return rightTurn; } public double getRoundaboutTurn() { - if(roundaboutTurn == null) { - roundaboutTurn = parseSilentFloat(attributes.get("roundaboutTurn"), 0); - } return roundaboutTurn; } @Override @@ -307,7 +303,7 @@ public class GeneralRouter extends VehicleRouter { return 0; } - private void specialize(String specializationTag, Map m){ + private void specialize(String specializationTag, Map m){ ArrayList ks = new ArrayList(m.keySet()); for(String s : ks){ if(s.startsWith(specializationTag +":")) { @@ -319,15 +315,25 @@ public class GeneralRouter extends VehicleRouter { @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); 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); + } + } diff --git a/DataExtractionOSM/src/net/osmand/router/RoutingConfiguration.java b/DataExtractionOSM/src/net/osmand/router/RoutingConfiguration.java index bfb95dadb6..8e83f48151 100644 --- a/DataExtractionOSM/src/net/osmand/router/RoutingConfiguration.java +++ b/DataExtractionOSM/src/net/osmand/router/RoutingConfiguration.java @@ -16,36 +16,29 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class RoutingConfiguration { + + public static final int DEFAULT_MEMORY_LIMIT = 30; + public Map attributes = new LinkedHashMap(); + // 1. parameters of routing and different tweaks // Influence on A* : f(x) + heuristicCoefficient*g(X) public float heuristicCoefficient = 1; - public static final int DEFAULT_MEMORY_LIMIT = 30; - - // 1.1 tile load parameters (should not affect routing) public int ZOOM_TO_LOAD_TILES = 16; public int memoryLimitation; - // 1.2 Dynamic road prioritizing (heuristic) - public boolean useDynamicRoadPrioritising = true; - public int dynamicRoadPriorityDistance = 0; - - // 1.3 Relaxing strategy - public boolean useRelaxingStrategy = true; - public int ITERATIONS_TO_RELAX_NODES = 100; - public float RELAX_NODES_IF_START_DIST_COEF = 3; - - // 1.4 Build A* graph in backward/forward direction (can affect results) + // 1.2 Build A* graph in backward/forward direction (can affect results) // 0 - 2 ways, 1 - direct way, -1 - reverse way public int planRoadDirection = 0; - // 1.5 Router specific coefficients and restrictions + // 1.3 Router specific coefficients and restrictions public VehicleRouter router = new GeneralRouter(GeneralRouterProfile.CAR, new LinkedHashMap()); public String routerName = ""; - // 1.6 Used to calculate route in movement + // 1.4 Used to calculate route in movement public Double initialDirection; + public static class Builder { @@ -62,10 +55,21 @@ public class RoutingConfiguration { router = defaultRouter; } RoutingConfiguration i = new RoutingConfiguration(); + if (routers.containsKey(router)) { + i.router = routers.get(router); + if (specialization != null) { + for (String s : specialization) { + i.router = i.router.specialization(s); + } + } + i.routerName = router; + } + attributes.put("routerName", router); + i.attributes.putAll(attributes); i.initialDirection = direction; - i.heuristicCoefficient = parseSilentFloat(getAttribute(router, "heuristicCoefficient"), i.heuristicCoefficient); - i.ZOOM_TO_LOAD_TILES = parseSilentInt(getAttribute(router, "zoomToLoadTiles"), i.ZOOM_TO_LOAD_TILES); - int desirable = parseSilentInt(getAttribute(router, "memoryLimitInMB"), 0); + i.heuristicCoefficient = parseSilentFloat(getAttribute(i.router, "heuristicCoefficient"), i.heuristicCoefficient); + i.ZOOM_TO_LOAD_TILES = parseSilentInt(getAttribute(i.router, "zoomToLoadTiles"), i.ZOOM_TO_LOAD_TILES); + int desirable = parseSilentInt(getAttribute(i.router, "memoryLimitInMB"), 0); if(desirable != 0) { i.memoryLimitation = desirable * (1 << 20); } else { @@ -74,29 +78,15 @@ public class RoutingConfiguration { } i.memoryLimitation = memoryLimitMB * (1 << 20); } - i.useDynamicRoadPrioritising = parseSilentBoolean(getAttribute(router, "useDynamicRoadPrioritising"), i.useDynamicRoadPrioritising); - i.useRelaxingStrategy = parseSilentBoolean(getAttribute(router, "useRelaxingStrategy"), i.useRelaxingStrategy); - i.dynamicRoadPriorityDistance = parseSilentInt(getAttribute(router, "dynamicRoadPriorityDistance"), i.dynamicRoadPriorityDistance); - i.ITERATIONS_TO_RELAX_NODES = parseSilentInt(getAttribute(router, "iterationsToRelaxRoutes"), i.ITERATIONS_TO_RELAX_NODES); - i.RELAX_NODES_IF_START_DIST_COEF = parseSilentFloat(getAttribute(router, "relaxNodesIfStartDistSmallCoeff"), i.RELAX_NODES_IF_START_DIST_COEF); i.planRoadDirection = parseSilentInt(getAttribute(router, "planRoadDirection"), i.planRoadDirection); - if (!routers.containsKey(router)) { - return i; - } - i.router = routers.get(router); - if(specialization != null) { - for(String s : specialization) { - i.router = i.router.specialization(s); - } - } - i.routerName = router; + return i; } - private String getAttribute(String router, String propertyName) { - if (attributes.containsKey(router + "$" + propertyName)) { - return attributes.get(router + "$" + propertyName); + private String getAttribute(VehicleRouter router, String propertyName) { + if (router.containsAttribute(propertyName)) { + return router.getAttribute(propertyName); } return attributes.get(propertyName); } @@ -151,15 +141,15 @@ public class RoutingConfiguration { @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { String name = parser.isNamespaceAware() ? localName : qName; + previousTag = name; if("osmand_routing_config".equals(name)) { config.defaultRouter = attributes.getValue("defaultProfile"); } else if("attribute".equals(name)) { - previousKey = attributes.getValue("name"); - previousTag = name; - if (currentSelectedRouter != null) { - previousKey = currentSelectedRouter + "$" + previousKey; + if(currentRouter != null) { + currentRouter.addAttribute(attributes.getValue("name"), attributes.getValue("value")); + } else { + config.attributes.put(attributes.getValue("name"), attributes.getValue("value")); } - config.attributes.put(previousKey, attributes.getValue("value")); } else if("routingProfile".equals(name)) { currentSelectedRouter = attributes.getValue("name"); Map attrs = new LinkedHashMap(); @@ -181,12 +171,12 @@ public class RoutingConfiguration { if (attributes.getValue("priority") != null) { currentRouter.highwayPriorities.put(k, parseSilentFloat(attributes.getValue("priority"), 0)); } - if (attributes.getValue("dynamicPriority") != null) { - currentRouter.highwayFuturePriorities.put(k, parseSilentFloat(attributes.getValue("dynamicPriority"), 0)); - } if (attributes.getValue("speed") != null) { currentRouter.highwaySpeed.put(k, parseSilentFloat(attributes.getValue("speed"), 0)); } + if ("attribute".equals(previousTag)) { + currentRouter.attributes.put(k, attributes.getValue("value")); + } if ("avoid".equals(previousTag)) { float priority = parseSilentFloat(attributes.getValue("decreasedPriority"), 0); if (priority == 0) { @@ -198,23 +188,18 @@ public class RoutingConfiguration { } } else if("road".equals(name)) { - previousTag = name; previousKey = attributes.getValue("tag") +"$" + attributes.getValue("value"); currentRouter.highwayPriorities.put(previousKey, parseSilentFloat(attributes.getValue("priority"), 1)); - currentRouter.highwayFuturePriorities.put(previousKey, parseSilentFloat(attributes.getValue("dynamicPriority"), - 1)); currentRouter.highwaySpeed.put(previousKey, parseSilentFloat(attributes.getValue("speed"), 10)); } else if("obstacle".equals(name)) { - previousTag = name; previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value"); float penalty = parseSilentFloat(attributes.getValue("penalty"), 0); currentRouter.obstacles.put(previousKey, penalty); float routingPenalty = parseSilentFloat(attributes.getValue("routingPenalty"), penalty ); currentRouter.routingObstacles.put(previousKey, routingPenalty); } else if("avoid".equals(name)) { - previousTag = name; previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value"); float priority = parseSilentFloat(attributes.getValue("decreasedPriority"), 0); diff --git a/DataExtractionOSM/src/net/osmand/router/VehicleRouter.java b/DataExtractionOSM/src/net/osmand/router/VehicleRouter.java index 56fc0c41a8..09388d4cb9 100644 --- a/DataExtractionOSM/src/net/osmand/router/VehicleRouter.java +++ b/DataExtractionOSM/src/net/osmand/router/VehicleRouter.java @@ -27,11 +27,11 @@ public abstract class VehicleRouter { return road.getHighway(); } + public abstract boolean containsAttribute(String attribute); + + public abstract String getAttribute(String attribute); + - /** - * Used for algorithm to multiply h(x) part A* based on current road - */ - public abstract float getFutureRoadPriority(RouteDataObject road); /** * return delay in seconds diff --git a/DataExtractionOSM/src/net/osmand/router/routing.xml b/DataExtractionOSM/src/net/osmand/router/routing.xml index c9d8f15d66..9822e1b61a 100644 --- a/DataExtractionOSM/src/net/osmand/router/routing.xml +++ b/DataExtractionOSM/src/net/osmand/router/routing.xml @@ -12,18 +12,6 @@ (don't specify here ! it is device dependent) --> - - - - - - - - - - - - diff --git a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java index 11c793fb0a..19079e9281 100644 --- a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java +++ b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java @@ -721,7 +721,7 @@ public class MapRouterLayer implements MapPanelLayer { int sx31 = st.getRoad().getPoint31XTile(st.getSegmentStart()); int sy31 = st.getRoad().getPoint31YTile(st.getSegmentStart()); // FIXME - RouteSegmentResult[] searchRoute = ctx.nativeLib.testRoutingInternal(sx31, sy31, ex31, ey31); + RouteSegmentResult[] searchRoute = ctx.nativeLib.runNativeRouting(sx31, sy31, ex31, ey31, ctx.config); /*List searchRoute = */router.searchRoute(ctx, st, e, inters, false); // this.previousRoute = searchRoute; if (animateRoutingCalculation) { diff --git a/Osmand-kernel/osmand/src/binaryRoutePlanner.cpp b/Osmand-kernel/osmand/src/binaryRoutePlanner.cpp index 7f60bfcc6b..a02ff9dce5 100644 --- a/Osmand-kernel/osmand/src/binaryRoutePlanner.cpp +++ b/Osmand-kernel/osmand/src/binaryRoutePlanner.cpp @@ -58,13 +58,13 @@ static double squareDist(int x1, int y1, int x2, int y2) { } static double h(RoutingContext* ctx, float distanceToFinalPoint, SHARED_PTR next) { - return distanceToFinalPoint / ctx->getMaxDefaultSpeed(); + return distanceToFinalPoint / ctx->config.getMaxDefaultSpeed(); } static double h(RoutingContext* ctx, int targetEndX, int targetEndY, int startX, int startY) { double distance = squareRootDist(startX, startY, targetEndX, targetEndY); - return distance / ctx->getMaxDefaultSpeed(); + return distance / ctx->config.getMaxDefaultSpeed(); } @@ -220,7 +220,7 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, // avoid empty segments to connect but mark the point as visited visitedSegments[nt] = SHARED_PTR(); - int oneway = ctx->isOneWay(road); + int oneway = ctx->config.isOneWay(road); bool minusAllowed; bool plusAllowed; if(ctx->firstRoadId == nt) { @@ -238,11 +238,11 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, int d = plusAllowed ? 1 : -1; if(segment->parentRoute.get() != NULL) { if(plusAllowed && middle < segment->road->pointsX.size() - 1) { - obstaclePlusTime = ctx->calculateTurnTime(segment, segment->road->pointsX.size() - 1, + obstaclePlusTime = ctx->config.calculateTurnTime(segment, segment->road->pointsX.size() - 1, segment->parentRoute, segment->parentSegmentEnd); } if(minusAllowed && middle > 0) { - obstacleMinusTime = ctx->calculateTurnTime(segment, 0, + obstacleMinusTime = ctx->config.calculateTurnTime(segment, 0, segment->parentRoute, segment->parentSegmentEnd); } } @@ -291,14 +291,14 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, // 2.1 calculate possible obstacle plus time if(positive) { - double obstacle = ctx->defineRoutingObstacle(road, segmentEnd); + double obstacle = ctx->config.defineRoutingObstacle(road, segmentEnd); if (obstacle < 0) { plusAllowed = false; continue; } obstaclePlusTime += obstacle; } else { - double obstacle = ctx->defineRoutingObstacle(road, segmentEnd); + double obstacle = ctx->config.defineRoutingObstacle(road, segmentEnd); if (obstacle < 0) { minusAllowed = false; continue; @@ -324,10 +324,10 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, // Using A* routing algorithm // g(x) - calculate distance to that point and calculate time - double priority = ctx->defineSpeedPriority(road); - double speed = ctx->defineSpeed(road) * priority; + double priority = ctx->config.defineSpeedPriority(road); + double speed = ctx->config.defineSpeed(road) * priority; if (speed == 0) { - speed = ctx->getMinDefaultSpeed() * priority; + speed = ctx->config.getMinDefaultSpeed() * priority; } double distOnRoadToPass = positive? posSegmentDist : negSegmentDist; double distStartObstacles = segment->distanceFromStart + ( positive ? obstaclePlusTime : obstacleMinusTime) + distOnRoadToPass / speed; @@ -353,7 +353,7 @@ bool proccessRestrictions(RoutingContext* ctx, SHARED_PTR road, if (!reverseWay && road->restrictions.size() == 0) { return false; } - if(!ctx->restrictionsAware()) { + if(!ctx->config.restrictionsAware()) { return false; } while (next.get() != NULL) { @@ -497,7 +497,7 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments, return false; } -// FIXME +// FIXME replace with adequate method SHARED_PTR findRouteSegment(int px, int py, RoutingContext* ctx) { return ctx->loadSegmentAround(px, py); } diff --git a/Osmand-kernel/osmand/src/binaryRoutePlanner.h b/Osmand-kernel/osmand/src/binaryRoutePlanner.h index bc222d3772..02621b2b64 100644 --- a/Osmand-kernel/osmand/src/binaryRoutePlanner.h +++ b/Osmand-kernel/osmand/src/binaryRoutePlanner.h @@ -3,6 +3,9 @@ #include "common.h" #include "binaryRead.h" +typedef UNORDERED(map) MAP_STR_FLOAT; +typedef UNORDERED(map) MAP_STR_STR; + static double measuredDist(int x1, int y1, int x2, int y2) { return getDistance(get31LatitudeY(y1), get31LongitudeX(x1), get31LatitudeY(y2), get31LongitudeX(x2)); @@ -54,7 +57,6 @@ struct FinalRouteSegment { -const static int ZOOM_TO_LOAD_TILES = 16; struct RoutingSubregionTile { RouteSubregion subregion; // make it without get/set for fast access @@ -99,9 +101,245 @@ static int64_t calcRouteId(SHARED_PTR o, int ind) { return (o->id << 10) + ind; } +typedef std::pair > ROUTE_TRIPLE; +struct RoutingConfiguration { + // 0 index in triple + MAP_STR_FLOAT highwaySpeed ; + // 1 index in triple + MAP_STR_FLOAT highwayPriorities ; + // 2 index in triple + MAP_STR_FLOAT avoid ; + // 3 index in triple + MAP_STR_FLOAT obstacles; + // 4 index in triple + MAP_STR_FLOAT routingObstacles; + // 5 index in triple + MAP_STR_STR attributes; + + int zoomToLoad; + float heurCoefficient; + float maxDefaultSpeed; + float minDefaultSpeed; + bool restrictions; + bool onewayAware; + bool followLimitations; + int memoryLimitation; + int planRoadDirection; + string routerName; + float initialDirection; + string routerProfile; + float roundaboutTurn; + float leftTurn; + float rightTurn; + + float parseFloat(string key, float def) { + if(attributes.find(key) != attributes.end() && attributes[key] != "") { + return atof(attributes[key].c_str()); + } + return def; + } + bool parseBool(string key, bool def) { + if (attributes.find(key) != attributes.end() && attributes[key] != "") { + return attributes[key] == "true"; + } + return def; + } + + string parseString(string key, string def) { + if (attributes.find(key) != attributes.end() && attributes[key] != "") { + return attributes[key]; + } + return def; + } + void defaultParams() { + planRoadDirection = (int) parseFloat("planRoadDirection", 0); + restrictions = parseBool("restrictionsAware", true); + followLimitations = parseBool("followSpeedLimitations", true); + onewayAware = parseBool("onewayAware", true); + roundaboutTurn = parseFloat("roundaboutTurn", 0); + leftTurn = parseFloat("leftTurn", 0); + rightTurn = parseFloat("rightTurn", 0); + minDefaultSpeed = parseFloat("minDefaultSpeed", 45) / 3.6; + maxDefaultSpeed = parseFloat("maxDefaultSpeed", 130) / 3.6; + heurCoefficient = parseFloat("heuristicCoefficient", 1); + memoryLimitation = (int)parseFloat("memoryLimitInMB", memoryLimitation); + zoomToLoad = (int)parseFloat("zoomToLoadTiles", 16); + routerName = parseString("name", "default"); + routerProfile = parseString("baseProfile", "car"); + } + + RoutingConfiguration(vector& config, int memLimit = 30, float initDirection = 0) : + memoryLimitation(memLimit), initialDirection(initDirection) { + for(int j = 0; j r) { + std::vector::iterator t = r->types.begin(); + bool accepted = false; + for(; t != r->types.end(); t++) { + tag_value type = r->region->decodingRules[*t]; + if(type.first=="highway" && highwaySpeed[type.second] > 0) { + accepted = true; + break; + } else if(highwaySpeed[type.first + '$' + type.second] > 0) { + accepted = true; + break; + } + } + if(!accepted) { + return false; + } + t = r->types.begin(); + for(; t != r->types.end(); t++) { + tag_value type = r->region->decodingRules[*t]; + if(avoid.find(type.first + '$' + type.second) != avoid.end()) { + return false; + } + } + return true; + } + + string getHighway(SHARED_PTR r) { + std::vector::iterator t = r->types.begin(); + for(; t != r->types.end(); t++) { + tag_value type = r->region->decodingRules[*t]; + if(type.first=="highway") { + return type.second; + } + } + return ""; + } + + float defineSpeedPriority(SHARED_PTR r) { + float priority = 1; + std::vector::iterator t = r->types.begin(); + for(; t != r->types.end(); t++) { + tag_value type = r->region->decodingRules[*t]; + if(highwayPriorities.find(type.first+"$"+type.second) != highwaySpeed.end()) { + priority *= highwayPriorities[type.first+"$"+type.second]; + } + } + return priority; + } + + float getMinDefaultSpeed() { + return minDefaultSpeed; + } + float getMaxDefaultSpeed() { + return maxDefaultSpeed; + } + + int isOneWay(SHARED_PTR r) { + if(!onewayAware){ + return 0; + } + std::vector::iterator t = r->types.begin(); + for(; t != r->types.end(); t++) { + tag_value type = r->region->decodingRules[*t]; + if(type.first == "oneway") { + string v = type.second; + if("-1" ==v || "reverse" == v) { + return -1; + } else if("1" == v || "yes" == v) { + return 1; + } + } + } + return 0; + } + +// TODO + float calculateTurnTime(SHARED_PTR segment, int index, SHARED_PTR next, int nextIndex) { + return 0; + } + + float defineRoutingObstacle(SHARED_PTR road, int segmentEnd) { + if(road->pointTypes.size() <= segmentEnd) { + return 0; + } + std::vector pointTypes = road->pointTypes[segmentEnd]; + std::vector::iterator t = pointTypes.begin(); + for(; t != pointTypes.end(); t++) { + tag_value type = road->region->decodingRules[*t]; + if(routingObstacles.find(type.first + "$" + type.second) != routingObstacles.end()) { + return routingObstacles[type.first + "$" + type.second]; + } + } + t = pointTypes.begin(); + for(; t != pointTypes.end(); t++) { + tag_value type = road->region->decodingRules[*t]; + if(routingObstacles.find(type.first + "$" ) != routingObstacles.end()) { + return routingObstacles[type.first + "$" ]; + } + } + return 0; + } + + bool restrictionsAware() { + return restrictions; + } + + float maxSpeed(SHARED_PTR r) { + std::vector::iterator t = r->types.begin(); + for(; t != r->types.end(); t++) { + tag_value type = r->region->decodingRules[*t]; + if(type.first=="maxspeed") { + std::string v = type.second; + int i = 0; + while(i < v.length() && v[i] >= '0' && v[i] <= '9') { + i++; + } + if(i > 0) { + float f = atoi(v.substr(0, i).c_str()); + f = f / 3.6; + if(v.find("mph") != std::string::npos ) { + f *= 1.6; + } + return f; + } + return 0; + } + } + return 0; + } + + float defineSpeed(SHARED_PTR r) { + if (followLimitations) { + float m = maxSpeed(r); + if(m > 0) { + return m; + } + } + std::vector::iterator t = r->types.begin(); + for(; t != r->types.end(); t++) { + tag_value type = r->region->decodingRules[*t]; + if(highwaySpeed.find(type.first+"$"+type.second) != highwaySpeed.end()) { + return highwaySpeed[type.first+"$"+type.second] / 3.6; + } + } + return getMinDefaultSpeed(); + } + +}; -// FIXME configuration methods struct RoutingContext { int visitedSegments; int loadedTiles; @@ -109,6 +347,7 @@ struct RoutingContext { ElapsedTimer timeToCalculate; int firstRoadDirection; int64_t firstRoadId; + RoutingConfiguration config; int startX; int startY; @@ -122,25 +361,12 @@ struct RoutingContext { UNORDERED(map) > subregionTiles; UNORDERED(map) > > indexedSubregions; - RoutingContext() : finalRouteSegment(), firstRoadDirection(0), loadedTiles(0), visitedSegments(0){ - } - bool acceptLine(SHARED_PTR r) { - string v = getHighway(r); - if(v != "" && v != "cycleway" && v != "footway" && v != "steps"){ - return true; - } - return false; + RoutingContext(RoutingConfiguration& config) : finalRouteSegment(), firstRoadDirection(0), loadedTiles(0), visitedSegments(0), + config(config){ } - string getHighway(SHARED_PTR r) { - std::vector::iterator t = r->types.begin(); - for(; t != r->types.end(); t++) { - tag_value type = r->region->decodingRules[*t]; - if(type.first=="highway") { - return type.second; - } - } - return ""; + bool acceptLine(SHARED_PTR r) { + return config.acceptLine(r); } void loadHeaderObjects(int64_t tileId) { @@ -167,7 +393,7 @@ struct RoutingContext { void loadHeaders(uint32_t xloc, uint32_t yloc) { timeToLoad.start(); - int z = ZOOM_TO_LOAD_TILES; + int z = config.zoomToLoad; int tz = 31 - z; int64_t tileId = (xloc << z) + yloc; if (indexedSubregions.find(tileId) == indexedSubregions.end()) { @@ -192,12 +418,12 @@ struct RoutingContext { } - // FIXME + // FIXME replace with adequate method SHARED_PTR loadSegmentAround(int x31, int y31) { timeToLoad.start(); SHARED_PTR r; float dist = -1; - int z = ZOOM_TO_LOAD_TILES; + int z = config.zoomToLoad; uint32_t xloc = x31 >> (31 - z); uint32_t yloc = y31 >> (31 - z); uint64_t l = (((uint64_t) x31) << 31) + (uint64_t) y31; @@ -227,7 +453,7 @@ struct RoutingContext { // void searchRouteRegion(SearchQuery* q, std::vector& list, RoutingIndex* rs, RouteSubregion* sub) SHARED_PTR loadRouteSegment(int x31, int y31) { - int z = ZOOM_TO_LOAD_TILES; + int z = config.zoomToLoad; int64_t xloc = x31 >> (31 - z); int64_t yloc = y31 >> (31 - z); uint64_t l = (((uint64_t) x31) << 31) + (uint64_t) y31; @@ -262,157 +488,16 @@ struct RoutingContext { return false; } float getHeuristicCoefficient(){ - return 1; + return config.heurCoefficient; } bool planRouteIn2Directions() { return getPlanRoadDirection() == 0; } int getPlanRoadDirection() { - return 1; + return config.planRoadDirection; } - float defineSpeedPriority(SHARED_PTR r) { - string v = getHighway(r); - if(v == "") { - return 1; - } else if(v == "motorway") { - return 1.2; - } else if(v == "motorway_link") { - return 1.2; - } else if(v == "trunk") { - return 1.2; - } else if(v == "trunk_link") { - return 1.2; - } else if(v == "primary") { - return 1.1; - } else if(v == "primary_link") { - return 1.1; - } else if(v == "secondary") { - return 1.05; - } else if(v == "secondary_link") { - return 1.05; - } else if(v == "tertiary") { - return 1; - } else if(v == "tertiary_link") { - return 1; - } else if(v == "unclassified") { - return 0.7; - } else if(v == "road") { - return 0.7; - } else if(v == "service") { - return 0.5; - } else if(v == "track") { - return 0.3; - } else if(v == "residential") { - return 0.5; - } else if(v == "living_street") { - return 0.5; - } - return 1; - } - - float maxSpeed(SHARED_PTR r) { - std::vector::iterator t = r->types.begin(); - for(; t != r->types.end(); t++) { - tag_value type = r->region->decodingRules[*t]; - if(type.first=="maxspeed") { - std::string v = type.second; - int i = 0; - while(i < v.length() && v[i] >= '0' && v[i] <= '9') { - i++; - } - if(i > 0) { - float f = atoi(v.substr(0, i).c_str()); - f /= 3.6; // km/h -> m/s - if(v.find("mph") != std::string::npos ) { - f *= 1.6; - } - return f; - } - return 0; - } - } - return 0; - } - - float defineSpeed(SHARED_PTR r) { - float speed = maxSpeed(r); - if(speed > 0) { - return speed; - } - string v = getHighway(r); - if(v == "") { - } else if(v == "motorway") { - speed = 110; - } else if(v == "motorway_link") { - speed = 80; - } else if(v == "trunk") { - speed = 100; - } else if(v == "trunk_link") { - speed = 75; - } else if(v == "primary") { - speed = 65; - } else if(v == "primary_link") { - speed = 50; - } else if(v == "secondary") { - speed = 60; - } else if(v == "secondary_link") { - speed = 50; - } else if(v == "tertiary") { - speed = 45; - } else if(v == "tertiary_link") { - speed = 40; - } else if(v == "unclassified") { - speed = 35; - } else if(v == "road") { - speed = 35; - } else if(v == "service") { - speed = 30; - } else if(v == "track") { - speed = 15; - } else if(v == "residential") { - speed = 35; - } else if(v == "living_street") { - speed = 25; - } - return speed / 3.; - } - - - float getMinDefaultSpeed(){ - return 40 / 3.6; - } - float getMaxDefaultSpeed(){ - return 130 / 3.6; - } - - int isOneWay(SHARED_PTR r) { - std::vector::iterator t = r->types.begin(); - for(; t != r->types.end(); t++){ - tag_value type = r->region->decodingRules[*t]; - if(type.first == "oneway") { - string v = type.second; - if("-1" ==v || "reverse" == v) { - return -1; - } else if("1" == v || "yes" == v) { - return 1; - } - } - } - return 0; - } - - float calculateTurnTime(SHARED_PTR segment, int index, SHARED_PTR next, int nextIndex){ - return 0; - } - float defineRoutingObstacle(SHARED_PTR road, int segmentEnd) { - return 0; - } - - bool restrictionsAware(){ - return true; - } }; diff --git a/Osmand-kernel/osmand/src/java_wrap.cpp b/Osmand-kernel/osmand/src/java_wrap.cpp index 778a4dd86a..ef45e9d2ea 100644 --- a/Osmand-kernel/osmand/src/java_wrap.cpp +++ b/Osmand-kernel/osmand/src/java_wrap.cpp @@ -580,15 +580,33 @@ extern "C" JNIEXPORT void JNICALL Java_net_osmand_NativeLibrary_deleteRouteSearc } delete t; } -extern "C" JNIEXPORT jobjectArray JNICALL Java_net_osmand_NativeLibrary_testRouting(JNIEnv* ienv, - jobject obj, jint sx31, - jint sy31, jint ex31, jint ey31) { - RoutingContext c; - c.startX = sx31; - c.startY = sy31; - c.endX = ex31; - c.endY = ey31; +//p RouteSegmentResult[] nativeRouting(int[] coordinates, int[] state, String[] keyConfig, String[] valueConfig); +extern "C" JNIEXPORT jobjectArray JNICALL Java_net_osmand_NativeLibrary_nativeRouting(JNIEnv* ienv, + jobject obj, jintArray coordinates, + jintArray stateConfig, jobjectArray keyConfig, jobjectArray valueConfig) { + + vector cfg; + int* data = ienv->GetIntArrayElements(stateConfig, NULL); + for(int k = 0; k < ienv->GetArrayLength(stateConfig); k++) { + ROUTE_TRIPLE t = ROUTE_TRIPLE (data[k], std::pair( + getString(ienv, (jstring) ienv->GetObjectArrayElement(keyConfig, k)), + getString(ienv, (jstring) ienv->GetObjectArrayElement(valueConfig, k))) + ); + cfg.push_back(t); + } + ienv->ReleaseIntArrayElements(stateConfig, data, 0); + + RoutingConfiguration config(cfg); + RoutingContext c(config); + data = ienv->GetIntArrayElements(coordinates, NULL); + c.startX = data[0]; + c.startY = data[1]; + c.endX = data[2]; + c.endY = data[3]; + ienv->ReleaseIntArrayElements(coordinates, data, 0); + vector r = searchRouteInternal(&c, false); + // convert results jobjectArray res = ienv->NewObjectArray(r.size(), jclass_RouteSegmentResult, NULL); for (int i = 0; i < r.size(); i++) { jobject robj = convertRouteDataObjectToJava(ienv, r[i].object.get(), NULL); diff --git a/Osmand-kernel/osmand/src/osmand_main.cpp b/Osmand-kernel/osmand/src/osmand_main.cpp index 35d94d159d..e87f3c21f1 100644 --- a/Osmand-kernel/osmand/src/osmand_main.cpp +++ b/Osmand-kernel/osmand/src/osmand_main.cpp @@ -160,11 +160,9 @@ void printFileInformation(const char* fileName, VerboseInfo* verbose) { i, j++, rt->minZoom, rt->maxZoom, rt->length, ch); } if ((verbose != NULL && verbose->vmap)) { - // FIXME //printMapDetailInfo(verbose, index); } } else if (it->type == TRANSPORT_INDEX) { - // FIXME // TransportIndex ti = ((TransportIndex) p); // int sh = (31 - BinaryMapIndexReader.TRANSPORT_STOP_ZOOM); // println(