Compare commits

...

33 Commits

Author SHA1 Message Date
Patrick Niklaus
f7fbca3e5e Update changelog 2017-03-03 17:27:28 +00:00
Patrick Niklaus
9695eaa28a Fix tile datasize check 2017-03-03 16:03:47 +00:00
Patrick Niklaus
0d7546a510 Only allow restricted access for road of certain highway type 2017-03-03 16:03:36 +00:00
Michael Krasnyk
9dc8136240 Fix incorrect forward datasources getter in facade 2017-03-03 10:52:53 +00:00
Patrick Niklaus
a02a83f8bd Other flakey test 2017-03-02 15:24:38 +00:00
Patrick Niklaus
9b18f55d29 Update changelog 2017-03-02 15:00:49 +00:00
Patrick Niklaus
a3434e7ae9 Mark test as flaky and track in own issue. 2017-03-02 14:59:10 +00:00
Patrick Niklaus
64b15028e4 Print 0 rate 2017-03-02 14:58:14 +00:00
karenzshea
d8e466fdaa simplify test, add intersection turn test 2017-03-02 14:58:01 +00:00
karenzshea
43bbe8f2ae add restricted penalty on NoTurn turns 2017-03-02 14:57:49 +00:00
karenzshea
b5c10b1fbf clamp speed value to js max 2017-02-22 16:13:01 +00:00
Daniel J. Hofmann
57d93fc5dc Updates TBB to latest stable version for 5.6 release 2017-02-20 13:55:42 +00:00
karenzshea
3aba2bc2d0 expose data about turning onto restricted roads to turn function 2017-02-20 13:55:19 +00:00
Daniel J. Hofmann
c42478f0ee Updates sol2 to v2.15.8, resolves #3733 2017-02-20 10:14:17 +00:00
Moritz Kobitzsch
ea583a77ff reduce verbosity of use-lane in combination with lane-anticipation 2017-02-15 21:57:58 +00:00
Kajari Ghosh
dd999e112e Update http.md
Clarify where optional rotary properties will be added
2017-02-15 21:56:30 +00:00
Daniel Patterson
69c54bef72 Allow routing on toll roads by default (#3712) 2017-02-14 20:02:15 -08:00
karenzshea
cfee0f1109 add unit test for annotations=true returning all annotations 2017-02-13 18:11:47 +00:00
karenzshea
c7ce758e1c parse parameters.annotations into AnnotationsType::All 2017-02-13 18:11:03 +00:00
Karen Shea
3ac4fb5933 add error logging for missing osrm file to library tests (#3704) 2017-02-13 17:22:42 +00:00
karenzshea
2afe5e971b use qi - parser to work with 0 speed file lines 2017-02-13 17:22:42 +00:00
karenzshea
519b744502 clang format 2017-02-13 17:22:42 +00:00
karenzshea
d3c2ac671f round speed to 1 decimal place 2017-02-13 17:22:42 +00:00
karenzshea
07a1a907f8 add unit test to check that speeds are equal to distance/duration 2017-02-13 17:22:42 +00:00
karenzshea
062cae82a0 return speed annotations 2017-02-13 17:22:42 +00:00
Quinn Chrzan
316c7781a3 Unit testing docs (#3698)
* Updating library-tests and associated documentation to be more informative

* Fixing heading markup for updated unit testing docs
2017-02-13 17:22:42 +00:00
Karen Shea
e11bcfece5 Update http.md 2017-02-13 17:22:42 +00:00
Moritz Kobitzsch
cb8dee3e60 comments 2017-02-13 17:22:42 +00:00
Moritz Kobitzsch
a1abe71d9f fix handling none-tags in presence of multiple turns within 2017-02-13 17:22:42 +00:00
Moritz Kobitzsch
d54c837e51 add failing test 2017-02-13 17:22:42 +00:00
Patrick Niklaus
106d17541d Fix side road penalties and add test 2017-02-13 17:22:42 +00:00
Michael Krasnyk
ad29b237e3 make annotations={true|false|(values)+} grammar 2017-02-13 17:22:42 +00:00
Patrick Niklaus
febefb4684 Enable 5.6 travis builds 2017-02-10 14:40:33 +00:00
46 changed files with 978 additions and 315 deletions

View File

@ -13,6 +13,7 @@ notifications:
branches: branches:
only: only:
- master - master
- "5.6"
cache: cache:
ccache: true ccache: true

View File

@ -1,3 +1,15 @@
# 5.6.2
- Changes from 5.6.0
- Bugfixes
- Fix incorrect forward datasources getter in facade
- Fix include `access=private` non-car roads in the car profile
# 5.6.1
- Changes from 5.6.0
- Bugfixes
- Fix #3754 restricted access roads not penalized if restriction begins non at an intersection
# 5.6.0 # 5.6.0
- Changes from 5.5 - Changes from 5.5
- Bugfixes - Bugfixes

View File

@ -32,7 +32,7 @@ if(ENABLE_MASON)
set(MASON_EXPAT_VERSION "2.2.0") set(MASON_EXPAT_VERSION "2.2.0")
set(MASON_LUA_VERSION "5.2.4") set(MASON_LUA_VERSION "5.2.4")
set(MASON_BZIP2_VERSION "1.0.6") set(MASON_BZIP2_VERSION "1.0.6")
set(MASON_TBB_VERSION "43_20150316") set(MASON_TBB_VERSION "2017_20161128")
message(STATUS "Enabling mason") message(STATUS "Enabling mason")

View File

@ -172,7 +172,7 @@ In addition to the [general options](#general-options) the following options are
|------------|---------------------------------------------|-------------------------------------------------------------------------------| |------------|---------------------------------------------|-------------------------------------------------------------------------------|
|alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* | |alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* |
|steps |`true`, `false` (default) |Return route steps for each route leg | |steps |`true`, `false` (default) |Return route steps for each route leg |
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. | |annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. | |continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. |
@ -275,7 +275,7 @@ In addition to the [general options](#general-options) the following options are
|------------|------------------------------------------------|------------------------------------------------------------------------------------------| |------------|------------------------------------------------|------------------------------------------------------------------------------------------|
|steps |`true`, `false` (default) |Return route steps for each route | |steps |`true`, `false` (default) |Return route steps for each route |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. | |annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamps for the input locations in seconds since UNIX epoch. Timestamps need to be monotonically increasing. | |timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamps for the input locations in seconds since UNIX epoch. Timestamps need to be monotonically increasing. |
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.| |radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
@ -327,7 +327,7 @@ In addition to the [general options](#general-options) the following options are
|source |`any` (default), `first` |Return route starts at `any` or `first` coordinate | |source |`any` (default), `first` |Return route starts at `any` or `first` coordinate |
|destination |`any` (default), `last` |Return route ends at `any` or `last` coordinate | |destination |`any` (default), `last` |Return route ends at `any` or `last` coordinate |
|steps |`true`, `false` (default) |Return route instructions for each trip | |steps |`true`, `false` (default) |Return route instructions for each trip |
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. | |annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
@ -518,7 +518,8 @@ With `steps=false` and `annotations=true`:
"distance": [5,5,10,5,5], "distance": [5,5,10,5,5],
"duration": [15,15,40,15,15], "duration": [15,15,40,15,15],
"datasources": [1,0,0,0,1], "datasources": [1,0,0,0,1],
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802] "nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
"speed": [0.3, 0.3, 0.3, 0.3, 0.3]
} }
} }
``` ```
@ -534,6 +535,7 @@ Annotation of the whole route leg with fine-grained information about each segme
- `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract` - `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract`
- `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates - `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates
- `weight`: The weights between each pair of coordinates - `weight`: The weights between each pair of coordinates
- `speed`: Convenience field, calculation of `distance / duration` rounded to one decimal place
#### Example #### Example
@ -574,6 +576,8 @@ step.
- `mode`: A string signifying the mode of transportation. - `mode`: A string signifying the mode of transportation.
- `maneuver`: A `StepManeuver` object representing the maneuver. - `maneuver`: A `StepManeuver` object representing the maneuver.
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver - `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
- `rotary_name`: The name for the rotary. Optionally included, if the step is a rotary and a rotary name is available.
- `rotary_pronunciation`: The pronunciation hint of the rotary name. Optionally included, if the step is a rotary and a rotary pronunciation is available.
#### Example #### Example
@ -628,7 +632,7 @@ step.
- `bearing_after`: The clockwise angle from true north to the - `bearing_after`: The clockwise angle from true north to the
direction of travel immediately after the maneuver. Range 0-359. direction of travel immediately after the maneuver. Range 0-359.
- `type` A string indicating the type of maneuver. **new identifiers might be introduced without API change** - `type` A string indicating the type of maneuver. **new identifiers might be introduced without API change**
Types unknown to the client should be handled like the `turn` type, the existance of correct `modifier` values is guranteed. Types unknown to the client should be handled like the `turn` type, the existence of correct `modifier` values is guranteed.
| `type` | Description | | `type` | Description |
|------------------|--------------------------------------------------------------| |------------------|--------------------------------------------------------------|
@ -644,8 +648,8 @@ step.
| `end of road` | road ends in a T intersection turn in direction of `modifier`| | `end of road` | road ends in a T intersection turn in direction of `modifier`|
| `use lane` | going straight on a specific lane | | `use lane` | going straight on a specific lane |
| `continue` | Turn in direction of `modifier` to stay on the same road | | `continue` | Turn in direction of `modifier` to stay on the same road |
| `roundabout` | traverse roundabout, has additional property `exit` with NR if the roundabout is left. `the modifier specifies the direction of entering the roundabout` | | `roundabout` | traverse roundabout, has additional property `exit` with NR if the roundabout is left. The modifier specifies the direction of entering the roundabout. |
| `rotary` | a traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name/rotary_pronunciation` in addition to the `exit` parameter. | | `rotary` | a traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name` and/or `rotary_pronunciation` parameters (located in the RouteStep object) in addition to the `exit` parameter (located on the StepManeuver object). |
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. | | `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode. If the road takes a turn itself, the `modifier` describes the direction | | `notification` | not an actual turn but a change in the driving conditions. For example the travel mode. If the road takes a turn itself, the `modifier` describes the direction |

View File

@ -28,6 +28,29 @@ This dataset is a small extract and may not even contain all tags or edge cases.
Furthermore this dataset is not in sync with what you see in up-to-date OSM maps or on the demo server. Furthermore this dataset is not in sync with what you see in up-to-date OSM maps or on the demo server.
See the library tests for how to add new dataset dependent tests. See the library tests for how to add new dataset dependent tests.
To prepare the test data simply `cd test/data/` and then run `make`.
### Running Tests
To build the unit tests:
```
cd build
cmake ..
make tests
```
You should see the compiled binaries in `build/unit_tests`, you can then run each suite individually:
```
./engine-tests
```
For `library-tests` you will need to provide a path to the test data:
```
./library-tests ../../test/data/monaco.osrm
```
## Cucumber ## Cucumber

View File

@ -119,12 +119,13 @@ Feature: Car - Restricted access
| permissive | x | | permissive | x |
| designated | x | | designated | x |
| no | | | no | |
| private | | | private | x |
| agricultural | | | agricultural | |
| forestry | | | forestry | |
| psv | | | psv | |
| delivery | | | delivery | x |
| some_tag | x | | some_tag | x |
| destination | x |
Scenario: Car - Access tags on nodes Scenario: Car - Access tags on nodes
@ -134,11 +135,11 @@ Feature: Car - Restricted access
| permissive | x | | permissive | x |
| designated | x | | designated | x |
| no | | | no | |
| private | | | private | x |
| agricultural | | | agricultural | |
| forestry | | | forestry | |
| psv | | | psv | |
| delivery | | | delivery | x |
| some_tag | x | | some_tag | x |
Scenario: Car - Access tags on both node and way Scenario: Car - Access tags on both node and way
@ -156,15 +157,15 @@ Feature: Car - Restricted access
Scenario: Car - Access combinations Scenario: Car - Access combinations
Then routability should be Then routability should be
| highway | accesss | vehicle | motor_vehicle | motorcar | bothw | | highway | access | vehicle | motor_vehicle | motorcar | forw | backw | # |
| runway | private | | | permissive | x | | runway | private | | | permissive | x | x | |
| primary | forestry | | yes | | x | | primary | forestry | | yes | | x | x | |
| cycleway | | | designated | | x | | cycleway | | | designated | | x | x | |
| residential | | yes | no | | | | residential | | yes | no | | | | |
| motorway | yes | permissive | | private | | | motorway | yes | permissive | | private | x | | implied oneway |
| trunk | agricultural | designated | permissive | no | | | trunk | agricultural | designated | permissive | no | | | |
| pedestrian | | | | | | | pedestrian | | | | | | | |
| pedestrian | | | | destination | x | | pedestrian | | | | destination | | | temporary disabled #3773 |
Scenario: Car - Ignore access tags for other modes Scenario: Car - Ignore access tags for other modes
Then routability should be Then routability should be
@ -182,7 +183,7 @@ Feature: Car - Restricted access
Scenario: Car - designated HOV ways are rated low Scenario: Car - designated HOV ways are rated low
Then routability should be Then routability should be
| highway | hov | bothw | forw_rate | backw_rate | | highway | hov | bothw | forw_rate | backw_rate |
| primary | designated | x | 2 | 2 | | primary | designated | x | 18 | 18 |
| primary | yes | x | 18 | 18 | | primary | yes | x | 18 | 18 |
| primary | no | x | 18 | 18 | | primary | no | x | 18 | 18 |
@ -193,28 +194,29 @@ Feature: Car - Restricted access
Scenario: Car - I-66 use HOV-only roads with heavy penalty Scenario: Car - I-66 use HOV-only roads with heavy penalty
Then routability should be Then routability should be
| highway | hov | hov:lanes | lanes | access | oneway | forw | backw | forw_rate | | highway | hov | hov:lanes | lanes | access | oneway | forw | backw | forw_rate |
| motorway | designated | designated\|designated\|designated | 3 | hov | yes | x | | 3 | | motorway | designated | designated\|designated\|designated | 3 | hov | yes | x | | 25 |
| motorway | lane | | 3 | designated | yes | x | | 25 | | motorway | lane | | 3 | designated | yes | x | | 25 |
@hov @hov
Scenario: Car - a way with all lanes HOV-designated is highly penalized by default (similar to hov=designated) Scenario: Car - a way with all lanes HOV-designated is highly penalized by default (similar to hov=designated)
Then routability should be Then routability should be
| highway | hov:lanes:forward | hov:lanes:backward | hov:lanes | oneway | forw | backw | forw_rate | backw_rate | | highway | hov:lanes:forward | hov:lanes:backward | hov:lanes | oneway | forw | backw | forw_rate | backw_rate |
| primary | designated | designated | | | x | x | 2 | 2 | | primary | designated | designated | | | x | x | 18 | 18 |
| primary | | designated | | | x | x | 18 | 2 | # This test is flaky because non-deterministic turn generation sometimes emits a NoTurn here that is marked as restricted. #3769
| primary | designated | | | | x | x | 2 | 18 | #| primary | | designated | | | x | x | 18 | 18 |
| primary | designated\|designated | designated\|designated | | | x | x | 2 | 2 | #| primary | designated | | | | x | x | 18 | 18 |
| primary | designated\|designated | designated\|designated | | | x | x | 18 | 18 |
| primary | designated\|no | designated\|no | | | x | x | 18 | 18 | | primary | designated\|no | designated\|no | | | x | x | 18 | 18 |
| primary | yes\|no | yes\|no | | | x | x | 18 | 18 | | primary | yes\|no | yes\|no | | | x | x | 18 | 18 |
| primary | | | | | x | x | 18 | 18 | | primary | | | | | x | x | 18 | 18 |
| primary | designated | | | -1 | | x | | 18 | | primary | designated | | | -1 | | x | | 18 |
| primary | | designated | | -1 | | x | | 2 | | primary | | designated | | -1 | | x | | 18 |
| primary | | | designated | yes | x | | 2 | | | primary | | | designated | yes | x | | 18 | |
| primary | | | designated | -1 | | x | | 2 | | primary | | | designated | -1 | | x | | 18 |
| primary | | | designated\| | yes | x | | 18 | | | primary | | | designated\| | yes | x | | 18 | |
| primary | | | designated\| | -1 | | x | | 18 | | primary | | | designated\| | -1 | | x | | 18 |
| primary | | | designated\|designated | yes | x | | 2 | | | primary | | | designated\|designated | yes | x | | 18 | |
| primary | | | designated\|designated | -1 | | x | | 2 | | primary | | | designated\|designated | -1 | | x | | 18 |
| primary | | | designated\|yes | yes | x | | 18 | | | primary | | | designated\|yes | yes | x | | 18 | |
| primary | | | designated\|no | -1 | | x | | 18 | | primary | | | designated\|no | -1 | | x | | 18 |
@ -224,12 +226,10 @@ Feature: Car - Restricted access
| primary | no | x | | primary | no | x |
| primary | snowmobile | x | | primary | snowmobile | x |
# To test this we need issue #2781 Scenario: Car - toll=yes ways are enabled by default
@todo
Scenario: Car - only toll=yes ways are ignored by default
Then routability should be Then routability should be
| highway | toll | bothw | | highway | toll | bothw |
| primary | yes | | | primary | yes | x |
Scenario: Car - directional access tags Scenario: Car - directional access tags
Then routability should be Then routability should be
@ -252,7 +252,7 @@ Feature: Car - Restricted access
| gate | yes | x | | gate | yes | x |
| gate | permissive | x | | gate | permissive | x |
| gate | designated | x | | gate | designated | x |
| gate | private | | | gate | private | x |
| gate | garbagetag | x | | gate | garbagetag | x |
Scenario: Car - a way with conditional access Scenario: Car - a way with conditional access
@ -262,9 +262,11 @@ Feature: Car - Restricted access
Scenario: Car - a way with a list of tags Scenario: Car - a way with a list of tags
Then routability should be Then routability should be
| highway | motor_vehicle | motor_vehicle:forward | motor_vehicle:backward | forw | backw | | highway | motor_vehicle | motor_vehicle:forward | motor_vehicle:backward | forw | backw | # |
| footway | | | destination | | x | | primary | | no | destination | | x | |
| track | destination;agricultural | destination | | x | x | | primary | destination;agricultural | destination | | x | x | |
| footway | | | destination | | | temporary #3373 |
| track | destination;agricultural | destination | | | x | temporary #3373 |
Scenario: Car - Don't route over steps even if marked as accessible Scenario: Car - Don't route over steps even if marked as accessible
Then routability should be Then routability should be
@ -280,3 +282,24 @@ Feature: Car - Restricted access
| steps | permissive | | | steps | permissive | |
| footway | permissive | x | | footway | permissive | x |
| garbagetag | permissive | x | | garbagetag | permissive | x |
Scenario: Car - Access private blacklist
Then routability should be
| highway | access | bothw |
| footway | yes | x |
| pedestrian | private | |
| footway | private | |
| service | private | |
| cycleway | private | |
| track | private | |
Scenario: Car - Access blacklist
Then routability should be
| highway | access | bothw |
| primary | | x |
| primary | customer | |
| primary | emergency | |
| primary | forestry | |
| primary | agricultural | |
| primary | psv | |
| primary | no | |

View File

@ -29,14 +29,14 @@ Feature: Car - Barriers
| gate | permissive | x | | gate | permissive | x |
| gate | designated | x | | gate | designated | x |
| gate | no | | | gate | no | |
| gate | private | | | gate | private | x |
| gate | agricultural | | | gate | agricultural | |
| wall | | | | wall | | |
| wall | yes | x | | wall | yes | x |
| wall | permissive | x | | wall | permissive | x |
| wall | designated | x | | wall | designated | x |
| wall | no | | | wall | no | |
| wall | private | | | wall | private | x |
| wall | agricultural | | | wall | agricultural | |
Scenario: Car - Rising bollard exception for barriers Scenario: Car - Rising bollard exception for barriers

View File

@ -1,4 +1,4 @@
@routing @car @destination @todo @routing @car @destination
Feature: Car - Destination only, no passing through Feature: Car - Destination only, no passing through
Background: Background:
@ -81,3 +81,53 @@ Feature: Car - Destination only, no passing through
| e | a | de,cd,bc,ab,ab | | e | a | de,cd,bc,ab,ab |
| b | d | bc,cd,cd | | b | d | bc,cd,cd |
| d | b | cd,bc,bc | | d | b | cd,bc,bc |
Scenario: Car - Routing around a way that becomes destination only
Given the node map
"""
b
\
|
e++d++++++c--i
| \
\ h--a
\ |
\___________g
"""
And the ways
| nodes | access | oneway |
| ah | | no |
| ihg | | no |
| eg | | no |
| icde | | no |
| cde | destination | no |
| eb | | no |
When I route I should get
| from | to | route | # |
| i | b | ihg,eg,eb,eb | # goes around access=destination, though restricted way starts at two node intersection |
| b | d | eb,cde,cde | # ends in restricted way correctly |
| b | i | eb,eg,ihg,ihg | # goes around restricted way correctly |
Scenario: Car - Routing around a way that becomes destination only
Given the node map
"""
a---c---b
+ \
+ |
d |
\___e
"""
And the ways
| nodes | access | oneway |
| acbe | | no |
| cd | destination | no |
| de | | no |
When I route I should get
| from | to | route |
| e | a | acbe,acbe |
| d | a | de,acbe,acbe |
| c | d | cd,cd |

36
features/car/hov.feature Normal file
View File

@ -0,0 +1,36 @@
@routing @car @hov
Feature: Car - Handle driving
Background:
Given the profile "car"
And a grid size of 100 meters
Scenario: Car - Avoid hov when not on hov
Given the node map
"""
b=========c========================e====j
~ ~ ~
a ~ f----m
| i |
| | ----------------l
| | /
g_______________h______k_____n
"""
And the ways
| nodes | highway | hov |
| ab | motorway_link | |
| bcej | motorway | designated |
| ag | primary | |
| ghkn | primary | |
| ih | primary | |
| kl | secondary | |
| lf | secondary | |
| ci | motorway_link | |
| ef | motorway_link | |
| fm | secondary | |
When I route I should get
| from | to | route |
| a | m | ag,ghkn,kl,lf,fm,fm |
| c | m | bcej,ef,fm,fm |

View File

@ -45,3 +45,9 @@ Feature: Car - speeds
| primary | 60 | 47 km/h | 47 km/h | | primary | 60 | 47 km/h | 47 km/h |
| primary | 60 | 47 km/h | 47 km/h | | primary | 60 | 47 km/h | 47 km/h |
| primary | 60 | 47 km/h | 47 km/h | | primary | 60 | 47 km/h | 47 km/h |
Scenario: Car - Side road penalties
Then routability should be
| highway | side_road | forw | backw | forw_rate | backw_rate |
| primary | yes | 64 km/h | 64 km/h | 14 | 14 |

View File

@ -40,13 +40,13 @@ Feature: Car - Surfaces
| highway | access | tracktype | smoothness | surface | forw | backw | | highway | access | tracktype | smoothness | surface | forw | backw |
| motorway | | | | | x | | | motorway | | | | | x | |
| motorway | no | grade1 | excellent | asphalt | | | | motorway | no | grade1 | excellent | asphalt | | |
| motorway | private | grade1 | excellent | asphalt | | | | motorway | private | grade1 | excellent | asphalt | x | |
| motorway | agricultural | grade1 | excellent | asphalt | | | | motorway | agricultural | grade1 | excellent | asphalt | | |
| motorway | forestry | grade1 | excellent | asphalt | | | | motorway | forestry | grade1 | excellent | asphalt | | |
| motorway | emergency | grade1 | excellent | asphalt | | | | motorway | emergency | grade1 | excellent | asphalt | | |
| primary | | | | | x | x | | primary | | | | | x | x |
| primary | private | grade1 | excellent | asphalt | x | x |
| primary | no | grade1 | excellent | asphalt | | | | primary | no | grade1 | excellent | asphalt | | |
| primary | private | grade1 | excellent | asphalt | | |
| primary | agricultural | grade1 | excellent | asphalt | | | | primary | agricultural | grade1 | excellent | asphalt | | |
| primary | forestry | grade1 | excellent | asphalt | | | | primary | forestry | grade1 | excellent | asphalt | | |
| primary | emergency | grade1 | excellent | asphalt | | | | primary | emergency | grade1 | excellent | asphalt | | |

View File

@ -818,3 +818,37 @@ Feature: Turn Lane Guidance
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,turn right,arrive | ,straight:false straight:false right:false right:true,left:false right:true, | | a,e | MySt,MySt,MySt,MySt | depart,continue right,turn right,arrive | ,straight:false straight:false right:false right:true,left:false right:true, |
@anticipate
Scenario: Don't Overdo It
Given the node map
"""
q r s t u v
| | | | | |
a - - - - - - - - - - b - - - - - - - - - - c - - - - - - - - - - d - - - - - - - - - - e - - - - - - - - - - f - - - - - - - - - - g - h - i
| | | | | | |
p o n m l k j
"""
And the ways
| nodes | name | turn:lanes:forward | oneway |
| ab | road | left\|\|\| | yes |
| bc | road | left\|\|\| | yes |
| cd | road | left\|\|\| | yes |
| de | road | left\|\|\| | yes |
| ef | road | left\|\|\| | yes |
| fg | road | left\|\|\| | yes |
| gh | road | \|\|right | yes |
| hi | road | | yes |
| qbp | 1st | | no |
| rco | 2nd | | no |
| sdn | 3rd | | no |
| tem | 4th | | no |
| ufl | 5th | | no |
| vgk | 6th | | no |
| hj | 7th | | no |
When I route I should get
| waypoints | route | turns | locations | lanes |
| a,i | road,road,road | depart,use lane straight,arrive | a,g,i | ,left:false none:true none:true none:false, |
| a,j | road,road,7th,7th | depart,use lane straight,turn right,arrive | a,f,h,j | ,left:false none:false none:false none:true,none:false none:false right:true, |

View File

@ -1158,3 +1158,45 @@ Feature: Turn Lane Guidance
When I route I should get When I route I should get
| waypoints | bearings | route | turns | | waypoints | bearings | route | turns |
| 1,a | 90,2 180,180 | | | | 1,a | 90,2 180,180 | | |
@3379
Scenario: Don't Turn through potential through lanes
Given the node map
"""
d
|
a - - - - b - - - - - c
|
e
"""
And the ways
| nodes | name | oneway | turn:lanes:forward |
| ab | road | yes | left\|none\|none |
| bc | road | yes | |
| ebd | cross | no | |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | road,cross,cross | depart,turn right,arrive | ,left:false none:false none:true, |
| a,c | road,road | depart,arrive | , |
@3379
Scenario: Don't Turn through potential through lanes
Given the node map
"""
d
|
a - - - - b - - - - - c
|
e
"""
And the ways
| nodes | name | oneway | turn:lanes:forward |
| ab | road | yes | none\|none\|right |
| bc | road | yes | |
| ebd | cross | no | |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,cross,cross | depart,turn left,arrive | ,none:true none:false right:false, |
| a,c | road,road | depart,arrive | , |

View File

@ -28,3 +28,11 @@ Feature: osrm-contract command line options: datasources
When I run "osrm-contract --segment-speed-file {speeds_file} {processed_file}" When I run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
Then datasource names should contain "lua profile,27_osrmcontract_passing_base_file_speeds" Then datasource names should contain "lua profile,27_osrmcontract_passing_base_file_speeds"
And it should exit successfully And it should exit successfully
Scenario: osrm-contract - Passing base file
Given the speed file
"""
"""
And the data has been extracted
When I run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
Then it should exit successfully

View File

@ -28,13 +28,14 @@ module.exports = function () {
directions.filter(d => headers.has(d + '_rate')).forEach((direction) => { directions.filter(d => headers.has(d + '_rate')).forEach((direction) => {
var rate = direction + '_rate'; var rate = direction + '_rate';
var want = row[rate]; var want = row[rate];
switch (true) { switch (true) {
case '' === want: case '' === want:
outputRow[rate] = result[direction].status ? outputRow[rate] = result[direction].status ?
result[direction].status.toString() : ''; result[direction].status.toString() : '';
break; break;
case /^\d+$/.test(want): case /^\d+$/.test(want):
if (result[direction].rate && !isNaN(result[direction].rate)) { if (result[direction].rate !== undefined && !isNaN(result[direction].rate)) {
outputRow[rate] = result[direction].rate.toString(); outputRow[rate] = result[direction].rate.toString();
} else { } else {
outputRow[rate] = ''; outputRow[rate] = '';

View File

@ -147,7 +147,7 @@ module.exports = function () {
// if header matches 'a:*', parse out the values for * // if header matches 'a:*', parse out the values for *
// and return in that header // and return in that header
headers.forEach((k) => { headers.forEach((k) => {
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight']; let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
if (k.match(/^a:/)) { if (k.match(/^a:/)) {
let a_type = k.slice(2); let a_type = k.slice(2);
if (whitelist.indexOf(a_type) == -1) if (whitelist.indexOf(a_type) == -1)

View File

@ -36,15 +36,18 @@ Feature: Traffic - speeds
1,4,27 1,4,27
4,1,27 4,1,27
""" """
And I route I should get And the query options
| from | to | route | speed | weights | | annotations | datasources |
| a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 |
| a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 | When I route I should get
| b | c | bc,bc | 27 km/h | 741.5,0 | | from | to | route | speed | weights | a:datasources |
| a | d | ad,ad | 27 km/h | 1275.7,0 | | a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 | 1:0:0:0 |
| d | c | dc,dc | 36 km/h | 956.8,0 | | a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 | 1:0 |
| g | b | fb,fb | 36 km/h | 164.7,0 | | b | c | bc,bc | 27 km/h | 741.5,0 | 1:0 |
| a | g | ad,df,fb,fb | 30 km/h | 1275.7,487.5,304.7,0 | | a | d | ad,ad | 27 km/h | 1275.7,0 | 1:0 |
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 |
| a | g | ad,df,fb,fb | 30 km/h | 1275.7,487.5,304.7,0 | 1:0:0 |
Scenario: Weighting based on speed file weights, ETA based on file durations Scenario: Weighting based on speed file weights, ETA based on file durations
@ -58,15 +61,18 @@ Feature: Traffic - speeds
1,4,27,1275.7 1,4,27,1275.7
4,1,27,1275.7 4,1,27,1275.7
""" """
And I route I should get And the query options
| from | to | route | speed | weights | | annotations | datasources |
| a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 |
| a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 | When I route I should get
| b | c | bc,bc | 27 km/h | 741.5,0 | | from | to | route | speed | weights | a:datasources |
| a | d | ad,ad | 27 km/h | 1275.7,0 | | a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 | 1:0:0:0 |
| d | c | dc,dc | 36 km/h | 956.8,0 | | a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 | 1:0 |
| g | b | ab,ab | 1 km/h | 10010.4,0 | | b | c | bc,bc | 27 km/h | 741.5,0 | 1:0 |
| a | g | ab,ab | 1 km/h | 10010.3,0 | | a | d | ad,ad | 27 km/h | 1275.7,0 | 1:0 |
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
| g | b | ab,ab | 1 km/h | 10010.4,0 | 1:0 |
| a | g | ab,ab | 1 km/h | 10010.3,0 | 1 |
Scenario: Weighting based on speed file weights, ETA based on file durations Scenario: Weighting based on speed file weights, ETA based on file durations
@ -87,16 +93,19 @@ Feature: Traffic - speeds
1,4,1,34445.12 1,4,1,34445.12
4,1,1,34445.3 4,1,1,34445.3
""" """
And I route I should get And the query options
| from | to | route | speed | weights | | annotations | datasources |
| a | b | ab,ab | 1 km/h | 20020.789,0 |
| a | c | ab,bc,bc | 2 km/h | 20020.789,741.568,0 | When I route I should get
| b | c | bc,bc | 27 km/h | 741.568,0 | | from | to | route | speed | weights | a:datasources |
| a | d | ab,eb,de,de | 2 km/h | 20020.789,378.169,400.415,0 | | a | b | ab,ab | 1 km/h | 20020.789,0 | 1:0 |
| d | c | dc,dc | 36 km/h | 956.805,0 | | a | c | ab,bc,bc | 2 km/h | 20020.789,741.568,0 | 1:1:0 |
| g | b | ab,ab | 1 km/h | 10010.392,0 | | b | c | bc,bc | 27 km/h | 741.568,0 | 1:0 |
| a | g | ab,ab | 1 km/h | 10010.397,0 | | a | d | ab,eb,de,de | 2 km/h | 20020.789,378.169,400.415,0 | 1:0:0 |
| g | a | ab,ab | 1 km/h | 10010.064,0 | | d | c | dc,dc | 36 km/h | 956.805,0 | 0 |
| g | b | ab,ab | 1 km/h | 10010.392,0 | 1:0 |
| a | g | ab,ab | 1 km/h | 10010.397,0 | 1 |
| g | a | ab,ab | 1 km/h | 10010.064,0 | 1:1 |
Scenario: Speeds that isolate a single node (a) Scenario: Speeds that isolate a single node (a)
@ -113,15 +122,18 @@ Feature: Traffic - speeds
1,4,0 1,4,0
4,1,0 4,1,0
""" """
And I route I should get And the query options
| from | to | route | speed | weights | | annotations | true |
| a | b | fb,fb | 36 km/h | 329.4,0 |
| a | c | fb,bc,bc | 30 km/h | 329.4,741.5,0 | When I route I should get
| b | c | bc,bc | 27 km/h | 741.5,0 | | from | to | route | speed | weights | a:datasources |
| a | d | fb,df,df | 36 km/h | 140,487.5,0 | | a | b | fb,fb | 36 km/h | 329.4,0 | 0 |
| d | c | dc,dc | 36 km/h | 956.8,0 | | a | c | fb,bc,bc | 30 km/h | 329.4,741.5,0 | 0:1:0 |
| g | b | fb,fb | 36 km/h | 164.7,0 | | b | c | bc,bc | 27 km/h | 741.5,0 | 1:0 |
| a | g | fb,fb | 36 km/h | 164.7,0 | | a | d | fb,df,df | 36 km/h | 140,487.5,0 | 0:0:0 |
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 |
| a | g | fb,fb | 36 km/h | 164.7,0 | 0 |
Scenario: Verify that negative values cause an error, they're not valid at all Scenario: Verify that negative values cause an error, they're not valid at all

View File

@ -39,7 +39,7 @@ Feature: Weight tests
# FIXME include/engine/guidance/assemble_geometry.hpp:95 # FIXME include/engine/guidance/assemble_geometry.hpp:95
Scenario: Start and target on the same and adjacent edge Scenario: Start and target on the same and adjacent edge
Given the query options Given the query options
| annotations | distance,duration,weight,nodes | | annotations | distance,duration,weight,nodes,speed |
Given the node map Given the node map
""" """
@ -53,11 +53,11 @@ Feature: Weight tests
| abc | | abc |
When I route I should get When I route I should get
| waypoints | route | distances | weights | times | a:distance | a:duration | a:weight | | waypoints | route | distances | weights | times | a:distance | a:duration | a:weight | a:speed |
| s,t | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3 | 3 | | s,t | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3 | 3 | 6.7 |
| t,s | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3.1 | 3.1 | | t,s | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3.1 | 3.1 | 6.5 |
| s,e | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 30.026527:10.008842 | 3.1:1 | 3.1:1 | | s,e | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 30.026527:10.008842 | 3.1:1 | 3.1:1 | 9.7:10 |
| e,s | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 10.008842:30.026527 | 1:3.1 | 1:3.1 | | e,s | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 10.008842:30.026527 | 1:3.1 | 1:3.1 | 10:9.7 |
Scenario: Step weights -- way_function: fail if no weight or weight_per_meter property Scenario: Step weights -- way_function: fail if no weight or weight_per_meter property

View File

@ -19,6 +19,7 @@
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include "util/integer_range.hpp" #include "util/integer_range.hpp"
#include "util/json_util.hpp"
#include <iterator> #include <iterator>
#include <vector> #include <vector>
@ -228,42 +229,60 @@ class RouteAPI : public BaseAPI
std::vector<util::json::Object> annotations; std::vector<util::json::Object> annotations;
if (parameters.annotations_type != RouteParameters::AnnotationsType::None) // To maintain support for uses of the old default constructors, we check
// if annotations property was set manually after default construction
auto requested_annotations = parameters.annotations_type;
if ((parameters.annotations == true) &&
(parameters.annotations_type == RouteParameters::AnnotationsType::None))
{
requested_annotations = RouteParameters::AnnotationsType::All;
}
if (requested_annotations != RouteParameters::AnnotationsType::None)
{ {
for (const auto idx : util::irange<std::size_t>(0UL, leg_geometries.size())) for (const auto idx : util::irange<std::size_t>(0UL, leg_geometries.size()))
{ {
auto &leg_geometry = leg_geometries[idx]; auto &leg_geometry = leg_geometries[idx];
util::json::Object annotation; util::json::Object annotation;
if (parameters.annotations_type & RouteParameters::AnnotationsType::Duration) // AnnotationsType uses bit flags, & operator checks if a property is set
if (parameters.annotations_type & RouteParameters::AnnotationsType::Speed)
{
annotation.values["speed"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
auto val = std::round(anno.distance / anno.duration * 10.) / 10.;
return util::json::clamp_float(val);
});
}
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
{ {
annotation.values["duration"] = GetAnnotations( annotation.values["duration"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) { leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.duration; return anno.duration;
}); });
} }
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
if (parameters.annotations_type & RouteParameters::AnnotationsType::Distance)
{ {
annotation.values["distance"] = GetAnnotations( annotation.values["distance"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) { leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.distance; return anno.distance;
}); });
} }
if (parameters.annotations_type & RouteParameters::AnnotationsType::Weight) if (requested_annotations & RouteParameters::AnnotationsType::Weight)
{ {
annotation.values["weight"] = GetAnnotations( annotation.values["weight"] = GetAnnotations(
leg_geometry, leg_geometry,
[](const guidance::LegGeometry::Annotation &anno) { return anno.weight; }); [](const guidance::LegGeometry::Annotation &anno) { return anno.weight; });
} }
if (parameters.annotations_type & RouteParameters::AnnotationsType::Datasources) if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
{ {
annotation.values["datasources"] = GetAnnotations( annotation.values["datasources"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) { leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.datasource; return anno.datasource;
}); });
} }
if (parameters.annotations_type & RouteParameters::AnnotationsType::Nodes) if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
{ {
util::json::Array nodes; util::json::Array nodes;
nodes.values.reserve(leg_geometry.osm_node_ids.size()); nodes.values.reserve(leg_geometry.osm_node_ids.size());

View File

@ -75,7 +75,8 @@ struct RouteParameters : public BaseParameters
Distance = 0x04, Distance = 0x04,
Weight = 0x08, Weight = 0x08,
Datasources = 0x10, Datasources = 0x10,
All = Duration | Nodes | Distance | Weight | Datasources Speed = 0x20,
All = Duration | Nodes | Distance | Weight | Datasources | Speed
}; };
RouteParameters() = default; RouteParameters() = default;

View File

@ -865,7 +865,6 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
} }
else else
{ {
result_datasources.resize(end - begin);
std::copy(m_datasource_list.begin() + begin, std::copy(m_datasource_list.begin() + begin,
m_datasource_list.begin() + end, m_datasource_list.begin() + end,
std::back_inserter(result_datasources)); std::back_inserter(result_datasources));

View File

@ -20,7 +20,7 @@ namespace guidance
// as separate maneuvers. // as separate maneuvers.
OSRM_ATTR_WARN_UNUSED OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps, std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
const double min_duration_needed_for_lane_change = 15); const double min_duration_needed_for_lane_change = 10);
} // namespace guidance } // namespace guidance
} // namespace engine } // namespace engine

View File

@ -28,6 +28,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps);
// A check whether two instructions can be treated as one. This is only the case for very short // 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. Lookahead of one step. // maneuvers that can, in some form, be seen as one. Lookahead of one step.
// This is only a pre-check and does not necessarily allow collapsing turns!!!
bool collapsable(const RouteStep &step, const RouteStep &next); bool collapsable(const RouteStep &step, const RouteStep &next);
// trim initial/final segment of very short length. // trim initial/final segment of very short length.

View File

@ -17,7 +17,8 @@ struct ExtractionTurn
ExtractionTurn(const guidance::ConnectedRoad &turn, bool has_traffic_light) ExtractionTurn(const guidance::ConnectedRoad &turn, bool has_traffic_light)
: angle(180. - turn.angle), turn_type(turn.instruction.type), : angle(180. - turn.angle), turn_type(turn.instruction.type),
direction_modifier(turn.instruction.direction_modifier), direction_modifier(turn.instruction.direction_modifier),
has_traffic_light(has_traffic_light), weight(0.), duration(0.) has_traffic_light(has_traffic_light), weight(0.), duration(0.), source_restricted(false),
target_restricted(false)
{ {
} }
@ -27,6 +28,8 @@ struct ExtractionTurn
const bool has_traffic_light; const bool has_traffic_light;
double weight; double weight;
double duration; double duration;
bool source_restricted;
bool target_restricted;
}; };
} }
} }

View File

@ -58,6 +58,8 @@ struct ExtractionWay
turn_lanes_forward.clear(); turn_lanes_forward.clear();
turn_lanes_backward.clear(); turn_lanes_backward.clear();
road_classification = guidance::RoadClassification(); road_classification = guidance::RoadClassification();
backward_restricted = false;
forward_restricted = false;
} }
// These accessors exists because it's not possible to take the address of a bitfield, // These accessors exists because it's not possible to take the address of a bitfield,
@ -106,6 +108,8 @@ struct ExtractionWay
bool roundabout; bool roundabout;
bool circular; bool circular;
bool is_startpoint; bool is_startpoint;
bool backward_restricted;
bool forward_restricted;
TravelMode forward_travel_mode : 4; TravelMode forward_travel_mode : 4;
TravelMode backward_travel_mode : 4; TravelMode backward_travel_mode : 4;
guidance::RoadClassification road_classification; guidance::RoadClassification road_classification;

View File

@ -70,8 +70,9 @@ struct InternalExtractorEdge
false, // roundabout false, // roundabout
false, // circular false, // circular
true, // can be startpoint true, // can be startpoint
false, // local access only
false, // split edge
TRAVEL_MODE_INACCESSIBLE, TRAVEL_MODE_INACCESSIBLE,
false,
guidance::TurnLaneType::empty, guidance::TurnLaneType::empty,
guidance::RoadClassification()), guidance::RoadClassification()),
weight_data(), duration_data() weight_data(), duration_data()
@ -88,8 +89,9 @@ struct InternalExtractorEdge
bool roundabout, bool roundabout,
bool circular, bool circular,
bool startpoint, bool startpoint,
TravelMode travel_mode, bool restricted,
bool is_split, bool is_split,
TravelMode travel_mode,
LaneDescriptionID lane_description, LaneDescriptionID lane_description,
guidance::RoadClassification road_classification, guidance::RoadClassification road_classification,
util::Coordinate source_coordinate) util::Coordinate source_coordinate)
@ -103,8 +105,9 @@ struct InternalExtractorEdge
roundabout, roundabout,
circular, circular,
startpoint, startpoint,
travel_mode, restricted,
is_split, is_split,
travel_mode,
lane_description, lane_description,
std::move(road_classification)), std::move(road_classification)),
weight_data(std::move(weight_data)), duration_data(std::move(duration_data)), weight_data(std::move(weight_data)), duration_data(std::move(duration_data)),
@ -134,8 +137,9 @@ struct InternalExtractorEdge
false, // roundabout false, // roundabout
false, // circular false, // circular
true, // can be startpoint true, // can be startpoint
false, // local access only
false, // split edge
TRAVEL_MODE_INACCESSIBLE, TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_DESCRIPTIONID, INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassification(), guidance::RoadClassification(),
util::Coordinate()); util::Coordinate());
@ -152,8 +156,9 @@ struct InternalExtractorEdge
false, // roundabout false, // roundabout
false, // circular false, // circular
true, // can be startpoint true, // can be startpoint
false, // local access only
false, // split edge
TRAVEL_MODE_INACCESSIBLE, TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_DESCRIPTIONID, INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassification(), guidance::RoadClassification(),
util::Coordinate()); util::Coordinate());

