KOSMIndoorMap

element.h
1/*
2 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#ifndef OSM_ELEMENT_H
8#define OSM_ELEMENT_H
9
10#include "kosm_export.h"
11
12#include "datatypes.h"
13#include "internal.h"
14
15#include <cstdint>
16
17namespace OSM {
18class Languages;
19
20/** A reference to any of OSM::Node/OSM::Way/OSM::Relation.
21 * Lifetime of the referenced object needs to extend beyond the lifetime of this.
22 */
23class KOSM_EXPORT Element
24{
25public:
26 inline constexpr Element() : m_elem(nullptr, static_cast<uint8_t>(Type::Null)) {}
27 inline Element(const Node *node) : m_elem(node, static_cast<uint8_t>(Type::Node)) {}
28 inline Element(const Way *way) : m_elem(way, static_cast<uint8_t>(Type::Way)) {}
29 inline Element(const Relation *relation) : m_elem(relation, static_cast<uint8_t>(Type::Relation)) {}
30
31 [[nodiscard]] inline bool operator==(Element other) const { return m_elem == other.m_elem; }
32 [[nodiscard]] inline bool operator!=(Element other) const { return m_elem != other.m_elem; }
33 [[nodiscard]] inline bool operator<(Element other) const { return m_elem < other.m_elem; }
34 [[nodiscard]] explicit inline operator bool() const { return type() != OSM::Type::Null; }
35
36 [[nodiscard]] inline Type type() const { return static_cast<Type>(m_elem.tag()); }
37 [[nodiscard]] inline const Node* node() const { return static_cast<const Node*>(m_elem.get()); }
38 [[nodiscard]] inline const Way* way() const { return static_cast<const Way*>(m_elem.get()); }
39 [[nodiscard]] inline const Relation* relation() const { return static_cast<const Relation*>(m_elem.get()); }
40 [[nodiscard]] Id id() const;
41
42 [[nodiscard]] Coordinate center() const;
43 [[nodiscard]] BoundingBox boundingBox() const;
44 [[nodiscard]] QByteArray tagValue(TagKey key) const;
45 [[nodiscard]] QByteArray tagValue(const char *keyName) const;
46 [[nodiscard]] QByteArray tagValue(const OSM::Languages &languages, const char *keyName) const;
47 /** Returns the value of the first non-empty tag.
48 * Both OSM::TagKey (fast) and const char* (slow) keys are accepted.
49 */
50 template <typename K, typename ...Args> [[nodiscard]] QByteArray tagValue(K key, Args... args) const;
51 template <typename K, typename ...Args> [[nodiscard]] QByteArray tagValue(const OSM::Languages &languages, K key, Args... args) const;
52 /** Returns whether or not this element has any tags set. */
53 [[nodiscard]] inline bool hasTags() const { return std::distance(tagsBegin(), tagsEnd()) > 0; }
54 /** Returns @c true if this element has a tag with key @p key. */
55 [[nodiscard]] bool hasTag(TagKey key) const;
56
57 [[nodiscard]] std::vector<Tag>::const_iterator tagsBegin() const;
58 [[nodiscard]] std::vector<Tag>::const_iterator tagsEnd() const;
59 [[nodiscard]] QString url() const;
60
61 /** Returns all nodes belonging to the outer path of this element.
62 * In the simplest case that's a single closed polygon, but it can also be a sequence of multiple
63 * closed loop polygons, or a polyline.
64 */
65 [[nodiscard]] std::vector<const Node*> outerPath(const DataSet &dataSet) const;
66
67 /** Recompute the bounding box of this element.
68 * We usually assume those to be provided by Overpass/osmconvert, but there seem to be cases where those
69 * aren't reliable.
70 */
71 void recomputeBoundingBox(const DataSet &dataSet);
72
73private:
75};
76
77template <typename K, typename ...Args>
78QByteArray Element::tagValue(K k, Args... args) const
79{
80 const auto v = tagValue(k);
81 if (!v.isEmpty()) {
82 return v;
83 }
84 return tagValue(args...);
85}
86
87template <typename K, typename ...Args>
88QByteArray Element::tagValue(const OSM::Languages &languages, K key, Args... args) const
89{
90 const auto v = tagValue(languages, key);
91 if (!v.isEmpty()) {
92 return v;
93 }
94 return tagValue(languages, args...);
95}
96
97
98/** A std::unique_ptr-like object for OSM element types. */
99class KOSM_EXPORT UniqueElement
100{
101public:
102 explicit inline UniqueElement() = default;
103 explicit inline UniqueElement(Node *node) : m_element(node) {}
104 explicit inline UniqueElement(Way *way) : m_element(way) {}
105 explicit inline UniqueElement(Relation *rel) : m_element(rel) {}
106
107 UniqueElement(const UniqueElement&) = delete;
108 inline UniqueElement(UniqueElement &&other) noexcept {
109 std::swap(m_element, other.m_element);
110 }
111
113
114 UniqueElement& operator=(const UniqueElement&) = delete;
115 UniqueElement& operator=(UniqueElement &&other) noexcept {
116 std::swap(m_element, other.m_element);
117 return *this;
118 }
119
120 [[nodiscard]] explicit inline operator bool() const { return m_element.type() != OSM::Type::Null; }
121
122 [[nodiscard]] constexpr inline Element element() const { return m_element; }
123 [[nodiscard]] constexpr inline operator Element() const { return m_element; }
124
125 [[nodiscard]] inline Node* node() const { return const_cast<Node*>(m_element.node()); }
126 [[nodiscard]] inline Way* way() const { return const_cast<Way*>(m_element.way()); }
127 [[nodiscard]] inline Relation* relation() const { return const_cast<Relation*>(m_element.relation()); }
128
129 void setId(Id id);
130 void setTagValue(TagKey key, QByteArray &&value);
131 void removeTag(TagKey key);
132
133private:
134 Element m_element;
135};
136
137/** Creates a copy of @p element. */
138KOSM_EXPORT UniqueElement copy_element(Element e);
139
140/** Utility function similar to SQL COALESCE for OSM::Element, ie. this returns the first non-null element passed as argument. */
141[[nodiscard]] constexpr Element coalesce(Element e) { return e; }
142template <typename ...Args>
143[[nodiscard]] constexpr Element coalesce(Element e, Args... args) { return e ? e : coalesce(args...); }
144
145/** Lookup element of given @p type and @p id in @p dataSet. */
146inline Element lookupElement(const DataSet &dataSet, OSM::Type type, OSM::Id id)
147{
148 switch (type) {
149 case Type::Null:
150 break;
151 case Type::Node:
152 if (auto node = dataSet.node(id)) {
153 return {node};
154 }
155 break;
156 case Type::Way:
157 if (auto way = dataSet.way(id)) {
158 return {way};
159 }
160 break;
161 case Type::Relation:
162 if (auto rel = dataSet.relation(id)) {
163 return {rel};
164 }
165 break;
166 }
167 return {};
168}
169
170enum ForeachFlag : uint8_t {
171 IncludeRelations = 1,
172 IncludeWays = 2,
173 IncludeNodes = 4,
174 IterateAll = IncludeRelations | IncludeWays | IncludeNodes,
175};
176
177template <typename Func>
178inline void for_each(const DataSet &dataSet, Func func, uint8_t flags = IterateAll)
179{
180 if (flags & IncludeRelations) {
181 for (const auto &rel : dataSet.relations) {
182 func(Element(&rel));
183 }
184 }
185 if (flags & IncludeWays) {
186 for (const auto &way : dataSet.ways) {
187 func(Element(&way));
188 }
189 }
190 if (flags & IncludeNodes) {
191 for (const auto &node : dataSet.nodes) {
192 func(Element(&node));
193 }
194 }
195}
196
197template <typename Func>
198inline void for_each_node(const DataSet &dataSet, const Way &way, Func func)
199{
200 for (auto nodeId : way.nodes) {
201 if (auto node = dataSet.node(nodeId)) {
202 func(*node);
203 }
204 }
205}
206
207template <typename Func>
208inline void for_each_member(const DataSet &dataSet, const Relation &rel, Func func)
209{
210 for (const auto &mem : rel.members) {
211 if (auto elem = lookupElement(dataSet, mem.type(), mem.id); elem.type() != OSM::Type::Null) {
212 func(elem);
213 }
214 }
215}
216
217}
218
219template<>
220struct std::hash<OSM::Element>
221{
222 std::size_t operator()(OSM::Element e) const noexcept
223 {
224 std::size_t h1 = std::hash<OSM::Id>{}(e.id());
225 std::size_t h2 = std::hash<int>{}(qToUnderlying(e.type()));
226 return h1 ^ (h2 << 1);
227 }
228};
229
230Q_DECLARE_METATYPE(OSM::Element)
231
232#endif // OSM_ELEMENT_H
Bounding box, ie.
Definition datatypes.h:95
Coordinate, stored as 1e7 * degree to avoid floating point precision issues, and offset to unsigned v...
Definition datatypes.h:37
A set of nodes, ways and relations.
Definition datatypes.h:343
const Relation * relation(Id id) const
Find a relation by its id.
Definition datatypes.cpp:75
const Way * way(Id id) const
Find a way by its id.
Definition datatypes.cpp:57
const Node * node(Id id) const
Find a node by its id.
Definition datatypes.cpp:48
A reference to any of OSM::Node/OSM::Way/OSM::Relation.
Definition element.h:24
bool hasTags() const
Returns whether or not this element has any tags set.
Definition element.h:53
Pointer with the lower bits used for compact flag storage.
Definition internal.h:17
Languages in preference order to consider when looking up translated tag values.
Definition languages.h:25
An OSM node.
Definition datatypes.h:204
An OSM relation.
Definition datatypes.h:314
A key of an OSM tag.
Definition datatypes.h:179
A std::unique_ptr-like object for OSM element types.
Definition element.h:100
An OSM way.
Definition datatypes.h:231
Low-level types and functions to work with raw OSM data as efficiently as possible.
void setTagValue(Elem &elem, TagKey key, QByteArray &&value)
Inserts a new tag, or updates an existing one.
Definition datatypes.h:487
constexpr Element coalesce(Element e)
Utility function similar to SQL COALESCE for OSM::Element, ie.
Definition element.h:141
int64_t Id
OSM element identifier.
Definition datatypes.h:30
Element lookupElement(const DataSet &dataSet, OSM::Type type, OSM::Id id)
Lookup element of given type and id in dataSet.
Definition element.h:146
KOSM_EXPORT UniqueElement copy_element(Element e)
Creates a copy of element.
Definition element.cpp:300
QByteArray tagValue(const Elem &elem, TagKey key)
Returns the tag value for key of elem.
Definition datatypes.h:413
Type
Element type.
Definition datatypes.h:262
void removeTag(Elem &elem, TagKey key)
Removes a tag from the given element.
Definition datatypes.h:494
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jun 14 2024 11:56:17 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.