From 006021eb93a71cde363a64cde651d53b0b904005 Mon Sep 17 00:00:00 2001 From: Viktor Govako Date: Mon, 31 Jul 2023 15:53:51 -0300 Subject: [PATCH] [generator] Save extended address data (place, suburb). Signed-off-by: Viktor Govako --- generator/osm2type.cpp | 103 +++++++++++++++++++++-------- generator/search_index_builder.cpp | 2 +- indexer/feature_data.cpp | 12 +--- indexer/feature_data.hpp | 6 +- indexer/feature_meta.hpp | 14 +++- 5 files changed, 96 insertions(+), 41 deletions(-) diff --git a/generator/osm2type.cpp b/generator/osm2type.cpp index 87854f2766..72500ea5fb 100644 --- a/generator/osm2type.cpp +++ b/generator/osm2type.cpp @@ -1158,15 +1158,34 @@ void GetNameAndType(OsmElement * p, FeatureBuilderParams & params, namesExtractor.Finish(); // Stage3: Process base feature tags. - std::string houseName, houseNumber, addrStreet, addrPostcode; + std::string houseName, houseNumber, conscriptionHN, streetHN, addrPostcode; + feature::AddressData addr; TagProcessor(p).ApplyRules( { - {"addr:housenumber", "*", - [&houseNumber](string & k, string & v) { - houseNumber = std::move(v); - k.clear(); - v.clear(); - }}, + {"addr:housenumber", "*", [&houseNumber](string & k, string & v) + { + houseNumber = std::move(v); + k.clear(); + v.clear(); + }}, + {"addr:conscriptionnumber", "*", [&conscriptionHN](string & k, string & v) + { + conscriptionHN = std::move(v); + k.clear(); + v.clear(); + }}, + {"addr:provisionalnumber", "*", [&conscriptionHN](string & k, string & v) + { + conscriptionHN = std::move(v); + k.clear(); + v.clear(); + }}, + {"addr:streetnumber", "*", [&streetHN](string & k, string & v) + { + streetHN = std::move(v); + k.clear(); + v.clear(); + }}, {"contact:housenumber", "*", [&houseNumber](string & k, string & v) { if (houseNumber.empty()) @@ -1174,22 +1193,33 @@ void GetNameAndType(OsmElement * p, FeatureBuilderParams & params, k.clear(); v.clear(); }}, - {"addr:housename", "*", - [&houseName](string & k, string & v) { - houseName = std::move(v); - k.clear(); - v.clear(); - }}, - {"addr:street", "*", [&addrStreet](string & k, string & v) + {"addr:housename", "*", [&houseName](string & k, string & v) { - addrStreet = std::move(v); + houseName = std::move(v); k.clear(); v.clear(); }}, - {"contact:street", "*", [&addrStreet](string & k, string & v) + {"addr:street", "*", [&addr](string & k, string & v) { - if (addrStreet.empty()) - addrStreet = std::move(v); + addr.Set(feature::AddressData::Type::Street, std::move(v)); + k.clear(); + v.clear(); + }}, + {"contact:street", "*", [&addr](string & k, string & v) + { + addr.SetIfAbsent(feature::AddressData::Type::Street, std::move(v)); + k.clear(); + v.clear(); + }}, + {"addr:place", "*", [&addr](string & k, string & v) + { + addr.Set(feature::AddressData::Type::Place, std::move(v)); + k.clear(); + v.clear(); + }}, + {"addr:suburb", "*", [&addr](string & k, string & v) + { + addr.Set(feature::AddressData::Type::Suburb, std::move(v)); k.clear(); v.clear(); }}, @@ -1239,8 +1269,32 @@ void GetNameAndType(OsmElement * p, FeatureBuilderParams & params, }}, }); - params.SetStreet(std::move(addrStreet)); - params.SetPostcode(addrPostcode); + // OSM consistency check with house numbers. + if (!conscriptionHN.empty() || !streetHN.empty()) + { + // Simple validity check, trust housenumber tag in other cases. + + char const * kHNLogTag = "HNLog"; + if (!conscriptionHN.empty() && !streetHN.empty()) + { + auto i = houseNumber.find('/'); + if (i == std::string::npos) + { + LOG(LWARNING, (kHNLogTag, "Override housenumber for:", DebugPrintID(*p), houseNumber, conscriptionHN, streetHN)); + houseNumber = conscriptionHN + "/" + streetHN; + } + } + else if (houseNumber.empty()) + { + LOG(LWARNING, (kHNLogTag, "Assign housenumber for:", DebugPrintID(*p), houseNumber, conscriptionHN, streetHN)); + houseNumber = conscriptionHN.empty() ? streetHN : conscriptionHN; + } + + /// @todo Remove "ev." prefix from HN? + } + + params.SetAddress(std::move(addr)); + params.SetPostcode(std::move(addrPostcode)); params.SetHouseNumberAndHouseName(std::move(houseNumber), std::move(houseName)); // Stage4: Match tags to classificator feature types via mapcss-mapping.csv. @@ -1252,15 +1306,12 @@ void GetNameAndType(OsmElement * p, FeatureBuilderParams & params, { std::string const typesString = params.PrintTypes(); - // Unknown type is possible in unit tests. - std::string const id = (p->m_type != OsmElement::EntityType::Unknown) ? - DebugPrint(GetGeoObjectId(*p)) : std::string("Unknown"); - if (params.RemoveInconsistentTypes()) - LOG(LWARNING, ("Inconsistent types for:", id, "Types:", typesString)); + LOG(LWARNING, ("Inconsistent types for:", DebugPrintID(*p), "Types:", typesString)); + size_t const typesCount = params.m_types.size(); if (params.FinishAddingTypesEx() == FeatureParams::TYPES_EXCEED_MAX) - LOG(LWARNING, ("Exceeded types count for:", id, "Types:", typesString)); + LOG(LWARNING, ("Exceeded types count for:", DebugPrintID(*p), "Types:", typesCount, typesString)); } // Stage6: Collect additional information about feature such as diff --git a/generator/search_index_builder.cpp b/generator/search_index_builder.cpp index e80c425c57..2967ab79ae 100644 --- a/generator/search_index_builder.cpp +++ b/generator/search_index_builder.cpp @@ -450,7 +450,7 @@ void BuildAddressTable(FilesContainerR & container, std::string const & addressD uint32_t address = 0, missing = 0; - auto const kEmptyResult = uint32_t(-1); + uint32_t constexpr kEmptyResult = uint32_t(-1); std::vector results(featuresCount, kEmptyResult); std::mutex resMutex; diff --git a/indexer/feature_data.cpp b/indexer/feature_data.cpp index 3a1d1c73bd..1fd3946a06 100644 --- a/indexer/feature_data.cpp +++ b/indexer/feature_data.cpp @@ -525,13 +525,7 @@ uint32_t FeatureParams::GetTypeForIndex(uint32_t i) void FeatureBuilderParams::SetStreet(string s) { - if (s.empty()) - return; - - // Replace \n with spaces because we write addresses to txt file. - replace(s.begin(), s.end(), '\n', ' '); - - m_addrTags.Set(AddressData::Type::Street, s); + m_addrTags.Set(AddressData::Type::Street, std::move(s)); } std::string_view FeatureBuilderParams::GetStreet() const @@ -539,10 +533,10 @@ std::string_view FeatureBuilderParams::GetStreet() const return m_addrTags.Get(AddressData::Type::Street); } -void FeatureBuilderParams::SetPostcode(string const & s) +void FeatureBuilderParams::SetPostcode(string s) { if (!s.empty()) - m_metadata.Set(Metadata::FMD_POSTCODE, s); + m_metadata.Set(Metadata::FMD_POSTCODE, std::move(s)); } std::string_view FeatureBuilderParams::GetPostcode() const diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp index 00199c4a99..d18355bcbd 100644 --- a/indexer/feature_data.hpp +++ b/indexer/feature_data.hpp @@ -323,8 +323,10 @@ public: m_reversedGeometry = rhs.m_reversedGeometry; } - /// @name Used to store address to temporary TEMP_ADDR_FILE_TAG section. + /// @name Used to store address to temporary TEMP_ADDR_EXTENSION file. /// @{ + void SetAddress(feature::AddressData && addr) { m_addrTags = std::move(addr); } + void SetStreet(std::string s); std::string_view GetStreet() const; @@ -334,7 +336,7 @@ public: } /// @} - void SetPostcode(std::string const & s); + void SetPostcode(std::string s); std::string_view GetPostcode() const; feature::Metadata const & GetMetadata() const { return m_metadata; } diff --git a/indexer/feature_meta.hpp b/indexer/feature_meta.hpp index 1cfbba4dac..539f724938 100644 --- a/indexer/feature_meta.hpp +++ b/indexer/feature_meta.hpp @@ -178,13 +178,21 @@ class AddressData : public MetadataBase public: enum class Type : uint8_t { - Street, + Street, Place, Suburb, }; // Store single value only. - void Set(Type type, std::string const & s) + void Set(Type type, std::string s) { - MetadataBase::Set(base::Underlying(type), s); + if (!s.empty()) + MetadataBase::Set(base::Underlying(type), std::move(s)); + } + + void SetIfAbsent(Type type, std::string s) + { + uint8_t const ut = base::Underlying(type); + if (!s.empty() && !Has(ut)) + MetadataBase::Set(ut, std::move(s)); } std::string_view Get(Type type) const { return MetadataBase::Get(base::Underlying(type)); }