View File

@ -25,27 +25,29 @@ struct NodeBasedEdge
bool roundabout, bool roundabout,
bool circular, bool circular,
bool startpoint, bool startpoint,
TravelMode travel_mode, bool restricted,
bool is_split, bool is_split,
TravelMode travel_mode,
const LaneDescriptionID lane_description_id, const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification); guidance::RoadClassification road_classification);
bool operator<(const NodeBasedEdge &other) const; bool operator<(const NodeBasedEdge &other) const;
NodeID source; NodeID source; // 32 4
NodeID target; NodeID target; // 32 4
NodeID name_id; NodeID name_id; // 32 4
EdgeWeight weight; EdgeWeight weight; // 32 4
EdgeWeight duration; EdgeWeight duration; // 32 4
std::uint8_t forward : 1; std::uint8_t forward : 1; // 1
std::uint8_t backward : 1; std::uint8_t backward : 1; // 1
std::uint8_t roundabout : 1; std::uint8_t roundabout : 1; // 1
std::uint8_t circular : 1; std::uint8_t circular : 1; // 1
std::uint8_t startpoint : 1; std::uint8_t startpoint : 1; // 1
std::uint8_t is_split : 1; std::uint8_t restricted : 1; // 1
TravelMode travel_mode : 4; std::uint8_t is_split : 1; // 1
LaneDescriptionID lane_description_id; TravelMode travel_mode : 4; // 4
guidance::RoadClassification road_classification; LaneDescriptionID lane_description_id; // 16 2
guidance::RoadClassification road_classification; // 16 2
}; };
struct NodeBasedEdgeWithOSM : NodeBasedEdge struct NodeBasedEdgeWithOSM : NodeBasedEdge
@ -60,8 +62,9 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
bool roundabout, bool roundabout,
bool circular, bool circular,
bool startpoint, bool startpoint,
TravelMode travel_mode, bool restricted,
bool is_split, bool is_split,
TravelMode travel_mode,
const LaneDescriptionID lane_description_id, const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification); guidance::RoadClassification road_classification);
@ -74,7 +77,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
inline NodeBasedEdge::NodeBasedEdge() inline NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), duration(0), : source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), duration(0),
forward(false), backward(false), roundabout(false), circular(false), startpoint(true), forward(false), backward(false), roundabout(false), circular(false), startpoint(true),
is_split(false), travel_mode(TRAVEL_MODE_INACCESSIBLE), restricted(false), is_split(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
lane_description_id(INVALID_LANE_DESCRIPTIONID) lane_description_id(INVALID_LANE_DESCRIPTIONID)
{ {
} }
@ -89,13 +92,14 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
bool roundabout, bool roundabout,
bool circular, bool circular,
bool startpoint, bool startpoint,
TravelMode travel_mode, bool restricted,
bool is_split, bool is_split,
TravelMode travel_mode,
const LaneDescriptionID lane_description_id, const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification) guidance::RoadClassification road_classification)
: source(source), target(target), name_id(name_id), weight(weight), duration(duration), : source(source), target(target), name_id(name_id), weight(weight), duration(duration),
forward(forward), backward(backward), roundabout(roundabout), circular(circular), forward(forward), backward(backward), roundabout(roundabout), circular(circular),
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode), startpoint(startpoint), restricted(restricted), is_split(is_split), travel_mode(travel_mode),
lane_description_id(lane_description_id), road_classification(std::move(road_classification)) lane_description_id(lane_description_id), road_classification(std::move(road_classification))
{ {
} }
@ -127,8 +131,9 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
bool roundabout, bool roundabout,
bool circular, bool circular,
bool startpoint, bool startpoint,
TravelMode travel_mode, bool restricted,
bool is_split, bool is_split,
TravelMode travel_mode,
const LaneDescriptionID lane_description_id, const LaneDescriptionID lane_description_id,
guidance::RoadClassification road_classification) guidance::RoadClassification road_classification)
: NodeBasedEdge(SPECIAL_NODEID, : NodeBasedEdge(SPECIAL_NODEID,
@ -141,8 +146,9 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
roundabout, roundabout,
circular, circular,
startpoint, startpoint,
travel_mode, restricted,
is_split, is_split,
travel_mode,
lane_description_id, lane_description_id,
std::move(road_classification)), std::move(road_classification)),
osm_source_id(std::move(source)), osm_target_id(std::move(target)) osm_source_id(std::move(source)), osm_target_id(std::move(target))

