Merge pull request #10729 from cc-engineering/generator.geo_objects.reproduced-streets

[generator:geo_objects] Generate surrogate streets for KV by POI
This commit is contained in:
Sergey Yershov 2019-04-22 18:29:24 +03:00 committed by GitHub
commit 6316937a10
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 24 deletions

View file

@ -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<int64_t>(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<int64_t>(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<KeyValue> StreetsBuilder::FindStreetRegionOwner(FeatureBuilder1 & fb)
@ -78,25 +118,36 @@ boost::optional<KeyValue> 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<char, JSONFreeDeleter> 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<char, JSONFreeDeleter> StreetsBuilder::MakeStreetValue(
return std::unique_ptr<char, JSONFreeDeleter>{value};
}
base::GeoObjectId StreetsBuilder::NextOsmSurrogateId()
{
return base::GeoObjectId{base::GeoObjectId::Type::OsmSurrogate, ++m_osmSurrogateCounter};
}
// static
bool StreetsBuilder::IsStreet(OsmElement const & element)
{

View file

@ -9,12 +9,13 @@
#include "geometry/point2d.hpp"
#include "base/geo_object_id.hpp"
#include <memory>
#include <ostream>
#include <stdint.h>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <boost/optional.hpp>
@ -33,13 +34,25 @@ public:
static bool IsStreet(FeatureBuilder1 const & fb);
private:
using RegionStreets = std::unordered_map<std::string, base::GeoObjectId>;
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<KeyValue> FindStreetRegionOwner(FeatureBuilder1 & fb);
boost::optional<KeyValue> FindStreetRegionOwner(m2::PointD const & point);
bool InsertStreet(KeyValue const & region, FeatureBuilder1 & fb);
std::unique_ptr<char, JSONFreeDeleter> 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<char, JSONFreeDeleter> MakeStreetValue(uint64_t regionId, base::Json const regionObject,
std::string const & streetName);
base::GeoObjectId NextOsmSurrogateId();
std::unordered_map<uint64_t, std::unordered_set<std::string>> m_regionsStreets;
std::unordered_map<uint64_t, RegionStreets> m_regions;
RegionInfoGetter const & m_regionInfoGetter;
uint64_t m_osmSurrogateCounter{0};
};
} // namespace geo_objects
} // namespace generator