Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Shalnev <c.shalnev@corp.mail.ru>2016-05-30 11:32:31 +0300
committerKonstantin Shalnev <c.shalnev@corp.mail.ru>2016-05-30 11:32:31 +0300
commitbb67816403f8fe94b6593fd4f63cf44fd7469877 (patch)
treea100d2ed84faa80e2773156dd0dbb69858d3114a /routing
parent82821e1ed30d9e923a08ea5a1fecaeabaac382ce (diff)
parent8f7da1501a7382a7ee16641fc459ee4354f43d37 (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.hpp1
-rw-r--r--routing/features_road_graph.cpp31
-rw-r--r--routing/features_road_graph.hpp9
-rw-r--r--routing/road_graph.cpp109
-rw-r--r--routing/road_graph.hpp88
-rw-r--r--routing/road_graph_router.cpp33
-rw-r--r--routing/road_graph_router.hpp6
-rw-r--r--routing/routing_integration_tests/bicycle_turn_test.cpp45
-rw-r--r--routing/routing_tests/road_graph_builder.cpp7
-rw-r--r--routing/routing_tests/road_graph_builder.hpp3
-rw-r--r--routing/vehicle_model.hpp6
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;