diff --git a/editor/editor_tests/osm_editor_test.hpp b/editor/editor_tests/osm_editor_test.hpp index a0c7829bd5..724eb8241a 100644 --- a/editor/editor_tests/osm_editor_test.hpp +++ b/editor/editor_tests/osm_editor_test.hpp @@ -69,7 +69,7 @@ private: auto const & info = id.GetInfo(); if (info) - m_infoGetter.AddCountry(storage::CountryDef(name, info->m_limitRect)); + m_infoGetter.AddCountry(storage::CountryDef(name, info->m_bordersRect)); CHECK(id.IsAlive(), ()); diff --git a/editor/osm_editor.cpp b/editor/osm_editor.cpp index f6a5421727..544eedb6bf 100644 --- a/editor/osm_editor.cpp +++ b/editor/osm_editor.cpp @@ -1004,7 +1004,7 @@ FeatureID Editor::GenerateNewFeatureId(MwmSet::MwmId const & id) const bool Editor::CreatePoint(uint32_t type, m2::PointD const & mercator, MwmSet::MwmId const & id, EditableMapObject & outFeature) { ASSERT(id.IsAlive(), ("Please check that feature is created in valid MWM file before calling this method.")); - if (!id.GetInfo()->m_limitRect.IsPointInside(mercator)) + if (!id.GetInfo()->m_bordersRect.IsPointInside(mercator)) { LOG(LERROR, ("Attempt to create a feature outside of the MWM's bounding box.")); return false; diff --git a/generator/borders_loader.cpp b/generator/borders_loader.cpp index dd4207838f..7daa361981 100644 --- a/generator/borders_loader.cpp +++ b/generator/borders_loader.cpp @@ -196,4 +196,15 @@ void UnpackBorders(std::string const & baseDir, std::string const & targetDir) } } +m2::RectD GetLimitRect(std::string const & baseDir, std::string const & country) +{ + std::string const bordersFile = my::JoinPath(baseDir, BORDERS_DIR, country + BORDERS_EXTENSION); + CHECK(Platform::IsFileExistsByFullPath(bordersFile), ("Cannot read borders file", bordersFile)); + std::vector borders; + CHECK(osm::LoadBorders(bordersFile, borders), ()); + m2::RectD rect; + for (auto const & border : borders) + rect.Add(border.GetRect()); + return rect; +} } // namespace borders diff --git a/generator/borders_loader.hpp b/generator/borders_loader.hpp index e2f9b11e33..03bfc8d487 100644 --- a/generator/borders_loader.hpp +++ b/generator/borders_loader.hpp @@ -1,5 +1,6 @@ #pragma once +#include "geometry/rect2d.hpp" #include "geometry/region2d.hpp" #include "geometry/tree4d.hpp" @@ -36,4 +37,5 @@ namespace borders void GeneratePackedBorders(std::string const & baseDir); void UnpackBorders(std::string const & baseDir, std::string const & targetDir); + m2::RectD GetLimitRect(std::string const & baseDir, std::string const & country); } diff --git a/generator/feature_sorter.cpp b/generator/feature_sorter.cpp index 86f2422869..e70ce3e305 100644 --- a/generator/feature_sorter.cpp +++ b/generator/feature_sorter.cpp @@ -1,5 +1,6 @@ #include "generator/feature_sorter.hpp" +#include "generator/borders_loader.hpp" #include "generator/feature_builder.hpp" #include "generator/feature_generator.hpp" #include "generator/gen_mwm_info.hpp" @@ -198,6 +199,8 @@ private: bool IsCountry() const { return m_header.GetType() == feature::DataHeader::country; } public: + void SetBounds(m2::RectD bounds) { m_bounds = bounds; } + uint32_t operator()(FeatureBuilder2 & fb) { GeometryHolder holder([this](int i) -> FileWriter & { return *m_geoFile[i]; }, @@ -371,6 +374,10 @@ bool GenerateFinalFeatures(feature::GenerateInfo const & info, string const & na collector(GetFeatureBuilder2(f)); } + // Update bounds with the limit rect corresponding to region borders. + // Bounds before update can be too big because of big invisible features like a + // relation that contains an entire country's border. + collector.SetBounds(borders::GetLimitRect(info.m_targetDir, name)); collector.Finish(); } catch (RootException const & ex) diff --git a/indexer/data_header.hpp b/indexer/data_header.hpp index 7bcd036399..ea56e5926b 100644 --- a/indexer/data_header.hpp +++ b/indexer/data_header.hpp @@ -25,6 +25,7 @@ namespace feature private: serial::GeometryCodingParams m_codingParams; + // Rect around region border. Features which cross region border may cross this rect. pair m_bounds; buffer_vector m_scales; diff --git a/indexer/data_source.cpp b/indexer/data_source.cpp index 7d26184a60..f7a65da761 100644 --- a/indexer/data_source.cpp +++ b/indexer/data_source.cpp @@ -158,7 +158,7 @@ unique_ptr DataSource::CreateInfo(platform::LocalCountryFile const & lo return nullptr; auto info = make_unique(); - info->m_limitRect = h.GetBounds(); + info->m_bordersRect = h.GetBounds(); pair const scaleR = h.GetScaleRange(); info->m_minScale = static_cast(scaleR.first); @@ -201,7 +201,7 @@ void DataSource::ForEachInIntervals(ReaderCallback const & fn, covering::Coverin for (shared_ptr const & info : mwms) { if (info->m_minScale <= scale && scale <= info->m_maxScale && - rect.IsIntersect(info->m_limitRect)) + rect.IsIntersect(info->m_bordersRect)) { MwmId const mwmId(info); switch (info->GetType()) diff --git a/indexer/indexer_tests/test_mwm_set.hpp b/indexer/indexer_tests/test_mwm_set.hpp index 4835730091..599f507555 100644 --- a/indexer/indexer_tests/test_mwm_set.hpp +++ b/indexer/indexer_tests/test_mwm_set.hpp @@ -21,7 +21,7 @@ protected: int const n = localFile.GetCountryName()[0] - '0'; unique_ptr info(new MwmInfo()); info->m_maxScale = n; - info->m_limitRect = m2::RectD(0, 0, 1, 1); + info->m_bordersRect = m2::RectD(0, 0, 1, 1); info->m_version.SetFormat(version::Format::lastFormat); return info; } diff --git a/indexer/mwm_set.hpp b/indexer/mwm_set.hpp index 62d708734f..2fa3a86f8d 100644 --- a/indexer/mwm_set.hpp +++ b/indexer/mwm_set.hpp @@ -49,7 +49,8 @@ public: MwmInfo(); virtual ~MwmInfo() = default; - m2::RectD m_limitRect; ///< Limit rect of mwm. + m2::RectD m_bordersRect; ///< Rect around region border. Features which cross region border may + ///< cross this rect. uint8_t m_minScale; ///< Min zoom level of mwm. uint8_t m_maxScale; ///< Max zoom level of mwm. version::MwmVersion m_version; ///< Mwm file version. diff --git a/map/benchmark_tool/features_loading.cpp b/map/benchmark_tool/features_loading.cpp index ddb1c952a6..36d38c5775 100644 --- a/map/benchmark_tool/features_loading.cpp +++ b/map/benchmark_tool/features_loading.cpp @@ -120,7 +120,7 @@ void RunFeaturesLoadingBenchmark(string const & file, pair scaleRange, if (scaleRange.first > scaleRange.second) return; - RunBenchmark(src, r.first.GetInfo()->m_limitRect, scaleRange, res); + RunBenchmark(src, r.first.GetInfo()->m_bordersRect, scaleRange, res); } } diff --git a/map/feature_vec_model.cpp b/map/feature_vec_model.cpp index d265a178a3..d4374697dd 100644 --- a/map/feature_vec_model.cpp +++ b/map/feature_vec_model.cpp @@ -57,7 +57,7 @@ pair FeaturesFetcher::RegisterMap( { MwmSet::MwmId const & id = result.first; ASSERT(id.IsAlive(), ()); - m_rect.Add(id.GetInfo()->m_limitRect); + m_rect.Add(id.GetInfo()->m_bordersRect); } return result; diff --git a/map/framework.cpp b/map/framework.cpp index 61cedb1282..9039f3cdaa 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -580,7 +580,7 @@ void Framework::OnCountryFileDownloaded(storage::TCountryId const & countryId, s auto p = m_model.RegisterMap(*localFile); MwmSet::MwmId const & id = p.first; if (id.IsAlive()) - rect = id.GetInfo()->m_limitRect; + rect = id.GetInfo()->m_bordersRect; } m_trafficManager.Invalidate(); m_transitManager.Invalidate(); diff --git a/map/map_tests/booking_filter_test.cpp b/map/map_tests/booking_filter_test.cpp index 8664127383..b995d9c5bc 100644 --- a/map/map_tests/booking_filter_test.cpp +++ b/map/map_tests/booking_filter_test.cpp @@ -46,7 +46,7 @@ protected: void OnMwmBuilt(MwmInfo const & info) override { - m_infoGetter.AddCountry(storage::CountryDef(info.GetCountryName(), info.m_limitRect)); + m_infoGetter.AddCountry(storage::CountryDef(info.GetCountryName(), info.m_bordersRect)); } private: diff --git a/routing/routing_tests/road_graph_builder.cpp b/routing/routing_tests/road_graph_builder.cpp index 37e6ce9fd0..7e3ceb1ad8 100644 --- a/routing/routing_tests/road_graph_builder.cpp +++ b/routing/routing_tests/road_graph_builder.cpp @@ -45,7 +45,7 @@ private: { unique_ptr info(new MwmInfo()); info->m_maxScale = 1; - info->m_limitRect = m2::RectD(0, 0, 1, 1); + info->m_bordersRect = m2::RectD(0, 0, 1, 1); info->m_version.SetFormat(version::Format::lastFormat); return info; } diff --git a/search/geocoder.cpp b/search/geocoder.cpp index b1d0a7cf91..913c2e7a73 100644 --- a/search/geocoder.cpp +++ b/search/geocoder.cpp @@ -284,7 +284,7 @@ struct KeyedMwmInfo { KeyedMwmInfo(shared_ptr const & info, m2::RectD const & pivot) : m_info(info) { - auto const & rect = m_info->m_limitRect; + auto const & rect = m_info->m_bordersRect; m_similarity = GetSimilarity(pivot, rect); m_distance = GetDistanceMeters(pivot.Center(), rect); } @@ -325,9 +325,8 @@ size_t OrderCountries(m2::RectD const & pivot, vector> & inf for (auto const & info : keyedInfos) infos.emplace_back(info.m_info); - auto intersects = [&](shared_ptr const & info) -> bool - { - return pivot.IsIntersect(info->m_limitRect); + auto intersects = [&](shared_ptr const & info) -> bool { + return pivot.IsIntersect(info->m_bordersRect); }; auto const sep = stable_partition(infos.begin(), infos.end(), intersects); @@ -427,10 +426,9 @@ void Geocoder::GoInViewport() vector> infos; m_dataSource.GetMwmsInfo(infos); - my::EraseIf(infos, [this](shared_ptr const & info) - { - return !m_params.m_pivot.IsIntersect(info->m_limitRect); - }); + my::EraseIf(infos, [this](shared_ptr const & info) { + return !m_params.m_pivot.IsIntersect(info->m_bordersRect); + }); GoImpl(infos, true /* inViewport */); } diff --git a/search/locality_finder.cpp b/search/locality_finder.cpp index 9da35b437b..8f9f0d932f 100644 --- a/search/locality_finder.cpp +++ b/search/locality_finder.cpp @@ -286,12 +286,8 @@ void LocalityFinder::UpdateMaps() switch (info->GetType()) { - case MwmInfo::WORLD: - m_worldId = id; - break; - case MwmInfo::COUNTRY: - m_maps.Add(id, info->m_limitRect); - break; + case MwmInfo::WORLD: m_worldId = id; break; + case MwmInfo::COUNTRY: m_maps.Add(id, info->m_bordersRect); break; case MwmInfo::COASTS: break; } } diff --git a/search/nested_rects_cache.cpp b/search/nested_rects_cache.cpp index 5ac54d9a21..6e5b87fe5a 100644 --- a/search/nested_rects_cache.cpp +++ b/search/nested_rects_cache.cpp @@ -56,7 +56,7 @@ double NestedRectsCache::GetDistanceToFeatureMeters(FeatureID const & id) const if (auto const & info = id.m_mwmId.GetInfo()) { - auto const & rect = info->m_limitRect; + auto const & rect = info->m_bordersRect; return max(MercatorBounds::DistanceOnEarth(rect.Center(), m_position), GetRadiusMeters(static_cast(scale))); } diff --git a/search/search_tests/locality_finder_test.cpp b/search/search_tests/locality_finder_test.cpp index 1d2383da4e..4b805918a8 100644 --- a/search/search_tests/locality_finder_test.cpp +++ b/search/search_tests/locality_finder_test.cpp @@ -47,7 +47,7 @@ public: MwmSet::MwmId const & id = p.first; TEST(id.IsAlive(), ()); - m_worldRect = id.GetInfo()->m_limitRect; + m_worldRect = id.GetInfo()->m_bordersRect; m_boundariesTable.Load(); } catch (RootException const & ex) diff --git a/search/search_tests_support/helpers.cpp b/search/search_tests_support/helpers.cpp index 3816f3650e..ed34586d5c 100644 --- a/search/search_tests_support/helpers.cpp +++ b/search/search_tests_support/helpers.cpp @@ -93,7 +93,7 @@ void SearchTest::OnMwmBuilt(MwmInfo const & info) { switch (info.GetType()) { - case MwmInfo::COUNTRY: RegisterCountry(info.GetCountryName(), info.m_limitRect); break; + case MwmInfo::COUNTRY: RegisterCountry(info.GetCountryName(), info.m_bordersRect); break; case MwmInfo::WORLD: m_engine.LoadCitiesBoundaries(); break; case MwmInfo::COASTS: break; } diff --git a/ugc/ugc_tests/storage_tests.cpp b/ugc/ugc_tests/storage_tests.cpp index 475ba41e48..69029f7175 100644 --- a/ugc/ugc_tests/storage_tests.cpp +++ b/ugc/ugc_tests/storage_tests.cpp @@ -133,7 +133,7 @@ private: auto const & info = id.GetInfo(); if (info) - m_infoGetter.AddCountry(storage::CountryDef(kTestMwmName, info->m_limitRect)); + m_infoGetter.AddCountry(storage::CountryDef(kTestMwmName, info->m_bordersRect)); CHECK(id.IsAlive(), ()); return id;