forked from organicmaps/organicmaps
Fixing incoming edge turn generation in some cases.
This commit is contained in:
parent
3ee9969263
commit
3397cbcfb8
6 changed files with 95 additions and 58 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue