Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
129
libs/routing/lanes/lanes_recommendation.cpp
Normal file
129
libs/routing/lanes/lanes_recommendation.cpp
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
#include "lanes_recommendation.hpp"
|
||||
|
||||
#include "routing/route.hpp"
|
||||
|
||||
namespace routing::turns::lanes
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void FixRecommendedReverseLane(LaneWays & ways, LaneWay const recommendedWay)
|
||||
{
|
||||
if (recommendedWay == LaneWay::ReverseLeft)
|
||||
ways.Remove(LaneWay::ReverseRight);
|
||||
else if (recommendedWay == LaneWay::ReverseRight)
|
||||
ways.Remove(LaneWay::ReverseLeft);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SelectRecommendedLanes(std::vector<RouteSegment> & routeSegments)
|
||||
{
|
||||
for (auto & segment : routeSegments)
|
||||
{
|
||||
auto & t = segment.GetTurn();
|
||||
if (t.IsTurnNone() || t.m_lanes.empty())
|
||||
continue;
|
||||
auto & lanesInfo = segment.GetTurnLanes();
|
||||
// Check if there are elements in lanesInfo that correspond with the turn exactly.
|
||||
// If so, fix up all the elements in lanesInfo that correspond with the turn.
|
||||
if (impl::SetRecommendedLaneWays(t.m_turn, lanesInfo))
|
||||
continue;
|
||||
// If not, check if there are elements in lanesInfo that correspond with the turn
|
||||
// approximately. If so, fix up all those elements.
|
||||
if (impl::SetRecommendedLaneWaysApproximately(t.m_turn, lanesInfo))
|
||||
continue;
|
||||
// If not, check if there is an unrestricted lane that could correspond to the
|
||||
// turn. If so, fix up that lane.
|
||||
if (impl::SetUnrestrictedLaneAsRecommended(t.m_turn, lanesInfo))
|
||||
continue;
|
||||
// Otherwise, we don't have lane recommendations for the user, so we don't
|
||||
// want to send the lane data any further.
|
||||
segment.ClearTurnLanes();
|
||||
}
|
||||
}
|
||||
|
||||
bool impl::SetRecommendedLaneWays(CarDirection const carDirection, LanesInfo & lanesInfo)
|
||||
{
|
||||
LaneWay laneWay;
|
||||
switch (carDirection)
|
||||
{
|
||||
case CarDirection::GoStraight: laneWay = LaneWay::Through; break;
|
||||
case CarDirection::TurnRight: laneWay = LaneWay::Right; break;
|
||||
case CarDirection::TurnSharpRight: laneWay = LaneWay::SharpRight; break;
|
||||
case CarDirection::TurnSlightRight: [[fallthrough]];
|
||||
case CarDirection::ExitHighwayToRight: laneWay = LaneWay::SlightRight; break;
|
||||
case CarDirection::TurnLeft: laneWay = LaneWay::Left; break;
|
||||
case CarDirection::TurnSharpLeft: laneWay = LaneWay::SharpLeft; break;
|
||||
case CarDirection::TurnSlightLeft: [[fallthrough]];
|
||||
case CarDirection::ExitHighwayToLeft: laneWay = LaneWay::SlightLeft; break;
|
||||
case CarDirection::UTurnLeft: laneWay = LaneWay::ReverseLeft; break;
|
||||
case CarDirection::UTurnRight: laneWay = LaneWay::ReverseRight; break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
bool isLaneConformed = false;
|
||||
for (auto & [laneWays, recommendedWay] : lanesInfo)
|
||||
{
|
||||
if (laneWays.Contains(laneWay))
|
||||
{
|
||||
recommendedWay = laneWay;
|
||||
isLaneConformed = true;
|
||||
}
|
||||
FixRecommendedReverseLane(laneWays, recommendedWay);
|
||||
}
|
||||
return isLaneConformed;
|
||||
}
|
||||
|
||||
bool impl::SetRecommendedLaneWaysApproximately(CarDirection const carDirection, LanesInfo & lanesInfo)
|
||||
{
|
||||
std::vector<LaneWay> approximateLaneWays;
|
||||
switch (carDirection)
|
||||
{
|
||||
case CarDirection::UTurnLeft: approximateLaneWays = {LaneWay::SharpLeft}; break;
|
||||
case CarDirection::TurnSharpLeft: approximateLaneWays = {LaneWay::Left}; break;
|
||||
case CarDirection::TurnLeft: approximateLaneWays = {LaneWay::SlightLeft, LaneWay::SharpLeft}; break;
|
||||
case CarDirection::TurnSlightLeft: [[fallthrough]];
|
||||
case CarDirection::ExitHighwayToLeft: approximateLaneWays = {LaneWay::Left}; break;
|
||||
case CarDirection::GoStraight: approximateLaneWays = {LaneWay::SlightRight, LaneWay::SlightLeft}; break;
|
||||
case CarDirection::ExitHighwayToRight: [[fallthrough]];
|
||||
case CarDirection::TurnSlightRight: approximateLaneWays = {LaneWay::Right}; break;
|
||||
case CarDirection::TurnRight: approximateLaneWays = {LaneWay::SlightRight, LaneWay::SharpRight}; break;
|
||||
case CarDirection::TurnSharpRight: approximateLaneWays = {LaneWay::Right}; break;
|
||||
case CarDirection::UTurnRight: approximateLaneWays = {LaneWay::SharpRight}; break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
bool isLaneConformed = false;
|
||||
for (auto & [laneWays, recommendedWay] : lanesInfo)
|
||||
{
|
||||
for (auto const & laneWay : approximateLaneWays)
|
||||
{
|
||||
if (laneWays.Contains(laneWay))
|
||||
{
|
||||
recommendedWay = laneWay;
|
||||
isLaneConformed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isLaneConformed;
|
||||
}
|
||||
|
||||
bool impl::SetUnrestrictedLaneAsRecommended(CarDirection const carDirection, LanesInfo & lanesInfo)
|
||||
{
|
||||
static auto constexpr setFirstUnrestrictedLane = [](LaneWay const laneWay, auto beginIt, auto endIt)
|
||||
{
|
||||
auto it = std::find_if(beginIt, endIt, [](auto const & laneInfo) { return laneInfo.laneWays.IsUnrestricted(); });
|
||||
if (it == endIt)
|
||||
return false;
|
||||
it->recommendedWay = laneWay;
|
||||
return true;
|
||||
};
|
||||
|
||||
if (IsTurnMadeFromLeft(carDirection))
|
||||
return setFirstUnrestrictedLane(LaneWay::Left, lanesInfo.begin(), lanesInfo.end());
|
||||
if (IsTurnMadeFromRight(carDirection))
|
||||
return setFirstUnrestrictedLane(LaneWay::Right, lanesInfo.rbegin(), lanesInfo.rend());
|
||||
return false;
|
||||
}
|
||||
} // namespace routing::turns::lanes
|
||||
Loading…
Add table
Add a link
Reference in a new issue