fix router for some cases

git-svn-id: https://osmand.googlecode.com/svn/trunk@855 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
vics001 2010-12-26 00:51:14 +00:00
parent a60ef26f4d
commit 0b064d51db
5 changed files with 196 additions and 42 deletions

View file

@ -73,11 +73,11 @@ public class BinaryRouteDataReader {
autoPriorityValues.put("tertiary", 1.0d); autoPriorityValues.put("tertiary", 1.0d);
autoPriorityValues.put("tertiary_link", 1.0d); autoPriorityValues.put("tertiary_link", 1.0d);
autoPriorityValues.put("residential", 0.8d); autoPriorityValues.put("residential", 0.8d);
autoPriorityValues.put("service", 0.5d); autoPriorityValues.put("service", 0.6d);
autoPriorityValues.put("unclassified", 0.7d); autoPriorityValues.put("unclassified", 0.7d);
autoPriorityValues.put("road", 0.7d); autoPriorityValues.put("road", 0.7d);
autoPriorityValues.put("track", 0.5d); autoPriorityValues.put("track", 0.2d);
autoPriorityValues.put("path", 0.5d); autoPriorityValues.put("path", 0.2d);
autoPriorityValues.put("living_street", 0.5d); autoPriorityValues.put("living_street", 0.5d);
} }
@ -216,6 +216,7 @@ public class BinaryRouteDataReader {
RouteSegment next = null; RouteSegment next = null;
// search context (needed for searching route) // search context (needed for searching route)
// Initially it should be null (!) because it checks was it segment visited before
RouteSegment parentRoute = null; RouteSegment parentRoute = null;
int parentSegmentEnd = 0; int parentSegmentEnd = 0;
@ -285,7 +286,9 @@ public class BinaryRouteDataReader {
for (BinaryMapIndexReader r : map) { for (BinaryMapIndexReader r : map) {
r.searchMapIndex(request); r.searchMapIndex(request);
for (BinaryMapDataObject o : request.searchResults) { for (BinaryMapDataObject o : request.searchResults) {
if (ctx.idObjects.containsKey(o.getId())) { BinaryMapDataObject old = ctx.idObjects.get(o.getId());
// sometimes way are presented only partially in one index
if (old != null && old.getPointsLength() >= o.getPointsLength()) {
continue; continue;
} }
ctx.idObjects.put(o.getId(), o); ctx.idObjects.put(o.getId(), o);
@ -338,11 +341,12 @@ public class BinaryRouteDataReader {
// TODO write unit tests // TODO write unit tests
// TODO add information about turns
// TODO think about u-turn // TODO think about u-turn
// TODO fix roundabout // TODO fix roundabout
// TODO access // TODO access
// TODO bicycle router (?) // TODO bicycle router (?)
// TODO routing between indexes // TODO fastest/shortest way
/** /**
* Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm) * Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm)
* return list of segments * return list of segments
@ -381,8 +385,9 @@ public class BinaryRouteDataReader {
// because first point of the start is not visited do the same as in cycle but only for one point // because first point of the start is not visited do the same as in cycle but only for one point
long ls = (((long) startX) << 31) + (long) startY; long ls = (((long) startX) << 31) + (long) startY;
loadRoutes(ctx, (startX >> (31 - ZOOM_LOAD_TILES)), (startY >> (31 - ZOOM_LOAD_TILES)));
RouteSegment startNbs = ctx.routes.get(ls); RouteSegment startNbs = ctx.routes.get(ls);
while(startNbs != null) { while(startNbs != null) { // startNbs.road.id >> 3, start.road.id >> 3
if(startNbs.road.id != start.road.id){ if(startNbs.road.id != start.road.id){
startNbs.parentRoute = start; startNbs.parentRoute = start;
startNbs.parentSegmentEnd = start.segmentStart; startNbs.parentSegmentEnd = start.segmentStart;
@ -453,6 +458,8 @@ public class BinaryRouteDataReader {
// 2. calculate point and try to load neighbor ways if they are not loaded // 2. calculate point and try to load neighbor ways if they are not loaded
long l = (((long) road.getPoint31XTile(j)) << 31) + (long) road.getPoint31YTile(j); long l = (((long) road.getPoint31XTile(j)) << 31) + (long) road.getPoint31YTile(j);
loadRoutes(ctx, (road.getPoint31XTile(j) >> (31 - ZOOM_LOAD_TILES)), (road.getPoint31YTile(j) >> (31 - ZOOM_LOAD_TILES))); loadRoutes(ctx, (road.getPoint31XTile(j) >> (31 - ZOOM_LOAD_TILES)), (road.getPoint31YTile(j) >> (31 - ZOOM_LOAD_TILES)));
long nt = (road.id << 8l) + segment.segmentStart;
visitedSegments.add(nt);
// 3. get intersected ways // 3. get intersected ways
RouteSegment next = ctx.routes.get(l); RouteSegment next = ctx.routes.get(l);
@ -473,9 +480,9 @@ public class BinaryRouteDataReader {
// 3.2 calculate possible ways to put into priority queue // 3.2 calculate possible ways to put into priority queue
while(next != null){ while(next != null){
long nt = (next.road.id << 8l) + next.segmentStart; long nts = (next.road.id << 8l) + next.segmentStart;
/* next.road.id >> 3 != road.id >> 3 - used that line for debug with osm map */ /* next.road.id >> 3 != road.id >> 3 - used that line for debug with osm map */
if(next.road.id != road.id && !visitedSegments.contains(nt)){ if(next.road.id != road.id && !visitedSegments.contains(nts)){
int type = -1; int type = -1;
for(int i = 0; i< road.getRestrictionCount(); i++){ for(int i = 0; i< road.getRestrictionCount(); i++){
if(road.getRestriction(i) == next.road.id){ if(road.getRestriction(i) == next.road.id){
@ -491,10 +498,7 @@ public class BinaryRouteDataReader {
type == MapRenderingTypes.RESTRICTION_NO_U_TURN){ type == MapRenderingTypes.RESTRICTION_NO_U_TURN){
// next = next.next; continue; // next = next.next; continue;
} else { } else {
// because no one segment is visited twice (see check before)
// put additional information to recover whole route after
next.parentRoute = segment;
next.parentSegmentEnd = j;
int x = road.getPoint31XTile(j); int x = road.getPoint31XTile(j);
int y = road.getPoint31YTile(j); int y = road.getPoint31YTile(j);
@ -505,24 +509,38 @@ public class BinaryRouteDataReader {
speed = ctx.router.getMinDefaultSpeed(); speed = ctx.router.getMinDefaultSpeed();
} }
next.distanceFromStart = segment.distanceFromStart + squareRootDist(x, y, middlex, middley) / speed; double distanceFromStart = segment.distanceFromStart + squareRootDist(x, y, middlex, middley) / speed;
// calculate turn time // calculate turn time
next.distanceFromStart += ctx.router.calculateTurnTime(middley, middlex, x, y, segment, next, j); distanceFromStart += ctx.router.calculateTurnTime(middley, middlex, x, y, segment, next, j);
// add obstacles time // add obstacles time
next.distanceFromStart += obstaclesTime; distanceFromStart += obstaclesTime;
next.distanceToEnd = squareRootDist(x, y, endX, endY) / ctx.router.getMaxDefaultSpeed(); double distanceToEnd = squareRootDist(x, y, endX, endY) / ctx.router.getMaxDefaultSpeed();
if(type == -1){
// case no restriction if(next.parentRoute == null || next.distanceFromStart + next.distanceToEnd >
segmentsToVisitNotForbidden.add(next); distanceFromStart + distanceToEnd){
} else { next.distanceFromStart = distanceFromStart;
// case exclusive restriction (only_right, only_straight, ...) next.distanceToEnd = distanceToEnd;
exclusiveRestriction = true; if(next.parentRoute != null){
segmentsToVisitNotForbidden.clear(); // already in queue remove it
segmentsToVisitPrescricted.add(next); graphSegments.remove(next);
}
// put additional information to recover whole route after
next.parentRoute = segment;
next.parentSegmentEnd = j;
if(type == -1){
// case no restriction
segmentsToVisitNotForbidden.add(next);
} else {
// case exclusive restriction (only_right, only_straight, ...)
exclusiveRestriction = true;
segmentsToVisitNotForbidden.clear();
segmentsToVisitPrescricted.add(next);
}
} }
} }
} }
next = next.next; next = next.next;
@ -530,13 +548,9 @@ public class BinaryRouteDataReader {
// add all allowed route segments to priority queue // add all allowed route segments to priority queue
for(RouteSegment s : segmentsToVisitNotForbidden){ for(RouteSegment s : segmentsToVisitNotForbidden){
long nt = (s.road.id << 8l) + s.segmentStart;
visitedSegments.add(nt);
graphSegments.add(s); graphSegments.add(s);
} }
for(RouteSegment s : segmentsToVisitPrescricted){ for(RouteSegment s : segmentsToVisitPrescricted){
long nt = (s.road.id << 8l) + s.segmentStart;
visitedSegments.add(nt);
graphSegments.add(s); graphSegments.add(s);
} }
} }
@ -551,6 +565,11 @@ public class BinaryRouteDataReader {
end.segmentEnd : end.segmentStart; end.segmentEnd : end.segmentStart;
RouteSegment segment = finalRoute; RouteSegment segment = finalRoute;
System.out.println("ROUTE : ");
System.out.println("Start lat=" + MapUtils.get31LatitudeY(start.road.getPoint31YTile(start.segmentEnd)) +
" lon=" + MapUtils.get31LongitudeX(start.road.getPoint31XTile(start.segmentEnd)));
System.out.println("END lat=" + MapUtils.get31LatitudeY(end.road.getPoint31YTile(end.segmentStart)) +
" lon=" + MapUtils.get31LongitudeX(end.road.getPoint31XTile(end.segmentStart)));
while(segment != null){ while(segment != null){
RouteSegmentResult res = new RouteSegmentResult(); RouteSegmentResult res = new RouteSegmentResult();
res.object = segment.road; res.object = segment.road;
@ -567,6 +586,7 @@ public class BinaryRouteDataReader {
} }
// do not add segments consists from 1 poitn // do not add segments consists from 1 poitn
if(res.startPointIndex != res.endPointIndex) { if(res.startPointIndex != res.endPointIndex) {
System.out.println("id="+(res.object.id >> 3) + " start=" + res.startPointIndex + " end=" + res.endPointIndex);
result.add(0, res); result.add(0, res);
} }
res.startPoint = convertPoint(res.object, res.startPointIndex); res.startPoint = convertPoint(res.object, res.startPointIndex);

View file

@ -0,0 +1,110 @@
package net.osmand.binary;
public class RouterTests {
//
// BELARUS
// 1. Correct BREST near to border!
// Start lat=52.15449120254751 lon=23.901958465576172
// END lat=52.07294489666366 lon=23.656225204467773
// id=34001524 start=0 end=2
// id=58208937 start=0 end=9
// id=58208944 start=0 end=20
// id=25297376 start=0 end=1
// id=64080970 start=0 end=1
// id=58208916 start=0 end=8
// id=28510027 start=0 end=2
// id=28510029 start=0 end=6
// id=25296360 start=0 end=4
// id=75839018 start=0 end=33
// id=84437417 start=0 end=3
// id=84437365 start=0 end=1
// id=31775053 start=5 end=22
// id=36294997 start=36 end=0
// MINSK (good known way). The best at 70%
// Start lat=53.91088592425074 lon=27.579095363616943
// END lat=53.953863330122196 lon=27.68131971359253
// id=46724311 start=6 end=2
// id=60889993 start=0 end=9
// id=25225646 start=0 end=18
// id=25225916 start=0 end=22
// id=30854239 start=16 end=0
// id=30854243 start=1 end=0
// id=30854252 start=0 end=8
// id=30854254 start=0 end=1
// id=33912019 start=0 end=2
// id=33912004 start=0 end=5
// id=33911980 start=0 end=9
// id=33911977 start=0 end=1
// id=33911967 start=0 end=3
// id=31499010 start=0 end=8
// id=35566247 start=0 end=5
// id=35566202 start=0 end=2
// id=37700614 start=0 end=1
// id=33911493 start=0 end=1
// id=31279905 start=0 end=3
// id=33911472 start=0 end=2
// id=33911443 start=1 end=7
// id=31691782 start=1 end=0
// id=40885457 start=1 end=0
// id=40885456 start=1 end=0
// id=40885459 start=3 end=2
// MINSK (restriction + roundabout). The best at 80%
// Start lat=53.91104391755144 lon=27.57664918899536
// END lat=53.91172012212507 lon=27.57993221282959
// id=40885459 start=2 end=3
// id=40885456 start=0 end=1
// id=40885457 start=0 end=1
// id=31691782 start=0 end=1
// id=33911443 start=0 end=1
// id=25228312 start=0 end=6
// id=61594239 start=0 end=1
// id=61594235 start=0 end=3
// id=25228310 start=0 end=5
// id=61594238 start=0 end=2
// id=25441562 start=0 end=3
// id=33911427 start=0 end=1
// id=33911466 start=0 end=4
// MINSK (restriction + roundabout). The best at 95%
// Start lat=53.90940707797713 lon=27.49480962753296
// END lat=53.910405620946285 lon=27.49556064605713
// id=30821192 start=0 end=3
// id=48470183 start=0 end=1
// id=48470184 start=0 end=1
// id=48470565 start=0 end=1
// id=30821117 start=0 end=1
// id=30813591 start=7 end=8
// MINSK. The best at 90%
// Start lat=53.92008645787278 lon=27.58763551712036
// END lat=53.93877827466741 lon=27.605509757995605
// id=25227299 start=0 end=1
// id=50727963 start=0 end=2
// id=50727962 start=0 end=4
// id=50728110 start=0 end=2
// id=33911936 start=0 end=12
// id=33911931 start=0 end=1
// id=33911932 start=0 end=1
// id=33911926 start=0 end=4
// id=33911764 start=0 end=3
// id=38575349 start=0 end=1
// id=38575351 start=0 end=2
// id=38575346 start=0 end=1
// id=33911503 start=0 end=2
// id=38571365 start=0 end=5
// id=38571368 start=0 end=4
// id=38571370 start=1 end=2
// POLAND/BELARUS (problems with way connection) The best at 100%
// Start lat=52.115756035004786 lon=23.56539487838745
// END lat=52.03710226357107 lon=23.47106695175171
// id=32032589 start=8 end=9
// id=32032656 start=0 end=18
// id=32031919 start=1 end=0
}

View file

@ -42,14 +42,36 @@ public class DataExtractionSettings {
} }
public File getDefaultRoutingFile(){ public File[] getDefaultRoutingFile(){
String routingFile = preferences.get("routing_file", null); String routingFile = preferences.get("routing_file", null);
if(routingFile == null || !new File(routingFile).exists()){ if(routingFile == null){
return null; return null;
} }
return new File(routingFile); String[] files = routingFile.split(",");
List<File> fs = new ArrayList<File>();
for(String f : files){
if(new File(f.trim()).exists()){
fs.add(new File(f.trim()));
}
}
return fs.toArray(new File[fs.size()]);
} }
public String getDefaultRoutingFilePath(){
File[] file = getDefaultRoutingFile();
String path = "";
if (file != null) {
for (int i = 0; i < file.length; i++) {
if (i > 0) {
path += ", ";
}
path += file[i].getAbsolutePath();
}
}
return path;
}
public void setDefaultRoutingPath(String path){ public void setDefaultRoutingPath(String path){
preferences.put("routing_file", path); preferences.put("routing_file", path);
} }

View file

@ -305,8 +305,8 @@ public class MapRouterLayer implements MapPanelLayer {
public List<Way> selfRoute(LatLon start, LatLon end) { public List<Way> selfRoute(LatLon start, LatLon end) {
List<Way> res = new ArrayList<Way>(); List<Way> res = new ArrayList<Way>();
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
File file = DataExtractionSettings.getSettings().getDefaultRoutingFile(); File[] files = DataExtractionSettings.getSettings().getDefaultRoutingFile();
if(file == null){ if(files == null){
JOptionPane.showMessageDialog(OsmExtractionUI.MAIN_APP.getFrame(), "Please specify obf file in settings", "Obf file not found", JOptionPane.showMessageDialog(OsmExtractionUI.MAIN_APP.getFrame(), "Please specify obf file in settings", "Obf file not found",
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
return null; return null;
@ -314,10 +314,14 @@ public class MapRouterLayer implements MapPanelLayer {
System.out.println("Self made route from " + start + " to " + end); System.out.println("Self made route from " + start + " to " + end);
if (start != null && end != null) { if (start != null && end != null) {
try { try {
BinaryMapIndexReader[] rs = new BinaryMapIndexReader[files.length];
for(int i=0; i<files.length; i++){
RandomAccessFile raf = new RandomAccessFile(files[i], "r"); //$NON-NLS-1$ //$NON-NLS-2$
rs[i] = new BinaryMapIndexReader(raf);
RandomAccessFile raf = new RandomAccessFile(file, "r"); //$NON-NLS-1$ //$NON-NLS-2$ }
BinaryMapIndexReader reader = new BinaryMapIndexReader(raf);
BinaryRouteDataReader router = new BinaryRouteDataReader(reader); BinaryRouteDataReader router = new BinaryRouteDataReader(rs);
RoutingContext ctx = new RoutingContext(); RoutingContext ctx = new RoutingContext();
// find closest way // find closest way

View file

@ -108,8 +108,8 @@ public class OsmExtractionPreferencesDialog extends JDialog {
l.setConstraints(label, constr); l.setConstraints(label, constr);
pathToObfRoutingFile = new JTextField(); pathToObfRoutingFile = new JTextField();
File file = DataExtractionSettings.getSettings().getDefaultRoutingFile();
pathToObfRoutingFile.setText(file == null ? "" : file.getAbsolutePath()); pathToObfRoutingFile.setText(DataExtractionSettings.getSettings().getDefaultRoutingFilePath());
panel.add(pathToObfRoutingFile); panel.add(pathToObfRoutingFile);
constr = new GridBagConstraints(); constr = new GridBagConstraints();
constr.weightx = 1; constr.weightx = 1;
@ -260,9 +260,7 @@ public class OsmExtractionPreferencesDialog extends JDialog {
if(!settings.getMapRenderingTypesFile().equals(renderingTypesFile.getText())){ if(!settings.getMapRenderingTypesFile().equals(renderingTypesFile.getText())){
settings.setMapRenderingTypesFile(renderingTypesFile.getText()); settings.setMapRenderingTypesFile(renderingTypesFile.getText());
} }
File f = settings.getDefaultRoutingFile(); if(!settings.getDefaultRoutingFilePath().equals(pathToObfRoutingFile.getText())){
String routingFile = f == null ? "" : f.getAbsolutePath();
if(!routingFile.equals(pathToObfRoutingFile.getText())){
settings.setDefaultRoutingPath(pathToObfRoutingFile.getText()); settings.setDefaultRoutingPath(pathToObfRoutingFile.getText());
} }
// if(settings.isSupressWarningsForDuplicatedId() != supressWarning.isSelected()){ // if(settings.isSupressWarningsForDuplicatedId() != supressWarning.isSelected()){