From fa0a5040e5dce0d7f5a37b55baedcdfb13a8f8f7 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Wed, 23 Mar 2016 13:04:23 +0100 Subject: [PATCH] adding tests for guidance --- cucumber.js | 4 +- features/bicycle/destination.feature | 46 +-- features/bicycle/mode.feature | 84 ++-- features/bicycle/pushing.feature | 22 +- features/bicycle/roundabout.feature | 30 -- features/car/destination.feature | 46 +-- features/car/mode.feature | 18 +- features/car/roundabout.feature | 30 -- features/guidance/continue.feature | 90 +++++ features/guidance/end-of-road.feature | 106 +++++ features/guidance/fork.feature | 213 ++++++++++ features/guidance/merge.feature | 52 +++ features/guidance/motorway.feature | 100 +++-- features/guidance/new-name.feature | 135 +++++++ features/guidance/ramp.feature | 229 +++++++++++ features/guidance/rotary-bike.feature | 167 ++++++++ features/guidance/rotary.feature | 167 ++++++++ features/guidance/roundabout-bike.feature | 166 ++++++++ features/guidance/roundabout.feature | 87 ++--- features/guidance/suppressed.feature | 66 ++++ features/guidance/turn.feature | 284 ++++++++++++++ features/support/route.js | 7 +- features/testbot/graph.feature | 4 +- features/testbot/overlap.feature | 20 +- features/testbot/roundabout.feature | 76 ---- features/testbot/turn_angles.feature | 74 ---- features/testbot/turns.feature | 115 ------ features/testbot/uturn.feature | 9 +- include/engine/guidance/assemble_steps.hpp | 57 +-- include/engine/guidance/route_step.hpp | 2 +- include/extractor/guidance/constants.hpp | 32 ++ include/extractor/guidance/toolkit.hpp | 70 ++-- include/extractor/guidance/turn_analysis.hpp | 13 +- include/util/name_table.hpp | 2 +- include/util/range_table.hpp | 7 +- src/engine/guidance/post_processing.cpp | 43 +-- src/extractor/guidance/turn_analysis.cpp | 386 ++++++++++++------- src/util/coordinate_calculation.cpp | 15 +- src/util/name_table.cpp | 25 +- 39 files changed, 2287 insertions(+), 812 deletions(-) delete mode 100644 features/bicycle/roundabout.feature delete mode 100644 features/car/roundabout.feature create mode 100644 features/guidance/continue.feature create mode 100644 features/guidance/end-of-road.feature create mode 100644 features/guidance/fork.feature create mode 100644 features/guidance/merge.feature create mode 100644 features/guidance/new-name.feature create mode 100644 features/guidance/ramp.feature create mode 100644 features/guidance/rotary-bike.feature create mode 100644 features/guidance/rotary.feature create mode 100644 features/guidance/roundabout-bike.feature create mode 100644 features/guidance/suppressed.feature create mode 100644 features/guidance/turn.feature delete mode 100644 features/testbot/roundabout.feature delete mode 100644 features/testbot/turn_angles.feature delete mode 100644 features/testbot/turns.feature create mode 100644 include/extractor/guidance/constants.hpp diff --git a/cucumber.js b/cucumber.js index c16104c05..5a87dd7f1 100644 --- a/cucumber.js +++ b/cucumber.js @@ -1,6 +1,6 @@ module.exports = { - default: '--require features --tags ~@todo --tags ~@bug --tags ~@stress --tags ~@guidance', - verify: '--require features --tags ~@todo --tags ~@bug --tags ~@stress -f progress --tags ~@guidance', + default: '--require features --tags ~@stress --tags ~@todo', + verify: '--require features --tags ~@todo --tags ~@bug --tags ~@stress -f progress', jenkins: '--require features --tags ~@todo --tags ~@bug --tags ~@stress --tags ~@options -f progress', bugs: '--require features --tags @bug', todo: '--require features --tags @todo', diff --git a/features/bicycle/destination.feature b/features/bicycle/destination.feature index 9c7119888..c3a0173cd 100644 --- a/features/bicycle/destination.feature +++ b/features/bicycle/destination.feature @@ -19,15 +19,15 @@ Feature: Bike - Destination only, no passing through | axye | | When I route I should get - | from | to | route | - | a | b | ab | - | a | c | ab,bcd | - | a | d | ab,bcd | - | a | e | axye | - | e | d | de | - | e | c | de,bcd | - | e | b | de,bcd | - | e | a | axye | + | from | to | route | + | a | b | ab,ab | + | a | c | ab,bcd,bcd | + | a | d | ab,bcd,bcd | + | a | e | axye,axye | + | e | d | de,de | + | e | c | de,bcd,bcd | + | e | b | de,bcd,bcd | + | e | a | axye,axye | Scenario: Bike - Destination only street Given the node map @@ -45,15 +45,15 @@ Feature: Bike - Destination only, no passing through | axye | | When I route I should get - | from | to | route | - | a | b | ab | - | a | c | ab,bc | - | a | d | ab,bc,cd | - | a | e | axye | - | e | d | de | - | e | c | de,dc | - | e | b | de,dc,bc | - | e | a | axye | + | from | to | route | + | a | b | ab,ab | + | a | c | ab,bc,bc | + | a | d | ab,bc,cd,cd | + | a | e | axye,axye | + | e | d | de,de | + | e | c | de,cd,cd | + | e | b | de,cd,bc,bc | + | e | a | axye,axye | Scenario: Bike - Routing inside a destination only area Given the node map @@ -70,8 +70,8 @@ Feature: Bike - Destination only, no passing through | axye | | When I route I should get - | from | to | route | - | a | e | ab,bc,cd,de | - | e | a | de,cd,bc,ab | - | b | d | bc,cd | - | d | b | cd,bc | + | from | to | route | + | a | e | ab,bc,cd,de,de | + | e | a | de,cd,bc,ab,ab | + | b | d | bc,cd,cd | + | d | b | cd,bc,bc | diff --git a/features/bicycle/mode.feature b/features/bicycle/mode.feature index 3587f6c64..852402a72 100644 --- a/features/bicycle/mode.feature +++ b/features/bicycle/mode.feature @@ -16,13 +16,13 @@ Feature: Bike - Mode flag | cd | primary | | | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd,cd | depart,right,left,arrive | cycling,ferry,cycling,cycling | - | d | a | cd,bc,ab,ab | depart,right,left,arrive | cycling,ferry,cycling,cycling | - | c | a | bc,ab,ab | depart,left,arrive | ferry,cycling,cycling | - | d | b | cd,bc,bc | depart,right,arrive | cycling,ferry,ferry | - | a | c | ab,bc,bc | depart,right,arrive | cycling,ferry,ferry | - | b | d | bc,cd,cd | depart,left,arrive | ferry,cycling,cycling | + | from | to | route | modes | + | a | d | ab,bc,cd,cd | cycling,ferry,cycling,cycling | + | d | a | cd,bc,ab,ab | cycling,ferry,cycling,cycling | + | c | a | bc,ab,ab | ferry,cycling,cycling | + | d | b | cd,bc,bc | cycling,ferry,ferry | + | a | c | ab,bc,bc | cycling,ferry,ferry | + | b | d | bc,cd,cd | ferry,cycling,cycling | Scenario: Bike - Mode when using a train Given the node map @@ -36,13 +36,13 @@ Feature: Bike - Mode flag | cd | primary | | | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd,cd | depart,right,left,arrive | cycling,train,cycling,cycling | - | d | a | cd,bc,ab,ab | depart,right,left,arrive | cycling,train,cycling,cycling | - | c | a | bc,ab,ab | depart,left,arrive | train,cycling,cycling | - | d | b | cd,bc,bc | depart,right,arrive | cycling,train,train | - | a | c | ab,bc,bc | depart,right,arrive | cycling,train,train | - | b | d | bc,cd,cd | depart,left,arrive | train,cycling,cycling | + | from | to | route | modes | + | a | d | ab,bc,cd,cd | cycling,train,cycling,cycling | + | d | a | cd,bc,ab,ab | cycling,train,cycling,cycling | + | c | a | bc,ab,ab | train,cycling,cycling | + | d | b | cd,bc,bc | cycling,train,train | + | a | c | ab,bc,bc | cycling,train,train | + | b | d | bc,cd,cd | train,cycling,cycling | Scenario: Bike - Mode when pushing bike against oneways Given the node map @@ -56,13 +56,13 @@ Feature: Bike - Mode flag | cd | primary | | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd,cd | depart,right,left,arrive | cycling,cycling,cycling,cycling | - | d | a | cd,bc,ab,ab | depart,right,left,arrive | cycling,pushing bike,cycling,cycling | - | c | a | bc,ab,ab | depart,left,arrive | pushing bike,cycling,cycling | - | d | b | cd,bc,bc | depart,right,arrive | cycling,pushing bike,pushing bike | - | a | c | ab,bc,bc | depart,right,arrive | cycling,cycling,cycling | - | b | d | bc,cd,cd | depart,left,arrive | cycling,cycling,cycling | + | from | to | route | modes | + | a | d | ab,bc,cd,cd | cycling,cycling,cycling,cycling | + | d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling | + | c | a | bc,ab,ab | pushing bike,cycling,cycling | + | d | b | cd,bc,bc | cycling,pushing bike,pushing bike | + | a | c | ab,bc,bc | cycling,cycling,cycling | + | b | d | bc,cd,cd | cycling,cycling,cycling | Scenario: Bike - Mode when pushing on pedestrain streets Given the node map @@ -76,13 +76,13 @@ Feature: Bike - Mode flag | cd | primary | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd,cd | depart,right,left,arrive | cycling,pushing bike,cycling,cycling | - | d | a | cd,bc,ab,ab | depart,right,left,arrive | cycling,pushing bike,cycling,cycling | - | c | a | bc,ab,ab | depart,left,arrive | pushing bike,cycling,cycling | - | d | b | cd,bc,bc | depart,right,arrive | cycling,pushing bike,pushing bike | - | a | c | ab,bc,bc | depart,right,arrive | cycling,pushing bike,pushing bike | - | b | d | bc,cd,cd | depart,left,arrive | pushing bike,cycling,cycling | + | from | to | route | modes | + | a | d | ab,bc,cd,cd | cycling,pushing bike,cycling,cycling | + | d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling | + | c | a | bc,ab,ab | pushing bike,cycling,cycling | + | d | b | cd,bc,bc | cycling,pushing bike,pushing bike | + | a | c | ab,bc,bc | cycling,pushing bike,pushing bike | + | b | d | bc,cd,cd | pushing bike,cycling,cycling | Scenario: Bike - Mode when pushing on pedestrain areas Given the node map @@ -116,13 +116,13 @@ Feature: Bike - Mode flag | cd | primary | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd,cd | depart,right,left,arrive | cycling,pushing bike,cycling,cycling | - | d | a | cd,bc,ab,ab | depart,right,left,arrive | cycling,pushing bike,cycling,cycling | - | c | a | bc,ab,ab | depart,left,arrive | pushing bike,cycling,cycling | - | d | b | cd,bc,bc | depart,right,arrive | cycling,pushing bike,pushing bike | - | a | c | ab,bc,bc | depart,right,arrive | cycling,pushing bike,pushing bike | - | b | d | bc,cd,cd | depart,left,arrive | pushing bike,cycling,cycling | + | from | to | route | modes | + | a | d | ab,bc,cd,cd | cycling,pushing bike,cycling,cycling | + | d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling | + | c | a | bc,ab,ab | pushing bike,cycling,cycling | + | d | b | cd,bc,bc | cycling,pushing bike,pushing bike | + | a | c | ab,bc,bc | cycling,pushing bike,pushing bike | + | b | d | bc,cd,cd | pushing bike,cycling,cycling | Scenario: Bike - Mode when bicycle=dismount Given the node map @@ -136,13 +136,13 @@ Feature: Bike - Mode flag | cd | primary | | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd,cd | depart,right,left,arrive | cycling,pushing bike,cycling,cycling | - | d | a | cd,bc,ab,ab | depart,right,left,arrive | cycling,pushing bike,cycling,cycling | - | c | a | bc,ab,ab | depart,left,arrive | pushing bike,cycling,cycling | - | d | b | cd,bc,bc | depart,right,arrive | cycling,pushing bike,pushing bike | - | a | c | ab,bc,bc | depart,right,arrive | cycling,pushing bike,pushing bike | - | b | d | bc,cd,cd | depart,left,arrive | pushing bike,cycling,cycling | + | from | to | route | modes | + | a | d | ab,bc,cd,cd | cycling,pushing bike,cycling,cycling | + | d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling | + | c | a | bc,ab,ab | pushing bike,cycling,cycling | + | d | b | cd,bc,bc | cycling,pushing bike,pushing bike | + | a | c | ab,bc,bc | cycling,pushing bike,pushing bike | + | b | d | bc,cd,cd | pushing bike,cycling,cycling | Scenario: Bicycle - Modes when starting on forward oneway Given the node map diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature index 3d00b53e3..d67282168 100644 --- a/features/bicycle/pushing.feature +++ b/features/bicycle/pushing.feature @@ -63,7 +63,6 @@ Feature: Bike - Accessability of different way types | runway | | | | | runway | yes | foot | foot | - @todo Scenario: Bike - Pushing bikes on ways with foot=yes in one direction Then routability should be | highway | foot:forward | foot:backward | forw | backw | @@ -98,13 +97,12 @@ Feature: Bike - Accessability of different way types | cd | primary | | When I route I should get - | from | to | route | turns | - | a | d | ab,bc,cd,cd | depart,right,left,arrive | - | d | a | cd,bc,ab,ab | depart,right,left,arrive | - | c | a | bc,ab,ab | depart,left,arrive | - | d | b | cd,bc,bc | depart,right,arrive | + | from | to | route | modes | + | a | d | ab,bc,cd,cd | cycling,cycling,cycling,cycling | + | d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling | + | c | a | bc,ab,ab | pushing bike,cycling,cycling | + | d | b | cd,bc,bc | cycling,pushing bike,pushing bike | - @todo Scenario: Bike - Instructions when pushing bike on footway/pedestrian, etc. Given the node map | a | b | | @@ -117,8 +115,8 @@ Feature: Bike - Accessability of different way types | cd | primary | When I route I should get - | from | to | route | turns | - | a | d | ab,bc,cd,cd | depart,right,left,arrive | - | d | a | cd,bc,ab,ab | depart,right,left,arrive | - | c | a | bc,ab,ab | depart,left,arrive | - | d | b | cd,bc,bc | depart,right,arrive | + | from | to | route | modes | + | a | d | ab,bc,cd,cd | cycling,pushing bike,cycling,cycling | + | d | a | cd,bc,ab,ab | cycling,pushing bike,cycling,cycling | + | c | a | bc,ab,ab | pushing bike,cycling,cycling | + | d | b | cd,bc,bc | cycling,pushing bike,pushing bike | diff --git a/features/bicycle/roundabout.feature b/features/bicycle/roundabout.feature deleted file mode 100644 index 2e0d099f1..000000000 --- a/features/bicycle/roundabout.feature +++ /dev/null @@ -1,30 +0,0 @@ -@routing @bicycle @roundabout @instruction -Feature: Roundabout Instructions - - Background: - Given the profile "bicycle" - - Scenario: Bicycle - Roundabout instructions - Given the node map - | | | v | | | - | | | d | | | - | s | a | | c | u | - | | | b | | | - | | | t | | | - - And the ways - | nodes | junction | - | sa | | - | tb | | - | uc | | - | vd | | - | abcda | roundabout | - - When I route I should get - | from | to | route | turns | - | s | t | sa,tb,tb | depart,roundabout-exit-1,arrive | - | s | u | sa,uc,uc | depart,roundabout-exit-2,arrive | - | s | v | sa,vd,vd | depart,roundabout-exit-3,arrive | - | u | v | uc,vd,vd | depart,roundabout-exit-1,arrive | - | u | s | uc,sa,sa | depart,roundabout-exit-2,arrive | - | u | t | uc,tb,tb | depart,roundabout-exit-3,arrive | diff --git a/features/car/destination.feature b/features/car/destination.feature index 506aa2101..3bf07331f 100644 --- a/features/car/destination.feature +++ b/features/car/destination.feature @@ -19,15 +19,15 @@ Feature: Car - Destination only, no passing through | axye | | When I route I should get - | from | to | route | - | a | b | ab | - | a | c | ab,bcd | - | a | d | ab,bcd | - | a | e | axye | - | e | d | de | - | e | c | de,bcd | - | e | b | de,bcd | - | e | a | axye | + | from | to | route | + | a | b | ab,ab | + | a | c | ab,bcd,bcd | + | a | d | ab,bcd,bcd | + | a | e | axye,axye | + | e | d | de,de | + | e | c | de,bcd,bcd | + | e | b | de,bcd,bcd | + | e | a | axye,axye | Scenario: Car - Destination only street Given the node map @@ -45,15 +45,15 @@ Feature: Car - Destination only, no passing through | axye | | When I route I should get - | from | to | route | - | a | b | ab | - | a | c | ab,bc | - | a | d | ab,bc,cd | - | a | e | axye | - | e | d | de | - | e | c | de,dc | - | e | b | de,dc,bc | - | e | a | axye | + | from | to | route | + | a | b | ab,ab | + | a | c | ab,bc,bc | + | a | d | ab,bc,cd,cd | + | a | e | axye,axye | + | e | d | de,de | + | e | c | de,cd,cd | + | e | b | de,cd,bc,bc | + | e | a | axye,axye | Scenario: Car - Routing inside a destination only area Given the node map @@ -70,8 +70,8 @@ Feature: Car - Destination only, no passing through | axye | | When I route I should get - | from | to | route | - | a | e | ab,bc,cd,de | - | e | a | de,cd,bc,ab | - | b | d | bc,cd | - | d | b | cd,bc | + | from | to | route | + | a | e | ab,bc,cd,de,de | + | e | a | de,cd,bc,ab,ab | + | b | d | bc,cd,cd | + | d | b | cd,bc,bc | diff --git a/features/car/mode.feature b/features/car/mode.feature index f390982f8..e0feff11a 100644 --- a/features/car/mode.feature +++ b/features/car/mode.feature @@ -15,13 +15,13 @@ Feature: Car - Mode flag | cd | primary | | | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd,cd | depart,right,left,arrive | driving,ferry,driving,driving | - | d | a | cd,bc,ab,ab | depart,right,left,arrive | driving,ferry,driving,driving | - | c | a | bc,ab,ab | depart,left,arrive | ferry,driving,driving | - | d | b | cd,bc,bc | depart,right,arrive | driving,ferry,ferry | - | a | c | ab,bc,bc | depart,right,arrive | driving,ferry,ferry | - | b | d | bc,cd,cd | depart,left,arrive | ferry,driving,driving | + | from | to | route | modes | + | a | d | ab,bc,cd,cd | driving,ferry,driving,driving | + | d | a | cd,bc,ab,ab | driving,ferry,driving,driving | + | c | a | bc,ab,ab | ferry,driving,driving | + | d | b | cd,bc,bc | driving,ferry,ferry | + | a | c | ab,bc,bc | driving,ferry,ferry | + | b | d | bc,cd,cd | ferry,driving,driving | Scenario: Car - Snapping when using a ferry Given the node map @@ -34,7 +34,7 @@ Feature: Car - Mode flag | ef | primary | | | When I route I should get - | from | to | route | turns | modes | time | - | c | d | bcde,bcde | depart,arrive | ferry,ferry | 600s | + | from | to | route | modes | time | + | c | d | bcde,bcde | ferry,ferry | 600s | diff --git a/features/car/roundabout.feature b/features/car/roundabout.feature deleted file mode 100644 index beb5d4e2e..000000000 --- a/features/car/roundabout.feature +++ /dev/null @@ -1,30 +0,0 @@ -@routing @car @roundabout @instruction -Feature: Roundabout Instructions - - Background: - Given the profile "car" - - Scenario: Car - Roundabout instructions - Given the node map - | | | v | | | - | | | d | | | - | s | a | | c | u | - | | | b | | | - | | | t | | | - - And the ways - | nodes | junction | - | sa | | - | tb | | - | uc | | - | vd | | - | abcda | roundabout | - - When I route I should get - | from | to | route | turns | - | s | t | sa,tb,tb | depart,roundabout-exit-1,arrive | - | s | u | sa,uc,uc | depart,roundabout-exit-2,arrive | - | s | v | sa,vd,vd | depart,roundabout-exit-3,arrive | - | u | v | uc,vd,vd | depart,roundabout-exit-1,arrive | - | u | s | uc,sa,sa | depart,roundabout-exit-2,arrive | - | u | t | uc,tb,tb | depart,roundabout-exit-3,arrive | diff --git a/features/guidance/continue.feature b/features/guidance/continue.feature new file mode 100644 index 000000000..b3abe4843 --- /dev/null +++ b/features/guidance/continue.feature @@ -0,0 +1,90 @@ +@routing @guidance +Feature: Continue Instructions + + Background: + Given the profile "car" + Given a grid size of 10 meters + + Scenario: Road turning left + Given the node map + | | | c | | + | a | | b | d | + + And the ways + | nodes | highway | + | abc | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc,abc | depart,continue left,arrive | + | a,d | abc,bd,bd | depart,new name straight,arrive | + + Scenario: Road turning right + Given the node map + | a | | b | d | + | | | c | | + + And the ways + | nodes | highway | + | abc | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc,abc | depart,continue right,arrive | + | a,d | abc,bd,bd | depart,new name straight,arrive | + + Scenario: Road turning slight left + Given the node map + | | | | | c | + | | | | | | + | a | | b | | | + | | | | d | | + + And the ways + | nodes | highway | + | abc | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc,abc | depart,continue left,arrive | + | a,d | abc,bd,bd | depart,turn right,arrive | + + Scenario: Road turning slight right + Given the node map + | | | | d | | + | a | | b | | | + | | | | | | + | | | | | c | + + And the ways + | nodes | highway | + | abc | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc,abc | depart,continue right,arrive | + | a,d | abc,bd,bd | depart,turn left,arrive | + + Scenario: Road Loop + Given the node map + | | | f | | e | + | | | | | | + | a | | b | g | | + | | | | | | + | | | c | | d | + + And the ways + | nodes | highway | + | abcdefb | primary | + | bg | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | abcdefb,abcdefb,abcdefb | depart,continue right,arrive | + | a,f | abcdefb,abcdefb,abcdefb | depart,continue left,arrive | + | a,d | abcdefb,abcdefb,abcdefb | depart,continue right,arrive | + | a,e | abcdefb,abcdefb,abcdefb | depart,continue left,arrive | diff --git a/features/guidance/end-of-road.feature b/features/guidance/end-of-road.feature new file mode 100644 index 000000000..7f8231b79 --- /dev/null +++ b/features/guidance/end-of-road.feature @@ -0,0 +1,106 @@ +@routing @guidance +Feature: End Of Road Instructions + + Background: + Given the profile "car" + Given a grid size of 10 meters + + Scenario: End of Road with through street + Given the node map + | | | c | + | a | | b | + | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | cbd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,cbd,cbd | depart,end of road left,arrive | + | a,d | ab,cbd,cbd | depart,end of road right,arrive | + + + Scenario: End of Road with three streets + Given the node map + | | | c | + | a | | b | + | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | cb | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,cb,cb | depart,end of road left,arrive | + | a,d | ab,bd,bd | depart,end of road right,arrive | + + Scenario: End of Road with three streets, slightly angled + Given the node map + | a | | | | | c | + | | | | | | b | + | | | | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | cb | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,cb,cb | depart,end of road left,arrive | + | a,d | ab,bd,bd | depart,end of road right,arrive | + + Scenario: End of Road with three streets, slightly angled + Given the node map + | | | | | | c | + | | | | | | b | + | a | | | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | cb | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,cb,cb | depart,end of road left,arrive | + | a,d | ab,bd,bd | depart,end of road right,arrive | + + Scenario: End of Road with through street, slightly angled + Given the node map + | a | | | | | c | + | | | | | | b | + | | | | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | cbd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,cbd,cbd | depart,end of road left,arrive | + | a,d | ab,cbd,cbd | depart,end of road right,arrive | + + Scenario: End of Road with through street, slightly angled + Given the node map + | | | | | | c | + | | | | | | b | + | a | | | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | cbd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,cbd,cbd | depart,end of road left,arrive | + | a,d | ab,cbd,cbd | depart,end of road right,arrive | diff --git a/features/guidance/fork.feature b/features/guidance/fork.feature new file mode 100644 index 000000000..7b78a28c7 --- /dev/null +++ b/features/guidance/fork.feature @@ -0,0 +1,213 @@ +@routing @guidance +Feature: Fork Instructions + + Background: + Given the profile "car" + Given a grid size of 10 meters + + Scenario: Fork Same Road Class + Given the node map + | | | | | c | + | a | | b | | | + | | | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | bc | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,fork slight left,arrive | + | a,d | ab,bd,bd | depart,fork slight right,arrive | + + Scenario: Do not fork on link type + Given the node map + | | | | | c | + | a | | b | | | + | | | | | d | + + And the ways + | nodes | highway | + | abc | primary | + | bd | primary_link | + + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc | depart,arrive | + | a,d | abc,bd,bd | depart,turn slight right,arrive | + + Scenario: Fork in presence of other roads + Given the node map + | | | | | c | + | a | | b | | | + | | e | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | bc | primary | + | bd | primary | + | eb | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,fork slight left,arrive | + | a,d | ab,bd,bd | depart,fork slight right,arrive | + + Scenario: Fork Turning Slight Left + Given the node map + | | | | | | c | + | | | | | | | + | a | | b | | | | + | | | | | d | | + + And the ways + | nodes | highway | + | ab | primary | + | bc | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,fork slight left,arrive | + | a,d | ab,bd,bd | depart,fork slight right,arrive | + + Scenario: Fork Turning Slight Right + Given the node map + | | | | | c | | + | a | | b | | | | + | | | | | | | + | | | | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | bc | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,fork slight left,arrive | + | a,d | ab,bd,bd | depart,fork slight right,arrive | + + Scenario: Do not fork on service + Given the node map + | | | | | c | + | a | | b | | | + | | | | | d | + + And the ways + | nodes | highway | + | abc | residential | + | bd | service | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc | depart,arrive | + | a,d | abc,bd,bd | depart,turn slight right,arrive | + + Scenario: Fork Both Turning Slight Right + Given the node map + | a | | b | | | | + | | | | | | c | + | | | | | | d | + + And the ways + | nodes | highway | + | ab | primary | + | bc | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,fork slight left,arrive | + | a,d | ab,bd,bd | depart,fork slight right,arrive | + + Scenario: Fork Both Turning Slight Left + Given the node map + | | | | | | c | + | | | | | | d | + | a | | b | | | | + + And the ways + | nodes | highway | + | ab | primary | + | bc | primary | + | bd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,fork slight left,arrive | + | a,d | ab,bd,bd | depart,fork slight right,arrive | + + Scenario: Fork Both Turning Slight Right - Unnamed + Given the node map + | a | | b | | | | + | | | | | | c | + | | | | | | d | + + And the ways + | nodes | highway | name | + | ab | primary | | + | bc | primary | | + | bd | primary | | + + When I route I should get + | waypoints | route | turns | + | a,c | ,, | depart,fork slight left,arrive | + | a,d | ,, | depart,fork slight right,arrive | + + Scenario: Fork Both Turning Slight Left - Unnamed + Given the node map + | | | | | | c | + | | | | | | d | + | a | | b | | | | + + And the ways + | nodes | highway | name | + | ab | primary | | + | bc | primary | | + | bd | primary | | + + When I route I should get + | waypoints | route | turns | + | a,c | ,, | depart,fork slight left,arrive | + | a,d | ,, | depart,fork slight right,arrive | + + Scenario: Fork Both Turning Very Slightly Right - Unnamed + Given the node map + | a | | b | | | | | | | | | | | | | | | | + | | | | | | | | | | | | c | | | | | | | + | | | | | | | | | | | | | | | | | | d | + + And the ways + | nodes | highway | name | + | ab | primary | | + | bc | primary | | + | bd | primary | | + + When I route I should get + | waypoints | route | turns | + | a,c | ,, | depart,fork slight left,arrive | + | a,d | ,, | depart,fork slight right,arrive | + + Scenario: Fork Both Turning Very Slightly Right - Unnamed Ramps + Given the node map + | a | | b | | | | | | | | | | | | | | | | + | | | | | | | | | | | | c | | | | | | | + | | | | | | | | | | | | | | | | | | d | + + And the ways + | nodes | highway | name | + | ab | motorway_link | | + | bc | motorway_link | | + | bd | motorway_link | | + + When I route I should get + | waypoints | route | turns | + | a,c | ,, | depart,fork slight left,arrive | + | a,d | ,, | depart,fork slight right,arrive | + diff --git a/features/guidance/merge.feature b/features/guidance/merge.feature new file mode 100644 index 000000000..0736e8f7c --- /dev/null +++ b/features/guidance/merge.feature @@ -0,0 +1,52 @@ +@routing @guidance +Feature: Merging + + Background: + Given the profile "car" + Given a grid size of 10 meters + + Scenario: Merge on Four Way Intersection + Given the node map + | d | | | + | a | b | c | + | e | | | + + And the ways + | nodes | highway | + | abc | primary | + | db | primary | + | eb | primary | + + When I route I should get + | waypoints | route | turns | + | d,c | db,abc,abc | depart,merge slight right,arrive | + | e,c | eb,abc,abc | depart,merge slight left,arrive | + + Scenario: Merge on Three Way Intersection Right + Given the node map + | d | | | + | a | b | c | + + And the ways + | nodes | highway | + | abc | primary | + | db | primary | + + When I route I should get + | waypoints | route | turns | + | d,c | db,abc,abc | depart,merge slight right,arrive | + + Scenario: Merge on Three Way Intersection Right + Given the node map + | a | b | c | + | d | | | + + And the ways + | nodes | highway | + | abc | primary | + | db | primary | + + When I route I should get + | waypoints | route | turns | + | d,c | db,abc,abc | depart,merge slight left,arrive | + diff --git a/features/guidance/motorway.feature b/features/guidance/motorway.feature index bcde32271..5e9b3128c 100644 --- a/features/guidance/motorway.feature +++ b/features/guidance/motorway.feature @@ -1,8 +1,8 @@ @routing @guidance -Feature: Basic Roundabout +Feature: Motorway Guidance Background: - Given the profile "testbot" + Given the profile "car" Given a grid size of 10 meters Scenario: Ramp Exit Right @@ -16,9 +16,9 @@ Feature: Basic Roundabout | bfg | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | a,g | abcde, bfg, bfg | depart, ramp-slight-right, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | a,g | abcde,bfg,bfg | depart,ramp slight right,arrive | Scenario: Ramp Exit Right Curved Right Given the node map @@ -32,9 +32,9 @@ Feature: Basic Roundabout | bfg | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | a,g | abcde, bfg, bfg | depart, ramp-slight-right, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | a,g | abcde,bfg,bfg | depart,ramp right,arrive | Scenario: Ramp Exit Right Curved Left Given the node map @@ -49,9 +49,9 @@ Feature: Basic Roundabout | cfg | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | a,g | abcde, cfg, cfg | depart, ramp-slight-right, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | a,g | abcde,cfg,cfg | depart,ramp slight right,arrive | Scenario: Ramp Exit Left @@ -65,9 +65,9 @@ Feature: Basic Roundabout | bfg | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | a,g | abcde, bfg, bfg | depart, ramp-slight-left, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | a,g | abcde,bfg,bfg | depart,ramp slight left,arrive | Scenario: Ramp Exit Left Curved Left Given the node map @@ -81,9 +81,9 @@ Feature: Basic Roundabout | bfg | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | a,g | abcde, bfg, bfg | depart, ramp-slight-left, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | a,g | abcde,bfg,bfg | depart,ramp left,arrive | Scenario: Ramp Exit Left Curved Right Given the node map @@ -97,9 +97,9 @@ Feature: Basic Roundabout | cfg | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | a,g | abcde, cfg, cfg | depart, ramp-slight-left, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | a,g | abcde,cfg,cfg | depart,ramp slight left,arrive | Scenario: On Ramp Right Given the node map @@ -112,9 +112,9 @@ Feature: Basic Roundabout | fgd | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | f,e | abcde, fgd, fgd | depart, merge-slight-left, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | f,e | fgd,abcde,abcde | depart,merge slight left,arrive | Scenario: On Ramp Left Given the node map @@ -127,9 +127,9 @@ Feature: Basic Roundabout | fgd | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | f,e | abcde, fgd, fgd | depart, merge-slight-right, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | f,e | fgd,abcde,abcde | depart,merge slight right,arrive | Scenario: Highway Fork Given the node map @@ -143,9 +143,9 @@ Feature: Basic Roundabout | cfg | motorway | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde, abcde | depart, fork-left, arrive | - | a,g | abcde, cfg, cfg | depart, fork-right, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde,abcde | depart,fork slight left,arrive | + | a,g | abcde,cfg,cfg | depart,fork slight right,arrive | Scenario: Fork After Ramp Given the node map @@ -160,9 +160,9 @@ Feature: Basic Roundabout | cfg | motorway | When I route I should get - | waypoints | route | turns | - | a,e | abc, cde, cde | depart, fork-left, arrive | - | a,g | abc, cfg, cfg | depart, fork-right, arrive | + | waypoints | route | turns | + | a,e | abc,cde,cde | depart,fork slight left,arrive | + | a,g | abc,cfg,cfg | depart,fork slight right,arrive | Scenario: On And Off Ramp Right Given the node map @@ -176,11 +176,11 @@ Feature: Basic Roundabout | chi | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | f,e | fgc, abcde, abcde | depart, merge-slight-left, arrive | - | a,i | abcde, chi, chi | depart, ramp-slight-right, arrive | - | f,i | fgc, chi, chi | depart, turn-slight-right, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | f,e | fgc,abcde,abcde | depart,merge slight left,arrive | + | a,i | abcde,chi,chi | depart,ramp slight right,arrive | + | f,i | fgc,chi,chi | depart,ramp right,arrive | Scenario: On And Off Ramp Left Given the node map @@ -194,9 +194,25 @@ Feature: Basic Roundabout | chi | motorway_link | When I route I should get - | waypoints | route | turns | - | a,e | abcde, abcde | depart, arrive | - | f,e | fgc, abcde, abcde | depart, merge-slight-right, arrive | - | a,i | abcde, chi, chi | depart, ramp-slight-left, arrive | - | f,i | fgc, chi, chi | depart, turn-slight-left, arrive | + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + | f,e | fgc,abcde,abcde | depart,merge slight right,arrive | + | a,i | abcde,chi,chi | depart,ramp slight left,arrive | + | f,i | fgc,chi,chi | depart,ramp left,arrive | + Scenario: Merging Motorways + Given the node map + | e | | | + | a | b | c | + | d | | | + + And the ways + | nodes | highway | + | abc | motorway | + | db | motorway | + | eb | motorway | + + When I route I should get + | waypoints | route | turns | + | d,c | db,abc,abc | depart,merge slight left,arrive | + | e,c | eb,abc,abc | depart,merge slight right,arrive | diff --git a/features/guidance/new-name.feature b/features/guidance/new-name.feature new file mode 100644 index 000000000..1fdf1ce42 --- /dev/null +++ b/features/guidance/new-name.feature @@ -0,0 +1,135 @@ +@routing @guidance +Feature: New-Name Instructions + + Background: + Given the profile "car" + Given a grid size of 10 meters + + Scenario: Undisturbed name Change + Given the node map + | a | | b | | c | + + And the ways + | nodes | + | ab | + | bc | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,new name straight,arrive | + + + Scenario: Undisturbed Name Change with unannounced Turn Right + Given the node map + | a | | b | | | + | | | | | c | + + And the ways + | nodes | + | ab | + | bc | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,new name slight right,arrive | + + Scenario: Undisturbed Name Change with unannounced Turn Left + Given the node map + | | | | | c | + | a | | b | | | + + And the ways + | nodes | + | ab | + | bc | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,new name slight left,arrive | + + Scenario: Disturbed Name Change with Turn + Given the node map + | a | | b | | | + | | d | | | c | + + And the ways + | nodes | + | ab | + | bc | + | db | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,new name slight right,arrive | + + Scenario: Undisturbed Name Change with announced Turn Left + Given the node map + | | | c | + | a | | b | + + And the ways + | nodes | + | ab | + | bc | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,new name left,arrive | + + Scenario: Undisturbed Name Change with announced Turn Sharp Left + Given the node map + | c | | | + | a | | b | + + And the ways + | nodes | + | ab | + | bc | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,new name sharp left,arrive | + + Scenario: Undisturbed Name Change with announced Turn Right + Given the node map + | a | | b | + | | | c | + + And the ways + | nodes | + | ab | + | bc | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,new name right,arrive | + + Scenario: Undisturbed Name Change with announced Turn Sharp Right + Given the node map + | a | | b | + | c | | | + + And the ways + | nodes | + | ab | + | bc | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,new name sharp right,arrive | + + + Scenario: Disturbed Name Change with minor road class + Given the node map + | a | | b | | d | + | | | | | c | + + And the ways + | nodes | highway | + | ab | residential | + | bc | residential | + | bd | service | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bc,bc | depart,new name slight right,arrive | diff --git a/features/guidance/ramp.feature b/features/guidance/ramp.feature new file mode 100644 index 000000000..3c3ce3959 --- /dev/null +++ b/features/guidance/ramp.feature @@ -0,0 +1,229 @@ +@routing @guidance +Feature: Ramp Guidance + + Background: + Given the profile "car" + Given a grid size of 10 meters + + Scenario: Ramp On Through Street Right + Given the node map + | a | b | c | + | | d | | + + And the ways + | nodes | highway | + | abc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | abc,bd,bd | depart,ramp right,arrive | + + Scenario: Ramp On Through Street Left + Given the node map + | | d | | + | a | b | c | + + And the ways + | nodes | highway | + | abc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | abc,bd,bd | depart,ramp left,arrive | + + Scenario: Ramp On Through Street Left and Right + Given the node map + | | e | | + | a | b | c | + | | d | | + + And the ways + | nodes | highway | + | be | motorway_link | + | abc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | abc,bd,bd | depart,ramp right,arrive | + | a,e | abc,be,be | depart,ramp left,arrive | + + Scenario: Ramp On Three Way Intersection Right + Given the node map + | a | b | c | + | | d | | + + And the ways + | nodes | highway | + | ab | tertiary | + | bc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | ab,bd,bd | depart,ramp right,arrive | + + Scenario: Ramp On Three Way Intersection Right + Given the node map + | | | c | + | a | b | | + | | d | | + + And the ways + | nodes | highway | + | ab | tertiary | + | bc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | ab,bd,bd | depart,ramp right,arrive | + + Scenario: Ramp Off Though Street + Given the node map + | | | c | + | a | b | | + | | d | | + + And the ways + | nodes | highway | + | abc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | abc,bd,bd | depart,ramp right,arrive | + | a,c | abc,abc | depart,arrive | + + Scenario: Straight Ramp Off Turning Though Street + Given the node map + | | | c | + | a | b | d | + + And the ways + | nodes | highway | + | abc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | abc,bd,bd | depart,ramp straight,arrive | + | a,c | abc,abc,abc | depart,continue left,arrive | + + Scenario: Fork Ramp Off Turning Though Street + Given the node map + | | | c | + | a | b | | + | | | d | + + And the ways + | nodes | highway | + | abc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | abc,bd,bd | depart,ramp right,arrive | + | a,c | abc,abc,abc | depart,continue left,arrive | + + Scenario: Fork Ramp + Given the node map + | | | c | + | a | b | | + | | | d | + + And the ways + | nodes | highway | + | ab | tertiary | + | bc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | ab,bd,bd | depart,ramp right,arrive | + | a,c | ab,bc,bc | depart,turn left,arrive | + + Scenario: Fork Slight Ramp + Given the node map + | | | | c | + | a | b | | | + | | | | d | + + And the ways + | nodes | highway | + | ab | tertiary | + | bc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | ab,bd,bd | depart,ramp slight right,arrive | + | a,c | ab,bc,bc | depart,turn slight left,arrive | + + Scenario: Fork Slight Ramp on Through Street + Given the node map + | | | | c | + | a | b | | | + | | | | d | + + And the ways + | nodes | highway | + | abc | tertiary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | abc,bd,bd | depart,ramp slight right,arrive | + | a,c | abc,abc,abc | depart,continue slight left,arrive | + + Scenario: Fork Slight Ramp on Obvious Through Street + Given the node map + | | | | c | + | a | b | | | + | | | | d | + + And the ways + | nodes | highway | + | abc | primary | + | bd | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,d | abc,bd,bd | depart,ramp slight right,arrive | + | a,c | abc,abc | depart,arrive | + + Scenario: Two Ramps Joining into common Motorway + Given the node map + | a | | | | + | | | c | d | + | b | | | | + + And the ways + | nodes | highway | + | ac | motorway_link | + | bc | motorway_link | + | cd | motorway | + + When I route I should get + | waypoints | route | turns | + | a,d | ac,cd,cd | depart,new name slight left,arrive | + | b,d | bc,cd,cd | depart,new name slight right,arrive | + + Scenario: Two Ramps Joining into common Motorway Unnamed + Given the node map + | a | | | | + | | | c | d | + | b | | | | + + And the ways + | nodes | highway | name | + | ac | motorway_link | | + | bc | motorway_link | | + | cd | motorway | | + + When I route I should get + | waypoints | route | turns | + | a,d | , | depart,arrive | + | b,d | , | depart,arrive | diff --git a/features/guidance/rotary-bike.feature b/features/guidance/rotary-bike.feature new file mode 100644 index 000000000..512b81580 --- /dev/null +++ b/features/guidance/rotary-bike.feature @@ -0,0 +1,167 @@ +@routing @guidance +Feature: Rotary + + Background: + Given the profile "bicycle" + Given a grid size of 30 meters + + Scenario: Enter and Exit + Given the node map + | | | a | | | + | | | b | | | + | h | g | | c | d | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bgecb | roundabout | + + When I route I should get + | waypoints | route | turns | + | a,d | ab,cd,cd | depart,bgecb-exit-3,arrive | + | a,f | ab,ef,ef | depart,bgecb-exit-2,arrive | + | a,h | ab,gh,gh | depart,bgecb-exit-1,arrive | + | d,f | cd,ef,ef | depart,bgecb-exit-3,arrive | + | d,h | cd,gh,gh | depart,bgecb-exit-2,arrive | + | d,a | cd,ab,ab | depart,bgecb-exit-1,arrive | + | f,h | ef,gh,gh | depart,bgecb-exit-3,arrive | + | f,a | ef,ab,ab | depart,bgecb-exit-2,arrive | + | f,d | ef,cd,cd | depart,bgecb-exit-1,arrive | + | h,a | gh,ab,ab | depart,bgecb-exit-3,arrive | + | h,d | gh,cd,cd | depart,bgecb-exit-2,arrive | + | h,f | gh,ef,ef | depart,bgecb-exit-1,arrive | + + Scenario: Only Enter + Given the node map + | | | a | | | + | | | b | | | + | d | c | | g | h | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | a,e | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | a,g | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | d,e | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | d,g | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | d,b | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | f,g | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | f,b | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | f,c | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | h,b | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | h,c | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | h,e | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + + Scenario: Only Exit + Given the node map + | | | a | | | + | | | b | | | + | d | c | | g | h | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | b,d | bcegb,cd,cd | depart,bcegb-exit-1,arrive | + | b,f | bcegb,ef,ef | depart,bcegb-exit-2,arrive | + | b,h | bcegb,gh,gh | depart,bcegb-exit-3,arrive | + | c,f | bcegb,ef,ef | depart,bcegb-exit-1,arrive | + | c,h | bcegb,gh,gh | depart,bcegb-exit-2,arrive | + | c,a | bcegb,ab,ab | depart,bcegb-exit-3,arrive | + | e,h | bcegb,gh,gh | depart,bcegb-exit-1,arrive | + | e,a | bcegb,ab,ab | depart,bcegb-exit-2,arrive | + | e,d | bcegb,cd,cd | depart,bcegb-exit-3,arrive | + | g,a | bcegb,ab,ab | depart,bcegb-exit-1,arrive | + | g,d | bcegb,cd,cd | depart,bcegb-exit-2,arrive | + | g,f | bcegb,ef,ef | depart,bcegb-exit-3,arrive | + #phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits + + Scenario: Drive Around + Given the node map + | | | a | | | + | | | b | | | + | d | c | | g | h | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | b,c | bcegb,bcegb | depart,arrive | + | b,e | bcegb,bcegb | depart,arrive | + | b,g | bcegb,bcegb | depart,arrive | + | c,e | bcegb,bcegb | depart,arrive | + | c,g | bcegb,bcegb | depart,arrive | + | c,b | bcegb,bcegb | depart,arrive | + | e,g | bcegb,bcegb | depart,arrive | + | e,b | bcegb,bcegb | depart,arrive | + | e,c | bcegb,bcegb | depart,arrive | + | g,b | bcegb,bcegb | depart,arrive | + | g,c | bcegb,bcegb | depart,arrive | + | g,e | bcegb,bcegb | depart,arrive | + + #needs to be adjusted when name-discovery works for entrys + Scenario: Mixed Entry and Exit + Given the node map + | | c | | a | | + | j | | b | | f | + | | k | | e | | + | l | | h | | d | + | | g | | i | | + + And the ways + | nodes | junction | oneway | + | abc | | yes | + | def | | yes | + | ghi | | yes | + | jkl | | yes | + | bkheb | roundabout | yes | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc,abc | depart,rotary-exit-1,arrive | + | a,l | abc,jkl,jkl | depart,bkheb-exit-2,arrive | + | a,i | abc,ghi,ghi | depart,bkheb-exit-3,arrive | + | a,f | abc,def,def | depart,bkheb-exit-4,arrive | + | d,f | def,def,def | depart,rotary-exit-1,arrive | + | d,c | def,abc,abc | depart,bkheb-exit-2,arrive | + | d,l | def,jkl,jkl | depart,bkheb-exit-3,arrive | + | d,i | def,ghi,ghi | depart,bkheb-exit-4,arrive | + | g,i | ghi,ghi,ghi | depart,rotary-exit-1,arrive | + | g,f | ghi,def,def | depart,bkheb-exit-2,arrive | + | g,c | ghi,abc,abc | depart,bkheb-exit-3,arrive | + | g,l | ghi,jkl,jkl | depart,bkheb-exit-4,arrive | + | j,l | jkl,jkl,jkl | depart,rotary-exit-1,arrive | + | j,i | jkl,ghi,ghi | depart,bkheb-exit-2,arrive | + | j,f | jkl,def,def | depart,bkheb-exit-3,arrive | + | j,c | jkl,abc,abc | depart,bkheb-exit-4,arrive | diff --git a/features/guidance/rotary.feature b/features/guidance/rotary.feature new file mode 100644 index 000000000..ef8a1eb14 --- /dev/null +++ b/features/guidance/rotary.feature @@ -0,0 +1,167 @@ +@routing @guidance +Feature: Rotary + + Background: + Given the profile "car" + Given a grid size of 30 meters + + Scenario: Enter and Exit + Given the node map + | | | a | | | + | | | b | | | + | h | g | | c | d | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bgecb | roundabout | + + When I route I should get + | waypoints | route | turns | + | a,d | ab,cd,cd | depart,bgecb-exit-3,arrive | + | a,f | ab,ef,ef | depart,bgecb-exit-2,arrive | + | a,h | ab,gh,gh | depart,bgecb-exit-1,arrive | + | d,f | cd,ef,ef | depart,bgecb-exit-3,arrive | + | d,h | cd,gh,gh | depart,bgecb-exit-2,arrive | + | d,a | cd,ab,ab | depart,bgecb-exit-1,arrive | + | f,h | ef,gh,gh | depart,bgecb-exit-3,arrive | + | f,a | ef,ab,ab | depart,bgecb-exit-2,arrive | + | f,d | ef,cd,cd | depart,bgecb-exit-1,arrive | + | h,a | gh,ab,ab | depart,bgecb-exit-3,arrive | + | h,d | gh,cd,cd | depart,bgecb-exit-2,arrive | + | h,f | gh,ef,ef | depart,bgecb-exit-1,arrive | + + Scenario: Only Enter + Given the node map + | | | a | | | + | | | b | | | + | d | c | | g | h | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | a,e | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | a,g | ab,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | d,e | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | d,g | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | d,b | cd,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | f,g | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | f,b | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | f,c | ef,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | h,b | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | h,c | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + | h,e | gh,bcegb,bcegb | depart,bcegb-exit-undefined,arrive | + + Scenario: Only Exit + Given the node map + | | | a | | | + | | | b | | | + | d | c | | g | h | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | b,d | bcegb,cd,cd | depart,bcegb-exit-1,arrive | + | b,f | bcegb,ef,ef | depart,bcegb-exit-2,arrive | + | b,h | bcegb,gh,gh | depart,bcegb-exit-3,arrive | + | c,f | bcegb,ef,ef | depart,bcegb-exit-1,arrive | + | c,h | bcegb,gh,gh | depart,bcegb-exit-2,arrive | + | c,a | bcegb,ab,ab | depart,bcegb-exit-3,arrive | + | e,h | bcegb,gh,gh | depart,bcegb-exit-1,arrive | + | e,a | bcegb,ab,ab | depart,bcegb-exit-2,arrive | + | e,d | bcegb,cd,cd | depart,bcegb-exit-3,arrive | + | g,a | bcegb,ab,ab | depart,bcegb-exit-1,arrive | + | g,d | bcegb,cd,cd | depart,bcegb-exit-2,arrive | + | g,f | bcegb,ef,ef | depart,bcegb-exit-3,arrive | + #phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits + + Scenario: Drive Around + Given the node map + | | | a | | | + | | | b | | | + | d | c | | g | h | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | b,c | bcegb,bcegb | depart,arrive | + | b,e | bcegb,bcegb | depart,arrive | + | b,g | bcegb,bcegb | depart,arrive | + | c,e | bcegb,bcegb | depart,arrive | + | c,g | bcegb,bcegb | depart,arrive | + | c,b | bcegb,bcegb | depart,arrive | + | e,g | bcegb,bcegb | depart,arrive | + | e,b | bcegb,bcegb | depart,arrive | + | e,c | bcegb,bcegb | depart,arrive | + | g,b | bcegb,bcegb | depart,arrive | + | g,c | bcegb,bcegb | depart,arrive | + | g,e | bcegb,bcegb | depart,arrive | + + #needs to be adjusted when name-discovery works for entrys + Scenario: Mixed Entry and Exit + Given the node map + | | c | | a | | + | j | | b | | f | + | | k | | e | | + | l | | h | | d | + | | g | | i | | + + And the ways + | nodes | junction | oneway | + | abc | | yes | + | def | | yes | + | ghi | | yes | + | jkl | | yes | + | bkheb | roundabout | yes | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc,abc | depart,rotary-exit-1,arrive | + | a,l | abc,jkl,jkl | depart,bkheb-exit-2,arrive | + | a,i | abc,ghi,ghi | depart,bkheb-exit-3,arrive | + | a,f | abc,def,def | depart,bkheb-exit-4,arrive | + | d,f | def,def,def | depart,rotary-exit-1,arrive | + | d,c | def,abc,abc | depart,bkheb-exit-2,arrive | + | d,l | def,jkl,jkl | depart,bkheb-exit-3,arrive | + | d,i | def,ghi,ghi | depart,bkheb-exit-4,arrive | + | g,i | ghi,ghi,ghi | depart,rotary-exit-1,arrive | + | g,f | ghi,def,def | depart,bkheb-exit-2,arrive | + | g,c | ghi,abc,abc | depart,bkheb-exit-3,arrive | + | g,l | ghi,jkl,jkl | depart,bkheb-exit-4,arrive | + | j,l | jkl,jkl,jkl | depart,rotary-exit-1,arrive | + | j,i | jkl,ghi,ghi | depart,bkheb-exit-2,arrive | + | j,f | jkl,def,def | depart,bkheb-exit-3,arrive | + | j,c | jkl,abc,abc | depart,bkheb-exit-4,arrive | diff --git a/features/guidance/roundabout-bike.feature b/features/guidance/roundabout-bike.feature new file mode 100644 index 000000000..3652c1520 --- /dev/null +++ b/features/guidance/roundabout-bike.feature @@ -0,0 +1,166 @@ +@routing @guidance +Feature: Basic Roundabout + + Background: + Given the profile "bicycle" + Given a grid size of 10 meters + + Scenario: Enter and Exit + Given the node map + | | | a | | | + | | | b | | | + | h | g | | c | d | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bgecb | roundabout | + + When I route I should get + | waypoints | route | turns | + | a,d | ab,cd,cd | depart,roundabout-exit-3,arrive | + | a,f | ab,ef,ef | depart,roundabout-exit-2,arrive | + | a,h | ab,gh,gh | depart,roundabout-exit-1,arrive | + | d,f | cd,ef,ef | depart,roundabout-exit-3,arrive | + | d,h | cd,gh,gh | depart,roundabout-exit-2,arrive | + | d,a | cd,ab,ab | depart,roundabout-exit-1,arrive | + | f,h | ef,gh,gh | depart,roundabout-exit-3,arrive | + | f,a | ef,ab,ab | depart,roundabout-exit-2,arrive | + | f,d | ef,cd,cd | depart,roundabout-exit-1,arrive | + | h,a | gh,ab,ab | depart,roundabout-exit-3,arrive | + | h,d | gh,cd,cd | depart,roundabout-exit-2,arrive | + | h,f | gh,ef,ef | depart,roundabout-exit-1,arrive | + + Scenario: Only Enter + Given the node map + | | | a | | | + | | | b | | | + | d | c | | g | h | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | a,e | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | a,g | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | d,e | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | d,g | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | d,b | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | f,g | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | f,b | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | f,c | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | h,b | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | h,c | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | h,e | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + + Scenario: Only Exit + Given the node map + | | | a | | | + | | | b | | | + | d | c | | g | h | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | b,d | bcegb,cd,cd | depart,roundabout-exit-1,arrive | + | b,f | bcegb,ef,ef | depart,roundabout-exit-2,arrive | + | b,h | bcegb,gh,gh | depart,roundabout-exit-3,arrive | + | c,f | bcegb,ef,ef | depart,roundabout-exit-1,arrive | + | c,h | bcegb,gh,gh | depart,roundabout-exit-2,arrive | + | c,a | bcegb,ab,ab | depart,roundabout-exit-3,arrive | + | e,h | bcegb,gh,gh | depart,roundabout-exit-1,arrive | + | e,a | bcegb,ab,ab | depart,roundabout-exit-2,arrive | + | e,d | bcegb,cd,cd | depart,roundabout-exit-3,arrive | + | g,a | bcegb,ab,ab | depart,roundabout-exit-1,arrive | + | g,d | bcegb,cd,cd | depart,roundabout-exit-2,arrive | + | g,f | bcegb,ef,ef | depart,roundabout-exit-3,arrive | + #phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits + + Scenario: Drive Around + Given the node map + | | | a | | | + | | | b | | | + | d | c | | g | h | + | | | e | | | + | | | f | | | + + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | b,c | bcegb,bcegb | depart,arrive | + | b,e | bcegb,bcegb | depart,arrive | + | b,g | bcegb,bcegb | depart,arrive | + | c,e | bcegb,bcegb | depart,arrive | + | c,g | bcegb,bcegb | depart,arrive | + | c,b | bcegb,bcegb | depart,arrive | + | e,g | bcegb,bcegb | depart,arrive | + | e,b | bcegb,bcegb | depart,arrive | + | e,c | bcegb,bcegb | depart,arrive | + | g,b | bcegb,bcegb | depart,arrive | + | g,c | bcegb,bcegb | depart,arrive | + | g,e | bcegb,bcegb | depart,arrive | + + Scenario: Mixed Entry and Exit + Given the node map + | | c | | a | | + | j | | b | | f | + | | k | | e | | + | l | | h | | d | + | | g | | i | | + + And the ways + | nodes | junction | oneway | + | abc | | yes | + | def | | yes | + | ghi | | yes | + | jkl | | yes | + | bkheb | roundabout | yes | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc,abc | depart,roundabout-exit-1,arrive | + | a,l | abc,jkl,jkl | depart,roundabout-exit-2,arrive | + | a,i | abc,ghi,ghi | depart,roundabout-exit-3,arrive | + | a,f | abc,def,def | depart,roundabout-exit-4,arrive | + | d,f | def,def,def | depart,roundabout-exit-1,arrive | + | d,c | def,abc,abc | depart,roundabout-exit-2,arrive | + | d,l | def,jkl,jkl | depart,roundabout-exit-3,arrive | + | d,i | def,ghi,ghi | depart,roundabout-exit-4,arrive | + | g,i | ghi,ghi,ghi | depart,roundabout-exit-1,arrive | + | g,f | ghi,def,def | depart,roundabout-exit-2,arrive | + | g,c | ghi,abc,abc | depart,roundabout-exit-3,arrive | + | g,l | ghi,jkl,jkl | depart,roundabout-exit-4,arrive | + | j,l | jkl,jkl,jkl | depart,roundabout-exit-1,arrive | + | j,i | jkl,ghi,ghi | depart,roundabout-exit-2,arrive | + | j,f | jkl,def,def | depart,roundabout-exit-3,arrive | + | j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive | diff --git a/features/guidance/roundabout.feature b/features/guidance/roundabout.feature index 21d653087..71e527a1a 100644 --- a/features/guidance/roundabout.feature +++ b/features/guidance/roundabout.feature @@ -2,7 +2,7 @@ Feature: Basic Roundabout Background: - Given the profile "testbot" + Given the profile "car" Given a grid size of 10 meters Scenario: Enter and Exit @@ -19,28 +19,28 @@ Feature: Basic Roundabout | cd | | | ef | | | gh | | - | bcegb | roundabout | + | bgecb | roundabout | When I route I should get | waypoints | route | turns | - | a,d | ab,cd,cd | depart,roundabout-exit-1,arrive | + | a,d | ab,cd,cd | depart,roundabout-exit-3,arrive | | a,f | ab,ef,ef | depart,roundabout-exit-2,arrive | - | a,h | ab,gh,gh | depart,roundabout-exit-3,arrive | - | d,f | cd,ef,ef | depart,roundabout-exit-1,arrive | + | a,h | ab,gh,gh | depart,roundabout-exit-1,arrive | + | d,f | cd,ef,ef | depart,roundabout-exit-3,arrive | | d,h | cd,gh,gh | depart,roundabout-exit-2,arrive | - | d,a | cd,ab,ab | depart,roundabout-exit-3,arrive | - | f,h | ef,gh,gh | depart,roundabout-exit-1,arrive | + | d,a | cd,ab,ab | depart,roundabout-exit-1,arrive | + | f,h | ef,gh,gh | depart,roundabout-exit-3,arrive | | f,a | ef,ab,ab | depart,roundabout-exit-2,arrive | - | f,d | ef,cd,cd | depart,roundabout-exit-3,arrive | - | h,a | gh,ab,ab | depart,roundabout-exit-1,arrive | + | f,d | ef,cd,cd | depart,roundabout-exit-1,arrive | + | h,a | gh,ab,ab | depart,roundabout-exit-3,arrive | | h,d | gh,cd,cd | depart,roundabout-exit-2,arrive | - | h,f | gh,ef,ef | depart,roundabout-exit-3,arrive | + | h,f | gh,ef,ef | depart,roundabout-exit-1,arrive | Scenario: Only Enter Given the node map | | | a | | | | | | b | | | - | h | g | | c | d | + | d | c | | g | h | | | | e | | | | | | f | | | @@ -53,29 +53,25 @@ Feature: Basic Roundabout | bcegb | roundabout | When I route I should get - | waypoints | route | turns | - | a,b | ab,ab | depart,arrive | - | a,c | ab,bcegb | depart,roundabout-enter,arrive | - | a,e | ab,bcegb | depart,roundabout-enter,arrive | - | a,g | ab,bcegb | depart,roundabout-enter,arrive | - | d,c | cd,cd | depart,arrive | - | d,e | cd,bcegb | depart,roundabout-enter,arrive | - | d,g | cd,bcegb | depart,roundabout-enter,arrive | - | d,b | cd,bcegb | depart,roundabout-enter,arrive | - | f,e | ef,ef | depart,arrive | - | f,g | ef,bcegb | depart,roundabout-enter,arrive | - | f,b | ef,bcegb | depart,roundabout-enter,arrive | - | f,c | ef,bcegb | depart,roundabout-enter,arrive | - | h,g | gh,gh | depart,arrive | - | h,b | gh,bcegb | depart,roundabout-enter,arrive | - | h,c | gh,bcegb | depart,roundabout-enter,arrive | - | h,e | gh,bcegb | depart,roundabout-enter,arrive | + | waypoints | route | turns | + | a,c | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | a,e | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | a,g | ab,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | d,e | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | d,g | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | d,b | cd,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | f,g | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | f,b | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | f,c | ef,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | h,b | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | h,c | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | + | h,e | gh,bcegb,bcegb | depart,roundabout-exit-undefined,arrive | Scenario: Only Exit Given the node map | | | a | | | | | | b | | | - | h | g | | c | d | + | d | c | | g | h | | | | e | | | | | | f | | | @@ -89,28 +85,25 @@ Feature: Basic Roundabout When I route I should get | waypoints | route | turns | - | b,a | ab,ab | depart,arrive | | b,d | bcegb,cd,cd | depart,roundabout-exit-1,arrive | | b,f | bcegb,ef,ef | depart,roundabout-exit-2,arrive | | b,h | bcegb,gh,gh | depart,roundabout-exit-3,arrive | - | c,d | cd,cd | depart,arrive | | c,f | bcegb,ef,ef | depart,roundabout-exit-1,arrive | | c,h | bcegb,gh,gh | depart,roundabout-exit-2,arrive | | c,a | bcegb,ab,ab | depart,roundabout-exit-3,arrive | - | e,f | ef,ef | depart,arrive | | e,h | bcegb,gh,gh | depart,roundabout-exit-1,arrive | | e,a | bcegb,ab,ab | depart,roundabout-exit-2,arrive | | e,d | bcegb,cd,cd | depart,roundabout-exit-3,arrive | - | g,h | gh,gh | depart,arrive | | g,a | bcegb,ab,ab | depart,roundabout-exit-1,arrive | | g,d | bcegb,cd,cd | depart,roundabout-exit-2,arrive | | g,f | bcegb,ef,ef | depart,roundabout-exit-3,arrive | + #phantom node snapping can result in a full round-trip here, therefore we cannot test b->a and the other direct exits Scenario: Drive Around Given the node map | | | a | | | | | | b | | | - | h | g | | c | d | + | d | c | | g | h | | | | e | | | | | | f | | | @@ -139,11 +132,11 @@ Feature: Basic Roundabout Scenario: Mixed Entry and Exit Given the node map - | | a | | c | | - | l | | b | | d | + | | c | | a | | + | j | | b | | f | | | k | | e | | - | j | | h | | f | - | | i | | g | | + | l | | h | | d | + | | g | | i | | And the ways | nodes | junction | oneway | @@ -151,23 +144,23 @@ Feature: Basic Roundabout | def | | yes | | ghi | | yes | | jkl | | yes | - | behkb | roundabout | yes | + | bkheb | roundabout | yes | When I route I should get | waypoints | route | turns | | a,c | abc,abc,abc | depart,roundabout-exit-1,arrive | - | a,f | abc,def,def | depart,roundabout-exit-2,arrive | + | a,l | abc,jkl,jkl | depart,roundabout-exit-2,arrive | | a,i | abc,ghi,ghi | depart,roundabout-exit-3,arrive | - | a,l | abc,jkl,jkl | depart,roundabout-exit-4,arrive | + | a,f | abc,def,def | depart,roundabout-exit-4,arrive | | d,f | def,def,def | depart,roundabout-exit-1,arrive | - | d,i | def,ghi,ghi | depart,roundabout-exit-2,arrive | + | d,c | def,abc,abc | depart,roundabout-exit-2,arrive | | d,l | def,jkl,jkl | depart,roundabout-exit-3,arrive | - | d,c | def,abc,abc | depart,roundabout-exit-4,arrive | + | d,i | def,ghi,ghi | depart,roundabout-exit-4,arrive | | g,i | ghi,ghi,ghi | depart,roundabout-exit-1,arrive | - | g,l | ghi,jkl,jkl | depart,roundabout-exit-2,arrive | + | g,f | ghi,def,def | depart,roundabout-exit-2,arrive | | g,c | ghi,abc,abc | depart,roundabout-exit-3,arrive | - | g,f | ghi,edf,edf | depart,roundabout-exit-4,arrive | + | g,l | ghi,jkl,jkl | depart,roundabout-exit-4,arrive | | j,l | jkl,jkl,jkl | depart,roundabout-exit-1,arrive | - | j,c | jkl,abc,abc | depart,roundabout-exit-2,arrive | + | j,i | jkl,ghi,ghi | depart,roundabout-exit-2,arrive | | j,f | jkl,def,def | depart,roundabout-exit-3,arrive | - | j,i | jkl,ghi,ghi | depart,roundabout-exit-4,arrive | + | j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive | diff --git a/features/guidance/suppressed.feature b/features/guidance/suppressed.feature new file mode 100644 index 000000000..89b58655c --- /dev/null +++ b/features/guidance/suppressed.feature @@ -0,0 +1,66 @@ +@routing @guidance +Feature: Suppressed Turns + + Background: + Given the profile "car" + Given a grid size of 10 meters + + Scenario: Do not announce passing a exit ramp + Given the node map + | a | b | c | d | e | + | | | | f | g | + + And the ways + | nodes | highway | + | abcde | motorway | + | bfg | motorway_link | + + When I route I should get + | waypoints | route | turns | + | a,e | abcde,abcde | depart,arrive | + + Scenario: Do not announce reference changes + Given the node map + | a | b | c | d | e | f | + + And the ways + | nodes | highway | name | ref | + | ab | motorway | highway | A1 | + | bc | motorway | highway | A1,A2 | + | cd | motorway | highway | A2 | + | de | motorway | highway | | + | ef | motorway | highway | A1 | + + When I route I should get + | waypoints | route | turns | + | a,f | highway (A1),highway (A1) | depart,arrive | + + + Scenario: Don't Announce Turn on following major road class -- service + Given the node map + | a | b | d | + | | | c | + + And the ways + | nodes | highway | + | abc | primary | + | bd | service | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc | depart,arrive | + + Scenario: Don't Announce Turn on following major road class -- residential + Given the node map + | a | b | d | + | | | c | + + And the ways + | nodes | highway | + | abc | primary | + | bd | residential | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc | depart,arrive | + | a,d | abc,bd,bd | depart,turn straight,arrive | diff --git a/features/guidance/turn.feature b/features/guidance/turn.feature new file mode 100644 index 000000000..3eb5fc354 --- /dev/null +++ b/features/guidance/turn.feature @@ -0,0 +1,284 @@ +@routing @guidance +Feature: Simple Turns + + Background: + Given the profile "car" + Given a grid size of 10 meters + + Scenario: Four Way Intersection + Given the node map + | | c | | + | a | b | e | + | | d | | + + And the ways + | nodes | highway | + | ab | primary | + | cb | primary | + | db | primary | + | eb | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,cb,cb | depart,turn left,arrive | + | a,e | ab,eb,eb | depart,new name straight,arrive | + | a,d | ab,db,db | depart,turn right,arrive | + | c,a | cb,ab,ab | depart,turn right,arrive | + | c,d | cb,db,db | depart,new name straight,arrive | + | c,e | cb,eb,eb | depart,turn left,arrive | + | d,a | db,ab,ab | depart,turn left,arrive | + | d,c | db,cb,cb | depart,new name straight,arrive | + | d,e | db,eb,eb | depart,turn right,arrive | + | e,a | eb,ab,ab | depart,new name straight,arrive | + | e,c | eb,cb,cb | depart,turn right,arrive | + | e,d | eb,db,db | depart,turn left,arrive | + + Scenario: Rotated Four Way Intersection + Given the node map + | a | | c | + | | b | | + | d | | e | + + And the ways + | nodes | highway | + | ab | primary | + | cb | primary | + | db | primary | + | eb | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,cb,cb | depart,turn left,arrive | + | a,e | ab,eb,eb | depart,new name straight,arrive | + | a,d | ab,db,db | depart,turn right,arrive | + | c,a | cb,ab,ab | depart,turn right,arrive | + | c,d | cb,db,db | depart,new name straight,arrive | + | c,e | cb,eb,eb | depart,turn left,arrive | + | d,a | db,ab,ab | depart,turn left,arrive | + | d,c | db,cb,cb | depart,new name straight,arrive | + | d,e | db,eb,eb | depart,turn right,arrive | + | e,a | eb,ab,ab | depart,new name straight,arrive | + | e,c | eb,cb,cb | depart,turn right,arrive | + | e,d | eb,db,db | depart,turn left,arrive | + + + Scenario: Four Way Intersection Through Street + Given the node map + | | c | | + | a | b | e | + | | d | | + + And the ways + | nodes | highway | + | abe | primary | + | cb | primary | + | db | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | abe,cb,cb | depart,turn left,arrive | + | a,e | abe,abe | depart,arrive | + | a,d | abe,db,db | depart,turn right,arrive | + | c,a | cb,abe,abe | depart,turn right,arrive | + | c,d | cb,db,db | depart,new name straight,arrive | + | c,e | cb,abe,abe | depart,turn left,arrive | + | d,a | db,abe,abe | depart,turn left,arrive | + | d,c | db,cb,cb | depart,new name straight,arrive | + | d,e | db,abe,abe | depart,turn right,arrive | + | e,a | abe,abe | depart,arrive | + | e,c | abe,cb,cb | depart,turn right,arrive | + | e,d | abe,db,db | depart,turn left,arrive | + + Scenario: Four Way Intersection Double Through Street + Given the node map + | | c | | + | a | b | e | + | | d | | + + And the ways + | nodes | highway | + | abe | primary | + | cbd | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | abe,cbd,cbd | depart,turn left,arrive | + | a,e | abe,abe | depart,arrive | + | a,d | abe,cbd,cbd | depart,turn right,arrive | + | c,a | cbd,abe,abe | depart,turn right,arrive | + | c,d | cbd,cbd | depart,arrive | + | c,e | cbd,abe,abe | depart,turn left,arrive | + | d,a | cbd,abe,abe | depart,turn left,arrive | + | d,c | cbd,cbd | depart,arrive | + | d,e | cbd,abe,abe | depart,turn right,arrive | + | e,a | abe,abe | depart,arrive | + | e,c | abe,cbd,cbd | depart,turn right,arrive | + | e,d | abe,cbd,cbd | depart,turn left,arrive | + + Scenario: Three Way Intersection + Given the node map + | | c | | + | a | b | d | + + And the ways + | nodes | highway | + | ab | primary | + | cb | primary | + | db | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | ab,cb,cb | depart,turn left,arrive | + | a,d | ab,db,db | depart,new name straight,arrive | + | d,c | db,cb,cb | depart,turn right,arrive | + | d,a | db,ab,ab | depart,new name straight,arrive | + + Scenario: Three Way Intersection on Through Street + Given the node map + | | d | | + | a | b | c | + + And the ways + | nodes | highway | + | abc | primary | + | db | primary | + + When I route I should get + | waypoints | route | turns | + | a,c | abc,abc | depart,arrive | + | a,d | abc,db,db | depart,turn left,arrive | + | c,a | abc,abc | depart,arrive | + | c,d | abc,db,db | depart,turn right,arrive | + + Scenario: High Degree Intersection + Given the node map + | i | | b | | c | + | | | | | | + | | | | | | + | h | | a | | d | + | | | | | | + | | | | | | + | g | | f | | e | + + And the ways + | nodes | highway | + | ab | primary | + | ac | primary | + | ad | primary | + | ae | primary | + | af | primary | + | ag | primary | + | ah | primary | + | ai | primary | + + When I route I should get + | waypoints | route | turns | + | b,c | ab,ac,ac | depart,turn sharp left,arrive | + | b,d | ab,ad,ad | depart,turn left,arrive | + | b,e | ab,ae,ae | depart,turn slight left,arrive | + | b,f | ab,af,af | depart,new name straight,arrive | + | b,g | ab,ag,ag | depart,turn slight right,arrive | + | b,h | ab,ah,ah | depart,turn right,arrive | + | b,i | ab,ai,ai | depart,turn sharp right,arrive | + + Scenario: Disturbed High Degree Intersection + Given the node map + | | | b | | | + | i | | | | c | + | | | | | | + | h | | a | | d | + | | | | | | + | g | | | | e | + | | | f | | | + + And the ways + | nodes | highway | + | ab | primary | + | ac | primary | + | ad | primary | + | ae | primary | + | af | primary | + | ag | primary | + | ah | primary | + | ai | primary | + + When I route I should get + | waypoints | route | turns | + | b,c | ab,ac,ac | depart,turn sharp left,arrive | + | b,d | ab,ad,ad | depart,turn left,arrive | + | b,e | ab,ae,ae | depart,turn slight left,arrive | + | b,f | ab,af,af | depart,new name straight,arrive | + | b,g | ab,ag,ag | depart,turn slight right,arrive | + | b,h | ab,ah,ah | depart,turn right,arrive | + | b,i | ab,ai,ai | depart,turn sharp right,arrive | + + Scenario: Turn instructions at high latitude + Given the node locations + | node | lat | lon | + | a | 55.68740 | 12.52430 | + | b | 55.68745 | 12.52409 | + | c | 55.68711 | 12.52383 | + | d | 55.68745 | 12.52450 | + | e | 55.68755 | 12.52450 | + | x | -55.68740 | 12.52430 | + | y | -55.68745 | 12.52409 | + | z | -55.68711 | 12.52383 | + | v | -55.68745 | 12.52450 | + | w | -55.68755 | 12.52450 | + + And the ways + | nodes | + | ab | + | bc | + | bd | + | be | + | xy | + | yz | + | vy | + | wy | + + When I route I should get + | from | to | route | turns | + | a | c | ab,bc,bc | depart,turn left,arrive | + | c | a | bc,ab,ab | depart,turn right,arrive | + | x | z | xy,yz,yz | depart,turn right,arrive | + | z | x | yz,xy,xy | depart,turn left,arrive | + + Scenario: Four Way Intersection Double Through Street Segregated + Given the node map + | | b | | c | | + | i | | | | d | + | | | a | | | + | h | | | | e | + | | g | | f | | + + And the ways + | nodes | highway | oneway | name | + | ha | primary | yes | first | + | ai | primary | yes | first | + | ae | primary | yes | first | + | da | primary | yes | first | + | ba | primary | yes | second | + | ac | primary | yes | second | + | fa | primary | yes | second | + | ag | primary | yes | second | + + When I route I should get + | waypoints | route | turns | + | f,e | second,first,first | depart,turn right,arrive | + | f,c | second,second | depart,arrive | + | f,i | second,first,first | depart,turn left,arrive | + | f,g | second,second,second | depart,continue uturn,arrive | + | d,c | first,second,second | depart,turn right,arrive | + | d,i | first,first | depart,arrive | + | d,g | first,second,second | depart,turn left,arrive | + | d,e | first,first,first | depart,continue uturn,arrive | + | b,i | second,first,first | depart,turn right,arrive | + | b,g | second,second | depart,arrive | + | b,e | second,first,first | depart,turn left,arrive | + | b,c | second,second,second | depart,continue uturn,arrive | + | h,g | first,second,second | depart,turn right,arrive | + | h,e | first,first | depart,arrive | + | h,c | first,second,second | depart,turn left,arrive | + | h,i | first,first,first | depart,continue uturn,arrive | + diff --git a/features/support/route.js b/features/support/route.js index 7c208ff0b..1dbce8cb9 100644 --- a/features/support/route.js +++ b/features/support/route.js @@ -144,9 +144,14 @@ module.exports = function () { return v.maneuver.type; case 'roundabout': return 'roundabout-exit-' + v.maneuver.exit; + case 'rotary': + if( 'rotary_name' in v ) + return v.rotary_name + '-exit-' + v.maneuver.exit; + else + return 'rotary-exit-' + v.maneuver.exit; // FIXME this is a little bit over-simplistic for merge/fork instructions default: - return v.maneuver.modifier; + return v.maneuver.type + ' ' + v.maneuver.modifier; } }) .join(','); diff --git a/features/testbot/graph.feature b/features/testbot/graph.feature index f86b99444..81741aa93 100644 --- a/features/testbot/graph.feature +++ b/features/testbot/graph.feature @@ -36,5 +36,5 @@ Feature: Basic Routing | fy | last | When I route I should get - | from | to | route | turns | - | x | y | first,compr,last,last | depart,right,left,arrive | + | from | to | route | + | x | y | first,compr,last,last | diff --git a/features/testbot/overlap.feature b/features/testbot/overlap.feature index 509867fb5..c76cff270 100644 --- a/features/testbot/overlap.feature +++ b/features/testbot/overlap.feature @@ -1,10 +1,9 @@ -@routing @testbot @overlap +@routing @testbot @overlap @todo Feature: Testbot - overlapping ways - + Background: Given the profile "testbot" - @bug @610 Scenario: Testbot - multiple way between same nodes Note that cb is connecting the same two nodes as bc Given the node map @@ -18,11 +17,10 @@ Feature: Testbot - overlapping ways | cb | secondary | When I route I should get - | from | to | route | - | a | d | ab,bc,cd | - | d | a | cd,bc,ab | - - @bug @610 + | from | to | route | + | a | d | ab,bc,cd,cd | + | d | a | cd,bc,ab,ab | + Scenario: Testbot - area on top of way Given the node map | x | a | b | y | @@ -34,6 +32,6 @@ Feature: Testbot - overlapping ways | abcda | secondary | yes | When I route I should get - | from | to | route | - | x | y | xaby | - | y | x | xaby | + | from | to | route | + | x | y | xaby,xaby | + | y | x | xaby,xaby | diff --git a/features/testbot/roundabout.feature b/features/testbot/roundabout.feature deleted file mode 100644 index 90f2fc0c3..000000000 --- a/features/testbot/roundabout.feature +++ /dev/null @@ -1,76 +0,0 @@ -@routing @testbot @roundabout @instruction -Feature: Roundabout Instructions - - Background: - Given the profile "testbot" - - Scenario: Testbot - Roundabout - Given the node map - | | | v | | | - | | | d | | | - | s | a | | c | u | - | | | b | | | - | | | t | | | - - And the ways - | nodes | junction | - | sa | | - | tb | | - | uc | | - | vd | | - | abcda | roundabout | - - When I route I should get - | from | to | route | turns | - | s | t | sa,tb,tb | depart,roundabout-exit-1,arrive | - | s | u | sa,uc,uc | depart,roundabout-exit-2,arrive | - | s | v | sa,vd,vd | depart,roundabout-exit-3,arrive | - | t | u | tb,uc,uc | depart,roundabout-exit-1,arrive | - | t | v | tb,vd,vd | depart,roundabout-exit-2,arrive | - | t | s | tb,sa,sa | depart,roundabout-exit-3,arrive | - | u | v | uc,vd,vd | depart,roundabout-exit-1,arrive | - | u | s | uc,sa,sa | depart,roundabout-exit-2,arrive | - | u | t | uc,tb,tb | depart,roundabout-exit-3,arrive | - | v | s | vd,sa,sa | depart,roundabout-exit-1,arrive | - | v | t | vd,tb,tb | depart,roundabout-exit-2,arrive | - | v | u | vd,uc,uc | depart,roundabout-exit-3,arrive | - - Scenario: Testbot - Roundabout with oneway links - Given the node map - | | | p | o | | | - | | | h | g | | | - | i | a | | | f | n | - | j | b | | | e | m | - | | | c | d | | | - | | | k | l | | | - - And the ways - | nodes | junction | oneway | - | ai | | yes | - | jb | | yes | - | ck | | yes | - | ld | | yes | - | em | | yes | - | nf | | yes | - | go | | yes | - | ph | | yes | - | abcdefgha | roundabout | | - - When I route I should get - | from | to | route | turns | - | j | k | jb,ck,ck | depart,roundabout-exit-1,arrive | - | j | m | jb,em,em | depart,roundabout-exit-2,arrive | - | j | o | jb,go,go | depart,roundabout-exit-3,arrive | - | j | i | jb,ai,ai | depart,roundabout-exit-4,arrive | - | l | m | ld,em,em | depart,roundabout-exit-1,arrive | - | l | o | ld,go,go | depart,roundabout-exit-2,arrive | - | l | i | ld,ai,ai | depart,roundabout-exit-3,arrive | - | l | k | ld,ck,ck | depart,roundabout-exit-4,arrive | - | n | o | nf,go,go | depart,roundabout-exit-1,arrive | - | n | i | nf,ai,ai | depart,roundabout-exit-2,arrive | - | n | k | nf,ck,ck | depart,roundabout-exit-3,arrive | - | n | m | nf,em,em | depart,roundabout-exit-4,arrive | - | p | i | ph,ai,ai | depart,roundabout-exit-1,arrive | - | p | k | ph,ck,ck | depart,roundabout-exit-2,arrive | - | p | m | ph,em,em | depart,roundabout-exit-3,arrive | - | p | o | ph,go,go | depart,roundabout-exit-4,arrive | diff --git a/features/testbot/turn_angles.feature b/features/testbot/turn_angles.feature deleted file mode 100644 index 115fd233d..000000000 --- a/features/testbot/turn_angles.feature +++ /dev/null @@ -1,74 +0,0 @@ -@routing @testbot @via -Feature: Via points - - Background: - Given the profile "testbot" - - And a grid size of 4 meters - - Scenario: Basic Right Turn - Given the node map - | a | b | c | d | e | f | g | - | | | | | | h | | - | | | | | | i | | - | | | | | | j | | - | | | | | | k | | - - And the ways - | nodes | oneway | - | abcdefg | yes | - | ehijk | yes | - - When I route I should get - | from | to | route | distance | turns | - | a | k | abcdefg,ehijk,ehijk | 34m +-1 | depart,right,arrive | - - Scenario: Slight Turn - Given the node map - | a | b | c | d | e | f | g | | - | | | | | | h | i | | - | | | | | | | | j | - | | | | | | | | k | - - And the ways - | nodes | oneway | - | abcdefg | yes | - | ehijk | yes | - - When I route I should get - | from | to | route | distance | turns | - | a | k | abcdefg,ehijk,ehijk | 35m +-1 | depart,slight right,arrive | - - Scenario: Nearly Slight Turn - Given the node map - | a | b | c | d | e | f | g | | - | | | | | | h | | | - | | | | | | | i | | - | | | | | | | | j | - | | | | | | | | k | - - And the ways - | nodes | oneway | - | abcdefg | yes | - | ehijk | yes | - - When I route I should get - | from | to | route | distance | turns | - | a | k | abcdefg,ehijk,ehijk | 37m +-1 | depart,right,arrive | - - Scenario: Nearly Slight Turn (Variation) - Given the node map - | a | b | c | d | e | f | g | | - | | | | | | h | | | - | | | | | | | i | | - | | | | | | | j | | - | | | | | | | | k | - - And the ways - | nodes | oneway | - | abcdefg | yes | - | ehijk | yes | - - When I route I should get - | from | to | route | distance | turns | - | a | k | abcdefg,ehijk,ehijk | 37m +-1 | depart,right,arrive | diff --git a/features/testbot/turns.feature b/features/testbot/turns.feature deleted file mode 100644 index c80bdf713..000000000 --- a/features/testbot/turns.feature +++ /dev/null @@ -1,115 +0,0 @@ -@routing @turns @testbot -Feature: Turn directions/codes - - Background: - Given the profile "testbot" - - Scenario: Turn directions - Given the node map - | o | p | a | b | c | - | n | | | | d | - | m | | x | | e | - | l | | | | f | - | k | j | i | h | g | - - And the ways - | nodes | - | xi | - | xk | - | xm | - | xo | - | xa | - | xc | - | xe | - | xg | - - When I route I should get - | from | to | route | turns | - | i | k | xi,xk,xk | depart,sharp left,arrive | - | i | m | xi,xm,xm | depart,left,arrive | - | i | o | xi,xo,xo | depart,slight left,arrive | - | i | a | xi,xa,xa | depart,straight,arrive | - | i | c | xi,xc,xc | depart,slight right,arrive | - | i | e | xi,xe,xe | depart,right,arrive | - | i | g | xi,xg,xg | depart,sharp right,arrive | - - | k | m | xk,xm,xm | depart,sharp left,arrive | - | k | o | xk,xo,xo | depart,left,arrive | - | k | a | xk,xa,xa | depart,slight left,arrive | - | k | c | xk,xc,xc | depart,straight,arrive | - | k | e | xk,xe,xe | depart,slight right,arrive | - | k | g | xk,xg,xg | depart,right,arrive | - | k | i | xk,xi,xi | depart,sharp right,arrive | - - | m | o | xm,xo,xo | depart,sharp left,arrive | - | m | a | xm,xa,xa | depart,left,arrive | - | m | c | xm,xc,xc | depart,slight left,arrive | - | m | e | xm,xe,xe | depart,straight,arrive | - | m | g | xm,xg,xg | depart,slight right,arrive | - | m | i | xm,xi,xi | depart,right,arrive | - | m | k | xm,xk,xk | depart,sharp right,arrive | - - | o | a | xo,xa,xa | depart,sharp left,arrive | - | o | c | xo,xc,xc | depart,left,arrive | - | o | e | xo,xe,xe | depart,slight left,arrive | - | o | g | xo,xg,xg | depart,straight,arrive | - | o | i | xo,xi,xi | depart,slight right,arrive | - | o | k | xo,xk,xk | depart,right,arrive | - | o | m | xo,xm,xm | depart,sharp right,arrive | - - | a | c | xa,xc,xc | depart,sharp left,arrive | - | a | e | xa,xe,xe | depart,left,arrive | - | a | g | xa,xg,xg | depart,slight left,arrive | - | a | i | xa,xi,xi | depart,straight,arrive | - | a | k | xa,xk,xk | depart,slight right,arrive | - | a | m | xa,xm,xm | depart,right,arrive | - | a | o | xa,xo,xo | depart,sharp right,arrive | - - | c | e | xc,xe,xe | depart,sharp left,arrive | - | c | g | xc,xg,xg | depart,left,arrive | - | c | i | xc,xi,xi | depart,slight left,arrive | - | c | k | xc,xk,xk | depart,straight,arrive | - | c | m | xc,xm,xm | depart,slight right,arrive | - | c | o | xc,xo,xo | depart,right,arrive | - | c | a | xc,xa,xa | depart,sharp right,arrive | - - | e | g | xe,xg,xg | depart,sharp left,arrive | - | e | i | xe,xi,xi | depart,left,arrive | - | e | k | xe,xk,xk | depart,slight left,arrive | - | e | m | xe,xm,xm | depart,straight,arrive | - | e | o | xe,xo,xo | depart,slight right,arrive | - | e | a | xe,xa,xa | depart,right,arrive | - | e | c | xe,xc,xc | depart,sharp right,arrive | - - | g | i | xg,xi,xi | depart,sharp left,arrive | - | g | k | xg,xk,xk | depart,left,arrive | - | g | m | xg,xm,xm | depart,slight left,arrive | - | g | o | xg,xo,xo | depart,straight,arrive | - | g | a | xg,xa,xa | depart,slight right,arrive | - | g | c | xg,xc,xc | depart,right,arrive | - | g | e | xg,xe,xe | depart,sharp right,arrive | - - Scenario: Turn instructions at high latitude - # https://github.com/DennisOSRM/Project-OSRM/issues/532 - Given the node locations - | node | lat | lon | - | a | 55.68740 | 12.52430 | - | b | 55.68745 | 12.52409 | - | c | 55.68711 | 12.52383 | - | x | -55.68740 | 12.52430 | - | y | -55.68745 | 12.52409 | - | z | -55.68711 | 12.52383 | - - And the ways - | nodes | - | ab | - | bc | - | xy | - | yz | - - When I route I should get - | from | to | route | turns | - | a | c | ab,bc,bc | depart,left,arrive | - | c | a | bc,ab,ab | depart,right,arrive | - | x | z | xy,yz,yz | depart,right,arrive | - | z | x | yz,xy,xy | depart,left,arrive | diff --git a/features/testbot/uturn.feature b/features/testbot/uturn.feature index cfa5fc13c..27ae5a482 100644 --- a/features/testbot/uturn.feature +++ b/features/testbot/uturn.feature @@ -20,8 +20,8 @@ Feature: U-turns at via points | fg | When I route I should get - | waypoints | route | turns | - | a,e,c | ab,be,be,ef,fg,dg,cd,cd | depart,right,arrive,depart,straight,left,left,arrive | + | waypoints | route | + | a,e,c | ab,be,be,ef,fg,dg,cd,cd | Scenario: Query param to allow U-turns at all via points Given the node map @@ -45,7 +45,6 @@ Feature: U-turns at via points | waypoints | route | | a,e,c | ab,be,be,be,bc,bc | - @todo Scenario: Instructions at via points at u-turns Given the node map | a | b | c | d | @@ -65,8 +64,8 @@ Feature: U-turns at via points | fg | When I route I should get - | waypoints | route | turns | - | a,e,c | ab,be,be,bc,bc | depart,right,uturn,right,arrive | + | waypoints | route | + | a,e,c | ab,be,be,be,bc,bc | Scenario: u-turn mixed with non-uturn vias Given the node map diff --git a/include/engine/guidance/assemble_steps.hpp b/include/engine/guidance/assemble_steps.hpp index 71b569375..0bc4d52ab 100644 --- a/include/engine/guidance/assemble_steps.hpp +++ b/include/engine/guidance/assemble_steps.hpp @@ -1,20 +1,20 @@ #ifndef ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_ #define ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_ +#include "engine/guidance/leg_geometry.hpp" #include "engine/guidance/route_step.hpp" #include "engine/guidance/step_maneuver.hpp" -#include "engine/guidance/leg_geometry.hpp" #include "engine/guidance/toolkit.hpp" -#include "extractor/guidance/turn_instruction.hpp" #include "engine/internal_route_result.hpp" #include "engine/phantom_node.hpp" -#include "util/coordinate_calculation.hpp" -#include "util/coordinate.hpp" -#include "util/bearing.hpp" +#include "extractor/guidance/turn_instruction.hpp" #include "extractor/travel_mode.hpp" +#include "util/bearing.hpp" +#include "util/coordinate.hpp" +#include "util/coordinate_calculation.hpp" -#include #include +#include namespace osrm { @@ -44,7 +44,7 @@ std::vector assembleSteps(const DataFacadeT &facade, const bool target_traversed_in_reverse) { const double constexpr ZERO_DURATION = 0., ZERO_DISTANCE = 0.; - const constexpr char* NO_ROTARY_NAME = ""; + const constexpr char *NO_ROTARY_NAME = ""; const EdgeWeight source_duration = source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight; const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode @@ -85,14 +85,9 @@ std::vector assembleSteps(const DataFacadeT &facade, BOOST_ASSERT(segment_duration >= 0); const auto name = facade.GetNameForID(path_point.name_id); const auto distance = leg_geometry.segment_distances[segment_index]; - steps.push_back(RouteStep{path_point.name_id, - name, - NO_ROTARY_NAME, - segment_duration / 10.0, - distance, - path_point.travel_mode, - maneuver, - leg_geometry.FrontIndex(segment_index), + steps.push_back(RouteStep{path_point.name_id, name, NO_ROTARY_NAME, + segment_duration / 10.0, distance, path_point.travel_mode, + maneuver, leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1}); maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction, leg_geometry, segment_index); @@ -103,13 +98,8 @@ std::vector assembleSteps(const DataFacadeT &facade, const auto distance = leg_geometry.segment_distances[segment_index]; const int duration = segment_duration + target_duration; BOOST_ASSERT(duration >= 0); - steps.push_back(RouteStep{target_node.name_id, - facade.GetNameForID(target_node.name_id), - NO_ROTARY_NAME, - duration / 10., - distance, - target_mode, - maneuver, + steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id), + NO_ROTARY_NAME, duration / 10., distance, target_mode, maneuver, leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1}); } @@ -127,14 +117,10 @@ std::vector assembleSteps(const DataFacadeT &facade, int duration = target_duration - source_duration; BOOST_ASSERT(duration >= 0); - steps.push_back(RouteStep{source_node.name_id, - facade.GetNameForID(source_node.name_id), - NO_ROTARY_NAME, - duration / 10., - leg_geometry.segment_distances[segment_index], - source_mode, - std::move(maneuver), - leg_geometry.FrontIndex(segment_index), + steps.push_back(RouteStep{source_node.name_id, facade.GetNameForID(source_node.name_id), + NO_ROTARY_NAME, duration / 10., + leg_geometry.segment_distances[segment_index], source_mode, + std::move(maneuver), leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1}); } @@ -142,14 +128,9 @@ std::vector assembleSteps(const DataFacadeT &facade, // This step has length zero, the only reason we need it is the target location auto final_maneuver = detail::stepManeuverFromGeometry( extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Arrive, leg_geometry); - steps.push_back(RouteStep{target_node.name_id, - facade.GetNameForID(target_node.name_id), - NO_ROTARY_NAME, - ZERO_DURATION, - ZERO_DISTANCE, - target_mode, - final_maneuver, - leg_geometry.locations.size(), + steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id), + NO_ROTARY_NAME, ZERO_DURATION, ZERO_DISTANCE, target_mode, + final_maneuver, leg_geometry.locations.size(), leg_geometry.locations.size()}); return steps; diff --git a/include/engine/guidance/route_step.hpp b/include/engine/guidance/route_step.hpp index 13f9ae150..d5950a61d 100644 --- a/include/engine/guidance/route_step.hpp +++ b/include/engine/guidance/route_step.hpp @@ -1,8 +1,8 @@ #ifndef ROUTE_STEP_HPP #define ROUTE_STEP_HPP -#include "extractor/travel_mode.hpp" #include "engine/guidance/step_maneuver.hpp" +#include "extractor/travel_mode.hpp" #include diff --git a/include/extractor/guidance/constants.hpp b/include/extractor/guidance/constants.hpp new file mode 100644 index 000000000..041868221 --- /dev/null +++ b/include/extractor/guidance/constants.hpp @@ -0,0 +1,32 @@ +#ifndef OSRM_EXTRACTOR_GUIDANCE_CONSTANTS_HPP_ +#define OSRM_EXTRACTOR_GUIDANCE_CONSTANTS_HPP_ + +namespace osrm +{ +namespace extractor +{ +namespace guidance +{ + +const bool constexpr INVERT = true; + +// what angle is interpreted as going straight +const double constexpr STRAIGHT_ANGLE = 180.; +// if a turn deviates this much from going straight, it will be kept straight +const double constexpr MAXIMAL_ALLOWED_NO_TURN_DEVIATION = 3.; +// angle that lies between two nearly indistinguishable roads +const double constexpr NARROW_TURN_ANGLE = 40.; +const double constexpr GROUP_ANGLE = 90; +// angle difference that can be classified as straight, if its the only narrow turn +const double constexpr FUZZY_ANGLE_DIFFERENCE = 15.; +const double constexpr DISTINCTION_RATIO = 2; +const unsigned constexpr INVALID_NAME_ID = 0; + +const double constexpr MAX_ROUNDABOUT_RADIUS = 15; // 30 m diameter as final distinction +const double constexpr INCREASES_BY_FOURTY_PERCENT = 1.4; + +} // namespace guidance +} // namespace extractor +} // namespace osrm + +#endif // OSRM_EXTRACTOR_GUIDANCE_CONSTANTS_HPP_ diff --git a/include/extractor/guidance/toolkit.hpp b/include/extractor/guidance/toolkit.hpp index 029c109af..ff3ba8e53 100644 --- a/include/extractor/guidance/toolkit.hpp +++ b/include/extractor/guidance/toolkit.hpp @@ -8,14 +8,14 @@ #include "extractor/compressed_edge_container.hpp" #include "extractor/query_node.hpp" -#include "extractor/guidance/discrete_angle.hpp" #include "extractor/guidance/classification_data.hpp" +#include "extractor/guidance/discrete_angle.hpp" #include "extractor/guidance/turn_instruction.hpp" #include -#include #include #include +#include #include namespace osrm @@ -42,16 +42,15 @@ getCoordinateFromCompressedRange(util::Coordinate current_coordinate, const util::Coordinate final_coordinate, const std::vector &query_nodes) { - const auto extractCoordinateFromNode = [](const extractor::QueryNode &node) -> util::Coordinate - { + const auto extractCoordinateFromNode = + [](const extractor::QueryNode &node) -> util::Coordinate { return {node.lon, node.lat}; }; double distance_to_current_coordinate = 0; double distance_to_next_coordinate = 0; // get the length that is missing from the current segment to reach DESIRED_SEGMENT_LENGTH - const auto getFactor = [](const double first_distance, const double second_distance) - { + const auto getFactor = [](const double first_distance, const double second_distance) { BOOST_ASSERT(first_distance < detail::DESIRED_SEGMENT_LENGTH); double segment_length = second_distance - first_distance; BOOST_ASSERT(segment_length > 0); @@ -104,8 +103,8 @@ getRepresentativeCoordinate(const NodeID from_node, const extractor::CompressedEdgeContainer &compressed_geometries, const std::vector &query_nodes) { - const auto extractCoordinateFromNode = [](const extractor::QueryNode &node) -> util::Coordinate - { + const auto extractCoordinateFromNode = + [](const extractor::QueryNode &node) -> util::Coordinate { return {node.lon, node.lat}; }; @@ -298,14 +297,10 @@ inline DirectionModifier getTurnDirection(const double angle) // swaps left <-> right modifier types inline DirectionModifier mirrorDirectionModifier(const DirectionModifier modifier) { - const constexpr DirectionModifier results[] = {DirectionModifier::UTurn, - DirectionModifier::SharpLeft, - DirectionModifier::Left, - DirectionModifier::SlightLeft, - DirectionModifier::Straight, - DirectionModifier::SlightRight, - DirectionModifier::Right, - DirectionModifier::SharpRight}; + const constexpr DirectionModifier results[] = { + DirectionModifier::UTurn, DirectionModifier::SharpLeft, DirectionModifier::Left, + DirectionModifier::SlightLeft, DirectionModifier::Straight, DirectionModifier::SlightRight, + DirectionModifier::Right, DirectionModifier::SharpRight}; return results[modifier]; } @@ -345,14 +340,14 @@ inline bool requiresNameAnnounced(const std::string &from, const std::string &to std::string to_ref; // Split from the format "{name} ({ref})" -> name, ref - auto split = [](const std::string &name, std::string &out_name, std::string &out_ref) - { + auto split = [](const std::string &name, std::string &out_name, std::string &out_ref) { const auto ref_begin = name.find_first_of('('); if (ref_begin != std::string::npos) { - //we might need to trim a space, if there is a reference - out_name = name.substr(0, ref_begin - (ref_begin > 0 && name[ref_begin-1] == ' ')); - out_ref = name.substr(ref_begin + 1, name.find_first_of(')') - 1); + if (ref_begin != 0) + out_name = name.substr(0, ref_begin - 1); + const auto ref_end = name.find_first_of(')'); + out_ref = name.substr(ref_begin + 1, ref_end - ref_begin - 1); } else { @@ -364,35 +359,38 @@ inline bool requiresNameAnnounced(const std::string &from, const std::string &to split(to, to_name, to_ref); // check similarity of names - auto names_are_empty = from_name.empty() && to_name.empty(); - auto names_are_equal = from_name == to_name; - auto name_is_removed = !from_name.empty() && to_name.empty(); + const auto names_are_empty = from_name.empty() && to_name.empty(); + const auto names_are_equal = from_name == to_name; + const auto name_is_removed = !from_name.empty() && to_name.empty(); // references are contained in one another - auto refs_are_empty = from_ref.empty() && to_ref.empty(); - auto ref_is_contained = - !from_ref.empty() && !to_ref.empty() && + const auto refs_are_empty = from_ref.empty() && to_ref.empty(); + const auto ref_is_contained = + from_ref.empty() || to_ref.empty() || (from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos); - auto ref_is_removed = !from_ref.empty() && to_ref.empty(); + const auto ref_is_removed = !from_ref.empty() && to_ref.empty(); - auto obvious_change = ref_is_contained || names_are_equal || - (names_are_empty && refs_are_empty) || name_is_removed || ref_is_removed; + const auto obvious_change = + (names_are_empty && refs_are_empty) || (names_are_equal && ref_is_contained) || + (names_are_equal && refs_are_empty) || name_is_removed || ref_is_removed; return !obvious_change; } -inline int getPriority( const FunctionalRoadClass road_class ) +inline int getPriority(const FunctionalRoadClass road_class) { - //The road priorities indicate which roads can bee seen as more or less equal. - //They are used in Fork-Discovery. Possibly should be moved to profiles post v5? - //A fork can happen between road types that are at most 1 priority apart from each other - const constexpr int road_priority[] = {10, 0, 10, 2, 10, 4, 10, 6, 10, 8, 10, 11, 10, 12, 10, 14}; + // The road priorities indicate which roads can bee seen as more or less equal. + // They are used in Fork-Discovery. Possibly should be moved to profiles post v5? + // A fork can happen between road types that are at most 1 priority apart from each other + const constexpr int road_priority[] = {10, 0, 10, 2, 10, 4, 10, 6, + 10, 8, 10, 11, 10, 12, 10, 14}; return road_priority[static_cast(road_class)]; } inline bool canBeSeenAsFork(const FunctionalRoadClass first, const FunctionalRoadClass second) { // forks require similar road categories - // Based on the priorities assigned above, we can set forks only if the road priorities match closely. + // Based on the priorities assigned above, we can set forks only if the road priorities match + // closely. // Potentially we could include features like number of lanes here and others? // Should also be moved to profiles return std::abs(getPriority(first) - getPriority(second)) <= 1; diff --git a/include/extractor/guidance/turn_analysis.hpp b/include/extractor/guidance/turn_analysis.hpp index 74ba7aca6..169ec234d 100644 --- a/include/extractor/guidance/turn_analysis.hpp +++ b/include/extractor/guidance/turn_analysis.hpp @@ -1,20 +1,20 @@ #ifndef OSRM_EXTRACTOR_TURN_ANALYSIS #define OSRM_EXTRACTOR_TURN_ANALYSIS -#include "extractor/guidance/turn_classification.hpp" -#include "extractor/guidance/toolkit.hpp" -#include "extractor/restriction_map.hpp" #include "extractor/compressed_edge_container.hpp" +#include "extractor/guidance/toolkit.hpp" +#include "extractor/guidance/turn_classification.hpp" +#include "extractor/restriction_map.hpp" #include "util/name_table.hpp" #include -#include -#include #include -#include +#include #include +#include +#include namespace osrm { @@ -129,6 +129,7 @@ class TurnAnalysis // Instruction will be a silent instruction TurnInstruction getInstructionForObvious(const std::size_t number_of_candidates, const EdgeID via_edge, + const bool through_street, const ConnectedRoad &candidate) const; // Helper Function that decides between NoTurn or NewName diff --git a/include/util/name_table.hpp b/include/util/name_table.hpp index 2f1887a35..318cffca1 100644 --- a/include/util/name_table.hpp +++ b/include/util/name_table.hpp @@ -1,8 +1,8 @@ #ifndef OSRM_UTIL_NAME_TABLE_HPP #define OSRM_UTIL_NAME_TABLE_HPP -#include "util/shared_memory_vector_wrapper.hpp" #include "util/range_table.hpp" +#include "util/shared_memory_vector_wrapper.hpp" #include diff --git a/include/util/range_table.hpp b/include/util/range_table.hpp index f01234958..c1a12c2ab 100644 --- a/include/util/range_table.hpp +++ b/include/util/range_table.hpp @@ -4,8 +4,8 @@ #include "util/integer_range.hpp" #include "util/shared_memory_vector_wrapper.hpp" -#include #include +#include #include namespace osrm @@ -61,8 +61,7 @@ template class RangeTable // construct table from length vector template explicit RangeTable(const VectorT &lengths) { - const unsigned number_of_blocks = [&lengths]() - { + const unsigned number_of_blocks = [&lengths]() { unsigned num = (lengths.size() + 1) / (BLOCK_SIZE + 1); if ((lengths.size() + 1) % (BLOCK_SIZE + 1) != 0) { @@ -169,7 +168,7 @@ template class RangeTable end_idx = block_offsets[block_idx + 1]; } - BOOST_ASSERT(begin_idx < sum_lengths && end_idx <= sum_lengths); + BOOST_ASSERT(end_idx <= sum_lengths); BOOST_ASSERT(begin_idx <= end_idx); return irange(begin_idx, end_idx); diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index d88220745..0e3018824 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -1,16 +1,16 @@ #include "engine/guidance/post_processing.hpp" #include "extractor/guidance/turn_instruction.hpp" -#include "engine/guidance/toolkit.hpp" #include "engine/guidance/assemble_steps.hpp" +#include "engine/guidance/toolkit.hpp" #include #include #include -#include #include #include +#include #include #include @@ -55,8 +55,8 @@ void fixFinalRoundabout(std::vector &steps) propagation_step.maneuver.exit = 0; propagation_step.geometry_end = steps.back().geometry_begin; - if( propagation_step.maneuver.instruction.type == TurnType::EnterRotary || - propagation_step.maneuver.instruction.type == TurnType::EnterRotaryAtExit ) + if (propagation_step.maneuver.instruction.type == TurnType::EnterRotary || + propagation_step.maneuver.instruction.type == TurnType::EnterRotaryAtExit) propagation_step.rotary_name = propagation_step.name; break; @@ -130,7 +130,7 @@ void closeOffRoundabout(const bool on_roundabout, steps[1].maneuver.instruction.type = step.maneuver.instruction.type == TurnType::ExitRotary ? TurnType::EnterRotary : TurnType::EnterRoundabout; - if( steps[1].maneuver.instruction.type == TurnType::EnterRotary ) + if (steps[1].maneuver.instruction.type == TurnType::EnterRotary) steps[1].rotary_name = steps[0].name; } @@ -154,8 +154,8 @@ void closeOffRoundabout(const bool on_roundabout, propagation_step.maneuver.exit = step.maneuver.exit; propagation_step.geometry_end = step.geometry_end; // remember rotary name - if( propagation_step.maneuver.instruction.type == TurnType::EnterRotary || - propagation_step.maneuver.instruction.type == TurnType::EnterRotaryAtExit ) + if (propagation_step.maneuver.instruction.type == TurnType::EnterRotary || + propagation_step.maneuver.instruction.type == TurnType::EnterRotaryAtExit) propagation_step.rotary_name = propagation_step.name; propagation_step.name = step.name; @@ -219,9 +219,8 @@ std::vector postProcess(std::vector steps) // adds an intersection to the initial route step // It includes the length of the last step, until the intersection // Also updates the length of the respective segment - auto addIntersection = - [](RouteStep into, const RouteStep &last_step, const RouteStep &intersection) - { + auto addIntersection = [](RouteStep into, const RouteStep &last_step, + const RouteStep &intersection) { into.maneuver.intersections.push_back( {last_step.duration, last_step.distance, intersection.maneuver.location}); @@ -294,8 +293,7 @@ std::vector postProcess(std::vector steps) // Two valid NO_TURNs exist in each leg in the form of Depart/Arrive // keep valid instructions - const auto not_is_valid = [](const RouteStep &step) - { + const auto not_is_valid = [](const RouteStep &step) { return step.maneuver.instruction == TurnInstruction::NO_TURN() && step.maneuver.waypoint_type == WaypointType::None; }; @@ -352,10 +350,8 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) // geometry offsets have to be adjusted. Move all offsets to the front and reduce by // one. (This is an inplace forward one and reduce by one) std::transform(geometry.segment_offsets.begin() + 1, geometry.segment_offsets.end(), - geometry.segment_offsets.begin(), [](const std::size_t val) - { - return val - 1; - }); + geometry.segment_offsets.begin(), + [](const std::size_t val) { return val - 1; }); geometry.segment_offsets.pop_back(); const auto ¤t_depart = steps.front(); @@ -378,21 +374,18 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) steps.front().geometry_begin = 1; // reduce all offsets by one (inplace) std::transform(geometry.segment_offsets.begin(), geometry.segment_offsets.end(), - geometry.segment_offsets.begin(), [](const std::size_t val) - { - return val - 1; - }); + geometry.segment_offsets.begin(), + [](const std::size_t val) { return val - 1; }); steps.front().maneuver = detail::stepManeuverFromGeometry( TurnInstruction::NO_TURN(), WaypointType::Depart, geometry); } // and update the leg geometry indices for the removed entry - std::for_each(steps.begin(), steps.end(), [](RouteStep &step) - { - --step.geometry_begin; - --step.geometry_end; - }); + std::for_each(steps.begin(), steps.end(), [](RouteStep &step) { + --step.geometry_begin; + --step.geometry_end; + }); } // make sure we still have enough segments diff --git a/src/extractor/guidance/turn_analysis.cpp b/src/extractor/guidance/turn_analysis.cpp index 6758f643b..1fdff1c25 100644 --- a/src/extractor/guidance/turn_analysis.cpp +++ b/src/extractor/guidance/turn_analysis.cpp @@ -1,12 +1,13 @@ +#include "extractor/guidance/constants.hpp" #include "extractor/guidance/turn_analysis.hpp" -#include "util/simple_logger.hpp" #include "util/coordinate.hpp" #include "util/coordinate_calculation.hpp" +#include "util/simple_logger.hpp" #include -#include #include +#include #include #include @@ -16,20 +17,6 @@ namespace extractor { namespace guidance { -// configuration of turn classification -const bool constexpr INVERT = true; - -// what angle is interpreted as going straight -const double constexpr STRAIGHT_ANGLE = 180.; -// if a turn deviates this much from going straight, it will be kept straight -const double constexpr MAXIMAL_ALLOWED_NO_TURN_DEVIATION = 3.; -// angle that lies between two nearly indistinguishable roads -const double constexpr NARROW_TURN_ANGLE = 30.; -const double constexpr GROUP_ANGLE = 90; -// angle difference that can be classified as straight, if its the only narrow turn -const double constexpr FUZZY_ANGLE_DIFFERENCE = 15.; -const double constexpr DISTINCTION_RATIO = 2; -const unsigned constexpr INVALID_NAME_ID = 0; using EdgeData = util::NodeBasedDynamicGraph::EdgeData; @@ -101,17 +88,15 @@ inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_base bool TurnAnalysis::isRotary(const NodeID nid) const { // translate a node ID into its respective coordinate stored in the node_info_list - const auto getCoordinate = [this](const NodeID node) - { + const auto getCoordinate = [this](const NodeID node) { return util::Coordinate(node_info_list[node].lon, node_info_list[node].lat); }; unsigned roundabout_name_id = 0; std::unordered_set connected_names; - const auto getNextOnRoundabout = - [this, &roundabout_name_id, &connected_names](const NodeID node) - { + const auto getNextOnRoundabout = [this, &roundabout_name_id, + &connected_names](const NodeID node) { EdgeID continue_edge = SPECIAL_EDGEID; for (const auto edge : node_based_graph.GetAdjacentEdgeRange(node)) { @@ -183,15 +168,20 @@ bool TurnAnalysis::isRotary(const NodeID nid) const // circle // with both vertices right at the other side (so half their distance in meters). // Otherwise, we construct a circle through the first tree vertices. - auto node_itr = roundabout_nodes.begin(); - const double radius = roundabout_nodes.size() >= 3 - ? util::coordinate_calculation::circleRadius( - getCoordinate(*node_itr++), - getCoordinate(*node_itr++), - getCoordinate(*node_itr)) - : 0.5 * util::coordinate_calculation::haversineDistance( - getCoordinate(*node_itr++), - getCoordinate(*node_itr)); + const auto getRadius = [&roundabout_nodes,&getCoordinate](){ + auto node_itr = roundabout_nodes.begin(); + if( roundabout_nodes.size() == 2 ) + { + const auto first = getCoordinate(*node_itr++), second = getCoordinate(*node_itr++); + return 0.5 * util::coordinate_calculation::haversineDistance( first, second ); + } + else + { + const auto first = getCoordinate(*node_itr++), second = getCoordinate(*node_itr++), third = getCoordinate(*node_itr++); + return util::coordinate_calculation::circleRadius(first,second,third); + } + }; + const double radius = getRadius(); // check whether the circle computation has gone wrong // The radius computation can result in infinity, if the three coordinates are non-distinct. @@ -199,7 +189,6 @@ bool TurnAnalysis::isRotary(const NodeID nid) const if (std::isinf(radius)) return false; - const double constexpr MAX_ROUNDABOUT_RADIUS = 15; // 30 m diameter as final distinction return radius > MAX_ROUNDABOUT_RADIUS; } @@ -240,10 +229,10 @@ std::vector TurnAnalysis::getTurns(const NodeID from, const EdgeI } if (on_roundabout || can_enter_roundabout) { - bool is_rotary = isRotary(node_based_graph.GetTarget(via_edge)); + const bool is_rotary = isRotary(node_based_graph.GetTarget(via_edge)); // find the radius of the roundabout - intersection = handleRoundabouts(is_rotary, via_edge, on_roundabout, can_exit_roundabout_separately, - std::move(intersection)); + intersection = handleRoundabouts(is_rotary, via_edge, on_roundabout, + can_exit_roundabout_separately, std::move(intersection)); } else { @@ -283,10 +272,8 @@ std::vector TurnAnalysis::getTurns(const NodeID from, const EdgeI inline std::size_t countValid(const std::vector &intersection) { - return std::count_if(intersection.begin(), intersection.end(), [](const ConnectedRoad &road) - { - return road.entry_allowed; - }); + return std::count_if(intersection.begin(), intersection.end(), + [](const ConnectedRoad &road) { return road.entry_allowed; }); } std::vector @@ -377,14 +364,23 @@ TurnAnalysis::fallbackTurnAssignmentMotorway(std::vector intersec const auto type = detail::isMotorwayClass(out_data.road_classification.road_class) ? TurnType::Merge : TurnType::Turn; - if (angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE) - road.turn.instruction = {type, DirectionModifier::Straight}; + + if (type == TurnType::Turn) + { + if (angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE) + road.turn.instruction = {type, DirectionModifier::Straight}; + else + { + road.turn.instruction = {type, road.turn.angle > STRAIGHT_ANGLE + ? DirectionModifier::SlightLeft + : DirectionModifier::SlightRight}; + } + } else { - road.turn.instruction = {type, - road.turn.angle > STRAIGHT_ANGLE - ? DirectionModifier::SlightLeft - : DirectionModifier::SlightRight}; + road.turn.instruction = {type, road.turn.angle < STRAIGHT_ANGLE + ? DirectionModifier::SlightLeft + : DirectionModifier::SlightRight}; } } return intersection; @@ -397,8 +393,7 @@ TurnAnalysis::handleFromMotorway(const EdgeID via_edge, const auto &in_data = node_based_graph.GetEdgeData(via_edge); BOOST_ASSERT(detail::isMotorwayClass(in_data.road_classification.road_class)); - const auto countExitingMotorways = [this](const std::vector &intersection) - { + const auto countExitingMotorways = [this](const std::vector &intersection) { unsigned count = 0; for (const auto &road : intersection) { @@ -409,22 +404,20 @@ TurnAnalysis::handleFromMotorway(const EdgeID via_edge, }; // find the angle that continues on our current highway - const auto getContinueAngle = [this, in_data](const std::vector &intersection) - { + const auto getContinueAngle = [this, in_data](const std::vector &intersection) { for (const auto &road : intersection) { const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid); if (road.turn.angle != 0 && in_data.name_id == out_data.name_id && - in_data.name_id != 0 && + in_data.name_id != INVALID_NAME_ID && detail::isMotorwayClass(out_data.road_classification.road_class)) return road.turn.angle; } return intersection[0].turn.angle; }; - const auto getMostLikelyContinue = - [this, in_data](const std::vector &intersection) - { + const auto getMostLikelyContinue = [this, + in_data](const std::vector &intersection) { double angle = intersection[0].turn.angle; double best = 180; for (const auto &road : intersection) @@ -440,18 +433,33 @@ TurnAnalysis::handleFromMotorway(const EdgeID via_edge, return angle; }; - const auto findBestContinue = [&]() - { + const auto findBestContinue = [&]() { const double continue_angle = getContinueAngle(intersection); if (continue_angle != intersection[0].turn.angle) return continue_angle; else return getMostLikelyContinue(intersection); }; + // check whether the obvious choice is actually a through street + const auto isThroughStreet = [&intersection, this](const ConnectedRoad &connection) { + if (node_based_graph.GetEdgeData(connection.turn.eid).name_id == INVALID_NAME_ID) + return false; + for (const auto &road : intersection) + { + // a through street cannot start at our own position + if (road.turn.angle < std::numeric_limits::epsilon()) + continue; + if (angularDeviation(road.turn.angle, connection.turn.angle) > + (STRAIGHT_ANGLE - NARROW_TURN_ANGLE) && + node_based_graph.GetEdgeData(road.turn.eid).name_id == + node_based_graph.GetEdgeData(connection.turn.eid).name_id) + return true; + } + return false; + }; // find continue angle const double continue_angle = findBestContinue(); - // highway does not continue and has no obvious choice if (continue_angle == intersection[0].turn.angle) { @@ -524,12 +532,11 @@ TurnAnalysis::handleFromMotorway(const EdgeID via_edge, BOOST_ASSERT(!detail::isRampClass(intersection[1].turn.eid, node_based_graph)); intersection[1].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[1]); + getInstructionForObvious(intersection.size(), via_edge, + isThroughStreet(intersection[1]), intersection[1]); } else { - // continue on the same highway - bool continues = (getContinueAngle(intersection) != intersection[0].turn.angle); // Normal Highway exit or merge for (auto &road : intersection) { @@ -539,11 +546,8 @@ TurnAnalysis::handleFromMotorway(const EdgeID via_edge, if (road.turn.angle == continue_angle) { - if (continues) - road.turn.instruction = - TurnInstruction::SUPPRESSED(DirectionModifier::Straight); - else // TODO handle turn direction correctly - road.turn.instruction = {TurnType::Merge, DirectionModifier::Straight}; + road.turn.instruction = getInstructionForObvious( + intersection.size(), via_edge, isThroughStreet(road), road); } else if (road.turn.angle < continue_angle) { @@ -570,7 +574,8 @@ TurnAnalysis::handleFromMotorway(const EdgeID via_edge, if (exiting_motorways == 2 && intersection.size() == 2) { intersection[1].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[1]); + getInstructionForObvious(intersection.size(), via_edge, + isThroughStreet(intersection[1]), intersection[1]); util::SimpleLogger().Write(logWARNING) << "Disabled U-Turn on a freeway at " << localizer(node_based_graph.GetTarget(via_edge)); @@ -633,8 +638,9 @@ TurnAnalysis::handleFromMotorway(const EdgeID via_edge, auto coord = localizer(node_based_graph.GetTarget(via_edge)); util::SimpleLogger().Write(logWARNING) << "Found motorway junction with more than " - "2 exiting motorways or additional ramps at " << std::setprecision(12) - << toFloating(coord.lat) << " " << toFloating(coord.lon); + "2 exiting motorways or additional ramps at " + << std::setprecision(12) << toFloating(coord.lat) << " " + << toFloating(coord.lon); fallbackTurnAssignmentMotorway(intersection); } } // done for more than one highway exit @@ -647,14 +653,30 @@ TurnAnalysis::handleMotorwayRamp(const EdgeID via_edge, std::vector intersection) const { auto num_valid_turns = countValid(intersection); + const auto isThroughStreet = [&intersection, this](const ConnectedRoad &connection) { + if (node_based_graph.GetEdgeData(connection.turn.eid).name_id == INVALID_NAME_ID) + return false; + for (const auto &road : intersection) + { + // a through street cannot start at our own position + if (road.turn.angle < std::numeric_limits::epsilon()) + continue; + if (angularDeviation(road.turn.angle, connection.turn.angle) > + (STRAIGHT_ANGLE - NARROW_TURN_ANGLE) && + node_based_graph.GetEdgeData(road.turn.eid).name_id == + node_based_graph.GetEdgeData(connection.turn.eid).name_id) + return true; + } + return false; + }; // ramp straight into a motorway/ramp if (intersection.size() == 2 && num_valid_turns == 1) { BOOST_ASSERT(!intersection[0].entry_allowed); BOOST_ASSERT(detail::isMotorwayClass(intersection[1].turn.eid, node_based_graph)); - intersection[1].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[1]); + intersection[1].turn.instruction = getInstructionForObvious( + intersection.size(), via_edge, isThroughStreet(intersection[1]), intersection[1]); } else if (intersection.size() == 3) { @@ -672,7 +694,11 @@ TurnAnalysis::handleMotorwayRamp(const EdgeID via_edge, // 0 if (intersection[1].entry_allowed) { - if (detail::isMotorwayClass(intersection[1].turn.eid, node_based_graph)) + if (detail::isMotorwayClass(intersection[1].turn.eid, node_based_graph) && + node_based_graph.GetEdgeData(intersection[2].turn.eid).name_id != + INVALID_NAME_ID && + node_based_graph.GetEdgeData(intersection[2].turn.eid).name_id == + node_based_graph.GetEdgeData(intersection[1].turn.eid).name_id) { // circular order indicates a merge to the left (0-3 onto 4 if (angularDeviation(intersection[1].turn.angle, STRAIGHT_ANGLE) < @@ -684,13 +710,20 @@ TurnAnalysis::handleMotorwayRamp(const EdgeID via_edge, TurnType::Merge, getTurnDirection(intersection[1].turn.angle)}; } else // passing by the end of a motorway + { intersection[1].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[1]); + getInstructionForObvious(intersection.size(), via_edge, + isThroughStreet(intersection[1]), intersection[1]); + } } else { BOOST_ASSERT(intersection[2].entry_allowed); - if (detail::isMotorwayClass(intersection[2].turn.eid, node_based_graph)) + if (detail::isMotorwayClass(intersection[2].turn.eid, node_based_graph) && + node_based_graph.GetEdgeData(intersection[1].turn.eid).name_id != + INVALID_NAME_ID && + node_based_graph.GetEdgeData(intersection[1].turn.eid).name_id == + node_based_graph.GetEdgeData(intersection[0].turn.eid).name_id) { // circular order (5-0) onto 4 if (angularDeviation(intersection[2].turn.angle, STRAIGHT_ANGLE) < @@ -702,8 +735,11 @@ TurnAnalysis::handleMotorwayRamp(const EdgeID via_edge, TurnType::Merge, getTurnDirection(intersection[2].turn.angle)}; } else // passing the end of a highway - intersection[1].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[1]); + { + intersection[2].turn.instruction = + getInstructionForObvious(intersection.size(), via_edge, + isThroughStreet(intersection[2]), intersection[2]); + } } } else @@ -733,17 +769,14 @@ TurnAnalysis::handleMotorwayRamp(const EdgeID via_edge, if (detail::isMotorwayClass(node_based_graph.GetEdgeData(intersection[1].turn.eid) .road_classification.road_class)) { - intersection[1].turn.instruction = {TurnType::Merge, + intersection[1].turn.instruction = {TurnType::Turn, DirectionModifier::SlightRight}; - intersection[2].turn.instruction = {TurnType::Fork, + intersection[2].turn.instruction = {TurnType::Continue, DirectionModifier::SlightLeft}; } else { - intersection[1].turn.instruction = {TurnType::Fork, - DirectionModifier::SlightRight}; - intersection[2].turn.instruction = {TurnType::Merge, - DirectionModifier::SlightLeft}; + assignFork(via_edge, intersection[2], intersection[1]); } } } @@ -762,8 +795,8 @@ TurnAnalysis::handleMotorwayRamp(const EdgeID via_edge, } else if (detail::isMotorwayClass(edge_data.road_classification.road_class)) { - road.turn.instruction = {TurnType::Merge, - passed_highway_entry ? DirectionModifier::SlightRight + road.turn.instruction = {TurnType::Merge, passed_highway_entry + ? DirectionModifier::SlightRight : DirectionModifier::SlightLeft}; } else @@ -814,9 +847,7 @@ bool TurnAnalysis::isMotorwayJunction(const EdgeID via_edge, { const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid); // not merging or forking? - if ((angularDeviation(road.turn.angle, 0) > 35 && - angularDeviation(road.turn.angle, 180) > 35) || - (road.entry_allowed && angularDeviation(road.turn.angle, 0) < 35)) + if (road.entry_allowed && angularDeviation(road.turn.angle, STRAIGHT_ANGLE) > 60) return false; else if (out_data.road_classification.road_class == FunctionalRoadClass::MOTORWAY || out_data.road_classification.road_class == FunctionalRoadClass::TRUNK) @@ -860,6 +891,7 @@ TurnType TurnAnalysis::findBasicTurnType(const EdgeID via_edge, const ConnectedR TurnInstruction TurnAnalysis::getInstructionForObvious(const std::size_t num_roads, const EdgeID via_edge, + const bool through_street, const ConnectedRoad &road) const { const auto type = findBasicTurnType(via_edge, road); @@ -882,7 +914,19 @@ TurnInstruction TurnAnalysis::getInstructionForObvious(const std::size_t num_roa if (in_data.name_id != out_data.name_id && requiresNameAnnounced(name_table.GetNameForID(in_data.name_id), name_table.GetNameForID(out_data.name_id))) - return {TurnType::NewName, getTurnDirection(road.turn.angle)}; + { + // obvious turn onto a through street is a merge + if (through_street) + { + return {TurnType::Merge, road.turn.angle > STRAIGHT_ANGLE + ? DirectionModifier::SlightRight + : DirectionModifier::SlightLeft}; + } + else + { + return {TurnType::NewName, getTurnDirection(road.turn.angle)}; + } + } else { if (in_mode == out_mode) @@ -918,7 +962,7 @@ TurnAnalysis::handleTwoWayTurn(const EdgeID via_edge, std::vector { BOOST_ASSERT(intersection[0].turn.angle < 0.001); intersection[1].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[1]); + getInstructionForObvious(intersection.size(), via_edge, false, intersection[1]); if (intersection[1].turn.instruction.type == TurnType::Suppressed) intersection[1].turn.instruction.type = TurnType::NoTurn; @@ -931,15 +975,28 @@ TurnAnalysis::handleThreeWayTurn(const EdgeID via_edge, std::vector intersection) const { BOOST_ASSERT(intersection[0].turn.angle < 0.001); - const auto isObviousOfTwo = [](const ConnectedRoad road, const ConnectedRoad other) - { - return (angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < NARROW_TURN_ANGLE && - angularDeviation(other.turn.angle, STRAIGHT_ANGLE) > 85) || - (angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < - std::numeric_limits::epsilon()) || - (angularDeviation(other.turn.angle, STRAIGHT_ANGLE) / - angularDeviation(road.turn.angle, STRAIGHT_ANGLE) > - 1.4); + const auto isObviousOfTwo = [this](const ConnectedRoad road, const ConnectedRoad other) { + const auto first_class = + node_based_graph.GetEdgeData(road.turn.eid).road_classification.road_class; + const bool is_ramp = isRampClass(first_class); + const auto second_class = + node_based_graph.GetEdgeData(other.turn.eid).road_classification.road_class; + const bool is_narrow_turn = + angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < NARROW_TURN_ANGLE; + const bool other_turn_is_at_least_orthogonal = + angularDeviation(other.turn.angle, STRAIGHT_ANGLE) > 85; + const bool turn_is_perfectly_straight = angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < + std::numeric_limits::epsilon(); + const bool is_obvious_by_road_class = + (!is_ramp && (2 * getPriority(first_class) < getPriority(second_class))) || + (!isLowPriorityRoadClass(first_class) && isLowPriorityRoadClass(second_class)); + const bool is_much_narrower_than_other = + angularDeviation(other.turn.angle, STRAIGHT_ANGLE) / + angularDeviation(road.turn.angle, STRAIGHT_ANGLE) > + INCREASES_BY_FOURTY_PERCENT; + return (is_narrow_turn && other_turn_is_at_least_orthogonal) || + turn_is_perfectly_straight || is_much_narrower_than_other || + is_obvious_by_road_class; }; /* Two nearly straight turns -> FORK @@ -959,30 +1016,39 @@ TurnAnalysis::handleThreeWayTurn(const EdgeID via_edge, const auto right_class = node_based_graph.GetEdgeData(intersection[1].turn.eid) .road_classification.road_class; if (canBeSeenAsFork(left_class, right_class)) + { assignFork(via_edge, intersection[2], intersection[1]); - else if (getPriority(left_class) > getPriority(right_class)) + } + else if (isObviousOfTwo(intersection[1], intersection[2])) { intersection[1].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[1]); + getInstructionForObvious(intersection.size(), via_edge, false, intersection[1]); intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]), DirectionModifier::SlightLeft}; } - else + else if (isObviousOfTwo(intersection[2], intersection[1])) { intersection[2].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[2]); + getInstructionForObvious(intersection.size(), via_edge, false, intersection[2]); intersection[1].turn.instruction = {findBasicTurnType(via_edge, intersection[1]), DirectionModifier::SlightRight}; } + else + { + intersection[1].turn.instruction = {findBasicTurnType(via_edge, intersection[1]), + DirectionModifier::SlightRight}; + intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]), + DirectionModifier::SlightLeft}; + } } else { if (intersection[1].entry_allowed) intersection[1].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[1]); + getInstructionForObvious(intersection.size(), via_edge, false, intersection[1]); if (intersection[2].entry_allowed) intersection[2].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[2]); + getInstructionForObvious(intersection.size(), via_edge, false, intersection[2]); } } /* T Intersection @@ -1028,7 +1094,7 @@ TurnAnalysis::handleThreeWayTurn(const EdgeID via_edge, { if (TurnType::Ramp != findBasicTurnType(via_edge, intersection[1])) intersection[1].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[1]); + getInstructionForObvious(intersection.size(), via_edge, false, intersection[1]); else intersection[1].turn.instruction = {TurnType::Ramp, DirectionModifier::Straight}; } @@ -1052,7 +1118,7 @@ TurnAnalysis::handleThreeWayTurn(const EdgeID via_edge, { if (intersection[2].entry_allowed) intersection[2].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[2]); + getInstructionForObvious(intersection.size(), via_edge, false, intersection[2]); if (intersection[1].entry_allowed) intersection[1].turn.instruction = {findBasicTurnType(via_edge, intersection[1]), DirectionModifier::Right}; @@ -1062,11 +1128,18 @@ TurnAnalysis::handleThreeWayTurn(const EdgeID via_edge, node_based_graph.GetEdgeData(intersection[1].turn.eid).name_id == node_based_graph.GetEdgeData(intersection[2].turn.eid).name_id) { - const auto findTurn = [isObviousOfTwo](const ConnectedRoad turn, const ConnectedRoad other) - -> TurnInstruction - { - return {isObviousOfTwo(turn, other) ? TurnType::Merge : TurnType::Turn, - getTurnDirection(turn.turn.angle)}; + const auto findTurn = [isObviousOfTwo](const ConnectedRoad turn, + const ConnectedRoad other) -> TurnInstruction { + if (isObviousOfTwo(turn, other)) + { + return {TurnType::Merge, turn.turn.angle < STRAIGHT_ANGLE + ? DirectionModifier::SlightLeft + : DirectionModifier::SlightRight}; + } + else + { + return {TurnType::Turn, getTurnDirection(turn.turn.angle)}; + } }; intersection[1].turn.instruction = findTurn(intersection[1], intersection[2]); intersection[2].turn.instruction = findTurn(intersection[2], intersection[1]); @@ -1087,7 +1160,7 @@ TurnAnalysis::handleThreeWayTurn(const EdgeID via_edge, intersection[1].turn.instruction = {TurnType::Continue, getTurnDirection(intersection[1].turn.angle)}; } - intersection[2].turn.instruction = {TurnType::Turn, + intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]), getTurnDirection(intersection[2].turn.angle)}; } // other street merges from the right @@ -1105,28 +1178,30 @@ TurnAnalysis::handleThreeWayTurn(const EdgeID via_edge, intersection[2].turn.instruction = {TurnType::Continue, getTurnDirection(intersection[2].turn.angle)}; } - intersection[1].turn.instruction = {TurnType::Turn, + intersection[1].turn.instruction = {findBasicTurnType(via_edge, intersection[1]), getTurnDirection(intersection[1].turn.angle)}; } else { if (isObviousOfTwo(intersection[1], intersection[2])) { - intersection[1].turn.instruction = getInstructionForObvious(3,via_edge,intersection[1]); + intersection[1].turn.instruction = + getInstructionForObvious(3, via_edge, false, intersection[1]); } else { - intersection[1].turn.instruction = {TurnType::Turn, + intersection[1].turn.instruction = {findBasicTurnType(via_edge, intersection[1]), getTurnDirection(intersection[1].turn.angle)}; } if (isObviousOfTwo(intersection[2], intersection[1])) { - intersection[2].turn.instruction = getInstructionForObvious(3,via_edge,intersection[2]); + intersection[2].turn.instruction = + getInstructionForObvious(3, via_edge, false, intersection[2]); } else { - intersection[2].turn.instruction = {TurnType::Turn, + intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]), getTurnDirection(intersection[2].turn.angle)}; } } @@ -1167,14 +1242,18 @@ void TurnAnalysis::handleDistinctConflict(const EdgeID via_edge, else if (getPriority(left_class) > getPriority(right_class)) { // FIXME this should possibly know about the actual roads? - right.turn.instruction = getInstructionForObvious(4, via_edge, right); + // here we don't know about the intersection size. To be on the save side, we declare it + // as complex (at least size 4) + right.turn.instruction = getInstructionForObvious(4, via_edge, false, right); left.turn.instruction = {findBasicTurnType(via_edge, left), DirectionModifier::SlightLeft}; } else { - // FIXME this should possibly know aboat the actual roads? - left.turn.instruction = getInstructionForObvious(4, via_edge, left); + // FIXME this should possibly know about the actual roads? + // here we don't know about the intersection size. To be on the save side, we declare it + // as complex (at least size 4) + left.turn.instruction = getInstructionForObvious(4, via_edge, false, left); right.turn.instruction = {findBasicTurnType(via_edge, right), DirectionModifier::SlightRight}; } @@ -1288,10 +1367,29 @@ TurnAnalysis::handleComplexTurn(const EdgeID via_edge, } } + // check whether the obvious choice is actually a through street + const auto isThroughStreet = [&intersection, this](const std::size_t index) { + if (node_based_graph.GetEdgeData(intersection[index].turn.eid).name_id == INVALID_NAME_ID) + return false; + for (const auto &road : intersection) + { + // a through street cannot start at our own position + if (road.turn.angle < std::numeric_limits::epsilon()) + continue; + if (angularDeviation(road.turn.angle, intersection[index].turn.angle) > + (STRAIGHT_ANGLE - NARROW_TURN_ANGLE) && + node_based_graph.GetEdgeData(road.turn.eid).name_id == + node_based_graph.GetEdgeData(intersection[index].turn.eid).name_id) + return true; + } + return false; + }; + if (obvious_index != 0) { intersection[obvious_index].turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, intersection[obvious_index]); + getInstructionForObvious(intersection.size(), via_edge, isThroughStreet(obvious_index), + intersection[obvious_index]); // assign left/right turns intersection = assignLeftTurns(via_edge, std::move(intersection), obvious_index + 1); @@ -1312,14 +1410,14 @@ TurnAnalysis::handleComplexTurn(const EdgeID via_edge, else if (getPriority(left_class) > getPriority(right_class)) { right.turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, right); + getInstructionForObvious(intersection.size(), via_edge, false, right); left.turn.instruction = {findBasicTurnType(via_edge, left), DirectionModifier::SlightLeft}; } else { left.turn.instruction = - getInstructionForObvious(intersection.size(), via_edge, left); + getInstructionForObvious(intersection.size(), via_edge, false, left); right.turn.instruction = {findBasicTurnType(via_edge, right), DirectionModifier::SlightRight}; } @@ -1489,8 +1587,7 @@ std::vector TurnAnalysis::getConnectedRoads(const NodeID from_nod {TurnOperation{via_eid, 0., {TurnType::Invalid, DirectionModifier::UTurn}}, false}); } - const auto ByAngle = [](const ConnectedRoad &first, const ConnectedRoad second) - { + const auto ByAngle = [](const ConnectedRoad &first, const ConnectedRoad second) { return first.turn.angle < second.turn.angle; }; std::sort(std::begin(intersection), std::end(intersection), ByAngle); @@ -1527,13 +1624,11 @@ std::vector TurnAnalysis::getConnectedRoads(const NodeID from_nod std::vector TurnAnalysis::mergeSegregatedRoads(std::vector intersection) const { - const auto getRight = [&](std::size_t index) - { + const auto getRight = [&](std::size_t index) { return (index + intersection.size() - 1) % intersection.size(); }; - const auto mergable = [&](std::size_t first, std::size_t second) -> bool - { + const auto mergable = [&](std::size_t first, std::size_t second) -> bool { const auto &first_data = node_based_graph.GetEdgeData(intersection[first].turn.eid); const auto &second_data = node_based_graph.GetEdgeData(intersection[second].turn.eid); @@ -1547,8 +1642,8 @@ TurnAnalysis::mergeSegregatedRoads(std::vector intersection) cons first_data.reversed != second_data.reversed; }; - const auto merge = [](const ConnectedRoad &first, const ConnectedRoad &second) -> ConnectedRoad - { + const auto merge = [](const ConnectedRoad &first, + const ConnectedRoad &second) -> ConnectedRoad { if (!first.entry_allowed) { ConnectedRoad result = second; @@ -1581,7 +1676,6 @@ TurnAnalysis::mergeSegregatedRoads(std::vector intersection) cons // these result in an adjustment of all other angles if (mergable(0, intersection.size() - 1)) { - // std::cout << "First merge" << std::endl; const double correction_factor = (360 - intersection[intersection.size() - 1].turn.angle) / 2; for (std::size_t i = 1; i + 1 < intersection.size(); ++i) @@ -1592,7 +1686,6 @@ TurnAnalysis::mergeSegregatedRoads(std::vector intersection) cons } else if (mergable(0, 1)) { - // std::cout << "First merge" << std::endl; const double correction_factor = (intersection[1].turn.angle) / 2; for (std::size_t i = 2; i < intersection.size(); ++i) intersection[i].turn.angle += correction_factor; @@ -1614,8 +1707,7 @@ TurnAnalysis::mergeSegregatedRoads(std::vector intersection) cons } } - const auto ByAngle = [](const ConnectedRoad &first, const ConnectedRoad second) - { + const auto ByAngle = [](const ConnectedRoad &first, const ConnectedRoad second) { return first.turn.angle < second.turn.angle; }; std::sort(std::begin(intersection), std::end(intersection), ByAngle); @@ -1640,7 +1732,7 @@ void TurnAnalysis::assignFork(const EdgeID via_edge, { if (low_priority_right && !low_priority_left) { - left.turn.instruction = getInstructionForObvious(3, via_edge, left); + left.turn.instruction = getInstructionForObvious(3, via_edge, false, left); right.turn.instruction = {findBasicTurnType(via_edge, right), DirectionModifier::SlightRight}; } @@ -1683,7 +1775,7 @@ void TurnAnalysis::assignFork(const EdgeID via_edge, { left.turn.instruction = {findBasicTurnType(via_edge, left), DirectionModifier::SlightLeft}; - right.turn.instruction = getInstructionForObvious(3, via_edge, right); + right.turn.instruction = getInstructionForObvious(3, via_edge, false, right); } else { @@ -1887,10 +1979,24 @@ TurnAnalysis::findFork(const std::vector &intersection) const best = i; } } - if (best_deviation <= NARROW_TURN_ANGLE) { std::size_t left = best, right = best; + if (intersection[left].turn.angle >= 180) + { + // due to best > 1, we can safely decrement right + --right; + if (angularDeviation(intersection[right].turn.angle, STRAIGHT_ANGLE) > + NARROW_TURN_ANGLE) + return std::make_pair(std::size_t{0}, std::size_t{0}); + } + else + { + ++left; + if (left >= intersection.size() || + angularDeviation(intersection[left].turn.angle, STRAIGHT_ANGLE) > NARROW_TURN_ANGLE) + return std::make_pair(std::size_t{0}, std::size_t{0}); + } while (left + 1 < intersection.size() && angularDeviation(intersection[left].turn.angle, intersection[left + 1].turn.angle) < NARROW_TURN_ANGLE) @@ -1909,7 +2015,7 @@ TurnAnalysis::findFork(const std::vector &intersection) const 2 * NARROW_TURN_ANGLE) return std::make_pair(right, left); } - return std::make_pair(0llu, 0llu); + return std::make_pair(std::size_t{0}, std::size_t{0}); } // Can only assign three turns @@ -1917,8 +2023,7 @@ std::vector TurnAnalysis::assignLeftTurns(const EdgeID via_edge, std::vector intersection, const std::size_t starting_at) const { - const auto count_valid = [&intersection, starting_at]() - { + const auto count_valid = [&intersection, starting_at]() { std::size_t count = 0; for (std::size_t i = starting_at; i < intersection.size(); ++i) if (intersection[i].entry_allowed) @@ -1990,7 +2095,7 @@ std::vector TurnAnalysis::assignLeftTurns(const EdgeID via_edge, findBasicTurnType(via_edge, intersection[starting_at + 1]), second_direction}; if (intersection[starting_at + 2].entry_allowed) intersection[starting_at + 2].turn.instruction = { - findBasicTurnType(via_edge, intersection[starting_at + 2]), second_direction}; + findBasicTurnType(via_edge, intersection[starting_at + 2]), third_direction}; } else if (2 >= (intersection[starting_at].entry_allowed + intersection[starting_at + 1].entry_allowed + @@ -2187,8 +2292,7 @@ std::vector TurnAnalysis::assignRightTurns(const EdgeID via_edge, const std::size_t up_to) const { BOOST_ASSERT(up_to <= intersection.size()); - const auto count_valid = [&intersection, up_to]() - { + const auto count_valid = [&intersection, up_to]() { std::size_t count = 0; for (std::size_t i = 1; i < up_to; ++i) if (intersection[i].entry_allowed) diff --git a/src/util/coordinate_calculation.cpp b/src/util/coordinate_calculation.cpp index c38b1c2fa..745ceb5f1 100644 --- a/src/util/coordinate_calculation.cpp +++ b/src/util/coordinate_calculation.cpp @@ -122,8 +122,9 @@ double perpendicularDistance(const Coordinate segment_source, BOOST_ASSERT(query_location.IsValid()); FloatCoordinate projected_nearest; - std::tie(ratio, projected_nearest) = - projectPointOnSegment(mercator::fromWGS84(segment_source), mercator::fromWGS84(segment_target), mercator::fromWGS84(query_location)); + std::tie(ratio, projected_nearest) = projectPointOnSegment(mercator::fromWGS84(segment_source), + mercator::fromWGS84(segment_target), + mercator::fromWGS84(query_location)); nearest_location = mercator::toWGS84(projected_nearest); const double approximate_distance = greatCircleDistance(query_location, nearest_location); @@ -215,7 +216,9 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3) // free after http://paulbourke.net/geometry/circlesphere/ // require three distinct points if (C1 == C2 || C2 == C3 || C1 == C3) + { return boost::none; + } // define line through c1, c2 and c2,c3 const double C2C1_lat = static_cast(toFloating(C2.lat - C1.lat)); // yDelta_a @@ -255,7 +258,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3) const double C2C1_slope = C2C1_lat / C2C1_lon; const double C3C2_slope = C3C2_lat / C3C2_lon; - //can this ever happen? + // can this ever happen? if (std::abs(C2C1_slope - C3C2_slope) < std::numeric_limits::epsilon()) return boost::none; @@ -356,12 +359,14 @@ double degreeToPixel(FloatLatitude lat, unsigned zoom) FloatCoordinate fromWGS84(const FloatCoordinate &wgs84_coordinate) { - return {wgs84_coordinate.lon, FloatLatitude{coordinate_calculation::mercator::latToY(wgs84_coordinate.lat)}}; + return {wgs84_coordinate.lon, + FloatLatitude{coordinate_calculation::mercator::latToY(wgs84_coordinate.lat)}}; } FloatCoordinate toWGS84(const FloatCoordinate &mercator_coordinate) { - return {mercator_coordinate.lon, coordinate_calculation::mercator::yToLat(static_cast(mercator_coordinate.lat))}; + return {mercator_coordinate.lon, + coordinate_calculation::mercator::yToLat(static_cast(mercator_coordinate.lat))}; } // Converts a WMS tile coordinate (z,x,y) into a wgs bounding box diff --git a/src/util/name_table.cpp b/src/util/name_table.cpp index e3d5cef35..fedc31f58 100644 --- a/src/util/name_table.cpp +++ b/src/util/name_table.cpp @@ -1,10 +1,10 @@ +#include "util/exception.hpp" #include "util/name_table.hpp" #include "util/simple_logger.hpp" -#include "util/exception.hpp" #include -#include #include +#include #include @@ -17,27 +17,30 @@ NameTable::NameTable(const std::string &filename) { boost::filesystem::ifstream name_stream(filename, std::ios::binary); - if( !name_stream ) + if (!name_stream) throw exception("Failed to open " + filename + " for reading."); name_stream >> m_name_table; unsigned number_of_chars = 0; name_stream.read(reinterpret_cast(&number_of_chars), sizeof(number_of_chars)); - if( !name_stream ) + if (!name_stream) throw exception("Encountered invalid file, failed to read number of contained chars"); - BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken"); m_names_char_list.resize(number_of_chars + 1); //+1 gives sentinel element - name_stream.read(reinterpret_cast(&m_names_char_list[0]), - number_of_chars * sizeof(m_names_char_list[0])); - if( !name_stream ) - throw exception("Failed to read " + std::to_string(number_of_chars) + " characters from file."); - - if (0 == m_names_char_list.size()) + m_names_char_list.back() = 0; + if (number_of_chars > 0) + { + name_stream.read(reinterpret_cast(&m_names_char_list[0]), + number_of_chars * sizeof(m_names_char_list[0])); + } + else { util::SimpleLogger().Write(logWARNING) << "list of street names is empty"; } + if (!name_stream) + throw exception("Failed to read " + std::to_string(number_of_chars) + + " characters from file."); } std::string NameTable::GetNameForID(const unsigned name_id) const