diff --git a/generator/feature_builder.cpp b/generator/feature_builder.cpp index b947d7fed6..bd9917d335 100644 --- a/generator/feature_builder.cpp +++ b/generator/feature_builder.cpp @@ -377,17 +377,23 @@ void FeatureBuilder1::Deserialize(buffer_t & data) CHECK ( CheckValid(), (*this) ); } -void FeatureBuilder1::AddOsmId(string const & type, uint64_t osmId) +void FeatureBuilder1::AddOsmId(osm::Id id) { - m_osmIds.push_back(osm::OsmId(type, osmId)); + m_osmIds.push_back(id); } string FeatureBuilder1::GetOsmIdsString() const { - ostringstream out; - for (size_t i = 0; i < m_osmIds.size(); ++i) - out << m_osmIds[i].Type() << " id=" << m_osmIds[i].Id() << " "; - return out.str(); + size_t const size = m_osmIds.size(); + if (size) + { + ostringstream out; + for (size_t i = 0; i < size; ++i) + out << m_osmIds[i].Type() << " id=" << m_osmIds[i].OsmId() << " "; + return out.str(); + } + else + return "(NOT AN OSM FEATURE)"; } int FeatureBuilder1::GetMinFeatureDrawScale() const @@ -418,7 +424,10 @@ string DebugPrint(FeatureBuilder1 const & f) default: out << "ERROR: unknown geometry type"; break; } - return (out.str() + " " + DebugPrint(f.m_limitRect) + " " + DebugPrint(f.m_params)); + return (out.str() + " " + + DebugPrint(f.m_limitRect) + " " + + DebugPrint(f.m_params) + " " + + DebugPrint(f.m_osmIds)); } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/generator/feature_builder.hpp b/generator/feature_builder.hpp index 6b94dc5aa1..54ddb6fdbb 100644 --- a/generator/feature_builder.hpp +++ b/generator/feature_builder.hpp @@ -5,6 +5,7 @@ #include "../indexer/feature.hpp" #include "../coding/file_reader.hpp" +#include "../coding/read_write_utils.hpp" #include "../std/bind.hpp" @@ -133,7 +134,7 @@ public: inline void SetParams(FeatureParams const & params) { m_params.SetParams(params); } /// For OSM debugging, store original OSM id - void AddOsmId(string const & type, uint64_t osmId); + void AddOsmId(osm::Id id); string GetOsmIdsString() const; int GetMinFeatureDrawScale() const; @@ -164,8 +165,8 @@ public: //@} protected: - /// Used for feature debugging - vector m_osmIds; + /// Used for features debugging + vector m_osmIds; FeatureParams m_params; diff --git a/generator/generator_tests/osm_id_test.cpp b/generator/generator_tests/osm_id_test.cpp index 31e237e6ad..d684da3cd1 100644 --- a/generator/generator_tests/osm_id_test.cpp +++ b/generator/generator_tests/osm_id_test.cpp @@ -9,15 +9,15 @@ using namespace osm; UNIT_TEST(OsmId) { - OsmId node("node", 12345); - TEST_EQUAL(node.Id(), 12345ULL, ()); + Id const node = Id::Node(12345); + TEST_EQUAL(node.OsmId(), 12345ULL, ()); TEST_EQUAL(node.Type(), "node", ()); - OsmId way("way", 93245123456332ULL); - TEST_EQUAL(way.Id(), 93245123456332ULL, ()); + Id const way = Id::Way(93245123456332ULL); + TEST_EQUAL(way.OsmId(), 93245123456332ULL, ()); TEST_EQUAL(way.Type(), "way", ()); - OsmId relation("relation", 5); - TEST_EQUAL(relation.Id(), 5ULL, ()); + Id const relation = Id::Relation(5); + TEST_EQUAL(relation.OsmId(), 5ULL, ()); TEST_EQUAL(relation.Type(), "relation", ()); } diff --git a/generator/osm_element.hpp b/generator/osm_element.hpp index 497ec33ede..ebce0ab0ac 100644 --- a/generator/osm_element.hpp +++ b/generator/osm_element.hpp @@ -321,7 +321,7 @@ protected: f.SetParams(m_params); for (size_t i = 0; i < ids.size(); ++i) - f.AddOsmId("way", ids[i]); + f.AddOsmId(osm::Id::Way(ids[i])); for (size_t i = 0; i < pts.size(); ++i) f.AddPoint(pts[i]); @@ -331,7 +331,7 @@ protected: f.SetAreaAddHoles(m_holes); if (f.PreSerialize()) { - f.AddOsmId("relation", m_relID); + f.AddOsmId(osm::Id::Relation(m_relID)); m_pMain->m_emitter(f); } } @@ -366,9 +366,10 @@ protected: return; feature_t ft; - + osm::Id osmId; if (p->name == "node") { + osmId = osm::Id::Node(id); if (!feature::RemoveNoDrawableTypes(fValue.m_Types, FEATURE_TYPE_POINT)) return; @@ -380,6 +381,7 @@ protected: } else if (p->name == "way") { + osmId = osm::Id::Way(id); // It's useless here to skip any types by drawing criteria. // Area features can combine all drawing types (point, linear, unique area). @@ -424,6 +426,7 @@ protected: if (NeedWriteAddress(params) && f.FormatFullAddress(addr)) m_addrWriter->Write(addr.c_str(), addr.size()); + f.AddOsmId(osmId); base_type::m_emitter(f); } } @@ -443,6 +446,7 @@ protected: } else if (p->name == "relation") { + osmId = osm::Id::Relation(id); { // 1. Check, if this is our processable relation. Here we process only polygon relations. size_t i = 0; @@ -497,7 +501,7 @@ protected: m_addrWriter->Write(addr.c_str(), addr.size()); // add osm id for debugging - ft.AddOsmId(p->name, id); + ft.AddOsmId(osmId); base_type::m_emitter(ft); } } diff --git a/generator/osm_id.cpp b/generator/osm_id.cpp index 3dafee3b7c..5d9e9fcad2 100644 --- a/generator/osm_id.cpp +++ b/generator/osm_id.cpp @@ -2,42 +2,59 @@ #include "../base/assert.hpp" +#include "../std/sstream.hpp" + + namespace osm { // Use 3 higher bits to encode type -static const uint64_t NODE = 0x2000000000000000ULL; -static const uint64_t WAY = 0x4000000000000000ULL; -static const uint64_t RELATION = 0x8000000000000000ULL; +static const uint64_t NODE = 0x4000000000000000ULL; +static const uint64_t WAY = 0x8000000000000000ULL; +static const uint64_t RELATION = 0xC000000000000000ULL; static const uint64_t RESET = ~(NODE | WAY | RELATION); -OsmId::OsmId(string const & type, uint64_t osmId) - : m_id(osmId) +Id::Id(uint64_t encodedId) : m_encodedId(encodedId) { - if (type == "node") - m_id |= NODE; - else if (type == "way") - m_id |= WAY; - else - { - m_id |= RELATION; - ASSERT_EQUAL(type, "relation", ("Invalid osm type:", type)); - } } -uint64_t OsmId::Id() const +Id Id::Node(uint64_t id) { - return m_id & RESET; + return Id( id | NODE ); } -string OsmId::Type() const +Id Id::Way(uint64_t id) { - if (m_id & NODE) + return Id( id | WAY ); +} + +Id Id::Relation(uint64_t id) +{ + return Id( id | RELATION ); +} + +uint64_t Id::OsmId() const +{ + return m_encodedId & RESET; +} + +string Id::Type() const +{ + if ((m_encodedId & RELATION) == RELATION) + return "relation"; + else if ((m_encodedId & NODE) == NODE) return "node"; - else if (m_id & WAY) + else if ((m_encodedId & WAY) == WAY) return "way"; else - return "relation"; + return "ERROR: Not initialized Osm ID"; +} + +string DebugPrint(osm::Id const & id) +{ + ostringstream stream; + stream << id.Type() << " " << id.OsmId(); + return stream.str(); } } // namespace osm diff --git a/generator/osm_id.hpp b/generator/osm_id.hpp index 7e746c0d20..e3401f0e6f 100644 --- a/generator/osm_id.hpp +++ b/generator/osm_id.hpp @@ -3,18 +3,29 @@ #include "../std/stdint.hpp" #include "../std/string.hpp" + namespace osm { -class OsmId +class Id { - uint64_t m_id; + uint64_t m_encodedId; + + static const uint64_t INVALID = 0ULL; public: - /// @param[in] type "node" "way" or "relation" - OsmId(string const & type, uint64_t osmId); - uint64_t Id() const; + explicit Id(uint64_t encodedId = INVALID); + static Id Node(uint64_t osmId); + static Id Way(uint64_t osmId); + static Id Relation(uint64_t osmId); + uint64_t OsmId() const; + /// For debug output string Type() const; + + bool operator<(Id const & other) const { return m_encodedId < other.m_encodedId; } + bool operator==(Id const & other) const { return m_encodedId == other.m_encodedId; } }; +string DebugPrint(osm::Id const & id); + } // namespace osm