bool OptimizeAreasLowZoomGenerator::GetAreas(const TypeConfig& typeConfig, const ImportParameter& parameter, Progress& progress, FileScanner& scanner, const TypeInfoSet& types, std::vector<std::list<AreaRef> >& areas, TypeInfoSet& loadedTypes) { uint32_t areaCount=0; size_t collectedAreasCount=0; loadedTypes=types; progress.SetAction("Collecting area data to optimize"); scanner.GotoBegin(); scanner.Read(areaCount); for (uint32_t a=1; a<=areaCount; a++) { AreaRef area=std::make_shared<Area>(); progress.SetProgress(a,areaCount); area->Read(typeConfig, scanner); if (loadedTypes.IsSet(area->GetType())) { areas[area->GetType()->GetIndex()].push_back(area); collectedAreasCount++; while (collectedAreasCount>parameter.GetOptimizationMaxWayCount() && loadedTypes.Size()>1) { TypeInfoRef victimType; for (auto &type : loadedTypes) { if (areas[type->GetIndex()].size()>0 && (!victimType || areas[type->GetIndex()].size()<areas[victimType->GetIndex()].size())) { victimType=type; } } assert(victimType); collectedAreasCount-=areas[victimType->GetIndex()].size(); areas[victimType->GetIndex()].clear(); loadedTypes.Remove(victimType); } } } progress.Info("Collected "+NumberToString(collectedAreasCount)+" areas for "+NumberToString(loadedTypes.Size())+" types"); return !scanner.HasError(); }
void Preprocess::Callback::ProcessMultipolygon(const TagMap& tags, const std::vector<RawRelation::Member>& members, OSMId id, const TypeInfoRef& type) { RawRelation relation; areaStat[type->GetIndex()]++; relation.SetId(id); if (type->GetIgnore()) { relation.SetType(typeConfig->typeInfoIgnore); } else { relation.SetType(type); } relation.members=members; relation.Parse(progress, *typeConfig, tags); relation.Write(*typeConfig, multipolygonWriter); multipolygonCount++; }
void AbstractRoutingProfile::AddType(const TypeInfoRef& type, double speed) { if (speeds.empty()) { minSpeed=speed; maxSpeed=speed; } else { minSpeed=std::min(minSpeed,speed); maxSpeed=std::max(maxSpeed,speed); } if (type->GetIndex()>=speeds.size()) { speeds.resize(type->GetIndex()+1,0.0); } speeds[type->GetIndex()]=speed; }
/** * Load areas which has a one for the types given by types. If at leats one node * in one of the outer rings of the areas is marked in nodeUseMap as "used at least twice", * index it into the areas map. * * If the number of indexed areas is bigger than parameter.GetRawWayBlockSize() types are * dropped form areas until the number is again below the lmit. */ bool MergeAreasGenerator::GetAreas(const ImportParameter& parameter, Progress& progress, const TypeConfig& typeConfig, const TypeInfoSet& candidateTypes, TypeInfoSet& loadedTypes, const std::unordered_set<Id>& nodeUseMap, FileScanner& scanner, FileWriter& writer, std::vector<AreaMergeData>& mergeJob, uint32_t& areasWritten) { bool firstCall=areasWritten==0; // We are called for the first time uint32_t areaCount=0; size_t collectedAreasCount=0; size_t typesWithAreas=0; for (auto& data : mergeJob) { data.areaCount=0; } loadedTypes=candidateTypes; scanner.GotoBegin(); scanner.Read(areaCount); for (uint32_t a=1; a<=areaCount; a++) { uint8_t type; Id id; AreaRef area=std::make_shared<Area>(); progress.SetProgress(a,areaCount); scanner.Read(type); scanner.Read(id); area->ReadImport(typeConfig, scanner); mergeJob[area->GetType()->GetIndex()].areaCount++; // This is an area of a type that does not get merged, // we directly store it in the target file. if (!loadedTypes.IsSet(area->GetType())) { if (firstCall) { writer.Write(type); writer.Write(id); area->WriteImport(typeConfig, writer); areasWritten++; } continue; } bool isMergeCandidate=false; for (const auto& ring: area->rings) { if (!ring.IsOuterRing()) { continue; } for (const auto node : ring.nodes) { if (nodeUseMap.find(node.GetId())!=nodeUseMap.end()) { isMergeCandidate=true; break; } } if (isMergeCandidate) { break; } } if (!isMergeCandidate) { continue; } if (mergeJob[area->GetType()->GetIndex()].areas.empty()) { typesWithAreas++; } mergeJob[area->GetType()->GetIndex()].areas.push_back(area); collectedAreasCount++; while (collectedAreasCount>parameter.GetRawWayBlockSize() && typesWithAreas>1) { TypeInfoRef victimType; // Find the type with the smallest amount of ways loaded for (auto &type : loadedTypes) { if (!mergeJob[type->GetIndex()].areas.empty() && (!victimType || mergeJob[type->GetIndex()].areas.size()<mergeJob[victimType->GetIndex()].areas.size())) { victimType=type; } } // If there is more then one type of way, we always must find a "victim" type. assert(victimType); // Correct the statistics collectedAreasCount-=mergeJob[victimType->GetIndex()].areas.size(); // Clear already loaded data of th victim type mergeJob[victimType->GetIndex()].areas.clear(); typesWithAreas--; loadedTypes.Remove(victimType); } } progress.SetAction("Collected "+NumberToString(collectedAreasCount)+" areas for "+NumberToString(loadedTypes.Size())+" types"); return true; }
void Preprocess::Callback::ProcessWay(const OSMId& id, std::vector<OSMId>& nodes, const TagMap& tagMap) { TypeInfoRef areaType; TypeInfoRef wayType; int isArea=0; // 0==unknown, 1==true, -1==false bool isCoastlineArea=false; RawWay way; bool isCoastline=false; if (nodes.size()<2) { progress.Warning("Way "+ NumberToString(id)+ " has less than two nodes!"); return; } if (id<lastWayId) { waySortingError=true; } way.SetId(id); auto areaTag=tagMap.find(typeConfig->tagArea); if (areaTag==tagMap.end()) { isArea=0; } else if (areaTag->second=="no" || areaTag->second=="false" || areaTag->second=="0") { isArea=-1; } else { isArea=1; } auto naturalTag=tagMap.find(typeConfig->tagNatural); if (naturalTag!=tagMap.end() && naturalTag->second=="coastline") { isCoastline=true; } if (isCoastline) { isCoastlineArea=nodes.size()>3 && (nodes.front()==nodes.back() || isArea==1); } typeConfig->GetWayAreaType(tagMap, wayType, areaType); if (isArea==1 && areaType==typeConfig->typeInfoIgnore) { isArea=0; } else if (isArea==-1 && wayType==typeConfig->typeInfoIgnore) { isArea=0; } if (isArea==0) { if (wayType!=typeConfig->typeInfoIgnore && areaType==typeConfig->typeInfoIgnore) { isArea=-1; } else if (wayType==typeConfig->typeInfoIgnore && areaType!=typeConfig->typeInfoIgnore) { isArea=1; } else if (wayType!=typeConfig->typeInfoIgnore && areaType!=typeConfig->typeInfoIgnore) { if (nodes.size()>3 && nodes.front()==nodes.back()) { if (wayType->GetPinWay()) { isArea=-1; } else { isArea=1; } } else { isArea=-1; } } } switch (isArea) { case 1: areaStat[areaType->GetIndex()]++; if (areaType->GetIgnore()) { way.SetType(typeConfig->typeInfoIgnore, true); } else { way.SetType(areaType,true); } if (nodes.size()>3 && nodes.front()==nodes.back()) { nodes.pop_back(); } areaCount++; break; case -1: wayStat[wayType->GetIndex()]++; if (wayType->GetIgnore()) { way.SetType(typeConfig->typeInfoIgnore,false); } else { way.SetType(wayType,false); } wayCount++; break; default: if (nodes.size()>3 && nodes.front()==nodes.back()) { areaStat[typeIgnore]++; way.SetType(typeConfig->typeInfoIgnore, true); nodes.pop_back(); areaCount++; } else { wayStat[typeIgnore]++; way.SetType(typeConfig->typeInfoIgnore, false); wayCount++; } } way.SetNodes(nodes); way.Parse(progress, *typeConfig, tagMap); way.Write(*typeConfig, wayWriter); lastWayId=id; if (isCoastline) { RawCoastline coastline; coastline.SetId(way.GetId()); coastline.SetType(isCoastlineArea); coastline.SetNodes(way.GetNodes()); coastline.Write(coastlineWriter); coastlineCount++; } }