bool LocationIndex::VisitLocationAddresses(const AdminRegion& region, const Location& location, AddressVisitor& visitor) const { FileScanner scanner; bool stopped=false; if (!scanner.Open(AppendFileToDir(path, FILENAME_LOCATION_IDX), FileScanner::LowMemRandom, true)) { log.Error() << "Cannot open file '" << scanner.GetFilename() << "'!"; return false; } if (!scanner.SetPos(indexOffset)) { return false; } if (!VisitLocationAddressEntries(scanner, region, location, visitor, stopped)) { return false; } return !scanner.HasError() && scanner.Close(); }
bool LocationIndex::ResolveAdminRegionHierachie(const AdminRegionRef& adminRegion, std::map<FileOffset,AdminRegionRef >& refs) const { FileScanner scanner; if (!scanner.Open(AppendFileToDir(path, FILENAME_LOCATION_IDX), FileScanner::LowMemRandom, true)) { log.Error() << "Cannot open file '" << scanner.GetFilename() << "'!"; return false; } if (!scanner.SetPos(indexOffset)) { return false; } std::list<FileOffset> offsets; refs[adminRegion->regionOffset]=adminRegion; if (adminRegion->parentRegionOffset!=0) { offsets.push_back(adminRegion->parentRegionOffset); } while (!offsets.empty()) { std::list<FileOffset> newOffsets; for (const auto& offset : offsets) { if (refs.find(offset)!=refs.end()) { continue; } if (!scanner.SetPos(offset)) { return false; } AdminRegion adminRegion; if (!LoadAdminRegion(scanner, adminRegion)) { return false; } refs[adminRegion.regionOffset]=std::make_shared<AdminRegion>(adminRegion); if (adminRegion.parentRegionOffset!=0) { newOffsets.push_back(adminRegion.parentRegionOffset); } } offsets.clear(); std::swap(offsets, newOffsets); } return !scanner.HasError() && scanner.Close(); }
bool LocationIndex::Load(const std::string& path) { this->path=path; FileScanner scanner; if (!scanner.Open(AppendFileToDir(path, FILENAME_LOCATION_IDX), FileScanner::LowMemRandom, true)) { log.Error() << "Cannot open file '" << scanner.GetFilename() << "'!"; return false; } if (!(scanner.Read(bytesForNodeFileOffset) && scanner.Read(bytesForAreaFileOffset) && scanner.Read(bytesForWayFileOffset))) { return false; } uint32_t ignoreTokenCount; if (!scanner.ReadNumber(ignoreTokenCount)) { return false; } for (size_t i=0; i<ignoreTokenCount; i++) { std::string token; if (!scanner.Read(token)) { return false; } regionIgnoreTokens.insert(token); } if (!scanner.ReadNumber(ignoreTokenCount)) { return false; } for (size_t i=0; i<ignoreTokenCount; i++) { std::string token; if (!scanner.Read(token)) { return false; } locationIgnoreTokens.insert(token); } if (!scanner.GetPos(indexOffset)) { return false; } return !scanner.HasError() && scanner.Close(); }
bool DebugDatabase::ResolveReferences(const std::string& mapName, RefType fileType, const std::set<ObjectOSMRef>& ids, const std::set<ObjectFileRef>& fileOffsets, std::map<ObjectOSMRef,ObjectFileRef>& idFileOffsetMap, std::map<ObjectFileRef,ObjectOSMRef>& fileOffsetIdMap) { FileScanner scanner; uint32_t entryCount; std::string filename=AppendFileToDir(path,mapName); if (!scanner.Open(filename,FileScanner::LowMemRandom,false)) { std::cerr << "Cannot open file '" << scanner.GetFilename() << "'!" << std::endl; return false; } if (!scanner.Read(entryCount)) { return false; } for (size_t i=1; i<=entryCount; i++) { Id id; uint8_t typeByte; OSMRefType osmType; FileOffset fileOffset; if (!scanner.Read(id)) { return false; } if (!scanner.Read(typeByte)) { return false; } osmType=(OSMRefType)typeByte; if (!scanner.ReadFileOffset(fileOffset)) { return false; } ObjectOSMRef osmRef(id,osmType); ObjectFileRef fileRef(fileOffset,fileType); if (ids.find(osmRef)!=ids.end() || fileOffsets.find(fileRef)!=fileOffsets.end()) { idFileOffsetMap.insert(std::make_pair(osmRef,fileRef)); fileOffsetIdMap.insert(std::make_pair(fileRef,osmRef)); } } return scanner.Close(); }
bool LocationIndex::VisitAdminRegions(AdminRegionVisitor& visitor) const { FileScanner scanner; if (!scanner.Open(AppendFileToDir(path, FILENAME_LOCATION_IDX), FileScanner::LowMemRandom, false)) { log.Error() << "Cannot open file '" << scanner.GetFilename() << "'!"; return false; } if (!scanner.SetPos(indexOffset)) { return false; } uint32_t regionCount; if (!scanner.ReadNumber(regionCount)) { return false; } for (size_t i=0; i<regionCount; i++) { AdminRegionVisitor::Action action; FileOffset nextChildOffset; if (!scanner.ReadFileOffset(nextChildOffset)) { return false; } action=VisitRegionEntries(scanner, visitor); if (action==AdminRegionVisitor::error) { return false; } else if (action==AdminRegionVisitor::stop) { return true; } else if (action==AdminRegionVisitor::skipChildren) { if (i+1<regionCount) { if (!scanner.SetPos(nextChildOffset)) { return false; } } } } return !scanner.HasError() && scanner.Close(); }
/** * Load the object variant data from the given file. * * @param typeConfig * TypeConfig instance * @param filename * Name of the file containing the object variant data * @return * True on success, else false */ bool ObjectVariantDataFile::Load(const TypeConfig& typeConfig, const std::string& filename) { FileScanner scanner; data.clear(); isLoaded=false; this->filename=filename; try { scanner.Open(filename, FileScanner::Sequential,true); uint32_t dataCount; scanner.Read(dataCount); data.resize(dataCount); for (size_t i=0; i<dataCount; i++) { data[i].Read(typeConfig, scanner); } scanner.Close(); isLoaded=true; } catch (IOException& e) { log.Error() << e.GetDescription(); scanner.CloseFailsafe(); return false; } return true; }
bool Database::Open(const std::string& path) { assert(!path.empty()); this->path=path; typeConfig=std::make_shared<TypeConfig>(); if (!typeConfig->LoadFromDataFile(path)) { log.Error() << "Cannot load 'types.dat'!"; return false; } FileScanner scanner; try { scanner.Open(AppendFileToDir(path,"bounding.dat"), FileScanner::Normal, false); scanner.ReadBox(boundingBox); log.Debug() << "BoundingBox: " << boundingBox.GetDisplayText(); scanner.Close(); } catch (IOException& e) { log.Error() << e.GetDescription(); scanner.CloseFailsafe(); return false; } isOpen=true; return true; }
bool Database::Open(const std::string& path) { assert(!path.empty()); this->path=path; typeConfig=new TypeConfig(); if (!typeConfig->LoadFromDataFile(path)) { log.Error() << "Cannot load 'types.dat'!"; return false; } FileScanner scanner; std::string file=AppendFileToDir(path,"bounding.dat"); if (!scanner.Open(file,FileScanner::Normal,true)) { log.Error() << "Cannot open '" << scanner.GetFilename() << "'"; return false; } if (!scanner.ReadBox(boundingBox)) { log.Error() << "Error while reading '" << scanner.GetFilename() << "'"; } log.Debug() << "BoundingBox: " << boundingBox.GetDisplayText(); if (scanner.HasError() || !scanner.Close()) { log.Error() << "Cannot while reading/closing '" << scanner.GetFilename() << "'"; return false; } isOpen=true; return true; }
bool NodeDataGenerator::Import(const TypeConfigRef& typeConfig, const ImportParameter& parameter, Progress& progress) { uint32_t rawNodeCount=0; uint32_t nodesReadCount=0; uint32_t nodesWrittenCount=0; // // Iterator over all raw nodes, hcekc they type, and convert them from raw nodes // to nodes if the type is interesting (!=typeIgnore). // // Count the bounding box by the way... // progress.SetAction("Generating nodes.tmp"); FileScanner scanner; FileWriter writer; if (!scanner.Open(AppendFileToDir(parameter.GetDestinationDirectory(), "rawnodes.dat"), FileScanner::Sequential, parameter.GetRawNodeDataMemoryMaped())) { progress.Error("Cannot open 'rawnodes.dat'"); return false; } if (!scanner.Read(rawNodeCount)) { progress.Error("Error while reading number of data entries in file"); return false; } if (!writer.Open(AppendFileToDir(parameter.GetDestinationDirectory(), "nodes.tmp"))) { progress.Error("Cannot create 'nodes.tmp'"); return false; } writer.Write(nodesWrittenCount); for (uint32_t n=1; n<=rawNodeCount; n++) { progress.SetProgress(n,rawNodeCount); RawNode rawNode; Node node; if (!rawNode.Read(typeConfig, scanner)) { progress.Error(std::string("Error while reading data entry ")+ NumberToString(n)+" of "+ NumberToString(rawNodeCount)+ " in file '"+ scanner.GetFilename()+"'"); return false; } nodesReadCount++; if (!rawNode.GetType()->GetIgnore()) { node.SetFeatures(rawNode.GetFeatureValueBuffer()); node.SetCoords(rawNode.GetCoords()); FileOffset fileOffset; if (!writer.GetPos(fileOffset)) { progress.Error(std::string("Error while reading current fileOffset in file '")+ writer.GetFilename()+"'"); return false; } writer.Write(rawNode.GetId()); node.Write(typeConfig, writer); nodesWrittenCount++; } } if (!scanner.Close()) { return false; } writer.SetPos(0); writer.Write(nodesWrittenCount); if (!writer.Close()) { return false; } progress.Info(std::string("Read "+NumberToString(nodesReadCount)+" nodes, wrote "+NumberToString(nodesWrittenCount)+" nodes")); return true; }
bool MergeAreasGenerator::Import(const TypeConfigRef& typeConfig, const ImportParameter& parameter, Progress& progress) { TypeInfoSet mergeTypes; FileScanner scanner; FileWriter writer; uint32_t areasWritten=0; for (const auto& type : typeConfig->GetTypes()) { if (type->CanBeArea() && type->GetMergeAreas()) { mergeTypes.Set(type); } } std::unordered_set<Id> nodeUseMap; try { scanner.Open(AppendFileToDir(parameter.GetDestinationDirectory(), MergeAreaDataGenerator::AREAS_TMP), FileScanner::Sequential, parameter.GetRawWayDataMemoryMaped()); if (!ScanAreaNodeIds(progress, *typeConfig, scanner, mergeTypes, nodeUseMap)) { return false; } uint32_t nodeCount=nodeUseMap.size(); progress.Info("Found "+NumberToString(nodeCount)+" nodes as possible connection points for areas"); /* ------ */ writer.Open(AppendFileToDir(parameter.GetDestinationDirectory(), AREAS2_TMP)); writer.Write(areasWritten); while (true) { TypeInfoSet loadedTypes; std::vector<AreaMergeData> mergeJob(typeConfig->GetTypeCount()); // // Load type data // progress.SetAction("Collecting area data by type"); if (!GetAreas(parameter, progress, *typeConfig, mergeTypes, loadedTypes, nodeUseMap, scanner, writer, mergeJob, areasWritten)) { return false; } // Merge progress.SetAction("Merging areas"); for (const auto& type : loadedTypes) { if (!mergeJob[type->GetIndex()].areas.empty()) { progress.Info("Merging areas of type "+type->GetName()); MergeAreas(progress, nodeUseMap, mergeJob[type->GetIndex()]); progress.Info("Reduced areas of '"+type->GetName()+"' from "+NumberToString(mergeJob[type->GetIndex()].areaCount)+" to "+NumberToString(mergeJob[type->GetIndex()].areaCount-mergeJob[type->GetIndex()].mergedAway.size())); mergeJob[type->GetIndex()].areas.clear(); } } // Store back merge result if (!loadedTypes.Empty()) { if (!WriteMergeResult(progress, *typeConfig, scanner, writer, loadedTypes, mergeJob, areasWritten)) { return false; } mergeTypes.Remove(loadedTypes); } if (mergeTypes.Empty()) { break; } } scanner.Close(); writer.GotoBegin(); writer.Write(areasWritten); writer.Close(); } catch (IOException& e) { progress.Error(e.GetDescription()); scanner.CloseFailsafe(); writer.CloseFailsafe(); return false; } return true; }
bool OptimizeAreaWayIdsGenerator::ScanAreaIds(const ImportParameter& parameter, Progress& progress, const TypeConfig& typeConfig, NodeUseMap& nodeUseMap) { FileScanner scanner; uint32_t dataCount=0; progress.SetAction("Scanning ids from 'areas2.tmp'"); if (!scanner.Open(AppendFileToDir(parameter.GetDestinationDirectory(), "areas2.tmp"), FileScanner::Sequential, parameter.GetAreaDataMemoryMaped())) { progress.Error(std::string("Cannot open '")+scanner.GetFilename()+"'"); return false; } if (!scanner.Read(dataCount)) { progress.Error("Error while reading number of data entries in file"); return false; } for (uint32_t current=1; current<=dataCount; current++) { uint8_t type; Id id; Area data; progress.SetProgress(current,dataCount); if (!scanner.Read(type) || !scanner.Read(id) || !data.ReadImport(typeConfig, scanner)) { progress.Error(std::string("Error while reading data entry ")+ NumberToString(current)+" of "+ NumberToString(dataCount)+ " in file '"+ scanner.GetFilename()+"'"); return false; } for (const auto& ring: data.rings) { std::unordered_set<Id> nodeIds; if (!ring.GetType()->CanRoute()) { continue; } for (const auto id: ring.ids) { if (nodeIds.find(id)==nodeIds.end()) { nodeUseMap.SetNodeUsed(id); nodeIds.insert(id); } } } } if (!scanner.Close()) { progress.Error(std::string("Error while closing file '")+ scanner.GetFilename()+"'"); return false; } return true; }
bool OptimizeAreaWayIdsGenerator::CopyWays(const ImportParameter& parameter, Progress& progress, const TypeConfig& typeConfig, NodeUseMap& nodeUseMap) { FileScanner scanner; FileWriter writer; uint32_t dataCount=0; progress.SetAction("Copy data from 'wayway.tmp' to 'ways.tmp'"); if (!scanner.Open(AppendFileToDir(parameter.GetDestinationDirectory(), "wayway.tmp"), FileScanner::Sequential, parameter.GetWayDataMemoryMaped())) { progress.Error(std::string("Cannot open '")+scanner.GetFilename()+"'"); return false; } if (!scanner.Read(dataCount)) { progress.Error("Error while reading number of data entries in file"); return false; } if (!writer.Open(AppendFileToDir(parameter.GetDestinationDirectory(), "ways.tmp"))) { progress.Error(std::string("Cannot create '")+writer.GetFilename()+"'"); return false; } writer.Write(dataCount); for (uint32_t current=1; current<=dataCount; current++) { uint8_t type; Id id; Way data; progress.SetProgress(current,dataCount); if (!scanner.Read(type) || !scanner.Read(id) || !data.Read(typeConfig, scanner)) { progress.Error(std::string("Error while reading data entry ")+ NumberToString(current)+" of "+ NumberToString(dataCount)+ " in file '"+ scanner.GetFilename()+"'"); return false; } for (auto& id : data.ids) { if (!nodeUseMap.IsNodeUsedAtLeastTwice(id)) { id=0; } } if (!writer.Write(type) || !writer.Write(id) || !data.Write(typeConfig, writer)) { progress.Error(std::string("Error while writing data entry to file '")+ writer.GetFilename()+"'"); return false; } } if (!scanner.Close()) { progress.Error(std::string("Error while closing file '")+ scanner.GetFilename()+"'"); return false; } if (!writer.Close()) { progress.Error(std::string("Error while closing file '")+ writer.GetFilename()+"'"); return false; } return true; }
bool OptimizeAreaWayIdsGenerator::ScanWayIds(const ImportParameter& parameter, Progress& progress, const TypeConfig& typeConfig, NodeUseMap& nodeUseMap) { FileScanner scanner; uint32_t dataCount=0; progress.SetAction("Scanning ids from 'wayway.tmp'"); if (!scanner.Open(AppendFileToDir(parameter.GetDestinationDirectory(), "wayway.tmp"), FileScanner::Sequential, parameter.GetWayDataMemoryMaped())) { progress.Error(std::string("Cannot open '")+scanner.GetFilename()+"'"); return false; } if (!scanner.Read(dataCount)) { progress.Error("Error while reading number of data entries in file"); return false; } for (uint32_t current=1; current<=dataCount; current++) { uint8_t type; Id id; Way data; progress.SetProgress(current,dataCount); if (!scanner.Read(type) || !scanner.Read(id) || !data.Read(typeConfig, scanner)) { progress.Error(std::string("Error while reading data entry ")+ NumberToString(current)+" of "+ NumberToString(dataCount)+ " in file '"+ scanner.GetFilename()+"'"); return false; } if (!data.GetType()->CanRoute()) { continue; } std::unordered_set<Id> nodeIds; for (const auto& id : data.ids) { if (nodeIds.find(id)==nodeIds.end()) { nodeUseMap.SetNodeUsed(id); nodeIds.insert(id); } } // If we have a circular way, we "fake" a double usage, // to make sure, that the node id of the first node // is not dropped later on, and we cannot detect // circular ways anymore if (data.ids.front()==data.ids.back()) { nodeUseMap.SetNodeUsed(data.ids.back()); } } if (!scanner.Close()) { progress.Error(std::string("Error while closing file '")+ scanner.GetFilename()+"'"); return false; } return true; }
bool OptimizeAreasLowZoomGenerator::HandleAreas(const ImportParameter& parameter, Progress& progress, const TypeConfig& typeConfig, FileWriter& writer, const TypeInfoSet& types, std::list<TypeData>& typesData) { FileScanner scanner; // Everything smaller than 2mm should get dropped. Width, height and DPI come from the Nexus 4 double dpi=320.0; double pixel=2.0/* mm */ * dpi / 25.4 /* inch */; progress.Info("Minimum visible size in pixel: "+NumberToString((unsigned long)pixel)); try { scanner.Open(AppendFileToDir(parameter.GetDestinationDirectory(), AreaDataFile::AREAS_DAT), FileScanner::Sequential, parameter.GetWayDataMemoryMaped()); TypeInfoSet typesToProcess(types); std::vector<std::list<AreaRef> > allAreas(typeConfig.GetTypeCount()); while (true) { // // Load type data // TypeInfoSet loadedTypes; if (!GetAreas(typeConfig, parameter, progress, scanner, typesToProcess, allAreas, loadedTypes)) { return false; } typesToProcess.Remove(loadedTypes); for (const auto& type : loadedTypes) { progress.SetAction("Optimizing type "+ type->GetName()); for (uint32_t level=parameter.GetOptimizationMinMag(); level<=parameter.GetOptimizationMaxMag(); level++) { Magnification magnification; // Magnification, we optimize for std::list<AreaRef> optimizedAreas; magnification.SetLevel(level); OptimizeAreas(allAreas[type->GetIndex()], optimizedAreas, 1280,768, dpi, pixel, magnification, parameter.GetOptimizationWayMethod()); if (optimizedAreas.empty()) { progress.Debug("Empty optimization result for level "+NumberToString(level)+", no index generated"); TypeData typeData; typeData.type=type; typeData.optLevel=level; typesData.push_back(typeData); continue; } progress.Info("Optimized from "+NumberToString(allAreas[type->GetIndex()].size())+" to "+NumberToString(optimizedAreas.size())+" areas"); /* size_t optAreas=optimizedAreas.size(); size_t optRoles=0; size_t optNodes=0; for (std::list<AreaRef>::const_iterator a=optimizedAreas.begin(); a!=optimizedAreas.end(); ++a) { AreaRef area=*a; optRoles+=area->rings.size(); for (size_t r=0; r<area->rings.size(); r++) { optNodes+=area->rings[r].nodes.size(); } }*/ /* std::cout << "Areas: " << origAreas << " => " << optAreas << std::endl; std::cout << "Roles: " << origRoles << " => " << optRoles << std::endl; std::cout << "Nodes: " << origNodes << " => " << optNodes << std::endl;*/ TypeData typeData; typeData.type=type; typeData.optLevel=level; GetAreaIndexLevel(parameter, optimizedAreas, typeData); //std::cout << "Resulting index level: " << typeData.indexLevel << ", " << typeData.indexCells << ", " << typeData.indexEntries << std::endl; FileOffsetFileOffsetMap offsets; WriteAreas(typeConfig, writer, optimizedAreas, offsets); if (!WriteAreaBitmap(progress, writer, optimizedAreas, offsets, typeData)) { return false; } typesData.push_back(typeData); } allAreas[type->GetIndex()].clear(); } if (typesToProcess.Empty()) { break; } } scanner.Close(); } catch (IOException& e) { progress.Error(e.GetDescription()); return false; } return true; }
bool AreaWayIndexGenerator::CalculateDistribution(const TypeConfigRef& typeConfig, const ImportParameter& parameter, Progress& progress, std::vector<TypeData>& wayTypeData, size_t& maxLevel) const { FileScanner wayScanner; TypeInfoSet remainingWayTypes; size_t level; maxLevel=0; wayTypeData.resize(typeConfig->GetTypeCount()); if (!wayScanner.Open(AppendFileToDir(parameter.GetDestinationDirectory(), "ways.dat"), FileScanner::Sequential, parameter.GetWayDataMemoryMaped())) { progress.Error("Cannot open 'ways.dat'"); return false; } remainingWayTypes.Set(typeConfig->GetWayTypes()); level=parameter.GetAreaWayMinMag(); while (!remainingWayTypes.Empty()) { uint32_t wayCount=0; TypeInfoSet currentWayTypes(remainingWayTypes); double cellWidth=360.0/pow(2.0,(int)level); double cellHeight=180.0/pow(2.0,(int)level); std::vector<CoordCountMap> cellFillCount(typeConfig->GetTypeCount()); progress.Info("Scanning Level "+NumberToString(level)+" ("+NumberToString(remainingWayTypes.Size())+" types remaining)"); wayScanner.GotoBegin(); if (!wayScanner.Read(wayCount)) { progress.Error("Error while reading number of data entries in file"); return false; } Way way; for (uint32_t w=1; w<=wayCount; w++) { progress.SetProgress(w,wayCount); if (!way.Read(*typeConfig, wayScanner)) { progress.Error(std::string("Error while reading data entry ")+ NumberToString(w)+" of "+ NumberToString(wayCount)+ " in file '"+ wayScanner.GetFilename()+"'"); return false; } // Count number of entries per current type and coordinate if (!currentWayTypes.IsSet(way.GetType())) { continue; } GeoBox boundingBox; way.GetBoundingBox(boundingBox); // // Calculate minimum and maximum tile ids that are covered // by the way // Renormalized coordinate space (everything is >=0) // uint32_t minxc=(uint32_t)floor((boundingBox.GetMinLon()+180.0)/cellWidth); uint32_t maxxc=(uint32_t)floor((boundingBox.GetMaxLon()+180.0)/cellWidth); uint32_t minyc=(uint32_t)floor((boundingBox.GetMinLat()+90.0)/cellHeight); uint32_t maxyc=(uint32_t)floor((boundingBox.GetMaxLat()+90.0)/cellHeight); for (uint32_t y=minyc; y<=maxyc; y++) { for (uint32_t x=minxc; x<=maxxc; x++) { cellFillCount[way.GetType()->GetIndex()][Pixel(x,y)]++; } } } // Check if cell fill for current type is in defined limits for (auto &type : currentWayTypes) { size_t i=type->GetIndex(); CalculateStatistics(level, wayTypeData[i], cellFillCount[i]); if (!FitsIndexCriteria(parameter, progress, *typeConfig->GetTypeInfo(i), wayTypeData[i], cellFillCount[i])) { currentWayTypes.Remove(type); } } for (const auto &type : currentWayTypes) { maxLevel=std::max(maxLevel,level); progress.Info("Type "+type->GetName()+", "+NumberToString(wayTypeData[type->GetIndex()].indexCells)+" cells, "+NumberToString(wayTypeData[type->GetIndex()].indexEntries)+" objects"); remainingWayTypes.Remove(type); } level++; } return !wayScanner.HasError() && wayScanner.Close(); }