View File

@ -42,11 +42,13 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
RouteParametersGrammar(qi::rule<Iterator, Signature> &root_rule_) : BaseGrammar(root_rule_) RouteParametersGrammar(qi::rule<Iterator, Signature> &root_rule_) : BaseGrammar(root_rule_)
{ {
using AnnotationsType = engine::api::RouteParameters::AnnotationsType;
const auto add_annotation = [](engine::api::RouteParameters &route_parameters, const auto add_annotation = [](engine::api::RouteParameters &route_parameters,
engine::api::RouteParameters::AnnotationsType &route_param) { AnnotationsType route_param) {
route_parameters.annotations_type = route_parameters.annotations_type | route_param; route_parameters.annotations_type = route_parameters.annotations_type | route_param;
route_parameters.annotations = route_parameters.annotations_type != route_parameters.annotations =
engine::api::RouteParameters::AnnotationsType::None; route_parameters.annotations_type != AnnotationsType::None;
}; };
geometries_type.add("geojson", engine::api::RouteParameters::GeometriesType::GeoJSON)( geometries_type.add("geojson", engine::api::RouteParameters::GeometriesType::GeoJSON)(
@ -57,13 +59,10 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
"full", engine::api::RouteParameters::OverviewType::Full)( "full", engine::api::RouteParameters::OverviewType::Full)(
"false", engine::api::RouteParameters::OverviewType::False); "false", engine::api::RouteParameters::OverviewType::False);
annotations_type.add("true", engine::api::RouteParameters::AnnotationsType::All)( annotations_type.add("duration", AnnotationsType::Duration)("nodes",
"false", engine::api::RouteParameters::AnnotationsType::None)( AnnotationsType::Nodes)(
"duration", engine::api::RouteParameters::AnnotationsType::Duration)( "distance", AnnotationsType::Distance)("weight", AnnotationsType::Weight)(
"nodes", engine::api::RouteParameters::AnnotationsType::Nodes)( "datasources", AnnotationsType::Datasources)("speed", AnnotationsType::Speed);
"distance", engine::api::RouteParameters::AnnotationsType::Distance)(
"weight", engine::api::RouteParameters::AnnotationsType::Weight)(
"datasources", engine::api::RouteParameters::AnnotationsType::Datasources);
base_rule = base_rule =
BaseGrammar::base_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1) |
@ -75,7 +74,9 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
(qi::lit("overview=") > (qi::lit("overview=") >
overview_type[ph::bind(&engine::api::RouteParameters::overview, qi::_r1) = qi::_1]) | overview_type[ph::bind(&engine::api::RouteParameters::overview, qi::_r1) = qi::_1]) |
(qi::lit("annotations=") > (qi::lit("annotations=") >
annotations_type[ph::bind(add_annotation, qi::_r1, qi::_1)] % ','); (qi::lit("true")[ph::bind(add_annotation, qi::_r1, AnnotationsType::All)] |
qi::lit("false")[ph::bind(add_annotation, qi::_r1, AnnotationsType::None)] |
(annotations_type[ph::bind(add_annotation, qi::_r1, qi::_1)] % ',')));
query_rule = BaseGrammar::query_rule(qi::_r1); query_rule = BaseGrammar::query_rule(qi::_r1);
} }

