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
145enum ForeachFlag : uint8_t {
146 IncludeRelations = 1,
147 IncludeWays = 2,
148 IncludeNodes = 4,
149 IterateAll = IncludeRelations | IncludeWays | IncludeNodes,
150};
151
152template <typename Func>
153inline void for_each(const DataSet &dataSet, Func func, uint8_t flags = IterateAll)
154{
155 if (flags & IncludeRelations) {
156 for (const auto &rel : dataSet.relations) {
157 func(Element(&rel));
158 }
159 }
160 if (flags & IncludeWays) {
161 for (const auto &way : dataSet.ways) {
162 func(Element(&way));
163 }
164 }
165 if (flags & IncludeNodes) {
166 for (const auto &node : dataSet.nodes) {
167 func(Element(&node));
168 }
169 }
170}
171
172template <typename Func>
173inline void for_each_node(const DataSet &dataSet, const Way &way, Func func)
174{
175 for (auto nodeId : way.nodes) {
176 if (auto node = dataSet.node(nodeId)) {
177 func(*node);
178 }
179 }
180}
181
182template <typename Func>
183inline void for_each_member(const DataSet &dataSet, const Relation &rel, Func func)
184{
185 for (const auto &mem : rel.members) {
186 switch (mem.type()) {
187 case Type::Null:
188 break;
189 case Type::Node:
190 if (auto node = dataSet.node(mem.id)) {
191 func(Element(node));
192 }
193 break;
194 case Type::Way:
195 if (auto way = dataSet.way(mem.id)) {
196 func(Element(way));
197 }
198 break;
199 case Type::Relation:
200 if (auto rel = dataSet.relation(mem.id)) {
201 func(Element(rel));
202 }
203 break;
204 }
205 }
206}
207
208}
209
210template<>
211struct std::hash<OSM::Element>
212{
213 std::size_t operator()(OSM::Element e) const noexcept
214 {
215 std::size_t h1 = std::hash<OSM::Id>{}(e.id());
216 std::size_t h2 = std::hash<int>{}(qToUnderlying(e.type()));
217 return h1 ^ (h2 << 1);
218 }
219};
220
221Q_DECLARE_METATYPE(OSM::Element)
222
223#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:340
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:311
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:484
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
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:410
Type
Element type.
Definition datatypes.h:262
void removeTag(Elem &elem, TagKey key)
Removes a tag from the given element.
Definition datatypes.h:491
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:03 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.