10#include "kosm_export.h"
13#include "stringpool.h"
40 explicit constexpr Coordinate(
double lat,
double lon)
41 : latitude((lat + 90.0) * 10'000'000)
42 , longitude((lon + 180.0) * 10'000'000)
44 explicit constexpr Coordinate(uint32_t lat, uint32_t lon)
54 for (
int i = 0; i < 32; ++i) {
55 latitude += (
z & (1ull << (i * 2))) >> i;
56 longitude += (
z & (1ull << (1 + i * 2))) >> (i + 1);
60 [[nodiscard]]
constexpr inline bool isValid()
const
62 return latitude != std::numeric_limits<uint32_t>::max() && longitude != std::numeric_limits<uint32_t>::max();
64 [[nodiscard]]
constexpr inline bool operator==(
Coordinate other)
const
70 [[nodiscard]]
constexpr inline uint64_t
z()
const
73 for (
int i = 0; i < 32; ++i) {
74 z += ((uint64_t)latitude & (1 << i)) << i;
75 z += ((uint64_t)longitude & (1 << i)) << (i + 1);
80 [[nodiscard]]
constexpr inline double latF()
const
82 return (latitude / 10'000'000.0) - 90.0;
84 [[nodiscard]]
constexpr inline double lonF()
const
86 return (longitude / 10'000'000.0) - 180.0;
89 uint32_t latitude = std::numeric_limits<uint32_t>::max();
90 uint32_t longitude = std::numeric_limits<uint32_t>::max();
102 [[nodiscard]]
constexpr inline bool isValid()
const
104 return min.isValid() && max.isValid();
106 [[nodiscard]]
constexpr inline bool operator==(
BoundingBox other)
const
108 return min == other.min && max == other.max;
111 [[nodiscard]]
constexpr inline uint32_t width()
const
113 return max.longitude - min.longitude;
115 [[nodiscard]]
constexpr inline uint32_t height()
const
117 return max.latitude - min.latitude;
120 [[nodiscard]]
constexpr inline double widthF()
const
122 return width() / 10'000'000.0;
124 [[nodiscard]]
constexpr inline double heightF()
const
126 return height() / 10'000'000.0;
129 [[nodiscard]]
constexpr inline Coordinate center()
const
131 return Coordinate(min.latitude + height() / 2, min.longitude + width() / 2);
140 if (!bbox1.isValid()) {
143 if (!bbox2.isValid()) {
147 ret.min.latitude = std::min(bbox1.min.latitude, bbox2.min.latitude);
148 ret.min.longitude = std::min(bbox1.min.longitude, bbox2.min.longitude);
149 ret.max.latitude = std::max(bbox1.max.latitude, bbox2.max.latitude);
150 ret.max.longitude = std::max(bbox1.max.longitude, bbox2.max.longitude);
154[[nodiscard]]
constexpr inline bool intersects(BoundingBox bbox1, BoundingBox bbox2)
156 return !(bbox2.min.latitude > bbox1.max.latitude || bbox2.max.latitude < bbox1.min.latitude
157 || bbox2.min.longitude > bbox1.max.longitude || bbox2.max.longitude < bbox1.min.longitude);
160[[nodiscard]]
constexpr inline bool contains(BoundingBox bbox,
Coordinate coord)
162 return bbox.min.latitude <= coord.
latitude && bbox.max.latitude >= coord.
latitude
166[[nodiscard]]
constexpr inline uint32_t latitudeDistance(BoundingBox bbox1, BoundingBox bbox2)
168 return bbox1.max.latitude < bbox2.min.latitude ? bbox2.min.latitude - bbox1.max.latitude : bbox1.min.latitude - bbox2.max.latitude;
171[[nodiscard]]
constexpr inline uint32_t longitudeDifference(BoundingBox bbox1, BoundingBox bbox2)
173 return bbox1.max.longitude < bbox2.min.longitude ? bbox2.min.longitude - bbox1.max.longitude : bbox1.min.longitude - bbox2.max.longitude;
187 , value(std::move(_value))
189 Tag(
const Tag&) =
default;
191 Tag& operator=(
const Tag &other) =
default;
192 Tag& operator=(
Tag &&other)
noexcept =
default;
194 [[nodiscard]]
inline constexpr bool operator<(
const Tag &other)
const {
return key < other.key; }
200[[nodiscard]]
inline constexpr bool operator<(
const Tag &lhs,
TagKey rhs) {
return lhs.key < rhs; }
201[[nodiscard]]
inline constexpr bool operator<(TagKey lhs,
const Tag &rhs) {
return lhs < rhs.key; }
206 explicit Node() =
default;
210 *
this = std::move(other);
212 Node& operator=(
const Node &other) =
default;
213 Node& operator=(
Node &&other)
noexcept
216 coordinate = other.coordinate;
217 std::swap(tags, other.tags);
221 [[nodiscard]]
constexpr inline bool operator<(
const Node &other)
const {
return id < other.id; }
222 [[nodiscard]]
constexpr inline bool operator<(
Id other)
const {
return id < other; };
224 [[nodiscard]]
QString url()
const;
228 std::vector<Tag> tags;
234 explicit Way() =
default;
235 Way(
const Way&) =
default;
238 *
this = std::move(other);
240 Way& operator=(
const Way &other) =
default;
241 Way& operator=(
Way &&other)
noexcept
245 std::swap(nodes, other.nodes);
246 std::swap(tags, other.tags);
250 [[nodiscard]]
constexpr inline bool operator<(
const Way &other)
const {
return id < other.id; }
251 [[nodiscard]]
constexpr inline bool operator<(
Id other)
const {
return id < other; };
253 [[nodiscard]]
bool isClosed()
const;
255 [[nodiscard]]
QString url()
const;
259 std::vector<Id> nodes;
260 std::vector<Tag> tags;
272[[nodiscard]] KOSM_EXPORT
const char*
typeName(Type type);
280 constexpr inline Role() =
default;
283 explicit constexpr inline Role(
const char *keyData) :
StringKey(keyData) {}
289 [[nodiscard]]
inline bool operator==(
const Member &other)
const {
return id == other.id && m_roleAndType == other.m_roleAndType; }
293 [[nodiscard]]
constexpr inline Role role()
const
295 return Role(m_roleAndType.get());
297 constexpr inline void setRole(
Role role)
299 m_roleAndType.set(role.name());
302 [[nodiscard]]
constexpr inline Type type()
const
304 return static_cast<Type>(m_roleAndType.tag());
306 constexpr inline void setType(
Type type)
308 m_roleAndType.setTag(
static_cast<uint8_t
>(type));
322 *
this = std::move(other);
329 std::swap(members, other.members);
330 std::swap(tags, other.tags);
334 [[nodiscard]]
constexpr inline bool operator<(
const Relation &other)
const {
return id < other.id; }
335 [[nodiscard]]
constexpr inline bool operator<(
Id other)
const {
return id < other; };
337 [[nodiscard]]
QString url()
const;
341 std::vector<Member> members;
342 std::vector<Tag> tags;
359 [[nodiscard]]
const Node* node(
Id id)
const;
364 [[nodiscard]]
const Way* way(
Id id)
const;
365 [[nodiscard]]
Way* way(
Id id);
370 [[nodiscard]]
const Relation* relation(
Id id)
const;
372 void addNode(
Node &&node);
373 void addWay(
Way &&way);
380 [[nodiscard]]
TagKey tagKey(
const char *keyName)
const;
388 [[nodiscard]]
TagKey makeTagKey(
const char *keyName, StringMemory keyMemOpt = StringMemory::Transient);
393 [[nodiscard]]
Role role(
const char *roleName)
const;
397 [[nodiscard]]
Role makeRole(
const char *roleName, StringMemory memOpt = StringMemory::Transient);
400 [[nodiscard]]
Id nextInternalId()
const;
402 std::vector<Node> nodes;
403 std::vector<Way> ways;
404 std::vector<Relation> relations;
408 const std::vector<Node> *transientNodes =
nullptr;
411 template <
typename T> T stringKey(
const char *name,
const std::vector<T> ®istry)
const;
412 template <
typename T> T makeStringKey(
const char *name, StringMemory memOpt, std::vector<T> ®istry);
419template <
typename Elem>
422 const auto it = std::lower_bound(elem.tags.begin(), elem.tags.end(), key);
423 if (it != elem.tags.end() && (*it).key == key) {
433template <
typename Elem>
436 const auto it = std::find_if(elem.tags.begin(), elem.tags.end(), [keyName](
const auto &tag) { return std::strcmp(tag.key.name(), keyName) == 0; });
437 if (it != elem.tags.end()) {
446template <
typename Elem>
449 const auto keyLen = std::strlen(keyName);
450 for (
const auto &lang : languages.languages) {
451 for (
const auto &tag : elem.tags) {
452 if (std::strlen(tag.key.name()) != keyLen + lang.size() + 1) {
455 if (std::strncmp(tag.key.name(), keyName, keyLen) == 0 && tag.key.name()[keyLen] ==
':'
456 && std::strncmp(tag.key.name() + keyLen + 1, lang.c_str(), lang.size()) == 0) {
463 const auto v =
tagValue(elem, keyName);
469 const auto it = std::find_if(elem.tags.begin(), elem.tags.end(), [keyName, keyLen](
const auto &tag) {
470 return std::strlen(tag.key.name()) == keyLen + 3
471 && std::strncmp(tag.key.name(), keyName, keyLen) == 0
472 && tag.key.name()[keyLen] ==
':';
474 if (it != elem.tags.end()) {
481template <
typename Elem>
484 const auto it = std::lower_bound(elem.tags.begin(), elem.tags.end(), tag);
485 if (it == elem.tags.end() || (*it).key != tag.key) {
486 elem.tags.insert(it, std::move(tag));
488 (*it) = std::move(tag);
493template <
typename Elem>
496 setTag(elem,
Tag(key, std::move(value)));
500template <
typename Elem>
503 const auto it = std::lower_bound(elem.tags.begin(), elem.tags.end(), key);
504 if (it != elem.tags.end() && (*it).key == key) {
Coordinate, stored as 1e7 * degree to avoid floating point precision issues, and offset to unsigned v...
constexpr uint64_t z() const
Z-order curve value for this coordinate.
constexpr Coordinate(uint64_t z)
Create a coordinate from a z-order curve index.
A set of nodes, ways and relations.
Pointer with the lower bits used for compact flag storage.
Languages in preference order to consider when looking up translated tag values.
A relation role name key.
Registry of unique string keys.
Base class for unique string keys.
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.
void setTag(Elem &elem, Tag &&tag)
Inserts a new tag, or replaces an existing one with the same key.
int64_t Id
OSM element identifier.
QByteArray tagValue(const Elem &elem, TagKey key)
Returns the tag value for key of elem.
KOSM_EXPORT const char * typeName(Type type)
Element type name.
void removeTag(Elem &elem, TagKey key)
Removes a tag from the given element.
QDebug operator<<(QDebug dbg, const PerceptualColor::MultiSpinBoxSection &value)