Work on relation extract refactoring to support recursive relations (superrelations)
This commit is contained in:
committed by
Patrick Niklaus
parent
7851de9af8
commit
c42e247d87
@@ -1,6 +1,8 @@
|
||||
#ifndef EXTRACTION_RELATION_HPP
|
||||
#define EXTRACTION_RELATION_HPP
|
||||
|
||||
#include "util/exception.hpp"
|
||||
|
||||
#include <osmium/osm/relation.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -16,63 +18,197 @@ namespace extractor
|
||||
|
||||
struct ExtractionRelation
|
||||
{
|
||||
using AttributesMap = std::unordered_map<std::string, std::string>;
|
||||
using OsmIDTyped = std::pair<osmium::object_id_type, osmium::item_type>;
|
||||
|
||||
struct OsmIDTypedHash
|
||||
class OsmIDTyped
|
||||
{
|
||||
std::size_t operator()(const OsmIDTyped &id) const
|
||||
public:
|
||||
OsmIDTyped(osmium::object_id_type _id, osmium::item_type _type)
|
||||
: id(_id), type(_type)
|
||||
{
|
||||
return id.first ^ (static_cast<std::uint64_t>(id.second) << 56);
|
||||
}
|
||||
|
||||
std::uint64_t GetID() const { return std::uint64_t(id); }
|
||||
osmium::item_type GetType() const { return type; }
|
||||
|
||||
std::uint64_t Hash() const
|
||||
{
|
||||
return id ^ (static_cast<std::uint64_t>(type) << 56);
|
||||
}
|
||||
|
||||
private:
|
||||
osmium::object_id_type id;
|
||||
osmium::item_type type;
|
||||
};
|
||||
|
||||
ExtractionRelation() : is_restriction(false) {}
|
||||
using AttributesList = std::vector<std::pair<std::string, std::string>>;
|
||||
using MembersRolesList = std::vector<std::pair<std::uint64_t, std::string>>;
|
||||
|
||||
void clear()
|
||||
explicit ExtractionRelation(const OsmIDTyped & _id)
|
||||
: id(_id)
|
||||
{
|
||||
is_restriction = false;
|
||||
values.clear();
|
||||
}
|
||||
|
||||
bool IsRestriction() const { return is_restriction; }
|
||||
|
||||
AttributesMap &GetMember(const osmium::RelationMember &member)
|
||||
void Clear()
|
||||
{
|
||||
return values[OsmIDTyped(member.ref(), member.type())];
|
||||
attributes.clear();
|
||||
members_role.clear();
|
||||
}
|
||||
|
||||
bool is_restriction;
|
||||
std::unordered_map<OsmIDTyped, AttributesMap, OsmIDTypedHash> values;
|
||||
const char * GetAttr(const std::string & attr) const
|
||||
{
|
||||
auto it = std::lower_bound(
|
||||
attributes.begin(),
|
||||
attributes.end(),
|
||||
std::make_pair(attr, std::string()));
|
||||
|
||||
if (it != attributes.end() && (*it).first == attr)
|
||||
return (*it).second.c_str();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Prepare()
|
||||
{
|
||||
std::sort(attributes.begin(), attributes.end());
|
||||
std::sort(members_role.begin(), members_role.end());
|
||||
}
|
||||
|
||||
void AddMember(const OsmIDTyped & member_id, const char * role)
|
||||
{
|
||||
members_role.emplace_back(std::make_pair(member_id.Hash(), std::string(role)));
|
||||
}
|
||||
|
||||
const char * GetRole(const OsmIDTyped & member_id) const
|
||||
{
|
||||
const auto hash = member_id.Hash();
|
||||
auto it = std::lower_bound(
|
||||
members_role.begin(),
|
||||
members_role.end(),
|
||||
std::make_pair(hash, std::string()));
|
||||
|
||||
if (it != members_role.end() && (*it).first == hash)
|
||||
return (*it).second.c_str();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OsmIDTyped id;
|
||||
AttributesList attributes;
|
||||
MembersRolesList members_role;
|
||||
};
|
||||
|
||||
// It contains data of all parsed relations for each node/way element
|
||||
class ExtractionRelationContainer
|
||||
{
|
||||
public:
|
||||
using AttributesMap = ExtractionRelation::AttributesMap;
|
||||
using AttributesMap = ExtractionRelation::AttributesList;
|
||||
using OsmIDTyped = ExtractionRelation::OsmIDTyped;
|
||||
using RelationList = std::vector<AttributesMap>;
|
||||
using RelationIDList = std::vector<ExtractionRelation::OsmIDTyped>;
|
||||
using RelationRefMap = std::unordered_map<std::uint64_t, RelationIDList>;
|
||||
|
||||
void AddRelation(const ExtractionRelation &rel)
|
||||
void AddRelation(ExtractionRelation && rel)
|
||||
{
|
||||
BOOST_ASSERT(!rel.is_restriction);
|
||||
for (auto it : rel.values)
|
||||
data[it.first].push_back(it.second);
|
||||
rel.Prepare();
|
||||
|
||||
BOOST_ASSERT(relations_data.find(rel.id.GetID()) == relations_data.end());
|
||||
relations_data.insert(std::make_pair(rel.id.GetID(), std::move(rel)));
|
||||
}
|
||||
|
||||
const RelationList &Get(const OsmIDTyped &id) const
|
||||
void AddRelationMember(const OsmIDTyped & relation_id, const OsmIDTyped & member_id)
|
||||
{
|
||||
const auto it = data.find(id);
|
||||
if (it != data.end())
|
||||
return it->second;
|
||||
switch (member_id.GetType())
|
||||
{
|
||||
case osmium::item_type::node:
|
||||
node_refs[member_id.GetID()].push_back(relation_id);
|
||||
break;
|
||||
|
||||
static RelationList empty;
|
||||
return empty;
|
||||
case osmium::item_type::way:
|
||||
way_refs[member_id.GetID()].push_back(relation_id);
|
||||
break;
|
||||
|
||||
case osmium::item_type::relation:
|
||||
rel_refs[member_id.GetID()].push_back(relation_id);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
void Merge(ExtractionRelationContainer && other)
|
||||
{
|
||||
for (auto it : other.relations_data)
|
||||
{
|
||||
const auto res = relations_data.insert(std::make_pair(it.first, std::move(it.second)));
|
||||
BOOST_ASSERT(res.second);
|
||||
(void)res; // prevent unused warning in release
|
||||
}
|
||||
|
||||
auto MergeRefMap = [&](RelationRefMap & source, RelationRefMap & target)
|
||||
{
|
||||
for (auto it : source)
|
||||
{
|
||||
auto & v = target[it.first];
|
||||
v.insert(v.end(), it.second.begin(), it.second.end());
|
||||
}
|
||||
};
|
||||
|
||||
MergeRefMap(other.way_refs, way_refs);
|
||||
MergeRefMap(other.node_refs, node_refs);
|
||||
MergeRefMap(other.rel_refs, rel_refs);
|
||||
}
|
||||
|
||||
std::size_t GetRelationsNum() const
|
||||
{
|
||||
return relations_data.size();
|
||||
}
|
||||
|
||||
const RelationIDList & GetRelations(const OsmIDTyped & member_id) const
|
||||
{
|
||||
auto getFromMap = [this](std::uint64_t id, const RelationRefMap & map) -> const RelationIDList &
|
||||
{
|
||||
auto it = map.find(id);
|
||||
if (it != map.end())
|
||||
return it->second;
|
||||
|
||||
return empty_rel_list;
|
||||
};
|
||||
|
||||
switch (member_id.GetType())
|
||||
{
|
||||
case osmium::item_type::node:
|
||||
return getFromMap(member_id.GetID(), node_refs);
|
||||
|
||||
case osmium::item_type::way:
|
||||
return getFromMap(member_id.GetID(), way_refs);
|
||||
|
||||
case osmium::item_type::relation:
|
||||
return getFromMap(member_id.GetID(), rel_refs);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return empty_rel_list;
|
||||
}
|
||||
|
||||
const ExtractionRelation & GetRelationData(const ExtractionRelation::OsmIDTyped & rel_id) const
|
||||
{
|
||||
auto it = relations_data.find(rel_id.GetID());
|
||||
if (it == relations_data.end())
|
||||
throw osrm::util::exception("Can't find relation data for " + std::to_string(rel_id.GetID()));
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<OsmIDTyped, RelationList, ExtractionRelation::OsmIDTypedHash> data;
|
||||
RelationIDList empty_rel_list;
|
||||
std::unordered_map<std::uint64_t, ExtractionRelation> relations_data;
|
||||
|
||||
// each map contains list of relation id's, that has keyed id as a member
|
||||
RelationRefMap way_refs;
|
||||
RelationRefMap node_refs;
|
||||
RelationRefMap rel_refs;
|
||||
};
|
||||
|
||||
} // namespace extractor
|
||||
|
||||
@@ -37,7 +37,6 @@ class RestrictionParser;
|
||||
class ExtractionRelationContainer;
|
||||
struct ExtractionNode;
|
||||
struct ExtractionWay;
|
||||
struct ExtractionRelation;
|
||||
struct ExtractionTurn;
|
||||
struct ExtractionSegment;
|
||||
|
||||
@@ -59,6 +58,7 @@ class ScriptingEnvironment
|
||||
virtual std::vector<std::string> GetClassNames() = 0;
|
||||
virtual std::vector<std::string> GetNameSuffixList() = 0;
|
||||
virtual std::vector<std::string> GetRestrictions() = 0;
|
||||
virtual std::vector<std::string> GetRelations() = 0;
|
||||
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
|
||||
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
|
||||
|
||||
@@ -68,7 +68,6 @@ class ScriptingEnvironment
|
||||
const ExtractionRelationContainer &relations,
|
||||
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
|
||||
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
|
||||
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
|
||||
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
|
||||
|
||||
virtual bool HasLocationDependentData() const = 0;
|
||||
|
||||
@@ -29,11 +29,10 @@ struct LuaScriptingContext final
|
||||
|
||||
void ProcessNode(const osmium::Node &,
|
||||
ExtractionNode &result,
|
||||
const ExtractionRelationContainer::RelationList &relations);
|
||||
const ExtractionRelationContainer &relations);
|
||||
void ProcessWay(const osmium::Way &,
|
||||
ExtractionWay &result,
|
||||
const ExtractionRelationContainer::RelationList &relations);
|
||||
void ProcessRelation(const osmium::Relation &, ExtractionRelation &result);
|
||||
const ExtractionRelationContainer &relations);
|
||||
|
||||
ProfileProperties properties;
|
||||
RasterContainer raster_sources;
|
||||
@@ -42,13 +41,11 @@ struct LuaScriptingContext final
|
||||
bool has_turn_penalty_function;
|
||||
bool has_node_function;
|
||||
bool has_way_function;
|
||||
bool has_relation_function;
|
||||
bool has_segment_function;
|
||||
|
||||
sol::function turn_function;
|
||||
sol::function way_function;
|
||||
sol::function node_function;
|
||||
sol::function relation_function;
|
||||
sol::function segment_function;
|
||||
|
||||
int api_version;
|
||||
@@ -84,6 +81,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
|
||||
std::vector<std::string> GetNameSuffixList() override;
|
||||
std::vector<std::string> GetClassNames() override;
|
||||
std::vector<std::string> GetRestrictions() override;
|
||||
std::vector<std::string> GetRelations() override;
|
||||
void ProcessTurn(ExtractionTurn &turn) override;
|
||||
void ProcessSegment(ExtractionSegment &segment) override;
|
||||
|
||||
@@ -93,7 +91,6 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
|
||||
const ExtractionRelationContainer &relations,
|
||||
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
|
||||
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
|
||||
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
|
||||
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
|
||||
|
||||
bool HasLocationDependentData() const override { return !location_dependent_data.empty(); }
|
||||
|
||||
Reference in New Issue
Block a user