From efaf4e25c4d9dadeca74406456a2bdcf0b227110 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Thu, 1 Nov 2012 00:46:09 +0100 Subject: [PATCH] Test native routing implementation --- .../src/net/osmand/NativeLibrary.java | 8 +- .../src/net/osmand/router/RoutingContext.java | 17 +- .../src/net/osmand/swing/MapRouterLayer.java | 19 +- Osmand-kernel/osmand/src/binaryRead.cpp | 167 ++++--- Osmand-kernel/osmand/src/binaryRead.h | 9 +- .../osmand/src/binaryRoutePlanner.cpp | 293 ++++++------- Osmand-kernel/osmand/src/binaryRoutePlanner.h | 414 ++++++++++++++++++ Osmand-kernel/osmand/src/common.cpp | 12 +- Osmand-kernel/osmand/src/java_wrap.cpp | 38 +- 9 files changed, 726 insertions(+), 251 deletions(-) diff --git a/DataExtractionOSM/src/net/osmand/NativeLibrary.java b/DataExtractionOSM/src/net/osmand/NativeLibrary.java index 1adbe0d1c8..67d3036eca 100644 --- a/DataExtractionOSM/src/net/osmand/NativeLibrary.java +++ b/DataExtractionOSM/src/net/osmand/NativeLibrary.java @@ -7,6 +7,7 @@ import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteSubregion; import net.osmand.binary.RouteDataObject; import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRulesStorage; +import net.osmand.router.RouteSegmentResult; public class NativeLibrary { @@ -81,7 +82,6 @@ public class NativeLibrary { if(rs.nativeHandler == 0) { // do not throw exception because it is expected situation return new RouteDataObject[0]; -// throw new IllegalStateException("Native route handler is 0"); } return getRouteDataObjects(rs.region.routeReg, rs.nativeHandler, x31, y31); } @@ -99,6 +99,10 @@ public class NativeLibrary { return closeBinaryMapFile(filePath); } + public RouteSegmentResult[] testRoutingInternal(int sx31, int sy31, int ex31, int ey31) { + return testRouting(sx31, sy31, ex31, ey31); + } + public NativeRouteSearchResult loadRouteRegion(RouteSubregion sub, boolean loadObjects) { @@ -118,6 +122,8 @@ public class NativeLibrary { protected static native RouteDataObject[] getRouteDataObjects(RouteRegion reg, long rs, int x31, int y31); + protected static native RouteSegmentResult[] testRouting(int sx31, int sy31, int ex31, int ey31); + protected static native void deleteSearchResult(long searchResultHandle); protected static native boolean initBinaryMapFile(String filePath); diff --git a/DataExtractionOSM/src/net/osmand/router/RoutingContext.java b/DataExtractionOSM/src/net/osmand/router/RoutingContext.java index 4bf2517e6d..684c51842b 100644 --- a/DataExtractionOSM/src/net/osmand/router/RoutingContext.java +++ b/DataExtractionOSM/src/net/osmand/router/RoutingContext.java @@ -517,13 +517,20 @@ public class RoutingContext { } public void loadTileData(int x31, int y31, int zoomAround, final List toFillIn) { - int coordinatesShift = (1 << (31 - zoomAround)); + int t = zoomAround - config.ZOOM_TO_LOAD_TILES; + if(t <= 0) { + t = 1; + } else { + t = 1 << t; + } + int coordinatesShift = (1 << (31 - config.ZOOM_TO_LOAD_TILES)); TLongHashSet ts = new TLongHashSet(); long now = System.nanoTime(); - ts.add(getRoutingTile(x31 - coordinatesShift, y31 - coordinatesShift, 0, OPTION_IN_MEMORY_LOAD)); - ts.add(getRoutingTile(x31 + coordinatesShift, y31 - coordinatesShift, 0, OPTION_IN_MEMORY_LOAD)); - ts.add(getRoutingTile(x31 - coordinatesShift, y31 + coordinatesShift, 0, OPTION_IN_MEMORY_LOAD)); - ts.add(getRoutingTile(x31 + coordinatesShift, y31 + coordinatesShift, 0, OPTION_IN_MEMORY_LOAD)); + for(int i = -t; i <= t; i++) { + for(int j = -t; j <= t; j++) { + ts.add(getRoutingTile(x31 +i*coordinatesShift, y31 + j*coordinatesShift, 0, OPTION_IN_MEMORY_LOAD)); + } + } TLongIterator it = ts.iterator(); while(it.hasNext()){ getAllObjects(it.next(), toFillIn); diff --git a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java index 74fd0e9c12..11c793fb0a 100644 --- a/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java +++ b/DataExtractionOSM/src/net/osmand/swing/MapRouterLayer.java @@ -631,6 +631,8 @@ public class MapRouterLayer implements MapPanelLayer { 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 inters = new ArrayList(); @@ -714,8 +716,14 @@ public class MapRouterLayer implements MapPanelLayer { }); - List searchRoute = router.searchRoute(ctx, st, e, inters, false); - this.previousRoute = searchRoute; + int ex31 = e.getRoad().getPoint31XTile(e.getSegmentStart()); + int ey31 = e.getRoad().getPoint31YTile(e.getSegmentStart()); + int sx31 = st.getRoad().getPoint31XTile(st.getSegmentStart()); + int sy31 = st.getRoad().getPoint31YTile(st.getSegmentStart()); + // FIXME + RouteSegmentResult[] searchRoute = ctx.nativeLib.testRoutingInternal(sx31, sy31, ex31, ey31); + /*List searchRoute = */router.searchRoute(ctx, st, e, inters, false); +// this.previousRoute = searchRoute; if (animateRoutingCalculation) { playPauseButton.setVisible(false); nextTurn.setText("FINISH"); @@ -734,13 +742,14 @@ public class MapRouterLayer implements MapPanelLayer { // String name = String.format("beg %.2f end %.2f ", s.getBearingBegin(), s.getBearingEnd()); way.putTag(OSMTagKey.NAME.getValue(),name); boolean plus = s.getStartPointIndex() < s.getEndPointIndex(); + System.out.println("Segment " + s.getObject().id + " "+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().getHighway() + " dist " + System.out.println("Warning not connected road " + " " + s.getObject().id + " dist " + MapUtils.getDistance(prevWayNode, n)); } prevWayNode = null; @@ -760,9 +769,7 @@ public class MapRouterLayer implements MapPanelLayer { } res.add(way); } - } catch (IOException e) { - ExceptionHandler.handle(e); - } catch (InterruptedException e) { + } catch (Exception e) { ExceptionHandler.handle(e); } finally { playPauseButton.setVisible(false); diff --git a/Osmand-kernel/osmand/src/binaryRead.cpp b/Osmand-kernel/osmand/src/binaryRead.cpp index 9d0778a310..6fc3b213ab 100644 --- a/Osmand-kernel/osmand/src/binaryRead.cpp +++ b/Osmand-kernel/osmand/src/binaryRead.cpp @@ -1,3 +1,4 @@ + #include "binaryRead.h" #include @@ -22,6 +23,7 @@ using google::protobuf::internal::WireFormatLite; static int zoomForBaseRouteRendering = 14; std::map< std::string, BinaryMapFile* > openFiles; OsmAndStoredIndex* cache = NULL; +typedef UNORDERED(set) IDS_SET; void searchRouteSubRegion(int fileInd, std::vector& list, RoutingIndex* routingIndex, RouteSubregion* sub); void searchRouteRegion(CodedInputStream* input, SearchQuery* q, RoutingIndex* ind, std::vector& subregions, @@ -249,7 +251,8 @@ bool readMapEncodingRule(CodedInputStream* input, MapIndex* index, uint32_t id) } -bool readRouteTree(CodedInputStream* input, RouteSubregion* thisTree, RouteSubregion* parentTree, int depth, bool readCoordinates) { +bool readRouteTree(CodedInputStream* input, RouteSubregion* thisTree, RouteSubregion* parentTree, RoutingIndex* ind, + int depth, bool readCoordinates) { bool readChildren = depth != 0; uint32_t tag; int i; @@ -290,11 +293,11 @@ bool readRouteTree(CodedInputStream* input, RouteSubregion* thisTree, RouteSubre } case OsmAndRoutingIndex_RouteDataBox::kBoxesFieldNumber: { if (readChildren) { - RouteSubregion subregion; + RouteSubregion subregion(ind); readInt(input, &subregion.length); subregion.filePointer = input->getTotalBytesRead(); int oldLimit = input->PushLimit(subregion.length); - readRouteTree(input, &subregion, thisTree, depth - 1, true); + readRouteTree(input, &subregion, thisTree, ind, depth - 1, true); input->PopLimit(oldLimit); input->Seek(subregion.filePointer + subregion.length); thisTree->subregions.push_back(subregion); @@ -340,18 +343,16 @@ bool readRoutingIndex(CodedInputStream* input, RoutingIndex* routingIndex) { case OsmAndRoutingIndex::kRootBoxesFieldNumber: case OsmAndRoutingIndex::kBasemapBoxesFieldNumber:{ bool basemap = WireFormatLite::GetTagFieldNumber(tag) == OsmAndRoutingIndex::kBasemapBoxesFieldNumber; - RouteSubregion subregion; + RouteSubregion subregion(routingIndex); readInt(input, &subregion.length); subregion.filePointer = input->getTotalBytesRead(); int oldLimit = input->PushLimit(subregion.length); - readRouteTree(input, &subregion, NULL, 0, true); + readRouteTree(input, &subregion, NULL, routingIndex, 0, true); input->PopLimit(oldLimit); input->Seek(subregion.filePointer + subregion.length); if(basemap) { - osmand_log_print(LOG_INFO, "route basemap %d %s",subregion.filePointer, routingIndex->name.c_str() ); routingIndex->basesubregions.push_back(subregion); } else { - osmand_log_print(LOG_INFO, "route map %d %s",subregion.filePointer, routingIndex->name.c_str() ); routingIndex->subregions.push_back(subregion); } break; @@ -902,7 +903,7 @@ void searchMapData(CodedInputStream* input, MapRoot* root, MapIndex* ind, Search void convertRouteDataObjecToMapObjects(SearchQuery* q, std::vector& list, std::vector& tempResult, - bool skipDuplicates, UNORDERED(set)& ids) { + bool skipDuplicates, IDS_SET& ids) { std::vector::iterator rIterator = list.begin(); tempResult.reserve((size_t) (list.size() + tempResult.size())); for (; rIterator != list.end(); rIterator++) { @@ -972,62 +973,97 @@ void checkAndInitRouteRegionRules(int fileInd, RoutingIndex* routingIndex){ } } - -void readRouteDataAsMapObjects(SearchQuery* q, BinaryMapFile* file, std::vector& tempResult, - bool skipDuplicates, UNORDERED(set)& ids) { - - for (std::vector::iterator routeIndex = file->routingIndexes.begin(); - routeIndex != file->routingIndexes.end(); routeIndex++) { - if (q->publisher->isCancelled()) { - break; - } - bool contains = false; - std::vector subs = - q->zoom <= zoomForBaseRouteRendering ? (*routeIndex)->basesubregions : (*routeIndex)->subregions; - for (std::vector::iterator subreg = subs.begin(); subreg != subs.end(); subreg++) { - if (subreg->right >= q->left && q->right >= subreg->left && subreg->bottom >= q->top - && q->bottom >= subreg->top) { - osmand_log_print(LOG_INFO, "Search route map %s", (*routeIndex)->name.c_str()); - contains = true; - } - } - osmand_log_print(LOG_INFO, "Search map %s %d", (*routeIndex)->name.c_str(), subs.size()); - if (contains) { - vector found; - lseek(file->fd, 0, SEEK_SET); - FileInputStream input(file->fd); - input.SetCloseOnDelete(false); - CodedInputStream cis(&input); - cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 1); - cis.Seek((*routeIndex)->filePointer); - uint32_t old = cis.PushLimit((*routeIndex)->length); - searchRouteRegion(&cis, q, *routeIndex, subs, found); - cis.PopLimit(old); - - checkAndInitRouteRegionRules(file->fd, (*routeIndex)); - osmand_log_print(LOG_INFO, "Search map %s %d", (*routeIndex)->name.c_str(), found.size()); - sort(found.begin(), found.end(), sortRouteRegions); - { - lseek(file->fd, 0, SEEK_SET); - FileInputStream input(file->fd); - input.SetCloseOnDelete(false); - CodedInputStream cis(&input); - cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 2); - for (std::vector::iterator sub = found.begin(); sub != found.end();sub++) { - std::vector list; - cis.Seek(sub->filePointer + sub->mapDataBlock); - uint32_t length; - cis.ReadVarint32(&length); - uint32_t old = cis.PushLimit(length); - readRouteTreeData(&cis, &(*sub), list, *routeIndex); - cis.PopLimit(old); - convertRouteDataObjecToMapObjects(q, list, tempResult, skipDuplicates, ids); - } - } +void searchRouteSubregions(SearchQuery* q, std::vector& tempResult) { + map::iterator i = openFiles.begin(); + for (; i != openFiles.end() && !q->publisher->isCancelled(); i++) { + BinaryMapFile* file = i->second; + std::vector::iterator routeIndex = file->routingIndexes.begin(); + for (; routeIndex != file->routingIndexes.end(); routeIndex++) { + bool contains = false; + std::vector& subs = (*routeIndex)->subregions; + for (std::vector::iterator subreg = subs.begin(); subreg != subs.end(); subreg++) { + if (subreg->right >= q->left && q->right >= subreg->left && subreg->bottom >= q->top + && q->bottom >= subreg->top) { + contains = true; } } + if (contains) { + lseek(file->fd, 0, SEEK_SET); + FileInputStream input(file->fd); + input.SetCloseOnDelete(false); + CodedInputStream cis(&input); + cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 1); + cis.Seek((*routeIndex)->filePointer); + uint32_t old = cis.PushLimit((*routeIndex)->length); + searchRouteRegion(&cis, q, *routeIndex, subs, tempResult); + cis.PopLimit(old); + checkAndInitRouteRegionRules(file->fd, (*routeIndex)); + } } + } +} + +void readRouteMapObjects(SearchQuery* q, BinaryMapFile* file, vector& found, + RoutingIndex* routeIndex, std::vector& tempResult, bool skipDuplicates, + IDS_SET& ids) { + osmand_log_print(LOG_INFO, "Search map %s %d", routeIndex->name.c_str(), found.size()); + sort(found.begin(), found.end(), sortRouteRegions); + lseek(file->fd, 0, SEEK_SET); + FileInputStream input(file->fd); + input.SetCloseOnDelete(false); + CodedInputStream cis(&input); + cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 2); + for (std::vector::iterator sub = found.begin(); sub != found.end(); sub++) { + std::vector list; + cis.Seek(sub->filePointer + sub->mapDataBlock); + uint32_t length; + cis.ReadVarint32(&length); + uint32_t old = cis.PushLimit(length); + readRouteTreeData(&cis, &(*sub), list, routeIndex); + cis.PopLimit(old); + convertRouteDataObjecToMapObjects(q, list, tempResult, skipDuplicates, ids); + } +} + +void readRouteDataAsMapObjects(SearchQuery* q, BinaryMapFile* file, std::vector& tempResult, + bool skipDuplicates, IDS_SET& ids) { + std::vector::iterator routeIndex = file->routingIndexes.begin(); + for (; routeIndex != file->routingIndexes.end(); routeIndex++) { + if (q->publisher->isCancelled()) { + break; + } + bool contains = false; + std::vector subs = (*routeIndex)->subregions; + if (q->zoom <= zoomForBaseRouteRendering) { + subs = (*routeIndex)->basesubregions; + } + for (std::vector::iterator subreg = subs.begin(); subreg != subs.end(); subreg++) { + if (subreg->right >= q->left && q->right >= subreg->left && subreg->bottom >= q->top + && q->bottom >= subreg->top) { + osmand_log_print(LOG_INFO, "Search route map %s", (*routeIndex)->name.c_str()); + contains = true; + } + } + osmand_log_print(LOG_INFO, "Search map %s %d", (*routeIndex)->name.c_str(), subs.size()); + if (contains) { + vector found; + lseek(file->fd, 0, SEEK_SET); + FileInputStream input(file->fd); + input.SetCloseOnDelete(false); + CodedInputStream cis(&input); + cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 1); + cis.Seek((*routeIndex)->filePointer); + uint32_t old = cis.PushLimit((*routeIndex)->length); + searchRouteRegion(&cis, q, *routeIndex, subs, found); + cis.PopLimit(old); + checkAndInitRouteRegionRules(file->fd, (*routeIndex)); + + readRouteMapObjects(q, file, found, (*routeIndex), tempResult, skipDuplicates, ids); + } + } +} + void readMapObjects(SearchQuery* q, BinaryMapFile* file) { for (std::vector::iterator mapIndex = file->mapIndexes.begin(); mapIndex != file->mapIndexes.end(); mapIndex++) { @@ -1080,7 +1116,7 @@ void readMapObjects(SearchQuery* q, BinaryMapFile* file) { ResultPublisher* searchObjectsForRendering(SearchQuery* q, bool skipDuplicates, int renderRouteDataFile, std::string msgNothingFound) { map::iterator i = openFiles.begin(); - UNORDERED(set) ids; + IDS_SET ids; if(skipDuplicates){ // override it for now // TODO skip duplicates doesn't work correctly with basemap ? @@ -1230,7 +1266,7 @@ void searchRouteRegion(CodedInputStream* input, SearchQuery* q, RoutingIndex* in && subreg->bottom >= q->bottom; input->Seek(subreg->filePointer); uint32_t old = input->PushLimit(subreg->length); - readRouteTree(input, &(*subreg), NULL, -1/*contains? -1 : 1*/, false); + readRouteTree(input, &(*subreg), NULL, ind, -1/*contains? -1 : 1*/, false); input->PopLimit(old); } searchRouteRegion(input, q, ind, subreg->subregions, toLoad); @@ -1507,9 +1543,10 @@ void searchRouteSubRegion(int fileInd, std::vector& list, Rou cis.PopLimit(old); } -void searchRouteDataForSubRegion(SearchQuery* q, std::vector& list, RoutingIndex* rs, RouteSubregion* sub){ +void searchRouteDataForSubRegion(SearchQuery* q, std::vector& list, RouteSubregion* sub){ map::iterator i = openFiles.begin(); - UNORDERED(set) ids; + RoutingIndex* rs = sub->routingIndex; + IDS_SET ids; bool basemapExists = false; for (; i != openFiles.end() && !q->publisher->isCancelled(); i++) { BinaryMapFile* file = i->second; @@ -1645,7 +1682,7 @@ BinaryMapFile* initBinaryMapFile(std::string inputName) { mi.name = mp.name(); for (int j = 0; j < mp.subregions_size(); j++) { RoutingSubregion ml = mp.subregions(j); - RouteSubregion mr; + RouteSubregion mr(&mi); mr.bottom = ml.bottom(); mr.left = ml.left(); mr.right = ml.right(); diff --git a/Osmand-kernel/osmand/src/binaryRead.h b/Osmand-kernel/osmand/src/binaryRead.h index 68aebef608..fe5f64b1a0 100644 --- a/Osmand-kernel/osmand/src/binaryRead.h +++ b/Osmand-kernel/osmand/src/binaryRead.h @@ -38,7 +38,7 @@ struct MapTreeBounds { ocean = -1; } }; - +struct RoutingIndex; struct RouteSubregion { uint32_t length; uint32_t filePointer; @@ -48,8 +48,9 @@ struct RouteSubregion { uint32_t top; uint32_t bottom; std::vector subregions; + RoutingIndex* routingIndex; - RouteSubregion() : length(0), filePointer(0), mapDataBlock(0){ + RouteSubregion(RoutingIndex* ind) : length(0), filePointer(0), mapDataBlock(0), routingIndex(ind){ } }; @@ -252,7 +253,9 @@ struct SearchQuery { } }; -void searchRouteDataForSubRegion(SearchQuery* q, std::vector& list, RoutingIndex* rs, RouteSubregion* sub); +void searchRouteSubregions(SearchQuery* q, std::vector& tempResult); + +void searchRouteDataForSubRegion(SearchQuery* q, std::vector& list, RouteSubregion* sub); ResultPublisher* searchObjectsForRendering(SearchQuery* q, bool skipDuplicates, int renderRouteDataFile, std::string msgNothingFound); diff --git a/Osmand-kernel/osmand/src/binaryRoutePlanner.cpp b/Osmand-kernel/osmand/src/binaryRoutePlanner.cpp index 54fb8f705d..7f60bfcc6b 100644 --- a/Osmand-kernel/osmand/src/binaryRoutePlanner.cpp +++ b/Osmand-kernel/osmand/src/binaryRoutePlanner.cpp @@ -1,6 +1,8 @@ #include "common.h" #include +#include #include "binaryRead.h" +#include "binaryRoutePlanner.h" #include static bool PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST = true; @@ -27,131 +29,6 @@ inline int roadPriorityComparator(float o1DistanceFromStart, float o1DistanceToE } return f1 < f2 ? -1 : 1; } -struct RouteSegment { -public : - int segmentStart; - SHARED_PTR road; - // needed to store intersection of routes - SHARED_PTR next; - - // search context (needed for searching route) - // Initially it should be null (!) because it checks was it segment visited before - SHARED_PTR parentRoute; - int parentSegmentEnd; - - // distance measured in time (seconds) - float distanceFromStart; - float distanceToEnd; - - RouteSegment(SHARED_PTR road, int segmentStart) : road(road), segmentStart(segmentStart), - parentSegmentEnd(0), distanceFromStart(0), distanceToEnd(0){ - } -}; - - -// FIXME -const static int ZOOM_TO_LOAD_TILES = 16; -struct RoutingSubregionTile { - RouteSubregion subregion; - // make it without get/set for fast access - int access; - int loaded; - UNORDERED(map) > routes; - - RoutingSubregionTile():access(0), loaded(0) { - - } - bool isLoaded(){ - return loaded > 0; - } -}; -static long calcRouteId(SHARED_PTR o, int ind) { - return (o->id << 10) + ind; -} - -struct RoutingContext { - int visitedSegments; - ElapsedTimer timeToLoad; - ElapsedTimer timeToCalculate; - int firstRoadDirection; - int64_t firstRoadId; - - vector > segmentsToVisitNotForbidden; - vector > segmentsToVisitPrescripted; - - int finalReverseEndSegment; - SHARED_PTR finalReverseRoute; - int finalDirectEndSegment; - SHARED_PTR finalDirectRoute; - UNORDERED(map) > > indexedSubregions; - - // void searchRouteRegion(SearchQuery* q, std::vector& list, RoutingIndex* rs, RouteSubregion* sub) - SHARED_PTR loadRouteSegment(int x31, int y31) { - timeToLoad.start(); - int64_t xloc = x31 >> (31 - ZOOM_TO_LOAD_TILES); - int64_t yloc = y31 >> (31 - ZOOM_TO_LOAD_TILES); - int64_t tileId = (xloc << ZOOM_TO_LOAD_TILES) + yloc; -// if (indexedSubregions[tileId] == indexedSubregions.end()) { -// SearchQuery q((int) (xloc << zoomToLoad), -// (int) ((xloc + 1) << zoomToLoad), (int) (yloc << zoomToLoad), (int) ((yloc + 1) << zoomToLoad)); -// vector > collection = loadTileHeaders(x31, y31); -// indexedSubregions.put(tileId, collection); -// } -// vector > subregions = indexedSubregions.get(tileId); -// if (subregions != null) { -// for (RoutingSubregionTile ts : subregions) { -// if (!ts.isLoaded()) { -// loadSubregionTile(ts, loadOptions == OPTION_IN_MEMORY_LOAD); -// } -// } -// } - timeToLoad.pause(); - return SHARED_PTR(); - } - - bool isInterrupted(){ - return false; - } - float getHeuristicCoefficient(){ - return 1; - } - - bool planRouteIn2Directions() { - return true; - } - int getPlanRoadDirection() { - return 0; - } - - float defineSpeedPriority(SHARED_PTR r) { - return 1; - } - - float defineSpeed(SHARED_PTR r) { - return 1; - } - - float getMinDefaultSpeed(){ - return 40; - } - float getMaxDefaultSpeed(){ - return 130; - } - - bool isOneWay(SHARED_PTR r) { - return true; - } - float calculateTurnTime(SHARED_PTR segment, int index, SHARED_PTR next, int nextIndex){ - return 0; - } - float defineRoutingObstacle(SHARED_PTR road, int segmentEnd) { - return 0; - } - - bool restrictionsAware(){ - return true; - } -}; static double convert31YToMeters(int y1, int y2) { @@ -172,10 +49,6 @@ static double squareRootDist(int x1, int y1, int x2, int y2) { // return measuredDist(x1, y1, x2, y2); } -static double measuredDist(int x1, int y1, int x2, int y2) { - return getDistance(get31LatitudeY(y1), get31LongitudeX(x1), get31LatitudeY(y2), - get31LongitudeX(x2)); -} static double squareDist(int x1, int y1, int x2, int y2) { // translate into meters @@ -203,18 +76,19 @@ struct SegmentsComparator : public std::binary_function } bool operator()(const SHARED_PTR lhs, const SHARED_PTR rhs) const { - return roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart, rhs.get()->distanceToEnd, ctx->getHeuristicCoefficient()) < 0; + return roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart, + rhs.get()->distanceToEnd, ctx->getHeuristicCoefficient()) > 0; } }; struct NonHeuristicSegmentsComparator : public std::binary_function, SHARED_PTR, bool> { bool operator()(const SHARED_PTR lhs, const SHARED_PTR rhs) const { - return roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart, rhs.get()->distanceToEnd, 0.5) < 0; + return roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart, rhs.get()->distanceToEnd, 0.5) > 0; } }; -typedef UNORDERED(map) > VISITED_MAP; +typedef UNORDERED(map) > VISITED_MAP; typedef priority_queue, vector >, SegmentsComparator > SEGMENTS_QUEUE; bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, SEGMENTS_QUEUE& graphSegments, VISITED_MAP& visitedSegments, int targetEndX, int targetEndY, @@ -225,7 +99,6 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments, SHARED_PTR segment, int segmentEnd, SHARED_PTR inputNext, bool reverseWay); - /** * Calculate route between start.segmentEnd and end.segmentStart (using A* algorithm) * return list of segments @@ -283,7 +156,6 @@ void searchRouteInternal(RoutingContext* ctx, SHARED_PTR start, SH while (graphSegments->size() > 0) { SHARED_PTR segment = graphSegments->top(); graphSegments->pop(); - ctx->visitedSegments++; bool routeFound = false; if (!inverse) { routeFound = processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, targetEndX, targetEndY, @@ -324,6 +196,9 @@ void searchRouteInternal(RoutingContext* ctx, SHARED_PTR start, SH } } ctx->timeToCalculate.pause(); + osmand_log_print(LOG_WARN, "[Native] Result visited (visited roads %d, visited segments %d / %d , queue sizes %d / %d ) ", + ctx-> visitedSegments, visitedDirectSegments.size(), visitedOppositeSegments.size(), + graphDirectSegments.size(),graphReverseSegments.size()); } bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, SEGMENTS_QUEUE& graphSegments, VISITED_MAP& visitedSegments, int targetEndX, int targetEndY, @@ -337,9 +212,13 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, double obstacleMinusTime = 0; // 0. mark route segment as visited - long nt = (road->id << ROUTE_POINTS) + middle; + int64_t nt = (road->id << ROUTE_POINTS) + middle; + if(visitedSegments.find(nt) != visitedSegments.end()) { + return false; + } + ctx->visitedSegments++; // avoid empty segments to connect but mark the point as visited - visitedSegments[nt] =SHARED_PTR(); + visitedSegments[nt] = SHARED_PTR(); int oneway = ctx->isOneWay(road); bool minusAllowed; @@ -396,7 +275,7 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, continue; } // if we found end point break cycle - long nts = (road->id << ROUTE_POINTS) + segmentEnd; + int64_t nts = (road->id << ROUTE_POINTS) + segmentEnd; visitedSegments[nts]=segment; // 2. calculate point and try to load neighbor ways if they are not loaded @@ -434,13 +313,14 @@ bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch, // throw new OutOfMemoryError("There is no enough memory " + ctx.config.memoryLimitation/(1<<20) + " Mb"); // } SHARED_PTR next = ctx->loadRouteSegment(x, y); + // 3. get intersected ways if (next.get() != NULL) { - // TO-DO U-Turn if((next.get() == segment.get() || next->road->id == road->id) && next->next.get() == NULL) { // simplification if there is no real intersection continue; } + // Using A* routing algorithm // g(x) - calculate distance to that point and calculate time @@ -488,7 +368,7 @@ bool proccessRestrictions(RoutingContext* ctx, SHARED_PTR road, } else { for (int i = 0; i < next->road->restrictions.size(); i++) { int rt = next->road->restrictions[i] & 7; - long restrictedTo = next->road->restrictions[i] >> 3; + int64_t restrictedTo = next->road->restrictions[i] >> 3; if (restrictedTo == road->id) { type = rt; break; @@ -557,26 +437,23 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments, if (thereAreRestrictions) { next = *nextIterator; } - long nts = (next->road->id << ROUTE_POINTS) + next->segmentStart; - + int64_t nts = (next->road->id << ROUTE_POINTS) + next->segmentStart; // 1. Check if opposite segment found so we can stop calculations - if (oppositeSegments[nts].get() != NULL) { + if (oppositeSegments.find(nts) != oppositeSegments.end()) { // restrictions checked SHARED_PTR opposite = oppositeSegments[nts]; // additional check if opposite way not the same as current one - if (next->segmentStart != segmentEnd || - opposite->road->id != segment->road->id) { - if (reverseWay) { - ctx->finalReverseEndSegment = segmentEnd; - ctx->finalReverseRoute = segment; - ctx->finalDirectEndSegment = next->segmentStart; - ctx->finalDirectRoute = opposite; - } else { - ctx->finalDirectEndSegment = segmentEnd; - ctx->finalDirectRoute = segment; - ctx->finalReverseEndSegment = next->segmentStart; - ctx->finalReverseRoute = opposite; - } + if (opposite.get() != NULL && (next->segmentStart != segmentEnd || + opposite->road->id != segment->road->id)) { + SHARED_PTR frs = SHARED_PTR(new FinalRouteSegment); + frs->direct = segment; + frs->reverseWaySearch = reverseWay; + SHARED_PTR op = SHARED_PTR(new RouteSegment(segment->road, segmentEnd)); + op->parentRoute = opposite; + op->parentSegmentEnd = next->getSegmentStart(); + frs->opposite = op; + frs->distanceFromStart = opposite->distanceFromStart + segment->distanceFromStart; + ctx->finalRouteSegment = frs; return true; } } @@ -588,14 +465,8 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments, || roadPriorityComparator(next->distanceFromStart, next->distanceToEnd, distFromStart, distanceToEnd, ctx->getHeuristicCoefficient()) > 0) { if (next->parentRoute.get() != NULL) { - // already in queue remove it - // FIXME remove -// if (!graphSegments.remove(next)) - { - // exist in different queue! - RouteSegment* cpy = new RouteSegment(next->road, next->segmentStart); - next = SHARED_PTR(cpy); - } + // already in queue remove it (we can not remove it) + next = SHARED_PTR(new RouteSegment(next->road, next->segmentStart)); } next->distanceFromStart = distFromStart; next->distanceToEnd = distanceToEnd; @@ -625,3 +496,99 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments, } return false; } + +// FIXME +SHARED_PTR findRouteSegment(int px, int py, RoutingContext* ctx) { + return ctx->loadSegmentAround(px, py); +} + + 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; + } + +void addRouteSegmentToResult(vector& result, RouteSegmentResult& res, bool reverse) { + if (res.endPointIndex != res.startPointIndex) { + if (result.size() > 0) { + RouteSegmentResult last = result[result.size() - 1]; + if (last.object->id == res.object->id) { + if (combineTwoSegmentResult(res, last, reverse)) { + return; + } + } + } + result.push_back(res); + } +} + +vector convertFinalSegmentToResults(RoutingContext* ctx) { + vector result; + if (ctx->finalRouteSegment.get() != NULL) { + osmand_log_print(LOG_INFO, "Routing calculated time distance %f", ctx->finalRouteSegment->distanceFromStart); + SHARED_PTR finalSegment = ctx->finalRouteSegment; + // Get results from opposite direction roads + SHARED_PTR segment = finalSegment->reverseWaySearch ? finalSegment->direct : finalSegment->opposite->parentRoute; + int parentSegmentStart = + finalSegment->reverseWaySearch ? + finalSegment->opposite->getSegmentStart() : finalSegment->opposite->parentSegmentEnd; + while (segment.get() != NULL) { + RouteSegmentResult res(segment->road, parentSegmentStart, segment->getSegmentStart()); + parentSegmentStart = segment->parentSegmentEnd; + segment = segment->parentRoute; + addRouteSegmentToResult(result, res, false); + } + // reverse it just to attach good direction roads + std::reverse(result.begin(), result.end()); + + segment = finalSegment->reverseWaySearch ? finalSegment->opposite->parentRoute : finalSegment->direct; + int parentSegmentEnd = + finalSegment->reverseWaySearch ? + finalSegment->opposite->parentSegmentEnd : finalSegment->opposite->getSegmentStart(); + + while (segment.get() != NULL) { + RouteSegmentResult res(segment->road, segment->getSegmentStart(), parentSegmentEnd); + parentSegmentEnd = segment->parentSegmentEnd; + segment = segment->parentRoute; + // happens in smart recalculation + addRouteSegmentToResult(result, res, true); + } + std::reverse(result.begin(), result.end()); + + } + return result; +} + + +vector searchRouteInternal(RoutingContext* ctx, bool leftSideNavigation) { + SHARED_PTR start = findRouteSegment(ctx->startX, ctx->startY, ctx); + if(start.get() == NULL) { + osmand_log_print(LOG_WARN, "Start point was not found [Native]"); + return vector(); + } else { + osmand_log_print(LOG_WARN, "Start point was found %lld [Native]", start->road->id); + } + SHARED_PTR end = findRouteSegment(ctx->endX, ctx->endY, ctx); + if(end.get() == NULL) { + osmand_log_print(LOG_WARN, "End point was not found [Native]"); + return vector(); + } else { + osmand_log_print(LOG_WARN, "End point was found %lld [Native]", end->road->id); + } + searchRouteInternal(ctx, start, end, leftSideNavigation); + 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); + return convertFinalSegmentToResults(ctx); +} + + diff --git a/Osmand-kernel/osmand/src/binaryRoutePlanner.h b/Osmand-kernel/osmand/src/binaryRoutePlanner.h index 108f34e567..bc222d3772 100644 --- a/Osmand-kernel/osmand/src/binaryRoutePlanner.h +++ b/Osmand-kernel/osmand/src/binaryRoutePlanner.h @@ -3,4 +3,418 @@ #include "common.h" #include "binaryRead.h" +static double measuredDist(int x1, int y1, int x2, int y2) { + return getDistance(get31LatitudeY(y1), get31LongitudeX(x1), get31LatitudeY(y2), + get31LongitudeX(x2)); +} + +struct RouteSegment { +public : + int segmentStart; + SHARED_PTR road; + // needed to store intersection of routes + SHARED_PTR next; + + // search context (needed for searching route) + // Initially it should be null (!) because it checks was it segment visited before + SHARED_PTR parentRoute; + int parentSegmentEnd; + + // distance measured in time (seconds) + float distanceFromStart; + float distanceToEnd; + + inline int getSegmentStart() { + return segmentStart; + } + + RouteSegment(SHARED_PTR road, int segmentStart) : road(road), segmentStart(segmentStart), + parentSegmentEnd(0), distanceFromStart(0), distanceToEnd(0),next(), parentRoute(){ + } + ~RouteSegment(){ + } +}; + +struct RouteSegmentResult { + SHARED_PTR object; + int startPointIndex; + int endPointIndex; + RouteSegmentResult(SHARED_PTR object, int startPointIndex, int endPointIndex) : + object(object), startPointIndex(startPointIndex), endPointIndex (endPointIndex) { + + } +}; + +struct FinalRouteSegment { + SHARED_PTR direct; + bool reverseWaySearch; + SHARED_PTR opposite; + float distanceFromStart; +}; + + + +const static int ZOOM_TO_LOAD_TILES = 16; +struct RoutingSubregionTile { + RouteSubregion subregion; + // make it without get/set for fast access + int access; + int loaded; + UNORDERED(map) > routes; + + RoutingSubregionTile(RouteSubregion& sub) : access(0), loaded(0), subregion(sub) { + + } + ~RoutingSubregionTile(){ + } + bool isLoaded(){ + return loaded > 0; + } + + void setLoaded(){ + loaded++; + } + + void add(SHARED_PTR o) { + for (int i = 0; i < o->pointsX.size(); i++) { + uint64_t x31 = o->pointsX[i]; + uint64_t y31 = o->pointsY[i]; + uint64_t l = (((uint64_t) x31) << 31) + (uint64_t) y31; + SHARED_PTR segment = SHARED_PTR(new RouteSegment(o, i)); + if (routes[l].get() == NULL) { + routes[l] = segment; + } else { + SHARED_PTR orig = routes[l]; + int cnt = 0; + while (orig->next.get() != NULL) { + orig = orig->next; + cnt++; + } + orig->next = segment; + } + } + } +}; +static int64_t calcRouteId(SHARED_PTR o, int ind) { + return (o->id << 10) + ind; +} + + + +// FIXME configuration methods +struct RoutingContext { + int visitedSegments; + int loadedTiles; + ElapsedTimer timeToLoad; + ElapsedTimer timeToCalculate; + int firstRoadDirection; + int64_t firstRoadId; + + int startX; + int startY; + int endX; + int endY; + + vector > segmentsToVisitNotForbidden; + vector > segmentsToVisitPrescripted; + + SHARED_PTR finalRouteSegment; + UNORDERED(map) > subregionTiles; + UNORDERED(map) > > indexedSubregions; + + RoutingContext() : finalRouteSegment(), firstRoadDirection(0), loadedTiles(0), visitedSegments(0){ + } + bool acceptLine(SHARED_PTR r) { + string v = getHighway(r); + if(v != "" && v != "cycleway" && v != "footway" && v != "steps"){ + return true; + } + return false; + } + + string getHighway(SHARED_PTR r) { + std::vector::iterator t = r->types.begin(); + for(; t != r->types.end(); t++) { + tag_value type = r->region->decodingRules[*t]; + if(type.first=="highway") { + return type.second; + } + } + return ""; + } + + void loadHeaderObjects(int64_t tileId) { + vector > subregions = indexedSubregions[tileId]; + for(int j = 0; jisLoaded()) { + loadedTiles++; + subregions[j]->setLoaded(); + SearchQuery q; + vector res; + searchRouteDataForSubRegion(&q, res, &subregions[j]->subregion); + vector::iterator i = res.begin(); + for(;i!=res.end(); i++) { + if(*i != NULL) { + SHARED_PTR o(*i); + if(acceptLine(o)) { + subregions[j]->add(o); + } + } + } + } + } + } + + void loadHeaders(uint32_t xloc, uint32_t yloc) { + timeToLoad.start(); + int z = ZOOM_TO_LOAD_TILES; + int tz = 31 - z; + int64_t tileId = (xloc << z) + yloc; + if (indexedSubregions.find(tileId) == indexedSubregions.end()) { + SearchQuery q((uint32_t) (xloc << tz), + (uint32_t) ((xloc + 1) << tz), (uint32_t) (yloc << tz), (uint32_t) ((yloc + 1) << tz)); + std::vector tempResult; + searchRouteSubregions(&q, tempResult); + std::vector > collection; + for(int i=0; i(new RoutingSubregionTile(rs)); + } + collection.push_back(subregionTiles[key]); + } + //osmand_log_print(LOG_INFO, "Native load %d %d (%d)", xloc, yloc, tempResult.size()); + indexedSubregions[tileId] = collection; + } + loadHeaderObjects(tileId); + timeToLoad.pause(); + } + + + // FIXME + SHARED_PTR loadSegmentAround(int x31, int y31) { + timeToLoad.start(); + SHARED_PTR r; + float dist = -1; + int z = ZOOM_TO_LOAD_TILES; + 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 > subregions = indexedSubregions[tileId]; + for(int j = 0; jisLoaded()) { + UNORDERED(map) >::iterator s = subregions[j]->routes.begin(); + while(s != subregions[j]->routes.end()) { + SHARED_PTR 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& list, RoutingIndex* rs, RouteSubregion* sub) + SHARED_PTR loadRouteSegment(int x31, int y31) { + int z = ZOOM_TO_LOAD_TILES; + int64_t xloc = x31 >> (31 - z); + int64_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 > subregions = indexedSubregions[tileId]; + UNORDERED(map) > excludeDuplications; + SHARED_PTR original; + for(int j = 0; jisLoaded()) { + SHARED_PTR segment = subregions[j]->routes[l]; + subregions[j]->access++; + while (segment.get() != NULL) { + SHARED_PTR ro = segment->road; + SHARED_PTR toCmp = excludeDuplications[calcRouteId(ro, segment->getSegmentStart())]; + if (toCmp.get() == NULL || toCmp->pointsX.size() < ro->pointsX.size()) { + excludeDuplications[calcRouteId(ro, segment->getSegmentStart())] = ro; + SHARED_PTR s = SHARED_PTR(new RouteSegment(ro, segment->getSegmentStart())); + s->next = original; + original = s; + } + segment = segment->next; + } + } + } + + return original; + } + + + bool isInterrupted(){ + return false; + } + float getHeuristicCoefficient(){ + return 1; + } + + bool planRouteIn2Directions() { + return getPlanRoadDirection() == 0; + } + int getPlanRoadDirection() { + return 1; + } + + float defineSpeedPriority(SHARED_PTR r) { + string v = getHighway(r); + if(v == "") { + return 1; + } else if(v == "motorway") { + return 1.2; + } else if(v == "motorway_link") { + return 1.2; + } else if(v == "trunk") { + return 1.2; + } else if(v == "trunk_link") { + return 1.2; + } else if(v == "primary") { + return 1.1; + } else if(v == "primary_link") { + return 1.1; + } else if(v == "secondary") { + return 1.05; + } else if(v == "secondary_link") { + return 1.05; + } else if(v == "tertiary") { + return 1; + } else if(v == "tertiary_link") { + return 1; + } else if(v == "unclassified") { + return 0.7; + } else if(v == "road") { + return 0.7; + } else if(v == "service") { + return 0.5; + } else if(v == "track") { + return 0.3; + } else if(v == "residential") { + return 0.5; + } else if(v == "living_street") { + return 0.5; + } + return 1; + } + + float maxSpeed(SHARED_PTR r) { + std::vector::iterator t = r->types.begin(); + for(; t != r->types.end(); t++) { + tag_value type = r->region->decodingRules[*t]; + if(type.first=="maxspeed") { + std::string v = type.second; + int i = 0; + while(i < v.length() && v[i] >= '0' && v[i] <= '9') { + i++; + } + if(i > 0) { + float f = atoi(v.substr(0, i).c_str()); + f /= 3.6; // km/h -> m/s + if(v.find("mph") != std::string::npos ) { + f *= 1.6; + } + return f; + } + return 0; + } + } + return 0; + } + + float defineSpeed(SHARED_PTR r) { + float speed = maxSpeed(r); + if(speed > 0) { + return speed; + } + string v = getHighway(r); + if(v == "") { + } else if(v == "motorway") { + speed = 110; + } else if(v == "motorway_link") { + speed = 80; + } else if(v == "trunk") { + speed = 100; + } else if(v == "trunk_link") { + speed = 75; + } else if(v == "primary") { + speed = 65; + } else if(v == "primary_link") { + speed = 50; + } else if(v == "secondary") { + speed = 60; + } else if(v == "secondary_link") { + speed = 50; + } else if(v == "tertiary") { + speed = 45; + } else if(v == "tertiary_link") { + speed = 40; + } else if(v == "unclassified") { + speed = 35; + } else if(v == "road") { + speed = 35; + } else if(v == "service") { + speed = 30; + } else if(v == "track") { + speed = 15; + } else if(v == "residential") { + speed = 35; + } else if(v == "living_street") { + speed = 25; + } + return speed / 3.; + } + + + float getMinDefaultSpeed(){ + return 40 / 3.6; + } + float getMaxDefaultSpeed(){ + return 130 / 3.6; + } + + int isOneWay(SHARED_PTR r) { + std::vector::iterator t = r->types.begin(); + for(; t != r->types.end(); t++){ + tag_value type = r->region->decodingRules[*t]; + if(type.first == "oneway") { + string v = type.second; + if("-1" ==v || "reverse" == v) { + return -1; + } else if("1" == v || "yes" == v) { + return 1; + } + } + } + return 0; + } + + float calculateTurnTime(SHARED_PTR segment, int index, SHARED_PTR next, int nextIndex){ + return 0; + } + float defineRoutingObstacle(SHARED_PTR road, int segmentEnd) { + return 0; + } + + bool restrictionsAware(){ + return true; + } +}; + + +vector searchRouteInternal(RoutingContext* ctx, bool leftSideNavigation); #endif /*_OSMAND_BINARY_ROUTE_PLANNER_H*/ diff --git a/Osmand-kernel/osmand/src/common.cpp b/Osmand-kernel/osmand/src/common.cpp index 82cee252e7..94b265e41b 100644 --- a/Osmand-kernel/osmand/src/common.cpp +++ b/Osmand-kernel/osmand/src/common.cpp @@ -79,7 +79,7 @@ void ElapsedTimer::start() #elif defined(__APPLE__) startInit = mach_absolute_time(); #else - clock_gettime(CLOCK_MONOTONIC, &startInit); + clock_gettime(CLOCK_REALTIME, &startInit); #endif } run = true; @@ -91,7 +91,7 @@ void ElapsedTimer::pause() return; #if defined(_WIN32) endInit = timeGetTime(); - elapsedTime += (endInit - startInit) * 1e6; + elapsedTime += (endInit - startInit) * 1000; #elif defined(__APPLE__) endInit = mach_absolute_time(); uint64_t duration = endInit - startInit; @@ -99,11 +99,11 @@ void ElapsedTimer::pause() duration /= machTimeInfo.denom; elapsedTime += duration; #else - clock_gettime(CLOCK_MONOTONIC, &endInit); + clock_gettime(CLOCK_REALTIME, &endInit); int sec = endInit.tv_sec - startInit.tv_sec; if (sec > 0) - elapsedTime += 1e9 * sec; - elapsedTime += endInit.tv_nsec - startInit.tv_nsec; + elapsedTime += 1000000 * sec; + elapsedTime += (endInit.tv_nsec - startInit.tv_nsec) / 1000; #endif run = false; } @@ -111,7 +111,7 @@ void ElapsedTimer::pause() int ElapsedTimer::getElapsedTime() { pause(); - return elapsedTime / 1e6; + return elapsedTime / 1000; } SkBitmap* RenderingContext::getCachedBitmap(const std::string& bitmapResource) { diff --git a/Osmand-kernel/osmand/src/java_wrap.cpp b/Osmand-kernel/osmand/src/java_wrap.cpp index 11e64ae03a..778a4dd86a 100644 --- a/Osmand-kernel/osmand/src/java_wrap.cpp +++ b/Osmand-kernel/osmand/src/java_wrap.cpp @@ -11,6 +11,7 @@ #include "java_wrap.h" #include "binaryRead.h" #include "rendering.h" +#include "binaryRoutePlanner.h" JavaVM* globalJVM = NULL; @@ -410,8 +411,17 @@ jfieldID jfield_RouteSubregion_bottom = NULL; jfieldID jfield_RouteSubregion_shiftToData = NULL; +jclass jclass_RouteSegmentResult = NULL; +jmethodID jmethod_RouteSegmentResult_ctor = NULL; + + + void loadJniRenderingContext(JNIEnv* env) { + jclass_RouteSegmentResult = findClass(env, "net/osmand/router/RouteSegmentResult"); + jmethod_RouteSegmentResult_ctor = env->GetMethodID(jclass_RouteSegmentResult, + "", "(Lnet/osmand/binary/RouteDataObject;II)V"); + 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" ); @@ -570,7 +580,31 @@ extern "C" JNIEXPORT void JNICALL Java_net_osmand_NativeLibrary_deleteRouteSearc } delete t; } +extern "C" JNIEXPORT jobjectArray JNICALL Java_net_osmand_NativeLibrary_testRouting(JNIEnv* ienv, + jobject obj, jint sx31, + jint sy31, jint ex31, jint ey31) { + RoutingContext c; + c.startX = sx31; + c.startY = sy31; + c.endX = ex31; + c.endY = ey31; + vector r = searchRouteInternal(&c, false); + jobjectArray res = ienv->NewObjectArray(r.size(), jclass_RouteSegmentResult, NULL); + for (int i = 0; i < r.size(); i++) { + jobject robj = convertRouteDataObjectToJava(ienv, r[i].object.get(), NULL); + jobject resobj = ienv->NewObject(jclass_RouteSegmentResult, jmethod_RouteSegmentResult_ctor, robj, + r[i].startPointIndex, r[i].endPointIndex); + ienv->SetObjectArrayElement(res, i, resobj); + ienv->DeleteLocalRef(robj); + ienv->DeleteLocalRef(resobj); + } + if (r.size() == 0) { + osmand_log_print(LOG_INFO, "No route found"); + } + fflush(stdout); + return res; +} // protected static native RouteDataObject[] getRouteDataObjects(NativeRouteSearchResult rs, int x31, int y31!); extern "C" JNIEXPORT jobjectArray JNICALL Java_net_osmand_NativeLibrary_getRouteDataObjects(JNIEnv* ienv, @@ -596,7 +630,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_NativeLibrary_loadRoutingDa RoutingIndex ind; ind.filePointer = regFilePointer; ind.name = getString(ienv, regName); - RouteSubregion sub; + RouteSubregion sub(&ind); sub.filePointer = ienv->GetIntField(subreg, jfield_RouteSubregion_filePointer); sub.length = ienv->GetIntField(subreg, jfield_RouteSubregion_length); sub.left = ienv->GetIntField(subreg, jfield_RouteSubregion_left); @@ -606,7 +640,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_net_osmand_NativeLibrary_loadRoutingDa sub.mapDataBlock= ienv->GetIntField(subreg, jfield_RouteSubregion_shiftToData); std::vector result; SearchQuery q; - searchRouteDataForSubRegion(&q, result, &ind, &sub); + searchRouteDataForSubRegion(&q, result, &sub); if (loadObjects) {