KOSMIndoorMap

element.cpp
1 /*
2  SPDX-FileCopyrightText: 2020 Volker Krause <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "element.h"
8 #include "pathutil.h"
9 
10 using namespace OSM;
11 
12 Id Element::id() const
13 {
14  switch (type()) {
15  case Type::Null:
16  return {};
17  case Type::Node:
18  return node()->id;
19  case Type::Way:
20  return way()->id;
21  case Type::Relation:
22  return relation()->id;
23  }
24 
25  Q_UNREACHABLE();
26  return {};
27 }
28 
29 Coordinate Element::center() const
30 {
31  switch (type()) {
32  case Type::Null:
33  return {};
34  case Type::Node:
35  return node()->coordinate;
36  case Type::Way:
37  return way()->bbox.center();
38  case Type::Relation:
39  return relation()->bbox.center();
40  }
41 
42  Q_UNREACHABLE();
43  return {};
44 }
45 
46 BoundingBox Element::boundingBox() const
47 {
48  switch (type()) {
49  case Type::Null:
50  return {};
51  case Type::Node:
52  return BoundingBox(node()->coordinate, node()->coordinate);
53  case Type::Way:
54  return way()->bbox;
55  case Type::Relation:
56  return relation()->bbox;
57  }
58 
59  Q_UNREACHABLE();
60  return {};
61 }
62 
63 QByteArray Element::tagValue(TagKey key) const
64 {
65  switch (type()) {
66  case Type::Null:
67  return {};
68  case Type::Node:
69  return OSM::tagValue(*node(), key);
70  case Type::Way:
71  return OSM::tagValue(*way(), key);
72  case Type::Relation:
73  return OSM::tagValue(*relation(), key);
74  }
75 
76  Q_UNREACHABLE();
77  return {};
78 }
79 
80 QByteArray Element::tagValue(const char *keyName) const
81 {
82  switch (type()) {
83  case Type::Null:
84  return {};
85  case Type::Node:
86  return OSM::tagValue(*node(), keyName);
87  case Type::Way:
88  return OSM::tagValue(*way(), keyName);
89  case Type::Relation:
90  return OSM::tagValue(*relation(), keyName);
91  }
92 
93  Q_UNREACHABLE();
94  return {};
95 }
96 
97 QByteArray Element::tagValue(const char *keyName, const QLocale &locale) const
98 {
99  switch (type()) {
100  case Type::Null:
101  return {};
102  case Type::Node:
103  return OSM::tagValue(*node(), keyName, locale);
104  case Type::Way:
105  return OSM::tagValue(*way(), keyName, locale);
106  case Type::Relation:
107  return OSM::tagValue(*relation(), keyName, locale);
108  }
109 
110  Q_UNREACHABLE();
111  return {};
112 }
113 
114 bool Element::hasTag(TagKey key) const
115 {
116  return std::binary_search(tagsBegin(), tagsEnd(), key);
117 }
118 
119 std::vector<Tag>::const_iterator OSM::Element::tagsBegin() const
120 {
121  switch (type()) {
122  case Type::Null:
123  Q_UNREACHABLE();
124  case Type::Node:
125  return node()->tags.begin();
126  case Type::Way:
127  return way()->tags.begin();
128  case Type::Relation:
129  return relation()->tags.begin();
130  }
131  Q_UNREACHABLE();
132 }
133 
134 std::vector<Tag>::const_iterator OSM::Element::tagsEnd() const
135 {
136  switch (type()) {
137  case Type::Null:
138  Q_UNREACHABLE();
139  case Type::Node:
140  return node()->tags.end();
141  case Type::Way:
142  return way()->tags.end();
143  case Type::Relation:
144  return relation()->tags.end();
145  }
146  Q_UNREACHABLE();
147 }
148 
149 QString Element::url() const
150 {
151  switch (type()) {
152  case Type::Null:
153  return {};
154  case Type::Node:
155  return node()->url();
156  case Type::Way:
157  return way()->url();
158  case Type::Relation:
159  return relation()->url();
160  }
161 
162  Q_UNREACHABLE();
163  return {};
164 }
165 
166 std::vector<const Node*> Element::outerPath(const DataSet &dataSet) const
167 {
168  switch (type()) {
169  case Type::Null:
170  return {};
171  case Type::Node:
172  return {node()};
173  case Type::Way:
174  {
175  std::vector<const Node*> nodes;
176  appendNodesFromWay(dataSet, nodes, way()->nodes.begin(), way()->nodes.end());
177  return nodes;
178  }
179  case Type::Relation:
180  {
181  if (tagValue("type") != "multipolygon") {
182  return {};
183  }
184 
185  // collect the relevant ways
186  std::vector<const Way*> ways;
187  for (const auto &member : relation()->members) {
188  if (std::strcmp(member.role().name(), "outer") != 0) {
189  continue;
190  }
191  if (auto way = dataSet.way(member.id)) {
192  ways.push_back(way);
193  }
194  }
195 
196  // stitch them together (there is no well-defined order)
197  std::vector<const Node*> nodes;
198  assemblePath(dataSet, std::move(ways), nodes);
199  return nodes;
200  }
201  }
202 
203  Q_UNREACHABLE();
204  return {};
205 }
206 
208 {
209  switch (type()) {
210  case Type::Null:
211  case Type::Node:
212  break;
213  case Type::Way:
214  way()->bbox = std::accumulate(way()->nodes.begin(), way()->nodes.end(), OSM::BoundingBox(), [&dataSet](auto bbox, auto nodeId) {
215  if (auto node = dataSet.node(nodeId)) {
216  return OSM::unite(bbox, {node->coordinate, node->coordinate});
217  }
218  return bbox;
219  });
220  break;
221  case Type::Relation:
222  relation()->bbox = {};
223  for_each_member(dataSet, *relation(), [this, &dataSet](auto mem) {
224  mem.recomputeBoundingBox(dataSet);
225  relation()->bbox = OSM::unite(relation()->bbox, mem.boundingBox());
226  });
227  break;
228  }
229 }
230 
231 
232 UniqueElement::~UniqueElement()
233 {
234  switch (m_element.type()) {
235  case OSM::Type::Null:
236  break;
237  case OSM::Type::Node:
238  delete m_element.node();
239  break;
240  case OSM::Type::Way:
241  delete m_element.way();
242  break;
243  case OSM::Type::Relation:
244  delete m_element.relation();
245  break;
246  }
247 }
248 
249 void UniqueElement::setId(Id id)
250 {
251  switch (m_element.type()) {
252  case OSM::Type::Null:
253  return;
254  case OSM::Type::Node:
255  const_cast<Node*>(m_element.node())->id = id;
256  break;
257  case OSM::Type::Way:
258  const_cast<Way*>(m_element.way())->id = id;
259  break;
260  case OSM::Type::Relation:
261  const_cast<Relation*>(m_element.relation())->id = id;
262  break;
263  }
264 }
265 
266 void UniqueElement::setTagValue(TagKey key, const QByteArray &value)
267 {
268  switch (m_element.type()) {
269  case OSM::Type::Null:
270  return;
271  case OSM::Type::Node:
272  OSM::setTagValue(*const_cast<Node*>(m_element.node()), key, value);
273  break;
274  case OSM::Type::Way:
275  OSM::setTagValue(*const_cast<Way*>(m_element.way()), key, value);
276  break;
277  case OSM::Type::Relation:
278  OSM::setTagValue(*const_cast<Relation*>(m_element.relation()), key, value);
279  break;
280  }
281 }
282 
283 void UniqueElement::removeTag(TagKey key)
284 {
285  switch (m_element.type()) {
286  case OSM::Type::Null:
287  return;
288  case OSM::Type::Node:
289  OSM::removeTag(*const_cast<Node*>(m_element.node()), key);
290  break;
291  case OSM::Type::Way:
292  OSM::removeTag(*const_cast<Way*>(m_element.way()), key);
293  break;
294  case OSM::Type::Relation:
295  OSM::removeTag(*const_cast<Relation*>(m_element.relation()), key);
296  break;
297  }
298 }
299 
301 {
302  switch (e.type()) {
303  case OSM::Type::Null:
304  return UniqueElement();
305  case OSM::Type::Node:
306  return UniqueElement(new Node(*e.node()));
307  case OSM::Type::Way:
308  return UniqueElement(new Way(*e.way()));
309  case OSM::Type::Relation:
310  return UniqueElement(new Relation(*e.relation()));
311  }
312  Q_UNREACHABLE();
313  return UniqueElement();
314 }
KOSM_EXPORT void assemblePath(const DataSet &dataSet, std::vector< const Way * > &&ways, std::vector< const Node * > &path)
Assemble a continuous path into path from the given ways.
Definition: pathutil.cpp:42
void removeTag(Elem &elem, TagKey key)
Removes a tag from the given element.
Definition: datatypes.h:441
Coordinate, stored as 1e7 * degree to avoid floating point precision issues, and offset to unsigned v...
Definition: datatypes.h:37
A reference to any of OSM::Node/OSMWay/OSMRelation.
Definition: element.h:22
A key of an OSM tag.
Definition: datatypes.h:179
void setTagValue(Elem &elem, TagKey key, const QByteArray &value)
Inserts a new tag, or updates an existing one.
Definition: datatypes.h:433
QByteArray tagValue(const Elem &elem, TagKey key)
Returns the tag value for key of elem.
Definition: datatypes.h:353
An OSM node.
Definition: datatypes.h:194
void recomputeBoundingBox(const DataSet &dataSet)
Recompute the bounding box of this element.
Definition: element.cpp:207
int64_t Id
OSM element identifier.
Definition: datatypes.h:27
static void appendNodesFromWay(const DataSet &dataSet, std::vector< const Node * > &nodes, const Iter &nodeBegin, const Iter &nodeEnd)
Appends the nodes referenced by nodesBegin and into nodes.
Definition: pathutil.h:24
An OSM way.
Definition: datatypes.h:206
std::vector< const Node * > outerPath(const DataSet &dataSet) const
Returns all nodes belonging to the outer path of this element.
Definition: element.cpp:166
KOSM_EXPORT UniqueElement copy_element(Element e)
Creates a copy of element.
Definition: element.cpp:300
An OSM relation.
Definition: datatypes.h:270
A set of nodes, ways and relations.
Definition: datatypes.h:283
A std::unique_ptr-like object for OSM element types.
Definition: element.h:98
const Way * way(Id id) const
Find a way by its id.
Definition: datatypes.cpp:46
Bounding box, ie.
Definition: datatypes.h:95
Low-level types and functions to work with raw OSM data as efficiently as possible.
bool hasTag(TagKey key) const
Returns true if this element has a tag with key key.
Definition: element.cpp:114
const Node * node(Id id) const
Find a node by its id.
Definition: datatypes.cpp:37
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 16 2021 23:05:32 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.