Memory limitation

This commit is contained in:
Victor Shcherb 2012-11-10 13:02:20 +01:00
parent 3e0c5d8466
commit 1e85c0234d
18 changed files with 690 additions and 649 deletions

View file

@ -12,7 +12,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
import net.osmand.NativeLibrary;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.router.BinaryRoutePlanner;
import net.osmand.router.BinaryRoutePlanner.FinalRouteSegment;
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
import net.osmand.router.RouteSegmentResult;
import net.osmand.router.RoutingConfiguration;
@ -170,7 +170,7 @@ public class RouterTestsSuite {
return;
}
RoutingConfiguration rconfig = config.build(vehicle, MEMORY_TEST_LIMIT);
BinaryRoutePlanner router = new BinaryRoutePlanner();
RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(false);
RoutingContext ctx = new RoutingContext(rconfig,
lib, rs);
String skip = testCase.getAttribute("skip_comment");
@ -238,12 +238,12 @@ public class RouterTestsSuite {
}
private static void runTestSpecialTest(NativeLibrary lib, BinaryMapIndexReader[] rs, RoutingConfiguration rconfig, BinaryRoutePlanner router,
private static void runTestSpecialTest(NativeLibrary lib, BinaryMapIndexReader[] rs, RoutingConfiguration rconfig, RoutePlannerFrontEnd router,
RouteSegment startSegment, RouteSegment endSegment, final float calcRoutingTime, String msg) throws IOException, InterruptedException {
RoutingContext ctx;
RouteSegment frs;
ctx = new RoutingContext(rconfig, lib, rs);
frs = router.searchRouteInternal(ctx, startSegment, endSegment, false);
router.searchRoute(ctx, startSegment, endSegment, false);
FinalRouteSegment frs = ctx.finalRouteSegment;
if(frs == null || !equalPercent(calcRoutingTime, frs.distanceFromStart, 0.5f)){
throw new IllegalArgumentException(String.format(msg, calcRoutingTime+"",frs == null?"0":frs.distanceFromStart+""));
}

View file

@ -16,6 +16,7 @@ import net.osmand.binary.RouteDataObject;
import net.osmand.render.RenderingRuleSearchRequest;
import net.osmand.render.RenderingRulesStorage;
import net.osmand.router.GeneralRouter;
import net.osmand.router.RouteCalculationProgress;
import net.osmand.router.RouteSegmentResult;
import net.osmand.router.RoutingConfiguration;
@ -110,7 +111,7 @@ public class NativeLibrary {
}
public RouteSegmentResult[] runNativeRouting(int sx31, int sy31, int ex31, int ey31, RoutingConfiguration config,
RouteRegion[] regions) {
RouteRegion[] regions, RouteCalculationProgress progress) {
TIntArrayList state = new TIntArrayList();
List<String> keys = new ArrayList<String>();
List<String> values = new ArrayList<String>();
@ -126,7 +127,7 @@ public class NativeLibrary {
return nativeRouting(new int[]{sx31, sy31, ex31, ey31}, state.toArray(), keys.toArray(new String[keys.size()]),
values.toArray(new String[values.size()]), config.initialDirection == null ? -360 : config.initialDirection.floatValue(),
regions);
regions, progress);
}
public <T> void fillObjects(TIntArrayList state, List<String> keys, List<String> values, int s, Map<String, T> map) {
@ -159,7 +160,7 @@ 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,
float initDirection, RouteRegion[] regions);
float initDirection, RouteRegion[] regions, RouteCalculationProgress progress);
protected static native void deleteSearchResult(long searchResultHandle);

View file

@ -37,7 +37,7 @@ public class CachedOsmandIndexes {
private Log log = LogUtil.getLog(CachedOsmandIndexes.class);
private boolean hasChanged = true;
public static final int VERSION = 1;
public static final int VERSION = 2;
public void addToCache(BinaryMapIndexReader reader, File f) {
hasChanged = true;

View file

@ -39,152 +39,6 @@ public class BinaryRoutePlanner {
}
public RouteSegment findRouteSegment(double lat, double lon, RoutingContext ctx) throws IOException {
int px = MapUtils.get31TileNumberX(lon);
int py = MapUtils.get31TileNumberY(lat);
ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
ctx.loadTileData(px, py, 17, dataObjects);
if (dataObjects.isEmpty()) {
ctx.loadTileData(px, py, 15, dataObjects);
}
RouteSegment road = null;
double sdist = 0;
@SuppressWarnings("unused")
int foundProjX = 0;
@SuppressWarnings("unused")
int foundProjY = 0;
for (RouteDataObject r : dataObjects) {
if (r.getPointsLength() > 1) {
for (int j = 1; j < r.getPointsLength(); j++) {
double mDist = squareRootDist(r.getPoint31XTile(j), r.getPoint31YTile(j), r.getPoint31XTile(j - 1),
r.getPoint31YTile(j - 1));
int prx = r.getPoint31XTile(j);
int pry = r.getPoint31YTile(j);
double projection = MapUtils. calculateProjection31TileMetric(r.getPoint31XTile(j - 1), r.getPoint31YTile(j - 1), r.getPoint31XTile(j),
r.getPoint31YTile(j), px, py);
if (projection < 0) {
prx = r.getPoint31XTile(j - 1);
pry = r.getPoint31YTile(j - 1);
} else if (projection >= mDist * mDist) {
prx = r.getPoint31XTile(j);
pry = r.getPoint31YTile(j);
} else {
prx = (int) (r.getPoint31XTile(j - 1) + (r.getPoint31XTile(j) - r.getPoint31XTile(j - 1))
* (projection / (mDist * mDist)));
pry = (int) (r.getPoint31YTile(j - 1) + (r.getPoint31YTile(j) - r.getPoint31YTile(j - 1))
* (projection / (mDist * mDist)));
}
double currentsDist = MapUtils.squareDist31TileMetric(prx, pry, px, py);
if (road == null || currentsDist < sdist) {
RouteDataObject ro = new RouteDataObject(r);
road = new RouteSegment(ro, j);
ro.insert(j, prx, pry);
sdist = currentsDist;
foundProjX = prx;
foundProjY = pry;
}
}
}
}
if (road != null) {
// re-register the best road because one more point was inserted
ctx.registerRouteDataObject(road.getRoad());
}
return road;
}
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, List<RouteSegment> intermediate, boolean leftSideNavigation) throws IOException, InterruptedException {
if(intermediate != null && intermediate.size() > 0) {
ArrayList<RouteSegment> ps = new ArrayList<RouteSegment>(intermediate);
ArrayList<RouteSegmentResult> firstPartRecalculatedRoute = null;
ArrayList<RouteSegmentResult> restPartRecalculatedRoute = null;
if (ctx.previouslyCalculatedRoute != null) {
List<RouteSegmentResult> prev = ctx.previouslyCalculatedRoute;
long id = intermediate.get(0).getRoad().id;
int ss = intermediate.get(0).getSegmentStart();
for (int i = 0; i < prev.size(); i++) {
RouteSegmentResult rsr = prev.get(i);
if (id == rsr.getObject().getId() && ss == rsr.getEndPointIndex()) {
firstPartRecalculatedRoute = new ArrayList<RouteSegmentResult>(prev.subList(0, i + 1));
restPartRecalculatedRoute = new ArrayList<RouteSegmentResult>(prev.subList(i + 1, prev.size()));
break;
}
}
}
ps.add(end);
ps.add(0, start);
List<RouteSegmentResult> results = new ArrayList<RouteSegmentResult>();
for (int i = 0; i < ps.size() - 1; i++) {
RoutingContext local = new RoutingContext(ctx);
if(i == 0) {
local.previouslyCalculatedRoute = firstPartRecalculatedRoute;
}
local.visitor = ctx.visitor;
List<RouteSegmentResult> res = searchRouteInternalPrepare(local, ps.get(i), ps.get(i + 1), leftSideNavigation);
results.addAll(res);
ctx.distinctLoadedTiles += local.distinctLoadedTiles;
ctx.loadedTiles += local.loadedTiles;
ctx.visitedSegments += local.visitedSegments;
ctx.loadedPrevUnloadedTiles += local.loadedPrevUnloadedTiles;
ctx.timeToCalculate += local.timeToCalculate;
ctx.timeToLoad += local.timeToLoad;
ctx.timeToLoadHeaders += local.timeToLoadHeaders;
ctx.relaxedSegments += local.relaxedSegments;
ctx.routingTime += local.routingTime;
local.unloadAllData(ctx);
if(restPartRecalculatedRoute != null) {
results.addAll(restPartRecalculatedRoute);
break;
}
}
ctx.unloadAllData();
new RouteResultPreparation().printResults(ctx, start, end, results);
return results;
}
return searchRoute(ctx, start, end, leftSideNavigation);
}
private void printMemoryConsumption(String message ){
RoutingContext.runGCUsedMemory();
long h1 = RoutingContext.runGCUsedMemory();
float mb = (1 << 20);
log.warn(message + h1 / mb+ " mb");
}
@SuppressWarnings("static-access")
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
if(ctx.SHOW_GC_SIZE){
printMemoryConsumption("Memory occupied before routing ");
}
List<RouteSegmentResult> result = searchRouteInternalPrepare(ctx, start, end, leftSideNavigation);
if(result != null) {
new RouteResultPreparation().printResults(ctx, start, end, result);
}
if (RoutingContext.SHOW_GC_SIZE) {
int sz = ctx.global.size;
log.warn("Subregion size " + ctx.subregionTiles.size() + " " + " tiles " + ctx.indexedSubregions.size());
ctx.runGCUsedMemory();
long h1 = ctx.runGCUsedMemory();
ctx.unloadAllData();
ctx.runGCUsedMemory();
long h2 = ctx.runGCUsedMemory();
float mb = (1 << 20);
log.warn("Unload context : estimated " + sz / mb + " ?= " + (h1 - h2) / mb + " actual");
}
return result;
}
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
FinalRouteSegment finalRouteSegment = searchRouteInternal(ctx, start, end, leftSideNavigation);
// 4. Route is found : collect all segments and prepare result
return new RouteResultPreparation().prepareResult(ctx, finalRouteSegment, leftSideNavigation);
}
private static class SegmentsComparator implements Comparator<RouteSegment> {
final RoutingContext ctx;
public SegmentsComparator(RoutingContext ctx) {
@ -207,10 +61,9 @@ public class BinaryRoutePlanner {
/**
* Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm)
* return list of segments
* @return
*/
@SuppressWarnings("unused")
FinalRouteSegment searchRouteInternal(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
FinalRouteSegment searchRouteInternal(final RoutingContext ctx, RouteSegment start, RouteSegment end) throws InterruptedException, IOException {
// measure time
ctx.timeToLoad = 0;
ctx.visitedSegments = 0;
@ -246,10 +99,6 @@ public class BinaryRoutePlanner {
}
// for start : f(start) = g(start) + h(start) = 0 + h(start) = h(start)
ctx.targetX = end.road.getPoint31XTile(end.getSegmentStart());
ctx.targetY = end.road.getPoint31YTile(end.getSegmentStart());
ctx.startX = start.road.getPoint31XTile(start.getSegmentStart());
ctx.startY = start.road.getPoint31YTile(start.getSegmentStart());
float estimatedDistance = (float) estimatedDistance(ctx, ctx.targetX, ctx.targetY, ctx.startX, ctx.startY);
end.distanceToEnd = start.distanceToEnd = estimatedDistance;
@ -305,6 +154,7 @@ public class BinaryRoutePlanner {
processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments, ctx.startX, ctx.startY, segment,
visitedDirectSegments, false);
}
updateCalculationProgress(ctx, graphDirectSegments, graphReverseSegments);
if(graphReverseSegments.isEmpty()){
throw new IllegalArgumentException("Route is not found to selected target point.");
}
@ -335,7 +185,7 @@ public class BinaryRoutePlanner {
}
// check if interrupted
if(ctx.interruptable != null && ctx.interruptable.isCancelled()) {
if(ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) {
throw new InterruptedException("Route calculation interrupted");
}
}
@ -344,6 +194,30 @@ public class BinaryRoutePlanner {
}
private void printMemoryConsumption( String string) {
long h1 = RoutingContext.runGCUsedMemory();
float mb = (1 << 20);
log.warn(string + h1 / mb);
}
private void updateCalculationProgress(final RoutingContext ctx, PriorityQueue<RouteSegment> graphDirectSegments,
PriorityQueue<RouteSegment> graphReverseSegments) {
if(ctx.calculationProgress != null) {
ctx.calculationProgress.reverseSegmentQueueSize = graphReverseSegments.size();
ctx.calculationProgress.directSegmentQueueSize = graphDirectSegments.size();
if(graphDirectSegments.size() > 0) {
ctx.calculationProgress.distanceFromBegin =
Math.max(graphDirectSegments.peek().distanceFromStart, ctx.calculationProgress.distanceFromBegin);
}
if(graphDirectSegments.size() > 0) {
ctx.calculationProgress.distanceFromEnd =
Math.max(graphReverseSegments.peek().distanceFromStart, ctx.calculationProgress.distanceFromBegin);
}
}
}
private RouteSegment smartRecalculationEnabled(final RoutingContext ctx, TLongObjectHashMap<RouteSegment> visitedOppositeSegments) {
boolean runRecalculation = ctx.previouslyCalculatedRoute != null && ctx.previouslyCalculatedRoute.size() > 0
&& ctx.config.recalculateDistance != 0;

View file

@ -4,7 +4,6 @@ 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;
@ -15,6 +14,7 @@ import net.osmand.LogUtil;
import net.osmand.binary.BinaryMapRouteReaderAdapter;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.RouteDataObject;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapRenderingTypes;
import net.osmand.osm.MapUtils;
import net.osmand.router.BinaryRoutePlanner.FinalRouteSegment;
@ -35,200 +35,18 @@ public class BinaryRoutePlannerOld {
private static double squareRootDist(int x1, int y1, int x2, int y2) {
// translate into meters
double dy = convert31YToMeters(y1, y2);
double dx = convert31XToMeters(x1, x2);
double dy = MapUtils.convert31YToMeters(y1, y2);
double dx = MapUtils.convert31XToMeters(x1, x2);
return Math.sqrt(dx * dx + dy * dy);
// return measuredDist(x1, y1, x2, y2);
}
private static double measuredDist(int x1, int y1, int x2, int y2) {
return MapUtils.getDistance(MapUtils.get31LatitudeY(y1), MapUtils.get31LongitudeX(x1),
MapUtils.get31LatitudeY(y2), MapUtils.get31LongitudeX(x2));
}
private static double squareDist(int x1, int y1, int x2, int y2) {
// translate into meters
double dy = convert31YToMeters(y1, y2);
double dx = convert31XToMeters(x1, x2);
return dx * dx + dy * dy;
}
private static double convert31YToMeters(int y1, int y2) {
// translate into meters
return (y1 - y2) * 0.01863d;
}
private static double convert31XToMeters(int x1, int x2) {
// translate into meters
return (x1 - x2) * 0.011d;
}
private static double calculateProjection(int xA, int yA, int xB, int yB, int xC, int yC) {
// Scalar multiplication between (AB, AC)
double multiple = convert31XToMeters(xB, xA) * convert31XToMeters(xC, xA) + convert31YToMeters(yB, yA) * convert31YToMeters(yC, yA);
return multiple;
}
public RouteSegment findRouteSegment(double lat, double lon, RoutingContext ctx) throws IOException {
int px = MapUtils.get31TileNumberX(lon);
int py = MapUtils.get31TileNumberY(lat);
ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
ctx.loadTileData(px, py, 17, dataObjects);
if (dataObjects.isEmpty()) {
ctx.loadTileData(px, py, 15, dataObjects);
}
RouteSegment road = null;
double sdist = 0;
int foundProjX = 0;
int foundProjY = 0;
for (RouteDataObject r : dataObjects) {
if (r.getPointsLength() > 1) {
for (int j = 1; j < r.getPointsLength(); j++) {
double mDist = squareRootDist(r.getPoint31XTile(j), r.getPoint31YTile(j), r.getPoint31XTile(j - 1),
r.getPoint31YTile(j - 1));
int prx = r.getPoint31XTile(j);
int pry = r.getPoint31YTile(j);
double projection = calculateProjection(r.getPoint31XTile(j - 1), r.getPoint31YTile(j - 1), r.getPoint31XTile(j),
r.getPoint31YTile(j), px, py);
if (projection < 0) {
prx = r.getPoint31XTile(j - 1);
pry = r.getPoint31YTile(j - 1);
} else if (projection >= mDist * mDist) {
prx = r.getPoint31XTile(j);
pry = r.getPoint31YTile(j);
} else {
prx = (int) (r.getPoint31XTile(j - 1) + (r.getPoint31XTile(j) - r.getPoint31XTile(j - 1))
* (projection / (mDist * mDist)));
pry = (int) (r.getPoint31YTile(j - 1) + (r.getPoint31YTile(j) - r.getPoint31YTile(j - 1))
* (projection / (mDist * mDist)));
}
double currentsDist = squareDist(prx, pry, px, py);
if (road == null || currentsDist < sdist) {
RouteDataObject ro = new RouteDataObject(r);
road = new RouteSegment(ro, j);
ro.insert(j, prx, pry);
sdist = currentsDist;
foundProjX = prx;
foundProjY = pry;
}
}
}
}
if (road != null) {
// re-register the best road because one more point was inserted
ctx.registerRouteDataObject(road.getRoad());
}
return road;
}
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, List<RouteSegment> intermediate, boolean leftSideNavigation) throws IOException, InterruptedException {
if(intermediate != null && intermediate.size() > 0) {
ArrayList<RouteSegment> ps = new ArrayList<RouteSegment>(intermediate);
ArrayList<RouteSegmentResult> firstPartRecalculatedRoute = null;
ArrayList<RouteSegmentResult> restPartRecalculatedRoute = null;
if (ctx.previouslyCalculatedRoute != null) {
List<RouteSegmentResult> prev = ctx.previouslyCalculatedRoute;
long id = intermediate.get(0).getRoad().id;
int ss = intermediate.get(0).getSegmentStart();
for (int i = 0; i < prev.size(); i++) {
RouteSegmentResult rsr = prev.get(i);
if (id == rsr.getObject().getId() && ss == rsr.getEndPointIndex()) {
firstPartRecalculatedRoute = new ArrayList<RouteSegmentResult>(prev.subList(0, i + 1));
restPartRecalculatedRoute = new ArrayList<RouteSegmentResult>(prev.subList(i + 1, prev.size()));
break;
}
}
}
ps.add(end);
ps.add(0, start);
List<RouteSegmentResult> results = new ArrayList<RouteSegmentResult>();
for (int i = 0; i < ps.size() - 1; i++) {
RoutingContext local = new RoutingContext(ctx);
if(i == 0) {
local.previouslyCalculatedRoute = firstPartRecalculatedRoute;
}
local.visitor = ctx.visitor;
List<RouteSegmentResult> res = searchRouteInternalPrepare(local, ps.get(i), ps.get(i + 1), leftSideNavigation);
results.addAll(res);
ctx.distinctLoadedTiles += local.distinctLoadedTiles;
ctx.loadedTiles += local.loadedTiles;
ctx.visitedSegments += local.visitedSegments;
ctx.loadedPrevUnloadedTiles += local.loadedPrevUnloadedTiles;
ctx.timeToCalculate += local.timeToCalculate;
ctx.timeToLoad += local.timeToLoad;
ctx.timeToLoadHeaders += local.timeToLoadHeaders;
ctx.relaxedSegments += local.relaxedSegments;
local.unloadAllData(ctx);
if(restPartRecalculatedRoute != null) {
results.addAll(restPartRecalculatedRoute);
break;
}
}
ctx.unloadAllData();
new RouteResultPreparation().printResults(ctx, start, end, results);
return results;
}
return searchRoute(ctx, start, end, leftSideNavigation);
}
@SuppressWarnings("static-access")
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
if(ctx.SHOW_GC_SIZE){
long h1 = ctx.runGCUsedMemory();
float mb = (1 << 20);
log.warn("Used before routing " + h1 / mb+ " actual");
}
List<RouteSegmentResult> result = searchRouteInternalPrepare(ctx, start, end, leftSideNavigation);
if(result != null) {
new RouteResultPreparation().printResults(ctx, start, end, result);
}
if (RoutingContext.SHOW_GC_SIZE) {
int sz = ctx.global.size;
log.warn("Subregion size " + ctx.subregionTiles.size() + " " + " tiles " + ctx.indexedSubregions.size());
ctx.runGCUsedMemory();
long h1 = ctx.runGCUsedMemory();
ctx.unloadAllData();
ctx.runGCUsedMemory();
long h2 = ctx.runGCUsedMemory();
float mb = (1 << 20);
log.warn("Unload context : estimated " + sz / mb + " ?= " + (h1 - h2) / mb + " actual");
}
return result;
}
private List<RouteSegmentResult> searchRouteInternalPrepare(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
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) throws IOException, InterruptedException {
void searchRouteInternal(final RoutingContext ctx, RouteSegment start, RouteSegment end) throws IOException, InterruptedException {
// measure time
ctx.timeToLoad = 0;
ctx.visitedSegments = 0;
@ -324,6 +142,7 @@ public class BinaryRoutePlannerOld {
if (ctx.visitor != null) {
// ctx.visitor.visitSegment(segment, true);
}
updateCalculationProgress(ctx, graphDirectSegments, graphReverseSegments);
boolean routeFound = false;
if (!inverse) {
routeFound = processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, targetEndX, targetEndY,
@ -358,7 +177,7 @@ public class BinaryRoutePlannerOld {
graphSegments = graphDirectSegments;
}
// check if interrupted
if(ctx.interruptable != null && ctx.interruptable.isCancelled()) {
if(ctx.calculationProgress != null && ctx.calculationProgress.isCancelled) {
throw new InterruptedException("Route calculation interrupted");
}
}
@ -366,9 +185,23 @@ public class BinaryRoutePlannerOld {
printDebugMemoryInformation(ctx, graphDirectSegments, graphReverseSegments, visitedDirectSegments, visitedOppositeSegments);
}
private void updateCalculationProgress(final RoutingContext ctx, PriorityQueue<RouteSegment> graphDirectSegments,
PriorityQueue<RouteSegment> graphReverseSegments) {
if(ctx.calculationProgress != null) {
ctx.calculationProgress.reverseSegmentQueueSize = graphReverseSegments.size();
ctx.calculationProgress.directSegmentQueueSize = graphDirectSegments.size();
if(graphDirectSegments.size() > 0) {
ctx.calculationProgress.distanceFromBegin =
Math.max(graphDirectSegments.peek().distanceFromStart, ctx.calculationProgress.distanceFromBegin);
}
if(graphDirectSegments.size() > 0) {
ctx.calculationProgress.distanceFromEnd =
Math.max(graphReverseSegments.peek().distanceFromStart, ctx.calculationProgress.distanceFromBegin);
}
}
}
private double h(final RoutingContext ctx, int targetEndX, int targetEndY,
int startX, int startY) {
double distance = squareRootDist(startX, startY, targetEndX, targetEndY);
@ -380,8 +213,6 @@ public class BinaryRoutePlannerOld {
return result;
}
private static void println(String logMsg) {
// log.info(logMsg);
System.out.println(logMsg);

View file

@ -1,7 +0,0 @@
package net.osmand.router;
public interface Interruptable {
public boolean isCancelled();
}

View file

@ -0,0 +1,14 @@
package net.osmand.router;
public class RouteCalculationProgress {
public int segmentNotFound = -1;
public float distanceFromBegin;
public int directSegmentQueueSize;
public float distanceFromEnd;
public int reverseSegmentQueueSize;
public float totalEstimatedDistance = 0;
public boolean isCancelled;
}

View file

@ -0,0 +1,266 @@
package net.osmand.router;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.logging.Log;
import net.osmand.LogUtil;
import net.osmand.binary.BinaryMapRouteReaderAdapter;
import net.osmand.binary.RouteDataObject;
import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
public class RoutePlannerFrontEnd {
private boolean useOldVersion;
protected static final Log log = LogUtil.getLog(BinaryRoutePlannerOld.class);
public RoutePlannerFrontEnd(boolean useOldVersion) {
this.useOldVersion = useOldVersion;
}
private static double squareRootDist(int x1, int y1, int x2, int y2) {
// translate into meters
double dy = MapUtils.convert31YToMeters(y1, y2);
double dx = MapUtils.convert31XToMeters(x1, x2);
return Math.sqrt(dx * dx + dy * dy);
// return measuredDist(x1, y1, x2, y2);
}
private static double calculateProjection(int xA, int yA, int xB, int yB, int xC, int yC) {
// Scalar multiplication between (AB, AC)
double multiple = MapUtils.convert31XToMeters(xB, xA) * MapUtils.convert31XToMeters(xC, xA) +
MapUtils.convert31YToMeters(yB, yA) * MapUtils.convert31YToMeters(yC, yA);
return multiple;
}
private static double squareDist(int x1, int y1, int x2, int y2) {
// translate into meters
double dy = MapUtils.convert31YToMeters(y1, y2);
double dx = MapUtils. convert31XToMeters(x1, x2);
return dx * dx + dy * dy;
}
public RouteSegment findRouteSegment(double lat, double lon, RoutingContext ctx) throws IOException {
int px = MapUtils.get31TileNumberX(lon);
int py = MapUtils.get31TileNumberY(lat);
ArrayList<RouteDataObject> dataObjects = new ArrayList<RouteDataObject>();
ctx.loadTileData(px, py, 17, dataObjects);
if (dataObjects.isEmpty()) {
ctx.loadTileData(px, py, 15, dataObjects);
}
RouteSegment road = null;
double sdist = 0;
int foundProjX = 0;
int foundProjY = 0;
for (RouteDataObject r : dataObjects) {
if (r.getPointsLength() > 1) {
for (int j = 1; j < r.getPointsLength(); j++) {
double mDist = squareRootDist(r.getPoint31XTile(j), r.getPoint31YTile(j), r.getPoint31XTile(j - 1),
r.getPoint31YTile(j - 1));
int prx = r.getPoint31XTile(j);
int pry = r.getPoint31YTile(j);
double projection = calculateProjection(r.getPoint31XTile(j - 1), r.getPoint31YTile(j - 1), r.getPoint31XTile(j),
r.getPoint31YTile(j), px, py);
if (projection < 0) {
prx = r.getPoint31XTile(j - 1);
pry = r.getPoint31YTile(j - 1);
} else if (projection >= mDist * mDist) {
prx = r.getPoint31XTile(j);
pry = r.getPoint31YTile(j);
} else {
prx = (int) (r.getPoint31XTile(j - 1) + (r.getPoint31XTile(j) - r.getPoint31XTile(j - 1))
* (projection / (mDist * mDist)));
pry = (int) (r.getPoint31YTile(j - 1) + (r.getPoint31YTile(j) - r.getPoint31YTile(j - 1))
* (projection / (mDist * mDist)));
}
double currentsDist = squareDist(prx, pry, px, py);
if (road == null || currentsDist < sdist) {
RouteDataObject ro = new RouteDataObject(r);
road = new RouteSegment(ro, j);
ro.insert(j, prx, pry);
sdist = currentsDist;
foundProjX = prx;
foundProjY = pry;
}
}
}
}
if (road != null) {
// re-register the best road because one more point was inserted
ctx.registerRouteDataObject(road.getRoad());
}
return road;
}
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, LatLon start, LatLon end, List<LatLon> intermediates, boolean leftSideNavigation) throws IOException, InterruptedException {
if(ctx.calculationProgress == null) {
ctx.calculationProgress = new RouteCalculationProgress();
}
if((intermediates == null || intermediates.isEmpty()) && useOldVersion && ctx.nativeLib != null) {
ctx.startX = MapUtils.get31TileNumberX(start.getLongitude());
ctx.startY = MapUtils.get31TileNumberY(start.getLatitude());
ctx.targetX = MapUtils.get31TileNumberX(end.getLongitude());
ctx.targetY = MapUtils.get31TileNumberY(end.getLatitude());
List<RouteSegmentResult> res = runNativeRouting(ctx, leftSideNavigation);
if(res != null) {
new RouteResultPreparation().printResults(ctx, start, end, res);
}
return res;
}
int indexNotFound = 0;
List<RouteSegment> points = new ArrayList<BinaryRoutePlanner.RouteSegment>();
if(!addSegment(start, ctx, indexNotFound++, points)){
return null;
}
if (intermediates != null) {
for (LatLon l : intermediates) {
if (!addSegment(l, ctx, indexNotFound++, points)) {
return null;
}
}
}
if(!addSegment(end, ctx, indexNotFound++, points)){
return null;
}
List<RouteSegmentResult> res = searchRoute(ctx, points, leftSideNavigation);
if(res != null) {
new RouteResultPreparation().printResults(ctx, start, end, res);
}
return res;
}
private boolean addSegment(LatLon s, RoutingContext ctx, int indexNotFound, List<RouteSegment> res) throws IOException {
RouteSegment f = findRouteSegment(s.getLatitude(), s.getLongitude(), ctx);
if(f == null){
ctx.calculationProgress.segmentNotFound = indexNotFound;
return false;
} else {
log.info("Route segment found " + f.getRoad().id + " " + f.getRoad().getName());
res.add(f);
return true;
}
}
private List<RouteSegmentResult> searchRouteInternalPrepare(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
ctx.targetX = end.road.getPoint31XTile(end.getSegmentStart());
ctx.targetY = end.road.getPoint31YTile(end.getSegmentStart());
ctx.startX = start.road.getPoint31XTile(start.getSegmentStart());
ctx.startY = start.road.getPoint31YTile(start.getSegmentStart());
if (ctx.nativeLib != null && useOldVersion) {
return runNativeRouting(ctx, leftSideNavigation);
} else {
refreshProgressDistance(ctx);
// Split into 2 methods to let GC work in between
if(useOldVersion) {
new BinaryRoutePlannerOld().searchRouteInternal(ctx, start, end);
} else {
ctx.finalRouteSegment = new BinaryRoutePlanner().searchRouteInternal(ctx, start, end);
}
// 4. Route is found : collect all segments and prepare result
return new RouteResultPreparation().prepareResult(ctx, ctx.finalRouteSegment, leftSideNavigation);
}
}
private void refreshProgressDistance(RoutingContext ctx) {
if(ctx.calculationProgress != null) {
ctx.calculationProgress.distanceFromBegin = 0;
ctx.calculationProgress.distanceFromEnd = 0;
ctx.calculationProgress.reverseSegmentQueueSize = 0;
ctx.calculationProgress.directSegmentQueueSize = 0;
float rd = (float) squareRootDist(ctx.startX, ctx.startY, ctx.targetX, ctx.targetY);
float speed = 0.9f * ctx.config.router.getMaxDefaultSpeed();
ctx.calculationProgress.totalEstimatedDistance = (float) (rd / speed);
}
}
private List<RouteSegmentResult> runNativeRouting(final RoutingContext ctx, boolean leftSideNavigation) {
refreshProgressDistance(ctx);
RouteRegion[] regions = ctx.reverseMap.keySet().toArray(new BinaryMapRouteReaderAdapter.RouteRegion[ctx.reverseMap.size()]);
RouteSegmentResult[] res = ctx.nativeLib.runNativeRouting(ctx.startX, ctx.startY, ctx.targetX, ctx.targetY,
ctx.config, regions, ctx.calculationProgress);
ArrayList<RouteSegmentResult> result = new ArrayList<RouteSegmentResult>(Arrays.asList(res));
return new RouteResultPreparation().prepareResult(ctx, leftSideNavigation, result);
}
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, List<RouteSegment> points, boolean leftSideNavigation) throws IOException, InterruptedException {
if(points.size() > 2) {
ArrayList<RouteSegmentResult> firstPartRecalculatedRoute = null;
ArrayList<RouteSegmentResult> restPartRecalculatedRoute = null;
if (ctx.previouslyCalculatedRoute != null) {
List<RouteSegmentResult> prev = ctx.previouslyCalculatedRoute;
long id = points.get(1).getRoad().id;
int ss = points.get(1).getSegmentStart();
for (int i = 0; i < prev.size(); i++) {
RouteSegmentResult rsr = prev.get(i);
if (id == rsr.getObject().getId() && ss == rsr.getEndPointIndex()) {
firstPartRecalculatedRoute = new ArrayList<RouteSegmentResult>(prev.subList(0, i + 1));
restPartRecalculatedRoute = new ArrayList<RouteSegmentResult>(prev.subList(i + 1, prev.size()));
break;
}
}
}
List<RouteSegmentResult> results = new ArrayList<RouteSegmentResult>();
for (int i = 0; i < points.size() - 1; i++) {
RoutingContext local = new RoutingContext(ctx);
if(i == 0) {
local.previouslyCalculatedRoute = firstPartRecalculatedRoute;
}
local.visitor = ctx.visitor;
List<RouteSegmentResult> res = searchRouteInternalPrepare(local, points.get(i), points.get(i + 1), leftSideNavigation);
results.addAll(res);
ctx.distinctLoadedTiles += local.distinctLoadedTiles;
ctx.loadedTiles += local.loadedTiles;
ctx.visitedSegments += local.visitedSegments;
ctx.loadedPrevUnloadedTiles += local.loadedPrevUnloadedTiles;
ctx.timeToCalculate += local.timeToCalculate;
ctx.timeToLoad += local.timeToLoad;
ctx.timeToLoadHeaders += local.timeToLoadHeaders;
ctx.relaxedSegments += local.relaxedSegments;
local.unloadAllData(ctx);
if(restPartRecalculatedRoute != null) {
results.addAll(restPartRecalculatedRoute);
break;
}
}
ctx.unloadAllData();
return results;
}
return searchRoute(ctx, points.get(0), points.get(1), leftSideNavigation);
}
@SuppressWarnings("static-access")
public List<RouteSegmentResult> searchRoute(final RoutingContext ctx, RouteSegment start, RouteSegment end, boolean leftSideNavigation) throws IOException, InterruptedException {
if(ctx.SHOW_GC_SIZE){
long h1 = ctx.runGCUsedMemory();
float mb = (1 << 20);
log.warn("Used before routing " + h1 / mb+ " actual");
}
List<RouteSegmentResult> result = searchRouteInternalPrepare(ctx, start, end, leftSideNavigation);
if (RoutingContext.SHOW_GC_SIZE) {
int sz = ctx.global.size;
log.warn("Subregion size " + ctx.subregionTiles.size() + " " + " tiles " + ctx.indexedSubregions.size());
ctx.runGCUsedMemory();
long h1 = ctx.runGCUsedMemory();
ctx.unloadAllData();
ctx.runGCUsedMemory();
long h2 = ctx.runGCUsedMemory();
float mb = (1 << 20);
log.warn("Unload context : estimated " + sz / mb + " ?= " + (h1 - h2) / mb + " actual");
}
return result;
}
}

View file

@ -8,6 +8,7 @@ import java.util.Iterator;
import java.util.List;
import net.osmand.binary.RouteDataObject;
import net.osmand.osm.LatLon;
import net.osmand.osm.MapUtils;
import net.osmand.router.BinaryRoutePlanner.FinalRouteSegment;
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
@ -184,7 +185,7 @@ public class RouteResultPreparation {
return false;
}
void printResults(RoutingContext ctx, RouteSegment start, RouteSegment end, List<RouteSegmentResult> result) {
void printResults(RoutingContext ctx, LatLon start, LatLon end, List<RouteSegmentResult> result) {
float completeTime = 0;
float completeDistance = 0;
for(RouteSegmentResult r : result) {
@ -193,10 +194,10 @@ public class RouteResultPreparation {
}
println("ROUTE : ");
double startLat = MapUtils.get31LatitudeY(start.road.getPoint31YTile(start.getSegmentStart()));
double startLon = MapUtils.get31LongitudeX(start.road.getPoint31XTile(start.getSegmentStart()));
double endLat = MapUtils.get31LatitudeY(end.road.getPoint31YTile(end.getSegmentStart()));
double endLon = MapUtils.get31LongitudeX(end.road.getPoint31XTile(end.getSegmentStart()));
double startLat = start.getLatitude();
double startLon = start.getLongitude();
double endLat = end.getLatitude();
double endLon = end.getLongitude();
StringBuilder add = new StringBuilder();
add.append("loadedTiles = \"").append(ctx.loadedTiles).append("\" ");
add.append("visitedSegments = \"").append(ctx.visitedSegments).append("\" ");

View file

@ -62,7 +62,7 @@ public class RoutingContext {
public int targetX;
public int targetY;
public Interruptable interruptable;
public RouteCalculationProgress calculationProgress;
public List<RouteSegmentResult> previouslyCalculatedRoute;
public BaseRouteResult baseRouteResult;

View file

@ -28,6 +28,7 @@ import net.osmand.osm.MapUtils;
import net.osmand.osm.Node;
import net.osmand.osm.Way;
import net.osmand.router.BinaryRoutePlanner;
import net.osmand.router.RoutePlannerFrontEnd;
import net.osmand.router.RoutingConfiguration;
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
import net.osmand.router.BinaryRoutePlanner.RouteSegmentVisitor;
@ -141,7 +142,7 @@ public class MapClusterLayer implements MapPanelLayer {
rs.add(new BinaryMapIndexReader(raf));
}
}
BinaryRoutePlanner router = new BinaryRoutePlanner();
RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(true);
Builder builder = RoutingConfiguration.getDefault();
RoutingConfiguration config = builder.build("car", RoutingConfiguration.DEFAULT_MEMORY_LIMIT * 3);
RoutingContext ctx = new RoutingContext(config, NativeSwingRendering.getDefaultFromSettings(),

View file

@ -41,6 +41,7 @@ import net.osmand.router.BinaryRoutePlanner;
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
import net.osmand.router.BinaryRoutePlanner.RouteSegmentVisitor;
import net.osmand.router.BinaryRoutePlannerOld;
import net.osmand.router.RoutePlannerFrontEnd;
import net.osmand.router.RouteSegmentResult;
import net.osmand.router.RoutingConfiguration;
import net.osmand.router.RoutingConfiguration.Builder;
@ -611,159 +612,73 @@ public class MapRouterLayer implements MapPanelLayer {
}
String m = DataExtractionSettings.getSettings().getRouteMode();
String[] props = m.split("\\,");
BinaryRoutePlannerOld router = new BinaryRoutePlannerOld();
// BinaryRoutePlanner router = new BinaryRoutePlanner();
RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(true);
RoutingConfiguration config = builder.build(props[0], RoutingConfiguration.DEFAULT_MEMORY_LIMIT, props);
// config.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY = 300;
// config.ZOOM_TO_LOAD_TILES = 14;
RoutingContext ctx = new RoutingContext(config, NativeSwingRendering.getDefaultFromSettings(), rs, useBasemap);
final RoutingContext ctx = new RoutingContext(config, NativeSwingRendering.getDefaultFromSettings(), rs, useBasemap);
ctx.previouslyCalculatedRoute = previousRoute;
log.info("Use " + config.routerName + "mode for routing");
// find closest way
RouteSegment st = router.findRouteSegment(start.getLatitude(), start.getLongitude(), ctx);
if (st == null) {
throw new RuntimeException("Starting point for route not found");
}
log.info("Start road " + st.getRoad().getHighway() + " " + st.getRoad().id);
RouteSegment e = router.findRouteSegment(end.getLatitude(), end.getLongitude(), ctx);
if (e == null) {
throw new RuntimeException("End point to calculate route was not found");
}
log.info("End road " + e.getRoad().getHighway() + " " + e.getRoad().id);
List<RouteSegment> inters = new ArrayList<BinaryRoutePlanner.RouteSegment>();
if (intermediates != null) {
int ind = 1;
for (LatLon il : intermediates) {
RouteSegment is = router.findRouteSegment(il.getLatitude(), il.getLongitude(), ctx);
if (is == null) {
throw new RuntimeException("Intremediate point "+ind+" was not found.");
}
inters.add(is);
ind++;
}
}
final DataTileManager<Entity> points = new DataTileManager<Entity>(11);
map.setPoints(points);
ctx.setVisitor(new RouteSegmentVisitor() {
private List<RouteSegment> cache = new ArrayList<RouteSegment>();
private List<RouteSegment> pollCache = new ArrayList<RouteSegment>();
private List<Integer> cacheInt = new ArrayList<Integer>();
@Override
public void visitSegment(RouteSegment s, int endSegment, boolean poll) {
if(stop) {
throw new RuntimeException("Interrupted");
}
if (!animateRoutingCalculation) {
return;
}
if (!poll && pause) {
pollCache.add(s);
return;
}
cache.add(s);
cacheInt.add(endSegment);
if (cache.size() < steps) {
return;
}
if(pause) {
registerObjects(points, poll, pollCache, null);
pollCache.clear();
}
registerObjects(points, !poll, cache, cacheInt);
cache.clear();
cacheInt.clear();
redraw();
if (pause) {
waitNextPress();
}
}
private void registerObjects(final DataTileManager<Entity> points, boolean white, List<RouteSegment> registerCache,
List<Integer> cacheInt) {
for (int l = 0; l < registerCache.size(); l++) {
RouteSegment segment = registerCache.get(l);
Way way = new Way(-1);
way.putTag(OSMTagKey.NAME.getValue(), segment.getTestName());
if (white) {
way.putTag("color", "white");
}
int from = cacheInt != null ? segment.getSegmentStart() : segment.getSegmentStart() - 2;
int to = cacheInt != null ? cacheInt.get(l) : segment.getSegmentStart() + 2;
if(from > to) {
int x = from;
from = to;
to = x;
}
for (int i = from; i <= to; i++) {
if (i >= 0 && i < segment.getRoad().getPointsLength()) {
net.osmand.osm.Node n = createNode(segment, i);
way.addNode(n);
}
}
LatLon n = way.getLatLon();
points.registerObject(n.getLatitude(), n.getLongitude(), way);
}
}
});
ctx.setVisitor(createSegmentVisitor(animateRoutingCalculation, points));
// 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");
waitNextPress();
nextTurn.setText(">>");
}
net.osmand.osm.Node prevWayNode = null;
for (RouteSegmentResult s : searchRoute) {
// double dist = MapUtils.getDistance(s.startPoint, s.endPoint);
Way way = new Way(-1);
// String name = String.format("time %.2f ", s.getSegmentTime());
String name = s.getDescription();
if(s.getTurnType() != null) {
name += " (TA " + s.getTurnType().getTurnAngle() + ") ";
}
// String name = String.format("beg %.2f end %.2f ", s.getBearingBegin(), s.getBearingEnd());
way.putTag(OSMTagKey.NAME.getValue(),name);
boolean plus = s.getStartPointIndex() < s.getEndPointIndex();
int i = s.getStartPointIndex();
while (true) {
LatLon l = s.getPoint(i);
net.osmand.osm.Node n = new net.osmand.osm.Node(l.getLatitude(), l.getLongitude(), -1);
if (prevWayNode != null) {
if (MapUtils.getDistance(prevWayNode, n) > 0) {
System.out.println("Warning not connected road " + " " + s.getObject().id + " dist "
+ MapUtils.getDistance(prevWayNode, n));
new Thread(){
@Override
public void run() {
while(!ctx.calculationProgress.isCancelled) {
float p = ctx.calculationProgress.distanceFromBegin + ctx.calculationProgress.distanceFromEnd;
float all = ctx.calculationProgress.totalEstimatedDistance;
// while (p > all * 0.9) {
// all *= 1.2;
// }
if(all > 0 ) {
int t = (int) (p*p/(all*all)*100f);
// int t = (int) (p/all*100f);
System.out.println("Progress " + t + " % " +
ctx.calculationProgress.distanceFromBegin + " " + ctx.calculationProgress.distanceFromEnd+" " + all);
}
try {
sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
prevWayNode = null;
}
way.addNode(n);
if (i == s.getEndPointIndex()) {
break;
}
if (plus) {
i++;
} else {
i--;
};
}.start();
try {
List<RouteSegmentResult> searchRoute = router.searchRoute(ctx, start, end, intermediates, false);
if (searchRoute == null) {
String reason = "unknown";
if (ctx.calculationProgress.segmentNotFound >= 0) {
if (ctx.calculationProgress.segmentNotFound == 0) {
reason = " start point is too far from road";
} else {
reason = " target point " + ctx.calculationProgress.segmentNotFound + " is too far from road";
}
} else if (ctx.calculationProgress.directSegmentQueueSize == 0) {
reason = " route can not be found from start point (" + ctx.calculationProgress.distanceFromBegin / 1000f
+ " km)";
} else if (ctx.calculationProgress.reverseSegmentQueueSize == 0) {
reason = " route can not be found from end point (" + ctx.calculationProgress.distanceFromEnd / 1000f + " km)";
}
throw new RuntimeException("Route not found : " + reason);
}
if (way.getNodes().size() > 0) {
prevWayNode = way.getNodes().get(way.getNodes().size() - 1);
System.out.println("External native time " + (System.nanoTime() - nt) / 1e9f);
if (animateRoutingCalculation) {
playPauseButton.setVisible(false);
nextTurn.setText("FINISH");
waitNextPress();
nextTurn.setText(">>");
}
res.add(way);
calculateResult(res, searchRoute);
} finally {
ctx.calculationProgress.isCancelled = true;
}
} catch (Exception e) {
ExceptionHandler.handle(e);
@ -779,6 +694,116 @@ public class MapRouterLayer implements MapPanelLayer {
}
return res;
}
private void calculateResult(List<Way> res, List<RouteSegmentResult> searchRoute) {
net.osmand.osm.Node prevWayNode = null;
for (RouteSegmentResult s : searchRoute) {
// double dist = MapUtils.getDistance(s.startPoint, s.endPoint);
Way way = new Way(-1);
// String name = String.format("time %.2f ", s.getSegmentTime());
String name = s.getDescription();
if(s.getTurnType() != null) {
name += " (TA " + s.getTurnType().getTurnAngle() + ") ";
}
// String name = String.format("beg %.2f end %.2f ", s.getBearingBegin(), s.getBearingEnd());
way.putTag(OSMTagKey.NAME.getValue(),name);
boolean plus = s.getStartPointIndex() < s.getEndPointIndex();
int i = s.getStartPointIndex();
while (true) {
LatLon l = s.getPoint(i);
net.osmand.osm.Node n = new net.osmand.osm.Node(l.getLatitude(), l.getLongitude(), -1);
if (prevWayNode != null) {
if (MapUtils.getDistance(prevWayNode, n) > 0) {
System.out.println("Warning not connected road " + " " + s.getObject().id + " dist "
+ MapUtils.getDistance(prevWayNode, n));
}
prevWayNode = null;
}
way.addNode(n);
if (i == s.getEndPointIndex()) {
break;
}
if (plus) {
i++;
} else {
i--;
}
}
if (way.getNodes().size() > 0) {
prevWayNode = way.getNodes().get(way.getNodes().size() - 1);
}
res.add(way);
}
}
private RouteSegmentVisitor createSegmentVisitor(final boolean animateRoutingCalculation, final DataTileManager<Entity> points) {
return new RouteSegmentVisitor() {
private List<RouteSegment> cache = new ArrayList<RouteSegment>();
private List<RouteSegment> pollCache = new ArrayList<RouteSegment>();
private List<Integer> cacheInt = new ArrayList<Integer>();
@Override
public void visitSegment(RouteSegment s, int endSegment, boolean poll) {
if(stop) {
throw new RuntimeException("Interrupted");
}
if (!animateRoutingCalculation) {
return;
}
if (!poll && pause) {
pollCache.add(s);
return;
}
cache.add(s);
cacheInt.add(endSegment);
if (cache.size() < steps) {
return;
}
if(pause) {
registerObjects(points, poll, pollCache, null);
pollCache.clear();
}
registerObjects(points, !poll, cache, cacheInt);
cache.clear();
cacheInt.clear();
redraw();
if (pause) {
waitNextPress();
}
}
private void registerObjects(final DataTileManager<Entity> points, boolean white, List<RouteSegment> registerCache,
List<Integer> cacheInt) {
for (int l = 0; l < registerCache.size(); l++) {
RouteSegment segment = registerCache.get(l);
Way way = new Way(-1);
way.putTag(OSMTagKey.NAME.getValue(), segment.getTestName());
if (white) {
way.putTag("color", "white");
}
int from = cacheInt != null ? segment.getSegmentStart() : segment.getSegmentStart() - 2;
int to = cacheInt != null ? cacheInt.get(l) : segment.getSegmentStart() + 2;
if(from > to) {
int x = from;
from = to;
to = x;
}
for (int i = from; i <= to; i++) {
if (i >= 0 && i < segment.getRoad().getPointsLength()) {
net.osmand.osm.Node n = createNode(segment, i);
way.addNode(n);
}
}
LatLon n = way.getLatLon();
points.registerObject(n.getLatitude(), n.getLongitude(), way);
}
}
};
}
private net.osmand.osm.Node createNode(RouteSegment segment, int i) {
net.osmand.osm.Node n = new net.osmand.osm.Node(MapUtils.get31LatitudeY(segment.getRoad().getPoint31YTile(i)),

View file

@ -6,7 +6,7 @@ import net.osmand.osm.LatLon;
import net.osmand.plus.activities.ApplicationMode;
import net.osmand.plus.routing.RouteProvider.GPXRouteParams;
import net.osmand.plus.routing.RouteProvider.RouteService;
import net.osmand.router.Interruptable;
import net.osmand.router.RouteCalculationProgress;
import android.content.Context;
import android.location.Location;
@ -24,5 +24,5 @@ public class RouteCalcuationParams {
public boolean fast;
public boolean optimal;
public boolean leftSide;
public Interruptable interruptable;
public RouteCalculationProgress calculationProgress;
}

View file

@ -35,11 +35,9 @@ import net.osmand.plus.R;
import net.osmand.plus.ResourceManager;
import net.osmand.plus.activities.ApplicationMode;
import net.osmand.plus.render.NativeOsmandLibrary;
import net.osmand.router.BinaryRoutePlanner;
import net.osmand.router.BinaryRoutePlanner.RouteSegment;
import net.osmand.router.GeneralRouter;
import net.osmand.router.GeneralRouter.GeneralRouterProfile;
import net.osmand.router.BinaryRoutePlannerOld;
import net.osmand.router.RoutePlannerFrontEnd;
import net.osmand.router.RouteSegmentResult;
import net.osmand.router.RoutingConfiguration;
import net.osmand.router.RoutingContext;
@ -311,7 +309,7 @@ public class RouteProvider {
protected RouteCalculationResult findVectorMapsRoute(RouteCalcuationParams params) throws IOException {
OsmandApplication app = (OsmandApplication) params.ctx.getApplicationContext();
BinaryMapIndexReader[] files = app.getResourceManager().getRoutingMapFiles();
BinaryRoutePlannerOld router = new BinaryRoutePlannerOld();
RoutePlannerFrontEnd router = new RoutePlannerFrontEnd(true);
File routingXml = app.getSettings().extendOsmandPath(ResourceManager.ROUTING_XML);
RoutingConfiguration.Builder config ;
if (routingXml.exists() && routingXml.canRead()) {
@ -364,39 +362,34 @@ public class RouteProvider {
cf.attributes.put("heuristicCoefficient", cf.heuristicCoefficient+"");
}
RoutingContext ctx = new RoutingContext(cf, NativeOsmandLibrary.getLoadedLibrary(), files);
ctx.interruptable = params.interruptable;
ctx.calculationProgress = params.calculationProgress;
if(params.previousToRecalculate != null) {
ctx.previouslyCalculatedRoute = params.previousToRecalculate.getOriginalRoute();
}
RouteSegment st= router.findRouteSegment(params.start.getLatitude(), params.start.getLongitude(), ctx);
if (st == null) {
return new RouteCalculationResult(app.getString(R.string.starting_point_too_far));
}
RouteSegment en = router.findRouteSegment(params.end.getLatitude(),
params.end.getLongitude(), ctx);
if (en == null) {
return new RouteCalculationResult(app.getString(R.string.ending_point_too_far));
}
List<RouteSegment> inters = new ArrayList<BinaryRoutePlanner.RouteSegment>();
LatLon st = new LatLon(params.start.getLatitude(), params.start.getLongitude());
LatLon en = new LatLon(params.end.getLatitude(), params.end.getLongitude());
List<LatLon> inters = new ArrayList<LatLon>();
if (params.intermediates != null) {
int ind = 1;
for (LatLon il : params.intermediates) {
RouteSegment is = router.findRouteSegment(il.getLatitude(), il.getLongitude(), ctx);
if (is == null) {
return new RouteCalculationResult(app.getString(R.string.intermediate_point_too_far, "'" + ind + "'"));
}
inters.add(is);
ind++;
}
inters = new ArrayList<LatLon>(params.intermediates);
}
try {
List<RouteSegmentResult> result;
if(inters.size() > 0){
result = router.searchRoute(ctx, st, en, inters, params.leftSide);
} else {
result = router.searchRoute(ctx, st, en, params.leftSide);
}
List<RouteSegmentResult> result = router.searchRoute(ctx, st, en, inters, params.leftSide);
if(result == null || result.isEmpty()) {
if(ctx.calculationProgress.segmentNotFound == 0) {
return new RouteCalculationResult(app.getString(R.string.starting_point_too_far));
} else if(ctx.calculationProgress.segmentNotFound == inters.size() + 1) {
return new RouteCalculationResult(app.getString(R.string.ending_point_too_far));
} else if(ctx.calculationProgress.segmentNotFound > 0) {
return new RouteCalculationResult(app.getString(R.string.intermediate_point_too_far, "'" + ctx.calculationProgress.segmentNotFound + "'"));
}
if(ctx.calculationProgress.directSegmentQueueSize == 0) {
return new RouteCalculationResult("Route can not be found from start point (" +ctx.calculationProgress.distanceFromBegin/1000f+" km)");
} else if(ctx.calculationProgress.reverseSegmentQueueSize == 0) {
return new RouteCalculationResult("Route can not be found from end point (" +ctx.calculationProgress.distanceFromEnd/1000f+" km)");
}
if(ctx.calculationProgress.isCancelled) {
return new RouteCalculationResult("Route calculation was interrupted");
}
// something really strange better to see that message on the scren
return new RouteCalculationResult("Empty result");
} else {

View file

@ -20,7 +20,7 @@ import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
import net.osmand.plus.routing.RouteProvider.GPXRouteParams;
import net.osmand.plus.routing.RouteProvider.RouteService;
import net.osmand.plus.voice.CommandPlayer;
import net.osmand.router.Interruptable;
import net.osmand.router.RouteCalculationProgress;
import net.osmand.router.RouteSegmentResult;
import android.content.Context;
import android.content.Intent;
@ -567,7 +567,7 @@ public class RoutingHelper {
private class RouteRecalculationThread extends Thread implements Interruptable {
private class RouteRecalculationThread extends Thread {
private boolean interrupted = false;
private final RouteCalcuationParams params;
@ -575,23 +575,21 @@ public class RoutingHelper {
public RouteRecalculationThread(String name, RouteCalcuationParams params) {
super(name);
this.params = params;
params.interruptable = this;
if(params.calculationProgress == null) {
params.calculationProgress = new RouteCalculationProgress();
}
}
public void stopCalculation(){
interrupted = true;
params.calculationProgress.isCancelled = true;
}
@Override
public boolean isCancelled() {
return interrupted;
}
@Override
public void run() {
RouteCalculationResult res = provider.calculateRouteImpl(params);
if (interrupted) {
if (params.calculationProgress.isCancelled) {
currentRunningJob = null;
return;
}

View file

@ -18,18 +18,17 @@ 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) {
inline int roadPriorityComparator(float o1DistanceFromStart, float o1DistanceToEnd, float o2DistanceFromStart,
float o2DistanceToEnd, float heuristicCoefficient) {
// f(x) = g(x) + h(x) --- g(x) - distanceFromStart, h(x) - distanceToEnd (not exact)
float f1 = o1DistanceFromStart + heuristicCoefficient * o1DistanceToEnd;
float f2 = o2DistanceFromStart + heuristicCoefficient * o2DistanceToEnd;
if(f1 == f2) {
if (f1 == f2) {
return 0;
}
return f1 < f2 ? -1 : 1;
}
// translate into meters
static double squareRootDist(int x1, int y1, int x2, int y2) {
double dy = convert31YToMeters(y1, y2);
@ -38,7 +37,6 @@ static double squareRootDist(int x1, int y1, int x2, int y2) {
// return measuredDist(x1, y1, x2, y2);
}
static double squareDist(int x1, int y1, int x2, int y2) {
// translate into meters
double dy = convert31YToMeters(y1, y2);
@ -50,65 +48,59 @@ static double h(RoutingContext* ctx, float distanceToFinalPoint, SHARED_PTR<Rout
return distanceToFinalPoint / ctx->config.getMaxDefaultSpeed();
}
static double h(RoutingContext* ctx, int targetEndX, int targetEndY,
int startX, int startY) {
static double h(RoutingContext* ctx, int targetEndX, int targetEndY, int startX, int startY) {
double distance = squareRootDist(startX, startY, targetEndX, targetEndY);
return distance / ctx->config.getMaxDefaultSpeed();
}
struct SegmentsComparator : public std::binary_function<SHARED_PTR<RouteSegment>, SHARED_PTR<RouteSegment>, bool>
struct SegmentsComparator: public std::binary_function<SHARED_PTR<RouteSegment>, SHARED_PTR<RouteSegment>, bool>
{
RoutingContext* ctx;
SegmentsComparator(RoutingContext* c) : ctx(c){
SegmentsComparator(RoutingContext* c) : ctx(c) {
}
bool operator()(const SHARED_PTR<RouteSegment> lhs, const SHARED_PTR<RouteSegment> rhs) const
{
{
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>
struct NonHeuristicSegmentsComparator: public std::binary_function<SHARED_PTR<RouteSegment>, SHARED_PTR<RouteSegment>, bool>
{
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, 0.5) > 0;
}
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, 0.5) > 0;
}
};
typedef UNORDERED(map)<int64_t, SHARED_PTR<RouteSegment> > VISITED_MAP;
typedef priority_queue<SHARED_PTR<RouteSegment>, vector<SHARED_PTR<RouteSegment> >, SegmentsComparator > SEGMENTS_QUEUE;
bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch,
SEGMENTS_QUEUE& graphSegments, VISITED_MAP& visitedSegments, int targetEndX, int targetEndY,
SHARED_PTR<RouteSegment> segment, VISITED_MAP& oppositeSegments);
bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
VISITED_MAP& visitedSegments, VISITED_MAP& oppositeSegments,
double distFromStart, double distToFinalPoint,
SHARED_PTR<RouteSegment> segment, int segmentEnd, SHARED_PTR<RouteSegment> inputNext,
bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, SEGMENTS_QUEUE& graphSegments,
VISITED_MAP& visitedSegments, int targetEndX, int targetEndY, SHARED_PTR<RouteSegment> segment, VISITED_MAP&oppositeSegments);
bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments, VISITED_MAP& visitedSegments,
VISITED_MAP& oppositeSegments, double distFromStart, double distToFinalPoint, 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> > );
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
*/
/**
* 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;
int iterationsToUpdate = 0;
ctx->timeToCalculate.start();
if(ctx->config.initialDirection != -360) {
if(ctx->config.initialDirection > -180 && ctx->config.initialDirection < 180) {
ctx->firstRoadId = (start->road->id << ROUTE_POINTS) + start->getSegmentStart();
double plusDir = start->road->directionRoute(start->getSegmentStart(), true);
double diff = plusDir - ctx->config.initialDirection;
@ -125,7 +117,7 @@ void searchRouteInternal(RoutingContext* ctx, SHARED_PTR<RouteSegment> start, SH
SEGMENTS_QUEUE graphReverseSegments(sgmCmp);
// Set to not visit one segment twice (stores road.id << X + segmentStart)
VISITED_MAP visitedDirectSegments ;
VISITED_MAP visitedDirectSegments;
VISITED_MAP visitedOppositeSegments;
// FIXME run recalculation
@ -164,6 +156,16 @@ void searchRouteInternal(RoutingContext* ctx, SHARED_PTR<RouteSegment> start, SH
routeFound = processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments, startX, startY, segment,
visitedDirectSegments);
}
if(ctx->progress.get() && iterationsToUpdate-- < 0) {
iterationsToUpdate = 100;
ctx->progress->updateStatus(graphDirectSegments.empty()? 0 :graphDirectSegments.top()->distanceFromStart,
graphDirectSegments.size(),
graphReverseSegments.empty()? 0 :graphReverseSegments.top()->distanceFromStart,
graphReverseSegments.size());
if(ctx->progress->isCancelled()) {
break;
}
}
if (graphReverseSegments.size() == 0 || graphDirectSegments.size() == 0 || routeFound) {
break;
}
@ -200,16 +202,13 @@ void searchRouteInternal(RoutingContext* ctx, SHARED_PTR<RouteSegment> start, SH
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);
, 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) {
bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, SEGMENTS_QUEUE& graphSegments,
VISITED_MAP& visitedSegments, int targetEndX, int targetEndY, SHARED_PTR<RouteSegment> segment, VISITED_MAP&oppositeSegments) {
// Always start from segmentStart (!), not from segmentEnd
// It makes difference only for the first start segment
// Middle point will always be skipped from observation considering already visited
@ -380,7 +379,7 @@ bool proccessRestrictions(RoutingContext* ctx, SHARED_PTR<RouteDataObject> road,
// Check if there is restriction only to the other than current road
if (rt == RESTRICTION_ONLY_RIGHT_TURN || rt == RESTRICTION_ONLY_LEFT_TURN
|| rt == RESTRICTION_ONLY_STRAIGHT_ON) {
|| rt == RESTRICTION_ONLY_STRAIGHT_ON) {
// check if that restriction applies to considered junk
SHARED_PTR<RouteSegment> foundNext = inputNext;
while (foundNext.get() != NULL) {
@ -400,7 +399,7 @@ bool proccessRestrictions(RoutingContext* ctx, SHARED_PTR<RouteDataObject> road,
} else if (type == -1 && exclusiveRestriction) {
// next = next.next; continue;
} else if (type == RESTRICTION_NO_LEFT_TURN || type == RESTRICTION_NO_RIGHT_TURN
|| type == RESTRICTION_NO_STRAIGHT_ON || type == RESTRICTION_NO_U_TURN) {
|| type == RESTRICTION_NO_STRAIGHT_ON || type == RESTRICTION_NO_U_TURN) {
// next = next.next; continue;
} else if (type == -1) {
// case no restriction
@ -424,10 +423,8 @@ bool proccessRestrictions(RoutingContext* ctx, SHARED_PTR<RouteDataObject> road,
return true;
}
bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
VISITED_MAP& visitedSegments, VISITED_MAP& oppositeSegments,
double distFromStart, double distToFinalPoint,
SHARED_PTR<RouteSegment> segment, int segmentEnd, SHARED_PTR<RouteSegment> inputNext,
bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments, VISITED_MAP& visitedSegments,
VISITED_MAP& oppositeSegments, double distFromStart, double distToFinalPoint, SHARED_PTR<RouteSegment> segment,int segmentEnd, SHARED_PTR<RouteSegment> inputNext,
bool reverseWay) {
bool thereAreRestrictions = proccessRestrictions(ctx, segment->road, inputNext, reverseWay);
vector<SHARED_PTR<RouteSegment> >::iterator nextIterator;
@ -448,7 +445,7 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
SHARED_PTR<RouteSegment> opposite = oppositeSegments[nts];
// additional check if opposite way not the same as current one
if (opposite.get() != NULL && (next->segmentStart != segmentEnd ||
opposite->road->id != segment->road->id)) {
opposite->road->id != segment->road->id)) {
SHARED_PTR<FinalRouteSegment> frs = SHARED_PTR<FinalRouteSegment>(new FinalRouteSegment);
frs->direct = segment;
frs->reverseWaySearch = reverseWay;
@ -505,7 +502,6 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
return false;
}
SHARED_PTR<RouteSegment> findRouteSegment(int px, int py, RoutingContext* ctx) {
vector<SHARED_PTR<RouteDataObject> > dataObjects;
ctx->loadTileData(px, py, 17, dataObjects);
@ -518,7 +514,7 @@ SHARED_PTR<RouteSegment> findRouteSegment(int px, int py, RoutingContext* ctx) {
for (; it!= dataObjects.end(); it++) {
SHARED_PTR<RouteDataObject> r = *it;
if (r->pointsX.size() > 1) {
for (int j = 1; j < r->pointsX.size() ; j++) {
for (int j = 1; j < r->pointsX.size(); j++) {
double mDist = squareRootDist(r->pointsX[j -1 ], r->pointsY[j-1], r->pointsX[j], r->pointsY[j]);
int prx = r->pointsX[j];
int pry = r->pointsY[j];
@ -532,8 +528,8 @@ SHARED_PTR<RouteSegment> findRouteSegment(int px, int py, RoutingContext* ctx) {
pry = r->pointsY[j ];
} else {
double c = projection / (mDist * mDist);
prx = (int) ((double)r->pointsX[j - 1] + ((double)r->pointsX[j] - r->pointsX[j - 1]) * c);
pry = (int) ((double)r->pointsY[j - 1] + ((double)r->pointsY[j] - r->pointsY[j - 1]) * c);
prx = (int) ((double)r->pointsX[j - 1] + ((double)r->pointsX[j] - r->pointsX[j - 1]) * c);
pry = (int) ((double)r->pointsY[j - 1] + ((double)r->pointsY[j] - r->pointsY[j - 1]) * c);
}
double currentsDist = squareDist31TileMetric(prx, pry, px, py);
if (road.get() == NULL || currentsDist < sdist) {
@ -554,21 +550,20 @@ SHARED_PTR<RouteSegment> findRouteSegment(int px, int py, RoutingContext* ctx) {
return road;
}
bool combineTwoSegmentResult(RouteSegmentResult& toAdd, RouteSegmentResult& previous,
bool reverse) {
bool ld = previous.endPointIndex > previous.startPointIndex;
bool rd = toAdd.endPointIndex > toAdd.startPointIndex;
if (rd == ld) {
if (toAdd.startPointIndex == previous.endPointIndex && !reverse) {
previous.endPointIndex = toAdd.endPointIndex;
return true;
} else if (toAdd.endPointIndex == previous.startPointIndex && reverse) {
previous.startPointIndex = toAdd.startPointIndex;
return true;
}
bool combineTwoSegmentResult(RouteSegmentResult& toAdd, RouteSegmentResult& previous, bool reverse) {
bool ld = previous.endPointIndex > previous.startPointIndex;
bool rd = toAdd.endPointIndex > toAdd.startPointIndex;
if (rd == ld) {
if (toAdd.startPointIndex == previous.endPointIndex && !reverse) {
previous.endPointIndex = toAdd.endPointIndex;
return true;
} else if (toAdd.endPointIndex == previous.startPointIndex && reverse) {
previous.startPointIndex = toAdd.startPointIndex;
return true;
}
return false;
}
return false;
}
void addRouteSegmentToResult(vector<RouteSegmentResult>& result, RouteSegmentResult& res, bool reverse) {
if (res.endPointIndex != res.startPointIndex) {
@ -584,9 +579,9 @@ void addRouteSegmentToResult(vector<RouteSegmentResult>& result, RouteSegmentRes
}
}
void attachConnectedRoads(RoutingContext* ctx, vector<RouteSegmentResult>& res ) {
void attachConnectedRoads(RoutingContext* ctx, vector<RouteSegmentResult>& res) {
vector<RouteSegmentResult>::iterator it = res.begin();
for(; it != res.end(); it++){
for (; it != res.end(); it++) {
bool plus = it->startPointIndex < it->endPointIndex;
int j = it->startPointIndex;
do {
@ -599,7 +594,7 @@ void attachConnectedRoads(RoutingContext* ctx, vector<RouteSegmentResult>& res )
}
it->attachedRoutes.push_back(r);
j = plus ? j + 1 : j - 1;
} while(j != it->endPointIndex);
}while(j != it->endPointIndex);
}
}
@ -641,17 +636,22 @@ vector<RouteSegmentResult> convertFinalSegmentToResults(RoutingContext* ctx) {
return result;
}
vector<RouteSegmentResult> searchRouteInternal(RoutingContext* ctx, bool leftSideNavigation) {
SHARED_PTR<RouteSegment> start = findRouteSegment(ctx->startX, ctx->startY, ctx);
if(start.get() == NULL) {
osmand_log_print(LOG_WARN, "Start point was not found [Native]");
if(ctx->progress.get()) {
ctx->progress->setSegmentNotFound(0);
}
return vector<RouteSegmentResult>();
} else {
osmand_log_print(LOG_WARN, "Start point was found %lld [Native]", start->road->id);
}
SHARED_PTR<RouteSegment> end = findRouteSegment(ctx->endX, ctx->endY, ctx);
if(end.get() == NULL) {
if(ctx->progress.get()) {
ctx->progress->setSegmentNotFound(1);
}
osmand_log_print(LOG_WARN, "End point was not found [Native]");
return vector<RouteSegmentResult>();
} else {
@ -663,8 +663,8 @@ vector<RouteSegmentResult> searchRouteInternal(RoutingContext* ctx, bool leftSid
return res;
}
bool compareRoutingSubregionTile(SHARED_PTR<RoutingSubregionTile> o1, SHARED_PTR<RoutingSubregionTile> o2){
bool compareRoutingSubregionTile(SHARED_PTR<RoutingSubregionTile> o1, SHARED_PTR<RoutingSubregionTile> o2) {
int v1 = (o1->access + 1) * pow((float)10, o1->getUnloadCount() -1);
int v2 = (o2->access + 1) * pow((float)10, o2->getUnloadCount() -1);
return v1 < v2 ;
return v1 < v2;
}

View file

@ -362,6 +362,38 @@ struct RoutingConfiguration {
bool compareRoutingSubregionTile(SHARED_PTR<RoutingSubregionTile> o1, SHARED_PTR<RoutingSubregionTile> o2);
class RouteCalculationProgress {
protected:
int segmentNotFound ;
float distanceFromBegin;
int directSegmentQueueSize;
float distanceFromEnd;
int reverseSegmentQueueSize;
bool cancelled;
public:
RouteCalculationProgress() : segmentNotFound(-1), distanceFromBegin(0),
distanceFromEnd(0), directSegmentQueueSize(0), reverseSegmentQueueSize(0), cancelled(false){
}
virtual bool isCancelled(){
return cancelled;
}
virtual void setSegmentNotFound(int s){
segmentNotFound = s;
}
virtual void updateStatus(float distanceFromBegin, int directSegmentQueueSize, float distanceFromEnd,
int reverseSegmentQueueSize) {
this->distanceFromBegin = max(distanceFromBegin, this->distanceFromBegin );
this->distanceFromEnd = max(distanceFromEnd,this->distanceFromEnd);
this->directSegmentQueueSize = directSegmentQueueSize;
this->reverseSegmentQueueSize = reverseSegmentQueueSize;
}
};
struct RoutingContext {
typedef UNORDERED(map)<int64_t, SHARED_PTR<RoutingSubregionTile> > MAP_SUBREGION_TILES;
@ -373,6 +405,7 @@ struct RoutingContext {
int firstRoadDirection;
int64_t firstRoadId;
RoutingConfiguration config;
SHARED_PTR<RouteCalculationProgress> progress;
int gcCollectIterations;
@ -436,7 +469,7 @@ struct RoutingContext {
for(i = 0; i<list.size(); i++) {
list[i]->access /= 3;
}
osmand_log_print(LOG_DEBUG, "Run GC (before %f Mb after %f Mb) unload %d of %d tiles",
osmand_log_print(LOG_INFO, "Run GC (before %f Mb after %f Mb) unload %d of %d tiles",
occupiedBefore, getSize() / (1024.0*1024.0),
unloadedTiles, loaded);
}
@ -535,38 +568,6 @@ struct RoutingContext {
}
}
SHARED_PTR<RouteSegment> loadSegmentAround(int x31, int y31) {
timeToLoad.start();
SHARED_PTR<RouteSegment> r;
float dist = -1;
int z = config.zoomToLoad;
uint32_t xloc = x31 >> (31 - z);
uint32_t yloc = y31 >> (31 - z);
uint64_t l = (((uint64_t) x31) << 31) + (uint64_t) y31;
int64_t tileId = (xloc << z) + yloc;
loadHeaders(xloc, yloc);
vector<SHARED_PTR<RoutingSubregionTile> >& subregions = indexedSubregions[tileId];
for(int j = 0; j<subregions.size(); j++) {
if(subregions[j]->isLoaded()) {
UNORDERED(map)<int64_t, SHARED_PTR<RouteSegment> >::iterator s = subregions[j]->routes.begin();
while(s != subregions[j]->routes.end()) {
SHARED_PTR<RouteSegment> seg = s->second;
if(seg.get() != NULL) {
double d = measuredDist(x31, y31, seg->road->pointsX[seg->getSegmentStart()],
seg->road->pointsY[seg->getSegmentStart()]);
if(dist == -1 || d < dist) {
r = seg;
dist = d;
}
}
s++;
}
}
}
timeToLoad.pause();
return r;
}
// void searchRouteRegion(SearchQuery* q, std::vector<RouteDataObject*>& list, RoutingIndex* rs, RouteSubregion* sub)
SHARED_PTR<RouteSegment> loadRouteSegment(int x31, int y31) {
int z = config.zoomToLoad;

View file

@ -365,6 +365,14 @@ jclass jclass_JUnidecode;
jclass jclass_Reshaper;
jmethodID jmethod_JUnidecode_unidecode;
jmethodID jmethod_Reshaper_reshape;
jclass jclass_RouteCalculationProgress = NULL;
jfieldID jfield_RouteCalculationProgress_segmentNotFound = NULL;
jfieldID jfield_RouteCalculationProgress_distanceFromBegin = NULL;
jfieldID jfield_RouteCalculationProgress_directSegmentQueueSize = NULL;
jfieldID jfield_RouteCalculationProgress_distanceFromEnd = NULL;
jfieldID jfield_RouteCalculationProgress_reverseSegmentQueueSize = NULL;
jfieldID jfield_RouteCalculationProgress_isCancelled = NULL;
jclass jclass_RenderingContext = NULL;
jfieldID jfield_RenderingContext_interrupted = NULL;
jfieldID jfield_RenderingContext_leftX = NULL;
@ -430,6 +438,14 @@ void loadJniRenderingContext(JNIEnv* env)
jfield_RouteSegmentResult_preAttachedRoutes = getFid(env, jclass_RouteSegmentResult, "preAttachedRoutes",
"[[Lnet/osmand/router/RouteSegmentResult;");
jclass_RouteCalculationProgress = findClass(env, "net/osmand/router/RouteCalculationProgress");
jfield_RouteCalculationProgress_isCancelled = getFid(env, jclass_RouteCalculationProgress, "isCancelled", "Z");
jfield_RouteCalculationProgress_segmentNotFound = getFid(env, jclass_RouteCalculationProgress, "segmentNotFound", "I");
jfield_RouteCalculationProgress_distanceFromBegin = getFid(env, jclass_RouteCalculationProgress, "distanceFromBegin", "F");
jfield_RouteCalculationProgress_distanceFromEnd = getFid(env, jclass_RouteCalculationProgress, "distanceFromEnd", "F");
jfield_RouteCalculationProgress_directSegmentQueueSize = getFid(env, jclass_RouteCalculationProgress, "directSegmentQueueSize", "I");
jfield_RouteCalculationProgress_reverseSegmentQueueSize = getFid(env, jclass_RouteCalculationProgress, "reverseSegmentQueueSize", "I");
jclass_RenderingContext = findClass(env, "net/osmand/RenderingContext");
jfield_RenderingContext_interrupted = getFid(env, jclass_RenderingContext, "interrupted", "Z");
jfield_RenderingContext_leftX = getFid(env, jclass_RenderingContext, "leftX", "F" );
@ -624,11 +640,37 @@ extern "C" JNIEXPORT void JNICALL Java_net_osmand_NativeLibrary_deleteRouteSearc
}
delete t;
}
class RouteCalculationProgressWrapper: public RouteCalculationProgress {
jobject j;
JNIEnv* ienv;
public:
RouteCalculationProgressWrapper(JNIEnv* ienv, jobject j) : RouteCalculationProgress(),
ienv(ienv), j(j) {
}
virtual bool isCancelled() {
return ienv->GetBooleanField(j, jfield_RouteCalculationProgress_isCancelled);
}
virtual void setSegmentNotFound(int s) {
ienv->SetIntField(j, jfield_RouteCalculationProgress_segmentNotFound, s);
}
virtual void updateStatus(float distanceFromBegin, int directSegmentQueueSize, float distanceFromEnd,
int reverseSegmentQueueSize) {
RouteCalculationProgress::updateStatus(distanceFromBegin, directSegmentQueueSize,
distanceFromEnd, reverseSegmentQueueSize);
ienv->SetFloatField(j, jfield_RouteCalculationProgress_distanceFromBegin, this->distanceFromBegin);
ienv->SetFloatField(j, jfield_RouteCalculationProgress_distanceFromEnd, this->distanceFromEnd);
ienv->SetIntField(j, jfield_RouteCalculationProgress_directSegmentQueueSize, this->directSegmentQueueSize);
ienv->SetIntField(j, jfield_RouteCalculationProgress_reverseSegmentQueueSize, this->reverseSegmentQueueSize);
}
};
//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, jfloat initDirection,
jobjectArray regions) {
jobjectArray regions, jobject progress) {
vector<ROUTE_TRIPLE> cfg;
int* data = ienv->GetIntArrayElements(stateConfig, NULL);
for(int k = 0; k < ienv->GetArrayLength(stateConfig); k++) {
@ -646,6 +688,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_net_osmand_NativeLibrary_nativeRo
RoutingConfiguration config(cfg, initDirection);
RoutingContext c(config);
c.progress = SHARED_PTR<RouteCalculationProgress>(new RouteCalculationProgressWrapper(ienv, progress));
data = ienv->GetIntArrayElements(coordinates, NULL);
c.startX = data[0];
c.startY = data[1];