View File

@ -33,11 +33,12 @@ struct NodeBasedEdgeData
bool roundabout, bool roundabout,
bool circular, bool circular,
bool startpoint, bool startpoint,
bool restricted,
extractor::TravelMode travel_mode, extractor::TravelMode travel_mode,
const LaneDescriptionID lane_description_id) const LaneDescriptionID lane_description_id)
: weight(weight), duration(duration), edge_id(edge_id), name_id(name_id), : weight(weight), duration(duration), edge_id(edge_id), name_id(name_id),
reversed(reversed), roundabout(roundabout), circular(circular), startpoint(startpoint), reversed(reversed), roundabout(roundabout), circular(circular), startpoint(startpoint),
travel_mode(travel_mode), lane_description_id(lane_description_id) restricted(restricted), travel_mode(travel_mode), lane_description_id(lane_description_id)
{ {
} }
@ -49,6 +50,7 @@ struct NodeBasedEdgeData
bool roundabout : 1; bool roundabout : 1;
bool circular : 1; bool circular : 1;
bool startpoint : 1; bool startpoint : 1;
bool restricted : 1;
extractor::TravelMode travel_mode : 4; extractor::TravelMode travel_mode : 4;
LaneDescriptionID lane_description_id; LaneDescriptionID lane_description_id;
extractor::guidance::RoadClassification road_classification; extractor::guidance::RoadClassification road_classification;
@ -58,7 +60,8 @@ struct NodeBasedEdgeData
return (reversed == other.reversed) && (roundabout == other.roundabout) && return (reversed == other.reversed) && (roundabout == other.roundabout) &&
(circular == other.circular) && (startpoint == other.startpoint) && (circular == other.circular) && (startpoint == other.startpoint) &&
(travel_mode == other.travel_mode) && (travel_mode == other.travel_mode) &&
(road_classification == other.road_classification); (road_classification == other.road_classification) &&
(restricted == other.restricted);
} }
bool CanCombineWith(const NodeBasedEdgeData &other) const bool CanCombineWith(const NodeBasedEdgeData &other) const
@ -87,6 +90,7 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
output_edge.data.name_id = input_edge.name_id; output_edge.data.name_id = input_edge.name_id;
output_edge.data.travel_mode = input_edge.travel_mode; output_edge.data.travel_mode = input_edge.travel_mode;
output_edge.data.startpoint = input_edge.startpoint; output_edge.data.startpoint = input_edge.startpoint;
output_edge.data.restricted = input_edge.restricted;
output_edge.data.road_classification = input_edge.road_classification; output_edge.data.road_classification = input_edge.road_classification;
output_edge.data.lane_description_id = input_edge.lane_description_id; output_edge.data.lane_description_id = input_edge.lane_description_id;

View File

@ -2,7 +2,7 @@
"name": "osrm-backend-test-suite", "name": "osrm-backend-test-suite",
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++11 designed to run on OpenStreetMap data.", "description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": { "dependencies": {
"chalk": "^1.1.3", "chalk": "^1.1.3",
"cucumber": "^1.2.1", "cucumber": "^1.2.1",

View File

