Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksim Andrianov <maksimandrianov1@gmail.com>2019-03-22 17:40:38 +0300
committerTatiana Yan <tatiana.kondakova@gmail.com>2019-04-09 20:52:09 +0300
commit4c858a1d1d5943310e155c0efb1265b640727697 (patch)
tree3141beaac3cd2d7a3a37bf3d553dfbfaf0385f52
parent14bf63e03275b4ff6c19685592d0ea3387668f0f (diff)
[generator] Added CollectionBase class.
[generator] Added TypeHelper class. [generator] Added filters. [generator] Added collectors. [generator] Changed interfaces of some classes. [generator] Added the feature maker. [generator] Added the city boundary processor. [generator] Added relation tags enricher. [generator] Added processing layers. [generator] Changed emitters. [generator] Changed translators. [generator] Some changes related to refactoring. [generator] Removed EmitterPlanet, TranslatorPlanet and TranslatorGeocoderBase. [generator] Changed cmake list. Review fixes
-rw-r--r--generator/CMakeLists.txt48
-rw-r--r--generator/booking_quality_check/booking_quality_check.cpp8
-rw-r--r--generator/camera_node_processor.cpp14
-rw-r--r--generator/camera_node_processor.hpp13
-rw-r--r--generator/city_boundary_processor.cpp67
-rw-r--r--generator/city_boundary_processor.hpp30
-rw-r--r--generator/coastlines_generator.cpp2
-rw-r--r--generator/coastlines_generator.hpp2
-rw-r--r--generator/collection_base.hpp35
-rw-r--r--generator/collector_addresses.cpp19
-rw-r--r--generator/collector_addresses.hpp25
-rw-r--r--generator/collector_collection.cpp32
-rw-r--r--generator/collector_collection.hpp24
-rw-r--r--generator/collector_interface.hpp8
-rw-r--r--generator/collector_tag.cpp4
-rw-r--r--generator/collector_tag.hpp2
-rw-r--r--generator/emitter_booking.hpp2
-rw-r--r--generator/emitter_coastline.cpp64
-rw-r--r--generator/emitter_coastline.hpp39
-rw-r--r--generator/emitter_country.cpp63
-rw-r--r--generator/emitter_country.hpp39
-rw-r--r--generator/emitter_factory.hpp20
-rw-r--r--generator/emitter_interface.hpp13
-rw-r--r--generator/emitter_planet.cpp280
-rw-r--r--generator/emitter_planet.hpp75
-rw-r--r--generator/emitter_restaurants.cpp2
-rw-r--r--generator/emitter_restaurants.hpp2
-rw-r--r--generator/emitter_simple.cpp15
-rw-r--r--generator/emitter_simple.hpp11
-rw-r--r--generator/emitter_world.cpp41
-rw-r--r--generator/emitter_world.hpp38
-rw-r--r--generator/feature_maker.cpp99
-rw-r--r--generator/feature_maker.hpp40
-rw-r--r--generator/feature_maker_base.cpp80
-rw-r--r--generator/feature_maker_base.hpp47
-rw-r--r--generator/feature_processing_layers.cpp396
-rw-r--r--generator/feature_processing_layers.hpp275
-rw-r--r--generator/filter_collection.cpp23
-rw-r--r--generator/filter_collection.hpp20
-rw-r--r--generator/filter_elements.cpp5
-rw-r--r--generator/filter_elements.hpp6
-rw-r--r--generator/filter_interface.hpp17
-rw-r--r--generator/filter_planet.cpp31
-rw-r--r--generator/filter_planet.hpp13
-rw-r--r--generator/generator_tests/common.cpp8
-rw-r--r--generator/generator_tests/common.hpp1
-rw-r--r--generator/generator_tests/osm_type_test.cpp4
-rw-r--r--generator/generator_tests/region_info_collector_tests.cpp23
-rw-r--r--generator/generator_tests/regions_tests.cpp22
-rw-r--r--generator/generator_tests/speed_cameras_test.cpp11
-rw-r--r--generator/generator_tool/generator_tool.cpp74
-rw-r--r--generator/maxspeeds_collector.cpp10
-rw-r--r--generator/maxspeeds_collector.hpp8
-rw-r--r--generator/metalines_builder.cpp17
-rw-r--r--generator/metalines_builder.hpp10
-rw-r--r--generator/osm_element.cpp16
-rw-r--r--generator/osm_element.hpp27
-rw-r--r--generator/osm_source.cpp148
-rw-r--r--generator/osm_source.hpp77
-rw-r--r--generator/place.cpp5
-rw-r--r--generator/place.hpp2
-rw-r--r--generator/regions/collector_region_info.cpp3
-rw-r--r--generator/regions/collector_region_info.hpp2
-rw-r--r--generator/relation_tags.cpp28
-rw-r--r--generator/relation_tags.hpp12
-rw-r--r--generator/relation_tags_enricher.cpp24
-rw-r--r--generator/relation_tags_enricher.hpp26
-rw-r--r--generator/restaurants_info/restaurants_info.cpp7
-rw-r--r--generator/restriction_writer.cpp10
-rw-r--r--generator/restriction_writer.hpp12
-rw-r--r--generator/road_access_generator.cpp6
-rw-r--r--generator/road_access_generator.hpp12
-rw-r--r--generator/routing_helpers.hpp10
-rw-r--r--generator/tag_admixer.hpp25
-rw-r--r--generator/translator.cpp79
-rw-r--r--generator/translator.hpp56
-rw-r--r--generator/translator_coastline.cpp40
-rw-r--r--generator/translator_coastline.hpp27
-rw-r--r--generator/translator_collection.cpp35
-rw-r--r--generator/translator_collection.hpp19
-rw-r--r--generator/translator_country.cpp114
-rw-r--r--generator/translator_country.hpp38
-rw-r--r--generator/translator_factory.hpp22
-rw-r--r--generator/translator_geo_objects.cpp27
-rw-r--r--generator/translator_geo_objects.hpp16
-rw-r--r--generator/translator_geocoder_base.cpp151
-rw-r--r--generator/translator_geocoder_base.hpp59
-rw-r--r--generator/translator_interface.hpp7
-rw-r--r--generator/translator_planet.cpp293
-rw-r--r--generator/translator_planet.hpp64
-rw-r--r--generator/translator_region.cpp55
-rw-r--r--generator/translator_region.hpp24
-rw-r--r--generator/translator_world.cpp35
-rw-r--r--generator/translator_world.hpp36
-rw-r--r--generator/type_helper.cpp17
-rw-r--r--generator/type_helper.hpp16
-rw-r--r--generator/world_map_generator.hpp33
-rw-r--r--indexer/feature_data.hpp1
-rw-r--r--indexer/feature_visibility.cpp55
-rw-r--r--indexer/feature_visibility.hpp6
-rw-r--r--indexer/ftypes_matcher.cpp36
-rw-r--r--indexer/ftypes_matcher.hpp25
102 files changed, 2784 insertions, 1331 deletions
diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt
index 010345b282..e683d76547 100644
--- a/generator/CMakeLists.txt
+++ b/generator/CMakeLists.txt
@@ -30,10 +30,17 @@ set(SRC
cities_boundaries_builder.hpp
cities_boundaries_checker.cpp
cities_boundaries_checker.hpp
+ city_boundary_processor.cpp
+ city_boundary_processor.hpp
city_roads_generator.cpp
city_roads_generator.hpp
coastlines_generator.cpp
coastlines_generator.hpp
+ collection_base.hpp
+ collector_addresses.cpp
+ collector_addresses.hpp
+ collector_collection.cpp
+ collector_collection.hpp
collector_interface.hpp
collector_tag.cpp
collector_tag.hpp
@@ -42,14 +49,18 @@ set(SRC
dumper.cpp
dumper.hpp
emitter_booking.hpp
+ emitter_coastline.cpp
+ emitter_coastline.hpp
+ emitter_country.cpp
+ emitter_country.hpp
emitter_factory.hpp
emitter_interface.hpp
- emitter_planet.cpp
- emitter_planet.hpp
- emitter_restaurants.hpp
emitter_restaurants.cpp
- emitter_simple.hpp
+ emitter_restaurants.hpp
emitter_simple.cpp
+ emitter_simple.hpp
+ emitter_world.cpp
+ emitter_world.hpp
factory_utils.hpp
feature_builder.cpp
feature_builder.hpp
@@ -58,12 +69,23 @@ set(SRC
feature_generator.hpp
feature_helpers.cpp
feature_helpers.hpp
+ feature_maker.cpp
+ feature_maker.hpp
+ feature_maker_base.cpp
+ feature_maker_base.hpp
feature_merger.cpp
feature_merger.hpp
+ feature_processing_layers.cpp
+ feature_processing_layers.hpp
feature_sorter.cpp
feature_sorter.hpp
+ filter_collection.cpp
+ filter_collection.hpp
filter_elements.cpp
filter_elements.hpp
+ filter_interface.hpp
+ filter_planet.cpp
+ filter_planet.hpp
gen_mwm_info.hpp
generate_info.hpp
geometry_holder.hpp
@@ -114,6 +136,8 @@ set(SRC
platform_helpers.hpp
relation_tags.cpp
relation_tags.hpp
+ relation_tags_enricher.cpp
+ relation_tags_enricher.hpp
region_meta.cpp
region_meta.hpp
regions/city.hpp
@@ -168,16 +192,24 @@ set(SRC
traffic_generator.hpp
transit_generator.cpp
transit_generator.hpp
+ translator.cpp
+ translator.hpp
+ translator_coastline.cpp
+ translator_coastline.hpp
+ translator_collection.cpp
+ translator_collection.hpp
+ translator_country.cpp
+ translator_country.hpp
translator_factory.hpp
translator_geo_objects.cpp
translator_geo_objects.hpp
- translator_geocoder_base.hpp
- translator_geocoder_base.cpp
translator_interface.hpp
- translator_planet.cpp
- translator_planet.hpp
translator_region.cpp
translator_region.hpp
+ translator_world.cpp
+ translator_world.hpp
+ type_helper.cpp
+ type_helper.hpp
ugc_db.cpp
ugc_db.hpp
ugc_section_builder.cpp
diff --git a/generator/booking_quality_check/booking_quality_check.cpp b/generator/booking_quality_check/booking_quality_check.cpp
index c2d122e0dc..3b0648c11d 100644
--- a/generator/booking_quality_check/booking_quality_check.cpp
+++ b/generator/booking_quality_check/booking_quality_check.cpp
@@ -4,6 +4,8 @@
#include "generator/opentable_dataset.hpp"
#include "generator/osm_source.hpp"
#include "generator/sponsored_scoring.hpp"
+#include "generator/translator_collection.hpp"
+#include "generator/translator_factory.hpp"
#include "indexer/classificator_loader.hpp"
@@ -325,8 +327,12 @@ void RunImpl(feature::GenerateInfo & info)
map<base::GeoObjectId, FeatureBuilder1> features;
LOG_SHORT(LINFO, ("OSM data:", FLAGS_osm));
+
+ CacheLoader cacheLoader(info);
+ TranslatorCollection translators;
auto emitter = make_shared<EmitterBooking<Dataset>>(dataset, features);
- GenerateFeatures(info, emitter);
+ translators.Append(CreateTranslator(TranslatorType::Country, emitter, cacheLoader.GetCache(), info));
+ GenerateRaw(info, translators);
if (FLAGS_generate)
{
diff --git a/generator/camera_node_processor.cpp b/generator/camera_node_processor.cpp
index bc62c11917..7718e78ac5 100644
--- a/generator/camera_node_processor.cpp
+++ b/generator/camera_node_processor.cpp
@@ -1,5 +1,6 @@
#include "generator/camera_node_processor.hpp"
+#include "generator/feature_builder.hpp"
#include "generator/maxspeeds_parser.hpp"
#include "routing_common/maxspeed_conversion.hpp"
@@ -20,6 +21,12 @@ size_t const CameraNodeIntermediateDataProcessor::kMaxSpeedSpeedStringLength = 3
namespace routing
{
+CameraNodeProcessor::CameraNodeProcessor(std::string const & writerFile, std::string const & readerFile,
+ std::string const & speedFile)
+{
+ Open(writerFile, readerFile, speedFile);
+}
+
void CameraNodeProcessor::Open(std::string const & writerFile, std::string const & readerFile,
std::string const & speedFile)
{
@@ -31,7 +38,7 @@ void CameraNodeProcessor::Open(std::string const & writerFile, std::string const
ReaderSource<FileReader> src(maxSpeedReader);
static auto constexpr kMaxSpeedSpeedStringLength =
- generator::CameraNodeIntermediateDataProcessor::kMaxSpeedSpeedStringLength;
+ generator::CameraNodeIntermediateDataProcessor::kMaxSpeedSpeedStringLength;
std::array<char, kMaxSpeedSpeedStringLength> buffer{};
uint64_t nodeOsmId = 0;
size_t maxSpeedStringLength = 0;
@@ -49,10 +56,9 @@ void CameraNodeProcessor::Open(std::string const & writerFile, std::string const
}
}
-void CameraNodeProcessor::Process(OsmElement & p, FeatureParams const & params,
- generator::cache::IntermediateDataReader & cache)
+void CameraNodeProcessor::CollectFeature(FeatureBuilder1 const & feature, OsmElement const & p)
{
- if (!(p.type == OsmElement::EntityType::Node && ftypes::IsSpeedCamChecker::Instance()(params.m_types)))
+ if (!(p.type == OsmElement::EntityType::Node && ftypes::IsSpeedCamChecker::Instance()(feature.GetTypes())))
return;
std::string maxSpeedStringKmPH = "0";
diff --git a/generator/camera_node_processor.hpp b/generator/camera_node_processor.hpp
index 44de7ad57c..c23b1665e4 100644
--- a/generator/camera_node_processor.hpp
+++ b/generator/camera_node_processor.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "generator/collector_interface.hpp"
#include "generator/osm_element.hpp"
#include "generator/intermediate_data.hpp"
@@ -21,12 +22,17 @@
#include <string>
#include <vector>
+class FeatureBuilder1;
// TODO (@gmoryes) move members of m_routingTagsProcessor to generator
namespace routing
{
-class CameraNodeProcessor
+class CameraNodeProcessor : public generator::CollectorInterface
{
public:
+ CameraNodeProcessor() = default;
+ CameraNodeProcessor(std::string const & writerFile, std::string const & readerFile,
+ std::string const & speedFile);
+
void Open(std::string const & writerFile, std::string const & readerFile,
std::string const & speedFile);
@@ -36,8 +42,9 @@ public:
m_cameraNodeToWays->ForEachByKey(id, std::forward<ToDo>(toDo));
}
- void Process(OsmElement & p, FeatureParams const & params,
- generator::cache::IntermediateDataReader & cache);
+ // generator::CollectorInterface overrides:
+ void CollectFeature(FeatureBuilder1 const & feature, OsmElement const & p) override;
+ void Save() override {}
private:
using Cache = generator::cache::IndexFileReader;
diff --git a/generator/city_boundary_processor.cpp b/generator/city_boundary_processor.cpp
new file mode 100644
index 0000000000..e2f6b74cdb
--- /dev/null
+++ b/generator/city_boundary_processor.cpp
@@ -0,0 +1,67 @@
+#include "generator/city_boundary_processor.hpp"
+
+#include "generator/type_helper.hpp"
+
+#include "indexer/classificator.hpp"
+
+#include "base/assert.hpp"
+
+namespace generator
+{
+namespace
+{
+std::shared_ptr<OsmIdToBoundariesTable>
+GetOrCreateBoundariesTable(std::shared_ptr<OsmIdToBoundariesTable> boundariesTable)
+{
+ return boundariesTable ? boundariesTable : std::make_shared<OsmIdToBoundariesTable>();
+}
+} // namespace
+
+CityBoundaryProcessor::CityBoundaryProcessor(std::shared_ptr<OsmIdToBoundariesTable> boundariesTable)
+ : m_boundariesTable(GetOrCreateBoundariesTable(boundariesTable))
+{
+ ASSERT(m_boundariesTable.get(), ());
+}
+
+void CityBoundaryProcessor::UnionEqualPlacesIds(Place const & place)
+{
+ auto const id = place.GetFeature().GetLastOsmId();
+ m_places.ForEachInRect(place.GetLimitRect(), [&](Place const & p) {
+ if (p.IsEqual(place))
+ m_boundariesTable->Union(p.GetFeature().GetLastOsmId(), id);
+ });
+}
+
+std::vector<FeatureBuilder1> CityBoundaryProcessor::GetFeatures() const
+{
+ std::vector<FeatureBuilder1> result;
+ m_places.ForEach([&result](Place const & p) {
+ result.emplace_back(p.GetFeature());
+ });
+
+ return result;
+}
+
+void CityBoundaryProcessor::Add(FeatureBuilder1 const & fb)
+{
+ auto const type = GetPlaceType(fb);
+ if (type == ftype::GetEmptyValue())
+ return;
+
+ auto const id = fb.GetLastOsmId();
+ m_boundariesTable->Append(id, indexer::CityBoundary(fb.GetOuterGeometry()));
+ UnionEqualPlacesIds(Place(fb, type, false /* saveParams */));
+}
+
+void CityBoundaryProcessor::Replace(FeatureBuilder1 const & fb)
+{
+ auto const type = GetPlaceType(fb);
+ Place const place(fb, type);
+ UnionEqualPlacesIds(place);
+ m_places.ReplaceEqualInRect(place, [](Place const & p1, Place const & p2) {
+ return p1.IsEqual(p2);
+ }, [](Place const & p1, Place const & p2) {
+ return p1.IsBetterThan(p2);
+ });
+}
+} // namespace generator
diff --git a/generator/city_boundary_processor.hpp b/generator/city_boundary_processor.hpp
new file mode 100644
index 0000000000..7a9f16582e
--- /dev/null
+++ b/generator/city_boundary_processor.hpp
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "generator/cities_boundaries_builder.hpp"
+#include "generator/feature_builder.hpp"
+#include "generator/place.hpp"
+
+#include "geometry/tree4d.hpp"
+
+#include <memory>
+#include <vector>
+
+namespace generator
+{
+// The class CityBoundaryProcessor is responsible for the union of boundaries of the cities.
+class CityBoundaryProcessor
+{
+public:
+ CityBoundaryProcessor(std::shared_ptr<OsmIdToBoundariesTable> boundariesTable);
+
+ void Add(FeatureBuilder1 const & fb);
+ void Replace(FeatureBuilder1 const & fb);
+ std::vector<FeatureBuilder1> GetFeatures() const;
+
+private:
+ void UnionEqualPlacesIds(Place const & place);
+
+ std::shared_ptr<OsmIdToBoundariesTable> m_boundariesTable;
+ m4::Tree<Place> m_places;
+};
+} // namespace generator
diff --git a/generator/coastlines_generator.cpp b/generator/coastlines_generator.cpp
index 1960dc7d7b..6ee42e5096 100644
--- a/generator/coastlines_generator.cpp
+++ b/generator/coastlines_generator.cpp
@@ -86,7 +86,7 @@ void CoastlineFeaturesGenerator::AddRegionToTree(FeatureBuilder1 const & fb)
fb.ForEachGeometryPointEx(createRgn);
}
-void CoastlineFeaturesGenerator::operator()(FeatureBuilder1 const & fb)
+void CoastlineFeaturesGenerator::Process(FeatureBuilder1 const & fb)
{
if (fb.IsGeometryClosed())
AddRegionToTree(fb);
diff --git a/generator/coastlines_generator.hpp b/generator/coastlines_generator.hpp
index 141dd03db2..b520f249d5 100644
--- a/generator/coastlines_generator.hpp
+++ b/generator/coastlines_generator.hpp
@@ -24,7 +24,7 @@ public:
void AddRegionToTree(FeatureBuilder1 const & fb);
- void operator() (FeatureBuilder1 const & fb);
+ void Process(FeatureBuilder1 const & fb);
/// @return false if coasts are not merged and FLAG_fail_on_coasts is set
bool Finish();
diff --git a/generator/collection_base.hpp b/generator/collection_base.hpp
new file mode 100644
index 0000000000..94acb8c32d
--- /dev/null
+++ b/generator/collection_base.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <algorithm>
+#include <iterator>
+#include <vector>
+
+// Implementing this base class allows an object to be collection of objects.
+template <typename T>
+class CollectionBase
+{
+public:
+ void Append(T const & collector)
+ {
+ m_collection.push_back(collector);
+ }
+
+ void AddCollection(CollectionBase<T> const & collection)
+ {
+ std::copy(std::begin(collection.m_collection), std::end(collection.m_collection),
+ std::back_inserter(m_collection));
+ }
+
+ std::vector<T> const & GetCollection() const
+ {
+ return m_collection;
+ }
+
+ bool Empty() const
+ {
+ return m_collection.empty();
+ }
+
+protected:
+ std::vector<T> m_collection;
+};
diff --git a/generator/collector_addresses.cpp b/generator/collector_addresses.cpp
new file mode 100644
index 0000000000..0b0065fc0e
--- /dev/null
+++ b/generator/collector_addresses.cpp
@@ -0,0 +1,19 @@
+#include "generator/collector_addresses.hpp"
+
+#include "generator/feature_builder.hpp"
+
+#include "indexer/ftypes_matcher.hpp"
+
+namespace generator
+{
+CollectorAddresses::CollectorAddresses(std::string const & filename)
+ : m_addrWriter(std::make_unique<FileWriter>(filename)) {}
+
+void CollectorAddresses::CollectFeature(FeatureBuilder1 const & feature, OsmElement const &)
+{
+ std::string addr;
+ auto const & checker = ftypes::IsBuildingChecker::Instance();
+ if (checker(feature.GetTypes()) && feature.FormatFullAddress(addr))
+ m_addrWriter->Write(addr.c_str(), addr.size());
+}
+} // namespace generator
diff --git a/generator/collector_addresses.hpp b/generator/collector_addresses.hpp
new file mode 100644
index 0000000000..154104d10a
--- /dev/null
+++ b/generator/collector_addresses.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "generator/collector_interface.hpp"
+
+#include "coding/file_writer.hpp"
+
+#include <memory>
+#include <string>
+
+namespace generator
+{
+// The class CollectorAddresses is responsible for the collecting addresses to the file.
+class CollectorAddresses : public CollectorInterface
+{
+public:
+ CollectorAddresses(std::string const & filename);
+
+ // CollectorInterface overrides:
+ void CollectFeature(FeatureBuilder1 const & feature, OsmElement const &) override;
+ void Save() override {}
+
+private:
+ std::unique_ptr<FileWriter> m_addrWriter;
+};
+} // namespace generator
diff --git a/generator/collector_collection.cpp b/generator/collector_collection.cpp
new file mode 100644
index 0000000000..4857365912
--- /dev/null
+++ b/generator/collector_collection.cpp
@@ -0,0 +1,32 @@
+#include "generator/collector_collection.hpp"
+
+#include "generator/feature_builder.hpp"
+#include "generator/intermediate_elements.hpp"
+#include "generator/osm_element.hpp"
+
+namespace generator
+{
+void CollectorCollection::Collect(OsmElement const & element)
+{
+ for (auto & c : m_collection)
+ c->Collect(element);
+}
+
+void CollectorCollection::CollectRelation(RelationElement const & element)
+{
+ for (auto & c : m_collection)
+ c->CollectRelation(element);
+}
+
+void CollectorCollection::CollectFeature(FeatureBuilder1 const & feature, OsmElement const & element)
+{
+ for (auto & c : m_collection)
+ c->CollectFeature(feature, element);
+}
+
+void CollectorCollection::Save()
+{
+ for (auto & c : m_collection)
+ c->Save();
+}
+} // namespace generator
diff --git a/generator/collector_collection.hpp b/generator/collector_collection.hpp
new file mode 100644
index 0000000000..f2dff15c89
--- /dev/null
+++ b/generator/collector_collection.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "generator/collection_base.hpp"
+#include "generator/collector_interface.hpp"
+
+#include <memory>
+
+struct OsmElement;
+class RelationElement;
+class FeatureBuilder1;
+
+namespace generator
+{
+// This class allows you to work with a group of collectors as with one.
+class CollectorCollection : public CollectionBase<std::shared_ptr<CollectorInterface>>, public CollectorInterface
+{
+public:
+ // CollectorInterface overrides:
+ void Collect(OsmElement const & element) override;
+ void CollectRelation(RelationElement const & element) override;
+ void CollectFeature(FeatureBuilder1 const & feature, OsmElement const & element) override;
+ void Save() override;
+};
+} // namespace generator
diff --git a/generator/collector_interface.hpp b/generator/collector_interface.hpp
index 9ce9259331..4ada6f923c 100644
--- a/generator/collector_interface.hpp
+++ b/generator/collector_interface.hpp
@@ -3,6 +3,8 @@
#include <string>
struct OsmElement;
+class FeatureBuilder1;
+class RelationElement;
namespace base
{
class GeoObjectId;
@@ -10,12 +12,16 @@ class GeoObjectId;
namespace generator
{
+// Implementing this interface allows an object to collect data from RelationElement,
+// OsmElement and FeatureBuilder1 elements.
class CollectorInterface
{
public:
virtual ~CollectorInterface() = default;
- virtual void Collect(base::GeoObjectId const & osmId, OsmElement const & el) = 0;
+ virtual void Collect(OsmElement const &) {}
+ virtual void CollectRelation(RelationElement const &) {}
+ virtual void CollectFeature(FeatureBuilder1 const &, OsmElement const &) {}
virtual void Save() = 0;
};
} // namespace generator
diff --git a/generator/collector_tag.cpp b/generator/collector_tag.cpp
index 29a17c0fb2..291cb1468f 100644
--- a/generator/collector_tag.cpp
+++ b/generator/collector_tag.cpp
@@ -30,13 +30,13 @@ CollectorTag::CollectorTag(std::string const & filename, std::string const & tag
}
}
-void CollectorTag::Collect(base::GeoObjectId const & osmId, OsmElement const & el)
+void CollectorTag::Collect(OsmElement const & el)
{
if (!m_needCollect)
return;
auto const tag = el.GetTag(m_tagKey);
if (!tag.empty() && m_validator(tag))
- m_stream << osmId.GetEncodedId() << "\t" << tag << "\n";
+ m_stream << GetGeoObjectId(el).GetEncodedId() << "\t" << tag << "\n";
}
} // namespace generator
diff --git a/generator/collector_tag.hpp b/generator/collector_tag.hpp
index 191fb9748f..25c43bdd55 100644
--- a/generator/collector_tag.hpp
+++ b/generator/collector_tag.hpp
@@ -25,7 +25,7 @@ public:
Validator const & validator, bool ignoreIfNotOpen = false);
// CollectorInterface overrides:
- void Collect(base::GeoObjectId const & osmId, OsmElement const & el) override;
+ void Collect(OsmElement const & el) override;
void Save() override {}
private:
diff --git a/generator/emitter_booking.hpp b/generator/emitter_booking.hpp
index 40a92e357d..99a336d687 100644
--- a/generator/emitter_booking.hpp
+++ b/generator/emitter_booking.hpp
@@ -25,7 +25,7 @@ public:
}
// EmitterInterface overrides:
- void operator()(FeatureBuilder1 & fb) override
+ void Process(FeatureBuilder1 & fb) override
{
if (m_dataset.NecessaryMatchingConditionHolds(fb))
m_features.emplace(fb.GetMostGenericOsmId(), fb);
diff --git a/generator/emitter_coastline.cpp b/generator/emitter_coastline.cpp
new file mode 100644
index 0000000000..e81c2d06a1
--- /dev/null
+++ b/generator/emitter_coastline.cpp
@@ -0,0 +1,64 @@
+#include "generator/emitter_coastline.hpp"
+
+#include "generator/coastlines_generator.hpp"
+#include "generator/feature_builder.hpp"
+#include "generator/feature_processing_layers.hpp"
+#include "generator/feature_generator.hpp"
+#include "generator/generate_info.hpp"
+#include "generator/type_helper.hpp"
+
+#include "base/logging.hpp"
+
+#include <cstddef>
+
+#include "defines.hpp"
+
+namespace generator
+{
+EmitterCoastline::EmitterCoastline(feature::GenerateInfo const & info)
+ : m_generator(std::make_shared<CoastlineFeaturesGenerator>(ftypes::IsCoastlineChecker::Instance().GetCoastlineType()))
+ , m_coastlineGeomFilename(info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, ".geom"))
+ , m_coastlineRawGeomFilename(info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, RAW_GEOM_FILE_EXTENSION))
+{
+ m_processingChain = std::make_shared<RepresentationCoastlineLayer>();
+ m_processingChain->Add(std::make_shared<PrepareCoastlineFeatureLayer>());
+ m_processingChain->Add(std::make_shared<CoastlineMapperLayer>(m_generator));
+}
+
+void EmitterCoastline::Process(FeatureBuilder1 & feature)
+{
+ m_processingChain->Handle(feature);
+}
+
+bool EmitterCoastline::Finish()
+{
+ feature::FeaturesAndRawGeometryCollector collector(m_coastlineGeomFilename, m_coastlineRawGeomFilename);
+ // Check and stop if some coasts were not merged
+ if (!m_generator->Finish())
+ return false;
+
+ LOG(LINFO, ("Generating coastline polygons"));
+
+ size_t totalFeatures = 0;
+ size_t totalPoints = 0;
+ size_t totalPolygons = 0;
+
+ vector<FeatureBuilder1> features;
+ m_generator->GetFeatures(features);
+ for (auto & feature : features)
+ {
+ collector(feature);
+
+ ++totalFeatures;
+ totalPoints += feature.GetPointsCount();
+ totalPolygons += feature.GetPolygonsCount();
+ }
+
+ LOG(LINFO, ("Total features:", totalFeatures, "total polygons:", totalPolygons,
+ "total points:", totalPoints));
+
+ return true;
+}
+
+void EmitterCoastline::GetNames(std::vector<std::string> &) const {}
+} // namespace generator
diff --git a/generator/emitter_coastline.hpp b/generator/emitter_coastline.hpp
new file mode 100644
index 0000000000..14b5cd2774
--- /dev/null
+++ b/generator/emitter_coastline.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "generator/emitter_interface.hpp"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+class FeatureBuilder1;
+class CoastlineFeaturesGenerator;
+namespace feature
+{
+struct GenerateInfo;
+} // namespace feature
+
+namespace generator
+{
+class CityBoundaryProcessor;
+class CountryMapper;
+class LayerBase;
+// This class is implementation of EmitterInterface for coastlines.
+class EmitterCoastline : public EmitterInterface
+{
+public:
+ explicit EmitterCoastline(feature::GenerateInfo const & info);
+
+ // EmitterInterface overrides:
+ void Process(FeatureBuilder1 & feature) override;
+ bool Finish() override;
+ void GetNames(std::vector<std::string> & names) const override;
+
+private:
+ std::shared_ptr<CityBoundaryProcessor> m_cityBoundaryProcessor;
+ std::shared_ptr<CoastlineFeaturesGenerator> m_generator;
+ std::shared_ptr<LayerBase> m_processingChain;
+ std::string m_coastlineGeomFilename;
+ std::string m_coastlineRawGeomFilename;
+};
+} // namespace generator
diff --git a/generator/emitter_country.cpp b/generator/emitter_country.cpp
new file mode 100644
index 0000000000..350520a81f
--- /dev/null
+++ b/generator/emitter_country.cpp
@@ -0,0 +1,63 @@
+#include "generator/emitter_country.hpp"
+
+#include "generator/city_boundary_processor.hpp"
+#include "generator/feature_builder.hpp"
+#include "generator/feature_processing_layers.hpp"
+#include "generator/generate_info.hpp"
+
+#include "base/logging.hpp"
+
+#include <fstream>
+
+#include "defines.hpp"
+
+namespace generator
+{
+EmitterCountry::EmitterCountry(feature::GenerateInfo const & info)
+ : m_cityBoundaryProcessor(std::make_shared<CityBoundaryProcessor>(info.m_boundariesTable))
+ , m_countryMapper(std::make_shared<CountryMapper>(info))
+ , m_skippedListFilename(info.GetIntermediateFileName("skipped_elements", ".lst"))
+{
+ m_processingChain = std::make_shared<RepresentationLayer>(m_cityBoundaryProcessor);
+ m_processingChain->Add(std::make_shared<PrepareFeatureLayer>());
+ m_processingChain->Add(std::make_shared<CityBoundaryLayer>(m_cityBoundaryProcessor));
+ m_processingChain->Add(std::make_shared<BookingLayer>(info.m_bookingDatafileName, m_countryMapper));
+ m_processingChain->Add(std::make_shared<OpentableLayer>(info.m_opentableDatafileName, m_countryMapper));
+ m_processingChain->Add(std::make_shared<CountryMapperLayer>(m_countryMapper));
+
+ if (info.m_emitCoasts)
+ {
+ auto const geomFilename = info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, ".geom");
+ auto const worldCoastsFilename = info.GetTmpFileName(WORLD_COASTS_FILE_NAME);
+ m_processingChain->Add(std::make_shared<EmitCoastsLayer>(worldCoastsFilename, geomFilename, m_countryMapper));
+ }
+}
+
+void EmitterCountry::Process(FeatureBuilder1 & feature)
+{
+ m_processingChain->Handle(feature);
+}
+
+bool EmitterCountry::Finish()
+{
+ for (auto & feature : m_cityBoundaryProcessor->GetFeatures())
+ m_countryMapper->RemoveInvalidTypesAndMap(feature);
+
+ WriteDump();
+ return true;
+}
+
+void EmitterCountry::GetNames(std::vector<std::string> & names) const
+{
+ names = m_countryMapper->GetNames();
+}
+
+void EmitterCountry::WriteDump()
+{
+ std::ofstream file;
+ file.exceptions(std::ios::failbit | std::ios::badbit);
+ file.open(m_skippedListFilename);
+ file << m_processingChain->GetAsStringRecursive();
+ LOG(LINFO, ("Skipped elements were saved to", m_skippedListFilename));
+}
+} // namespace generator
diff --git a/generator/emitter_country.hpp b/generator/emitter_country.hpp
new file mode 100644
index 0000000000..8d247448c2
--- /dev/null
+++ b/generator/emitter_country.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "generator/emitter_interface.hpp"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+class FeatureBuilder1;
+namespace feature
+{
+struct GenerateInfo;
+} // namespace feature
+
+namespace generator
+{
+class CityBoundaryProcessor;
+class CountryMapper;
+class LayerBase;
+// This class is the implementation of EmitterInterface for countries.
+class EmitterCountry : public EmitterInterface
+{
+public:
+ explicit EmitterCountry(feature::GenerateInfo const & info);
+
+ // EmitterInterface overrides:
+ void Process(FeatureBuilder1 & feature) override;
+ bool Finish() override;
+ void GetNames(std::vector<std::string> & names) const override;
+
+private:
+ void WriteDump();
+
+ std::shared_ptr<CityBoundaryProcessor> m_cityBoundaryProcessor;
+ std::shared_ptr<CountryMapper> m_countryMapper;
+ std::string m_skippedListFilename;
+ std::shared_ptr<LayerBase> m_processingChain;
+};
+} // namespace generator
diff --git a/generator/emitter_factory.hpp b/generator/emitter_factory.hpp
index 3b07f8033c..265e9cee3d 100644
--- a/generator/emitter_factory.hpp
+++ b/generator/emitter_factory.hpp
@@ -1,23 +1,29 @@
#pragma once
+#include "generator/emitter_coastline.hpp"
+#include "generator/emitter_country.hpp"
#include "generator/emitter_interface.hpp"
#include "generator/emitter_booking.hpp"
-#include "generator/emitter_planet.hpp"
#include "generator/emitter_restaurants.hpp"
#include "generator/emitter_simple.hpp"
+#include "generator/emitter_world.hpp"
#include "generator/factory_utils.hpp"
#include "base/assert.hpp"
#include <memory>
+#include <utility>
namespace generator
{
enum class EmitterType
{
- Planet,
Restaurants,
Simple,
+ SimpleWithPreserialize,
+ Country,
+ Coastline,
+ World
// Booking
};
@@ -26,12 +32,18 @@ std::shared_ptr<EmitterInterface> CreateEmitter(EmitterType type, Args&&... args
{
switch (type)
{
- case EmitterType::Planet:
- return create<EmitterPlanet>(std::forward<Args>(args)...);
+ case EmitterType::Coastline:
+ return create<EmitterCoastline>(std::forward<Args>(args)...);
+ case EmitterType::Country:
+ return create<EmitterCountry>(std::forward<Args>(args)...);
case EmitterType::Simple:
return create<EmitterSimple>(std::forward<Args>(args)...);
+ case EmitterType::SimpleWithPreserialize:
+ return create<EmitterPreserialize>(std::forward<Args>(args)...);
case EmitterType::Restaurants:
return create<EmitterRestaurants>(std::forward<Args>(args)...);
+ case EmitterType::World:
+ return create<EmitterWorld>(std::forward<Args>(args)...);
}
UNREACHABLE();
}
diff --git a/generator/emitter_interface.hpp b/generator/emitter_interface.hpp
index d2b93d9987..88dcee0b82 100644
--- a/generator/emitter_interface.hpp
+++ b/generator/emitter_interface.hpp
@@ -8,19 +8,18 @@ class FeatureParams;
namespace generator
{
-// Emitter is used in OsmElement to FeatureBuilder translation process.
+// Implementing this interface allows an object to process FeatureBuilder1 objects and broadcast them.
class EmitterInterface
{
public:
virtual ~EmitterInterface() = default;
- /// This method is used by OsmTranslator to pass |fb| to Emitter for further processing.
- virtual void operator()(FeatureBuilder1 & fb) = 0;
- virtual void EmitCityBoundary(FeatureBuilder1 const & fb, FeatureParams const & params) {}
- /// Finish is used in GenerateFeatureImpl to make whatever work is needed after
- /// all OsmElements are processed.
+ // This method is used by OsmTranslator to pass |fb| to Emitter for further processing.
+ virtual void Process(FeatureBuilder1 & fb) = 0;
+ // Finish is used in GenerateFeatureImpl to make whatever work is needed after all OsmElements
+ // are processed.
virtual bool Finish() = 0;
- /// Sets buckets (mwm names).
+ // Sets buckets (mwm names).
// TODO(syershov): Make this topic clear.
virtual void GetNames(std::vector<std::string> & names) const = 0;
};
diff --git a/generator/emitter_planet.cpp b/generator/emitter_planet.cpp
deleted file mode 100644
index 5d1d2759d8..0000000000
--- a/generator/emitter_planet.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-#include "generator/emitter_planet.hpp"
-
-#include "generator/brands_loader.hpp"
-#include "generator/feature_builder.hpp"
-#include "generator/emitter_interface.hpp"
-
-#include "base/macros.hpp"
-
-#include <fstream>
-#include <memory>
-
-using namespace std;
-
-namespace generator
-{
-EmitterPlanet::EmitterPlanet(feature::GenerateInfo const & info) :
- m_skippedElementsPath(info.GetIntermediateFileName("skipped_elements", ".lst")),
- m_failOnCoasts(info.m_failOnCoasts),
- m_bookingDataset(info.m_bookingDatafileName),
- m_opentableDataset(info.m_opentableDatafileName),
- m_boundariesTable(info.m_boundariesTable)
-{
- if (!info.m_brandsFilename.empty() && !info.m_brandsTranslationsFilename.empty())
- CHECK(LoadBrands(info.m_brandsFilename, info.m_brandsTranslationsFilename, m_brands), ());
-
- Classificator const & c = classif();
- char const * arr[][2] = {
- {"natural", "coastline"}, {"natural", "land"}, {"place", "island"}, {"place", "islet"}};
- static_assert(ARRAY_SIZE(arr) == TYPES_COUNT, "");
-
- for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
- m_types[i] = c.GetTypeByPath({arr[i][0], arr[i][1]});
-
- m_srcCoastsFile = info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, ".geom");
-
- CHECK(!info.m_makeCoasts || !info.m_createWorld,
- ("We can't do make_coasts and generate_world at the same time"));
-
- if (info.m_makeCoasts)
- {
- m_coasts.reset(new CoastlineFeaturesGenerator(Type(NATURAL_COASTLINE)));
-
- m_coastsHolder.reset(new feature::FeaturesAndRawGeometryCollector(
- m_srcCoastsFile,
- info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, RAW_GEOM_FILE_EXTENSION)));
- return;
- }
-
- if (info.m_emitCoasts)
- m_coastsHolder.reset(
- new feature::FeaturesCollector(info.GetTmpFileName(WORLD_COASTS_FILE_NAME)));
-
- if (info.m_splitByPolygons || !info.m_fileName.empty())
- m_countries = make_unique<CountriesGenerator>(info);
-
- if (info.m_createWorld)
- m_world.reset(new WorldGenerator(info));
-}
-
-void EmitterPlanet::operator()(FeatureBuilder1 & fb)
-{
- uint32_t const type = GetPlaceType(fb.GetParams());
-
- // TODO(mgserigio): Would it be better to have objects that store callback
- // and can be piped: action-if-cond1 | action-if-cond-2 | ... ?
- // The first object which perform action terminates the cahin.
- if (type != ftype::GetEmptyValue() && !fb.GetName().empty())
- {
- Place const place(fb, type);
- UnionEqualPlacesIds(place);
- m_places.ReplaceEqualInRect(
- place, [](Place const & p1, Place const & p2) { return p1.IsEqual(p2); },
- [](Place const & p1, Place const & p2) { return p1.IsBetterThan(p2); });
- return;
- }
-
- auto const bookingObjId = m_bookingDataset.FindMatchingObjectId(fb);
- if (bookingObjId != BookingHotel::InvalidObjectId())
- {
- m_bookingDataset.PreprocessMatchedOsmObject(bookingObjId, fb, [this, bookingObjId](FeatureBuilder1 & fb)
- {
- m_skippedElements << "BOOKING\t" << DebugPrint(fb.GetMostGenericOsmId())
- << '\t' << bookingObjId.Get() << endl;
- Emit(fb);
- });
- return;
- }
-
- auto const opentableObjId = m_opentableDataset.FindMatchingObjectId(fb);
- if (opentableObjId != OpentableRestaurant::InvalidObjectId())
- {
- m_opentableDataset.PreprocessMatchedOsmObject(opentableObjId, fb, [this, opentableObjId](FeatureBuilder1 & fb)
- {
- m_skippedElements << "OPENTABLE\t" << DebugPrint(fb.GetMostGenericOsmId())
- << '\t' << opentableObjId.Get() << endl;
- Emit(fb);
- });
- return;
- }
-
- auto const it = m_brands.find(fb.GetMostGenericOsmId());
- if (it != m_brands.cend())
- {
- auto & metadata = fb.GetMetadata();
- metadata.Set(feature::Metadata::FMD_BRAND, it->second);
- }
-
- Emit(fb);
-}
-
-void EmitterPlanet::EmitCityBoundary(FeatureBuilder1 const & fb, FeatureParams const & params)
-{
- if (!m_boundariesTable)
- return;
-
- auto const type = GetPlaceType(params);
- if (type == ftype::GetEmptyValue())
- return;
-
- auto const id = fb.GetLastOsmId();
- m_boundariesTable->Append(id, indexer::CityBoundary(fb.GetOuterGeometry()));
-
- Place const place(fb, type);
- UnionEqualPlacesIds(place);
-}
-
-/// @return false if coasts are not merged and FLAG_fail_on_coasts is set
-bool EmitterPlanet::Finish()
-{
- DumpSkippedElements();
-
- // Emit all required booking objects to the map.
- m_bookingDataset.BuildOsmObjects([this](FeatureBuilder1 & fb) { Emit(fb); });
- // No opentable objects should be emitted. Opentable data enriches some data
- // with a link to a restaurant's reservation page.
-
- m_places.ForEach([this](Place const & p)
- {
- // m_places are no longer used after this point.
- Emit(const_cast<FeatureBuilder1 &>(p.GetFeature()));
- });
-
- if (m_world)
- m_world->DoMerge();
-
- if (m_coasts)
- {
- // Check and stop if some coasts were not merged
- if (!m_coasts->Finish() && m_failOnCoasts)
- return false;
-
- LOG(LINFO, ("Generating coastline polygons"));
-
- size_t totalFeatures = 0;
- size_t totalPoints = 0;
- size_t totalPolygons = 0;
-
- vector<FeatureBuilder1> vecFb;
- m_coasts->GetFeatures(vecFb);
-
- for (auto & fb : vecFb)
- {
- (*m_coastsHolder)(fb);
-
- ++totalFeatures;
- totalPoints += fb.GetPointsCount();
- totalPolygons += fb.GetPolygonsCount();
- }
- LOG(LINFO, ("Total features:", totalFeatures, "total polygons:", totalPolygons,
- "total points:", totalPoints));
- }
- else if (m_coastsHolder)
- {
- CHECK(m_countries, ());
-
- feature::ForEachFromDatRawFormat(m_srcCoastsFile, [this](FeatureBuilder1 fb, uint64_t)
- {
- auto & emitter = m_countries->Parent();
-
- emitter.Start();
- (*m_countries)(fb);
- emitter.Finish();
-
- if (m_coastsHolder)
- {
- fb.AddName("default", emitter.m_currentNames);
- (*m_coastsHolder)(fb);
- }
- });
- }
- return true;
-}
-
-void EmitterPlanet::GetNames(vector<string> & names) const
-{
- if (m_countries)
- names = m_countries->Parent().Names();
- else
- names.clear();
-}
-
-void EmitterPlanet::Emit(FeatureBuilder1 & fb)
-{
- uint32_t const coastType = Type(NATURAL_COASTLINE);
- bool const hasCoast = fb.HasType(coastType);
-
- if (m_coasts)
- {
- if (hasCoast)
- {
- CHECK(fb.GetGeomType() != feature::GEOM_POINT, ());
- // Leave only coastline type.
- fb.SetType(coastType);
- (*m_coasts)(fb);
- }
- return;
- }
-
- if (hasCoast)
- {
- fb.PopExactType(Type(NATURAL_LAND));
- fb.PopExactType(coastType);
- }
- else if ((fb.HasType(Type(PLACE_ISLAND)) || fb.HasType(Type(PLACE_ISLET))) &&
- fb.GetGeomType() == feature::GEOM_AREA)
- {
- fb.AddType(Type(NATURAL_LAND));
- }
-
- if (!fb.RemoveInvalidTypes())
- return;
-
- if (m_world)
- (*m_world)(fb);
-
- if (m_countries)
- (*m_countries)(fb);
-}
-
-void EmitterPlanet::DumpSkippedElements()
-{
- auto const skippedElements = m_skippedElements.str();
-
- if (skippedElements.empty())
- {
- LOG(LINFO, ("No osm object was skipped."));
- return;
- }
-
- ofstream file(m_skippedElementsPath, ios_base::app);
- if (file.is_open())
- {
- file << m_skippedElements.str();
- LOG(LINFO, ("Saving skipped elements to", m_skippedElementsPath, "done."));
- }
- else
- {
- LOG(LERROR, ("Can't output into", m_skippedElementsPath));
- }
-}
-
-
-uint32_t EmitterPlanet::GetPlaceType(FeatureParams const & params) const
-{
- static uint32_t const placeType = classif().GetTypeByPath({"place"});
- return params.FindType(placeType, 1 /* level */);
-}
-
-void EmitterPlanet::UnionEqualPlacesIds(Place const & place)
-{
- if (!m_boundariesTable)
- return;
-
- auto const id = place.GetFeature().GetLastOsmId();
- m_places.ForEachInRect(place.GetLimitRect(), [&](Place const & p) {
- if (p.IsEqual(place))
- m_boundariesTable->Union(p.GetFeature().GetLastOsmId(), id);
- });
-}
-} // namespace generator
diff --git a/generator/emitter_planet.hpp b/generator/emitter_planet.hpp
deleted file mode 100644
index 29b083d358..0000000000
--- a/generator/emitter_planet.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#pragma once
-
-#include "generator/booking_dataset.hpp"
-#include "generator/cities_boundaries_builder.hpp"
-#include "generator/coastlines_generator.hpp"
-#include "generator/emitter_interface.hpp"
-#include "generator/feature_generator.hpp"
-#include "generator/generate_info.hpp"
-#include "generator/opentable_dataset.hpp"
-#include "generator/place.hpp"
-#include "generator/polygonizer.hpp"
-#include "generator/world_map_generator.hpp"
-
-#include "indexer/feature_data.hpp"
-
-#include "base/geo_object_id.hpp"
-
-#include <cstdint>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-
-namespace generator
-{
-class EmitterPlanet : public EmitterInterface
-{
- using WorldGenerator = WorldMapGenerator<feature::FeaturesCollector>;
- using CountriesGenerator = CountryMapGenerator<feature::Polygonizer<feature::FeaturesCollector>>;
-
-public:
- explicit EmitterPlanet(feature::GenerateInfo const & info);
-
- // EmitterInterface overrides:
- void operator()(FeatureBuilder1 & fb) override;
- void EmitCityBoundary(FeatureBuilder1 const & fb, FeatureParams const & params) override;
- /// @return false if coasts are not merged and FLAG_fail_on_coasts is set
- bool Finish() override;
- void GetNames(std::vector<std::string> & names) const override;
-
-private:
- enum TypeIndex
- {
- NATURAL_COASTLINE,
- NATURAL_LAND,
- PLACE_ISLAND,
- PLACE_ISLET,
-
- TYPES_COUNT
- };
-
- void Emit(FeatureBuilder1 & fb);
- void DumpSkippedElements();
- uint32_t Type(TypeIndex i) const { return m_types[i]; }
- uint32_t GetPlaceType(FeatureParams const & params) const;
- void UnionEqualPlacesIds(Place const & place);
-
- uint32_t m_types[TYPES_COUNT];
- std::unique_ptr<CountriesGenerator> m_countries;
- std::unique_ptr<WorldGenerator> m_world;
- std::unique_ptr<CoastlineFeaturesGenerator> m_coasts;
- std::unique_ptr<feature::FeaturesCollector> m_coastsHolder;
- std::string const m_skippedElementsPath;
- std::ostringstream m_skippedElements;
- std::string m_srcCoastsFile;
- bool m_failOnCoasts;
- BookingDataset m_bookingDataset;
- OpentableDataset m_opentableDataset;
- std::unordered_map<base::GeoObjectId, std::string> m_brands;
- shared_ptr<OsmIdToBoundariesTable> m_boundariesTable;
- /// Used to prepare a list of cities to serve as a list of nodes
- /// for building a highway graph with OSRM for low zooms.
- m4::Tree<Place> m_places;
-};
-} // namespace generator
diff --git a/generator/emitter_restaurants.cpp b/generator/emitter_restaurants.cpp
index 6512e34ae6..fbf2140bd8 100644
--- a/generator/emitter_restaurants.cpp
+++ b/generator/emitter_restaurants.cpp
@@ -10,7 +10,7 @@ EmitterRestaurants::EmitterRestaurants(std::vector<FeatureBuilder1> & features)
{
}
-void EmitterRestaurants::operator()(FeatureBuilder1 & fb)
+void EmitterRestaurants::Process(FeatureBuilder1 & fb)
{
if (!ftypes::IsEatChecker::Instance()(fb.GetParams().m_types) || fb.GetParams().name.IsEmpty())
{
diff --git a/generator/emitter_restaurants.hpp b/generator/emitter_restaurants.hpp
index c26e4903d1..35bcb2200f 100644
--- a/generator/emitter_restaurants.hpp
+++ b/generator/emitter_restaurants.hpp
@@ -12,7 +12,7 @@ public:
EmitterRestaurants(std::vector<FeatureBuilder1> & features);
// EmitterInterface overrides:
- void operator()(FeatureBuilder1 & fb) override;
+ void Process(FeatureBuilder1 & fb) override;
void GetNames(std::vector<std::string> & names) const override;
bool Finish() override;
diff --git a/generator/emitter_simple.cpp b/generator/emitter_simple.cpp
index e1bc19cd58..9d7a5eac43 100644
--- a/generator/emitter_simple.cpp
+++ b/generator/emitter_simple.cpp
@@ -2,6 +2,8 @@
#include "generator/feature_builder.hpp"
+#include "base/macros.hpp"
+
namespace generator
{
EmitterSimple::EmitterSimple(feature::GenerateInfo const & info) :
@@ -9,14 +11,17 @@ EmitterSimple::EmitterSimple(feature::GenerateInfo const & info) :
void EmitterSimple::GetNames(std::vector<std::string> & names) const
{
- if (m_regionGenerator)
- names = m_regionGenerator->Parent().Names();
- else
- names.clear();
+ names = m_regionGenerator->Parent().Names();
}
-void EmitterSimple::operator()(FeatureBuilder1 & fb)
+void EmitterSimple::Process(FeatureBuilder1 & fb)
{
(*m_regionGenerator)(fb);
}
+
+void EmitterPreserialize::Process(FeatureBuilder1 & fb)
+{
+ UNUSED_VALUE(fb.PreSerialize());
+ EmitterSimple::Process(fb);
+}
} // namespace generator
diff --git a/generator/emitter_simple.hpp b/generator/emitter_simple.hpp
index 1d8a8e5a81..b96f9097ff 100644
--- a/generator/emitter_simple.hpp
+++ b/generator/emitter_simple.hpp
@@ -20,7 +20,7 @@ public:
// EmitterInterface overrides:
void GetNames(std::vector<std::string> & names) const override;
- void operator()(FeatureBuilder1 & fb) override;
+ void Process(FeatureBuilder1 & fb) override;
bool Finish() override { return true; }
private:
@@ -28,4 +28,13 @@ private:
std::unique_ptr<SimpleGenerator> m_regionGenerator;
};
+
+class EmitterPreserialize : public EmitterSimple
+{
+public:
+ using EmitterSimple::EmitterSimple;
+
+ // EmitterInterface overrides:
+ void Process(FeatureBuilder1 & fb) override;
+};
} // namespace generator
diff --git a/generator/emitter_world.cpp b/generator/emitter_world.cpp
new file mode 100644
index 0000000000..ac408059ec
--- /dev/null
+++ b/generator/emitter_world.cpp
@@ -0,0 +1,41 @@
+#include "generator/emitter_world.hpp"
+
+#include "generator/cities_boundaries_builder.hpp"
+#include "generator/city_boundary_processor.hpp"
+#include "generator/feature_builder.hpp"
+#include "generator/feature_processing_layers.hpp"
+#include "generator/generate_info.hpp"
+
+#include "defines.hpp"
+
+namespace generator
+{
+EmitterWorld::EmitterWorld(feature::GenerateInfo const & info)
+ : m_cityBoundaryProcessor(
+ std::make_shared<CityBoundaryProcessor>(make_shared<generator::OsmIdToBoundariesTable>()))
+ , m_worldMapper(std::make_shared<WorldMapper>(
+ info.GetTmpFileName(WORLD_FILE_NAME),
+ info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, RAW_GEOM_FILE_EXTENSION),
+ info.m_popularPlacesFilename))
+{
+ m_processingChain = std::make_shared<RepresentationLayer>(m_cityBoundaryProcessor);
+ m_processingChain->Add(std::make_shared<PrepareFeatureLayer>());
+ m_processingChain->Add(std::make_shared<CityBoundaryLayer>(m_cityBoundaryProcessor));
+ m_processingChain->Add(std::make_shared<WorldAreaLayer>(m_worldMapper));
+}
+
+void EmitterWorld::Process(FeatureBuilder1 & feature)
+{
+ m_processingChain->Handle(feature);
+}
+
+bool EmitterWorld::Finish()
+{
+ for (auto & feature : m_cityBoundaryProcessor->GetFeatures())
+ m_worldMapper->RemoveInvalidTypesAndMap(feature);
+
+ return true;
+}
+
+void EmitterWorld::GetNames(vector<string> &) const {}
+} // namespace generator
diff --git a/generator/emitter_world.hpp b/generator/emitter_world.hpp
new file mode 100644
index 0000000000..b03692d5c5
--- /dev/null
+++ b/generator/emitter_world.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "generator/emitter_interface.hpp"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+class FeatureBuilder1;
+
+namespace feature
+{
+struct GenerateInfo;
+} // namespace feature
+
+namespace generator
+{
+class CityBoundaryProcessor;
+class WorldMapper;
+class LayerBase;
+
+// This class is implementation of EmitterInterface for the world.
+class EmitterWorld : public EmitterInterface
+{
+public:
+ explicit EmitterWorld(feature::GenerateInfo const & info);
+
+ // EmitterInterface overrides:
+ void Process(FeatureBuilder1 & feature) override;
+ bool Finish() override;
+ void GetNames(std::vector<std::string> & names) const override;
+
+private:
+ std::shared_ptr<CityBoundaryProcessor> m_cityBoundaryProcessor;
+ std::shared_ptr<WorldMapper> m_worldMapper;
+ std::shared_ptr<LayerBase> m_processingChain;
+};
+} // namespace generator
diff --git a/generator/feature_maker.cpp b/generator/feature_maker.cpp
new file mode 100644
index 0000000000..ed280396a0
--- /dev/null
+++ b/generator/feature_maker.cpp
@@ -0,0 +1,99 @@
+#include "generator/feature_maker.hpp"
+
+#include "generator/holes.hpp"
+#include "generator/osm2type.hpp"
+#include "generator/osm_element.hpp"
+#include "generator/type_helper.hpp"
+
+#include "indexer/classificator.hpp"
+#include "indexer/feature_visibility.hpp"
+#include "indexer/ftypes_matcher.hpp"
+
+#include <utility>
+
+namespace generator
+{
+void FeatureMakerSimple::ParseParams(FeatureParams & params, OsmElement & p) const
+{
+ ftype::GetNameAndType(&p, params, [] (uint32_t type) {
+ return classif().IsTypeValid(type);
+ });
+}
+
+bool FeatureMakerSimple::BuildFromNode(OsmElement & p, FeatureParams const & params)
+{
+ FeatureBuilder1 fb;
+ fb.SetCenter(MercatorBounds::FromLatLon(p.lat, p.lon));
+ fb.SetOsmId(base::MakeOsmNode(p.id));
+ fb.SetParams(params);
+ m_queue.push(std::move(fb));
+ return true;
+}
+
+bool FeatureMakerSimple::BuildFromWay(OsmElement & p, FeatureParams const & params)
+{
+ auto const & nodes = p.Nodes();
+ if (nodes.size() < 2)
+ return false;
+
+ FeatureBuilder1 fb;
+ m2::PointD pt;
+ for (uint64_t ref : nodes)
+ {
+ if (!m_holder.GetNode(ref, pt.y, pt.x))
+ return false;
+
+ fb.AddPoint(pt);
+ }
+
+ fb.SetOsmId(base::MakeOsmWay(p.id));
+ fb.SetParams(params);
+ if (fb.IsGeometryClosed())
+ {
+ HolesProcessor processor(p.id, m_holder);
+ m_holder.ForEachRelationByWay(p.id, processor);
+ fb.SetAreaAddHoles(processor.GetHoles());
+ }
+ else
+ {
+ fb.SetLinear(params.m_reverseGeometry);
+ }
+
+ m_queue.push(std::move(fb));
+ return true;
+}
+
+bool FeatureMakerSimple::BuildFromRelation(OsmElement & p, FeatureParams const & params)
+{
+ HolesRelation helper(m_holder);
+ helper.Build(&p);
+ auto const & holesGeometry = helper.GetHoles();
+ auto & outer = helper.GetOuter();
+ auto const size = m_queue.size();
+ auto const func = [&](FeatureBuilder1::PointSeq const & pts, std::vector<uint64_t> const & ids)
+ {
+ FeatureBuilder1 fb;
+ for (uint64_t id : ids)
+ fb.AddOsmId(base::MakeOsmWay(id));
+
+ for (auto const & pt : pts)
+ fb.AddPoint(pt);
+
+ fb.AddOsmId(base::MakeOsmRelation(p.id));
+ if (!fb.IsGeometryClosed())
+ return;
+
+ fb.SetAreaAddHoles(holesGeometry);
+ fb.SetParams(params);
+ m_queue.push(std::move(fb));
+ };
+
+ outer.ForEachArea(true /* collectID */, func);
+ return size != m_queue.size();
+}
+
+void FeatureMaker::ParseParams(FeatureParams & params, OsmElement & p) const
+{
+ ftype::GetNameAndType(&p, params);
+}
+} // namespace generator
diff --git a/generator/feature_maker.hpp b/generator/feature_maker.hpp
new file mode 100644
index 0000000000..9568a3627a
--- /dev/null
+++ b/generator/feature_maker.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "generator/feature_builder.hpp"
+#include "generator/feature_maker_base.hpp"
+
+struct OsmElement;
+
+namespace generator
+{
+// Class FeatureMakerSimple is class FeatureMakerBase implementation for simple features building.
+// It is only trying to build a feature and does not filter features in any way,
+// except for bad geometry. This class is suitable for most cases.
+class FeatureMakerSimple: public FeatureMakerBase
+{
+public:
+ using FeatureMakerBase::FeatureMakerBase;
+
+protected:
+ // FeatureMaker overrides:
+ void ParseParams(FeatureParams & params, OsmElement & p) const override;
+
+private:
+ // FeatureMaker overrides:
+ bool BuildFromNode(OsmElement & p, FeatureParams const & params) override;
+ bool BuildFromWay(OsmElement & p, FeatureParams const & params) override;
+ bool BuildFromRelation(OsmElement & p, FeatureParams const & params) override;
+};
+
+// The difference between class FeatureMakerSimple and class FeatureMaker is that
+// class FeatureMaker processes the types more strictly.
+class FeatureMaker : public FeatureMakerSimple
+{
+public:
+ using FeatureMakerSimple::FeatureMakerSimple;
+
+private:
+ // FeatureMaker overrides:
+ void ParseParams(FeatureParams & params, OsmElement & p) const override;
+};
+} // namespace generator
diff --git a/generator/feature_maker_base.cpp b/generator/feature_maker_base.cpp
new file mode 100644
index 0000000000..d8e15d1895
--- /dev/null
+++ b/generator/feature_maker_base.cpp
@@ -0,0 +1,80 @@
+#include "generator/feature_maker_base.hpp"
+
+#include "generator/osm_element.hpp"
+
+#include "base/assert.hpp"
+
+#include <utility>
+
+namespace generator
+{
+FeatureMakerBase::FeatureMakerBase(cache::IntermediateDataReader & holder) : m_holder(holder) {}
+
+bool FeatureMakerBase::Add(OsmElement & p)
+{
+ FeatureParams params;
+ ParseParams(params, p);
+ switch (p.type)
+ {
+ case OsmElement::EntityType::Node:
+ return BuildFromNode(p, params);
+ case OsmElement::EntityType::Way:
+ return BuildFromWay(p, params);
+ case OsmElement::EntityType::Relation:
+ return BuildFromRelation(p, params);
+ default:
+ return false;
+ }
+}
+
+size_t FeatureMakerBase::Size() const
+{
+ return m_queue.size();
+}
+
+bool FeatureMakerBase::Empty() const
+{
+ return m_queue.empty();
+}
+
+bool FeatureMakerBase::GetNextFeature(FeatureBuilder1 & feature)
+{
+ if (m_queue.empty())
+ return false;
+
+ feature = std::move(m_queue.front());
+ m_queue.pop();
+ return true;
+}
+
+
+void TransformAreaToPoint(FeatureBuilder1 & feature)
+{
+ CHECK(feature.IsArea(), ());
+ auto const center = feature.GetGeometryCenter();
+ auto const id = feature.GetLastOsmId();
+ feature.ResetGeometry();
+ feature.SetOsmId(id);
+ feature.SetCenter(center);
+}
+
+void TransformAreaToLine(FeatureBuilder1 & feature)
+{
+ CHECK(feature.IsArea(), ());
+ feature.SetLinear(feature.GetParams().m_reverseGeometry);
+}
+
+FeatureBuilder1 MakePointFromArea(FeatureBuilder1 const & feature)
+{
+ FeatureBuilder1 tmp(feature);
+ TransformAreaToPoint(tmp);
+ return tmp;
+}
+
+FeatureBuilder1 MakeLineFromArea(FeatureBuilder1 const & feature)
+{
+ FeatureBuilder1 tmp(feature);
+ TransformAreaToLine(tmp);
+ return tmp;
+}
+} // namespace generator
diff --git a/generator/feature_maker_base.hpp b/generator/feature_maker_base.hpp
new file mode 100644
index 0000000000..d026baf6d0
--- /dev/null
+++ b/generator/feature_maker_base.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "generator/feature_builder.hpp"
+
+#include <queue>
+
+struct OsmElement;
+
+namespace generator
+{
+namespace cache
+{
+class IntermediateDataReader;
+} // namespace cache
+
+// Abstract class FeatureMakerBase is responsible for the conversion OsmElement to FeatureBuilder1.
+// The main task of this class is to create features of the necessary types.
+// At least one feature should turn out from one OSM element. You can get several features from one element.
+class FeatureMakerBase
+{
+public:
+ explicit FeatureMakerBase(cache::IntermediateDataReader & holder);
+ virtual ~FeatureMakerBase() = default;
+
+ bool Add(OsmElement & p);
+ // The function returns true when the receiving feature was successful and a false when not successful.
+ bool GetNextFeature(FeatureBuilder1 & feature);
+ size_t Size() const;
+ bool Empty() const;
+
+protected:
+ virtual bool BuildFromNode(OsmElement & p, FeatureParams const & params) = 0;
+ virtual bool BuildFromWay(OsmElement & p, FeatureParams const & params) = 0;
+ virtual bool BuildFromRelation(OsmElement & p, FeatureParams const & params) = 0;
+
+ virtual void ParseParams(FeatureParams & params, OsmElement & p) const = 0;
+
+ cache::IntermediateDataReader & m_holder;
+ std::queue<FeatureBuilder1> m_queue;
+};
+
+void TransformAreaToPoint(FeatureBuilder1 & feature);
+void TransformAreaToLine(FeatureBuilder1 & feature);
+
+FeatureBuilder1 MakePointFromArea(FeatureBuilder1 const & feature);
+FeatureBuilder1 MakeLineFromArea(FeatureBuilder1 const & feature);
+} // namespace generator
diff --git a/generator/feature_processing_layers.cpp b/generator/feature_processing_layers.cpp
new file mode 100644
index 0000000000..74109bf146
--- /dev/null
+++ b/generator/feature_processing_layers.cpp
@@ -0,0 +1,396 @@
+#include "generator/feature_processing_layers.hpp"
+
+#include "generator/city_boundary_processor.hpp"
+#include "generator/coastlines_generator.hpp"
+#include "generator/feature_builder.hpp"
+#include "generator/feature_maker.hpp"
+#include "generator/generate_info.hpp"
+#include "generator/emitter_interface.hpp"
+#include "generator/type_helper.hpp"
+
+#include "indexer/feature_visibility.hpp"
+#include "indexer/ftypes_matcher.hpp"
+
+#include "base/assert.hpp"
+#include "base/geo_object_id.hpp"
+
+namespace generator
+{
+namespace
+{
+void FixLandType(FeatureBuilder1 & feature)
+{
+ auto const & types = feature.GetTypes();
+ auto const & isIslandChecker = ftypes::IsIslandChecker::Instance();
+ auto const & isLandChecker = ftypes::IsLandChecker::Instance();
+ auto const & isCoastlineChecker = ftypes::IsCoastlineChecker::Instance();
+ if (isCoastlineChecker(types))
+ {
+ feature.PopExactType(isLandChecker.GetLandType());
+ feature.PopExactType(isCoastlineChecker.GetCoastlineType());
+ }
+ else if (isIslandChecker(types) && feature.IsArea())
+ {
+ feature.AddType(isLandChecker.GetLandType());
+ }
+}
+} // namespace
+
+std::string LogBuffer::GetAsString() const
+{
+ return m_buffer.str();
+}
+
+void LayerBase::Handle(FeatureBuilder1 & feature)
+{
+ if (m_next)
+ m_next->Handle(feature);
+}
+
+void LayerBase::SetNext(std::shared_ptr<LayerBase> next)
+{
+ m_next = next;
+}
+
+std::shared_ptr<LayerBase> LayerBase::Add(std::shared_ptr<LayerBase> next)
+{
+ if (m_next)
+ m_next->Add(next);
+ else
+ m_next = next;
+
+ return next;
+}
+
+std::string LayerBase::GetAsString() const
+{
+ return m_logBuffer.GetAsString();
+}
+
+std::string LayerBase::GetAsStringRecursive() const
+{
+ std::ostringstream m_buffer;
+ auto temp = shared_from_this();
+ while (temp)
+ {
+ m_buffer << temp->GetAsString();
+ temp = temp->m_next;
+ }
+
+ return m_buffer.str();
+}
+
+RepresentationLayer::RepresentationLayer(std::shared_ptr<CityBoundaryProcessor> processor)
+ : m_processor(processor) {}
+
+void RepresentationLayer::Handle(FeatureBuilder1 & feature)
+{
+ auto const sourceType = feature.GetMostGenericOsmId().GetType();
+ auto const geomType = feature.GetGeomType();
+ // There is a copy of params here, if there is a reference here, then the params can be
+ // implicitly changed at other layers.
+ auto const params = feature.GetParams();
+ switch (sourceType)
+ {
+ case base::GeoObjectId::Type::ObsoleteOsmNode:
+ LayerBase::Handle(feature);
+ break;
+ case base::GeoObjectId::Type::ObsoleteOsmWay:
+ {
+ switch (geomType)
+ {
+ case feature::EGeomType::GEOM_AREA:
+ {
+ HandleArea(feature, params);
+ if (CanBeLine(params))
+ {
+ auto featureLine = MakeLineFromArea(feature);
+ LayerBase::Handle(featureLine);
+ }
+ break;
+ }
+ case feature::EGeomType::GEOM_LINE:
+ LayerBase::Handle(feature);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+ }
+ case base::GeoObjectId::Type::ObsoleteOsmRelation:
+ {
+ switch (geomType)
+ {
+ case feature::EGeomType::GEOM_AREA:
+ HandleArea(feature, params);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void RepresentationLayer::HandleArea(FeatureBuilder1 & feature, FeatureParams const & params)
+{
+ if (ftypes::IsCityTownOrVillage(params.m_types))
+ m_processor->Add(feature);
+
+ if (CanBeArea(params))
+ {
+ LayerBase::Handle(feature);
+ feature.SetParams(params);
+ }
+ else if (CanBePoint(params))
+ {
+ auto featurePoint = MakePointFromArea(feature);
+ LayerBase::Handle(featurePoint);
+ }
+}
+
+// static
+bool RepresentationLayer::CanBeArea(FeatureParams const & params)
+{
+ return feature::IsDrawableLike(params.m_types, feature::GEOM_AREA);
+}
+
+// static
+bool RepresentationLayer::CanBePoint(FeatureParams const & params)
+{
+ return feature::HasUsefulType(params.m_types, feature::GEOM_POINT);
+}
+
+// static
+bool RepresentationLayer::CanBeLine(FeatureParams const & params)
+{
+ return feature::HasUsefulType(params.m_types, feature::GEOM_LINE);
+}
+
+void PrepareFeatureLayer::Handle(FeatureBuilder1 & feature)
+{
+ auto const type = feature.GetGeomType();
+ auto const & types = feature.GetParams().m_types;
+ if (!feature::HasUsefulType(types, type))
+ return;
+
+ auto & params = feature.GetParams();
+ feature::RemoveUselessTypes(params.m_types, type);
+ feature.PreSerializeAndRemoveUselessNames();
+ FixLandType(feature);
+ LayerBase::Handle(feature);
+}
+
+CityBoundaryLayer::CityBoundaryLayer(std::shared_ptr<CityBoundaryProcessor> processor)
+ : m_processor(processor) {}
+
+void CityBoundaryLayer::Handle(FeatureBuilder1 & feature)
+{
+ auto const type = GetPlaceType(feature);
+ if (type != ftype::GetEmptyValue() && !feature.GetName().empty())
+ m_processor->Replace(feature);
+ else
+ LayerBase::Handle(feature);
+}
+
+BookingLayer::~BookingLayer()
+{
+ m_dataset.BuildOsmObjects([&] (FeatureBuilder1 & feature) {
+ m_countryMapper->RemoveInvalidTypesAndMap(feature);
+ });
+}
+
+BookingLayer::BookingLayer(std::string const & filename, std::shared_ptr<CountryMapper> countryMapper)
+ : m_dataset(filename), m_countryMapper(countryMapper) {}
+
+void BookingLayer::Handle(FeatureBuilder1 & feature)
+{
+ auto const id = m_dataset.FindMatchingObjectId(feature);
+ if (id == BookingHotel::InvalidObjectId())
+ {
+ LayerBase::Handle(feature);
+ return;
+ }
+
+ m_dataset.PreprocessMatchedOsmObject(id, feature, [&](FeatureBuilder1 & newFeature) {
+ AppendLine("BOOKING", DebugPrint(newFeature.GetMostGenericOsmId()), DebugPrint(id));
+ m_countryMapper->RemoveInvalidTypesAndMap(newFeature);
+ });
+}
+
+OpentableLayer::OpentableLayer(std::string const & filename, std::shared_ptr<CountryMapper> countryMapper)
+ : m_dataset(filename), m_countryMapper(countryMapper) {}
+
+void OpentableLayer::Handle(FeatureBuilder1 & feature)
+{
+ auto const id = m_dataset.FindMatchingObjectId(feature);
+ if (id == OpentableRestaurant::InvalidObjectId())
+ {
+ LayerBase::Handle(feature);
+ return;
+ }
+
+ m_dataset.PreprocessMatchedOsmObject(id, feature, [&](FeatureBuilder1 & newFeature) {
+ AppendLine("OPENTABLE", DebugPrint(newFeature.GetMostGenericOsmId()), DebugPrint(id));
+ m_countryMapper->RemoveInvalidTypesAndMap(newFeature);
+ });
+}
+
+CountryMapperLayer::CountryMapperLayer(std::shared_ptr<CountryMapper> countryMapper)
+ : m_countryMapper(countryMapper) {}
+
+void CountryMapperLayer::Handle(FeatureBuilder1 & feature)
+{
+ m_countryMapper->RemoveInvalidTypesAndMap(feature);
+ LayerBase::Handle(feature);
+}
+
+void RepresentationCoastlineLayer::Handle(FeatureBuilder1 & feature)
+{
+ auto const sourceType = feature.GetMostGenericOsmId().GetType();
+ auto const geomType = feature.GetGeomType();
+ switch (sourceType)
+ {
+ case base::GeoObjectId::Type::ObsoleteOsmNode:
+ break;
+ case base::GeoObjectId::Type::ObsoleteOsmWay:
+ {
+ switch (geomType)
+ {
+ case feature::EGeomType::GEOM_AREA:
+ LayerBase::Handle(feature);
+ break;
+ case feature::EGeomType::GEOM_LINE:
+ LayerBase::Handle(feature);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+ }
+ case base::GeoObjectId::Type::ObsoleteOsmRelation:
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void PrepareCoastlineFeatureLayer::Handle(FeatureBuilder1 & feature)
+{
+ if (feature.IsArea())
+ {
+ auto & params = feature.GetParams();
+ feature::RemoveUselessTypes(params.m_types, feature.GetGeomType());
+ }
+
+ feature.PreSerializeAndRemoveUselessNames();
+ LayerBase::Handle(feature);
+}
+
+CoastlineMapperLayer::CoastlineMapperLayer(std::shared_ptr<CoastlineFeaturesGenerator> coastlineMapper)
+ : m_coastlineGenerator(coastlineMapper) {}
+
+void CoastlineMapperLayer::Handle(FeatureBuilder1 & feature)
+{
+ auto const & isCoastlineChecker = ftypes::IsCoastlineChecker::Instance();
+ auto const kCoastType = isCoastlineChecker.GetCoastlineType();
+ feature.SetType(kCoastType);
+ m_coastlineGenerator->Process(feature);
+ LayerBase::Handle(feature);
+}
+
+WorldAreaLayer::WorldAreaLayer(std::shared_ptr<WorldMapper> mapper)
+ : m_mapper(mapper) {}
+
+
+WorldAreaLayer::~WorldAreaLayer()
+{
+ m_mapper->Merge();
+}
+
+void WorldAreaLayer::Handle(FeatureBuilder1 & feature)
+{
+ m_mapper->RemoveInvalidTypesAndMap(feature);
+ LayerBase::Handle(feature);
+}
+
+EmitCoastsLayer::EmitCoastsLayer(std::string const & worldCoastsFilename, std::string const & geometryFilename,
+ std::shared_ptr<CountryMapper> countryMapper)
+ : m_collector(std::make_shared<feature::FeaturesCollector>(worldCoastsFilename))
+ , m_countryMapper(countryMapper)
+ , m_geometryFilename(geometryFilename) {}
+
+EmitCoastsLayer::~EmitCoastsLayer()
+{
+ feature::ForEachFromDatRawFormat(m_geometryFilename, [&](FeatureBuilder1 fb, uint64_t)
+ {
+ auto & emitter = m_countryMapper->Parent();
+ emitter.Start();
+ m_countryMapper->Map(fb);
+ emitter.Finish();
+
+ fb.AddName("default", emitter.m_currentNames);
+ (*m_collector)(fb);
+ });
+}
+
+void EmitCoastsLayer::Handle(FeatureBuilder1 & feature)
+{
+ LayerBase::Handle(feature);
+}
+
+CountryMapper::CountryMapper(feature::GenerateInfo const & info)
+ : m_countries(std::make_unique<CountriesGenerator>(info)) {}
+
+void CountryMapper::Map(FeatureBuilder1 & feature)
+{
+ m_countries->Process(feature);
+}
+
+void CountryMapper::RemoveInvalidTypesAndMap(FeatureBuilder1 & feature)
+{
+ if (!feature.RemoveInvalidTypes())
+ return;
+
+ m_countries->Process(feature);
+}
+
+CountryMapper::Polygonizer & CountryMapper::Parent()
+{
+ return m_countries->Parent();
+}
+
+std::vector<std::string> const & CountryMapper::GetNames() const
+{
+ return m_countries->Parent().Names();
+}
+
+WorldMapper::WorldMapper(std::string const & worldFilename, std::string const & rawGeometryFilename,
+ std::string const & popularPlacesFilename)
+ : m_world(std::make_unique<WorldGenerator>(worldFilename, rawGeometryFilename, popularPlacesFilename)) {}
+
+void WorldMapper::Map(FeatureBuilder1 & feature)
+{
+ m_world->Process(feature);
+}
+
+void WorldMapper::RemoveInvalidTypesAndMap(FeatureBuilder1 & feature)
+{
+ if (!feature.RemoveInvalidTypes())
+ return;
+
+ m_world->Process(feature);
+}
+
+void WorldMapper::Merge()
+{
+ m_world->DoMerge();
+}
+} // namespace generator
diff --git a/generator/feature_processing_layers.hpp b/generator/feature_processing_layers.hpp
new file mode 100644
index 0000000000..af60293b25
--- /dev/null
+++ b/generator/feature_processing_layers.hpp
@@ -0,0 +1,275 @@
+#pragma once
+
+#include "generator/booking_dataset.hpp"
+#include "generator/feature_generator.hpp"
+#include "generator/opentable_dataset.hpp"
+#include "generator/polygonizer.hpp"
+#include "generator/world_map_generator.hpp"
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+class FeatureBuilder1;
+class CoastlineFeaturesGenerator;
+
+namespace feature
+{
+struct GenerateInfo;
+} // namespace feature
+
+namespace generator
+{
+class CityBoundaryProcessor;
+class CountryMapper;
+class WorldMapper;
+
+// Responsibility of the class Log Buffer - encapsulation of the buffer for internal logs.
+class LogBuffer
+{
+public:
+ template <class T, class... Ts>
+ void AppendLine(T const & value, Ts... rest)
+ {
+ AppendImpl(value, rest...);
+ // The last "\t" is overwritten here
+ m_buffer.seekp(-1, std::ios_base::end);
+ m_buffer << "\n";
+ }
+
+ std::string GetAsString() const;
+
+private:
+ template <class T, class... Ts>
+ void AppendImpl(T const & value, Ts... rest)
+ {
+ m_buffer << value << "\t";
+ AppendImpl(rest...);
+ }
+
+ void AppendImpl() {}
+
+ std::ostringstream m_buffer;
+};
+
+// This is the base layer class. Inheriting from it allows you to create a chain of layers.
+class LayerBase : public std::enable_shared_from_this<LayerBase>
+{
+public:
+ LayerBase() = default;
+ virtual ~LayerBase() = default;
+
+ // The function works in linear time from the number of layers that exist after that.
+ virtual void Handle(FeatureBuilder1 & feature);
+
+ void SetNext(std::shared_ptr<LayerBase> next);
+ std::shared_ptr<LayerBase> Add(std::shared_ptr<LayerBase> next);
+
+ template <class T, class... Ts>
+ constexpr void AppendLine(T const & value, Ts... rest)
+ {
+ m_logBuffer.AppendLine(value, rest...);
+ }
+
+ std::string GetAsString() const;
+ std::string GetAsStringRecursive() const;
+
+private:
+ LogBuffer m_logBuffer;
+ std::shared_ptr<LayerBase> m_next;
+};
+
+// Responsibility of class RepresentationLayer is converting features from one form to another for countries.
+// Here we can use the knowledge of the rules for drawing objects.
+// The class transfers control to the CityBoundaryProcessor if for the feature it is a city, town or village.
+// Osm object can be represented as feature of following geometry types: point, line, area depending on
+// its types and geometry. Sometimes one osm object can be represented as two features e.g. object with
+// closed geometry with types "leisure=playground" and "barrier=fence" splits into two objects: area object
+// with type "leisure=playground" and line object with type "barrier=fence".
+class RepresentationLayer : public LayerBase
+{
+public:
+ explicit RepresentationLayer(std::shared_ptr<CityBoundaryProcessor> processor);
+
+ // LayerBase overrides:
+ void Handle(FeatureBuilder1 & feature) override;
+
+private:
+ static bool CanBeArea(FeatureParams const & params);
+ static bool CanBePoint(FeatureParams const & params);
+ static bool CanBeLine(FeatureParams const & params);
+
+ void HandleArea(FeatureBuilder1 & feature, FeatureParams const & params);
+
+ std::shared_ptr<CityBoundaryProcessor> m_processor;
+};
+
+// Responsibility of class PrepareFeatureLayer is the removal of unused types and names,
+// as well as the preparation of features for further processing for countries.
+class PrepareFeatureLayer : public LayerBase
+{
+public:
+ // LayerBase overrides:
+ void Handle(FeatureBuilder1 & feature) override;
+};
+
+// Responsibility of class CityBoundaryLayer - transfering control to the CityBoundaryProcessor
+// if the feature is a place.
+class CityBoundaryLayer : public LayerBase
+{
+public:
+ explicit CityBoundaryLayer(std::shared_ptr<CityBoundaryProcessor> processor);
+
+ // LayerBase overrides:
+ void Handle(FeatureBuilder1 & feature) override;
+
+private:
+ std::shared_ptr<CityBoundaryProcessor> m_processor;
+};
+
+// Responsibility of class BookingLayer - mixing information from booking. If there is a
+// coincidence of the hotel and feature, the processing of the feature is performed.
+class BookingLayer : public LayerBase
+{
+public:
+ explicit BookingLayer(std::string const & filename, std::shared_ptr<CountryMapper> countryMapper);
+
+ // LayerBase overrides:
+ ~BookingLayer() override;
+
+ void Handle(FeatureBuilder1 & feature) override;
+
+private:
+ BookingDataset m_dataset;
+ std::shared_ptr<CountryMapper> m_countryMapper;
+};
+
+// Responsibility of class OpentableLayer - mixing information from opentable. If there is a
+// coincidence of the restaurant and feature, the processing of the feature is performed.
+class OpentableLayer : public LayerBase
+{
+public:
+ explicit OpentableLayer(std::string const & filename, std::shared_ptr<CountryMapper> countryMapper);
+
+ // LayerBase overrides:
+ void Handle(FeatureBuilder1 & feature) override;
+
+private:
+ OpentableDataset m_dataset;
+ std::shared_ptr<CountryMapper> m_countryMapper;
+};
+
+// Responsibility of class CountryMapperLayer - mapping of features to countries.
+class CountryMapperLayer : public LayerBase
+{
+public:
+ explicit CountryMapperLayer(std::shared_ptr<CountryMapper> countryMapper);
+
+ // LayerBase overrides:
+ void Handle(FeatureBuilder1 & feature) override;
+
+private:
+ std::shared_ptr<CountryMapper> m_countryMapper;
+};
+
+// Responsibility of class EmitCoastsLayer is adding coastlines to countries.
+class EmitCoastsLayer : public LayerBase
+{
+public:
+ explicit EmitCoastsLayer(std::string const & worldCoastsFilename, std::string const & geometryFilename,
+ std::shared_ptr<CountryMapper> countryMapper);
+
+ // LayerBase overrides:
+ ~EmitCoastsLayer() override;
+
+ void Handle(FeatureBuilder1 & feature) override;
+
+private:
+ std::shared_ptr<feature::FeaturesCollector> m_collector;
+ std::shared_ptr<CountryMapper> m_countryMapper;
+ std::string m_geometryFilename;
+};
+
+// Responsibility of class RepresentationCoastlineLayer is converting features from one form to
+// another for coastlines. Here we can use the knowledge of the rules for drawing objects.
+class RepresentationCoastlineLayer : public LayerBase
+{
+public:
+ // LayerBase overrides:
+ void Handle(FeatureBuilder1 & feature) override;
+};
+
+// Responsibility of class PrepareCoastlineFeatureLayer is the removal of unused types and names,
+// as well as the preparation of features for further processing for coastlines.
+class PrepareCoastlineFeatureLayer : public LayerBase
+{
+public:
+ // LayerBase overrides:
+ void Handle(FeatureBuilder1 & feature) override;
+};
+
+// Responsibility of class CoastlineMapperLayer - mapping of features on coastline.
+class CoastlineMapperLayer : public LayerBase
+{
+public:
+ explicit CoastlineMapperLayer(std::shared_ptr<CoastlineFeaturesGenerator> coastlineMapper);
+
+ // LayerBase overrides:
+ void Handle(FeatureBuilder1 & feature) override;
+
+private:
+ std::shared_ptr<CoastlineFeaturesGenerator> m_coastlineGenerator;
+};
+
+// Responsibility of class CountryMapperLayer - mapping of features on the world.
+class WorldAreaLayer : public LayerBase
+{
+public:
+ using WorldGenerator = WorldMapGenerator<feature::FeaturesCollector>;
+
+ explicit WorldAreaLayer(std::shared_ptr<WorldMapper> mapper);
+
+ // LayerBase overrides:
+ ~WorldAreaLayer() override;
+
+ void Handle(FeatureBuilder1 & feature) override;
+
+private:
+ std::shared_ptr<WorldMapper> m_mapper;
+};
+
+// This is the class-wrapper over CountriesGenerator class.
+class CountryMapper
+{
+public:
+ using Polygonizer = feature::Polygonizer<feature::FeaturesCollector>;
+ using CountriesGenerator = CountryMapGenerator<Polygonizer>;
+
+ explicit CountryMapper(feature::GenerateInfo const & info);
+
+ void Map(FeatureBuilder1 & feature);
+ void RemoveInvalidTypesAndMap(FeatureBuilder1 & feature);
+ Polygonizer & Parent();
+ std::vector<std::string> const & GetNames() const;
+
+private:
+ std::unique_ptr<CountriesGenerator> m_countries;
+};
+
+// This is the class-wrapper over WorldGenerator class.
+class WorldMapper
+{
+public:
+ using WorldGenerator = WorldMapGenerator<feature::FeaturesCollector>;
+
+ explicit WorldMapper(std::string const & worldFilename, std::string const & rawGeometryFilename,
+ std::string const & popularPlacesFilename);
+
+ void Map(FeatureBuilder1 & feature);
+ void RemoveInvalidTypesAndMap(FeatureBuilder1 & feature);
+ void Merge();
+
+private:
+ std::unique_ptr<WorldGenerator> m_world;
+};
+} // namespace generator
diff --git a/generator/filter_collection.cpp b/generator/filter_collection.cpp
new file mode 100644
index 0000000000..19873820c8
--- /dev/null
+++ b/generator/filter_collection.cpp
@@ -0,0 +1,23 @@
+#include "generator/filter_collection.hpp"
+
+#include "generator/feature_builder.hpp"
+#include "generator/osm_element.hpp"
+
+#include <algorithm>
+
+namespace generator
+{
+bool FilterCollection::IsAccepted(OsmElement const & element)
+{
+ return std::all_of(std::begin(m_collection), std::end(m_collection), [&] (auto & filter) {
+ return filter->IsAccepted(element);
+ });
+}
+
+bool FilterCollection::IsAccepted(FeatureBuilder1 const & feature)
+{
+ return std::all_of(std::begin(m_collection), std::end(m_collection), [&] (auto & filter) {
+ return filter->IsAccepted(feature);
+ });
+}
+} // namespace generator
diff --git a/generator/filter_collection.hpp b/generator/filter_collection.hpp
new file mode 100644
index 0000000000..bdb0afcce9
--- /dev/null
+++ b/generator/filter_collection.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "generator/collection_base.hpp"
+#include "generator/filter_interface.hpp"
+
+#include <memory>
+
+struct OsmElement;
+class FeatureBuilder1;
+namespace generator
+{
+// This class allows you to work with a group of filters as with one.
+class FilterCollection : public CollectionBase<std::shared_ptr<FilterInterface>>, public FilterInterface
+{
+public:
+ // FilterInterface overrides:
+ bool IsAccepted(OsmElement const & element) override;
+ bool IsAccepted(FeatureBuilder1 const & feature) override;
+};
+} // namespace generator
diff --git a/generator/filter_elements.cpp b/generator/filter_elements.cpp
index ce87770a69..c36d963e5a 100644
--- a/generator/filter_elements.cpp
+++ b/generator/filter_elements.cpp
@@ -160,6 +160,11 @@ FilterElements::FilterElements(std::string const & filename)
LOG(LERROR, ("Cannot parse file", filename));
}
+bool FilterElements::IsAccepted(OsmElement const & element)
+{
+ return !NeedSkip(element);
+}
+
bool FilterElements::NeedSkip(OsmElement const & element) const
{
switch (element.type)
diff --git a/generator/filter_elements.hpp b/generator/filter_elements.hpp
index 081c5592c7..3ab8b4e675 100644
--- a/generator/filter_elements.hpp
+++ b/generator/filter_elements.hpp
@@ -33,6 +33,7 @@
// (https://wiki.openstreetmap.org/wiki/Multiple_values).
#pragma once
+#include "generator/filter_interface.hpp"
#include "generator/osm_element.hpp"
#include <cstdint>
@@ -68,11 +69,14 @@ private:
};
// This is the main class that implements the element skipping mechanism.
-class FilterElements
+class FilterElements : public FilterInterface
{
public:
explicit FilterElements(const std::string & filename);
+ // FilterInterface overrides:
+ bool IsAccepted(OsmElement const & element) override;
+
bool NeedSkip(OsmElement const & element) const;
private:
diff --git a/generator/filter_interface.hpp b/generator/filter_interface.hpp
new file mode 100644
index 0000000000..fec8cdceff
--- /dev/null
+++ b/generator/filter_interface.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+struct OsmElement;
+class FeatureBuilder1;
+
+namespace generator
+{
+// Implementing this interface allows an object to filter OsmElement and FeatureBuilder1 elements.
+class FilterInterface
+{
+public:
+ virtual ~FilterInterface() = default;
+
+ virtual bool IsAccepted(OsmElement const &) { return true; }
+ virtual bool IsAccepted(FeatureBuilder1 const &) { return true; }
+};
+} // namespace generator
diff --git a/generator/filter_planet.cpp b/generator/filter_planet.cpp
new file mode 100644
index 0000000000..e477976d28
--- /dev/null
+++ b/generator/filter_planet.cpp
@@ -0,0 +1,31 @@
+#include "generator/filter_planet.hpp"
+
+#include "generator/feature_builder.hpp"
+#include "generator/osm_element.hpp"
+
+#include "indexer/classificator.hpp"
+#include "indexer/feature_visibility.hpp"
+#include "indexer/ftypes_matcher.hpp"
+
+#include "base/assert.hpp"
+
+#include <algorithm>
+
+namespace generator
+{
+bool FilterPlanet::IsAccepted(OsmElement const & element)
+{
+ if (element.IsRelation())
+ return element.HasAnyTag({{"type", "multipolygon"}, {"type", "boundary"}});
+ if (element.IsNode())
+ return !element.m_tags.empty();
+
+ return true;
+}
+
+bool FilterPlanet::IsAccepted(FeatureBuilder1 const & feature)
+{
+ auto const & params = feature.GetParams();
+ return params.IsValid();
+}
+} // namespace generator
diff --git a/generator/filter_planet.hpp b/generator/filter_planet.hpp
new file mode 100644
index 0000000000..e1055596ef
--- /dev/null
+++ b/generator/filter_planet.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "generator/filter_interface.hpp"
+
+namespace generator
+{
+class FilterPlanet : public FilterInterface
+{
+public:
+ bool IsAccepted(OsmElement const & element) override;
+ bool IsAccepted(FeatureBuilder1 const & feature) override;
+};
+} // namespace generator
diff --git a/generator/generator_tests/common.cpp b/generator/generator_tests/common.cpp
index 7ca55f6cbd..a3bfaf09be 100644
--- a/generator/generator_tests/common.cpp
+++ b/generator/generator_tests/common.cpp
@@ -8,15 +8,9 @@ namespace generator_tests
{
OsmElement MakeOsmElement(uint64_t id, Tags const & tags, OsmElement::EntityType t)
{
- OsmElement el = MakeOsmElement(id, tags);
- el.type = t;
- return el;
-}
-
-OsmElement MakeOsmElement(uint64_t id, Tags const & tags)
-{
OsmElement el;
el.id = id;
+ el.type = t;
for (auto const & t : tags)
el.AddTag(t.first, t.second);
diff --git a/generator/generator_tests/common.hpp b/generator/generator_tests/common.hpp
index 7efcc58643..929191fc0d 100644
--- a/generator/generator_tests/common.hpp
+++ b/generator/generator_tests/common.hpp
@@ -10,7 +10,6 @@ namespace generator_tests
using Tags = std::vector<std::pair<std::string, std::string>>;
OsmElement MakeOsmElement(uint64_t id, Tags const & tags, OsmElement::EntityType t);
-OsmElement MakeOsmElement(uint64_t id, Tags const & tags);
std::string GetFileName();
} // generator_tests
diff --git a/generator/generator_tests/osm_type_test.cpp b/generator/generator_tests/osm_type_test.cpp
index 9c7a96a045..d7ec7f5e42 100644
--- a/generator/generator_tests/osm_type_test.cpp
+++ b/generator/generator_tests/osm_type_test.cpp
@@ -262,7 +262,7 @@ UNIT_CLASS_TEST(TestWithClassificator, OsmType_Synonyms)
FillXmlElement(arr, ARRAY_SIZE(arr), &e);
TagReplacer tagReplacer(GetPlatform().ResourcesDir() + REPLACED_TAGS_FILE);
- tagReplacer(&e);
+ tagReplacer(e);
FeatureParams params;
ftype::GetNameAndType(&e, params);
@@ -823,7 +823,7 @@ UNIT_CLASS_TEST(TestWithClassificator, OsmType_Entrance)
FillXmlElement(arr, ARRAY_SIZE(arr), &e);
TagReplacer tagReplacer(GetPlatform().ResourcesDir() + REPLACED_TAGS_FILE);
- tagReplacer(&e);
+ tagReplacer(e);
FeatureParams params;
ftype::GetNameAndType(&e, params);
diff --git a/generator/generator_tests/region_info_collector_tests.cpp b/generator/generator_tests/region_info_collector_tests.cpp
index e40c6f7625..54c8fab9d8 100644
--- a/generator/generator_tests/region_info_collector_tests.cpp
+++ b/generator/generator_tests/region_info_collector_tests.cpp
@@ -1,5 +1,6 @@
#include "testing/testing.hpp"
+#include "generator/feature_builder.hpp"
#include "generator/generator_tests/common.hpp"
#include "generator/osm_element.hpp"
#include "generator/regions/collector_region_info.hpp"
@@ -24,23 +25,25 @@ using namespace base;
namespace
{
auto const kNotExistingId = std::numeric_limits<uint64_t>::max();
-auto const kOsmElementEmpty = MakeOsmElement(0, {});
+auto const kOsmElementEmpty = MakeOsmElement(0, {}, OsmElement::EntityType::Relation);
auto const kOsmElementCity = MakeOsmElement(1, {{"place", "city"},
- {"admin_level", "6"}});
+ {"admin_level", "6"}},
+ OsmElement::EntityType::Relation);
auto const kOsmElementCountry = MakeOsmElement(2, {{"admin_level", "2"},
{"ISO3166-1:alpha2", "RU"},
{"ISO3166-1:alpha3", "RUS"},
- {"ISO3166-1:numeric", "643"}});
-
+ {"ISO3166-1:numeric", "643"}},
+ OsmElement::EntityType::Relation);
+FeatureBuilder1 const kEmptyFeature;
} // namespace
UNIT_TEST(RegionInfoCollector_Collect)
{
auto const filename = GetFileName();
CollectorRegionInfo regionInfoCollector(filename);
- regionInfoCollector.Collect(MakeOsmRelation(kOsmElementCity.id), kOsmElementCity);
- regionInfoCollector.Collect(MakeOsmRelation(kOsmElementCountry.id), kOsmElementCountry);
- regionInfoCollector.Collect(MakeOsmRelation(kOsmElementEmpty.id), kOsmElementEmpty);
+ regionInfoCollector.CollectFeature(kEmptyFeature, kOsmElementCity);
+ regionInfoCollector.CollectFeature(kEmptyFeature, kOsmElementCountry);
+ regionInfoCollector.CollectFeature(kEmptyFeature, kOsmElementEmpty);
regionInfoCollector.Save();
RegionInfo regionInfo(filename);
@@ -83,7 +86,7 @@ UNIT_TEST(RegionInfoCollector_Get)
{
auto const filename = GetFileName();
CollectorRegionInfo regionInfoCollector(filename);
- regionInfoCollector.Collect(MakeOsmRelation(kOsmElementCity.id), kOsmElementCity);
+ regionInfoCollector.CollectFeature(kEmptyFeature, kOsmElementCity);
regionInfoCollector.Save();
RegionInfo regionInfo(filename);
@@ -97,8 +100,8 @@ UNIT_TEST(RegionInfoCollector_Exists)
{
auto const filename = GetFileName();
CollectorRegionInfo regionInfoCollector(filename);
- regionInfoCollector.Collect(MakeOsmRelation(kOsmElementCity.id), kOsmElementCity);
- regionInfoCollector.Collect(MakeOsmRelation(kOsmElementCountry.id), kOsmElementCountry);
+ regionInfoCollector.CollectFeature(kEmptyFeature, kOsmElementCity);
+ regionInfoCollector.CollectFeature(kEmptyFeature, kOsmElementCountry);
regionInfoCollector.Save();
RegionInfo regionInfo(filename);
diff --git a/generator/generator_tests/regions_tests.cpp b/generator/generator_tests/regions_tests.cpp
index e1a3cca236..d2b55568b8 100644
--- a/generator/generator_tests/regions_tests.cpp
+++ b/generator/generator_tests/regions_tests.cpp
@@ -1,5 +1,6 @@
#include "testing/testing.hpp"
+#include "generator/feature_builder.hpp"
#include "generator/generator_tests/common.hpp"
#include "generator/osm_element.hpp"
#include "generator/regions/collector_region_info.hpp"
@@ -29,11 +30,14 @@ namespace
{
using Tags = std::vector<std::pair<std::string, std::string>>;
-OsmElement MakeOsmElement(uint64_t id, std::string const & adminLevel,
+FeatureBuilder1 const kEmptyFeature;
+
+OsmElement CreateOsmRelation(uint64_t id, std::string const & adminLevel,
std::string const & place = "")
{
OsmElement el;
el.id = id;
+ el.type = OsmElement::EntityType::Relation;
el.AddTag("place", place);
el.AddTag("admin_level", adminLevel);
@@ -44,14 +48,14 @@ std::string MakeCollectorData()
{
auto const filename = GetFileName();
CollectorRegionInfo collector(filename);
- collector.Collect(MakeOsmRelation(1 /* id */), MakeOsmElement(1 /* id */, "2" /* adminLevel */));
- collector.Collect(MakeOsmRelation(2 /* id */), MakeOsmElement(2 /* id */, "2" /* adminLevel */));
- collector.Collect(MakeOsmRelation(3 /* id */), MakeOsmElement(3 /* id */, "4" /* adminLevel */));
- collector.Collect(MakeOsmRelation(4 /* id */), MakeOsmElement(4 /* id */, "4" /* adminLevel */));
- collector.Collect(MakeOsmRelation(5 /* id */), MakeOsmElement(5 /* id */, "4" /* adminLevel */));
- collector.Collect(MakeOsmRelation(6 /* id */), MakeOsmElement(6 /* id */, "6" /* adminLevel */));
- collector.Collect(MakeOsmRelation(7 /* id */), MakeOsmElement(7 /* id */, "6" /* adminLevel */));
- collector.Collect(MakeOsmRelation(8 /* id */), MakeOsmElement(8 /* id */, "4" /* adminLevel */));
+ collector.CollectFeature(kEmptyFeature, CreateOsmRelation(1 /* id */, "2" /* adminLevel */));
+ collector.CollectFeature(kEmptyFeature, CreateOsmRelation(2 /* id */, "2" /* adminLevel */));
+ collector.CollectFeature(kEmptyFeature, CreateOsmRelation(3 /* id */, "4" /* adminLevel */));
+ collector.CollectFeature(kEmptyFeature, CreateOsmRelation(4 /* id */, "4" /* adminLevel */));
+ collector.CollectFeature(kEmptyFeature, CreateOsmRelation(5 /* id */, "4" /* adminLevel */));
+ collector.CollectFeature(kEmptyFeature, CreateOsmRelation(6 /* id */, "6" /* adminLevel */));
+ collector.CollectFeature(kEmptyFeature, CreateOsmRelation(7 /* id */, "6" /* adminLevel */));
+ collector.CollectFeature(kEmptyFeature, CreateOsmRelation(8 /* id */, "4" /* adminLevel */));
collector.Save();
return filename;
}
diff --git a/generator/generator_tests/speed_cameras_test.cpp b/generator/generator_tests/speed_cameras_test.cpp
index 66b714a668..6355e346cd 100644
--- a/generator/generator_tests/speed_cameras_test.cpp
+++ b/generator/generator_tests/speed_cameras_test.cpp
@@ -9,6 +9,8 @@
#include "generator/maxspeeds_parser.hpp"
#include "generator/metalines_builder.hpp"
#include "generator/osm_source.hpp"
+#include "generator/translator_collection.hpp"
+#include "generator/translator_factory.hpp"
#include "routing/speed_camera_ser_des.hpp"
@@ -164,7 +166,7 @@ void TestSpeedCameraSectionBuilding(string const & osmContent, CameraMap const &
genInfo.m_osmFileName = base::JoinPath(tmpDir, osmRelativePath);
genInfo.m_osmFileType = feature::GenerateInfo::OsmSourceType::XML;
- TEST(GenerateIntermediateData(genInfo), ("Can not generate intermediate data for speed cam"));
+ TEST(GenerateIntermediateData(genInfo), ("Cannot generate intermediate data for speed cam"));
// Building empty mwm.
LocalCountryFile country(base::JoinPath(tmpDir, kTestDir), CountryFile(kTestMwm), 0 /* version */);
@@ -173,8 +175,11 @@ void TestSpeedCameraSectionBuilding(string const & osmContent, CameraMap const &
// Step 2. Generate binary file about cameras.
{
- auto emitter = CreateEmitter(EmitterType::Planet, genInfo);
- TEST(GenerateFeatures(genInfo, emitter), ("Can not generate features for speed camera"));
+ CacheLoader cacheLoader(genInfo);
+ TranslatorCollection translators;
+ auto emitter = CreateEmitter(EmitterType::Country, genInfo);
+ translators.Append(CreateTranslator(TranslatorType::Country, emitter, cacheLoader.GetCache(), genInfo));
+ TEST(GenerateRaw(genInfo, translators), ("Cannot generate features for speed camera"));
}
TEST(GenerateFinalFeatures(genInfo, country.GetCountryName(),
diff --git a/generator/generator_tool/generator_tool.cpp b/generator/generator_tool/generator_tool.cpp
index 396cf98a90..107a6197a2 100644
--- a/generator/generator_tool/generator_tool.cpp
+++ b/generator/generator_tool/generator_tool.cpp
@@ -29,6 +29,8 @@
#include "generator/statistics.hpp"
#include "generator/traffic_generator.hpp"
#include "generator/transit_generator.hpp"
+#include "generator/translator_collection.hpp"
+#include "generator/translator_factory.hpp"
#include "generator/ugc_section_builder.hpp"
#include "generator/unpack_mwm.hpp"
#include "generator/wiki_url_dumper.hpp"
@@ -268,7 +270,7 @@ int GeneratorToolMain(int argc, char ** argv)
LOG(LINFO, ("Generating intermediate data ...."));
if (!GenerateIntermediateData(genInfo))
{
- return -1;
+ return EXIT_FAILURE;
}
}
@@ -296,12 +298,9 @@ int GeneratorToolMain(int argc, char ** argv)
countryParentGetter = make_unique<storage::CountryParentGetter>();
// Generate dat file.
- if (FLAGS_generate_features || FLAGS_make_coasts)
+ if (FLAGS_generate_features || FLAGS_make_coasts || FLAGS_generate_world)
{
LOG(LINFO, ("Generating final data ..."));
- CHECK(!FLAGS_generate_region_features, ("FLAGS_generate_features and FLAGS_make_coasts should "
- "not be used with FLAGS_generate_region_features"));
-
genInfo.m_splitByPolygons = FLAGS_split_by_polygons;
genInfo.m_createWorld = FLAGS_generate_world;
genInfo.m_makeCoasts = FLAGS_make_coasts;
@@ -310,9 +309,33 @@ int GeneratorToolMain(int argc, char ** argv)
genInfo.m_genAddresses = FLAGS_generate_addresses_file;
genInfo.m_idToWikidataFilename = FLAGS_idToWikidata;
- auto emitter = CreateEmitter(EmitterType::Planet, genInfo);
- if (!GenerateFeatures(genInfo, emitter))
- return -1;
+ CHECK(!(FLAGS_generate_features && FLAGS_make_coasts), ());
+ CHECK(!(FLAGS_generate_world && FLAGS_make_coasts), ());
+ if (FLAGS_dump_cities_boundaries)
+ CHECK(FLAGS_generate_features, ());
+
+ CacheLoader cacheLoader(genInfo);
+ TranslatorCollection translators;
+ if (FLAGS_generate_features)
+ {
+ auto emitter = CreateEmitter(EmitterType::Country, genInfo);
+ translators.Append(CreateTranslator(TranslatorType::Country, emitter, cacheLoader.GetCache(), genInfo));
+ }
+
+ if (FLAGS_generate_world)
+ {
+ auto emitter = CreateEmitter(EmitterType::World, genInfo);
+ translators.Append(CreateTranslator(TranslatorType::World, emitter, cacheLoader.GetCache(), genInfo));
+ }
+
+ if (FLAGS_make_coasts)
+ {
+ auto emitter = CreateEmitter(EmitterType::Coastline, genInfo);
+ translators.Append(CreateTranslator(TranslatorType::Coastline, emitter, cacheLoader.GetCache()));
+ }
+
+ if (!GenerateRaw(genInfo, translators))
+ return EXIT_FAILURE;
if (FLAGS_generate_world)
{
@@ -331,8 +354,7 @@ int GeneratorToolMain(int argc, char ** argv)
}
}
}
-
- if (FLAGS_generate_region_features || FLAGS_generate_geo_objects_features)
+ else if (FLAGS_generate_region_features || FLAGS_generate_geo_objects_features)
{
CHECK(!FLAGS_generate_features && !FLAGS_make_coasts,
("FLAGS_generate_features and FLAGS_make_coasts should "
@@ -340,17 +362,23 @@ int GeneratorToolMain(int argc, char ** argv)
CHECK(!(FLAGS_generate_region_features && FLAGS_generate_geo_objects_features), ());
genInfo.m_fileName = FLAGS_output;
+
+ CacheLoader cacheLoader(genInfo);
+ TranslatorCollection translators;
if (FLAGS_generate_region_features)
{
- if (!GenerateRegionFeatures(genInfo))
- return -1;
+ auto emitter = CreateEmitter(EmitterType::SimpleWithPreserialize, genInfo);
+ translators.Append(CreateTranslator(TranslatorType::Regions, emitter, cacheLoader.GetCache(), genInfo));
}
if (FLAGS_generate_geo_objects_features)
{
- if (!GenerateGeoObjectsFeatures(genInfo))
- return -1;
+ auto emitter = CreateEmitter(EmitterType::SimpleWithPreserialize, genInfo);
+ translators.Append(CreateTranslator(TranslatorType::GeoObjects, emitter, cacheLoader.GetCache()));
}
+
+ if (!GenerateRaw(genInfo, translators))
+ return EXIT_FAILURE;
}
if (!FLAGS_geo_objects_key_value.empty())
@@ -358,7 +386,7 @@ int GeneratorToolMain(int argc, char ** argv)
if (!geo_objects::GenerateGeoObjects(FLAGS_regions_index, FLAGS_regions_key_value,
FLAGS_geo_objects_features, FLAGS_ids_without_addresses,
FLAGS_geo_objects_key_value, FLAGS_verbose))
- return -1;
+ return EXIT_FAILURE;
}
if (genInfo.m_bucketNames.empty() && !FLAGS_output.empty())
@@ -369,7 +397,7 @@ int GeneratorToolMain(int argc, char ** argv)
if (FLAGS_output.empty())
{
LOG(LCRITICAL, ("Bad output or intermediate_data_path. Output:", FLAGS_output));
- return -1;
+ return EXIT_FAILURE;
}
auto const locDataFile = base::JoinPath(path, FLAGS_output + LOC_DATA_FILE_EXTENSION);
@@ -379,7 +407,7 @@ int GeneratorToolMain(int argc, char ** argv)
if (!feature::GenerateGeoObjectsData(FLAGS_geo_objects_features, FLAGS_nodes_list_path, locDataFile))
{
LOG(LCRITICAL, ("Error generating geo objects data."));
- return -1;
+ return EXIT_FAILURE;
}
LOG(LINFO, ("Saving geo objects index to", outFile));
@@ -387,7 +415,7 @@ int GeneratorToolMain(int argc, char ** argv)
if (!indexer::BuildGeoObjectsIndexFromDataFile(locDataFile, outFile))
{
LOG(LCRITICAL, ("Error generating geo objects index."));
- return -1;
+ return EXIT_FAILURE;
}
}
@@ -396,7 +424,7 @@ int GeneratorToolMain(int argc, char ** argv)
if (!feature::GenerateRegionsData(FLAGS_regions_features, locDataFile))
{
LOG(LCRITICAL, ("Error generating regions data."));
- return -1;
+ return EXIT_FAILURE;
}
LOG(LINFO, ("Saving regions index to", outFile));
@@ -404,12 +432,12 @@ int GeneratorToolMain(int argc, char ** argv)
if (!indexer::BuildRegionsIndexFromDataFile(locDataFile, outFile))
{
LOG(LCRITICAL, ("Error generating regions index."));
- return -1;
+ return EXIT_FAILURE;
}
if (!feature::GenerateBorders(FLAGS_regions_features, outFile))
{
LOG(LCRITICAL, ("Error generating regions borders."));
- return -1;
+ return EXIT_FAILURE;
}
}
}
@@ -551,7 +579,7 @@ int GeneratorToolMain(int argc, char ** argv)
// All the mwms should use proper VehicleModels.
LOG(LCRITICAL, ("Countries file is needed. Please set countries file name (countries.txt or "
"countries_obsolete.txt). File must be located in data directory."));
- return -1;
+ return EXIT_FAILURE;
}
string const restrictionsFilename =
@@ -589,7 +617,7 @@ int GeneratorToolMain(int argc, char ** argv)
// All the mwms should use proper VehicleModels.
LOG(LCRITICAL, ("Countries file is needed. Please set countries file name (countries.txt or "
"countries_obsolete.txt). File must be located in data directory."));
- return -1;
+ return EXIT_FAILURE;
}
if (FLAGS_make_cross_mwm)
diff --git a/generator/maxspeeds_collector.cpp b/generator/maxspeeds_collector.cpp
index bb7235819a..3b56ca9737 100644
--- a/generator/maxspeeds_collector.cpp
+++ b/generator/maxspeeds_collector.cpp
@@ -32,8 +32,11 @@ bool ParseMaxspeedAndWriteToStream(string const & maxspeed, SpeedInUnits & speed
namespace generator
{
-void MaxspeedsCollector::Process(OsmElement const & p)
+void MaxspeedsCollector::CollectFeature(FeatureBuilder1 const &, OsmElement const & p)
{
+ if (!p.IsWay())
+ return;
+
ostringstream ss;
ss << p.id << ",";
@@ -95,6 +98,11 @@ void MaxspeedsCollector::Process(OsmElement const & p)
m_data.push_back(ss.str());
}
+void MaxspeedsCollector::Save()
+{
+ Flush();
+}
+
void MaxspeedsCollector::Flush()
{
LOG(LINFO, ("Saving maxspeed tag values to", m_filePath));
diff --git a/generator/maxspeeds_collector.hpp b/generator/maxspeeds_collector.hpp
index 0a7d3cadc2..b1961e3366 100644
--- a/generator/maxspeeds_collector.hpp
+++ b/generator/maxspeeds_collector.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "generator/collector_interface.hpp"
#include "generator/osm_element.hpp"
#include <string>
@@ -10,14 +11,15 @@ namespace generator
/// \brief Collects all maxspeed tags value and saves them to a csv file.
/// Every line describes maxspeed, maxspeed:forward and maxspeed:backward
/// tags of features. The format of the lines is described below.
-class MaxspeedsCollector
+class MaxspeedsCollector : public CollectorInterface
{
public:
/// \param filePath path to csv file.
explicit MaxspeedsCollector(std::string const & filePath) : m_filePath(filePath) {}
- ~MaxspeedsCollector() { Flush(); }
- void Process(OsmElement const & p);
+ // CollectorInterface overrides:
+ void CollectFeature(FeatureBuilder1 const &, OsmElement const & p) override;
+ void Save() override;
private:
void Flush();
diff --git a/generator/metalines_builder.cpp b/generator/metalines_builder.cpp
index 8569726bde..4a7a263925 100644
--- a/generator/metalines_builder.cpp
+++ b/generator/metalines_builder.cpp
@@ -140,11 +140,15 @@ public:
};
// MetalinesBuilder --------------------------------------------------------------------------------
-void MetalinesBuilder::operator()(OsmElement const & el, FeatureParams const & params)
+void MetalinesBuilder::CollectFeature(FeatureBuilder1 const & feature, OsmElement const & element)
{
+ if (!feature.IsLine())
+ return;
+
+ auto const & params = feature.GetParams();
static uint32_t const highwayType = classif().GetTypeByPath({"highway"});
if (params.FindType(highwayType, 1) == ftype::GetEmptyValue() ||
- el.Nodes().front() == el.Nodes().back())
+ element.Nodes().front() == element.Nodes().back())
{
return;
}
@@ -157,9 +161,14 @@ void MetalinesBuilder::operator()(OsmElement const & el, FeatureParams const & p
size_t const key = std::hash<std::string>{}(name + '\0' + params.ref);
auto segment = m_data.find(key);
if (segment == m_data.cend())
- m_data.emplace(key, std::make_shared<Segments>(el));
+ m_data.emplace(key, std::make_shared<Segments>(element));
else
- segment->second->Add(el);
+ segment->second->Add(element);
+}
+
+void MetalinesBuilder::Save()
+{
+ Flush();
}
void MetalinesBuilder::Flush()
diff --git a/generator/metalines_builder.hpp b/generator/metalines_builder.hpp
index bf7e160d30..a42e8aa148 100644
--- a/generator/metalines_builder.hpp
+++ b/generator/metalines_builder.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "generator/collector_interface.hpp"
#include "generator/feature_builder.hpp"
#include "generator/osm_element.hpp"
@@ -13,15 +14,16 @@ namespace feature
class Segments;
/// Merges road segments with similar name and ref values into groups called metalines.
-class MetalinesBuilder
+class MetalinesBuilder : public generator::CollectorInterface
{
public:
explicit MetalinesBuilder(std::string const & filePath) : m_filePath(filePath) {}
- ~MetalinesBuilder() { Flush(); }
-
+ // CollectorInterface overrides:
/// Add a highway segment to the collection of metalines.
- void operator()(OsmElement const & el, FeatureParams const & params);
+ void CollectFeature(FeatureBuilder1 const & feature, OsmElement const & element) override;
+
+ void Save() override;
/// Write all metalines to the intermediate file.
void Flush();
diff --git a/generator/osm_element.cpp b/generator/osm_element.cpp
index dbcdb2cee7..d44fbe6e17 100644
--- a/generator/osm_element.cpp
+++ b/generator/osm_element.cpp
@@ -70,13 +70,27 @@ void OsmElement::AddTag(std::string const & k, std::string const & v)
m_tags.emplace_back(k, value);
}
-bool OsmElement::HasTagValue(std::string const & k, std::string const & v) const
+bool OsmElement::HasTag(std::string const & k, std::string const & v) const
{
return std::any_of(m_tags.begin(), m_tags.end(), [&](auto const & t) {
return t.key == k && t.value == v;
});
}
+bool OsmElement::HasAnyTag(std::unordered_multimap<std::string, std::string> const & tags) const
+{
+ return std::any_of(std::begin(m_tags), std::end(m_tags), [&](auto const & t) {
+ auto beginEnd = tags.equal_range(t.key);
+ for (auto it = beginEnd.first; it != beginEnd.second; ++it)
+ {
+ if (it->second == t.value)
+ return true;
+ }
+
+ return false;
+ });
+}
+
std::string OsmElement::ToString(std::string const & shift) const
{
std::stringstream ss;
diff --git a/generator/osm_element.hpp b/generator/osm_element.hpp
index dca542b96c..f4ae77f646 100644
--- a/generator/osm_element.hpp
+++ b/generator/osm_element.hpp
@@ -35,7 +35,7 @@ struct OsmElement
Member() = default;
Member(uint64_t ref, EntityType type, std::string const & role)
- : ref(ref), type(type), role(role)
+ : ref(ref), type(type), role(role)
{}
bool operator == (Member const & e) const
@@ -120,17 +120,17 @@ struct OsmElement
bool operator==(OsmElement const & e) const
{
return type == e.type
- && id == e.id
- && base::AlmostEqualAbs(lon, e.lon, 1e-7)
- && base::AlmostEqualAbs(lat, e.lat, 1e-7)
- && ref == e.ref
- && k == e.k
- && v == e.v
- && memberType == e.memberType
- && role == e.role
- && m_nds == e.m_nds
- && m_members == e.m_members
- && m_tags == e.m_tags;
+ && id == e.id
+ && base::AlmostEqualAbs(lon, e.lon, 1e-7)
+ && base::AlmostEqualAbs(lat, e.lat, 1e-7)
+ && ref == e.ref
+ && k == e.k
+ && v == e.v
+ && memberType == e.memberType
+ && role == e.role
+ && m_nds == e.m_nds
+ && m_members == e.m_members
+ && m_tags == e.m_tags;
}
void AddNd(uint64_t ref) { m_nds.emplace_back(ref); }
@@ -140,7 +140,8 @@ struct OsmElement
}
void AddTag(std::string const & k, std::string const & v);
- bool HasTagValue(std::string const & k, std::string const & v) const;
+ bool HasTag(std::string const & k, std::string const & v) const;
+ bool HasAnyTag(std::unordered_multimap<std::string, std::string> const & tags) const;
template <class Fn>
void UpdateTag(std::string const & k, Fn && fn)
diff --git a/generator/osm_source.cpp b/generator/osm_source.cpp
index d0585aae34..8cf6061950 100644
--- a/generator/osm_source.cpp
+++ b/generator/osm_source.cpp
@@ -1,35 +1,19 @@
#include "generator/osm_source.hpp"
#include "generator/camera_node_processor.hpp"
-#include "generator/cities_boundaries_builder.hpp"
-#include "generator/coastlines_generator.hpp"
-#include "generator/emitter_factory.hpp"
-#include "generator/feature_generator.hpp"
-#include "generator/filter_elements.hpp"
-#include "generator/intermediate_data.hpp"
#include "generator/intermediate_elements.hpp"
#include "generator/node_mixer.hpp"
#include "generator/osm_element.hpp"
#include "generator/osm_o5m_source.hpp"
#include "generator/osm_xml_source.hpp"
-#include "generator/polygonizer.hpp"
-#include "generator/regions/collector_region_info.hpp"
-#include "generator/tag_admixer.hpp"
#include "generator/towns_dumper.hpp"
-#include "generator/translator_factory.hpp"
-#include "generator/translator_interface.hpp"
-#include "generator/world_map_generator.hpp"
-#include "generator/booking_dataset.hpp"
-#include "generator/opentable_dataset.hpp"
-
-#include "indexer/city_boundary.hpp"
-#include "indexer/classificator.hpp"
#include "platform/platform.hpp"
#include "geometry/mercator.hpp"
#include "geometry/tree4d.hpp"
+#include "base/assert.hpp"
#include "base/stl_helpers.hpp"
#include "coding/file_name_utils.hpp"
@@ -227,121 +211,53 @@ void ProcessOsmElementsFromO5M(SourceReader & stream, function<void(OsmElement *
// Generate functions implementations.
///////////////////////////////////////////////////////////////////////////////////////////////////
-using PreEmit = function<bool(OsmElement *)>;
-
-// static
-static bool GenerateRaw(feature::GenerateInfo & info, PreEmit const & preEmit,
- std::vector<std::shared_ptr<TranslatorInterface>> translators)
+bool GenerateRaw(feature::GenerateInfo & info, TranslatorInterface & translators)
{
- // todo(maksimandrianov): Add support for multiple translators.
- CHECK_EQUAL(translators.size(), 1, ("Only one translator is supported."));
-
- try
- {
- auto const fn = [&](OsmElement * e) {
- if (!preEmit(e))
- return;
-
- for (auto & translator : translators)
- translator->EmitElement(e);
- };
-
- SourceReader reader = info.m_osmFileName.empty() ? SourceReader() : SourceReader(info.m_osmFileName);
- switch (info.m_osmFileType)
- {
- case feature::GenerateInfo::OsmSourceType::XML:
- ProcessOsmElementsFromXML(reader, fn);
- break;
- case feature::GenerateInfo::OsmSourceType::O5M:
- ProcessOsmElementsFromO5M(reader, fn);
- break;
- }
-
- LOG(LINFO, ("Processing", info.m_osmFileName, "done."));
-
- MixFakeNodes(GetPlatform().ResourcesDir() + MIXED_NODES_FILE, fn);
-
- // Stop if coasts are not merged and FLAG_fail_on_coasts is set
- for (auto & translator : translators)
- {
- if (!translator->Finish())
- return false;
- }
+ auto const fn = [&](OsmElement * e) {
+ CHECK(e, ());
+ auto & element = *e;
+ translators.Emit(element);
+ };
- for (auto & translator : translators)
- translator->GetNames(info.m_bucketNames);
- }
- catch (Reader::Exception const & ex)
+ SourceReader reader = info.m_osmFileName.empty() ? SourceReader() : SourceReader(info.m_osmFileName);
+ switch (info.m_osmFileType)
{
- LOG(LCRITICAL, ("Error with file", ex.Msg()));
+ case feature::GenerateInfo::OsmSourceType::XML:
+ ProcessOsmElementsFromXML(reader, fn);
+ break;
+ case feature::GenerateInfo::OsmSourceType::O5M:
+ ProcessOsmElementsFromO5M(reader, fn);
+ break;
}
+ LOG(LINFO, ("Processing", info.m_osmFileName, "done."));
+ MixFakeNodes(GetPlatform().ResourcesDir() + MIXED_NODES_FILE, fn);
+ if (!translators.Finish())
+ return false;
+
+ translators.GetNames(info.m_bucketNames);
return true;
}
-static cache::IntermediateDataReader LoadCache(feature::GenerateInfo & info)
+LoaderWrapper::LoaderWrapper(feature::GenerateInfo & info)
+ : m_reader(cache::CreatePointStorageReader(info.m_nodeStorageType, info.GetIntermediateFileName(NODES_FILE)), info)
{
- auto nodes = cache::CreatePointStorageReader(info.m_nodeStorageType,
- info.GetIntermediateFileName(NODES_FILE));
- cache::IntermediateDataReader cache(nodes, info);
- cache.LoadIndex();
- return cache;
+ m_reader.LoadIndex();
}
-bool GenerateFeatures(feature::GenerateInfo & info, shared_ptr<EmitterInterface> emitter)
+cache::IntermediateDataReader & LoaderWrapper::GetReader()
{
- TagAdmixer tagAdmixer(info.GetIntermediateFileName("ways", ".csv"),
- info.GetIntermediateFileName("towns", ".csv"));
- TagReplacer tagReplacer(GetPlatform().ResourcesDir() + REPLACED_TAGS_FILE);
- OsmTagMixer osmTagMixer(GetPlatform().ResourcesDir() + MIXED_TAGS_FILE);
- FilterElements filterElements(GetPlatform().ResourcesDir() + SKIPPED_ELEMENTS_FILE);
-
- auto preEmit = [&](OsmElement * e) {
- if (filterElements.NeedSkip(*e))
- return false;
-
- // Here we can add new tags to the elements!
- tagReplacer(e);
- tagAdmixer(e);
- osmTagMixer(e);
- return true;
- };
-
- auto cache = LoadCache(info);
- auto translator = CreateTranslator(TranslatorType::Planet, emitter, cache, info);
- return GenerateRaw(info, preEmit, {translator, });
+ return m_reader;
}
-bool GenerateRegionFeatures(feature::GenerateInfo & info)
-{
- auto const preEmit = [](OsmElement * e)
- {
- UNUSED_VALUE(e);
- return true;
- };
- auto cache = LoadCache(info);
- std::vector<std::shared_ptr<TranslatorInterface>> translators;
- auto emitter = CreateEmitter(EmitterType::Simple, info);
- auto const filename = info.GetTmpFileName(info.m_fileName, regions::CollectorRegionInfo::kDefaultExt);
- auto collector = std::make_shared<regions::CollectorRegionInfo>(filename);
- auto translator = CreateTranslator(TranslatorType::Region, emitter, cache, collector);
- translators.emplace_back(translator);
- return GenerateRaw(info, preEmit, translators);
-}
+CacheLoader::CacheLoader(feature::GenerateInfo & info) : m_info(info) {}
-bool GenerateGeoObjectsFeatures(feature::GenerateInfo & info)
+cache::IntermediateDataReader & CacheLoader::GetCache()
{
- auto const preEmit = [](OsmElement * e)
- {
- UNUSED_VALUE(e);
- return true;
- };
- auto cache = LoadCache(info);
- std::vector<std::shared_ptr<TranslatorInterface>> translators;
- auto emitter = CreateEmitter(EmitterType::Simple, info);
- auto translator = CreateTranslator(TranslatorType::GeoObjects, emitter, cache);
- translators.emplace_back(translator);
- return GenerateRaw(info, preEmit, translators);
+ if (!m_loader)
+ m_loader = std::make_unique<LoaderWrapper>(m_info);
+
+ return m_loader->GetReader();
}
bool GenerateIntermediateData(feature::GenerateInfo & info)
diff --git a/generator/osm_source.hpp b/generator/osm_source.hpp
index 853ed0307e..fd1ba1ae65 100644
--- a/generator/osm_source.hpp
+++ b/generator/osm_source.hpp
@@ -2,7 +2,8 @@
#include "generator/emitter_interface.hpp"
#include "generator/generate_info.hpp"
-#include "generator/osm_element.hpp"
+#include "generator/intermediate_data.hpp"
+#include "generator/translator_interface.hpp"
#include <functional>
#include <iostream>
@@ -11,6 +12,7 @@
#include <string>
#include <vector>
+struct OsmElement;
class FeatureBuilder1;
class FeatureParams;
@@ -39,7 +41,78 @@ public:
uint64_t Read(char * buffer, uint64_t bufferSize);
};
-bool GenerateFeatures(feature::GenerateInfo & info, std::shared_ptr<EmitterInterface> emitter);
+class LoaderWrapper
+{
+public:
+ LoaderWrapper(feature::GenerateInfo & info);
+ cache::IntermediateDataReader & GetReader();
+
+private:
+ cache::IntermediateDataReader m_reader;
+};
+
+class CacheLoader
+{
+public:
+ CacheLoader(feature::GenerateInfo & info);
+ cache::IntermediateDataReader & GetCache();
+
+private:
+ feature::GenerateInfo & m_info;
+ std::unique_ptr<LoaderWrapper> m_loader;
+
+ DISALLOW_COPY(CacheLoader);
+};
+
+
+// This function is needed to generate intermediate data from OSM elements.
+// The translators collection contains translators that translate the OSM element into
+// some intermediate representation.
+//
+// To better understand the generation process of this step,
+// we are looking at generation using the example of generation for countries.
+//
+// To start the generation we make the following calls:
+// 1. feature::GenerateInfo genInfo;
+// ...
+// 2. CacheLoader cacheLoader(genInfo);
+// 3. TranslatorCollection translators;
+// 4. auto emitter = CreateEmitter(EmitterType::Country, genInfo);
+// 5. translators.Append(CreateTranslator(TranslatorType::Country, emitter, cacheLoader.GetCache(), genInfo));
+// 6. GenerateRaw(genInfo, translators);
+//
+// In line 5, we create and add a translator for countries to the translator collection.
+// TranslatorCountry is inheritor of Translator.
+//
+// Translator contains several important entities: FeatureMaker, FilterCollection, CollectorCollection
+// and Emitter. In short,
+// * FeatureMaker - an object that can create FeatureBuilder1 from OSM element,
+// * FilterCollection - an object that contains a group of filters that may or may not pass OSM elements
+// and FeatureBuilder1s,
+// * CollectorCollection - an object that contains a group of collectors that collect additional
+// information about OSM elements and FeatureBuilder1s (most often it is information that cannot
+// be saved in FeatureBuilder1s from OSM element),
+// * Emitter - an object that converts an element and saves it.
+//
+// The most important method is Translator::Emit. Please read it to understand how generation works.
+// The order of calls is very important. First, the FilterCollection will filter the OSM elements,
+// then call the CollectorCollection for OSM elements, then build the FeatureBuilder1 element
+// form OSM element, then FilterCollection will filter the FeatureBuilder1, then call the
+// CollectorCollection for the FeatureBuilder1, and then FeatureBuilder1 will fall into the emitter.
+//
+// TranslatorCountry contains for it specific filters, collectors, emitter and FeatureMaker.
+// For example, there are FilterPlanet, which only passes relations with types multipolygon or boundary,
+// and CameraNodeProcessor, which collects information about the cameras on the roads.
+//
+// In line 4, we create emitter for countries.
+// The emitter is an important entity that needs to transform FeatureBuilder1 and save them in some way.
+// The emitter can filter objects and change the representation of an object based on drawing rules
+// and other application rules.
+// In EmitterCountry stages are divided into layers. The layers are connected in a chain.
+// For example, there are RepresentationLayer, which may change the presentation of the FeatureBuilder1
+// depending on the rules of the application, and BookingLayer, which mixes information from booking.
+// You can read a more detailed look into the appropriate class code.
+bool GenerateRaw(feature::GenerateInfo & info, TranslatorInterface & translators);
bool GenerateRegionFeatures(feature::GenerateInfo & info);
bool GenerateGeoObjectsFeatures(feature::GenerateInfo & info);
diff --git a/generator/place.cpp b/generator/place.cpp
index 4891973b2b..59874d0780 100644
--- a/generator/place.cpp
+++ b/generator/place.cpp
@@ -7,13 +7,16 @@
namespace generator
{
-Place::Place(FeatureBuilder1 const & ft, uint32_t type) :
+Place::Place(FeatureBuilder1 const & ft, uint32_t type, bool saveParams) :
m_ft(ft),
m_pt(ft.GetKeyPoint()),
m_type(type)
{
using namespace ftypes;
+ if (!saveParams)
+ m_ft.SetParams({}/* params */);
+
switch (IsLocalityChecker::Instance().GetType(m_type))
{
case COUNTRY: m_thresholdM = 300000.0; break;
diff --git a/generator/place.hpp b/generator/place.hpp
index fb9044071a..d26c6e85c6 100644
--- a/generator/place.hpp
+++ b/generator/place.hpp
@@ -13,7 +13,7 @@ namespace generator
class Place
{
public:
- Place(FeatureBuilder1 const & ft, uint32_t type);
+ Place(FeatureBuilder1 const & ft, uint32_t type, bool saveParams = true);
FeatureBuilder1 const & GetFeature() const { return m_ft; }
m2::RectD GetLimitRect() const;
diff --git a/generator/regions/collector_region_info.cpp b/generator/regions/collector_region_info.cpp
index df57c8964c..fcdc495ab0 100644
--- a/generator/regions/collector_region_info.cpp
+++ b/generator/regions/collector_region_info.cpp
@@ -37,8 +37,9 @@ PlaceType EncodePlaceType(std::string const & place)
CollectorRegionInfo::CollectorRegionInfo(std::string const & filename) : m_filename(filename) {}
-void CollectorRegionInfo::Collect(base::GeoObjectId const & osmId, OsmElement const & el)
+void CollectorRegionInfo::CollectFeature(const FeatureBuilder1 &, OsmElement const & el)
{
+ base::GeoObjectId const osmId = GetGeoObjectId(el);
RegionData regionData;
FillRegionData(osmId, el, regionData);
m_mapRegionData.emplace(osmId, regionData);
diff --git a/generator/regions/collector_region_info.hpp b/generator/regions/collector_region_info.hpp
index 975d85ee6c..33bfaf62ba 100644
--- a/generator/regions/collector_region_info.hpp
+++ b/generator/regions/collector_region_info.hpp
@@ -100,7 +100,7 @@ public:
CollectorRegionInfo(std::string const & filename);
// CollectorInterface overrides:
- void Collect(base::GeoObjectId const & osmId, OsmElement const & el) override;
+ void CollectFeature(FeatureBuilder1 const &, OsmElement const & el) override;
void Save() override;
private:
diff --git a/generator/relation_tags.cpp b/generator/relation_tags.cpp
index 32872adeb1..ba86d7c9b3 100644
--- a/generator/relation_tags.cpp
+++ b/generator/relation_tags.cpp
@@ -4,11 +4,7 @@
namespace generator
{
-RelationTagsBase::RelationTagsBase(routing::TagsProcessor & tagsProcessor) :
- m_routingTagsProcessor(tagsProcessor),
- m_cache(14 /* logCacheSize */)
-{
-}
+RelationTagsBase::RelationTagsBase() : m_cache(14 /* logCacheSize */) {}
void RelationTagsBase::Reset(uint64_t fID, OsmElement * p)
{
@@ -35,23 +31,12 @@ void RelationTagsBase::AddCustomTag(std::pair<std::string, std::string> const &
m_current->AddTag(p.first, p.second);
}
-RelationTagsNode::RelationTagsNode(routing::TagsProcessor & tagsProcessor) :
- RelationTagsBase(tagsProcessor)
-{
-}
-
void RelationTagsNode::Process(RelationElement const & e)
{
std::string const & type = e.GetType();
if (Base::IsSkipRelation(type))
return;
- if (type == "restriction")
- {
- m_routingTagsProcessor.m_restrictionWriter.Write(e);
- return;
- }
-
bool const processAssociatedStreet = type == "associatedStreet" &&
Base::IsKeyTagExists("addr:housenumber") &&
!Base::IsKeyTagExists("addr:street");
@@ -73,11 +58,6 @@ void RelationTagsNode::Process(RelationElement const & e)
}
}
-RelationTagsWay::RelationTagsWay(routing::TagsProcessor & routingTagsProcessor) :
- RelationTagsBase(routingTagsProcessor)
-{
-}
-
bool RelationTagsWay::IsAcceptBoundary(RelationElement const & e) const
{
std::string role;
@@ -117,12 +97,6 @@ void RelationTagsWay::Process(RelationElement const & e)
return;
}
- if (type == "restriction")
- {
- m_routingTagsProcessor.m_restrictionWriter.Write(e);
- return;
- }
-
if (type == "building")
{
// If this way has "outline" role, add [building=has_parts] type.
diff --git a/generator/relation_tags.hpp b/generator/relation_tags.hpp
index aa584f680a..fd4d4bd61a 100644
--- a/generator/relation_tags.hpp
+++ b/generator/relation_tags.hpp
@@ -20,9 +20,8 @@ namespace generator
class RelationTagsBase
{
public:
- explicit RelationTagsBase(routing::TagsProcessor & tagsProcessor);
-
- virtual ~RelationTagsBase() {}
+ RelationTagsBase();
+ virtual ~RelationTagsBase() = default;
void Reset(uint64_t fID, OsmElement * p);
@@ -46,7 +45,6 @@ protected:
uint64_t m_featureID;
OsmElement * m_current;
- routing::TagsProcessor & m_routingTagsProcessor;
private:
base::Cache<uint64_t, RelationElement> m_cache;
@@ -54,9 +52,6 @@ private:
class RelationTagsNode : public RelationTagsBase
{
-public:
- explicit RelationTagsNode(routing::TagsProcessor & tagsProcessor);
-
protected:
void Process(RelationElement const & e) override;
@@ -66,9 +61,6 @@ private:
class RelationTagsWay : public RelationTagsBase
{
-public:
- explicit RelationTagsWay(routing::TagsProcessor & routingTagsProcessor);
-
private:
using Base = RelationTagsBase;
using NameKeys = std::unordered_set<std::string>;
diff --git a/generator/relation_tags_enricher.cpp b/generator/relation_tags_enricher.cpp
new file mode 100644
index 0000000000..896d46d04d
--- /dev/null
+++ b/generator/relation_tags_enricher.cpp
@@ -0,0 +1,24 @@
+#include "generator/relation_tags_enricher.hpp"
+
+#include "generator/intermediate_data.hpp"
+#include "generator/osm_element.hpp"
+
+namespace generator
+{
+RelationTagsEnricher::RelationTagsEnricher(cache::IntermediateDataReader & cache)
+ : m_cache(cache) {}
+
+void RelationTagsEnricher::operator()(OsmElement & p)
+{
+ if (p.IsNode())
+ {
+ m_nodeRelations.Reset(p.id, &p);
+ m_cache.ForEachRelationByNodeCached(p.id, m_nodeRelations);
+ }
+ else if (p.IsWay())
+ {
+ m_wayRelations.Reset(p.id, &p);
+ m_cache.ForEachRelationByWayCached(p.id, m_wayRelations);
+ }
+}
+} // namespace generator
diff --git a/generator/relation_tags_enricher.hpp b/generator/relation_tags_enricher.hpp
new file mode 100644
index 0000000000..04bc8bac4b
--- /dev/null
+++ b/generator/relation_tags_enricher.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "generator/relation_tags.hpp"
+
+struct OsmElement;
+
+namespace generator
+{
+namespace cache
+{
+class IntermediateDataReader;
+} // namespace cache
+
+// Class RelationTagsEnricher enriches relation element tags.
+class RelationTagsEnricher
+{
+public:
+ explicit RelationTagsEnricher(cache::IntermediateDataReader & cache);
+ void operator()(OsmElement & p);
+
+private:
+ cache::IntermediateDataReader & m_cache;
+ RelationTagsNode m_nodeRelations;
+ RelationTagsWay m_wayRelations;
+};
+} // namespace generator
diff --git a/generator/restaurants_info/restaurants_info.cpp b/generator/restaurants_info/restaurants_info.cpp
index 6b0f17946a..ec6b954dc2 100644
--- a/generator/restaurants_info/restaurants_info.cpp
+++ b/generator/restaurants_info/restaurants_info.cpp
@@ -1,6 +1,8 @@
#include "generator/emitter_factory.hpp"
#include "generator/feature_builder.hpp"
#include "generator/osm_source.hpp"
+#include "generator/translator_collection.hpp"
+#include "generator/translator_factory.hpp"
#include "indexer/classificator.hpp"
#include "indexer/classificator_loader.hpp"
@@ -87,8 +89,11 @@ int main(int argc, char * argv[])
LOG_SHORT(LINFO, ("OSM data:", FLAGS_osm));
std::vector<FeatureBuilder1> features;
+ generator::CacheLoader cacheLoader(info);
+ generator::TranslatorCollection translators;
auto emitter = generator::CreateEmitter(generator::EmitterType::Restaurants, features);
- generator::GenerateFeatures(info, emitter);
+ translators.Append(generator::CreateTranslator(generator::TranslatorType::Country, emitter, cacheLoader.GetCache(), info));
+ GenerateRaw(info, translators);
{
std::ofstream ost(FLAGS_out);
diff --git a/generator/restriction_writer.cpp b/generator/restriction_writer.cpp
index 1eb2f99599..1c7f119dcc 100644
--- a/generator/restriction_writer.cpp
+++ b/generator/restriction_writer.cpp
@@ -43,6 +43,11 @@ bool TagToType(std::string const & tag, Restriction::Type & type)
namespace routing
{
+RestrictionWriter::RestrictionWriter(std::string const & fullPath)
+{
+ Open(fullPath);
+}
+
void RestrictionWriter::Open(std::string const & fullPath)
{
LOG(LINFO, ("Saving road restrictions in osm id terms to", fullPath));
@@ -52,7 +57,7 @@ void RestrictionWriter::Open(std::string const & fullPath)
LOG(LINFO, ("Cannot open file", fullPath));
}
-void RestrictionWriter::Write(RelationElement const & relationElement)
+void RestrictionWriter::CollectRelation(RelationElement const & relationElement)
{
if (!IsOpened())
{
@@ -60,7 +65,8 @@ void RestrictionWriter::Write(RelationElement const & relationElement)
return;
}
- CHECK_EQUAL(relationElement.GetType(), "restriction", ());
+ if (relationElement.GetType() != "restriction")
+ return;
// Note. For the time being only line-point-line road restriction is supported.
if (relationElement.nodes.size() != 1 || relationElement.ways.size() != 2)
diff --git a/generator/restriction_writer.hpp b/generator/restriction_writer.hpp
index f2eab58160..cb451fb7f9 100644
--- a/generator/restriction_writer.hpp
+++ b/generator/restriction_writer.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include "generator/collector_interface.hpp"
+
#include <fstream>
#include <string>
@@ -7,19 +9,21 @@ class RelationElement;
namespace routing
{
-class RestrictionWriter
+class RestrictionWriter : public generator::CollectorInterface
{
public:
- void Open(std::string const & fullPath);
-
+ RestrictionWriter(std::string const & fullPath);
+ // CollectorRelationsInterface overrides:
/// \brief Writes |relationElement| to |m_stream| if |relationElement| is a supported restriction.
/// See restriction_generator.hpp for the description of the format.
/// \note For the time being only line-point-line restrictions are processed. The other
/// restrictions are ignored.
// @TODO(bykoianko) It's necessary to process all kind of restrictions.
- void Write(RelationElement const & relationElement);
+ void CollectRelation(RelationElement const & relationElement) override;
+ void Save() override {}
private:
+ void Open(std::string const & fullPath);
bool IsOpened() const;
std::ofstream m_stream;
diff --git a/generator/road_access_generator.cpp b/generator/road_access_generator.cpp
index 3c399013d0..03e389a094 100644
--- a/generator/road_access_generator.cpp
+++ b/generator/road_access_generator.cpp
@@ -314,10 +314,12 @@ RoadAccess::Type RoadAccessTagProcessor::GetAccessType(OsmElement const & elem)
}
// RoadAccessWriter ------------------------------------------------------------
-RoadAccessWriter::RoadAccessWriter()
+RoadAccessWriter::RoadAccessWriter(std::string const & filePath)
{
for (size_t i = 0; i < static_cast<size_t>(VehicleType::Count); ++i)
m_tagProcessors.emplace_back(static_cast<VehicleType>(i));
+
+ Open(filePath);
}
void RoadAccessWriter::Open(string const & filePath)
@@ -330,7 +332,7 @@ void RoadAccessWriter::Open(string const & filePath)
LOG(LINFO, ("Cannot open file", filePath));
}
-void RoadAccessWriter::Process(OsmElement const & elem)
+void RoadAccessWriter::CollectFeature(FeatureBuilder1 const &, OsmElement const & elem)
{
if (!IsOpened())
{
diff --git a/generator/road_access_generator.hpp b/generator/road_access_generator.hpp
index 5ebf448758..f08006c8ea 100644
--- a/generator/road_access_generator.hpp
+++ b/generator/road_access_generator.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "generator/collector_interface.hpp"
#include "generator/intermediate_elements.hpp"
#include "generator/osm_element.hpp"
@@ -42,16 +43,17 @@ private:
std::map<uint64_t, RoadAccess::Type> m_barriers;
};
-class RoadAccessWriter
+class RoadAccessWriter : public generator::CollectorInterface
{
public:
- RoadAccessWriter();
+ RoadAccessWriter(std::string const & filePath);
- void Open(std::string const & filePath);
-
- void Process(OsmElement const & elem);
+ // CollectorInterface overrides:
+ void CollectFeature(FeatureBuilder1 const &, OsmElement const & elem) override;
+ void Save() override {}
private:
+ void Open(std::string const & filePath);
bool IsOpened() const;
std::ofstream m_stream;
diff --git a/generator/routing_helpers.hpp b/generator/routing_helpers.hpp
index fdec661b3b..54fd988ee7 100644
--- a/generator/routing_helpers.hpp
+++ b/generator/routing_helpers.hpp
@@ -15,16 +15,6 @@
namespace routing
{
-struct TagsProcessor
-{
- explicit TagsProcessor(std::string const & maxspeedsFilePath) : m_maxspeedsCollector(maxspeedsFilePath) {}
-
- RoadAccessWriter m_roadAccessWriter;
- RestrictionWriter m_restrictionWriter;
- CameraNodeProcessor m_cameraNodeWriter;
- generator::MaxspeedsCollector m_maxspeedsCollector;
-};
-
// Adds feature id and corresponding |osmId| to |osmIdToFeatureId|.
// Note. In general, one |featureId| may correspond to several osm ids.
// But for a road feature |featureId| corresponds to exactly one osm id.
diff --git a/generator/tag_admixer.hpp b/generator/tag_admixer.hpp
index eb5e254f72..24f9ce928b 100644
--- a/generator/tag_admixer.hpp
+++ b/generator/tag_admixer.hpp
@@ -6,6 +6,7 @@
#include "base/stl_helpers.hpp"
#include "base/string_utils.hpp"
+#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
@@ -105,20 +106,20 @@ public:
}
}
- void operator()(OsmElement * e)
+ void operator()(OsmElement & element)
{
- if (e->type == OsmElement::EntityType::Way && m_ways.find(e->id) != m_ways.end())
+ if (element.type == OsmElement::EntityType::Way && m_ways.find(element.id) != m_ways.end())
{
// Exclude ferry routes.
- if (find(e->Tags().begin(), e->Tags().end(), m_ferryTag) == e->Tags().end())
- e->AddTag("highway", m_ways[e->id]);
+ if (find(element.Tags().begin(), element.Tags().end(), m_ferryTag) == element.Tags().end())
+ element.AddTag("highway", m_ways[element.id]);
}
- else if (e->type == OsmElement::EntityType::Node && m_capitals.find(e->id) != m_capitals.end())
+ else if (element.type == OsmElement::EntityType::Node && m_capitals.find(element.id) != m_capitals.end())
{
// Our goal here - to make some capitals visible in World map.
// The simplest way is to upgrade population to 45000,
// according to our visibility rules in mapcss files.
- e->UpdateTag("population", [] (std::string & v)
+ element.UpdateTag("population", [] (std::string & v)
{
uint64_t n;
if (!strings::to_uint64(v, n) || n < 45000)
@@ -167,9 +168,9 @@ public:
}
}
- void operator()(OsmElement * p)
+ void operator()(OsmElement & element)
{
- for (auto & tag : p->m_tags)
+ for (auto & tag : element.m_tags)
{
auto it = m_entries.find(tag);
if (it != m_entries.end())
@@ -178,7 +179,7 @@ public:
tag.key = v[0];
tag.value = v[1];
for (size_t i = 2; i < v.size(); i += 2)
- p->AddTag(v[i], v[i + 1]);
+ element.AddTag(v[i], v[i + 1]);
}
}
}
@@ -224,14 +225,14 @@ public:
}
}
- void operator()(OsmElement * p)
+ void operator()(OsmElement & element)
{
- std::pair<OsmElement::EntityType, uint64_t> elementId = {p->type, p->id};
+ std::pair<OsmElement::EntityType, uint64_t> elementId = {element.type, element.id};
auto elements = m_elements.find(elementId);
if (elements != m_elements.end())
{
for (OsmElement::Tag tag : elements->second)
- p->UpdateTag(tag.key, [&tag](std::string & v) { v = tag.value; });
+ element.UpdateTag(tag.key, [&tag](std::string & v) { v = tag.value; });
}
}
};
diff --git a/generator/translator.cpp b/generator/translator.cpp
new file mode 100644
index 0000000000..69f1c8b1a5
--- /dev/null
+++ b/generator/translator.cpp
@@ -0,0 +1,79 @@
+#include "generator/translator.hpp"
+
+#include "generator/collector_interface.hpp"
+#include "generator/emitter_interface.hpp"
+#include "generator/intermediate_data.hpp"
+#include "generator/osm_element.hpp"
+
+#include "base/assert.hpp"
+
+namespace generator
+{
+Translator::Translator(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ std::shared_ptr<FeatureMakerBase> maker, FilterCollection const & filters,
+ CollectorCollection const & collectors)
+ : m_filters(filters)
+ , m_collectors(collectors)
+ , m_tagsEnricher(holder)
+ , m_featureMaker(maker)
+ , m_emitter(emitter)
+ , m_holder(holder)
+{
+ CHECK(m_emitter, ());
+}
+
+Translator::Translator(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ std::shared_ptr<FeatureMakerBase> maker)
+ : Translator(emitter, holder, maker, {} /* filters */, {} /* collectors */) {}
+
+void Translator::Emit(OsmElement & element)
+{
+ if (!m_filters.IsAccepted(element))
+ return;
+
+ Preprocess(element);
+ m_tagsEnricher(element);
+ m_collectors.Collect(element);
+ m_featureMaker->Add(element);
+ FeatureBuilder1 feature;
+ while (m_featureMaker->GetNextFeature(feature))
+ {
+ if (!m_filters.IsAccepted(feature))
+ continue;
+
+ m_collectors.CollectFeature(feature, element);
+ m_emitter->Process(feature);
+ }
+}
+
+bool Translator::Finish()
+{
+ m_collectors.Save();
+ return m_emitter->Finish();
+}
+
+void Translator::GetNames(std::vector<std::string> & names) const
+{
+ m_emitter->GetNames(names);
+}
+
+void Translator::AddCollector(std::shared_ptr<CollectorInterface> collector)
+{
+ m_collectors.Append(collector);
+}
+
+void Translator::AddCollectorCollection(CollectorCollection const & collectors)
+{
+ m_collectors.AddCollection(collectors);
+}
+
+void Translator::AddFilter(std::shared_ptr<FilterInterface> filter)
+{
+ m_filters.Append(filter);
+}
+
+void Translator::AddFilterCollection(FilterCollection const & filters)
+{
+ m_filters.AddCollection(filters);
+}
+} // namespace generator
diff --git a/generator/translator.hpp b/generator/translator.hpp
new file mode 100644
index 0000000000..0f1c8c4424
--- /dev/null
+++ b/generator/translator.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "generator/collector_collection.hpp"
+#include "generator/feature_maker_base.hpp"
+#include "generator/filter_collection.hpp"
+#include "generator/filter_interface.hpp"
+#include "generator/relation_tags_enricher.hpp"
+#include "generator/translator_interface.hpp"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+struct OsmElement;
+
+namespace generator
+{
+class EmitterInterface;
+class CollectorInterface;
+
+namespace cache
+{
+class IntermediateDataReader;
+} // namespace cache
+
+// Implementing this base class allows an object to create FeatureBuilder1 from OsmElement and then process it.
+// You can add any collectors and filters.
+class Translator : public TranslatorInterface
+{
+public:
+ explicit Translator(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ std::shared_ptr<FeatureMakerBase> maker, FilterCollection const & filters,
+ CollectorCollection const & collectors);
+ explicit Translator(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ std::shared_ptr<FeatureMakerBase> maker);
+
+ // TranslatorInterface overrides:
+ void Emit(OsmElement & element) override;
+ bool Finish() override;
+ void GetNames(std::vector<std::string> & names) const override;
+
+ void AddCollector(std::shared_ptr<CollectorInterface> collector);
+ void AddCollectorCollection(CollectorCollection const & collectors);
+
+ void AddFilter(std::shared_ptr<FilterInterface> filter);
+ void AddFilterCollection(FilterCollection const & filters);
+
+protected:
+ FilterCollection m_filters;
+ CollectorCollection m_collectors;
+ RelationTagsEnricher m_tagsEnricher;
+ std::shared_ptr<FeatureMakerBase> m_featureMaker;
+ std::shared_ptr<EmitterInterface> m_emitter;
+ cache::IntermediateDataReader & m_holder;
+};
+} // namespace generator
diff --git a/generator/translator_coastline.cpp b/generator/translator_coastline.cpp
new file mode 100644
index 0000000000..75dfe6454b
--- /dev/null
+++ b/generator/translator_coastline.cpp
@@ -0,0 +1,40 @@
+#include "generator/translator_coastline.hpp"
+
+#include "generator/feature_maker.hpp"
+#include "generator/filter_elements.hpp"
+#include "generator/filter_planet.hpp"
+#include "generator/generate_info.hpp"
+#include "generator/intermediate_data.hpp"
+
+#include "indexer/ftypes_matcher.hpp"
+
+#include "platform/platform.hpp"
+
+#include "coding/file_name_utils.hpp"
+
+#include "defines.hpp"
+
+namespace generator
+{
+namespace
+{
+class CoastlineFilter : public FilterInterface
+{
+public:
+ bool IsAccepted(FeatureBuilder1 const & feature)
+ {
+ auto const & checker = ftypes::IsCoastlineChecker::Instance();
+ return checker(feature.GetTypes());
+ }
+};
+} // namespace
+
+TranslatorCoastline::TranslatorCoastline(std::shared_ptr<EmitterInterface> emitter,
+ cache::IntermediateDataReader & holder)
+ : Translator(emitter, holder, std::make_shared<FeatureMaker>(holder))
+{
+ AddFilter(std::make_shared<FilterPlanet>());
+ AddFilter(std::make_shared<CoastlineFilter>());
+ AddFilter(std::make_shared<FilterElements>(base::JoinPath(GetPlatform().ResourcesDir(), SKIPPED_ELEMENTS_FILE)));
+}
+} // namespace generator
diff --git a/generator/translator_coastline.hpp b/generator/translator_coastline.hpp
new file mode 100644
index 0000000000..7b920ed13f
--- /dev/null
+++ b/generator/translator_coastline.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "generator/emitter_interface.hpp"
+#include "generator/translator.hpp"
+
+#include <memory>
+
+namespace feature
+{
+struct GenerateInfo;
+} // namespace feature
+
+namespace cache
+{
+class IntermediateDataReader;
+} // namespace cache
+
+namespace generator
+{
+// The TranslatorCoastline class implements translator for building coastlines.
+class TranslatorCoastline : public Translator
+{
+public:
+ explicit TranslatorCoastline(std::shared_ptr<EmitterInterface> emitter,
+ cache::IntermediateDataReader & holder);
+};
+} // namespace generator
diff --git a/generator/translator_collection.cpp b/generator/translator_collection.cpp
new file mode 100644
index 0000000000..c63e847e88
--- /dev/null
+++ b/generator/translator_collection.cpp
@@ -0,0 +1,35 @@
+#include "generator/translator_collection.hpp"
+
+#include "generator/osm_element.hpp"
+
+#include <algorithm>
+#include <iterator>
+
+namespace generator
+{
+void TranslatorCollection::Emit(OsmElement /* const */ & element)
+{
+ for (auto & t : m_collection)
+ {
+ OsmElement copy = element;
+ t->Emit(copy);
+ }
+}
+
+bool TranslatorCollection::Finish()
+{
+ return std::all_of(std::begin(m_collection), std::end(m_collection), [](auto & t) {
+ return t->Finish();
+ });
+}
+
+void TranslatorCollection::GetNames(std::vector<std::string> & names) const
+{
+ for (auto & t : m_collection)
+ {
+ std::vector<std::string> temp;
+ t->GetNames(temp);
+ std::move(std::begin(temp), std::end(temp), std::back_inserter(names));
+ }
+}
+} // namespace generator
diff --git a/generator/translator_collection.hpp b/generator/translator_collection.hpp
new file mode 100644
index 0000000000..3bf45cbf2f
--- /dev/null
+++ b/generator/translator_collection.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "generator/collection_base.hpp"
+#include "generator/translator_interface.hpp"
+
+#include <memory>
+
+namespace generator
+{
+// This class allows you to work with a group of translators as with one.
+class TranslatorCollection : public CollectionBase<std::shared_ptr<TranslatorInterface>>, public TranslatorInterface
+{
+public:
+ // TranslatorInterface overrides:
+ void Emit(OsmElement /* const */ & element) override;
+ bool Finish() override;
+ void GetNames(std::vector<std::string> & names) const override;
+};
+} // namespace generator
diff --git a/generator/translator_country.cpp b/generator/translator_country.cpp
new file mode 100644
index 0000000000..97851a973b
--- /dev/null
+++ b/generator/translator_country.cpp
@@ -0,0 +1,114 @@
+#include "generator/translator_country.hpp"
+
+#include "generator/camera_node_processor.hpp"
+#include "generator/collector_addresses.hpp"
+#include "generator/collector_interface.hpp"
+#include "generator/collector_tag.hpp"
+#include "generator/feature_maker.hpp"
+#include "generator/filter_elements.hpp"
+#include "generator/filter_planet.hpp"
+#include "generator/generate_info.hpp"
+#include "generator/intermediate_data.hpp"
+#include "generator/maxspeeds_collector.hpp"
+#include "generator/metalines_builder.hpp"
+#include "generator/restriction_writer.hpp"
+#include "generator/road_access_generator.hpp"
+
+#include "platform/platform.hpp"
+
+#include "coding/file_name_utils.hpp"
+
+#include "base/assert.hpp"
+
+#include <cctype>
+#include <cstdint>
+#include <string>
+
+#include "defines.hpp"
+
+namespace generator
+{
+namespace
+{
+class RelationCollector
+{
+public:
+ explicit RelationCollector(CollectorCollection & collectors) : m_collectors(collectors) {}
+
+ template <class Reader>
+ base::ControlFlow operator()(uint64_t id, Reader & reader)
+ {
+ RelationElement element;
+ CHECK(reader.Read(id, element), (id));
+ m_collectors.CollectRelation(element);
+ return base::ControlFlow::Continue;
+ }
+
+private:
+ CollectorInterface & m_collectors;
+};
+
+// https://www.wikidata.org/wiki/Wikidata:Identifiers
+bool WikiDataValidator(std::string const & tagValue)
+{
+ if (tagValue.size() < 2)
+ return false;
+
+ size_t pos = 0;
+ // Only items are are needed.
+ if (tagValue[pos++] != 'Q')
+ return false;
+
+ while (pos != tagValue.size())
+ {
+ if (!std::isdigit(tagValue[pos++]))
+ return false;
+ }
+
+ return true;
+}
+} // namespace
+
+TranslatorCountry::TranslatorCountry(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ feature::GenerateInfo const & info)
+ : Translator(emitter, holder, std::make_shared<FeatureMaker>(holder))
+ , m_tagAdmixer(info.GetIntermediateFileName("ways", ".csv"), info.GetIntermediateFileName("towns", ".csv"))
+ , m_tagReplacer(base::JoinPath(GetPlatform().ResourcesDir(), REPLACED_TAGS_FILE))
+ , m_osmTagMixer(base::JoinPath(GetPlatform().ResourcesDir(), MIXED_TAGS_FILE))
+{
+ AddFilter(std::make_shared<FilterPlanet>());
+ AddFilter(std::make_shared<FilterElements>(base::JoinPath(GetPlatform().ResourcesDir(), SKIPPED_ELEMENTS_FILE)));
+
+ AddCollector(std::make_shared<CollectorTag>(info.m_idToWikidataFilename, "wikidata" /* tagKey */,
+ WikiDataValidator, true /* ignoreIfNotOpen */));
+ AddCollector(std::make_shared<feature::MetalinesBuilder>(info.GetIntermediateFileName(METALINES_FILENAME)));
+
+ // These are the four collector that collect additional information for the future building of routing section.
+ AddCollector(std::make_shared<MaxspeedsCollector>(info.GetIntermediateFileName(MAXSPEEDS_FILENAME)));
+ AddCollector(std::make_shared<routing::RestrictionWriter>(info.GetIntermediateFileName(RESTRICTIONS_FILENAME)));
+ AddCollector(std::make_shared<routing::RoadAccessWriter>(info.GetIntermediateFileName(ROAD_ACCESS_FILENAME)));
+ AddCollector(std::make_shared<routing::CameraNodeProcessor>(info.GetIntermediateFileName(CAMERAS_TO_WAYS_FILENAME),
+ info.GetIntermediateFileName(CAMERAS_NODES_TO_WAYS_FILE),
+ info.GetIntermediateFileName(CAMERAS_MAXSPEED_FILE)));
+ if (info.m_genAddresses)
+ AddCollector(std::make_shared<CollectorAddresses>(info.GetAddressesFileName()));
+}
+
+void TranslatorCountry::Preprocess(OsmElement & element)
+{
+ // Here we can add new tags to the elements!
+ m_tagReplacer(element);
+ m_tagAdmixer(element);
+ m_osmTagMixer(element);
+ CollectFromRelations(element);
+}
+
+void TranslatorCountry::CollectFromRelations(OsmElement const & element)
+{
+ RelationCollector collector(m_collectors);
+ if (element.IsNode())
+ m_holder.ForEachRelationByNodeCached(element.id, collector);
+ else if (element.IsWay())
+ m_holder.ForEachRelationByWayCached(element.id, collector);
+}
+} // namespace generator
diff --git a/generator/translator_country.hpp b/generator/translator_country.hpp
new file mode 100644
index 0000000000..1ad9bd4c08
--- /dev/null
+++ b/generator/translator_country.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "generator/emitter_interface.hpp"
+#include "generator/tag_admixer.hpp"
+#include "generator/translator.hpp"
+
+#include <memory>
+
+namespace feature
+{
+struct GenerateInfo;
+} // namespace feature
+
+namespace cache
+{
+class IntermediateDataReader;
+} // namespace cache
+
+namespace generator
+{
+// The TranslatorArea class implements translator for building countries.
+class TranslatorCountry : public Translator
+{
+public:
+ explicit TranslatorCountry(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ feature::GenerateInfo const & info);
+
+ // TranslatorInterface overrides:
+ void Preprocess(OsmElement & element) override;
+
+private:
+ void CollectFromRelations(OsmElement const & element);
+
+ TagAdmixer m_tagAdmixer;
+ TagReplacer m_tagReplacer;
+ OsmTagMixer m_osmTagMixer;
+};
+} // namespace generator
diff --git a/generator/translator_factory.hpp b/generator/translator_factory.hpp
index fb5049e06e..0f1dd016b0 100644
--- a/generator/translator_factory.hpp
+++ b/generator/translator_factory.hpp
@@ -1,10 +1,12 @@
#pragma once
#include "generator/factory_utils.hpp"
+#include "generator/translator_coastline.hpp"
+#include "generator/translator_country.hpp"
#include "generator/translator_geo_objects.hpp"
#include "generator/translator_interface.hpp"
-#include "generator/translator_planet.hpp"
#include "generator/translator_region.hpp"
+#include "generator/translator_world.hpp"
#include "base/assert.hpp"
@@ -15,9 +17,11 @@ namespace generator
{
enum class TranslatorType
{
- Planet,
- Region,
- GeoObjects
+ Regions,
+ GeoObjects,
+ Country,
+ Coastline,
+ World
};
template <class... Args>
@@ -25,12 +29,16 @@ std::shared_ptr<TranslatorInterface> CreateTranslator(TranslatorType type, Args&
{
switch (type)
{
- case TranslatorType::Planet:
- return create<TranslatorPlanet>(std::forward<Args>(args)...);
- case TranslatorType::Region:
+ case TranslatorType::Coastline:
+ return create<TranslatorCoastline>(std::forward<Args>(args)...);
+ case TranslatorType::Country:
+ return create<TranslatorCountry>(std::forward<Args>(args)...);
+ case TranslatorType::Regions:
return create<TranslatorRegion>(std::forward<Args>(args)...);
case TranslatorType::GeoObjects:
return create<TranslatorGeoObjects>(std::forward<Args>(args)...);
+ case TranslatorType::World:
+ return create<TranslatorWorld>(std::forward<Args>(args)...);
}
UNREACHABLE();
}
diff --git a/generator/translator_geo_objects.cpp b/generator/translator_geo_objects.cpp
index d5d92e784e..92c253deeb 100644
--- a/generator/translator_geo_objects.cpp
+++ b/generator/translator_geo_objects.cpp
@@ -1,19 +1,36 @@
#include "generator/translator_geo_objects.hpp"
-#include "generator/collector_interface.hpp"
-#include "generator/emitter_interface.hpp"
+#include "generator/feature_maker.hpp"
+#include "generator/filter_interface.hpp"
#include "generator/intermediate_data.hpp"
#include "generator/osm_element.hpp"
#include "generator/osm_element_helpers.hpp"
namespace generator
{
+namespace
+{
+class FilterGeoObjects : public FilterInterface
+{
+public:
+ // FilterInterface overrides:
+ bool IsAccepted(OsmElement const & element) override
+ {
+ return osm_element::IsBuilding(element) || osm_element::IsPoi(element);
+ }
+
+ bool IsAccepted(FeatureBuilder1 const & feature) override
+ {
+ return feature.GetParams().IsValid() && !feature.IsLine();
+ }
+};
+} // namespace
+
TranslatorGeoObjects::TranslatorGeoObjects(std::shared_ptr<EmitterInterface> emitter,
cache::IntermediateDataReader & holder)
- : TranslatorGeocoderBase(emitter, holder) {}
+ : Translator(emitter, holder, std::make_shared<FeatureMakerSimple>(holder))
-bool TranslatorGeoObjects::IsSuitableElement(OsmElement const * p) const
{
- return osm_element::IsBuilding(*p) || osm_element::IsPoi(*p);
+ AddFilter(std::make_shared<FilterGeoObjects>());
}
} // namespace generator
diff --git a/generator/translator_geo_objects.hpp b/generator/translator_geo_objects.hpp
index 4ed6f2509d..31a2d89b21 100644
--- a/generator/translator_geo_objects.hpp
+++ b/generator/translator_geo_objects.hpp
@@ -1,21 +1,23 @@
#pragma once
-#include "generator/translator_geocoder_base.hpp"
+#include "generator/emitter_interface.hpp"
+#include "generator/translator.hpp"
#include <memory>
+namespace cache
+{
+class IntermediateDataReader;
+} // namespace cache
+
namespace generator
{
-// TranslatorGeoObjects class is responsible for processing geo objects.
+// The TranslatorGeoObjects class implements translator for building geo objects.
// Every GeoObject is either a building or a POI.
-class TranslatorGeoObjects : public TranslatorGeocoderBase
+class TranslatorGeoObjects : public Translator
{
public:
explicit TranslatorGeoObjects(std::shared_ptr<EmitterInterface> emitter,
cache::IntermediateDataReader & holder);
-
-private:
- // TranslatorGeocoderBase overrides:
- bool IsSuitableElement(OsmElement const * p) const;
};
} // namespace generator
diff --git a/generator/translator_geocoder_base.cpp b/generator/translator_geocoder_base.cpp
deleted file mode 100644
index 84df34b21e..0000000000
--- a/generator/translator_geocoder_base.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-#include "generator/translator_geocoder_base.hpp"
-
-#include "generator/collector_interface.hpp"
-#include "generator/emitter_interface.hpp"
-#include "generator/feature_builder.hpp"
-#include "generator/generate_info.hpp"
-#include "generator/holes.hpp"
-#include "generator/intermediate_data.hpp"
-#include "generator/osm2type.hpp"
-#include "generator/osm_element.hpp"
-#include "generator/regions/collector_region_info.hpp"
-
-#include "indexer/classificator.hpp"
-
-#include "geometry/point2d.hpp"
-
-#include "base/assert.hpp"
-#include "base/geo_object_id.hpp"
-
-#include <set>
-
-namespace generator
-{
-TranslatorGeocoderBase::TranslatorGeocoderBase(std::shared_ptr<EmitterInterface> emitter,
- cache::IntermediateDataReader & holder)
- : m_emitter(emitter), m_holder(holder) {}
-
-void TranslatorGeocoderBase::EmitElement(OsmElement * p)
-{
- CHECK(p, ("Tried to emit a null OsmElement"));
-
- FeatureParams params;
- // We are forced to copy because ParseParams() removes tags from OsmElement.
- OsmElement osmElement = *p;
- if (!(IsSuitableElement(p) && ParseParams(&osmElement, params)))
- return;
-
- switch (p->type)
- {
- case OsmElement::EntityType::Node:
- BuildFeatureAndEmitFromNode(p, params);
- break;
- case OsmElement::EntityType::Relation:
- BuildFeatureAndEmitFromRelation(p, params);
- break;
- case OsmElement::EntityType::Way:
- BuildFeatureAndEmitFromWay(p, params);
- break;
- default:
- break;
- }
-}
-
-bool TranslatorGeocoderBase::Finish()
-{
- for (auto & collector : m_collectors)
- collector->Save();
-
- return m_emitter->Finish();
-}
-
-void TranslatorGeocoderBase::GetNames(std::vector<std::string> & names) const
-{
- m_emitter->GetNames(names);
-}
-
-void TranslatorGeocoderBase::AddCollector(std::shared_ptr<CollectorInterface> collector)
-{
- m_collectors.push_back(collector);
-}
-
-bool TranslatorGeocoderBase::ParseParams(OsmElement * p, FeatureParams & params) const
-{
- ftype::GetNameAndType(p, params, [] (uint32_t type) {
- return classif().IsTypeValid(type);
- });
- return params.IsValid();
-}
-
-void TranslatorGeocoderBase::Emit(FeatureBuilder1 & fb, OsmElement const * p)
-{
- auto const id = fb.GetMostGenericOsmId();
- for (auto const & collector : m_collectors)
- collector->Collect(id, *p);
-
- auto unused = fb.PreSerialize();
- UNUSED_VALUE(unused);
-
- (*m_emitter)(fb);
-}
-
-void TranslatorGeocoderBase::BuildFeatureAndEmitFromRelation(OsmElement const * p,
- FeatureParams const & params)
-{
- HolesRelation helper(m_holder);
- helper.Build(p);
- auto const & holesGeometry = helper.GetHoles();
- auto & outer = helper.GetOuter();
- outer.ForEachArea(true, [&] (FeatureBuilder1::PointSeq const & pts,
- std::vector<uint64_t> const & ids)
- {
- FeatureBuilder1 fb;
- for (uint64_t id : ids)
- fb.AddOsmId(base::MakeOsmWay(id));
-
- for (auto const & pt : pts)
- fb.AddPoint(pt);
-
- fb.AddOsmId(base::MakeOsmRelation(p->id));
- if (!fb.IsGeometryClosed())
- return;
-
- fb.SetAreaAddHoles(holesGeometry);
- fb.SetParams(params);
- Emit(fb, p);
- });
-}
-
-void TranslatorGeocoderBase::BuildFeatureAndEmitFromWay(OsmElement const * p,
- FeatureParams const & params)
-{
- FeatureBuilder1 fb;
- m2::PointD pt;
- for (uint64_t ref : p->Nodes())
- {
- if (!m_holder.GetNode(ref, pt.y, pt.x))
- return;
-
- fb.AddPoint(pt);
- }
-
- fb.SetOsmId(base::MakeOsmWay(p->id));
- fb.SetParams(params);
- if (!fb.IsGeometryClosed())
- return;
-
- fb.SetArea();
- Emit(fb, p);
-}
-
-void TranslatorGeocoderBase::BuildFeatureAndEmitFromNode(OsmElement const * p,
- FeatureParams const & params)
-{
- m2::PointD const pt = MercatorBounds::FromLatLon(p->lat, p->lon);
- FeatureBuilder1 fb;
- fb.SetCenter(pt);
- fb.SetOsmId(base::MakeOsmNode(p->id));
- fb.SetParams(params);
- Emit(fb, p);
-}
-} // namespace generator
diff --git a/generator/translator_geocoder_base.hpp b/generator/translator_geocoder_base.hpp
deleted file mode 100644
index 88971d3197..0000000000
--- a/generator/translator_geocoder_base.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma once
-
-#include "generator/osm_element.hpp"
-#include "generator/translator_interface.hpp"
-
-#include "indexer/feature_data.hpp"
-
-#include <memory>
-#include <vector>
-#include <string>
-
-class FeatureBuilder1;
-struct OsmElement;
-
-namespace feature
-{
-struct GenerateInfo;
-} // namespace feature
-
-namespace generator
-{
-class EmitterInterface;
-namespace cache
-{
-class IntermediateDataReader;
-} // namespace cache
-
-class CollectorInterface;
-// TranslatorGeocoderBase class is responsible for processing only points and polygons.
-class TranslatorGeocoderBase : public TranslatorInterface
-{
-public:
- explicit TranslatorGeocoderBase(std::shared_ptr<EmitterInterface> emitter,
- cache::IntermediateDataReader & holder);
- virtual ~TranslatorGeocoderBase() = default;
-
- // TranslatorInterface overrides:
- void EmitElement(OsmElement * p) override;
- bool Finish() override;
- void GetNames(std::vector<std::string> & names) const override;
-
- void AddCollector(std::shared_ptr<CollectorInterface> collector);
-
-protected:
- virtual bool IsSuitableElement(OsmElement const * p) const = 0;
-
- bool ParseParams(OsmElement * p, FeatureParams & params) const;
- void BuildFeatureAndEmitFromRelation(OsmElement const * p, FeatureParams const & params);
- void BuildFeatureAndEmitFromWay(OsmElement const * p, FeatureParams const & params);
- void BuildFeatureAndEmitFromNode(OsmElement const * p, FeatureParams const & params);
-
-private:
- void Emit(FeatureBuilder1 & fb, OsmElement const * p);
-
- std::shared_ptr<EmitterInterface> m_emitter;
- cache::IntermediateDataReader & m_holder;
- std::vector<std::shared_ptr<CollectorInterface>> m_collectors;
-};
-} // namespace generator
diff --git a/generator/translator_interface.hpp b/generator/translator_interface.hpp
index ce9d510375..52e057a8c4 100644
--- a/generator/translator_interface.hpp
+++ b/generator/translator_interface.hpp
@@ -7,13 +7,14 @@ struct OsmElement;
namespace generator
{
-// Osm to feature translator interface.
+// Implementing this interface allows an object to create intermediate data from OsmElement.
class TranslatorInterface
{
public:
- virtual ~TranslatorInterface() {}
+ virtual ~TranslatorInterface() = default;
- virtual void EmitElement(OsmElement * p) = 0;
+ virtual void Preprocess(OsmElement & element) {}
+ virtual void Emit(OsmElement & element) = 0;
virtual bool Finish() = 0;
virtual void GetNames(std::vector<std::string> & names) const = 0;
};
diff --git a/generator/translator_planet.cpp b/generator/translator_planet.cpp
deleted file mode 100644
index b0c73cbe02..0000000000
--- a/generator/translator_planet.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-#include "generator/translator_planet.hpp"
-
-#include "generator/emitter_interface.hpp"
-#include "generator/feature_builder.hpp"
-#include "generator/generate_info.hpp"
-#include "generator/holes.hpp"
-#include "generator/intermediate_data.hpp"
-#include "generator/osm2type.hpp"
-#include "generator/osm_element.hpp"
-
-#include "indexer/classificator.hpp"
-#include "indexer/feature_visibility.hpp"
-#include "indexer/ftypes_matcher.hpp"
-
-#include "geometry/point2d.hpp"
-
-#include "base/assert.hpp"
-#include "base/string_utils.hpp"
-
-#include <cctype>
-#include <string>
-#include <vector>
-
-namespace generator
-{
-namespace
-{
-// https://www.wikidata.org/wiki/Wikidata:Identifiers
-bool WikiDataValidator(std::string const & tagValue)
-{
- if (tagValue.size() < 2)
- return false;
-
- size_t pos = 0;
- // Only items are are needed.
- if (tagValue[pos++] != 'Q')
- return false;
-
- while (pos != tagValue.size())
- {
- if (!std::isdigit(tagValue[pos++]))
- return false;
- }
-
- return true;
-}
-} // namespace
-
-TranslatorPlanet::TranslatorPlanet(std::shared_ptr<EmitterInterface> emitter,
- cache::IntermediateDataReader & holder,
- feature::GenerateInfo const & info)
- : m_emitter(emitter)
- , m_cache(holder)
- , m_coastType(info.m_makeCoasts ? classif().GetCoastType() : 0)
- , m_routingTagsProcessor(info.GetIntermediateFileName(MAXSPEEDS_FILENAME))
- , m_nodeRelations(m_routingTagsProcessor)
- , m_wayRelations(m_routingTagsProcessor)
- , m_metalinesBuilder(info.GetIntermediateFileName(METALINES_FILENAME))
- , m_wikiDataCollector(info.m_idToWikidataFilename, "wikidata", WikiDataValidator, true /* ignoreIfNotOpen */)
-{
- auto const addrFilePath = info.GetAddressesFileName();
- if (!addrFilePath.empty())
- m_addrWriter.reset(new FileWriter(addrFilePath));
-
- auto const restrictionsFilePath = info.GetIntermediateFileName(RESTRICTIONS_FILENAME);
- if (!restrictionsFilePath.empty())
- m_routingTagsProcessor.m_restrictionWriter.Open(restrictionsFilePath);
-
- auto const roadAccessFilePath = info.GetIntermediateFileName(ROAD_ACCESS_FILENAME);
- if (!roadAccessFilePath.empty())
- m_routingTagsProcessor.m_roadAccessWriter.Open(roadAccessFilePath);
-
- auto const camerasToWaysFilePath = info.GetIntermediateFileName(CAMERAS_TO_WAYS_FILENAME);
- auto const camerasNodesToWaysFilePath = info.GetIntermediateFileName(CAMERAS_NODES_TO_WAYS_FILE);
- auto const camerasMaxSpeedFilePath = info.GetIntermediateFileName(CAMERAS_MAXSPEED_FILE);
- if (!camerasToWaysFilePath.empty() && !camerasNodesToWaysFilePath.empty() &&
- !camerasMaxSpeedFilePath.empty())
- {
- m_routingTagsProcessor.m_cameraNodeWriter.Open(camerasToWaysFilePath, camerasNodesToWaysFilePath,
- camerasMaxSpeedFilePath);
- }
-}
-
-void TranslatorPlanet::EmitElement(OsmElement * p)
-{
- CHECK(p, ("Tried to emit a null OsmElement"));
-
- FeatureParams params;
- switch (p->type)
- {
- case OsmElement::EntityType::Node:
- {
- if (p->m_tags.empty())
- break;
-
- if (!ParseType(p, params))
- break;
-
- m2::PointD const pt = MercatorBounds::FromLatLon(p->lat, p->lon);
- EmitPoint(pt, params, base::MakeOsmNode(p->id));
- break;
- }
- case OsmElement::EntityType::Way:
- {
- FeatureBuilder1 ft;
- m2::PointD pt;
- // Parse geometry.
- for (uint64_t ref : p->Nodes())
- {
- if (!m_cache.GetNode(ref, pt.y, pt.x))
- break;
- ft.AddPoint(pt);
- }
-
- if (p->Nodes().size() != ft.GetPointsCount())
- break;
-
- if (ft.GetPointsCount() < 2)
- break;
-
- if (!ParseType(p, params))
- break;
-
- ft.SetOsmId(base::MakeOsmWay(p->id));
-
- m_routingTagsProcessor.m_maxspeedsCollector.Process(*p);
-
- bool isCoastline = (m_coastType != 0 && params.IsTypeExist(m_coastType));
-
- EmitArea(ft, params, [&] (FeatureBuilder1 & ft)
- {
- // Emit coastline feature only once.
- isCoastline = false;
- HolesProcessor processor(p->id, m_cache);
- m_cache.ForEachRelationByWay(p->id, processor);
- ft.SetAreaAddHoles(processor.GetHoles());
- });
-
- m_metalinesBuilder(*p, params);
- EmitLine(ft, params, isCoastline);
- break;
- }
- case OsmElement::EntityType::Relation:
- {
- if (!p->HasTagValue("type", "multipolygon") && !p->HasTagValue("type", "boundary"))
- break;
-
- if (!ParseType(p, params))
- break;
-
- HolesRelation helper(m_cache);
- helper.Build(p);
-
- auto const & holesGeometry = helper.GetHoles();
- auto & outer = helper.GetOuter();
-
- outer.ForEachArea(true /* collectID */, [&] (FeatureBuilder1::PointSeq const & pts,
- std::vector<uint64_t> const & ids)
- {
- FeatureBuilder1 ft;
-
- for (uint64_t id : ids)
- ft.AddOsmId(base::MakeOsmWay(id));
-
- for (auto const & pt : pts)
- ft.AddPoint(pt);
-
- ft.AddOsmId(base::MakeOsmRelation(p->id));
- EmitArea(ft, params, [&holesGeometry] (FeatureBuilder1 & ft) {
- ft.SetAreaAddHoles(holesGeometry);
- });
- });
- break;
- }
- default:
- break;
- }
-}
-
-bool TranslatorPlanet::Finish()
-{
- return m_emitter->Finish();
-}
-
-void TranslatorPlanet::GetNames(std::vector<std::string> & names) const
-{
- m_emitter->GetNames(names);
-}
-
-bool TranslatorPlanet::ParseType(OsmElement * p, FeatureParams & params)
-{
- // Get tags from parent relations.
- if (p->IsNode())
- {
- m_nodeRelations.Reset(p->id, p);
- m_cache.ForEachRelationByNodeCached(p->id, m_nodeRelations);
- }
- else if (p->IsWay())
- {
- m_wayRelations.Reset(p->id, p);
- m_cache.ForEachRelationByWayCached(p->id, m_wayRelations);
- }
-
- // Get params from element tags.
- ftype::GetNameAndType(p, params);
- if (!params.IsValid())
- return false;
-
- m_routingTagsProcessor.m_cameraNodeWriter.Process(*p, params, m_cache);
- m_routingTagsProcessor.m_roadAccessWriter.Process(*p);
- m_wikiDataCollector.Collect(GetGeoObjectId(*p), *p);
- return true;
-}
-
-void TranslatorPlanet::EmitPoint(m2::PointD const & pt, FeatureParams params,
- base::GeoObjectId id) const
-{
- if (!feature::RemoveUselessTypes(params.m_types, feature::GEOM_POINT))
- return;
-
- FeatureBuilder1 ft;
- ft.SetCenter(pt);
- ft.SetOsmId(id);
- EmitFeatureBase(ft, params);
-}
-
-void TranslatorPlanet::EmitLine(FeatureBuilder1 & ft, FeatureParams params, bool isCoastLine) const
-{
- if (!isCoastLine && !feature::RemoveUselessTypes(params.m_types, feature::GEOM_LINE))
- return;
-
- ft.SetLinear(params.m_reverseGeometry);
- EmitFeatureBase(ft, params);
-}
-
-void TranslatorPlanet::EmitArea(FeatureBuilder1 & ft, FeatureParams params,
- std::function<void(FeatureBuilder1 &)> fn)
-{
- using namespace feature;
-
- // Ensure that we have closed area geometry.
- if (!ft.IsGeometryClosed())
- return;
-
- // @TODO(bykoianko) Now if a feature (a relation in most cases and a way in a rare case) has tag
- // place with a value city, town, village or hamlet (IsCityTownOrVillage() returns true) city boundary
- // will be emitted. It's correct according to osm documentation but very often city boundaries
- // are mapped in another way. City boundary may be mapped with a relation of a few lines and
- // one point (town of city name). And only this point has tag place with an appropriate value.
- // For example almost all cities and towns in Poland are mapped this way. It's wrong to consider
- // such relations as a city boundaries directly because sometimes it may cover much bigger area.
- // But to use information about such city boundaries some investigation should be made.
- if (ftypes::IsCityTownOrVillage(params.m_types))
- {
- auto fb = ft;
- fn(fb);
- m_emitter->EmitCityBoundary(fb, params);
- }
-
- // Key point here is that IsDrawableLike and RemoveUselessTypes
- // work a bit differently for GEOM_AREA.
- if (IsDrawableLike(params.m_types, GEOM_AREA))
- {
- // Make the area feature if it has unique area styles.
- VERIFY(RemoveUselessTypes(params.m_types, GEOM_AREA), (params));
- fn(ft);
- EmitFeatureBase(ft, params);
- }
- else
- {
- // Try to make the point feature if it has point styles.
- EmitPoint(ft.GetGeometryCenter(), params, ft.GetLastOsmId());
- }
-}
-
-void TranslatorPlanet::EmitFeatureBase(FeatureBuilder1 & ft,
- FeatureParams const & params) const
-{
- ft.SetParams(params);
- if (!ft.PreSerializeAndRemoveUselessNames())
- return;
-
- std::string addr;
- if (m_addrWriter &&
- ftypes::IsBuildingChecker::Instance()(params.m_types) &&
- ft.FormatFullAddress(addr))
- {
- m_addrWriter->Write(addr.c_str(), addr.size());
- }
-
- (*m_emitter)(ft);
-}
-} // namespace generator
diff --git a/generator/translator_planet.hpp b/generator/translator_planet.hpp
deleted file mode 100644
index f370112d07..0000000000
--- a/generator/translator_planet.hpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-
-#include "generator/camera_info_collector.hpp"
-#include "generator/collector_tag.hpp"
-#include "generator/metalines_builder.hpp"
-#include "generator/relation_tags.hpp"
-#include "generator/routing_helpers.hpp"
-#include "generator/translator_interface.hpp"
-
-#include "indexer/feature_data.hpp"
-
-#include "base/geo_object_id.hpp"
-
-#include <cstdint>
-#include <functional>
-#include <memory>
-
-struct OsmElement;
-class FeatureBuilder1;
-namespace feature
-{
-struct GenerateInfo;
-} // namespace feature
-
-namespace generator
-{
-class EmitterInterface;
-namespace cache
-{
-class IntermediateDataReader;
-} // namespace cache
-
-// Osm to feature translator for planet.
-class TranslatorPlanet : public TranslatorInterface
-{
-public:
- TranslatorPlanet(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
- feature::GenerateInfo const & info);
-
- // The main entry point for parsing process.
- void EmitElement(OsmElement * p) override;
- bool Finish() override;
- void GetNames(std::vector<std::string> & names) const override;
-
-private:
- bool ParseType(OsmElement * p, FeatureParams & params);
- void EmitFeatureBase(FeatureBuilder1 & ft, FeatureParams const & params) const;
- /// @param[in] params Pass by value because it can be modified.
- void EmitPoint(m2::PointD const & pt, FeatureParams params, base::GeoObjectId id) const;
- void EmitLine(FeatureBuilder1 & ft, FeatureParams params, bool isCoastLine) const;
- void EmitArea(FeatureBuilder1 & ft, FeatureParams params, std::function<void(FeatureBuilder1 &)> fn);
-
-private:
- std::shared_ptr<EmitterInterface> m_emitter;
- cache::IntermediateDataReader & m_cache;
- uint32_t m_coastType;
- std::unique_ptr<FileWriter> m_addrWriter;
- routing::TagsProcessor m_routingTagsProcessor;
- RelationTagsNode m_nodeRelations;
- RelationTagsWay m_wayRelations;
- feature::MetalinesBuilder m_metalinesBuilder;
- CollectorTag m_wikiDataCollector;
-};
-} // namespace generator
diff --git a/generator/translator_region.cpp b/generator/translator_region.cpp
index 95fdc7f3e4..aabe07205c 100644
--- a/generator/translator_region.cpp
+++ b/generator/translator_region.cpp
@@ -1,10 +1,12 @@
#include "generator/translator_region.hpp"
-#include "generator/collector_interface.hpp"
-#include "generator/emitter_interface.hpp"
-#include "generator/intermediate_data.hpp"
+#include "generator/feature_maker.hpp"
+#include "generator/filter_interface.hpp"
+#include "generator/generate_info.hpp"
#include "generator/intermediate_data.hpp"
#include "generator/osm_element.hpp"
+#include "generator/osm_element_helpers.hpp"
+#include "generator/regions/collector_region_info.hpp"
#include <algorithm>
#include <set>
@@ -12,28 +14,41 @@
namespace generator
{
-TranslatorRegion::TranslatorRegion(std::shared_ptr<EmitterInterface> emitter,
- cache::IntermediateDataReader & holder,
- std::shared_ptr<CollectorInterface> collector)
- : TranslatorGeocoderBase(emitter, holder)
+namespace
{
- AddCollector(collector);
-}
-
-bool TranslatorRegion::IsSuitableElement(OsmElement const * p) const
+class FilterRegions : public FilterInterface
{
- static std::set<std::string> const places = {"city", "town", "village", "suburb", "neighbourhood",
- "hamlet", "locality", "isolated_dwelling"};
-
- for (auto const & t : p->Tags())
+public:
+ // FilterInterface overrides:
+ bool IsAccepted(OsmElement const & element) override
{
- if (t.key == "place" && places.find(t.value) != places.end())
- return true;
+ for (auto const & t : element.Tags())
+ {
+ if (t.key == "place" && regions::EncodePlaceType(t.value) != regions::PlaceType::Unknown)
+ return true;
+
+ if (t.key == "boundary" && t.value == "administrative")
+ return true;
+ }
- if (t.key == "boundary" && t.value == "administrative")
- return true;
+ return false;
}
- return false;
+ bool IsAccepted(FeatureBuilder1 const & feature) override
+ {
+ return feature.GetParams().IsValid() && !feature.IsLine();
+ }
+};
+} // namespace
+
+TranslatorRegion::TranslatorRegion(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ feature::GenerateInfo const & info)
+ : Translator(emitter, holder, std::make_shared<FeatureMakerSimple>(holder))
+
+{
+ AddFilter(std::make_shared<FilterRegions>());
+
+ auto filename = info.GetTmpFileName(info.m_fileName, regions::CollectorRegionInfo::kDefaultExt);
+ AddCollector(std::make_shared<regions::CollectorRegionInfo>(filename));
}
} // namespace generator
diff --git a/generator/translator_region.hpp b/generator/translator_region.hpp
index 9ebc475ee3..18f2f61c0f 100644
--- a/generator/translator_region.hpp
+++ b/generator/translator_region.hpp
@@ -1,21 +1,27 @@
#pragma once
-#include "generator/translator_geocoder_base.hpp"
+#include "generator/emitter_interface.hpp"
+#include "generator/translator.hpp"
#include <memory>
+namespace feature
+{
+struct GenerateInfo;
+} // namespace feature
+
+namespace cache
+{
+class IntermediateDataReader;
+} // namespace cache
+
namespace generator
{
// TranslatorRegion class is responsible for processing regions.
-class TranslatorRegion : public TranslatorGeocoderBase
+class TranslatorRegion : public Translator
{
public:
- explicit TranslatorRegion(std::shared_ptr<EmitterInterface> emitter,
- cache::IntermediateDataReader & holder,
- std::shared_ptr<CollectorInterface> collector);
-
-private:
- // TranslatorGeocoderBase overrides:
- bool IsSuitableElement(OsmElement const * p) const override;
+ explicit TranslatorRegion(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ feature::GenerateInfo const & info);
};
} // namespace generator
diff --git a/generator/translator_world.cpp b/generator/translator_world.cpp
new file mode 100644
index 0000000000..1dcde63119
--- /dev/null
+++ b/generator/translator_world.cpp
@@ -0,0 +1,35 @@
+#include "generator/translator_world.hpp"
+
+#include "generator/feature_maker.hpp"
+#include "generator/filter_planet.hpp"
+#include "generator/filter_elements.hpp"
+#include "generator/generate_info.hpp"
+#include "generator/intermediate_data.hpp"
+
+#include "platform/platform.hpp"
+
+#include "coding/file_name_utils.hpp"
+
+#include "defines.hpp"
+
+namespace generator
+{
+TranslatorWorld::TranslatorWorld(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ feature::GenerateInfo const & info)
+ : Translator(emitter, holder, std::make_shared<FeatureMaker>(holder))
+ , m_tagAdmixer(info.GetIntermediateFileName("ways", ".csv"), info.GetIntermediateFileName("towns", ".csv"))
+ , m_tagReplacer(GetPlatform().ResourcesDir() + REPLACED_TAGS_FILE)
+ , m_osmTagMixer(GetPlatform().ResourcesDir() + MIXED_TAGS_FILE)
+{
+ AddFilter(std::make_shared<FilterPlanet>());
+ AddFilter(std::make_shared<FilterElements>(base::JoinPath(GetPlatform().ResourcesDir(), SKIPPED_ELEMENTS_FILE)));
+}
+
+void TranslatorWorld::Preprocess(OsmElement & element)
+{
+ // Here we can add new tags to the elements!
+ m_tagReplacer(element);
+ m_tagAdmixer(element);
+ m_osmTagMixer(element);
+}
+} // namespace generator
diff --git a/generator/translator_world.hpp b/generator/translator_world.hpp
new file mode 100644
index 0000000000..ba0f6fdc60
--- /dev/null
+++ b/generator/translator_world.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "generator/emitter_interface.hpp"
+#include "generator/tag_admixer.hpp"
+#include "generator/translator.hpp"
+
+#include <memory>
+
+namespace feature
+{
+struct GenerateInfo;
+} // namespace feature
+
+namespace cache
+{
+class IntermediateDataReader;
+} // namespace cache
+
+namespace generator
+{
+// The TranslatorWorld class implements translator for building the world.
+class TranslatorWorld : public Translator
+{
+public:
+ explicit TranslatorWorld(std::shared_ptr<EmitterInterface> emitter, cache::IntermediateDataReader & holder,
+ feature::GenerateInfo const & info);
+
+ // TranslatorInterface overrides:
+ void Preprocess(OsmElement & element) override;
+
+private:
+ TagAdmixer m_tagAdmixer;
+ TagReplacer m_tagReplacer;
+ OsmTagMixer m_osmTagMixer;
+};
+} // namespace generator
diff --git a/generator/type_helper.cpp b/generator/type_helper.cpp
new file mode 100644
index 0000000000..c7bc1f615f
--- /dev/null
+++ b/generator/type_helper.cpp
@@ -0,0 +1,17 @@
+#include "generator/type_helper.hpp"
+
+#include "indexer/classificator.hpp"
+
+namespace generator
+{
+uint32_t GetPlaceType(FeatureParams const & params)
+{
+ auto static const placeType = classif().GetTypeByPath({"place"});
+ return params.FindType(placeType, 1 /* level */);
+}
+
+uint32_t GetPlaceType(FeatureBuilder1 const & feature)
+{
+ return GetPlaceType(feature.GetParams());
+}
+} // namespace generator
diff --git a/generator/type_helper.hpp b/generator/type_helper.hpp
new file mode 100644
index 0000000000..a350f4885e
--- /dev/null
+++ b/generator/type_helper.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "generator/feature_builder.hpp"
+
+#include "indexer/feature_data.hpp"
+#include "indexer/ftypes_matcher.hpp"
+
+#include <cstdint>
+
+#include <boost/noncopyable.hpp>
+
+namespace generator
+{
+uint32_t GetPlaceType(FeatureParams const & params);
+uint32_t GetPlaceType(FeatureBuilder1 const & feature);
+} // namespace generator
diff --git a/generator/world_map_generator.hpp b/generator/world_map_generator.hpp
index f5b349a7dc..53152292fa 100644
--- a/generator/world_map_generator.hpp
+++ b/generator/world_map_generator.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "generator/feature_maker_base.hpp"
#include "generator/feature_merger.hpp"
#include "generator/generate_info.hpp"
#include "generator/popular_places_section_builder.hpp"
@@ -44,11 +45,10 @@ class WaterBoundaryChecker
size_t m_selectedPolygons = 0;
public:
- WaterBoundaryChecker(feature::GenerateInfo const & info)
+ WaterBoundaryChecker(std::string const & rawGeometryFileName)
{
m_boundaryType = classif().GetTypeByPath({"boundary", "administrative"});
- LoadWaterGeometry(
- info.GetIntermediateFileName(WORLD_COASTS_FILE_NAME, RAW_GEOM_FILE_EXTENSION));
+ LoadWaterGeometry(rawGeometryFileName);
}
~WaterBoundaryChecker()
@@ -205,10 +205,10 @@ class WorldMapGenerator
std::map<uint32_t, size_t> m_mapTypes;
public:
- explicit EmitterImpl(feature::GenerateInfo const & info)
- : m_output(info.GetTmpFileName(WORLD_FILE_NAME))
+ explicit EmitterImpl(std::string const & worldFilename)
+ : m_output(worldFilename)
{
- LOG_SHORT(LINFO, ("Output World file:", info.GetTmpFileName(WORLD_FILE_NAME)));
+ LOG_SHORT(LINFO, ("Output World file:", worldFilename));
}
~EmitterImpl() override
@@ -253,10 +253,11 @@ class WorldMapGenerator
generator::PopularPlaces m_popularPlaces;
public:
- explicit WorldMapGenerator(feature::GenerateInfo const & info)
- : m_worldBucket(info)
+ explicit WorldMapGenerator(std::string const & worldFilename, std::string const & rawGeometryFileName,
+ std::string const & popularPlacesFilename)
+ : m_worldBucket(worldFilename)
, m_merger(kPointCoordBits - (scales::GetUpperScale() - scales::GetUpperWorldScale()) / 2)
- , m_boundaryChecker(info)
+ , m_boundaryChecker(rawGeometryFileName)
{
// Do not strip last types for given tags,
// for example, do not cut 'admin_level' in 'boundary-administrative-XXX'.
@@ -270,13 +271,13 @@ public:
char const * arr2[] = {"boundary", "administrative", "4", "state"};
m_typesCorrector.SetDontNormalizeType(arr2);
- if (!info.m_popularPlacesFilename.empty())
- generator::LoadPopularPlaces(info.m_popularPlacesFilename, m_popularPlaces);
+ if (!popularPlacesFilename.empty())
+ generator::LoadPopularPlaces(popularPlacesFilename, m_popularPlaces);
else
LOG(LWARNING, ("popular_places_data option not set. Popular atractions will not be added to World.mwm"));
}
- void operator()(FeatureBuilder1 fb)
+ void Process(FeatureBuilder1 & fb)
{
auto const isPopularAttraction = IsPopularAttraction(fb);
auto const isInternationalAirport =
@@ -300,11 +301,7 @@ public:
// because we do not need geometry for invisible features (just search index and placepage
// data) and want to avoid size checks applied to areas.
if (originalFeature.GetGeomType() != feature::GEOM_POINT)
- {
- auto const center = originalFeature.GetGeometryCenter();
- originalFeature.ResetGeometry();
- originalFeature.SetCenter(center);
- }
+ generator::TransformAreaToPoint(originalFeature);
m_worldBucket.PushSure(originalFeature);
return;
@@ -405,7 +402,7 @@ public:
CountryMapGenerator(feature::GenerateInfo const & info) :
SimpleCountryMapGenerator<FeatureOut>(info) {}
- void operator()(FeatureBuilder1 fb)
+ void Process(FeatureBuilder1 fb)
{
if (feature::PreprocessForCountryMap(fb))
SimpleCountryMapGenerator<FeatureOut>::operator()(fb);
diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp
index 8db386ddab..97dbf92bd7 100644
--- a/indexer/feature_data.hpp
+++ b/indexer/feature_data.hpp
@@ -256,6 +256,7 @@ public:
m_types = rhs.m_types;
m_addrTags = rhs.m_addrTags;
m_metadata = rhs.m_metadata;
+ m_reverseGeometry = rhs.m_reverseGeometry;
}
bool IsValid() const { return !m_types.empty(); }
diff --git a/indexer/feature_visibility.cpp b/indexer/feature_visibility.cpp
index 51077d6a85..d7480d3cdd 100644
--- a/indexer/feature_visibility.cpp
+++ b/indexer/feature_visibility.cpp
@@ -8,6 +8,7 @@
#include "base/assert.hpp"
+#include <algorithm>
#include <array>
using namespace std;
@@ -348,30 +349,44 @@ bool IsDrawableForIndexClassifOnly(TypesHolder const & types, int level)
return false;
}
-bool RemoveUselessTypes(vector<uint32_t> & types, EGeomType geomType, bool emptyName)
+bool IsUsefulType(uint32_t t, EGeomType geomType, bool emptyName)
{
Classificator const & c = classif();
- types.erase(remove_if(types.begin(), types.end(), [&] (uint32_t t)
+ if (IsUsefulNondrawableType(t, geomType))
+ return true;
+
+ IsDrawableLikeChecker doCheck(geomType, emptyName);
+ if (c.ProcessObjects(t, doCheck))
+ return true;
+
+ // IsDrawableLikeChecker checks only unique area styles,
+ // so we need to take into account point styles too.
+ if (geomType == GEOM_AREA)
{
- if (IsUsefulNondrawableType(t, geomType))
- return false;
-
- IsDrawableLikeChecker doCheck(geomType, emptyName);
- if (c.ProcessObjects(t, doCheck))
- return false;
-
- // IsDrawableLikeChecker checks only unique area styles,
- // so we need to take into account point styles too.
- if (geomType == GEOM_AREA)
- {
- IsDrawableLikeChecker doCheck(GEOM_POINT, emptyName);
- if (c.ProcessObjects(t, doCheck))
- return false;
- }
-
- return true;
- }), types.end());
+ IsDrawableLikeChecker doCheck(GEOM_POINT, emptyName);
+ if (c.ProcessObjects(t, doCheck))
+ return true;
+ }
+
+ return false;
+}
+
+bool HasUsefulType(vector<uint32_t> const & types, EGeomType geomType, bool emptyName)
+{
+ if (types.empty())
+ return false;
+
+ return any_of(types.begin(), types.end(), [&](uint32_t t) {
+ return IsUsefulType(t, geomType, emptyName);
+ });
+}
+
+bool RemoveUselessTypes(vector<uint32_t> & types, EGeomType geomType, bool emptyName)
+{
+ base::EraseIf(types, [&] (uint32_t t) {
+ return !IsUsefulType(t, geomType, emptyName);
+ });
return !types.empty();
}
diff --git a/indexer/feature_visibility.hpp b/indexer/feature_visibility.hpp
index 57db612238..400ee5b0e1 100644
--- a/indexer/feature_visibility.hpp
+++ b/indexer/feature_visibility.hpp
@@ -6,6 +6,7 @@
#include "base/base.hpp"
+#include <cstdint>
#include <initializer_list>
#include <string>
#include <utility>
@@ -34,7 +35,10 @@ namespace feature
/// For FEATURE_TYPE_AREA removes line-drawing only types.
bool RemoveUselessTypes(std::vector<uint32_t> & types, EGeomType geomType,
bool emptyName = false);
- //@}
+
+ // Returns true, if there is at least one type that is needed for the application.
+ // This can be specified either by the drawing rule or by other rules.
+ bool HasUsefulType(std::vector<uint32_t> const & types, EGeomType geomType, bool emptyName = false);
int GetMinDrawableScale(FeatureType & ft);
int GetMinDrawableScale(TypesHolder const & types, m2::RectD limitRect);
diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp
index b141bc6096..276e963994 100644
--- a/indexer/ftypes_matcher.cpp
+++ b/indexer/ftypes_matcher.cpp
@@ -476,6 +476,42 @@ IsPopularityPlaceChecker::IsPopularityPlaceChecker()
m_types.push_back(c.GetTypeByPath({t.first, t.second}));
}
+IsIslandChecker::IsIslandChecker()
+{
+ vector<pair<string, string>> const types = {
+ {"place", "island"},
+ {"place", "islet"},
+ };
+
+ Classificator const & c = classif();
+ for (auto const & t : types)
+ m_types.push_back(c.GetTypeByPath({t.first, t.second}));
+}
+
+IsLandChecker::IsLandChecker()
+{
+ Classificator const & c = classif();
+ m_types.push_back(c.GetTypeByPath({"natural", "land"}));
+}
+
+uint32_t IsLandChecker::GetLandType() const
+{
+ CHECK_EQUAL(m_types.size(), 1, ());
+ return m_types[0];
+}
+
+IsCoastlineChecker::IsCoastlineChecker()
+{
+ Classificator const & c = classif();
+ m_types.push_back(c.GetTypeByPath({"natural", "coastline"}));
+}
+
+uint32_t IsCoastlineChecker::GetCoastlineType() const
+{
+ CHECK_EQUAL(m_types.size(), 1, ());
+ return m_types[0];
+}
+
boost::optional<IsHotelChecker::Type> IsHotelChecker::GetHotelType(FeatureType & ft) const
{
feature::TypesHolder types(ft);
diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp
index 5747d91786..f9261f3140 100644
--- a/indexer/ftypes_matcher.hpp
+++ b/indexer/ftypes_matcher.hpp
@@ -243,6 +243,31 @@ public:
DECLARE_CHECKER_INSTANCE(IsPopularityPlaceChecker);
};
+class IsIslandChecker : public BaseChecker
+{
+ IsIslandChecker();
+public:
+ DECLARE_CHECKER_INSTANCE(IsIslandChecker);
+};
+
+class IsLandChecker : public BaseChecker
+{
+ IsLandChecker();
+public:
+ DECLARE_CHECKER_INSTANCE(IsLandChecker);
+
+ uint32_t GetLandType() const;
+};
+
+class IsCoastlineChecker : public BaseChecker
+{
+ IsCoastlineChecker();
+public:
+ DECLARE_CHECKER_INSTANCE(IsCoastlineChecker);
+
+ uint32_t GetCoastlineType() const;
+};
+
class IsHotelChecker : public BaseChecker
{
public: