Test native routing implementation
This commit is contained in:
parent
95c90a0784
commit
efaf4e25c4
9 changed files with 726 additions and 251 deletions
|
@ -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);
|
||||
|
|
|
@ -517,13 +517,20 @@ public class RoutingContext {
|
|||
}
|
||||
|
||||
public void loadTileData(int x31, int y31, int zoomAround, final List<RouteDataObject> 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);
|
||||
|
|
|
@ -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<RouteSegment> inters = new ArrayList<BinaryRoutePlanner.RouteSegment>();
|
||||
|
@ -714,8 +716,14 @@ public class MapRouterLayer implements MapPanelLayer {
|
|||
|
||||
});
|
||||
|
||||
List<RouteSegmentResult> 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<RouteSegmentResult> 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);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
#include "binaryRead.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
@ -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)<long long> IDS_SET;
|
||||
|
||||
void searchRouteSubRegion(int fileInd, std::vector<RouteDataObject*>& list, RoutingIndex* routingIndex, RouteSubregion* sub);
|
||||
void searchRouteRegion(CodedInputStream* input, SearchQuery* q, RoutingIndex* ind, std::vector<RouteSubregion>& 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<RouteDataObject*>& list, std::vector<MapDataObject*>& tempResult,
|
||||
bool skipDuplicates, UNORDERED(set)<long long>& ids) {
|
||||
bool skipDuplicates, IDS_SET& ids) {
|
||||
std::vector<RouteDataObject*>::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<MapDataObject*>& tempResult,
|
||||
bool skipDuplicates, UNORDERED(set)<long long>& ids) {
|
||||
|
||||
for (std::vector<RoutingIndex*>::iterator routeIndex = file->routingIndexes.begin();
|
||||
routeIndex != file->routingIndexes.end(); routeIndex++) {
|
||||
if (q->publisher->isCancelled()) {
|
||||
break;
|
||||
}
|
||||
bool contains = false;
|
||||
std::vector<RouteSubregion> subs =
|
||||
q->zoom <= zoomForBaseRouteRendering ? (*routeIndex)->basesubregions : (*routeIndex)->subregions;
|
||||
for (std::vector<RouteSubregion>::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<RouteSubregion> 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<RouteSubregion>::iterator sub = found.begin(); sub != found.end();sub++) {
|
||||
std::vector<RouteDataObject*> 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<RouteSubregion>& tempResult) {
|
||||
map<std::string, BinaryMapFile*>::iterator i = openFiles.begin();
|
||||
for (; i != openFiles.end() && !q->publisher->isCancelled(); i++) {
|
||||
BinaryMapFile* file = i->second;
|
||||
std::vector<RoutingIndex*>::iterator routeIndex = file->routingIndexes.begin();
|
||||
for (; routeIndex != file->routingIndexes.end(); routeIndex++) {
|
||||
bool contains = false;
|
||||
std::vector<RouteSubregion>& subs = (*routeIndex)->subregions;
|
||||
for (std::vector<RouteSubregion>::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<RouteSubregion>& found,
|
||||
RoutingIndex* routeIndex, std::vector<MapDataObject*>& 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<RouteSubregion>::iterator sub = found.begin(); sub != found.end(); sub++) {
|
||||
std::vector<RouteDataObject*> 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<MapDataObject*>& tempResult,
|
||||
bool skipDuplicates, IDS_SET& ids) {
|
||||
std::vector<RoutingIndex*>::iterator routeIndex = file->routingIndexes.begin();
|
||||
for (; routeIndex != file->routingIndexes.end(); routeIndex++) {
|
||||
if (q->publisher->isCancelled()) {
|
||||
break;
|
||||
}
|
||||
bool contains = false;
|
||||
std::vector<RouteSubregion> subs = (*routeIndex)->subregions;
|
||||
if (q->zoom <= zoomForBaseRouteRendering) {
|
||||
subs = (*routeIndex)->basesubregions;
|
||||
}
|
||||
for (std::vector<RouteSubregion>::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<RouteSubregion> 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<MapIndex>::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<std::string, BinaryMapFile*>::iterator i = openFiles.begin();
|
||||
UNORDERED(set)<long long> 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<RouteDataObject*>& list, Rou
|
|||
cis.PopLimit(old);
|
||||
}
|
||||
|
||||
void searchRouteDataForSubRegion(SearchQuery* q, std::vector<RouteDataObject*>& list, RoutingIndex* rs, RouteSubregion* sub){
|
||||
void searchRouteDataForSubRegion(SearchQuery* q, std::vector<RouteDataObject*>& list, RouteSubregion* sub){
|
||||
map<std::string, BinaryMapFile*>::iterator i = openFiles.begin();
|
||||
UNORDERED(set)<long long> 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();
|
||||
|
|
|
@ -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<RouteSubregion> 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<RouteDataObject*>& list, RoutingIndex* rs, RouteSubregion* sub);
|
||||
void searchRouteSubregions(SearchQuery* q, std::vector<RouteSubregion>& tempResult);
|
||||
|
||||
void searchRouteDataForSubRegion(SearchQuery* q, std::vector<RouteDataObject*>& list, RouteSubregion* sub);
|
||||
|
||||
ResultPublisher* searchObjectsForRendering(SearchQuery* q, bool skipDuplicates, int renderRouteDataFile, std::string msgNothingFound);
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "common.h"
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
#include "binaryRead.h"
|
||||
#include "binaryRoutePlanner.h"
|
||||
#include <functional>
|
||||
|
||||
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<RouteDataObject> road;
|
||||
// needed to store intersection of routes
|
||||
SHARED_PTR<RouteSegment> next;
|
||||
|
||||
// search context (needed for searching route)
|
||||
// Initially it should be null (!) because it checks was it segment visited before
|
||||
SHARED_PTR<RouteSegment> parentRoute;
|
||||
int parentSegmentEnd;
|
||||
|
||||
// distance measured in time (seconds)
|
||||
float distanceFromStart;
|
||||
float distanceToEnd;
|
||||
|
||||
RouteSegment(SHARED_PTR<RouteDataObject> 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)<long long, SHARED_PTR<RouteSegment> > routes;
|
||||
|
||||
RoutingSubregionTile():access(0), loaded(0) {
|
||||
|
||||
}
|
||||
bool isLoaded(){
|
||||
return loaded > 0;
|
||||
}
|
||||
};
|
||||
static long calcRouteId(SHARED_PTR<RouteDataObject> o, int ind) {
|
||||
return (o->id << 10) + ind;
|
||||
}
|
||||
|
||||
struct RoutingContext {
|
||||
int visitedSegments;
|
||||
ElapsedTimer timeToLoad;
|
||||
ElapsedTimer timeToCalculate;
|
||||
int firstRoadDirection;
|
||||
int64_t firstRoadId;
|
||||
|
||||
vector<SHARED_PTR<RouteSegment> > segmentsToVisitNotForbidden;
|
||||
vector<SHARED_PTR<RouteSegment> > segmentsToVisitPrescripted;
|
||||
|
||||
int finalReverseEndSegment;
|
||||
SHARED_PTR<RouteSegment> finalReverseRoute;
|
||||
int finalDirectEndSegment;
|
||||
SHARED_PTR<RouteSegment> finalDirectRoute;
|
||||
UNORDERED(map)<long long, vector<SHARED_PTR<RoutingSubregionTile> > > indexedSubregions;
|
||||
|
||||
// void searchRouteRegion(SearchQuery* q, std::vector<RouteDataObject*>& list, RoutingIndex* rs, RouteSubregion* sub)
|
||||
SHARED_PTR<RouteSegment> 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<SHARED_PTR<RoutingSubregionTile> > collection = loadTileHeaders(x31, y31);
|
||||
// indexedSubregions.put(tileId, collection);
|
||||
// }
|
||||
// vector<SHARED_PTR<RoutingSubregionTile> > 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<RouteSegment>();
|
||||
}
|
||||
|
||||
bool isInterrupted(){
|
||||
return false;
|
||||
}
|
||||
float getHeuristicCoefficient(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool planRouteIn2Directions() {
|
||||
return true;
|
||||
}
|
||||
int getPlanRoadDirection() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float defineSpeedPriority(SHARED_PTR<RouteDataObject> r) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
float defineSpeed(SHARED_PTR<RouteDataObject> r) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
float getMinDefaultSpeed(){
|
||||
return 40;
|
||||
}
|
||||
float getMaxDefaultSpeed(){
|
||||
return 130;
|
||||
}
|
||||
|
||||
bool isOneWay(SHARED_PTR<RouteDataObject> r) {
|
||||
return true;
|
||||
}
|
||||
float calculateTurnTime(SHARED_PTR<RouteSegment> segment, int index, SHARED_PTR<RouteSegment> next, int nextIndex){
|
||||
return 0;
|
||||
}
|
||||
float defineRoutingObstacle(SHARED_PTR<RouteDataObject> 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<SHARED_PTR<RouteSegment>
|
|||
}
|
||||
bool operator()(const SHARED_PTR<RouteSegment> lhs, const SHARED_PTR<RouteSegment> rhs) const
|
||||
{
|
||||
return roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart, rhs.get()->distanceToEnd, 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<RouteSegment>, SHARED_PTR<RouteSegment>, bool>
|
||||
{
|
||||
bool operator()(const SHARED_PTR<RouteSegment> lhs, const SHARED_PTR<RouteSegment> rhs) const
|
||||
{
|
||||
return roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart, rhs.get()->distanceToEnd, 0.5) < 0;
|
||||
return roadPriorityComparator(lhs.get()->distanceFromStart, lhs.get()->distanceToEnd, rhs.get()->distanceFromStart, rhs.get()->distanceToEnd, 0.5) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef UNORDERED(map)<long long, SHARED_PTR<RouteSegment> > VISITED_MAP;
|
||||
typedef UNORDERED(map)<int64_t, SHARED_PTR<RouteSegment> > VISITED_MAP;
|
||||
typedef priority_queue<SHARED_PTR<RouteSegment>, vector<SHARED_PTR<RouteSegment> >, SegmentsComparator > SEGMENTS_QUEUE;
|
||||
bool processRouteSegment(RoutingContext* ctx, bool reverseWaySearch,
|
||||
SEGMENTS_QUEUE& graphSegments, VISITED_MAP& visitedSegments, int targetEndX, int targetEndY,
|
||||
|
@ -225,7 +99,6 @@ bool processIntersections(RoutingContext* ctx, SEGMENTS_QUEUE& graphSegments,
|
|||
SHARED_PTR<RouteSegment> segment, int segmentEnd, SHARED_PTR<RouteSegment> 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<RouteSegment> start, SH
|
|||
while (graphSegments->size() > 0) {
|
||||
SHARED_PTR<RouteSegment> 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<RouteSegment> 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<RouteSegment>();
|
||||
visitedSegments[nt] = SHARED_PTR<RouteSegment>();
|
||||
|
||||
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<RouteSegment> 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<RouteDataObject> 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<RouteSegment> 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<FinalRouteSegment> frs = SHARED_PTR<FinalRouteSegment>(new FinalRouteSegment);
|
||||
frs->direct = segment;
|
||||
frs->reverseWaySearch = reverseWay;
|
||||
SHARED_PTR<RouteSegment> op = SHARED_PTR<RouteSegment>(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<RouteSegment>(cpy);
|
||||
}
|
||||
// already in queue remove it (we can not remove it)
|
||||
next = SHARED_PTR<RouteSegment>(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<RouteSegment> 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<RouteSegmentResult>& 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<RouteSegmentResult> convertFinalSegmentToResults(RoutingContext* ctx) {
|
||||
vector<RouteSegmentResult> result;
|
||||
if (ctx->finalRouteSegment.get() != NULL) {
|
||||
osmand_log_print(LOG_INFO, "Routing calculated time distance %f", ctx->finalRouteSegment->distanceFromStart);
|
||||
SHARED_PTR<FinalRouteSegment> finalSegment = ctx->finalRouteSegment;
|
||||
// Get results from opposite direction roads
|
||||
SHARED_PTR<RouteSegment> 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<RouteSegmentResult> searchRouteInternal(RoutingContext* ctx, bool leftSideNavigation) {
|
||||
SHARED_PTR<RouteSegment> start = findRouteSegment(ctx->startX, ctx->startY, ctx);
|
||||
if(start.get() == NULL) {
|
||||
osmand_log_print(LOG_WARN, "Start point was not found [Native]");
|
||||
return vector<RouteSegmentResult>();
|
||||
} else {
|
||||
osmand_log_print(LOG_WARN, "Start point was found %lld [Native]", start->road->id);
|
||||
}
|
||||
SHARED_PTR<RouteSegment> end = findRouteSegment(ctx->endX, ctx->endY, ctx);
|
||||
if(end.get() == NULL) {
|
||||
osmand_log_print(LOG_WARN, "End point was not found [Native]");
|
||||
return vector<RouteSegmentResult>();
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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<RouteDataObject> road;
|
||||
// needed to store intersection of routes
|
||||
SHARED_PTR<RouteSegment> next;
|
||||
|
||||
// search context (needed for searching route)
|
||||
// Initially it should be null (!) because it checks was it segment visited before
|
||||
SHARED_PTR<RouteSegment> parentRoute;
|
||||
int parentSegmentEnd;
|
||||
|
||||
// distance measured in time (seconds)
|
||||
float distanceFromStart;
|
||||
float distanceToEnd;
|
||||
|
||||
inline int getSegmentStart() {
|
||||
return segmentStart;
|
||||
}
|
||||
|
||||
RouteSegment(SHARED_PTR<RouteDataObject> road, int segmentStart) : road(road), segmentStart(segmentStart),
|
||||
parentSegmentEnd(0), distanceFromStart(0), distanceToEnd(0),next(), parentRoute(){
|
||||
}
|
||||
~RouteSegment(){
|
||||
}
|
||||
};
|
||||
|
||||
struct RouteSegmentResult {
|
||||
SHARED_PTR<RouteDataObject> object;
|
||||
int startPointIndex;
|
||||
int endPointIndex;
|
||||
RouteSegmentResult(SHARED_PTR<RouteDataObject> object, int startPointIndex, int endPointIndex) :
|
||||
object(object), startPointIndex(startPointIndex), endPointIndex (endPointIndex) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
struct FinalRouteSegment {
|
||||
SHARED_PTR<RouteSegment> direct;
|
||||
bool reverseWaySearch;
|
||||
SHARED_PTR<RouteSegment> 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)<int64_t, SHARED_PTR<RouteSegment> > routes;
|
||||
|
||||
RoutingSubregionTile(RouteSubregion& sub) : access(0), loaded(0), subregion(sub) {
|
||||
|
||||
}
|
||||
~RoutingSubregionTile(){
|
||||
}
|
||||
bool isLoaded(){
|
||||
return loaded > 0;
|
||||
}
|
||||
|
||||
void setLoaded(){
|
||||
loaded++;
|
||||
}
|
||||
|
||||
void add(SHARED_PTR<RouteDataObject> 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<RouteSegment> segment = SHARED_PTR<RouteSegment>(new RouteSegment(o, i));
|
||||
if (routes[l].get() == NULL) {
|
||||
routes[l] = segment;
|
||||
} else {
|
||||
SHARED_PTR<RouteSegment> orig = routes[l];
|
||||
int cnt = 0;
|
||||
while (orig->next.get() != NULL) {
|
||||
orig = orig->next;
|
||||
cnt++;
|
||||
}
|
||||
orig->next = segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
static int64_t calcRouteId(SHARED_PTR<RouteDataObject> 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<SHARED_PTR<RouteSegment> > segmentsToVisitNotForbidden;
|
||||
vector<SHARED_PTR<RouteSegment> > segmentsToVisitPrescripted;
|
||||
|
||||
SHARED_PTR<FinalRouteSegment> finalRouteSegment;
|
||||
UNORDERED(map)<int64_t, SHARED_PTR<RoutingSubregionTile> > subregionTiles;
|
||||
UNORDERED(map)<int64_t, std::vector<SHARED_PTR<RoutingSubregionTile> > > indexedSubregions;
|
||||
|
||||
RoutingContext() : finalRouteSegment(), firstRoadDirection(0), loadedTiles(0), visitedSegments(0){
|
||||
}
|
||||
bool acceptLine(SHARED_PTR<RouteDataObject> r) {
|
||||
string v = getHighway(r);
|
||||
if(v != "" && v != "cycleway" && v != "footway" && v != "steps"){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
string getHighway(SHARED_PTR<RouteDataObject> r) {
|
||||
std::vector<uint32_t>::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<SHARED_PTR<RoutingSubregionTile> > subregions = indexedSubregions[tileId];
|
||||
for(int j = 0; j<subregions.size(); j++) {
|
||||
if(!subregions[j]->isLoaded()) {
|
||||
loadedTiles++;
|
||||
subregions[j]->setLoaded();
|
||||
SearchQuery q;
|
||||
vector<RouteDataObject*> res;
|
||||
searchRouteDataForSubRegion(&q, res, &subregions[j]->subregion);
|
||||
vector<RouteDataObject*>::iterator i = res.begin();
|
||||
for(;i!=res.end(); i++) {
|
||||
if(*i != NULL) {
|
||||
SHARED_PTR<RouteDataObject> 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<RouteSubregion> tempResult;
|
||||
searchRouteSubregions(&q, tempResult);
|
||||
std::vector<SHARED_PTR<RoutingSubregionTile> > collection;
|
||||
for(int i=0; i<tempResult.size(); i++) {
|
||||
RouteSubregion& rs = tempResult[i];
|
||||
int64_t key = ((int64_t)rs.left << 31)+ rs.length;
|
||||
if(subregionTiles.find(key) == subregionTiles.end()) {
|
||||
subregionTiles[key] = SHARED_PTR<RoutingSubregionTile>(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<RouteSegment> loadSegmentAround(int x31, int y31) {
|
||||
timeToLoad.start();
|
||||
SHARED_PTR<RouteSegment> 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<SHARED_PTR<RoutingSubregionTile> > subregions = indexedSubregions[tileId];
|
||||
for(int j = 0; j<subregions.size(); j++) {
|
||||
if(subregions[j]->isLoaded()) {
|
||||
UNORDERED(map)<int64_t, SHARED_PTR<RouteSegment> >::iterator s = subregions[j]->routes.begin();
|
||||
while(s != subregions[j]->routes.end()) {
|
||||
SHARED_PTR<RouteSegment> seg = s->second;
|
||||
if(seg.get() != NULL) {
|
||||
double d = measuredDist(x31, y31, seg->road->pointsX[seg->getSegmentStart()],
|
||||
seg->road->pointsY[seg->getSegmentStart()]);
|
||||
if(dist == -1 || d < dist) {
|
||||
r = seg;
|
||||
dist = d;
|
||||
}
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
timeToLoad.pause();
|
||||
return r;
|
||||
}
|
||||
|
||||
// void searchRouteRegion(SearchQuery* q, std::vector<RouteDataObject*>& list, RoutingIndex* rs, RouteSubregion* sub)
|
||||
SHARED_PTR<RouteSegment> loadRouteSegment(int x31, int y31) {
|
||||
int z = 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<SHARED_PTR<RoutingSubregionTile> > subregions = indexedSubregions[tileId];
|
||||
UNORDERED(map)<int64_t, SHARED_PTR<RouteDataObject> > excludeDuplications;
|
||||
SHARED_PTR<RouteSegment> original;
|
||||
for(int j = 0; j<subregions.size(); j++) {
|
||||
if(subregions[j]->isLoaded()) {
|
||||
SHARED_PTR<RouteSegment> segment = subregions[j]->routes[l];
|
||||
subregions[j]->access++;
|
||||
while (segment.get() != NULL) {
|
||||
SHARED_PTR<RouteDataObject> ro = segment->road;
|
||||
SHARED_PTR<RouteDataObject> toCmp = excludeDuplications[calcRouteId(ro, segment->getSegmentStart())];
|
||||
if (toCmp.get() == NULL || toCmp->pointsX.size() < ro->pointsX.size()) {
|
||||
excludeDuplications[calcRouteId(ro, segment->getSegmentStart())] = ro;
|
||||
SHARED_PTR<RouteSegment> s = SHARED_PTR<RouteSegment>(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<RouteDataObject> 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<RouteDataObject> r) {
|
||||
std::vector<uint32_t>::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<RouteDataObject> 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<RouteDataObject> r) {
|
||||
std::vector<uint32_t>::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<RouteSegment> segment, int index, SHARED_PTR<RouteSegment> next, int nextIndex){
|
||||
return 0;
|
||||
}
|
||||
float defineRoutingObstacle(SHARED_PTR<RouteDataObject> road, int segmentEnd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool restrictionsAware(){
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
vector<RouteSegmentResult> searchRouteInternal(RoutingContext* ctx, bool leftSideNavigation);
|
||||
#endif /*_OSMAND_BINARY_ROUTE_PLANNER_H*/
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
"<init>", "(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<RouteSegmentResult> 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<RouteDataObject*> result;
|
||||
SearchQuery q;
|
||||
searchRouteDataForSubRegion(&q, result, &ind, &sub);
|
||||
searchRouteDataForSubRegion(&q, result, &sub);
|
||||
|
||||
|
||||
if (loadObjects) {
|
||||
|
|
Loading…
Reference in a new issue