From f041c28247bf7ca9aaaf1679d93d66ff46267977 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Fri, 2 Feb 2018 11:55:28 +0300 Subject: [PATCH] Analizing all the information about ingoing and outgoing edges before making make a decision about turn generation. --- .../bicycle_turn_test.cpp | 25 ++++++++----- .../street_names_test.cpp | 2 +- .../routing_integration_tests/turn_test.cpp | 13 +++---- routing/turns_generator.cpp | 35 +++++++++++-------- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/routing/routing_integration_tests/bicycle_turn_test.cpp b/routing/routing_integration_tests/bicycle_turn_test.cpp index 981b566ad5..a858a61925 100644 --- a/routing/routing_integration_tests/bicycle_turn_test.cpp +++ b/routing/routing_integration_tests/bicycle_turn_test.cpp @@ -18,9 +18,14 @@ UNIT_TEST(RussiaMoscowSevTushinoParkBicycleWayTurnTest) IRouter::ResultCode const result = routeResult.second; TEST_EQUAL(result, IRouter::NoError, ()); - integration::TestTurnCount(route, 2 /* expectedTurnCount */); - integration::GetNthTurn(route, 0).TestValid().TestDirection(CarDirection::TurnLeft); - integration::GetNthTurn(route, 1).TestValid().TestDirection(CarDirection::TurnLeft); + integration::TestTurnCount(route, 4 /* expectedTurnCount */); + integration::GetNthTurn(route, 0).TestValid().TestOneOfDirections( + {CarDirection::GoStraight, CarDirection::TurnSlightLeft}); + integration::GetNthTurn(route, 1).TestValid().TestOneOfDirections( + {CarDirection::GoStraight, CarDirection::TurnSlightRight}); + integration::GetNthTurn(route, 2).TestValid().TestDirection(CarDirection::TurnLeft); + integration::GetNthTurn(route, 3).TestValid().TestOneOfDirections( + {CarDirection::TurnSlightLeft, CarDirection::TurnLeft}); integration::TestRouteLength(route, 1054.0); } @@ -57,8 +62,8 @@ UNIT_TEST(RussiaMoscowSalameiNerisPossibleTurnCorrectionBicycleWayTurnTest) TEST_EQUAL(result, IRouter::NoError, ()); integration::TestTurnCount(route, 2 /* expectedTurnCount */); - integration::GetNthTurn(route, 0).TestValid().TestDirection(CarDirection::TurnRight); - integration::GetNthTurn(route, 1).TestValid().TestDirection(CarDirection::TurnLeft); + integration::GetNthTurn(route, 0).TestValid().TestDirection(CarDirection::TurnSlightLeft); + integration::GetNthTurn(route, 1).TestValid().TestDirection(CarDirection::TurnSlightLeft); } // Test that there's no uturn notification in case of zero point edges on two way edges. @@ -119,11 +124,15 @@ UNIT_TEST(RussiaMoscowSvobodiOnewayBicycleWayTurnTest) IRouter::ResultCode const result = routeResult.second; TEST_EQUAL(result, IRouter::NoError, ()); - integration::TestTurnCount(route, 3 /* expectedTurnCount */); + integration::TestTurnCount(route, 7 /* expectedTurnCount */); integration::GetNthTurn(route, 0).TestValid().TestDirection(CarDirection::TurnLeft); - integration::GetNthTurn(route, 1).TestValid().TestDirection(CarDirection::TurnLeft); - integration::GetNthTurn(route, 2).TestValid().TestDirection(CarDirection::TurnLeft); + integration::GetNthTurn(route, 1).TestValid().TestDirection(CarDirection::TurnSlightRight); + integration::GetNthTurn(route, 2).TestValid().TestDirection(CarDirection::TurnSlightLeft); + integration::GetNthTurn(route, 3).TestValid().TestDirection(CarDirection::GoStraight); + integration::GetNthTurn(route, 4).TestValid().TestDirection(CarDirection::TurnRight); + integration::GetNthTurn(route, 5).TestValid().TestDirection(CarDirection::TurnLeft); + integration::GetNthTurn(route, 6).TestValid().TestDirection(CarDirection::TurnLeft); integration::TestRouteLength(route, 768.0); } diff --git a/routing/routing_integration_tests/street_names_test.cpp b/routing/routing_integration_tests/street_names_test.cpp index 2f9af27893..e0aca3daa8 100644 --- a/routing/routing_integration_tests/street_names_test.cpp +++ b/routing/routing_integration_tests/street_names_test.cpp @@ -31,7 +31,7 @@ UNIT_TEST(RussiaTulskayaToPaveletskayaStreetNamesTest) TEST_EQUAL(result, IRouter::NoError, ()); integration::TestCurrentStreetName(route, "Большая Тульская улица"); - integration::TestNextStreetName(route, "Подольское шоссе"); + integration::TestNextStreetName(route, "Валовая улица"); MoveRoute(route, ms::LatLon(55.71398, 37.62443)); diff --git a/routing/routing_integration_tests/turn_test.cpp b/routing/routing_integration_tests/turn_test.cpp index e5675e68c9..93018d0ee3 100644 --- a/routing/routing_integration_tests/turn_test.cpp +++ b/routing/routing_integration_tests/turn_test.cpp @@ -155,16 +155,16 @@ UNIT_TEST(RussiaMoscowPlanetnayaOnlyStraightTest) IRouter::ResultCode const result = routeResult.second; TEST_EQUAL(result, IRouter::NoError, ()); - integration::TestTurnCount(route, 4 /* expectedTurnCount */); + integration::TestTurnCount(route, 5 /* expectedTurnCount */); integration::GetNthTurn(route, 0).TestValid().TestDirection(CarDirection::TurnRight); integration::GetNthTurn(route, 1).TestValid().TestDirection(CarDirection::TurnRight); integration::GetNthTurn(route, 2).TestValid().TestDirection(CarDirection::TurnLeft); - integration::GetNthTurn(route, 3).TestValid().TestDirection(CarDirection::TurnRight); + integration::GetNthTurn(route, 3).TestValid().TestDirection(CarDirection::GoStraight); + integration::GetNthTurn(route, 4).TestValid().TestDirection(CarDirection::TurnRight); integration::TestRouteLength(route, 454.); } -// Fails: generates "GoStraight" description instead of TurnSlightRight/TurnRight. UNIT_TEST(RussiaMoscowNoTurnsOnMKADTurnTest) { TRouteResult const routeResult = @@ -185,7 +185,6 @@ UNIT_TEST(RussiaMoscowNoTurnsOnMKADTurnTest) integration::TestRouteLength(route, 43233.7); } -// Fails: generates "GoStraight" description instead of TurnSlightRight/TurnRight. UNIT_TEST(RussiaMoscowTTKKashirskoeShosseOutTurnTest) { TRouteResult const routeResult = @@ -522,8 +521,9 @@ UNIT_TEST(RussiaMoscowLeningradskiyPrptToTTKTest) IRouter::ResultCode const result = routeResult.second; TEST_EQUAL(result, IRouter::NoError, ()); - integration::TestTurnCount(route, 1 /* expectedTurnCount */); + integration::TestTurnCount(route, 2 /* expectedTurnCount */); integration::GetNthTurn(route, 0).TestValid().TestDirection(CarDirection::TurnSlightRight); + integration::GetNthTurn(route, 1).TestValid().TestDirection(CarDirection::GoStraight); } UNIT_TEST(RussiaMoscowLeningradskiyPrptDublToTTKTest) @@ -537,8 +537,9 @@ UNIT_TEST(RussiaMoscowLeningradskiyPrptDublToTTKTest) IRouter::ResultCode const result = routeResult.second; TEST_EQUAL(result, IRouter::NoError, ()); - integration::TestTurnCount(route, 1 /* expectedTurnCount */); + integration::TestTurnCount(route, 2 /* expectedTurnCount */); integration::GetNthTurn(route, 0).TestValid().TestDirection(CarDirection::TurnSlightLeft); + integration::GetNthTurn(route, 1).TestValid().TestDirection(CarDirection::GoStraight); } UNIT_TEST(RussiaMoscowSvobodaStTest) diff --git a/routing/turns_generator.cpp b/routing/turns_generator.cpp index 4b61d867db..ac01a1a407 100644 --- a/routing/turns_generator.cpp +++ b/routing/turns_generator.cpp @@ -20,8 +20,10 @@ using namespace routing::turns; namespace { -size_t constexpr kMaxPointsCount = 5; -double constexpr kMinDistMeters = 200.; +size_t constexpr kMaxOutgoingPointsCount = 5; +double constexpr kMinOutgoingDistMeters = 200.; +size_t constexpr kMaxIngoingPointsCount = 2; +double constexpr kMinIngoingDistMeters = 300.; size_t constexpr kNotSoCloseMaxPointsCount = 3; double constexpr kNotSoCloseMinDistMeters = 30.; @@ -97,13 +99,14 @@ bool KeepRoundaboutTurnByHighwayClass(CarDirection turn, TurnCandidates const & return false; } -bool DiscardTurnByIngoingAndOutgoingEdges(CarDirection intermediateDirection, +bool DiscardTurnByIngoingAndOutgoingEdges(CarDirection intermediateDirection, bool hasMultiTurns, TurnInfo const & turnInfo, TurnItem const & turn) { return !turn.m_keepAnyway && !turnInfo.m_ingoing.m_onRoundabout && - !turnInfo.m_outgoing.m_onRoundabout && IsGoStraightOrSlightTurn(intermediateDirection) && + !turnInfo.m_outgoing.m_onRoundabout && turnInfo.m_ingoing.m_highwayClass == turnInfo.m_outgoing.m_highwayClass && - turn.m_sourceName == turn.m_targetName; + ((!hasMultiTurns && IsGoStraightOrSlightTurn(intermediateDirection)) || + (hasMultiTurns && intermediateDirection == CarDirection::GoStraight)); } // turnEdgesCount calculates both ingoing ond outgoing edges without user's edge. @@ -116,7 +119,7 @@ bool KeepTurnByIngoingEdges(m2::PointD const & junctionPoint, my::RadToDeg(PiMinusTwoVectorsAngle(junctionPoint, ingoingPointOneSegment, outgoingPoint)); bool const isGoStraightOrSlightTurn = IsGoStraightOrSlightTurn(IntermediateDirection(turnAngle)); - // The code below is resposible for cases when there is only one way to leave the junction. + // The code below is responsible 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); return hasMultiTurns || (!isGoStraightOrSlightTurn && turnEdgesCount > 1); @@ -180,8 +183,10 @@ CarDirection FindDirectionByAngle(vector> const & low * - going from junctionPoint along segment path according to the direction which is set in GetPointIndex(). * - until one of following conditions is fulfilled: * - the end of ft is reached; (returns the last feature point) - * - more than kMaxPointsCount points are passed; (returns the kMaxPointsCount-th point) - * - the length of passed parts of segment exceeds kMinDistMeters; (returns the next point after the event) + * - more than kMaxIngoingPointsCount or kMaxOutgoingPointsCount points are passed; + * (returns the kMaxIngoingPointsCount-th or kMaxOutgoingPointsCount point) + * - the length of passed parts of segment exceeds kMinIngoingDistMeters or kMinOutgoingDistMeters; + * (returns the next point after the event) * \param path geometry of the segment. * \param junctionPoint is a junction point. * \param maxPointsCount returned poit could't be more than maxPointsCount poins away from junctionPoint @@ -557,10 +562,10 @@ void GetTurnDirection(IRoutingResult const & result, NumMwmIds const & numMwmIds m2::PointD const junctionPoint = turnInfo.m_ingoing.m_path.back().GetPoint(); m2::PointD const ingoingPoint = GetPointForTurn(turnInfo.m_ingoing.m_path, junctionPoint, - kMaxPointsCount, kMinDistMeters, + kMaxIngoingPointsCount, kMinIngoingDistMeters, GetIngoingPointIndex); m2::PointD const outgoingPoint = GetPointForTurn(turnInfo.m_outgoing.m_path, junctionPoint, - kMaxPointsCount, kMinDistMeters, + kMaxOutgoingPointsCount, kMinOutgoingDistMeters, GetOutgoingPointIndex); double const turnAngle = my::RadToDeg(PiMinusTwoVectorsAngle(junctionPoint, ingoingPoint, outgoingPoint)); @@ -570,9 +575,6 @@ void GetTurnDirection(IRoutingResult const & result, NumMwmIds const & numMwmIds turn.m_sourceName = turnInfo.m_ingoing.m_name; turn.m_targetName = turnInfo.m_outgoing.m_name; turn.m_turn = CarDirection::None; - // Early filtering based only on the information about ingoing and outgoing edges. - if (DiscardTurnByIngoingAndOutgoingEdges(intermediateDirection, turnInfo, turn)) - return; ASSERT_GREATER(turnInfo.m_ingoing.m_path.size(), 1, ()); m2::PointD const ingoingPointOneSegment = turnInfo.m_ingoing.m_path[turnInfo.m_ingoing.m_path.size() - 2].GetPoint(); @@ -587,6 +589,9 @@ void GetTurnDirection(IRoutingResult const & result, NumMwmIds const & numMwmIds if (numNodes == 0) return; + if (DiscardTurnByIngoingAndOutgoingEdges(intermediateDirection, hasMultiTurns, turnInfo, turn)) + return; + if (!hasMultiTurns || !nodes.isCandidatesAngleValid) { turn.m_turn = intermediateDirection; @@ -703,10 +708,10 @@ size_t CheckUTurnOnRoute(TUnpackedPathSegments const & segments, // Determine turn direction. m2::PointD const junctionPoint = masterSegment.m_path.back().GetPoint(); m2::PointD const ingoingPoint = GetPointForTurn(masterSegment.m_path, junctionPoint, - kMaxPointsCount, kMinDistMeters, + kMaxIngoingPointsCount, kMinIngoingDistMeters, GetIngoingPointIndex); m2::PointD const outgoingPoint = GetPointForTurn(segments[currentSegment].m_path, junctionPoint, - kMaxPointsCount, kMinDistMeters, + kMaxOutgoingPointsCount, kMinOutgoingDistMeters, GetOutgoingPointIndex); if (PiMinusTwoVectorsAngle(junctionPoint, ingoingPoint, outgoingPoint) < 0) turn.m_turn = CarDirection::UTurnLeft;