From e7243ce30f196dab249c48c0f1333c9c8815e249 Mon Sep 17 00:00:00 2001 From: Anatoly Serdtcev Date: Mon, 8 Apr 2019 10:59:18 +0300 Subject: [PATCH] [generator:geo_objects] Generate surrogate streets for KV by POI --- generator/geo_objects/streets_builder.cpp | 96 ++++++++++++++++++----- generator/geo_objects/streets_builder.hpp | 21 ++++- 2 files changed, 93 insertions(+), 24 deletions(-) diff --git a/generator/geo_objects/streets_builder.cpp b/generator/geo_objects/streets_builder.cpp index f96cf4051f..813e21daca 100644 --- a/generator/geo_objects/streets_builder.cpp +++ b/generator/geo_objects/streets_builder.cpp @@ -20,22 +20,62 @@ StreetsBuilder::StreetsBuilder(RegionInfoGetter const & regionInfoGetter) void StreetsBuilder::Build(std::string const & pathInGeoObjectsTmpMwm, std::ostream & streamGeoObjectsKv) { auto const transform = [this, &streamGeoObjectsKv](FeatureBuilder1 & fb, uint64_t /* currPos */) { - if (!IsStreet(fb)) + if (IsStreet(fb)) + { + AddStreet(fb); return; + } - auto const region = FindStreetRegionOwner(fb); - if (!region) - return; - - if (!InsertStreet(*region, fb)) - return; - - auto const value = MakeStreetValue(fb, *region); - auto const id = static_cast(fb.GetMostGenericOsmId().GetEncodedId()); - streamGeoObjectsKv << id << " " << value.get() << "\n"; + auto streetName = fb.GetParams().GetStreet(); + if (!streetName.empty()) + AddStreetBinding(std::move(streetName), fb); }; - feature::ForEachFromDatRawFormat(pathInGeoObjectsTmpMwm, transform); + + SaveStreetGeoObjects(streamGeoObjectsKv); +} + +void StreetsBuilder::SaveStreetGeoObjects(std::ostream & streamGeoObjectsKv) +{ + for (auto const & region : m_regions) + SaveRegionStreetGeoObjects(streamGeoObjectsKv, region.first, region.second); +} + +void StreetsBuilder::SaveRegionStreetGeoObjects(std::ostream & streamGeoObjectsKv, uint64_t regionId, + RegionStreets const & streets) +{ + auto const & regionsStorage = m_regionInfoGetter.GetStorage(); + auto const && regionObject = regionsStorage.Find(regionId); + ASSERT(regionObject, ()); + + for (auto const & street : streets) + { + auto streetId = street.second; + if (base::GeoObjectId::Type::Invalid == streetId.GetType()) + streetId = NextOsmSurrogateId(); + + auto const id = static_cast(streetId.GetEncodedId()); + auto const value = MakeStreetValue(regionId, *regionObject, street.first); + streamGeoObjectsKv << id << " " << value.get() << "\n"; + } +} + +void StreetsBuilder::AddStreet(FeatureBuilder1 & fb) +{ + auto const region = FindStreetRegionOwner(fb); + if (!region) + return; + + InsertStreet(*region, fb.GetName(), fb.GetMostGenericOsmId()); +} + +void StreetsBuilder::AddStreetBinding(std::string && streetName, FeatureBuilder1 & fb) +{ + auto const region = FindStreetRegionOwner(fb.GetKeyPoint()); + if (!region) + return; + + InsertSurrogateStreet(*region, std::move(streetName)); } boost::optional StreetsBuilder::FindStreetRegionOwner(FeatureBuilder1 & fb) @@ -78,25 +118,36 @@ boost::optional StreetsBuilder::FindStreetRegionOwner(m2::PointD const return m_regionInfoGetter.FindDeepest(point, isStreetAdministrator); } -bool StreetsBuilder::InsertStreet(KeyValue const & region, FeatureBuilder1 & fb) +bool StreetsBuilder::InsertStreet(KeyValue const & region, std::string && streetName, base::GeoObjectId id) { - auto & regionStreets = m_regionsStreets[region.first]; - auto emplace = regionStreets.emplace(fb.GetName()); + auto & regionStreets = m_regions[region.first]; + auto emplace = regionStreets.emplace(std::move(streetName), id); + + if (!emplace.second && base::GeoObjectId::Type::Invalid == emplace.first->second.GetType()) + emplace.first->second = id; + + return emplace.second; +} + +bool StreetsBuilder::InsertSurrogateStreet(KeyValue const & region, std::string && streetName) +{ + auto & regionStreets = m_regions[region.first]; + auto emplace = regionStreets.emplace(std::move(streetName), base::GeoObjectId{}); return emplace.second; } std::unique_ptr StreetsBuilder::MakeStreetValue( - FeatureBuilder1 const & fb, KeyValue const & region) + uint64_t regionId, base::Json const regionObject, std::string const & streetName) { - auto const && regionProperties = base::GetJSONObligatoryField(region.second.get(), "properties"); + auto const && regionProperties = base::GetJSONObligatoryField(regionObject.get(), "properties"); auto const && regionAddress = base::GetJSONObligatoryField(regionProperties, "address"); auto address = base::JSONPtr{json_deep_copy(regionAddress)}; - ToJSONObject(*address, "street", fb.GetName()); + ToJSONObject(*address, "street", streetName); auto properties = base::NewJSONObject(); ToJSONObject(*properties, "address", std::move(address)); - ToJSONObject(*properties, "name", fb.GetName()); - ToJSONObject(*properties, "pid", region.first); + ToJSONObject(*properties, "name", streetName); + ToJSONObject(*properties, "pid", regionId); auto streetObject = base::NewJSONObject(); ToJSONObject(*streetObject, "properties", std::move(properties)); @@ -105,6 +156,11 @@ std::unique_ptr StreetsBuilder::MakeStreetValue( return std::unique_ptr{value}; } +base::GeoObjectId StreetsBuilder::NextOsmSurrogateId() +{ + return base::GeoObjectId{base::GeoObjectId::Type::OsmSurrogate, ++m_osmSurrogateCounter}; +} + // static bool StreetsBuilder::IsStreet(OsmElement const & element) { diff --git a/generator/geo_objects/streets_builder.hpp b/generator/geo_objects/streets_builder.hpp index e15e1f3502..7f5bb2a397 100644 --- a/generator/geo_objects/streets_builder.hpp +++ b/generator/geo_objects/streets_builder.hpp @@ -9,12 +9,13 @@ #include "geometry/point2d.hpp" +#include "base/geo_object_id.hpp" + #include #include #include #include #include -#include #include @@ -33,13 +34,25 @@ public: static bool IsStreet(FeatureBuilder1 const & fb); private: + using RegionStreets = std::unordered_map; + + void SaveStreetGeoObjects(std::ostream & streamGeoObjectsKv); + void SaveRegionStreetGeoObjects(std::ostream & streamGeoObjectsKv, uint64_t regionId, + RegionStreets const & streets); + + void AddStreet(FeatureBuilder1 & fb); + void AddStreetBinding(std::string && streetName, FeatureBuilder1 & fb); boost::optional FindStreetRegionOwner(FeatureBuilder1 & fb); boost::optional FindStreetRegionOwner(m2::PointD const & point); - bool InsertStreet(KeyValue const & region, FeatureBuilder1 & fb); - std::unique_ptr MakeStreetValue(FeatureBuilder1 const & fb, KeyValue const & region); + bool InsertStreet(KeyValue const & region, std::string && streetName, base::GeoObjectId id); + bool InsertSurrogateStreet(KeyValue const & region, std::string && streetName); + std::unique_ptr MakeStreetValue(uint64_t regionId, base::Json const regionObject, + std::string const & streetName); + base::GeoObjectId NextOsmSurrogateId(); - std::unordered_map> m_regionsStreets; + std::unordered_map m_regions; RegionInfoGetter const & m_regionInfoGetter; + uint64_t m_osmSurrogateCounter{0}; }; } // namespace geo_objects } // namespace generator