improve collapse-handling
This commit is contained in:
parent
dfafe7dc5f
commit
1dfdb38d4a
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
- Guidance:
|
- Guidance:
|
||||||
- improved handling of sliproads (emit turns instead of 'take the ramp')
|
- improved handling of sliproads (emit turns instead of 'take the ramp')
|
||||||
|
- improved collapsing of instructions. Some 'new name' instructions will be suppressed if they are without alternative and the segment is short
|
||||||
- BREAKING: modifies the file format with new internal identifiers
|
- BREAKING: modifies the file format with new internal identifiers
|
||||||
|
|
||||||
- API:
|
- API:
|
||||||
|
@ -115,7 +115,7 @@ Feature: Bike - Oneway streets
|
|||||||
|
|
||||||
Scenario: Bike - Two consecutive oneways
|
Scenario: Bike - Two consecutive oneways
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c |
|
| a | b | | c |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | oneway |
|
| nodes | oneway |
|
||||||
|
@ -68,7 +68,7 @@ Feature: Car - Oneway streets
|
|||||||
|
|
||||||
Scenario: Car - Two consecutive oneways
|
Scenario: Car - Two consecutive oneways
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c |
|
| a | b | | c |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | oneway |
|
| nodes | oneway |
|
||||||
|
@ -5,6 +5,7 @@ Feature: Car - Turn restrictions
|
|||||||
|
|
||||||
Background: Use car routing
|
Background: Use car routing
|
||||||
Given the profile "car"
|
Given the profile "car"
|
||||||
|
Given a grid size of 200 meters
|
||||||
|
|
||||||
@no_turning
|
@no_turning
|
||||||
Scenario: Car - No left turn
|
Scenario: Car - No left turn
|
||||||
|
@ -12,19 +12,17 @@ Feature: Traffic - turn penalties
|
|||||||
| nodes | highway |
|
| nodes | highway |
|
||||||
| ad | primary |
|
| ad | primary |
|
||||||
| cd | primary |
|
| cd | primary |
|
||||||
| de | primary |
|
| def | primary |
|
||||||
| dhk | primary |
|
| dhk | primary |
|
||||||
|
|
||||||
| bf | primary |
|
| bf | primary |
|
||||||
| ef | primary |
|
|
||||||
| fg | primary |
|
| fg | primary |
|
||||||
| fim | primary |
|
| fim | primary |
|
||||||
|
|
||||||
| jk | primary |
|
| jk | primary |
|
||||||
| kl | primary |
|
| klm | primary |
|
||||||
| ko | primary |
|
| ko | primary |
|
||||||
|
|
||||||
| lm | primary |
|
|
||||||
| mn | primary |
|
| mn | primary |
|
||||||
| mp | primary |
|
| mp | primary |
|
||||||
And the profile "car"
|
And the profile "car"
|
||||||
@ -32,22 +30,22 @@ Feature: Traffic - turn penalties
|
|||||||
|
|
||||||
Scenario: Weighting not based on turn penalty file
|
Scenario: Weighting not based on turn penalty file
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | speed | time |
|
| from | to | route | speed | time |
|
||||||
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
|
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
|
||||||
# straight
|
# straight
|
||||||
| i | g | fim,fg,fg | 59 km/h | 12s +-1 |
|
| i | g | fim,fg,fg | 59 km/h | 12s +-1 |
|
||||||
# right
|
# right
|
||||||
| a | e | ad,de,de | 57 km/h | 12.5s +-1 |
|
| a | e | ad,def,def | 57 km/h | 12.5s +-1 |
|
||||||
# left
|
# left
|
||||||
| c | g | cd,de,ef,fg,fg | 63 km/h | 23s +-1 |
|
| c | g | cd,def,fg,fg | 63 km/h | 23s +-1 |
|
||||||
# double straight
|
# double straight
|
||||||
| p | g | mp,fim,fg,fg | 61 km/h | 23.5s +-1 |
|
| p | g | mp,fim,fg,fg | 61 km/h | 23.5s +-1 |
|
||||||
# straight-right
|
# straight-right
|
||||||
| a | l | ad,dhk,kl,kl | 60 km/h | 24s +-1 |
|
| a | l | ad,dhk,klm,klm | 60 km/h | 24s +-1 |
|
||||||
# straight-left
|
# straight-left
|
||||||
| l | e | kl,dhk,de,de | 59 km/h | 24.5s +-1 |
|
| l | e | klm,dhk,def,def | 59 km/h | 24.5s +-1 |
|
||||||
# double right
|
# double right
|
||||||
| g | n | fg,fim,mn,mn | 57 km/h | 25s +-1 |
|
| g | n | fg,fim,mn,mn | 57 km/h | 25s +-1 |
|
||||||
# double left
|
# double left
|
||||||
|
|
||||||
Scenario: Weighting based on turn penalty file
|
Scenario: Weighting based on turn penalty file
|
||||||
@ -62,24 +60,24 @@ Feature: Traffic - turn penalties
|
|||||||
"""
|
"""
|
||||||
And the contract extra arguments "--turn-penalty-file penalties.csv"
|
And the contract extra arguments "--turn-penalty-file penalties.csv"
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | speed | time |
|
| from | to | route | speed | time |
|
||||||
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
|
| a | h | ad,dhk,dhk | 63 km/h | 11.5s +-1 |
|
||||||
# straight
|
# straight
|
||||||
| i | g | fim,fg,fg | 55 km/h | 13s +-1 |
|
| i | g | fim,fg,fg | 55 km/h | 13s +-1 |
|
||||||
# right - ifg penalty
|
# right - ifg penalty
|
||||||
| a | e | ad,de,de | 64 km/h | 11s +-1 |
|
| a | e | ad,def,def | 64 km/h | 11s +-1 |
|
||||||
# left - faster because of negative ade penalty
|
# left - faster because of negative ade penalty
|
||||||
| c | g | cd,de,ef,fg,fg | 63 km/h | 23s +-1 |
|
| c | g | cd,def,fg,fg | 63 km/h | 23s +-1 |
|
||||||
# double straight
|
# double straight
|
||||||
| p | g | mp,fim,fg,fg | 59 km/h | 24.5s +-1 |
|
| p | g | mp,fim,fg,fg | 59 km/h | 24.5s +-1 |
|
||||||
# straight-right - ifg penalty
|
# straight-right - ifg penalty
|
||||||
| a | l | ad,de,ef,fim,lm,lm | 61 km/h | 35.5s +-1 |
|
| a | l | ad,def,fim,klm,klm | 61 km/h | 35.5s +-1 |
|
||||||
# was straight-left - forced around by hkl penalty
|
# was straight-left - forced around by hkl penalty
|
||||||
| l | e | lm,fim,ef,ef | 57 km/h | 25s +-1 |
|
| l | e | klm,fim,def,def | 57 km/h | 25s +-1 |
|
||||||
# double right - forced left by lkh penalty
|
# double right - forced left by lkh penalty
|
||||||
| g | n | fg,fim,mn,mn | 30 km/h | 47.5s +-1 |
|
| g | n | fg,fim,mn,mn | 30 km/h | 47.5s +-1 |
|
||||||
# double left - imn penalty
|
# double left - imn penalty
|
||||||
| j | c | jk,kl,lm,fim,ef,de,cd,cd | 60 km/h | 48s +-1 |
|
| j | c | jk,klm,fim,def,cd,cd | 60 km/h | 48s +-1 |
|
||||||
# double left - hdc penalty ever so slightly higher than imn; forces all the way around
|
# double left - hdc penalty ever so slightly higher than imn; forces all the way around
|
||||||
|
|
||||||
Scenario: Too-negative penalty clamps, but does not fail
|
Scenario: Too-negative penalty clamps, but does not fail
|
||||||
@ -90,8 +88,8 @@ Feature: Traffic - turn penalties
|
|||||||
1,4,5,-10
|
1,4,5,-10
|
||||||
"""
|
"""
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | time |
|
||||||
| a | d | ad,ad | 10s +-1 |
|
| a | d | ad,ad | 10s +-1 |
|
||||||
| a | e | ad,de,de | 10s +-1 |
|
| a | e | ad,def,def | 10s +-1 |
|
||||||
| b | f | bf,bf | 10s +-1 |
|
| b | f | bf,bf | 10s +-1 |
|
||||||
| b | g | bf,fg,fg | 20s +-1 |
|
| b | g | bf,fg,fg | 20s +-1 |
|
||||||
|
@ -345,3 +345,143 @@ Feature: Collapse
|
|||||||
| a,d | first,first,first,first | depart,continue left,continue right,arrive |
|
| a,d | first,first,first,first | depart,continue left,continue right,arrive |
|
||||||
| a,e | first,second,second | depart,turn left,arrive |
|
| a,e | first,second,second | depart,turn left,arrive |
|
||||||
| a,f | first,third,third | depart,turn straight,arrive |
|
| a,f | first,third,third | depart,turn straight,arrive |
|
||||||
|
|
||||||
|
Scenario: Bridge on unnamed road
|
||||||
|
Given the node map
|
||||||
|
| a | b | | | | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name |
|
||||||
|
| ab | primary | |
|
||||||
|
| bc | primary | Bridge |
|
||||||
|
| cd | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | , | depart,arrive |
|
||||||
|
|
||||||
|
Scenario: Crossing Bridge into Segregated Turn
|
||||||
|
Given the node map
|
||||||
|
| | | | | | f |
|
||||||
|
| i | h | | | g | e |
|
||||||
|
| a | b | | | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | oneway | name |
|
||||||
|
| ab | primary | yes | to_bridge |
|
||||||
|
| bc | primary | yes | bridge |
|
||||||
|
| cd | primary | yes | off_bridge |
|
||||||
|
| de | primary | yes | |
|
||||||
|
| ef | primary | no | target_road |
|
||||||
|
| eg | primary | yes | off_bridge |
|
||||||
|
| gh | primary | yes | bridge |
|
||||||
|
| hi | primary | yes | to_bridge |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,f | to_bridge,target_road,target_road | depart,turn left,arrive |
|
||||||
|
|
||||||
|
Scenario: Pankenbruecke
|
||||||
|
Given the node map
|
||||||
|
| h | | | | | | i | | | | | | |
|
||||||
|
| | | b | c | d | e | f | | | | | | g |
|
||||||
|
| a | | | | | | | | | | | | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | oneway |
|
||||||
|
| abh | primary | inroad | yes |
|
||||||
|
| bc | primary | inroad | no |
|
||||||
|
| cd | primary | bridge | no |
|
||||||
|
| defg | primary | outroad | no |
|
||||||
|
| fi | primary | cross | no |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,g | inroad,outroad,outroad | depart,new name straight,arrive |
|
||||||
|
| a,i | inroad,cross,cross | depart,turn left,arrive |
|
||||||
|
|
||||||
|
Scenario: Close Turns - Don't Collapse
|
||||||
|
Given the node map
|
||||||
|
| | g | d | |
|
||||||
|
| | | | |
|
||||||
|
| e | b | c | f |
|
||||||
|
| | | | |
|
||||||
|
| | a | h | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name |
|
||||||
|
| ab | primary | in |
|
||||||
|
| ebcf | primary | cross |
|
||||||
|
| cd | primary | out |
|
||||||
|
| bg | primary | straight |
|
||||||
|
| ch | primary | reverse |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | in,cross,out,out | depart,turn right,turn left,arrive |
|
||||||
|
| a,h | in,cross,reverse,reverse | depart,turn right,turn right,arrive |
|
||||||
|
| g,d | straight,cross,out,out | depart,turn left,turn left,arrive |
|
||||||
|
|
||||||
|
Scenario: No Name During Turns
|
||||||
|
Given the node map
|
||||||
|
| a | b | |
|
||||||
|
| | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name |
|
||||||
|
| ab | tertiary | road |
|
||||||
|
| bc | tertiary | |
|
||||||
|
| cd | tertiary | road |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | road,road | depart,arrive |
|
||||||
|
|
||||||
|
Scenario: No Name During Turns, Random Oneway
|
||||||
|
Given the node map
|
||||||
|
| a | b | |
|
||||||
|
| | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | oneway |
|
||||||
|
| ab | tertiary | road | no |
|
||||||
|
| bc | tertiary | | yes |
|
||||||
|
| cd | tertiary | road | no |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | road,road | depart,arrive |
|
||||||
|
|
||||||
|
Scenario: Pulled Back Turn
|
||||||
|
Given the node map
|
||||||
|
| | | d |
|
||||||
|
| a | b | c |
|
||||||
|
| | e | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name |
|
||||||
|
| abc | tertiary | road |
|
||||||
|
| cd | tertiary | left |
|
||||||
|
| be | tertiary | right |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | road,left,left | depart,turn left,arrive |
|
||||||
|
| a,e | road,right,right | depart,turn right,arrive |
|
||||||
|
|
||||||
|
Scenario: No Name During Turns, keep important turns
|
||||||
|
Given the node map
|
||||||
|
| a | b | e |
|
||||||
|
| | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name |
|
||||||
|
| ab | tertiary | road |
|
||||||
|
| bc | tertiary | |
|
||||||
|
| cd | tertiary | road |
|
||||||
|
| be | tertiary | other |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,d | road,road,road | depart,continue right,arrive |
|
||||||
|
|
||||||
|
@ -117,9 +117,9 @@ Feature: Intersections Data
|
|||||||
| cf | corner |
|
| cf | corner |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | intersections |
|
| waypoints | route | turns | intersections |
|
||||||
| a,d | through,through | depart,arrive | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
|
| a,d | through,through | depart,arrive | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
|
||||||
| f,a | corner,throughbridge,through | depart,end of road left,arrive | true:0;true:90 false:180 true:270,true:0 false:90 true:270;true:90 |
|
| f,a | corner,through,through | depart,end of road left,arrive | true:0;true:90 false:180 true:270,true:0 false:90 true:270;true:90 |
|
||||||
|
|
||||||
Scenario: Roundabouts
|
Scenario: Roundabouts
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -3,7 +3,7 @@ Feature: New-Name Instructions
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "car"
|
Given the profile "car"
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 100 meters
|
||||||
|
|
||||||
Scenario: Undisturbed name Change
|
Scenario: Undisturbed name Change
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -136,7 +136,7 @@ Feature: New-Name Instructions
|
|||||||
|
|
||||||
Scenario: Empty road names - Announce Change From, suppress Change To
|
Scenario: Empty road names - Announce Change From, suppress Change To
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | | b | | c | | d |
|
| a | | b | 1 | c | | d |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | name |
|
| nodes | name |
|
||||||
@ -147,7 +147,7 @@ Feature: New-Name Instructions
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,d | ab,cd,cd | depart,new name straight,arrive |
|
| a,d | ab,cd,cd | depart,new name straight,arrive |
|
||||||
| a,c | ab, | depart,arrive |
|
| a,1 | ab, | depart,arrive |
|
||||||
|
|
||||||
Scenario: Empty road names - Loose name shortly
|
Scenario: Empty road names - Loose name shortly
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -3,6 +3,7 @@ Feature: Alternative route
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
And a grid size of 200 meters
|
||||||
|
|
||||||
And the node map
|
And the node map
|
||||||
| | b | c | d | | |
|
| | b | c | d | | |
|
||||||
@ -17,11 +18,11 @@ Feature: Alternative route
|
|||||||
| dz |
|
| dz |
|
||||||
| ag |
|
| ag |
|
||||||
| gh |
|
| gh |
|
||||||
|
| ck |
|
||||||
|
| kh |
|
||||||
| hi |
|
| hi |
|
||||||
| ij |
|
| ij |
|
||||||
| jz |
|
| jz |
|
||||||
| ck |
|
|
||||||
| kh |
|
|
||||||
|
|
||||||
Scenario: Enabled alternative
|
Scenario: Enabled alternative
|
||||||
Given the query options
|
Given the query options
|
||||||
|
@ -56,7 +56,7 @@ Feature: Basic Routing
|
|||||||
|
|
||||||
Scenario: Two ways connected in a straight line
|
Scenario: Two ways connected in a straight line
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c |
|
| a | | b | | c |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes |
|
| nodes |
|
||||||
|
@ -43,8 +43,8 @@ Feature: Bearing parameter
|
|||||||
|
|
||||||
Scenario: Testbot - Initial bearing on split way
|
Scenario: Testbot - Initial bearing on split way
|
||||||
Given the node map
|
Given the node map
|
||||||
| d | | | | | 1 | | | | | c |
|
| g | d | | | | | 1 | | | | | c | f |
|
||||||
| a | | | | | 0 | | | | | b |
|
| h | a | | | | | 0 | | | | | b | e |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | oneway |
|
| nodes | oneway |
|
||||||
@ -52,6 +52,10 @@ Feature: Bearing parameter
|
|||||||
| bc | yes |
|
| bc | yes |
|
||||||
| cd | yes |
|
| cd | yes |
|
||||||
| da | yes |
|
| da | yes |
|
||||||
|
| be | yes |
|
||||||
|
| fc | yes |
|
||||||
|
| dg | yes |
|
||||||
|
| ha | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | bearings | route | bearing |
|
| from | to | bearings | route | bearing |
|
||||||
|
@ -3,6 +3,7 @@ Feature: U-turns at via points
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
Given a grid size of 100 meters
|
||||||
|
|
||||||
Scenario: Continue straight at waypoints enabled by default
|
Scenario: Continue straight at waypoints enabled by default
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -11,6 +11,7 @@ Feature: Testbot - Travel mode
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
Given a grid size of 200 meters
|
||||||
|
|
||||||
Scenario: Testbot - Always announce mode change
|
Scenario: Testbot - Always announce mode change
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -72,9 +73,9 @@ Feature: Testbot - Travel mode
|
|||||||
| ab | steps |
|
| ab | steps |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | modes | time |
|
| from | to | route | modes | time |
|
||||||
| 0 | 1 | ab,ab | steps down,steps down | 60s +-1 |
|
| 0 | 1 | ab,ab | steps down,steps down | 120s +-1 |
|
||||||
| 1 | 0 | ab,ab | steps up,steps up | 60s +-1 |
|
| 1 | 0 | ab,ab | steps up,steps up | 120s +-1 |
|
||||||
|
|
||||||
@oneway
|
@oneway
|
||||||
Scenario: Testbot - Modes for oneway, different forward/backward speeds
|
Scenario: Testbot - Modes for oneway, different forward/backward speeds
|
||||||
|
@ -3,6 +3,7 @@ Feature: Basic Routing
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
Given a grid size of 200 meters
|
||||||
|
|
||||||
@smallest
|
@smallest
|
||||||
Scenario: Checking
|
Scenario: Checking
|
||||||
|
@ -144,6 +144,7 @@ class RouteAPI : public BaseAPI
|
|||||||
guidance::trimShortSegments(steps, leg_geometry);
|
guidance::trimShortSegments(steps, leg_geometry);
|
||||||
leg.steps = guidance::postProcess(std::move(steps));
|
leg.steps = guidance::postProcess(std::move(steps));
|
||||||
leg.steps = guidance::collapseTurns(std::move(leg.steps));
|
leg.steps = guidance::collapseTurns(std::move(leg.steps));
|
||||||
|
leg.steps = guidance::buildIntersections(std::move(leg.steps));
|
||||||
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
|
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
|
||||||
leg_geometry,
|
leg_geometry,
|
||||||
phantoms.source_phantom,
|
phantoms.source_phantom,
|
||||||
|
@ -37,6 +37,9 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
|
|||||||
const PhantomNode &source_node,
|
const PhantomNode &source_node,
|
||||||
const PhantomNode &target_node);
|
const PhantomNode &target_node);
|
||||||
|
|
||||||
|
// collapse suppressed instructions remaining into intersections array
|
||||||
|
std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps);
|
||||||
|
|
||||||
// remove steps invalidated by post-processing
|
// remove steps invalidated by post-processing
|
||||||
std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps);
|
std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "engine/guidance/post_processing.hpp"
|
|
||||||
#include "extractor/guidance/turn_instruction.hpp"
|
#include "extractor/guidance/turn_instruction.hpp"
|
||||||
|
#include "engine/guidance/post_processing.hpp"
|
||||||
|
|
||||||
#include "engine/guidance/assemble_steps.hpp"
|
#include "engine/guidance/assemble_steps.hpp"
|
||||||
#include "engine/guidance/toolkit.hpp"
|
#include "engine/guidance/toolkit.hpp"
|
||||||
@ -31,35 +31,76 @@ namespace guidance
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
const constexpr double MAX_COLLAPSE_DISTANCE = 25;
|
||||||
|
|
||||||
|
// List of types that can be collapsed, if all other restrictions pass
|
||||||
|
bool isCollapsableInstruction(const TurnInstruction instruction)
|
||||||
|
{
|
||||||
|
return instruction.type == TurnType::NewName ||
|
||||||
|
(instruction.type == TurnType::Suppressed &&
|
||||||
|
instruction.direction_modifier == DirectionModifier::Straight) ||
|
||||||
|
(instruction.type == TurnType::Turn &&
|
||||||
|
instruction.direction_modifier == DirectionModifier::Straight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// A check whether two instructions can be treated as one. This is only the case for very short
|
||||||
|
// maneuvers that can, in some form, be seen as one. The additional in_step is to find out about
|
||||||
|
// a possible u-turn.
|
||||||
|
bool collapsable(const RouteStep &step)
|
||||||
|
{
|
||||||
|
|
||||||
|
return step.distance < MAX_COLLAPSE_DISTANCE &&
|
||||||
|
isCollapsableInstruction(step.maneuver.instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compatible(const RouteStep &lhs, const RouteStep &rhs) { return lhs.mode == rhs.mode; }
|
||||||
|
|
||||||
|
double nameSegmentLength(std::size_t at, const std::vector<RouteStep> &steps)
|
||||||
|
{
|
||||||
|
double result = steps[at].distance;
|
||||||
|
while (at + 1 < steps.size() && steps[at + 1].name_id == steps[at].name_id)
|
||||||
|
{
|
||||||
|
++at;
|
||||||
|
result += steps[at].distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// invalidate a step and set its content to nothing
|
// invalidate a step and set its content to nothing
|
||||||
void invalidateStep(RouteStep &step) { step = getInvalidRouteStep(); }
|
void invalidateStep(RouteStep &step) { step = getInvalidRouteStep(); }
|
||||||
|
|
||||||
|
void print(const RouteStep &step)
|
||||||
|
{
|
||||||
|
std::cout << static_cast<int>(step.maneuver.instruction.type) << " "
|
||||||
|
<< static_cast<int>(step.maneuver.instruction.direction_modifier) << " "
|
||||||
|
<< static_cast<int>(step.maneuver.waypoint_type) << " Duration: " << step.duration
|
||||||
|
<< " Distance: " << step.distance << " Geometry: " << step.geometry_begin << " "
|
||||||
|
<< step.geometry_end << " exit: " << step.maneuver.exit
|
||||||
|
<< " Intersections: " << step.intersections.size() << " [";
|
||||||
|
|
||||||
|
for (const auto &intersection : step.intersections)
|
||||||
|
{
|
||||||
|
std::cout << "(bearings:";
|
||||||
|
for (auto bearing : intersection.bearings)
|
||||||
|
std::cout << " " << bearing;
|
||||||
|
std::cout << ", entry: ";
|
||||||
|
for (auto entry : intersection.entry)
|
||||||
|
std::cout << " " << entry;
|
||||||
|
std::cout << ")";
|
||||||
|
}
|
||||||
|
std::cout << "] name[" << step.name_id << "]: " << step.name;
|
||||||
|
}
|
||||||
|
|
||||||
void print(const std::vector<RouteStep> &steps)
|
void print(const std::vector<RouteStep> &steps)
|
||||||
{
|
{
|
||||||
std::cout << "Path\n";
|
std::cout << "Path\n";
|
||||||
int segment = 0;
|
int segment = 0;
|
||||||
for (const auto &step : steps)
|
for (const auto &step : steps)
|
||||||
{
|
{
|
||||||
std::cout << "\t[" << ++segment << "]: " << static_cast<int>(step.maneuver.instruction.type)
|
std::cout << "\t[" << segment++ << "]: ";
|
||||||
<< " " << static_cast<int>(step.maneuver.instruction.direction_modifier) << " "
|
print(step);
|
||||||
<< static_cast<int>(step.maneuver.waypoint_type) << " Duration: " << step.duration
|
std::cout << std::endl;
|
||||||
<< " Distance: " << step.distance << " Geometry: " << step.geometry_begin << " "
|
|
||||||
<< step.geometry_end << " exit: " << step.maneuver.exit
|
|
||||||
<< " Intersections: " << step.intersections.size() << " [";
|
|
||||||
|
|
||||||
for (const auto &intersection : step.intersections)
|
|
||||||
{
|
|
||||||
std::cout << "(bearings:";
|
|
||||||
for (auto bearing : intersection.bearings)
|
|
||||||
std::cout << " " << bearing;
|
|
||||||
std::cout << ", entry: ";
|
|
||||||
for (auto entry : intersection.entry)
|
|
||||||
std::cout << " " << entry;
|
|
||||||
std::cout << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "] name[" << step.name_id << "]: " << step.name << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,15 +368,6 @@ RouteStep elongate(RouteStep step, const RouteStep &by_step)
|
|||||||
return step;
|
return step;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A check whether two instructions can be treated as one. This is only the case for very short
|
|
||||||
// maneuvers that can, in some form, be seen as one. The additional in_step is to find out about
|
|
||||||
// a possible u-turn.
|
|
||||||
bool collapsable(const RouteStep &step)
|
|
||||||
{
|
|
||||||
const constexpr double MAX_COLLAPSE_DISTANCE = 25;
|
|
||||||
return step.distance < MAX_COLLAPSE_DISTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void collapseTurnAt(std::vector<RouteStep> &steps,
|
void collapseTurnAt(std::vector<RouteStep> &steps,
|
||||||
const std::size_t two_back_index,
|
const std::size_t two_back_index,
|
||||||
const std::size_t one_back_index,
|
const std::size_t one_back_index,
|
||||||
@ -353,46 +385,59 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
|||||||
};
|
};
|
||||||
|
|
||||||
BOOST_ASSERT(!one_back_step.intersections.empty() && !current_step.intersections.empty());
|
BOOST_ASSERT(!one_back_step.intersections.empty() && !current_step.intersections.empty());
|
||||||
const auto isCollapsableInstruction = [](const TurnInstruction instruction) {
|
|
||||||
return instruction.type == TurnType::NewName ||
|
|
||||||
(instruction.type == TurnType::Turn &&
|
|
||||||
instruction.direction_modifier == DirectionModifier::Straight);
|
|
||||||
};
|
|
||||||
// Very Short New Name
|
// Very Short New Name
|
||||||
if (isCollapsableInstruction(one_back_step.maneuver.instruction))
|
if (collapsable(one_back_step))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(two_back_index < steps.size());
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
if (one_back_step.mode == steps[two_back_index].mode)
|
if (compatible(one_back_step, steps[two_back_index]))
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(!one_back_step.intersections.empty());
|
||||||
|
if (TurnType::Continue == current_step.maneuver.instruction.type ||
|
||||||
|
TurnType::Suppressed == current_step.maneuver.instruction.type)
|
||||||
|
steps[step_index].maneuver.instruction.type = TurnType::Turn;
|
||||||
|
else if (TurnType::NewName == current_step.maneuver.instruction.type &&
|
||||||
|
current_step.maneuver.instruction.direction_modifier !=
|
||||||
|
DirectionModifier::Straight &&
|
||||||
|
one_back_step.intersections.front().bearings.size() > 2)
|
||||||
|
steps[step_index].maneuver.instruction.type = TurnType::Turn;
|
||||||
|
|
||||||
steps[two_back_index] = elongate(std::move(steps[two_back_index]), one_back_step);
|
steps[two_back_index] = elongate(std::move(steps[two_back_index]), one_back_step);
|
||||||
// If the previous instruction asked to continue, the name change will have to
|
// If the previous instruction asked to continue, the name change will have to
|
||||||
// be changed into a turn
|
// be changed into a turn
|
||||||
invalidateStep(steps[one_back_index]);
|
invalidateStep(steps[one_back_index]);
|
||||||
|
|
||||||
if (TurnType::Continue == current_step.maneuver.instruction.type)
|
|
||||||
steps[step_index].maneuver.instruction.type = TurnType::Turn;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// very short segment after turn
|
// very short segment after turn
|
||||||
else if (isCollapsableInstruction(current_step.maneuver.instruction))
|
else if (one_back_step.distance <= MAX_COLLAPSE_DISTANCE &&
|
||||||
|
isCollapsableInstruction(current_step.maneuver.instruction))
|
||||||
{
|
{
|
||||||
if (one_back_step.mode == current_step.mode)
|
if (compatible(one_back_step, current_step))
|
||||||
{
|
{
|
||||||
steps[step_index] = elongate(std::move(steps[step_index]), steps[one_back_index]);
|
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
|
||||||
invalidateStep(steps[one_back_index]);
|
if ((TurnType::Continue == one_back_step.maneuver.instruction.type ||
|
||||||
|
TurnType::Suppressed == one_back_step.maneuver.instruction.type) &&
|
||||||
if (TurnType::Continue == current_step.maneuver.instruction.type)
|
current_step.name_id != steps[two_back_index].name_id)
|
||||||
{
|
{
|
||||||
steps[step_index].maneuver.instruction.type = TurnType::Turn;
|
steps[one_back_index].maneuver.instruction.type = TurnType::Turn;
|
||||||
}
|
}
|
||||||
|
else if (TurnType::Turn == one_back_step.maneuver.instruction.type &&
|
||||||
|
current_step.name_id == steps[two_back_index].name_id)
|
||||||
|
{
|
||||||
|
steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
|
||||||
|
}
|
||||||
|
steps[one_back_index].name = current_step.name;
|
||||||
|
steps[one_back_index].name_id = current_step.name_id;
|
||||||
|
invalidateStep(steps[step_index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Potential U-Turn
|
// Potential U-Turn
|
||||||
else if (bearingsAreReversed(util::bearing::reverseBearing(
|
else if (one_back_step.distance <= MAX_COLLAPSE_DISTANCE &&
|
||||||
|
bearingsAreReversed(util::bearing::reverseBearing(
|
||||||
one_back_step.intersections.front()
|
one_back_step.intersections.front()
|
||||||
.bearings[one_back_step.intersections.front().in]),
|
.bearings[one_back_step.intersections.front().in]),
|
||||||
current_step.intersections.front()
|
current_step.intersections.front()
|
||||||
.bearings[current_step.intersections.front().out]))
|
.bearings[current_step.intersections.front().out]) &&
|
||||||
|
compatible(one_back_step, current_step))
|
||||||
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(two_back_index < steps.size());
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
@ -405,8 +450,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
|||||||
(step_index + 1 < steps.size()) &&
|
(step_index + 1 < steps.size()) &&
|
||||||
isCollapsableInstruction(steps[step_index + 1].maneuver.instruction);
|
isCollapsableInstruction(steps[step_index + 1].maneuver.instruction);
|
||||||
const bool u_turn_with_name_change =
|
const bool u_turn_with_name_change =
|
||||||
collapsable(current_step) && continues_with_name_change &&
|
continues_with_name_change && steps[step_index + 1].name == steps[two_back_index].name;
|
||||||
steps[step_index + 1].name == steps[two_back_index].name;
|
|
||||||
|
|
||||||
if (direct_u_turn || u_turn_with_name_change)
|
if (direct_u_turn || u_turn_with_name_change)
|
||||||
{
|
{
|
||||||
@ -518,13 +562,6 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
|
|||||||
has_entered_roundabout = false;
|
has_entered_roundabout = false;
|
||||||
on_roundabout = false;
|
on_roundabout = false;
|
||||||
}
|
}
|
||||||
else if (instruction.type == TurnType::Suppressed)
|
|
||||||
{
|
|
||||||
// count intersections. We cannot use exit, since intersections can follow directly
|
|
||||||
// after a roundabout
|
|
||||||
steps[last_valid_instruction] = elongate(steps[last_valid_instruction], step);
|
|
||||||
step.maneuver.instruction = TurnInstruction::NO_TURN();
|
|
||||||
}
|
|
||||||
else if (!isSilent(instruction))
|
else if (!isSilent(instruction))
|
||||||
{
|
{
|
||||||
// Remember the last non silent instruction
|
// Remember the last non silent instruction
|
||||||
@ -564,58 +601,57 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
BOOST_ASSERT(index > 0);
|
BOOST_ASSERT(index > 0);
|
||||||
BOOST_ASSERT(index < steps.size());
|
BOOST_ASSERT(index < steps.size());
|
||||||
--index;
|
--index;
|
||||||
while (index > 0 && steps[index].maneuver.instruction == TurnInstruction::NO_TURN())
|
while (index > 0 && steps[index].maneuver.instruction.type == TurnType::NoTurn)
|
||||||
--index;
|
--index;
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check for an initial unwanted new-name
|
const auto getPreviousNameIndex = [&steps](std::size_t index) {
|
||||||
{
|
BOOST_ASSERT(index > 0);
|
||||||
const auto ¤t_step = steps[1];
|
BOOST_ASSERT(index < steps.size());
|
||||||
if (TurnType::NewName == current_step.maneuver.instruction.type &&
|
--index; // make sure to skip the current name
|
||||||
current_step.name == steps[0].name)
|
while (index > 0 && steps[index].name_id == EMPTY_NAMEID)
|
||||||
{
|
{
|
||||||
steps[0] = elongate(std::move(steps[0]), steps[1]);
|
--index;
|
||||||
invalidateStep(steps[1]);
|
|
||||||
}
|
}
|
||||||
}
|
return index;
|
||||||
const auto isCollapsableInstruction = [](const TurnInstruction instruction) {
|
|
||||||
return instruction.type == TurnType::NewName ||
|
|
||||||
(instruction.type == TurnType::Turn &&
|
|
||||||
instruction.direction_modifier == DirectionModifier::Straight);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Special case handling: if the phantomnode landed on a sliproad, we
|
// a series of turns is only possible to collapse if its only name changes and suppressed turns.
|
||||||
// change this into a 'turn' instruction. Sliproads are small ramps
|
const auto canCollapseAll = [&steps](std::size_t index, const std::size_t end_index) {
|
||||||
// between roads, not ramps.
|
BOOST_ASSERT(end_index <= steps.size());
|
||||||
if (steps.size() >= 3 &&
|
for (; index < end_index; ++index)
|
||||||
steps[steps.size() - 2].maneuver.instruction.type == TurnType::Sliproad)
|
{
|
||||||
{
|
if (steps[index].maneuver.instruction.type != TurnType::Suppressed &&
|
||||||
steps[steps.size() - 2].maneuver.instruction.type = TurnType::Turn;
|
steps[index].maneuver.instruction.type != TurnType::NewName)
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
// first and last instructions are waypoints that cannot be collapsed
|
// first and last instructions are waypoints that cannot be collapsed
|
||||||
for (std::size_t step_index = 2; step_index < steps.size(); ++step_index)
|
for (std::size_t step_index = 1; step_index + 1 < steps.size(); ++step_index)
|
||||||
{
|
{
|
||||||
const auto ¤t_step = steps[step_index];
|
const auto ¤t_step = steps[step_index];
|
||||||
const auto one_back_index = getPreviousIndex(step_index);
|
const auto one_back_index = getPreviousIndex(step_index);
|
||||||
BOOST_ASSERT(one_back_index < steps.size());
|
BOOST_ASSERT(one_back_index < steps.size());
|
||||||
|
|
||||||
// cannot collapse the depart instruction
|
|
||||||
if (one_back_index == 0 || current_step.maneuver.instruction == TurnInstruction::NO_TURN())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto &one_back_step = steps[one_back_index];
|
const auto &one_back_step = steps[one_back_index];
|
||||||
const auto two_back_index = getPreviousIndex(one_back_index);
|
// how long has a name change to be so that we announce it, even as a bridge?
|
||||||
BOOST_ASSERT(two_back_index < steps.size());
|
const constexpr auto name_segment_cutoff_length = 100;
|
||||||
|
const auto isBasicNameChange = [](const RouteStep &step) {
|
||||||
|
return step.intersections.size() == 1 &&
|
||||||
|
step.intersections.front().bearings.size() == 2 &&
|
||||||
|
DirectionModifier::Straight == step.maneuver.instruction.direction_modifier;
|
||||||
|
};
|
||||||
|
|
||||||
// Handle sliproads from motorways in urban areas
|
// Handle sliproads from motorways in urban areas, save from modifying depart, since
|
||||||
|
// TurnType::Sliproad != TurnType::NoTurn
|
||||||
if (one_back_step.maneuver.instruction.type == TurnType::Sliproad)
|
if (one_back_step.maneuver.instruction.type == TurnType::Sliproad)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Handle possible u-turns between highways that look like slip-roads
|
// Handle possible u-turns between highways that look like slip-roads
|
||||||
if (steps[two_back_index].name_id == steps[step_index].name_id &&
|
if (steps[getPreviousIndex(one_back_index)].name_id == steps[step_index].name_id &&
|
||||||
steps[step_index].name_id != EMPTY_NAMEID)
|
steps[step_index].name_id != EMPTY_NAMEID)
|
||||||
{
|
{
|
||||||
steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
|
steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
|
||||||
@ -624,42 +660,57 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
{
|
{
|
||||||
steps[one_back_index].maneuver.instruction.type = TurnType::Turn;
|
steps[one_back_index].maneuver.instruction.type = TurnType::Turn;
|
||||||
}
|
}
|
||||||
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
|
if (compatible(one_back_step, current_step))
|
||||||
steps[one_back_index].name_id = steps[step_index].name_id;
|
{
|
||||||
steps[one_back_index].name = steps[step_index].name;
|
steps[one_back_index] =
|
||||||
|
elongate(std::move(steps[one_back_index]), steps[step_index]);
|
||||||
|
steps[one_back_index].name_id = steps[step_index].name_id;
|
||||||
|
steps[one_back_index].name = steps[step_index].name;
|
||||||
|
|
||||||
const auto exit_intersection = steps[step_index].intersections.front();
|
const auto exit_intersection = steps[step_index].intersections.front();
|
||||||
const auto exit_bearing = exit_intersection.bearings[exit_intersection.out];
|
const auto exit_bearing = exit_intersection.bearings[exit_intersection.out];
|
||||||
|
|
||||||
const auto entry_intersection = steps[one_back_index].intersections.front();
|
const auto entry_intersection = steps[one_back_index].intersections.front();
|
||||||
const auto entry_bearing = entry_intersection.bearings[entry_intersection.in];
|
const auto entry_bearing = entry_intersection.bearings[entry_intersection.in];
|
||||||
|
|
||||||
const double angle =
|
const double angle =
|
||||||
turn_angle(util::bearing::reverseBearing(entry_bearing), exit_bearing);
|
turn_angle(util::bearing::reverseBearing(entry_bearing), exit_bearing);
|
||||||
steps[one_back_index].maneuver.instruction.direction_modifier =
|
steps[one_back_index].maneuver.instruction.direction_modifier =
|
||||||
::osrm::util::guidance::getTurnDirection(angle);
|
::osrm::util::guidance::getTurnDirection(angle);
|
||||||
invalidateStep(steps[step_index]);
|
invalidateStep(steps[step_index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Due to empty segments, we can get name-changes from A->A
|
// Due to empty segments, we can get name-changes from A->A
|
||||||
// These have to be handled in post-processing
|
// These have to be handled in post-processing
|
||||||
else if (isCollapsableInstruction(current_step.maneuver.instruction) &&
|
else if (isCollapsableInstruction(current_step.maneuver.instruction) &&
|
||||||
current_step.name == steps[one_back_index].name)
|
current_step.maneuver.instruction.type != TurnType::Suppressed &&
|
||||||
|
steps[getPreviousNameIndex(step_index)].name == current_step.name &&
|
||||||
|
canCollapseAll(getPreviousNameIndex(step_index) + 1, step_index + 1))
|
||||||
{
|
{
|
||||||
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
|
BOOST_ASSERT(step_index > 0);
|
||||||
invalidateStep(steps[step_index]);
|
const std::size_t last_available_name_index = getPreviousNameIndex(step_index);
|
||||||
|
|
||||||
|
for (std::size_t index = last_available_name_index + 1; index <= step_index; ++index)
|
||||||
|
{
|
||||||
|
steps[last_available_name_index] =
|
||||||
|
elongate(std::move(steps[last_available_name_index]), steps[index]);
|
||||||
|
invalidateStep(steps[index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// If we look at two consecutive name changes, we can check for a name oszillation.
|
// If we look at two consecutive name changes, we can check for a name oszillation.
|
||||||
// A name oszillation changes from name A shortly to name B and back to A.
|
// A name oszillation changes from name A shortly to name B and back to A.
|
||||||
// In these cases, the name change will be suppressed.
|
// In these cases, the name change will be suppressed.
|
||||||
else if (isCollapsableInstruction(current_step.maneuver.instruction) &&
|
else if (one_back_index > 0 && compatible(current_step, one_back_step) &&
|
||||||
|
isCollapsableInstruction(current_step.maneuver.instruction) &&
|
||||||
isCollapsableInstruction(one_back_step.maneuver.instruction))
|
isCollapsableInstruction(one_back_step.maneuver.instruction))
|
||||||
{
|
{
|
||||||
// valid due to step_index starting at 2
|
const auto two_back_index = getPreviousIndex(one_back_index);
|
||||||
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
|
// valid, since one_back is collapsable:
|
||||||
const auto &coming_from_name = steps[two_back_index].name;
|
const auto &coming_from_name = steps[two_back_index].name;
|
||||||
if (current_step.name == coming_from_name)
|
if (current_step.name == coming_from_name)
|
||||||
{
|
{
|
||||||
if (current_step.mode == one_back_step.mode &&
|
if (compatible(one_back_step, steps[two_back_index]))
|
||||||
one_back_step.mode == steps[two_back_index].mode)
|
|
||||||
{
|
{
|
||||||
steps[two_back_index] =
|
steps[two_back_index] =
|
||||||
elongate(elongate(std::move(steps[two_back_index]), steps[one_back_index]),
|
elongate(elongate(std::move(steps[two_back_index]), steps[one_back_index]),
|
||||||
@ -670,14 +721,44 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
// TODO discuss: we could think about changing the new-name to a pure notification
|
// TODO discuss: we could think about changing the new-name to a pure notification
|
||||||
// about mode changes
|
// about mode changes
|
||||||
}
|
}
|
||||||
|
else if (nameSegmentLength(one_back_index, steps) < name_segment_cutoff_length &&
|
||||||
|
isBasicNameChange(one_back_step) && isBasicNameChange(current_step))
|
||||||
|
{
|
||||||
|
steps[two_back_index] =
|
||||||
|
elongate(std::move(steps[two_back_index]), steps[one_back_index]);
|
||||||
|
invalidateStep(steps[one_back_index]);
|
||||||
|
if (nameSegmentLength(step_index, steps) < name_segment_cutoff_length)
|
||||||
|
{
|
||||||
|
steps[two_back_index] =
|
||||||
|
elongate(std::move(steps[two_back_index]), steps[step_index]);
|
||||||
|
invalidateStep(steps[step_index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (one_back_step.distance <= MAX_COLLAPSE_DISTANCE)
|
||||||
|
{
|
||||||
|
// check for one of the multiple collapse scenarios and, if possible, collapse the
|
||||||
|
// turn
|
||||||
|
const auto two_back_index = getPreviousIndex(one_back_index);
|
||||||
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
|
collapseTurnAt(steps, two_back_index, one_back_index, step_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (collapsable(one_back_step))
|
else if (one_back_index > 0 && one_back_step.distance <= MAX_COLLAPSE_DISTANCE)
|
||||||
{
|
{
|
||||||
// check for one of the multiple collapse scenarios and, if possible, collapse the turn
|
// check for one of the multiple collapse scenarios and, if possible, collapse the turn
|
||||||
|
const auto two_back_index = getPreviousIndex(one_back_index);
|
||||||
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
collapseTurnAt(steps, two_back_index, one_back_index, step_index);
|
collapseTurnAt(steps, two_back_index, one_back_index, step_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle final sliproad
|
||||||
|
if (steps.size() >= 3 &&
|
||||||
|
steps[steps.size() - 2].maneuver.instruction.type == TurnType::Sliproad)
|
||||||
|
{
|
||||||
|
steps[steps.size() - 2].maneuver.instruction.type = TurnType::Turn;
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(steps.front().intersections.size() >= 1);
|
BOOST_ASSERT(steps.front().intersections.size() >= 1);
|
||||||
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
||||||
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
|
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
|
||||||
@ -700,7 +781,6 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
// usually not be as relevant.
|
// usually not be as relevant.
|
||||||
void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (steps.size() < 2 || geometry.locations.size() <= 2)
|
if (steps.size() < 2 || geometry.locations.size() <= 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -955,6 +1035,29 @@ LegGeometry resyncGeometry(LegGeometry leg_geometry, const std::vector<RouteStep
|
|||||||
return leg_geometry;
|
return leg_geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps)
|
||||||
|
{
|
||||||
|
std::size_t last_valid_instruction = 0;
|
||||||
|
for (std::size_t step_index = 0; step_index < steps.size(); ++step_index)
|
||||||
|
{
|
||||||
|
auto &step = steps[step_index];
|
||||||
|
const auto instruction = step.maneuver.instruction;
|
||||||
|
if (instruction.type == TurnType::Suppressed)
|
||||||
|
{
|
||||||
|
// count intersections. We cannot use exit, since intersections can follow directly
|
||||||
|
// after a roundabout
|
||||||
|
steps[last_valid_instruction] = elongate(steps[last_valid_instruction], step);
|
||||||
|
step.maneuver.instruction = TurnInstruction::NO_TURN();
|
||||||
|
}
|
||||||
|
else if (!isSilent(instruction))
|
||||||
|
{
|
||||||
|
// Remember the last non silent instruction
|
||||||
|
last_valid_instruction = step_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return removeNoTurnInstructions(std::move(steps));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -69,9 +69,6 @@ Intersection TurnHandler::handleTwoWayTurn(const EdgeID via_edge, Intersection i
|
|||||||
intersection[1].turn.instruction =
|
intersection[1].turn.instruction =
|
||||||
getInstructionForObvious(intersection.size(), via_edge, false, 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;
|
|
||||||
|
|
||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user