From 6d5a2d0e0ce7486fa371bba56fc8d4bae98956ad Mon Sep 17 00:00:00 2001 From: Mikhail Gorbushin Date: Mon, 18 Nov 2019 12:38:09 +0300 Subject: [PATCH] [generator] Review fixes --- generator/city_roads_generator.cpp | 28 ++-- generator/city_roads_generator.hpp | 2 +- .../collector_routing_city_boundaries.cpp | 22 +-- .../collector_routing_city_boundaries.hpp | 6 +- .../final_processor_intermediate_mwm.cpp | 6 +- .../final_processor_intermediate_mwm.hpp | 4 +- ...ollector_routing_city_boundaries_tests.cpp | 125 ++++++++++++------ generator/raw_generator.cpp | 2 +- .../routing_city_boundaries_processor.cpp | 93 +++++-------- .../routing_city_boundaries_processor.hpp | 7 +- generator/translator_country.cpp | 3 +- routing/routing_helpers.hpp | 8 +- 12 files changed, 164 insertions(+), 142 deletions(-) diff --git a/generator/city_roads_generator.cpp b/generator/city_roads_generator.cpp index 7fa2ebbd3b..34a00ee5c2 100644 --- a/generator/city_roads_generator.cpp +++ b/generator/city_roads_generator.cpp @@ -16,6 +16,7 @@ #include "base/assert.hpp" #include "base/geo_object_id.hpp" +#include "base/logging.hpp" #include @@ -26,8 +27,8 @@ using namespace std; namespace { -void LoadFeatureBuildersToVector(string const & boundariesPath, - CitiesBoundariesChecker::CitiesBoundaries & result) +void LoadCitiesBoundariesGeometry(string const & boundariesPath, + CitiesBoundariesChecker::CitiesBoundaries & result) { if (!Platform::IsFileExistsByFullPath(boundariesPath)) { @@ -57,12 +58,14 @@ vector CalcRoadFeatureIds(string const & dataPath, string const & boun { CitiesBoundariesChecker::CitiesBoundaries citiesBoundaries; - LoadFeatureBuildersToVector(boundariesPath, citiesBoundaries); + LoadCitiesBoundariesGeometry(boundariesPath, citiesBoundaries); CitiesBoundariesChecker const checker(citiesBoundaries); vector cityRoadFeatureIds; ForEachFromDat(dataPath, [&cityRoadFeatureIds, &checker](FeatureType & ft, uint32_t fid) { - if (!routing::IsCarRoad(TypesHolder(ft))) + bool const needToProcess = + routing::IsCarRoad(TypesHolder(ft)) || routing::IsBicycleRoad(TypesHolder(ft)); + if (!needToProcess) return; ft.ParseGeometry(FeatureType::BEST_GEOMETRY); @@ -74,8 +77,12 @@ vector CalcRoadFeatureIds(string const & dataPath, string const & boun ++inCityPointsCounter; } - double constexpr kInCityPointsRatio = 0.8; - if (inCityPointsCounter > kInCityPointsRatio * ft.GetPointsCount()) + // Our approximation of boundary overestimates it, because of different + // bounding boxes (in order to increase performance). So we don't want + // match some long roads as city roads, because they pass near city, but + // not though it. + double constexpr kPointsRatioInCity = 0.8; + if (inCityPointsCounter > kPointsRatioInCity * ft.GetPointsCount()) cityRoadFeatureIds.push_back(ft.GetID().m_index); }); @@ -98,19 +105,14 @@ void SerializeCityRoads(string const & dataPath, vector && cityRoadFea bool BuildCityRoads(string const & mwmPath, string const & boundariesPath) { - vector cityRoadFeatureIds; try { - // @TODO(bykoianko) The generation city roads section process is based on two stages now: + // The generation city roads section process is based on two stages now: // * dumping cities boundaries on feature generation step // * calculating feature ids and building section when feature ids are available // As a result of dumping cities boundaries instances of indexer::CityBoundary objects // are generated and dumped. These objects are used for generating city roads section. - // Using real geometry of cities boundaries should be considered for generating city road - // features. That mean that the real geometry of cities boundaries should be dumped - // on the first step. And then to try using the real geometry should be used for generating city - // road features. But there's a chance that it takes to long time. - cityRoadFeatureIds = CalcRoadFeatureIds(mwmPath, boundariesPath); + auto cityRoadFeatureIds = CalcRoadFeatureIds(mwmPath, boundariesPath); SerializeCityRoads(mwmPath, move(cityRoadFeatureIds)); } catch (Reader::Exception const & e) diff --git a/generator/city_roads_generator.hpp b/generator/city_roads_generator.hpp index 30dc771571..a7420c21bc 100644 --- a/generator/city_roads_generator.hpp +++ b/generator/city_roads_generator.hpp @@ -12,7 +12,7 @@ namespace routing /// \param cityRoadFeatureIds a vector of road feature ids in cities. void SerializeCityRoads(std::string const & mwmPath, std::vector && cityRoadFeatureIds); -/// \brief Marks road-features as city roads if they intersect some boundary from data dumped in +/// \brief Marks road-features as city roads if they covered some boundary from data dumped in /// |boundariesPath|. Then serialize ids of such features to "city_roads" section. bool BuildCityRoads(std::string const & mwmPath, std::string const & boundariesPath); } // namespace routing diff --git a/generator/collector_routing_city_boundaries.cpp b/generator/collector_routing_city_boundaries.cpp index 44251f7466..fc9e9d02ab 100644 --- a/generator/collector_routing_city_boundaries.cpp +++ b/generator/collector_routing_city_boundaries.cpp @@ -109,18 +109,21 @@ RoutingCityBoundariesCollector::LocalityData::Deserialize(ReaderSource const & cache) + std::string const & filename, std::string const & dumpFilename, + std::shared_ptr const & cache) : CollectorInterface(filename) , m_writer(std::make_unique(GetTmpFilename())) , m_cache(cache) , m_featureMakerSimple(cache) + , m_dumpFilename(dumpFilename) { } std::shared_ptr RoutingCityBoundariesCollector::Clone( std::shared_ptr const & cache) const { - return std::make_shared(GetFilename(), cache ? m_cache : cache); + return std::make_shared(GetFilename(), m_dumpFilename, + cache ? cache : m_cache); } void RoutingCityBoundariesCollector::Collect(OsmElement const & osmElement) @@ -178,7 +181,7 @@ void RoutingCityBoundariesCollector::Finish() { m_writer->Reset(); } void RoutingCityBoundariesCollector::Save() { - m_writer->Save(GetFilename()); + m_writer->Save(GetFilename(), m_dumpFilename); } void RoutingCityBoundariesCollector::Merge(generator::CollectorInterface const & collector) @@ -245,9 +248,9 @@ void RoutingCityBoundariesWriter::Process(feature::FeatureBuilder const & featur void RoutingCityBoundariesWriter::Reset() { - m_nodeOsmIdToLocalityDataWriter.reset({}); - m_nodeOsmIdToBoundariesWriter.reset({}); - m_finalBoundariesGeometryWriter.reset({}); + m_nodeOsmIdToLocalityDataWriter.reset(); + m_nodeOsmIdToBoundariesWriter.reset(); + m_finalBoundariesGeometryWriter.reset(); } void RoutingCityBoundariesWriter::MergeInto(RoutingCityBoundariesWriter & writer) @@ -271,17 +274,18 @@ void RoutingCityBoundariesWriter::MergeInto(RoutingCityBoundariesWriter & writer writer.m_nodeOsmIdToBoundariesCount += m_nodeOsmIdToBoundariesCount; } -void RoutingCityBoundariesWriter::Save(std::string const & finalFileName) +void RoutingCityBoundariesWriter::Save(std::string const & finalFileName, + std::string const & dumpFilename) { auto const nodeToLocalityFilename = GetNodeToLocalityDataFilename(finalFileName); auto const nodeToBoundariesFilename = GetNodeToBoundariesFilename(finalFileName); - auto const finalBoundariesGeometry = GetBoundariesFilename(finalFileName); TruncateAndWriteCount(nodeToLocalityFilename, m_nodeOsmIdToLocalityDataCount); TruncateAndWriteCount(nodeToBoundariesFilename, m_nodeOsmIdToBoundariesCount); base::AppendFileToFile(m_nodeOsmIdToLocalityDataFilename, nodeToLocalityFilename); base::AppendFileToFile(m_nodeOsmIdToBoundariesFilename, nodeToBoundariesFilename); - base::CopyFileX(m_finalBoundariesGeometryFilename, finalBoundariesGeometry); + if (Platform::IsFileExistsByFullPath(m_finalBoundariesGeometryFilename)) + CHECK(base::CopyFileX(m_finalBoundariesGeometryFilename, dumpFilename), ()); } } // namespace generator diff --git a/generator/collector_routing_city_boundaries.hpp b/generator/collector_routing_city_boundaries.hpp index 986cac205b..f791b3c63b 100644 --- a/generator/collector_routing_city_boundaries.hpp +++ b/generator/collector_routing_city_boundaries.hpp @@ -41,6 +41,7 @@ public: }; RoutingCityBoundariesCollector(std::string const & filename, + std::string const & dumpFilename, std::shared_ptr const & cache); // CollectorInterface overrides: @@ -55,11 +56,12 @@ public: void MergeInto(RoutingCityBoundariesCollector & collector) const override; void Process(feature::FeatureBuilder & feature, OsmElement const & osmElement); -private: +private: std::unique_ptr m_writer; std::shared_ptr m_cache; FeatureMakerSimple m_featureMakerSimple; + std::string m_dumpFilename; }; class RoutingCityBoundariesWriter @@ -79,7 +81,7 @@ public: void Reset(); void MergeInto(RoutingCityBoundariesWriter & writer); - void Save(std::string const & finalFileName); + void Save(std::string const & finalFileName, std::string const & dumpFilename); private: using MinAccuracy = feature::serialization_policy::MinSize; diff --git a/generator/final_processor_intermediate_mwm.cpp b/generator/final_processor_intermediate_mwm.cpp index d2f3f549ff..21cdd625b8 100644 --- a/generator/final_processor_intermediate_mwm.cpp +++ b/generator/final_processor_intermediate_mwm.cpp @@ -295,7 +295,7 @@ void CountryFinalProcessor::DumpCitiesBoundaries(std::string const & filename) m_citiesBoundariesFilename = filename; } -void CountryFinalProcessor::DumpRoutingCitiesBoundariesFilename( +void CountryFinalProcessor::DumpRoutingCitiesBoundaries( std::string const & collectorFilename, std::string const & dumpPath) { m_routingCityBoundariesCollectorFilename = collectorFilename; @@ -405,9 +405,9 @@ void CountryFinalProcessor::ProcessRoutingCityBoundaries() CHECK(!m_routingCityBoundariesCollectorFilename.empty() && !m_routingCityBoundariesDumpPath.empty(), ()); - RoutingCityBoundariesProcessor processor(m_routingCityBoundariesCollectorFilename); + RoutingCityBoundariesProcessor processor(m_routingCityBoundariesCollectorFilename, + m_routingCityBoundariesDumpPath); processor.ProcessDataFromCollector(); - processor.DumpBoundaries(m_routingCityBoundariesDumpPath); } void CountryFinalProcessor::ProcessCities() diff --git a/generator/final_processor_intermediate_mwm.hpp b/generator/final_processor_intermediate_mwm.hpp index 6fc28864d1..1927b3f0fa 100644 --- a/generator/final_processor_intermediate_mwm.hpp +++ b/generator/final_processor_intermediate_mwm.hpp @@ -57,8 +57,8 @@ public: void SetMiniRoundabouts(std::string const & filename); void DumpCitiesBoundaries(std::string const & filename); - void DumpRoutingCitiesBoundariesFilename(std::string const & collectorFilename, - std::string const & dumpPath); + void DumpRoutingCitiesBoundaries(std::string const & collectorFilename, + std::string const & dumpPath); // FinalProcessorIntermediateMwmInterface overrides: void Process() override; diff --git a/generator/generator_tests/collector_routing_city_boundaries_tests.cpp b/generator/generator_tests/collector_routing_city_boundaries_tests.cpp index b18b979e92..8e274682fd 100644 --- a/generator/generator_tests/collector_routing_city_boundaries_tests.cpp +++ b/generator/generator_tests/collector_routing_city_boundaries_tests.cpp @@ -10,6 +10,8 @@ #include "platform/platform.hpp" +#include "coding/read_write_utils.hpp" + #include "geometry/point2d.hpp" #include "geometry/area_on_earth.hpp" @@ -29,19 +31,21 @@ namespace { using BoundariesCollector = RoutingCityBoundariesCollector; -std::vector GetFeatureBuilderGeometry() -{ - static std::vector const kPolygon = {{0, 0}, {0, 2}, {2, 2}, {2, 0}, {0, 0}}; - return kPolygon; -} +std::string const kDumpFileName = "dump.bin"; -feature::FeatureBuilder MakeAreaFeatureBuilder(OsmElement element) +std::vector const kPolygon1 = {{1, 0}, {0, 2}, {2, 2}, {2, 0}, {0, 0}, {1, 0}}; +std::vector const kPolygon2 = {{2, 0}, {0, 2}, {2, 2}, {2, 0}, {0, 0}, {2, 0}}; +std::vector const kPolygon3 = {{3, 0}, {0, 2}, {2, 2}, {2, 0}, {0, 0}, {3, 0}}; +std::vector const kPolygon4 = {{4, 0}, {0, 2}, {2, 2}, {2, 0}, {0, 0}, {4, 0}}; + +feature::FeatureBuilder MakeAreaFeatureBuilder(OsmElement element, + std::vector const & geometry) { feature::FeatureBuilder result; auto const filterType = [](uint32_t) { return true; }; ftype::GetNameAndType(&element, result.GetParams(), filterType); result.SetOsmId(base::MakeOsmRelation(element.m_id)); - auto polygon = GetFeatureBuilderGeometry(); + auto polygon = geometry; result.AddPolygon(polygon); result.SetArea(); return result; @@ -64,12 +68,6 @@ OsmElement MakeAreaWithPlaceNode(uint64_t id, uint64_t placeId, std::string cons return area; } -bool HasRelationWithId(std::vector const & fbs, uint64_t id) { - return std::find_if(std::begin(fbs), std::end(fbs), [&](auto const & fb) { - return fb.GetMostGenericOsmId() == base::MakeOsmRelation(id); - }) != std::end(fbs); -}; - auto const placeRelation1 = MakeOsmElement(1 /* id */, {{"place", "city"}}, OsmElement::EntityType::Relation); auto const placeRelation2 = MakeOsmElement(2 /* id */, {{"place", "town"}}, OsmElement::EntityType::Relation); auto const placeRelation3 = MakeOsmElement(3 /* id */, {{"place", "village"}}, OsmElement::EntityType::Relation); @@ -85,34 +83,76 @@ auto const relationWithLabel2 = MakeAreaWithPlaceNode(6 /* id */, 10 /* placeId auto const relationWithLabel3 = MakeAreaWithPlaceNode(7 /* id */, 11 /* placeId */, "label" /* role */); auto const relationWithLabel4 = MakeAreaWithPlaceNode(8 /* id */, 12 /* placeId */, "country" /* role */); -void Collect(BoundariesCollector & collector, std::vector const & elements) +void Collect(BoundariesCollector & collector, std::vector const & elements, + std::vector> const & geometries = {}) { - for (auto const & element : elements) + for (size_t i = 0; i < elements.size(); ++i) { + auto const & element = elements[i]; auto featureBuilder = element.IsNode() ? MakeNodeFeatureBuilder(element) - : MakeAreaFeatureBuilder(element); + : MakeAreaFeatureBuilder(element, geometries[i]); collector.Process(featureBuilder, element); } } void Collect(std::shared_ptr & collector, - std::vector const & elements) + std::vector const & elements, + std::vector> const & geometries = {}) { auto boundariesCollector = dynamic_cast(collector.get()); - Collect(*boundariesCollector, elements); + Collect(*boundariesCollector, elements, geometries); } -void Check(std::string const & filename) +std::vector> ReadBoundaries(std::string const & dumpFilename) +{ + FileReader reader(dumpFilename); + ReaderSource src(reader); + + std::vector> result; + std::vector boundary; + while (src.Size() > 0) + { + rw::ReadVectorOfPOD(src, boundary); + result.emplace_back(std::move(boundary)); + } + return result; +} + +bool CheckPolygonExistance(std::vector> const & polygons, + std::vector const & polygonToFind) +{ + for (auto const & polygon : polygons) + { + bool same = true; + if (polygon.size() != polygonToFind.size()) + continue; + + for (size_t i = 0; i < polygon.size(); ++i) + { + if (!base::AlmostEqualAbs(polygon[i], polygonToFind[i], 1e-6)) + { + same = false; + break; + } + } + + if (same) + return true; + } + + return false; +} + +void Check(std::string const & filename, std::string const & dumpFilename) { using Writer = RoutingCityBoundariesWriter; - auto const featuresFileName = Writer::GetBoundariesFilename(filename); + auto const boundaries = ReadBoundaries(dumpFilename); - auto const fbs = ReadAllDatRawFormat(featuresFileName); - TEST(HasRelationWithId(fbs, 1), ()); - TEST(HasRelationWithId(fbs, 2), ()); - TEST(HasRelationWithId(fbs, 3), ()); - TEST(!HasRelationWithId(fbs, 4), ()); + TEST(CheckPolygonExistance(boundaries, kPolygon1), ()); + TEST(CheckPolygonExistance(boundaries, kPolygon2), ()); + TEST(CheckPolygonExistance(boundaries, kPolygon3), ()); + TEST(!CheckPolygonExistance(boundaries, kPolygon4), ()); auto const nodeToBoundaryFilename = Writer::GetNodeToBoundariesFilename(filename); auto nodeToBoundary = routing_city_boundaries::LoadNodeToBoundariesData(nodeToBoundaryFilename); @@ -121,13 +161,9 @@ void Check(std::string const & filename) TEST(nodeToBoundary.count(11), ()); TEST(!nodeToBoundary.count(12), ()); - auto const truePolygon = GetFeatureBuilderGeometry(); - for (size_t id = 9; id <= 11; ++id) - { - auto const & geometryFromFile = nodeToBoundary[id].back().GetOuterGeometry(); - for (size_t i = 0; i < geometryFromFile.size(); ++i) - TEST_ALMOST_EQUAL_ABS(geometryFromFile[i], truePolygon[i], 1e-6, ()); - } + TEST(CheckPolygonExistance({nodeToBoundary[9].back().GetOuterGeometry()}, kPolygon1), ()); + TEST(CheckPolygonExistance({nodeToBoundary[10].back().GetOuterGeometry()}, kPolygon2), ()); + TEST(CheckPolygonExistance({nodeToBoundary[11].back().GetOuterGeometry()}, kPolygon3), ()); auto const nodeToLocalityFilename = Writer::GetNodeToLocalityDataFilename(filename); auto nodeToLocality = routing_city_boundaries::LoadNodeToLocalityData(nodeToLocalityFilename); @@ -170,34 +206,38 @@ UNIT_CLASS_TEST(TestWithClassificator, CollectorRoutingCityBoundaries_1) { auto const filename = generator_tests::GetFileName(); SCOPE_GUARD(_, std::bind(Platform::RemoveFileIfExists, std::cref(filename))); + SCOPE_GUARD(rmDump, std::bind(Platform::RemoveFileIfExists, std::cref(kDumpFileName))); std::shared_ptr cache; - auto c1 = std::make_shared(filename, cache); + auto c1 = std::make_shared(filename, kDumpFileName, cache); - Collect(*c1, {placeRelation1, placeRelation2, placeRelation3, placeRelation4}); - Collect(*c1, {relationWithLabel1, relationWithLabel2, relationWithLabel3, relationWithLabel4}); + Collect(*c1, {placeRelation1, placeRelation2, placeRelation3, placeRelation4}, + {kPolygon1, kPolygon2, kPolygon3, kPolygon4}); + Collect(*c1, {relationWithLabel1, relationWithLabel2, relationWithLabel3, relationWithLabel4}, + {kPolygon1, kPolygon2, kPolygon3, kPolygon4}); Collect(*c1, {placeNode1, placeNode2, placeNode3, placeNode4}); c1->Finish(); c1->Save(); - Check(filename); + Check(filename, kDumpFileName); } UNIT_CLASS_TEST(TestWithClassificator, CollectorRoutingCityBoundaries_2) { auto const filename = generator_tests::GetFileName(); SCOPE_GUARD(_, std::bind(Platform::RemoveFileIfExists, std::cref(filename))); + SCOPE_GUARD(rmDump, std::bind(Platform::RemoveFileIfExists, std::cref(kDumpFileName))); std::shared_ptr cache; - auto c1 = std::make_shared(filename, cache); + auto c1 = std::make_shared(filename, kDumpFileName, cache); auto c2 = c1->Clone(); - Collect(*c1, {placeRelation1, placeRelation2}); - Collect(c2, {placeRelation3, placeRelation4}); + Collect(*c1, {placeRelation1, placeRelation2}, {kPolygon1, kPolygon2}); + Collect(c2, {placeRelation3, placeRelation4}, {kPolygon3, kPolygon4}); - Collect(*c1, {relationWithLabel1, relationWithLabel2}); - Collect(c2, {relationWithLabel3, relationWithLabel4}); + Collect(*c1, {relationWithLabel1, relationWithLabel2}, {kPolygon1, kPolygon2}); + Collect(c2, {relationWithLabel3, relationWithLabel4}, {kPolygon3, kPolygon4}); Collect(*c1, {placeNode1, placeNode2}); Collect(c2, {placeNode3, placeNode4}); @@ -207,7 +247,7 @@ UNIT_CLASS_TEST(TestWithClassificator, CollectorRoutingCityBoundaries_2) c1->Merge(*c2); c1->Save(); - Check(filename); + Check(filename, kDumpFileName); } UNIT_TEST(AreaOnEarth_Convex_Polygon_1) @@ -287,4 +327,3 @@ UNIT_TEST(AreaOnEarth_Concave_Polygon) areaOnEarth, 1e-6), ()); } - diff --git a/generator/raw_generator.cpp b/generator/raw_generator.cpp index 4816b548a0..f25906dbc7 100644 --- a/generator/raw_generator.cpp +++ b/generator/raw_generator.cpp @@ -121,7 +121,7 @@ RawGenerator::FinalProcessorPtr RawGenerator::CreateCountryFinalProcessor(bool a } finalProcessor->DumpCitiesBoundaries(m_genInfo.m_citiesBoundariesFilename); - finalProcessor->DumpRoutingCitiesBoundariesFilename( + finalProcessor->DumpRoutingCitiesBoundaries( m_genInfo.GetIntermediateFileName(ROUTING_CITY_BOUNDARIES_TMP_FILENAME), m_genInfo.GetIntermediateFileName(ROUTING_CITY_BOUNDARIES_DUMP_FILENAME)); return finalProcessor; diff --git a/generator/routing_city_boundaries_processor.cpp b/generator/routing_city_boundaries_processor.cpp index d4cc2e3a36..01212c65a1 100644 --- a/generator/routing_city_boundaries_processor.cpp +++ b/generator/routing_city_boundaries_processor.cpp @@ -20,7 +20,7 @@ #include "3party/boost/boost/geometry/geometries/polygon.hpp" #include -#include +#include #include #include @@ -115,17 +115,6 @@ std::pair GetBoundaryWithSmallestArea( return {boundaries[bestIndex], minArea}; } - -void TransformPointToCircle(feature::FeatureBuilder & feature, m2::PointD const & center, - double radiusMeters) -{ - auto circleGeometry = ms::CreateCircleGeometryOnEarth(mercator::ToLatLon(center), radiusMeters, - 30.0 /* angleStepDegree */); - - feature.SetArea(); - feature.ResetGeometry(); - feature.AddPolygon(circleGeometry); -} } // routing_city_boundaries } // namespace generator @@ -133,83 +122,63 @@ namespace generator { using namespace routing_city_boundaries; -RoutingCityBoundariesProcessor::RoutingCityBoundariesProcessor(std::string filename) - : m_filename(std::move(filename)) +RoutingCityBoundariesProcessor::RoutingCityBoundariesProcessor(std::string tmpFilename, + std::string dumpFilename) + : m_tmpFilename(std::move(tmpFilename)) + , m_dumpFilename(std::move(dumpFilename)) { } void RoutingCityBoundariesProcessor::ProcessDataFromCollector() { - auto nodeOsmIdToLocalityData = LoadNodeToLocalityData( - RoutingCityBoundariesWriter::GetNodeToLocalityDataFilename(m_filename)); + auto const nodeOsmIdToLocalityData = LoadNodeToLocalityData( + RoutingCityBoundariesWriter::GetNodeToLocalityDataFilename(m_tmpFilename)); auto const nodeOsmIdToBoundaries = LoadNodeToBoundariesData( - RoutingCityBoundariesWriter::GetNodeToBoundariesFilename(m_filename)); + RoutingCityBoundariesWriter::GetNodeToBoundariesFilename(m_tmpFilename)); - FileWriter boundariesWriter(RoutingCityBoundariesWriter::GetBoundariesFilename(m_filename), - FileWriter::Op::OP_APPEND); + FileWriter boundariesWriter(m_dumpFilename, FileWriter::Op::OP_APPEND); uint32_t pointToCircle = 0; uint32_t matchedBoundary = 0; - for (auto const & item : nodeOsmIdToBoundaries) + for (auto const & item : nodeOsmIdToLocalityData) { uint64_t const nodeOsmId = item.first; - auto const & boundaries = item.second; - auto const it = nodeOsmIdToLocalityData.find(nodeOsmId); - if (it == nodeOsmIdToLocalityData.cend()) - continue; - - auto const & localityData = it->second; + auto const & localityData = item.second; if (localityData.m_population == 0) continue; - double bestFeatureBuilderArea = 0.0; - feature::FeatureBuilder bestFeatureBuilder; - std::tie(bestFeatureBuilder, bestFeatureBuilderArea) = GetBoundaryWithSmallestArea(boundaries); - double const radiusMeters = ftypes::GetRadiusByPopulationForRouting(localityData.m_population, localityData.m_place); double const areaUpperBound = ms::CircleAreaOnEarth(radiusMeters); - if (bestFeatureBuilderArea > areaUpperBound) - { - ++pointToCircle; - TransformPointToCircle(bestFeatureBuilder, localityData.m_position, radiusMeters); - } - else - { - ++matchedBoundary; - } - - rw::WriteVectorOfPOD(boundariesWriter, bestFeatureBuilder.GetOuterGeometry()); - nodeOsmIdToLocalityData.erase(it); - } - - for (auto const & item : nodeOsmIdToLocalityData) - { - auto const & localityWithoutBoundary = item.second; - if (localityWithoutBoundary.m_population == 0) - continue; - - double const radiusMeters = - ftypes::GetRadiusByPopulationForRouting(localityWithoutBoundary.m_population, - localityWithoutBoundary.m_place); - feature::FeatureBuilder feature; - TransformPointToCircle(feature, localityWithoutBoundary.m_position, radiusMeters); - ++pointToCircle; - rw::WriteVectorOfPOD(boundariesWriter, feature.GetOuterGeometry()); + auto const boundariesIt = nodeOsmIdToBoundaries.find(nodeOsmId); + if (boundariesIt != nodeOsmIdToBoundaries.cend()) + { + auto const & boundaries = boundariesIt->second; + double bestFeatureBuilderArea = 0.0; + std::tie(feature, bestFeatureBuilderArea) = GetBoundaryWithSmallestArea(boundaries); + + if (bestFeatureBuilderArea <= areaUpperBound) + { + ++matchedBoundary; + rw::WriteVectorOfPOD(boundariesWriter, feature.GetOuterGeometry()); + continue; + } + } + + auto const circleGeometry = ms::CreateCircleGeometryOnEarth( + mercator::ToLatLon(localityData.m_position), radiusMeters, 30.0 /* angleStepDegree */); + + ++pointToCircle; + rw::WriteVectorOfPOD(boundariesWriter, circleGeometry); } LOG(LINFO, (pointToCircle, "places were transformed to circle.")); LOG(LINFO, (matchedBoundary, "boundaries were approved as city/town/village boundary.")); } - -void RoutingCityBoundariesProcessor::DumpBoundaries(std::string const & dumpFilename) -{ - base::CopyFileX(RoutingCityBoundariesWriter::GetBoundariesFilename(m_filename), dumpFilename); -} } // namespace generator diff --git a/generator/routing_city_boundaries_processor.hpp b/generator/routing_city_boundaries_processor.hpp index bb5c6db59f..6d9e6c295e 100644 --- a/generator/routing_city_boundaries_processor.hpp +++ b/generator/routing_city_boundaries_processor.hpp @@ -25,13 +25,12 @@ double AreaOnEarth(std::vector const & points); class RoutingCityBoundariesProcessor { public: - explicit RoutingCityBoundariesProcessor(std::string filename); + RoutingCityBoundariesProcessor(std::string tmpFilename, std::string dumpFilename); void ProcessDataFromCollector(); - void DumpBoundaries(std::string const & dumpFilename); private: - std::string m_filename; + std::string m_tmpFilename; + std::string m_dumpFilename; }; } // namespace generator - diff --git a/generator/translator_country.cpp b/generator/translator_country.cpp index 37c763feb7..61de3cc6e4 100644 --- a/generator/translator_country.cpp +++ b/generator/translator_country.cpp @@ -107,7 +107,8 @@ TranslatorCountry::TranslatorCountry(std::shared_ptr std::make_shared(info.GetIntermediateFileName(CITIES_AREAS_TMP_FILENAME))); // Collectors for gathering of additional information for the future building of routing section. collectors->Append(std::make_shared( - info.GetIntermediateFileName(ROUTING_CITY_BOUNDARIES_TMP_FILENAME), cache->GetCache())); + info.GetIntermediateFileName(ROUTING_CITY_BOUNDARIES_TMP_FILENAME), + info.GetIntermediateFileName(ROUTING_CITY_BOUNDARIES_DUMP_FILENAME), cache->GetCache())); collectors->Append( std::make_shared(info.GetIntermediateFileName(MAXSPEEDS_FILENAME))); collectors->Append(std::make_shared( diff --git a/routing/routing_helpers.hpp b/routing/routing_helpers.hpp index d72d3eaecc..5e8b14ece3 100644 --- a/routing/routing_helpers.hpp +++ b/routing/routing_helpers.hpp @@ -32,12 +32,18 @@ bool IsCarRoad(Types const & types) return CarModel::AllLimitsInstance().HasRoadType(types); } +template +bool IsBicycleRoad(Types const & types) +{ + return BicycleModel::AllLimitsInstance().HasRoadType(types); +} + /// \returns true when there exists a routing mode where the feature with |types| can be used. template bool IsRoad(Types const & types) { return IsCarRoad(types) || PedestrianModel::AllLimitsInstance().HasRoadType(types) || - BicycleModel::AllLimitsInstance().HasRoadType(types); + IsBicycleRoad(types); } void FillSegmentInfo(std::vector const & segments, std::vector const & junctions,