Skip to content

Commit c42e247

Browse files
deniskoronchikPatrick Niklaus
authored andcommitted
Work on relation extract refactoring to support recursive relations (superrelations)
1 parent 7851de9 commit c42e247

File tree

6 files changed

+289
-120
lines changed

6 files changed

+289
-120
lines changed

include/extractor/extraction_relation.hpp

Lines changed: 163 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef EXTRACTION_RELATION_HPP
22
#define EXTRACTION_RELATION_HPP
33

4+
#include "util/exception.hpp"
5+
46
#include <osmium/osm/relation.hpp>
57

68
#include <boost/assert.hpp>
@@ -16,63 +18,197 @@ namespace extractor
1618

1719
struct ExtractionRelation
1820
{
19-
using AttributesMap = std::unordered_map<std::string, std::string>;
20-
using OsmIDTyped = std::pair<osmium::object_id_type, osmium::item_type>;
21-
22-
struct OsmIDTypedHash
21+
class OsmIDTyped
2322
{
24-
std::size_t operator()(const OsmIDTyped &id) const
23+
public:
24+
OsmIDTyped(osmium::object_id_type _id, osmium::item_type _type)
25+
: id(_id), type(_type)
2526
{
26-
return id.first ^ (static_cast<std::uint64_t>(id.second) << 56);
2727
}
28+
29+
std::uint64_t GetID() const { return std::uint64_t(id); }
30+
osmium::item_type GetType() const { return type; }
31+
32+
std::uint64_t Hash() const
33+
{
34+
return id ^ (static_cast<std::uint64_t>(type) << 56);
35+
}
36+
37+
private:
38+
osmium::object_id_type id;
39+
osmium::item_type type;
2840
};
2941

30-
ExtractionRelation() : is_restriction(false) {}
42+
using AttributesList = std::vector<std::pair<std::string, std::string>>;
43+
using MembersRolesList = std::vector<std::pair<std::uint64_t, std::string>>;
3144

32-
void clear()
45+
explicit ExtractionRelation(const OsmIDTyped & _id)
46+
: id(_id)
3347
{
34-
is_restriction = false;
35-
values.clear();
3648
}
3749

38-
bool IsRestriction() const { return is_restriction; }
50+
void Clear()
51+
{
52+
attributes.clear();
53+
members_role.clear();
54+
}
55+
56+
const char * GetAttr(const std::string & attr) const
57+
{
58+
auto it = std::lower_bound(
59+
attributes.begin(),
60+
attributes.end(),
61+
std::make_pair(attr, std::string()));
62+
63+
if (it != attributes.end() && (*it).first == attr)
64+
return (*it).second.c_str();
65+
66+
return nullptr;
67+
}
3968

40-
AttributesMap &GetMember(const osmium::RelationMember &member)
69+
void Prepare()
4170
{
42-
return values[OsmIDTyped(member.ref(), member.type())];
71+
std::sort(attributes.begin(), attributes.end());
72+
std::sort(members_role.begin(), members_role.end());
4373
}
4474

45-
bool is_restriction;
46-
std::unordered_map<OsmIDTyped, AttributesMap, OsmIDTypedHash> values;
75+
void AddMember(const OsmIDTyped & member_id, const char * role)
76+
{
77+
members_role.emplace_back(std::make_pair(member_id.Hash(), std::string(role)));
78+
}
79+
80+
const char * GetRole(const OsmIDTyped & member_id) const
81+
{
82+
const auto hash = member_id.Hash();
83+
auto it = std::lower_bound(
84+
members_role.begin(),
85+
members_role.end(),
86+
std::make_pair(hash, std::string()));
87+
88+
if (it != members_role.end() && (*it).first == hash)
89+
return (*it).second.c_str();
90+
91+
return nullptr;
92+
}
93+
94+
OsmIDTyped id;
95+
AttributesList attributes;
96+
MembersRolesList members_role;
4797
};
4898

