Native routing

This commit is contained in:
Victor Shcherb 2012-11-05 01:38:24 +01:00
parent 657a9b7d94
commit 7068dd3b61
18 changed files with 437 additions and 250 deletions

View file

@ -109,7 +109,8 @@ public class NativeLibrary {
return closeBinaryMapFile(filePath);
}
public RouteSegmentResult[] runNativeRouting(int sx31, int sy31, int ex31, int ey31, RoutingConfiguration config) {
public RouteSegmentResult[] runNativeRouting(int sx31, int sy31, int ex31, int ey31, RoutingConfiguration config,
RouteRegion[] regions) {
TIntArrayList state = new TIntArrayList();
List<String> keys = new ArrayList<String>();
List<String> values = new ArrayList<String>();
@ -124,7 +125,8 @@ public class NativeLibrary {
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()]));
values.toArray(new String[values.size()]), config.initialDirection == null ? -360 : config.initialDirection.floatValue(),
regions);
}
public <T> void fillObjects(TIntArrayList state, List<String> keys, List<String> values, int s, Map<String, T> map) {
@ -156,7 +158,8 @@ public class NativeLibrary {
protected static native RouteDataObject[] getRouteDataObjects(RouteRegion reg, long rs, int x31, int y31);
protected static native RouteSegmentResult[] nativeRouting(int[] coordinates, int[] state, String[] keyConfig, String[] valueConfig);
protected static native RouteSegmentResult[] nativeRouting(int[] coordinates, int[] state, String[] keyConfig, String[] valueConfig,
float initDirection, RouteRegion[] regions);
protected static native void deleteSearchResult(long searchResultHandle);

View file

@ -845,7 +845,7 @@ public class BinaryMapRouteReaderAdapter {
RouteBorderLine ln = readBorderLine();
if(ln.hasTox() && req.intersects(ln.getX(), ln.getY(), ln.getTox(), ln.getY())) {
blocksToRead.add(ln.getShiftToPointsBlock() + fp);
// FIXME
// FIXME borders approach
// } else if(ln.hasToy() && req.intersects(ln.getX(), ln.getY(), ln.getX(), ln.getToy())) {
// blocksToRead.add(ln.getShiftToPointsBlock() + fp);
}

View file

@ -11,7 +11,7 @@ public class RouteDataObject {
public final RouteRegion region;
// all these arrays supposed to be immutable!
// These feilds accessible from C++
// These fields accessible from C++
public int[] types;
public int[] pointsX;
public int[] pointsY;
@ -213,6 +213,7 @@ public class RouteDataObject {
}
public double directionRoute(int startPoint, boolean plus) {
// same goes to C++
// Victor : the problem to put more than 5 meters that BinaryRoutePlanner will treat
// 2 consequent Turn Right as UT and here 2 points will have same turn angle
// So it should be fix in both places

View file

@ -422,6 +422,7 @@ public class IndexRouteCreator extends AbstractIndexPartCreator {
routeTree, false);
TLongObjectHashMap<BinaryFileReference> base = writeBinaryRouteIndexHeader(writer,
baserouteTree, true);
// FIXME borders should not be committed in master branch
// writeBorderBox(writer, routeBorders);
// writeBorderBox(writer, baseRouteBorders);

View file

@ -43,9 +43,9 @@ public class BinaryRoutePlanner {
int px = MapUtils.get31TileNumberX(lon);
int py = MapUtils.get31TileNumberY(lat);
ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
ctx.loadTileData(px, py, 16, dataObjects);
ctx.loadTileData(px, py, 17, dataObjects);
if (dataObjects.isEmpty()) {
ctx.loadTileData(px, py, 14, dataObjects);
ctx.loadTileData(px, py, 15, dataObjects);
}
RouteSegment road = null;
double sdist = 0;
@ -334,10 +334,6 @@ public class BinaryRoutePlanner {
graphSegments = graphDirectSegments;
}
if(ctx.runRelaxingStrategy() ) {
relaxNotNeededSegments(ctx, graphDirectSegments, true);
relaxNotNeededSegments(ctx, graphReverseSegments, false);
}
// check if interrupted
if(ctx.interruptable != null && ctx.interruptable.isCancelled()) {
throw new InterruptedException("Route calculation interrupted");
@ -349,12 +345,12 @@ public class BinaryRoutePlanner {
private RouteSegment smartRecalculationEnabled(final RoutingContext ctx, TLongObjectHashMap<RouteSegment> visitedOppositeSegments) {
boolean runRecalculation = ctx.previouslyCalculatedRoute != null && ctx.previouslyCalculatedRoute.size() > 0;
boolean runRecalculation = ctx.previouslyCalculatedRoute != null && ctx.previouslyCalculatedRoute.size() > 0
&& ctx.config.recalculateDistance != 0;
if (runRecalculation) {
RouteSegment previous = null;
List<RouteSegmentResult> rlist = new ArrayList<RouteSegmentResult>();
// always recalculate first 7 km
int distanceThreshold = 7000;
float distanceThreshold = ctx.config.recalculateDistance;
float threshold = 0;
for(RouteSegmentResult rr : ctx.previouslyCalculatedRoute) {
threshold += rr.getDistance();
@ -489,16 +485,6 @@ public class BinaryRoutePlanner {
}
double result = distToFinalPoint / ctx.getRouter().getMaxDefaultSpeed();
if(ctx.isUseDynamicRoadPrioritising() && next != null){
double priority = ctx.getRouter().getFutureRoadPriority(next.road);
result /= priority;
int dist = ctx.getDynamicRoadPriorityDistance();
// only first N km-s count by dynamic priority
if(distToFinalPoint > dist && dist != 0){
result = (distToFinalPoint - dist) / ctx.getRouter().getMaxDefaultSpeed() +
dist / (ctx.getRouter().getMaxDefaultSpeed() * priority);
}
}
return (float) result;
}
@ -984,6 +970,30 @@ public class BinaryRoutePlanner {
return String.format("s%.2f e%.2f", ((float)distanceFromStart), ((float)distanceToEnd));
}
public Iterator<RouteSegment> getIterator() {
return new Iterator<BinaryRoutePlanner.RouteSegment>() {
RouteSegment next = RouteSegment.this;
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public RouteSegment next() {
RouteSegment c = next;
if(next != null) {
next = next.next;
}
return c;
}
@Override
public boolean hasNext() {
return next != null;
}
};
}
}
static class FinalRouteSegment extends RouteSegment {

View file

@ -5,12 +5,15 @@ import gnu.trove.map.hash.TLongObjectHashMap;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
import net.osmand.LogUtil;
import net.osmand.binary.BinaryMapRouteReaderAdapter;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.RouteDataObject;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapUtils;
@ -73,9 +76,9 @@ public class BinaryRoutePlannerOld {
int px = MapUtils.get31TileNumberX(lon);
int py = MapUtils.get31TileNumberY(lat);
ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
ctx.loadTileData(px, py, 16, dataObjects);
ctx.loadTileData(px, py, 17, dataObjects);
if (dataObjects.isEmpty()) {
ctx.loadTileData(px, py, 14, dataObjects);
ctx.loadTileData(px, py, 15, dataObjects);
}
RouteSegment road = null;
double sdist = 0;
@ -201,17 +204,31 @@ public class BinaryRoutePlannerOld {
private List<RouteSegmentResult> searchRouteInternalPrepare(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
// Split into 2 methods to let GC work in between
searchRouteInternal(ctx, start, end, leftSideNavigation);
// 4. Route is found : collect all segments and prepare result
return new RouteResultPreparation().prepareResult(ctx, ctx.finalRouteSegment, leftSideNavigation);
if (ctx.nativeLib != null) {
int ex31 = end.getRoad().getPoint31XTile(end.getSegmentStart());
int ey31 = end.getRoad().getPoint31YTile(end.getSegmentStart());
int sx31 = start.getRoad().getPoint31XTile(start.getSegmentStart());
int sy31 = start.getRoad().getPoint31YTile(start.getSegmentStart());
RouteRegion[] regions = ctx.reverseMap.keySet().toArray(new BinaryMapRouteReaderAdapter.RouteRegion[ctx.reverseMap.size()]);
RouteSegmentResult[] res = ctx.nativeLib.runNativeRouting(sx31, sy31, ex31, ey31, ctx.config, regions);
ArrayList<RouteSegmentResult> result = new ArrayList<RouteSegmentResult>(Arrays.asList(res));
return new RouteResultPreparation().prepareResult(ctx, leftSideNavigation, result);
} else {
// Split into 2 methods to let GC work in between
searchRouteInternal(ctx, start, end);
// 4. Route is found : collect all segments and prepare result
return new RouteResultPreparation().prepareResult(ctx, ctx.finalRouteSegment, leftSideNavigation);
}
}
/**
* Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm)
* return list of segments
*/
private void searchRouteInternal(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
private void searchRouteInternal(final RoutingContext ctx, RouteSegment start, RouteSegment end) throws IOException, InterruptedException {
// measure time
ctx.timeToLoad = 0;
ctx.visitedSegments = 0;
@ -250,12 +267,12 @@ public class BinaryRoutePlannerOld {
TLongObjectHashMap<RouteSegment> visitedDirectSegments = new TLongObjectHashMap<RouteSegment>();
TLongObjectHashMap<RouteSegment> visitedOppositeSegments = new TLongObjectHashMap<RouteSegment>();
boolean runRecalculation = ctx.previouslyCalculatedRoute != null && ctx.previouslyCalculatedRoute.size() > 0;
boolean runRecalculation = ctx.previouslyCalculatedRoute != null && ctx.previouslyCalculatedRoute.size() > 0
&& ctx.config.recalculateDistance != 0;
if (runRecalculation) {
RouteSegment previous = null;
List<RouteSegmentResult> rlist = new ArrayList<RouteSegmentResult>();
// always recalculate first 7 km
int distanceThreshold = 7000;
float distanceThreshold = ctx.config.recalculateDistance;
float threshold = 0;
for(RouteSegmentResult rr : ctx.previouslyCalculatedRoute) {
threshold += rr.getDistance();
@ -340,11 +357,6 @@ public class BinaryRoutePlannerOld {
} else {
graphSegments = graphDirectSegments;
}
if(ctx.runRelaxingStrategy() ) {
relaxNotNeededSegments(ctx, graphDirectSegments, true);
relaxNotNeededSegments(ctx, graphReverseSegments, false);
}
// check if interrupted
if(ctx.interruptable != null && ctx.interruptable.isCancelled()) {
throw new InterruptedException("Route calculation interrupted");
@ -356,35 +368,6 @@ public class BinaryRoutePlannerOld {
private void relaxNotNeededSegments(RoutingContext ctx, PriorityQueue<RouteSegment> graphSegments, boolean inverse) {
RouteSegment next = graphSegments.peek();
double mine = next.distanceToEnd;
// int before = graphSegments.size();
// SegmentStat statStart = new SegmentStat("Distance from start (" + inverse + ") ");
// SegmentStat statEnd = new SegmentStat("Distance to end (" + inverse + ") ");
Iterator<RouteSegment> iterator = graphSegments.iterator();
while (iterator.hasNext()) {
RouteSegment s = iterator.next();
// statStart.addNumber((float) s.distanceFromStart);
// statEnd.addNumber((float) s.distanceToEnd);
if (s.distanceToEnd < mine) {
mine = s.distanceToEnd;
}
}
double d = mine * ctx.config.RELAX_NODES_IF_START_DIST_COEF;
iterator = graphSegments.iterator();
while (iterator.hasNext()) {
RouteSegment s = iterator.next();
if (s.distanceToEnd > d) {
ctx.relaxedSegments++;
iterator.remove();
}
}
// int after = graphSegments.size();
// println(statStart.toString());
// println(statEnd.toString());
// println("Relaxing : before " + before + " after " + after + " minend " + ((float) mine));
}
private double h(final RoutingContext ctx, int targetEndX, int targetEndY,
int startX, int startY) {
@ -394,16 +377,6 @@ public class BinaryRoutePlannerOld {
protected static double h(RoutingContext ctx, double distToFinalPoint, RouteSegment next) {
double result = distToFinalPoint / ctx.getRouter().getMaxDefaultSpeed();
if(ctx.isUseDynamicRoadPrioritising() && next != null){
double priority = ctx.getRouter().getFutureRoadPriority(next.road);
result /= priority;
int dist = ctx.getDynamicRoadPriorityDistance();
// only first N km-s count by dynamic priority
if(distToFinalPoint > dist && dist != 0){
result = (distToFinalPoint - dist) / ctx.getRouter().getMaxDefaultSpeed() +
dist / (ctx.getRouter().getMaxDefaultSpeed() * priority);
}
}
return result;
}

View file

@ -4,6 +4,7 @@ import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.osmand.binary.RouteDataObject;
@ -20,9 +21,12 @@ public class RouteResultPreparation {
*/
List<RouteSegmentResult> prepareResult(RoutingContext ctx, FinalRouteSegment finalSegment,boolean leftside) {
List<RouteSegmentResult> result = convertFinalSegmentToResults(ctx, finalSegment);
prepareResult(ctx, leftside, result);
return result;
}
List<RouteSegmentResult> prepareResult(RoutingContext ctx, boolean leftside, List<RouteSegmentResult> result) {
validateAllPointsConnected(result);
// calculate time
calculateTimeSpeedAndAttachRoadSegments(ctx, result);
@ -47,12 +51,12 @@ public class RouteResultPreparation {
double distance = 0;
for (int j = rr.getStartPointIndex(); j != rr.getEndPointIndex(); j = next) {
next = plus ? j + 1 : j - 1;
if(j == rr.getStartPointIndex()) {
attachRoadSegments(ctx, result, i, j, plus);
}
if(next != rr.getEndPointIndex()) {
attachRoadSegments(ctx, result, i, next, plus);
}
if (j == rr.getStartPointIndex()) {
attachRoadSegments(ctx, result, i, j, plus);
}
if (next != rr.getEndPointIndex()) {
attachRoadSegments(ctx, result, i, next, plus);
}
double d = measuredDist(road.getPoint31XTile(j), road.getPoint31YTile(j), road.getPoint31XTile(next),
road.getPoint31YTile(next));
@ -81,6 +85,7 @@ public class RouteResultPreparation {
if (isSplit) {
int endPointIndex = rr.getEndPointIndex();
RouteSegmentResult split = new RouteSegmentResult(rr.getObject(), next, endPointIndex);
split.copyPreattachedRoutes(rr, Math.abs(next - rr.getStartPointIndex()));
rr.setSegmentTime((float) distOnRoadToPass);
rr.setSegmentSpeed((float) speed);
rr.setDistance((float) distance);
@ -496,12 +501,35 @@ public class RouteResultPreparation {
}
}
}
RouteSegment routeSegment = ctx.loadRouteSegment(road.getPoint31XTile(pointInd), road.getPoint31YTile(pointInd), ctx.config.memoryLimitation);
Iterator<RouteSegment> it;
if(rr.getPreAttachedRoutes(pointInd) != null) {
final RouteSegmentResult[] list = rr.getPreAttachedRoutes(pointInd);
it = new Iterator<BinaryRoutePlanner.RouteSegment>() {
int i = 0;
@Override
public boolean hasNext() {
return i < list.length;
}
@Override
public RouteSegment next() {
RouteSegmentResult r = list[i++];
return new RouteSegment(r.getObject(), r.getStartPointIndex());
}
@Override
public void remove() {
}
};
} else {
RouteSegment rt = ctx.loadRouteSegment(road.getPoint31XTile(pointInd), road.getPoint31YTile(pointInd), ctx.config.memoryLimitation);
it = rt.getIterator();
}
// try to attach all segments except with current id
while (routeSegment != null) {
while (it.hasNext()) {
RouteSegment routeSegment = it.next();
if (routeSegment.road.getId() != road.getId() && routeSegment.road.getId() != previousRoadId) {
RouteDataObject addRoad = routeSegment.road;
// TODO restrictions can be considered as well
int oneWay = ctx.getRouter().isOneWay(addRoad);
if (oneWay >= 0 && routeSegment.getSegmentStart() < addRoad.getPointsLength() - 1) {
@ -519,7 +547,6 @@ public class RouteResultPreparation {
}
}
}
routeSegment = routeSegment.next;
}
}

View file

@ -14,6 +14,7 @@ public class RouteSegmentResult {
private int startPointIndex;
private int endPointIndex;
private List<RouteSegmentResult>[] attachedRoutes;
private RouteSegmentResult[][] preAttachedRoutes;
private float segmentTime;
private float speed;
private float distance;
@ -29,6 +30,7 @@ public class RouteSegmentResult {
updateCapacity();
}
@SuppressWarnings("unchecked")
private void updateCapacity() {
int capacity = Math.abs(endPointIndex - startPointIndex) + 1;
@ -43,6 +45,20 @@ public class RouteSegmentResult {
attachedRoutes[st].add(r);
}
public void copyPreattachedRoutes(RouteSegmentResult toCopy, int shift) {
int l = toCopy.preAttachedRoutes.length - shift;
preAttachedRoutes = new RouteSegmentResult[l][];
System.arraycopy(toCopy.preAttachedRoutes, shift, preAttachedRoutes, 0, l);
}
public RouteSegmentResult[] getPreAttachedRoutes(int routeInd) {
int st = Math.abs(routeInd - startPointIndex);
if(st < preAttachedRoutes.length) {
return preAttachedRoutes[st];
}
return null;
}
public List<RouteSegmentResult> getAttachedRoutes(int routeInd) {
int st = Math.abs(routeInd - startPointIndex);
List<RouteSegmentResult> list = attachedRoutes[st];

View file

@ -39,6 +39,9 @@ public class RoutingConfiguration {
// 1.4 Used to calculate route in movement
public Double initialDirection;
// 1.5 Recalculate distance help
public float recalculateDistance = 10000f;
public static class Builder {
@ -67,6 +70,7 @@ public class RoutingConfiguration {
attributes.put("routerName", router);
i.attributes.putAll(attributes);
i.initialDirection = direction;
i.recalculateDistance = parseSilentFloat(getAttribute(i.router, "recalculateDistanceHelp"), i.recalculateDistance) ;
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);
@ -78,7 +82,7 @@ public class RoutingConfiguration {
}
i.memoryLimitation = memoryLimitMB * (1 << 20);
}
i.planRoadDirection = parseSilentInt(getAttribute(router, "planRoadDirection"), i.planRoadDirection);
i.planRoadDirection = parseSilentInt(getAttribute(i.router, "planRoadDirection"), i.planRoadDirection);
return i;

View file

@ -54,7 +54,6 @@ public class RoutingContext {
public final Map<RouteRegion, BinaryMapIndexReader> reverseMap = new LinkedHashMap<RouteRegion, BinaryMapIndexReader>();
// 1. Initial variables
private int relaxingIteration = 0;
public long firstRoadId = 0;
public int firstRoadDirection = 0;
@ -179,42 +178,11 @@ public class RoutingContext {
return global.size;
}
public boolean runRelaxingStrategy(){
if(!isUseRelaxingStrategy()){
return false;
}
relaxingIteration++;
if(relaxingIteration > config.ITERATIONS_TO_RELAX_NODES){
relaxingIteration = 0;
return true;
}
return false;
}
public void setVisitor(RouteSegmentVisitor visitor) {
this.visitor = visitor;
}
public boolean isUseDynamicRoadPrioritising() {
return config.useDynamicRoadPrioritising;
}
public int getDynamicRoadPriorityDistance() {
return config.dynamicRoadPriorityDistance;
}
public boolean isUseRelaxingStrategy() {
return config.useRelaxingStrategy;
}
public void setUseRelaxingStrategy(boolean useRelaxingStrategy) {
config.useRelaxingStrategy = useRelaxingStrategy;
}
public void setUseDynamicRoadPrioritising(boolean useDynamicRoadPrioritising) {
config.useDynamicRoadPrioritising = useDynamicRoadPrioritising;
}
public void setRouter(VehicleRouter router) {
config.router = router;
}
@ -350,7 +318,7 @@ public class RoutingContext {
borderLineCoordinates = new int[borderLines.length];
for(int i=0; i<borderLineCoordinates.length; i++) {
borderLineCoordinates[i] = borderLines[i].borderLine;
// FIXME
// FIXME borders approach
// not less then 14th zoom
if(i > 0 && borderLineCoordinates[i - 1] >> 17 == borderLineCoordinates[i] >> 17) {
throw new IllegalStateException();
@ -517,13 +485,15 @@ public class RoutingContext {
}
public void loadTileData(int x31, int y31, int zoomAround, final List<RouteDataObject> toFillIn) {
int t = zoomAround - config.ZOOM_TO_LOAD_TILES;
int t = config.ZOOM_TO_LOAD_TILES - zoomAround;
int coordinatesShift = (1 << (31 - config.ZOOM_TO_LOAD_TILES));
if(t <= 0) {
t = 1;
coordinatesShift = (1 << (31 - zoomAround));
} else {
t = 1 << t;
}
int coordinatesShift = (1 << (31 - config.ZOOM_TO_LOAD_TILES));
TLongHashSet ts = new TLongHashSet();
long now = System.nanoTime();
for(int i = -t; i <= t; i++) {

View file

@ -12,23 +12,24 @@
(don't specify here ! it is device dependent) -->
<attribute name="memoryLimitInMB" value="155" />
<!-- 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 -->
<attribute name="planRoadDirection" value="0" />
<!-- 1.3 When there is a query to recalculate route, -->
<!-- recalculate smart using old route withot N-meters (0 recalculate fresh, default 10km) -->
<attribute name="recalculateDistanceHelp" value="10000" />
<!-- HELP INFORMATION ABOUT FILE -->
<!-- 1) Highway defines acceptable route for routingProfile, speed in km/h (if it is not specified on level road) -->
<!-- priority is multiplicator for already passed road (consider it is an accelerator of the road) -->
<!-- dynamicPriority is multiplicator for future roads used by heuristic useDynamicRoadPrioritising -->
<!-- <road tag="highway" value="living_street" speed="25" priority="0.5" dynamicPriority="0.5"/> -->
<!-- <road tag="route" value="ferry" speed="15" priority="1.0" dynamicPriority="0.7"/> -->
<!-- <road tag="route" value="ferry" speed="15" priority="1.0" /> -->
<!-- 2) Obstacle defines a point of the road and how it could be passed by vehicle -->
<!-- penalty is measured in time and -1 means it could not be passed! -->
<!-- <obstacle tag="highway" value="traffic_signals" penalty="35"/> -->
<!-- 3) Avoid describes what road should be completely avoided or passed with multiplied (decreased) priority -->
<!-- <avoid tag="access" value="no" decreasedPriority="0.9"/> -->
<!-- obstacle tag="highway" value="traffic_signals" penalty="35", penalty measured in seconds -->
<routingProfile name="car" baseProfile="car" restrictionsAware="true" minDefaultSpeed="45.0" maxDefaultSpeed="130.0"
leftTurn="0" rightTurn="0" roundaboutTurn="0" followSpeedLimitations="true" onewayAware="true">
@ -36,55 +37,55 @@
<attribute name="heuristicCoefficient" value="1.5" />
-->
<road tag="highway" value="motorway" speed="110" priority="1.2" dynamicPriority="1">
<road tag="highway" value="motorway" speed="110" priority="1.2">
<specialization input="avoid_motorway" speed="0"/>
</road>
<road tag="highway" value="motorway_link" speed="80" priority="1.2" dynamicPriority="1">
<road tag="highway" value="motorway_link" speed="80" priority="1.2" >
<specialization input="avoid_motorway" speed="0"/>
</road>
<road tag="highway" value="trunk" speed="100" priority="1.2" dynamicPriority="0.9"/>
<road tag="highway" value="trunk_link" speed="75" priority="1.2" dynamicPriority="0.9"/>
<road tag="highway" value="trunk" speed="100" priority="1.2" />
<road tag="highway" value="trunk_link" speed="75" priority="1.2" />
<!-- generally linking larger towns. -->
<road tag="highway" value="primary" speed="65" priority="1.1" dynamicPriority="0.7"/>
<road tag="highway" value="primary_link" speed="50" priority="1.1" dynamicPriority="0.7"/>
<road tag="highway" value="primary" speed="65" priority="1.05" />
<road tag="highway" value="primary_link" speed="50" priority="1.05" />
<!-- generally linking smaller towns and villages -->
<road tag="highway" value="secondary" speed="60" priority="1.05" dynamicPriority="0.6"/>
<road tag="highway" value="secondary_link" speed="50" priority="1.05" dynamicPriority="0.6"/>
<road tag="highway" value="secondary" speed="60" priority="1" />
<road tag="highway" value="secondary_link" speed="50" priority="1" />
<!-- important urban roads -->
<road tag="highway" value="tertiary" speed="45" priority="1" dynamicPriority="0.5"/>
<road tag="highway" value="tertiary_link" speed="40" priority="1" dynamicPriority="0.5"/>
<road tag="highway" value="tertiary" speed="45" priority="0.95" />
<road tag="highway" value="tertiary_link" speed="40" priority="0.95" />
<!-- lowest form of grid network, usually 90% of urban roads -->
<road tag="highway" value="unclassified" speed="35" priority="0.7" dynamicPriority="0.3">
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
<road tag="highway" value="unclassified" speed="35" priority="0.7" >
<specialization input="short_way" priority="1" speed="45"/>
</road>
<!-- road = no type, no review and may be not accurate -->
<road tag="highway" value="road" speed="35" priority="0.7" dynamicPriority="0.3">
<road tag="highway" value="road" speed="35" priority="0.7" >
<specialization input="short_way" priority="1" speed="45"/>
</road>
<!-- primarily for access to properties, small roads with 1/2 intersections -->
<road tag="highway" value="residential" speed="35" priority="0.7" dynamicPriority="0.3">
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
<road tag="highway" value="residential" speed="35" priority="0.7" >
<specialization input="short_way" priority="1" speed="45"/>
</road>
<!-- parking + private roads -->
<road tag="highway" value="service" speed="30" priority="0.5" dynamicPriority="0.3">
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/>
<road tag="highway" value="service" speed="30" priority="0.5" >
<specialization input="short_way" priority="1" speed="45"/>
</road>
<!-- very bad roads -->
<road tag="highway" value="track" speed="15" priority="0.3" dynamicPriority="0.2">
<specialization input="short_way" priority="0.7" speed="45" dynamicPriority="0.7" />
<road tag="highway" value="track" speed="15" priority="0.3" >
<specialization input="short_way" priority="0.7" speed="45" />
<specialization input="avoid_unpaved" priority="0.1"/>
</road>
<!-- too small for cars usually -->
<road tag="highway" value="living_street" speed="25" priority="0.5" dynamicPriority="0.3">
<specialization input="short_way" priority="1" dynamicPriority="1" speed="35"/>
<road tag="highway" value="living_street" speed="25" priority="0.5" >
<specialization input="short_way" priority="1" speed="35"/>
</road>
<!-- car are able to enter in highway=pedestrian with restrictions -->
<!-- Time actually is uknown. Currently unsupported -->
<road tag="route" value="ferry" speed="15" priority="1.0" dynamicPriority="0.9">
<road tag="route" value="ferry" speed="15" priority="1.0" >
<specialization input="avoid_ferries" speed="0"/>
</road>
@ -121,36 +122,36 @@
leftTurn="0" rightTurn="0" followSpeedLimitations="false" onewayAware="true">
<!-- <attribute name="relaxNodesIfStartDistSmallCoeff" value="2.5"/> -->
<road tag="highway" value="motorway" speed="16" priority="0.4" dynamicPriority="0.9">
<road tag="highway" value="motorway" speed="16" priority="0.4" >
<specialization input="avoid_motorway" speed="0"/>
</road>
<road tag="highway" value="motorway_link" speed="16" priority="0.4" dynamicPriority="0.9">
<road tag="highway" value="motorway_link" speed="16" priority="0.4" >
<specialization input="avoid_motorway" speed="0"/>
</road>
<road tag="highway" value="trunk" speed="16" priority="0.6" dynamicPriority="0.9"/>
<road tag="highway" value="trunk_link" speed="16" priority="0.7" dynamicPriority="0.9"/>
<road tag="highway" value="primary" speed="16" priority="0.8" dynamicPriority="0.9"/>
<road tag="highway" value="primary_link" speed="16" priority="0.8" dynamicPriority="0.9"/>
<road tag="highway" value="secondary" speed="16" priority="1" dynamicPriority="1"/>
<road tag="highway" value="secondary_link" speed="16" priority="1" dynamicPriority="1"/>
<road tag="highway" value="tertiary" speed="16" priority="1" dynamicPriority="1"/>
<road tag="highway" value="tertiary_link" speed="16" priority="1" dynamicPriority="1"/>
<road tag="highway" value="road" speed="16" priority="1" dynamicPriority="1"/>
<road tag="highway" value="residential" speed="16" priority="1.1" dynamicPriority="1"/>
<road tag="highway" value="cycleway" speed="16" priority="1.5" dynamicPriority="1.3"/>
<road tag="highway" value="trunk" speed="16" priority="0.6" />
<road tag="highway" value="trunk_link" speed="16" priority="0.7" />
<road tag="highway" value="primary" speed="16" priority="0.8" />
<road tag="highway" value="primary_link" speed="16" priority="0.8" />
<road tag="highway" value="secondary" speed="16" priority="1" />
<road tag="highway" value="secondary_link" speed="16" priority="1" />
<road tag="highway" value="tertiary" speed="16" priority="1" />
<road tag="highway" value="tertiary_link" speed="16" priority="1" />
<road tag="highway" value="road" speed="16" priority="1" />
<road tag="highway" value="residential" speed="16" priority="1.1" />
<road tag="highway" value="cycleway" speed="16" priority="1.5" />
<road tag="highway" value="unclassified" speed="13" priority="1" dynamicPriority="1"/>
<road tag="highway" value="service" speed="13" priority="1" dynamicPriority="1"/>
<road tag="highway" value="track" speed="12" priority="1.5" dynamicPriority="1.5"/>
<road tag="highway" value="path" speed="12" priority="1.5" dynamicPriority="1.5"/>
<road tag="highway" value="living_street" speed="15" priority="1.1" dynamicPriority="1"/>
<road tag="highway" value="pedestrian" speed="10" priority="0.9" dynamicPriority="1"/>
<road tag="highway" value="footway" speed="8" priority="0.9" dynamicPriority="1"/>
<road tag="highway" value="byway" speed="8" priority="1" dynamicPriority="1"/>
<road tag="highway" value="services" speed="13" priority="1" dynamicPriority="1"/>
<road tag="highway" value="bridleway" speed="8" priority="0.8" dynamicPriority="1"/>
<road tag="highway" value="steps" speed="3" priority="0.5" dynamicPriority="0.9"/>
<road tag="highway" value="unclassified" speed="13" priority="1" />
<road tag="highway" value="service" speed="13" priority="1" />
<road tag="highway" value="track" speed="12" priority="1.5" />
<road tag="highway" value="path" speed="12" priority="1.5" />
<road tag="highway" value="living_street" speed="15" priority="1.1" />
<road tag="highway" value="pedestrian" speed="10" priority="0.9" />
<road tag="highway" value="footway" speed="8" priority="0.9" />
<road tag="highway" value="byway" speed="8" priority="1" />
<road tag="highway" value="services" speed="13" priority="1" />
<road tag="highway" value="bridleway" speed="8" priority="0.8" />
<road tag="highway" value="steps" speed="3" priority="0.5" />
<obstacle tag="highway" value="traffic_signals" penalty="25" routingPenalty="10"/>
<obstacle tag="railway" value="crossing" penalty="15"/>
@ -171,36 +172,36 @@
<attribute name="heuristicCoefficient" value="1.2" />
<road tag="highway" value="motorway" speed="5" priority="0.7" dynamicPriority="0.7">
<road tag="highway" value="motorway" speed="5" priority="0.7" >
<specialization input="avoid_motorway" speed="0"/>
</road>
<road tag="highway" value="motorway_link" speed="5" priority="0.7" dynamicPriority="0.7">
<road tag="highway" value="motorway_link" speed="5" priority="0.7" >
<specialization input="avoid_motorway" speed="0"/>
</road>
<road tag="highway" value="trunk" speed="5" priority="0.7" dynamicPriority="0.7"/>
<road tag="highway" value="trunk_link" speed="5" priority="0.7" dynamicPriority="0.7"/>
<road tag="highway" value="primary" speed="5" priority="0.9" dynamicPriority="0.9"/>
<road tag="highway" value="primary_link" speed="5" priority="0.9" dynamicPriority="0.9"/>
<road tag="highway" value="secondary" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="secondary_link" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="tertiary" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="tertiary_link" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="road" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="residential" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="cycleway" speed="5" priority="1" dynamicPriority="1.1"/>
<road tag="highway" value="trunk" speed="5" priority="0.7" />
<road tag="highway" value="trunk_link" speed="5" priority="0.7" />
<road tag="highway" value="primary" speed="5" priority="0.9" />
<road tag="highway" value="primary_link" speed="5" priority="0.9" />
<road tag="highway" value="secondary" speed="5" priority="1" />
<road tag="highway" value="secondary_link" speed="5" priority="1" />
<road tag="highway" value="tertiary" speed="5" priority="1" />
<road tag="highway" value="tertiary_link" speed="5" priority="1" />
<road tag="highway" value="road" speed="5" priority="1" />
<road tag="highway" value="residential" speed="5" priority="1" />
<road tag="highway" value="cycleway" speed="5" priority="1" />
<road tag="highway" value="unclassified" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="service" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="track" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="path" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="living_street" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="pedestrian" speed="5" priority="1.2" dynamicPriority="1.1"/>
<road tag="highway" value="footway" speed="5" priority="1.2" dynamicPriority="1.1"/>
<road tag="highway" value="byway" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="services" speed="5" priority="1" dynamicPriority="1"/>
<road tag="highway" value="bridleway" speed="5" priority="0.8" dynamicPriority="0.8"/>
<road tag="highway" value="steps" speed="4" priority="1.2" dynamicPriority="1"/>
<road tag="highway" value="unclassified" speed="5" priority="1" />
<road tag="highway" value="service" speed="5" priority="1" />
<road tag="highway" value="track" speed="5" priority="1" />
<road tag="highway" value="path" speed="5" priority="1" />
<road tag="highway" value="living_street" speed="5" priority="1" />
<road tag="highway" value="pedestrian" speed="5" priority="1.2" />
<road tag="highway" value="footway" speed="5" priority="1.2" />
<road tag="highway" value="byway" speed="5" priority="1" />
<road tag="highway" value="services" speed="5" priority="1" />
<road tag="highway" value="bridleway" speed="5" priority="0.8" />
<road tag="highway" value="steps" speed="4" priority="1.2" />
<obstacle tag="highway" value="traffic_signals" penalty="30"/>
<obstacle tag="railway" value="crossing" penalty="15"/>

View file

@ -716,14 +716,11 @@ public class MapRouterLayer implements MapPanelLayer {
});
int ex31 = e.getRoad().getPoint31XTile(e.getSegmentStart());
int ey31 = e.getRoad().getPoint31YTile(e.getSegmentStart());
int sx31 = st.getRoad().getPoint31XTile(st.getSegmentStart());
int sy31 = st.getRoad().getPoint31YTile(st.getSegmentStart());
// FIXME
RouteSegmentResult[] searchRoute = ctx.nativeLib.runNativeRouting(sx31, sy31, ex31, ey31, ctx.config);
// /*List<RouteSegmentResult> searchRoute = */router.searchRoute(ctx, st, e, inters, false);
// this.previousRoute = searchRoute;
// Choose native or not native
long nt = System.nanoTime();
List<RouteSegmentResult> searchRoute = router.searchRoute(ctx, st, e, inters, false);
System.out.println("External native time " + (System.nanoTime() - nt) / 1e9f);
if (animateRoutingCalculation) {
playPauseButton.setVisible(false);
nextTurn.setText("FINISH");
@ -742,7 +739,6 @@ public class MapRouterLayer implements MapPanelLayer {
// String name = String.format("beg %.2f end %.2f ", s.getBearingBegin(), s.getBearingEnd());
way.putTag(OSMTagKey.NAME.getValue(),name);
boolean plus = s.getStartPointIndex() < s.getEndPointIndex();
System.out.println("Segment " + s.getObject().id + " "+s.getStartPointIndex() + " -> " + s.getEndPointIndex());
int i = s.getStartPointIndex();
while (true) {
LatLon l = s.getPoint(i);

View file

@ -10,8 +10,6 @@
#include <map>
#include <string>
#include <stdint.h>
#include "mapObjects.h"
#include "multipolygons.h"
#include "common.h"
@ -108,6 +106,61 @@ struct RouteDataObject {
UNORDERED(map)<int, std::string > names;
vector<pair<uint32_t, uint32_t> > namesIds;
string getName() {
if(names.size() > 0) {
return names.begin()->second;
}
return "";
}
int getSize() {
int s = sizeof(this);
s += pointsX.capacity()*sizeof(uint32_t);
s += pointsY.capacity()*sizeof(uint32_t);
s += types.capacity()*sizeof(uint32_t);
s += restrictions.capacity()*sizeof(uint64_t);
std::vector<std::vector<uint32_t> >::iterator t = pointTypes.begin();
for(;t!=pointTypes.end(); t++) {
s+= (*t).capacity() * sizeof(uint32_t);
}
s += namesIds.capacity()*sizeof(pair<uint32_t, uint32_t>);
s += names.size()*sizeof(pair<int, string>)*10;
return s;
}
double directionRoute(int startPoint, bool plus){
// look at comment JAVA
return directionRoute(startPoint, plus, 5);
}
// Gives route direction of EAST degrees from NORTH ]-PI, PI]
double directionRoute(int startPoint, bool plus, float dist) {
int x = pointsX[startPoint];
int y = pointsY[startPoint];
int nx = startPoint;
int px = x;
int py = y;
double total = 0;
do {
if (plus) {
nx++;
if (nx >= pointsX.size()) {
break;
}
} else {
nx--;
if (nx < 0) {
break;
}
}
px = pointsX[nx];
py = pointsY[nx];
// translate into meters
total += abs(px - x) * 0.011 + abs(py - y) * 0.01863;
} while (total < dist);
return -atan2( (float)x - px, (float) y - py ) + M_PI/2;
}
};

View file

@ -7,7 +7,6 @@
static bool PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true;
static const int REVERSE_WAY_RESTRICTION_ONLY = 1024;
static const int STANDARD_ROAD_IN_QUEUE_OVERHEAD = 900;
static const int ROUTE_POINTS = 11;
static const float TURN_DEGREE_MIN = 45;
@ -18,6 +17,7 @@ static const short RESTRICTION_NO_STRAIGHT_ON = 4;
static const short RESTRICTION_ONLY_RIGHT_TURN = 5;
static const short RESTRICTION_ONLY_LEFT_TURN = 6;
static const short RESTRICTION_ONLY_STRAIGHT_ON = 7;
static const bool TRACE_ROUTING = false;
inline int roadPriorityComparator(float o1DistanceFromStart, float o1DistanceToEnd,
float o2DistanceFromStart, float o2DistanceToEnd, float heuristicCoefficient) {
@ -66,8 +66,9 @@ struct SegmentsComparator : public std::binary_function<SHARED_PTR<RouteSegment>
}
bool operator()(const SHARED_PTR<RouteSegment> lhs, const SHARED_PTR<RouteSegment> rhs) const
{
return roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart,
rhs.get()->distanceToEnd, ctx->getHeuristicCoefficient()) > 0;
int cmp = roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart,
rhs.get()->distanceToEnd, ctx->getHeuristicCoefficient());
return cmp > 0;
}
};
struct NonHeuristicSegmentsComparator : public std::binary_function<SHARED_PTR<RouteSegment>, SHARED_PTR<RouteSegment>, bool>
@ -89,26 +90,36 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
SHARED_PTR<RouteSegment> segment, int segmentEnd, SHARED_PTR<RouteSegment> inputNext,
bool reverseWay);
int calculateSizeOfSearchMaps(SEGMENTS_QUEUE graphDirectSegments,
SEGMENTS_QUEUE graphReverseSegments, VISITED_MAP visitedDirectSegments,
VISITED_MAP visitedOppositeSegments){
int sz = visitedDirectSegments.size()*sizeof(pair<int64_t, SHARED_PTR<RouteSegment> > );
sz += visitedOppositeSegments.size()*sizeof(pair<int64_t, SHARED_PTR<RouteSegment> >);
sz += graphDirectSegments.size()*sizeof(SHARED_PTR<RouteSegment>);
sz += graphReverseSegments.size()*sizeof(SHARED_PTR<RouteSegment>);
return sz;
}
/**
* Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm)
* return list of segments
*/
void searchRouteInternal(RoutingContext* ctx, SHARED_PTR<RouteSegment> start, SHARED_PTR<RouteSegment> end, bool leftSideNavigation) {
// FIXME intermediate points
// measure time
ctx->visitedSegments = 0;
ctx->timeToCalculate.start();
// FIXME initial direction
// if(ctx.config.initialDirection != null) {
// ctx.firstRoadId = (start->road->id << ROUTE_POINTS) + start.getSegmentStart();
// double plusDir = start->road->directionRoute(start.segmentStart, true);
// double diff = plusDir - ctx.config.initialDirection;
// if(Math.abs(MapUtils.alignAngleDifference(diff)) <= Math.PI / 3) {
// ctx.firstRoadDirection = 1;
// } else if(Math.abs(MapUtils.alignAngleDifference(diff - Math.PI)) <= Math.PI / 3) {
// ctx.firstRoadDirection = -1;
// }
//
// }
if(ctx->config.initialDirection != -360) {
ctx->firstRoadId = (start->road->id << ROUTE_POINTS) + start->getSegmentStart();
double plusDir = start->road->directionRoute(start->getSegmentStart(), true);
double diff = plusDir - ctx->config.initialDirection;
if(abs(alignAngleDifference(diff)) <= M_PI / 3) {
ctx->firstRoadDirection = 1;
} else if(abs(alignAngleDifference(diff - M_PI )) <= M_PI / 3) {
ctx->firstRoadDirection = -1;
}
}
SegmentsComparator sgmCmp(ctx);
SEGMENTS_QUEUE graphDirectSegments(sgmCmp);
@ -189,7 +200,14 @@ void searchRouteInternal(RoutingContext* ctx, SHARED_PTR<RouteSegment> start, SH
osmand_log_print(LOG_WARN, "[Native] Result visited (visited roads %d, visited segments %d / %d , queue sizes %d / %d ) ",
ctx-> visitedSegments, visitedDirectSegments.size(), visitedOppositeSegments.size(),
graphDirectSegments.size(),graphReverseSegments.size());
osmand_log_print(LOG_WARN, "[Native] Result timing (time to load %d, time to calc %d, loaded tiles %d) ", ctx->timeToLoad.getElapsedTime()
, ctx->timeToCalculate.getElapsedTime(), ctx->loadedTiles);
int sz = calculateSizeOfSearchMaps(graphDirectSegments, graphReverseSegments, visitedDirectSegments, visitedOppositeSegments);
osmand_log_print(LOG_WARN, "[Native] Memory occupied (Routing context %d Kb, search %d Kb)", ctx->getSize()/ 1024, sz/1024);
}
bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch,
SEGMENTS_QUEUE& graphSegments, VISITED_MAP& visitedSegments, int targetEndX, int targetEndY,
SHARED_PTR<RouteSegment> segment, VISITED_MAP& oppositeSegments) {
@ -206,6 +224,10 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch,
if(visitedSegments.find(nt) != visitedSegments.end()) {
return false;
}
if(TRACE_ROUTING) {
osmand_log_print(LOG_DEBUG, "Process segment id=%lld name=%s dist=%f", road->id, road->getName().c_str(), segment->distanceFromStart);
}
ctx->visitedSegments++;
// avoid empty segments to connect but mark the point as visited
visitedSegments[nt] = SHARED_PTR<RouteSegment>();
@ -303,7 +325,6 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch,
// throw new OutOfMemoryError("There is no enough memory " + ctx.config.memoryLimitation/(1<<20) + " Mb");
// }
SHARED_PTR<RouteSegment> next = ctx->loadRouteSegment(x, y);
// 3. get intersected ways
if (next.get() != NULL) {
if((next.get() == segment.get() || next->road->id == road->id) && next->next.get() == NULL) {
@ -447,6 +468,7 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
return true;
}
}
// road.id could be equal on roundabout, but we should accept them
bool alreadyVisited = visitedSegments.find(nts) != visitedSegments.end();
if (!alreadyVisited) {
@ -463,6 +485,9 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
// put additional information to recover whole route after
next->parentRoute = segment;
next->parentSegmentEnd = segmentEnd;
if(TRACE_ROUTING) {
osmand_log_print(LOG_DEBUG, ">> next segment id=%lld name=%s dist=%f", next->road->id, next->road->getName().c_str(), next->distanceFromStart);
}
graphSegments.push(next);
}
} else {
@ -490,9 +515,9 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
SHARED_PTR<RouteSegment> findRouteSegment(int px, int py, RoutingContext* ctx) {
vector<SHARED_PTR<RouteDataObject> > dataObjects;
ctx->loadTileData(px, py, 16, dataObjects);
ctx->loadTileData(px, py, 17, dataObjects);
if (dataObjects.size() == 0) {
ctx->loadTileData(px, py, 14, dataObjects);
ctx->loadTileData(px, py, 15, dataObjects);
}
SHARED_PTR<RouteSegment> road;
double sdist = 0;
@ -566,6 +591,26 @@ void addRouteSegmentToResult(vector<RouteSegmentResult>& result, RouteSegmentRes
}
}
void attachConnectedRoads(RoutingContext* ctx, vector<RouteSegmentResult>& res ) {
vector<RouteSegmentResult>::iterator it = res.begin();
for(; it != res.end(); it++){
bool plus = it->startPointIndex < it->endPointIndex;
int j = it->startPointIndex;
do {
SHARED_PTR<RouteSegment> s = ctx->loadRouteSegment(it->object->pointsX[j], it->object->pointsY[j]);
vector<RouteSegmentResult> r;
while(s.get() != NULL) {
RouteSegmentResult res(s->road, s->getSegmentStart(), s->getSegmentStart());
r.push_back(res);
s = s->next;
}
it->attachedRoutes.push_back(r);
j = plus ? j + 1 : j - 1;
} while(j != it->endPointIndex);
}
}
vector<RouteSegmentResult> convertFinalSegmentToResults(RoutingContext* ctx) {
vector<RouteSegmentResult> result;
if (ctx->finalRouteSegment.get() != NULL) {
@ -620,9 +665,9 @@ vector<RouteSegmentResult> searchRouteInternal(RoutingContext* ctx, bool leftSid
osmand_log_print(LOG_WARN, "End point was found %lld [Native]", end->road->id);
}
searchRouteInternal(ctx, start, end, leftSideNavigation);
osmand_log_print(LOG_WARN, "[Native] Result timing (time to load %d, time to calc %d, loaded tiles %d) ", ctx->timeToLoad.getElapsedTime()
, ctx->timeToCalculate.getElapsedTime(), ctx->loadedTiles);
return convertFinalSegmentToResults(ctx);
vector<RouteSegmentResult> res = convertFinalSegmentToResults(ctx);
attachConnectedRoads(ctx, res);
return res;
}

View file

@ -42,6 +42,7 @@ struct RouteSegmentResult {
SHARED_PTR<RouteDataObject> object;
int startPointIndex;
int endPointIndex;
vector<vector<RouteSegmentResult> > attachedRoutes;
RouteSegmentResult(SHARED_PTR<RouteDataObject> object, int startPointIndex, int endPointIndex) :
object(object), startPointIndex(startPointIndex), endPointIndex (endPointIndex) {
@ -62,10 +63,11 @@ struct RoutingSubregionTile {
// make it without get/set for fast access
int access;
int loaded;
int size ;
UNORDERED(map)<int64_t, SHARED_PTR<RouteSegment> > routes;
RoutingSubregionTile(RouteSubregion& sub) : access(0), loaded(0), subregion(sub) {
size = sizeof(RoutingSubregionTile);
}
~RoutingSubregionTile(){
}
@ -77,7 +79,12 @@ struct RoutingSubregionTile {
loaded++;
}
int getSize(){
return size + routes.size() * sizeof(std::pair<int64_t, SHARED_PTR<RouteSegment> >);
}
void add(SHARED_PTR<RouteDataObject> o) {
size += o->getSize() + sizeof(RouteSegment)* o->pointsX.size();
for (int i = 0; i < o->pointsX.size(); i++) {
uint64_t x31 = o->pointsX[i];
uint64_t y31 = o->pointsY[i];
@ -98,7 +105,7 @@ struct RoutingSubregionTile {
}
};
static int64_t calcRouteId(SHARED_PTR<RouteDataObject> o, int ind) {
return (o->id << 10) + ind;
return ((int64_t) o->id << 10) + ind;
}
typedef std::pair<int, std::pair<string, string> > ROUTE_TRIPLE;
@ -127,6 +134,7 @@ struct RoutingConfiguration {
int planRoadDirection;
string routerName;
float initialDirection;
float distanceRecalculate;
string routerProfile;
float roundaboutTurn;
float leftTurn;
@ -166,9 +174,10 @@ struct RoutingConfiguration {
zoomToLoad = (int)parseFloat("zoomToLoadTiles", 16);
routerName = parseString("name", "default");
routerProfile = parseString("baseProfile", "car");
distanceRecalculate = parseFloat("recalculateDistanceHelp", 10000) ;
}
RoutingConfiguration(vector<ROUTE_TRIPLE>& config, int memLimit = 30, float initDirection = 0) :
RoutingConfiguration(vector<ROUTE_TRIPLE>& config, float initDirection = -360, int memLimit = 30) :
memoryLimitation(memLimit), initialDirection(initDirection) {
for(int j = 0; j<config.size(); j++) {
ROUTE_TRIPLE r = config[j];
@ -341,6 +350,8 @@ struct RoutingConfiguration {
struct RoutingContext {
typedef UNORDERED(map)<int64_t, SHARED_PTR<RoutingSubregionTile> > MAP_SUBREGION_TILES;
int visitedSegments;
int loadedTiles;
ElapsedTimer timeToLoad;
@ -358,7 +369,7 @@ struct RoutingContext {
vector<SHARED_PTR<RouteSegment> > segmentsToVisitPrescripted;
SHARED_PTR<FinalRouteSegment> finalRouteSegment;
UNORDERED(map)<int64_t, SHARED_PTR<RoutingSubregionTile> > subregionTiles;
MAP_SUBREGION_TILES subregionTiles;
UNORDERED(map)<int64_t, std::vector<SHARED_PTR<RoutingSubregionTile> > > indexedSubregions;
RoutingContext(RoutingConfiguration& config) : finalRouteSegment(), firstRoadDirection(0), loadedTiles(0), visitedSegments(0),
@ -369,6 +380,16 @@ struct RoutingContext {
return config.acceptLine(r);
}
int getSize() {
// multiply 2 for to maps
int sz = subregionTiles.size() * sizeof(pair< int64_t, SHARED_PTR<RoutingSubregionTile> >) * 2;
MAP_SUBREGION_TILES::iterator it = subregionTiles.begin();
for(;it != subregionTiles.end(); it++) {
sz += it->second->getSize();
}
return sz;
}
void loadHeaderObjects(int64_t tileId) {
vector<SHARED_PTR<RoutingSubregionTile> > subregions = indexedSubregions[tileId];
for(int j = 0; j<subregions.size(); j++) {
@ -404,27 +425,27 @@ struct RoutingContext {
std::vector<SHARED_PTR<RoutingSubregionTile> > collection;
for(int i=0; i<tempResult.size(); i++) {
RouteSubregion& rs = tempResult[i];
int64_t key = ((int64_t)rs.left << 31)+ rs.length;
int64_t key = ((int64_t)rs.left << 31)+ rs.filePointer;
if(subregionTiles.find(key) == subregionTiles.end()) {
subregionTiles[key] = SHARED_PTR<RoutingSubregionTile>(new RoutingSubregionTile(rs));
}
collection.push_back(subregionTiles[key]);
}
//osmand_log_print(LOG_INFO, "Native load %d %d (%d)", xloc, yloc, tempResult.size());
indexedSubregions[tileId] = collection;
}
loadHeaderObjects(tileId);
timeToLoad.pause();
}
void loadTileData(int x31, int y31, int zoomAround, vector<SHARED_PTR<RouteDataObject> >& dataObjects ){
int t = zoomAround - config.zoomToLoad;
void loadTileData(int x31, int y31, int zoomAround, vector<SHARED_PTR<RouteDataObject> >& dataObjects ) {
int t = config.zoomToLoad - zoomAround;
int coordinatesShift = (1 << (31 - config.zoomToLoad));
if(t <= 0) {
t = 1;
coordinatesShift = (1 << (31 - zoomAround));
} else {
t = 1 << t;
}
int coordinatesShift = (1 << (31 - config.zoomToLoad));
UNORDERED(set)<int64_t> ids;
int z = config.zoomToLoad;
for(int i = -t; i <= t; i++) {

View file

@ -300,3 +300,14 @@ double getDistance(double lat1, double lon1, double lat2, double lon2) {
double c = 2 * atan2(sqrt(a), sqrt(1 - a));
return R * c * 1000;
}
double alignAngleDifference(double diff) {
while (diff > M_PI) {
diff -= 2 * M_PI;
}
while (diff <= -M_PI) {
diff += 2 * M_PI;
}
return diff;
}

View file

@ -322,6 +322,7 @@ double calculateProjection31TileMetric(int xA, int yA, int xB, int yB, int xC, i
double squareDist31TileMetric(int x1, int y1, int x2, int y2) ;
double convert31YToMeters(int y1, int y2);
double convert31XToMeters(int y1, int y2);
double alignAngleDifference(double diff);
#endif /*_OSMAND_COMMON_H*/

View file

@ -410,17 +410,25 @@ jfieldID jfield_RouteSubregion_top = NULL;
jfieldID jfield_RouteSubregion_bottom = NULL;
jfieldID jfield_RouteSubregion_shiftToData = NULL;
jclass jclass_RouteRegion = NULL;
jfieldID jfield_RouteRegion_length = NULL;
jfieldID jfield_RouteRegion_filePointer= NULL;
jclass jclass_RouteSegmentResult = NULL;
jclass jclass_RouteSegmentResultAr = NULL;
jmethodID jmethod_RouteSegmentResult_ctor = NULL;
jfieldID jfield_RouteSegmentResult_preAttachedRoutes = NULL;
void loadJniRenderingContext(JNIEnv* env)
{
jclass_RouteSegmentResult = findClass(env, "net/osmand/router/RouteSegmentResult");
jclass_RouteSegmentResultAr = findClass(env, "[Lnet/osmand/router/RouteSegmentResult;");
jmethod_RouteSegmentResult_ctor = env->GetMethodID(jclass_RouteSegmentResult,
"<init>", "(Lnet/osmand/binary/RouteDataObject;II)V");
jfield_RouteSegmentResult_preAttachedRoutes = getFid(env, jclass_RouteSegmentResult, "preAttachedRoutes",
"[[Lnet/osmand/router/RouteSegmentResult;");
jclass_RenderingContext = findClass(env, "net/osmand/RenderingContext");
jfield_RenderingContext_interrupted = getFid(env, jclass_RenderingContext, "interrupted", "Z");
@ -467,6 +475,10 @@ void loadJniRenderingContext(JNIEnv* env)
jmethod_RouteDataObject_init = env->GetMethodID(jclass_RouteDataObject, "<init>", "(Lnet/osmand/binary/BinaryMapRouteReaderAdapter$RouteRegion;[I[Ljava/lang/String;)V");
jclass_RouteRegion = findClass(env, "net/osmand/binary/BinaryMapRouteReaderAdapter$RouteRegion");
jfield_RouteRegion_length= getFid(env, jclass_RouteRegion, "length", "I" );
jfield_RouteRegion_filePointer= getFid(env, jclass_RouteRegion, "filePointer", "I" );
jclass_RouteSubregion = findClass(env, "net/osmand/binary/BinaryMapRouteReaderAdapter$RouteSubregion");
jfield_RouteSubregion_length= getFid(env, jclass_RouteSubregion, "length", "I" );
jfield_RouteSubregion_filePointer= getFid(env, jclass_RouteSubregion, "filePointer", "I" );
@ -563,6 +575,38 @@ jobject convertRouteDataObjectToJava(JNIEnv* ienv, RouteDataObject* route, jobje
return robj;
}
jobject convertRouteSegmentResultToJava(JNIEnv* ienv, RouteSegmentResult& r, UNORDERED(map)<int64_t, int>& indexes,
jobjectArray regions) {
RouteDataObject* rdo = r.object.get();
jobject reg = NULL;
int64_t fp = rdo->region->filePointer;
int64_t ln = rdo->region->length;
if(indexes.find((fp <<31) + ln) != indexes.end()) {
reg = ienv->GetObjectArrayElement(regions, indexes[(fp <<31) + ln]);
}
jobjectArray ar = ienv->NewObjectArray(r.attachedRoutes.size(), jclass_RouteSegmentResultAr, NULL);
for(jsize k = 0; k < r.attachedRoutes.size(); k++) {
jobjectArray art = ienv->NewObjectArray(r.attachedRoutes[k].size(), jclass_RouteSegmentResult, NULL);
for(jsize kj = 0; kj < r.attachedRoutes[k].size(); kj++) {
jobject jo = convertRouteSegmentResultToJava(ienv, r.attachedRoutes[k][kj], indexes, regions);
ienv->SetObjectArrayElement(art, kj, jo);
ienv->DeleteLocalRef(jo);
}
ienv->SetObjectArrayElement(ar, k, art);
ienv->DeleteLocalRef(art);
}
jobject robj = convertRouteDataObjectToJava(ienv, rdo, reg);
jobject resobj = ienv->NewObject(jclass_RouteSegmentResult, jmethod_RouteSegmentResult_ctor, robj,
r.startPointIndex, r.endPointIndex);
ienv->SetObjectField(resobj, jfield_RouteSegmentResult_preAttachedRoutes, ar);
if(reg != NULL) {
ienv->DeleteLocalRef(reg);
}
ienv->DeleteLocalRef(robj);
ienv->DeleteLocalRef(ar);
return resobj;
}
class NativeRoutingTile {
public:
std::vector<RouteDataObject*> result;
@ -583,20 +627,25 @@ extern "C" JNIEXPORT void JNICALL Java_net_osmand_NativeLibrary_deleteRouteSearc
//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) {
jintArray stateConfig, jobjectArray keyConfig, jobjectArray valueConfig, jfloat initDirection,
jobjectArray regions) {
vector<ROUTE_TRIPLE> cfg;
int* data = ienv->GetIntArrayElements(stateConfig, NULL);
for(int k = 0; k < ienv->GetArrayLength(stateConfig); k++) {
jstring kl = (jstring)ienv->GetObjectArrayElement(keyConfig, k);
jstring vl = (jstring)ienv->GetObjectArrayElement(valueConfig, k);
ROUTE_TRIPLE t = ROUTE_TRIPLE (data[k], std::pair<string, string>(
getString(ienv, (jstring) ienv->GetObjectArrayElement(keyConfig, k)),
getString(ienv, (jstring) ienv->GetObjectArrayElement(valueConfig, k)))
getString(ienv, kl),
getString(ienv, vl))
);
ienv->DeleteLocalRef(kl);
ienv->DeleteLocalRef(vl);
cfg.push_back(t);
}
ienv->ReleaseIntArrayElements(stateConfig, data, 0);
RoutingConfiguration config(cfg);
RoutingConfiguration config(cfg, initDirection);
RoutingContext c(config);
data = ienv->GetIntArrayElements(coordinates, NULL);
c.startX = data[0];
@ -606,16 +655,21 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_net_osmand_NativeLibrary_nativeRo
ienv->ReleaseIntArrayElements(coordinates, data, 0);
vector<RouteSegmentResult> r = searchRouteInternal(&c, false);
UNORDERED(map)<int64_t, int> indexes;
for (int t = 0; t< ienv->GetArrayLength(regions); t++) {
jobject oreg = ienv->GetObjectArrayElement(regions, t);
int64_t fp = ienv->GetIntField(oreg, jfield_RouteRegion_filePointer);
int64_t ln = ienv->GetIntField(oreg, jfield_RouteRegion_length);
ienv->DeleteLocalRef(oreg);
indexes[(fp <<31) + ln] = t;
}
// 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);
jobject resobj = ienv->NewObject(jclass_RouteSegmentResult, jmethod_RouteSegmentResult_ctor, robj,
r[i].startPointIndex, r[i].endPointIndex);
jobject resobj = convertRouteSegmentResultToJava(ienv, r[i], indexes, regions);
ienv->SetObjectArrayElement(res, i, resobj);
ienv->DeleteLocalRef(robj);
ienv->DeleteLocalRef(resobj);
}
if (r.size() == 0) {
osmand_log_print(LOG_INFO, "No route found");