diff --git a/DataExtractionOSM/src/net/osmand/binary/BinaryRouteDataReader.java b/DataExtractionOSM/src/net/osmand/binary/BinaryRouteDataReader.java index efbe7c92e0..f756686a6a 100644 --- a/DataExtractionOSM/src/net/osmand/binary/BinaryRouteDataReader.java +++ b/DataExtractionOSM/src/net/osmand/binary/BinaryRouteDataReader.java @@ -73,11 +73,11 @@ public class BinaryRouteDataReader { autoPriorityValues.put("tertiary", 1.0d); autoPriorityValues.put("tertiary_link", 1.0d); autoPriorityValues.put("residential", 0.8d); - autoPriorityValues.put("service", 0.5d); + autoPriorityValues.put("service", 0.6d); autoPriorityValues.put("unclassified", 0.7d); autoPriorityValues.put("road", 0.7d); - autoPriorityValues.put("track", 0.5d); - autoPriorityValues.put("path", 0.5d); + autoPriorityValues.put("track", 0.2d); + autoPriorityValues.put("path", 0.2d); autoPriorityValues.put("living_street", 0.5d); } @@ -216,6 +216,7 @@ public class BinaryRouteDataReader { RouteSegment next = null; // search context (needed for searching route) + // Initially it should be null (!) because it checks was it segment visited before RouteSegment parentRoute = null; int parentSegmentEnd = 0; @@ -285,7 +286,9 @@ public class BinaryRouteDataReader { for (BinaryMapIndexReader r : map) { r.searchMapIndex(request); 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; } ctx.idObjects.put(o.getId(), o); @@ -338,11 +341,12 @@ public class BinaryRouteDataReader { // TODO write unit tests + // TODO add information about turns // TODO think about u-turn // TODO fix roundabout // TODO access // TODO bicycle router (?) - // TODO routing between indexes + // TODO fastest/shortest way /** * Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm) * 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 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); - while(startNbs != null) { + while(startNbs != null) { // startNbs.road.id >> 3, start.road.id >> 3 if(startNbs.road.id != start.road.id){ startNbs.parentRoute = start; 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 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))); + long nt = (road.id << 8l) + segment.segmentStart; + visitedSegments.add(nt); // 3. get intersected ways RouteSegment next = ctx.routes.get(l); @@ -473,9 +480,9 @@ public class BinaryRouteDataReader { // 3.2 calculate possible ways to put into priority queue 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 */ - if(next.road.id != road.id && !visitedSegments.contains(nt)){ + if(next.road.id != road.id && !visitedSegments.contains(nts)){ int type = -1; for(int i = 0; i< road.getRestrictionCount(); i++){ if(road.getRestriction(i) == next.road.id){ @@ -491,10 +498,7 @@ public class BinaryRouteDataReader { type == MapRenderingTypes.RESTRICTION_NO_U_TURN){ // next = next.next; continue; } 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 y = road.getPoint31YTile(j); @@ -505,24 +509,38 @@ public class BinaryRouteDataReader { 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 - 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 - next.distanceFromStart += obstaclesTime; + distanceFromStart += obstaclesTime; - next.distanceToEnd = squareRootDist(x, y, endX, endY) / ctx.router.getMaxDefaultSpeed(); - if(type == -1){ - // case no restriction - segmentsToVisitNotForbidden.add(next); - } else { - // case exclusive restriction (only_right, only_straight, ...) - exclusiveRestriction = true; - segmentsToVisitNotForbidden.clear(); - segmentsToVisitPrescricted.add(next); + double distanceToEnd = squareRootDist(x, y, endX, endY) / ctx.router.getMaxDefaultSpeed(); + + if(next.parentRoute == null || next.distanceFromStart + next.distanceToEnd > + distanceFromStart + distanceToEnd){ + next.distanceFromStart = distanceFromStart; + next.distanceToEnd = distanceToEnd; + if(next.parentRoute != null){ + // already in queue remove it + 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; @@ -530,13 +548,9 @@ public class BinaryRouteDataReader { // add all allowed route segments to priority queue for(RouteSegment s : segmentsToVisitNotForbidden){ - long nt = (s.road.id << 8l) + s.segmentStart; - visitedSegments.add(nt); graphSegments.add(s); } for(RouteSegment s : segmentsToVisitPrescricted){ - long nt = (s.road.id << 8l) + s.segmentStart; - visitedSegments.add(nt); graphSegments.add(s); } } @@ -551,6 +565,11 @@ public class BinaryRouteDataReader { end.segmentEnd : end.segmentStart; 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){ RouteSegmentResult res = new RouteSegmentResult(); res.object = segment.road; @@ -567,6 +586,7 @@ public class BinaryRouteDataReader { } // do not add segments consists from 1 poitn if(res.startPointIndex != res.endPointIndex) { + System.out.println("id="+(res.object.id >> 3) + " start=" + res.startPointIndex + " end=" + res.endPointIndex); result.add(0, res); } res.startPoint = convertPoint(res.object, res.startPointIndex); diff --git a/DataExtractionOSM/src/net/osmand/binary/RouterTests.java b/DataExtractionOSM/src/net/osmand/binary/RouterTests.java new file mode 100644 index 0000000000..0fc3d1df5c --- /dev/null +++ b/DataExtractionOSM/src/net/osmand/binary/RouterTests.java @@ -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 + + + +} diff --git a/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java b/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java index a47474fea0..b96ace153a 100644 --- a/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java +++ b/DataExtractionOSM/src/net/osmand/swing/DataExtractionSettings.java @@ -42,14 +42,36 @@ public class DataExtractionSettings { } - public File getDefaultRoutingFile(){ + public File[] getDefaultRoutingFile(){ String routingFile = preferences.get("routing_file", null); - if(routingFile == null || !new File(routingFile).exists()){ + if(routingFile == null){ return null; } - return new File(routingFile); + String[] files = routingFile.split(","); + List fs = new ArrayList(); + 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){ preferences.put("routing_file", path); } diff --git a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java index a8760a7d0e..bf905d62eb 100644 --- a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java +++ b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java @@ -305,8 +305,8 @@ public class MapRouterLayer implements MapPanelLayer { public List selfRoute(LatLon start, LatLon end) { List res = new ArrayList(); long time = System.currentTimeMillis(); - File file = DataExtractionSettings.getSettings().getDefaultRoutingFile(); - if(file == null){ + File[] files = DataExtractionSettings.getSettings().getDefaultRoutingFile(); + if(files == null){ JOptionPane.showMessageDialog(OsmExtractionUI.MAIN_APP.getFrame(), "Please specify obf file in settings", "Obf file not found", JOptionPane.ERROR_MESSAGE); return null; @@ -314,10 +314,14 @@ public class MapRouterLayer implements MapPanelLayer { System.out.println("Self made route from " + start + " to " + end); if (start != null && end != null) { try { + BinaryMapIndexReader[] rs = new BinaryMapIndexReader[files.length]; + for(int i=0; i