4999
// It contains data of all parsed relations for each node/way element
50100
class ExtractionRelationContainer
51101
{
52102
public:
53-
using AttributesMap = ExtractionRelation::AttributesMap;
103+
using AttributesMap = ExtractionRelation::AttributesList;
54104
using OsmIDTyped = ExtractionRelation::OsmIDTyped;
55105
using RelationList = std::vector<AttributesMap>;
106+
using RelationIDList = std::vector<ExtractionRelation::OsmIDTyped>;
107+
using RelationRefMap = std::unordered_map<std::uint64_t, RelationIDList>;
56108

57-
void AddRelation(const ExtractionRelation &rel)
109+
void AddRelation(ExtractionRelation && rel)
58110
{
59-
BOOST_ASSERT(!rel.is_restriction);
60-
for (auto it : rel.values)
61-
data[it.first].push_back(it.second);
111+
rel.Prepare();
112+
113+
BOOST_ASSERT(relations_data.find(rel.id.GetID()) == relations_data.end());
114+
relations_data.insert(std::make_pair(rel.id.GetID(), std::move(rel)));
62115
}
63116

64-
const RelationList &Get(const OsmIDTyped &id) const
117+
void AddRelationMember(const OsmIDTyped & relation_id, const OsmIDTyped & member_id)
65118
{
66-
const auto it = data.find(id);
67-
if (it != data.end())
68-
return it->second;
119+
switch (member_id.GetType())
120+
{
121+
case osmium::item_type::node:
122+
node_refs[member_id.GetID()].push_back(relation_id);
123+
break;
69124

70-
static RelationList empty;
71-
return empty;
125+
case osmium::item_type::way:
126+
way_refs[member_id.GetID()].push_back(relation_id);
127+
break;
128+
129+
case osmium::item_type::relation:
130+
rel_refs[member_id.GetID()].push_back(relation_id);
131+
break;
132+
133+
default:
134+
break;
135+
};
136+
}
137+
138+
void Merge(ExtractionRelationContainer && other)
139+
{
140+
for (auto it : other.relations_data)
141+
{
142+
const auto res = relations_data.insert(std::make_pair(it.first, std::move(it.second)));
143+
BOOST_ASSERT(res.second);
144+
(void)res; // prevent unused warning in release
145+
}
146+
147+
auto MergeRefMap = [&](RelationRefMap & source, RelationRefMap & target)
148+
{
149+
for (auto it : source)
150+
{
151+
auto & v = target[it.first];
152+
v.insert(v.end(), it.second.begin(), it.second.end());
153+
}
154+
};
155+
156+
MergeRefMap(other.way_refs, way_refs);
157+
MergeRefMap(other.node_refs, node_refs);
158+
MergeRefMap(other.rel_refs, rel_refs);
159+
}
160+
161+
std::size_t GetRelationsNum() const
162+
{
163+
return relations_data.size();
164+
}
165+
166+
const RelationIDList & GetRelations(const OsmIDTyped & member_id) const
167+
{
168+
auto getFromMap = [this](std::uint64_t id, const RelationRefMap & map) -> const RelationIDList &
169+
{
170+
auto it = map.find(id);
171+
if (it != map.end())
172+
return it->second;
173+
174+
return empty_rel_list;
175+
};
176+
177+
switch (member_id.GetType())
178+
{
179+
case osmium::item_type::node:
180+
return getFromMap(member_id.GetID(), node_refs);
181+
182+
case osmium::item_type::way:
183+
return getFromMap(member_id.GetID(), way_refs);
184+
185+
case osmium::item_type::relation:
186+
return getFromMap(member_id.GetID(), rel_refs);
187+
188+
default:
189+
break;
190+
}
191+
192+
return empty_rel_list;
193+
}
194+
195+
const ExtractionRelation & GetRelationData(const ExtractionRelation::OsmIDTyped & rel_id) const
196+
{
197+
auto it = relations_data.find(rel_id.GetID());
198+
if (it == relations_data.end())
199+
throw osrm::util::exception("Can't find relation data for " + std::to_string(rel_id.GetID()));
200+
201+
return it->second;
72202
}
73203

74204
private:
75-
std::unordered_map<OsmIDTyped, RelationList, ExtractionRelation::OsmIDTypedHash> data;
205+
RelationIDList empty_rel_list;
206+
std::unordered_map<std::uint64_t, ExtractionRelation> relations_data;
207+
208+
// each map contains list of relation id's, that has keyed id as a member
209+
RelationRefMap way_refs;
210+
RelationRefMap node_refs;
211+
RelationRefMap rel_refs;
76212
};
77213

78214
} // namespace extractor

include/extractor/scripting_environment.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ class RestrictionParser;
3737
class ExtractionRelationContainer;
3838
struct ExtractionNode;
3939
struct ExtractionWay;
40-
struct ExtractionRelation;
4140
struct ExtractionTurn;
4241
struct ExtractionSegment;
4342

@@ -59,6 +58,7 @@ class ScriptingEnvironment
5958
virtual std::vector<std::string> GetClassNames() = 0;
6059
virtual std::vector<std::string> GetNameSuffixList() = 0;
6160
virtual std::vector<std::string> GetRestrictions() = 0;
61+
virtual std::vector<std::string> GetRelations() = 0;
6262
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
6363
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
6464

@@ -68,7 +68,6 @@ class ScriptingEnvironment
6868
const ExtractionRelationContainer &relations,
6969
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
7070
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
71-
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
7271
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
7372

7473
virtual bool HasLocationDependentData() const = 0;

include/extractor/scripting_environment_lua.hpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,10 @@ struct LuaScriptingContext final
2929

3030
void ProcessNode(const osmium::Node &,
3131
ExtractionNode &result,
32-
const ExtractionRelationContainer::RelationList &relations);
32+
const ExtractionRelationContainer &relations);
3333
void ProcessWay(const osmium::Way &,
3434
ExtractionWay &result,
35-
const ExtractionRelationContainer::RelationList &relations);
36-
void ProcessRelation(const osmium::Relation &, ExtractionRelation &result);
35+
const ExtractionRelationContainer &relations);
3736

3837
ProfileProperties properties;
3938
RasterContainer raster_sources;
@@ -42,13 +41,11 @@ struct LuaScriptingContext final
4241
bool has_turn_penalty_function;
4342
bool has_node_function;
4443
bool has_way_function;
45-
bool has_relation_function;
4644
bool has_segment_function;
4745

4846
sol::function turn_function;
4947
sol::function way_function;
5048
sol::function node_function;
51-
sol::function relation_function;
5249
sol::function segment_function;
5350

5451
int api_version;
@@ -84,6 +81,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
8481
std::vector<std::string> GetNameSuffixList() override;
8582
std::vector<std::string> GetClassNames() override;
8683
std::vector<std::string> GetRestrictions() override;
84+
std::vector<std::string> GetRelations() override;
8785
void ProcessTurn(ExtractionTurn &turn) override;
8886
void ProcessSegment(ExtractionSegment &segment) override;
8987

@@ -93,7 +91,6 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
9391
const ExtractionRelationContainer &relations,
9492
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
9593
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
96-
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
9794
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
9895

9996
bool HasLocationDependentData() const override { return !location_dependent_data.empty(); }

profiles/car.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ function setup()
281281
['za:urban'] = 60,
282282
['za:rural'] = 100,
283283
["none"] = 140
284+
},
285+
286+
relation_types = Sequence {
287+
"route"
284288
}
285289
}
286290
end

0 commit comments

Comments
 (0)