@ -65,6 +65,10 @@ local profile = {
'delivery' 'delivery'
}, },
restricted_access_tag_list = Set { },
restricted_highway_whitelist = Set { },
access_tags_hierarchy = Sequence { access_tags_hierarchy = Sequence {
'bicycle', 'bicycle',
'vehicle', 'vehicle',
@ -521,4 +525,10 @@ function turn_function(turn)
if turn.has_traffic_light then if turn.has_traffic_light then
turn.duration = turn.duration + profile.traffic_light_penalty turn.duration = turn.duration + profile.traffic_light_penalty
end end
if properties.weight_name == 'cyclability' then
-- penalize turns from non-local access only segments onto local access only tags
if not turn.source_restricted and turn.target_restricted then
turn.weight = turn.weight + 3000
end
end
end end

View File

@ -34,6 +34,9 @@ local profile = {
speed_reduction = 0.8, speed_reduction = 0.8,
traffic_light_penalty = 2, traffic_light_penalty = 2,
u_turn_penalty = 20, u_turn_penalty = 20,
restricted_penalty = 3000,
-- Note^: abstract value but in seconds correlates approximately to 50 min
-- meaning that a route through a local access way is > 50 min faster than around
-- Note: this biases right-side driving. -- Note: this biases right-side driving.
-- Should be inverted for left-driving countries. -- Should be inverted for left-driving countries.
@ -63,18 +66,25 @@ local profile = {
'vehicle', 'vehicle',
'permissive', 'permissive',
'designated', 'designated',
'destination', 'hov'
'hov' -- we might filter hov out later depending on the avoid settings or add penalties
}, },
access_tag_blacklist = Set { access_tag_blacklist = Set {
'no', 'no',
'private',
'agricultural', 'agricultural',
'forestry', 'forestry',
'emergency', 'emergency',
'psv', 'psv',
'delivery' 'customer',
'private',
'delivery',
'destination'
},
restricted_access_tag_list = Set {
'private',
'delivery',
'destination'
}, },
access_tags_hierarchy = Sequence { access_tags_hierarchy = Sequence {
@ -96,7 +106,7 @@ local profile = {
avoid = Set { avoid = Set {
'area', 'area',
'toll', -- 'toll', -- uncomment this to avoid tolls
'reversible', 'reversible',
'impassable', 'impassable',
'hov_lanes', 'hov_lanes',
@ -131,6 +141,21 @@ local profile = {
["drive-thru"] = 0.5 ["drive-thru"] = 0.5
}, },
restricted_highway_whitelist = Set {
'motorway',
'motorway_link',
'trunk',
'trunk_link',
'primary',
'primary_link',
'secondary',
'secondary_link',
'tertiary',
'tertiary_link',
'residential',
'living_street',
},
route_speeds = { route_speeds = {
ferry = 5, ferry = 5,
shuttle_train = 10 shuttle_train = 10
@ -253,7 +278,7 @@ function node_function (node, result)
-- parse access and barrier tags -- parse access and barrier tags
local access = find_access_tag(node, profile.access_tags_hierarchy) local access = find_access_tag(node, profile.access_tags_hierarchy)
if access then if access then
if profile.access_tag_blacklist[access] then if profile.access_tag_blacklist[access] and not profile.restricted_access_tag_list[access] then
result.barrier = true result.barrier = true
end end
else else
@ -331,7 +356,7 @@ function way_function(way, result)
-- handle service road restrictions -- handle service road restrictions
'handle_service', 'handle_service',
-- check high occupancy vehicle restrictions -- handle hov
'handle_hov', 'handle_hov',
-- compute speed taking into account way type, maxspeed tags, etc. -- compute speed taking into account way type, maxspeed tags, etc.
@ -387,4 +412,10 @@ function turn_function (turn)
turn.weight = turn.duration turn.weight = turn.duration
end end
end end
if properties.weight_name == 'routability' then
-- penalize turns from non-local access only segments onto local access only tags
if not turn.source_restricted and turn.target_restricted then
turn.weight = turn.weight + profile.restricted_penalty
end
end
end end

View File

@ -12,6 +12,7 @@ properties.max_speed_for_map_matching = 40/3.6 -- kmph -> m/s
properties.use_turn_restrictions = false properties.use_turn_restrictions = false
properties.continue_straight_at_waypoint = false properties.continue_straight_at_waypoint = false
properties.weight_name = 'duration' properties.weight_name = 'duration'
--properties.weight_name = 'routability'
local walking_speed = 5 local walking_speed = 5
@ -44,12 +45,16 @@ local profile = {
access_tag_blacklist = Set { access_tag_blacklist = Set {
'no', 'no',
'private',
'agricultural', 'agricultural',
'forestry', 'forestry',
'delivery' 'private',
'delivery',
}, },
restricted_access_tag_list = Set { },
restricted_highway_whitelist = Set { },
access_tags_hierarchy = Sequence { access_tags_hierarchy = Sequence {
'foot', 'foot',
'access' 'access'
@ -244,4 +249,10 @@ function turn_function (turn)
if turn.has_traffic_light then if turn.has_traffic_light then
turn.duration = profile.traffic_light_penalty turn.duration = profile.traffic_light_penalty
end end
if properties.weight_name == 'routability' then
-- penalize turns from non-local access only segments onto local access only tags
if not turn.source_restricted and turn.target_restricted then
turn.weight = turn.weight + 3000
end
end
end end

View File

@ -177,34 +177,57 @@ function Handlers.handle_hov(way,result,data,profile)
return return
end end
-- in this case we will use penalties instead of filtering out local hov = way:get_value_by_key("hov")
if "designated" == hov then
result.forward_restricted = true
result.backward_restricted = true
end
data.hov_lanes_forward, data.hov_lanes_backward = Tags.get_forward_backward_by_key(way,data,'hov:lanes')
local all_hov_forward = Handlers.has_all_designated_hov_lanes(data.hov_lanes_forward)
local all_hov_backward = Handlers.has_all_designated_hov_lanes(data.hov_lanes_backward)
-- in this case we will use turn penalties instead of filtering out
if properties.weight_name == 'routability' then if properties.weight_name == 'routability' then
if (all_hov_forward) then
result.forward_restricted = true
end
if (all_hov_backward) then
result.backward_restricted = true
end
return return
end end
-- check if all lanes are hov only -- filter out ways where all lanes are hov only
data.hov_lanes_forward, data.hov_lanes_backward = Tags.get_forward_backward_by_key(way,data,'hov:lanes') if all_hov_forward then
local inaccessible_forward = Handlers.has_all_designated_hov_lanes(data.hov_lanes_forward)
local inaccessible_backward = Handlers.has_all_designated_hov_lanes(data.hov_lanes_backward)
if inaccessible_forward then
result.forward_mode = mode.inaccessible result.forward_mode = mode.inaccessible
end end
if inaccessible_backward then if all_hov_backward then
result.backward_mode = mode.inaccessible result.backward_mode = mode.inaccessible
end end
end end
-- check accessibility by traversing our acces tag hierarchy -- check accessibility by traversing our access tag hierarchy
function Handlers.handle_access(way,result,data,profile) function Handlers.handle_access(way,result,data,profile)
data.forward_access, data.backward_access = data.forward_access, data.backward_access =
Tags.get_forward_backward_by_set(way,data,profile.access_tags_hierarchy) Tags.get_forward_backward_by_set(way,data,profile.access_tags_hierarchy)
if profile.access_tag_blacklist[data.forward_access] then -- only allow a subset of roads that are marked as restricted
if profile.restricted_highway_whitelist[data.highway] then
if profile.restricted_access_tag_list[data.forward_access] then
result.forward_restricted = true
end
if profile.restricted_access_tag_list[data.backward_access] then
result.backward_restricted = true
end
end
if profile.access_tag_blacklist[data.forward_access] and not result.forward_restricted then
result.forward_mode = mode.inaccessible result.forward_mode = mode.inaccessible
end end
if profile.access_tag_blacklist[data.backward_access] then if profile.access_tag_blacklist[data.backward_access] and not result.backward_restricted then
result.backward_mode = mode.inaccessible result.backward_mode = mode.inaccessible
end end
@ -273,24 +296,6 @@ end
function Handlers.handle_penalties(way,result,data,profile) function Handlers.handle_penalties(way,result,data,profile)
-- heavily penalize a way tagged with all HOV lanes -- heavily penalize a way tagged with all HOV lanes
-- in order to only route over them if there is no other option -- in order to only route over them if there is no other option
local forward_hov_penalty = 1.0
local backward_hov_penalty = 1.0
if profile.avoid.hov_lanes then
local hov = way:get_value_by_key("hov")
if "designated" == hov then
forward_hov_penalty = 0.1
backward_hov_penalty = 0.1
else
data.hov_lanes_forward, data.hov_lanes_backward = Tags.get_forward_backward_by_key(way,data,'hov:lanes')
if Handlers.has_all_designated_hov_lanes(data.hov_lanes_forward) then
forward_hov_penalty = 0.1
end
if Handlers.has_all_designated_hov_lanes(data.hov_lanes_backward) then
backward_hov_penalty = 0.1
end
end
end
local service_penalty = 1.0 local service_penalty = 1.0
local service = way:get_value_by_key("service") local service = way:get_value_by_key("service")
if service and profile.service_penalties[service] then if service and profile.service_penalties[service] then
@ -327,11 +332,11 @@ function Handlers.handle_penalties(way,result,data,profile)
local sideroad_penalty = 1.0 local sideroad_penalty = 1.0
data.sideroad = way:get_value_by_key("side_road") data.sideroad = way:get_value_by_key("side_road")
if "yes" == data.sideroad or "rotary" == data.sideroad then if "yes" == data.sideroad or "rotary" == data.sideroad then
sideroad_penalty = side_road_multiplier; sideroad_penalty = profile.side_road_multiplier
end end
local forward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty, forward_hov_penalty) local forward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty)
local backward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty, backward_hov_penalty) local backward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty)
if properties.weight_name == 'routability' then if properties.weight_name == 'routability' then
if result.forward_speed > 0 then if result.forward_speed > 0 then

View File

@ -268,7 +268,7 @@ template <typename Key, typename Value> struct CSVFilesParser
qi::rule<Iterator, std::pair<Key, Value>()> csv_line = qi::rule<Iterator, std::pair<Key, Value>()> csv_line =
(key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol)); (key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol));
std::vector<std::pair<Key, Value>> result; std::vector<std::pair<Key, Value>> result;
const auto ok = qi::parse(first, last, (csv_line % qi::eol) >> *qi::eol, result); const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
if (!ok || first != last) if (!ok || first != last)
{ {

View File

@ -74,6 +74,15 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
// We're walking backwards over all adjacent turns: // We're walking backwards over all adjacent turns:
// the current turn lanes constrain the lanes we have to take in the previous turn. // the current turn lanes constrain the lanes we have to take in the previous turn.
// state for the lamda
// the number of lanes we have to change depends on the number of lanes that are allowed for
// a turn (in general) and the set of lanes which would allow for us to do the turn without
// a problem. In a sequence of turns, we have to look at how much time we need to switch the
// sequence. Given the turns in between, we would expect a bit longer than on a straight
// segment for a lane switch, but the total time shouldn't be unlimited.
double time_to_constrained = 0.0;
util::for_each_pair(rev_first, rev_last, [&](RouteStep &current, RouteStep &previous) { util::for_each_pair(rev_first, rev_last, [&](RouteStep &current, RouteStep &previous) {
const auto current_inst = current.maneuver.instruction; const auto current_inst = current.maneuver.instruction;
const auto current_lanes = current.intersections.front().lanes; const auto current_lanes = current.intersections.front().lanes;
@ -88,7 +97,18 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1; const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1;
const bool lanes_fan_in = previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn; const bool lanes_fan_in = previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn;
if (!lanes_to_constrain || !lanes_fan_in) // only prevent use lanes due to making all turns. don't make turns during curvy
// segments
if (previous_inst.type == TurnType::UseLane)
time_to_constrained += previous.duration;
else
time_to_constrained = 0;
const auto lane_delta = previous_lanes.lanes_in_turn - current_lanes.lanes_in_turn;
const auto can_make_all_turns =
time_to_constrained > lane_delta * min_duration_needed_for_lane_change;
if (!lanes_to_constrain || !lanes_fan_in || can_make_all_turns)
return; return;
// We do not have a mapping from lanes to lanes. All we have is the lanes in the turn // We do not have a mapping from lanes to lanes. All we have is the lanes in the turn
@ -99,9 +119,6 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
const LaneID current_num_lanes_right_of_turn = current.NumLanesToTheRight(); const LaneID current_num_lanes_right_of_turn = current.NumLanesToTheRight();
const LaneID current_num_lanes_left_of_turn = current.NumLanesToTheLeft(); const LaneID current_num_lanes_left_of_turn = current.NumLanesToTheLeft();
const LaneID num_shared_lanes = std::min(current_lanes.lanes_in_turn, //
previous_lanes.lanes_in_turn); //
// 0/ Tag keep straight with the next turn's direction if available // 0/ Tag keep straight with the next turn's direction if available
const auto previous_is_straight = const auto previous_is_straight =
!isLeftTurn(previous_inst) && !isRightTurn(previous_inst); !isLeftTurn(previous_inst) && !isRightTurn(previous_inst);
@ -121,14 +138,14 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
LaneID new_first_lane_from_the_right = LaneID new_first_lane_from_the_right =
previous_lanes.first_lane_from_the_right // start from rightmost lane previous_lanes.first_lane_from_the_right // start from rightmost lane
+ previous_lanes.lanes_in_turn // one past leftmost lane + previous_lanes.lanes_in_turn // one past leftmost lane
- num_shared_lanes; // back number of new lanes - current_lanes.lanes_in_turn; // back number of new lanes
// The leftmost target lanes might not be involved in the turn. Figure out // The leftmost target lanes might not be involved in the turn. Figure out
// how many lanes are to the left and not in the turn. // how many lanes are to the left and not in the turn.
new_first_lane_from_the_right -= new_first_lane_from_the_right -=
std::min(current_num_lanes_left_of_turn, num_shared_lanes); std::min(current_num_lanes_left_of_turn, current_lanes.lanes_in_turn);
previous_lanes = {num_shared_lanes, new_first_lane_from_the_right}; previous_lanes = {current_lanes.lanes_in_turn, new_first_lane_from_the_right};
}; };
const auto anticipate_for_right_turn = [&] { const auto anticipate_for_right_turn = [&] {
@ -139,9 +156,9 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
// The rightmost target lanes might not be involved in the turn. Figure out // The rightmost target lanes might not be involved in the turn. Figure out
// how many lanes are to the right and not in the turn. // how many lanes are to the right and not in the turn.
new_first_lane_from_the_right += new_first_lane_from_the_right +=
std::min(current_num_lanes_right_of_turn, num_shared_lanes); std::min(current_num_lanes_right_of_turn, current_lanes.lanes_in_turn);
previous_lanes = {num_shared_lanes, new_first_lane_from_the_right}; previous_lanes = {current_lanes.lanes_in_turn, new_first_lane_from_the_right};
}; };
// 2/ When to anticipate a left, right turn // 2/ When to anticipate a left, right turn
@ -179,13 +196,11 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
anticipate_for_right_turn(); anticipate_for_right_turn();
} }
// We might have constrained the previous step in a way that makes it compatible if (previous_inst.type == TurnType::UseLane && current_inst.type == TurnType::UseLane &&
// with the current step. If we did so we collapse it here and mark the current previous.mode == current.mode && previous_lanes == current_lanes)
// step as invalid, scheduled for later removal.
if (collapsable(previous, current))
{ {
previous.ElongateBy(current); previous.ElongateBy(current);
current.maneuver.instruction = TurnInstruction::NO_TURN(); current.Invalidate();
} }
}); });
}; };

View File

@ -526,6 +526,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// compute weight and duration penalties // compute weight and duration penalties
auto is_traffic_light = m_traffic_lights.count(node_at_center_of_intersection); auto is_traffic_light = m_traffic_lights.count(node_at_center_of_intersection);
ExtractionTurn extracted_turn(turn, is_traffic_light); ExtractionTurn extracted_turn(turn, is_traffic_light);
extracted_turn.source_restricted = edge_data1.restricted;
extracted_turn.target_restricted = edge_data2.restricted;
scripting_environment.ProcessTurn(extracted_turn); scripting_environment.ProcessTurn(extracted_turn);
// turn penalties are limited to [-2^15, 2^15) which roughly // turn penalties are limited to [-2^15, 2^15) which roughly

View File

@ -121,6 +121,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
const auto toValueByEdgeOrByMeter = [&nodes](const double by_way, const double by_meter) { const auto toValueByEdgeOrByMeter = [&nodes](const double by_way, const double by_meter) {
using Value = detail::ByEdgeOrByMeterValue; using Value = detail::ByEdgeOrByMeterValue;
// get value by weight per edge
if (by_way >= 0) if (by_way >= 0)
{ {
// FIXME We divide by the number of edges here, but should rather consider // FIXME We divide by the number of edges here, but should rather consider
@ -132,6 +133,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
} }
else else
{ {
// get value by deriving weight from speed per edge
return Value(Value::by_meter, by_meter); return Value(Value::by_meter, by_meter);
} }
}; };
@ -320,6 +322,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.weight > 0) && parsed_way.weight > 0) &&
(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE); (parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
// split an edge into two edges if forwards/backwards behavior differ
const bool split_edge = in_forward_direction && in_backward_direction && const bool split_edge = in_forward_direction && in_backward_direction &&
((parsed_way.forward_rate != parsed_way.backward_rate) || ((parsed_way.forward_rate != parsed_way.backward_rate) ||
(parsed_way.forward_speed != parsed_way.backward_speed) || (parsed_way.forward_speed != parsed_way.backward_speed) ||
@ -343,8 +346,9 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.roundabout, parsed_way.roundabout,
parsed_way.circular, parsed_way.circular,
parsed_way.is_startpoint, parsed_way.is_startpoint,
parsed_way.forward_travel_mode, parsed_way.forward_restricted,
split_edge, split_edge,
parsed_way.forward_travel_mode,
turn_lane_id_forward, turn_lane_id_forward,
road_classification, road_classification,
{})); {}));
@ -368,8 +372,9 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.roundabout, parsed_way.roundabout,
parsed_way.circular, parsed_way.circular,
parsed_way.is_startpoint, parsed_way.is_startpoint,
parsed_way.backward_travel_mode, parsed_way.backward_restricted,
split_edge, split_edge,
parsed_way.backward_travel_mode,
turn_lane_id_backward, turn_lane_id_backward,
road_classification, road_classification,
{})); {}));

View File

