[Routing] Fixes: #2422 + GetTurnDirection() refactoring #2427
|
@ -328,17 +328,17 @@ UNIT_TEST(TestRightmostDirection)
|
|||
TEST_EQUAL(RightmostDirection(90.), CarDirection::TurnRight, ());
|
||||
TEST_EQUAL(RightmostDirection(45.), CarDirection::TurnSlightRight, ());
|
||||
TEST_EQUAL(RightmostDirection(0.), CarDirection::GoStraight, ());
|
||||
TEST_EQUAL(RightmostDirection(-20.), CarDirection::TurnSlightLeft, ());
|
||||
TEST_EQUAL(RightmostDirection(-90.), CarDirection::TurnLeft, ());
|
||||
TEST_EQUAL(RightmostDirection(-170.), CarDirection::TurnSharpLeft, ());
|
||||
TEST_EQUAL(RightmostDirection(-20.), CarDirection::GoStraight, ());
|
||||
TEST_EQUAL(RightmostDirection(-90.), CarDirection::GoStraight, ());
|
||||
TEST_EQUAL(RightmostDirection(-170.), CarDirection::GoStraight, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(TestLeftmostDirection)
|
||||
![]() I was trying to explain it in RighmostDirection() definition:
If necessary I can make it more clear or move comments to \brief section. I was trying to explain it in RighmostDirection() definition:
```
// For sure it's incorrect to give directions TurnLeft or TurnSlighLeft if we need the rightmost turn.
// So GoStraight direction is given even for needed sharp left turn when other turns on the left and are more sharp.
// The reason: the rightmost turn is the most straight one here.
```
If necessary I can make it more clear or move comments to \brief section.
![]() Ok, but could you also provide an example (in brief or description or when RighmostDirection/LeftmostDirection functions are called), who decided that the turn is "rightmost" or "leftmost"? Ok, but could you also provide an example (in brief or description or when RighmostDirection/LeftmostDirection functions are called), who decided that the turn is "rightmost" or "leftmost"?
What does "rightmost/leftmost" actually mean?
![]() I see this block but can't understand what does it mean?
I see this block but can't understand what does it mean?
```
if (nodes.candidates.front().m_segment == firstOutgoingSeg)
turn.m_turn = LeftmostDirection(turnAngle);
else if (nodes.candidates.back().m_segment == firstOutgoingSeg)
turn.m_turn = RightmostDirection(turnAngle);
else
turn.m_turn = intermediateDirection;
```
![]() Ah, if nodes.candidates are sorted by direction angle, then it makes sense :) Ah, if nodes.candidates are sorted by direction angle, then it makes sense :)
Ok, please, add some comments, but now I got the logic!
![]() Running road_access_test.cpp::RoadAccess_WayBlockedWhenStartButOpenWhenReach Running opening_hours_serdes_tests.cpp::BitReaderWriter_OpeningHoursSerDes_MonthHours_Usage Running opening_hours_serdes_tests.cpp::BitReaderWriter_OpeningHoursSerDes_Weekday_Usage_2 Running road_access_test.cpp::RoadAccess_WayBlockedWhenStartButOpenWhenReach
FAILED
routing_tests/index_graph_tools.cpp:606 TEST(base::AlmostEqualAbs(pathWeight, expectedWeight, kEpsilon)) 10804 12802 [5: (0, 1) (1, 2) (2, 3) (3, 4) (4, 5) ]
Running opening_hours_serdes_tests.cpp::BitReaderWriter_OpeningHoursSerDes_MonthHours_Usage
FAILED
routing_tests/opening_hours_serdes_tests.cpp:823 TEST(oh.IsClosed(GetUnixtimeByDate(2020, Month::May, 6, 01 , 00 )))
Running opening_hours_serdes_tests.cpp::BitReaderWriter_OpeningHoursSerDes_Weekday_Usage_2
FAILED
routing_tests/opening_hours_serdes_tests.cpp:750 TEST(oh.IsOpen(GetUnixtimeByDate(2023, Month::Apr, Weekday::Saturday, 13 , 30 )))
![]() What is your env (Linux/MacOS) and toolchain (gcc/clang --version)? What is your env (Linux/MacOS) and toolchain (gcc/clang --version)?
Looks like OpeningHours (boost/spirit) is buggy on your system.
Do you have boost submodule latest and updated?
![]() BTW, try to run ./opening_hours_tests BTW, try to run ./opening_hours_tests
![]() MacOS 12.13.1 Boost just pulled. *** 12 failures are detected in the test module "OpeningHours" MacOS 12.13.1
Apple clang version 13.1.6 (clang-1316.0.21.2)
Target: x86_64-apple-darwin21.4.0
Thread model: posix
Boost just pulled.
*** 12 failures are detected in the test module "OpeningHours"
![]() Added:
Added:
```
// turnCandidates are sorted by angle from leftmost to rightmost.
if (turnCandidates.front().m_segment == firstOutgoingSeg)
```
![]() Strange, because I have exactly the same toolchain .. Strange, because I have exactly the same toolchain ..
![]() Do I need any additional data to run the tests? Do I need any additional data to run the tests?
I used "--filter=blob:limit=128k"
![]() No, you don't .. Could you show me: No, you don't .. Could you show me:
cat 3party/boost/boost/version.hpp | grep "VERSION"
cat 3party/boost/boost/spirit/include/version.hpp | grep "VERSION"
cat 3party/boost/boost/phoenix/version.hpp | grep "VERSION"
![]()
```
#define BOOST_VERSION 107900
#define BOOST_LIB_VERSION "1_79"
#define SPIRIT_VERSION 0x2059
#define SPIRIT_PIZZA_VERSION SUPER_HOT_SPANISH_SARDINES // :-O
#define BOOST_PHOENIX_VERSION 0x3200 // 3.2.0
#define BOOST_PHOENIX_VERSION_NUMBER = BOOST_VERSION_NUMBER(3,2,0)
```
![]()
```
$ ../omim-build-debug/opening_hours_tests
Running 23 test cases...
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1348: error: in "OpeningHours_TestIsActive": check IsActive(rules[0], time) has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1351: error: in "OpeningHours_TestIsActive": check IsActive(rules[1], time) has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1458: error: in "OpeningHours_TestIsActive": check IsActive(rules[0], time) has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1478: error: in "OpeningHours_TestIsActive": check IsActive(rules[0], time) has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1553: error: in "OpeningHours_TestIsOpen": check IsOpen(rules, "2021-05-08 19:40") has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1592: error: in "OpeningHours_TestIsOpen": check IsOpen(rules, "2015-07-09 16:50") has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1615: error: in "OpeningHours_TestIsOpen": check IsClosed(rules, "2012-10-08 15:59") has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1628: error: in "OpeningHours_TestIsOpen": check IsOpen(rules, "2015-04-10 07:15") has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1629: error: in "OpeningHours_TestIsOpen": check IsOpen(rules, "2015-05-01 07:15") has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1630: error: in "OpeningHours_TestIsOpen": check IsOpen(rules, "2015-04-11 07:15") has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1649: error: in "OpeningHours_TestIsOpen": check IsOpen(rules, "2017-05-31 23:35") has failed
/Users/alex/Developer/omim/omim/3party/opening_hours/opening_hours_tests/opening_hours_tests.cpp:1659: error: in "OpeningHours_TestIsOpen": check !IsOpen(rules, "2017-05-31 23:35") has failed
*** 12 failures are detected in the test module "OpeningHours"
```
|
||||
{
|
||||
TEST_EQUAL(LeftmostDirection(180.), CarDirection::TurnSharpRight, ());
|
||||
TEST_EQUAL(LeftmostDirection(170.), CarDirection::TurnSharpRight, ());
|
||||
TEST_EQUAL(LeftmostDirection(90.), CarDirection::TurnRight, ());
|
||||
TEST_EQUAL(LeftmostDirection(45.), CarDirection::TurnSlightRight, ());
|
||||
TEST_EQUAL(LeftmostDirection(180.), CarDirection::GoStraight, ());
|
||||
TEST_EQUAL(LeftmostDirection(170.), CarDirection::GoStraight, ());
|
||||
TEST_EQUAL(LeftmostDirection(90.), CarDirection::GoStraight, ());
|
||||
TEST_EQUAL(LeftmostDirection(45.), CarDirection::GoStraight, ());
|
||||
TEST_EQUAL(LeftmostDirection(0.), CarDirection::GoStraight, ());
|
||||
TEST_EQUAL(LeftmostDirection(-20.), CarDirection::TurnSlightLeft, ());
|
||||
TEST_EQUAL(LeftmostDirection(-90.), CarDirection::TurnLeft, ());
|
||||
|
|
|
@ -125,7 +125,7 @@ bool GetTurnHighwayClasses(TurnCandidates const & possibleTurns, TurnInfo const
|
|||
{
|
||||
// Let's consider all outgoing segments except for
|
||||
// (1) route outgoing segment
|
||||
// (2) a U-turn segment (inversedLastIngoingSegment)
|
||||
// (2) a U-turn segment (inversedLastIngoingSegment).
|
||||
if (t.m_segment == firstOutgoingSegment || t.m_segment == inversedLastIngoingSegment)
|
||||
continue;
|
||||
ftypes::HighwayClass const highwayClass = t.m_highwayClass;
|
||||
|
@ -180,7 +180,7 @@ bool DiscardTurnByHighwayClass(TurnCandidates const & possibleTurns, TurnInfo co
|
|||
int constexpr kMaxHighwayClassDiffForService = 1;
|
||||
|
||||
TurnHighwayClasses turnHighwayClasses;
|
||||
// Looks like a bug. If no info received turn should not be discarded
|
||||
// Looks like a bug. If no info received turn should not be discarded.
|
||||
if (!GetTurnHighwayClasses(possibleTurns, turnInfo, numMwmIds, turnHighwayClasses))
|
||||
return true;
|
||||
|
||||
|
@ -197,19 +197,26 @@ bool DiscardTurnByHighwayClass(TurnCandidates const & possibleTurns, TurnInfo co
|
|||
}
|
||||
|
||||
/// * \returns false when
|
||||
/// * for routes which go straight and don't go to a smaller road:
|
||||
![]()
Надо соблюдать наше текущее соглашение о форматировании. ```suggestion
bool DiscardTurnByNoAlignedAlternatives(std::vector<TurnCandidate> const & candidatesWithoutUturn, TurnInfo const & turnInfo,
```
Надо соблюдать наше текущее соглашение о форматировании.
![]() ок ок
|
||||
/// * - any alternative GoStraight or SlightTurn turn
|
||||
/// * for other routes:
|
||||
/// * - any alternative turn to a bigger road
|
||||
/// * - or any alternative turn to a similar road if the turn's angle is less than kMaxAbsAngleSameRoadClass degrees (wider than SlightTurn)
|
||||
/// * - or any alternative turn to a smaller road if it's GoStraight or SlightTurn.
|
||||
/// * Returns true otherwise.
|
||||
/// \param possibleTurns is all possible ways out from a junction.
|
||||
/// \param turnRoute is current route turn
|
||||
/// \param turnCandidates is all possible ways out from a junction except uturn.
|
||||
/// \param turnInfo is information about ingoing and outgoing segments of the route.
|
||||
/// it is supposed that current turn is GoStraight or SlightTurn
|
||||
bool DiscardTurnByNoAlignedAlternatives(TurnCandidates const & possibleTurns, TurnInfo const & turnInfo,
|
||||
bool DiscardTurnByNoAlignedAlternatives(TurnItem const & turnRoute,
|
||||
std::vector<TurnCandidate> const & turnCandidates,
|
||||
TurnInfo const & turnInfo,
|
||||
NumMwmIds const & numMwmIds)
|
||||
{
|
||||
double constexpr kMaxAbsAngleSameRoadClass = 70.0;
|
||||
![]() Это можно в одну строку вместо двух, и точку в конце. Это можно в одну строку вместо двух, и точку в конце.
![]() ок ок
|
||||
|
||||
ftypes::HighwayClass outgoingRouteRoadClass = turnInfo.m_outgoing.m_highwayClass;
|
||||
ftypes::HighwayClass ingoingRouteRoadClass = turnInfo.m_ingoing.m_highwayClass;
|
||||
|
||||
// The turn should be kept if there's no any information about feature id of outgoing segment
|
||||
// just to be on the safe side. It may happen in case of outgoing segment is a finish segment.
|
||||
|
@ -217,38 +224,40 @@ bool DiscardTurnByNoAlignedAlternatives(TurnCandidates const & possibleTurns, Tu
|
|||
if (!turnInfo.m_outgoing.m_segmentRange.GetFirstSegment(numMwmIds, firstOutgoingSegment))
|
||||
return false;
|
||||
|
||||
Segment inversedLastIngoingSegment;
|
||||
if (!turnInfo.m_ingoing.m_segmentRange.GetLastSegment(numMwmIds, inversedLastIngoingSegment))
|
||||
return false;
|
||||
inversedLastIngoingSegment.Inverse();
|
||||
|
||||
for (auto const & t : possibleTurns.candidates)
|
||||
for (auto const & t : turnCandidates)
|
||||
{
|
||||
// Let's consider all outgoing segments except for
|
||||
// (1) route outgoing segment
|
||||
// (2) a U-turn segment (inversedLastIngoingSegment)
|
||||
if (t.m_segment == firstOutgoingSegment || t.m_segment == inversedLastIngoingSegment)
|
||||
// Let's consider all outgoing segments except for route outgoing segment.
|
||||
if (t.m_segment == firstOutgoingSegment)
|
||||
continue;
|
||||
ftypes::HighwayClass const highwayClass = t.m_highwayClass;
|
||||
// @note The bigger is the road, the lesser is HighwayClass value.
|
||||
if (static_cast<int>(highwayClass) < static_cast<int>(outgoingRouteRoadClass))
|
||||
|
||||
if (turnRoute.m_turn == CarDirection::GoStraight && static_cast<int>(outgoingRouteRoadClass) >= static_cast<int>(ingoingRouteRoadClass))
|
||||
{
|
||||
// Any alternative turn to a bigger road keeps the turn direction.
|
||||
return false;
|
||||
}
|
||||
else if (highwayClass == outgoingRouteRoadClass)
|
||||
{
|
||||
// Any alternative turn to a similar road keeps the turn direction if the turn's angle is less than
|
||||
// kMaxAbsAngleSameRoadClass degrees (wider than SlightTurn).
|
||||
if (fabs(t.m_angle) < kMaxAbsAngleSameRoadClass)
|
||||
return false;
|
||||
}
|
||||
else // static_cast<int>(highwayClass) > static_cast<int>(outgoingRouteRoadClass)
|
||||
{
|
||||
// Any alternative turn to a smaller road keeps the turn direction if it's GoStraight or SlightTurn.
|
||||
if (IsGoStraightOrSlightTurn(IntermediateDirection(t.m_angle)))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ftypes::HighwayClass const highwayClass = t.m_highwayClass;
|
||||
// @note The bigger is the road, the lesser is HighwayClass value.
|
||||
if (static_cast<int>(highwayClass) < static_cast<int>(outgoingRouteRoadClass))
|
||||
{
|
||||
// Any alternative turn to a bigger road keeps the turn direction.
|
||||
return false;
|
||||
}
|
||||
else if (highwayClass == outgoingRouteRoadClass)
|
||||
{
|
||||
// Any alternative turn to a similar road keeps the turn direction if the turn's angle is less than
|
||||
// kMaxAbsAngleSameRoadClass degrees (wider than SlightTurn).
|
||||
if (fabs(t.m_angle) < kMaxAbsAngleSameRoadClass)
|
||||
return false;
|
||||
}
|
||||
else // static_cast<int>(highwayClass) > static_cast<int>(outgoingRouteRoadClass)
|
||||
{
|
||||
// Any alternative turn to a smaller road keeps the turn direction if it's GoStraight or SlightTurn.
|
||||
if (IsGoStraightOrSlightTurn(IntermediateDirection(t.m_angle)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -256,7 +265,7 @@ bool DiscardTurnByNoAlignedAlternatives(TurnCandidates const & possibleTurns, Tu
|
|||
/*!
|
||||
* \brief Returns false when other possible turns leads to service roads;
|
||||
*/
|
||||
bool KeepRoundaboutTurnByHighwayClass(CarDirection turn, TurnCandidates const & possibleTurns,
|
||||
bool KeepRoundaboutTurnByHighwayClass(TurnCandidates const & possibleTurns,
|
||||
TurnInfo const & turnInfo, NumMwmIds const & numMwmIds)
|
||||
{
|
||||
Segment firstOutgoingSegment;
|
||||
|
@ -273,50 +282,10 @@ bool KeepRoundaboutTurnByHighwayClass(CarDirection turn, TurnCandidates const &
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DoAllTurnCandidatesGoAlmostStraight(vector<TurnCandidate> const & candidates)
|
||||
{
|
||||
return all_of(candidates.cbegin(), candidates.cend(), [](TurnCandidate const & c) {
|
||||
return IsGoStraightOrSlightTurn(IntermediateDirection(c.m_angle));
|
||||
});
|
||||
}
|
||||
|
||||
/// \brief Analyzes its args and makes a decision if it's possible to have a turn at this junction
|
||||
/// or not.
|
||||
/// \returns true if based on this analysis there's no turn at this junction and
|
||||
/// false if the junction should be considered as possible turn.
|
||||
bool DiscardTurnByIngoingAndOutgoingEdges(CarDirection intermediateDirection, bool hasMultiTurns,
|
||||
TurnInfo const & turnInfo, TurnItem const & turn,
|
||||
TurnCandidates const & turnCandidates)
|
||||
{
|
||||
if (turn.m_keepAnyway || turnInfo.m_ingoing.m_onRoundabout ||
|
||||
turnInfo.m_outgoing.m_onRoundabout ||
|
||||
turnInfo.m_ingoing.m_highwayClass != turnInfo.m_outgoing.m_highwayClass)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// @TODO(bykoianko) If all turn candidates go almost straight and there are several ways
|
||||
// from the junction (|hasMultiTurns| == true) the turn will be discarded.
|
||||
// If all turn candidates go almost straight and there is only one way
|
||||
// from the junction (|hasMultiTurns| == false) the turn will not be discarded in this method,
|
||||
// and then may be kept. It means that in some cases if there are two or more possible
|
||||
// ways from a junction the turn may be discarded and if there is only one way out
|
||||
// the turn may be kept. This code should be redesigned.
|
||||
if (turnCandidates.isCandidatesAngleValid &&
|
||||
DoAllTurnCandidatesGoAlmostStraight(turnCandidates.candidates))
|
||||
{
|
||||
return !hasMultiTurns;
|
||||
}
|
||||
|
||||
return ((!hasMultiTurns && IsGoStraightOrSlightTurn(intermediateDirection)) ||
|
||||
(hasMultiTurns && intermediateDirection == CarDirection::GoStraight));
|
||||
}
|
||||
|
||||
// turnEdgesCount calculates both ingoing ond outgoing edges without user's edge.
|
||||
bool KeepTurnByIngoingEdges(m2::PointD const & junctionPoint,
|
||||
m2::PointD const & ingoingPointOneSegment,
|
||||
m2::PointD const & outgoingPoint, bool hasMultiTurns,
|
||||
size_t const turnEdgesCount)
|
||||
size_t const ingoingEdgesCount)
|
||||
{
|
||||
double const turnAngle =
|
||||
base::RadToDeg(PiMinusTwoVectorsAngle(junctionPoint, ingoingPointOneSegment, outgoingPoint));
|
||||
|
@ -325,7 +294,7 @@ bool KeepTurnByIngoingEdges(m2::PointD const & junctionPoint,
|
|||
// 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);
|
||||
return hasMultiTurns || (!isGoStraightOrSlightTurn && ingoingEdgesCount > 0);
|
||||
}
|
||||
|
||||
bool FixupLaneSet(CarDirection turn, vector<SingleLaneInfo> & lanes,
|
||||
|
@ -574,7 +543,8 @@ bool GetPrevInSegmentRoutePoint(RoutePointIndex const & index, RoutePointIndex &
|
|||
void GoStraightCorrection(TurnCandidate const & notRouteCandidate, CarDirection turnToSet,
|
||||
TurnItem & turn)
|
||||
{
|
||||
CHECK_EQUAL(turn.m_turn, CarDirection::GoStraight, ());
|
||||
if (turn.m_turn != CarDirection::GoStraight)
|
||||
return;
|
||||
|
||||
if (!IsGoStraightOrSlightTurn(IntermediateDirection(notRouteCandidate.m_angle)))
|
||||
return;
|
||||
|
@ -981,11 +951,11 @@ CarDirection RightmostDirection(const double angle)
|
|||
static vector<pair<double, CarDirection>> const kLowerBounds = {
|
||||
{157., CarDirection::TurnSharpRight},
|
||||
{50., CarDirection::TurnRight},
|
||||
{2., CarDirection::TurnSlightRight},
|
||||
{-10., CarDirection::GoStraight},
|
||||
{-50., CarDirection::TurnSlightLeft},
|
||||
{-157., CarDirection::TurnLeft},
|
||||
{-180., CarDirection::TurnSharpLeft}};
|
||||
{10., CarDirection::TurnSlightRight},
|
||||
// For sure it's incorrect to give directions TurnLeft or TurnSlighLeft if we need the rightmost turn.
|
||||
// So GoStraight direction is given even for needed sharp left turn when other turns on the left and are more sharp.
|
||||
// The reason: the rightmost turn is the most straight one here.
|
||||
{-180., CarDirection::GoStraight}};
|
||||
|
||||
return FindDirectionByAngle(kLowerBounds, angle);
|
||||
}
|
||||
|
@ -1054,6 +1024,18 @@ bool HasMultiTurns(NumMwmIds const & numMwmIds, TurnCandidates const & turnCandi
|
|||
return !OneOfTurnCandidatesGoesAlongIngoingSegment(numMwmIds, turnCandidates, turnInfo);
|
||||
}
|
||||
|
||||
void RemoveUTurnCandidate(TurnInfo const & turnInfo, NumMwmIds const & numMwmIds, std::vector<TurnCandidate> & turnCandidates)
|
||||
{
|
||||
Segment lastIngoingSegment;
|
||||
if (turnInfo.m_ingoing.m_segmentRange.GetLastSegment(numMwmIds, lastIngoingSegment))
|
||||
{
|
||||
if (turnCandidates.front().m_segment.IsInverse(lastIngoingSegment))
|
||||
turnCandidates.erase(turnCandidates.begin());
|
||||
else if (turnCandidates.back().m_segment.IsInverse(lastIngoingSegment))
|
||||
turnCandidates.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns true if there is exactly 1 turn in |turnCandidates| with angle less then
|
||||
/// |kMaxForwardAngleCandidates|.
|
||||
bool HasSingleForwardTurn(TurnCandidates const & turnCandidates)
|
||||
|
@ -1152,60 +1134,41 @@ void GetTurnDirection(IRoutingResult const & result, size_t outgoingSegmentIndex
|
|||
return;
|
||||
|
||||
bool const hasMultiTurns = HasMultiTurns(numMwmIds, nodes, turnInfo);
|
||||
RemoveUTurnCandidate(turnInfo, numMwmIds, nodes.candidates);
|
||||
auto const & turnCandidates = nodes.candidates;
|
||||
ASSERT(hasMultiTurns == (turnCandidates.size() >= 2),
|
||||
("hasMultiTurns is true if there are two or more possible ways which don't go along an ingoing segment and false otherwise"));
|
||||
|
||||
// Check for enter or exit to/from roundabout.
|
||||
if (turnInfo.m_ingoing.m_onRoundabout || turnInfo.m_outgoing.m_onRoundabout)
|
||||
{
|
||||
bool const keepTurnByHighwayClass = KeepRoundaboutTurnByHighwayClass(nodes, turnInfo, numMwmIds);
|
||||
turn.m_turn = GetRoundaboutDirection(turnInfo.m_ingoing.m_onRoundabout,
|
||||
![]()
```suggestion
// Check for enter or exit to/from roundabout.
```
![]() Тогда уже и hasMultiTurns на отдельную строку. Тогда уже и hasMultiTurns на отдельную строку.
![]() Не надо тут переносить на новую строку. Не надо тут переносить на новую строку.
![]() ок ок
![]() ок ок
![]() ок ок
|
||||
turnInfo.m_outgoing.m_onRoundabout,
|
||||
hasMultiTurns,
|
||||
keepTurnByHighwayClass);
|
||||
return;
|
||||
}
|
||||
|
||||
// Checking for exits from highways.
|
||||
Segment firstOutgoingSeg;
|
||||
bool const isFirstOutgoingSegValid =
|
||||
turnInfo.m_outgoing.m_segmentRange.GetFirstSegment(numMwmIds, firstOutgoingSeg);
|
||||
if (!turnInfo.m_ingoing.m_onRoundabout && isFirstOutgoingSegValid &&
|
||||
if (isFirstOutgoingSegValid &&
|
||||
IsExit(nodes, turnInfo, firstOutgoingSeg, intermediateDirection, turn.m_turn))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (DiscardTurnByIngoingAndOutgoingEdges(intermediateDirection, hasMultiTurns, turnInfo, turn, nodes))
|
||||
return;
|
||||
|
||||
if (!hasMultiTurns || !nodes.isCandidatesAngleValid)
|
||||
{
|
||||
turn.m_turn = intermediateDirection;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isFirstOutgoingSegValid)
|
||||
{
|
||||
if (nodes.candidates.front().m_segment == firstOutgoingSeg)
|
||||
turn.m_turn = LeftmostDirection(turnAngle);
|
||||
else if (nodes.candidates.back().m_segment == firstOutgoingSeg)
|
||||
turn.m_turn = RightmostDirection(turnAngle);
|
||||
else
|
||||
turn.m_turn = intermediateDirection;
|
||||
}
|
||||
else
|
||||
{
|
||||
turn.m_turn = intermediateDirection;
|
||||
}
|
||||
}
|
||||
|
||||
if (turnInfo.m_ingoing.m_onRoundabout || turnInfo.m_outgoing.m_onRoundabout)
|
||||
{
|
||||
bool const keepTurnByHighwayClass =
|
||||
KeepRoundaboutTurnByHighwayClass(turn.m_turn, nodes, turnInfo, numMwmIds);
|
||||
turn.m_turn = GetRoundaboutDirection(turnInfo.m_ingoing.m_onRoundabout,
|
||||
turnInfo.m_outgoing.m_onRoundabout, hasMultiTurns,
|
||||
keepTurnByHighwayClass);
|
||||
return;
|
||||
}
|
||||
turn.m_turn = intermediateDirection;
|
||||
|
||||
// Note 1. If the road significantly changes its direction this turn shall be kept here.
|
||||
// Note 2. If there's only one exit from this junction (nodes.candidates.size() == 1)
|
||||
// this turn should be kept (because it was kept by previous logic as an exception).
|
||||
// Note 3. Keeping a turn at this point means that the decision to keep this turn or not
|
||||
// Note 2. Keeping a turn at this point means that the decision to keep this turn or not
|
||||
// will be made after.
|
||||
if (!turn.m_keepAnyway && IsGoStraightOrSlightTurn(turn.m_turn) && nodes.candidates.size() != 1)
|
||||
if (!turn.m_keepAnyway && IsGoStraightOrSlightTurn(turn.m_turn))
|
||||
{
|
||||
![]() Хм, такое вообще потенциально небезопасно, грубо говоря мы делаем memcpy(dest, src) где src, dest на одном буфере. Я бы написал так:
Хм, такое вообще потенциально небезопасно, грубо говоря мы делаем memcpy(dest, src) где src, dest на одном буфере. Я бы написал так:
```
std::vector candidatesWithoutUturn;
if (...)
{
auto const & src = nodes.candidates;
if (..)
candidatesWithoutUturn.assign(src.begin() + 1, src.end());
else if (..)
candidatesWithoutUturn.assign(src.begin(), src.end() - 1);
else
candidatesWithoutUturn = src;
}
else
candidatesWithoutUturn = nodes.candidates;
```
![]() Почему бы не использовать Почему бы не использовать `candidatesWithoutUturn.erase(candidatesWithoutUturn.begin());` и `candidatesWithoutUturn.erase(candidatesWithoutUturn.rbegin());`?
![]() Тогда уж, pop_front(), pop_back(). В моем варианте меньше манипуляций с вектором. Он только присваивается, когда erase/pop_front() сделает его переалокацию. Тогда уж, pop_front(), pop_back(). В моем варианте меньше манипуляций с вектором. Он только присваивается, когда erase/pop_front() сделает его переалокацию.
![]() pop_back() да, а вот когда это у вектора появился pop_front() ? :) pop_back() да, а вот когда это у вектора появился pop_front() ? :)
![]() Исправил Исправил
|
||||
if (DiscardTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) ||
|
||||
![]()
```suggestion
auto candidatesWithoutUturn = nodes.candidates;
```
![]() Почему это условие должно выполняться? Надо комментарий в пустых скобках. Почему это условие должно выполняться? Надо комментарий в пустых скобках.
![]() А по сути — зачем здесь создавать копию nodes.candidates? Если нужно модифицировать, то нужна ссылка: А по сути — зачем здесь создавать копию nodes.candidates? Если нужно модифицировать, то нужна ссылка:
`auto & candidates_without_uturn = nodes.candidates;`
![]() Если часто нужно удалять первый элемент вектора, то имеет смысл использовать не вектор, а другую структуру данных, list или deque. @vng что думаешь? Если часто нужно удалять первый элемент вектора, то имеет смысл использовать не вектор, а другую структуру данных, list или deque. @vng что думаешь?
![]() это хороший вопрос.
Предлагаю вместе разобраться с DiscardTurnByIngoingAndOutgoingEdges и модифицировать оригинал. это хороший вопрос.
выглядит так, что этот uturn нигде не нужен в GetTurnDirection.
из того, где все еще используется nodes:
- KeepRoundaboutTurnByHighwayClass - не нужен (и не мешает)
- IsExit - не нужен (и не мешает)
- DiscardTurnByIngoingAndOutgoingEdges - очень запутанный метод. Предположительно, там не нужен и мешает!
- проверка на nodes.candidates.size() != 1 - предположительно не нужен. Зависит от DiscardTurnByIngoingAndOutgoingEdges
- DiscardTurnByHighwayClass - не нужен. Обратить внимание: вызывается также из GetNextCrossSegmentRoutePoint.
Предлагаю вместе разобраться с DiscardTurnByIngoingAndOutgoingEdges и модифицировать оригинал.
![]() ок ок
|
||||
DiscardTurnByNoAlignedAlternatives(nodes, turnInfo, numMwmIds))
|
||||
DiscardTurnByNoAlignedAlternatives(turn, turnCandidates, turnInfo, numMwmIds))
|
||||
{
|
||||
turn.m_turn = CarDirection::None;
|
||||
return;
|
||||
|
@ -1219,47 +1182,49 @@ void GetTurnDirection(IRoutingResult const & result, size_t outgoingSegmentIndex
|
|||
vehicleSettings.m_notSoCloseMaxDistMeters, false /* forward */);
|
||||
|
||||
// Removing a slight turn if there's only one way to leave the turn and there's no ingoing edges.
|
||||
if (!KeepTurnByIngoingEdges(junctionPoint, notSoCloseToTheTurnPoint, outgoingPoint, hasMultiTurns,
|
||||
nodes.candidates.size() + ingoingCount))
|
||||
if (!KeepTurnByIngoingEdges(junctionPoint, notSoCloseToTheTurnPoint, outgoingPoint, hasMultiTurns, ingoingCount))
|
||||
{
|
||||
turn.m_turn = CarDirection::None;
|
||||
return;
|
||||
}
|
||||
|
||||
// Removing a slight turn if ingoing and outgoing edges are not links and all other
|
||||
// possible ways out are links.
|
||||
// possible ways out (except of uturn) are links.
|
||||
if (!turnInfo.m_ingoing.m_isLink && !turnInfo.m_outgoing.m_isLink &&
|
||||
turnInfo.m_ingoing.m_highwayClass == turnInfo.m_outgoing.m_highwayClass &&
|
||||
GetLinkCount(nodes.candidates) + 1 == nodes.candidates.size())
|
||||
GetLinkCount(turnCandidates) + 1 == turnCandidates.size())
|
||||
{
|
||||
turn.m_turn = CarDirection::None;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (turn.m_turn == CarDirection::GoStraight)
|
||||
if (turnCandidates.size() >= 2)
|
||||
{
|
||||
if (!hasMultiTurns)
|
||||
turn.m_turn = CarDirection::None;
|
||||
// If the route goes along the rightmost or the leftmost way among available ones:
|
||||
// 1. RightmostDirection or LeftmostDirection is selected
|
||||
// 2. If the turn direction is |CarDirection::GoStraight|
|
||||
![]()
```suggestion
// Compare with the closest right candidate.
```
![]() ок ок
|
||||
// and there's another GoStraight or SlightTurn turn
|
||||
// GoStraight is corrected to TurnSlightRight/TurnSlightLeft
|
||||
// to avoid ambiguity: 2 or more almost straight turns and GoStraight direction.
|
||||
|
||||
// Note. If the turn direction is |CarDirection::GoStraight| and there's only one extra way out
|
||||
// from the junction the direction may be corrected in some cases. So two turn candidates
|
||||
// (one for the route and an extra one) require special processing.
|
||||
if (nodes.candidates.size() != 2)
|
||||
return;
|
||||
|
||||
if (nodes.candidates.front().m_segment == firstOutgoingSeg)
|
||||
// turnCandidates are sorted by angle from leftmost to rightmost.
|
||||
if (turnCandidates.front().m_segment == firstOutgoingSeg)
|
||||
{
|
||||
// The route goes along the leftmost candidate.
|
||||
GoStraightCorrection(nodes.candidates.back(), CarDirection::TurnSlightLeft, turn);
|
||||
// The route goes along the leftmost candidate.
|
||||
turn.m_turn = LeftmostDirection(turnAngle);
|
||||
// Compare with the closest left candidate.
|
||||
GoStraightCorrection(turnCandidates[1], CarDirection::TurnSlightLeft, turn);
|
||||
}
|
||||
else if (nodes.candidates.back().m_segment == firstOutgoingSeg)
|
||||
else if (turnCandidates.back().m_segment == firstOutgoingSeg)
|
||||
{
|
||||
// The route goes along the rightmost candidate.
|
||||
GoStraightCorrection(nodes.candidates.front(), CarDirection::TurnSlightRight, turn);
|
||||
// The route goes along the rightmost candidate.
|
||||
turn.m_turn = RightmostDirection(turnAngle);
|
||||
// Compare with the closest right candidate.
|
||||
GoStraightCorrection(turnCandidates[turnCandidates.size() - 2], CarDirection::TurnSlightRight, turn);
|
||||
}
|
||||
// Note. It's possible that |firstOutgoingSeg| is not contained in |nodes.candidates|.
|
||||
// It may happened if |firstOutgoingSeg| and candidates in |nodes.candidates| are
|
||||
// Note. It's possible that |firstOutgoingSeg| is not contained in |turnCandidates|.
|
||||
// It may happened if |firstOutgoingSeg| and candidates in |turnCandidates| are
|
||||
// from different mwms.
|
||||
}
|
||||
}
|
||||
|
|
Could you explain why 90 degrees is TurnRight and -90 degrees is GoStraight?
The same with others .. Am I miss something with these angles?