Memory limitation
This commit is contained in:
parent
3e0c5d8466
commit
1e85c0234d
18 changed files with 690 additions and 649 deletions
|
@ -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+""));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
package net.osmand.router;
|
||||
|
||||
public interface Interruptable {
|
||||
|
||||
|
||||
public boolean isCancelled();
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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("\" ");
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in a new issue