diff options
author | Konstantin Shalnev <c.shalnev@corp.mail.ru> | 2016-05-30 11:32:31 +0300 |
---|---|---|
committer | Konstantin Shalnev <c.shalnev@corp.mail.ru> | 2016-05-30 11:32:31 +0300 |
commit | bb67816403f8fe94b6593fd4f63cf44fd7469877 (patch) | |
tree | a100d2ed84faa80e2773156dd0dbb69858d3114a /routing | |
parent | 82821e1ed30d9e923a08ea5a1fecaeabaac382ce (diff) | |
parent | 8f7da1501a7382a7ee16641fc459ee4354f43d37 (diff) |
Merge pull request #3338 from bykoianko/master-velo-direction
[bicycle routing] "oneway" tag is taken into account while bicycle routing.
Diffstat (limited to 'routing')
-rw-r--r-- | routing/bicycle_model.hpp | 1 | ||||
-rw-r--r-- | routing/features_road_graph.cpp | 31 | ||||
-rw-r--r-- | routing/features_road_graph.hpp | 9 | ||||
-rw-r--r-- | routing/road_graph.cpp | 109 | ||||
-rw-r--r-- | routing/road_graph.hpp | 88 | ||||
-rw-r--r-- | routing/road_graph_router.cpp | 33 | ||||
-rw-r--r-- | routing/road_graph_router.hpp | 6 | ||||
-rw-r--r-- | routing/routing_integration_tests/bicycle_turn_test.cpp | 45 | ||||
-rw-r--r-- | routing/routing_tests/road_graph_builder.cpp | 7 | ||||
-rw-r--r-- | routing/routing_tests/road_graph_builder.hpp | 3 | ||||
-rw-r--r-- | routing/vehicle_model.hpp | 6 |
11 files changed, 230 insertions, 108 deletions
diff --git a/routing/bicycle_model.hpp b/routing/bicycle_model.hpp index 2c420ccd83..2a7fdaa4fa 100644 --- a/routing/bicycle_model.hpp +++ b/routing/bicycle_model.hpp @@ -17,7 +17,6 @@ public: /// @name Overrides from VehicleModel. //@{ double GetSpeed(FeatureType const & f) const override; - bool IsOneWay(FeatureType const &) const override { return false; } //@} private: diff --git a/routing/features_road_graph.cpp b/routing/features_road_graph.cpp index 65e5b039bc..f32794f4a6 100644 --- a/routing/features_road_graph.cpp +++ b/routing/features_road_graph.cpp @@ -36,12 +36,6 @@ string GetFeatureCountryName(FeatureID const featureId) return countryName; return countryName.substr(0, pos); } - -inline bool PointsAlmostEqualAbs(const m2::PointD & pt1, const m2::PointD & pt2) -{ - double constexpr kEpsilon = 1e-6; - return my::AlmostEqualAbs(pt1.x, pt2.x, kEpsilon) && my::AlmostEqualAbs(pt1.y, pt2.y, kEpsilon); -} } // namespace @@ -101,10 +95,11 @@ void FeaturesRoadGraph::RoadInfoCache::Clear() m_cache.clear(); } - -FeaturesRoadGraph::FeaturesRoadGraph(Index & index, unique_ptr<IVehicleModelFactory> && vehicleModelFactory) - : m_index(index), - m_vehicleModel(move(vehicleModelFactory)) +FeaturesRoadGraph::FeaturesRoadGraph(Index const & index, IRoadGraph::Mode mode, + unique_ptr<IVehicleModelFactory> && vehicleModelFactory) + : m_index(index) + , m_mode(mode) + , m_vehicleModel(move(vehicleModelFactory)) { } @@ -113,9 +108,8 @@ uint32_t FeaturesRoadGraph::GetStreetReadScale() { return scales::GetUpperScale( class CrossFeaturesLoader { public: - CrossFeaturesLoader(FeaturesRoadGraph const & graph, - IRoadGraph::CrossEdgesLoader & edgesLoader) - : m_graph(graph), m_edgesLoader(edgesLoader) + CrossFeaturesLoader(FeaturesRoadGraph const & graph, IRoadGraph::ICrossEdgesLoader & edgesLoader) + : m_graph(graph), m_edgesLoader(edgesLoader) {} void operator()(FeatureType & ft) @@ -136,7 +130,7 @@ public: private: FeaturesRoadGraph const & m_graph; - IRoadGraph::CrossEdgesLoader & m_edgesLoader; + IRoadGraph::ICrossEdgesLoader & m_edgesLoader; }; IRoadGraph::RoadInfo FeaturesRoadGraph::GetRoadInfo(FeatureID const & featureId) const @@ -159,7 +153,7 @@ double FeaturesRoadGraph::GetMaxSpeedKMPH() const } void FeaturesRoadGraph::ForEachFeatureClosestToCross(m2::PointD const & cross, - CrossEdgesLoader & edgesLoader) const + ICrossEdgesLoader & edgesLoader) const { CrossFeaturesLoader featuresLoader(*this, edgesLoader); m2::RectD const rect = MercatorBounds::RectByCenterXYAndSizeInMeters(cross, kMwmRoadCrossingRadiusMeters); @@ -218,7 +212,7 @@ void FeaturesRoadGraph::GetJunctionTypes(Junction const & junction, feature::Typ if (ft.GetFeatureType() != feature::GEOM_POINT) return; - if (!PointsAlmostEqualAbs(ft.GetCenter(), cross)) + if (!my::AlmostEqualAbs(ft.GetCenter(), cross, routing::kPointsEqualEpsilon)) return; feature::TypesHolder typesHolder(ft); @@ -230,6 +224,11 @@ void FeaturesRoadGraph::GetJunctionTypes(Junction const & junction, feature::Typ m_index.ForEachInRect(f, rect, GetStreetReadScale()); } +IRoadGraph::Mode FeaturesRoadGraph::GetMode() const +{ + return m_mode; +}; + void FeaturesRoadGraph::ClearState() { m_cache.Clear(); diff --git a/routing/features_road_graph.hpp b/routing/features_road_graph.hpp index ae0576647c..af61afd11f 100644 --- a/routing/features_road_graph.hpp +++ b/routing/features_road_graph.hpp @@ -56,7 +56,8 @@ private: }; public: - FeaturesRoadGraph(Index & index, unique_ptr<IVehicleModelFactory> && vehicleModelFactory); + FeaturesRoadGraph(Index const & index, IRoadGraph::Mode mode, + unique_ptr<IVehicleModelFactory> && vehicleModelFactory); static uint32_t GetStreetReadScale(); @@ -65,11 +66,12 @@ public: double GetSpeedKMPH(FeatureID const & featureId) const override; double GetMaxSpeedKMPH() const override; void ForEachFeatureClosestToCross(m2::PointD const & cross, - CrossEdgesLoader & edgesLoader) const override; + ICrossEdgesLoader & edgesLoader) const override; void FindClosestEdges(m2::PointD const & point, uint32_t count, vector<pair<Edge, m2::PointD>> & vicinities) const override; void GetFeatureTypes(FeatureID const & featureId, feature::TypesHolder & types) const override; void GetJunctionTypes(Junction const & junction, feature::TypesHolder & types) const override; + IRoadGraph::Mode GetMode() const override; void ClearState() override; private: @@ -89,7 +91,8 @@ private: void LockFeatureMwm(FeatureID const & featureId) const; - Index & m_index; + Index const & m_index; + IRoadGraph::Mode const m_mode; mutable RoadInfoCache m_cache; mutable CrossCountryVehicleModel m_vehicleModel; mutable map<MwmSet::MwmId, MwmSet::MwmHandle> m_mwmLocks; diff --git a/routing/road_graph.cpp b/routing/road_graph.cpp index c0a314ca23..271e258e63 100644 --- a/routing/road_graph.cpp +++ b/routing/road_graph.cpp @@ -15,16 +15,8 @@ namespace routing { - namespace { - -inline bool PointsAlmostEqualAbs(const m2::PointD & pt1, const m2::PointD & pt2) -{ - double constexpr kEpsilon = 1e-6; - return my::AlmostEqualAbs(pt1.x, pt2.x, kEpsilon) && my::AlmostEqualAbs(pt1.y, pt2.y, kEpsilon); -} - vector<Edge>::const_iterator FindEdgeContainingPoint(vector<Edge> const & edges, m2::PointD const & pt) { // A P B @@ -38,7 +30,8 @@ vector<Edge>::const_iterator FindEdgeContainingPoint(vector<Edge> const & edges, m2::PointD const v1 = e.GetStartJunction().GetPoint() - pt; m2::PointD const v2 = e.GetEndJunction().GetPoint() - pt; - if (PointsAlmostEqualAbs(v1, m2::PointD::Zero()) || PointsAlmostEqualAbs(v2, m2::PointD::Zero())) + if (my::AlmostEqualAbs(v1, m2::PointD::Zero(), kPointsEqualEpsilon) + || my::AlmostEqualAbs(v2, m2::PointD::Zero(), kPointsEqualEpsilon)) { // Point p corresponds to the start or the end of the edge. return true; @@ -61,6 +54,14 @@ vector<Edge>::const_iterator FindEdgeContainingPoint(vector<Edge> const & edges, return find_if(edges.begin(), edges.end(), liesOnEdgeFn); } +/// \brief Reverses |edges| starting from index |beginIdx| and upto the end of |v|. +void ReverseEdges(size_t beginIdx, IRoadGraph::TEdgeVector & edges) +{ + ASSERT_LESS_OR_EQUAL(beginIdx, edges.size(), ("Index too large.")); + + for (size_t i = beginIdx; i < edges.size(); ++i) + edges[i] = edges[i].GetReverseEdge(); +} } // namespace // Junction -------------------------------------------------------------------- @@ -154,76 +155,70 @@ IRoadGraph::RoadInfo::RoadInfo(bool bidirectional, double speedKMPH, initializer : m_points(points), m_speedKMPH(speedKMPH), m_bidirectional(bidirectional) {} -// IRoadGraph::CrossEdgesLoader ------------------------------------------------ - -IRoadGraph::CrossEdgesLoader::CrossEdgesLoader(m2::PointD const & cross, TEdgeVector & outgoingEdges) - : m_cross(cross), m_outgoingEdges(outgoingEdges) +// IRoadGraph::CrossOutgoingLoader --------------------------------------------- +void IRoadGraph::CrossOutgoingLoader::LoadEdges(FeatureID const & featureId, RoadInfo const & roadInfo) { + ForEachEdge(roadInfo, [&featureId, &roadInfo, this](size_t segId, m2::PointD const & endPoint, bool forward) + { + if (forward || roadInfo.m_bidirectional || m_mode == IRoadGraph::Mode::IgnoreOnewayTag) + m_edges.emplace_back(featureId, forward, segId, m_cross, endPoint); + }); } -void IRoadGraph::CrossEdgesLoader::operator()(FeatureID const & featureId, RoadInfo const & roadInfo) +// IRoadGraph::CrossIngoingLoader ---------------------------------------------- +void IRoadGraph::CrossIngoingLoader::LoadEdges(FeatureID const & featureId, RoadInfo const & roadInfo) { - size_t const numPoints = roadInfo.m_points.size(); - - for (size_t i = 0; i < numPoints; ++i) + ForEachEdge(roadInfo, [&featureId, &roadInfo, this](size_t segId, m2::PointD const & endPoint, bool forward) { - m2::PointD const & p = roadInfo.m_points[i]; - - if (!PointsAlmostEqualAbs(m_cross, p)) - continue; - - if (i > 0) - { - // p - // o------------>o - - m_outgoingEdges.emplace_back(featureId, false /* forward */, i - 1, p, roadInfo.m_points[i - 1]); - } - - if (i < numPoints - 1) - { - // p - // o------------>o - - m_outgoingEdges.emplace_back(featureId, true /* forward */, i, p, roadInfo.m_points[i + 1]); - } - } + if (!forward || roadInfo.m_bidirectional || m_mode == IRoadGraph::Mode::IgnoreOnewayTag) + m_edges.emplace_back(featureId, !forward, segId, endPoint, m_cross); + }); } // IRoadGraph ------------------------------------------------------------------ - void IRoadGraph::GetOutgoingEdges(Junction const & junction, TEdgeVector & edges) const { - auto const itr = m_outgoingEdges.find(junction); - if (itr != m_outgoingEdges.end()) - { - edges.reserve(edges.size() + itr->second.size()); - edges.insert(edges.end(), itr->second.begin(), itr->second.end()); - } - else - { - GetRegularOutgoingEdges(junction, edges); - } + GetFakeOutgoingEdges(junction, edges); + GetRegularOutgoingEdges(junction, edges); } void IRoadGraph::GetIngoingEdges(Junction const & junction, TEdgeVector & edges) const { - size_t const wasSize = edges.size(); - - GetOutgoingEdges(junction, edges); - - size_t const size = edges.size(); - for (size_t i = wasSize; i < size; ++i) - edges[i] = edges[i].GetReverseEdge(); + GetFakeIngoingEdges(junction, edges); + GetRegularIngoingEdges(junction, edges); } void IRoadGraph::GetRegularOutgoingEdges(Junction const & junction, TEdgeVector & edges) const { m2::PointD const cross = junction.GetPoint(); - CrossEdgesLoader loader(cross, edges); + CrossOutgoingLoader loader(cross, GetMode(), edges); + ForEachFeatureClosestToCross(cross, loader); +} + +void IRoadGraph::GetRegularIngoingEdges(Junction const & junction, TEdgeVector & edges) const +{ + m2::PointD const cross = junction.GetPoint(); + CrossIngoingLoader loader(cross, GetMode(), edges); ForEachFeatureClosestToCross(cross, loader); } +void IRoadGraph::GetFakeOutgoingEdges(Junction const & junction, TEdgeVector & edges) const +{ + auto const itr = m_outgoingEdges.find(junction); + if (itr == m_outgoingEdges.cend()) + return; + + edges.reserve(edges.size() + itr->second.size()); + edges.insert(edges.end(), itr->second.begin(), itr->second.end()); +} + +void IRoadGraph::GetFakeIngoingEdges(Junction const & junction, TEdgeVector & edges) const +{ + size_t const oldSize = edges.size(); + GetFakeOutgoingEdges(junction, edges); + ReverseEdges(oldSize, edges); +} + void IRoadGraph::ResetFakes() { m_outgoingEdges.clear(); diff --git a/routing/road_graph.hpp b/routing/road_graph.hpp index 982c98ff6c..e97a9cb0f2 100644 --- a/routing/road_graph.hpp +++ b/routing/road_graph.hpp @@ -12,6 +12,7 @@ namespace routing { +double constexpr kPointsEqualEpsilon = 1e-6; /// The Junction class represents a node description on a road network graph class Junction @@ -83,6 +84,12 @@ public: typedef vector<Junction> TJunctionVector; typedef vector<Edge> TEdgeVector; + enum class Mode + { + ObeyOnewayTag, + IgnoreOnewayTag, + }; + /// This struct contains the part of a feature's metadata that is /// relevant for routing. struct RoadInfo @@ -99,17 +106,75 @@ public: }; /// This class is responsible for loading edges in a cross. - /// It loades only outgoing edges. - class CrossEdgesLoader + class ICrossEdgesLoader { public: - CrossEdgesLoader(m2::PointD const & cross, TEdgeVector & outgoingEdges); + ICrossEdgesLoader(m2::PointD const & cross, IRoadGraph::Mode mode, TEdgeVector & edges) + : m_cross(cross), m_mode(mode), m_edges(edges) + { + } - void operator()(FeatureID const & featureId, RoadInfo const & roadInfo); + virtual ~ICrossEdgesLoader() = default; + + void operator()(FeatureID const & featureId, RoadInfo const & roadInfo) + { + LoadEdges(featureId, roadInfo); + } private: + virtual void LoadEdges(FeatureID const & featureId, RoadInfo const & roadInfo) = 0; + + protected: + template <typename TFn> + void ForEachEdge(RoadInfo const & roadInfo, TFn && fn) + { + for (size_t i = 0; i < roadInfo.m_points.size(); ++i) + { + if (!my::AlmostEqualAbs(m_cross, roadInfo.m_points[i], kPointsEqualEpsilon)) + continue; + + if (i < roadInfo.m_points.size() - 1) + { + // Head of the edge. + // m_cross + // o------------>o + fn(i, roadInfo.m_points[i + 1], true /* forward */); + } + if (i > 0) + { + // Tail of the edge. + // m_cross + // o------------>o + fn(i - 1, roadInfo.m_points[i - 1], false /* backward */); + } + } + } + m2::PointD const m_cross; - TEdgeVector & m_outgoingEdges; + IRoadGraph::Mode const m_mode; + TEdgeVector & m_edges; + }; + + class CrossOutgoingLoader : public ICrossEdgesLoader + { + public: + CrossOutgoingLoader(m2::PointD const & cross, IRoadGraph::Mode mode, TEdgeVector & edges) + : ICrossEdgesLoader(cross, mode, edges) {} + + private: + // ICrossEdgesLoader overrides: + virtual void LoadEdges(FeatureID const & featureId, RoadInfo const & roadInfo) override; + }; + + class CrossIngoingLoader : public ICrossEdgesLoader + { + public: + CrossIngoingLoader(m2::PointD const & cross, IRoadGraph::Mode mode, TEdgeVector & edges) + : ICrossEdgesLoader(cross, mode, edges) {} + + private: + // ICrossEdgesLoader overrides: + virtual void LoadEdges(FeatureID const & featureId, RoadInfo const & roadInfo) override; }; virtual ~IRoadGraph() = default; @@ -141,7 +206,7 @@ public: /// Calls edgesLoader on each feature which is close to cross. virtual void ForEachFeatureClosestToCross(m2::PointD const & cross, - CrossEdgesLoader & edgesLoader) const = 0; + ICrossEdgesLoader & edgesLoader) const = 0; /// Finds the closest edges to the point. /// @return Array of pairs of Edge and projection point on the Edge. If there is no the closest edges @@ -158,12 +223,20 @@ public: /// @return Types for specified junction virtual void GetJunctionTypes(Junction const & junction, feature::TypesHolder & types) const = 0; + virtual IRoadGraph::Mode GetMode() const = 0; + /// Clear all temporary buffers. virtual void ClearState() {} private: - /// Finds all outgoing regular (non-fake) edges for junction. + /// \brief Finds all outgoing regular (non-fake) edges for junction. void GetRegularOutgoingEdges(Junction const & junction, TEdgeVector & edges) const; + /// \brief Finds all ingoing regular (non-fake) edges for junction. + void GetRegularIngoingEdges(Junction const & junction, TEdgeVector & edges) const; + /// \brief Finds all outgoing fake edges for junction. + void GetFakeOutgoingEdges(Junction const & junction, TEdgeVector & edges) const; + /// \brief Finds all ingoing fake edges for junction. + void GetFakeIngoingEdges(Junction const & junction, TEdgeVector & edges) const; /// Determines if the edge has been split by fake edges and if yes returns these fake edges. bool HasBeenSplitToFakes(Edge const & edge, vector<Edge> & fakeEdges) const; @@ -171,5 +244,4 @@ private: // Map of outgoing edges for junction map<Junction, TEdgeVector> m_outgoingEdges; }; - } // namespace routing diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp index 0cab63e835..83934557e8 100644 --- a/routing/road_graph_router.cpp +++ b/routing/road_graph_router.cpp @@ -130,17 +130,17 @@ void FindClosestEdges(IRoadGraph const & graph, m2::PointD const & point, RoadGraphRouter::~RoadGraphRouter() {} -RoadGraphRouter::RoadGraphRouter(string const & name, Index & index, - TCountryFileFn const & countryFileFn, +RoadGraphRouter::RoadGraphRouter(string const & name, Index const & index, + TCountryFileFn const & countryFileFn, IRoadGraph::Mode mode, unique_ptr<IVehicleModelFactory> && vehicleModelFactory, unique_ptr<IRoutingAlgorithm> && algorithm, unique_ptr<IDirectionsEngine> && directionsEngine) - : m_name(name) - , m_countryFileFn(countryFileFn) - , m_index(index) - , m_algorithm(move(algorithm)) - , m_roadGraph(make_unique<FeaturesRoadGraph>(index, move(vehicleModelFactory))) - , m_directionsEngine(move(directionsEngine)) + : m_name(name) + , m_countryFileFn(countryFileFn) + , m_index(index) + , m_algorithm(move(algorithm)) + , m_roadGraph(make_unique<FeaturesRoadGraph>(index, mode, move(vehicleModelFactory))) + , m_directionsEngine(move(directionsEngine)) { } @@ -258,9 +258,9 @@ unique_ptr<IRouter> CreatePedestrianAStarRouter(Index & index, TCountryFileFn co unique_ptr<IVehicleModelFactory> vehicleModelFactory(new PedestrianModelFactory()); unique_ptr<IRoutingAlgorithm> algorithm(new AStarRoutingAlgorithm()); unique_ptr<IDirectionsEngine> directionsEngine(new PedestrianDirectionsEngine()); - unique_ptr<IRouter> router(new RoadGraphRouter("astar-pedestrian", index, countryFileFn, - move(vehicleModelFactory), move(algorithm), - move(directionsEngine))); + unique_ptr<IRouter> router(new RoadGraphRouter( + "astar-pedestrian", index, countryFileFn, IRoadGraph::Mode::IgnoreOnewayTag, + move(vehicleModelFactory), move(algorithm), move(directionsEngine))); return router; } @@ -269,9 +269,9 @@ unique_ptr<IRouter> CreatePedestrianAStarBidirectionalRouter(Index & index, TCou unique_ptr<IVehicleModelFactory> vehicleModelFactory(new PedestrianModelFactory()); unique_ptr<IRoutingAlgorithm> algorithm(new AStarBidirectionalRoutingAlgorithm()); unique_ptr<IDirectionsEngine> directionsEngine(new PedestrianDirectionsEngine()); - unique_ptr<IRouter> router(new RoadGraphRouter("astar-bidirectional-pedestrian", index, - countryFileFn, move(vehicleModelFactory), - move(algorithm), move(directionsEngine))); + unique_ptr<IRouter> router(new RoadGraphRouter( + "astar-bidirectional-pedestrian", index, countryFileFn, IRoadGraph::Mode::IgnoreOnewayTag, + move(vehicleModelFactory), move(algorithm), move(directionsEngine))); return router; } @@ -280,8 +280,9 @@ unique_ptr<IRouter> CreateBicycleAStarBidirectionalRouter(Index & index, TCountr unique_ptr<IVehicleModelFactory> vehicleModelFactory(new BicycleModelFactory()); unique_ptr<IRoutingAlgorithm> algorithm(new AStarBidirectionalRoutingAlgorithm()); unique_ptr<IDirectionsEngine> directionsEngine(new BicycleDirectionsEngine(index)); - unique_ptr<IRouter> router(new RoadGraphRouter("astar-bidirectional-bicycle", index, countryFileFn, move(vehicleModelFactory), - move(algorithm), move(directionsEngine))); + unique_ptr<IRouter> router(new RoadGraphRouter( + "astar-bidirectional-bicycle", index, countryFileFn, IRoadGraph::Mode::ObeyOnewayTag, + move(vehicleModelFactory), move(algorithm), move(directionsEngine))); return router; } } // namespace routing diff --git a/routing/road_graph_router.hpp b/routing/road_graph_router.hpp index 17127bb124..17701bdc7a 100644 --- a/routing/road_graph_router.hpp +++ b/routing/road_graph_router.hpp @@ -23,8 +23,8 @@ namespace routing class RoadGraphRouter : public IRouter { public: - RoadGraphRouter(string const & name, Index & index, - TCountryFileFn const & countryFileFn, + RoadGraphRouter(string const & name, Index const & index, TCountryFileFn const & countryFileFn, + IRoadGraph::Mode mode, unique_ptr<IVehicleModelFactory> && vehicleModelFactory, unique_ptr<IRoutingAlgorithm> && algorithm, unique_ptr<IDirectionsEngine> && directionsEngine); @@ -47,7 +47,7 @@ private: string const m_name; TCountryFileFn const m_countryFileFn; - Index & m_index; + Index const & m_index; unique_ptr<IRoutingAlgorithm> const m_algorithm; unique_ptr<IRoadGraph> const m_roadGraph; unique_ptr<IDirectionsEngine> const m_directionsEngine; diff --git a/routing/routing_integration_tests/bicycle_turn_test.cpp b/routing/routing_integration_tests/bicycle_turn_test.cpp index f3906d80d4..81f02a9942 100644 --- a/routing/routing_integration_tests/bicycle_turn_test.cpp +++ b/routing/routing_integration_tests/bicycle_turn_test.cpp @@ -17,11 +17,13 @@ UNIT_TEST(RussiaMoscowSevTushinoParkBicycleWayTurnTest) IRouter::ResultCode const result = routeResult.second; TEST_EQUAL(result, IRouter::NoError, ()); - integration::TestTurnCount(route, 1); + integration::TestTurnCount(route, 3); integration::GetNthTurn(route, 0).TestValid().TestDirection(TurnDirection::TurnLeft); + integration::GetNthTurn(route, 1).TestValid().TestDirection(TurnDirection::TurnLeft); + integration::GetNthTurn(route, 2).TestValid().TestDirection(TurnDirection::TurnLeft); - integration::TestRouteLength(route, 752.); + integration::TestRouteLength(route, 2350.0); } UNIT_TEST(RussiaMoscowGerPanfilovtsev22BicycleWayTurnTest) @@ -67,3 +69,42 @@ UNIT_TEST(RussiaMoscowSevTushinoParkBicycleOnePointTurnTest) TEST_EQUAL(route.GetTurns().size(), 0, ()); integration::TestRouteLength(route, 0.0); } + +UNIT_TEST(RussiaMoscowPlanernaiOnewayCarRoadTurnTest) +{ + TRouteResult const routeResult = integration::CalculateRoute( + integration::GetBicycleComponents(), MercatorBounds::FromLatLon(55.87012, 37.44028), + {0.0, 0.0}, MercatorBounds::FromLatLon(55.87153, 37.43928)); + + Route const & route = *routeResult.first; + IRouter::ResultCode const result = routeResult.second; + TEST_EQUAL(result, IRouter::NoError, ()); + + integration::TestTurnCount(route, 4); + + integration::GetNthTurn(route, 0).TestValid().TestDirection(TurnDirection::TurnLeft); + integration::GetNthTurn(route, 1).TestValid().TestDirection(TurnDirection::TurnLeft); + integration::GetNthTurn(route, 2).TestValid().TestDirection(TurnDirection::TurnSlightRight); + integration::GetNthTurn(route, 3).TestValid().TestDirection(TurnDirection::TurnLeft); + + integration::TestRouteLength(route, 420.0); +} + +UNIT_TEST(RussiaMoscowSvobodiOnewayBicycleWayTurnTest) +{ + TRouteResult const routeResult = integration::CalculateRoute( + integration::GetBicycleComponents(), MercatorBounds::FromLatLon(55.87277, 37.44002), + {0.0, 0.0}, MercatorBounds::FromLatLon(55.87362, 37.43853)); + + Route const & route = *routeResult.first; + IRouter::ResultCode const result = routeResult.second; + TEST_EQUAL(result, IRouter::NoError, ()); + + integration::TestTurnCount(route, 3); + + integration::GetNthTurn(route, 0).TestValid().TestDirection(TurnDirection::TurnLeft); + integration::GetNthTurn(route, 1).TestValid().TestDirection(TurnDirection::TurnLeft); + integration::GetNthTurn(route, 2).TestValid().TestDirection(TurnDirection::TurnLeft); + + integration::TestRouteLength(route, 768.0); +} diff --git a/routing/routing_tests/road_graph_builder.cpp b/routing/routing_tests/road_graph_builder.cpp index 00f8f55d95..158dec6321 100644 --- a/routing/routing_tests/road_graph_builder.cpp +++ b/routing/routing_tests/road_graph_builder.cpp @@ -84,7 +84,7 @@ double RoadGraphMockSource::GetMaxSpeedKMPH() const } void RoadGraphMockSource::ForEachFeatureClosestToCross(m2::PointD const & /* cross */, - CrossEdgesLoader & edgesLoader) const + ICrossEdgesLoader & edgesLoader) const { for (size_t roadId = 0; roadId < m_roads.size(); ++roadId) edgesLoader(MakeTestFeatureID(roadId), m_roads[roadId]); @@ -110,6 +110,11 @@ void RoadGraphMockSource::GetJunctionTypes(Junction const & junction, feature::T UNUSED_VALUE(types); } +IRoadGraph::Mode RoadGraphMockSource::GetMode() const +{ + return IRoadGraph::Mode::IgnoreOnewayTag; +} + FeatureID MakeTestFeatureID(uint32_t offset) { static TestValidFeatureIDProvider instance; diff --git a/routing/routing_tests/road_graph_builder.hpp b/routing/routing_tests/road_graph_builder.hpp index 9501c9f4ed..bb7c2a6240 100644 --- a/routing/routing_tests/road_graph_builder.hpp +++ b/routing/routing_tests/road_graph_builder.hpp @@ -17,11 +17,12 @@ public: double GetSpeedKMPH(FeatureID const & featureId) const override; double GetMaxSpeedKMPH() const override; void ForEachFeatureClosestToCross(m2::PointD const & cross, - CrossEdgesLoader & edgeLoader) const override; + ICrossEdgesLoader & edgeLoader) const override; void FindClosestEdges(m2::PointD const & point, uint32_t count, vector<pair<routing::Edge, m2::PointD>> & vicinities) const override; void GetFeatureTypes(FeatureID const & featureId, feature::TypesHolder & types) const override; void GetJunctionTypes(routing::Junction const & junction, feature::TypesHolder & types) const override; + routing::IRoadGraph::Mode GetMode() const override; private: vector<RoadInfo> m_roads; diff --git a/routing/vehicle_model.hpp b/routing/vehicle_model.hpp index 17b7d91fe8..dbd1ef5205 100644 --- a/routing/vehicle_model.hpp +++ b/routing/vehicle_model.hpp @@ -64,6 +64,12 @@ public: //@} double GetSpeed(feature::TypesHolder const & types) const; + + /// \returns true if |types| is a oneway feature. + /// \note According to OSM tag "oneway" could have value "-1". That means it's a oneway feature + /// with reversed geometry. In that case while map generation the geometry of such features + /// is reversed (the order of points is changed) so in vehicle model all oneway feature + /// could be considered as features with forward geometry. bool IsOneWay(feature::TypesHolder const & types) const; bool IsRoad(FeatureType const & f) const; |