[generator] Removed code for geocoders. Bye, B2B!

This commit is contained in:
Maksim Andrianov 2019-08-30 13:18:36 +03:00 committed by Tatiana Yan
parent 2f70fa1cba
commit aa8f3bc483
191 changed files with 2 additions and 12511 deletions

View file

@ -85,14 +85,6 @@ set(
final_processor_intermediate_mwm.hpp
gen_mwm_info.hpp
generate_info.hpp
geo_objects/geo_objects.cpp
geo_objects/geo_objects.hpp
geo_objects/geo_objects_filter.cpp
geo_objects/geo_objects_filter.hpp
geo_objects/geo_objects_generator.cpp
geo_objects/geo_objects_generator.hpp
geo_objects/geo_objects_maintainer.cpp
geo_objects/geo_objects_maintainer.hpp
geometry_holder.hpp
holes.cpp
holes.hpp
@ -101,8 +93,6 @@ set(
intermediate_elements.hpp
key_value_storage.cpp
key_value_storage.hpp
locality_sorter.cpp
locality_sorter.hpp
maxspeeds_builder.cpp
maxspeeds_builder.hpp
maxspeeds_collector.cpp
@ -157,34 +147,6 @@ set(
raw_generator_writer.hpp
region_meta.cpp
region_meta.hpp
regions/admin_suburbs_marker.cpp
regions/admin_suburbs_marker.hpp
regions/collector_region_info.cpp
regions/collector_region_info.hpp
regions/country_specifier.cpp
regions/country_specifier.hpp
regions/country_specifier_builder.cpp
regions/country_specifier_builder.hpp
regions/level_region.hpp
regions/locality_point_integrator.cpp
regions/locality_point_integrator.hpp
regions/node.cpp
regions/node.hpp
regions/place_point.hpp
regions/place_points_integrator.cpp
regions/place_points_integrator.hpp
regions/region.cpp
regions/region.hpp
regions/region_base.cpp
regions/region_base.hpp
regions/region_info.cpp
regions/region_info.hpp
regions/region_info_getter.cpp
regions/region_info_getter.hpp
regions/regions.cpp
regions/regions.hpp
regions/regions_builder.cpp
regions/regions_builder.hpp
relation_tags.cpp
relation_tags.hpp
relation_tags_enricher.cpp
@ -213,16 +175,6 @@ set(
srtm_parser.hpp
statistics.cpp
statistics.hpp
streets/street_geometry.cpp
streets/street_geometry.hpp
streets/street_regions_tracing.cpp
streets/street_regions_tracing.hpp
streets/streets.cpp
streets/streets.hpp
streets/streets_builder.cpp
streets/streets_builder.hpp
streets/streets_filter.cpp
streets/streets_filter.hpp
tag_admixer.hpp
tesselator.cpp
tesselator.hpp
@ -243,13 +195,7 @@ set(
translator_country.cpp
translator_country.hpp
translator_factory.hpp
translator_geo_objects.cpp
translator_geo_objects.hpp
translator_interface.hpp
translator_region.cpp
translator_region.hpp
translator_streets.cpp
translator_streets.hpp
translator_world.cpp
translator_world.hpp
translators_pool.cpp

View file

@ -17,7 +17,6 @@ set(
feature_builder_test.cpp
feature_merger_test.cpp
filter_elements_tests.cpp
geo_objects_tests.cpp
intermediate_data_test.cpp
maxspeeds_tests.cpp
merge_collectors_tests.cpp
@ -29,8 +28,6 @@ set(
osm_type_test.cpp
place_processor_tests.cpp
popularity_builder_tests.cpp
region_info_collector_tests.cpp
regions_tests.cpp
restriction_collector_test.cpp
restriction_test.cpp
road_access_test.cpp
@ -40,8 +37,6 @@ set(
speed_cameras_test.cpp
sponsored_storage_tests.cpp
srtm_parser_test.cpp
street_geometry_tests.cpp
street_regions_tracing_tests.cpp
tag_admixer_test.cpp
tesselator_test.cpp
translation_test.cpp

View file

@ -1,274 +0,0 @@
#include "testing/testing.hpp"
#include "platform/platform_tests_support/scoped_file.hpp"
#include "generator/feature_builder.hpp"
#include "generator/feature_generator.hpp"
#include "generator/generator_tests/common.hpp"
#include "generator/geo_objects/geo_objects_filter.hpp"
#include "generator/geo_objects/geo_objects_generator.hpp"
#include "generator/geo_objects/geo_objects_maintainer.hpp"
#include "indexer/classificator_loader.hpp"
#include <iostream>
using namespace generator_tests;
using namespace platform::tests_support;
using namespace generator;
using namespace generator::geo_objects;
using namespace feature;
using namespace base;
bool CheckWeGotExpectedIdsByPoint(m2::PointD const & point,
std::vector<base::GeoObjectId> reference,
indexer::GeoObjectsIndex<IndexReader> const & index)
{
std::vector<base::GeoObjectId> test =
GeoObjectMaintainer::GeoObjectsView::SearchGeoObjectIdsByPoint(index, point);
std::sort(test.begin(), test.end());
std::sort(reference.begin(), reference.end());
return test == reference;
}
std::vector<base::GeoObjectId> CollectFeatures(
std::vector<OsmElementData> const & osmElements, ScopedFile const & geoObjectsFeatures,
std::function<bool(FeatureBuilder const &)> && accepter)
{
std::vector<base::GeoObjectId> expectedIds;
{
FeaturesCollector collector(geoObjectsFeatures.GetFullPath());
for (OsmElementData const & elementData : osmElements)
{
FeatureBuilder fb = FeatureBuilderFromOmsElementData(elementData);
if (accepter(fb))
expectedIds.emplace_back(fb.GetMostGenericOsmId());
TEST(fb.PreSerialize(), ());
collector.Collect(fb);
}
}
return expectedIds;
}
std::unique_ptr<GeoObjectsGenerator> TearUp(std::vector<OsmElementData> const & osmElements,
ScopedFile const & geoObjectsFeatures,
ScopedFile const & idsWithoutAddresses,
ScopedFile const & geoObjectsKeyValue)
{
// Absolutely random region.
std::shared_ptr<JsonValue> value = std::make_shared<JsonValue>(LoadFromString(
R"({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-77.263927,
26.6210869
]
},
"properties": {
"locales": {
"default": {
"address": {
"country": "Bahamas",
"region": "Central Abaco",
"locality": "Leisure Lee"
},
"name": "Leisure Lee"
},
"en": {
"address": {
"country": "Bahamas",
"region": "Central Abaco",
"locality": "Leisure Lee"
},
"name": "Leisure Lee"
},
"ru": {
"address": {
"country": "Багамы"
}
}
},
"rank": 4,
"dref": "C00000000039A088",
"code": "BS"
}
})"));
auto regionInfoGetter = [value](auto && point) { return KeyValue{1, value}; };
auto regionIdGetter = [value](auto && point) { return value; };
auto result = std::make_unique<GeoObjectsGenerator>(
regionInfoGetter, regionIdGetter, geoObjectsFeatures.GetFullPath(), idsWithoutAddresses.GetFullPath(),
geoObjectsKeyValue.GetFullPath(), false /* verbose */, 1 /* threadsCount */);
TEST(result->GenerateGeoObjects(), ("Generate Geo Objects failed"));
return result;
}
void TestRegionAddress(json_t const * json)
{
const auto address =
GetJSONObligatoryFieldByPath(json, "properties", "locales", "default", "address");
TEST_EQUAL(FromJSONToString(GetJSONObligatoryField(address, "country")), "Bahamas", ());
TEST_EQUAL(FromJSONToString(GetJSONObligatoryField(address, "region")), "Central Abaco", ());
TEST_EQUAL(FromJSONToString(GetJSONObligatoryField(address, "locality")), "Leisure Lee", ());
}
void TestFindReverse(std::vector<OsmElementData> const & osmElements,
std::vector<m2::PointD> const & where,
std::vector<GeoObjectId> const & expected = {}
)
{
classificator::Load();
ScopedFile const geoObjectsFeatures{"geo_objects_features.mwm", ScopedFile::Mode::DoNotCreate};
ScopedFile const idsWithoutAddresses{"ids_without_addresses.txt", ScopedFile::Mode::DoNotCreate};
ScopedFile const geoObjectsKeyValue{"geo_objects.jsonl", ScopedFile::Mode::DoNotCreate};
auto const & expectedIds = CollectFeatures(
osmElements, geoObjectsFeatures, [](FeatureBuilder const & fb) { return fb.IsPoint(); });
std::unique_ptr<GeoObjectsGenerator> geoObjectsGenerator{
TearUp(osmElements, geoObjectsFeatures, idsWithoutAddresses, geoObjectsKeyValue)};
auto const geoObjectsIndex = MakeTempGeoObjectsIndex(geoObjectsFeatures.GetFullPath());
TEST(geoObjectsIndex.has_value(), ("Temporary index build failed"));
for (auto const & point : where)
{
TEST(CheckWeGotExpectedIdsByPoint(point, expectedIds, *geoObjectsIndex), ());
}
auto const & view = geoObjectsGenerator->GetMaintainer().CreateView();
const auto & toCheck = expected.empty() ? expectedIds : expected;
for (auto const & id : toCheck)
{
auto json = view.GetFullGeoObjectWithoutNameAndCoordinates(id);
TestRegionAddress(json.get());
TEST(JsonHasBuilding(JsonValue{std::move(json)}), ("No address for", id));
}
// Flush all streams inside geoObjectsGenerator in d-tor
geoObjectsGenerator.reset(nullptr);
// Commented due mac problems
// KeyValueStorage kvStorage{geoObjectsKeyValue.GetFullPath(), 0 /*cacheValuesCountLimit*/};
//
// for (GeoObjectId id : toCheck)
// {
// std::shared_ptr<JsonValue> value = kvStorage.Find(id.GetEncodedId());
// TEST(value, ("Id", id.GetEncodedId(), "is not stored in key value"));
// TEST(JsonHasBuilding(*value), ("No address for", id));
// TestRegionAddress(*value);
// }
}
UNIT_TEST(GenerateGeoObjects_AddNullBuildingGeometryForPointsWithAddressesInside)
{
std::vector<OsmElementData> const osmElements{
{1,
{{"addr:housenumber", "39 с79"},
{"addr:street", "Ленинградский проспект"},
{"building", "yes"}},
{{1.5, 1.5}},
{}},
{2,
{{"building", "commercial"}, {"type", "multipolygon"}, {"name", "superbuilding"}},
{{1, 1}, {4, 4}},
{}},
{3,
{{"addr:housenumber", "39 с80"}, {"addr:street", "Ленинградский проспект"}},
{{1.6, 1.6}},
{}}};
TestFindReverse(osmElements, {{1.5, 1.5}, {2, 2}, {4, 4}});
}
UNIT_TEST(GenerateGeoObjects_AddNullBuildingGeometryForPointsWithAddressesReverse)
{
std::vector<OsmElementData> const osmElements{
{1,
{{"addr:housenumber", "39 с80"}, {"addr:street", "Ленинградский проспект"}},
{{1.6, 1.6}},
{}},
{2,
{{"addr:housenumber", "39 с79"},
{"addr:street", "Ленинградский проспект"},
{"building", "yes"}},
{{1.5, 1.5}},
{}},
{3,
{{"building", "commercial"}, {"type", "multipolygon"}, {"name", "superbuilding"}},
{{1, 1}, {4, 4}},
{}},
};
TestFindReverse(osmElements, {{1.5, 1.5}, {2, 2}, {4, 4}});
}
UNIT_TEST(GenerateGeoObjects_AddNullBuildingPointToPoint)
{
std::vector<OsmElementData> const osmElements{
{1,
{{"addr:housenumber", "39 с79"},
{"addr:street", "Ленинградский проспект"},
{"building", "yes"}},
{{1.5, 1.5}},
{}},
{3,
{{"building", "commercial"}, {"type", "multipolygon"}, {"name", "superbuilding"}},
{{1.5, 1.5}},
{}},
};
TestFindReverse(osmElements, {}, {base::MakeOsmNode(1)});
}
void TestPoiHasAddress(std::vector<OsmElementData> const & osmElements)
{
classificator::Load();
ScopedFile const geoObjectsFeatures{"geo_objects_features.mwm", ScopedFile::Mode::DoNotCreate};
ScopedFile const idsWithoutAddresses{"ids_without_addresses.txt", ScopedFile::Mode::DoNotCreate};
ScopedFile const geoObjectsKeyValue{"geo_objects.jsonl", ScopedFile::Mode::DoNotCreate};
CollectFeatures(osmElements, geoObjectsFeatures,
[](FeatureBuilder const & fb) { return GeoObjectsFilter::IsPoi(fb); });
std::unique_ptr<GeoObjectsGenerator> geoObjectsGenerator = {
TearUp(osmElements, geoObjectsFeatures, idsWithoutAddresses, geoObjectsKeyValue)};
// Flush all streams inside geoObjectsGenerator in d-tor
geoObjectsGenerator.reset(nullptr);
// Commented due mac problems
// KeyValueStorage kvStorage{geoObjectsKeyValue.GetFullPath(), 0 /*cacheValuesCountLimit*/};
//
// for (GeoObjectId id : expectedIds)
// {
// std::shared_ptr<JsonValue> value = kvStorage.Find(id.GetEncodedId());
// TEST(value, ("Id", id, "is not stored in key value"));
// TEST(JsonHasBuilding(*value), ("No address for", id));
// TestRegionAddress(*value);
// }
}
UNIT_TEST(GenerateGeoObjects_CheckPoiEnrichedWithAddress)
{
std::vector<OsmElementData> const osmElements{
{1, {{"addr:housenumber", "111"}, {"addr:street", "Healing street"}}, {{1.6, 1.6}}, {}},
{2,
{{"building", "commercial"}, {"type", "multipolygon"}, {"name", "superbuilding"}},
{{1, 1}, {4, 4}},
{}},
{3,
{{"shop", "supermarket"}, {"population", "1"}, {"name", "ForgetMeNot"}},
{{1.5, 1.5}},
{}},
};
TestPoiHasAddress(osmElements);
}

View file

@ -1,170 +0,0 @@
#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"
#include "generator/regions/region_info.hpp"
#include "platform/platform.hpp"
#include "base/file_name_utils.hpp"
#include "base/geo_object_id.hpp"
#include "base/scope_guard.hpp"
#include <cstdint>
#include <limits>
#include <memory>
#include <string>
#include <utility>
#include <vector>
using namespace generator_tests;
using namespace generator::regions;
using namespace feature;
using namespace base;
namespace
{
auto const kNotExistingId = std::numeric_limits<uint64_t>::max();
auto const kOsmElementEmpty = MakeOsmElement(0, {}, OsmElement::EntityType::Relation);
auto const kOsmElementCity = MakeOsmElement(1, {{"place", "city"},
{"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"}},
OsmElement::EntityType::Relation);
FeatureBuilder const kEmptyFeature;
} // namespace
UNIT_TEST(RegionInfoCollector_Collect)
{
auto const filename = GetFileName();
CollectorRegionInfo regionInfoCollector(filename);
regionInfoCollector.Collect(kOsmElementCity);
regionInfoCollector.Collect(kOsmElementCountry);
regionInfoCollector.Collect(kOsmElementEmpty);
regionInfoCollector.Save();
RegionInfo regionInfo(filename);
{
auto const regionData = regionInfo.Get(MakeOsmRelation(kOsmElementCity.m_id));
TEST_EQUAL(regionData.GetOsmId(), MakeOsmRelation(kOsmElementCity.m_id), ());
TEST_EQUAL(regionData.GetAdminLevel(), AdminLevel::Six, ());
TEST_EQUAL(regionData.GetPlaceType(), PlaceType::City, ());
TEST(!regionData.GetIsoCodeAlpha2(), ());
TEST(!regionData.GetIsoCodeAlpha3(), ());
TEST(!regionData.GetIsoCodeAlphaNumeric(), ());
}
{
auto const regionData = regionInfo.Get(MakeOsmRelation(kOsmElementCountry.m_id));
TEST_EQUAL(regionData.GetOsmId(), MakeOsmRelation(kOsmElementCountry.m_id), ());
TEST_EQUAL(regionData.GetAdminLevel(), AdminLevel::Two, ());
TEST_EQUAL(regionData.GetPlaceType(), PlaceType::Unknown, ());
TEST(regionData.GetIsoCodeAlpha2(), ());
TEST(regionData.GetIsoCodeAlpha3(), ());
TEST(regionData.GetIsoCodeAlphaNumeric(), ());
TEST_EQUAL(*regionData.GetIsoCodeAlpha2(), "RU", ());
TEST_EQUAL(*regionData.GetIsoCodeAlpha3(), "RUS", ());
TEST_EQUAL(*regionData.GetIsoCodeAlphaNumeric(), "643", ());
}
{
auto const regionDataEmpty = regionInfo.Get(MakeOsmRelation(kOsmElementEmpty.m_id));
TEST_EQUAL(regionDataEmpty.GetOsmId(), MakeOsmRelation(kOsmElementEmpty.m_id), ());
TEST_EQUAL(regionDataEmpty.GetAdminLevel(), AdminLevel::Unknown, ());
TEST_EQUAL(regionDataEmpty.GetPlaceType(), PlaceType::Unknown, ());
TEST(!regionDataEmpty.GetIsoCodeAlpha2(), ());
TEST(!regionDataEmpty.GetIsoCodeAlpha3(), ());
TEST(!regionDataEmpty.GetIsoCodeAlphaNumeric(), ());
}
}
UNIT_TEST(RegionInfoCollector_Get)
{
auto const filename = GetFileName();
CollectorRegionInfo regionInfoCollector(filename);
regionInfoCollector.Collect(kOsmElementCity);
regionInfoCollector.Save();
RegionInfo regionInfo(filename);
auto const regionData = regionInfo.Get(MakeOsmRelation(kOsmElementCity.m_id));
TEST_EQUAL(regionData.GetOsmId(), MakeOsmRelation(kOsmElementCity.m_id), ());
TEST_EQUAL(regionData.GetAdminLevel(), AdminLevel::Six, ());
TEST_EQUAL(regionData.GetPlaceType(), PlaceType::City, ());
}
UNIT_TEST(RegionInfoCollector_Exists)
{
auto const filename = GetFileName();
CollectorRegionInfo regionInfoCollector(filename);
regionInfoCollector.Collect(kOsmElementCity);
regionInfoCollector.Collect(kOsmElementCountry);
regionInfoCollector.Save();
RegionInfo regionInfo(filename);
{
auto const rg = regionInfo.Get(MakeOsmRelation(kOsmElementCountry.m_id));
TEST_NOT_EQUAL(rg.GetAdminLevel(), AdminLevel::Unknown, ());
TEST_EQUAL(rg.GetPlaceType(), PlaceType::Unknown, ());
TEST(rg.GetIsoCodeAlpha2(), ());
TEST(rg.GetIsoCodeAlpha3(), ());
TEST(rg.GetIsoCodeAlphaNumeric(), ());
}
{
auto const rg = regionInfo.Get(MakeOsmRelation(kOsmElementCity.m_id));
TEST_NOT_EQUAL(rg.GetAdminLevel(), AdminLevel::Unknown, ());
TEST_NOT_EQUAL(rg.GetPlaceType(), PlaceType::Unknown, ());
TEST(!rg.GetIsoCodeAlpha2(), ());
TEST(!rg.GetIsoCodeAlpha3(), ());
TEST(!rg.GetIsoCodeAlphaNumeric(), ());
}
{
auto const rg = regionInfo.Get(MakeOsmRelation(kNotExistingId));
TEST_EQUAL(rg.GetAdminLevel(), AdminLevel::Unknown, ());
TEST_EQUAL(rg.GetPlaceType(), PlaceType::Unknown, ());
TEST(!rg.GetIsoCodeAlpha2(), ());
TEST(!rg.GetIsoCodeAlpha3(), ());
TEST(!rg.GetIsoCodeAlphaNumeric(), ());
}
}
UNIT_TEST(RegionInfoCollector_MergeAndSave)
{
auto const filename = generator_tests::GetFileName();
SCOPE_GUARD(_, std::bind(Platform::RemoveFileIfExists, std::cref(filename)));
auto c1 = std::make_shared<CollectorRegionInfo>(filename);
auto c2 = c1->Clone();
c1->Collect(kOsmElementCity);
c2->Collect(kOsmElementCountry);
c1->Finish();
c2->Finish();
c1->Merge(*c2);
c1->Save();
RegionInfo regionInfo(filename);
{
auto const rg = regionInfo.Get(MakeOsmRelation(kOsmElementCountry.m_id));
TEST_NOT_EQUAL(rg.GetAdminLevel(), AdminLevel::Unknown, ());
TEST_EQUAL(rg.GetPlaceType(), PlaceType::Unknown, ());
TEST(rg.GetIsoCodeAlpha2(), ());
TEST(rg.GetIsoCodeAlpha3(), ());
TEST(rg.GetIsoCodeAlphaNumeric(), ());
}
{
auto const rg = regionInfo.Get(MakeOsmRelation(kOsmElementCity.m_id));
TEST_NOT_EQUAL(rg.GetAdminLevel(), AdminLevel::Unknown, ());
TEST_NOT_EQUAL(rg.GetPlaceType(), PlaceType::Unknown, ());
TEST(!rg.GetIsoCodeAlpha2(), ());
TEST(!rg.GetIsoCodeAlpha3(), ());
TEST(!rg.GetIsoCodeAlphaNumeric(), ());
}
}

View file

@ -1,626 +0,0 @@
#include "testing/testing.hpp"
#include "generator/feature_builder.hpp"
#include "generator/generator_tests/common.hpp"
#include "generator/osm2type.hpp"
#include "generator/osm_element.hpp"
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/place_point.hpp"
#include "generator/regions/regions.hpp"
#include "generator/regions/regions_builder.hpp"
#include "indexer/classificator.hpp"
#include "indexer/classificator_loader.hpp"
#include "platform/platform.hpp"
#include "coding/transliteration.hpp"
#include "base/file_name_utils.hpp"
#include "base/macros.hpp"
#include "base/scope_guard.hpp"
#include <algorithm>
#include <cstdint>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
using namespace generator_tests;
using namespace generator;
using namespace generator::regions;
using namespace feature;
using namespace base;
namespace
{
using Tags = std::vector<std::pair<std::string, std::string>>;
auto NodeEntry = OsmElement::EntityType::Node;
FeatureBuilder const kEmptyFeature;
OsmElement CreateOsmRelation(uint64_t id, std::string const & adminLevel,
std::string const & place = "")
{
OsmElement el;
el.m_id = id;
el.m_type = OsmElement::EntityType::Relation;
el.AddTag("place", place);
el.AddTag("admin_level", adminLevel);
return el;
}
void CollectRegionInfo(std::string const & filename, std::vector<OsmElementData> const & testData)
{
CollectorRegionInfo collector(filename);
for (auto const & elementData : testData)
{
auto el = MakeOsmElement(elementData);
collector.Collect(el);
}
collector.Save();
}
void BuildTestData(std::vector<OsmElementData> const & testData, RegionsBuilder::Regions & regions,
PlacePointsMap & placePointsMap, RegionInfo & collector)
{
for (auto const & elementData : testData)
{
FeatureBuilder fb = FeatureBuilderFromOmsElementData(elementData);
auto const id = fb.GetMostGenericOsmId();
if (elementData.m_polygon.size() == 1)
placePointsMap.emplace(id, PlacePoint{fb, collector.Get(id)});
else
regions.emplace_back(fb, collector.Get(id));
}
}
std::string ToLabelingString(vector<Node::Ptr> const & path, bool withGeometry)
{
CHECK(!path.empty(), ());
std::stringstream stream;
auto i = path.begin();
auto const & countryName = (*i)->GetData().GetName();
CHECK(!countryName.empty(), ());
stream << (*i)->GetData().GetName();
++i;
for (; i != path.end(); ++i)
{
auto const & region = (*i)->GetData();
stream << ", " << GetLabel(region.GetLevel()) << ": " << region.GetName();
if (withGeometry)
{
stream << " [";
auto const & rect = region.GetRect();
stream << std::fixed << std::setprecision(2);
stream << "(" << rect.min_corner().get<0>() << ", " << rect.min_corner().get<1>() << "), ";
stream << "(" << rect.max_corner().get<0>() << ", " << rect.max_corner().get<1>() << ")";
stream << "]";
}
}
return stream.str();
}
std::vector<std::string> GenerateTestRegions(std::vector<OsmElementData> const & testData,
bool withGeometry = false)
{
classificator::Load();
auto const filename = GetFileName();
SCOPE_GUARD(removeCollectorFile, std::bind(Platform::RemoveFileIfExists, std::cref(filename)));
CollectRegionInfo(filename, testData);
RegionsBuilder::Regions regions;
PlacePointsMap placePointsMap;
RegionInfo collector(filename);
BuildTestData(testData, regions, placePointsMap, collector);
RegionsBuilder builder(std::move(regions), std::move(placePointsMap));
std::vector<std::string> kvRegions;
builder.ForEachCountry([&](std::string const & name, Node::PtrList const & outers) {
for (auto const & tree : outers)
{
ForEachLevelPath(tree, [&](std::vector<Node::Ptr> const & path) {
kvRegions.push_back(ToLabelingString(path, withGeometry));
});
}
});
return kvRegions;
}
bool HasName(std::vector<string> const & coll, std::string const & name)
{
auto const end = std::end(coll);
return std::find(std::begin(coll), end, name) != end;
}
bool ContainsSubname(std::vector<string> const & coll, std::string const & name)
{
auto const end = std::end(coll);
auto hasSubname = [&name](std::string const & item) { return item.find(name) != string::npos; };
return std::find_if(std::begin(coll), end, hasSubname) != end;
}
std::string MakeCollectorData()
{
auto const filename = GetFileName();
CollectorRegionInfo collector(filename);
collector.Collect(CreateOsmRelation(1 /* id */, "2" /* adminLevel */));
collector.Collect(CreateOsmRelation(2 /* id */, "2" /* adminLevel */));
collector.Collect(CreateOsmRelation(3 /* id */, "4" /* adminLevel */, "state"));
collector.Collect(CreateOsmRelation(4 /* id */, "4" /* adminLevel */, "state"));
collector.Collect(CreateOsmRelation(5 /* id */, "4" /* adminLevel */, "state"));
collector.Collect(CreateOsmRelation(6 /* id */, "6" /* adminLevel */, "district"));
collector.Collect(CreateOsmRelation(7 /* id */, "6" /* adminLevel */, "district"));
collector.Collect(CreateOsmRelation(8 /* id */, "4" /* adminLevel */, "state"));
collector.Save();
return filename;
}
RegionsBuilder::Regions MakeTestDataSet1(RegionInfo & collector)
{
RegionsBuilder::Regions regions;
{
FeatureBuilder fb;
fb.AddName("default", "Country_1");
fb.SetOsmId(MakeOsmRelation(1 /* id */));
vector<m2::PointD> poly = {{2, 8}, {3, 12}, {8, 15}, {13, 12},
{15, 7}, {11, 2}, {4, 4}, {2, 8}};
fb.AddPolygon(poly);
fb.SetHoles({{{5, 8}, {7, 10}, {10, 10}, {11, 7}, {10, 4}, {7, 5}, {5, 8}}});
fb.SetArea();
regions.emplace_back(Region(fb, collector.Get(MakeOsmRelation(1 /* id */))));
}
{
FeatureBuilder fb;
fb.AddName("default", "Country_2");
fb.SetOsmId(MakeOsmRelation(2 /* id */));
vector<m2::PointD> poly = {{5, 8}, {7, 10}, {10, 10}, {11, 7}, {10, 4}, {7, 5}, {5, 8}};
fb.AddPolygon(poly);
fb.SetArea();
regions.emplace_back(Region(fb, collector.Get(MakeOsmRelation(2 /* id */))));
}
{
FeatureBuilder fb;
fb.AddName("default", "Country_2");
fb.SetOsmId(MakeOsmRelation(2 /* id */));
vector<m2::PointD> poly = {{0, 0}, {0, 2}, {2, 2}, {2, 0}, {0, 0}};
fb.AddPolygon(poly);
fb.SetArea();
regions.emplace_back(Region(fb, collector.Get(MakeOsmRelation(2 /* id */))));
}
{
FeatureBuilder fb;
fb.AddName("default", "Country_1_Region_3");
fb.SetOsmId(MakeOsmRelation(3 /* id */));
vector<m2::PointD> poly = {{4, 4}, {7, 5}, {10, 4}, {12, 9}, {15, 7}, {11, 2}, {4, 4}};
fb.AddPolygon(poly);
fb.SetArea();
regions.emplace_back(Region(fb, collector.Get(MakeOsmRelation(3 /* id */))));
}
{
FeatureBuilder fb;
fb.AddName("default", "Country_1_Region_4");
fb.SetOsmId(MakeOsmRelation(4 /* id */));
vector<m2::PointD> poly = {{7, 10}, {9, 12}, {8, 15}, {13, 12}, {15, 7},
{12, 9}, {11, 7}, {10, 10}, {7, 10}};
fb.AddPolygon(poly);
fb.SetArea();
regions.emplace_back(Region(fb, collector.Get(MakeOsmRelation(4 /* id */))));
}
{
FeatureBuilder fb;
fb.AddName("default", "Country_1_Region_5");
fb.SetOsmId(MakeOsmRelation(5 /* id */));
vector<m2::PointD> poly = {{4, 4}, {2, 8}, {3, 12}, {8, 15}, {9, 12},
{7, 10}, {5, 8}, {7, 5}, {4, 4}};
fb.AddPolygon(poly);
fb.SetArea();
regions.emplace_back(Region(fb, collector.Get(MakeOsmRelation(5 /* id */))));
}
{
FeatureBuilder fb;
fb.AddName("default", "Country_1_Region_5_Subregion_6");
fb.SetOsmId(MakeOsmRelation(6 /* id */));
vector<m2::PointD> poly = {{4, 4}, {2, 8}, {3, 12}, {4, 10}, {5, 10}, {5, 8}, {7, 5}, {4, 4}};
fb.AddPolygon(poly);
fb.SetArea();
regions.emplace_back(Region(fb, collector.Get(MakeOsmRelation(6 /* id */))));
}
{
FeatureBuilder fb;
fb.AddName("default", "Country_1_Region_5_Subregion_7");
fb.SetOsmId(MakeOsmRelation(7 /* id */));
vector<m2::PointD> poly = {{3, 12}, {8, 15}, {9, 12}, {7, 10},
{5, 8}, {5, 10}, {4, 10}, {3, 12}};
fb.AddPolygon(poly);
fb.SetArea();
regions.emplace_back(Region(fb, collector.Get(MakeOsmRelation(7 /* id */))));
}
{
FeatureBuilder fb;
fb.AddName("default", "Country_2_Region_8");
fb.SetOsmId(MakeOsmRelation(8 /* id */));
vector<m2::PointD> poly = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}};
fb.AddPolygon(poly);
fb.SetArea();
regions.emplace_back(Region(fb, collector.Get(MakeOsmRelation(8 /* id */))));
}
return regions;
}
class StringJoinPolicy
{
public:
std::string ToString(NodePath const & nodePath) const
{
std::stringstream stream;
for (auto const & n : nodePath)
stream << n->GetData().GetName();
return stream.str();
}
};
bool NameExists(std::vector<std::string> const & coll, std::string const & name)
{
auto const end = std::end(coll);
return std::find(std::begin(coll), end, name) != end;
};
} // namespace
UNIT_TEST(RegionsBuilderTest_GetCountryNames)
{
auto const filename = MakeCollectorData();
SCOPE_GUARD(removeCollectorFile, std::bind(Platform::RemoveFileIfExists, std::cref(filename)));
RegionInfo collector(filename);
RegionsBuilder builder(MakeTestDataSet1(collector), {} /* placePointsMap */);
auto const & countryNames = builder.GetCountryInternationalNames();
TEST_EQUAL(countryNames.size(), 2, ());
TEST(std::count(std::begin(countryNames), std::end(countryNames), "Country_1"), ());
TEST(std::count(std::begin(countryNames), std::end(countryNames), "Country_2"), ());
}
UNIT_TEST(RegionsBuilderTest_GetCountries)
{
auto const filename = MakeCollectorData();
SCOPE_GUARD(removeCollectorFile, std::bind(Platform::RemoveFileIfExists, std::cref(filename)));
RegionInfo collector(filename);
RegionsBuilder builder(MakeTestDataSet1(collector), {} /* placePointsMap */);
auto const & countries = builder.GetCountriesOuters();
TEST_EQUAL(countries.size(), 3, ());
TEST_EQUAL(std::count_if(std::begin(countries), std::end(countries),
[](const Region & r) { return r.GetName() == "Country_1"; }),
1, ());
TEST_EQUAL(std::count_if(std::begin(countries), std::end(countries),
[](const Region & r) { return r.GetName() == "Country_2"; }),
2, ());
}
UNIT_TEST(RegionsBuilderTest_GetCountryTrees)
{
auto const filename = MakeCollectorData();
SCOPE_GUARD(removeCollectorFile, std::bind(Platform::RemoveFileIfExists, std::cref(filename)));
RegionInfo collector(filename);
std::vector<std::string> bankOfNames;
RegionsBuilder builder(MakeTestDataSet1(collector), {} /* placePointsMap */);
builder.ForEachCountry([&](std::string const & name, Node::PtrList const & outers) {
for (auto const & tree : outers)
{
ForEachLevelPath(tree, [&](NodePath const & path) {
StringJoinPolicy stringifier;
bankOfNames.push_back(stringifier.ToString(path));
});
}
});
TEST(NameExists(bankOfNames, "Country_2"), ());
TEST(NameExists(bankOfNames, "Country_2Country_2_Region_8"), ());
TEST(NameExists(bankOfNames, "Country_1"), ());
TEST(NameExists(bankOfNames, "Country_1Country_1_Region_3"), ());
TEST(NameExists(bankOfNames, "Country_1Country_1_Region_4"), ());
TEST(NameExists(bankOfNames, "Country_1Country_1_Region_5"), ());
TEST(NameExists(bankOfNames, "Country_1Country_1_Region_5Country_1_Region_5_Subregion_6"), ());
TEST(NameExists(bankOfNames, "Country_1Country_1_Region_5Country_1_Region_5_Subregion_7"), ());
}
// City generation tests ---------------------------------------------------------------------------
UNIT_TEST(RegionsBuilderTest_GenerateCityPointRegionByAround)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions(
{
{1, {name = u8"Nederland", admin = "2", ba}, {{0.00, 0.00}, {0.50, 0.50}}},
{2, {name = u8"Nederland", admin = "3", ba}, {{0.10, 0.10}, {0.20, 0.20}}},
{3, {name = u8"Noord-Holland", admin = "4", ba}, {{0.12, 0.12}, {0.18, 0.18}}},
{6, {name = u8"Amsterdam", place = "city", admin = "2"}, {{0.15, 0.15}}},
},
true /* withGeometry */);
TEST(HasName(regions, u8"Nederland, locality: Amsterdam [(0.07, 0.07), (0.23, 0.23)]"),
(regions));
}
UNIT_TEST(RegionsBuilderTest_GenerateCityPointRegionByNameMatching)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions(
{
{1, {name = u8"Nederland", admin = "2", ba}, {{0.00, 0.00}, {0.50, 0.50}}},
{2, {name = u8"Nederland", admin = "3", ba}, {{0.10, 0.10}, {0.20, 0.20}}},
{3, {name = u8"Noord-Holland", admin = "4", ba}, {{0.12, 0.12}, {0.18, 0.18}}},
{4, {name = u8"Amsterdam", admin = "8", ba}, {{0.14, 0.14}, {0.17, 0.17}}},
{5, {name = u8"Amsterdam", admin = "10", ba}, {{0.14, 0.14}, {0.16, 0.16}}},
{6, {name = u8"Amsterdam", place = "city", admin = "2"}, {{0.15, 0.15}}},
},
true /* withGeometry */);
TEST(HasName(regions, u8"Nederland, locality: Amsterdam [(0.14, 0.14), (0.16, 0.16)]"), ());
}
UNIT_TEST(RegionsBuilderTest_GenerateCityPointRegionByEnglishNameMatching)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions(
{
{1,
{name = u8"België / Belgique / Belgien", admin = "2", ba},
{{0.00, 0.00}, {0.50, 0.50}}},
{3,
{name = u8"Ville de Bruxelles - Stad Brussel", admin = "8", ba},
{{0.12, 0.12}, {0.18, 0.18}}},
{4,
{name = u8"Bruxelles / Brussel", {"name:en", "Brussels"}, admin = "9", ba},
{{0.12, 0.12}, {0.17, 0.17}}},
{5,
{name = u8"Bruxelles - Brussel", {"name:en", "Brussels"}, place = "city"},
{{0.15, 0.15}}},
},
true /* withGeometry */);
TEST(HasName(regions,
u8"België / Belgique / Belgien, "
u8"locality: Bruxelles - Brussel [(0.12, 0.12), (0.17, 0.17)]"),
());
}
UNIT_TEST(RegionsBuilderTest_GenerateCityPointRegionByNameMatchingWithCityPrefix)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions(
{
{1, {name = u8"United Kingdom", admin = "2", ba}, {{0.00, 0.00}, {0.50, 0.50}}},
{3, {name = u8"Scotland", admin = "4", ba}, {{0.12, 0.12}, {0.18, 0.18}}},
{4, {name = u8"City of Edinburgh", admin = "6", ba}, {{0.12, 0.12}, {0.17, 0.17}}},
{5, {name = u8"Edinburgh", place = "city"}, {{0.15, 0.15}}},
},
true /* withGeometry */);
TEST(HasName(regions,
u8"United Kingdom, region: Scotland [(0.12, 0.12), (0.18, 0.18)], "
u8"locality: Edinburgh [(0.12, 0.12), (0.17, 0.17)]"),
());
}
UNIT_TEST(RegionsBuilderTest_GenerateCityPointRegionByNameMatchingWithCityPostfix)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions(
{
{1, {name = u8"United Kingdom", admin = "2", ba}, {{0.00, 0.00}, {0.50, 0.50}}},
{3, {name = u8"Scotland", admin = "4", ba}, {{0.12, 0.12}, {0.18, 0.18}}},
{4, {name = u8"Edinburgh (city)", admin = "6", ba}, {{0.12, 0.12}, {0.17, 0.17}}},
{5, {name = u8"Edinburgh", place = "city"}, {{0.15, 0.15}}},
},
true /* withGeometry */);
TEST(HasName(regions,
u8"United Kingdom, region: Scotland [(0.12, 0.12), (0.18, 0.18)], "
u8"locality: Edinburgh [(0.12, 0.12), (0.17, 0.17)]"),
());
}
UNIT_TEST(RegionsBuilderTest_GenerateCapitalPointRegionAndAdminRegionWithSameBoundary)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions(
{
{1, {name = u8"Country", admin = "2", ba}, {{0.00, 0.00}, {0.50, 0.50}}},
{2, {name = u8"Region", admin = "6", ba}, {{0.10, 0.10}, {0.20, 0.20}}},
{3, {name = u8"Washington", admin = "8", ba}, {{0.10, 0.10}, {0.20, 0.20}}},
{4, {name = u8"Washington", place = "city", admin = "2"}, {{0.15, 0.15}}},
},
true /* withGeometry */);
TEST_EQUAL(regions.size(), 2, (regions));
TEST(HasName(regions, u8"Country"), (regions));
TEST(HasName(regions, u8"Country, locality: Washington [(0.10, 0.10), (0.20, 0.20)]"),
(regions));
}
// Russia regions tests ----------------------------------------------------------------------------
UNIT_TEST(RegionsBuilderTest_GenerateRusCitySuburb)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions({
{1, {name = u8"Россия", admin = "2", ba}, {{0, 0}, {50, 50}}},
{2, {name = u8"Сибирский федеральный округ", admin = "3", ba}, {{10, 10}, {20, 20}}},
{3, {name = u8"Омская область", admin = "4", ba}, {{12, 12}, {18, 18}}},
{4, {name = u8"Омск", place = "city"}, {{14, 14}, {16, 16}}},
{5,
{name = u8"городской округ Омск", admin = "6", ba},
{{14, 14}, {16, 16}},
{{6, NodeEntry, "admin_centre"}}},
{6, {name = u8"Омск", place = "city"}, {{15, 15}}},
{7, {name = u8"Кировский административный округ", admin = "9", ba}, {{14, 14}, {15, 15}}},
});
TEST(HasName(regions,
u8"Россия, region: Омская область, subregion: городской округ Омск, "
u8"locality: Омск"),
());
TEST(HasName(regions,
u8"Россия, region: Омская область, subregion: городской округ Омск, "
u8"locality: Омск, suburb: Кировский административный округ"),
());
}
UNIT_TEST(RegionsBuilderTest_GenerateRusMoscowSubregion)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions({
{1, {name = u8"Россия", admin = "2", ba}, {{0, 0}, {50, 50}}},
{2, {name = u8"Центральный федеральный округ", admin = "3", ba}, {{10, 10}, {20, 20}}},
{3, {name = u8"Москва", admin = "4", ba}, {{12, 12}, {16, 16}}},
{4, {name = u8"Западный административный округ", admin = "5", ba}, {{12, 12}, {13, 13}}},
{4, {name = u8"Западный административный округ", admin = "5", ba}, {{13, 13}, {15, 14}}},
{5, {name = u8"Северный административный округ", admin = "5", ba}, {{13, 14}, {15, 15}}},
{6, {name = u8"Троицкий административный округ", admin = "5", ba}, {{15, 15}, {16, 16}}},
{7, {name = u8"Москва", place = "city"}, {{12, 12}, {13, 13}}},
{7, {name = u8"Москва", place = "city"}, {{13, 13}, {15, 15}}},
});
TEST(HasName(regions, u8"Россия, region: Москва"), ());
TEST(HasName(regions, u8"Россия, region: Москва, locality: Москва"), ());
TEST(!HasName(regions,
u8"Россия, region: Москва, subregion: Западный административный округ, "
u8"locality: Москва"),
());
TEST(HasName(regions,
u8"Россия, region: Москва, locality: Москва, "
u8"subregion: Западный административный округ"),
());
TEST(HasName(regions,
u8"Россия, region: Москва, locality: Москва, "
u8"subregion: Северный административный округ"),
());
TEST(HasName(regions, u8"Россия, region: Москва, subregion: Троицкий административный округ"),
());
}
UNIT_TEST(RegionsBuilderTest_GenerateRusMoscowSuburb)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions({
{1, {name = u8"Россия", admin = "2", ba}, {{0, 0}, {50, 50}}},
{2, {name = u8"Центральный федеральный округ", admin = "3", ba}, {{10, 10}, {20, 20}}},
{3, {name = u8"Москва", admin = "4", ba}, {{12, 12}, {20, 20}}},
{4, {name = u8"Москва", place = "city"}, {{12, 12}, {19, 19}}},
{5, {name = u8"Западный административный округ", admin = "5", ba}, {{12, 12}, {18, 18}}},
{6,
{name = u8"район Раменки", admin = "8", ba},
{{12, 12}, {15, 15}},
{{7, NodeEntry, "label"}}},
{7, {name = u8"Раменки", place = "suburb"}, {{13, 13}}}, // label
{8, {name = u8"Тропарёво", place = "suburb"}, {{16, 16}}}, // no label
{9, {name = u8"Воробъёвы горы", place = "suburb"}, {{12, 12}, {14, 14}}},
{10, {name = u8"Центр", place = "suburb"}, {{15, 15}, {16, 16}}},
});
TEST(HasName(regions, u8"Россия, region: Москва"), ());
TEST(HasName(regions,
u8"Россия, region: Москва, locality: Москва, "
u8"subregion: Западный административный округ"),
());
TEST(HasName(regions,
u8"Россия, region: Москва, locality: Москва, "
u8"subregion: Западный административный округ, suburb: Раменки"),
());
TEST(HasName(regions,
u8"Россия, region: Москва, locality: Москва, "
u8"subregion: Западный административный округ, "
u8"suburb: Раменки, sublocality: Воробъёвы горы"),
());
TEST(HasName(regions,
u8"Россия, region: Москва, locality: Москва, "
u8"subregion: Западный административный округ, sublocality: Центр"),
());
TEST(!ContainsSubname(regions, u8"Тропарёво"), ());
}
UNIT_TEST(RegionsBuilderTest_GenerateRusSPetersburgSuburb)
{
Tag const admin{"admin_level"};
Tag const place{"place"};
Tag const name{"name"};
TagValue const ba{"boundary", "administrative"};
auto regions = GenerateTestRegions({
{1, {name = u8"Россия", admin = "2", ba}, {{0, 0}, {50, 50}}},
{2, {name = u8"Северо-Западный федеральный округ", admin = "3", ba}, {{10, 10}, {20, 20}}},
{3, {name = u8"Санкт-Петербург", admin = "4", ba}, {{12, 12}, {18, 18}}},
{4, {name = u8"Санкт-Петербург", place = "city"}, {{12, 12}, {17, 17}}},
{5, {name = u8"Центральный район", admin = "5", ba}, {{14, 14}, {16, 16}}},
{6, {name = u8"Дворцовый округ", admin = "8", ba}, {{14, 14}, {15, 15}}},
});
TEST(HasName(regions, u8"Россия, region: Санкт-Петербург, locality: Санкт-Петербург"), ());
TEST(HasName(regions,
u8"Россия, region: Санкт-Петербург, locality: Санкт-Петербург, "
u8"suburb: Центральный район"),
());
TEST(HasName(regions,
u8"Россия, region: Санкт-Петербург, locality: Санкт-Петербург, "
u8"suburb: Центральный район, sublocality: Дворцовый округ"),
());
}

