Add map processing
This commit is contained in:
parent
e36e6110c9
commit
05d50bd54c
5 changed files with 171 additions and 111 deletions
|
@ -16,6 +16,7 @@
|
|||
#include "renderRules.h"
|
||||
#include "common.h"
|
||||
#include "mapObjects.h"
|
||||
#include "multipolygons.h"
|
||||
//#include "multipolygons.h"
|
||||
#include "proto/osmand_odb.pb.h"
|
||||
|
||||
|
@ -24,6 +25,7 @@ using namespace google::protobuf;
|
|||
using namespace google::protobuf::internal;
|
||||
|
||||
static const int MAP_VERSION = 2;
|
||||
static const int BASEMAP_ZOOM = 11;
|
||||
|
||||
|
||||
|
||||
|
@ -187,6 +189,11 @@ struct BinaryMapFile {
|
|||
std::string inputName;
|
||||
vector<MapIndex> mapIndexes;
|
||||
FILE* f;
|
||||
bool basemap;
|
||||
|
||||
bool isBasemap(){
|
||||
return basemap;
|
||||
}
|
||||
|
||||
~BinaryMapFile() {
|
||||
fclose(f);
|
||||
|
@ -410,6 +417,7 @@ bool initMapStructure(io::CodedInputStream* input, BinaryMapFile* file) {
|
|||
input->PopLimit(oldLimit);
|
||||
input->Seek(mapIndex.filePointer + mapIndex.length);
|
||||
file->mapIndexes.push_back(mapIndex);
|
||||
file->basemap = file->basemap || mapIndex.name.find("basemap") != string::npos;
|
||||
break;
|
||||
}
|
||||
case OsmAndStructure::kVersionConfirmFieldNumber: {
|
||||
|
@ -443,9 +451,6 @@ extern "C" JNIEXPORT void JNICALL Java_net_osmand_plus_render_NativeOsmandLibrar
|
|||
jobject obj, jint searchResult) {
|
||||
SearchResult* result = (SearchResult*) searchResult;
|
||||
if(result != NULL){
|
||||
deleteObjects(result->basemapCoastLines);
|
||||
deleteObjects(result->result);
|
||||
deleteObjects(result->coastLines);
|
||||
deleteObjects(result->result);
|
||||
delete result;
|
||||
}
|
||||
|
@ -850,74 +855,149 @@ void searchMapData(io::CodedInputStream* input, MapRoot* root, MapIndex* ind, Se
|
|||
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_searchObjectsForRendering(JNIEnv* ienv,
|
||||
jobject obj, jint sleft, jint sright, jint stop, jint sbottom, jint zoom, jstring mapName,
|
||||
jobject renderingRuleSearchRequest, bool skipDuplicates, jint searchResult, jobject objInterrupted) {
|
||||
// TODO skipDuplicates not supported
|
||||
SearchResult* result = (SearchResult*) searchResult;
|
||||
if(result == NULL) {
|
||||
result = new SearchResult();
|
||||
}
|
||||
std::string map = getString(ienv, mapName);
|
||||
std::map<std::string, BinaryMapFile*>::iterator i = openFiles.find(map);
|
||||
if(i == openFiles.end()) {
|
||||
return (jint) result;
|
||||
}
|
||||
BinaryMapFile* file = i->second;
|
||||
|
||||
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_searchNativeObjectsForRendering(JNIEnv* ienv,
|
||||
jobject obj, jint sleft, jint sright, jint stop, jint sbottom, jint zoom, jobject renderingRuleSearchRequest, bool skipDuplicates, jobject objInterrupted) {
|
||||
RenderingRuleSearchRequest* req = initSearchRequest(ienv, renderingRuleSearchRequest);
|
||||
jclass clObjInterrupted = ienv->GetObjectClass(objInterrupted);
|
||||
jfieldID interruptedField = getFid(ienv, clObjInterrupted, "interrupted", "Z");
|
||||
ienv->DeleteLocalRef(clObjInterrupted);
|
||||
|
||||
SearchQuery q(sleft,sright, stop, sbottom, req, objInterrupted, interruptedField, ienv);
|
||||
q.zoom = zoom;
|
||||
|
||||
fseek(file->f, 0, 0);
|
||||
io::FileInputStream input(fileno(file->f));
|
||||
input.SetCloseOnDelete(false);
|
||||
io::CodedInputStream cis(&input);
|
||||
cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 2);
|
||||
if(req != NULL){
|
||||
req->clearState();
|
||||
}
|
||||
SearchResult* searchRes = new SearchResult();
|
||||
std::map<std::string, BinaryMapFile*>::iterator i = openFiles.begin();
|
||||
std::hash_set<long long> ids;
|
||||
int count = 0;
|
||||
bool ocean = false;
|
||||
std::vector< MapDataObject* > tempResult;
|
||||
std::vector< MapDataObject* > basemapResult;
|
||||
std::vector< MapDataObject* > coastLines;
|
||||
std::vector< MapDataObject* > basemapCoastLines;
|
||||
|
||||
for(vector<MapIndex>::iterator mapIndex = file->mapIndexes.begin();
|
||||
mapIndex != file->mapIndexes.end(); mapIndex++) {
|
||||
for (vector<MapRoot>::iterator mapLevel = mapIndex->levels.begin(); mapLevel != mapIndex->levels.end();
|
||||
mapLevel++) {
|
||||
if (q.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
if(mapLevel->minZoom <= zoom && mapLevel->maxZoom >= zoom) {
|
||||
if(mapLevel->right >= q.left && q.right >= mapLevel->left &&
|
||||
mapLevel->bottom >= q.top && q.bottom >= mapLevel->top) {
|
||||
searchMapData(&cis, mapLevel, mapIndex, &q);
|
||||
for (; i != openFiles.end() && !q.isCancelled(); i++) {
|
||||
BinaryMapFile* file = i->second;
|
||||
fseek(file->f, 0, 0);
|
||||
io::FileInputStream input(fileno(file->f));
|
||||
input.SetCloseOnDelete(false);
|
||||
io::CodedInputStream cis(&input);
|
||||
cis.SetTotalBytesLimit(INT_MAX, INT_MAX >> 2);
|
||||
if (req != NULL) {
|
||||
req->clearState();
|
||||
}
|
||||
q.result.clear();
|
||||
for (vector<MapIndex>::iterator mapIndex = file->mapIndexes.begin(); mapIndex != file->mapIndexes.end();
|
||||
mapIndex++) {
|
||||
for (vector<MapRoot>::iterator mapLevel = mapIndex->levels.begin(); mapLevel != mapIndex->levels.end();
|
||||
mapLevel++) {
|
||||
if (q.isCancelled()) {
|
||||
break;
|
||||
}
|
||||
if (mapLevel->minZoom <= zoom && mapLevel->maxZoom >= zoom) {
|
||||
if (mapLevel->right >= q.left && q.right >= mapLevel->left && mapLevel->bottom >= q.top
|
||||
&& q.bottom >= mapLevel->top) {
|
||||
searchMapData(&cis, mapLevel, mapIndex, &q);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!q.isCancelled()) {
|
||||
std::vector<MapDataObject*>::iterator r = q.result.begin();
|
||||
tempResult.reserve(q.result.size() + tempResult.size());
|
||||
for (; r != q.result.end(); r++) {
|
||||
if (skipDuplicates && (*r)->id > 0) {
|
||||
if (ids.find((*r)->id) != ids.end()) {
|
||||
continue;
|
||||
}
|
||||
ids.insert((*r)->id);
|
||||
}
|
||||
}
|
||||
count++;
|
||||
if ((*r)->contains("natural", "coastline")) {
|
||||
if (i->second->isBasemap()) {
|
||||
basemapCoastLines.push_back(*r);
|
||||
} else {
|
||||
coastLines.push_back(*r);
|
||||
}
|
||||
} else {
|
||||
// do not mess coastline and other types
|
||||
if (i->second->isBasemap()) {
|
||||
basemapResult.push_back(*r);
|
||||
} else {
|
||||
tempResult.push_back(*r);
|
||||
}
|
||||
}
|
||||
|
||||
if (q.ocean) {
|
||||
ocean = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
result->result.insert(result->result.end(), q.result.begin(), q.result.end());
|
||||
// FIXME process multi polygons
|
||||
// std::map<tagValueType, std::vector<MapDataObject*> > multyPolygons;
|
||||
// std::vector<MapDataObject*>::iterator mdo = q.result.begin();
|
||||
// for(;mdo!= q.result.end(); mdo++) {
|
||||
// for(size_t j = 0; j<(*mdo)->types.size(); j++) {
|
||||
// int type = (*mdo)->types.at(j);
|
||||
// if((type & 0x3) == RenderingRulesStorage::MULTI_POLYGON_TYPE) {
|
||||
// tagValueType tagValue((*mdo)->tagValues.at(j), type);
|
||||
// multyPolygons[tagValue].push_back(*mdo);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// proccessMultiPolygons(multyPolygons, q.left, q.right, q.bottom, q.top, q.zoom, result->result);
|
||||
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Search : tree - read( %d), accept( %d), objs - visit( %d), accept(%d), in result(%d) ", q.numberOfReadSubtrees,
|
||||
q.numberOfAcceptedSubtrees, q.numberOfVisitedObjects, q.numberOfAcceptedObjects, result->result.size());
|
||||
if(q.result.size() > 0) {
|
||||
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Search : tree - read( %d), accept( %d), objs - visit( %d), accept(%d), in result(%d) ", q.numberOfReadSubtrees,
|
||||
q.numberOfAcceptedSubtrees, q.numberOfVisitedObjects, q.numberOfAcceptedObjects, result->result.size());
|
||||
if (q.isCancelled()) {
|
||||
deleteObjects(coastLines);
|
||||
deleteObjects(tempResult);
|
||||
deleteObjects(basemapCoastLines);
|
||||
deleteObjects(basemapResult);
|
||||
} else {
|
||||
bool addBasemapCoastlines = true;
|
||||
bool emptyData = zoom > BASEMAP_ZOOM && tempResult.empty() && coastLines.empty();
|
||||
|
||||
if (!coastLines.empty()) {
|
||||
// TODO suspicious memory leak?
|
||||
std::vector< MapDataObject* > pcoastlines;
|
||||
processCoastlines(coastLines, sleft, sright, sbottom, stop, zoom,
|
||||
basemapCoastLines.empty(), pcoastlines);
|
||||
addBasemapCoastlines = pcoastlines.empty() || zoom <= BASEMAP_ZOOM;
|
||||
tempResult.insert(tempResult.end(), pcoastlines.begin(), pcoastlines.end());
|
||||
}
|
||||
if (addBasemapCoastlines) {
|
||||
addBasemapCoastlines = false;
|
||||
// TODO suspicious memory leak?
|
||||
std::vector< MapDataObject* > pcoastlines;
|
||||
processCoastlines(basemapCoastLines, sleft, sright, sbottom,
|
||||
stop, zoom, true, pcoastlines);
|
||||
addBasemapCoastlines = pcoastlines.empty();
|
||||
tempResult.insert(tempResult.end(), pcoastlines.begin(), pcoastlines.end());
|
||||
}
|
||||
if (addBasemapCoastlines) {
|
||||
MapDataObject* o = new MapDataObject();
|
||||
o->points.push_back(int_pair(sleft, stop));
|
||||
o->points.push_back(int_pair(sright, stop));
|
||||
o->points.push_back(int_pair(sright, sbottom));
|
||||
o->points.push_back(int_pair(sleft, sbottom));
|
||||
o->points.push_back(int_pair(sleft, stop));
|
||||
if (ocean) {
|
||||
o->types.push_back(tag_value("natural", "coastline"));
|
||||
} else {
|
||||
o->types.push_back(tag_value("natural", "land"));
|
||||
}
|
||||
tempResult.push_back(o);
|
||||
}
|
||||
if (emptyData) {
|
||||
// message
|
||||
// avoid overflow int errors
|
||||
MapDataObject* o = new MapDataObject();
|
||||
o->points.push_back(int_pair(sleft + (sright - sleft) / 2, stop + (sbottom - stop) / 2 ));
|
||||
o->types.push_back(tag_value("natural", "coastline"));
|
||||
// TODO string
|
||||
o->objectNames["name"]="Switch To See";
|
||||
tempResult.push_back(o);
|
||||
}
|
||||
if (zoom <= BASEMAP_ZOOM || emptyData) {
|
||||
tempResult.insert(tempResult.end(), basemapResult.begin(), basemapResult.end());
|
||||
}
|
||||
searchRes->result.insert(searchRes->result.end(), tempResult.begin(), tempResult.end());
|
||||
__android_log_print(ANDROID_LOG_INFO, LOG_TAG,
|
||||
"Search : tree - read( %d), accept( %d), objs - visit( %d), accept(%d), in result(%d) ",
|
||||
q.numberOfReadSubtrees, q.numberOfAcceptedSubtrees, q.numberOfVisitedObjects, q.numberOfAcceptedObjects,
|
||||
searchRes->result.size());
|
||||
}
|
||||
delete req;
|
||||
return (jint)result;
|
||||
return (jint)searchRes;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_closeBinaryMapFile(JNIEnv* ienv,
|
||||
|
|
|
@ -46,6 +46,17 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool contains(std::string key, std::string val) {
|
||||
std::vector<tag_value>::iterator it = types.begin();
|
||||
while (it != types.end()) {
|
||||
if (it->first == key) {
|
||||
return it->second == val;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int getSimpleLayer() {
|
||||
std::vector<tag_value>::iterator it = additionalTypes.begin();
|
||||
while (it != additionalTypes.end()) {
|
||||
|
@ -69,11 +80,6 @@ public:
|
|||
struct SearchResult {
|
||||
std::vector< MapDataObject* > result;
|
||||
int count;
|
||||
std::vector< MapDataObject* > tempResult;
|
||||
std::vector< MapDataObject* > basemapResult;
|
||||
std::vector< MapDataObject* > coastLines;
|
||||
std::vector< MapDataObject* > basemapCoastLines;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -10,23 +10,6 @@
|
|||
#include "common.h"
|
||||
#include "mapObjects.h"
|
||||
|
||||
struct tagValueType {
|
||||
int type;
|
||||
std::string tag;
|
||||
std::string value;
|
||||
|
||||
tagValueType(tag_value t, int type) : type(type) {
|
||||
tag = t.first;
|
||||
value = t.second;
|
||||
}
|
||||
|
||||
};
|
||||
bool operator==(const tagValueType& __x, const tagValueType& __y) {
|
||||
return __x.type == __y.type;
|
||||
}
|
||||
bool operator<(const tagValueType& __x, const tagValueType& __y) {
|
||||
return __x.type < __y.type;
|
||||
}
|
||||
/// !!! Fuly copied from MapRenderRepositories.java, should be carefully synchroinized
|
||||
bool isClockwiseWay(std::vector<int_pair>& c) ;
|
||||
bool calculateLineCoordinates(bool inside, int x, int y, bool pinside, int px, int py, int leftX, int rightX,
|
||||
|
@ -38,6 +21,8 @@ void processMultipolygonLine(std::vector<std::vector<int_pair> >& completedRings
|
|||
void unifyIncompletedRings(std::vector<std::vector<int_pair> >& incompletedRings, std::vector<std::vector<int_pair> >& completedRings, std::vector<std::string> &completedRingNames,
|
||||
std::vector<std::string> &incompletedRingNames, int leftX, int rightX, int bottomY, int topY, long dbId, int zoom);
|
||||
|
||||
|
||||
|
||||
MapDataObject* processMultiPolygon(int leftX, int rightX, int bottomY, int topY,
|
||||
std::vector<std::vector<int_pair > >& completedRings, std::vector<std::vector<int_pair> >& incompletedRings,
|
||||
std::vector<std::string>& completedRingNames, std::vector<std::string>& incompletedRingNames,
|
||||
|
@ -125,6 +110,12 @@ MapDataObject* processMultiPolygon(int leftX, int rightX, int bottomY, int topY,
|
|||
return pl;
|
||||
}
|
||||
|
||||
|
||||
void processCoastlines(std::vector<MapDataObject*>& coastLines, int leftX, int rightX,
|
||||
int bottomY, int topY, int zoom, bool showIncompleted, std::vector<MapDataObject*>& res) {
|
||||
|
||||
}
|
||||
|
||||
static std::vector<MapDataObject*> EMPTY_LIST;
|
||||
void proccessMultiPolygons(std::map<tagValueType, std::vector<MapDataObject*> >& multyPolygons, int leftX,
|
||||
int rightX, int bottomY, int topY, int zoom, std::vector<MapDataObject*>& listPolygons) {
|
||||
|
|
|
@ -267,8 +267,7 @@ public class MapRenderRepositories {
|
|||
int topY = MapUtils.get31TileNumberY(dataBox.top);
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
// additionally initialize
|
||||
NativeSearchResult resultHandler = null;
|
||||
// check that everything is initialized
|
||||
for (String mapName : files.keySet()) {
|
||||
if (!nativeFiles.contains(mapName)) {
|
||||
nativeFiles.add(mapName);
|
||||
|
@ -279,19 +278,14 @@ public class MapRenderRepositories {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO coastline/land tiles
|
||||
for (String mapName : files.keySet()) {
|
||||
BinaryMapIndexReader reader = files.get(mapName);
|
||||
if(!reader.containsMapData(leftX, topY, rightX, bottomY, zoom)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
resultHandler = library.searchObjectsForRendering(leftX, rightX, topY, bottomY, zoom, mapName, renderingReq,
|
||||
PerformanceFlags.checkForDuplicateObjectIds, resultHandler, this);
|
||||
if (checkWhetherInterrupted()) {
|
||||
library.deleteSearchResult(resultHandler);
|
||||
return false;
|
||||
}
|
||||
NativeSearchResult resultHandler = library.searchObjectsForRendering(leftX, rightX, topY, bottomY, zoom, renderingReq,
|
||||
PerformanceFlags.checkForDuplicateObjectIds, this);
|
||||
if (checkWhetherInterrupted()) {
|
||||
library.deleteSearchResult(resultHandler);
|
||||
return false;
|
||||
}
|
||||
if(cNativeObjects != null) {
|
||||
library.deleteSearchResult(cNativeObjects);
|
||||
}
|
||||
cNativeObjects = resultHandler;
|
||||
cObjectsBox = dataBox;
|
||||
|
|
|
@ -99,21 +99,10 @@ public class NativeOsmandLibrary {
|
|||
* @param searchResultHandle
|
||||
* - must be null if there is no need to append to previous results returns native handle to results
|
||||
*/
|
||||
public NativeSearchResult searchObjectsForRendering(int sleft, int sright, int stop, int sbottom, int zoom, String mapName,
|
||||
RenderingRuleSearchRequest request, boolean skipDuplicates, NativeSearchResult searchResultHandler,
|
||||
Object objectWithInterruptedField) {
|
||||
if (searchResultHandler == null) {
|
||||
return new NativeSearchResult(searchObjectsForRendering(sleft, sright, stop, sbottom, zoom, mapName, request, skipDuplicates,
|
||||
0, objectWithInterruptedField));
|
||||
} else {
|
||||
int res = searchObjectsForRendering(sleft, sright, stop, sbottom, zoom, mapName, request, skipDuplicates,
|
||||
searchResultHandler.nativeHandler, objectWithInterruptedField);
|
||||
if (res == searchResultHandler.nativeHandler) {
|
||||
return searchResultHandler;
|
||||
}
|
||||
return new NativeSearchResult(res);
|
||||
}
|
||||
|
||||
public NativeSearchResult searchObjectsForRendering(int sleft, int sright, int stop, int sbottom, int zoom,
|
||||
RenderingRuleSearchRequest request, boolean skipDuplicates, Object objectWithInterruptedField) {
|
||||
return new NativeSearchResult(searchNativeObjectsForRendering(sleft, sright, stop, sbottom, zoom, request, skipDuplicates,
|
||||
objectWithInterruptedField));
|
||||
}
|
||||
|
||||
public void deleteSearchResult(NativeSearchResult searchResultHandler) {
|
||||
|
@ -170,8 +159,8 @@ public class NativeOsmandLibrary {
|
|||
Bitmap bitmap, boolean useEnglishNames,
|
||||
RenderingRuleSearchRequest render, int defaultColor);
|
||||
|
||||
private static native int searchObjectsForRendering(int sleft, int sright, int stop, int sbottom, int zoom, String mapnaem,
|
||||
RenderingRuleSearchRequest request, boolean skipDuplicates, int searchResultHandler, Object objectWithInterruptedField);
|
||||
private static native int searchNativeObjectsForRendering(int sleft, int sright, int stop, int sbottom, int zoom,
|
||||
RenderingRuleSearchRequest request, boolean skipDuplicates, Object objectWithInterruptedField);
|
||||
|
||||
public static native int getCpuCount();
|
||||
public static native boolean cpuHasNeonSupport();
|
||||
|
|
Loading…
Reference in a new issue