From 57dfbf64f5821c5818e6a715112e37fc94d891c0 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Wed, 12 Apr 2017 16:16:03 +0300 Subject: [PATCH] Using osm id for twin calculation in case of all neighboring mwm with cross_mwm section. --- map/framework.cpp | 15 +++++-- routing/car_router.hpp | 2 + routing/cross_mwm_graph.cpp | 44 ++++++++++++++++--- routing/cross_mwm_graph.hpp | 22 +++++++++- routing/cross_mwm_index_graph.cpp | 20 +++++++++ routing/cross_mwm_index_graph.hpp | 6 +++ routing/index_router.cpp | 28 ++++++++---- routing/index_router.hpp | 17 +++++-- routing/router.hpp | 2 + .../routing_test_tools.cpp | 13 +++++- routing/world_graph.cpp | 3 +- routing/world_graph.hpp | 5 ++- 12 files changed, 149 insertions(+), 28 deletions(-) diff --git a/map/framework.cpp b/map/framework.cpp index 1d48ca1c7b..b51bc9832d 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2660,6 +2660,11 @@ void Framework::SetRouterImpl(RouterType type) return m_infoGetter->GetRegionCountryId(p); }; + auto getMwmRectByName = [this](string const & countryId) -> m2::RectD + { + return m_infoGetter->GetLimitRectForLeaf(countryId); + }; + if (type == RouterType::Pedestrian) { router = CreatePedestrianAStarBidirectionalRouter(m_model.GetIndex(), countryFileGetter); @@ -2681,12 +2686,14 @@ void Framework::SetRouterImpl(RouterType type) m_storage.ForEachCountryFile( [&](platform::CountryFile const & file) { numMwmIds->RegisterFile(file); }); - // TODO: pass numMwmTree to router. - // auto numMwmTree = MakeNumMwmTree(*numMwmIds, *m_infoGetter); - router.reset( new CarRouter(m_model.GetIndex(), countryFileGetter, - IndexRouter::CreateCarRouter(countryFileGetter, numMwmIds, m_routingSession, m_model.GetIndex()))); + IndexRouter::CreateCarRouter(countryFileGetter, + getMwmRectByName, + numMwmIds, + MakeNumMwmTree(*numMwmIds, *m_infoGetter), + m_routingSession, + m_model.GetIndex()))); fetcher.reset(new OnlineAbsentCountriesFetcher(countryFileGetter, localFileChecker)); m_routingSession.SetRoutingSettings(routing::GetCarRoutingSettings()); } diff --git a/routing/car_router.hpp b/routing/car_router.hpp index d32fc9252a..6e7e0fdbc7 100644 --- a/routing/car_router.hpp +++ b/routing/car_router.hpp @@ -7,6 +7,8 @@ #include "routing/router.hpp" #include "routing/routing_mapping.hpp" +#include "geometry/tree4d.hpp" + #include "std/unique_ptr.hpp" #include "std/vector.hpp" diff --git a/routing/cross_mwm_graph.cpp b/routing/cross_mwm_graph.cpp index 94a085996a..8a4ccb933a 100644 --- a/routing/cross_mwm_graph.cpp +++ b/routing/cross_mwm_graph.cpp @@ -43,12 +43,17 @@ void CrossMwmGraph::ClosestSegment::Update(double distM, Segment const & bestSeg } // CrossMwmGraph ---------------------------------------------------------------------------------- -CrossMwmGraph::CrossMwmGraph(Index & index, shared_ptr numMwmIds, +CrossMwmGraph::CrossMwmGraph(shared_ptr numMwmIds, + m4::Tree const & numMwmTree, shared_ptr vehicleModelFactory, + CourntryRectFn const & countryRectFn, + Index & index, RoutingIndexManager & indexManager) : m_index(index) , m_numMwmIds(numMwmIds) + , m_numMwmTree(numMwmTree) , m_vehicleModelFactory(vehicleModelFactory) + , m_countryRectFn(countryRectFn) , m_crossMwmIndexGraph(index, numMwmIds) , m_crossMwmOsrmGraph(numMwmIds, indexManager) { @@ -101,6 +106,19 @@ void CrossMwmGraph::FindBestTwins(NumMwmId sMwmId, bool isOutgoing, FeatureType } } +bool CrossMwmGraph::AreAllNeighborsWithCrossMwmSection(NumMwmId numMwmId, std::vector & neighbors) +{ + m2::RectD const rect = m_countryRectFn(m_numMwmIds->GetFile(numMwmId).GetName()); + bool allNeighborsWithCrossMwmSection = true; + m_numMwmTree.ForEachInRect(rect, [&](NumMwmId id){ + if (allNeighborsWithCrossMwmSection && GetMwmStatus(id) == MwmStatus::NoCrossMwmSection) + allNeighborsWithCrossMwmSection = false; + neighbors.push_back(id); + }); + + return allNeighborsWithCrossMwmSection; +} + void CrossMwmGraph::GetTwins(Segment const & s, bool isOutgoing, vector & twins) { CHECK(IsTransition(s, isOutgoing), @@ -113,6 +131,13 @@ void CrossMwmGraph::GetTwins(Segment const & s, bool isOutgoing, vector twins.clear(); + vector neighbors; + if (AreAllNeighborsWithCrossMwmSection(s.GetMwmId(), neighbors)) + { + m_crossMwmIndexGraph.GetTwinsByOsmId(s, isOutgoing, neighbors, twins); + return; + } + // Note. The code below looks for twins based on geometry index. This code works for // any combination mwms with different cross mwm sections. // It's possible to implement a faster version for two special cases: @@ -170,18 +195,27 @@ TransitionPoints CrossMwmGraph::GetTransitionPoints(Segment const & s, bool isOu : m_crossMwmOsrmGraph.GetTransitionPoints(s, isOutgoing); } -bool CrossMwmGraph::CrossMwmSectionExists(NumMwmId numMwmId) +CrossMwmGraph::MwmStatus CrossMwmGraph::GetMwmStatus(NumMwmId numMwmId) { if (m_crossMwmIndexGraph.InCache(numMwmId)) - return true; + return MwmStatus::CrossMwmSectionExists; MwmSet::MwmHandle handle = m_index.GetMwmHandleByCountryFile(m_numMwmIds->GetFile(numMwmId)); if (!handle.IsAlive()) - MYTHROW(RoutingException, ("Mwm", m_numMwmIds->GetFile(numMwmId), "cannot be loaded.")); + return MwmStatus::NotLoaded; MwmValue * value = handle.GetValue(); CHECK(value != nullptr, ("Country file:", m_numMwmIds->GetFile(numMwmId))); - return value->m_cont.IsExist(CROSS_MWM_FILE_TAG); + return value->m_cont.IsExist(CROSS_MWM_FILE_TAG) ? MwmStatus::CrossMwmSectionExists : MwmStatus::NoCrossMwmSection; +} + +bool CrossMwmGraph::CrossMwmSectionExists(NumMwmId numMwmId) +{ + CrossMwmGraph::MwmStatus const status = GetMwmStatus(numMwmId); + if (status == MwmStatus::NotLoaded) + MYTHROW(RoutingException, ("Mwm", m_numMwmIds->GetFile(numMwmId), "cannot be loaded.")); + + return status == MwmStatus::CrossMwmSectionExists; } void CrossMwmGraph::GetTwinCandidates(FeatureType const & ft, bool isOutgoing, diff --git a/routing/cross_mwm_graph.hpp b/routing/cross_mwm_graph.hpp index 350a267a71..35f3e9434e 100644 --- a/routing/cross_mwm_graph.hpp +++ b/routing/cross_mwm_graph.hpp @@ -3,13 +3,14 @@ #include "routing/cross_mwm_index_graph.hpp" #include "routing/cross_mwm_osrm_graph.hpp" #include "routing/num_mwm_id.hpp" - #include "routing/segment.hpp" #include "routing_common/vehicle_model.hpp" #include "indexer/index.hpp" +#include "geometry/tree4d.hpp" + #include "base/math.hpp" #include @@ -22,8 +23,11 @@ namespace routing class CrossMwmGraph final { public: - CrossMwmGraph(Index & index, std::shared_ptr numMwmIds, + CrossMwmGraph(std::shared_ptr numMwmIds, + m4::Tree const & numMwmTree, std::shared_ptr vehicleModelFactory, + CourntryRectFn const & countryRectFn, + Index & index, RoutingIndexManager & indexManager); /// \brief Transition segment is a segment which is crossed by mwm border. That means @@ -80,6 +84,13 @@ public: void Clear(); private: + enum class MwmStatus + { + NotLoaded, + CrossMwmSectionExists, + NoCrossMwmSection, + }; + struct ClosestSegment { ClosestSegment(); @@ -98,6 +109,7 @@ private: /// one or very small in rare cases in OSRM. TransitionPoints GetTransitionPoints(Segment const & s, bool isOutgoing); + MwmStatus GetMwmStatus(NumMwmId numMwmId); bool CrossMwmSectionExists(NumMwmId numMwmId); /// \brief Fills |twins| with transition segments of feature |ft| of type |isOutgoing|. @@ -117,9 +129,15 @@ private: void FindBestTwins(NumMwmId sMwmId, bool isOutgoing, FeatureType const & ft, m2::PointD const & point, map & minDistSegs, vector & twins); + /// \brief Fills |neighbors| with number mwm id of all neighbors of |numMwmId| and returns true + /// if all the neighbors have cross_mwm section. + bool AreAllNeighborsWithCrossMwmSection(NumMwmId numMwmId, std::vector & neighbors); + Index & m_index; std::shared_ptr m_numMwmIds; + m4::Tree const & m_numMwmTree; std::shared_ptr m_vehicleModelFactory; + CourntryRectFn const & m_countryRectFn; CrossMwmIndexGraph m_crossMwmIndexGraph; CrossMwmOsrmGraph m_crossMwmOsrmGraph; }; diff --git a/routing/cross_mwm_index_graph.cpp b/routing/cross_mwm_index_graph.cpp index 9f92e01e59..8afe9e2b78 100644 --- a/routing/cross_mwm_index_graph.cpp +++ b/routing/cross_mwm_index_graph.cpp @@ -11,6 +11,26 @@ bool CrossMwmIndexGraph::IsTransition(Segment const & s, bool isOutgoing) return c.IsTransition(s, isOutgoing); } +void CrossMwmIndexGraph::GetTwinsByOsmId(Segment const & s, bool isOutgoing, + vector const & neighbors, vector & twins) +{ + uint64_t const osmId = GetCrossMwmConnectorWithTransitions(s.GetMwmId()).GetOsmId(s); + + for (NumMwmId const neighbor : neighbors) + { + auto const it = m_connectors.find(neighbor); + if (it == m_connectors.cend()) + continue; + + CrossMwmConnector const & connector = it->second; + Segment const * twinSeg = connector.GetTransition(osmId, s.GetSegmentIdx(), !isOutgoing); + if (twinSeg == nullptr) + continue; + + twins.push_back(*twinSeg); + } +} + void CrossMwmIndexGraph::GetEdgeList(Segment const & s, bool isOutgoing, vector & edges) { diff --git a/routing/cross_mwm_index_graph.hpp b/routing/cross_mwm_index_graph.hpp index 279dadc257..e992b2f186 100644 --- a/routing/cross_mwm_index_graph.hpp +++ b/routing/cross_mwm_index_graph.hpp @@ -31,6 +31,12 @@ public: } bool IsTransition(Segment const & s, bool isOutgoing); + /// \brief Fills |twins| based on transitions defined in cross_mwm section. + /// \note In cross_mwm section transitions are defined by osm ids of theirs features. + /// \note This method fills |twins| with all available twins iff all neighboring of mwm of |s| + // have cross_mwm section. + void GetTwinsByOsmId(Segment const & s, bool isOutgoing, std::vector const & neighbors, + std::vector & twins); void GetEdgeList(Segment const & s, bool isOutgoing, std::vector & edges); void Clear() { m_connectors.clear(); } TransitionPoints GetTransitionPoints(Segment const & s, bool isOutgoing); diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 565f97ca8a..3fcd2808ba 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -39,15 +39,22 @@ uint32_t constexpr kDrawPointsPeriod = 10; namespace routing { -IndexRouter::IndexRouter(string const & name, TCountryFileFn const & countryFileFn, - shared_ptr numMwmIds, shared_ptr trafficStash, +IndexRouter::IndexRouter(string const & name, + TCountryFileFn const & countryFileFn, + CourntryRectFn const & countryRectFn, + shared_ptr numMwmIds, + unique_ptr> numMwmTree, + shared_ptr trafficStash, shared_ptr vehicleModelFactory, shared_ptr estimator, - unique_ptr directionsEngine, Index & index) + unique_ptr directionsEngine, + Index & index) : m_name(name) , m_index(index) , m_countryFileFn(countryFileFn) + , m_countryRectFn(countryRectFn) , m_numMwmIds(numMwmIds) + , m_numMwmTree(move(numMwmTree)) , m_trafficStash(trafficStash) , m_indexManager(countryFileFn, m_index) , m_roadGraph(index, IRoadGraph::Mode::ObeyOnewayTag, vehicleModelFactory) @@ -109,6 +116,7 @@ IRouter::ResultCode IndexRouter::DoCalculateRoute(string const & startCountry, m2::PointD const & finalPoint, RouterDelegate const & delegate, Route & route) { + CHECK(m_numMwmTree, ()); auto const startFile = platform::CountryFile(startCountry); auto const finishFile = platform::CountryFile(finishCountry); @@ -128,10 +136,10 @@ IRouter::ResultCode IndexRouter::DoCalculateRoute(string const & startCountry, finishEdge.GetSegId(), finalPoint); TrafficStash::Guard guard(*m_trafficStash); - WorldGraph graph( - make_unique(m_index, m_numMwmIds, m_vehicleModelFactory, m_indexManager), - IndexGraphLoader::Create(m_numMwmIds, m_vehicleModelFactory, m_estimator, m_index), - m_estimator); + WorldGraph graph(make_unique(m_numMwmIds, *m_numMwmTree, m_vehicleModelFactory, m_countryRectFn, + m_index, m_indexManager), + IndexGraphLoader::Create(m_numMwmIds, m_vehicleModelFactory, m_estimator, m_index), + m_estimator); graph.SetMode(forSingleMwm ? WorldGraph::Mode::SingleMwm : WorldGraph::Mode::WorldWithLeaps); IndexGraphStarter starter(start, finish, graph); @@ -315,7 +323,9 @@ bool IndexRouter::RedressRoute(vector const & segments, RouterDelegate // static unique_ptr IndexRouter::CreateCarRouter(TCountryFileFn const & countryFileFn, + CourntryRectFn const & coutryRectFn, shared_ptr numMwmIds, + unique_ptr> numMwmTree, traffic::TrafficCache const & trafficCache, Index & index) { @@ -337,8 +347,8 @@ unique_ptr IndexRouter::CreateCarRouter(TCountryFileFn const & coun auto estimator = EdgeEstimator::CreateForCar(trafficStash, maxSpeed); auto router = - make_unique("astar-bidirectional-car", countryFileFn, numMwmIds, trafficStash, - vehicleModelFactory, estimator, move(directionsEngine), index); + make_unique("astar-bidirectional-car", countryFileFn, coutryRectFn, numMwmIds, move(numMwmTree), + trafficStash, vehicleModelFactory, estimator, move(directionsEngine), index); return router; } } // namespace routing diff --git a/routing/index_router.hpp b/routing/index_router.hpp index 2b34b69fea..e797674b8c 100644 --- a/routing/index_router.hpp +++ b/routing/index_router.hpp @@ -14,6 +14,8 @@ #include "indexer/index.hpp" #include "indexer/mwm_set.hpp" +#include "geometry/tree4d.hpp" + #include "std/shared_ptr.hpp" #include "std/unique_ptr.hpp" #include "std/vector.hpp" @@ -26,10 +28,15 @@ class IndexGraphStarter; class IndexRouter : public IRouter { public: - IndexRouter(string const & name, TCountryFileFn const & countryFileFn, - shared_ptr numMwmIds, shared_ptr trafficStash, + IndexRouter(string const & name, + TCountryFileFn const & countryFileFn, + CourntryRectFn const & countryRectFn, + shared_ptr numMwmIds, + unique_ptr> numMwmTree, + shared_ptr trafficStash, shared_ptr vehicleModelFactory, - shared_ptr estimator, unique_ptr directionsEngine, + shared_ptr estimator, + unique_ptr directionsEngine, Index & index); // IRouter overrides: @@ -48,7 +55,9 @@ public: /// \note |numMwmIds| should not be null. static unique_ptr CreateCarRouter(TCountryFileFn const & countryFileFn, + CourntryRectFn const & coutryRectFn, shared_ptr numMwmIds, + unique_ptr> numMwmTree, traffic::TrafficCache const & trafficCache, Index & index); @@ -75,7 +84,9 @@ private: string const m_name; Index & m_index; TCountryFileFn const m_countryFileFn; + CourntryRectFn const m_countryRectFn; shared_ptr m_numMwmIds; + unique_ptr> m_numMwmTree; shared_ptr m_trafficStash; RoutingIndexManager m_indexManager; FeaturesRoadGraph m_roadGraph; diff --git a/routing/router.hpp b/routing/router.hpp index 9c7d110dc0..46aba92536 100644 --- a/routing/router.hpp +++ b/routing/router.hpp @@ -3,6 +3,7 @@ #include "routing/router_delegate.hpp" #include "geometry/point2d.hpp" +#include "geometry/rect2d.hpp" #include "base/cancellable.hpp" @@ -13,6 +14,7 @@ namespace routing { using TCountryFileFn = std::function; +using CourntryRectFn = std::function; class Route; diff --git a/routing/routing_integration_tests/routing_test_tools.cpp b/routing/routing_integration_tests/routing_test_tools.cpp index 45c7ec0fa6..1c4df3d1df 100644 --- a/routing/routing_integration_tests/routing_test_tools.cpp +++ b/routing/routing_integration_tests/routing_test_tools.cpp @@ -86,13 +86,22 @@ namespace integration return infoGetter.GetRegionCountryId(pt); }; + auto const getMwmRectByName = [&infoGetter](string const & countryId) -> m2::RectD + { + return infoGetter.GetLimitRectForLeaf(countryId); + }; + shared_ptr numMwmIds = make_shared(); for (LocalCountryFile const & f : localFiles) numMwmIds->RegisterFile(f.GetCountryFile()); auto carRouter = make_unique(index, countryFileGetter, - IndexRouter::CreateCarRouter(countryFileGetter, numMwmIds, - trafficCache, index)); + IndexRouter::CreateCarRouter(countryFileGetter, + getMwmRectByName, + numMwmIds, + unique_ptr>(), + trafficCache, + index)); return carRouter; } diff --git a/routing/world_graph.cpp b/routing/world_graph.cpp index 1f7e4c1249..f8e6070046 100644 --- a/routing/world_graph.cpp +++ b/routing/world_graph.cpp @@ -4,7 +4,8 @@ namespace routing { using namespace std; -WorldGraph::WorldGraph(unique_ptr crossMwmGraph, unique_ptr loader, +WorldGraph::WorldGraph(unique_ptr crossMwmGraph, + unique_ptr loader, shared_ptr estimator) : m_crossMwmGraph(move(crossMwmGraph)), m_loader(move(loader)), m_estimator(estimator) { diff --git a/routing/world_graph.hpp b/routing/world_graph.hpp index be568b12de..98b7cb74bf 100644 --- a/routing/world_graph.hpp +++ b/routing/world_graph.hpp @@ -23,8 +23,9 @@ public: WorldWithoutLeaps, }; - WorldGraph(std::unique_ptr crossMwmGraph, std::unique_ptr loader, - std::shared_ptr estimator); + WorldGraph(std::unique_ptr crossMwmGraph, + std::unique_ptr loader, + std::shared_ptr estimator); void GetEdgeList(Segment const & segment, bool isOutgoing, bool isLeap, std::vector & edges);