View file

@ -1,31 +0,0 @@
#include "testing/testing.hpp"
#include "generator/streets/street_geometry.hpp"
#include "geometry/point2d.hpp"
using namespace generator::streets;
UNIT_TEST(HighwayGeometryTest_PinAtSingleLineCenter)
{
HighwayGeometry highway{};
highway.AddLine(base::MakeOsmWay(1), {{0.0, 0.0}, {1.0, 1.0}});
auto pin = highway.ChoosePin();
TEST_EQUAL(pin.m_osmId, base::MakeOsmWay(1), ());
TEST(m2::AlmostEqualAbs(pin.m_position, {0.5, 0.5}, 0.001), ());
}
UNIT_TEST(HighwayGeometryTest_PinAtHalfWaySegmentCenter)
{
HighwayGeometry highway{};
highway.AddLine(base::MakeOsmWay(1), {{0.0, 0.0}, {1.0, 0.0}});
highway.AddLine(base::MakeOsmWay(3), {{1.5, 0.5}, {2.0, 0.5}});
highway.AddLine(base::MakeOsmWay(5), {{2.5, 0.0}, {3.8, 0.0}});
highway.AddLine(base::MakeOsmWay(2), {{1.0, 0.0}, {1.5, 0.5}});
highway.AddLine(base::MakeOsmWay(4), {{2.0, 0.5}, {2.5, 0.0}});
auto pin = highway.ChoosePin();
TEST_EQUAL(pin.m_osmId, base::MakeOsmWay(3), ());
TEST(m2::AlmostEqualAbs(pin.m_position, {1.75, 0.5}, 0.001), ());
}

View file

@ -1,64 +0,0 @@
#include "testing/testing.hpp"
#include "generator/streets/street_regions_tracing.hpp"
#include "base/geo_object_id.hpp"
using namespace generator::streets;
using generator::KeyValue;
UNIT_TEST(StreetRegionTracingTest_StreetInOneRegion)
{
auto regionGetter = [] (auto &&) { return KeyValue{1, {}}; };
auto && tracing = StreetRegionsTracing{{{0.0, 0.0}, {1.0, 1.0}}, regionGetter};
auto && segments = tracing.StealPathSegments();
TEST_EQUAL(segments.size(), 1, ());
TEST_EQUAL(segments.front().m_region.first, 1, ());
}
UNIT_TEST(StreetRegionTracingTest_OutgoingStreet)
{
auto regionGetter = [] (auto && point) {
if (point.x < 0.001)
return KeyValue{1, {}};
return KeyValue{2, {}};
};
auto && tracing = StreetRegionsTracing{{{0.0, 0.0}, {1.0, 0.0}}, regionGetter};
auto && segments = tracing.StealPathSegments();
TEST_EQUAL(segments.size(), 2, ());
TEST_EQUAL(segments.front().m_region.first, 1, ());
TEST_EQUAL(segments.back().m_region.first, 2, ());
}
UNIT_TEST(StreetRegionTracingTest_IncomingStreet)
{
auto regionGetter = [] (auto && point) {
if (point.x < 0.999)
return KeyValue{1, {}};
return KeyValue{2, {}};
};
auto && tracing = StreetRegionsTracing{{{0.0, 0.0}, {1.0, 0.0}}, regionGetter};
auto && segments = tracing.StealPathSegments();
TEST_EQUAL(segments.size(), 2, ());
TEST_EQUAL(segments.front().m_region.first, 1, ());
TEST_EQUAL(segments.back().m_region.first, 2, ());
}
UNIT_TEST(StreetRegionTracingTest_StreetWithTransitRegion)
{
auto regionGetter = [] (auto && point) {
if (0.5 <= point.x && point.x <= 0.501)
return KeyValue{2, {}};
return KeyValue{1, {}};
};
auto && tracing = StreetRegionsTracing{{{0.0, 0.0}, {1.0, 0.0}}, regionGetter};
auto && segments = tracing.StealPathSegments();
TEST_EQUAL(segments.size(), 3, ());
TEST_EQUAL(segments[0].m_region.first, 1, ());
TEST_EQUAL(segments[1].m_region.first, 2, ());
TEST_EQUAL(segments[2].m_region.first, 1, ());
}

View file