@ -40,7 +40,6 @@ LaneDataVector augmentMultiple(const std::size_t none_index,
LaneDataVector lane_data, LaneDataVector lane_data,
const Intersection &intersection) const Intersection &intersection)
{ {
// a none-turn is allowing multiple turns. we have to add a lane-data entry for // a none-turn is allowing multiple turns. we have to add a lane-data entry for
// every possible turn. This should, hopefully, only be the case for single lane // every possible turn. This should, hopefully, only be the case for single lane
// entries? // entries?
@ -107,20 +106,64 @@ LaneDataVector augmentMultiple(const std::size_t none_index,
util::Log(logWARNING) << "Failed lane assignment. Reached bad situation."; util::Log(logWARNING) << "Failed lane assignment. Reached bad situation.";
return std::make_pair(std::size_t{0}, std::size_t{0}); return std::make_pair(std::size_t{0}, std::size_t{0});
}(); }();
for (auto intersection_index = range.first; intersection_index < range.second;
++intersection_index) const auto intersection_range_first = intersection.begin() + range.first;
const auto intersection_range_end = intersection.begin() + range.second;
const auto allowed_in_range =
std::count_if(intersection_range_first, intersection_range_end, [](const auto &road) {
return road.entry_allowed;
});
if (allowed_in_range > 1 && lane_data[none_index].to - lane_data[none_index].from >= 1)
{ {
if (intersection[intersection_index].entry_allowed) // check if there is a straight turn
auto straight_itr =
std::find_if(intersection_range_first, intersection_range_end, [](const auto &road) {
return road.instruction.direction_modifier == DirectionModifier::Straight;
});
// we have a straight turn?
if (straight_itr != intersection_range_end)
{ {
// FIXME this probably can be only a subset of these turns here? for (auto itr = intersection_range_first; itr != straight_itr; ++itr)
lane_data.push_back( {
{tag_by_modifier[intersection[intersection_index].instruction.direction_modifier], lane_data.push_back({tag_by_modifier[itr->instruction.direction_modifier],
lane_data[none_index].from, lane_data[none_index].from,
lane_data[none_index].to, lane_data[none_index].from,
false}); false});
}
lane_data.push_back({tag_by_modifier[straight_itr->instruction.direction_modifier],
lane_data[none_index].from,
lane_data[none_index].to,
false});
for (auto itr = straight_itr + 1; itr != intersection_range_end; ++itr)
{
lane_data.push_back({tag_by_modifier[itr->instruction.direction_modifier],
lane_data[none_index].to,
lane_data[none_index].to,
false});
}
lane_data.erase(lane_data.begin() + none_index);
} }
return lane_data;
}
else
{
for (auto intersection_index = range.first; intersection_index < range.second;
++intersection_index)
{
if (intersection[intersection_index].entry_allowed)
{
lane_data.push_back({tag_by_modifier[intersection[intersection_index]
.instruction.direction_modifier],
lane_data[none_index].from,
lane_data[none_index].to,
false});
}
}
lane_data.erase(lane_data.begin() + none_index);
} }
lane_data.erase(lane_data.begin() + none_index);
return lane_data; return lane_data;
} }

View File

