#pragma once #include "base/assert.hpp" #include "base/geo_object_id.hpp" #include "base/math.hpp" #include "base/string_utils.hpp" #include "std/string_view.hpp" #include #include #include #include #include #include #include struct OsmElement { enum class EntityType { Unknown = 0x0, Node = 0x6F6E, // "no" Way = 0x6177, // "wa" Relation = 0x6572, // "re" Tag = 0x6174, // "ta" Nd = 0x646E, // "nd" Member = 0x656D, // "me" Osm = 0x736F, // "os" }; struct Member { uint64_t ref = 0; EntityType type = EntityType::Unknown; std::string role; Member() = default; Member(uint64_t ref, EntityType type, std::string const & role) : ref(ref), type(type), role(role) {} bool operator == (Member const & e) const { return ref == e.ref && type == e.type && role == e.role; } }; struct Tag { std::string key; std::string value; Tag() = default; Tag(std::string const & k, std::string const & v) : key(k), value(v) {} bool operator == (Tag const & e) const { return key == e.key && value == e.value; } bool operator < (Tag const & e) const { if (key == e.key) return value < e.value; return key < e.key; } }; EntityType type = EntityType::Unknown; uint64_t id = 0; double lon = 0; double lat = 0; uint64_t ref = 0; std::string k; std::string v; EntityType memberType = EntityType::Unknown; std::string role; std::vector m_nds; std::vector m_members; std::vector m_tags; void Clear() { type = EntityType::Unknown; id = 0; lon = 0; lat = 0; ref = 0; k.clear(); v.clear(); memberType = EntityType::Unknown; role.clear(); m_nds.clear(); m_members.clear(); m_tags.clear(); } std::string ToString(std::string const & shift = std::string()) const; std::vector const & Nodes() const { return m_nds; } std::vector const & Members() const { return m_members; } std::vector const & Tags() const { return m_tags; } bool IsNode() const { return type == EntityType::Node; } bool IsWay() const { return type == EntityType::Way; } bool IsRelation() const { return type == EntityType::Relation; } static EntityType StringToEntityType(std::string const & t) { if (t == "way") return EntityType::Way; if (t == "node") return EntityType::Node; if (t == "relation") return EntityType::Relation; ASSERT(false, ("Unknown type", t)); return EntityType::Unknown; } bool operator==(OsmElement const & e) const { return type == e.type && id == e.id && base::AlmostEqualAbs(lon, e.lon, 1e-7) && base::AlmostEqualAbs(lat, e.lat, 1e-7) && ref == e.ref && k == e.k && v == e.v && memberType == e.memberType && role == e.role && m_nds == e.m_nds && m_members == e.m_members && m_tags == e.m_tags; } void AddNd(uint64_t ref) { m_nds.emplace_back(ref); } void AddMember(uint64_t ref, EntityType type, std::string const & role) { m_members.emplace_back(ref, type, role); } void AddTag(std::string_view const & k, std::string_view const & v); bool HasTag(std::string_view const & key) const; bool HasTag(std::string_view const & k, std::string_view const & v) const; bool HasAnyTag(std::unordered_multimap const & tags) const; template void UpdateTag(std::string const & k, Fn && fn) { for (auto & tag : m_tags) { if (tag.key == k) { fn(tag.value); return; } } std::string v; fn(v); if (!v.empty()) AddTag(k, v); } std::string GetTag(std::string const & key) const; std::string_view GetTagValue(std::string_view const & key, std::string_view const & defaultValue) const; }; base::GeoObjectId GetGeoObjectId(OsmElement const & element); std::string DebugPrint(OsmElement const & e); std::string DebugPrint(OsmElement::EntityType e); std::string DebugPrint(OsmElement::Tag const & tag);