From 58699e2c56ec8bed8ba531a3f8f89187f2c1fbd7 Mon Sep 17 00:00:00 2001 From: Viktor Govako Date: Mon, 13 Nov 2023 22:44:04 -0300 Subject: [PATCH] [generator][search] Treat addr:city and addr:suburb as Place without addr:street or addr:place. Signed-off-by: Viktor Govako --- data/osm_test_data/zelenograd.osm | 59 ++++++++ .../generator_tests/raw_generator_test.cpp | 10 +- generator/osm2type.cpp | 126 ++++++++++-------- indexer/feature_meta.hpp | 2 +- indexer/ftypes_matcher.hpp | 6 - 5 files changed, 139 insertions(+), 64 deletions(-) create mode 100644 data/osm_test_data/zelenograd.osm diff --git a/data/osm_test_data/zelenograd.osm b/data/osm_test_data/zelenograd.osm new file mode 100644 index 0000000000..24cebffa7c --- /dev/null +++ b/data/osm_test_data/zelenograd.osm @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/generator/generator_tests/raw_generator_test.cpp b/generator/generator_tests/raw_generator_test.cpp index 890b52cdc2..64942614e3 100644 --- a/generator/generator_tests/raw_generator_test.cpp +++ b/generator/generator_tests/raw_generator_test.cpp @@ -1101,11 +1101,12 @@ UNIT_CLASS_TEST(TestRawGenerator, Addr_Street_Place) { std::string m_file; size_t m_addrCount; - bool m_checkPlace; + bool m_checkStreet, m_checkPlace; }; TestData const arrFiles[] = { - { "./data/osm_test_data/addr_street_place.osm", 1, true }, - { "./data/osm_test_data/addr_street_very_far.osm", 2, false }, + { "./data/osm_test_data/addr_street_place.osm", 1, true, true }, + { "./data/osm_test_data/addr_street_very_far.osm", 2, true, false }, + { "./data/osm_test_data/zelenograd.osm", 1, false, true }, }; for (auto const & data : arrFiles) @@ -1135,7 +1136,8 @@ UNIT_CLASS_TEST(TestRawGenerator, Addr_Street_Place) TEST(!ft->GetHouseNumber().empty(), ()); ++count; - TEST(house2street->Get(ft->GetID().m_index), ()); + if (data.m_checkStreet) + TEST(house2street->Get(ft->GetID().m_index), ()); if (data.m_checkPlace) TEST(house2place->Get(ft->GetID().m_index), ()); } diff --git a/generator/osm2type.cpp b/generator/osm2type.cpp index 97acb28833..c003c28bb2 100644 --- a/generator/osm2type.cpp +++ b/generator/osm2type.cpp @@ -200,6 +200,8 @@ protected: static void Call(std::function const & f, string & k, string & v) { f(k, v); + k.clear(); + v.clear(); } private: @@ -1173,114 +1175,91 @@ void GetNameAndType(OsmElement * p, FeatureBuilderParams & params, // Stage3: Process base feature tags. std::string houseName, houseNumber, conscriptionHN, streetHN, addrPostcode; + std::string addrCity, addrSuburb; feature::AddressData addr; TagProcessor(p).ApplyRules( { {"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()) houseNumber = std::move(v); - k.clear(); - v.clear(); }}, {"addr:housename", "*", [&houseName](string & k, string & v) { houseName = std::move(v); - k.clear(); - v.clear(); }}, {"addr:street", "*", [&addr](string & k, string & 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:city", "*", [&addrCity](string & k, string & v) + { + addrCity = std::move(v); + }}, + {"addr:suburb", "*", [&addrSuburb](string & k, string & v) { - addr.Set(feature::AddressData::Type::Suburb, std::move(v)); - k.clear(); - v.clear(); + addrSuburb = std::move(v); }}, {"addr:postcode", "*", [&addrPostcode](string & k, string & v) { addrPostcode = std::move(v); - k.clear(); - v.clear(); }}, {"postal_code", "*", [&addrPostcode](string & k, string & v) { addrPostcode = std::move(v); - k.clear(); - v.clear(); }}, {"contact:postcode", "*", [&addrPostcode](string & k, string & v) { if (addrPostcode.empty()) addrPostcode = std::move(v); - k.clear(); - v.clear(); }}, - {"population", "*", - [¶ms](string & k, string & v) { - // Get population rank. - uint64_t const population = generator::osm_element::GetPopulation(v); - if (population != 0) - params.rank = feature::PopulationToRank(population); - }}, - {"ref", "*", - [¶ms](string & k, string & v) { - // Get reference (we process road numbers only). - params.ref = v; - k.clear(); - v.clear(); - }}, - {"layer", "*", - [¶ms](string & /* k */, string & v) { - // Get layer. - if (params.layer == feature::LAYER_EMPTY) - { - // atoi error value (0) should match empty layer constant. - static_assert(feature::LAYER_EMPTY == 0); - params.layer = atoi(v.c_str()); - params.layer = base::Clamp(params.layer, int8_t(feature::LAYER_LOW), int8_t(feature::LAYER_HIGH)); - } - }}, + {"population", "*", [¶ms](string & k, string & v) + { + // Get population rank. + uint64_t const population = generator::osm_element::GetPopulation(v); + if (population != 0) + params.rank = feature::PopulationToRank(population); + }}, + {"ref", "*", [¶ms](string & k, string & v) + { + // Get reference (we process road numbers only). + params.ref = std::move(v); + }}, + {"layer", "*", [¶ms](string & k, string & v) + { + // Get layer. + if (params.layer == feature::LAYER_EMPTY) + { + // atoi error value (0) should match empty layer constant. + static_assert(feature::LAYER_EMPTY == 0); + params.layer = atoi(v.c_str()); + params.layer = base::Clamp(params.layer, int8_t(feature::LAYER_LOW), int8_t(feature::LAYER_HIGH)); + } + }}, }); // OSM consistency check with house numbers. @@ -1307,6 +1286,47 @@ void GetNameAndType(OsmElement * p, FeatureBuilderParams & params, /// @todo Remove "ev." prefix from HN? } + if (!houseNumber.empty() && addr.Empty()) + { + if (!addrSuburb.empty()) + { + // Treat addr:suburb as addr:place (https://overpass-turbo.eu/s/1Dlz) + addr.Set(feature::AddressData::Type::Place, std::move(addrSuburb)); + } + else if (!addrCity.empty()) + { + // Treat addr:city as addr:place + class CityBBox + { + std::vector m_rects; + public: + CityBBox() + { + // Зеленоград + m_rects.emplace_back(37.119113, 55.944925, 37.273608, 56.026874); + + // Add new {lon, lat} city bboxes here. + } + bool IsInside(m2::PointD const & pt) + { + auto const ll = mercator::ToLatLon(pt); + for (auto const & r : m_rects) + { + if (r.IsPointInside({ll.m_lon, ll.m_lat})) + return true; + } + return false; + } + }; + + static CityBBox s_cityBBox; + + auto const org = calcOrg(p); + if (org && s_cityBBox.IsInside(*org)) + addr.Set(feature::AddressData::Type::Place, std::move(addrCity)); + } + } + params.SetAddress(std::move(addr)); params.SetPostcode(std::move(addrPostcode)); params.SetHouseNumberAndHouseName(std::move(houseNumber), std::move(houseName)); diff --git a/indexer/feature_meta.hpp b/indexer/feature_meta.hpp index f969ef20b1..d59ae3798b 100644 --- a/indexer/feature_meta.hpp +++ b/indexer/feature_meta.hpp @@ -182,7 +182,7 @@ class AddressData : public MetadataBase public: enum class Type : uint8_t { - Street, Place, Suburb, + Street, Place, }; // Store single value only. diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index 4397bfd256..ceb3ffef54 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -188,12 +188,6 @@ enum class SuburbType Count }; -static_assert(base::Underlying(SuburbType::Residential) < - base::Underlying(SuburbType::Neighbourhood), - ""); -static_assert(base::Underlying(SuburbType::Neighbourhood) < base::Underlying(SuburbType::Suburb), - ""); - class IsSuburbChecker : public BaseChecker { IsSuburbChecker();