@ -9,11 +9,10 @@
#include "generator/data_version.hpp"
#include "generator/descriptions_section_builder.hpp"
#include "generator/dumper.hpp"
#include "generator/feature_builder.hpp"
#include "generator/feature_generator.hpp"
#include "generator/feature_sorter.hpp"
#include "generator/generate_info.hpp"
#include "generator/geo_objects/geo_objects_generator.hpp"
#include "generator/locality_sorter.hpp"
#include "generator/maxspeeds_builder.hpp"
#include "generator/metalines_builder.hpp"
#include "generator/osm_source.hpp"
@ -23,14 +22,11 @@
#include "generator/processor_factory.hpp"
#include "generator/ratings_section_builder.hpp"
#include "generator/raw_generator.hpp"
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/regions.hpp"
#include "generator/restriction_generator.hpp"
#include "generator/road_access_generator.hpp"
#include "generator/routing_index_generator.hpp"
#include "generator/search_index_builder.hpp"
#include "generator/statistics.hpp"
#include "generator/streets/streets.hpp"
#include "generator/traffic_generator.hpp"
#include "generator/transit_generator.hpp"
#include "generator/translator_collection.hpp"
@ -117,23 +113,10 @@ DEFINE_uint64(planet_version, base::SecondsSinceEpoch(),
DEFINE_bool(preprocess, false, "1st pass - create nodes/ways/relations data.");
DEFINE_bool(generate_features, false, "2nd pass - generate intermediate features.");
DEFINE_bool(no_ads, false, "generation without ads.");
DEFINE_bool(generate_region_features, false,
"Generate intermediate features for regions to use in regions index and borders generation.");
DEFINE_bool(generate_streets_features, false,
"Generate intermediate features for streets to use in server-side forward geocoder.");
DEFINE_bool(generate_geo_objects_features, false,
"Generate intermediate features for geo objects to use in geo objects index.");
DEFINE_bool(generate_geometry, false,
"3rd pass - split and simplify geometry and triangles for features.");
DEFINE_bool(generate_index, false, "4rd pass - generate index.");
DEFINE_bool(generate_search_index, false, "5th pass - generate search index.");
DEFINE_bool(generate_geo_objects_index, false,
"Generate objects and index for server-side reverse geocoder.");
DEFINE_bool(generate_regions, false,
"Generate regions index and borders for server-side reverse geocoder.");
DEFINE_bool(generate_regions_kv, false,
"Generate regions key-value for server-side reverse geocoder.");
DEFINE_bool(dump_cities_boundaries, false, "Dump cities boundaries to a file");
DEFINE_bool(generate_cities_boundaries, false, "Generate the cities boundaries section");
DEFINE_string(cities_boundaries_data, "", "File with cities boundaries");
@ -207,19 +190,6 @@ DEFINE_bool(generate_addresses_file, false,
DEFINE_bool(generate_traffic_keys, false,
"Generate keys for the traffic map (road segment -> speed group).");
// Generating geo objects key-value.
DEFINE_string(regions_index, "", "Input regions index file.");
DEFINE_string(regions_key_value, "", "Input regions key-value file.");
DEFINE_string(streets_features, "", "Input tmp.mwm file with streets.");
DEFINE_string(streets_key_value, "", "Output streets key-value file.");
DEFINE_string(geo_objects_features, "", "Input tmp.mwm file with geo objects.");
DEFINE_string(ids_without_addresses, "", "Output file with objects ids without addresses.");
DEFINE_string(geo_objects_key_value, "", "Output geo objects key-value file.");
DEFINE_string(allow_addressless_for_countries, "*",
"Allow addressless buildings for only specified countries separated by commas.");
DEFINE_string(regions_features, "", "Input tmp.mwm file with regions.");
DEFINE_string(popularity_csv, "", "Output csv for popularity.");
DEFINE_bool(dump_mwm_tmp, false, "Prints feature builder objects from .mwm.tmp");
@ -310,10 +280,7 @@ int GeneratorToolMain(int argc, char ** argv)
// Generate .mwm.tmp files.
if (FLAGS_generate_features ||
FLAGS_generate_world ||
FLAGS_make_coasts ||
FLAGS_generate_region_features ||
FLAGS_generate_streets_features ||
FLAGS_generate_geo_objects_features)
FLAGS_make_coasts)
{
RawGenerator rawGenerator(genInfo, threadsCount);
if (FLAGS_generate_features)
@ -322,12 +289,6 @@ int GeneratorToolMain(int argc, char ** argv)
rawGenerator.GenerateWorld(FLAGS_no_ads);
if (FLAGS_make_coasts)
rawGenerator.GenerateCoasts();
if (FLAGS_generate_region_features)
rawGenerator.GenerateRegionFeatures(FLAGS_output);
if (FLAGS_generate_streets_features)
rawGenerator.GenerateStreetsFeatures(FLAGS_output);
if (FLAGS_generate_geo_objects_features)
rawGenerator.GenerateGeoObjectsFeatures(FLAGS_output);
if (!rawGenerator.Execute())
return EXIT_FAILURE;
@ -349,88 +310,6 @@ int GeneratorToolMain(int argc, char ** argv)
if (FLAGS_make_routing_index || FLAGS_make_cross_mwm || FLAGS_make_transit_cross_mwm)
countryParentGetter = make_unique<storage::CountryParentGetter>();
if (!FLAGS_streets_key_value.empty())
{
streets::GenerateStreets(FLAGS_regions_index, FLAGS_regions_key_value, FLAGS_streets_features,
FLAGS_geo_objects_features, FLAGS_streets_key_value, FLAGS_verbose,
threadsCount);
}
if (!FLAGS_geo_objects_key_value.empty())
{
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, threadsCount))
return EXIT_FAILURE;
}
if (FLAGS_generate_geo_objects_index || FLAGS_generate_regions)
{
if (FLAGS_output.empty())
{
LOG(LCRITICAL, ("Bad output or intermediate_data_path. Output:", FLAGS_output));
return EXIT_FAILURE;
}
auto const locDataFile = base::JoinPath(path, FLAGS_output + LOC_DATA_FILE_EXTENSION);
auto const outFile = base::JoinPath(path, FLAGS_output + LOC_IDX_FILE_EXTENSION);
if (FLAGS_generate_geo_objects_index)
{
if (!feature::GenerateGeoObjectsData(FLAGS_geo_objects_features, FLAGS_nodes_list_path,
locDataFile))
{
LOG(LCRITICAL, ("Error generating geo objects data."));
return EXIT_FAILURE;
}
LOG(LINFO, ("Saving geo objects index to", outFile));
if (!indexer::BuildGeoObjectsIndexFromDataFile(
locDataFile, outFile, DataVersion::LoadFromPath(path).GetVersionJson(),
DataVersion::kFileTag))
{
LOG(LCRITICAL, ("Error generating geo objects index."));
return EXIT_FAILURE;
}
}
if (FLAGS_generate_regions)
{
if (!feature::GenerateRegionsData(FLAGS_regions_features, locDataFile))
{
LOG(LCRITICAL, ("Error generating regions data."));
return EXIT_FAILURE;
}
LOG(LINFO, ("Saving regions index to", outFile));
if (!indexer::BuildRegionsIndexFromDataFile(locDataFile, outFile,
DataVersion::LoadFromPath(path).GetVersionJson(),
DataVersion::kFileTag))
{
LOG(LCRITICAL, ("Error generating regions index."));
return EXIT_FAILURE;
}
if (!feature::GenerateBorders(FLAGS_regions_features, outFile))
{
LOG(LCRITICAL, ("Error generating regions borders."));
return EXIT_FAILURE;
}
}
}
if (FLAGS_generate_regions_kv)
{
auto const pathInRegionsCollector =
genInfo.GetTmpFileName(genInfo.m_fileName, regions::CollectorRegionInfo::kDefaultExt);
auto const pathInRegionsTmpMwm = genInfo.GetTmpFileName(genInfo.m_fileName);
auto const pathOutRepackedRegionsTmpMwm =
genInfo.GetTmpFileName(genInfo.m_fileName + "_repacked");
auto const pathOutRegionsKv = genInfo.GetIntermediateFileName(genInfo.m_fileName, ".jsonl");
regions::GenerateRegions(pathInRegionsTmpMwm, pathInRegionsCollector, pathOutRegionsKv,
pathOutRepackedRegionsTmpMwm, FLAGS_verbose, threadsCount);
}
if (!FLAGS_popularity_csv.empty())
{
popularity::BuildPopularitySrcFromAllData(genInfo.m_tmpDir, FLAGS_popularity_csv, threadsCount);

View file

@ -1,325 +0,0 @@
#include "generator/data_version.hpp"
#include "generator/feature_builder.hpp"
#include "generator/feature_generator.hpp"
#include "generator/key_value_storage.hpp"
#include "generator/locality_sorter.hpp"
#include "generator/geo_objects/geo_objects.hpp"
#include "generator/geo_objects/geo_objects_filter.hpp"
#include "generator/geo_objects/geo_objects_maintainer.hpp"
#include "generator/regions/region_base.hpp"
#include "indexer/classificator.hpp"
#include "indexer/locality_index.hpp"
#include "indexer/locality_index_builder.hpp"
#include "coding/mmap_reader.hpp"
#include "coding/internal/file_data.hpp"
#include "geometry/mercator.hpp"
#include "base/geo_object_id.hpp"
#include <boost/optional.hpp>
#include "3party/jansson/myjansson.hpp"
#include <cstdint>
#include <fstream>
#include <functional>
#include <mutex>
using namespace feature;
namespace generator
{
namespace geo_objects
{
namespace
{
NullBuildingsInfo GetHelpfulNullBuildings(GeoObjectMaintainer & geoObjectMaintainer,
std::string const & pathInGeoObjectsTmpMwm,
size_t threadsCount)
{
NullBuildingsInfo result;
static int64_t counter = 0;
std::mutex updateMutex;
auto const & view = geoObjectMaintainer.CreateView();
auto const saveIdFold = [&](FeatureBuilder & fb, uint64_t /* currPos */) {
if (!GeoObjectsFilter::HasHouse(fb) || !fb.IsPoint())
return;
// search for ids of Buildinds not stored with geoObjectsMantainer
// they are nullBuildings
auto const buildingId =
view.SearchIdOfFirstMatchedObject(fb.GetKeyPoint(), [&view](base::GeoObjectId id) {
auto const & geoData = view.GetGeoData(id);
return geoData && geoData->m_house.empty();
});
if (!buildingId)
return;
auto const id = fb.GetMostGenericOsmId();
std::lock_guard<std::mutex> lock(updateMutex);
result.m_addressPoints2Buildings[id] = *buildingId;
counter++;
if (counter % 100000 == 0)
LOG(LINFO, (counter, "Helpful building added"));
result.m_Buildings2AddressPoint[*buildingId] = id;
};
ForEachParallelFromDatRawFormat(threadsCount, pathInGeoObjectsTmpMwm, saveIdFold);
return result;
}
using BuildingsGeometries =
std::unordered_map<base::GeoObjectId, feature::FeatureBuilder::Geometry>;
BuildingsGeometries GetBuildingsGeometry(std::string const & pathInGeoObjectsTmpMwm,
NullBuildingsInfo const & buildingsInfo,
size_t threadsCount)
{
BuildingsGeometries result;
std::mutex updateMutex;
static int64_t counter = 0;
auto const saveIdFold = [&](FeatureBuilder & fb, uint64_t /* currPos */) {
auto const id = fb.GetMostGenericOsmId();
if (buildingsInfo.m_Buildings2AddressPoint.find(id) ==
buildingsInfo.m_Buildings2AddressPoint.end() ||
fb.GetParams().GetGeomType() != feature::GeomType::Area)
return;
std::lock_guard<std::mutex> lock(updateMutex);
if (result.find(id) != result.end())
LOG(LINFO, ("More than one geometry for", id));
else
result[id] = fb.GetGeometry();
counter++;
if (counter % 100000 == 0)
LOG(LINFO, (counter, "Building geometries added"));
};
ForEachParallelFromDatRawFormat(threadsCount, pathInGeoObjectsTmpMwm, saveIdFold);
return result;
}
size_t AddBuildingGeometriesToAddressPoints(std::string const & pathInGeoObjectsTmpMwm,
NullBuildingsInfo const & buildingsInfo,
BuildingsGeometries const & geometries,
size_t threadsCount)
{
auto const path = GetPlatform().TmpPathForFile();
FeaturesCollector collector(path);
std::atomic_size_t pointsEnriched{0};
std::mutex collectorMutex;
auto concurrentCollector = [&](FeatureBuilder & fb, uint64_t /* currPos */) {
auto const id = fb.GetMostGenericOsmId();
auto point2BuildingIt = buildingsInfo.m_addressPoints2Buildings.find(id);
if (point2BuildingIt != buildingsInfo.m_addressPoints2Buildings.end())
{
auto geometryIt = geometries.find(point2BuildingIt->second);
if (geometryIt != geometries.end())
{
auto const & geometry = geometryIt->second;
// ResetGeometry does not reset center but SetCenter changes geometry type to Point and
// adds center to bounding rect
fb.SetCenter({});
// ResetGeometry clears bounding rect
fb.ResetGeometry();
fb.GetParams().SetGeomType(feature::GeomType::Area);
for (std::vector<m2::PointD> poly : geometry)
fb.AddPolygon(poly);
fb.PreSerialize();
++pointsEnriched;
if (pointsEnriched % 100000 == 0)
LOG(LINFO, (pointsEnriched, "Points enriched with geometry"));
}
else
{
LOG(LINFO, (point2BuildingIt->second, "is a null building with strange geometry"));
}
}
std::lock_guard<std::mutex> lock(collectorMutex);
collector.Collect(fb);
};
ForEachParallelFromDatRawFormat(threadsCount, pathInGeoObjectsTmpMwm, concurrentCollector);
CHECK(base::RenameFileX(path, pathInGeoObjectsTmpMwm), ());
return pointsEnriched;
}
base::JSONPtr FindHouse(FeatureBuilder const & fb,
GeoObjectMaintainer::GeoObjectsView const & geoView,
NullBuildingsInfo const & buildingsInfo)
{
base::JSONPtr house =
geoView.GetFullGeoObject(fb.GetKeyPoint(), [](GeoObjectMaintainer::GeoObjectData const & data) {
return !data.m_house.empty();
});
if (house)
return house;
std::vector<base::GeoObjectId> potentialIds = geoView.SearchObjectsInIndex(fb.GetKeyPoint());
for (base::GeoObjectId id : potentialIds)
{
auto const it = buildingsInfo.m_Buildings2AddressPoint.find(id);
if (it != buildingsInfo.m_Buildings2AddressPoint.end())
return geoView.GetFullGeoObjectWithoutNameAndCoordinates(it->second);
}
return {};
}
base::JSONPtr MakeJsonValueWithNameFromFeature(FeatureBuilder const & fb, JsonValue const & json)
{
auto jsonWithAddress = json.MakeDeepCopyJson();
auto properties = json_object_get(jsonWithAddress.get(), "properties");
Localizator localizator(*properties);
localizator.SetLocale("name", Localizator::EasyObjectWithTranslation(fb.GetMultilangName()));
UpdateCoordinates(fb.GetKeyPoint(), jsonWithAddress);
return jsonWithAddress;
}
} // namespace
bool JsonHasBuilding(JsonValue const & json)
{
auto && address =
base::GetJSONObligatoryFieldByPath(json, "properties", "locales", "default", "address");
auto && building = base::GetJSONOptionalField(address, "building");
return building && !base::JSONIsNull(building);
}
boost::optional<indexer::GeoObjectsIndex<IndexReader>> MakeTempGeoObjectsIndex(
std::string const & pathToGeoObjectsTmpMwm)
{
auto const dataFile = GetPlatform().TmpPathForFile();
SCOPE_GUARD(removeDataFile, std::bind(Platform::RemoveFileIfExists, std::cref(dataFile)));
if (!GenerateGeoObjectsData(pathToGeoObjectsTmpMwm, "" /* nodesFile */, dataFile))
{
LOG(LCRITICAL, ("Error generating geo objects data."));
return {};
}
auto const indexFile = GetPlatform().TmpPathForFile();
SCOPE_GUARD(removeIndexFile, std::bind(Platform::RemoveFileIfExists, std::cref(indexFile)));
if (!indexer::BuildGeoObjectsIndexFromDataFile(dataFile, indexFile, std::string(), DataVersion::kFileTag))
{
LOG(LCRITICAL, ("Error generating geo objects index."));
return {};
}
return indexer::ReadIndex<indexer::GeoObjectsIndexBox<IndexReader>, MmapReader>(indexFile);
}
void AddBuildingsAndThingsWithHousesThenEnrichAllWithRegionAddresses(
GeoObjectMaintainer & geoObjectMaintainer, std::string const & pathInGeoObjectsTmpMwm,
bool verbose, size_t threadsCount)
{
auto const concurrentTransformer = [&](FeatureBuilder & fb, uint64_t /* currPos */) {
geoObjectMaintainer.StoreAndEnrich(fb);
};
ForEachParallelFromDatRawFormat(threadsCount, pathInGeoObjectsTmpMwm, concurrentTransformer);
LOG(LINFO, ("Added", geoObjectMaintainer.Size(), "geo objects with addresses."));
}
NullBuildingsInfo EnrichPointsWithOuterBuildingGeometry(GeoObjectMaintainer & geoObjectMaintainer,
std::string const & pathInGeoObjectsTmpMwm,
size_t threadsCount)
{
auto const buildingInfo =
GetHelpfulNullBuildings(geoObjectMaintainer, pathInGeoObjectsTmpMwm, threadsCount);
LOG(LINFO, ("Found", buildingInfo.m_addressPoints2Buildings.size(),
"address points with outer building geometry"));
LOG(LINFO,
("Found", buildingInfo.m_Buildings2AddressPoint.size(), "helpful addressless buildings"));
auto const buildingGeometries =
GetBuildingsGeometry(pathInGeoObjectsTmpMwm, buildingInfo, threadsCount);
LOG(LINFO, ("Saved", buildingGeometries.size(), "buildings geometries"));
size_t const pointsCount = AddBuildingGeometriesToAddressPoints(
pathInGeoObjectsTmpMwm, buildingInfo, buildingGeometries, threadsCount);
LOG(LINFO, (pointsCount, "address points were enriched with outer building geomery"));
return buildingInfo;
}
void AddPoisEnrichedWithHouseAddresses(GeoObjectMaintainer & geoObjectMaintainer,
NullBuildingsInfo const & buildingsInfo,
std::string const & pathInGeoObjectsTmpMwm,
std::ostream & streamPoiIdsToAddToLocalityIndex,
bool verbose, size_t threadsCount)
{
std::atomic_size_t counter{0};
std::mutex streamMutex;
auto const & view = geoObjectMaintainer.CreateView();
auto const concurrentTransformer = [&](FeatureBuilder & fb, uint64_t /* currPos */) {
if (!GeoObjectsFilter::IsPoi(fb))
return;
if (GeoObjectsFilter::IsBuilding(fb) || GeoObjectsFilter::HasHouse(fb))
return;
// No name and coordinates here, we will take it from fb in MakeJsonValueWithNameFromFeature
auto house = FindHouse(fb, view, buildingsInfo);
if (!house)
return;
auto const id = fb.GetMostGenericOsmId();
auto jsonValue = MakeJsonValueWithNameFromFeature(fb, JsonValue{std::move(house)});
counter++;
if (counter % 100000 == 0)
LOG(LINFO, (counter, "pois added"));
geoObjectMaintainer.WriteToStorage(id, JsonValue{std::move(jsonValue)});
std::lock_guard<std::mutex> lock(streamMutex);
streamPoiIdsToAddToLocalityIndex << id << "\n";
};
ForEachParallelFromDatRawFormat(threadsCount, pathInGeoObjectsTmpMwm, concurrentTransformer);
LOG(LINFO, ("Added", counter, "POIs enriched with address."));
}
void FilterAddresslessThanGaveTheirGeometryToInnerPoints(std::string const & pathInGeoObjectsTmpMwm,
NullBuildingsInfo const & buildingsInfo,
size_t threadsCount)
{
auto const path = GetPlatform().TmpPathForFile();
FeaturesCollector collector(path);
std::mutex collectorMutex;
auto concurrentCollect = [&](FeatureBuilder const & fb, uint64_t /* currPos */) {
auto const id = fb.GetMostGenericOsmId();
if (buildingsInfo.m_Buildings2AddressPoint.find(id) !=
buildingsInfo.m_Buildings2AddressPoint.end())
return;
std::lock_guard<std::mutex> lock(collectorMutex);
collector.Collect(fb);
};
ForEachParallelFromDatRawFormat(threadsCount, pathInGeoObjectsTmpMwm, concurrentCollect);
CHECK(base::RenameFileX(path, pathInGeoObjectsTmpMwm), ());
}
} // namespace geo_objects
} // namespace generator

View file

@ -1,59 +0,0 @@
#pragma once
#include "generator/key_value_storage.hpp"
#include "generator/geo_objects/geo_objects_maintainer.hpp"
#include "geometry/meter.hpp"
#include "geometry/point2d.hpp"
#include "base/logging.hpp"
#include "base/scope_guard.hpp"
#include "base/timer.hpp"
#include "platform/platform.hpp"
#include <string>
namespace generator
{
namespace geo_objects
{
using IndexReader = ReaderPtr<Reader>;
boost::optional<indexer::GeoObjectsIndex<IndexReader>> MakeTempGeoObjectsIndex(
std::string const & pathToGeoObjectsTmpMwm);
bool JsonHasBuilding(JsonValue const & json);
void AddBuildingsAndThingsWithHousesThenEnrichAllWithRegionAddresses(
GeoObjectMaintainer & geoObjectMaintainer, std::string const & pathInGeoObjectsTmpMwm,
bool verbose, size_t threadsCount);
struct NullBuildingsInfo
{
std::unordered_map<base::GeoObjectId, base::GeoObjectId> m_addressPoints2Buildings;
// Quite possible to have many points for one building. We want to use
// their addresses for POIs according to buildings and have no idea how to distinguish between
// them, so take one random
std::unordered_map<base::GeoObjectId, base::GeoObjectId> m_Buildings2AddressPoint;
};
NullBuildingsInfo EnrichPointsWithOuterBuildingGeometry(
GeoObjectMaintainer & geoObjectMaintainer, std::string const & pathInGeoObjectsTmpMwm,
size_t threadsCount);
void AddPoisEnrichedWithHouseAddresses(GeoObjectMaintainer & geoObjectMaintainer,
NullBuildingsInfo const & buildingsInfo,
std::string const & pathInGeoObjectsTmpMwm,
std::ostream & streamPoiIdsToAddToLocalityIndex,
bool verbose, size_t threadsCount);
void FilterAddresslessThanGaveTheirGeometryToInnerPoints(std::string const & pathInGeoObjectsTmpMwm,
NullBuildingsInfo const & buildingsInfo,
size_t threadsCount);
} // namespace geo_objects
} // namespace generator

View file

@ -1,54 +0,0 @@
#include "generator/geo_objects/geo_objects_filter.hpp"
#include "generator/osm_element_helpers.hpp"
#include "indexer/ftypes_matcher.hpp"
using namespace feature;
namespace generator
{
namespace geo_objects
{
std::shared_ptr<FilterInterface> GeoObjectsFilter::Clone() const
{
return std::make_shared<GeoObjectsFilter>();
}
bool GeoObjectsFilter::IsAccepted(OsmElement const & element)
{
return osm_element::IsBuilding(element) || osm_element::HasHouse(element) || osm_element::IsPoi(element);
}
bool GeoObjectsFilter::IsAccepted(FeatureBuilder const & feature)
{
if (!feature.GetParams().IsValid())
return false;
if (feature.IsLine())
return false;
return IsBuilding(feature) || HasHouse(feature) || IsPoi(feature);
}
// static
bool GeoObjectsFilter::IsBuilding(FeatureBuilder const & fb)
{
auto const & checker = ftypes::IsBuildingChecker::Instance();
return checker(fb.GetTypes());
}
// static
bool GeoObjectsFilter::HasHouse(FeatureBuilder const & fb)
{
return !fb.GetParams().house.IsEmpty();
}
// static
bool GeoObjectsFilter::IsPoi(FeatureBuilder const & fb)
{
auto const & poiChecker = ftypes::IsPoiChecker::Instance();
return poiChecker(fb.GetTypes());
}
} // namespace geo_objects
} // namespace generator

View file

@ -1,25 +0,0 @@
#pragma once
#include "generator/feature_builder.hpp"
#include "generator/filter_interface.hpp"
#include "generator/osm_element.hpp"
namespace generator
{
namespace geo_objects
{
class GeoObjectsFilter : public FilterInterface
{
public:
// FilterInterface overrides:
std::shared_ptr<FilterInterface> Clone() const override;
bool IsAccepted(OsmElement const & element) override;
bool IsAccepted(feature::FeatureBuilder const & feature) override;
static bool IsBuilding(feature::FeatureBuilder const & fb);
static bool HasHouse(feature::FeatureBuilder const & fb);
static bool IsPoi(feature::FeatureBuilder const & fb);
};
} // namespace geo_objects
} // namespace generator

View file

@ -1,113 +0,0 @@
#include "generator/geo_objects/geo_objects_generator.hpp"
#include "base/logging.hpp"
#include "base/scope_guard.hpp"
#include "base/timer.hpp"
#include <future>
namespace
{
template <class Activist>
auto Measure(std::string activity, Activist && activist)
{
LOG(LINFO, ("Start", activity));
auto timer = base::Timer();
SCOPE_GUARD(_, [&]() { LOG(LINFO, ("Finish", activity, timer.ElapsedSeconds(), "seconds.")); });
return activist();
}
} // namespace
namespace generator
{
namespace geo_objects
{
GeoObjectsGenerator::GeoObjectsGenerator(
GeoObjectMaintainer::RegionInfoGetter && regionInfoGetter,
GeoObjectMaintainer::RegionIdGetter && regionIdGetter, std::string pathInGeoObjectsTmpMwm,
std::string pathOutIdsWithoutAddress, std::string pathOutGeoObjectsKv, bool verbose,
size_t threadsCount)
: m_pathInGeoObjectsTmpMwm(std::move(pathInGeoObjectsTmpMwm))
, m_pathOutPoiIdsToAddToLocalityIndex(std::move(pathOutIdsWithoutAddress))
, m_pathOutGeoObjectsKv(std::move(pathOutGeoObjectsKv))
, m_verbose(verbose)
, m_threadsCount(threadsCount)
, m_geoObjectMaintainer{m_pathOutGeoObjectsKv, std::move(regionInfoGetter), std::move(regionIdGetter)}
{
}
bool GeoObjectsGenerator::GenerateGeoObjects()
{
return Measure("generating geo objects", [&]() { return GenerateGeoObjectsPrivate(); });
}
bool GeoObjectsGenerator::GenerateGeoObjectsPrivate()
{
auto geoObjectIndexFuture =
std::async(std::launch::async, MakeTempGeoObjectsIndex, m_pathInGeoObjectsTmpMwm);
AddBuildingsAndThingsWithHousesThenEnrichAllWithRegionAddresses(
m_geoObjectMaintainer, m_pathInGeoObjectsTmpMwm, m_verbose, m_threadsCount);
LOG(LINFO, ("Geo objects with addresses were built."));
auto geoObjectIndex = geoObjectIndexFuture.get();
LOG(LINFO, ("Index was built."));
if (!geoObjectIndex)
return false;
m_geoObjectMaintainer.SetIndex(std::move(*geoObjectIndex));
LOG(LINFO, ("Enrich address points with outer null building geometry."));
NullBuildingsInfo const & buildingInfo = EnrichPointsWithOuterBuildingGeometry(
m_geoObjectMaintainer, m_pathInGeoObjectsTmpMwm, m_threadsCount);
std::ofstream streamPoiIdsToAddToLocalityIndex(m_pathOutPoiIdsToAddToLocalityIndex);
AddPoisEnrichedWithHouseAddresses(m_geoObjectMaintainer, buildingInfo, m_pathInGeoObjectsTmpMwm,
streamPoiIdsToAddToLocalityIndex, m_verbose, m_threadsCount);
FilterAddresslessThanGaveTheirGeometryToInnerPoints(m_pathInGeoObjectsTmpMwm, buildingInfo,
m_threadsCount);
LOG(LINFO, ("Addressless buildings with geometry we used for inner points were filtered"));
LOG(LINFO, ("Geo objects without addresses were built."));
LOG(LINFO, ("Geo objects key-value storage saved to", m_pathOutGeoObjectsKv));
LOG(LINFO, ("Ids of POIs without addresses saved to", m_pathOutPoiIdsToAddToLocalityIndex));
return true;
}
bool GenerateGeoObjects(std::string const & regionsIndex, std::string const & regionsKeyValue,
std::string const & geoObjectsFeatures,
std::string const & nodesListToIndex, std::string const & geoObjectKeyValue,
bool verbose, size_t threadsCount)
{
auto regionInfoGetter = regions::RegionInfoGetter(regionsIndex, regionsKeyValue);
LOG(LINFO, ("Size of regions key-value storage:", regionInfoGetter.GetStorage().Size()));
auto findDeepest = [&regionInfoGetter](auto && point) {
return regionInfoGetter.FindDeepest(point);
};
auto keyValueFind = [&regionInfoGetter](auto && id) {
return regionInfoGetter.GetStorage().Find(id.GetEncodedId());
};
geo_objects::GeoObjectsGenerator geoObjectsGenerator{std::move(findDeepest),
std::move(keyValueFind),
geoObjectsFeatures,
nodesListToIndex,
geoObjectKeyValue,
verbose,
threadsCount};
return geoObjectsGenerator.GenerateGeoObjects();
}
} // namespace geo_objects
} // namespace generator

View file

@ -1,54 +0,0 @@
#include "generator/key_value_storage.hpp"
#include "generator/regions/region_info_getter.hpp"
#include "generator/geo_objects/geo_objects.hpp"
#include "geometry/meter.hpp"
#include "geometry/point2d.hpp"
#include "platform/platform.hpp"
#include <string>
namespace generator
{
namespace geo_objects
{
class GeoObjectsGenerator
{
public:
GeoObjectsGenerator(GeoObjectMaintainer::RegionInfoGetter && regionInfoGetter,
GeoObjectMaintainer::RegionIdGetter && regionIdGetter,
std::string pathInGeoObjectsTmpMwm, std::string pathOutIdsWithoutAddress,
std::string pathOutGeoObjectsKv, bool verbose, size_t threadsCount);
// This function generates key-value pairs for geo objects.
// First, we try to generate key-value pairs only for houses, since we cannot say anything about
// poi. In this step, we need key-value pairs for the regions and the index for the regions. Then
// we build an index for houses. And then we finish building key-value pairs for poi using this
// index for houses.
bool GenerateGeoObjects();
GeoObjectMaintainer& GetMaintainer()
{
return m_geoObjectMaintainer;
}
private:
bool GenerateGeoObjectsPrivate();
std::string m_pathInGeoObjectsTmpMwm;
std::string m_pathOutPoiIdsToAddToLocalityIndex;
std::string m_pathOutGeoObjectsKv;
bool m_verbose = false;
size_t m_threadsCount = 1;
GeoObjectMaintainer m_geoObjectMaintainer;
};
bool GenerateGeoObjects(std::string const & regionsIndex, std::string const & regionsKeyValue,
std::string const & geoObjectsFeatures,
std::string const & nodesListToIndex, std::string const & geoObjectKeyValue,
bool verbose, size_t threadsCount);
} // namespace geo_objects
} // namespace generator

View file

@ -1,183 +0,0 @@
#include "generator/geo_objects/geo_objects_maintainer.hpp"
#include "generator/geo_objects/geo_objects_filter.hpp"
#include "generator/key_value_storage.hpp"
#include "generator/translation.hpp"
#include <utility>
namespace generator
{
namespace geo_objects
{
GeoObjectMaintainer::GeoObjectMaintainer(std::string const & pathOutGeoObjectsKv,
RegionInfoGetter && regionInfoGetter,
RegionIdGetter && regionIdGetter)
: m_geoObjectsKvStorage{InitGeoObjectsKv(pathOutGeoObjectsKv)}
, m_regionInfoGetter{std::move(regionInfoGetter)}
, m_regionIdGetter(std::move(regionIdGetter))
{
}
// static
std::fstream GeoObjectMaintainer::InitGeoObjectsKv(std::string const & pathOutGeoObjectsKv)
{
std::fstream result{pathOutGeoObjectsKv,
std::ios_base::in | std::ios_base::out | std::ios_base::app};
if (!result)
MYTHROW(Reader::OpenException, ("Failed to open file", pathOutGeoObjectsKv));
return result;
}
void UpdateCoordinates(m2::PointD const & point, base::JSONPtr & json)
{
auto geometry = json_object_get(json.get(), "geometry");
auto coordinates = json_object_get(geometry, "coordinates");
if (json_array_size(coordinates) == 2)
{
auto const latLon = MercatorBounds::ToLatLon(point);
json_array_set_new(coordinates, 0, ToJSON(latLon.m_lon).release());
json_array_set_new(coordinates, 1, ToJSON(latLon.m_lat).release());
}
}
base::JSONPtr AddAddress(std::string const & street, std::string const & house, m2::PointD point,
StringUtf8Multilang const & name, KeyValue const & regionKeyValue)
{
auto result = regionKeyValue.second->MakeDeepCopyJson();
UpdateCoordinates(point, result);
auto properties = base::GetJSONObligatoryField(result.get(), "properties");
auto address = base::GetJSONObligatoryFieldByPath(properties, "locales", "default", "address");
if (!street.empty())
ToJSONObject(*address, "street", street);
// By writing home null in the field we can understand that the house has no address.
if (!house.empty())
ToJSONObject(*address, "building", house);
else
ToJSONObject(*address, "building", base::NewJSONNull());
Localizator localizator(*properties);
localizator.SetLocale("name", Localizator::EasyObjectWithTranslation(name));
int const kHouseOrPoiRank = 30;
ToJSONObject(*properties, "rank", kHouseOrPoiRank);
ToJSONObject(*properties, "dref", KeyValueStorage::SerializeDref(regionKeyValue.first));
return result;
}
void GeoObjectMaintainer::StoreAndEnrich(feature::FeatureBuilder & fb)
{
if (!GeoObjectsFilter::IsBuilding(fb) && !GeoObjectsFilter::HasHouse(fb))
return;
auto regionKeyValue = m_regionInfoGetter(fb.GetKeyPoint());
if (!regionKeyValue)
return;
auto const id = fb.GetMostGenericOsmId();
auto jsonValue = AddAddress(fb.GetParams().GetStreet(), fb.GetParams().house.Get(),
fb.GetKeyPoint(), fb.GetMultilangName(), *regionKeyValue);
{
std::lock_guard<std::mutex> lock(m_updateMutex);
auto const it = m_geoId2GeoData.emplace(
std::make_pair(id, GeoObjectData{fb.GetParams().GetStreet(), fb.GetParams().house.Get(),
base::GeoObjectId(regionKeyValue->first)}));
// Duplicate ID's are possible
if (!it.second)
return;
}
WriteToStorage(id, JsonValue{std::move(jsonValue)});
}
void GeoObjectMaintainer::WriteToStorage(base::GeoObjectId id, JsonValue && value)
{
std::lock_guard<std::mutex> lock(m_storageMutex);
m_geoObjectsKvStorage << KeyValueStorage::SerializeFullLine(id.GetEncodedId(), std::move(value));
}
// GeoObjectMaintainer::GeoObjectsView
base::JSONPtr GeoObjectMaintainer::GeoObjectsView::GetFullGeoObject(
m2::PointD point,
std::function<bool(GeoObjectMaintainer::GeoObjectData const &)> && pred) const
{
auto const ids = SearchGeoObjectIdsByPoint(m_geoIndex, point);
for (auto const & id : ids)
{
auto const it = m_geoId2GeoData.find(id);
if (it == m_geoId2GeoData.end())
continue;
auto const geoData = it->second;
if (!pred(geoData))
continue;
auto regionJsonValue = m_regionIdGetter(geoData.m_regionId);
if (!regionJsonValue)
return {};
return AddAddress(geoData.m_street, geoData.m_house, point, StringUtf8Multilang(),
KeyValue(geoData.m_regionId.GetEncodedId(), regionJsonValue));
}
return {};
}
base::JSONPtr GeoObjectMaintainer::GeoObjectsView::GetFullGeoObjectWithoutNameAndCoordinates(
base::GeoObjectId id) const
{
auto const it = m_geoId2GeoData.find(id);
if (it == m_geoId2GeoData.end())
return {};
auto const geoData = it->second;
auto regionJsonValue = m_regionIdGetter(geoData.m_regionId);
if (!regionJsonValue)
return {};
// no need to store name here, it will be overriden by poi name
return AddAddress(geoData.m_street, geoData.m_house, m2::PointD(), StringUtf8Multilang(),
KeyValue(geoData.m_regionId.GetEncodedId(), regionJsonValue));
}
boost::optional<GeoObjectMaintainer::GeoObjectData> GeoObjectMaintainer::GeoObjectsView::GetGeoData(
base::GeoObjectId id) const
{
auto const it = m_geoId2GeoData.find(id);
if (it == m_geoId2GeoData.end())
return {};
return it->second;
}
boost::optional<base::GeoObjectId>
GeoObjectMaintainer::GeoObjectsView::SearchIdOfFirstMatchedObject(
m2::PointD const & point, std::function<bool(base::GeoObjectId)> && pred) const
{
auto const ids = SearchObjectsInIndex(point);
for (auto const & id : ids)
{
if (pred(id))
return id;
}
return {};
}
std::vector<base::GeoObjectId> GeoObjectMaintainer::GeoObjectsView::SearchGeoObjectIdsByPoint(
GeoIndex const & index, m2::PointD point)
{
std::vector<base::GeoObjectId> ids;
auto const emplace = [&ids](base::GeoObjectId const & osmId) { ids.emplace_back(osmId); };
index.ForEachAtPoint(emplace, point);
return ids;
}
} // namespace geo_objects
} // namespace generator

View file

@ -1,114 +0,0 @@
#pragma once
#include "generator/key_value_storage.hpp"
#include "generator/regions/region_info_getter.hpp"
#include "generator/feature_builder.hpp"
#include "indexer/locality_index.hpp"
#include "coding/reader.hpp"
#include "geometry/point2d.hpp"
#include "base/geo_object_id.hpp"
#include <functional>
#include <memory>
#include <utility>
#include <vector>
#include <boost/optional.hpp>
#include "3party/jansson/myjansson.hpp"
namespace generator
{
namespace geo_objects
{
void UpdateCoordinates(m2::PointD const & point, base::JSONPtr & json);
class GeoObjectMaintainer
{
public:
using RegionInfoGetter = std::function<boost::optional<KeyValue>(m2::PointD const & pathPoint)>;
using RegionIdGetter = std::function<std::shared_ptr<JsonValue>(base::GeoObjectId id)>;
struct GeoObjectData
{
std::string m_street;
std::string m_house;
base::GeoObjectId m_regionId;
};
using GeoId2GeoData = std::unordered_map<base::GeoObjectId, GeoObjectData>;
using GeoIndex = indexer::GeoObjectsIndex<ReaderPtr<Reader>>;
class GeoObjectsView
{
public:
GeoObjectsView(GeoIndex const & geoIndex, GeoId2GeoData const & geoId2GeoData,
RegionIdGetter const & regionIdGetter, std::mutex & updateMutex)
: m_geoIndex(geoIndex)
, m_geoId2GeoData(geoId2GeoData)
, m_regionIdGetter(regionIdGetter)
, m_lock(updateMutex, std::defer_lock)
{
CHECK(m_lock.try_lock(), ("Cannot create GeoObjectView on locked mutex"));
}
boost::optional<base::GeoObjectId> SearchIdOfFirstMatchedObject(
m2::PointD const & point, std::function<bool(base::GeoObjectId)> && pred) const;
boost::optional<GeoObjectData> GetGeoData(base::GeoObjectId id) const;
std::vector<base::GeoObjectId> SearchObjectsInIndex(m2::PointD const & point) const
{
return SearchGeoObjectIdsByPoint(m_geoIndex, point);
}
base::JSONPtr GetFullGeoObjectWithoutNameAndCoordinates(base::GeoObjectId id) const;
base::JSONPtr GetFullGeoObject(
m2::PointD point,
std::function<bool(GeoObjectMaintainer::GeoObjectData const &)> && pred) const;
static std::vector<base::GeoObjectId> SearchGeoObjectIdsByPoint(GeoIndex const & index,
m2::PointD point);
private:
GeoIndex const & m_geoIndex;
GeoId2GeoData const & m_geoId2GeoData;
RegionIdGetter const & m_regionIdGetter;
std::unique_lock<std::mutex> m_lock;
};
GeoObjectMaintainer(std::string const & pathOutGeoObjectsKv, RegionInfoGetter && regionInfoGetter,
RegionIdGetter && regionIdGetter);
void SetIndex(GeoIndex && index) { m_index = std::move(index); }
void StoreAndEnrich(feature::FeatureBuilder & fb);
void WriteToStorage(base::GeoObjectId id, JsonValue && value);
size_t Size() const { return m_geoId2GeoData.size(); }
GeoObjectsView CreateView()
{
return GeoObjectsView(m_index, m_geoId2GeoData, m_regionIdGetter, m_updateMutex);
}
private:
static std::fstream InitGeoObjectsKv(std::string const & pathOutGeoObjectsKv);
std::fstream m_geoObjectsKvStorage;
std::mutex m_updateMutex;
std::mutex m_storageMutex;
GeoIndex m_index;
RegionInfoGetter m_regionInfoGetter;
RegionIdGetter m_regionIdGetter;
GeoId2GeoData m_geoId2GeoData;
};
} // namespace geo_objects
} // namespace generator

View file

@ -1,292 +0,0 @@
#include "generator/locality_sorter.hpp"
#include "generator/geo_objects/geo_objects_filter.hpp"
#include "generator/geometry_holder.hpp"
#include "generator/utils.hpp"
#include "indexer/data_header.hpp"
#include "indexer/scales.hpp"
#include "indexer/scales_patch.hpp"
#include "coding/file_container.hpp"
#include "coding/internal/file_data.hpp"
#include "geometry/convex_hull.hpp"
#include "platform/platform.hpp"
#include "base/assert.hpp"
#include "base/file_name_utils.hpp"
#include "base/logging.hpp"
#include "base/scope_guard.hpp"
#include "base/string_utils.hpp"
#include "base/timer.hpp"
#include "defines.hpp"
#include <cstdint>
#include <fstream>
#include <functional>
#include <limits>
#include <set>
#include <vector>
using namespace feature;
using namespace std;
namespace
{
class BordersCollector : public FeaturesCollector
{
public:
explicit BordersCollector(string const & filename)
: FeaturesCollector(filename + EXTENSION_TMP), m_writer(filename, FileWriter::OP_WRITE_EXISTING)
{
}
// FeaturesCollector overrides:
uint32_t Collect(FeatureBuilder & fb) override
{
if (fb.IsArea())
{
FeatureBuilder::Buffer buffer;
fb.SerializeBorderForIntermediate(serial::GeometryCodingParams(), buffer);
WriteFeatureBase(buffer, fb);
}
return 0;
}
void Finish() override
{
Flush();
m_writer.Write(m_datFile.GetName(), BORDERS_FILE_TAG);
m_writer.Finish();
}
private:
FilesContainerW m_writer;
DataHeader m_header;
DISALLOW_COPY_AND_MOVE(BordersCollector);
};
class LocalityCollector : public FeaturesCollector
{
public:
LocalityCollector(string const & filename, DataHeader const & header, uint32_t versionDate)
: FeaturesCollector(filename + EXTENSION_TMP)
, m_writer(filename)
, m_header(header)
, m_versionDate(versionDate)
{
}
// FeaturesCollector overrides:
void Finish() override
{
{
auto w = m_writer.GetWriter(VERSION_FILE_TAG);
version::WriteVersion(*w, m_versionDate);
}
m_header.SetBounds(m_bounds);
{
auto w = m_writer.GetWriter(HEADER_FILE_TAG);
m_header.Save(*w);
}
Flush();
m_writer.Write(m_datFile.GetName(), LOCALITY_DATA_FILE_TAG);
m_writer.Finish();
}
uint32_t Collect(FeatureBuilder & fb) override
{
// Do not limit inner triangles number to save all geometry without additional sections.
GeometryHolder holder(fb, m_header, numeric_limits<uint32_t>::max() /* maxTrianglesNumber */);
// Simplify and serialize geometry.
vector<m2::PointD> points;
m2::SquaredDistanceFromSegmentToPoint<m2::PointD> distFn;
SimplifyPoints(distFn, scales::GetUpperScale(), holder.GetSourcePoints(), points);
// For areas we save outer geometry only.
if (fb.IsArea() && holder.NeedProcessTriangles())
{
// At this point we don't need last point equal to first.
points.pop_back();
auto const & polys = fb.GetGeometry();
if (polys.size() != 1)
{
points.clear();
for (auto const & poly : polys)
points.insert(points.end(), poly.begin(), poly.end());
}
if (points.size() > 2)
{
if (!holder.TryToMakeStrip(points))
{
m2::ConvexHull hull(points, 1e-16);
vector<m2::PointD> hullPoints = hull.Points();
holder.SetInner();
auto const id = fb.GetMostGenericOsmId();
if (!holder.TryToMakeStrip(hullPoints))
{
LOG(LWARNING, ("Error while building tringles for object with OSM Id:", id.GetSerialId(),
"Type:", id.GetType(), "points:", points, "hull:", hull.Points()));
return 0;
}
}
}
}
auto & buffer = holder.GetBuffer();
if (fb.PreSerializeAndRemoveUselessNamesForMwm(buffer))
{
fb.SerializeLocalityObject(serial::GeometryCodingParams(), buffer);
WriteFeatureBase(buffer.m_buffer, fb);
}
return 0;
}
private:
FilesContainerW m_writer;
DataHeader m_header;
uint32_t m_versionDate;
DISALLOW_COPY_AND_MOVE(LocalityCollector);
};
bool ParseNodes(string nodesFile, set<uint64_t> & nodeIds)
{
if (nodesFile.empty())
return true;
ifstream stream(nodesFile);
if (!stream)
{
LOG(LERROR, ("Could not open", nodesFile));
return false;
}
string line;
size_t lineNumber = 1;
while (getline(stream, line))
{
strings::SimpleTokenizer iter(line, " ");
uint64_t nodeId;
if (!iter || !strings::to_uint64(*iter, nodeId))
{
LOG(LERROR, ("Error while parsing node id at line", lineNumber, "Line contents:", line));
return false;
}
nodeIds.insert(nodeId);
++lineNumber;
}
return true;
}
using NeedSerialize = function<bool(FeatureBuilder & fb1)>;
bool GenerateLocalityDataImpl(FeaturesCollector & collector,
CalculateMidPoints::MinDrawableScalePolicy const & minDrawableScalePolicy,
NeedSerialize const & needSerialize,
string const & featuresFile, string const & dataFile)
{
// Transform features from raw format to LocalityObject format.
try
{
LOG(LINFO, ("Processing", featuresFile));
CalculateMidPoints midPoints{minDrawableScalePolicy};
ForEachFromDatRawFormat(featuresFile, midPoints);
// Sort features by their middle point.
midPoints.Sort();
FileReader reader(featuresFile);
for (auto const & point : midPoints.GetVector())
{
ReaderSource<FileReader> src(reader);
src.Skip(point.second);
FeatureBuilder f;
ReadFromSourceRawFormat(src, f);
// Emit object.
if (needSerialize(f))
collector.Collect(f);
}
collector.Finish();
}
catch (RootException const & ex)
{
LOG(LCRITICAL, ("Locality data writing error:", ex.Msg()));
return false;
}
return true;
}
} // namespace
namespace feature
{
bool GenerateGeoObjectsData(string const & featuresFile, string const & nodesFile,
string const & dataFile)
{
set<uint64_t> nodeIds;
if (!ParseNodes(nodesFile, nodeIds))
return false;
auto const needSerialize = [&nodeIds](FeatureBuilder & fb) {
if (!fb.IsPoint() && !fb.IsArea())
return false;
using generator::geo_objects::GeoObjectsFilter;
if (GeoObjectsFilter::IsBuilding(fb) || GeoObjectsFilter::HasHouse(fb))
return true;
if (GeoObjectsFilter::IsPoi(fb))
return 0 != nodeIds.count(fb.GetMostGenericOsmId().GetEncodedId());
return false;
};
DataHeader header;
header.SetGeometryCodingParams(serial::GeometryCodingParams());
header.SetScales({scales::GetUpperScale()});
LocalityCollector localityCollector(dataFile, header,
static_cast<uint32_t>(base::SecondsSinceEpoch()));
return GenerateLocalityDataImpl(
localityCollector,
static_cast<int (*)(TypesHolder const & types, m2::RectD limitRect)>(GetMinDrawableScale),
needSerialize, featuresFile, dataFile);
}
bool GenerateRegionsData(string const & featuresFile, string const & dataFile)
{
DataHeader header;
header.SetGeometryCodingParams(serial::GeometryCodingParams());
header.SetScales({scales::GetUpperScale()});
LocalityCollector regionsCollector(dataFile, header,
static_cast<uint32_t>(base::SecondsSinceEpoch()));
auto const needSerialize = [](FeatureBuilder const & fb) { return fb.IsArea(); };
return GenerateLocalityDataImpl(regionsCollector, GetMinDrawableScaleGeometryOnly,
needSerialize, featuresFile, dataFile);
}
bool GenerateBorders(string const & featuresFile, string const & dataFile)
{
BordersCollector bordersCollector(dataFile);
auto const needSerialize = [](FeatureBuilder const & fb) { return fb.IsArea(); };
return GenerateLocalityDataImpl(bordersCollector, GetMinDrawableScaleGeometryOnly,
needSerialize, featuresFile, dataFile);
}
} // namespace feature

View file

@ -1,23 +0,0 @@
#pragma once
#include <string>
namespace feature
{
// Generates data for GeoObjectsIndexBuilder from input feature-dat-files.
// @param featuresDir - path to folder with pregenerated features data;
// @param nodesFile - path to file with list of node ids we need to add to output;
// @param out - output file name;
bool GenerateGeoObjectsData(std::string const & featuresFile, std::string const & nodesFile,
std::string const & out);
// Generates data for RegionsIndexBuilder from input feature-dat-files.
// @param featuresDir - path to folder with pregenerated features data;
// @param out - output file name;
bool GenerateRegionsData(std::string const & featuresFile, std::string const & out);
// Generates borders section for server-side reverse geocoder from input feature-dat-files.
// @param featuresDir - path to folder with pregenerated features data;
// @param out - output file to add borders section;
bool GenerateBorders(std::string const & featuresDir, std::string const & out);
} // namespace feature

View file

@ -56,24 +56,6 @@ void RawGenerator::GenerateCoasts()
m_finalProcessors.emplace(CreateCoslineFinalProcessor());
}
void RawGenerator::GenerateRegionFeatures(string const & filename)
{
auto processor = CreateProcessor(ProcessorType::Simple, m_queue, filename);
m_translators->Append(CreateTranslator(TranslatorType::Regions, processor, m_cache, m_genInfo));
}
void RawGenerator::GenerateStreetsFeatures(string const & filename)
{
auto processor = CreateProcessor(ProcessorType::Simple, m_queue, filename);
m_translators->Append(CreateTranslator(TranslatorType::Streets, processor, m_cache));
}
void RawGenerator::GenerateGeoObjectsFeatures(string const & filename)
{
auto processor = CreateProcessor(ProcessorType::Simple, m_queue, filename);
m_translators->Append(CreateTranslator(TranslatorType::GeoObjects, processor, m_cache));
}
void RawGenerator::GenerateCustom(std::shared_ptr<TranslatorInterface> const & translator)
{
m_translators->Append(translator);

View file

@ -23,9 +23,6 @@ public:
void GenerateCountries(bool disableAds = true);
void GenerateWorld(bool disableAds = true);
void GenerateCoasts();
void GenerateRegionFeatures(std::string const & filename);
void GenerateStreetsFeatures(std::string const & filename);
void GenerateGeoObjectsFeatures(std::string const & filename);
void GenerateCustom(std::shared_ptr<TranslatorInterface> const & translator);
void GenerateCustom(std::shared_ptr<TranslatorInterface> const & translator,
std::shared_ptr<FinalProcessorIntermediateMwmInterface> const & finalProcessor);

View file

@ -1,77 +0,0 @@
#include "generator/regions/admin_suburbs_marker.hpp"
#include "generator/regions/region.hpp"
namespace generator
{
namespace regions
{
void AdminSuburbsMarker::MarkSuburbs(Node::Ptr & tree)
{
auto const & region = tree->GetData();
if (region.GetLevel() == PlaceLevel::Locality)
{
MarkLocality(tree);
return;
}
for (auto & subtree : tree->GetChildren())
MarkSuburbs(subtree);
}
void AdminSuburbsMarker::MarkLocality(Node::Ptr & tree)
{
ASSERT(tree->GetData().GetLevel() == PlaceLevel::Locality, ());
for (auto & subtree : tree->GetChildren())
MarkSuburbsInLocality(subtree, tree->GetData());
}
void AdminSuburbsMarker::MarkSuburbsInLocality(Node::Ptr & tree, LevelRegion const & locality)
{
auto & region = tree->GetData();
if (region.GetLevel() == PlaceLevel::Locality)
{
MarkLocality(tree);
return;
}
if (region.GetLevel() == PlaceLevel::Unknown && region.GetAdminLevel() != AdminLevel::Unknown)
{
if (region.GetName() != locality.GetName() ||
region.GetArea() < kLocalityAreaRatioMax * locality.GetArea())
{
region.SetLevel(PlaceLevel::Suburb);
}
}
if (region.GetLevel() >= PlaceLevel::Suburb)
{
for (auto & subtree : tree->GetChildren())
MarkUnderLocalityAsSublocalities(subtree);
return;
}
for (auto & subtree : tree->GetChildren())
MarkSuburbsInLocality(subtree, locality);
}
void AdminSuburbsMarker::MarkUnderLocalityAsSublocalities(Node::Ptr & tree)
{
auto & region = tree->GetData();
auto const level = region.GetLevel();
if (level == PlaceLevel::Locality)
{
MarkLocality(tree);
return;
}
if (level == PlaceLevel::Suburb)
region.SetLevel(PlaceLevel::Sublocality);
else if (level == PlaceLevel::Unknown)
region.SetLevel(PlaceLevel::Sublocality);
for (auto & subtree : tree->GetChildren())
MarkUnderLocalityAsSublocalities(subtree);
}
} // namespace regions
} // namespace generator

View file

@ -1,22 +0,0 @@
#pragma once
#include "generator/regions/node.hpp"
namespace generator
{
namespace regions
{
class AdminSuburbsMarker
{
public:
static constexpr double kLocalityAreaRatioMax = 0.8;
void MarkSuburbs(Node::Ptr & tree);
private:
void MarkLocality(Node::Ptr & tree);
void MarkSuburbsInLocality(Node::Ptr & tree, LevelRegion const & locality);
void MarkUnderLocalityAsSublocalities(Node::Ptr & tree);
};
} // namespace regions
} // namespace generator

View file

@ -1,214 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/intermediate_data.hpp"
#include "generator/osm_element.hpp"
#include "coding/file_writer.hpp"
#include "base/assert.hpp"
#include "base/logging.hpp"
#include "base/macros.hpp"
#include <map>
using namespace feature;
namespace generator
{
namespace regions
{
std::string const CollectorRegionInfo::kDefaultExt = ".regions.bin";
uint8_t const CollectorRegionInfo::kVersion = 0;
PlaceType EncodePlaceType(std::string const & place)
{
static std::map<std::string, PlaceType> const m = {
{"country", PlaceType::Country},
{"state", PlaceType::State},
{"province", PlaceType::Province},
{"district", PlaceType::District},
{"county", PlaceType::County},
{"municipality", PlaceType::Municipality},
{"city", PlaceType::City},
{"town", PlaceType::Town},
{"village", PlaceType::Village},
{"hamlet", PlaceType::Hamlet},
{"isolated_dwelling", PlaceType::IsolatedDwelling},
{"suburb", PlaceType::Suburb},
{"quarter", PlaceType::Quarter},
{"neighbourhood", PlaceType::Neighbourhood},
};
auto const it = m.find(place);
return it == m.end() ? PlaceType::Unknown : it->second;
}
char const * StringifyPlaceType(PlaceType placeType)
{
switch (placeType)
{
case PlaceType::Country:
return "country";
case PlaceType::State:
return "state";
case PlaceType::Province:
return "province";
case PlaceType::District:
return "district";
case PlaceType::County:
return "county";
case PlaceType::Municipality:
return "municipality";
case PlaceType::City:
return "city";
case PlaceType::Town:
return "town";
case PlaceType::Village:
return "village";
case PlaceType::Hamlet:
return "hamlet";
case PlaceType::IsolatedDwelling:
return "isolated_dwelling";
case PlaceType::Suburb:
return "suburb";
case PlaceType::Quarter:
return "quarter";
case PlaceType::Neighbourhood:
return "neighbourhood";
case PlaceType::Unknown:
return "unknown";
};
UNREACHABLE();
}
char const * GetLabel(PlaceLevel level)
{
switch (level)
{
case PlaceLevel::Country:
return "country";
case PlaceLevel::Region:
return "region";
case PlaceLevel:: Subregion:
return "subregion";
case PlaceLevel::Locality:
return "locality";
case PlaceLevel::Suburb:
return "suburb";
case PlaceLevel::Sublocality:
return "sublocality";
case PlaceLevel::Unknown:
return nullptr;
case PlaceLevel::Count:
UNREACHABLE();
}
UNREACHABLE();
}
CollectorRegionInfo::CollectorRegionInfo(std::string const & filename)
: CollectorInterface(filename) {}
std::shared_ptr<CollectorInterface>
CollectorRegionInfo::Clone(std::shared_ptr<cache::IntermediateDataReader> const &) const
{
return std::make_shared<CollectorRegionInfo>(GetFilename());
}
void CollectorRegionInfo::Collect(OsmElement const & el)
{
base::GeoObjectId const osmId = GetGeoObjectId(el);
RegionData regionData;
FillRegionData(osmId, el, regionData);
m_mapRegionData.emplace(osmId, regionData);
// If the region is a country.
if (regionData.m_place == PlaceType::Country || regionData.m_adminLevel == AdminLevel::Two)
{
IsoCode isoCode;
FillIsoCode(osmId, el, isoCode);
m_mapIsoCode.emplace(osmId, isoCode);
}
}
void CollectorRegionInfo::Save()
{
FileWriter writer(GetFilename());
WriteToSink(writer, kVersion);
WriteMap(writer, m_mapRegionData);
WriteMap(writer, m_mapIsoCode);
}
void CollectorRegionInfo::Merge(CollectorInterface const & collector)
{
collector.MergeInto(*this);
}
void CollectorRegionInfo::MergeInto(CollectorRegionInfo & collector) const
{
collector.m_mapRegionData.insert(std::begin(m_mapRegionData), std::end(m_mapRegionData));
collector.m_mapIsoCode.insert(std::begin(m_mapIsoCode), std::end(m_mapIsoCode));
}
void CollectorRegionInfo::FillRegionData(base::GeoObjectId const & osmId, OsmElement const & el,
RegionData & rd)
{
rd.m_osmId = osmId;
rd.m_place = EncodePlaceType(el.GetTag("place"));
auto const al = el.GetTag("admin_level");
if (!al.empty())
{
try
{
auto const adminLevel = std::stoi(al);
// Administrative level is in the range [1 ... 12].
// https://wiki.openstreetmap.org/wiki/Tag:boundary=administrative
rd.m_adminLevel = (adminLevel >= 1 && adminLevel <= 12) ?
static_cast<AdminLevel>(adminLevel) : AdminLevel::Unknown;
}
catch (std::exception const & e) // std::invalid_argument, std::out_of_range
{
LOG(LWARNING, (e.what()));
rd.m_adminLevel = AdminLevel::Unknown;
}
}
for (auto const & member : el.Members())
{
if (member.m_role == "label" && member.m_type == OsmElement::EntityType::Node)
rd.m_labelOsmId = base::MakeOsmNode(member.m_ref);
}
}
void CollectorRegionInfo::FillIsoCode(base::GeoObjectId const & osmId, OsmElement const & el,
IsoCode & rd)
{
rd.m_osmId = osmId;
rd.SetAlpha2(el.GetTag("ISO3166-1:alpha2"));
rd.SetAlpha3(el.GetTag("ISO3166-1:alpha3"));
rd.SetNumeric(el.GetTag("ISO3166-1:numeric"));
}
void IsoCode::SetAlpha2(std::string const & alpha2)
{
if (alpha2.size() + 1 != ARRAY_SIZE(m_alpha2))
return;
std::strcpy(m_alpha2, alpha2.data());
}
void IsoCode::SetAlpha3(std::string const & alpha3)
{
if (alpha3.size() + 1 != ARRAY_SIZE(m_alpha3))
return;
std::strcpy(m_alpha3, alpha3.data());
}
void IsoCode::SetNumeric(std::string const & numeric)
{
if (numeric.size() + 1 != ARRAY_SIZE(m_numeric))
return;
std::strcpy(m_numeric, numeric.data());
}
} // namespace regions
} // namespace generator

View file

@ -1,169 +0,0 @@
#pragma once
#include "generator/collector_interface.hpp"
#include "generator/feature_builder.hpp"
#include "platform/platform.hpp"
#include "coding/write_to_sink.hpp"
#include "base/geo_object_id.hpp"
#include <cstdint>
#include <ostream>
#include <memory>
#include <string>
#include <type_traits>
#include <unordered_map>
struct OsmElement;
class FeatureParams;
class FileWriter;
namespace generator
{
namespace cache
{
class IntermediateDataReader;
} // namespace cache
namespace regions
{
// https://wiki.openstreetmap.org/wiki/Tag:boundary=administrative
enum class AdminLevel : uint8_t
{
Unknown = 0,
Two = 2,
Three = 3,
Four = 4,
Five = 5,
Six = 6,
Seven = 7,
Eight = 8,
Nine = 9,
Ten = 10,
Eleven = 11,
Twelve = 12,
};
// https://wiki.openstreetmap.org/wiki/Key:place
enum class PlaceType: uint8_t
{
Unknown = 0,
Country = 1,
State = 2,
Province = 3,
District = 4,
County = 5,
Municipality = 6,
City = 7,
Town = 8,
Village = 9,
Hamlet = 10,
IsolatedDwelling = 11,
Suburb = 12,
Quarter = 13,
Neighbourhood = 14,
};
PlaceType EncodePlaceType(std::string const & place);
char const * StringifyPlaceType(PlaceType placeType);
enum class PlaceLevel : uint8_t
{
Unknown = 0,
Country = 1,
Region = 2,
Subregion = 3,
Locality = 4,
Suburb = 5,
Sublocality = 6,
Count,
};
char const * GetLabel(PlaceLevel level);
// Codes for the names of countries, dependent territories, and special areas of geographical
// interest.
// https://en.wikipedia.org/wiki/ISO_3166-1
struct IsoCode
{
bool HasAlpha2() const { return m_alpha2[0] != '\0'; }
bool HasAlpha3() const { return m_alpha3[0] != '\0'; }
bool HasNumeric() const { return m_numeric[0] != '\0'; }
void SetAlpha2(std::string const & alpha2);
void SetAlpha3(std::string const & alpha3);
void SetNumeric(std::string const & numeric);
std::string GetAlpha2() const { return m_alpha2; }
std::string GetAlpha3() const { return m_alpha3; }
std::string GetNumeric() const { return m_numeric; }
base::GeoObjectId m_osmId;
char m_alpha2[3] = {};
char m_alpha3[4] = {};
char m_numeric[4] = {};
};
struct RegionData
{
base::GeoObjectId m_osmId;
AdminLevel m_adminLevel = AdminLevel::Unknown;
PlaceType m_place = PlaceType::Unknown;
base::GeoObjectId m_labelOsmId;
};
using MapRegionData = std::unordered_map<base::GeoObjectId, RegionData>;
using MapIsoCode = std::unordered_map<base::GeoObjectId, IsoCode>;
// CollectorRegionInfo class is responsible for collecting additional information about regions.
class CollectorRegionInfo : public CollectorInterface
{
public:
static uint8_t const kVersion;
static std::string const kDefaultExt;
CollectorRegionInfo(std::string const & filename);
// CollectorInterface overrides:
std::shared_ptr<CollectorInterface>
Clone(std::shared_ptr<cache::IntermediateDataReader> const & = {}) const override;
void Collect(OsmElement const & el) override;
void Save() override;
void Merge(CollectorInterface const & collector) override;
void MergeInto(CollectorRegionInfo & collector) const override;
private:
template <typename Sink, typename Map>
void WriteMap(Sink & sink, Map & seq)
{
static_assert(std::is_trivially_copyable<typename Map::mapped_type>::value, "");
uint32_t const sizeRegionData = static_cast<uint32_t>(seq.size());
WriteToSink(sink, sizeRegionData);
for (auto const & el : seq)
sink.Write(&el.second, sizeof(el.second));
}
void FillRegionData(base::GeoObjectId const & osmId, OsmElement const & el, RegionData & rd);
void FillIsoCode(base::GeoObjectId const & osmId, OsmElement const & el, IsoCode & rd);
MapRegionData m_mapRegionData;
MapIsoCode m_mapIsoCode;
};
inline std::ostream & operator<<(std::ostream & out, AdminLevel const & t)
{
out << static_cast<int>(t);
return out;
}
inline std::ostream & operator<<(std::ostream & out, PlaceType const & t)
{
out << static_cast<int>(t);
return out;
}
} // namespace regions
} // namespace generator

View file

@ -1,129 +0,0 @@
#include "generator/regions/country_specifier.hpp"
namespace generator
{
namespace regions
{
void CountrySpecifier::AdjustRegionsLevel(Node::PtrList & outers)
{ }
PlaceLevel CountrySpecifier::GetLevel(Region const & region) const
{
auto const placeType = region.GetPlaceType();
auto const placeLevel = GetLevel(placeType);
if (placeLevel != PlaceLevel::Unknown)
return placeLevel;
return GetSpecificCountryLevel(region);
}
PlaceLevel CountrySpecifier::GetSpecificCountryLevel(Region const & region) const
{
auto const placeType = region.GetPlaceType();
if (region.GetAdminLevel() == AdminLevel::Two &&
(placeType == PlaceType::Country || placeType == PlaceType::Unknown))
{
return PlaceLevel::Country;
}
return PlaceLevel::Unknown;
}
// static
PlaceLevel CountrySpecifier::GetLevel(PlaceType placeType)
{
switch (placeType)
{
case PlaceType::Country:
return PlaceLevel::Country;
case PlaceType::State:
case PlaceType::Province:
return PlaceLevel::Region;
case PlaceType::District:
case PlaceType::County:
case PlaceType::Municipality:
return PlaceLevel::Subregion;
case PlaceType::City:
case PlaceType::Town:
case PlaceType::Village:
case PlaceType::Hamlet:
case PlaceType::IsolatedDwelling:
return PlaceLevel::Locality;
case PlaceType::Suburb:
return PlaceLevel::Suburb;
case PlaceType::Quarter:
case PlaceType::Neighbourhood:
return PlaceLevel::Sublocality;
return PlaceLevel::Sublocality;
case PlaceType::Unknown:
break;
}
return PlaceLevel::Unknown;
}
int CountrySpecifier::RelateByWeight(LevelRegion const & l, LevelRegion const & r) const
{
auto const lLevel = l.GetLevel();
auto const rLevel = r.GetLevel();
if (lLevel != PlaceLevel::Unknown && rLevel != PlaceLevel::Unknown)
{
if (lLevel > rLevel)
return -1;
if (lLevel < rLevel)
return 1;
}
auto const lPlaceType = l.GetPlaceType();
auto const rPlaceType = r.GetPlaceType();
if (lPlaceType != PlaceType::Unknown && rPlaceType != PlaceType::Unknown)
{
if (lPlaceType > rPlaceType)
return -1;
if (lPlaceType < rPlaceType)
return 1;
// Check by admin level (administrative city (district + city) > city).
}
auto const lAdminLevel = l.GetAdminLevel();
auto const rAdminLevel = r.GetAdminLevel();
if (lAdminLevel != AdminLevel::Unknown && rAdminLevel != AdminLevel::Unknown)
{
if (lAdminLevel > rAdminLevel &&
// Ignore capital point (admin_level=2).
(rAdminLevel != AdminLevel::Two || rLevel == PlaceLevel::Country))
{
return -1;
}
if (lAdminLevel < rAdminLevel &&
// Ignore capital point (admin_level=2).
(lAdminLevel != AdminLevel::Two || lLevel == PlaceLevel::Country))
{
return 1;
}
}
else
{
if (lAdminLevel != AdminLevel::Unknown)
return 1;
else if (rAdminLevel != AdminLevel::Unknown)
return -1;
}
// Let leveled region is derived region.
if (lLevel != PlaceLevel::Unknown && rLevel == PlaceLevel::Unknown)
return -1;
if (rLevel != PlaceLevel::Unknown && lLevel == PlaceLevel::Unknown)
return 1;
// Let place-marked region is derived region.
if (lPlaceType != PlaceType::Unknown && rPlaceType == PlaceType::Unknown)
return -1;
if (rPlaceType != PlaceType::Unknown && lPlaceType == PlaceType::Unknown)
return 1;
CHECK_NOT_EQUAL(l.GetOriginId(), r.GetOriginId(), ());
return l.GetOriginId() < r.GetOriginId() ? 1 : -1;
}
} // namespace regions
} // namespace generator

View file

@ -1,28 +0,0 @@
#pragma once
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/level_region.hpp"
#include "generator/regions/node.hpp"
#include "generator/regions/region.hpp"
namespace generator
{
namespace regions
{
class CountrySpecifier
{
public:
virtual ~CountrySpecifier() = default;
virtual void AdjustRegionsLevel(Node::PtrList & outers);
PlaceLevel GetLevel(Region const & region) const;
// Return -1 - |l| is under place of |r|, 1 - |r| is under place of |l|.
virtual int RelateByWeight(LevelRegion const & l, LevelRegion const & r) const;
static PlaceLevel GetLevel(PlaceType placeType);
private:
virtual PlaceLevel GetSpecificCountryLevel(Region const & region) const;
};
} // namespace regions
} // namespace generator

View file

@ -1,147 +0,0 @@
#include "country_specifier_builder.hpp"
namespace generator
{
namespace regions
{
std::unique_ptr<CountrySpecifier> CountrySpecifierBuilder::MakeCountrySpecifier(
std::string const & country) const
{
auto it = m_specifiers.find(country);
if (it == m_specifiers.end())
{
LOG(LWARNING, ("Country", country, "has not specifier, look at generator/regions/specs"));
return std::make_unique<CountrySpecifier>();
}
return it->second();
}
} // namespace regions
} // namespace generator
#include "generator/regions/specs/afghanistan.inl"
#include "generator/regions/specs/albania.inl"
#include "generator/regions/specs/algeria.inl"
#include "generator/regions/specs/andorra.inl"
#include "generator/regions/specs/angola.inl"
#include "generator/regions/specs/antigua_and_barbuda.inl"
#include "generator/regions/specs/argentina.inl"
#include "generator/regions/specs/aruba.inl"
#include "generator/regions/specs/australia.inl"
#include "generator/regions/specs/austria.inl"
#include "generator/regions/specs/azerbaijan.inl"
#include "generator/regions/specs/bahamas.inl"
#include "generator/regions/specs/bahrain.inl"
#include "generator/regions/specs/bangladesh.inl"
#include "generator/regions/specs/barbados.inl"
#include "generator/regions/specs/belarus.inl"
#include "generator/regions/specs/belgium.inl"
#include "generator/regions/specs/belize.inl"
#include "generator/regions/specs/benin.inl"
#include "generator/regions/specs/bhutan.inl"
#include "generator/regions/specs/bolivia.inl"
#include "generator/regions/specs/bosnia_and_herzegovina.inl"
#include "generator/regions/specs/brazil.inl"
#include "generator/regions/specs/brunei.inl"
#include "generator/regions/specs/bulgaria.inl"
#include "generator/regions/specs/burkina_faso.inl"
#include "generator/regions/specs/burundi.inl"
#include "generator/regions/specs/cameroon.inl"
#include "generator/regions/specs/canada.inl"
#include "generator/regions/specs/chad.inl"
#include "generator/regions/specs/chile.inl"
#include "generator/regions/specs/china.inl"
#include "generator/regions/specs/colombia.inl"
#include "generator/regions/specs/costa_rica.inl"
#include "generator/regions/specs/cote_divoire.inl"
#include "generator/regions/specs/croatia.inl"
#include "generator/regions/specs/cuba.inl"
#include "generator/regions/specs/cyprus.inl"
#include "generator/regions/specs/czech_republic.inl"
#include "generator/regions/specs/denmark.inl"
#include "generator/regions/specs/dominican_republic.inl"
#include "generator/regions/specs/egypt.inl"
#include "generator/regions/specs/estonia.inl"
#include "generator/regions/specs/ethiopia.inl"
#include "generator/regions/specs/finland.inl"
#include "generator/regions/specs/france.inl"
#include "generator/regions/specs/french_polynesia.inl"
#include "generator/regions/specs/gabon.inl"
#include "generator/regions/specs/gambia.inl"
#include "generator/regions/specs/georgia.inl"
#include "generator/regions/specs/germany.inl"
#include "generator/regions/specs/ghana.inl"
#include "generator/regions/specs/greece.inl"
#include "generator/regions/specs/guinea.inl"
#include "generator/regions/specs/haiti.inl"
#include "generator/regions/specs/hong_kong.inl"
#include "generator/regions/specs/hungary.inl"
#include "generator/regions/specs/iceland.inl"
#include "generator/regions/specs/india.inl"
#include "generator/regions/specs/indonesia.inl"
#include "generator/regions/specs/iran.inl"
#include "generator/regions/specs/iraq.inl"
#include "generator/regions/specs/ireland.inl"
#include "generator/regions/specs/isle_of_man.inl"
#include "generator/regions/specs/israel.inl"
#include "generator/regions/specs/italy.inl"
#include "generator/regions/specs/japan.inl"
#include "generator/regions/specs/jordan.inl"
#include "generator/regions/specs/kosovo.inl"
#include "generator/regions/specs/laos.inl"
#include "generator/regions/specs/latvia.inl"
#include "generator/regions/specs/lebanon.inl"
#include "generator/regions/specs/lesotho.inl"
#include "generator/regions/specs/liberia.inl"
#include "generator/regions/specs/libya.inl"
#include "generator/regions/specs/lithuania.inl"
#include "generator/regions/specs/luxembourg.inl"
#include "generator/regions/specs/macedonia.inl"
#include "generator/regions/specs/madagascar.inl"
#include "generator/regions/specs/malawi.inl"
#include "generator/regions/specs/malaysia.inl"
#include "generator/regions/specs/mali.inl"
#include "generator/regions/specs/mauritania.inl"
#include "generator/regions/specs/moldova.inl"
#include "generator/regions/specs/morocco.inl"
#include "generator/regions/specs/mozambique.inl"
#include "generator/regions/specs/myanmar.inl"
#include "generator/regions/specs/nepal.inl"
#include "generator/regions/specs/netherlands.inl"
#include "generator/regions/specs/new_zealand.inl"
#include "generator/regions/specs/niger.inl"
#include "generator/regions/specs/nigeria.inl"
#include "generator/regions/specs/north_korea.inl"
#include "generator/regions/specs/norway.inl"
#include "generator/regions/specs/philippines.inl"
#include "generator/regions/specs/poland.inl"
#include "generator/regions/specs/portugal.inl"
#include "generator/regions/specs/romania.inl"
#include "generator/regions/specs/russia.inl"
#include "generator/regions/specs/senegal.inl"
#include "generator/regions/specs/serbia.inl"
#include "generator/regions/specs/sierra_leone.inl"
#include "generator/regions/specs/slovakia.inl"
#include "generator/regions/specs/slovenia.inl"
#include "generator/regions/specs/south_africa.inl"
#include "generator/regions/specs/south_korea.inl"
#include "generator/regions/specs/south_sudan.inl"
#include "generator/regions/specs/suriname.inl"
#include "generator/regions/specs/swaziland.inl"
#include "generator/regions/specs/sweden.inl"
#include "generator/regions/specs/switzerland.inl"
#include "generator/regions/specs/syria.inl"
#include "generator/regions/specs/taiwan.inl"
#include "generator/regions/specs/tajikistan.inl"
#include "generator/regions/specs/tanzania.inl"
#include "generator/regions/specs/thailand.inl"
#include "generator/regions/specs/the_central_african_republic.inl"
#include "generator/regions/specs/togo.inl"
#include "generator/regions/specs/tunisia.inl"
#include "generator/regions/specs/turkey.inl"
#include "generator/regions/specs/uganda.inl"
#include "generator/regions/specs/ukraine.inl"
#include "generator/regions/specs/united_kingdom.inl"
#include "generator/regions/specs/united_states.inl"
#include "generator/regions/specs/vanuatu.inl"
#include "generator/regions/specs/vietnam.inl"

View file

@ -1,55 +0,0 @@
#pragma once
#include "generator/regions/country_specifier.hpp"
#include "base/logging.hpp"
#include <memory>
#include <string>
namespace generator
{
namespace regions
{
class CountrySpecifierBuilder
{
public:
static CountrySpecifierBuilder & GetInstance()
{
static CountrySpecifierBuilder instance;
return instance;
}
std::unique_ptr<CountrySpecifier> MakeCountrySpecifier(std::string const & country) const;
template <class T>
void Register()
{
for (std::string name : T::GetCountryNames())
m_specifiers.emplace(std::make_pair(std::move(name), []() { return std::make_unique<T>(); }));
}
private:
CountrySpecifierBuilder() = default;
CountrySpecifierBuilder(const CountrySpecifierBuilder&) = delete;
CountrySpecifierBuilder& operator=(const CountrySpecifierBuilder&) = delete;
CountrySpecifierBuilder(CountrySpecifierBuilder&&) = delete;
CountrySpecifierBuilder& operator=(CountrySpecifierBuilder&&) = delete;
std::unordered_map<std::string, std::function<std::unique_ptr<CountrySpecifier>(void)>>
m_specifiers;
};
#define REGISTER_COUNTRY_SPECIFIER(Specifier) \
struct COUNTRY_SPECIFIER_##Specifier \
{ \
COUNTRY_SPECIFIER_##Specifier() \
{ \
CountrySpecifierBuilder::GetInstance().Register<Specifier>(); \
} \
}; \
static COUNTRY_SPECIFIER_##Specifier STATIC_VAR_COUNTRY_SPECIFIER_##Specifier;
} // namespace regions
} // namespace generator

View file

@ -1,29 +0,0 @@
#pragma once
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/region.hpp"
namespace generator
{
namespace regions
{
class LevelRegion : public Region
{
public:
LevelRegion(PlaceLevel level, Region const & region)
: Region(region), m_level{level} { }
PlaceLevel GetLevel() const noexcept { return m_level; }
void SetLevel(PlaceLevel level) { m_level = level; }
// Absolute rank values do not mean anything (except 1-4 values). But if the rank of the first
// object is more than the rank of the second object, then the first object is considered
// more nested.
// Specific values: 1 - country, 2 - region, 3 - subregion, 4 - locality.
uint8_t GetRank() const { return static_cast<uint8_t>(m_level); }
private:
PlaceLevel m_level;
};
} // namespace regions
} // namespace generator

View file

@ -1,226 +0,0 @@
#include "generator/regions/locality_point_integrator.hpp"
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/regions_builder.hpp"
#include "base/string_utils.hpp"
#include <utility>
#include <vector>
#include <boost/geometry.hpp>
namespace generator
{
namespace regions
{
LocalityPointIntegrator::LocalityPointIntegrator(PlacePoint const & localityPoint,
CountrySpecifier const & countrySpecifier)
: m_localityRegion{MakeAroundRegion(localityPoint, countrySpecifier)}
, m_countrySpecifier{countrySpecifier}
{
CHECK(countrySpecifier.GetLevel(localityPoint.GetPlaceType()) == PlaceLevel::Locality, ());
}
bool LocalityPointIntegrator::IntegrateInto(Node::Ptr & tree)
{
auto & region = tree->GetData();
if (HasIntegratingLocalityName(region))
{
// Match any locality type (city/town/village).
if (region.GetLevel() == PlaceLevel::Locality)
{
EnlargeRegion(region);
return true;
}
if (IsSuitableForLocalityRegionize(region))
RegionizeBy(region);
}
// Find deepest region for integration.
for (auto & subtree : tree->GetChildren())
{
auto const & subregion = subtree->GetData();
if (!subregion.Contains(m_localityRegion.GetCenter()))
continue;
if (IntegrateInto(subtree))
return true;
}
if (0 < RegionsBuilder::CompareAffiliation(region, m_localityRegion, m_countrySpecifier))
{
InsertInto(tree);
return true;
}
return false;
}
bool LocalityPointIntegrator::HasIntegratingLocalityName(LevelRegion const & region) const
{
auto const & regionName = region.GetName();
auto const & localityName = m_localityRegion.GetName();
if (regionName == localityName)
return true;
if (strings::StartsWith(regionName, "City of") && regionName == "City of " + localityName)
return true;
if (strings::EndsWith(regionName, "(city)") && regionName == localityName + " (city)")
return true;
auto const & regionEnglishName = region.GetName(StringUtf8Multilang::kEnglishCode);
if (!regionEnglishName.empty())
{
auto const & localityEnglishName = m_localityRegion.GetName(StringUtf8Multilang::kEnglishCode);
if (regionEnglishName == localityEnglishName)
return true;
}
return false;
}
bool LocalityPointIntegrator::IsSuitableForLocalityRegionize(LevelRegion const & region) const
{
auto const adminLevel = region.GetAdminLevel();
if (adminLevel != AdminLevel::Unknown && adminLevel < AdminLevel::Three)
return false;
auto const regionPlaceType = region.GetPlaceType();
if (regionPlaceType != PlaceType::Unknown && regionPlaceType >= PlaceType::City)
return false;
if (region.GetArea() > 10 * GetRadiusByPlaceType(m_localityRegion.GetPlaceType()))
return false;
return true;
}
void LocalityPointIntegrator::EnlargeRegion(LevelRegion & region)
{
LOG(LDEBUG, ("Enclose",
StringifyPlaceType(m_localityRegion.GetPlaceType()), "place point",
m_localityRegion.GetId(), "(", GetRegionNotation(m_localityRegion), ")",
"into", region.GetId(), "(", GetRegionNotation(region), ")"));
if (!region.GetLabel())
region.SetLabel(*m_localityRegion.GetLabel());
}
void LocalityPointIntegrator::RegionizeBy(LevelRegion const & region)
{
m_localityRegion.SetPolygon(region.GetPolygon());
m_regionizedByRegion = region;
}
void LocalityPointIntegrator::InsertInto(Node::Ptr & node)
{
if (m_regionizedByRegion)
{
LOG(LDEBUG, ("Regionize",
StringifyPlaceType(m_localityRegion.GetPlaceType()), "place point",
m_localityRegion.GetId(), "(", GetRegionNotation(m_localityRegion), ")",
"by", m_regionizedByRegion->GetId(),
"(", GetRegionNotation(*m_regionizedByRegion), ")"));
}
else
{
auto const & region = node->GetData();
LOG(LDEBUG, ("Insert around",
StringifyPlaceType(m_localityRegion.GetPlaceType()), "place point",
m_localityRegion.GetId(), "(", GetRegionNotation(m_localityRegion), ")",
"into", region.GetId(), "(", GetRegionNotation(region), ")"));
EmboundBy(region);
}
RegionsBuilder::InsertIntoSubtree(node, std::move(m_localityRegion), m_countrySpecifier);
}
void LocalityPointIntegrator::EmboundBy(LevelRegion const & region)
{
auto const & regionPolygon = *region.GetPolygon();
auto const & localityPolygon = *m_localityRegion.GetPolygon();
auto intersection = boost::geometry::model::multi_polygon<BoostPolygon>{};
boost::geometry::intersection(regionPolygon, localityPolygon, intersection);
// Select one with label point.
for (auto & polygon : intersection)
{
if (!boost::geometry::covered_by(m_localityRegion.GetCenter(), polygon))
continue;
// Skip error in boost::geometry::intersection(): there are A and B when
// intersection(A, B) != null but intersection(A, B) != intersection(A, intersection(A, B))
// or !covered_by(intersection(A, B), A).
auto checkLocalityRegion = m_localityRegion;
checkLocalityRegion.SetPolygon(std::make_shared<BoostPolygon>(std::move(polygon)));
if (0 < RegionsBuilder::CompareAffiliation(region, checkLocalityRegion,
m_countrySpecifier))
{
m_localityRegion = checkLocalityRegion;
return;
}
}
LOG(LWARNING, ("Failed to embound",
StringifyPlaceType(m_localityRegion.GetPlaceType()), "place",
m_localityRegion.GetId(), "(", GetRegionNotation(m_localityRegion), ")",
"by", region.GetId(), "(", GetRegionNotation(region), ")"));
}
// static
LevelRegion LocalityPointIntegrator::MakeAroundRegion(PlacePoint const & localityPoint,
CountrySpecifier const & countrySpecifier)
{
auto const placeType = localityPoint.GetPlaceType();
auto const radius = GetRadiusByPlaceType(placeType);
auto polygon = MakePolygonWithRadius(localityPoint.GetPosition(), radius);
auto region = LevelRegion{
PlaceLevel::Locality,
{localityPoint.GetMultilangName(), localityPoint.GetRegionData(), std::move(polygon)}};
region.SetLabel(localityPoint);
return region;
}
// static
double LocalityPointIntegrator::GetRadiusByPlaceType(PlaceType place)
{
// Based on average radiuses of OSM place polygons.
switch (place)
{
case PlaceType::City:
return 0.078;
case PlaceType::Town:
return 0.033;
case PlaceType::Village:
return 0.013;
case PlaceType::Hamlet:
return 0.0067;
case PlaceType::IsolatedDwelling:
return 0.0035;
default:
UNREACHABLE();
}
UNREACHABLE();
}
// static
std::shared_ptr<BoostPolygon> LocalityPointIntegrator::MakePolygonWithRadius(
BoostPoint const & point, double radius, size_t numPoints)
{
boost::geometry::strategy::buffer::point_circle point_strategy(numPoints);
boost::geometry::strategy::buffer::distance_symmetric<double> distance_strategy(radius);
static boost::geometry::strategy::buffer::join_round const join_strategy;
static boost::geometry::strategy::buffer::end_round const end_strategy;
static boost::geometry::strategy::buffer::side_straight const side_strategy;
boost::geometry::model::multi_polygon<BoostPolygon> result;
boost::geometry::buffer(point, result, distance_strategy, side_strategy, join_strategy,
end_strategy, point_strategy);
CHECK_EQUAL(result.size(), 1, ());
return std::make_shared<BoostPolygon>(std::move(result.front()));
}
} // namespace regions
} // namespace generator

View file

@ -1,45 +0,0 @@
#pragma once
#include "generator/boost_helpers.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/level_region.hpp"
#include "generator/regions/node.hpp"
#include "generator/regions/place_point.hpp"
#include <memory>
namespace generator
{
namespace regions
{
// LocalityPointIntegrator inserts place point (city/town/village) into region tree
// as region with around boundary or boundary from administrative region (by name matching).
class LocalityPointIntegrator
{
public:
LocalityPointIntegrator(PlacePoint const & localityPoint,
CountrySpecifier const & countrySpecifier);
bool IntegrateInto(Node::Ptr & tree);
private:
bool IsSuitableForLocalityRegionize(LevelRegion const & region) const;
bool HasIntegratingLocalityName(LevelRegion const & region) const;
void EnlargeRegion(LevelRegion & region);
void RegionizeBy(LevelRegion const & region);
void InsertInto(Node::Ptr & node);
void EmboundBy(LevelRegion const & region);
static LevelRegion MakeAroundRegion(PlacePoint const & localityPoint,
CountrySpecifier const & countrySpecifier);
// This function uses heuristics and assigns a radius according to the tag place.
// The radius will be returned in mercator units.
static double GetRadiusByPlaceType(PlaceType place);
static std::shared_ptr<BoostPolygon> MakePolygonWithRadius(
BoostPoint const & point, double radius, size_t numPoints = 16);
LevelRegion m_localityRegion;
CountrySpecifier const & m_countrySpecifier;
boost::optional<LevelRegion> m_regionizedByRegion;
};
} // namespace regions
} // namespace generator

View file

@ -1,107 +0,0 @@
#include "generator/regions/node.hpp"
#include "geometry/mercator.hpp"
#include <algorithm>
#include <array>
#include <iomanip>
#include <numeric>
namespace generator
{
namespace regions
{
size_t TreeSize(Node::Ptr const & node)
{
if (node == nullptr)
return 0;
size_t size = 1;
for (auto const & n : node->GetChildren())
size += TreeSize(n);
return size;
}
size_t MaxDepth(Node::Ptr const & node)
{
if (node == nullptr)
return 0;
size_t depth = 1;
for (auto const & n : node->GetChildren())
depth = std::max(MaxDepth(n), depth);
return depth;
}
NodePath MakeLevelPath(Node::Ptr const & node)
{
CHECK(node->GetData().GetLevel() != PlaceLevel::Unknown, ());
std::array<bool, static_cast<std::size_t>(PlaceLevel::Count)> skipLevels{};
NodePath path{node};
for (auto p = node->GetParent(); p; p = p->GetParent())
{
auto const level = p->GetData().GetLevel();
if (PlaceLevel::Unknown == level)
continue;
auto levelIndex = static_cast<std::size_t>(level);
if (skipLevels.at(levelIndex))
continue;
skipLevels[levelIndex] = true;
if (PlaceLevel::Locality == level)
{
// To ignore covered locality.
skipLevels[static_cast<std::size_t>(PlaceLevel::Suburb)] = true;
skipLevels[static_cast<std::size_t>(PlaceLevel::Sublocality)] = true;
}
path.push_back(p);
}
std::reverse(path.begin(), path.end());
return path;
}
void PrintTree(Node::Ptr const & node, std::ostream & stream = std::cout, std::string prefix = "",
bool isTail = true)
{
auto const & children = node->GetChildren();
stream << prefix;
if (isTail)
{
stream << "└───";
prefix += " ";
}
else
{
stream << "├───";
prefix += "";
}
auto const & d = node->GetData();
auto const point = d.GetCenter();
auto const center = MercatorBounds::ToLatLon({point.get<0>(), point.get<1>()});
auto const label = GetLabel(d.GetLevel());
stream << d.GetName() << "<"
<< d.GetTranslatedOrTransliteratedName(StringUtf8Multilang::GetLangIndex("en")) << "> ("
<< DebugPrint(d.GetId()) << ";" << (label ? label : "-") << ";"
<< static_cast<size_t>(d.GetRank()) << ";[" << std::fixed << std::setprecision(7)
<< center.m_lat << "," << center.m_lon << "])" << std::endl;
for (size_t i = 0, size = children.size(); i < size; ++i)
PrintTree(children[i], stream, prefix, i == size - 1);
}
void DebugPrintTree(Node::Ptr const & tree, std::ostream & stream)
{
stream << "ROOT NAME: " << tree->GetData().GetName() << std::endl;
stream << "MAX DEPTH: " << MaxDepth(tree) << std::endl;
stream << "TREE SIZE: " << TreeSize(tree) << std::endl;
PrintTree(tree, stream);
stream << std::endl;
}
} // namespace regions
} // namespace generator

View file

@ -1,38 +0,0 @@
#pragma once
#include "generator/place_node.hpp"
#include "generator/regions/level_region.hpp"
#include <iostream>
namespace generator
{
namespace regions
{
using Node = PlaceNode<LevelRegion>;
using NodePath = std::vector<Node::Ptr>;
NodePath MakeLevelPath(Node::Ptr const & node);
// The function has formally quadratic time complexity: depth * size of tree.
// In fact, tree depth is low value and thus the function time complexity is linear.
template <typename Fn>
void ForEachLevelPath(Node::Ptr const & tree, Fn && fn)
{
if (!tree)
return;
if (tree->GetData().GetLevel() != PlaceLevel::Unknown)
fn(MakeLevelPath(tree));
for (auto const & subtree : tree->GetChildren())
ForEachLevelPath(subtree, fn);
}
size_t TreeSize(Node::Ptr const & node);
size_t MaxDepth(Node::Ptr const & node);
void DebugPrintTree(Node::Ptr const & tree, std::ostream & stream = std::cout);
} // namespace regions
} // namespace generator

View file

@ -1,39 +0,0 @@
#pragma once
#include "generator/feature_builder.hpp"
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/region_base.hpp"
#include <unordered_map>
namespace generator
{
namespace regions
{
class PlacePoint;
using PlacePointsMap = std::unordered_map<base::GeoObjectId, PlacePoint>;
// PlacePoint objects presents centers (place=* nodes) of localities (city/town/village/...)
// and their subdivision parts (suburb/quarter/...).
// PlacePoint objects are converted to Region objects with approximated boundaries
// when there is no the same places with original boundaries.
// Approximation depends on place type of point (see MakePolygonWithRadius()).
// Conversion is performed by Region constructor: Region{placePoint}.
class PlacePoint : public RegionWithName, public RegionWithData
{
public:
explicit PlacePoint(feature::FeatureBuilder const & fb, RegionDataProxy const & rd)
: RegionWithName(fb.GetParams().name),
RegionWithData(rd)
{
auto const p = fb.GetKeyPoint();
m_position = {p.x, p.y};
}
BoostPoint GetPosition() const { return m_position; }
private:
BoostPoint m_position;
};
} // namespace regions
} // namespace generator

View file

@ -1,63 +0,0 @@
#include "generator/regions/place_points_integrator.hpp"
#include "generator/regions/locality_point_integrator.hpp"
namespace generator
{
namespace regions
{
PlacePointsIntegrator::PlacePointsIntegrator(PlacePointsMap const & placePoints,
CountrySpecifier const & countrySpecifier)
: m_placePoints(placePoints)
, m_countrySpecifier{countrySpecifier}
{ }
void PlacePointsIntegrator::ApplyTo(Node::PtrList & outers)
{
ApplyLocalityPointsTo(outers);
}
void PlacePointsIntegrator::ApplyLocalityPointsTo(Node::PtrList & outers)
{
// Intergrate from biggest to smallest location types for intersections of nested localities.
auto localityTypes = {PlaceType::City, PlaceType::Town,
PlaceType::Village, PlaceType::Hamlet, PlaceType::IsolatedDwelling};
for (auto type : localityTypes)
{
for (auto const & placePoint : m_placePoints)
{
auto const & place = placePoint.second;
if (place.GetPlaceType() == type)
ApplyLocalityPointTo(place, outers);
}
}
}
void PlacePointsIntegrator::ApplyLocalityPointTo(PlacePoint const & localityPoint,
Node::PtrList & outers)
{
for (auto & tree : outers)
{
auto & countryRegion = tree->GetData();
if (countryRegion.Contains(localityPoint))
{
IntegrateLocalityPointInto(localityPoint, tree);
return;
}
}
}
void PlacePointsIntegrator::IntegrateLocalityPointInto(
PlacePoint const & localityPoint, Node::Ptr & tree)
{
auto localityIntegrator = LocalityPointIntegrator{localityPoint, m_countrySpecifier};
if (!localityIntegrator.IntegrateInto(tree))
{
LOG(LWARNING, ("Can't integrate the",
StringifyPlaceType(localityPoint.GetPlaceType()), "place",
localityPoint.GetId(), "(", GetRegionNotation(localityPoint), ")",
"into", GetRegionNotation(tree->GetData())));
}
}
} // namespace regions
} // namespace generator

View file

@ -1,28 +0,0 @@
#pragma once
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/node.hpp"
#include "generator/regions/place_point.hpp"
namespace generator
{
namespace regions
{
class PlacePointsIntegrator
{
public:
PlacePointsIntegrator(PlacePointsMap const & placePoints,
CountrySpecifier const & countrySpecifier);
void ApplyTo(Node::PtrList & outers);
private:
void ApplyLocalityPointsTo(Node::PtrList & outers);
void ApplyLocalityPointTo(PlacePoint const & localityPoint, Node::PtrList & outers);
void IntegrateLocalityPointInto(PlacePoint const & localityPoint, Node::Ptr & tree);
PlacePointsMap const & m_placePoints;
CountrySpecifier const & m_countrySpecifier;
};
} // namespace regions
} // namespace generator

View file

@ -1,180 +0,0 @@
#include "generator/regions/region.hpp"
#include "generator/boost_helpers.hpp"
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/place_point.hpp"
#include "geometry/mercator.hpp"
#include "base/assert.hpp"
#include <algorithm>
#include <numeric>
#include <boost/geometry.hpp>
using namespace feature;
namespace generator
{
namespace regions
{
Region::Region(FeatureBuilder const & fb, RegionDataProxy const & rd)
: RegionWithName(fb.GetParams().name)
, RegionWithData(rd)
, m_polygon(std::make_shared<BoostPolygon>())
{
FillPolygon(fb);
boost::geometry::envelope(*m_polygon, m_rect);
m_area = boost::geometry::area(*m_polygon);
CHECK_GREATER_OR_EQUAL(m_area, 0.0, ());
}
Region::Region(StringUtf8Multilang const & name, RegionDataProxy const & rd,
std::shared_ptr<BoostPolygon> const & polygon)
: RegionWithName(name), RegionWithData(rd)
{
SetPolygon(polygon);
}
std::string Region::GetTranslatedOrTransliteratedName(LanguageCode languageCode) const
{
if (!m_placeLabel)
return RegionWithName::GetTranslatedOrTransliteratedName(languageCode);
std::string const & name = m_placeLabel->GetTranslatedOrTransliteratedName(languageCode);
return name.empty() ? RegionWithName::GetTranslatedOrTransliteratedName(languageCode) : name;
}
std::string Region::GetInternationalName() const
{
if (!m_placeLabel)
return RegionWithName::GetInternationalName();
std::string intName = m_placeLabel->GetInternationalName();
return intName.empty() ? RegionWithName::GetInternationalName() : intName;
}
std::string Region::GetName(int8_t lang) const
{
if (m_placeLabel)
return m_placeLabel->GetName(lang);
return RegionWithName::GetName(lang);
}
base::GeoObjectId Region::GetId() const
{
if (m_placeLabel)
return m_placeLabel->GetId();
return RegionWithData::GetId();
}
base::GeoObjectId Region::GetOriginId() const
{
return RegionWithData::GetId();
}
PlaceType Region::GetPlaceType() const
{
if (m_placeLabel)
return m_placeLabel->GetPlaceType();
return RegionWithData::GetPlaceType();
}
boost::optional<std::string> Region::GetIsoCode() const
{
if (m_placeLabel)
{
if (auto isoCode = m_placeLabel->GetIsoCode())
return isoCode;
}
return RegionWithData::GetIsoCode();
}
boost::optional<PlacePoint> const & Region::GetLabel() const noexcept { return m_placeLabel; }
void Region::SetLabel(PlacePoint const & place)
{
CHECK(!m_placeLabel, ());
m_placeLabel = place;
}
void Region::FillPolygon(FeatureBuilder const & fb)
{
CHECK(m_polygon, ());
boost_helpers::FillPolygon(*m_polygon, fb);
}
bool Region::IsLocality() const { return GetPlaceType() >= PlaceType::City; }
void Region::SetPolygon(std::shared_ptr<BoostPolygon> const & polygon)
{
m_polygon = polygon;
m_rect = {};
boost::geometry::envelope(*m_polygon, m_rect);
m_area = boost::geometry::area(*m_polygon);
CHECK_GREATER_OR_EQUAL(m_area, 0.0, ());
}
bool Region::Contains(Region const & smaller) const
{
CHECK(m_polygon, ());
CHECK(smaller.m_polygon, ());
return boost::geometry::covered_by(smaller.m_rect, m_rect) &&
boost::geometry::covered_by(*smaller.m_polygon, *m_polygon);
}
double Region::CalculateOverlapPercentage(Region const & other) const
{
CHECK(m_polygon, ());
CHECK(other.m_polygon, ());
if (!boost::geometry::intersects(other.m_rect, m_rect))
return 0.0;
std::vector<BoostPolygon> coll;
boost::geometry::intersection(*other.m_polygon, *m_polygon, coll);
auto const min =
std::min(boost::geometry::area(*other.m_polygon), boost::geometry::area(*m_polygon));
auto const binOp = [](double x, BoostPolygon const & y) { return x + boost::geometry::area(y); };
auto const sum = std::accumulate(std::begin(coll), std::end(coll), 0., binOp);
return (sum / min) * 100;
}
bool Region::ContainsRect(Region const & smaller) const
{
return boost::geometry::covered_by(smaller.m_rect, m_rect);
}
BoostPoint Region::GetCenter() const
{
if (m_placeLabel)
return m_placeLabel->GetPosition();
BoostPoint p;
boost::geometry::centroid(m_rect, p);
return p;
}
bool Region::Contains(PlacePoint const & place) const
{
CHECK(m_polygon, ());
return Contains(place.GetPosition());
}
bool Region::Contains(BoostPoint const & point) const
{
CHECK(m_polygon, ());
return boost::geometry::covered_by(point, m_rect) &&
boost::geometry::covered_by(point, *m_polygon);
}
} // namespace regions
} // namespace generator

View file

@ -1,65 +0,0 @@
#pragma once
#include "generator/feature_builder.hpp"
#include "generator/regions/place_point.hpp"
#include "generator/regions/region_base.hpp"
#include <memory>
namespace feature
{
class FeatureBuilder;
} // namespace feature
namespace generator
{
class RegionDataProxy;
namespace regions
{
// This is a helper class that is needed to represent the region.
// With this view, further processing is simplified.
class Region : protected RegionWithName, protected RegionWithData
{
public:
explicit Region(feature::FeatureBuilder const & fb, RegionDataProxy const & rd);
Region(StringUtf8Multilang const & name, RegionDataProxy const & rd,
std::shared_ptr<BoostPolygon> const & polygon);
// See RegionWithName::GetTranslatedOrTransliteratedName().
std::string GetTranslatedOrTransliteratedName(LanguageCode languageCode) const;
std::string GetInternationalName() const;
std::string GetName(int8_t lang = StringUtf8Multilang::kDefaultCode) const;
base::GeoObjectId GetId() const;
base::GeoObjectId GetOriginId() const;
using RegionWithData::GetAdminLevel;
PlaceType GetPlaceType() const;
boost::optional<std::string> GetIsoCode() const;
using RegionWithData::GetLabelOsmId;
boost::optional<PlacePoint> const & GetLabel() const noexcept;
void SetLabel(PlacePoint const & place);
bool Contains(Region const & smaller) const;
bool ContainsRect(Region const & smaller) const;
bool Contains(PlacePoint const & place) const;
bool Contains(BoostPoint const & point) const;
double CalculateOverlapPercentage(Region const & other) const;
BoostPoint GetCenter() const;
bool IsLocality() const;
BoostRect const & GetRect() const { return m_rect; }
std::shared_ptr<BoostPolygon> const & GetPolygon() const noexcept { return m_polygon; }
void SetPolygon(std::shared_ptr<BoostPolygon> const & polygon);
double GetArea() const { return m_area; }
private:
void FillPolygon(feature::FeatureBuilder const & fb);
boost::optional<PlacePoint> m_placeLabel;
std::shared_ptr<BoostPolygon> m_polygon;
BoostRect m_rect;
double m_area;
};
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/region_base.hpp"
#include "base/assert.hpp"
#include "base/control_flow.hpp"
namespace generator
{
namespace regions
{
std::string RegionWithName::GetName(LanguageCode languageCode) const
{
return ::generator::GetName(m_name, languageCode);
}
std::string RegionWithName::GetTranslatedOrTransliteratedName(LanguageCode languageCode) const
{
return ::generator::GetTranslatedOrTransliteratedName(m_name, languageCode);
}
std::string RegionWithName::GetInternationalName() const
{
std::string intName = ::generator::GetTranslatedOrTransliteratedName(
m_name, StringUtf8Multilang::kInternationalCode);
return intName.empty() ? GetName() : intName;
}
StringUtf8Multilang const & RegionWithName::GetMultilangName() const { return m_name; }
base::GeoObjectId RegionWithData::GetId() const { return m_regionData.GetOsmId(); }
boost::optional<std::string> RegionWithData::GetIsoCode() const
{
return m_regionData.GetIsoCodeAlpha2();
}
boost::optional<base::GeoObjectId> RegionWithData::GetLabelOsmId() const
{
return m_regionData.GetLabelOsmId();
}
} // namespace regions
} // namespace generator

View file

@ -1,77 +0,0 @@
#pragma once
#include "generator/feature_builder.hpp"
#include "generator/regions/region_info.hpp"
#include "generator/translation.hpp"
#include "geometry/rect2d.hpp"
#include "coding/string_utf8_multilang.hpp"
#include "base/geo_object_id.hpp"
#include <cstdint>
#include <string>
#include <boost/geometry.hpp>
#include <boost/optional.hpp>
namespace generator
{
namespace regions
{
using Point = feature::FeatureBuilder::PointSeq::value_type;
using BoostPoint = boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>;
using BoostPolygon = boost::geometry::model::polygon<BoostPoint>;
using BoostRect = boost::geometry::model::box<BoostPoint>;
class RegionWithName
{
public:
explicit RegionWithName(StringUtf8Multilang name) : m_name(std::move(name)) {}
std::string GetTranslatedOrTransliteratedName(LanguageCode languageCode) const;
// returns default name if int_name is empty
std::string GetInternationalName() const;
std::string GetName(int8_t lang = StringUtf8Multilang::kDefaultCode) const;
StringUtf8Multilang const & GetMultilangName() const;
protected:
StringUtf8Multilang m_name;
};
class RegionWithData
{
public:
explicit RegionWithData(RegionDataProxy const & regionData) : m_regionData(regionData) {}
base::GeoObjectId GetId() const;
boost::optional<std::string> GetIsoCode() const;
boost::optional<base::GeoObjectId> GetLabelOsmId() const;
AdminLevel GetAdminLevel() const { return m_regionData.GetAdminLevel(); }
PlaceType GetPlaceType() const { return m_regionData.GetPlaceType(); }
void SetAdminLevel(AdminLevel adminLevel) { m_regionData.SetAdminLevel(adminLevel); }
void SetPlaceType(PlaceType placeType) { m_regionData.SetPlaceType(placeType); }
RegionDataProxy const & GetRegionData() const { return m_regionData; }
protected:
RegionDataProxy m_regionData;
};
template <typename Place>
std::string GetRegionNotation(Place const & place)
{
auto notation = place.GetTranslatedOrTransliteratedName(StringUtf8Multilang::GetLangIndex("en"));
if (notation.empty())
return place.GetName();
if (notation != place.GetName())
notation += " / " + place.GetName();
return notation;
}
} // namespace regions
} // namespace generator

View file

@ -1,169 +0,0 @@
#include "generator/regions/region_info.hpp"
#include "generator/regions/collector_region_info.hpp"
#include "coding/file_reader.hpp"
#include "base/assert.hpp"
#include "base/logging.hpp"
#include "base/macros.hpp"
namespace generator
{
namespace regions
{
RegionInfo::RegionInfo(std::string const & filename)
{
ParseFile(filename);
}
RegionInfo::RegionInfo(Platform::FilesList const & filenames)
{
for (auto const & filename : filenames)
ParseFile(filename);
}
void RegionInfo::ParseFile(std::string const & filename)
{
FileReader reader(filename);
ReaderSource<FileReader> src(reader);
uint8_t version;
ReadPrimitiveFromSource(src, version);
CHECK_EQUAL(version, CollectorRegionInfo::kVersion, ());
ReadMap(src, m_mapRegionData);
ReadMap(src, m_mapIsoCode);
}
RegionDataProxy RegionInfo::Get(base::GeoObjectId const & osmId)
{
return RegionDataProxy(*this, osmId);
}
ConstRegionDataProxy RegionInfo::Get(base::GeoObjectId const & osmId) const
{
return ConstRegionDataProxy(*this, osmId);
}
RegionInfo & RegionDataProxy::GetCollector()
{
return m_regionInfoCollector;
}
MapRegionData & RegionDataProxy::GetMapRegionData()
{
return GetCollector().m_mapRegionData;
}
void RegionDataProxy::SetAdminLevel(AdminLevel adminLevel)
{
GetMapRegionData().at(m_osmId).m_adminLevel = adminLevel;
}
void RegionDataProxy::SetPlaceType(PlaceType placeType)
{
GetMapRegionData().at(m_osmId).m_place = placeType;
}
template <typename T>
BaseRegionDataProxy<T>::BaseRegionDataProxy(T & regionInfoCollector, base::GeoObjectId const & osmId)
: m_regionInfoCollector(regionInfoCollector), m_osmId(osmId) {}
template <typename T>
RegionInfo const & BaseRegionDataProxy<T>::GetCollector() const
{
return m_regionInfoCollector;
}
template <typename T>
MapRegionData const & BaseRegionDataProxy<T>::GetMapRegionData() const
{
return GetCollector().m_mapRegionData;
}
template <typename T>
MapIsoCode const & BaseRegionDataProxy<T>::GetMapIsoCode() const
{
return GetCollector().m_mapIsoCode;
}
template <typename T>
base::GeoObjectId const & BaseRegionDataProxy<T>::GetOsmId() const
{
return m_osmId;
}
template <typename T>
AdminLevel BaseRegionDataProxy<T>::GetAdminLevel() const
{
auto const & regionDataMap = GetMapRegionData();
auto const regionData = regionDataMap.find(m_osmId);
if (regionData == end(regionDataMap))
return AdminLevel::Unknown;
return regionData->second.m_adminLevel;
}
template <typename T>
PlaceType BaseRegionDataProxy<T>::GetPlaceType() const
{
auto const & regionDataMap = GetMapRegionData();
auto const regionData = regionDataMap.find(m_osmId);
if (regionData == end(regionDataMap))
return PlaceType::Unknown;
return regionData->second.m_place;
}
template <typename T>
boost::optional<base::GeoObjectId> BaseRegionDataProxy<T>::GetLabelOsmId() const
{
auto const & labelId = GetMapRegionData().at(m_osmId).m_labelOsmId;
if (!labelId.GetEncodedId())
return {};
return labelId;
}
template <typename T>
boost::optional<std::string> BaseRegionDataProxy<T>::GetIsoCodeAlpha2() const
{
auto const & codesMap = GetMapIsoCode();
auto const code = codesMap.find(m_osmId);
if (code == end(codesMap))
return {};
if (!code->second.HasAlpha2())
return {};
return code->second.GetAlpha2();
}
template <typename T>
boost::optional<std::string> BaseRegionDataProxy<T>::GetIsoCodeAlpha3() const
{
auto const & codesMap = GetMapIsoCode();
auto const code = codesMap.find(m_osmId);
if (code == end(codesMap))
return {};
if (!code->second.HasAlpha3())
return {};
return code->second.GetAlpha3();
}
template <typename T>
boost::optional<std::string> BaseRegionDataProxy<T>::GetIsoCodeAlphaNumeric() const
{
auto const & codesMap = GetMapIsoCode();
auto const code = codesMap.find(m_osmId);
if (code == end(codesMap))
return {};
if (!code->second.HasNumeric())
return {};
return code->second.GetNumeric();
}
template class BaseRegionDataProxy<RegionInfo>;
template class BaseRegionDataProxy<RegionInfo const>;
} // namespace regions
} // namespace generator

View file

@ -1,106 +0,0 @@
#pragma once
#include "generator/regions/collector_region_info.hpp"
#include "platform/platform.hpp"
#include "coding/reader.hpp"
#include "base/geo_object_id.hpp"
#include <cstdint>
#include <functional>
#include <string>
#include <utility>
#include <boost/optional.hpp>
namespace generator
{
namespace regions
{
template <typename T>
class BaseRegionDataProxy;
class RegionDataProxy;
class ConstRegionDataProxy;
// RegionInfo class is responsible for reading and accessing additional information about the regions.
class RegionInfo
{
public:
RegionInfo() = default;
explicit RegionInfo(std::string const & filename);
explicit RegionInfo(Platform::FilesList const & filenames);
RegionDataProxy Get(base::GeoObjectId const & osmId);
ConstRegionDataProxy Get(base::GeoObjectId const & osmId) const;
private:
friend class BaseRegionDataProxy<RegionInfo>;
friend class BaseRegionDataProxy<RegionInfo const>;
friend class RegionDataProxy;
friend class ConstRegionDataProxy;
template <typename Source, typename Map>
void ReadMap(Source & src, Map & seq)
{
uint32_t size = 0;
ReadPrimitiveFromSource(src, size);
typename Map::mapped_type data;
for (uint32_t i = 0; i < size; ++i)
{
ReadPrimitiveFromSource(src, data);
seq.emplace(data.m_osmId, std::move(data));
}
}
void ParseFile(std::string const & filename);
MapRegionData m_mapRegionData;
MapIsoCode m_mapIsoCode;
};
template <typename T>
class BaseRegionDataProxy
{
public:
BaseRegionDataProxy(T & regionInfoCollector, base::GeoObjectId const & osmId);
base::GeoObjectId const & GetOsmId() const;
AdminLevel GetAdminLevel() const;
PlaceType GetPlaceType() const;
boost::optional<base::GeoObjectId> GetLabelOsmId() const;
boost::optional<std::string> GetIsoCodeAlpha2() const;
boost::optional<std::string> GetIsoCodeAlpha3() const;
boost::optional<std::string> GetIsoCodeAlphaNumeric() const;
protected:
RegionInfo const & GetCollector() const;
MapRegionData const & GetMapRegionData() const;
MapIsoCode const & GetMapIsoCode() const;
std::reference_wrapper<T> m_regionInfoCollector;
base::GeoObjectId m_osmId;
};
class ConstRegionDataProxy : public BaseRegionDataProxy<RegionInfo const>
{
public:
using BaseRegionDataProxy<RegionInfo const>::BaseRegionDataProxy;
};
class RegionDataProxy : public BaseRegionDataProxy<RegionInfo>
{
public:
using BaseRegionDataProxy<RegionInfo>::BaseRegionDataProxy;
void SetAdminLevel(AdminLevel adminLevel);
void SetPlaceType(PlaceType placeType);
private:
RegionInfo & GetCollector();
MapRegionData & GetMapRegionData();
};
} // namespace regions
} // namespace generator

View file

@ -1,103 +0,0 @@
#include "generator/regions/region_info_getter.hpp"
#include "coding/mmap_reader.hpp"
#include "base/logging.hpp"
namespace generator
{
namespace regions
{
RegionInfoGetter::RegionInfoGetter(std::string const & indexPath, std::string const & kvPath)
: m_index{indexer::ReadIndex<indexer::RegionsIndexBox<IndexReader>, MmapReader>(indexPath)}
, m_storage(kvPath, 1'000'000)
{
m_borders.Deserialize(indexPath);
}
boost::optional<KeyValue> RegionInfoGetter::FindDeepest(m2::PointD const & point) const
{
return FindDeepest(point, [] (...) { return true; });
}
boost::optional<KeyValue> RegionInfoGetter::FindDeepest(
m2::PointD const & point, Selector const & selector) const
{
static_assert(std::is_base_of<ConcurrentGetProcessability, RegionInfoGetter>::value, "");
auto const ids = SearchObjectsInIndex(point);
return GetDeepest(point, ids, selector);
}
std::vector<base::GeoObjectId> RegionInfoGetter::SearchObjectsInIndex(m2::PointD const & point) const
{
std::vector<base::GeoObjectId> ids;
auto const emplace = [&ids] (base::GeoObjectId const & osmId) { ids.emplace_back(osmId); };
m_index.ForEachAtPoint(emplace, point);
return ids;
}
boost::optional<KeyValue> RegionInfoGetter::GetDeepest(m2::PointD const & point,
std::vector<base::GeoObjectId> const & ids, Selector const & selector) const
{
// Minimize CPU consumption by minimizing the number of calls to heavy m_borders.IsPointInside().
std::multimap<int, KeyValue> regionsByRank;
for (auto const & id : ids)
{
auto const region = m_storage.Find(id.GetEncodedId());
if (!region)
{
LOG(LWARNING, ("Id not found in region key-value storage:", id));
continue;
}
auto rank = GetRank(*region);
regionsByRank.emplace(rank, KeyValue{id.GetEncodedId(), std::move(region)});
}
boost::optional<uint64_t> borderCheckSkipRegionId;
for (auto i = regionsByRank.rbegin(); i != regionsByRank.rend(); ++i)
{
auto & kv = i->second;
auto regionId = kv.first;
if (regionId != borderCheckSkipRegionId && !m_borders.IsPointInside(regionId, point))
continue;
if (selector(kv))
return std::move(kv);
// Skip border check for parent region.
if (auto dref = GetDref(*kv.second))
borderCheckSkipRegionId = dref;
}
return {};
}
int RegionInfoGetter::GetRank(JsonValue const & json) const
{
auto && properties = base::GetJSONObligatoryField(json, "properties");
return FromJSONObject<int>(properties, "rank");
}
boost::optional<uint64_t> RegionInfoGetter::GetDref(JsonValue const & json) const
{
auto && properties = base::GetJSONObligatoryField(json, "properties");
auto && drefField = base::GetJSONOptionalField(properties, "dref");
if (!drefField || base::JSONIsNull(drefField))
return {};
std::string drefStr = FromJSON<std::string>(drefField);
uint64_t dref = 0;
CHECK(strings::to_uint64(drefStr, dref, 16), ());
return dref;
}
KeyValueStorage const & RegionInfoGetter::GetStorage() const noexcept
{
return m_storage;
}
} // namespace regions
} // namespace generator

View file

@ -1,55 +0,0 @@
#pragma once
#include "generator/key_value_storage.hpp"
#include "indexer/borders.hpp"
#include "indexer/locality_index.hpp"
#include "coding/reader.hpp"
#include "geometry/point2d.hpp"
#include "base/geo_object_id.hpp"
#include <string>
#include <vector>
#include <boost/optional.hpp>
#include "3party/jansson/myjansson.hpp"
namespace generator
{
namespace regions
{
// ConcurrentGetProcessability is marker inteface: concurrent mode capability for any get operations.
struct ConcurrentGetProcessability
{ };
class RegionInfoGetter : public ConcurrentGetProcessability
{
public:
using Selector = std::function<bool(KeyValue const & json)>;
RegionInfoGetter(std::string const & indexPath, std::string const & kvPath);
boost::optional<KeyValue> FindDeepest(m2::PointD const & point) const;
boost::optional<KeyValue> FindDeepest(m2::PointD const & point, Selector const & selector) const;
KeyValueStorage const & GetStorage() const noexcept;
private:
using IndexReader = ReaderPtr<Reader>;
std::vector<base::GeoObjectId> SearchObjectsInIndex(m2::PointD const & point) const;
boost::optional<KeyValue> GetDeepest(m2::PointD const & point, std::vector<base::GeoObjectId> const & ids,
Selector const & selector) const;
int GetRank(JsonValue const & json) const;
// Get parent id of object: optional field `properties.dref` in JSON.
boost::optional<uint64_t> GetDref(JsonValue const & json) const;
indexer::RegionsIndex<IndexReader> m_index;
indexer::Borders m_borders;
KeyValueStorage m_storage;
};
} // namespace regions
} // namespace generator

View file

@ -1,333 +0,0 @@
#include "generator/regions/regions.hpp"
#include "generator/key_value_storage.hpp"
#include "generator/feature_builder.hpp"
#include "generator/feature_generator.hpp"
#include "generator/generate_info.hpp"
#include "generator/regions/node.hpp"
#include "generator/regions/place_point.hpp"
#include "generator/regions/regions.hpp"
#include "generator/regions/regions_builder.hpp"
#include "geometry/mercator.hpp"
#include "coding/transliteration.hpp"
#include "base/assert.hpp"
#include "base/file_name_utils.hpp"
#include "base/logging.hpp"
#include "base/stl_helpers.hpp"
#include "base/timer.hpp"
#include <algorithm>
#include <fstream>
#include <map>
#include <memory>
#include <numeric>
#include <queue>
#include <set>
#include <thread>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "defines.hpp"
using namespace feature;
namespace generator
{
namespace regions
{
namespace
{
class RegionsGenerator
{
public:
RegionsGenerator(std::string const & pathInRegionsTmpMwm,
std::string const & pathInRegionsCollector, std::string const & pathOutRegionsKv,
std::string const & pathOutRepackedRegionsTmpMwm, bool verbose,
size_t threadsCount)
: m_pathInRegionsTmpMwm{pathInRegionsTmpMwm}
, m_pathOutRegionsKv{pathOutRegionsKv}
, m_pathOutRepackedRegionsTmpMwm{pathOutRepackedRegionsTmpMwm}
, m_verbose{verbose}
, m_regionsInfoCollector{pathInRegionsCollector}
, m_regionsKv{pathOutRegionsKv, std::ofstream::out}
{
LOG(LINFO, ("Start generating regions from", m_pathInRegionsTmpMwm));
auto timer = base::Timer{};
RegionsBuilder::Regions regions;
PlacePointsMap placePointsMap;
std::tie(regions, placePointsMap) =
ReadDatasetFromTmpMwm(m_pathInRegionsTmpMwm, m_regionsInfoCollector);
RegionsBuilder builder{std::move(regions), std::move(placePointsMap), threadsCount};
GenerateRegions(builder);
LOG(LINFO, ("Finish generating regions.", timer.ElapsedSeconds(), "seconds."));
}
private:
void GenerateRegions(RegionsBuilder & builder)
{
builder.ForEachCountry([&](std::string const & name, Node::PtrList const & outers) {
auto const & countryPlace = outers.front()->GetData();
auto const & countryName =
countryPlace.GetTranslatedOrTransliteratedName(StringUtf8Multilang::GetLangIndex("en"));
GenerateKv(countryName, outers);
});
LOG(LINFO, ("Regions objects key-value for", builder.GetCountryInternationalNames().size(),
"countries storage saved to", m_pathOutRegionsKv));
LOG(LINFO,
(m_objectsRegions.size(), "total regions.", m_regionsCountries.size(), "total objects."));
RepackTmpMwm();
}
base::JSONPtr BuildRegionValue(regions::NodePath const & path) const
{
auto const & main = path.back()->GetData();
auto geometry = base::NewJSONObject();
ToJSONObject(*geometry, "type", "Point");
auto coordinates = base::NewJSONArray();
auto const tmpCenter = main.GetCenter();
auto const center = MercatorBounds::ToLatLon({tmpCenter.get<0>(), tmpCenter.get<1>()});
ToJSONArray(*coordinates, center.m_lon);
ToJSONArray(*coordinates, center.m_lat);
ToJSONObject(*geometry, "coordinates", coordinates);
auto properties = base::NewJSONObject();
Localizator localizator(*properties);
for (auto const & p : path)
{
auto const & region = p->GetData();
CHECK(region.GetLevel() != regions::PlaceLevel::Unknown, ());
auto const label = GetLabel(region.GetLevel());
CHECK(label, ());
localizator.SetLocale(label, region, "address");
if (m_verbose)
{
localizator.AddVerbose(
[&label, &region](auto & node) {
ToJSONObject(node, std::string{label} + "_i", DebugPrint(region.GetId()));
ToJSONObject(node, std::string{label} + "_a", region.GetArea());
ToJSONObject(node, std::string{label} + "_r", region.GetRank());
},
"address");
}
}
localizator.SetLocale("name", main);
ToJSONObject(*properties, "rank", main.GetRank());
if (path.size() > 1)
{
auto const & parent = (*(path.rbegin() + 1))->GetData();
auto const parentId = parent.GetId().GetEncodedId();
ToJSONObject(*properties, "dref", KeyValueStorage::SerializeDref(parentId));
}
else
{
ToJSONObject(*properties, "dref", base::NewJSONNull());
}
auto const & country = path.front()->GetData();
if (auto && isoCode = country.GetIsoCode())
ToJSONObject(*properties, "code", *isoCode);
auto feature = base::NewJSONObject();
ToJSONObject(*feature, "type", "Feature");
ToJSONObject(*feature, "geometry", geometry);
ToJSONObject(*feature, "properties", properties);
return feature;
}
void GenerateKv(std::string const & countryName, Node::PtrList const & outers)
{
LOG(LINFO, ("Generate country", countryName));
auto country = std::make_shared<std::string>(countryName);
size_t countryRegionsCount = 0;
size_t countryObjectCount = 0;
std::vector<base::GeoObjectId> objectsOrder;
std::map<base::GeoObjectId, NodePath> objectsPaths;
for (auto const & tree : outers)
{
if (m_verbose)
DebugPrintTree(tree);
ForEachLevelPath(tree, [&](NodePath const & path) {
auto const & node = path.back();
auto const & region = node->GetData();
auto const & objectId = region.GetId();
auto const & regionCountryEmplace = m_regionsCountries.emplace(objectId, country);
bool firstRegionOfObject = regionCountryEmplace.second;
if (!regionCountryEmplace.second && regionCountryEmplace.first->second != country)
{
LOG(LWARNING, ("Failed to place", GetLabel(region.GetLevel()), "region", objectId, "(",
GetRegionNotation(region), ")", "into", *country,
": region already exists in", *regionCountryEmplace.first->second));
return;
}
m_objectsRegions.emplace(objectId, node);
++countryRegionsCount;
if (firstRegionOfObject)
{
objectsOrder.push_back(objectId);
++countryObjectCount;
}
auto pathEmplace = objectsPaths.emplace(objectId, path);
if (!pathEmplace.second)
{
auto & objectMaxRegionPath = pathEmplace.first->second;
auto & objectMaxRegion = objectMaxRegionPath.back()->GetData();
if (RegionsBuilder::IsAreaLessRely(objectMaxRegion, region))
objectMaxRegionPath = path;
}
});
}
WriteObjectsInKv(objectsOrder, objectsPaths);
LOG(LINFO, ("Country regions of", *country, "has built:", countryRegionsCount, "total regions.",
countryObjectCount, "objects."));
}
void WriteObjectsInKv(std::vector<base::GeoObjectId> const & objectsOrder,
std::map<base::GeoObjectId, NodePath> const & objectsPaths)
{
for (auto const & objectId : objectsOrder)
{
auto pathIter = objectsPaths.find(objectId);
CHECK(pathIter != objectsPaths.end(), ());
auto const & path = pathIter->second;
m_regionsKv << KeyValueStorage::SerializeDref(objectId.GetEncodedId()) << " "
<< KeyValueStorage::Serialize(BuildRegionValue(path)) << "\n";
}
}
std::tuple<RegionsBuilder::Regions, PlacePointsMap> ReadDatasetFromTmpMwm(
std::string const & tmpMwmFilename, RegionInfo & collector)
{
RegionsBuilder::Regions regions;
PlacePointsMap placePointsMap;
auto const toDo = [&](FeatureBuilder const & fb, uint64_t /* currPos */) {
if (fb.IsArea() && fb.IsGeometryClosed())
{
auto const id = fb.GetMostGenericOsmId();
auto region = Region(fb, collector.Get(id));
auto const & name = region.GetName();
if (name.empty())
return;
regions.emplace_back(std::move(region));
}
else if (fb.IsPoint())
{
auto const id = fb.GetMostGenericOsmId();
auto place = PlacePoint{fb, collector.Get(id)};
auto const & name = place.GetName();
auto const placeType = place.GetPlaceType();
if (name.empty() || placeType == PlaceType::Unknown)
return;
placePointsMap.emplace(id, std::move(place));
}
};
ForEachFromDatRawFormat(tmpMwmFilename, toDo);
return std::make_tuple(std::move(regions), std::move(placePointsMap));
}
void RepackTmpMwm()
{
feature::FeaturesCollector featuresCollector{m_pathOutRepackedRegionsTmpMwm};
std::set<base::GeoObjectId> processedObjects;
auto const toDo = [&](FeatureBuilder & fb, uint64_t /* currPos */) {
auto const id = fb.GetMostGenericOsmId();
auto objectRegions = m_objectsRegions.equal_range(id);
if (objectRegions.first == objectRegions.second)
return;
if (!processedObjects.insert(id).second)
return;
for (auto item = objectRegions.first; item != objectRegions.second; ++item)
{
auto const & region = item->second->GetData();
ResetGeometry(fb, region);
fb.SetOsmId(region.GetId());
fb.SetRank(0);
featuresCollector.Collect(fb);
}
};
LOG(LINFO, ("Start regions repacking from", m_pathInRegionsTmpMwm));
feature::ForEachFromDatRawFormat(m_pathInRegionsTmpMwm, toDo);
LOG(LINFO, ("Repacked regions temporary mwm saved to", m_pathOutRepackedRegionsTmpMwm));
}
void ResetGeometry(FeatureBuilder & fb, Region const & region)
{
fb.ResetGeometry();
auto const & polygon = region.GetPolygon();
auto outer = GetPointSeq(polygon->outer());
fb.AddPolygon(outer);
FeatureBuilder::Geometry holes;
auto const & inners = polygon->inners();
std::transform(std::begin(inners), std::end(inners), std::back_inserter(holes),
[this](auto && polygon) { return this->GetPointSeq(polygon); });
fb.SetHoles(std::move(holes));
fb.SetArea();
CHECK(fb.IsArea(), ());
CHECK(fb.IsGeometryClosed(), ());
}
template <typename Polygon>
FeatureBuilder::PointSeq GetPointSeq(Polygon const & polygon)
{
FeatureBuilder::PointSeq seq;
std::transform(std::begin(polygon), std::end(polygon), std::back_inserter(seq),
[](BoostPoint const & p) { return m2::PointD(p.get<0>(), p.get<1>()); });
return seq;
}
std::string m_pathInRegionsTmpMwm;
std::string m_pathOutRegionsKv;
std::string m_pathOutRepackedRegionsTmpMwm;
bool m_verbose{false};
RegionInfo m_regionsInfoCollector;
std::ofstream m_regionsKv;
std::multimap<base::GeoObjectId, Node::Ptr> m_objectsRegions;
std::map<base::GeoObjectId, std::shared_ptr<std::string>> m_regionsCountries;
};
} // namespace
void GenerateRegions(std::string const & pathInRegionsTmpMwm,
std::string const & pathInRegionsCollector,
std::string const & pathOutRegionsKv,
std::string const & pathOutRepackedRegionsTmpMwm, bool verbose,
size_t threadsCount)
{
RegionsGenerator(pathInRegionsTmpMwm, pathInRegionsCollector, pathOutRegionsKv,
pathOutRepackedRegionsTmpMwm, verbose, threadsCount);
}
} // namespace regions
} // namespace generator

View file

@ -1,16 +0,0 @@
#pragma once
#include <string>
namespace generator
{
namespace regions
{
void GenerateRegions(std::string const & pathInRegionsTmpMwm,
std::string const & pathInRegionsCollector,
std::string const & pathOutRegionsKv,
std::string const & pathOutRepackedRegionsTmpMwm,
bool verbose,
size_t threadsCount = 1);
} // namespace regions
} // namespace generator

View file

@ -1,338 +0,0 @@
#include "generator/regions/regions_builder.hpp"
#include "generator/regions/admin_suburbs_marker.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/place_points_integrator.hpp"
#include "base/assert.hpp"
#include "base/stl_helpers.hpp"
#include "base/thread_pool_computational.hpp"
#include <algorithm>
#include <chrono>
#include <fstream>
#include <functional>
#include <numeric>
#include <queue>
#include <thread>
#include <unordered_set>
namespace generator
{
namespace regions
{
RegionsBuilder::RegionsBuilder(Regions && regions, PlacePointsMap && placePointsMap,
size_t threadsCount)
: m_threadsCount(threadsCount)
{
ASSERT(m_threadsCount != 0, ());
MoveLabelPlacePoints(placePointsMap, regions);
m_regionsInAreaOrder = FormRegionsInAreaOrder(std::move(regions));
m_countriesOuters = ExtractCountriesOuters(m_regionsInAreaOrder);
m_placePointsMap = std::move(placePointsMap);
}
void RegionsBuilder::MoveLabelPlacePoints(PlacePointsMap & placePointsMap, Regions & regions)
{
for (auto & region : regions)
{
if (auto labelOsmId = region.GetLabelOsmId())
{
auto label = placePointsMap.find(*labelOsmId);
if (label != placePointsMap.end())
region.SetLabel(label->second);
}
}
for (auto & region : regions)
{
if (auto const & label = region.GetLabel())
placePointsMap.erase(label->GetId());
}
}
RegionsBuilder::Regions RegionsBuilder::FormRegionsInAreaOrder(Regions && regions)
{
auto const cmp = [](Region const & l, Region const & r) { return l.GetArea() > r.GetArea(); };
std::sort(std::begin(regions), std::end(regions), cmp);
return std::move(regions);
}
RegionsBuilder::Regions RegionsBuilder::ExtractCountriesOuters(Regions & regions)
{
Regions countriesOuters;
auto const isCountry = [](Region const & region) {
auto const placeType = region.GetPlaceType();
if (placeType == PlaceType::Country)
return true;
auto const adminLevel = region.GetAdminLevel();
return adminLevel == AdminLevel::Two && placeType == PlaceType::Unknown;
};
std::copy_if(std::begin(regions), std::end(regions), std::back_inserter(countriesOuters),
isCountry);
base::EraseIf(regions, isCountry);
return countriesOuters;
}
RegionsBuilder::Regions const & RegionsBuilder::GetCountriesOuters() const
{
return m_countriesOuters;
}
RegionsBuilder::StringsList RegionsBuilder::GetCountryInternationalNames() const
{
StringsList result;
std::unordered_set<std::string> set;
for (auto const & c : GetCountriesOuters())
{
auto const & name = c.GetInternationalName();
if (set.insert(name).second)
result.emplace_back(std::move(name));
}
return result;
}
Node::Ptr RegionsBuilder::BuildCountryRegionTree(Region const & outer,
CountrySpecifier const & countrySpecifier) const
{
auto nodes = MakeCountryNodesInAreaOrder(outer, m_regionsInAreaOrder, countrySpecifier);
for (auto i = std::crbegin(nodes), end = std::crend(nodes); i != end; ++i)
{
if (auto parent = ChooseParent(nodes, i, countrySpecifier))
{
(*i)->SetParent(parent);
parent->AddChild(*i);
}
}
return nodes.front();
}
std::vector<Node::Ptr> RegionsBuilder::MakeCountryNodesInAreaOrder(
Region const & countryOuter, Regions const & regionsInAreaOrder,
CountrySpecifier const & countrySpecifier) const
{
std::vector<Node::Ptr> nodes{
std::make_shared<Node>(LevelRegion{PlaceLevel::Country, countryOuter})};
for (auto const & region : regionsInAreaOrder)
{
if (countryOuter.ContainsRect(region))
{
auto level = countrySpecifier.GetLevel(region);
auto node = std::make_shared<Node>(LevelRegion{level, region});
nodes.emplace_back(std::move(node));
}
}
return nodes;
}
Node::Ptr RegionsBuilder::ChooseParent(std::vector<Node::Ptr> const & nodesInAreaOrder,
std::vector<Node::Ptr>::const_reverse_iterator forItem,
CountrySpecifier const & countrySpecifier) const
{
auto const & node = *forItem;
auto const & region = node->GetData();
auto const from = FindAreaLowerBoundRely(nodesInAreaOrder, forItem);
CHECK(from <= forItem, ());
Node::Ptr parent;
for (auto i = from, end = std::crend(nodesInAreaOrder); i != end; ++i)
{
auto const & candidate = *i;
auto const & candidateRegion = candidate->GetData();
if (parent)
{
auto const & parentRegion = parent->GetData();
if (IsAreaLessRely(parentRegion, candidateRegion))
break;
}
if (!candidateRegion.ContainsRect(region) && !candidateRegion.Contains(region.GetCenter()))
continue;
if (i == forItem)
continue;
auto const c = CompareAffiliation(candidateRegion, region, countrySpecifier);
if (c == 1)
{
if (parent && 0 <= CompareAffiliation(candidateRegion, parent->GetData(), countrySpecifier))
continue;
parent = candidate;
}
}
CHECK(!parent || -1 == CompareAffiliation(region, parent->GetData(), countrySpecifier),
(GetRegionNotation(region), GetRegionNotation(parent->GetData())));
return parent;
}
std::vector<Node::Ptr>::const_reverse_iterator RegionsBuilder::FindAreaLowerBoundRely(
std::vector<Node::Ptr> const & nodesInAreaOrder,
std::vector<Node::Ptr>::const_reverse_iterator forItem) const
{
auto const & region = (*forItem)->GetData();
auto areaLessRely = [](Node::Ptr const & element, Region const & region) {
auto const & elementRegion = element->GetData();
return IsAreaLessRely(elementRegion, region);
};
return std::lower_bound(std::crbegin(nodesInAreaOrder), forItem, region, areaLessRely);
}
// static
void RegionsBuilder::InsertIntoSubtree(Node::Ptr & subtree, LevelRegion && region,
CountrySpecifier const & countrySpecifier)
{
auto newNode = std::make_shared<Node>(std::move(region));
InsertIntoSubtree(subtree, std::move(newNode), countrySpecifier);
}
// static
void RegionsBuilder::InsertIntoSubtree(Node::Ptr & subtree, Node::Ptr && newNode,
CountrySpecifier const & countrySpecifier)
{
CHECK(0 < CompareAffiliation(subtree->GetData(), newNode->GetData(), countrySpecifier), ());
auto & children = subtree->GetChildren();
auto childIt = children.begin();
while (childIt != children.end())
{
auto & child = *childIt;
auto const c = CompareAffiliation(child->GetData(), newNode->GetData(), countrySpecifier);
if (c > 0)
return InsertIntoSubtree(child, std::move(newNode), countrySpecifier);
if (c < 0)
{
child->SetParent(newNode);
newNode->AddChild(child);
childIt = children.erase(childIt);
continue;
}
ASSERT(c == 0, ());
++childIt;
}
newNode->SetParent(subtree);
subtree->AddChild(newNode);
}
// static
int RegionsBuilder::CompareAffiliation(LevelRegion const & l, LevelRegion const & r,
CountrySpecifier const & countrySpecifier)
{
if (IsAreaLessRely(r, l) && l.Contains(r))
return 1;
if (IsAreaLessRely(l, r) && r.Contains(l))
return -1;
if (l.CalculateOverlapPercentage(r) < 50.0)
return 0;
auto const lArea = l.GetArea();
auto const rArea = r.GetArea();
if (0.5 * lArea > rArea)
{
ASSERT_GREATER(0.5 * lArea, 0, ());
LOG(LDEBUG, ("Region", l.GetId(), GetRegionNotation(l), "contains partly", r.GetId(),
GetRegionNotation(r)));
return 1;
}
if (0.5 * rArea > lArea)
{
ASSERT_GREATER(0.5 * rArea, 0, ());
LOG(LDEBUG, ("Region", r.GetId(), GetRegionNotation(r), "contains partly", l.GetId(),
GetRegionNotation(l)));
return -1;
}
return countrySpecifier.RelateByWeight(l, r);
}
// static
bool RegionsBuilder::IsAreaLessRely(Region const & l, Region const & r)
{
constexpr auto lAreaRation = 1. + kAreaRelativeErrorPercent / 100.;
return lAreaRation * l.GetArea() < r.GetArea();
}
void RegionsBuilder::ForEachCountry(CountryFn fn)
{
std::vector<std::future<Node::PtrList>> buildingTasks;
{
base::thread_pool::computational::ThreadPool threadPool(m_threadsCount);
for (auto const & countryName : GetCountryInternationalNames())
{
auto result = threadPool.Submit([this, countryName]() { return BuildCountry(countryName); });
buildingTasks.emplace_back(std::move(result));
}
}
for (auto && task : buildingTasks)
{
auto countryTrees = task.get();
CHECK(!countryTrees.empty(), ());
auto && countryName = countryTrees.front()->GetData().GetInternationalName();
fn(countryName, countryTrees);
}
}
Node::PtrList RegionsBuilder::BuildCountry(std::string const & countryName) const
{
Regions outers;
auto const & countries = GetCountriesOuters();
auto const pred = [&](Region const & country) {
return countryName == country.GetInternationalName();
};
std::copy_if(std::begin(countries), std::end(countries), std::back_inserter(outers), pred);
auto countrySpecifier = CountrySpecifierBuilder::GetInstance().MakeCountrySpecifier(countryName);
auto countryTrees = BuildCountryRegionTrees(outers, *countrySpecifier);
PlacePointsIntegrator pointsIntegrator{m_placePointsMap, *countrySpecifier};
LOG(LINFO, ("Start integrate place points for", countryName));
pointsIntegrator.ApplyTo(countryTrees);
LOG(LINFO, ("Finish integrate place points for", countryName));
AdminSuburbsMarker suburbsMarker;
LOG(LINFO, ("Start mark admin suburbs for", countryName));
for (auto & tree : countryTrees)
suburbsMarker.MarkSuburbs(tree);
LOG(LINFO, ("Finish mark admin suburbs for", countryName));
countrySpecifier->AdjustRegionsLevel(countryTrees);
return countryTrees;
}
Node::PtrList RegionsBuilder::BuildCountryRegionTrees(
Regions const & outers, CountrySpecifier const & countrySpecifier) const
{
Node::PtrList trees;
for (auto const & outer : outers)
{
auto tree = BuildCountryRegionTree(outer, countrySpecifier);
trees.push_back(std::move(tree));
}
return trees;
}
} // namespace regions
} // namespace generator

View file

@ -1,70 +0,0 @@
#pragma once
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/level_region.hpp"
#include "generator/regions/node.hpp"
#include "generator/regions/region.hpp"
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
// This class is needed to build a hierarchy of regions. We can have several nodes for a region
// with the same name, represented by a multi-polygon (several polygons).
class RegionsBuilder
{
public:
using Regions = std::vector<Region>;
using StringsList = std::vector<std::string>;
using CountryFn = std::function<void(std::string const &, Node::PtrList const &)>;
explicit RegionsBuilder(Regions && regions, PlacePointsMap && placePointsMap,
size_t threadsCount = 1);
Regions const & GetCountriesOuters() const;
StringsList GetCountryInternationalNames() const;
void ForEachCountry(CountryFn fn);
static void InsertIntoSubtree(Node::Ptr & subtree, LevelRegion && region,
CountrySpecifier const & countrySpecifier);
// Return: 0 - no relation, 1 - |l| contains |r|, -1 - |r| contains |l|.
static int CompareAffiliation(LevelRegion const & l, LevelRegion const & r,
CountrySpecifier const & countrySpecifier);
static bool IsAreaLessRely(Region const & l, Region const & r);
private:
static constexpr double kAreaRelativeErrorPercent = 0.1;
void MoveLabelPlacePoints(PlacePointsMap & placePointsMap, Regions & regions);
Regions FormRegionsInAreaOrder(Regions && regions);
Regions ExtractCountriesOuters(Regions & regions);
Node::PtrList BuildCountry(std::string const & countryName) const;
Node::PtrList BuildCountryRegionTrees(Regions const & outers,
CountrySpecifier const & countrySpecifier) const;
Node::Ptr BuildCountryRegionTree(Region const & outer,
CountrySpecifier const & countrySpecifier) const;
std::vector<Node::Ptr> MakeCountryNodesInAreaOrder(
Region const & countryOuter, Regions const & regionsInAreaOrder,
CountrySpecifier const & countrySpecifier) const;
Node::Ptr ChooseParent(std::vector<Node::Ptr> const & nodesInAreaOrder,
std::vector<Node::Ptr>::const_reverse_iterator forItem,
CountrySpecifier const & countrySpecifier) const;
std::vector<Node::Ptr>::const_reverse_iterator FindAreaLowerBoundRely(
std::vector<Node::Ptr> const & nodesInAreaOrder,
std::vector<Node::Ptr>::const_reverse_iterator forItem) const;
static void InsertIntoSubtree(Node::Ptr & subtree, Node::Ptr && newNode,
CountrySpecifier const & countrySpecifier);
Regions m_countriesOuters;
Regions m_regionsInAreaOrder;
PlacePointsMap m_placePointsMap;
size_t m_threadsCount;
};
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class AfghanistanSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Afghanistan"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(AfghanistanSpecifier);
PlaceLevel AfghanistanSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Province
case AdminLevel::Six: return PlaceLevel::Subregion; // Districts
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class AlbaniaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Albania"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(AlbaniaSpecifier);
PlaceLevel AlbaniaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Six: return PlaceLevel::Region; // counties
case AdminLevel::Seven: return PlaceLevel::Subregion; // districts
case AdminLevel::Nine: return PlaceLevel::Suburb; // Neighborhoods of Tirana
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class AlgeriaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Algeria"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(AlgeriaSpecifier);
PlaceLevel AlgeriaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Provinces of Algeria
case AdminLevel::Six: return PlaceLevel::Subregion; // Districts of Algeria
case AdminLevel::Eight: return PlaceLevel::Locality; // Communes of Algeria, also towns
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class AndorraSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Andorra"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(AndorraSpecifier);
PlaceLevel AndorraSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Seven: return PlaceLevel::Region; // Parròquies borders (communes)
case AdminLevel::Eight:
return PlaceLevel::Sublocality; // Municipality borders Only used for the capital city Andorra
// la Vella.
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class AngolaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Angola"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(AngolaSpecifier);
PlaceLevel AngolaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Províncias
case AdminLevel::Six: return PlaceLevel::Subregion; // Municípios (Municipalities)
case AdminLevel::Seven:
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,40 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class AntiguaAndBarbudaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"AntiguaAndBarbuda"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(AntiguaAndBarbudaSpecifier);
PlaceLevel AntiguaAndBarbudaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Parishes and dependencies borders
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class ArgentinaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Argentina"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(ArgentinaSpecifier);
PlaceLevel ArgentinaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Province / Ciudad Autónoma de Buenos Aires
case AdminLevel::Five: return PlaceLevel::Subregion; // Departamento / partido
case AdminLevel::Eight: return PlaceLevel::Locality; // Villages, City, town
case AdminLevel::Nine: return PlaceLevel::Suburb; // Barrio
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,40 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class ArubaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Aruba"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(ArubaSpecifier);
PlaceLevel ArubaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Eight:
return PlaceLevel::Region; // Districts (Municipalities) known as GAC regions
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,46 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class AustraliaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Australia"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(AustraliaSpecifier);
PlaceLevel AustraliaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // State or Territory Border
case AdminLevel::Seven:
return PlaceLevel::Subregion; // District or Region Border (e.g Perthshire, Fitzroy, Canning,
// Greater Sydney, Greater Melbourne, etc.)
case AdminLevel::Nine:
return PlaceLevel::Locality; // Suburb and Locality Border (If larger than ABS boundary)
case AdminLevel::Ten: return PlaceLevel::Locality; // Suburb and Locality Border (ABS boundaries)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class AustriaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Austria"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(AustriaSpecifier);
PlaceLevel AustriaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Bundesland
case AdminLevel::Nine:
return PlaceLevel::Locality; // Wiener / Grazer / ... Stadt- / Gemeindebezirk
case AdminLevel::Ten: return PlaceLevel::Sublocality; // Stadtteile
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class AzerbaijanSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Azerbaijan"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(AzerbaijanSpecifier);
PlaceLevel AzerbaijanSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // autonomous republic
case AdminLevel::Seven:
return PlaceLevel::Subregion; // regions (rayons) and cities with authority of republic level
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BahamasSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Bahamas"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BahamasSpecifier);
PlaceLevel BahamasSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Six:
return PlaceLevel::Region; // Central government district - New Providence (main island) only
case AdminLevel::Eight:
return PlaceLevel::Region; // Districts of the Bahamas (Local government) (other islands)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BahrainSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Bahrain"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BahrainSpecifier);
PlaceLevel BahrainSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Governorate
case AdminLevel::Six:
return PlaceLevel::Subregion; // Municipality Example: Al Manamah, Ras Rumman
case AdminLevel::Nine: return PlaceLevel::Locality; // neighbourhood
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BangladeshSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Bangladesh"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BangladeshSpecifier);
PlaceLevel BangladeshSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Three: return PlaceLevel::Region; // Division
case AdminLevel::Five: return PlaceLevel::Subregion; // District
case AdminLevel::Nine: return PlaceLevel::Locality; // Union
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BarbadosSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Barbados"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BarbadosSpecifier);
PlaceLevel BarbadosSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Six: return PlaceLevel::Region; // Parishes of Barbados
case AdminLevel::Nine: return PlaceLevel::Suburb; // Suburbs, Hamlets and Villages
case AdminLevel::Ten: return PlaceLevel::Suburb; // Neighbourhoods, Housing Developments
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,46 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BelarusSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Belarus"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BelarusSpecifier);
PlaceLevel BelarusSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Oblasts (вобласьць / область)
case AdminLevel::Six: return PlaceLevel::Subregion; // Regions (раён / район)
case AdminLevel::Eight:
return PlaceLevel::Locality; // Soviets of settlement (сельсавет / cельсовет)
case AdminLevel::Nine: return PlaceLevel::Sublocality; // Suburbs (раён гораду / район города)
case AdminLevel::Ten:
return PlaceLevel::Locality; // Municipalities (населены пункт / населённый пункт)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BelgiumSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Belgium"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BelgiumSpecifier);
PlaceLevel BelgiumSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four:
return PlaceLevel::Region; // Communities, regions and language areas of Belgium
case AdminLevel::Six: return PlaceLevel::Subregion; // Provinces
case AdminLevel::Nine: return PlaceLevel::Suburb; // Deelgemeenten (sections)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BelizeSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Belize"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BelizeSpecifier);
PlaceLevel BelizeSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Département
case AdminLevel::Eight: return PlaceLevel::Subregion; // Commune
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BeninSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Benin"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BeninSpecifier);
PlaceLevel BeninSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four:
return PlaceLevel::Region; // Communities, regions and language areas of Belgium
case AdminLevel::Six: return PlaceLevel::Subregion; // Provinces
case AdminLevel::Nine: return PlaceLevel::Suburb; // Deelgemeenten (sections)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,44 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BhutanSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Bhutan"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BhutanSpecifier);
PlaceLevel BhutanSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four:
return PlaceLevel::Region; // Dzongkhag (the primary subdivisions of Bhutan)
case AdminLevel::Five:
return PlaceLevel::Subregion; // Dungkhag (sub-district of a
// dzongkhag)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BoliviaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Bolivia"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BoliviaSpecifier);
PlaceLevel BoliviaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Departamentos
case AdminLevel::Six: return PlaceLevel::Subregion; // Provincias / provinces
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BosniaAndHerzegovinaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Bosnia And Herzegovina"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BosniaAndHerzegovinaSpecifier);
PlaceLevel BosniaAndHerzegovinaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // entitet / eнтитет / entity
case AdminLevel::Five: return PlaceLevel::Subregion; // kanton (FBiH)
case AdminLevel::Six: return PlaceLevel::Locality; // grad / град / city
case AdminLevel::Nine: return PlaceLevel::Locality; // naselje / насеље / localities
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BrazilSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Brazil"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BrazilSpecifier);
PlaceLevel BrazilSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four:
return PlaceLevel::Region; // Unidades Federativas (Estados e Distrito Federal)
case AdminLevel::Five: return PlaceLevel::Subregion; // Mesorregiões
case AdminLevel::Ten: return PlaceLevel::Suburb; // Bairros e Sub-Distritos
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,44 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BruneiSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Brunei"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BruneiSpecifier);
PlaceLevel BruneiSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Districts
case AdminLevel::Six: return PlaceLevel::Subregion; // Mukims (subdistricts)
case AdminLevel::Eight:
return PlaceLevel::Locality; // Villages (kampung or kampong), as designated by the Survey
// Department
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BulgariaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Bulgaria"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BulgariaSpecifier);
PlaceLevel BulgariaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Райони за планиране
case AdminLevel::Six: return PlaceLevel::Subregion; // Regions (Области)
case AdminLevel::Eight: return PlaceLevel::Locality; // Borders of city, town, village
case AdminLevel::Nine: return PlaceLevel::Suburb; // Districts and suburbs
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,46 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BurkinaFasoSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Burkina Faso"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BurkinaFasoSpecifier);
PlaceLevel BurkinaFasoSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Régions
case AdminLevel::Five: return PlaceLevel::Subregion; // Provinces
case AdminLevel::Eight:
return PlaceLevel::Locality; // Towns or villages (excluding their surrounding rural areas)
case AdminLevel::Nine:
return PlaceLevel::Sublocality; // Urban sectors (only in cities, and in the capital town of
// other urban municipalities)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class BurundiSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Burundi"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(BurundiSpecifier);
PlaceLevel BurundiSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Provinces
case AdminLevel::Five: return PlaceLevel::Subregion; // Communes
case AdminLevel::Eight: return PlaceLevel::Locality; // Collines
case AdminLevel::Ten: return PlaceLevel::Sublocality; // Sous-Collines
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class CameroonSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Cameroon"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(CameroonSpecifier);
PlaceLevel CameroonSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Regions, like Extrême-Nord
case AdminLevel::Six: return PlaceLevel::Subregion; // Départements, like Mayo-Danay
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,43 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class CanadaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Canada"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(CanadaSpecifier);
PlaceLevel CanadaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Provinces & territories
case AdminLevel::Six:
return PlaceLevel::Subregion; // Regional municipalities & single-tier municipalities
case AdminLevel::Ten: return PlaceLevel::Locality; // Neighborhoods
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class ChadSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Chad"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(ChadSpecifier);
PlaceLevel ChadSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Régions (23)
case AdminLevel::Six: return PlaceLevel::Subregion; // Départments (61)
case AdminLevel::Nine: return PlaceLevel::Locality; // Villages ou localités
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class ChileSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Chile"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(ChileSpecifier);
PlaceLevel ChileSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Regiones
case AdminLevel::Six: return PlaceLevel::Subregion; // Provincias
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,44 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class ChinaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"China"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(ChinaSpecifier);
PlaceLevel ChinaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Two: return PlaceLevel::Country; // Hong Kong, Macau
case AdminLevel::Four: return PlaceLevel::Region; // Provinces
case AdminLevel::Six: return PlaceLevel::Subregion; // County
case AdminLevel::Eight: return PlaceLevel::Subregion; // Township / Town / Subdistrict
case AdminLevel::Ten: return PlaceLevel::Locality; // Village
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class ColombiaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Colombia"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(ColombiaSpecifier);
PlaceLevel ColombiaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Departamento
case AdminLevel::Five: return PlaceLevel::Subregion; // Provincia
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class CostaRicaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"CostaRica"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(CostaRicaSpecifier);
PlaceLevel CostaRicaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Provincia
case AdminLevel::Six: return PlaceLevel::Subregion; // Cantón
case AdminLevel::Ten: return PlaceLevel::Sublocality; // Barrio
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,46 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class CoteDivoireSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {u8"Côte d'Ivoire"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(CoteDivoireSpecifier);
PlaceLevel CoteDivoireSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four:
return PlaceLevel::Region; // district (example: Lagunes) où disctrict autonome (example:
// Abidjan) place=state (not place=district)
case AdminLevel::Five:
return PlaceLevel::Subregion; // region (example: Agnéby-Tiassa) place=region
case AdminLevel::Nine: return PlaceLevel::Locality; // village
case AdminLevel::Ten: return PlaceLevel::Sublocality; // quartier
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,40 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class CroatiaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Croatia"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(CroatiaSpecifier);
PlaceLevel CroatiaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Six: return PlaceLevel::Region; // County (hr: županije)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class CubaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Cuba"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(CubaSpecifier);
PlaceLevel CubaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Provincia
case AdminLevel::Six: return PlaceLevel::Subregion; // Municipio
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,40 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class CyprusSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Cyprus"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(CyprusSpecifier);
PlaceLevel CyprusSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Six: return PlaceLevel::Region; // The 6 districts
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class CzechRepublicSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"CzechRepublic"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(CzechRepublicSpecifier);
PlaceLevel CzechRepublicSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Six: return PlaceLevel::Region; // Regions
case AdminLevel::Seven: return PlaceLevel::Subregion; // Districts
case AdminLevel::Eight: return PlaceLevel::Locality; // Towns / village
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class DenmarkSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Denmark"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(DenmarkSpecifier);
PlaceLevel DenmarkSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Regioner (regions - administrative unit)
case AdminLevel::Seven: return PlaceLevel::Subregion; // Districts
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class DominicanRepublicSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"DominicanRepublic"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(DominicanRepublicSpecifier);
PlaceLevel DominicanRepublicSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Province (Provincia)
case AdminLevel::Six: return PlaceLevel::Subregion; // Municipality (Municipio)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,40 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class EgyptSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Egypt"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(EgyptSpecifier);
PlaceLevel EgyptSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Three: return PlaceLevel::Region; // Governorate (Mouhafazah محافظة)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,40 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class EstoniaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Estonia"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(EstoniaSpecifier);
PlaceLevel EstoniaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Six: return PlaceLevel::Region; // Countys
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class EthiopiaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Ethiopia"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(EthiopiaSpecifier);
PlaceLevel EthiopiaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Administrative States (9)
case AdminLevel::Six: return PlaceLevel::Subregion; // Woreda
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class FinlandSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Finland"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(FinlandSpecifier);
PlaceLevel FinlandSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Provinces
case AdminLevel::Six: return PlaceLevel::Subregion; // Regions
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class FranceSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"France"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(FranceSpecifier);
PlaceLevel FranceSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Régions
case AdminLevel::Six: return PlaceLevel::Subregion; // Départements
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class FrenchPolynesiaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"FrenchPolynesia"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(FrenchPolynesiaSpecifier);
PlaceLevel FrenchPolynesiaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Six:
return PlaceLevel::Region; // Administratrive divisions (archipelagos or sub-archipelagos)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class GabonSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Gabon"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(GabonSpecifier);
PlaceLevel GabonSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Provinces
case AdminLevel::Six: return PlaceLevel::Subregion; // Departments
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class GambiaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Gambia"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(GambiaSpecifier);
PlaceLevel GambiaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Regions (Divisions)
case AdminLevel::Six: return PlaceLevel::Subregion; // Districts
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class GeorgiaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Georgia"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(GeorgiaSpecifier);
PlaceLevel GeorgiaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four:
return PlaceLevel::Region; // regions (მხარე) including the Ajaran Autonomous Republic
case AdminLevel::Six: return PlaceLevel::Subregion; // districts (რაიონი)
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,42 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class GermanySpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Germany"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(GermanySpecifier);
PlaceLevel GermanySpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // federal states border
case AdminLevel::Five: return PlaceLevel::Subregion; // state-district border
case AdminLevel::Eight: return PlaceLevel::Locality; // Towns, Municipalities / City-districts
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

View file

@ -1,41 +0,0 @@
#include "generator/regions/collector_region_info.hpp"
#include "generator/regions/country_specifier.hpp"
#include "generator/regions/country_specifier_builder.hpp"
#include "generator/regions/region.hpp"
#include <string>
#include <vector>
namespace generator
{
namespace regions
{
namespace specs
{
class GhanaSpecifier final : public CountrySpecifier
{
public:
static std::vector<std::string> GetCountryNames() { return {"Ghana"}; }
private:
// CountrySpecifier overrides:
PlaceLevel GetSpecificCountryLevel(Region const & region) const override;
};
REGISTER_COUNTRY_SPECIFIER(GhanaSpecifier);
PlaceLevel GhanaSpecifier::GetSpecificCountryLevel(Region const & region) const
{
AdminLevel adminLevel = region.GetAdminLevel();
switch (adminLevel)
{
case AdminLevel::Four: return PlaceLevel::Region; // Region
case AdminLevel::Six: return PlaceLevel::Subregion; // District
default: break;
}
return PlaceLevel::Unknown;
}
} // namespace specs
} // namespace regions
} // namespace generator

Some files were not shown because too many files have changed in this diff Show more