forked from organicmaps/organicmaps
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:
commit
6316937a10
2 changed files with 93 additions and 24 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue