Fixing incoming edge turn generation in some cases.

This commit is contained in:
Vladimir Byko-Ianko 2015-05-14 14:26:26 +03:00 committed by Alex Zolotarev
parent 3ee9969263
commit 3397cbcfb8
6 changed files with 95 additions and 58 deletions

View file

@ -314,7 +314,7 @@ string DebugPrint(HighwayClass const cls)
case HighwayClass::LivingStreet: out << "LivingStreet";
case HighwayClass::Service: out << "Service";
case HighwayClass::Count: out << "Count";
default: out <<"Unknown value of HighwayClass: " << static_cast<int>(cls);
default: out << "Unknown value of HighwayClass: " << static_cast<int>(cls);
}
out << " ]";
return out.str();
@ -345,10 +345,11 @@ HighwayClass GetHighwayClass(feature::TypesHolder const & types)
for (auto t : types)
{
ftype::TruncValue(t, kTruncLevel);
auto const it = find_if(kHighwayClasses.cbegin(), kHighwayClasses.cend(),
[t](pair<HighwayClass, uint32_t> const & p){ return p.second == t; });
if (it != kHighwayClasses.cend())
return it->first;
for (auto const & cls : kHighwayClasses)
{
if (cls.second == t)
return cls.first;
}
}
return HighwayClass::None;

View file

@ -18,21 +18,15 @@ UNIT_TEST(RussiaMoscowLenigradskiy39UturnTurnTest)
OsrmRouter::ResultCode const result = routeResult.second;
TEST_EQUAL(result, OsrmRouter::NoError, ());
integration::TestTurnCount(route, 3);
integration::GetNthTurn(route, 0)
.TestValid()
.TestPoint({37.545981835916507, 67.530713137468041})
.TestOneOfDirections({TurnDirection::TurnSlightLeft, TurnDirection::TurnLeft});
integration::GetNthTurn(route, 1)
.TestValid()
.TestPoint({37.546738218864334, 67.531659957257347})
.TestDirection(TurnDirection::TurnLeft);
integration::GetNthTurn(route, 2)
.TestValid()
.TestPoint({37.539925407915746, 67.537083383925875})
.TestDirection(TurnDirection::TurnRight);
integration::GetTurnByPoint(route, {37., 67.}).TestNotValid();
integration::GetTurnByPoint(route, {37.546738218864334, 67.531659957257347})
integration::GetNthTurn(route, 2)
.TestValid()
.TestDirection(TurnDirection::TurnLeft);
@ -78,7 +72,7 @@ UNIT_TEST(RussiaMoscowTrikotagniAndPohodniRoundaboutTurnTest)
OsrmRouter::ResultCode const result = routeResult.second;
TEST_EQUAL(result, OsrmRouter::NoError, ());
integration::TestTurnCount(route, 3);
integration::TestTurnCount(route, 2);
integration::GetNthTurn(route, 0)
.TestValid()
@ -131,13 +125,10 @@ UNIT_TEST(RussiaMoscowTTKKashirskoeShosseOutTurnTest)
OsrmRouter::ResultCode const result = routeResult.second;
TEST_EQUAL(result, OsrmRouter::NoError, ());
integration::TestTurnCount(route, 2);
/// Checking turn in case going from not link to link
integration::TestTurnCount(route, 1);
// Checking a turn in case going from not a link to a link
integration::GetNthTurn(route, 0).TestValid().TestOneOfDirections(
{TurnDirection::TurnSlightRight, TurnDirection::TurnRight});
/// Checking turn in case of ingoing edge(s)
integration::GetNthTurn(route, 1).TestValid().TestOneOfDirections(
{TurnDirection::TurnSlightRight, TurnDirection::TurnRight});
}
UNIT_TEST(RussiaMoscowPankratevskiPerBolshaySuharedskazPloschadTurnTest)
@ -192,7 +183,7 @@ UNIT_TEST(RussiaHugeRoundaboutTurnTest)
integration::GetNthTurn(route, 0)
.TestValid()
.TestDirection(TurnDirection::EnterRoundAbout)
.TestRoundAboutExitNum(5);
.TestRoundAboutExitNum(4);
integration::GetNthTurn(route, 1)
.TestValid()
.TestDirection(TurnDirection::LeaveRoundAbout)
@ -212,3 +203,60 @@ UNIT_TEST(BelarusMiskProspNezavisimostiMKADTurnTest)
integration::GetNthTurn(route, 0).TestValid().TestOneOfDirections(
{TurnDirection::TurnSlightRight, TurnDirection::TurnRight});
}
// Test case: turning form one street to another one with the same name.
// An end user shall be informed about this manoeuvre.
UNIT_TEST(RussiaMoscowPetushkovaPetushkovaTest)
{
TRouteResult const routeResult = integration::CalculateRoute(
integration::GetAllMaps(), {37.405555547431582, 67.606396877452852}, {0., 0.},
{37.404889653177761, 67.607659749718096});
Route const & route = *routeResult.first;
OsrmRouter::ResultCode const result = routeResult.second;
TEST_EQUAL(result, OsrmRouter::NoError, ());
integration::TestTurnCount(route, 1);
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.
// 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});
Route const & route = *routeResult.first;
OsrmRouter::ResultCode const result = routeResult.second;
TEST_EQUAL(result, OsrmRouter::NoError, ());
integration::TestTurnCount(route, 1);
}
UNIT_TEST(BelarusMKADShosseinai)
{
TRouteResult const routeResult = integration::CalculateRoute(
integration::GetAllMaps(), {29.431229709918465, 66.684863888688056}, {0., 0.},
{29.426264439664614, 66.686867924003238});
Route const & route = *routeResult.first;
OsrmRouter::ResultCode const result = routeResult.second;
TEST_EQUAL(result, OsrmRouter::NoError, ());
integration::TestTurnCount(route, 1);
integration::GetNthTurn(route, 0).TestValid().TestOneOfDirections(
{TurnDirection::GoStraight, TurnDirection::TurnSlightRight});
}
// Test case: a route goes straightly 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});
Route const & route = *routeResult.first;
OsrmRouter::ResultCode const result = routeResult.second;
TEST_EQUAL(result, OsrmRouter::NoError, ());
integration::TestTurnCount(route, 0);
}

View file

@ -1331,24 +1331,20 @@ void OsrmRouter::GetTurnGeometry(m2::PointD const & p, m2::PointD const & p1,
scales::GetUpperScale(), mapping->GetMwmId());
}
bool OsrmRouter::KeepOnewayOutgoingTurnIncomingEdges(TurnItem const & turn,
bool OsrmRouter::KeepOnewayOutgoingTurnIncomingEdges(turns::TurnDirection intermediateTurnDirection,
m2::PointD const & p, m2::PointD const & p1OneSeg,
RoutingMappingPtrT const & mapping)
{
ASSERT(mapping.get(), ());
size_t const outgoingNotesCount = 1;
if (turns::IsGoStraightOrSlightTurn(turn.m_turn))
{
if (turns::IsGoStraightOrSlightTurn(intermediateTurnDirection))
return false;
}
else
{
GeomTurnCandidateT geoNodes;
GetTurnGeometry(p, p1OneSeg, geoNodes, mapping);
if (geoNodes.size() <= outgoingNotesCount)
return false;
return true;
}
GeomTurnCandidateT geoNodes;
GetTurnGeometry(p, p1OneSeg, geoNodes, mapping);
if (geoNodes.size() <= outgoingNotesCount)
return false;
return true;
}
// @todo(vbykoianko) Move this method and all dependencies to turns_generator.cpp
@ -1433,17 +1429,7 @@ void OsrmRouter::GetTurnDirection(PathData const & node1,
search::GetStreetNameAsKey(turn.m_sourceName, name1);
search::GetStreetNameAsKey(turn.m_targetName, name2);
}
/*
string road1 = ft1.GetRoadNumber();
string road2 = ft2.GetRoadNumber();
if (!turn.m_keepAnyway
&& ((!name1.empty() && name1 == name2) || (!road1.empty() && road1 == road2)))
{
turn.m_turn = turns::TurnDirection::NoTurn;
return;
}
*/
ftypes::HighwayClass const highwayClass1 = ftypes::GetHighwayClass(ft1);
ftypes::HighwayClass const highwayClass2 = ftypes::GetHighwayClass(ft2);
if (!turn.m_keepAnyway
@ -1456,7 +1442,9 @@ void OsrmRouter::GetTurnDirection(PathData const & node1,
}
if (!hasMultiTurns
&& !KeepOnewayOutgoingTurnIncomingEdges(turn, p, p1OneSeg, routingMapping)
&& !KeepOnewayOutgoingTurnIncomingEdges(turns::IntermediateDirection(
my::RadToDeg(ang::TwoVectorsAngle(p, p1OneSeg, p2))),
p, p1OneSeg, routingMapping)
&& !turns::KeepOnewayOutgoingTurnRoundabout(isRound1, isRound2))
{
turn.m_turn = turns::TurnDirection::NoTurn;

View file

@ -198,8 +198,9 @@ 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(TurnItem const & turn,
m2::PointD const & p, m2::PointD const & p1, RoutingMappingPtrT const & mapping);
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;

View file

@ -181,12 +181,12 @@ void FixupTurns(vector<m2::PointD> const & points, Route::TurnsT & turnsDir)
}
// @todo(vbykoianko) The sieve below is made for filtering unnecessary turns on Moscow's MKAD
// and roads like it. It's quick fix but it's possible to do better.
// and roads like it. It's a quick fix but it's possible to do better.
// 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 quickly.
// 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 (if them have been calculated).
// FeatureType for outgoing turns in TurnCandidatesT (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.
if (!t.m_keepAnyway && IsGoStraightOrSlightTurn(t.m_turn) && !t.m_sourceName.empty() &&
@ -240,9 +240,9 @@ bool KeepMultiTurnClassHighwayClass(ftypes::HighwayClass ingoingClass, ftypes::H
RoutingMapping const & routingMapping, Index const & index)
{
if (!IsGoStraightOrSlightTurn(turn))
return true; // The road significantly changes the direction here. Leaves this 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 it is outgoingNode */)
if (possibleTurns.size() == 1 /* There's only one exit from this vertex. NodeID of the exit is outgoingNode */)
return true;
ftypes::HighwayClass maxClassForPossibleTurns = ftypes::HighwayClass::None;
@ -256,7 +256,7 @@ bool KeepMultiTurnClassHighwayClass(ftypes::HighwayClass ingoingClass, ftypes::H
}
if (maxClassForPossibleTurns == ftypes::HighwayClass::None)
{
ASSERT(false, ("The route contains undefined HighwayClass."));
ASSERT(false, ("One of possible turns follows along an undefined HighwayClass."));
return true;
}
@ -273,7 +273,7 @@ bool KeepMultiTurnClassHighwayClass(ftypes::HighwayClass ingoingClass, ftypes::H
if (static_cast<int>(maxClassForPossibleTurns) - static_cast<int>(minClassForTheRoute) >=
maxHighwayClassDiffToKeepTheTurn)
{
// The turn shall be removed if the route passes near small roads with out changing the direction.
// The turn shall be removed if the route goes near small roads without changing the direction.
return false;
}
return true;
@ -291,8 +291,7 @@ TurnDirection RoundaboutDirection(bool isRound1, bool isRound2,
{
if (hasMultiTurns)
return TurnDirection::StayOnRoundAbout;
else
return TurnDirection::NoTurn;
return TurnDirection::NoTurn;
}
if (!isRound1 && isRound2)

View file

@ -44,9 +44,9 @@ 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 the route goes from one big road to another and the other possible turn(s) are to small roads
// in case of slight turns (that means turn is GoStraight or TurnSlight*)
/// 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,