Merge pull request #3338 from bykoianko/master-velo-direction

[bicycle routing] "oneway" tag is taken into account while bicycle routing.
This commit is contained in:
Konstantin Shalnev 2016-05-30 11:32:31 +03:00
commit bb67816403
15 changed files with 288 additions and 112 deletions

View file

@ -74,4 +74,40 @@ UNIT_TEST(EqualsBy)
TEST_EQUAL(expected[i], actual[i].Get(), ());
}
}
UNIT_TEST(SortUnique)
{
{
vector<int> actual = {1, 2, 1, 4, 3, 5, 2, 7, 1};
my::SortUnique(actual);
vector<int> const expected = {1, 2, 3, 4, 5, 7};
TEST_EQUAL(actual, expected, ());
}
{
using TValue = int;
using TPair = pair<TValue, int>;
vector<TPair> v =
{{1, 22}, {2, 33}, {1, 23}, {4, 54}, {3, 34}, {5, 23}, {2, 23}, {7, 32}, {1, 12}};
my::SortUnique<TPair>(v, my::LessBy(&TPair::first), my::EqualsBy(&TPair::first));
vector<TValue> const expected = {1, 2, 3, 4, 5, 7};
TEST_EQUAL(v.size(), expected.size(), ());
for (int i = 0; i < v.size(); ++i)
TEST_EQUAL(v[i].first, expected[i], (i));
}
{
using TValue = double;
using TPair = pair<TValue, int>;
vector<TPair> v =
{{0.5, 11}, {1000.99, 234}, {0.5, 23}, {1234.56789, 54}, {1000.99, 34}};
my::SortUnique<TPair>(v, my::LessBy(&TPair::first), my::EqualsBy(&TPair::first));
vector<TValue> const expected = {0.5, 1000.99, 1234.56789};
TEST_EQUAL(v.size(), expected.size(), ());
for (int i = 0; i < v.size(); ++i)
TEST_EQUAL(v[i].first, expected[i], (i));
}
}
} // namespace

View file

@ -1,8 +1,11 @@
#pragma once
#include "std/algorithm.hpp"
#include "std/functional.hpp"
#include "std/utility.hpp"
#include "std/vector.hpp"
namespace my
{
namespace impl
@ -85,6 +88,16 @@ void SortUnique(vector<T> & v)
v.erase(unique(v.begin(), v.end()), v.end());
}
// Sorts according to |comp| and removes duplicate entries according to |pred| from |v|.
// Note. If several entries are equal according to |pred| an arbitrary entry of them
// is left in |v| after a call of this function.
template <typename T, typename TLess, typename TEquals>
void SortUnique(vector<T> & v, TLess && less, TEquals && equals)
{
sort(v.begin(), v.end(), forward<TLess>(less));
v.erase(unique(v.begin(), v.end(), forward<TEquals>(equals)), v.end());
}
template <typename T, class TFn>
void EraseIf(vector<T> & v, TFn && fn)
{

View file

@ -1035,7 +1035,7 @@ void Framework::StartInteractiveSearch(search::SearchParams const & params)
m_lastInteractiveSearchParams = params;
m_lastInteractiveSearchParams.SetForceSearch(false);
m_lastInteractiveSearchParams.SetMode(Mode::Viewport);
m_lastInteractiveSearchParams.SetMode(search::Mode::Viewport);
m_lastInteractiveSearchParams.SetSuggestsEnabled(false);
m_lastInteractiveSearchParams.m_onResults = [this](Results const & results)
{

View file

@ -94,7 +94,9 @@ unique_ptr<routing::IRouter> CreatePedestrianAStarTestRouter(Index & index, stor
auto UKGetter = [&](m2::PointD const & pt) { return cig.GetRegionCountryId(pt); };
unique_ptr<routing::IVehicleModelFactory> vehicleModelFactory(new SimplifiedPedestrianModelFactory());
unique_ptr<routing::IRoutingAlgorithm> algorithm(new routing::AStarRoutingAlgorithm());
unique_ptr<routing::IRouter> router(new routing::RoadGraphRouter("test-astar-pedestrian", index, UKGetter, move(vehicleModelFactory), move(algorithm), nullptr));
unique_ptr<routing::IRouter> router(new routing::RoadGraphRouter(
"test-astar-pedestrian", index, UKGetter, routing::IRoadGraph::Mode::IgnoreOnewayTag,
move(vehicleModelFactory), move(algorithm), nullptr));
return router;
}
@ -103,7 +105,9 @@ unique_ptr<routing::IRouter> CreatePedestrianAStarBidirectionalTestRouter(Index
auto UKGetter = [&](m2::PointD const & pt) { return cig.GetRegionCountryId(pt); };
unique_ptr<routing::IVehicleModelFactory> vehicleModelFactory(new SimplifiedPedestrianModelFactory());
unique_ptr<routing::IRoutingAlgorithm> algorithm(new routing::AStarBidirectionalRoutingAlgorithm());
unique_ptr<routing::IRouter> router(new routing::RoadGraphRouter("test-astar-bidirectional-pedestrian", index, UKGetter, move(vehicleModelFactory), move(algorithm), nullptr));
unique_ptr<routing::IRouter> router(new routing::RoadGraphRouter(
"test-astar-bidirectional-pedestrian", index, UKGetter, routing::IRoadGraph::Mode::IgnoreOnewayTag,
move(vehicleModelFactory), move(algorithm), nullptr));
return router;
}
@ -120,7 +124,8 @@ m2::PointD GetPointOnEdge(routing::Edge & e, double posAlong)
void GetNearestPedestrianEdges(Index & index, m2::PointD const & pt, vector<pair<routing::Edge, m2::PointD>> & edges)
{
unique_ptr<routing::IVehicleModelFactory> vehicleModelFactory(new SimplifiedPedestrianModelFactory());
routing::FeaturesRoadGraph roadGraph(index, move(vehicleModelFactory));
routing::FeaturesRoadGraph roadGraph(index, routing::IRoadGraph::Mode::IgnoreOnewayTag,
move(vehicleModelFactory));
roadGraph.FindClosestEdges(pt, 1 /*count*/, edges);
}

View file

@ -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:

View file

@ -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();

View file

@ -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;

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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;