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); 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(); TIntArrayList state = new TIntArrayList();
List<String> keys = new ArrayList<String>(); List<String> keys = new ArrayList<String>();
List<String> values = new ArrayList<String>(); List<String> values = new ArrayList<String>();
@ -124,7 +125,8 @@ public class NativeLibrary {
fillObjects(state, keys, values, 5, attrs); fillObjects(state, keys, values, 5, attrs);
return nativeRouting(new int[]{sx31, sy31, ex31, ey31}, state.toArray(), keys.toArray(new String[keys.size()]), 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) { 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 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); protected static native void deleteSearchResult(long searchResultHandle);

View file

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

View file

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

View file

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

View file

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

View file

@ -5,12 +5,15 @@ import gnu.trove.map.hash.TLongObjectHashMap;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.PriorityQueue; import java.util.PriorityQueue;
import net.osmand.LogUtil; import net.osmand.LogUtil;
import net.osmand.binary.BinaryMapRouteReaderAdapter;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.RouteDataObject; import net.osmand.binary.RouteDataObject;
import net.osmand.osm.MapRenderingTypes; import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapUtils; import net.osmand.osm.MapUtils;
@ -73,9 +76,9 @@ public class BinaryRoutePlannerOld {
int px = MapUtils.get31TileNumberX(lon); int px = MapUtils.get31TileNumberX(lon);
int py = MapUtils.get31TileNumberY(lat); int py = MapUtils.get31TileNumberY(lat);
ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>(); ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
ctx.loadTileData(px, py, 16, dataObjects); ctx.loadTileData(px, py, 17, dataObjects);
if (dataObjects.isEmpty()) { if (dataObjects.isEmpty()) {
ctx.loadTileData(px, py, 14, dataObjects); ctx.loadTileData(px, py, 15, dataObjects);
} }
RouteSegment road = null; RouteSegment road = null;
double sdist = 0; 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 { 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 if (ctx.nativeLib != null) {
searchRouteInternal(ctx, start, end, leftSideNavigation); int ex31 = end.getRoad().getPoint31XTile(end.getSegmentStart());
// 4. Route is found : collect all segments and prepare result int ey31 = end.getRoad().getPoint31YTile(end.getSegmentStart());
return new RouteResultPreparation().prepareResult(ctx, ctx.finalRouteSegment, leftSideNavigation); 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) * Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm)
* return list of segments * 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 // measure time
ctx.timeToLoad = 0; ctx.timeToLoad = 0;
ctx.visitedSegments = 0; ctx.visitedSegments = 0;
@ -250,12 +267,12 @@ public class BinaryRoutePlannerOld {
TLongObjectHashMap<RouteSegment> visitedDirectSegments = new TLongObjectHashMap<RouteSegment>(); TLongObjectHashMap<RouteSegment> visitedDirectSegments = new TLongObjectHashMap<RouteSegment>();
TLongObjectHashMap<RouteSegment> visitedOppositeSegments = 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) { if (runRecalculation) {
RouteSegment previous = null; RouteSegment previous = null;
List<RouteSegmentResult> rlist = new ArrayList<RouteSegmentResult>(); List<RouteSegmentResult> rlist = new ArrayList<RouteSegmentResult>();
// always recalculate first 7 km float distanceThreshold = ctx.config.recalculateDistance;
int distanceThreshold = 7000;
float threshold = 0; float threshold = 0;
for(RouteSegmentResult rr : ctx.previouslyCalculatedRoute) { for(RouteSegmentResult rr : ctx.previouslyCalculatedRoute) {
threshold += rr.getDistance(); threshold += rr.getDistance();
@ -340,11 +357,6 @@ public class BinaryRoutePlannerOld {
} else { } else {
graphSegments = graphDirectSegments; graphSegments = graphDirectSegments;
} }
if(ctx.runRelaxingStrategy() ) {
relaxNotNeededSegments(ctx, graphDirectSegments, true);
relaxNotNeededSegments(ctx, graphReverseSegments, false);
}
// check if interrupted // check if interrupted
if(ctx.interruptable != null && ctx.interruptable.isCancelled()) { if(ctx.interruptable != null && ctx.interruptable.isCancelled()) {
throw new InterruptedException("Route calculation interrupted"); 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, private double h(final RoutingContext ctx, int targetEndX, int targetEndY,
int startX, int startY) { int startX, int startY) {
@ -394,16 +377,6 @@ public class BinaryRoutePlannerOld {
protected static double h(RoutingContext ctx, double distToFinalPoint, RouteSegment next) { protected static double h(RoutingContext ctx, double distToFinalPoint, RouteSegment next) {
double result = distToFinalPoint / ctx.getRouter().getMaxDefaultSpeed(); 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; return result;
} }

View file

@ -4,6 +4,7 @@ import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.List; import java.util.List;
import net.osmand.binary.RouteDataObject; import net.osmand.binary.RouteDataObject;
@ -20,9 +21,12 @@ public class RouteResultPreparation {
*/ */
List<RouteSegmentResult> prepareResult(RoutingContext ctx, FinalRouteSegment finalSegment,boolean leftside) { List<RouteSegmentResult> prepareResult(RoutingContext ctx, FinalRouteSegment finalSegment,boolean leftside) {
List<RouteSegmentResult> result = convertFinalSegmentToResults(ctx, finalSegment); List<RouteSegmentResult> result = convertFinalSegmentToResults(ctx, finalSegment);
prepareResult(ctx, leftside, result);
return result;
}
List<RouteSegmentResult> prepareResult(RoutingContext ctx, boolean leftside, List<RouteSegmentResult> result) {
validateAllPointsConnected(result); validateAllPointsConnected(result);
// calculate time // calculate time
calculateTimeSpeedAndAttachRoadSegments(ctx, result); calculateTimeSpeedAndAttachRoadSegments(ctx, result);
@ -47,12 +51,12 @@ public class RouteResultPreparation {
double distance = 0; double distance = 0;
for (int j = rr.getStartPointIndex(); j != rr.getEndPointIndex(); j = next) { for (int j = rr.getStartPointIndex(); j != rr.getEndPointIndex(); j = next) {
next = plus ? j + 1 : j - 1; next = plus ? j + 1 : j - 1;
if(j == rr.getStartPointIndex()) { if (j == rr.getStartPointIndex()) {
attachRoadSegments(ctx, result, i, j, plus); attachRoadSegments(ctx, result, i, j, plus);
} }
if(next != rr.getEndPointIndex()) { if (next != rr.getEndPointIndex()) {
attachRoadSegments(ctx, result, i, next, plus); attachRoadSegments(ctx, result, i, next, plus);
} }
double d = measuredDist(road.getPoint31XTile(j), road.getPoint31YTile(j), road.getPoint31XTile(next), double d = measuredDist(road.getPoint31XTile(j), road.getPoint31YTile(j), road.getPoint31XTile(next),
road.getPoint31YTile(next)); road.getPoint31YTile(next));
@ -81,6 +85,7 @@ public class RouteResultPreparation {
if (isSplit) { if (isSplit) {
int endPointIndex = rr.getEndPointIndex(); int endPointIndex = rr.getEndPointIndex();
RouteSegmentResult split = new RouteSegmentResult(rr.getObject(), next, endPointIndex); RouteSegmentResult split = new RouteSegmentResult(rr.getObject(), next, endPointIndex);
split.copyPreattachedRoutes(rr, Math.abs(next - rr.getStartPointIndex()));
rr.setSegmentTime((float) distOnRoadToPass); rr.setSegmentTime((float) distOnRoadToPass);
rr.setSegmentSpeed((float) speed); rr.setSegmentSpeed((float) speed);
rr.setDistance((float) distance); 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 // 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) { if (routeSegment.road.getId() != road.getId() && routeSegment.road.getId() != previousRoadId) {
RouteDataObject addRoad = routeSegment.road; RouteDataObject addRoad = routeSegment.road;
// TODO restrictions can be considered as well // TODO restrictions can be considered as well
int oneWay = ctx.getRouter().isOneWay(addRoad); int oneWay = ctx.getRouter().isOneWay(addRoad);
if (oneWay >= 0 && routeSegment.getSegmentStart() < addRoad.getPointsLength() - 1) { 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 startPointIndex;
private int endPointIndex; private int endPointIndex;
private List<RouteSegmentResult>[] attachedRoutes; private List<RouteSegmentResult>[] attachedRoutes;
private RouteSegmentResult[][] preAttachedRoutes;
private float segmentTime; private float segmentTime;
private float speed; private float speed;
private float distance; private float distance;
@ -29,6 +30,7 @@ public class RouteSegmentResult {
updateCapacity(); updateCapacity();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void updateCapacity() { private void updateCapacity() {
int capacity = Math.abs(endPointIndex - startPointIndex) + 1; int capacity = Math.abs(endPointIndex - startPointIndex) + 1;
@ -43,6 +45,20 @@ public class RouteSegmentResult {
attachedRoutes[st].add(r); 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) { public List<RouteSegmentResult> getAttachedRoutes(int routeInd) {
int st = Math.abs(routeInd - startPointIndex); int st = Math.abs(routeInd - startPointIndex);
List<RouteSegmentResult> list = attachedRoutes[st]; List<RouteSegmentResult> list = attachedRoutes[st];

View file

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

View file

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

View file

@ -12,23 +12,24 @@
(don't specify here ! it is device dependent) --> (don't specify here ! it is device dependent) -->
<attribute name="memoryLimitInMB" value="155" /> <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 --> <!-- 0 - 2 ways, 1 - direct way, -1 - reverse way -->
<attribute name="planRoadDirection" value="0" /> <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 --> <!-- HELP INFORMATION ABOUT FILE -->
<!-- 1) Highway defines acceptable route for routingProfile, speed in km/h (if it is not specified on level road) --> <!-- 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) --> <!-- 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="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 --> <!-- 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! --> <!-- penalty is measured in time and -1 means it could not be passed! -->
<!-- <obstacle tag="highway" value="traffic_signals" penalty="35"/> --> <!-- <obstacle tag="highway" value="traffic_signals" penalty="35"/> -->
<!-- 3) Avoid describes what road should be completely avoided or passed with multiplied (decreased) priority --> <!-- 3) Avoid describes what road should be completely avoided or passed with multiplied (decreased) priority -->
<!-- <avoid tag="access" value="no" decreasedPriority="0.9"/> --> <!-- <avoid tag="access" value="no" decreasedPriority="0.9"/> -->
<!-- obstacle tag="highway" value="traffic_signals" penalty="35", penalty measured in seconds --> <!-- 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" <routingProfile name="car" baseProfile="car" restrictionsAware="true" minDefaultSpeed="45.0" maxDefaultSpeed="130.0"
leftTurn="0" rightTurn="0" roundaboutTurn="0" followSpeedLimitations="true" onewayAware="true"> leftTurn="0" rightTurn="0" roundaboutTurn="0" followSpeedLimitations="true" onewayAware="true">
@ -36,55 +37,55 @@
<attribute name="heuristicCoefficient" value="1.5" /> <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"/> <specialization input="avoid_motorway" speed="0"/>
</road> </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"/> <specialization input="avoid_motorway" speed="0"/>
</road> </road>
<road tag="highway" value="trunk" speed="100" 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" dynamicPriority="0.9"/> <road tag="highway" value="trunk_link" speed="75" priority="1.2" />
<!-- generally linking larger towns. --> <!-- generally linking larger towns. -->
<road tag="highway" value="primary" speed="65" 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.1" dynamicPriority="0.7"/> <road tag="highway" value="primary_link" speed="50" priority="1.05" />
<!-- generally linking smaller towns and villages --> <!-- generally linking smaller towns and villages -->
<road tag="highway" value="secondary" speed="60" 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.05" dynamicPriority="0.6"/> <road tag="highway" value="secondary_link" speed="50" priority="1" />
<!-- important urban roads --> <!-- important urban roads -->
<road tag="highway" value="tertiary" speed="45" priority="1" dynamicPriority="0.5"/> <road tag="highway" value="tertiary" speed="45" priority="0.95" />
<road tag="highway" value="tertiary_link" speed="40" priority="1" dynamicPriority="0.5"/> <road tag="highway" value="tertiary_link" speed="40" priority="0.95" />
<!-- lowest form of grid network, usually 90% of urban roads --> <!-- lowest form of grid network, usually 90% of urban roads -->
<road tag="highway" value="unclassified" speed="35" priority="0.7" dynamicPriority="0.3"> <road tag="highway" value="unclassified" speed="35" priority="0.7" >
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/> <specialization input="short_way" priority="1" speed="45"/>
</road> </road>
<!-- road = no type, no review and may be not accurate --> <!-- 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"/> <specialization input="short_way" priority="1" speed="45"/>
</road> </road>
<!-- primarily for access to properties, small roads with 1/2 intersections --> <!-- primarily for access to properties, small roads with 1/2 intersections -->
<road tag="highway" value="residential" speed="35" priority="0.7" dynamicPriority="0.3"> <road tag="highway" value="residential" speed="35" priority="0.7" >
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/> <specialization input="short_way" priority="1" speed="45"/>
</road> </road>
<!-- parking + private roads --> <!-- parking + private roads -->
<road tag="highway" value="service" speed="30" priority="0.5" dynamicPriority="0.3"> <road tag="highway" value="service" speed="30" priority="0.5" >
<specialization input="short_way" priority="1" dynamicPriority="1" speed="45"/> <specialization input="short_way" priority="1" speed="45"/>
</road> </road>
<!-- very bad roads --> <!-- very bad roads -->
<road tag="highway" value="track" speed="15" priority="0.3" dynamicPriority="0.2"> <road tag="highway" value="track" speed="15" priority="0.3" >
<specialization input="short_way" priority="0.7" speed="45" dynamicPriority="0.7" /> <specialization input="short_way" priority="0.7" speed="45" />
<specialization input="avoid_unpaved" priority="0.1"/> <specialization input="avoid_unpaved" priority="0.1"/>
</road> </road>
<!-- too small for cars usually --> <!-- too small for cars usually -->
<road tag="highway" value="living_street" speed="25" priority="0.5" dynamicPriority="0.3"> <road tag="highway" value="living_street" speed="25" priority="0.5" >
<specialization input="short_way" priority="1" dynamicPriority="1" speed="35"/> <specialization input="short_way" priority="1" speed="35"/>
</road> </road>
<!-- car are able to enter in highway=pedestrian with restrictions --> <!-- car are able to enter in highway=pedestrian with restrictions -->
<!-- Time actually is uknown. Currently unsupported --> <!-- 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"/> <specialization input="avoid_ferries" speed="0"/>
</road> </road>
@ -121,36 +122,36 @@
leftTurn="0" rightTurn="0" followSpeedLimitations="false" onewayAware="true"> leftTurn="0" rightTurn="0" followSpeedLimitations="false" onewayAware="true">
<!-- <attribute name="relaxNodesIfStartDistSmallCoeff" value="2.5"/> --> <!-- <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"/> <specialization input="avoid_motorway" speed="0"/>
</road> </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"/> <specialization input="avoid_motorway" speed="0"/>
</road> </road>
<road tag="highway" value="trunk" speed="16" priority="0.6" dynamicPriority="0.9"/> <road tag="highway" value="trunk" speed="16" priority="0.6" />
<road tag="highway" value="trunk_link" speed="16" priority="0.7" dynamicPriority="0.9"/> <road tag="highway" value="trunk_link" speed="16" priority="0.7" />
<road tag="highway" value="primary" speed="16" priority="0.8" dynamicPriority="0.9"/> <road tag="highway" value="primary" speed="16" priority="0.8" />
<road tag="highway" value="primary_link" speed="16" priority="0.8" dynamicPriority="0.9"/> <road tag="highway" value="primary_link" speed="16" priority="0.8" />
<road tag="highway" value="secondary" speed="16" priority="1" dynamicPriority="1"/> <road tag="highway" value="secondary" speed="16" priority="1" />
<road tag="highway" value="secondary_link" speed="16" priority="1" dynamicPriority="1"/> <road tag="highway" value="secondary_link" speed="16" priority="1" />
<road tag="highway" value="tertiary" speed="16" priority="1" dynamicPriority="1"/> <road tag="highway" value="tertiary" speed="16" priority="1" />
<road tag="highway" value="tertiary_link" speed="16" priority="1" dynamicPriority="1"/> <road tag="highway" value="tertiary_link" speed="16" priority="1" />
<road tag="highway" value="road" speed="16" priority="1" dynamicPriority="1"/> <road tag="highway" value="road" speed="16" priority="1" />
<road tag="highway" value="residential" speed="16" priority="1.1" dynamicPriority="1"/> <road tag="highway" value="residential" speed="16" priority="1.1" />
<road tag="highway" value="cycleway" speed="16" priority="1.5" dynamicPriority="1.3"/> <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="unclassified" speed="13" priority="1" />
<road tag="highway" value="service" speed="13" priority="1" dynamicPriority="1"/> <road tag="highway" value="service" speed="13" priority="1" />
<road tag="highway" value="track" speed="12" priority="1.5" dynamicPriority="1.5"/> <road tag="highway" value="track" speed="12" priority="1.5" />
<road tag="highway" value="path" speed="12" priority="1.5" dynamicPriority="1.5"/> <road tag="highway" value="path" speed="12" priority="1.5" />
<road tag="highway" value="living_street" speed="15" priority="1.1" dynamicPriority="1"/> <road tag="highway" value="living_street" speed="15" priority="1.1" />
<road tag="highway" value="pedestrian" speed="10" priority="0.9" dynamicPriority="1"/> <road tag="highway" value="pedestrian" speed="10" priority="0.9" />
<road tag="highway" value="footway" speed="8" priority="0.9" dynamicPriority="1"/> <road tag="highway" value="footway" speed="8" priority="0.9" />
<road tag="highway" value="byway" speed="8" priority="1" dynamicPriority="1"/> <road tag="highway" value="byway" speed="8" priority="1" />
<road tag="highway" value="services" speed="13" priority="1" dynamicPriority="1"/> <road tag="highway" value="services" speed="13" priority="1" />
<road tag="highway" value="bridleway" speed="8" priority="0.8" dynamicPriority="1"/> <road tag="highway" value="bridleway" speed="8" priority="0.8" />
<road tag="highway" value="steps" speed="3" priority="0.5" dynamicPriority="0.9"/> <road tag="highway" value="steps" speed="3" priority="0.5" />
<obstacle tag="highway" value="traffic_signals" penalty="25" routingPenalty="10"/> <obstacle tag="highway" value="traffic_signals" penalty="25" routingPenalty="10"/>
<obstacle tag="railway" value="crossing" penalty="15"/> <obstacle tag="railway" value="crossing" penalty="15"/>
@ -171,36 +172,36 @@
<attribute name="heuristicCoefficient" value="1.2" /> <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"/> <specialization input="avoid_motorway" speed="0"/>
</road> </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"/> <specialization input="avoid_motorway" speed="0"/>
</road> </road>
<road tag="highway" value="trunk" speed="5" priority="0.7" dynamicPriority="0.7"/> <road tag="highway" value="trunk" speed="5" priority="0.7" />
<road tag="highway" value="trunk_link" speed="5" priority="0.7" dynamicPriority="0.7"/> <road tag="highway" value="trunk_link" speed="5" priority="0.7" />
<road tag="highway" value="primary" speed="5" priority="0.9" dynamicPriority="0.9"/> <road tag="highway" value="primary" speed="5" priority="0.9" />
<road tag="highway" value="primary_link" speed="5" priority="0.9" dynamicPriority="0.9"/> <road tag="highway" value="primary_link" speed="5" priority="0.9" />
<road tag="highway" value="secondary" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="secondary" speed="5" priority="1" />
<road tag="highway" value="secondary_link" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="secondary_link" speed="5" priority="1" />
<road tag="highway" value="tertiary" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="tertiary" speed="5" priority="1" />
<road tag="highway" value="tertiary_link" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="tertiary_link" speed="5" priority="1" />
<road tag="highway" value="road" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="road" speed="5" priority="1" />
<road tag="highway" value="residential" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="residential" speed="5" priority="1" />
<road tag="highway" value="cycleway" speed="5" priority="1" dynamicPriority="1.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="unclassified" speed="5" priority="1" />
<road tag="highway" value="service" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="service" speed="5" priority="1" />
<road tag="highway" value="track" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="track" speed="5" priority="1" />
<road tag="highway" value="path" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="path" speed="5" priority="1" />
<road tag="highway" value="living_street" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="living_street" speed="5" priority="1" />
<road tag="highway" value="pedestrian" speed="5" priority="1.2" dynamicPriority="1.1"/> <road tag="highway" value="pedestrian" speed="5" priority="1.2" />
<road tag="highway" value="footway" speed="5" priority="1.2" dynamicPriority="1.1"/> <road tag="highway" value="footway" speed="5" priority="1.2" />
<road tag="highway" value="byway" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="byway" speed="5" priority="1" />
<road tag="highway" value="services" speed="5" priority="1" dynamicPriority="1"/> <road tag="highway" value="services" speed="5" priority="1" />
<road tag="highway" value="bridleway" speed="5" priority="0.8" dynamicPriority="0.8"/> <road tag="highway" value="bridleway" speed="5" priority="0.8" />
<road tag="highway" value="steps" speed="4" priority="1.2" dynamicPriority="1"/> <road tag="highway" value="steps" speed="4" priority="1.2" />
<obstacle tag="highway" value="traffic_signals" penalty="30"/> <obstacle tag="highway" value="traffic_signals" penalty="30"/>
<obstacle tag="railway" value="crossing" penalty="15"/> <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()); // Choose native or not native
int sx31 = st.getRoad().getPoint31XTile(st.getSegmentStart()); long nt = System.nanoTime();
int sy31 = st.getRoad().getPoint31YTile(st.getSegmentStart()); List<RouteSegmentResult> searchRoute = router.searchRoute(ctx, st, e, inters, false);
// FIXME System.out.println("External native time " + (System.nanoTime() - nt) / 1e9f);
RouteSegmentResult[] searchRoute = ctx.nativeLib.runNativeRouting(sx31, sy31, ex31, ey31, ctx.config);
// /*List<RouteSegmentResult> searchRoute = */router.searchRoute(ctx, st, e, inters, false);
// this.previousRoute = searchRoute;
if (animateRoutingCalculation) { if (animateRoutingCalculation) {
playPauseButton.setVisible(false); playPauseButton.setVisible(false);
nextTurn.setText("FINISH"); nextTurn.setText("FINISH");
@ -742,7 +739,6 @@ public class MapRouterLayer implements MapPanelLayer {
// String name = String.format("beg %.2f end %.2f ", s.getBearingBegin(), s.getBearingEnd()); // String name = String.format("beg %.2f end %.2f ", s.getBearingBegin(), s.getBearingEnd());
way.putTag(OSMTagKey.NAME.getValue(),name); way.putTag(OSMTagKey.NAME.getValue(),name);
boolean plus = s.getStartPointIndex() < s.getEndPointIndex(); boolean plus = s.getStartPointIndex() < s.getEndPointIndex();
System.out.println("Segment " + s.getObject().id + " "+s.getStartPointIndex() + " -> " + s.getEndPointIndex());
int i = s.getStartPointIndex(); int i = s.getStartPointIndex();
while (true) { while (true) {
LatLon l = s.getPoint(i); LatLon l = s.getPoint(i);

View file

@ -10,8 +10,6 @@
#include <map> #include <map>
#include <string> #include <string>
#include <stdint.h> #include <stdint.h>
#include "mapObjects.h" #include "mapObjects.h"
#include "multipolygons.h" #include "multipolygons.h"
#include "common.h" #include "common.h"
@ -108,6 +106,61 @@ struct RouteDataObject {
UNORDERED(map)<int, std::string > names; UNORDERED(map)<int, std::string > names;
vector<pair<uint32_t, uint32_t> > namesIds; 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 bool PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true;
static const int REVERSE_WAY_RESTRICTION_ONLY = 1024; 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 int ROUTE_POINTS = 11;
static const float TURN_DEGREE_MIN = 45; 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_RIGHT_TURN = 5;
static const short RESTRICTION_ONLY_LEFT_TURN = 6; static const short RESTRICTION_ONLY_LEFT_TURN = 6;
static const short RESTRICTION_ONLY_STRAIGHT_ON = 7; static const short RESTRICTION_ONLY_STRAIGHT_ON = 7;
static const bool TRACE_ROUTING = false;
inline int roadPriorityComparator(float o1DistanceFromStart, float o1DistanceToEnd, inline int roadPriorityComparator(float o1DistanceFromStart, float o1DistanceToEnd,
float o2DistanceFromStart, float o2DistanceToEnd, float heuristicCoefficient) { 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 bool operator()(const SHARED_PTR<RouteSegment> lhs, const SHARED_PTR<RouteSegment> rhs) const
{ {
return roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart, int cmp = roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart,
rhs.get()->distanceToEnd, ctx->getHeuristicCoefficient()) > 0; rhs.get()->distanceToEnd, ctx->getHeuristicCoefficient());
return cmp > 0;
} }
}; };
struct NonHeuristicSegmentsComparator : public std::binary_function<SHARED_PTR<RouteSegment>, SHARED_PTR<RouteSegment>, bool> 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, SHARED_PTR<RouteSegment> segment, int segmentEnd, SHARED_PTR<RouteSegment> inputNext,
bool reverseWay); 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) * Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm)
* return list of segments * return list of segments
*/ */
void searchRouteInternal(RoutingContext* ctx, SHARED_PTR<RouteSegment> start, SHARED_PTR<RouteSegment> end, bool leftSideNavigation) { void searchRouteInternal(RoutingContext* ctx, SHARED_PTR<RouteSegment> start, SHARED_PTR<RouteSegment> end, bool leftSideNavigation) {
// FIXME intermediate points
// measure time // measure time
ctx->visitedSegments = 0; ctx->visitedSegments = 0;
ctx->timeToCalculate.start(); ctx->timeToCalculate.start();
// FIXME initial direction if(ctx->config.initialDirection != -360) {
// if(ctx.config.initialDirection != null) { ctx->firstRoadId = (start->road->id << ROUTE_POINTS) + start->getSegmentStart();
// ctx.firstRoadId = (start->road->id << ROUTE_POINTS) + start.getSegmentStart(); double plusDir = start->road->directionRoute(start->getSegmentStart(), true);
// double plusDir = start->road->directionRoute(start.segmentStart, true); double diff = plusDir - ctx->config.initialDirection;
// double diff = plusDir - ctx.config.initialDirection; if(abs(alignAngleDifference(diff)) <= M_PI / 3) {
// if(Math.abs(MapUtils.alignAngleDifference(diff)) <= Math.PI / 3) { ctx->firstRoadDirection = 1;
// ctx.firstRoadDirection = 1; } else if(abs(alignAngleDifference(diff - M_PI )) <= M_PI / 3) {
// } else if(Math.abs(MapUtils.alignAngleDifference(diff - Math.PI)) <= Math.PI / 3) { ctx->firstRoadDirection = -1;
// ctx.firstRoadDirection = -1; }
// }
// }
// }
SegmentsComparator sgmCmp(ctx); SegmentsComparator sgmCmp(ctx);
SEGMENTS_QUEUE graphDirectSegments(sgmCmp); 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 ) ", 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(), ctx-> visitedSegments, visitedDirectSegments.size(), visitedOppositeSegments.size(),
graphDirectSegments.size(),graphReverseSegments.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, bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch,
SEGMENTS_QUEUE& graphSegments, VISITED_MAP& visitedSegments, int targetEndX, int targetEndY, SEGMENTS_QUEUE& graphSegments, VISITED_MAP& visitedSegments, int targetEndX, int targetEndY,
SHARED_PTR<RouteSegment> segment, VISITED_MAP& oppositeSegments) { SHARED_PTR<RouteSegment> segment, VISITED_MAP& oppositeSegments) {
@ -206,6 +224,10 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch,
if(visitedSegments.find(nt) != visitedSegments.end()) { if(visitedSegments.find(nt) != visitedSegments.end()) {
return false; 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++; ctx->visitedSegments++;
// avoid empty segments to connect but mark the point as visited // avoid empty segments to connect but mark the point as visited
visitedSegments[nt] = SHARED_PTR<RouteSegment>(); 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"); // throw new OutOfMemoryError("There is no enough memory " + ctx.config.memoryLimitation/(1<<20) + " Mb");
// } // }
SHARED_PTR<RouteSegment> next = ctx->loadRouteSegment(x, y); SHARED_PTR<RouteSegment> next = ctx->loadRouteSegment(x, y);
// 3. get intersected ways // 3. get intersected ways
if (next.get() != NULL) { if (next.get() != NULL) {
if((next.get() == segment.get() || next->road->id == road->id) && next->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; return true;
} }
} }
// road.id could be equal on roundabout, but we should accept them // road.id could be equal on roundabout, but we should accept them
bool alreadyVisited = visitedSegments.find(nts) != visitedSegments.end(); bool alreadyVisited = visitedSegments.find(nts) != visitedSegments.end();
if (!alreadyVisited) { if (!alreadyVisited) {
@ -463,6 +485,9 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
// put additional information to recover whole route after // put additional information to recover whole route after
next->parentRoute = segment; next->parentRoute = segment;
next->parentSegmentEnd = segmentEnd; 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); graphSegments.push(next);
} }
} else { } else {
@ -490,9 +515,9 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
SHARED_PTR<RouteSegment> findRouteSegment(int px, int py, RoutingContext* ctx) { SHARED_PTR<RouteSegment> findRouteSegment(int px, int py, RoutingContext* ctx) {
vector<SHARED_PTR<RouteDataObject> > dataObjects; vector<SHARED_PTR<RouteDataObject> > dataObjects;
ctx->loadTileData(px, py, 16, dataObjects); ctx->loadTileData(px, py, 17, dataObjects);
if (dataObjects.size() == 0) { if (dataObjects.size() == 0) {
ctx->loadTileData(px, py, 14, dataObjects); ctx->loadTileData(px, py, 15, dataObjects);
} }
SHARED_PTR<RouteSegment> road; SHARED_PTR<RouteSegment> road;
double sdist = 0; 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> convertFinalSegmentToResults(RoutingContext* ctx) {
vector<RouteSegmentResult> result; vector<RouteSegmentResult> result;
if (ctx->finalRouteSegment.get() != NULL) { 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); osmand_log_print(LOG_WARN, "End point was found %lld [Native]", end->road->id);
} }
searchRouteInternal(ctx, start, end, leftSideNavigation); 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() vector<RouteSegmentResult> res = convertFinalSegmentToResults(ctx);
, ctx->timeToCalculate.getElapsedTime(), ctx->loadedTiles); attachConnectedRoads(ctx, res);
return convertFinalSegmentToResults(ctx); return res;
} }

View file

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

View file

@ -410,17 +410,25 @@ jfieldID jfield_RouteSubregion_top = NULL;
jfieldID jfield_RouteSubregion_bottom = NULL; jfieldID jfield_RouteSubregion_bottom = NULL;
jfieldID jfield_RouteSubregion_shiftToData = 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_RouteSegmentResult = NULL;
jclass jclass_RouteSegmentResultAr = NULL;
jmethodID jmethod_RouteSegmentResult_ctor = NULL; jmethodID jmethod_RouteSegmentResult_ctor = NULL;
jfieldID jfield_RouteSegmentResult_preAttachedRoutes = NULL;
void loadJniRenderingContext(JNIEnv* env) void loadJniRenderingContext(JNIEnv* env)
{ {
jclass_RouteSegmentResult = findClass(env, "net/osmand/router/RouteSegmentResult"); jclass_RouteSegmentResult = findClass(env, "net/osmand/router/RouteSegmentResult");
jclass_RouteSegmentResultAr = findClass(env, "[Lnet/osmand/router/RouteSegmentResult;");
jmethod_RouteSegmentResult_ctor = env->GetMethodID(jclass_RouteSegmentResult, jmethod_RouteSegmentResult_ctor = env->GetMethodID(jclass_RouteSegmentResult,
"<init>", "(Lnet/osmand/binary/RouteDataObject;II)V"); "<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"); jclass_RenderingContext = findClass(env, "net/osmand/RenderingContext");
jfield_RenderingContext_interrupted = getFid(env, jclass_RenderingContext, "interrupted", "Z"); 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"); 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"); jclass_RouteSubregion = findClass(env, "net/osmand/binary/BinaryMapRouteReaderAdapter$RouteSubregion");
jfield_RouteSubregion_length= getFid(env, jclass_RouteSubregion, "length", "I" ); jfield_RouteSubregion_length= getFid(env, jclass_RouteSubregion, "length", "I" );
jfield_RouteSubregion_filePointer= getFid(env, jclass_RouteSubregion, "filePointer", "I" ); jfield_RouteSubregion_filePointer= getFid(env, jclass_RouteSubregion, "filePointer", "I" );
@ -563,6 +575,38 @@ jobject convertRouteDataObjectToJava(JNIEnv* ienv, RouteDataObject* route, jobje
return robj; 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 { class NativeRoutingTile {
public: public:
std::vector<RouteDataObject*> result; 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); //p RouteSegmentResult[] nativeRouting(int[] coordinates, int[] state, String[] keyConfig, String[] valueConfig);
extern "C" JNIEXPORT jobjectArray JNICALL Java_net_osmand_NativeLibrary_nativeRouting(JNIEnv* ienv, extern "C" JNIEXPORT jobjectArray JNICALL Java_net_osmand_NativeLibrary_nativeRouting(JNIEnv* ienv,
jobject obj, jintArray coordinates, jobject obj, jintArray coordinates,
jintArray stateConfig, jobjectArray keyConfig, jobjectArray valueConfig) { jintArray stateConfig, jobjectArray keyConfig, jobjectArray valueConfig, jfloat initDirection,
jobjectArray regions) {
vector<ROUTE_TRIPLE> cfg; vector<ROUTE_TRIPLE> cfg;
int* data = ienv->GetIntArrayElements(stateConfig, NULL); int* data = ienv->GetIntArrayElements(stateConfig, NULL);
for(int k = 0; k < ienv->GetArrayLength(stateConfig); k++) { 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>( ROUTE_TRIPLE t = ROUTE_TRIPLE (data[k], std::pair<string, string>(
getString(ienv, (jstring) ienv->GetObjectArrayElement(keyConfig, k)), getString(ienv, kl),
getString(ienv, (jstring) ienv->GetObjectArrayElement(valueConfig, k))) getString(ienv, vl))
); );
ienv->DeleteLocalRef(kl);
ienv->DeleteLocalRef(vl);
cfg.push_back(t); cfg.push_back(t);
} }
ienv->ReleaseIntArrayElements(stateConfig, data, 0); ienv->ReleaseIntArrayElements(stateConfig, data, 0);
RoutingConfiguration config(cfg); RoutingConfiguration config(cfg, initDirection);
RoutingContext c(config); RoutingContext c(config);
data = ienv->GetIntArrayElements(coordinates, NULL); data = ienv->GetIntArrayElements(coordinates, NULL);
c.startX = data[0]; c.startX = data[0];
@ -606,16 +655,21 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_net_osmand_NativeLibrary_nativeRo
ienv->ReleaseIntArrayElements(coordinates, data, 0); ienv->ReleaseIntArrayElements(coordinates, data, 0);
vector<RouteSegmentResult> r = searchRouteInternal(&c, false); 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 // convert results
jobjectArray res = ienv->NewObjectArray(r.size(), jclass_RouteSegmentResult, NULL); jobjectArray res = ienv->NewObjectArray(r.size(), jclass_RouteSegmentResult, NULL);
for (int i = 0; i < r.size(); i++) { for (int i = 0; i < r.size(); i++) {
jobject robj = convertRouteDataObjectToJava(ienv, r[i].object.get(), NULL); jobject resobj = convertRouteSegmentResultToJava(ienv, r[i], indexes, regions);
jobject resobj = ienv->NewObject(jclass_RouteSegmentResult, jmethod_RouteSegmentResult_ctor, robj,
r[i].startPointIndex, r[i].endPointIndex);
ienv->SetObjectArrayElement(res, i, resobj); ienv->SetObjectArrayElement(res, i, resobj);
ienv->DeleteLocalRef(robj);
ienv->DeleteLocalRef(resobj); ienv->DeleteLocalRef(resobj);
} }
if (r.size() == 0) { if (r.size() == 0) {
osmand_log_print(LOG_INFO, "No route found"); osmand_log_print(LOG_INFO, "No route found");