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:
authorVladimir Byko-Ianko <v.bykoianko@corp.mail.ru>2015-05-18 16:47:11 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:48:02 +0300
commitb9d22c8fb11a9e7bd526ec3852b0d16fb5ec44e4 (patch)
tree9bfad4c0dfbc4ad993a01a71e3c650b9b5ab414a
parent8fd9d2fff3e186a42ae64b41cbc72d55e804897a (diff)
Changes after colleagues comments.
-rw-r--r--indexer/ftypes_matcher.cpp4
-rw-r--r--indexer/ftypes_matcher.hpp1
-rw-r--r--integration_tests/osrm_turn_test.cpp18
-rw-r--r--routing/osrm_router.cpp68
-rw-r--r--routing/osrm_router.hpp30
-rw-r--r--routing/routing_tests/turns_generator_test.cpp37
-rw-r--r--routing/turns.hpp2
-rw-r--r--routing/turns_generator.cpp128
-rw-r--r--routing/turns_generator.hpp33
9 files changed, 180 insertions, 141 deletions
diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp
index a8c5faa37e..cf90ae2985 100644
--- a/indexer/ftypes_matcher.cpp
+++ b/indexer/ftypes_matcher.cpp
@@ -4,6 +4,8 @@
#include "indexer/feature_data.hpp"
#include "indexer/classificator.hpp"
+#include "std/sstream.hpp"
+#include "std/utility.hpp"
namespace ftypes
{
@@ -332,7 +334,7 @@ string DebugPrint(HighwayClass const cls)
HighwayClass GetHighwayClass(feature::TypesHolder const & types)
{
Classificator const & c = classif();
- vector<pair<HighwayClass, uint32_t>> const kHighwayClasses = {
+ static pair<HighwayClass, uint32_t> const kHighwayClasses[] = {
{HighwayClass::Trunk, c.GetTypeByPath({"highway", "motorway"})},
{HighwayClass::Trunk, c.GetTypeByPath({"highway", "motorway_link"})},
{HighwayClass::Trunk, c.GetTypeByPath({"highway", "trunk"})},
diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp
index c9eebf6c30..ac3a918a47 100644
--- a/indexer/ftypes_matcher.hpp
+++ b/indexer/ftypes_matcher.hpp
@@ -150,6 +150,7 @@ enum class HighwayClass
Service,
Count // This value is used for internals only.
};
+
string DebugPrint(HighwayClass const cls);
HighwayClass GetHighwayClass(feature::TypesHolder const & types);
diff --git a/integration_tests/osrm_turn_test.cpp b/integration_tests/osrm_turn_test.cpp
index a128f61676..d1dfe0b5eb 100644
--- a/integration_tests/osrm_turn_test.cpp
+++ b/integration_tests/osrm_turn_test.cpp
@@ -124,7 +124,7 @@ UNIT_TEST(RussiaMoscowTTKKashirskoeShosseOutTurnTest)
TEST_EQUAL(result, OsrmRouter::NoError, ());
integration::TestTurnCount(route, 1);
- // Checking a turn in case going from not a link to a link
+ // Checking a turn in case going from a not-link to a link
integration::GetNthTurn(route, 0).TestValid().TestOneOfDirections(
{TurnDirection::TurnSlightRight, TurnDirection::TurnRight});
}
@@ -207,8 +207,7 @@ UNIT_TEST(BelarusMiskProspNezavisimostiMKADTurnTest)
UNIT_TEST(RussiaMoscowPetushkovaPetushkovaTest)
{
TRouteResult const routeResult = integration::CalculateRoute(
- integration::GetAllMaps(), {37.405555547431582, 67.606396877452852}, {0., 0.},
- {37.404889653177761, 67.607659749718096});
+ integration::GetAllMaps(), {37.40555, 67.60640}, {0., 0.}, {37.40489, 67.60766});
Route const & route = *routeResult.first;
OsrmRouter::ResultCode const result = routeResult.second;
@@ -217,13 +216,12 @@ UNIT_TEST(RussiaMoscowPetushkovaPetushkovaTest)
integration::GetNthTurn(route, 0).TestValid().TestDirection(TurnDirection::TurnLeft);
}
-// Test case: a route goes straightly along a unnamed big link road when joined a small road.
+// Test case: a route goes straight along a unnamed big link road when joined a small road.
// An end user shall not be informed about such manoeuvres.
UNIT_TEST(RussiaMoscowMKADLeningradkaTest)
{
TRouteResult const routeResult = integration::CalculateRoute(
- integration::GetAllMaps(), {37.438582086802406, 67.683581448033891}, {0., 0.},
- {37.448852064651611, 67.681148387254225});
+ integration::GetAllMaps(), {37.43858, 67.68358}, {0., 0.}, {37.44885, 67.68115});
Route const & route = *routeResult.first;
OsrmRouter::ResultCode const result = routeResult.second;
@@ -234,8 +232,7 @@ UNIT_TEST(RussiaMoscowMKADLeningradkaTest)
UNIT_TEST(BelarusMKADShosseinai)
{
TRouteResult const routeResult = integration::CalculateRoute(
- integration::GetAllMaps(), {29.431229709918465, 66.684863888688056}, {0., 0.},
- {29.426264439664614, 66.686867924003238});
+ integration::GetAllMaps(), {29.43123, 66.68486}, {0., 0.}, {29.42626, 66.68687});
Route const & route = *routeResult.first;
OsrmRouter::ResultCode const result = routeResult.second;
@@ -245,13 +242,12 @@ UNIT_TEST(BelarusMKADShosseinai)
{TurnDirection::GoStraight, TurnDirection::TurnSlightRight});
}
-// Test case: a route goes straightly along a unnamed big road when joined small road.
+// Test case: a route goes straight along a unnamed big road when joined small road.
// An end user shall not be informed about such manoeuvres.
UNIT_TEST(ThailandPhuketNearPrabarameeRoad)
{
TRouteResult const routeResult = integration::CalculateRoute(
- integration::GetAllMaps(), {98.369368627299635, 7.9432901571200318}, {0., 0.},
- {98.367845572071232, 7.9324732487227401});
+ integration::GetAllMaps(), {98.36937, 7.94330}, {0., 0.}, {98.36785, 7.93247});
Route const & route = *routeResult.first;
OsrmRouter::ResultCode const result = routeResult.second;
diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp
index b243537ca6..d4f2a903ca 100644
--- a/routing/osrm_router.cpp
+++ b/routing/osrm_router.cpp
@@ -114,21 +114,14 @@ public:
size_t const count = ft.GetPointsCount();
ASSERT_GREATER(count, 1, ());
- auto addAngle = [&](m2::PointD const & p, m2::PointD const & p1, m2::PointD const & p2)
- {
- double const a = my::RadToDeg(ang::TwoVectorsAngle(p, p1, p2));
- if (!my::AlmostEqual(a, 0.))
- m_candidates.push_back(a);
- };
-
for (size_t i = 0; i < count; ++i)
{
if (MercatorBounds::DistanceOnEarth(m_p, ft.GetPoint(i)) < FEATURES_NEAR_TURN_M)
{
if (i > 0)
- addAngle(m_p, m_p1, ft.GetPoint(i - 1));
+ m_candidates.push_back(my::RadToDeg(ang::TwoVectorsAngle(m_p, m_p1, ft.GetPoint(i - 1))));
if (i < count - 1)
- addAngle(m_p, m_p1, ft.GetPoint(i + 1));
+ m_candidates.push_back(my::RadToDeg(ang::TwoVectorsAngle(m_p, m_p1, ft.GetPoint(i + 1))));
return;
}
}
@@ -1272,7 +1265,7 @@ NodeID OsrmRouter::GetTurnTargetNode(NodeID src, NodeID trg, QueryEdge::EdgeData
void OsrmRouter::GetPossibleTurns(NodeID node, m2::PointD const & p1, m2::PointD const & p,
RoutingMappingPtrT const & routingMapping,
- turns::TurnCandidatesT & candidates)
+ turns::TTurnCandidates & candidates)
{
ASSERT(routingMapping.get(), ());
for (EdgeID e : routingMapping->m_dataFacade.GetAdjacentEdgeRange(node))
@@ -1309,7 +1302,7 @@ void OsrmRouter::GetPossibleTurns(NodeID node, m2::PointD const & p1, m2::PointD
return t1.m_node < t2.m_node;
});
- auto last = unique(candidates.begin(), candidates.end(),
+ auto const last = unique(candidates.begin(), candidates.end(),
[](turns::TurnCandidate const & t1, turns::TurnCandidate const & t2)
{
return t1.m_node == t2.m_node;
@@ -1323,31 +1316,26 @@ void OsrmRouter::GetPossibleTurns(NodeID node, m2::PointD const & p1, m2::PointD
});
}
-void OsrmRouter::GetTurnGeometry(m2::PointD const & p, m2::PointD const & p1,
+void OsrmRouter::GetTurnGeometry(m2::PointD const & junctionPoint, m2::PointD const & ingoingPoint,
GeomTurnCandidateT & candidates,
RoutingMappingPtrT const & mapping) const
{
ASSERT(mapping.get(), ());
- Point2Geometry getter(p, p1, candidates);
- m_pIndex->ForEachInRectForMWM(getter, MercatorBounds::RectByCenterXYAndSizeInMeters(p, FEATURES_NEAR_TURN_M),
- scales::GetUpperScale(), mapping->GetMwmId());
+ Point2Geometry getter(junctionPoint, ingoingPoint, candidates);
+ m_pIndex->ForEachInRectForMWM(
+ getter, MercatorBounds::RectByCenterXYAndSizeInMeters(junctionPoint, FEATURES_NEAR_TURN_M),
+ scales::GetUpperScale(), mapping->GetMwmId());
}
-bool OsrmRouter::KeepOnewayOutgoingTurnIncomingEdges(turns::TurnDirection intermediateTurnDirection,
- m2::PointD const & p,
- m2::PointD const & p1OneSeg,
- RoutingMappingPtrT const & mapping)
+size_t OsrmRouter::NumberOfIngoingAndOutgoingSegments(m2::PointD const & junctionPoint,
+ m2::PointD const & ingoingPointOneSegment,
+ RoutingMappingPtrT const & mapping) const
{
ASSERT(mapping.get(), ());
- size_t const outgoingNotesCount = 1;
- if (turns::IsGoStraightOrSlightTurn(intermediateTurnDirection))
- return false;
GeomTurnCandidateT geoNodes;
- GetTurnGeometry(p, p1OneSeg, geoNodes, mapping);
- if (geoNodes.size() <= outgoingNotesCount)
- return false;
- return true;
+ GetTurnGeometry(junctionPoint, ingoingPointOneSegment, geoNodes, mapping);
+ return geoNodes.size();
}
// @todo(vbykoianko) Move this method and all dependencies to turns_generator.cpp
@@ -1393,7 +1381,7 @@ void OsrmRouter::GetTurnDirection(PathData const & node1,
double const a = my::RadToDeg(ang::TwoVectorsAngle(p, p1, p2));
m2::PointD const p1OneSeg = ft1.GetPoint(seg1.m_pointStart < seg1.m_pointEnd ? seg1.m_pointEnd - 1 : seg1.m_pointEnd + 1);
- turns::TurnCandidatesT nodes;
+ turns::TTurnCandidates nodes;
GetPossibleTurns(node1.node, p1OneSeg, p, routingMapping, nodes);
turn.m_turn = turns::TurnDirection::NoTurn;
@@ -1412,12 +1400,13 @@ void OsrmRouter::GetTurnDirection(PathData const & node1,
else
turn.m_turn = turns::IntermediateDirection(a);
- bool const isRound1 = ftypes::IsRoundAboutChecker::Instance()(ft1);
- bool const isRound2 = ftypes::IsRoundAboutChecker::Instance()(ft2);
+ bool const isIngoingEdgeRoundabout = ftypes::IsRoundAboutChecker::Instance()(ft1);
+ bool const isOutgoingEdgeRoundabout = ftypes::IsRoundAboutChecker::Instance()(ft2);
- if (isRound1 || isRound2)
+ if (isIngoingEdgeRoundabout || isOutgoingEdgeRoundabout)
{
- turn.m_turn = turns::RoundaboutDirection(isRound1, isRound2, hasMultiTurns);
+ turn.m_turn = turns::GetRoundaboutDirection(isIngoingEdgeRoundabout, isOutgoingEdgeRoundabout,
+ hasMultiTurns);
return;
}
@@ -1437,18 +1426,22 @@ void OsrmRouter::GetTurnDirection(PathData const & node1,
ftypes::HighwayClass const highwayClass1 = ftypes::GetHighwayClass(ft1);
ftypes::HighwayClass const highwayClass2 = ftypes::GetHighwayClass(ft2);
if (!turn.m_keepAnyway &&
- !turns::KeepMultiTurnClassHighwayClass(highwayClass1, highwayClass2, node2.node, turn.m_turn,
- nodes, *routingMapping, *m_pIndex))
+ !turns::HighwayClassFilter(highwayClass1, highwayClass2, node2.node, turn.m_turn, nodes,
+ *routingMapping, *m_pIndex))
{
turn.m_turn = turns::TurnDirection::NoTurn;
return;
}
+ bool const isGoStraightOrSlightTurn =
+ turns::IsGoStraightOrSlightTurn(turns::IntermediateDirection(my::RadToDeg(ang::TwoVectorsAngle(p,p1OneSeg, p2))));
+ // The code below is resposible for cases when there is only one way to leave the junction.
+ // Such junction has to be kept as a turn when
+ // * it's not a slight turn and it has ingoing edges (one or more);
+ // * it's an entrance to a roundabout;
if (!hasMultiTurns &&
- !KeepOnewayOutgoingTurnIncomingEdges(
- turns::IntermediateDirection(my::RadToDeg(ang::TwoVectorsAngle(p, p1OneSeg, p2))), p,
- p1OneSeg, routingMapping) &&
- !turns::KeepOnewayOutgoingTurnRoundabout(isRound1, isRound2))
+ (isGoStraightOrSlightTurn || NumberOfIngoingAndOutgoingSegments(p, p1OneSeg, routingMapping) <= 2) &&
+ !turns::CheckRoundaboutEntrance(isIngoingEdgeRoundabout, isOutgoingEdgeRoundabout))
{
turn.m_turn = turns::TurnDirection::NoTurn;
return;
@@ -1462,6 +1455,7 @@ void OsrmRouter::GetTurnDirection(PathData const & node1,
return;
}
+ // @todo(vbykoianko) Checking if it's a uturn or not shall be moved to FindDirectionByAngle.
if (turn.m_turn == turns::TurnDirection::NoTurn)
turn.m_turn = turns::TurnDirection::UTurn;
}
diff --git a/routing/osrm_router.hpp b/routing/osrm_router.hpp
index e394835e4a..e37406f4c2 100644
--- a/routing/osrm_router.hpp
+++ b/routing/osrm_router.hpp
@@ -188,7 +188,7 @@ private:
NodeID GetTurnTargetNode(NodeID src, NodeID trg, QueryEdge::EdgeData const & edgeData, RoutingMappingPtrT const & routingMapping);
void GetPossibleTurns(NodeID node, m2::PointD const & p1, m2::PointD const & p,
RoutingMappingPtrT const & routingMapping,
- turns::TurnCandidatesT & candidates);
+ turns::TTurnCandidates & candidates);
void GetTurnDirection(PathData const & node1,
PathData const & node2,
RoutingMappingPtrT const & routingMapping,
@@ -196,11 +196,29 @@ private:
m2::PointD GetPointForTurnAngle(OsrmMappingTypes::FtSeg const & seg,
FeatureType const & ft, m2::PointD const & turnPnt,
size_t (*GetPndInd)(const size_t, const size_t, const size_t)) const;
- bool KeepOnewayOutgoingTurnIncomingEdges(turns::TurnDirection intermediateTurnDirection,
- m2::PointD const & p, m2::PointD const & p1,
- RoutingMappingPtrT const & mapping);
- void GetTurnGeometry(m2::PointD const & p, m2::PointD const & p1, GeomTurnCandidateT & candidates,
- RoutingMappingPtrT const & mapping) const;
+ /*!
+ * \param junctionPoint is a point of the junction.
+ * \param ingoingPointOneSegment is a point one segment before the junction along the route.
+ * \param mapping is a route mapping.
+ * \return number of all the segments which joins junctionPoint. That means
+ * the number of ingoing segments plus the number of outgoing segments.
+ * \warning NumberOfIngoingAndOutgoingSegments should be used carefully because
+ * it's a time-consuming function.
+ * \warning In multilevel crossroads there is an insignificant possibility that the returned value
+ * contains redundant segments of roads of different levels.
+ */
+ size_t NumberOfIngoingAndOutgoingSegments(m2::PointD const & junctionPoint,
+ m2::PointD const & ingoingPointOneSegment,
+ RoutingMappingPtrT const & mapping) const;
+ /*!
+ * \brief GetTurnGeometry looks for all the road network edges near ingoingPoint.
+ * GetTurnGeometry fills candidates with angles of all the incoming and outgoint segments.
+ * \warning GetTurnGeometry should be used carefully because it's a time-consuming function.
+ * \warning In multilevel crossroads there is an insignificant possibility that candidates
+ * is filled with redundant segments of roads of different levels.
+ */
+ void GetTurnGeometry(m2::PointD const & junctionPoint, m2::PointD const & ingoingPoint,
+ GeomTurnCandidateT & candidates, RoutingMappingPtrT const & mapping) const;
Index const * m_pIndex;
diff --git a/routing/routing_tests/turns_generator_test.cpp b/routing/routing_tests/turns_generator_test.cpp
index 3741d18ca6..5e0bd1b40c 100644
--- a/routing/routing_tests/turns_generator_test.cpp
+++ b/routing/routing_tests/turns_generator_test.cpp
@@ -294,20 +294,25 @@ UNIT_TEST(TestAddingActiveLaneInformation)
TEST(!turns[1].m_lanes[1].m_isRecommended, ());
}
-UNIT_TEST(TestRoundaboutDirection)
+UNIT_TEST(TestGetRoundaboutDirection)
{
- TEST_EQUAL(RoundaboutDirection(true, true, true), TurnDirection::StayOnRoundAbout, ());
- TEST_EQUAL(RoundaboutDirection(true, true, false), TurnDirection::NoTurn, ());
- TEST_EQUAL(RoundaboutDirection(false, true, false), TurnDirection::EnterRoundAbout, ());
- TEST_EQUAL(RoundaboutDirection(true, false, false), TurnDirection::LeaveRoundAbout, ());
+ // The signature of GetRoundaboutDirection function is
+ // GetRoundaboutDirection(bool isIngoingEdgeRoundabout, bool isOutgoingEdgeRoundabout, bool
+ // isJunctionOfSeveralTurns)
+ TEST_EQUAL(GetRoundaboutDirection(true, true, true), TurnDirection::StayOnRoundAbout, ());
+ TEST_EQUAL(GetRoundaboutDirection(true, true, false), TurnDirection::NoTurn, ());
+ TEST_EQUAL(GetRoundaboutDirection(false, true, false), TurnDirection::EnterRoundAbout, ());
+ TEST_EQUAL(GetRoundaboutDirection(true, false, false), TurnDirection::LeaveRoundAbout, ());
}
-UNIT_TEST(TestKeepOnewayOutgoingTurnRoundabout)
+UNIT_TEST(TestCheckRoundaboutEntrance)
{
- TEST(!KeepOnewayOutgoingTurnRoundabout(true, true), ());
- TEST(!KeepOnewayOutgoingTurnRoundabout(false, false), ());
- TEST(!KeepOnewayOutgoingTurnRoundabout(true, false), ());
- TEST(KeepOnewayOutgoingTurnRoundabout(false, true), ());
+ // The signature of GetRoundaboutDirection function is
+ // CheckRoundaboutEntrance(bool isIngoingEdgeRoundabout, bool isOutgoingEdgeRoundabout)
+ TEST(!CheckRoundaboutEntrance(true, true), ());
+ TEST(!CheckRoundaboutEntrance(false, false), ());
+ TEST(!CheckRoundaboutEntrance(true, false), ());
+ TEST(CheckRoundaboutEntrance(false, true), ());
}
UNIT_TEST(TestInvertDirection)
@@ -324,24 +329,36 @@ UNIT_TEST(TestInvertDirection)
UNIT_TEST(TestMostRightDirection)
{
TEST_EQUAL(MostRightDirection(0.), TurnDirection::NoTurn, ());
+ TEST_EQUAL(MostRightDirection(10.), TurnDirection::NoTurn, ());
TEST_EQUAL(MostRightDirection(90.), TurnDirection::TurnRight, ());
+ TEST_EQUAL(MostRightDirection(135.), TurnDirection::TurnRight, ());
TEST_EQUAL(MostRightDirection(180.), TurnDirection::TurnSlightRight, ());
+ TEST_EQUAL(MostRightDirection(200.), TurnDirection::GoStraight, ());
TEST_EQUAL(MostRightDirection(270.), TurnDirection::TurnLeft, ());
+ TEST_EQUAL(MostRightDirection(350.), TurnDirection::NoTurn, ());
}
UNIT_TEST(TestMostLeftDirection)
{
TEST_EQUAL(MostLeftDirection(0.), TurnDirection::NoTurn, ());
+ TEST_EQUAL(MostLeftDirection(10.), TurnDirection::NoTurn, ());
TEST_EQUAL(MostLeftDirection(90.), TurnDirection::TurnRight, ());
+ TEST_EQUAL(MostLeftDirection(135.), TurnDirection::TurnSlightRight, ());
TEST_EQUAL(MostLeftDirection(180.), TurnDirection::TurnSlightLeft, ());
+ TEST_EQUAL(MostLeftDirection(200.), TurnDirection::TurnSlightLeft, ());
TEST_EQUAL(MostLeftDirection(270.), TurnDirection::TurnLeft, ());
+ TEST_EQUAL(MostLeftDirection(350.), TurnDirection::NoTurn, ());
}
UNIT_TEST(TestIntermediateDirection)
{
TEST_EQUAL(IntermediateDirection(0.), TurnDirection::NoTurn, ());
+ TEST_EQUAL(IntermediateDirection(10.), TurnDirection::NoTurn, ());
TEST_EQUAL(IntermediateDirection(90.), TurnDirection::TurnRight, ());
+ TEST_EQUAL(IntermediateDirection(135.), TurnDirection::TurnSlightRight, ());
TEST_EQUAL(IntermediateDirection(180.), TurnDirection::GoStraight, ());
+ TEST_EQUAL(IntermediateDirection(200.), TurnDirection::TurnSlightLeft, ());
TEST_EQUAL(IntermediateDirection(270.), TurnDirection::TurnLeft, ());
+ TEST_EQUAL(IntermediateDirection(350.), TurnDirection::NoTurn, ());
}
} // namespace
diff --git a/routing/turns.hpp b/routing/turns.hpp
index 9e3160dea1..77db7774ad 100644
--- a/routing/turns.hpp
+++ b/routing/turns.hpp
@@ -109,7 +109,7 @@ struct TurnCandidate
TurnCandidate(double a, NodeID n) : m_angle(a), m_node(n) {}
};
-typedef vector<TurnCandidate> TurnCandidatesT;
+typedef vector<TurnCandidate> TTurnCandidates;
string const GetTurnString(TurnDirection turn);
diff --git a/routing/turns_generator.cpp b/routing/turns_generator.cpp
index b948314ba4..6502bb975a 100644
--- a/routing/turns_generator.cpp
+++ b/routing/turns_generator.cpp
@@ -33,6 +33,33 @@ bool FixupLaneSet(TurnDirection turn, vector<SingleLaneInfo> & lanes,
}
return isLaneConformed;
}
+
+// Converts a turn angle (double) into a turn direction (TurnDirection).
+// upperBounds is a table of pairs: an angle and a direction.
+// upperBounds shall be sorted by the first parameter (angle) from small angles to big angles.
+// These angles should be measured in degrees and should belong to the range [0; 360].
+// The second paramer (angle) shall be greater than or equal to zero and is measured in degrees.
+TurnDirection FindDirectionByAngle(vector<pair<double, TurnDirection>> const & upperBounds,
+ double angle)
+{
+ ASSERT_GREATER_OR_EQUAL(angle, 0., (angle));
+ ASSERT_LESS_OR_EQUAL(angle, 360., (angle));
+ ASSERT_GREATER(upperBounds.size(), 0, ());
+ ASSERT(is_sorted(upperBounds.cbegin(), upperBounds.cend(),
+ [](pair<double, TurnDirection> const & p1, pair<double, TurnDirection> const & p2)
+ {
+ return p1.first < p2.first;
+ }), ());
+
+ for (auto const & upper : upperBounds)
+ {
+ if (angle <= upper.first)
+ return upper.second;
+ }
+
+ ASSERT(false, ("The angle is not covered by the table. angle = ", angle));
+ return TurnDirection::NoTurn;
+}
} // namespace
namespace routing
@@ -182,10 +209,10 @@ void FixupTurns(vector<m2::PointD> const & points, Route::TurnsT & turnsDir)
// The better solution is to remove all "slight" turns if the route goes form one not-link road
// to another not-link road and other possible turns are links. But it's not possible to
// implement it quickly. To do that you need to calculate FeatureType for most possible turns.
- // But it is already made once in KeepMultiTurnClassHighwayClass(GetOutgoingHighwayClass).
- // So it's a good idea to keep FeatureType for outgoing turns in TurnCandidatesT
+ // But it is already made once in HighwayClassFilter(GetOutgoingHighwayClass).
+ // So it's a good idea to keep FeatureType for outgoing turns in TTurnCandidates
// (if they have been calculated). For the time being I decided to postpone the implementation
- // of the feature but it worth implementing it in the future.
+ // of the feature but it is worth implementing it in the future.
if (!t.m_keepAnyway && IsGoStraightOrSlightTurn(t.m_turn) && !t.m_sourceName.empty() &&
strings::AlmostEqual(t.m_sourceName, t.m_targetName, 2 /* mismatched symbols count */))
{
@@ -231,16 +258,16 @@ ftypes::HighwayClass GetOutgoingHighwayClass(NodeID outgoingNode,
return ftypes::GetHighwayClass(ft);
}
-bool KeepMultiTurnClassHighwayClass(ftypes::HighwayClass ingoingClass,
- ftypes::HighwayClass outgoingClass, NodeID outgoingNode,
- TurnDirection turn, TurnCandidatesT const & possibleTurns,
- RoutingMapping const & routingMapping, Index const & index)
+bool HighwayClassFilter(ftypes::HighwayClass ingoingClass, ftypes::HighwayClass outgoingClass,
+ NodeID outgoingNode, TurnDirection turn,
+ TTurnCandidates const & possibleTurns,
+ RoutingMapping const & routingMapping, Index const & index)
{
if (!IsGoStraightOrSlightTurn(turn))
return true; // The road significantly changes its direction here. So this turn shall be kept.
- if (possibleTurns.size() ==
- 1 /* There's only one exit from this vertex. NodeID of the exit is outgoingNode */)
+ // There's only one exit from this junction. NodeID of the exit is outgoingNode.
+ if (possibleTurns.size() == 1)
return true;
ftypes::HighwayClass maxClassForPossibleTurns = ftypes::HighwayClass::None;
@@ -277,24 +304,25 @@ bool KeepMultiTurnClassHighwayClass(ftypes::HighwayClass ingoingClass,
return true;
}
-bool KeepOnewayOutgoingTurnRoundabout(bool isRound1, bool isRound2)
+bool CheckRoundaboutEntrance(bool isIngoingEdgeRoundabout, bool isOutgoingEdgeRoundabout)
{
- return !isRound1 && isRound2;
+ return !isIngoingEdgeRoundabout && isOutgoingEdgeRoundabout;
}
-TurnDirection RoundaboutDirection(bool isRound1, bool isRound2, bool hasMultiTurns)
+TurnDirection GetRoundaboutDirection(bool isIngoingEdgeRoundabout, bool isOutgoingEdgeRoundabout,
+ bool isJunctionOfSeveralTurns)
{
- if (isRound1 && isRound2)
+ if (isIngoingEdgeRoundabout && isOutgoingEdgeRoundabout)
{
- if (hasMultiTurns)
+ if (isJunctionOfSeveralTurns)
return TurnDirection::StayOnRoundAbout;
return TurnDirection::NoTurn;
}
- if (!isRound1 && isRound2)
+ if (!isIngoingEdgeRoundabout && isOutgoingEdgeRoundabout)
return TurnDirection::EnterRoundAbout;
- if (isRound1 && !isRound2)
+ if (isIngoingEdgeRoundabout && !isOutgoingEdgeRoundabout)
return TurnDirection::LeaveRoundAbout;
ASSERT(false, ());
@@ -324,27 +352,17 @@ TurnDirection InvertDirection(TurnDirection dir)
TurnDirection MostRightDirection(const double angle)
{
- double const lowerSharpRightBound = 23.;
- double const upperSharpRightBound = 67.;
- double const upperRightBound = 140.;
- double const upperSlightRight = 195.;
- double const upperGoStraitBound = 205.;
- double const upperSlightLeftBound = 240.;
- double const upperLeftBound = 336.;
-
- if (angle >= lowerSharpRightBound && angle < upperSharpRightBound)
- return TurnDirection::TurnSharpRight;
- else if (angle >= upperSharpRightBound && angle < upperRightBound)
- return TurnDirection::TurnRight;
- else if (angle >= upperRightBound && angle < upperSlightRight)
- return TurnDirection::TurnSlightRight;
- else if (angle >= upperSlightRight && angle < upperGoStraitBound)
- return TurnDirection::GoStraight;
- else if (angle >= upperGoStraitBound && angle < upperSlightLeftBound)
- return TurnDirection::TurnSlightLeft;
- else if (angle >= upperSlightLeftBound && angle < upperLeftBound)
- return TurnDirection::TurnLeft;
- return TurnDirection::NoTurn;
+ static vector<pair<double, TurnDirection>> const kUpperBounds = {
+ {23., TurnDirection::NoTurn},
+ {67., TurnDirection::TurnSharpRight},
+ {140., TurnDirection::TurnRight},
+ {195., TurnDirection::TurnSlightRight},
+ {205., TurnDirection::GoStraight},
+ {240., TurnDirection::TurnSlightLeft},
+ {336., TurnDirection::TurnLeft},
+ {360., TurnDirection::NoTurn}};
+
+ return FindDirectionByAngle(kUpperBounds, angle);
}
TurnDirection MostLeftDirection(const double angle)
@@ -354,30 +372,18 @@ TurnDirection MostLeftDirection(const double angle)
TurnDirection IntermediateDirection(const double angle)
{
- double const lowerSharpRightBound = 23.;
- double const upperSharpRightBound = 67.;
- double const upperRightBound = 130.;
- double const upperSlightRight = 170.;
- double const upperGoStraitBound = 190.;
- double const upperSlightLeftBound = 230.;
- double const upperLeftBound = 292.;
- double const upperSharpLeftBound = 336.;
-
- if (angle >= lowerSharpRightBound && angle < upperSharpRightBound)
- return TurnDirection::TurnSharpRight;
- else if (angle >= upperSharpRightBound && angle < upperRightBound)
- return TurnDirection::TurnRight;
- else if (angle >= upperRightBound && angle < upperSlightRight)
- return TurnDirection::TurnSlightRight;
- else if (angle >= upperSlightRight && angle < upperGoStraitBound)
- return TurnDirection::GoStraight;
- else if (angle >= upperGoStraitBound && angle < upperSlightLeftBound)
- return TurnDirection::TurnSlightLeft;
- else if (angle >= upperSlightLeftBound && angle < upperLeftBound)
- return TurnDirection::TurnLeft;
- else if (angle >= upperLeftBound && angle < upperSharpLeftBound)
- return TurnDirection::TurnSharpLeft;
- return TurnDirection::NoTurn;
+ static vector<pair<double, TurnDirection>> const kUpperBounds = {
+ {23., TurnDirection::NoTurn},
+ {67., TurnDirection::TurnSharpRight},
+ {130., TurnDirection::TurnRight},
+ {170., TurnDirection::TurnSlightRight},
+ {190., TurnDirection::GoStraight},
+ {230., TurnDirection::TurnSlightLeft},
+ {292., TurnDirection::TurnLeft},
+ {336., TurnDirection::TurnSharpLeft},
+ {360., TurnDirection::NoTurn}};
+
+ return FindDirectionByAngle(kUpperBounds, angle);
}
} // namespace turns
} // namespace routing
diff --git a/routing/turns_generator.hpp b/routing/turns_generator.hpp
index d26cac0abb..162ab3e042 100644
--- a/routing/turns_generator.hpp
+++ b/routing/turns_generator.hpp
@@ -19,7 +19,7 @@ struct RoutingMapping;
namespace turns
{
-/// Returns a segment index by STL-like range [s, e) of segments indices for passed node.
+// Returns a segment index by STL-like range [s, e) of segments indices for the passed node.
typedef function<size_t(pair<size_t, size_t>)> TGetIndexFunction;
size_t GetFirstSegmentPointIndex(pair<size_t, size_t> const & p);
@@ -27,12 +27,11 @@ OsrmMappingTypes::FtSeg GetSegment(NodeID node, RoutingMapping const & routingMa
TGetIndexFunction GetIndex);
vector<SingleLaneInfo> GetLanesInfo(NodeID node, RoutingMapping const & routingMapping,
TGetIndexFunction GetIndex, Index const & index);
-/// CalculateTurnGeometry calculates geometry for all the turns. That means that for every turn
-/// CalculateTurnGeometry calculates a sequence of points which will be used
-/// for displaying arrows on the route.
+// Returns geometry for all the turns. That means that for every turn CalculateTurnGeometry calculates
+// a sequence of points.
void CalculateTurnGeometry(vector<m2::PointD> const & points, Route::TurnsT const & turnsDir,
TurnsGeomT & turnsGeom);
-/// Selects lanes which are recommended for an end user.
+// Selects lanes which are recommended for an end user.
void SelectRecommendedLanes(Route::TurnsT & turnsDir);
void FixupTurns(vector<m2::PointD> const & points, Route::TurnsT & turnsDir);
ftypes::HighwayClass GetOutgoingHighwayClass(NodeID node, RoutingMapping const & routingMapping,
@@ -42,14 +41,20 @@ TurnDirection MostRightDirection(double angle);
TurnDirection MostLeftDirection(double angle);
TurnDirection IntermediateDirection(double angle);
-bool KeepOnewayOutgoingTurnRoundabout(bool isRound1, bool isRound2);
-/// Returns false (that means it removes the turn between ingoingClass and outgoingClass)
-/// if (1) the route leads from one big road to another one; (2) the other possible turns lead to
-/// small roads; and (2) turn is GoStraight or TurnSlight*.
-bool KeepMultiTurnClassHighwayClass(ftypes::HighwayClass ingoingClass,
- ftypes::HighwayClass outgoingClass, NodeID outgoingNode,
- TurnDirection turn, TurnCandidatesT const & possibleTurns,
- RoutingMapping const & routingMapping, Index const & index);
-TurnDirection RoundaboutDirection(bool isRound1, bool isRound2, bool hasMultiTurns);
+// Returns true if the route enters a roundabout.
+// That means isIngoingEdgeRoundabout is false and isOutgoingEdgeRoundabout is true.
+bool CheckRoundaboutEntrance(bool isIngoingEdgeRoundabout, bool isOutgoingEdgeRoundabout);
+// Returns a turn instruction if an ingoing edge or (and) outgoing edge belongs to a roundabout.
+TurnDirection GetRoundaboutDirection(bool isIngoingEdgeRoundabout, bool isOutgoingEdgeRoundabout,
+ bool isJunctionOfSeveralTurns);
+
+// Returns false when
+// * the route leads from one big road to another one;
+// * and the other possible turns lead to small roads;
+// * and the turn is GoStraight or TurnSlight*.
+bool HighwayClassFilter(ftypes::HighwayClass ingoingClass, ftypes::HighwayClass outgoingClass,
+ NodeID outgoingNode, TurnDirection turn,
+ TTurnCandidates const & possibleTurns,
+ RoutingMapping const & routingMapping, Index const & index);
} // namespace routing
} // namespace turns