@ -343,7 +343,11 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"forward_mode", "forward_mode",
sol::property(&ExtractionWay::get_forward_mode, &ExtractionWay::set_forward_mode), sol::property(&ExtractionWay::get_forward_mode, &ExtractionWay::set_forward_mode),
"backward_mode", "backward_mode",
sol::property(&ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode)); sol::property(&ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode),
"forward_restricted",
&ExtractionWay::forward_restricted,
"backward_restricted",
&ExtractionWay::backward_restricted);
context.state.new_usertype<ExtractionSegment>("ExtractionSegment", context.state.new_usertype<ExtractionSegment>("ExtractionSegment",
"source", "source",
@ -369,7 +373,11 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"weight", "weight",
&ExtractionTurn::weight, &ExtractionTurn::weight,
"duration", "duration",
&ExtractionTurn::duration); &ExtractionTurn::duration,
"source_restricted",
&ExtractionTurn::source_restricted,
"target_restricted",
&ExtractionTurn::target_restricted);
// Keep in mind .location is undefined since we're not using libosmium's location cache // Keep in mind .location is undefined since we're not using libosmium's location cache
context.state.new_usertype<osmium::NodeRef>("NodeRef", "id", &osmium::NodeRef::ref); context.state.new_usertype<osmium::NodeRef>("NodeRef", "id", &osmium::NodeRef::ref);

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script. // This file was generated with a script.
// Generated 2016-12-16 05:28:22.940422 UTC // Generated 2017-02-19 09:59:38.638408 UTC
// This header was generated with sol v2.15.5 (revision bbcbd41) // This header was generated with sol v2.15.8 (revision 0c8ec82)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -47,6 +47,9 @@
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wshadow"
#pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wconversion"
#elif defined _MSC_VER
#pragma warning( push )
#pragma warning( disable : 4324 ) // structure was padded due to alignment specifier
#endif // g++ #endif // g++
// beginning of sol/state.hpp // beginning of sol/state.hpp
@ -790,7 +793,13 @@ namespace sol {
// beginning of sol/compatibility/version.hpp // beginning of sol/compatibility/version.hpp
#ifdef SOL_USING_CXX_LUA
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#else
#include <lua.hpp> #include <lua.hpp>
#endif // C++-compiler Lua
#if defined(_WIN32) || defined(_MSC_VER) #if defined(_WIN32) || defined(_MSC_VER)
#ifndef SOL_CODECVT_SUPPORT #ifndef SOL_CODECVT_SUPPORT
@ -1022,7 +1031,7 @@ inline const char* kepler_lua_compat_get_string(lua_State* L, void* ud, size_t*
return ls->s; return ls->s;
} }
#if !defined(SOL_LUAJIT) || ((SOL_LUAJIT_VERSION - 20100) <= 0) #if !defined(SOL_LUAJIT) || (SOL_LUAJIT_VERSION < 20100)
inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) { inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) {
kepler_lua_compat_get_string_view ls; kepler_lua_compat_get_string_view ls;
@ -1035,7 +1044,8 @@ inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const c
#endif /* Lua 5.1 */ #endif /* Lua 5.1 */
#endif // SOL_5_1_0_H// end of sol/compatibility/5.1.0.h #endif // SOL_5_1_0_H
// end of sol/compatibility/5.1.0.h
// beginning of sol/compatibility/5.0.0.h // beginning of sol/compatibility/5.0.0.h
@ -2089,8 +2099,8 @@ namespace sol {
}; };
template <class T> template <class T>
struct optional_base { struct alignas(T) optional_base {
char storage_[sizeof(T) + (sizeof(T) % alignof(T))]; char storage_[sizeof(T)];
bool init_; bool init_;
constexpr optional_base() noexcept : storage_(), init_(false) {}; constexpr optional_base() noexcept : storage_(), init_(false) {};
@ -2137,8 +2147,8 @@ namespace sol {
using constexpr_optional_base = optional_base<T>; using constexpr_optional_base = optional_base<T>;
#else #else
template <class T> template <class T>
struct constexpr_optional_base { struct alignas(T) constexpr_optional_base {
char storage_[sizeof(T) + (sizeof(T) % alignof(T))]; char storage_[sizeof(T)];
bool init_; bool init_;
constexpr constexpr_optional_base() noexcept : storage_(), init_(false) {} constexpr constexpr_optional_base() noexcept : storage_(), init_(false) {}
@ -3315,7 +3325,7 @@ namespace sol {
memory = LUA_ERRMEM, memory = LUA_ERRMEM,
gc = LUA_ERRGCMM, gc = LUA_ERRGCMM,
handler = LUA_ERRERR, handler = LUA_ERRERR,
dead, dead = -1,
}; };
enum class load_status : int { enum class load_status : int {
@ -3374,6 +3384,8 @@ namespace sol {
bitwise_and, bitwise_and,
bitwise_or, bitwise_or,
bitwise_xor, bitwise_xor,
pairs,
next
}; };
typedef meta_function meta_method; typedef meta_function meta_method;
@ -3383,7 +3395,7 @@ namespace sol {
"__newindex", "__newindex",
} }; } };
const std::array<std::string, 21> meta_function_names = { { const std::array<std::string, 29> meta_function_names = { {
"new", "new",
"__index", "__index",
"__newindex", "__newindex",
@ -3404,6 +3416,17 @@ namespace sol {
"__lt", "__lt",
"__le", "__le",
"__gc", "__gc",
"__idiv",
"__shl",
"__shr",
"__bnot",
"__band",
"__bor",
"__bxor",
"__pairs",
"__next"
} }; } };
inline const std::string& name_of(meta_function mf) { inline const std::string& name_of(meta_function mf) {
@ -3473,6 +3496,10 @@ namespace sol {
using protected_function = basic_protected_function<reference>; using protected_function = basic_protected_function<reference>;
using stack_function = basic_function<stack_reference>; using stack_function = basic_function<stack_reference>;
using stack_protected_function = basic_protected_function<stack_reference>; using stack_protected_function = basic_protected_function<stack_reference>;
using unsafe_function = basic_function<reference>;
using safe_function = basic_protected_function<reference>;
using stack_unsafe_function = basic_function<stack_reference>;
using stack_safe_function = basic_protected_function<stack_reference>;
template <typename base_t> template <typename base_t>
class basic_object; class basic_object;
template <typename base_t> template <typename base_t>
@ -3716,11 +3743,15 @@ namespace sol {
template <> template <>
struct is_transparent_argument<variadic_args> : std::true_type {}; struct is_transparent_argument<variadic_args> : std::true_type {};
template <typename T>
struct is_variadic_arguments : std::is_same<T, variadic_args> {};
template <typename Signature> template <typename Signature>
struct lua_bind_traits : meta::bind_traits<Signature> { struct lua_bind_traits : meta::bind_traits<Signature> {
private: private:
typedef meta::bind_traits<Signature> base_t; typedef meta::bind_traits<Signature> base_t;
public: public:
typedef std::integral_constant<bool, meta::count_for<is_transparent_argument, typename base_t::args_list>::value != 0> runtime_variadics_t;
static const std::size_t true_arity = base_t::arity; static const std::size_t true_arity = base_t::arity;
static const std::size_t arity = base_t::arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value; static const std::size_t arity = base_t::arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value;
static const std::size_t true_free_arity = base_t::free_arity; static const std::size_t true_free_arity = base_t::free_arity;
@ -3790,7 +3821,10 @@ namespace sol {
} }
int push(lua_State* Ls) const noexcept { int push(lua_State* Ls) const noexcept {
lua_pushvalue(Ls, index); lua_pushvalue(lua_state(), index);
if (Ls != lua_state()) {
lua_xmove(lua_state(), Ls, 1);
}
return 1; return 1;
} }
@ -3923,6 +3957,9 @@ namespace sol {
} }
reference& operator=(reference&& o) noexcept { reference& operator=(reference&& o) noexcept {
if (valid()) {
deref();
}
luastate = o.luastate; luastate = o.luastate;
ref = o.ref; ref = o.ref;
@ -4114,7 +4151,7 @@ namespace sol {
void set_extra(std::true_type, std::index_sequence<I...>, T&& target) { void set_extra(std::true_type, std::index_sequence<I...>, T&& target) {
using std::get; using std::get;
(void)detail::swallow{ 0, (void)detail::swallow{ 0,
(get<I>(*this) = get<I>(types<Tn...>(), target), 0)... (get<I>(static_cast<base_t&>(*this)) = get<I>(types<Tn...>(), target), 0)...
, 0 }; , 0 };
} }
@ -4122,7 +4159,7 @@ namespace sol {
void set_extra(std::false_type, std::index_sequence<I...>, T&& target) { void set_extra(std::false_type, std::index_sequence<I...>, T&& target) {
using std::get; using std::get;
(void)detail::swallow{ 0, (void)detail::swallow{ 0,
(get<I>(*this) = get<I>(target), 0)... (get<I>(static_cast<base_t&>(*this)) = get<I>(target), 0)...
, 0 }; , 0 };
} }
@ -4580,7 +4617,39 @@ namespace sol {
namespace sol { namespace sol {
namespace detail { namespace detail {
#ifdef _MSC_VER #if defined(__GNUC__) || defined(__clang__)
template <typename T, class seperator_mark = int>
inline std::string ctti_get_type_name() {
const static std::array<std::string, 2> removals = { { "{anonymous}", "(anonymous namespace)" } };
std::string name = __PRETTY_FUNCTION__;
std::size_t start = name.find_first_of('[');
start = name.find_first_of('=', start);
std::size_t end = name.find_last_of(']');
if (end == std::string::npos)
end = name.size();
if (start == std::string::npos)
start = 0;
if (start < name.size() - 1)
start += 1;
name = name.substr(start, end - start);
start = name.rfind("seperator_mark");
if (start != std::string::npos) {
name.erase(start - 2, name.length());
}
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin());
while (!name.empty() && std::isblank(name.back())) name.pop_back();
for (std::size_t r = 0; r < removals.size(); ++r) {
auto found = name.find(removals[r]);
while (found != std::string::npos) {
name.erase(found, removals[r].size());
found = name.find(removals[r]);
}
}
return name;
}
#elif defined(_MSC_VER)
template <typename T> template <typename T>
inline std::string ctti_get_type_name() { inline std::string ctti_get_type_name() {
const static std::array<std::string, 7> removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } }; const static std::array<std::string, 7> removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } };
@ -4611,38 +4680,6 @@ namespace sol {
} }
} }
return name;
}
#elif defined(__GNUC__) || defined(__clang__)
template <typename T, class seperator_mark = int>
inline std::string ctti_get_type_name() {
const static std::array<std::string, 2> removals = { { "{anonymous}", "(anonymous namespace)" } };
std::string name = __PRETTY_FUNCTION__;
std::size_t start = name.find_first_of('[');
start = name.find_first_of('=', start);
std::size_t end = name.find_last_of(']');
if (end == std::string::npos)
end = name.size();
if (start == std::string::npos)
start = 0;
if (start < name.size() - 1)
start += 1;
name = name.substr(start, end - start);
start = name.rfind("seperator_mark");
if (start != std::string::npos) {
name.erase(start - 2, name.length());
}
while (!name.empty() && std::isblank(name.front())) name.erase(name.begin());
while (!name.empty() && std::isblank(name.back())) name.pop_back();
for (std::size_t r = 0; r < removals.size(); ++r) {
auto found = name.find(removals[r]);
while (found != std::string::npos) {
name.erase(found, removals[r].size());
found = name.find(removals[r]);
}
}
return name; return name;
} }
#else #else
@ -5458,7 +5495,7 @@ namespace sol {
if (len < 1) if (len < 1)
return std::wstring(); return std::wstring();
if (sizeof(wchar_t) == 2) { if (sizeof(wchar_t) == 2) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
std::wstring r = convert.from_bytes(str, str + len); std::wstring r = convert.from_bytes(str, str + len);
#ifdef __MINGW32__ #ifdef __MINGW32__
// Fuck you, MinGW, and fuck you libstdc++ for introducing this absolutely asinine bug // Fuck you, MinGW, and fuck you libstdc++ for introducing this absolutely asinine bug
@ -5471,7 +5508,7 @@ namespace sol {
#endif #endif
return r; return r;
} }
std::wstring_convert<std::codecvt_utf8<wchar_t>> convert; static std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
std::wstring r = convert.from_bytes(str, str + len); std::wstring r = convert.from_bytes(str, str + len);
return r; return r;
} }
@ -5486,12 +5523,12 @@ namespace sol {
if (len < 1) if (len < 1)
return std::u16string(); return std::u16string();
#ifdef _MSC_VER #ifdef _MSC_VER
std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert; static std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert;
auto intd = convert.from_bytes(str, str + len); auto intd = convert.from_bytes(str, str + len);
std::u16string r(intd.size(), '\0'); std::u16string r(intd.size(), '\0');
std::memcpy(&r[0], intd.data(), intd.size() * sizeof(char16_t)); std::memcpy(&r[0], intd.data(), intd.size() * sizeof(char16_t));
#else #else
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
std::u16string r = convert.from_bytes(str, str + len); std::u16string r = convert.from_bytes(str, str + len);
#endif // VC++ is a shit #endif // VC++ is a shit
return r; return r;
@ -5507,12 +5544,12 @@ namespace sol {
if (len < 1) if (len < 1)
return std::u32string(); return std::u32string();
#ifdef _MSC_VER #ifdef _MSC_VER
std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t> convert; static std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t> convert;
auto intd = convert.from_bytes(str, str + len); auto intd = convert.from_bytes(str, str + len);
std::u32string r(intd.size(), '\0'); std::u32string r(intd.size(), '\0');
std::memcpy(&r[0], intd.data(), r.size() * sizeof(char32_t)); std::memcpy(&r[0], intd.data(), r.size() * sizeof(char32_t));
#else #else
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; static std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
std::u32string r = convert.from_bytes(str, str + len); std::u32string r = convert.from_bytes(str, str + len);
#endif // VC++ is a shit #endif // VC++ is a shit
return r; return r;
@ -6394,11 +6431,11 @@ namespace sol {
static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) {
if (sizeof(wchar_t) == 2) { if (sizeof(wchar_t) == 2) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
std::string u8str = convert.to_bytes(strb, stre); std::string u8str = convert.to_bytes(strb, stre);
return stack::push(L, u8str); return stack::push(L, u8str);
} }
std::wstring_convert<std::codecvt_utf8<wchar_t>> convert; static std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
std::string u8str = convert.to_bytes(strb, stre); std::string u8str = convert.to_bytes(strb, stre);
return stack::push(L, u8str); return stack::push(L, u8str);
} }
@ -6416,10 +6453,10 @@ namespace sol {
static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { static int push(lua_State* L, const char16_t* strb, const char16_t* stre) {
#ifdef _MSC_VER #ifdef _MSC_VER
std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert; static std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert;
std::string u8str = convert.to_bytes(reinterpret_cast<const int16_t*>(strb), reinterpret_cast<const int16_t*>(stre)); std::string u8str = convert.to_bytes(reinterpret_cast<const int16_t*>(strb), reinterpret_cast<const int16_t*>(stre));
#else #else
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
std::string u8str = convert.to_bytes(strb, stre); std::string u8str = convert.to_bytes(strb, stre);
#endif // VC++ is a shit #endif // VC++ is a shit
return stack::push(L, u8str); return stack::push(L, u8str);
@ -6438,10 +6475,10 @@ namespace sol {
static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { static int push(lua_State* L, const char32_t* strb, const char32_t* stre) {
#ifdef _MSC_VER #ifdef _MSC_VER
std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t> convert; static std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t> convert;
std::string u8str = convert.to_bytes(reinterpret_cast<const int32_t*>(strb), reinterpret_cast<const int32_t*>(stre)); std::string u8str = convert.to_bytes(reinterpret_cast<const int32_t*>(strb), reinterpret_cast<const int32_t*>(stre));
#else #else
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; static std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
std::string u8str = convert.to_bytes(strb, stre); std::string u8str = convert.to_bytes(strb, stre);
#endif // VC++ is a shit #endif // VC++ is a shit
return stack::push(L, u8str); return stack::push(L, u8str);
@ -7632,7 +7669,7 @@ namespace sol {
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
} }
if (traits::free_arity != fxarity) { if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) {
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
} }
stack::record tracking{}; stack::record tracking{};
@ -7656,7 +7693,7 @@ namespace sol {
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
} }
if (traits::free_arity != fxarity) { if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) {
return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
} }
return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...);
@ -7671,7 +7708,7 @@ namespace sol {
if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) {
return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
} }
if (traits::free_arity != fxarity) { if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) {
return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
} }
stack::record tracking{}; stack::record tracking{};
@ -8057,7 +8094,7 @@ namespace sol {
}; };
static int call(lua_State* L, F& fx) { static int call(lua_State* L, F& fx) {
return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx); return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx);
} }
}; };
@ -8498,7 +8535,7 @@ namespace sol {
namespace sol { namespace sol {
namespace function_detail { namespace function_detail {
template <typename... Functions> template <int start_skew = 0, typename... Functions>
struct overloaded_function { struct overloaded_function {
typedef std::tuple<Functions...> overload_list; typedef std::tuple<Functions...> overload_list;
typedef std::make_index_sequence<sizeof...(Functions)> indices; typedef std::make_index_sequence<sizeof...(Functions)> indices;
@ -8515,12 +8552,12 @@ namespace sol {
template <typename Fx, std::size_t I, typename... R, typename... Args> template <typename Fx, std::size_t I, typename... R, typename... Args>
int call(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int) { int call(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int) {
auto& func = std::get<I>(overloads); auto& func = std::get<I>(overloads);
return call_detail::call_wrapped<void, true, false>(L, func); return call_detail::call_wrapped<void, true, false, start_skew>(L, func);
} }
int operator()(lua_State* L) { int operator()(lua_State* L) {
auto mfx = [&](auto&&... args) { return this->call(std::forward<decltype(args)>(args)...); }; auto mfx = [&](auto&&... args) { return this->call(std::forward<decltype(args)>(args)...); };
return call_detail::overload_match<Functions...>(mfx, L, 1); return call_detail::overload_match<Functions...>(mfx, L, 1 + start_skew);
} }
}; };
} // function_detail } // function_detail
@ -8531,9 +8568,10 @@ namespace sol {
// beginning of sol/resolve.hpp // beginning of sol/resolve.hpp
namespace sol { namespace sol {
// Clang has distinct problems with constexpr arguments,
// so don't use the constexpr versions inside of clang.
#ifndef __clang__ #ifndef __clang__
// constexpr is fine for not-clang
namespace detail { namespace detail {
template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>> template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>>
inline constexpr auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) { inline constexpr auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) {
@ -8600,6 +8638,10 @@ namespace sol {
return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
} }
#else #else
// Clang has distinct problems with constexpr arguments,
// so don't use the constexpr versions inside of clang.
namespace detail { namespace detail {
template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>> template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>>
inline auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) { inline auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) {
@ -8665,12 +8707,20 @@ namespace sol {
inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) {
return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); return detail::resolve_i(types<Sig...>(), std::forward<F>(f));
} }
#endif #endif
} // sol } // sol
// end of sol/resolve.hpp // end of sol/resolve.hpp
namespace sol { namespace sol {
namespace function_detail {
template<typename T>
struct class_indicator {};
struct call_indicator {};
}
namespace stack { namespace stack {
template<typename... Sigs> template<typename... Sigs>
struct pusher<function_sig<Sigs...>> { struct pusher<function_sig<Sigs...>> {
@ -8726,12 +8776,19 @@ namespace sol {
select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
} }
template <typename Fx, typename T, typename... Args> template <typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<function_detail::class_indicator, meta::unqualified_t<T>>> = meta::enabler>
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference; typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
} }
template <typename Fx, typename C>
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call;
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
stack::push(L, c_closure(freefunc, upvalues));
}
template <typename Fx> template <typename Fx>
static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) {
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
@ -8764,12 +8821,19 @@ namespace sol {
select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...);
} }
template <typename Fx, typename T, typename... Args> template <typename Fx, typename T, typename... Args, meta::disable<meta::is_specialization_of<function_detail::class_indicator, meta::unqualified_t<T>>> = meta::enabler>
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) {
typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference; typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference;
select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...);
} }
template <typename Fx, typename C>
static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator<C>) {
lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call;
int upvalues = stack::stack_detail::push_as_upvalues(L, fx);
stack::push(L, c_closure(freefunc, upvalues));
}
template <typename Fx> template <typename Fx>
static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { static void select_member_function(std::true_type, lua_State* L, Fx&& fx) {
typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C;
@ -8842,9 +8906,9 @@ namespace sol {
template<typename Signature> template<typename Signature>
struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> { struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> {
template <typename F> template <typename F, typename... Args>
static int push(lua_State* L, F&& f) { static int push(lua_State* L, F&& f, Args&&... args) {
return pusher<function_sig<>>{}.push(L, std::forward<F>(f)); return pusher<function_sig<>>{}.push(L, std::forward<F>(f), std::forward<Args>(args)...);
} }
}; };
@ -8859,13 +8923,13 @@ namespace sol {
template<typename... Functions> template<typename... Functions>
struct pusher<overload_set<Functions...>> { struct pusher<overload_set<Functions...>> {
static int push(lua_State* L, overload_set<Functions...>&& set) { static int push(lua_State* L, overload_set<Functions...>&& set) {
typedef function_detail::overloaded_function<Functions...> F; typedef function_detail::overloaded_function<0, Functions...> F;
pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions)); pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions));
return 1; return 1;
} }
static int push(lua_State* L, const overload_set<Functions...>& set) { static int push(lua_State* L, const overload_set<Functions...>& set) {
typedef function_detail::overloaded_function<Functions...> F; typedef function_detail::overloaded_function<0, Functions...> F;
pusher<function_sig<>>{}.set_fx<F>(L, set.functions); pusher<function_sig<>>{}.set_fx<F>(L, set.functions);
return 1; return 1;
} }
@ -8929,16 +8993,28 @@ namespace sol {
template <typename... Functions> template <typename... Functions>
struct pusher<factory_wrapper<Functions...>> { struct pusher<factory_wrapper<Functions...>> {
static int push(lua_State* L, const factory_wrapper<Functions...>& fw) { static int push(lua_State* L, const factory_wrapper<Functions...>& fw) {
typedef function_detail::overloaded_function<Functions...> F; typedef function_detail::overloaded_function<0, Functions...> F;
pusher<function_sig<>>{}.set_fx<F>(L, fw.functions); pusher<function_sig<>>{}.set_fx<F>(L, fw.functions);
return 1; return 1;
} }
static int push(lua_State* L, factory_wrapper<Functions...>&& fw) { static int push(lua_State* L, factory_wrapper<Functions...>&& fw) {
typedef function_detail::overloaded_function<Functions...> F; typedef function_detail::overloaded_function<0, Functions...> F;
pusher<function_sig<>>{}.set_fx<F>(L, std::move(fw.functions)); pusher<function_sig<>>{}.set_fx<F>(L, std::move(fw.functions));
return 1; return 1;
} }
static int push(lua_State* L, const factory_wrapper<Functions...>& set, function_detail::call_indicator) {
typedef function_detail::overloaded_function<1, Functions...> F;
pusher<function_sig<>>{}.set_fx<F>(L, set.functions);
return 1;
}
static int push(lua_State* L, factory_wrapper<Functions...>&& set, function_detail::call_indicator) {
typedef function_detail::overloaded_function<1, Functions...> F;
pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions));
return 1;
}
}; };
template <typename T, typename... Lists> template <typename T, typename... Lists>
@ -9653,11 +9729,18 @@ namespace sol {
const_reverse_iterator crend() const { return std::reverse_iterator<const_iterator>(cend()); } const_reverse_iterator crend() const { return std::reverse_iterator<const_iterator>(cend()); }
int push() const { int push() const {
return push(L);
}
int push(lua_State* target) const {
int pushcount = 0; int pushcount = 0;
for (int i = index; i <= stacktop; ++i) { for (int i = index; i <= stacktop; ++i) {
lua_pushvalue(L, i); lua_pushvalue(L, i);
pushcount += 1; pushcount += 1;
} }
if (target != L) {
lua_xmove(L, target, pushcount);
}
return pushcount; return pushcount;
} }
@ -9687,8 +9770,8 @@ namespace sol {
template <> template <>
struct pusher<variadic_args> { struct pusher<variadic_args> {
static int push(lua_State*, const variadic_args& ref) { static int push(lua_State* L, const variadic_args& ref) {
return ref.push(); return ref.push(L);
} }
}; };
} // stack } // stack
@ -9906,7 +9989,7 @@ namespace sol {
} }
bool valid() const { bool valid() const {
stack::push_pop(tbl); auto pp = stack::push_pop(tbl);
auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(tbl.lua_state(), key, lua_gettop(tbl.lua_state())); auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(tbl.lua_state(), key, lua_gettop(tbl.lua_state()));
lua_pop(tbl.lua_state(), p.levels); lua_pop(tbl.lua_state(), p.levels);
return p; return p;
@ -10073,9 +10156,9 @@ namespace sol {
auto maybeaccessor = stack::get<optional<string_detail::string_shim>>(L, is_index ? -1 : -2); auto maybeaccessor = stack::get<optional<string_detail::string_shim>>(L, is_index ? -1 : -2);
string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)"));
if (is_index) if (is_index)
return luaL_error(L, "sol: attempt to index (get) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str());
else else
return luaL_error(L, "sol: attempt to index (set) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str());
} }
template <bool is_index, typename Base> template <bool is_index, typename Base>
@ -10153,20 +10236,23 @@ namespace sol {
struct verified_tag {} const verified{}; struct verified_tag {} const verified{};
template <typename T> template <typename T>
struct is_constructor : std::false_type {}; struct is_non_factory_constructor : std::false_type {};
template <typename... Args> template <typename... Args>
struct is_constructor<constructors<Args...>> : std::true_type {}; struct is_non_factory_constructor<constructors<Args...>> : std::true_type {};
template <typename... Args> template <typename... Args>
struct is_constructor<constructor_wrapper<Args...>> : std::true_type {}; struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type {};
template <>
struct is_non_factory_constructor<no_construction> : std::true_type {};
template <typename T>
struct is_constructor : is_non_factory_constructor<T> {};
template <typename... Args> template <typename... Args>
struct is_constructor<factory_wrapper<Args...>> : std::true_type {}; struct is_constructor<factory_wrapper<Args...>> : std::true_type {};
template <>
struct is_constructor<no_construction> : std::true_type {};
template <typename... Args> template <typename... Args>
using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>; using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>;
@ -10391,8 +10477,14 @@ namespace sol {
template <std::size_t Idx, bool is_index = true, bool is_variable = false> template <std::size_t Idx, bool is_index = true, bool is_variable = false>
static int real_call_with(lua_State* L, usertype_metatable& um) { static int real_call_with(lua_State* L, usertype_metatable& um) {
typedef meta::unqualified_tuple_element_t<Idx - 1, Tuple> K;
typedef meta::unqualified_tuple_element_t<Idx, Tuple> F;
static const int boost =
!usertype_detail::is_non_factory_constructor<F>::value
&& std::is_same<K, call_construction>::value ?
1 : 0;
auto& f = std::get<Idx>(um.functions); auto& f = std::get<Idx>(um.functions);
return call_detail::call_wrapped<T, is_index, is_variable>(L, f); return call_detail::call_wrapped<T, is_index, is_variable, boost>(L, f);
} }
template <std::size_t Idx, bool is_index = true, bool is_variable = false> template <std::size_t Idx, bool is_index = true, bool is_variable = false>
@ -10637,10 +10729,13 @@ namespace sol {
lua_settop(L, 0); lua_settop(L, 0);
return 0; return 0;
} }
lua_pop(L, 1);
return indexing_fail<false>(L); return indexing_fail<false>(L);
} }
inline int simple_indexing_fail(lua_State* L) {
return stack::push(L, sol::lua_nil);
}
template <bool is_index, bool toplevel = false> template <bool is_index, bool toplevel = false>
inline int simple_core_indexing_call(lua_State* L) { inline int simple_core_indexing_call(lua_State* L) {
simple_map& sm = toplevel ? stack::get<user<simple_map>>(L, upvalue_index(1)) : stack::pop<user<simple_map>>(L); simple_map& sm = toplevel ? stack::get<user<simple_map>>(L, upvalue_index(1)) : stack::pop<user<simple_map>>(L);
@ -10747,14 +10842,31 @@ namespace sol {
hint->second = std::move(o); hint->second = std::move(o);
} }
template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler> template <typename N, typename F, typename... Args>
void add_function(lua_State* L, N&& n, F&& f) { void insert_prepare(std::true_type, lua_State* L, N&&, F&& f, Args&&... args) {
insert(std::forward<N>(n), make_object(L, as_function_reference(std::forward<F>(f)))); object o = make_object<F>(L, std::forward<F>(f), function_detail::call_indicator(), std::forward<Args>(args)...);
callconstructfunc = std::move(o);
} }
template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler> template <typename N, typename F, typename... Args>
void insert_prepare(std::false_type, lua_State* L, N&& n, F&& f, Args&&... args) {
object o = make_object<F>(L, std::forward<F>(f), std::forward<Args>(args)...);
insert(std::forward<N>(n), std::move(o));
}
template <typename N, typename F>
void add_member_function(std::true_type, lua_State* L, N&& n, F&& f) {
insert_prepare(std::is_same<meta::unqualified_t<N>, call_construction>(), L, std::forward<N>(n), std::forward<F>(f), function_detail::class_indicator<T>());
}
template <typename N, typename F>
void add_member_function(std::false_type, lua_State* L, N&& n, F&& f) {
insert_prepare(std::is_same<meta::unqualified_t<N>, call_construction>(), L, std::forward<N>(n), std::forward<F>(f));
}
template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
void add_function(lua_State* L, N&& n, F&& f) { void add_function(lua_State* L, N&& n, F&& f) {
object o = make_object(L, std::forward<F>(f)); object o = make_object(L, as_function_reference(std::forward<F>(f)));
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
callconstructfunc = std::move(o); callconstructfunc = std::move(o);
return; return;
@ -10762,6 +10874,11 @@ namespace sol {
insert(std::forward<N>(n), std::move(o)); insert(std::forward<N>(n), std::move(o));
} }
template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
void add_function(lua_State* L, N&& n, F&& f) {
add_member_function(std::is_member_pointer<meta::unwrap_unqualified_t<F>>(), L, std::forward<N>(n), std::forward<F>(f));
}
template <typename N, typename F, meta::disable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler> template <typename N, typename F, meta::disable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler>
void add(lua_State* L, N&& n, F&& f) { void add(lua_State* L, N&& n, F&& f) {
add_function(L, std::forward<N>(n), std::forward<F>(f)); add_function(L, std::forward<N>(n), std::forward<F>(f));
@ -10842,7 +10959,7 @@ namespace sol {
template<std::size_t... I, typename Tuple> template<std::size_t... I, typename Tuple>
simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args) simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args)
: callconstructfunc(lua_nil), : callconstructfunc(lua_nil),
indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>), indexfunc(&usertype_detail::simple_indexing_fail), newindexfunc(&usertype_detail::simple_metatable_newindex<T>),
indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>), indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>),
indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>), indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>),
baseclasscheck(nullptr), baseclasscast(nullptr), baseclasscheck(nullptr), baseclasscast(nullptr),
@ -11072,15 +11189,15 @@ namespace sol {
stack::set_field(L, meta_function::index, stack::set_field(L, meta_function::index,
make_closure(&usertype_detail::simple_index_call, make_closure(&usertype_detail::simple_index_call,
make_light(varmap), make_light(varmap),
&usertype_detail::simple_index_call, umx.indexfunc,
&usertype_detail::simple_metatable_newindex<T>, umx.newindexfunc,
usertype_detail::toplevel_magic usertype_detail::toplevel_magic
), metabehind.stack_index()); ), metabehind.stack_index());
stack::set_field(L, meta_function::new_index, stack::set_field(L, meta_function::new_index,
make_closure(&usertype_detail::simple_new_index_call, make_closure(&usertype_detail::simple_new_index_call,
make_light(varmap), make_light(varmap),
&usertype_detail::simple_index_call, umx.indexfunc,
&usertype_detail::simple_metatable_newindex<T>, umx.newindexfunc,
usertype_detail::toplevel_magic usertype_detail::toplevel_magic
), metabehind.stack_index()); ), metabehind.stack_index());
stack::set_field(L, metatable_key, metabehind, t.stack_index()); stack::set_field(L, metatable_key, metabehind, t.stack_index());
@ -12829,7 +12946,23 @@ namespace sol {
stack::luajit_exception_handler(unique_base::get()); stack::luajit_exception_handler(unique_base::get());
} }
state(const state&) = delete;
state(state&&) = default;
state& operator=(const state&) = delete;
state& operator=(state&& that) {
state_view::operator=(std::move(that));
unique_base::operator=(std::move(that));
return *this;
}
using state_view::get; using state_view::get;
~state() {
auto& handler = protected_function::get_default_handler();
if (handler.lua_state() == this->lua_state()) {
protected_function::set_default_handler(reference());
}
}
}; };
} // sol } // sol
@ -13079,6 +13212,8 @@ namespace sol {
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#elif defined _MSC_VER
#pragma warning( push )
#endif // g++ #endif // g++
#ifdef SOL_INSIDE_UNREAL #ifdef SOL_INSIDE_UNREAL

View File

@ -22,7 +22,8 @@ namespace
// creates a default edge of unit weight // creates a default edge of unit weight
inline InputEdge MakeUnitEdge(const NodeID from, const NodeID to) inline InputEdge MakeUnitEdge(const NodeID from, const NodeID to)
{ {
// src, tgt, dist, edge_id, name_id, fwd, bkwd, roundabout, circular, travel_mode // src, tgt, dist, edge_id, name_id, fwd, bkwd, roundabout, circular, startpoint, local access,
// split edge, travel_mode
return {from, return {from,
to, to,
1, 1,
@ -32,6 +33,7 @@ inline InputEdge MakeUnitEdge(const NodeID from, const NodeID to)
false, false,
false, false,
false, false,
false,
true, true,
TRAVEL_MODE_INACCESSIBLE, TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_DESCRIPTIONID}; INVALID_LANE_DESCRIPTIONID};

View File

@ -1,11 +1,27 @@
#ifndef OSRM_UNIT_TEST_ARGS #ifndef OSRM_UNIT_TEST_ARGS
#define OSRM_UNIT_TEST_ARGS #define OSRM_UNIT_TEST_ARGS
#include "util/log.hpp"
#include <boost/filesystem.hpp>
#include <iostream>
#include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
inline std::vector<std::string> get_args() inline std::vector<std::string> get_args()
{ {
osrm::util::LogPolicy::GetInstance().Unmute();
if ((boost::unit_test::framework::master_test_suite().argc != 2) ||
(!boost::filesystem::is_regular_file(
boost::unit_test::framework::master_test_suite().argv[1])))
{
osrm::util::Log(logERROR) << "Please provide valid input osrm file";
osrm::util::Log(logERROR) << "Usage: "
<< boost::unit_test::framework::master_test_suite().argv[0]
<< " /path/to/input_osrm_file" << std::endl;
std::exit(EXIT_FAILURE);
}
// Split off argv[0], store actual positional arguments in args // Split off argv[0], store actual positional arguments in args
const auto argc = boost::unit_test::framework::master_test_suite().argc - 1; const auto argc = boost::unit_test::framework::master_test_suite().argc - 1;
const auto argv = boost::unit_test::framework::master_test_suite().argv + 1; const auto argv = boost::unit_test::framework::master_test_suite().argv + 1;

View File

@ -387,4 +387,72 @@ BOOST_AUTO_TEST_CASE(test_route_user_disables_generating_hints)
BOOST_CHECK_EQUAL(waypoint.get<json::Object>().values.count("hint"), 0); BOOST_CHECK_EQUAL(waypoint.get<json::Object>().values.count("hint"), 0);
} }
BOOST_AUTO_TEST_CASE(speed_annotation_matches_duration_and_distance)
{
const auto args = get_args();
auto osrm = getOSRM(args.at(0));
using namespace osrm;
RouteParameters params;
params.annotations_type = RouteParameters::AnnotationsType::Duration |
RouteParameters::AnnotationsType::Distance |
RouteParameters::AnnotationsType::Speed;
params.coordinates.push_back(get_dummy_location());
params.coordinates.push_back(get_dummy_location());
json::Object result;
const auto rc = osrm.Route(params, result);
BOOST_CHECK(rc == Status::Ok);
const auto &routes = result.values["routes"].get<json::Array>().values;
const auto &legs = routes[0].get<json::Object>().values.at("legs").get<json::Array>().values;
const auto &annotation =
legs[0].get<json::Object>().values.at("annotation").get<json::Object>();
const auto &speeds = annotation.values.at("speed").get<json::Array>().values;
const auto &durations = annotation.values.at("duration").get<json::Array>().values;
const auto &distances = annotation.values.at("distance").get<json::Array>().values;
int length = speeds.size();
for (int i = 0; i < length; i++)
{
auto speed = speeds[i].get<json::Number>().value;
auto duration = durations[i].get<json::Number>().value;
auto distance = distances[i].get<json::Number>().value;
BOOST_CHECK_EQUAL(speed, std::round(distance / duration * 10.) / 10.);
}
}
BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property)
{
const auto args = get_args();
auto osrm = getOSRM(args.at(0));
using namespace osrm;
RouteParameters params{};
params.annotations = true;
params.coordinates.push_back(get_dummy_location());
params.coordinates.push_back(get_dummy_location());
json::Object result;
const auto rc = osrm.Route(params, result);
BOOST_CHECK(rc == Status::Ok);
const auto code = result.values.at("code").get<json::String>().value;
BOOST_CHECK_EQUAL(code, "Ok");
auto annotations = result.values["routes"]
.get<json::Array>()
.values[0]
.get<json::Object>()
.values["legs"]
.get<json::Array>()
.values[0]
.get<json::Object>()
.values["annotation"]
.get<json::Object>()
.values;
BOOST_CHECK_EQUAL(annotations.size(), 5);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(test_tile)
const auto rc = osrm.Tile(params, result); const auto rc = osrm.Tile(params, result);
BOOST_CHECK(rc == Status::Ok); BOOST_CHECK(rc == Status::Ok);
BOOST_CHECK_EQUAL(result.size(), 113824); BOOST_CHECK(result.size() > 114000);
protozero::pbf_reader tile_message(result); protozero::pbf_reader tile_message(result);
tile_message.next(); tile_message.next();
@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE(test_tile)
} }
BOOST_CHECK_EQUAL(number_of_turn_keys, 3); BOOST_CHECK_EQUAL(number_of_turn_keys, 3);
BOOST_CHECK_EQUAL(number_of_turns_found, 732); BOOST_CHECK(number_of_turns_found > 700);
} }
BOOST_AUTO_TEST_CASE(test_tile_turns) BOOST_AUTO_TEST_CASE(test_tile_turns)

View File

@ -67,6 +67,7 @@ BOOST_AUTO_TEST_CASE(invalid_route_urls)
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>(std::string{"1,2;3,"} + '\0'), 6); BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>(std::string{"1,2;3,"} + '\0'), 6);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations=distances"), 28UL); BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations=distances"), 28UL);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations="), 20UL); BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations="), 20UL);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations=true,false"), 24UL);
BOOST_CHECK_EQUAL( BOOST_CHECK_EQUAL(
testInvalidOptions<RouteParameters>("1,2;3,4?annotations=&overview=simplified"), 20UL); testInvalidOptions<RouteParameters>("1,2;3,4?annotations=&overview=simplified"), 20UL);
@ -349,6 +350,22 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
true); true);
BOOST_CHECK_EQUAL(result_15->annotations, true); BOOST_CHECK_EQUAL(result_15->annotations, true);
RouteParameters reference_speed{};
reference_speed.annotations_type = RouteParameters::AnnotationsType::Duration;
reference_speed.coordinates = coords_1;
auto result_speed =
parseParameters<RouteParameters>("1,2;3,4?geometries=polyline&"
"overview=simplified&annotations=duration,distance,speed");
BOOST_CHECK(result_speed);
BOOST_CHECK_EQUAL(reference_speed.geometries, result_speed->geometries);
BOOST_CHECK_EQUAL(reference_speed.overview, result_speed->overview);
BOOST_CHECK_EQUAL(result_speed->annotations_type ==
(RouteParameters::AnnotationsType::Duration |
RouteParameters::AnnotationsType::Distance |
RouteParameters::AnnotationsType::Speed),
true);
BOOST_CHECK_EQUAL(result_speed->annotations, true);
// parse multiple annotations correctly // parse multiple annotations correctly
RouteParameters reference_16{}; RouteParameters reference_16{};
reference_16.annotations_type = RouteParameters::AnnotationsType::Duration | reference_16.annotations_type = RouteParameters::AnnotationsType::Duration |