From 2a44a8c8102818ff8e0b70c81e5baf38fe610f91 Mon Sep 17 00:00:00 2001 From: Constantin Shalnev Date: Wed, 22 Jul 2015 13:33:33 +0300 Subject: [PATCH] Directions engine moved to separate class, directions engine was made abstract --- .../pedestrian_routing_benchmarks.cpp | 4 +- routing/directions_engine.hpp | 20 +++ routing/pedestrian_directions.cpp | 146 ++++++++++++++++++ routing/pedestrian_directions.hpp | 32 ++++ routing/pedestrian_turns_genetator.cpp | 117 -------------- routing/pedestrian_turns_genetator.hpp | 32 ---- routing/road_graph_router.cpp | 90 +++++------ routing/road_graph_router.hpp | 8 +- routing/routing.pro | 5 +- 9 files changed, 245 insertions(+), 209 deletions(-) create mode 100644 routing/directions_engine.hpp create mode 100644 routing/pedestrian_directions.cpp create mode 100644 routing/pedestrian_directions.hpp delete mode 100644 routing/pedestrian_turns_genetator.cpp delete mode 100644 routing/pedestrian_turns_genetator.hpp diff --git a/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp b/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp index 0abd488c93..4ef02dc4ac 100644 --- a/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp +++ b/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp @@ -61,7 +61,7 @@ unique_ptr CreatePedestrianAStarTestRouter(Index & index) { unique_ptr vehicleModelFactory(new SimplifiedPedestrianModelFactory()); unique_ptr algorithm(new routing::AStarRoutingAlgorithm(nullptr)); - unique_ptr router(new routing::RoadGraphRouter("test-astar-pedestrian", index, move(vehicleModelFactory), move(algorithm))); + unique_ptr router(new routing::RoadGraphRouter("test-astar-pedestrian", index, move(vehicleModelFactory), move(algorithm), nullptr)); return router; } @@ -69,7 +69,7 @@ unique_ptr CreatePedestrianAStarBidirectionalTestRouter(Index { unique_ptr vehicleModelFactory(new SimplifiedPedestrianModelFactory()); unique_ptr algorithm(new routing::AStarBidirectionalRoutingAlgorithm(nullptr)); - unique_ptr router(new routing::RoadGraphRouter("test-astar-bidirectional-pedestrian", index, move(vehicleModelFactory), move(algorithm))); + unique_ptr router(new routing::RoadGraphRouter("test-astar-bidirectional-pedestrian", index, move(vehicleModelFactory), move(algorithm), nullptr)); return router; } diff --git a/routing/directions_engine.hpp b/routing/directions_engine.hpp new file mode 100644 index 0000000000..8abcc22f96 --- /dev/null +++ b/routing/directions_engine.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "routing/road_graph.hpp" +#include "routing/route.hpp" + +namespace routing +{ + +class IDirectionsEngine +{ +public: + virtual ~IDirectionsEngine() = default; + + virtual void Generate(IRoadGraph const & graph, vector const & path, + Route::TTimes & times, + Route::TTurns & turnsDir, + turns::TTurnsGeom & turnsGeom) = 0; +}; + +} // namespace routing diff --git a/routing/pedestrian_directions.cpp b/routing/pedestrian_directions.cpp new file mode 100644 index 0000000000..6e839d56dc --- /dev/null +++ b/routing/pedestrian_directions.cpp @@ -0,0 +1,146 @@ +#include "routing/pedestrian_directions.hpp" +#include "routing/turns_generator.hpp" + +#include "indexer/classificator.hpp" +#include "indexer/feature.hpp" +#include "indexer/ftypes_matcher.hpp" +#include "indexer/index.hpp" + +#include "base/assert.hpp" +#include "base/logging.hpp" + +namespace +{ +double constexpr KMPH2MPS = 1000.0 / (60 * 60); + +bool HasType(uint32_t type, feature::TypesHolder const & types) +{ + for (uint32_t t : types) + { + t = ftypes::BaseChecker::PrepareToMatch(t, 2); + if (type == t) + return true; + } + return false; +} +} // namespace + +namespace routing +{ + +PedestrianDirectionsEngine::PedestrianDirectionsEngine() + : m_typeSteps(classif().GetTypeByPath({"highway", "steps"})) +{ +} + +void PedestrianDirectionsEngine::Generate(IRoadGraph const & graph, vector const & path, + Route::TTimes & times, + Route::TTurns & turnsDir, + turns::TTurnsGeom & turnsGeom) +{ + CHECK_GREATER(path.size(), 1, ()); + + CalculateTimes(graph, path, times); + + vector routeEdges; + if (!ReconstructPath(graph, path, routeEdges)) + { + LOG(LDEBUG, ("Couldn't reconstruct path")); + // use only "arrival" direction + turnsDir.emplace_back(path.size() - 1, turns::PedestrianDirection::ReachedYourDestination); + return; + } + + CalculateTurns(graph, routeEdges, turnsDir); + + // Do not show arrows for pedestrian routing until a good design solution + // turns::CalculateTurnGeometry(path, turnsDir, turnsGeom); + UNUSED_VALUE(turnsGeom); +} + +bool PedestrianDirectionsEngine::ReconstructPath(IRoadGraph const & graph, vector const & path, + vector & routeEdges) const +{ + routeEdges.reserve(path.size() - 1); + + Junction curr = path[0]; + vector currEdges; + for (size_t i = 1; i < path.size(); ++i) + { + Junction const & next = path[i]; + + currEdges.clear(); + graph.GetOutgoingEdges(curr, currEdges); + + bool found = false; + for (Edge const & e : currEdges) + { + if (e.GetEndJunction() == next) + { + routeEdges.emplace_back(e); + found = true; + break; + } + } + + if (!found) + return false; + + curr = next; + } + + ASSERT_EQUAL(routeEdges.size()+1, path.size(), ()); + + return true; +} + +void PedestrianDirectionsEngine::CalculateTimes(IRoadGraph const & graph, vector const & path, + Route::TTimes & times) const +{ + double const speedMPS = graph.GetMaxSpeedKMPH() * KMPH2MPS; + + times.reserve(path.size()); + + double trackTimeSec = 0.0; + times.emplace_back(0, trackTimeSec); + + m2::PointD prev = path[0].GetPoint(); + for (size_t i = 1; i < path.size(); ++i) + { + m2::PointD const & curr = path[i].GetPoint(); + + double const lengthM = MercatorBounds::DistanceOnEarth(prev, curr); + trackTimeSec += lengthM / speedMPS; + + times.emplace_back(i, trackTimeSec); + + prev = curr; + } +} + +void PedestrianDirectionsEngine::CalculateTurns(IRoadGraph const & graph, vector const & routeEdges, + Route::TTurns & turnsDir) const +{ + for (size_t i = 0; i < routeEdges.size(); ++i) + { + Edge const & edge = routeEdges[i]; + + feature::TypesHolder types; + graph.GetEdgeTypes(edge, types); + + // direction "steps" + if (HasType(m_typeSteps, types)) + { + if (edge.IsForward()) + turnsDir.emplace_back(i, turns::PedestrianDirection::Upstairs); + else + turnsDir.emplace_back(i, turns::PedestrianDirection::Downstairs); + } + } + + // direction "arrival" + // (index of last junction is the same as number of edges) + turnsDir.emplace_back(routeEdges.size(), turns::PedestrianDirection::ReachedYourDestination); +} + +} // namespace routing diff --git a/routing/pedestrian_directions.hpp b/routing/pedestrian_directions.hpp new file mode 100644 index 0000000000..6e1d3e8fbc --- /dev/null +++ b/routing/pedestrian_directions.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "routing/directions_engine.hpp" + +namespace routing +{ + +class PedestrianDirectionsEngine : public IDirectionsEngine +{ +public: + PedestrianDirectionsEngine(); + + // IDirectionsEngine override: + void Generate(IRoadGraph const & graph, vector const & path, + Route::TTimes & times, + Route::TTurns & turnsDir, + turns::TTurnsGeom & turnsGeom) override; + +private: + bool ReconstructPath(IRoadGraph const & graph, vector const & path, + vector & routeEdges) const; + + void CalculateTimes(IRoadGraph const & graph, vector const & path, + Route::TTimes & times) const; + + void CalculateTurns(IRoadGraph const & graph, vector const & routeEdges, + Route::TTurns & turnsDir) const; + + uint32_t const m_typeSteps; +}; + +} // namespace routing diff --git a/routing/pedestrian_turns_genetator.cpp b/routing/pedestrian_turns_genetator.cpp deleted file mode 100644 index 4bda7f41dd..0000000000 --- a/routing/pedestrian_turns_genetator.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "routing/pedestrian_turns_genetator.hpp" -#include "routing/turns_generator.hpp" - -#include "indexer/classificator.hpp" -#include "indexer/feature.hpp" -#include "indexer/ftypes_matcher.hpp" -#include "indexer/index.hpp" - -#include "base/assert.hpp" -#include "base/logging.hpp" - -namespace -{ -bool HasType(uint32_t type, feature::TypesHolder const & types) -{ - for (uint32_t t : types) - { - t = ftypes::BaseChecker::PrepareToMatch(t, 2); - if (type == t) - return true; - } - return false; -} -} // namespace - -namespace routing -{ -namespace turns -{ - -PedestrianTurnsGenerator::PedestrianTurnsGenerator() - : m_typeSteps(classif().GetTypeByPath({"highway", "steps"})) -{ -} - -void PedestrianTurnsGenerator::Generate(IRoadGraph const & graph, vector const & path, - Route::TTurns & turnsDir, - TTurnsGeom & turnsGeom) const -{ - ASSERT_GREATER(path.size(), 1, ()); - - vector routeEdges; - if (!ReconstructPath(graph, path, routeEdges)) - { - LOG(LDEBUG, ("Couldn't reconstruct path")); - // use only "arrival" direction - turnsDir.emplace_back(path.size() - 1, turns::PedestrianDirection::ReachedYourDestination); - return; - } - - for (size_t i = 0; i < routeEdges.size(); ++i) - { - Edge const & edge = routeEdges[i]; - - feature::TypesHolder types; - graph.GetEdgeTypes(edge, types); - - if (HasType(m_typeSteps, types)) - { - // direction "steps" - if (edge.IsForward()) - { - LOG(LDEBUG, ("Edge", i, edge.GetFeatureId(), "upstairs")); - turnsDir.emplace_back(i, turns::PedestrianDirection::Upstairs); - } - else - { - LOG(LDEBUG, ("Edge", i, edge.GetFeatureId(), "downstairs")); - turnsDir.emplace_back(i, turns::PedestrianDirection::Downstairs); - } - } - } - - // direction "arrival" - turnsDir.emplace_back(path.size() - 1, turns::PedestrianDirection::ReachedYourDestination); - - // Do not show arrows for pedestrian routing until a good design solution - // CalculateTurnGeometry(path, turnsDir, turnsGeom); - UNUSED_VALUE(turnsGeom); -} - -bool PedestrianTurnsGenerator::ReconstructPath(IRoadGraph const & graph, vector const & path, - vector & routeEdges) const -{ - Junction curr = path[0]; - vector currEdges; - for (size_t i = 1; i < path.size(); ++i) - { - Junction const next = path[i]; - - currEdges.clear(); - graph.GetOutgoingEdges(curr, currEdges); - - bool found = false; - for (Edge const & e : currEdges) - { - if (e.GetEndJunction() == next) - { - routeEdges.emplace_back(e); - found = true; - break; - } - } - - if (!found) - return false; - - curr = next; - } - - ASSERT_EQUAL(routeEdges.size()+1, path.size(), ()); - - return true; -} - -} // namespace turns -} // namespace routing diff --git a/routing/pedestrian_turns_genetator.hpp b/routing/pedestrian_turns_genetator.hpp deleted file mode 100644 index 009d24b37e..0000000000 --- a/routing/pedestrian_turns_genetator.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "routing/road_graph.hpp" -#include "routing/route.hpp" - -#include "std/vector.hpp" - -class Index; - -namespace routing -{ -namespace turns -{ - -class PedestrianTurnsGenerator -{ -public: - PedestrianTurnsGenerator(); - - void Generate(IRoadGraph const & graph, vector const & path, - Route::TTurns & turnsDir, - TTurnsGeom & turnsGeom) const; - -private: - bool ReconstructPath(IRoadGraph const & graph, vector const & path, - vector & routeEdges) const; - - uint32_t const m_typeSteps; -}; - -} // namespace turns -} // namespace routing diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp index 902f1958d2..f76b69b698 100644 --- a/routing/road_graph_router.cpp +++ b/routing/road_graph_router.cpp @@ -1,7 +1,7 @@ #include "routing/features_road_graph.hpp" #include "routing/nearest_edge_finder.hpp" +#include "routing/pedestrian_directions.hpp" #include "routing/pedestrian_model.hpp" -#include "routing/pedestrian_turns_genetator.hpp" #include "routing/road_graph_router.hpp" #include "routing/route.hpp" @@ -28,8 +28,6 @@ namespace // eliminates) this risk. size_t const MAX_ROAD_CANDIDATES = 1; -double constexpr KMPH2MPS = 1000.0 / (60 * 60); - IRouter::ResultCode Convert(IRoutingAlgorithm::Result value) { switch (value) @@ -41,16 +39,26 @@ IRouter::ResultCode Convert(IRoutingAlgorithm::Result value) ASSERT(false, ("Unexpected IRoutingAlgorithm::Result value:", value)); return IRouter::ResultCode::RouteNotFound; } + +void Convert(vector const & path, vector & geometry) +{ + geometry.clear(); + geometry.reserve(path.size()); + for (auto const & pos : path) + geometry.emplace_back(pos.GetPoint()); +} } // namespace RoadGraphRouter::~RoadGraphRouter() {} RoadGraphRouter::RoadGraphRouter(string const & name, Index & index, unique_ptr && vehicleModelFactory, - unique_ptr && algorithm) + unique_ptr && algorithm, + unique_ptr && directionsEngine) : m_name(name) , m_algorithm(move(algorithm)) , m_roadGraph(make_unique(index, move(vehicleModelFactory))) + , m_directionsEngine(move(directionsEngine)) { } @@ -83,14 +91,15 @@ IRouter::ResultCode RoadGraphRouter::CalculateRoute(m2::PointD const & startPoin m_roadGraph->AddFakeEdges(startPos, startVicinity); m_roadGraph->AddFakeEdges(finalPos, finalVicinity); - vector routePos; - IRoutingAlgorithm::Result const resultCode = m_algorithm->CalculateRoute(*m_roadGraph, startPos, finalPos, routePos); + vector path; + IRoutingAlgorithm::Result const resultCode = m_algorithm->CalculateRoute(*m_roadGraph, startPos, finalPos, path); if (resultCode == IRoutingAlgorithm::Result::OK) { - ASSERT_EQUAL(routePos.front(), startPos, ()); - ASSERT_EQUAL(routePos.back(), finalPos, ()); - ReconstructRoute(routePos, route); + ASSERT(!path.empty(), ()); + ASSERT_EQUAL(path.front(), startPos, ()); + ASSERT_EQUAL(path.back(), finalPos, ()); + ReconstructRoute(move(path), route); } m_roadGraph->ResetFakes(); @@ -98,57 +107,28 @@ IRouter::ResultCode RoadGraphRouter::CalculateRoute(m2::PointD const & startPoin return Convert(resultCode); } -void RoadGraphRouter::ReconstructRoute(vector const & junctions, Route & route) const +void RoadGraphRouter::ReconstructRoute(vector && path, Route & route) const { - CHECK(!junctions.empty(), ("Can't reconstruct path from an empty list of positions.")); + CHECK(!path.empty(), ("Can't reconstruct route from an empty list of positions.")); - vector path; - path.reserve(junctions.size()); + // By some reason there're two adjacent positions on a road with + // the same end-points. This could happen, for example, when + // direction on a road was changed. But it doesn't matter since + // this code reconstructs only geometry of a route. + path.erase(unique(path.begin(), path.end()), path.end()); + if (path.size() == 1) + path.emplace_back(path.back()); - double const speedMPS = m_roadGraph->GetMaxSpeedKMPH() * KMPH2MPS; + vector geometry; + Convert(path, geometry); Route::TTimes times; - times.reserve(junctions.size()); - - double trackTimeSec = 0.0; - times.emplace_back(0, 0.0); - - m2::PointD prevPoint = junctions[0].GetPoint(); - path.emplace_back(prevPoint); - for (size_t i = 1; i < junctions.size(); ++i) - { - m2::PointD const curPoint = junctions[i].GetPoint(); - - // By some reason there're two adjacent positions on a road with - // the same end-points. This could happen, for example, when - // direction on a road was changed. But it doesn't matter since - // this code reconstructs only geometry of a route. - if (curPoint == prevPoint) - continue; - - double const lengthM = MercatorBounds::DistanceOnEarth(prevPoint, curPoint); - trackTimeSec += lengthM / speedMPS; - - path.emplace_back(curPoint); - times.emplace_back(path.size()-1, trackTimeSec); - - prevPoint = curPoint; - } - - if (path.size() == 1) - { - path.emplace_back(path.front()); - times.emplace_back(path.size()-1, trackTimeSec); - } - - ASSERT_EQUAL(path.size(), times.size(), ()); - ASSERT_GREATER_OR_EQUAL(path.size(), 2, ()); - Route::TTurns turnsDir; turns::TTurnsGeom turnsGeom; - turns::PedestrianTurnsGenerator().Generate(*m_roadGraph, path, turnsDir, turnsGeom); + if (m_directionsEngine) + m_directionsEngine->Generate(*m_roadGraph, path, times, turnsDir, turnsGeom); - route.SetGeometry(path.begin(), path.end()); + route.SetGeometry(geometry.begin(), geometry.end()); route.SetSectionTimes(times); route.SetTurnInstructions(turnsDir); route.SetTurnInstructionsGeometry(turnsGeom); @@ -159,7 +139,8 @@ unique_ptr CreatePedestrianAStarRouter(Index & index, { unique_ptr vehicleModelFactory(new PedestrianModelFactory()); unique_ptr algorithm(new AStarRoutingAlgorithm(visualizerFn)); - unique_ptr router(new RoadGraphRouter("astar-pedestrian", index, move(vehicleModelFactory), move(algorithm))); + unique_ptr directionsEngine(new PedestrianDirectionsEngine()); + unique_ptr router(new RoadGraphRouter("astar-pedestrian", index, move(vehicleModelFactory), move(algorithm), move(directionsEngine))); return router; } @@ -168,7 +149,8 @@ unique_ptr CreatePedestrianAStarBidirectionalRouter( { unique_ptr vehicleModelFactory(new PedestrianModelFactory()); unique_ptr algorithm(new AStarBidirectionalRoutingAlgorithm(visualizerFn)); - unique_ptr router(new RoadGraphRouter("astar-bidirectional-pedestrian", index, move(vehicleModelFactory), move(algorithm))); + unique_ptr directionsEngine(new PedestrianDirectionsEngine()); + unique_ptr router(new RoadGraphRouter("astar-bidirectional-pedestrian", index, move(vehicleModelFactory), move(algorithm), move(directionsEngine))); return router; } diff --git a/routing/road_graph_router.hpp b/routing/road_graph_router.hpp index 160ad9640b..d652746893 100644 --- a/routing/road_graph_router.hpp +++ b/routing/road_graph_router.hpp @@ -1,5 +1,6 @@ #pragma once +#include "routing/directions_engine.hpp" #include "routing/road_graph.hpp" #include "routing/router.hpp" #include "routing/routing_algorithm.hpp" @@ -24,7 +25,8 @@ class RoadGraphRouter : public IRouter public: RoadGraphRouter(string const & name, Index & index, unique_ptr && vehicleModelFactory, - unique_ptr && algorithm); + unique_ptr && algorithm, + unique_ptr && directionsEngine); ~RoadGraphRouter() override; // IRouter overrides: @@ -39,15 +41,17 @@ public: bool IsCancelled() const override { return m_algorithm->IsCancelled(); } private: - void ReconstructRoute(vector const & junctions, Route & route) const; + void ReconstructRoute(vector && junctions, Route & route) const; string const m_name; unique_ptr const m_algorithm; unique_ptr const m_roadGraph; + unique_ptr const m_directionsEngine; }; unique_ptr CreatePedestrianAStarRouter(Index & index, TRoutingVisualizerFn const & visualizerFn); + unique_ptr CreatePedestrianAStarBidirectionalRouter( Index & index, TRoutingProgressFn const & progressFn, TRoutingVisualizerFn const & visualizerFn); diff --git a/routing/routing.pro b/routing/routing.pro index 3febae9d25..51ecd2aaef 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -26,8 +26,8 @@ SOURCES += \ osrm_engine.cpp \ osrm_online_router.cpp \ osrm_router.cpp \ + pedestrian_directions.cpp \ pedestrian_model.cpp \ - pedestrian_turns_genetator.cpp \ road_graph.cpp \ road_graph_router.cpp \ route.cpp \ @@ -47,6 +47,7 @@ HEADERS += \ cross_mwm_road_graph.hpp \ cross_mwm_router.hpp \ cross_routing_context.hpp \ + directions_engine.hpp \ features_road_graph.hpp \ nearest_edge_finder.hpp \ online_absent_fetcher.hpp \ @@ -56,8 +57,8 @@ HEADERS += \ osrm_engine.hpp \ osrm_online_router.hpp \ osrm_router.hpp \ + pedestrian_directions.hpp \ pedestrian_model.hpp \ - pedestrian_turns_genetator.hpp \ road_graph.hpp \ road_graph_router.hpp \ route.hpp \