Adjust route planner

This commit is contained in:
Victor Shcherb 2012-10-13 13:38:54 +02:00
parent ca090e9a74
commit 7e5601c0d8
6 changed files with 231 additions and 217 deletions

View file

@ -30,6 +30,7 @@ public class BinaryRoutePlanner {
private static final int ROUTE_POINTS = 11; private static final int ROUTE_POINTS = 11;
private static final float TURN_DEGREE_MIN = 45; private static final float TURN_DEGREE_MIN = 45;
private static final boolean TRACE_ROUTING = false;
private static double squareRootDist(int x1, int y1, int x2, int y2) { private static double squareRootDist(int x1, int y1, int x2, int y2) {
@ -298,10 +299,10 @@ public class BinaryRoutePlanner {
(graphDirectSegments.size() + (graphDirectSegments.size() +
graphReverseSegments.size()) * STANDARD_ROAD_IN_QUEUE_OVERHEAD; graphReverseSegments.size()) * STANDARD_ROAD_IN_QUEUE_OVERHEAD;
if(TRACE_ROUTING){
// String pr = " pend="+segment.parentSegmentEnd +" " +( segment.parentRoute == null ? "" : (" parent=" + segment.parentRoute.road)); System.out.print(">");
// System.out.println("Seg " + segment.road + " ind=" + segment.segmentStart + printRoad(segment);
// " ds=" + ((float)segment.distanceFromStart) + " es="+((float)segment.distanceToEnd) + pr); }
if(segment instanceof FinalRouteSegment) { if(segment instanceof FinalRouteSegment) {
if(RoutingContext.SHOW_GC_SIZE){ if(RoutingContext.SHOW_GC_SIZE){
log.warn("Estimated overhead " + (ctx.memoryOverhead / (1<<20))+ " mb"); log.warn("Estimated overhead " + (ctx.memoryOverhead / (1<<20))+ " mb");
@ -317,16 +318,16 @@ public class BinaryRoutePlanner {
throw new IllegalStateException("There is no enough memory " + ctx.config.memoryLimitation/(1<<20) + " Mb"); throw new IllegalStateException("There is no enough memory " + ctx.config.memoryLimitation/(1<<20) + " Mb");
} }
ctx.visitedSegments++; ctx.visitedSegments++;
// for debug purposes
if (ctx.visitor != null) {
ctx.visitor.visitSegment(segment, true);
}
if (!inverse) { if (!inverse) {
processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, targetEndX, targetEndY, processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, targetEndX, targetEndY,
segment, visitedOppositeSegments); segment, visitedOppositeSegments, true);
processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, targetEndX, targetEndY,
segment, visitedOppositeSegments, false);
} else { } else {
processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments, startX, startY, segment, processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments, startX, startY, segment,
visitedDirectSegments); visitedDirectSegments, true);
processRouteSegment(ctx, true, graphReverseSegments, visitedOppositeSegments, startX, startY, segment,
visitedDirectSegments, false);
} }
if(graphReverseSegments.isEmpty()){ if(graphReverseSegments.isEmpty()){
throw new IllegalArgumentException("Route is not found to selected target point."); throw new IllegalArgumentException("Route is not found to selected target point.");
@ -372,10 +373,21 @@ public class BinaryRoutePlanner {
private void printRoad(RouteSegment segment) {
String pr;
if(segment.parentRoute != null){
pr = " pend="+segment.parentSegmentEnd +" parent=" + segment.parentRoute.road;
} else {
pr = "";
}
System.out.println("" + segment.road + " ind=" + segment.getSegmentStart() +
" ds=" + ((float)segment.distanceFromStart) + " es="+((float)segment.distanceToEnd) + pr);
}
private void relaxNotNeededSegments(RoutingContext ctx, PriorityQueue<RouteSegment> graphSegments, boolean inverse) { private void relaxNotNeededSegments(RoutingContext ctx, PriorityQueue<RouteSegment> graphSegments, boolean inverse) {
// relax strategy is incorrect if we already found a route but it is very long due to some obstacles // relax strategy is incorrect if we already found a route but it is very long due to some obstacles
RouteSegment next = graphSegments.peek(); RouteSegment next = graphSegments.peek();
double mine = next.distanceToEnd; double mine = next.distanceFromStart;
// int before = graphSegments.size(); // int before = graphSegments.size();
// SegmentStat statStart = new SegmentStat("Distance from start (" + inverse + ") "); // SegmentStat statStart = new SegmentStat("Distance from start (" + inverse + ") ");
// SegmentStat statEnd = new SegmentStat("Distance to end (" + inverse + ") "); // SegmentStat statEnd = new SegmentStat("Distance to end (" + inverse + ") ");
@ -388,7 +400,8 @@ public class BinaryRoutePlanner {
mine = s.distanceToEnd; mine = s.distanceToEnd;
} }
} }
double d = mine * ctx.config.RELAX_NODES_IF_START_DIST_COEF; double d = mine + 5000; // ctx.config.RELAX_NODES_IF_START_DIST_COEF;
if (d > 0) {
iterator = graphSegments.iterator(); iterator = graphSegments.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
RouteSegment s = iterator.next(); RouteSegment s = iterator.next();
@ -397,6 +410,7 @@ public class BinaryRoutePlanner {
iterator.remove(); iterator.remove();
} }
} }
}
// int after = graphSegments.size(); // int after = graphSegments.size();
// println(statStart.toString()); // println(statStart.toString());
// println(statEnd.toString()); // println(statEnd.toString());
@ -443,12 +457,12 @@ public class BinaryRoutePlanner {
printInfo("Loaded tiles " + ctx.loadedTiles + " (distinct "+ctx.distinctLoadedTiles+ "), unloaded tiles " + ctx.unloadedTiles + printInfo("Loaded tiles " + ctx.loadedTiles + " (distinct "+ctx.distinctLoadedTiles+ "), unloaded tiles " + ctx.unloadedTiles +
", loaded more than once same tiles " ", loaded more than once same tiles "
+ ctx.loadedPrevUnloadedTiles ); + ctx.loadedPrevUnloadedTiles );
printInfo("Visited roads, " + ctx.visitedSegments + ", relaxed roads " + ctx.relaxedSegments); printInfo("Visited roads " + ctx.visitedSegments + ", relaxed roads " + ctx.relaxedSegments);
if (graphDirectSegments != null && graphReverseSegments != null) { if (graphDirectSegments != null && graphReverseSegments != null) {
printInfo("Priority queues sizes : " + graphDirectSegments.size() + "/" + graphReverseSegments.size()); printInfo("Priority queues sizes : " + graphDirectSegments.size() + "/" + graphReverseSegments.size());
} }
if (visitedDirectSegments != null && visitedOppositeSegments != null) { if (visitedDirectSegments != null && visitedOppositeSegments != null) {
printInfo("Visited segments sizes: " + visitedDirectSegments.size() + "/" + visitedOppositeSegments.size()); printInfo("Visited interval sizes: " + visitedDirectSegments.size() + "/" + visitedOppositeSegments.size());
} }
} }
@ -456,131 +470,153 @@ public class BinaryRoutePlanner {
private void processRouteSegment(final RoutingContext ctx, boolean reverseWaySearch, private void processRouteSegment(final RoutingContext ctx, boolean reverseWaySearch,
PriorityQueue<RouteSegment> graphSegments, TLongObjectHashMap<RouteSegment> visitedSegments, int targetEndX, int targetEndY, PriorityQueue<RouteSegment> graphSegments, TLongObjectHashMap<RouteSegment> visitedSegments, int targetEndX, int targetEndY,
RouteSegment segment, TLongObjectHashMap<RouteSegment> oppositeSegments) throws IOException { RouteSegment segment, TLongObjectHashMap<RouteSegment> oppositeSegments, boolean direction) throws IOException {
// 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
final RouteDataObject road = segment.road; final RouteDataObject road = segment.road;
boolean initDirectionAllowed = checkIfInitialMovementAllowedOnSegment(ctx, reverseWaySearch, visitedSegments, segment, direction, road);
boolean directionAllowed = initDirectionAllowed;
// Go through all point of the way and find ways to continue
// ! Actually there is small bug when there is restriction to move forward on the way (it doesn't take into account)
float obstaclesTime = 0;
if(segment.getParentRoute() != null && directionAllowed) {
obstaclesTime = (float) ctx.getRouter().calculateTurnTime(segment, direction? segment.getRoad().getPointsLength() - 1 : 0,
segment.getParentRoute(), segment.getParentSegmentEnd());
}
float segmentDist = 0;
// +/- diff from middle point
int segmentEnd = segment.getSegmentStart();
while (directionAllowed) {
int prevInd = segmentEnd;
if(direction) {
segmentEnd ++;
} else {
segmentEnd --;
}
if (segmentEnd < 0 || segmentEnd >= road.getPointsLength()) {
directionAllowed = false;
continue;
}
final int intervalId = direction ? segmentEnd - 1 : segmentEnd;
visitedSegments.put(calculateRoutePointId(road, intervalId, direction), segment);
final int x = road.getPoint31XTile(segmentEnd);
final int y = road.getPoint31YTile(segmentEnd);
final int prevx = road.getPoint31XTile(prevInd);
final int prevy = road.getPoint31YTile(prevInd);
if(x == prevx && y == prevy) {
continue;
}
// 2. calculate point and try to load neighbor ways if they are not loaded
segmentDist += squareRootDist(x, y, prevx, prevy);
// 2.1 calculate possible obstacle plus time
double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentEnd);
if (obstacle < 0) {
directionAllowed = false;
continue;
}
obstaclesTime += obstacle;
boolean alreadyVisited = checkIfOppositieSegmentWasVisited(ctx, reverseWaySearch, graphSegments, segment, oppositeSegments, road,
segmentEnd, direction, intervalId, segmentDist, obstaclesTime);
if (alreadyVisited) {
directionAllowed = false;
continue;
}
// could be expensive calculation
// 3. get intersected ways
final RouteSegment roadNext = ctx.loadRouteSegment(x, y, ctx.config.memoryLimitation - ctx.memoryOverhead);
if(roadNext != null &&
!((roadNext == segment || roadNext.road.id == road.id) && roadNext.next == null)) {
// check if there are outgoing connections in that case we need to stop processing
boolean outgoingConnections = false;
RouteSegment r = roadNext;
while(r != null && !outgoingConnections) {
if(r.road.id != road.id || r.getSegmentStart() != 0 || r.road.getOneway() != 1){
outgoingConnections = true;
}
r = r.next;
}
if (outgoingConnections) {
directionAllowed = false;
}
float distToFinalPoint = (float) squareRootDist(x, y, targetEndX, targetEndY);
float distStartObstacles = segment.distanceFromStart + calculateTimeWithObstacles(ctx, road, segmentDist , obstaclesTime);
processIntersections(ctx, graphSegments, visitedSegments,
distStartObstacles, distToFinalPoint, segment, segmentEnd, roadNext, reverseWaySearch, outgoingConnections);
}
}
if(initDirectionAllowed && ctx.visitor != null){
ctx.visitor.visitSegment(segment, segmentEnd, true);
}
}
private boolean checkIfInitialMovementAllowedOnSegment(final RoutingContext ctx, boolean reverseWaySearch,
TLongObjectHashMap<RouteSegment> visitedSegments, RouteSegment segment, boolean direction, final RouteDataObject road
) {
boolean directionAllowed;
final int middle = segment.getSegmentStart(); final int middle = segment.getSegmentStart();
float obstaclePlusTime = 0;
float obstacleMinusTime = 0;
int oneway = ctx.getRouter().isOneWay(road); int oneway = ctx.getRouter().isOneWay(road);
boolean minusAllowed;
boolean plusAllowed;
// use positive direction as agreed // use positive direction as agreed
if(ctx.firstRoadId == calculateRoutePointId(road, middle, true) ) { if(ctx.firstRoadId == calculateRoutePointId(road, middle, true) ) {
minusAllowed = ctx.firstRoadDirection <= 0; if(direction){
plusAllowed = ctx.firstRoadDirection >= 0; directionAllowed = ctx.firstRoadDirection >= 0;
} else if (!reverseWaySearch) {
minusAllowed = oneway <= 0;
plusAllowed = oneway >= 0;
} else { } else {
minusAllowed = oneway >= 0; directionAllowed = ctx.firstRoadDirection <= 0;
plusAllowed = oneway <= 0;
} }
} else if (!reverseWaySearch) {
if(direction){
directionAllowed = oneway >= 0;
} else {
directionAllowed = oneway <= 0;
}
} else {
if(direction){
directionAllowed = oneway <= 0;
} else {
directionAllowed = oneway >= 0;
}
}
if(direction) {
if(middle == road.getPointsLength() - 1 || if(middle == road.getPointsLength() - 1 ||
visitedSegments.containsKey(calculateRoutePointId(road, middle, true)) || visitedSegments.containsKey(calculateRoutePointId(road, middle, true)) ||
segment.getAllowedDirection() == -1) { segment.getAllowedDirection() == -1) {
plusAllowed = false; directionAllowed = false;
} }
} else {
if(middle == 0 || visitedSegments.containsKey(calculateRoutePointId(road, middle - 1, false)) || if(middle == 0 || visitedSegments.containsKey(calculateRoutePointId(road, middle - 1, false)) ||
segment.getAllowedDirection() == 1) { segment.getAllowedDirection() == 1) {
minusAllowed = false; directionAllowed = false;
}
}
return directionAllowed;
} }
// +/- diff from middle point private boolean checkIfOppositieSegmentWasVisited(final RoutingContext ctx, boolean reverseWaySearch,
int d = plusAllowed ? 1 : -1; PriorityQueue<RouteSegment> graphSegments, RouteSegment segment, TLongObjectHashMap<RouteSegment> oppositeSegments,
if(segment.getParentRoute() != null) { final RouteDataObject road, int segmentEnd, boolean positive, int intervalId, float segmentDist, float obstaclesTime) {
if(plusAllowed && middle < segment.getRoad().getPointsLength() - 1) {
obstaclePlusTime = (float) ctx.getRouter().calculateTurnTime(segment, segment.getRoad().getPointsLength() - 1,
segment.getParentRoute(), segment.getParentSegmentEnd());
}
if(minusAllowed && middle > 0) {
obstacleMinusTime = (float) ctx.getRouter().calculateTurnTime(segment, 0,
segment.getParentRoute(), segment.getParentSegmentEnd());
}
}
// Go through all point of the way and find ways to continue
// ! Actually there is small bug when there is restriction to move forward on the way (it doesn't take into account)
float posSegmentDist = 0;
float negSegmentDist = 0;
while (minusAllowed || plusAllowed) {
// 1. calculate point not equal to middle
// (algorithm should visit all point on way if it is not oneway)
int segmentEnd = middle + d;
boolean positive = d > 0;
// calculate d for next iteration
if (!minusAllowed && d > 0) {
d++;
} else if (!plusAllowed && d < 0) {
d--;
} else {
if (d <= 0) {
d = -d + 1;
} else {
d = -d;
}
}
if (segmentEnd < 0) {
minusAllowed = false;
continue;
}
if (segmentEnd >= road.getPointsLength()) {
plusAllowed = false;
continue;
}
int intervalId = positive ? segmentEnd - 1 : segmentEnd;
long nds = calculateRoutePointId(road, intervalId, positive);
visitedSegments.put(nds, segment);
RouteSegment opposite = null;
// check if that segment was already visited in different direction
long opp = calculateRoutePointId(road, intervalId, !positive); long opp = calculateRoutePointId(road, intervalId, !positive);
if (oppositeSegments.containsKey(opp)) { if (oppositeSegments.containsKey(opp)) {
opposite = oppositeSegments.get(opp); RouteSegment opposite = oppositeSegments.get(opp);
if (opposite.getSegmentStart() != segmentEnd) { if (opposite.getSegmentStart() == segmentEnd) {
opposite = null; FinalRouteSegment frs = new FinalRouteSegment(road, segment.getSegmentStart());
float distStartObstacles = segment.distanceFromStart + calculateTimeWithObstacles(ctx, road, segmentDist , obstaclesTime);
frs.setParentRoute(segment.getParentRoute());
frs.setParentSegmentEnd(segment.getParentSegmentEnd());
frs.reverseWaySearch = reverseWaySearch;
frs.distanceFromStart = opposite.distanceFromStart + distStartObstacles;
frs.distanceToEnd = 0;
frs.opposite = opposite;
graphSegments.add(frs);
return true;
} }
} }
return false;
}
// 2. calculate point and try to load neighbor ways if they are not loaded private float calculateTimeWithObstacles(RoutingContext ctx, RouteDataObject road, float distOnRoadToPass, float obstaclesTime) {
int x = road.getPoint31XTile(segmentEnd);
int y = road.getPoint31YTile(segmentEnd);
if(positive) {
posSegmentDist += squareRootDist(x, y,
road.getPoint31XTile(segmentEnd - 1), road.getPoint31YTile(segmentEnd - 1));
} else {
negSegmentDist += squareRootDist(x, y,
road.getPoint31XTile(segmentEnd + 1), road.getPoint31YTile(segmentEnd + 1));
}
// 2.1 calculate possible obstacle plus time
if(positive){
double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentEnd);
if (obstacle < 0) {
plusAllowed = false;
continue;
}
obstaclePlusTime += obstacle;
} else {
double obstacle = ctx.getRouter().defineRoutingObstacle(road, segmentEnd);
if (obstacle < 0) {
minusAllowed = false;
continue;
}
obstacleMinusTime += obstacle;
}
// could be expensive calculation
RouteSegment next = ctx.loadRouteSegment(x, y, ctx.config.memoryLimitation - ctx.memoryOverhead);
// 3. get intersected ways
if (next != null || opposite != null) {
// Using A* routing algorithm
// g(x) - calculate distance to that point and calculate time
float priority = ctx.getRouter().defineSpeedPriority(road); float priority = ctx.getRouter().defineSpeedPriority(road);
float speed = (ctx.getRouter().defineSpeed(road) * priority); float speed = (ctx.getRouter().defineSpeed(road) * priority);
if (speed == 0) { if (speed == 0) {
@ -590,61 +626,11 @@ public class BinaryRoutePlanner {
if(speed > ctx.getRouter().getMaxDefaultSpeed()) { if(speed > ctx.getRouter().getMaxDefaultSpeed()) {
speed = ctx.getRouter().getMaxDefaultSpeed(); speed = ctx.getRouter().getMaxDefaultSpeed();
} }
float distOnRoadToPass = positive? posSegmentDist : negSegmentDist; float distStartObstacles = obstaclesTime +
float distStartObstacles = segment.distanceFromStart + ( positive ? obstaclePlusTime : obstacleMinusTime) +
distOnRoadToPass / speed; distOnRoadToPass / speed;
return distStartObstacles;
if(opposite != null) {
FinalRouteSegment frs = new FinalRouteSegment(road, segment.getSegmentStart());
frs.setParentRoute(segment.getParentRoute());
frs.setParentSegmentEnd(segment.getParentSegmentEnd());
frs.reverseWaySearch = reverseWaySearch;
frs.distanceFromStart = opposite.distanceFromStart + distStartObstacles;
frs.distanceToEnd = 0;
frs.opposite = opposite;
graphSegments.add(frs);
if(positive) {
plusAllowed = false;
} else {
minusAllowed = false;
}
continue;
}
if(next == null) {
continue;
}
// TO-DO U-Turn
if((next == segment || next.road.id == road.id) && next.next == null) {
// simplification if there is no real intersection
continue;
}
// check if there are outgoing connections in that case we need to stop processing
boolean outgoingConnections = false;
RouteSegment r = next;
while(r != null && !outgoingConnections) {
if(r.road.id != road.id || r.getSegmentStart() != 0 || r.road.getOneway() != 1){
outgoingConnections = true;
}
r = r.next;
}
if (outgoingConnections) {
if (positive) {
plusAllowed = false;
} else {
minusAllowed = false;
}
}
float distToFinalPoint = (float) squareRootDist(x, y, targetEndX, targetEndY);
processIntersections(ctx, graphSegments, visitedSegments,
distStartObstacles, distToFinalPoint, segment, segmentEnd, next, reverseWaySearch, outgoingConnections);
} }
}
}
private long calculateRoutePointId(final RouteDataObject road, int intervalId, boolean positive) { private long calculateRoutePointId(final RouteDataObject road, int intervalId, boolean positive) {
return (road.getId() << ROUTE_POINTS) + (intervalId << 1) + (positive ? 1 : 0); return (road.getId() << ROUTE_POINTS) + (intervalId << 1) + (positive ? 1 : 0);
@ -738,6 +724,9 @@ public class BinaryRoutePlanner {
Iterator<RouteSegment> nextIterator = null; Iterator<RouteSegment> nextIterator = null;
if (thereAreRestrictions) { if (thereAreRestrictions) {
nextIterator = ctx.segmentsToVisitPrescripted.iterator(); nextIterator = ctx.segmentsToVisitPrescripted.iterator();
if(TRACE_ROUTING){
System.out.println(" >> There are restrictions");
}
} }
// Calculate possible ways to put into priority queue // Calculate possible ways to put into priority queue
RouteSegment next = inputNext; RouteSegment next = inputNext;
@ -774,13 +763,18 @@ public class BinaryRoutePlanner {
if(sameRoadFutureDirection) { if(sameRoadFutureDirection) {
next.setAllowedDirection((byte) (segment.getSegmentStart() < next.getSegmentStart() ? 1 : - 1)); next.setAllowedDirection((byte) (segment.getSegmentStart() < next.getSegmentStart() ? 1 : - 1));
} }
if(TRACE_ROUTING) {
System.out.print(" >>");
printRoad(next);
}
// put additional information to recover whole route after // put additional information to recover whole route after
next.setParentRoute(segment); next.setParentRoute(segment);
next.setParentSegmentEnd(segmentEnd); next.setParentSegmentEnd(segmentEnd);
graphSegments.add(next); graphSegments.add(next);
} }
if (ctx.visitor != null) { if (ctx.visitor != null) {
ctx.visitor.visitSegment(next, false); // ctx.visitor.visitSegment(next, false);
} }
} else if(!sameRoadFutureDirection){ } else if(!sameRoadFutureDirection){
// the segment was already visited! We need to follow better route if it exists // the segment was already visited! We need to follow better route if it exists
@ -797,7 +791,7 @@ public class BinaryRoutePlanner {
next.setParentRoute(segment); next.setParentRoute(segment);
next.setParentSegmentEnd(segmentEnd); next.setParentSegmentEnd(segmentEnd);
if (ctx.visitor != null) { if (ctx.visitor != null) {
ctx.visitor.visitSegment(next, false); // ctx.visitor.visitSegment(next, false);
} }
} }
} }
@ -1295,7 +1289,7 @@ public class BinaryRoutePlanner {
public interface RouteSegmentVisitor { public interface RouteSegmentVisitor {
public void visitSegment(RouteSegment segment, boolean poll); public void visitSegment(RouteSegment segment, int segmentEnd, boolean poll);
} }
public static class RouteSegment { public static class RouteSegment {

View file

@ -18,7 +18,7 @@ import org.xml.sax.helpers.DefaultHandler;
public class RoutingConfiguration { public class RoutingConfiguration {
// 1. parameters of routing and different tweaks // 1. parameters of routing and different tweaks
// Influence on A* : f(x) + heuristicCoefficient*g(X) // Influence on A* : f(x) + heuristicCoefficient*g(X)
public double heuristicCoefficient = 1; public float heuristicCoefficient = 1;
public static final int DEFAULT_MEMORY_LIMIT = 30; public static final int DEFAULT_MEMORY_LIMIT = 30;
@ -34,7 +34,7 @@ public class RoutingConfiguration {
// 1.3 Relaxing strategy // 1.3 Relaxing strategy
public boolean useRelaxingStrategy = true; public boolean useRelaxingStrategy = true;
public int ITERATIONS_TO_RELAX_NODES = 100; public int ITERATIONS_TO_RELAX_NODES = 100;
public double RELAX_NODES_IF_START_DIST_COEF = 3; public float RELAX_NODES_IF_START_DIST_COEF = 3;
// 1.4 Build A* graph in backward/forward direction (can affect results) // 1.4 Build A* graph in backward/forward direction (can affect results)
// 0 - 2 ways, 1 - direct way, -1 - reverse way // 0 - 2 ways, 1 - direct way, -1 - reverse way
@ -63,7 +63,7 @@ public class RoutingConfiguration {
} }
RoutingConfiguration i = new RoutingConfiguration(); RoutingConfiguration i = new RoutingConfiguration();
i.initialDirection = direction; i.initialDirection = direction;
i.heuristicCoefficient = parseSilentDouble(getAttribute(router, "heuristicCoefficient"), i.heuristicCoefficient); i.heuristicCoefficient = parseSilentFloat(getAttribute(router, "heuristicCoefficient"), i.heuristicCoefficient);
i.ZOOM_TO_LOAD_TILES = parseSilentInt(getAttribute(router, "zoomToLoadTiles"), i.ZOOM_TO_LOAD_TILES); i.ZOOM_TO_LOAD_TILES = parseSilentInt(getAttribute(router, "zoomToLoadTiles"), i.ZOOM_TO_LOAD_TILES);
int desirable = parseSilentInt(getAttribute(router, "memoryLimitInMB"), 0); int desirable = parseSilentInt(getAttribute(router, "memoryLimitInMB"), 0);
if(desirable != 0) { if(desirable != 0) {
@ -78,7 +78,7 @@ public class RoutingConfiguration {
i.useRelaxingStrategy = parseSilentBoolean(getAttribute(router, "useRelaxingStrategy"), i.useRelaxingStrategy); i.useRelaxingStrategy = parseSilentBoolean(getAttribute(router, "useRelaxingStrategy"), i.useRelaxingStrategy);
i.dynamicRoadPriorityDistance = parseSilentInt(getAttribute(router, "dynamicRoadPriorityDistance"), i.dynamicRoadPriorityDistance); i.dynamicRoadPriorityDistance = parseSilentInt(getAttribute(router, "dynamicRoadPriorityDistance"), i.dynamicRoadPriorityDistance);
i.ITERATIONS_TO_RELAX_NODES = parseSilentInt(getAttribute(router, "iterationsToRelaxRoutes"), i.ITERATIONS_TO_RELAX_NODES); i.ITERATIONS_TO_RELAX_NODES = parseSilentInt(getAttribute(router, "iterationsToRelaxRoutes"), i.ITERATIONS_TO_RELAX_NODES);
i.RELAX_NODES_IF_START_DIST_COEF = parseSilentDouble(getAttribute(router, "relaxNodesIfStartDistSmallCoeff"), i.RELAX_NODES_IF_START_DIST_COEF); i.RELAX_NODES_IF_START_DIST_COEF = parseSilentFloat(getAttribute(router, "relaxNodesIfStartDistSmallCoeff"), i.RELAX_NODES_IF_START_DIST_COEF);
i.planRoadDirection = parseSilentInt(getAttribute(router, "planRoadDirection"), i.planRoadDirection); i.planRoadDirection = parseSilentInt(getAttribute(router, "planRoadDirection"), i.planRoadDirection);
if (!routers.containsKey(router)) { if (!routers.containsKey(router)) {
@ -117,11 +117,11 @@ public class RoutingConfiguration {
return Boolean.parseBoolean(t); return Boolean.parseBoolean(t);
} }
private static double parseSilentDouble(String t, double v) { private static float parseSilentFloat(String t, float v) {
if (t == null || t.length() == 0) { if (t == null || t.length() == 0) {
return v; return v;
} }
return Double.parseDouble(t); return Float.parseFloat(t);
} }
@ -173,22 +173,22 @@ public class RoutingConfiguration {
if (previousKey != null) { if (previousKey != null) {
String k = in + ":" + previousKey; String k = in + ":" + previousKey;
if (attributes.getValue("penalty") != null) { if (attributes.getValue("penalty") != null) {
double penalty = parseSilentDouble(attributes.getValue("penalty"), 0); float penalty = parseSilentFloat(attributes.getValue("penalty"), 0);
currentRouter.obstacles.put(k, penalty); currentRouter.obstacles.put(k, penalty);
double routingPenalty = parseSilentDouble(attributes.getValue("routingPenalty"), penalty ); float routingPenalty = parseSilentFloat(attributes.getValue("routingPenalty"), penalty );
currentRouter.routingObstacles.put(k, routingPenalty); currentRouter.routingObstacles.put(k, routingPenalty);
} }
if (attributes.getValue("priority") != null) { if (attributes.getValue("priority") != null) {
currentRouter.highwayPriorities.put(k, parseSilentDouble(attributes.getValue("priority"), 0)); currentRouter.highwayPriorities.put(k, parseSilentFloat(attributes.getValue("priority"), 0));
} }
if (attributes.getValue("dynamicPriority") != null) { if (attributes.getValue("dynamicPriority") != null) {
currentRouter.highwayFuturePriorities.put(k, parseSilentDouble(attributes.getValue("dynamicPriority"), 0)); currentRouter.highwayFuturePriorities.put(k, parseSilentFloat(attributes.getValue("dynamicPriority"), 0));
} }
if (attributes.getValue("speed") != null) { if (attributes.getValue("speed") != null) {
currentRouter.highwaySpeed.put(k, parseSilentDouble(attributes.getValue("speed"), 0)); currentRouter.highwaySpeed.put(k, parseSilentFloat(attributes.getValue("speed"), 0));
} }
if ("avoid".equals(previousTag)) { if ("avoid".equals(previousTag)) {
double priority = parseSilentDouble(attributes.getValue("decreasedPriority"), 0); float priority = parseSilentFloat(attributes.getValue("decreasedPriority"), 0);
if (priority == 0) { if (priority == 0) {
currentRouter.avoid.put(k, priority); currentRouter.avoid.put(k, priority);
} else { } else {
@ -200,23 +200,23 @@ public class RoutingConfiguration {
} else if("road".equals(name)) { } else if("road".equals(name)) {
previousTag = name; previousTag = name;
previousKey = attributes.getValue("tag") +"$" + attributes.getValue("value"); previousKey = attributes.getValue("tag") +"$" + attributes.getValue("value");
currentRouter.highwayPriorities.put(previousKey, parseSilentDouble(attributes.getValue("priority"), currentRouter.highwayPriorities.put(previousKey, parseSilentFloat(attributes.getValue("priority"),
1)); 1));
currentRouter.highwayFuturePriorities.put(previousKey, parseSilentDouble(attributes.getValue("dynamicPriority"), currentRouter.highwayFuturePriorities.put(previousKey, parseSilentFloat(attributes.getValue("dynamicPriority"),
1)); 1));
currentRouter.highwaySpeed.put(previousKey, parseSilentDouble(attributes.getValue("speed"), currentRouter.highwaySpeed.put(previousKey, parseSilentFloat(attributes.getValue("speed"),
10)); 10));
} else if("obstacle".equals(name)) { } else if("obstacle".equals(name)) {
previousTag = name; previousTag = name;
previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value"); previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value");
double penalty = parseSilentDouble(attributes.getValue("penalty"), 0); float penalty = parseSilentFloat(attributes.getValue("penalty"), 0);
currentRouter.obstacles.put(previousKey, penalty); currentRouter.obstacles.put(previousKey, penalty);
double routingPenalty = parseSilentDouble(attributes.getValue("routingPenalty"), penalty ); float routingPenalty = parseSilentFloat(attributes.getValue("routingPenalty"), penalty );
currentRouter.routingObstacles.put(previousKey, routingPenalty); currentRouter.routingObstacles.put(previousKey, routingPenalty);
} else if("avoid".equals(name)) { } else if("avoid".equals(name)) {
previousTag = name; previousTag = name;
previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value"); previousKey = attributes.getValue("tag") + "$" + attributes.getValue("value");
double priority = parseSilentDouble(attributes.getValue("decreasedPriority"), float priority = parseSilentFloat(attributes.getValue("decreasedPriority"),
0); 0);
if(priority == 0) { if(priority == 0) {
currentRouter.avoid.put(previousKey, priority); currentRouter.avoid.put(previousKey, priority);

View file

@ -34,7 +34,7 @@ import org.apache.commons.logging.Log;
public class RoutingContext { public class RoutingContext {
public static final boolean SHOW_GC_SIZE = false; public static final boolean SHOW_GC_SIZE = false;
public boolean USE_BASEMAP = false;
private final static Log log = LogUtil.getLog(RoutingContext.class); private final static Log log = LogUtil.getLog(RoutingContext.class);
public static final int OPTION_NO_LOAD = 0; public static final int OPTION_NO_LOAD = 0;
@ -42,6 +42,7 @@ public class RoutingContext {
public static final int OPTION_IN_MEMORY_LOAD = 2; public static final int OPTION_IN_MEMORY_LOAD = 2;
// Final context variables // Final context variables
public final RoutingConfiguration config; public final RoutingConfiguration config;
private final boolean useBaseMap;
public final NativeLibrary nativeLib; public final NativeLibrary nativeLib;
public final Map<BinaryMapIndexReader, List<RouteSubregion>> map = new LinkedHashMap<BinaryMapIndexReader, List<RouteSubregion>>(); public final Map<BinaryMapIndexReader, List<RouteSubregion>> map = new LinkedHashMap<BinaryMapIndexReader, List<RouteSubregion>>();
public final Map<RouteRegion, BinaryMapIndexReader> reverseMap = new LinkedHashMap<RouteRegion, BinaryMapIndexReader>(); public final Map<RouteRegion, BinaryMapIndexReader> reverseMap = new LinkedHashMap<RouteRegion, BinaryMapIndexReader>();
@ -96,6 +97,7 @@ public class RoutingContext {
public RoutingContext(RoutingContext cp) { public RoutingContext(RoutingContext cp) {
this.config = cp.config; this.config = cp.config;
this.map.putAll(cp.map); this.map.putAll(cp.map);
this.useBaseMap = cp.useBaseMap;
this.reverseMap.putAll(cp.reverseMap); this.reverseMap.putAll(cp.reverseMap);
this.nativeLib = cp.nativeLib; this.nativeLib = cp.nativeLib;
// copy local data and clear caches // copy local data and clear caches
@ -117,11 +119,16 @@ public class RoutingContext {
} }
public RoutingContext(RoutingConfiguration config, NativeLibrary nativeLibrary, BinaryMapIndexReader[] map) { public RoutingContext(RoutingConfiguration config, NativeLibrary nativeLibrary, BinaryMapIndexReader[] map) {
this(config, nativeLibrary, map, false);
}
public RoutingContext(RoutingConfiguration config, NativeLibrary nativeLibrary, BinaryMapIndexReader[] map, boolean useBasemap) {
this.useBaseMap = useBasemap;
for (BinaryMapIndexReader mr : map) { for (BinaryMapIndexReader mr : map) {
List<RouteRegion> rr = mr.getRoutingIndexes(); List<RouteRegion> rr = mr.getRoutingIndexes();
List<RouteSubregion> subregions = new ArrayList<BinaryMapRouteReaderAdapter.RouteSubregion>(); List<RouteSubregion> subregions = new ArrayList<BinaryMapRouteReaderAdapter.RouteSubregion>();
for (RouteRegion r : rr) { for (RouteRegion r : rr) {
List<RouteSubregion> subregs = USE_BASEMAP ? r.getBaseSubregions() : List<RouteSubregion> subregs = useBaseMap ? r.getBaseSubregions() :
r.getSubregions(); r.getSubregions();
for (RouteSubregion rs : subregs) { for (RouteSubregion rs : subregs) {
subregions.add(new RouteSubregion(rs)); subregions.add(new RouteSubregion(rs));
@ -193,7 +200,7 @@ public class RoutingContext {
config.router = router; config.router = router;
} }
public void setHeuristicCoefficient(double heuristicCoefficient) { public void setHeuristicCoefficient(float heuristicCoefficient) {
config.heuristicCoefficient = heuristicCoefficient; config.heuristicCoefficient = heuristicCoefficient;
} }

View file

@ -10,7 +10,7 @@
<attribute name="zoomToLoadTiles" value="16" /> <attribute name="zoomToLoadTiles" value="16" />
<!-- by default it is 30. Value specified here overwrites all others <!-- by default it is 30. Value specified here overwrites all others
(don't specify here ! it is device dependent) --> (don't specify here ! it is device dependent) -->
<attribute name="memoryLimitInMB" value="" /> <attribute name="memoryLimitInMB" value="450" />
<!-- 1.2 Dynamic road prioritizing (heuristic) --> <!-- 1.2 Dynamic road prioritizing (heuristic) -->
<attribute name="useDynamicRoadPrioritising" value="false" /> <attribute name="useDynamicRoadPrioritising" value="false" />

View file

@ -138,8 +138,9 @@ public class MapClusterLayer implements MapPanelLayer {
ctx.setVisitor(new RouteSegmentVisitor() { ctx.setVisitor(new RouteSegmentVisitor() {
private List<RouteSegment> cache = new ArrayList<RouteSegment>(); private List<RouteSegment> cache = new ArrayList<RouteSegment>();
@Override @Override
public void visitSegment(RouteSegment s, boolean poll) { public void visitSegment(RouteSegment s, int endSegment, boolean poll) {
if(!ANIMATE_CLUSTERING){ if(!ANIMATE_CLUSTERING){
return; return;
} }
@ -269,7 +270,7 @@ public class MapClusterLayer implements MapPanelLayer {
if (!onTheMap.contains(toAdd.getRoad().getId())) { if (!onTheMap.contains(toAdd.getRoad().getId())) {
onTheMap.add(toAdd.getRoad().getId()); onTheMap.add(toAdd.getRoad().getId());
// Visualization of steps ! // Visualization of steps !
ctx.getVisitor().visitSegment(toAdd, true); ctx.getVisitor().visitSegment(toAdd, -1, true);
} }
List<RouteSegment> nextSegments = new ArrayList<BinaryRoutePlanner.RouteSegment>(); List<RouteSegment> nextSegments = new ArrayList<BinaryRoutePlanner.RouteSegment>();
boolean out = false; boolean out = false;

View file

@ -617,8 +617,7 @@ public class MapRouterLayer implements MapPanelLayer {
RoutingConfiguration config = builder.build(props[0], RoutingConfiguration.DEFAULT_MEMORY_LIMIT / 2, props); RoutingConfiguration config = builder.build(props[0], RoutingConfiguration.DEFAULT_MEMORY_LIMIT / 2, props);
// config.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY = 300; // config.NUMBER_OF_DESIRABLE_TILES_IN_MEMORY = 300;
// config.ZOOM_TO_LOAD_TILES = 14; // config.ZOOM_TO_LOAD_TILES = 14;
RoutingContext ctx = new RoutingContext(config, NativeSwingRendering.getDefaultFromSettings(), rs); RoutingContext ctx = new RoutingContext(config, NativeSwingRendering.getDefaultFromSettings(), rs, useBasemap);
ctx.USE_BASEMAP = useBasemap;
ctx.previouslyCalculatedRoute = previousRoute; ctx.previouslyCalculatedRoute = previousRoute;
log.info("Use " + config.routerName + "mode for routing"); log.info("Use " + config.routerName + "mode for routing");
@ -655,9 +654,10 @@ public class MapRouterLayer implements MapPanelLayer {
private List<RouteSegment> cache = new ArrayList<RouteSegment>(); private List<RouteSegment> cache = new ArrayList<RouteSegment>();
private List<RouteSegment> pollCache = new ArrayList<RouteSegment>(); private List<RouteSegment> pollCache = new ArrayList<RouteSegment>();
private List<Integer> cacheInt = new ArrayList<Integer>();
@Override @Override
public void visitSegment(RouteSegment s, boolean poll) { public void visitSegment(RouteSegment s, int endSegment, boolean poll) {
if(stop) { if(stop) {
throw new RuntimeException("Interrupted"); throw new RuntimeException("Interrupted");
} }
@ -670,33 +670,45 @@ public class MapRouterLayer implements MapPanelLayer {
} }
cache.add(s); cache.add(s);
cacheInt.add(endSegment);
if (cache.size() < steps) { if (cache.size() < steps) {
return; return;
} }
if(pause) { if(pause) {
registerObjects(points, poll, pollCache); registerObjects(points, poll, pollCache, null);
pollCache.clear(); pollCache.clear();
} }
registerObjects(points, !poll, cache); registerObjects(points, !poll, cache, cacheInt);
cache.clear(); cache.clear();
cacheInt.clear();
redraw(); redraw();
if (pause) { if (pause) {
waitNextPress(); waitNextPress();
} }
} }
private void registerObjects(final DataTileManager<Entity> points, boolean white, private void registerObjects(final DataTileManager<Entity> points, boolean white, List<RouteSegment> registerCache,
List<RouteSegment> registerCache) { List<Integer> cacheInt) {
for (RouteSegment segment : registerCache) { for (int l = 0; l < registerCache.size(); l++) {
RouteSegment segment = registerCache.get(l);
Way way = new Way(-1); Way way = new Way(-1);
way.putTag(OSMTagKey.NAME.getValue(), segment.getTestName()); way.putTag(OSMTagKey.NAME.getValue(), segment.getTestName());
if (white) { if (white) {
way.putTag("color", "white"); way.putTag("color", "white");
} }
for (int i = 0; i < segment.getRoad().getPointsLength(); i++) { 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); net.osmand.osm.Node n = createNode(segment, i);
way.addNode(n); way.addNode(n);
} }
}
LatLon n = way.getLatLon(); LatLon n = way.getLatLon();
points.registerObject(n.getLatitude(), n.getLongitude(), way); points.registerObject(n.getLatitude(), n.getLongitude(), way);
} }