Merge branch 'master' into sf-tbb3

This commit is contained in:
Siarhei Fedartsou 2022-08-23 22:24:22 +02:00
commit d68f66f759
60 changed files with 1081 additions and 600 deletions

View File

@ -49,7 +49,6 @@ Checks: >
-misc-unused-parameters, -misc-unused-parameters,
performance-*, performance-*,
-performance-noexcept-move-constructor, -performance-noexcept-move-constructor,
-performance-move-const-arg,
-performance-no-int-to-ptr, -performance-no-int-to-ptr,
readability-*, readability-*,
-readability-avoid-const-params-in-decls, -readability-avoid-const-params-in-decls,

View File

@ -469,9 +469,9 @@ jobs:
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: ${{github.workspace}}/test/cache path: ${{github.workspace}}/test/cache
key: v2-test-${{ matrix.name }}-${{ github.sha }} key: v3-test-${{ matrix.name }}-${{ github.sha }}
restore-keys: | restore-keys: |
v2-test-${{ matrix.name }}- v3-test-${{ matrix.name }}-
- name: Prepare environment - name: Prepare environment
run: | run: |
@ -668,7 +668,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
ci-complete: ci-complete:
runs-on: ubuntu-18.04 runs-on: ubuntu-22.04
needs: [build-test-publish, docker-image, windows] needs: [build-test-publish, docker-image, windows]
steps: steps:
- run: echo "CI complete" - run: echo "CI complete"

View File

@ -1,17 +1,23 @@
# Unreleased # Unreleased
- Changes from 5.26.0 - Changes from 5.26.0
- API: - API:
- CHANGED: Add `data_version` field to responses of all services. [#5387](https://github.com/Project-OSRM/osrm-backend/pull/5387)
- FIXED: Use Boost.Beast to parse HTTP request. [#6294](https://github.com/Project-OSRM/osrm-backend/pull/6294) - FIXED: Use Boost.Beast to parse HTTP request. [#6294](https://github.com/Project-OSRM/osrm-backend/pull/6294)
- FIXED: Fix inefficient osrm-routed connection handling [#6113](https://github.com/Project-OSRM/osrm-backend/pull/6113) - FIXED: Fix inefficient osrm-routed connection handling [#6113](https://github.com/Project-OSRM/osrm-backend/pull/6113)
- NodeJS:
- FIXED: Support `skip_waypoints` in Node bindings [#6060](https://github.com/Project-OSRM/osrm-backend/pull/6060)
- Misc: - Misc:
- CHANGED: missing files list is included in exception message. [#5360](https://github.com/Project-OSRM/osrm-backend/pull/5360)
- CHANGED: Do not use deprecated Callback::Call overload in Node bindings. [#6318](https://github.com/Project-OSRM/osrm-backend/pull/6318) - CHANGED: Do not use deprecated Callback::Call overload in Node bindings. [#6318](https://github.com/Project-OSRM/osrm-backend/pull/6318)
- FIXED: Fix distance calculation consistency. [#6315](https://github.com/Project-OSRM/osrm-backend/pull/6315) - FIXED: Fix distance calculation consistency. [#6315](https://github.com/Project-OSRM/osrm-backend/pull/6315)
- FIXED: Fix performance issue after migration to sol2 3.3.0. [#6304](https://github.com/Project-OSRM/osrm-backend/pull/6304) - FIXED: Fix performance issue after migration to sol2 3.3.0. [#6304](https://github.com/Project-OSRM/osrm-backend/pull/6304)
- CHANGED: Pass osm_node_ids by reference in osrm::updater::Updater class. [#6298](https://github.com/Project-OSRM/osrm-backend/pull/6298) - CHANGED: Pass osm_node_ids by reference in osrm::updater::Updater class. [#6298](https://github.com/Project-OSRM/osrm-backend/pull/6298)
- FIXED: Fix bug with reading Set values from Lua scripts. [#6285](https://github.com/Project-OSRM/osrm-backend/pull/6285) - FIXED: Fix bug with reading Set values from Lua scripts. [#6285](https://github.com/Project-OSRM/osrm-backend/pull/6285)
- FIXED: Bug in bicycle profile that caused exceptions if there is a highway=bicycle in the data. [#6296](https://github.com/Project-OSRM/osrm-backend/pull/6296) - FIXED: Bug in bicycle profile that caused exceptions if there is a highway=bicycle in the data. [#6296](https://github.com/Project-OSRM/osrm-backend/pull/6296)
- FIXED: Internal refactoring of identifier types used in data facade [#6044](https://github.com/Project-OSRM/osrm-backend/pull/6044)
- Build: - Build:
- CHANGED: Migrate to modern TBB version. [#6300](https://github.com/Project-OSRM/osrm-backend/pull/6300) - CHANGED: Migrate to modern TBB version. [#6300](https://github.com/Project-OSRM/osrm-backend/pull/6300)
- CHANGED: Enable performance-move-const-arg clang-tidy check. [#6319](https://github.com/Project-OSRM/osrm-backend/pull/6319)
- CHANGED: Use the latest node on CI. [#6317](https://github.com/Project-OSRM/osrm-backend/pull/6317) - CHANGED: Use the latest node on CI. [#6317](https://github.com/Project-OSRM/osrm-backend/pull/6317)
- CHANGED: Migrate Windows CI to GitHub Actions. [#6312](https://github.com/Project-OSRM/osrm-backend/pull/6312) - CHANGED: Migrate Windows CI to GitHub Actions. [#6312](https://github.com/Project-OSRM/osrm-backend/pull/6312)
- ADDED: Add smoke test for Docker image. [#6313](https://github.com/Project-OSRM/osrm-backend/pull/6313) - ADDED: Add smoke test for Docker image. [#6313](https://github.com/Project-OSRM/osrm-backend/pull/6313)
@ -34,6 +40,11 @@
- FIXED: Fixed Node docs generation check in CI. [#6058](https://github.com/Project-OSRM/osrm-backend/pull/6058) - FIXED: Fixed Node docs generation check in CI. [#6058](https://github.com/Project-OSRM/osrm-backend/pull/6058)
- CHANGED: Docker build, enabled arm64 build layer [#6172](https://github.com/Project-OSRM/osrm-backend/pull/6172) - CHANGED: Docker build, enabled arm64 build layer [#6172](https://github.com/Project-OSRM/osrm-backend/pull/6172)
- CHANGED: Docker build, enabled apt-get update/install caching in separate layer for build phase [#6175](https://github.com/Project-OSRM/osrm-backend/pull/6175) - CHANGED: Docker build, enabled apt-get update/install caching in separate layer for build phase [#6175](https://github.com/Project-OSRM/osrm-backend/pull/6175)
- FIXED: Bump CI complete meta job to ubuntu-20.04 [#6323](https://github.com/Project-OSRM/osrm-backend/pull/6323)
- Routing:
- CHANGED: Lazily generate optional route path data [#6045](https://github.com/Project-OSRM/osrm-backend/pull/6045)
- FIXED: Completed support for no_entry and no_exit turn restrictions. [#5988](https://github.com/Project-OSRM/osrm-backend/pull/5988)
- ADDED: Add support for non-round-trips with a single fixed endpoint. [#6050](https://github.com/Project-OSRM/osrm-backend/pull/6050)
# 5.26.0 # 5.26.0
- Changes from 5.25.0 - Changes from 5.25.0

View File

@ -507,8 +507,8 @@ Right now, the following combinations are possible:
| true | any | last | **yes** | | true | any | last | **yes** |
| true | any | any | **yes** | | true | any | any | **yes** |
| false | first | last | **yes** | | false | first | last | **yes** |
| false | first | any | no | | false | first | any | **yes** |
| false | any | last | no | | false | any | last | **yes** |
| false | any | any | no | | false | any | any | no |
#### Example Requests #### Example Requests

View File

@ -1008,3 +1008,123 @@ Feature: Car - Turn restrictions
| from | to | route | | from | to | route |
| d | x | bd,abc,xa,xa | | d | x | bd,abc,xa,xa |
| d | z | bd,abc,cz,cz | | d | z | bd,abc,cz,cz |
Scenario: Multiple restricted entrances
Given the node map
"""
b
|
a----e----c
|
d
"""
And the ways
| nodes |
| ae |
| be |
| ce |
| de |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ae,be | ed | e | no_entry |
When I route I should get
| from | to | route |
| a | d | ae,ce,ce,de,de |
| b | d | be,ce,ce,de,de |
| c | d | ce,de,de |
Scenario: Multiple restricted exits
Given the node map
"""
b
|
a----e----c
|
d
"""
And the ways
| nodes |
| ae |
| be |
| ce |
| de |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ae | ce,de | e | no_exit |
When I route I should get
| from | to | route |
| a | b | ae,be,be |
| a | c | ae,be,be,ce,ce |
| a | d | ae,be,be,de,de |
Scenario: Invalid restricted entrances/exits
Given the node map
"""
b
|
a----e----c
|
d
"""
And the ways
| nodes |
| ae |
| be |
| ce |
| de |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ae | ce,de | e | no_entry |
| restriction | ae,be | ed | e | no_exit |
When I route I should get
| from | to | route |
| a | b | ae,be,be |
| a | c | ae,ce,ce |
| a | d | ae,de,de |
| b | d | be,de,de |
| c | d | ce,de,de |
Scenario: Invalid multi from/to restrictions
Given the node map
"""
b
|
a----e----c
|
d
"""
And the ways
| nodes |
| ae |
| be |
| ce |
| de |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ae,de | ce,de | e | no_right_turn |
| restriction | ae,be | ce,de | e | no_straight_on |
| restriction | ae,be | be,ce | e | only_left_turn |
| restriction | ae,be | ce,de | e | only_straight_on |
When I route I should get
| from | to | route |
| a | b | ae,be,be |
| a | c | ae,ce,ce |
| a | d | ae,de,de |
| b | d | be,de,de |
| c | d | ce,de,de |

View File

@ -59,6 +59,31 @@ Feature: Locating Nearest node on a Way - pick closest way
| 3 | u | | 3 | u |
| 4 | w | | 4 | w |
Scenario: Nearest - inside a oneway triangle
Given the node map
"""
c
y z
0 1
2 3 4
a x u w b
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
| ca | yes |
When I request nearest I should get
| in | out |
| 0 | y |
| 1 | z |
| 2 | x |
| 3 | u |
| 4 | w |
Scenario: Nearest - High lat/lon Scenario: Nearest - High lat/lon
Given the node locations Given the node locations
| node | lat | lon | | node | lat | lon |
@ -78,3 +103,30 @@ Feature: Locating Nearest node on a Way - pick closest way
| x | a | | x | a |
| y | b | | y | b |
| z | c | | z | c |
Scenario: Nearest - data version
Given the node map
"""
c
y z
0 1
2 3 4
a x u w b
"""
And the ways
| nodes |
| ab |
| bc |
| ca |
And the extract extra arguments "--data_version cucumber_data_version"
When I request nearest I should get
| in | out | data_version |
| 0 | y | cucumber_data_version |
| 1 | z | cucumber_data_version |
| 2 | x | cucumber_data_version |
| 3 | u | cucumber_data_version |
| 4 | w | cucumber_data_version |

View File

@ -117,6 +117,10 @@ module.exports = function () {
got.duration = duration.toString(); got.duration = duration.toString();
} }
if (headers.has('data_version')) {
got.data_version = json.data_version || '';
}
// 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) => {

View File

@ -8,6 +8,7 @@ module.exports = function () {
this.reprocessAndLoadData((e) => { this.reprocessAndLoadData((e) => {
if (e) return callback(e); if (e) return callback(e);
var testRow = (row, ri, cb) => { var testRow = (row, ri, cb) => {
var inNode = this.findNodeByName(row.in); var inNode = this.findNodeByName(row.in);
if (!inNode) throw new Error(util.format('*** unknown in-node "%s"', row.in)); if (!inNode) throw new Error(util.format('*** unknown in-node "%s"', row.in));
@ -17,6 +18,7 @@ module.exports = function () {
this.requestNearest(inNode, this.queryParams, (err, response) => { this.requestNearest(inNode, this.queryParams, (err, response) => {
if (err) return cb(err); if (err) return cb(err);
var coord; var coord;
var headers = new Set(table.raw()[0]);
if (response.statusCode === 200 && response.body.length) { if (response.statusCode === 200 && response.body.length) {
var json = JSON.parse(response.body); var json = JSON.parse(response.body);
@ -25,6 +27,10 @@ module.exports = function () {
var got = { in: row.in, out: row.out }; var got = { in: row.in, out: row.out };
if (headers.has('data_version')) {
got.data_version = json.data_version || '';
}
Object.keys(row).forEach((key) => { Object.keys(row).forEach((key) => {
if (key === 'out') { if (key === 'out') {
if (this.FuzzyMatch.matchLocation(coord, outNode)) { if (this.FuzzyMatch.matchLocation(coord, outNode)) {

View File

@ -43,6 +43,10 @@ module.exports = function () {
got.message = json.message; got.message = json.message;
} }
if (headers.has('data_version')) {
got.data_version = json.data_version || '';
}
if (headers.has('geometry')) { if (headers.has('geometry')) {
if (this.queryParams['geometries'] === 'polyline') { if (this.queryParams['geometries'] === 'polyline') {
got.geometry = polyline.decode(json.trips[0].geometry).toString(); got.geometry = polyline.decode(json.trips[0].geometry).toString();
@ -61,7 +65,8 @@ module.exports = function () {
var subTrips; var subTrips;
var trip_durations; var trip_durations;
var trip_distance; var trip_distance;
if (res.statusCode === 200) { var ok = res.statusCode === 200;
if (ok) {
if (headers.has('trips')) { if (headers.has('trips')) {
subTrips = json.trips.filter(t => !!t).map(t => t.legs).map(tl => Array.prototype.concat.apply([], tl.map((sl, i) => { subTrips = json.trips.filter(t => !!t).map(t => t.legs).map(tl => Array.prototype.concat.apply([], tl.map((sl, i) => {
var toAdd = []; var toAdd = [];
@ -84,8 +89,7 @@ module.exports = function () {
} }
} }
var ok = true, var encodedResult = '';
encodedResult = '';
if (json.trips) row.trips.split(',').forEach((sub, si) => { if (json.trips) row.trips.split(',').forEach((sub, si) => {
if (si >= subTrips.length) { if (si >= subTrips.length) {

View File

@ -727,3 +727,4 @@ Feature: Basic Distance Matrix
| 1 | 0 | 1000.1 | 1400.1 | | 1 | 0 | 1000.1 | 1400.1 |
| 2 | 1000.1 | 0 | 400 | | 2 | 1000.1 | 0 | 400 |
| 3 | 1400.1 | 400 | 0 | | 3 | 1400.1 | 400 | 0 |

View File

@ -21,8 +21,27 @@ Feature: Basic Map Matching
| abcd | no | | abcd | no |
When I match I should get When I match I should get
| trace | timestamps | matchings | | trace | timestamps | matchings | data_version |
| ab1d | 0 1 2 3 | ad | | ab1d | 0 1 2 3 | ad | |
Scenario: Data_version test on matching
Given a grid size of 100 meters
Given the node map
"""
a b c d
1
"""
And the extract extra arguments "--data_version cucumber_data_version"
And the ways
| nodes | oneway |
| abcd | no |
When I match I should get
| trace | timestamps | matchings | data_version |
| ab1d | 0 1 2 3 | ad | cucumber_data_version |
Scenario: Testbot - Map matching with trace splitting Scenario: Testbot - Map matching with trace splitting
Given the node map Given the node map
@ -793,3 +812,4 @@ Feature: Basic Map Matching
| trace | geometry | a:distance | a:duration | a:weight | duration | | trace | geometry | a:distance | a:duration | a:weight | duration |
| 2345 | 1.00018,1,1.000314,1 | 14.914666 | 1.4 | 1.4 | 1.4 | | 2345 | 1.00018,1,1.000314,1 | 14.914666 | 1.4 | 1.4 | 1.4 |
| 4321 | 1.00027,1,1.000135,1 | 15.02597 | 1.5 | 1.5 | 1.5 | | 4321 | 1.00027,1,1.000135,1 | 15.02597 | 1.5 | 1.5 | 1.5 |

View File

@ -47,11 +47,31 @@ Feature: Snap start/end point to the nearest way
| adb | | adb |
When I route I should get When I route I should get
| from | to | route | | from | to | route | data_version |
| 1 | b | adb,adb | | 1 | b | adb,adb | |
| 2 | b | adb,adb | | 2 | b | adb,adb | |
| 6 | b | aub,aub | | 6 | b | aub,aub | |
| 7 | b | aub,aub | | 7 | b | aub,aub | |
Scenario: Data_version check on nearest
Given the node map
"""
4 5 6 7
3 a u
2
1 d b
"""
And the extract extra arguments "--data_version cucumber_data_version"
And the ways
| nodes |
| aub |
| adb |
When I route I should get
| from | to | route | data_version |
| 1 | b | adb,adb | cucumber_data_version |
Scenario: Snap to edge right under start/end point Scenario: Snap to edge right under start/end point
Given the node map Given the node map

View File

@ -5,7 +5,7 @@ Feature: Basic trip planning
Given the profile "testbot" Given the profile "testbot"
Given a grid size of 10 meters Given a grid size of 10 meters
Scenario: Testbot - Trip: Roundtrip with one waypoint Scenario: Testbot - Trip: Invalid options (like was in test suite for a long time)
Given the node map Given the node map
""" """
a b a b
@ -20,8 +20,46 @@ Feature: Basic trip planning
| da | | da |
When I plan a trip I should get When I plan a trip I should get
| waypoints | trips | | waypoints | trips | code |
| a | aa | | a | | InvalidOptions |
Scenario: Testbot - Trip: Roundtrip between same waypoint
Given the node map
"""
a b
c d
"""
And the ways
| nodes |
| ab |
| bc |
| cb |
| da |
When I plan a trip I should get
| waypoints | trips | code |
| a,a | aa | Ok |
Scenario: Testbot - Trip: data version check
Given the node map
"""
a b
c d
"""
And the ways
| nodes |
| ab |
| bc |
| cb |
| da |
And the extract extra arguments "--data_version cucumber_data_version"
When I plan a trip I should get
| waypoints | trips | data_version | code |
| a,a | aa | cucumber_data_version | Ok |
Scenario: Testbot - Trip: Roundtrip with waypoints (less than 10) Scenario: Testbot - Trip: Roundtrip with waypoints (less than 10)
Given the node map Given the node map
@ -38,9 +76,9 @@ Feature: Basic trip planning
| da | | da |
When I plan a trip I should get When I plan a trip I should get
| waypoints | trips | durations | | waypoints | trips | durations | code |
| a,b,c,d | abcda | 7.6 | | a,b,c,d | abcda | 7.6 | Ok |
| d,b,c,a | dbcad | 7.6 | | d,b,c,a | dbcad | 7.6 | Ok |
Scenario: Testbot - Trip: Roundtrip waypoints (more than 10) Scenario: Testbot - Trip: Roundtrip waypoints (more than 10)
Given the node map Given the node map
@ -69,36 +107,37 @@ Feature: Basic trip planning
| waypoints | trips | | waypoints | trips |
| a,b,c,d,e,f,g,h,i,j,k,l | alkjihgfedcba | | a,b,c,d,e,f,g,h,i,j,k,l | alkjihgfedcba |
Scenario: Testbot - Trip: Roundtrip FS waypoints (more than 10) Scenario: Testbot - Trip: FS waypoints (less than 10)
Given the node map
"""
a b c d
l e
k f
j i h g
"""
And the ways
| nodes |
| ab |
| bc |
| de |
| ef |
| fg |
| gh |
| hi |
| ij |
| jk |
| kl |
| la |
When I plan a trip I should get
| waypoints | source | trips |
| a,b,c,d,e,f,g,h,i,j,k,l | first | alkjihgfedcba |
Scenario: Testbot - Trip: Roundtrip FE waypoints (more than 10)
Given the query options Given the query options
| source | last | | source | first |
Given the node map
"""
a b c d
l e
j i g
"""
And the ways
| nodes |
| ab |
| bc |
| de |
| eg |
| gi |
| ij |
| jl |
| la |
When I plan a trip I should get
| waypoints | trips | roundtrip | durations |
| a,b,c,d,e,g,i,j,l | abcdegijla | true | 22 |
| a,b,c,d,e,g,i,j,l | abcljiged | false | 13 |
Scenario: Testbot - Trip: FS waypoints (more than 10)
Given the query options
| source | first |
Given the node map Given the node map
""" """
a b c d a b c d
@ -122,8 +161,67 @@ Feature: Basic trip planning
| la | | la |
When I plan a trip I should get When I plan a trip I should get
| waypoints | trips | | waypoints | trips | roundtrip | durations |
| a,b,c,d,e,f,g,h,i,j,k,l | lkjihgfedcbal | | a,b,c,d,e,f,g,h,i,j,k,l | alkjihgfedcba | true | 22 |
| a,b,c,d,e,f,g,h,i,j,k,l | acblkjihgfed | false | 13 |
Scenario: Testbot - Trip: FE waypoints (less than 10)
Given the query options
| destination | last |
Given the node map
"""
a b c d
l e
j i g
"""
And the ways
| nodes |
| ab |
| bc |
| de |
| eg |
| gi |
| ij |
| jl |
| la |
When I plan a trip I should get
| waypoints | trips | roundtrip | durations |
| a,b,c,d,e,g,i,j,l | labcdegijl | true | 22 |
| a,b,c,d,e,g,i,j,l | degijabcl | false | 14 |
Scenario: Testbot - Trip: FE waypoints (more than 10)
Given the query options
| destination | last |
Given the node map
"""
a b c d
l e
k f
j i h g
"""
And the ways
| nodes |
| ab |
| bc |
| de |
| ef |
| fg |
| gh |
| hi |
| ij |
| jk |
| kl |
| la |
When I plan a trip I should get
| waypoints | trips | roundtrip | durations |
| a,b,c,d,e,f,g,h,i,j,k,l | lkjihgfedcbal | true | 22 |
| a,b,c,d,e,f,g,h,i,j,k,l | cbakjihgfedl | false | 19 |
Scenario: Testbot - Trip: Unroutable roundtrip with waypoints (less than 10) Scenario: Testbot - Trip: Unroutable roundtrip with waypoints (less than 10)
Given the node map Given the node map
@ -274,7 +372,7 @@ Feature: Basic trip planning
| a,b,d,e,c | first | last | true | abedca | | a,b,d,e,c | first | last | true | abedca |
Scenario: Testbot - Trip: midway points in isoldated roads should return no trips Scenario: Testbot - Trip: midway points in isolated roads should return no trips
Given the node map Given the node map
""" """
a 1 b a 1 b

View File

@ -187,5 +187,5 @@ Feature: Check zero speed updates
When I plan a trip I should get When I plan a trip I should get
| waypoints | trips | code | | waypoints | trips | code |
| a,b,c,d | abcda | NoTrips | | a,b,c,d | | NoTrips |
| d,b,c,a | dbcad | NoTrips | | d,b,c,a | | NoTrips |

View File

@ -23,7 +23,7 @@ inline auto contractFullGraph(ContractorGraph contractor_graph,
auto edges = toEdges<QueryEdge>(std::move(contractor_graph)); auto edges = toEdges<QueryEdge>(std::move(contractor_graph));
std::vector<bool> edge_filter(edges.size(), true); std::vector<bool> edge_filter(edges.size(), true);
return GraphAndFilter{QueryGraph{num_nodes, std::move(edges)}, {std::move(edge_filter)}}; return GraphAndFilter{QueryGraph{num_nodes, edges}, {std::move(edge_filter)}};
} }
inline auto contractExcludableGraph(ContractorGraph contractor_graph_, inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
@ -91,7 +91,7 @@ inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
edge_container.Merge(toEdges<QueryEdge>(std::move(filtered_core_graph))); edge_container.Merge(toEdges<QueryEdge>(std::move(filtered_core_graph)));
} }
return GraphAndFilter{QueryGraph{num_nodes, std::move(edge_container.edges)}, return GraphAndFilter{QueryGraph{num_nodes, edge_container.edges},
edge_container.MakeEdgeFilters()}; edge_container.MakeEdgeFilters()};
} }
} // namespace contractor } // namespace contractor

View File

@ -58,8 +58,8 @@ struct QueryEdge
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {} QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
QueryEdge(NodeID source, NodeID target, EdgeData data) QueryEdge(NodeID source, NodeID target, const EdgeData &data)
: source(source), target(target), data(std::move(data)) : source(source), target(target), data(data)
{ {
} }

View File

@ -89,6 +89,11 @@ class MatchAPI final : public RouteAPI
} }
response.values["matchings"] = std::move(routes); response.values["matchings"] = std::move(routes);
response.values["code"] = "Ok"; response.values["code"] = "Ok";
auto data_timestamp = facade.GetTimestamp();
if (!data_timestamp.empty())
{
response.values["data_version"] = data_timestamp;
}
} }
protected: protected:

View File

@ -116,6 +116,11 @@ class NearestAPI final : public BaseAPI
} }
response.values["code"] = "Ok"; response.values["code"] = "Ok";
auto data_timestamp = facade.GetTimestamp();
if (!data_timestamp.empty())
{
response.values["data_version"] = data_timestamp;
}
} }
const NearestParameters &parameters; const NearestParameters &parameters;

View File

@ -367,7 +367,7 @@ class RouteAPI : public BaseAPI
// To maintain support for uses of the old default constructors, we check // To maintain support for uses of the old default constructors, we check
// if annotations property was set manually after default construction // if annotations property was set manually after default construction
auto requested_annotations = parameters.annotations_type; auto requested_annotations = parameters.annotations_type;
if ((parameters.annotations == true) && if (parameters.annotations &&
(parameters.annotations_type == RouteParameters::AnnotationsType::None)) (parameters.annotations_type == RouteParameters::AnnotationsType::None))
{ {
requested_annotations = RouteParameters::AnnotationsType::All; requested_annotations = RouteParameters::AnnotationsType::All;
@ -497,10 +497,10 @@ class RouteAPI : public BaseAPI
std::vector<uint32_t> nodes; std::vector<uint32_t> nodes;
if (requested_annotations & RouteParameters::AnnotationsType::Nodes) if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
{ {
nodes.reserve(leg_geometry.osm_node_ids.size()); nodes.reserve(leg_geometry.node_ids.size());
for (const auto node_id : leg_geometry.osm_node_ids) for (const auto node_id : leg_geometry.node_ids)
{ {
nodes.emplace_back(static_cast<uint64_t>(node_id)); nodes.emplace_back(static_cast<uint64_t>(facade.GetOSMNodeIDOfNode(node_id)));
} }
} }
auto nodes_vector = fb_result.CreateVector(nodes); auto nodes_vector = fb_result.CreateVector(nodes);
@ -515,7 +515,7 @@ class RouteAPI : public BaseAPI
{ {
const auto name = facade.GetDatasourceName(i); const auto name = facade.GetDatasourceName(i);
// Length of 0 indicates the first empty name, so we can stop here // Length of 0 indicates the first empty name, so we can stop here
if (name.size() == 0) if (name.empty())
break; break;
names.emplace_back( names.emplace_back(
fb_result.CreateString(std::string(facade.GetDatasourceName(i)))); fb_result.CreateString(std::string(facade.GetDatasourceName(i))));
@ -763,7 +763,7 @@ class RouteAPI : public BaseAPI
// To maintain support for uses of the old default constructors, we check // To maintain support for uses of the old default constructors, we check
// if annotations property was set manually after default construction // if annotations property was set manually after default construction
auto requested_annotations = parameters.annotations_type; auto requested_annotations = parameters.annotations_type;
if ((parameters.annotations == true) && if (parameters.annotations &&
(parameters.annotations_type == RouteParameters::AnnotationsType::None)) (parameters.annotations_type == RouteParameters::AnnotationsType::None))
{ {
requested_annotations = RouteParameters::AnnotationsType::All; requested_annotations = RouteParameters::AnnotationsType::All;
@ -825,10 +825,11 @@ class RouteAPI : public BaseAPI
if (requested_annotations & 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.node_ids.size());
for (const auto node_id : leg_geometry.osm_node_ids) for (const auto node_id : leg_geometry.node_ids)
{ {
nodes.values.push_back(static_cast<std::uint64_t>(node_id)); nodes.values.push_back(
static_cast<std::uint64_t>(facade.GetOSMNodeIDOfNode(node_id)));
} }
annotation.values["nodes"] = std::move(nodes); annotation.values["nodes"] = std::move(nodes);
} }
@ -842,7 +843,7 @@ class RouteAPI : public BaseAPI
{ {
const auto name = facade.GetDatasourceName(i); const auto name = facade.GetDatasourceName(i);
// Length of 0 indicates the first empty name, so we can stop here // Length of 0 indicates the first empty name, so we can stop here
if (name.size() == 0) if (name.empty())
break; break;
datasource_names.values.push_back(std::string(facade.GetDatasourceName(i))); datasource_names.values.push_back(std::string(facade.GetDatasourceName(i)));
} }
@ -888,23 +889,35 @@ class RouteAPI : public BaseAPI
const bool reversed_source = source_traversed_in_reverse[idx]; const bool reversed_source = source_traversed_in_reverse[idx];
const bool reversed_target = target_traversed_in_reverse[idx]; const bool reversed_target = target_traversed_in_reverse[idx];
auto leg_geometry = guidance::assembleGeometry(BaseAPI::facade, auto leg = guidance::assembleLeg(facade,
path_data,
phantoms.source_phantom,
phantoms.target_phantom,
reversed_target);
guidance::LegGeometry leg_geometry;
// Generate additional geometry data if request includes turn-by-turn steps,
// overview geometry or route geometry annotations.
// Note that overview geometry and route geometry annotations can return different
// results depending on whether turn-by-turn steps are also requested.
if (parameters.steps || parameters.annotations ||
parameters.overview != RouteParameters::OverviewType::False)
{
leg_geometry = guidance::assembleGeometry(BaseAPI::facade,
path_data, path_data,
phantoms.source_phantom, phantoms.source_phantom,
phantoms.target_phantom, phantoms.target_phantom,
reversed_source, reversed_source,
reversed_target); reversed_target);
auto leg = guidance::assembleLeg(facade,
path_data,
leg_geometry,
phantoms.source_phantom,
phantoms.target_phantom,
reversed_target,
parameters.steps);
util::Log(logDEBUG) << "Assembling steps " << std::endl; util::Log(logDEBUG) << "Assembling steps " << std::endl;
if (parameters.steps) if (parameters.steps)
{ {
leg.summary = guidance::assembleSummary(
facade, path_data, phantoms.target_phantom, reversed_target);
auto steps = guidance::assembleSteps(BaseAPI::facade, auto steps = guidance::assembleSteps(BaseAPI::facade,
path_data, path_data,
leg_geometry, leg_geometry,
@ -924,10 +937,11 @@ class RouteAPI : public BaseAPI
* *
* Using post-processing on basis of route-steps for a single leg at a time * Using post-processing on basis of route-steps for a single leg at a time
* comes at the cost that we cannot count the correct exit for roundabouts. * comes at the cost that we cannot count the correct exit for roundabouts.
* We can only emit the exit nr/intersections up to/starting at a part of the leg. * We can only emit the exit nr/intersections up to/starting at a part of the
* If a roundabout is not terminated in a leg, we will end up with a *leg. If a roundabout is not terminated in a leg, we will end up with a
*enter-roundabout *enter-roundabout
* and exit-roundabout-nr where the exit nr is out of sync with the previous enter. * and exit-roundabout-nr where the exit nr is out of sync with the previous
*enter.
* *
* | S | * | S |
* * * * * *
@ -938,14 +952,11 @@ class RouteAPI : public BaseAPI
* | | * | |
* | | * | |
* *
* Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say to * Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say
*take *to take the second exit, even though counting from S it would be the third.
* the second exit, even though counting from S it would be the third. * For S, we only emit `roundabout` without an exit number, showing that we
* For S, we only emit `roundabout` without an exit number, showing that we enter a *enter a roundabout to find a via point. The same exit will be emitted, though,
*roundabout *if we should start routing at S, making the overall response consistent.
* to find a via point.
* The same exit will be emitted, though, if we should start routing at S, making
* the overall response consistent.
* *
* CAUTION: order of post-processing steps is important * CAUTION: order of post-processing steps is important
* - handleRoundabouts must be called before collapseTurnInstructions that * - handleRoundabouts must be called before collapseTurnInstructions that
@ -964,6 +975,7 @@ class RouteAPI : public BaseAPI
phantoms.target_phantom); phantoms.target_phantom);
leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps); leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps);
} }
}
leg_geometries.push_back(std::move(leg_geometry)); leg_geometries.push_back(std::move(leg_geometry));
legs.push_back(std::move(leg)); legs.push_back(std::move(leg));

View File

@ -226,6 +226,11 @@ class TableAPI final : public BaseAPI
} }
response.values["code"] = "Ok"; response.values["code"] = "Ok";
auto data_timestamp = facade.GetTimestamp();
if (!data_timestamp.empty())
{
response.values["data_version"] = data_timestamp;
}
} }
protected: protected:

View File

@ -87,6 +87,11 @@ class TripAPI final : public RouteAPI
} }
response.values["trips"] = std::move(routes); response.values["trips"] = std::move(routes);
response.values["code"] = "Ok"; response.values["code"] = "Ok";
auto data_timestamp = facade.GetTimestamp();
if (!data_timestamp.empty())
{
response.values["data_version"] = data_timestamp;
}
} }
protected: protected:

View File

@ -36,24 +36,27 @@ template <> class AlgorithmDataFacade<CH>
virtual unsigned GetNumberOfEdges() const = 0; virtual unsigned GetNumberOfEdges() const = 0;
virtual unsigned GetOutDegree(const NodeID n) const = 0; virtual unsigned GetOutDegree(const NodeID edge_based_node_id) const = 0;
virtual NodeID GetTarget(const EdgeID e) const = 0; virtual NodeID GetTarget(const EdgeID edge_based_edge_id) const = 0;
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0; virtual const EdgeData &GetEdgeData(const EdgeID edge_based_edge_id) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0; virtual EdgeRange GetAdjacentEdgeRange(const NodeID edge_based_node_id) const = 0;
// searches for a specific edge // searches for a specific edge
virtual EdgeID FindEdge(const NodeID from, const NodeID to) const = 0; virtual EdgeID FindEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to) const = 0;
virtual EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const = 0; virtual EdgeID FindEdgeInEitherDirection(const NodeID edge_based_node_from,
const NodeID edge_based_node_to) const = 0;
virtual EdgeID virtual EdgeID FindEdgeIndicateIfReverse(const NodeID edge_based_node_from,
FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const = 0; const NodeID edge_based_node_to,
bool &result) const = 0;
virtual EdgeID FindSmallestEdge(const NodeID from, virtual EdgeID FindSmallestEdge(const NodeID edge_based_node_from,
const NodeID to, const NodeID edge_based_node_to,
const std::function<bool(EdgeData)> filter) const = 0; const std::function<bool(EdgeData)> filter) const = 0;
}; };
@ -70,23 +73,24 @@ template <> class AlgorithmDataFacade<MLD>
virtual unsigned GetNumberOfEdges() const = 0; virtual unsigned GetNumberOfEdges() const = 0;
virtual unsigned GetOutDegree(const NodeID n) const = 0; virtual unsigned GetOutDegree(const NodeID edge_based_node_id) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0; virtual EdgeRange GetAdjacentEdgeRange(const NodeID edge_based_node_id) const = 0;
virtual EdgeWeight GetNodeWeight(const NodeID node) const = 0; virtual EdgeWeight GetNodeWeight(const NodeID edge_based_node_id) const = 0;
virtual EdgeWeight GetNodeDuration(const NodeID node) const = 0; // TODO: to be removed virtual EdgeWeight
GetNodeDuration(const NodeID edge_based_node_id) const = 0; // TODO: to be removed
virtual EdgeDistance GetNodeDistance(const NodeID node) const = 0; virtual EdgeDistance GetNodeDistance(const NodeID edge_based_node_id) const = 0;
virtual bool IsForwardEdge(EdgeID edge) const = 0; virtual bool IsForwardEdge(EdgeID edge_based_edge_id) const = 0;
virtual bool IsBackwardEdge(EdgeID edge) const = 0; virtual bool IsBackwardEdge(EdgeID edge_based_edge_id) const = 0;
virtual NodeID GetTarget(const EdgeID e) const = 0; virtual NodeID GetTarget(const EdgeID edge_based_edge_id) const = 0;
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0; virtual const EdgeData &GetEdgeData(const EdgeID edge_based_edge_id) const = 0;
virtual const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const = 0; virtual const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
@ -94,10 +98,12 @@ template <> class AlgorithmDataFacade<MLD>
virtual const customizer::CellMetricView &GetCellMetric() const = 0; virtual const customizer::CellMetricView &GetCellMetric() const = 0;
virtual EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const = 0; virtual EdgeRange GetBorderEdgeRange(const LevelID level,
const NodeID edge_based_node_id) const = 0;
// searches for a specific edge // searches for a specific edge
virtual EdgeID FindEdge(const NodeID from, const NodeID to) const = 0; virtual EdgeID FindEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to) const = 0;
}; };
} // namespace datafacade } // namespace datafacade
} // namespace engine } // namespace engine

View File

@ -73,45 +73,52 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
unsigned GetNumberOfEdges() const override final { return m_query_graph.GetNumberOfEdges(); } unsigned GetNumberOfEdges() const override final { return m_query_graph.GetNumberOfEdges(); }
unsigned GetOutDegree(const NodeID n) const override final unsigned GetOutDegree(const NodeID edge_based_node_id) const override final
{ {
return m_query_graph.GetOutDegree(n); return m_query_graph.GetOutDegree(edge_based_node_id);
} }
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph.GetTarget(e); } NodeID GetTarget(const EdgeID edge_based_edge_id) const override final
const EdgeData &GetEdgeData(const EdgeID e) const override final
{ {
return m_query_graph.GetEdgeData(e); return m_query_graph.GetTarget(edge_based_edge_id);
} }
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final const EdgeData &GetEdgeData(const EdgeID edge_based_edge_id) const override final
{ {
return m_query_graph.GetAdjacentEdgeRange(node); return m_query_graph.GetEdgeData(edge_based_edge_id);
}
EdgeRange GetAdjacentEdgeRange(const NodeID edge_based_node_id) const override final
{
return m_query_graph.GetAdjacentEdgeRange(edge_based_node_id);
} }
// searches for a specific edge // searches for a specific edge
EdgeID FindEdge(const NodeID from, const NodeID to) const override final EdgeID FindEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to) const override final
{ {
return m_query_graph.FindEdge(from, to); return m_query_graph.FindEdge(edge_based_node_from, edge_based_node_to);
} }
EdgeID FindEdgeInEitherDirection(const NodeID from, const NodeID to) const override final EdgeID FindEdgeInEitherDirection(const NodeID edge_based_node_from,
const NodeID edge_based_node_to) const override final
{ {
return m_query_graph.FindEdgeInEitherDirection(from, to); return m_query_graph.FindEdgeInEitherDirection(edge_based_node_from, edge_based_node_to);
} }
EdgeID EdgeID FindEdgeIndicateIfReverse(const NodeID edge_based_node_from,
FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final const NodeID edge_based_node_to,
bool &result) const override final
{ {
return m_query_graph.FindEdgeIndicateIfReverse(from, to, result); return m_query_graph.FindEdgeIndicateIfReverse(
edge_based_node_from, edge_based_node_to, result);
} }
EdgeID FindSmallestEdge(const NodeID from, EdgeID FindSmallestEdge(const NodeID edge_based_node_from,
const NodeID to, const NodeID edge_based_node_to,
std::function<bool(EdgeData)> filter) const override final std::function<bool(EdgeData)> filter) const override final
{ {
return m_query_graph.FindSmallestEdge(from, to, filter); return m_query_graph.FindSmallestEdge(edge_based_node_from, edge_based_node_to, filter);
} }
}; };
@ -126,11 +133,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
{ {
private: private:
using super = BaseDataFacade; using super = BaseDataFacade;
using IndexBlock = util::RangeTable<16, storage::Ownership::View>::BlockT;
using RTreeLeaf = super::RTreeLeaf; using RTreeLeaf = super::RTreeLeaf;
using SharedRTree = util::StaticRTree<RTreeLeaf, storage::Ownership::View>; using SharedRTree = util::StaticRTree<RTreeLeaf, storage::Ownership::View>;
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>; using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
using RTreeNode = SharedRTree::TreeNode;
extractor::ClassData exclude_mask; extractor::ClassData exclude_mask;
extractor::ProfileProperties *m_profile_properties; extractor::ProfileProperties *m_profile_properties;
@ -231,76 +236,80 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
} }
// node and edge information access // node and edge information access
util::Coordinate GetCoordinateOfNode(const NodeID id) const override final util::Coordinate GetCoordinateOfNode(const NodeID node_based_node_id) const override final
{ {
return m_coordinate_list[id]; return m_coordinate_list[node_based_node_id];
} }
OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const override final OSMNodeID GetOSMNodeIDOfNode(const NodeID node_based_node_id) const override final
{ {
return m_osmnodeid_list[id]; return m_osmnodeid_list[node_based_node_id];
} }
NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const override final NodeForwardRange GetUncompressedForwardGeometry(const PackedGeometryID id) const override final
{ {
return segment_data.GetForwardGeometry(id); return segment_data.GetForwardGeometry(id);
} }
NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const override final NodeReverseRange GetUncompressedReverseGeometry(const PackedGeometryID id) const override final
{ {
return segment_data.GetReverseGeometry(id); return segment_data.GetReverseGeometry(id);
} }
DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const override final DurationForwardRange
GetUncompressedForwardDurations(const PackedGeometryID id) const override final
{ {
return segment_data.GetForwardDurations(id); return segment_data.GetForwardDurations(id);
} }
DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const override final DurationReverseRange
GetUncompressedReverseDurations(const PackedGeometryID id) const override final
{ {
return segment_data.GetReverseDurations(id); return segment_data.GetReverseDurations(id);
} }
WeightForwardRange GetUncompressedForwardWeights(const EdgeID id) const override final WeightForwardRange GetUncompressedForwardWeights(const PackedGeometryID id) const override final
{ {
return segment_data.GetForwardWeights(id); return segment_data.GetForwardWeights(id);
} }
WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const override final WeightReverseRange GetUncompressedReverseWeights(const PackedGeometryID id) const override final
{ {
return segment_data.GetReverseWeights(id); return segment_data.GetReverseWeights(id);
} }
// Returns the data source ids that were used to supply the edge // Returns the data source ids that were used to supply the edge
// weights. // weights.
DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const override final DatasourceForwardRange
GetUncompressedForwardDatasources(const PackedGeometryID id) const override final
{ {
return segment_data.GetForwardDatasources(id); return segment_data.GetForwardDatasources(id);
} }
// Returns the data source ids that were used to supply the edge // Returns the data source ids that were used to supply the edge
// weights. // weights.
DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const override final DatasourceReverseRange
GetUncompressedReverseDatasources(const PackedGeometryID id) const override final
{ {
return segment_data.GetReverseDatasources(id); return segment_data.GetReverseDatasources(id);
} }
TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const override final TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID edge_based_edge_id) const override final
{ {
BOOST_ASSERT(m_turn_weight_penalties.size() > id); BOOST_ASSERT(m_turn_weight_penalties.size() > edge_based_edge_id);
return m_turn_weight_penalties[id]; return m_turn_weight_penalties[edge_based_edge_id];
} }
TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const override final TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID edge_based_edge_id) const override final
{ {
BOOST_ASSERT(m_turn_duration_penalties.size() > id); BOOST_ASSERT(m_turn_duration_penalties.size() > edge_based_edge_id);
return m_turn_duration_penalties[id]; return m_turn_duration_penalties[edge_based_edge_id];
} }
osrm::guidance::TurnInstruction osrm::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const EdgeID id) const override final GetTurnInstructionForEdgeID(const EdgeID edge_based_edge_id) const override final
{ {
return turn_data.GetTurnInstruction(id); return turn_data.GetTurnInstruction(edge_based_edge_id);
} }
std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west, std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
@ -444,29 +453,29 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return std::string(m_data_timestamp.begin(), m_data_timestamp.end()); return std::string(m_data_timestamp.begin(), m_data_timestamp.end());
} }
GeometryID GetGeometryIndex(const NodeID id) const override final GeometryID GetGeometryIndex(const NodeID edge_based_node_id) const override final
{ {
return edge_based_node_data.GetGeometryID(id); return edge_based_node_data.GetGeometryID(edge_based_node_id);
} }
ComponentID GetComponentID(const NodeID id) const override final ComponentID GetComponentID(const NodeID edge_based_node_id) const override final
{ {
return edge_based_node_data.GetComponentID(id); return edge_based_node_data.GetComponentID(edge_based_node_id);
} }
extractor::TravelMode GetTravelMode(const NodeID id) const override final extractor::TravelMode GetTravelMode(const NodeID edge_based_node_id) const override final
{ {
return edge_based_node_data.GetTravelMode(id); return edge_based_node_data.GetTravelMode(edge_based_node_id);
} }
extractor::ClassData GetClassData(const NodeID id) const override final extractor::ClassData GetClassData(const NodeID edge_based_node_id) const override final
{ {
return edge_based_node_data.GetClassData(id); return edge_based_node_data.GetClassData(edge_based_node_id);
} }
bool ExcludeNode(const NodeID id) const override final bool ExcludeNode(const NodeID edge_based_node_id) const override final
{ {
return (edge_based_node_data.GetClassData(id) & exclude_mask) > 0; return (edge_based_node_data.GetClassData(edge_based_node_id) & exclude_mask) > 0;
} }
std::vector<std::string> GetClasses(const extractor::ClassData class_data) const override final std::vector<std::string> GetClasses(const extractor::ClassData class_data) const override final
@ -480,9 +489,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return classes; return classes;
} }
NameID GetNameIndex(const NodeID id) const override final NameID GetNameIndex(const NodeID edge_based_node_id) const override final
{ {
return edge_based_node_data.GetNameID(id); return edge_based_node_data.GetNameID(edge_based_node_id);
} }
StringView GetNameForID(const NameID id) const override final StringView GetNameForID(const NameID id) const override final
@ -537,32 +546,37 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return m_profile_properties->GetWeightMultiplier(); return m_profile_properties->GetWeightMultiplier();
} }
util::guidance::BearingClass GetBearingClass(const NodeID node) const override final util::guidance::BearingClass
GetBearingClass(const NodeID node_based_node_id) const override final
{ {
return intersection_bearings_view.GetBearingClass(node); return intersection_bearings_view.GetBearingClass(node_based_node_id);
} }
guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final guidance::TurnBearing PreTurnBearing(const EdgeID edge_based_edge_id) const override final
{ {
return turn_data.GetPreTurnBearing(eid); return turn_data.GetPreTurnBearing(edge_based_edge_id);
} }
guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final guidance::TurnBearing PostTurnBearing(const EdgeID edge_based_edge_id) const override final
{ {
return turn_data.GetPostTurnBearing(eid); return turn_data.GetPostTurnBearing(edge_based_edge_id);
} }
util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const override final util::guidance::EntryClass GetEntryClass(const EdgeID edge_based_edge_id) const override final
{ {
auto entry_class_id = turn_data.GetEntryClassID(turn_id); auto entry_class_id = turn_data.GetEntryClassID(edge_based_edge_id);
return m_entry_class_table.at(entry_class_id); return m_entry_class_table.at(entry_class_id);
} }
bool HasLaneData(const EdgeID id) const override final { return turn_data.HasLaneData(id); } bool HasLaneData(const EdgeID edge_based_edge_id) const override final
util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final
{ {
BOOST_ASSERT(HasLaneData(id)); return turn_data.HasLaneData(edge_based_edge_id);
return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(id)); }
util::guidance::LaneTupleIdPair
GetLaneData(const EdgeID edge_based_edge_id) const override final
{
BOOST_ASSERT(HasLaneData(edge_based_edge_id));
return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(edge_based_edge_id));
} }
extractor::TurnLaneDescription extractor::TurnLaneDescription
@ -577,15 +591,15 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
m_lane_description_offsets[lane_description_id + 1]); m_lane_description_offsets[lane_description_id + 1]);
} }
bool IsLeftHandDriving(const NodeID id) const override final bool IsLeftHandDriving(const NodeID edge_based_node_id) const override final
{ {
// TODO: can be moved to a data block indexed by GeometryID // TODO: can be moved to a data block indexed by GeometryID
return edge_based_node_data.IsLeftHandDriving(id); return edge_based_node_data.IsLeftHandDriving(edge_based_node_id);
} }
bool IsSegregated(const NodeID id) const override final bool IsSegregated(const NodeID edge_based_node_id) const override final
{ {
return edge_based_node_data.IsSegregated(id); return edge_based_node_data.IsSegregated(edge_based_node_id);
} }
std::vector<extractor::ManeuverOverride> std::vector<extractor::ManeuverOverride>
@ -691,57 +705,62 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
unsigned GetNumberOfEdges() const override final { return query_graph.GetNumberOfEdges(); } unsigned GetNumberOfEdges() const override final { return query_graph.GetNumberOfEdges(); }
unsigned GetOutDegree(const NodeID n) const override final unsigned GetOutDegree(const NodeID edge_based_node_id) const override final
{ {
return query_graph.GetOutDegree(n); return query_graph.GetOutDegree(edge_based_node_id);
} }
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final EdgeRange GetAdjacentEdgeRange(const NodeID edge_based_node_id) const override final
{ {
return query_graph.GetAdjacentEdgeRange(node); return query_graph.GetAdjacentEdgeRange(edge_based_node_id);
} }
EdgeWeight GetNodeWeight(const NodeID node) const override final EdgeWeight GetNodeWeight(const NodeID edge_based_node_id) const override final
{ {
return query_graph.GetNodeWeight(node); return query_graph.GetNodeWeight(edge_based_node_id);
} }
EdgeDuration GetNodeDuration(const NodeID node) const override final EdgeDuration GetNodeDuration(const NodeID edge_based_node_id) const override final
{ {
return query_graph.GetNodeDuration(node); return query_graph.GetNodeDuration(edge_based_node_id);
} }
EdgeDistance GetNodeDistance(const NodeID node) const override final EdgeDistance GetNodeDistance(const NodeID edge_based_node_id) const override final
{ {
return query_graph.GetNodeDistance(node); return query_graph.GetNodeDistance(edge_based_node_id);
} }
bool IsForwardEdge(const NodeID node) const override final bool IsForwardEdge(const NodeID edge_based_node_id) const override final
{ {
return query_graph.IsForwardEdge(node); return query_graph.IsForwardEdge(edge_based_node_id);
} }
bool IsBackwardEdge(const NodeID node) const override final bool IsBackwardEdge(const NodeID edge_based_node_id) const override final
{ {
return query_graph.IsBackwardEdge(node); return query_graph.IsBackwardEdge(edge_based_node_id);
} }
NodeID GetTarget(const EdgeID e) const override final { return query_graph.GetTarget(e); } NodeID GetTarget(const EdgeID edge_based_edge_id) const override final
const EdgeData &GetEdgeData(const EdgeID e) const override final
{ {
return query_graph.GetEdgeData(e); return query_graph.GetTarget(edge_based_edge_id);
} }
EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const override final const EdgeData &GetEdgeData(const EdgeID edge_based_edge_id) const override final
{ {
return query_graph.GetBorderEdgeRange(level, node); return query_graph.GetEdgeData(edge_based_edge_id);
}
EdgeRange GetBorderEdgeRange(const LevelID level,
const NodeID edge_based_node_id) const override final
{
return query_graph.GetBorderEdgeRange(level, edge_based_node_id);
} }
// searches for a specific edge // searches for a specific edge
EdgeID FindEdge(const NodeID from, const NodeID to) const override final EdgeID FindEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to) const override final
{ {
return query_graph.FindEdge(from, to); return query_graph.FindEdge(edge_based_node_from, edge_based_node_to);
} }
}; };

View File

@ -77,46 +77,51 @@ class BaseDataFacade
virtual std::string GetTimestamp() const = 0; virtual std::string GetTimestamp() const = 0;
// node and edge information access // node and edge information access
virtual util::Coordinate GetCoordinateOfNode(const NodeID id) const = 0; virtual util::Coordinate GetCoordinateOfNode(const NodeID node_based_node_id) const = 0;
virtual OSMNodeID GetOSMNodeIDOfNode(const NodeID id) const = 0; virtual OSMNodeID GetOSMNodeIDOfNode(const NodeID node_based_node_id) const = 0;
virtual GeometryID GetGeometryIndex(const NodeID id) const = 0; virtual GeometryID GetGeometryIndex(const NodeID edge_based_node_id) const = 0;
virtual ComponentID GetComponentID(const NodeID id) const = 0; virtual ComponentID GetComponentID(const NodeID edge_based_node_id) const = 0;
virtual NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const = 0; virtual NodeForwardRange GetUncompressedForwardGeometry(const PackedGeometryID id) const = 0;
virtual NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const = 0; virtual NodeReverseRange GetUncompressedReverseGeometry(const PackedGeometryID id) const = 0;
virtual TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const = 0; virtual TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID edge_based_edge_id) const = 0;
virtual TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const = 0; virtual TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID edge_based_edge_id) const = 0;
// Gets the weight values for each segment in an uncompressed geometry. // Gets the weight values for each segment in an uncompressed geometry.
// Should always be 1 shorter than GetUncompressedGeometry // Should always be 1 shorter than GetUncompressedGeometry
virtual WeightForwardRange GetUncompressedForwardWeights(const EdgeID id) const = 0; virtual WeightForwardRange GetUncompressedForwardWeights(const PackedGeometryID id) const = 0;
virtual WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const = 0; virtual WeightReverseRange GetUncompressedReverseWeights(const PackedGeometryID id) const = 0;
// Gets the duration values for each segment in an uncompressed geometry. // Gets the duration values for each segment in an uncompressed geometry.
// Should always be 1 shorter than GetUncompressedGeometry // Should always be 1 shorter than GetUncompressedGeometry
virtual DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const = 0; virtual DurationForwardRange
virtual DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const = 0; GetUncompressedForwardDurations(const PackedGeometryID id) const = 0;
virtual DurationReverseRange
GetUncompressedReverseDurations(const PackedGeometryID id) const = 0;
// Returns the data source ids that were used to supply the edge // Returns the data source ids that were used to supply the edge
// weights. Will return an empty array when only the base profile is used. // weights. Will return an empty array when only the base profile is used.
virtual DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const = 0; virtual DatasourceForwardRange
virtual DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const = 0; GetUncompressedForwardDatasources(const PackedGeometryID id) const = 0;
virtual DatasourceReverseRange
GetUncompressedReverseDatasources(const PackedGeometryID id) const = 0;
// Gets the name of a datasource // Gets the name of a datasource
virtual StringView GetDatasourceName(const DatasourceID id) const = 0; virtual StringView GetDatasourceName(const DatasourceID id) const = 0;
virtual osrm::guidance::TurnInstruction GetTurnInstructionForEdgeID(const EdgeID id) const = 0; virtual osrm::guidance::TurnInstruction
GetTurnInstructionForEdgeID(const EdgeID edge_based_edge_id) const = 0;
virtual extractor::TravelMode GetTravelMode(const NodeID id) const = 0; virtual extractor::TravelMode GetTravelMode(const NodeID edge_based_node_id) const = 0;
virtual extractor::ClassData GetClassData(const NodeID id) const = 0; virtual extractor::ClassData GetClassData(const NodeID edge_based_node_id) const = 0;
virtual bool ExcludeNode(const NodeID id) const = 0; virtual bool ExcludeNode(const NodeID edge_based_node_id) const = 0;
virtual std::vector<std::string> GetClasses(const extractor::ClassData class_data) const = 0; virtual std::vector<std::string> GetClasses(const extractor::ClassData class_data) const = 0;
@ -182,12 +187,12 @@ class BaseDataFacade
const Approach approach, const Approach approach,
const bool use_all_edges = false) const = 0; const bool use_all_edges = false) const = 0;
virtual bool HasLaneData(const EdgeID id) const = 0; virtual bool HasLaneData(const EdgeID edge_based_edge_id) const = 0;
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0; virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID edge_based_edge_id) const = 0;
virtual extractor::TurnLaneDescription virtual extractor::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0; GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0;
virtual NameID GetNameIndex(const NodeID id) const = 0; virtual NameID GetNameIndex(const NodeID edge_based_node_id) const = 0;
virtual StringView GetNameForID(const NameID id) const = 0; virtual StringView GetNameForID(const NameID id) const = 0;
@ -209,16 +214,16 @@ class BaseDataFacade
virtual double GetWeightMultiplier() const = 0; virtual double GetWeightMultiplier() const = 0;
virtual osrm::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0; virtual osrm::guidance::TurnBearing PreTurnBearing(const EdgeID edge_based_edge_id) const = 0;
virtual osrm::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const = 0; virtual osrm::guidance::TurnBearing PostTurnBearing(const EdgeID edge_based_edge_id) const = 0;
virtual util::guidance::BearingClass GetBearingClass(const NodeID node) const = 0; virtual util::guidance::BearingClass GetBearingClass(const NodeID node_based_node_id) const = 0;
virtual util::guidance::EntryClass GetEntryClass(const EdgeID turn_id) const = 0; virtual util::guidance::EntryClass GetEntryClass(const EdgeID edge_based_edge_id) const = 0;
virtual bool IsLeftHandDriving(const NodeID id) const = 0; virtual bool IsLeftHandDriving(const NodeID edge_based_node_id) const = 0;
virtual bool IsSegregated(const NodeID) const = 0; virtual bool IsSegregated(const NodeID edge_based_node_id) const = 0;
virtual std::vector<extractor::ManeuverOverride> virtual std::vector<extractor::ManeuverOverride>
GetOverridesThatStartAt(const NodeID edge_based_node_id) const = 0; GetOverridesThatStartAt(const NodeID edge_based_node_id) const = 0;

View File

@ -57,8 +57,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id; const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
const auto source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id); const auto source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id);
geometry.osm_node_ids.push_back( geometry.node_ids.push_back(source_geometry(source_segment_start_coordinate));
facade.GetOSMNodeIDOfNode(source_geometry(source_segment_start_coordinate)));
auto cumulative_distance = 0.; auto cumulative_distance = 0.;
auto current_distance = 0.; auto current_distance = 0.;
@ -71,7 +70,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
cumulative_distance += current_distance; cumulative_distance += current_distance;
// all changes to this check have to be matched with assemble_steps // all changes to this check have to be matched with assemble_steps
if (path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn) auto turn_instruction = path_point.turn_edge
? facade.GetTurnInstructionForEdgeID(*path_point.turn_edge)
: osrm::guidance::TurnInstruction::NO_TURN();
if (turn_instruction.type != osrm::guidance::TurnType::NoTurn)
{ {
geometry.segment_distances.push_back(cumulative_distance); geometry.segment_distances.push_back(cumulative_distance);
geometry.segment_offsets.push_back(geometry.locations.size()); geometry.segment_offsets.push_back(geometry.locations.size());
@ -79,11 +81,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
} }
prev_coordinate = coordinate; prev_coordinate = coordinate;
const auto node_id = path_point.turn_via_node;
const auto osm_node_id = facade.GetOSMNodeIDOfNode(path_point.turn_via_node); if (node_id != geometry.node_ids.back() ||
turn_instruction.type != osrm::guidance::TurnType::NoTurn)
if (osm_node_id != geometry.osm_node_ids.back() ||
path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn)
{ {
geometry.annotations.emplace_back(LegGeometry::Annotation{ geometry.annotations.emplace_back(LegGeometry::Annotation{
current_distance, current_distance,
@ -98,8 +99,8 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
(path_point.weight_until_turn - path_point.weight_of_turn) / (path_point.weight_until_turn - path_point.weight_of_turn) /
facade.GetWeightMultiplier(), facade.GetWeightMultiplier(),
path_point.datasource_id}); path_point.datasource_id});
geometry.locations.push_back(std::move(coordinate)); geometry.locations.push_back(coordinate);
geometry.osm_node_ids.push_back(osm_node_id); geometry.node_ids.push_back(node_id);
} }
} }
current_distance = current_distance =
@ -158,8 +159,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
const auto target_segment_end_coordinate = const auto target_segment_end_coordinate =
target_node.fwd_segment_position + (reversed_target ? 0 : 1); target_node.fwd_segment_position + (reversed_target ? 0 : 1);
const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id); const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id);
geometry.osm_node_ids.push_back( geometry.node_ids.push_back(target_geometry(target_segment_end_coordinate));
facade.GetOSMNodeIDOfNode(target_geometry(target_segment_end_coordinate)));
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1); BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size()); BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());

View File

@ -75,9 +75,13 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
std::vector<NamedSegment> segments(route_data.size()); std::vector<NamedSegment> segments(route_data.size());
std::uint32_t index = 0; std::uint32_t index = 0;
std::transform( std::transform(route_data.begin(),
route_data.begin(), route_data.end(), segments.begin(), [&index](const PathData &point) { route_data.end(),
return NamedSegment{point.duration_until_turn, index++, point.name_id}; segments.begin(),
[&index, &facade](const PathData &point) {
return NamedSegment{point.duration_until_turn,
index++,
facade.GetNameIndex(point.from_edge_based_node)};
}); });
const auto target_duration = const auto target_duration =
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration; target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
@ -124,21 +128,59 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
} }
} // namespace detail } // namespace detail
inline std::string assembleSummary(const datafacade::BaseDataFacade &facade,
const std::vector<PathData> &route_data,
const PhantomNode &target_node,
const bool target_traversed_in_reverse)
{
auto summary_array = detail::summarizeRoute<detail::MAX_USED_SEGMENTS>(
facade, route_data, target_node, target_traversed_in_reverse);
BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
BOOST_ASSERT(summary_array.begin() != summary_array.end());
// transform a name_id into a string containing either the name, or -if the name is empty-
// the reference.
const auto name_id_to_string = [&](const NameID name_id) {
const auto name = facade.GetNameForID(name_id);
if (!name.empty())
return name.to_string();
else
{
const auto ref = facade.GetRefForID(name_id);
return ref.to_string();
}
};
const auto not_empty = [&](const std::string &name) { return !name.empty(); };
const auto summary_names = summary_array | boost::adaptors::transformed(name_id_to_string) |
boost::adaptors::filtered(not_empty);
return boost::algorithm::join(summary_names, ", ");
}
inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade, inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
const std::vector<PathData> &route_data, const std::vector<PathData> &route_data,
const LegGeometry &leg_geometry,
const PhantomNode &source_node, const PhantomNode &source_node,
const PhantomNode &target_node, const PhantomNode &target_node,
const bool target_traversed_in_reverse, const bool target_traversed_in_reverse)
const bool needs_summary)
{ {
auto distance = 0.;
auto prev_coordinate = source_node.location;
for (const auto &path_point : route_data)
{
auto coordinate = facade.GetCoordinateOfNode(path_point.turn_via_node);
distance += util::coordinate_calculation::greatCircleDistance(prev_coordinate, coordinate);
prev_coordinate = coordinate;
}
distance +=
util::coordinate_calculation::greatCircleDistance(prev_coordinate, target_node.location);
const auto target_duration = const auto target_duration =
(target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration); (target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration);
const auto target_weight = const auto target_weight =
(target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight); (target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight);
auto distance = std::accumulate(
leg_geometry.segment_distances.begin(), leg_geometry.segment_distances.end(), 0.);
auto duration = std::accumulate( auto duration = std::accumulate(
route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) { route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) {
return sum + data.duration_until_turn; return sum + data.duration_until_turn;
@ -182,39 +224,10 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
duration = std::max(0, duration); duration = std::max(0, duration);
} }
std::string summary;
if (needs_summary)
{
auto summary_array = detail::summarizeRoute<detail::MAX_USED_SEGMENTS>(
facade, route_data, target_node, target_traversed_in_reverse);
BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0);
BOOST_ASSERT(summary_array.begin() != summary_array.end());
// transform a name_id into a string containing either the name, or -if the name is empty-
// the reference.
const auto name_id_to_string = [&](const NameID name_id) {
const auto name = facade.GetNameForID(name_id);
if (!name.empty())
return name.to_string();
else
{
const auto ref = facade.GetRefForID(name_id);
return ref.to_string();
}
};
const auto not_empty = [&](const std::string &name) { return !name.empty(); };
const auto summary_names = summary_array | boost::adaptors::transformed(name_id_to_string) |
boost::adaptors::filtered(not_empty);
summary = boost::algorithm::join(summary_names, ", ");
}
return RouteLeg{std::round(distance * 10.) / 10., return RouteLeg{std::round(distance * 10.) / 10.,
duration / 10., duration / 10.,
weight / facade.GetWeightMultiplier(), weight / facade.GetWeightMultiplier(),
summary, "",
{}}; {}};
} }

View File

@ -19,6 +19,7 @@
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <cstddef> #include <cstddef>
#include <guidance/turn_bearing.hpp>
#include <vector> #include <vector>
namespace osrm namespace osrm
@ -96,7 +97,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
{}, {},
source_classes}; source_classes};
if (leg_data.size() > 0) if (!leg_data.empty())
{ {
// PathData saves the information we need of the segment _before_ the turn, // PathData saves the information we need of the segment _before_ the turn,
// but a RouteStep is with regard to the segment after the turn. // but a RouteStep is with regard to the segment after the turn.
@ -115,7 +116,10 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
segment_weight += path_point.weight_until_turn; segment_weight += path_point.weight_until_turn;
// all changes to this check have to be matched with assemble_geometry // all changes to this check have to be matched with assemble_geometry
if (path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn) const auto turn_instruction =
path_point.turn_edge ? facade.GetTurnInstructionForEdgeID(*path_point.turn_edge)
: osrm::guidance::TurnInstruction::NO_TURN();
if (turn_instruction.type != osrm::guidance::TurnType::NoTurn)
{ {
BOOST_ASSERT(segment_weight >= 0); BOOST_ASSERT(segment_weight >= 0);
const auto name = facade.GetNameForID(step_name_id); const auto name = facade.GetNameForID(step_name_id);
@ -125,7 +129,13 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
const auto exits = facade.GetExitsForID(step_name_id); const auto exits = facade.GetExitsForID(step_name_id);
const auto distance = leg_geometry.segment_distances[segment_index]; const auto distance = leg_geometry.segment_distances[segment_index];
// intersections contain the classes of exiting road // intersections contain the classes of exiting road
intersection.classes = facade.GetClasses(path_point.classes); intersection.classes =
facade.GetClasses(facade.GetClassData(path_point.from_edge_based_node));
const auto is_left_hand_driving =
facade.IsLeftHandDriving(path_point.from_edge_based_node);
const auto travel_mode = facade.GetTravelMode(path_point.from_edge_based_node);
BOOST_ASSERT(travel_mode > 0);
steps.push_back(RouteStep{path_point.from_edge_based_node, steps.push_back(RouteStep{path_point.from_edge_based_node,
step_name_id, step_name_id,
@ -140,17 +150,19 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
segment_duration / 10., segment_duration / 10.,
distance, distance,
segment_weight / weight_multiplier, segment_weight / weight_multiplier,
path_point.travel_mode, travel_mode,
maneuver, maneuver,
leg_geometry.FrontIndex(segment_index), leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1, leg_geometry.BackIndex(segment_index) + 1,
{intersection}, {intersection},
path_point.is_left_hand_driving}); is_left_hand_driving});
if (leg_data_index + 1 < leg_data.size()) if (leg_data_index + 1 < leg_data.size())
{ {
step_name_id = leg_data[leg_data_index + 1].name_id; step_name_id =
is_segregated = leg_data[leg_data_index + 1].is_segregated; facade.GetNameIndex(leg_data[leg_data_index + 1].from_edge_based_node);
is_segregated =
facade.IsSegregated(leg_data[leg_data_index + 1].from_edge_based_node);
} }
else else
{ {
@ -159,19 +171,32 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
} }
// extract bearings // extract bearings
bearings = std::make_pair<std::uint16_t, std::uint16_t>( auto pre_turn_bearing = path_point.turn_edge
path_point.pre_turn_bearing.Get(), path_point.post_turn_bearing.Get()); ? facade.PreTurnBearing(*path_point.turn_edge)
: osrm::guidance::TurnBearing(0);
auto post_turn_bearing = path_point.turn_edge
? facade.PostTurnBearing(*path_point.turn_edge)
: osrm::guidance::TurnBearing(0);
bearings = std::make_pair<std::uint16_t, std::uint16_t>(pre_turn_bearing.Get(),
post_turn_bearing.Get());
const auto bearing_class = facade.GetBearingClass(path_point.turn_via_node); const auto bearing_class = facade.GetBearingClass(path_point.turn_via_node);
auto bearing_data = bearing_class.getAvailableBearings(); auto bearing_data = bearing_class.getAvailableBearings();
util::guidance::LaneTupleIdPair lane_data = {{0, INVALID_LANEID},
INVALID_LANE_DESCRIPTIONID};
if (path_point.turn_edge && facade.HasLaneData(*path_point.turn_edge))
{
lane_data = facade.GetLaneData(*path_point.turn_edge);
}
intersection.in = bearing_class.findMatchingBearing(bearings.first); intersection.in = bearing_class.findMatchingBearing(bearings.first);
intersection.out = bearing_class.findMatchingBearing(bearings.second); intersection.out = bearing_class.findMatchingBearing(bearings.second);
intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node); intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
intersection.bearings.clear(); intersection.bearings.clear();
intersection.bearings.reserve(bearing_data.size()); intersection.bearings.reserve(bearing_data.size());
intersection.lanes = path_point.lane_data.first; intersection.lanes = lane_data.first;
intersection.lane_description = intersection.lane_description = lane_data.second != INVALID_LANE_DESCRIPTIONID
path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID ? facade.GetTurnDescription(lane_data.second)
? facade.GetTurnDescription(path_point.lane_data.second)
: extractor::TurnLaneDescription(); : extractor::TurnLaneDescription();
// Lanes in turn are bound by total number of lanes at the location // Lanes in turn are bound by total number of lanes at the location
@ -183,20 +208,23 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
(!intersection.lane_description.empty() && (!intersection.lane_description.empty() &&
intersection.lanes.lanes_in_turn != 0)); intersection.lanes.lanes_in_turn != 0));
auto entry_class = path_point.turn_edge
? facade.GetEntryClass(*path_point.turn_edge)
: EMPTY_ENTRY_CLASS;
std::copy(bearing_data.begin(), std::copy(bearing_data.begin(),
bearing_data.end(), bearing_data.end(),
std::back_inserter(intersection.bearings)); std::back_inserter(intersection.bearings));
intersection.entry.clear(); intersection.entry.clear();
for (auto idx : util::irange<std::size_t>(0, intersection.bearings.size())) for (auto idx : util::irange<std::size_t>(0, intersection.bearings.size()))
{ {
intersection.entry.push_back(path_point.entry_class.allowsEntry(idx)); intersection.entry.push_back(entry_class.allowsEntry(idx));
} }
std::int16_t bearing_in_driving_direction = std::int16_t bearing_in_driving_direction =
util::bearing::reverse(std::round(bearings.first)); util::bearing::reverse(std::round(bearings.first));
maneuver = {intersection.location, maneuver = {intersection.location,
bearing_in_driving_direction, bearing_in_driving_direction,
bearings.second, bearings.second,
path_point.turn_instruction, turn_instruction,
WaypointType::None, WaypointType::None,
0}; 0};
segment_index++; segment_index++;
@ -269,7 +297,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
leg_geometry.segment_distances[segment_index], leg_geometry.segment_distances[segment_index],
weight / weight_multiplier, weight / weight_multiplier,
source_mode, source_mode,
std::move(maneuver), maneuver,
leg_geometry.FrontIndex(segment_index), leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1, leg_geometry.BackIndex(segment_index) + 1,
{intersection}, {intersection},
@ -312,7 +340,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
ZERO_DISTANCE, ZERO_DISTANCE,
ZERO_WEIGHT, ZERO_WEIGHT,
target_mode, target_mode,
std::move(maneuver), maneuver,
leg_geometry.locations.size() - 1, leg_geometry.locations.size() - 1,
leg_geometry.locations.size(), leg_geometry.locations.size(),
{intersection}, {intersection},

View File

@ -32,7 +32,7 @@ struct LegGeometry
// length of the segment in meters // length of the segment in meters
std::vector<double> segment_distances; std::vector<double> segment_distances;
// original OSM node IDs for each coordinate // original OSM node IDs for each coordinate
std::vector<OSMNodeID> osm_node_ids; std::vector<NodeID> node_ids;
// Per-coordinate metadata // Per-coordinate metadata
struct Annotation struct Annotation

View File

@ -15,6 +15,7 @@
#include "util/integer_range.hpp" #include "util/integer_range.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/optional.hpp>
#include <vector> #include <vector>
namespace osrm namespace osrm
@ -28,43 +29,22 @@ struct PathData
NodeID from_edge_based_node; NodeID from_edge_based_node;
// the internal OSRM id of the OSM node id that is the via node of the turn // the internal OSRM id of the OSM node id that is the via node of the turn
NodeID turn_via_node; NodeID turn_via_node;
// name of the street that leads to the turn
unsigned name_id;
// segregated edge-based node that leads to the turn
bool is_segregated;
// weight that is traveled on the segment until the turn is reached // weight that is traveled on the segment until the turn is reached
// including the turn weight, if one exists // including the turn weight, if one exists
EdgeWeight weight_until_turn; EdgeWeight weight_until_turn;
// If this segment immediately preceeds a turn, then duration_of_turn // If this segment immediately precedes a turn, then duration_of_turn
// will contain the weight of the turn. Otherwise it will be 0. // will contain the weight of the turn. Otherwise it will be 0.
EdgeWeight weight_of_turn; EdgeWeight weight_of_turn;
// duration that is traveled on the segment until the turn is reached, // duration that is traveled on the segment until the turn is reached,
// including a turn if the segment preceeds one. // including a turn if the segment precedes one.
EdgeWeight duration_until_turn; EdgeWeight duration_until_turn;
// If this segment immediately preceeds a turn, then duration_of_turn // If this segment immediately precedes a turn, then duration_of_turn
// will contain the duration of the turn. Otherwise it will be 0. // will contain the duration of the turn. Otherwise it will be 0.
EdgeWeight duration_of_turn; EdgeWeight duration_of_turn;
// instruction to execute at the turn
osrm::guidance::TurnInstruction turn_instruction;
// turn lane data
util::guidance::LaneTupleIdPair lane_data;
// travel mode of the street that leads to the turn
extractor::TravelMode travel_mode : 4;
// user defined classed of the street that leads to the turn
extractor::ClassData classes;
// entry class of the turn, indicating possibility of turns
util::guidance::EntryClass entry_class;
// Source of the speed value on this road segment // Source of the speed value on this road segment
DatasourceID datasource_id; DatasourceID datasource_id;
// If segment precedes a turn, ID of the turn itself
// bearing (as seen from the intersection) pre-turn boost::optional<EdgeID> turn_edge;
osrm::guidance::TurnBearing pre_turn_bearing;
// bearing (as seen from the intersection) post-turn
osrm::guidance::TurnBearing post_turn_bearing;
// Driving side of the turn
bool is_left_hand_driving;
}; };
struct InternalRouteResult struct InternalRouteResult

View File

@ -176,11 +176,6 @@ void annotatePath(const FacadeT &facade,
const auto &edge_data = facade.GetEdgeData(*edge); const auto &edge_data = facade.GetEdgeData(*edge);
const auto turn_id = edge_data.turn_id; // edge-based graph edge index const auto turn_id = edge_data.turn_id; // edge-based graph edge index
const auto node_id = *node_from; // edge-based graph node index const auto node_id = *node_from; // edge-based graph node index
const auto name_index = facade.GetNameIndex(node_id);
const bool is_segregated = facade.IsSegregated(node_id);
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
const auto classes = facade.GetClassData(node_id);
const auto geometry_index = facade.GetGeometryIndex(node_id); const auto geometry_index = facade.GetGeometryIndex(node_id);
get_segment_geometry(geometry_index); get_segment_geometry(geometry_index);
@ -206,45 +201,29 @@ void annotatePath(const FacadeT &facade,
} }
const std::size_t end_index = weight_vector.size(); const std::size_t end_index = weight_vector.size();
bool is_left_hand_driving = facade.IsLeftHandDriving(node_id);
BOOST_ASSERT(start_index < end_index); BOOST_ASSERT(start_index < end_index);
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx) for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
{ {
unpacked_path.push_back( unpacked_path.push_back(
PathData{*node_from, PathData{node_id,
id_vector[segment_idx + 1], id_vector[segment_idx + 1],
name_index,
is_segregated,
static_cast<EdgeWeight>(weight_vector[segment_idx]), static_cast<EdgeWeight>(weight_vector[segment_idx]),
0, 0,
static_cast<EdgeDuration>(duration_vector[segment_idx]), static_cast<EdgeDuration>(duration_vector[segment_idx]),
0, 0,
guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
travel_mode,
classes,
EMPTY_ENTRY_CLASS,
datasource_vector[segment_idx], datasource_vector[segment_idx],
osrm::guidance::TurnBearing(0), boost::none});
osrm::guidance::TurnBearing(0),
is_left_hand_driving});
} }
BOOST_ASSERT(unpacked_path.size() > 0); BOOST_ASSERT(unpacked_path.size() > 0);
if (facade.HasLaneData(turn_id))
unpacked_path.back().lane_data = facade.GetLaneData(turn_id);
const auto turn_duration = facade.GetDurationPenaltyForEdgeID(turn_id); const auto turn_duration = facade.GetDurationPenaltyForEdgeID(turn_id);
const auto turn_weight = facade.GetWeightPenaltyForEdgeID(turn_id); const auto turn_weight = facade.GetWeightPenaltyForEdgeID(turn_id);
unpacked_path.back().entry_class = facade.GetEntryClass(turn_id);
unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().duration_until_turn += turn_duration; unpacked_path.back().duration_until_turn += turn_duration;
unpacked_path.back().duration_of_turn = turn_duration; unpacked_path.back().duration_of_turn = turn_duration;
unpacked_path.back().weight_until_turn += turn_weight; unpacked_path.back().weight_until_turn += turn_weight;
unpacked_path.back().weight_of_turn = turn_weight; unpacked_path.back().weight_of_turn = turn_weight;
unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(turn_id); unpacked_path.back().turn_edge = turn_id;
unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(turn_id);
} }
std::size_t start_index = 0, end_index = 0; std::size_t start_index = 0, end_index = 0;
@ -280,33 +259,22 @@ void annotatePath(const FacadeT &facade,
// t: fwd_segment 3 // t: fwd_segment 3
// -> (U, v), (v, w), (w, x) // -> (U, v), (v, w), (w, x)
// note that (x, t) is _not_ included but needs to be added later. // note that (x, t) is _not_ included but needs to be added later.
bool is_target_left_hand_driving = facade.IsLeftHandDriving(target_node_id);
for (std::size_t segment_idx = start_index; segment_idx != end_index; for (std::size_t segment_idx = start_index; segment_idx != end_index;
(start_index < end_index ? ++segment_idx : --segment_idx)) (start_index < end_index ? ++segment_idx : --segment_idx))
{ {
BOOST_ASSERT(segment_idx < static_cast<std::size_t>(id_vector.size() - 1)); BOOST_ASSERT(segment_idx < static_cast<std::size_t>(id_vector.size() - 1));
BOOST_ASSERT(facade.GetTravelMode(target_node_id) > 0);
unpacked_path.push_back( unpacked_path.push_back(
PathData{target_node_id, PathData{target_node_id,
id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1], id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
facade.GetNameIndex(target_node_id),
facade.IsSegregated(target_node_id),
static_cast<EdgeWeight>(weight_vector[segment_idx]), static_cast<EdgeWeight>(weight_vector[segment_idx]),
0, 0,
static_cast<EdgeDuration>(duration_vector[segment_idx]), static_cast<EdgeDuration>(duration_vector[segment_idx]),
0, 0,
guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
facade.GetTravelMode(target_node_id),
facade.GetClassData(target_node_id),
EMPTY_ENTRY_CLASS,
datasource_vector[segment_idx], datasource_vector[segment_idx],
guidance::TurnBearing(0), boost::none});
guidance::TurnBearing(0),
is_target_left_hand_driving});
} }
if (unpacked_path.size() > 0) if (!unpacked_path.empty())
{ {
const auto source_weight = start_traversed_in_reverse const auto source_weight = start_traversed_in_reverse
? phantom_node_pair.source_phantom.reverse_weight ? phantom_node_pair.source_phantom.reverse_weight

View File

@ -63,8 +63,8 @@ struct InternalExtractorEdge
WeightData weight_data, WeightData weight_data,
DurationData duration_data, DurationData duration_data,
util::Coordinate source_coordinate) util::Coordinate source_coordinate)
: result(source, target, 0, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)), : result(source, target, 0, 0, 0, {}, -1, {}), weight_data(weight_data),
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate)) duration_data(duration_data), source_coordinate(source_coordinate)
{ {
} }
@ -72,7 +72,7 @@ struct InternalExtractorEdge
WeightData weight_data, WeightData weight_data,
DurationData duration_data, DurationData duration_data,
util::Coordinate source_coordinate) util::Coordinate source_coordinate)
: result(std::move(edge)), weight_data(weight_data), duration_data(duration_data), : result(edge), weight_data(weight_data), duration_data(duration_data),
source_coordinate(source_coordinate) source_coordinate(source_coordinate)
{ {
} }

View File

@ -44,7 +44,7 @@ class RestrictionParser
RestrictionParser(bool use_turn_restrictions, RestrictionParser(bool use_turn_restrictions,
bool parse_conditionals, bool parse_conditionals,
std::vector<std::string> &restrictions); std::vector<std::string> &restrictions);
boost::optional<InputTurnRestriction> TryParse(const osmium::Relation &relation) const; std::vector<InputTurnRestriction> TryParse(const osmium::Relation &relation) const;
private: private:
bool ShouldIgnoreRestriction(const std::string &except_tag_string) const; bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;

View File

@ -675,6 +675,22 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
params->generate_hints = Nan::To<bool>(generate_hints).FromJust(); params->generate_hints = Nan::To<bool>(generate_hints).FromJust();
} }
if (Nan::Has(obj, Nan::New("skip_waypoints").ToLocalChecked()).FromJust())
{
v8::Local<v8::Value> skip_waypoints =
Nan::Get(obj, Nan::New("skip_waypoints").ToLocalChecked()).ToLocalChecked();
if (skip_waypoints.IsEmpty())
return false;
if (!skip_waypoints->IsBoolean())
{
Nan::ThrowError("skip_waypoints must be of type Boolean");
return false;
}
params->skip_waypoints = Nan::To<bool>(skip_waypoints).FromJust();
}
if (Nan::Has(obj, Nan::New("exclude").ToLocalChecked()).FromJust()) if (Nan::Has(obj, Nan::New("exclude").ToLocalChecked()).FromJust())
{ {
v8::Local<v8::Value> exclude = v8::Local<v8::Value> exclude =

View File

@ -24,9 +24,10 @@ namespace partitioner
// located at for use in the inertial flow sorting by slope. // located at for use in the inertial flow sorting by slope.
struct BisectionNode struct BisectionNode
{ {
BisectionNode(util::Coordinate coordinate_ = {util::FloatLongitude{0}, util::FloatLatitude{0}}, BisectionNode(const util::Coordinate &coordinate_ = {util::FloatLongitude{0},
util::FloatLatitude{0}},
const NodeID original_id_ = SPECIAL_NODEID) const NodeID original_id_ = SPECIAL_NODEID)
: coordinate(std::move(coordinate_)), original_id(original_id_) : coordinate(coordinate_), original_id(original_id_)
{ {
} }

View File

@ -195,7 +195,7 @@ inline DynamicEdgeBasedGraph LoadEdgeBasedGraph(const boost::filesystem::path &p
auto directed = splitBidirectionalEdges(edges); auto directed = splitBidirectionalEdges(edges);
auto tidied = prepareEdgesForUsageInGraph<DynamicEdgeBasedGraphEdge>(std::move(directed)); auto tidied = prepareEdgesForUsageInGraph<DynamicEdgeBasedGraphEdge>(std::move(directed));
return DynamicEdgeBasedGraph(number_of_edge_based_nodes, std::move(tidied), checksum); return DynamicEdgeBasedGraph(number_of_edge_based_nodes, tidied, checksum);
} }
} // namespace partitioner } // namespace partitioner

View File

@ -25,6 +25,7 @@ struct IOConfig
} }
bool IsValid() const; bool IsValid() const;
std::vector<std::string> GetMissingFiles() const;
boost::filesystem::path GetPath(const std::string &fileName) const boost::filesystem::path GetPath(const std::string &fileName) const
{ {
if (!IsConfigured(fileName, required_input_files) && if (!IsConfigured(fileName, required_input_files) &&

View File

@ -59,7 +59,7 @@ class BaseDataLayout
public: public:
virtual ~BaseDataLayout() = default; virtual ~BaseDataLayout() = default;
inline void SetBlock(const std::string &name, Block block) { blocks[name] = std::move(block); } inline void SetBlock(const std::string &name, const Block &block) { blocks[name] = block; }
inline std::uint64_t GetBlockEntries(const std::string &name) const inline std::uint64_t GetBlockEntries(const std::string &name) const
{ {

View File

@ -77,7 +77,7 @@ inline auto make_name_table_view(const SharedDataIndex &index, const std::string
auto values = auto values =
make_vector_view<extractor::NameTableView::IndexedData::ValueType>(index, name + "/values"); make_vector_view<extractor::NameTableView::IndexedData::ValueType>(index, name + "/values");
extractor::NameTableView::IndexedData index_data_view{std::move(blocks), std::move(values)}; extractor::NameTableView::IndexedData index_data_view{blocks, values};
return extractor::NameTableView{index_data_view}; return extractor::NameTableView{index_data_view};
} }
@ -156,14 +156,14 @@ inline auto make_segment_data_view(const SharedDataIndex &index, const std::stri
auto rev_datasources_list = auto rev_datasources_list =
make_vector_view<DatasourceID>(index, name + "/reverse_data_sources"); make_vector_view<DatasourceID>(index, name + "/reverse_data_sources");
return extractor::SegmentDataView{std::move(geometry_begin_indices), return extractor::SegmentDataView{geometry_begin_indices,
std::move(node_list), node_list,
std::move(fwd_weight_list), fwd_weight_list,
std::move(rev_weight_list), rev_weight_list,
std::move(fwd_duration_list), fwd_duration_list,
std::move(rev_duration_list), rev_duration_list,
std::move(fwd_datasources_list), fwd_datasources_list,
std::move(rev_datasources_list)}; rev_datasources_list};
} }
inline auto make_coordinates_view(const SharedDataIndex &index, const std::string &name) inline auto make_coordinates_view(const SharedDataIndex &index, const std::string &name)
@ -214,7 +214,7 @@ inline auto make_search_tree_view(const SharedDataIndex &index, const std::strin
} }
return util::StaticRTree<RTreeLeaf, storage::Ownership::View>{ return util::StaticRTree<RTreeLeaf, storage::Ownership::View>{
std::move(search_tree), std::move(rtree_level_starts), path, std::move(coordinates)}; search_tree, rtree_level_starts, path, coordinates};
} }
inline auto make_intersection_bearings_view(const SharedDataIndex &index, const std::string &name) inline auto make_intersection_bearings_view(const SharedDataIndex &index, const std::string &name)
@ -225,13 +225,11 @@ inline auto make_intersection_bearings_view(const SharedDataIndex &index, const
index, name + "/class_id_to_ranges/diff_blocks"); index, name + "/class_id_to_ranges/diff_blocks");
auto bearing_values = make_vector_view<DiscreteBearing>(index, name + "/bearing_values"); auto bearing_values = make_vector_view<DiscreteBearing>(index, name + "/bearing_values");
util::RangeTable<16, storage::Ownership::View> bearing_range_table( util::RangeTable<16, storage::Ownership::View> bearing_range_table(
std::move(bearing_offsets), bearing_offsets, bearing_blocks, static_cast<unsigned>(bearing_values.size()));
std::move(bearing_blocks),
static_cast<unsigned>(bearing_values.size()));
auto bearing_class_id = make_vector_view<BearingClassID>(index, name + "/node_to_class_id"); auto bearing_class_id = make_vector_view<BearingClassID>(index, name + "/node_to_class_id");
return extractor::IntersectionBearingsView{ return extractor::IntersectionBearingsView{
std::move(bearing_values), std::move(bearing_class_id), std::move(bearing_range_table)}; bearing_values, bearing_class_id, bearing_range_table};
} }
inline auto make_entry_classes_view(const SharedDataIndex &index, const std::string &name) inline auto make_entry_classes_view(const SharedDataIndex &index, const std::string &name)
@ -252,8 +250,7 @@ inline auto make_contracted_metric_view(const SharedDataIndex &index, const std:
edge_filter.push_back(make_vector_view<bool>(index, filter_name)); edge_filter.push_back(make_vector_view<bool>(index, filter_name));
})); }));
return contractor::ContractedMetricView{{std::move(node_list), std::move(edge_list)}, return contractor::ContractedMetricView{{node_list, edge_list}, std::move(edge_filter)};
std::move(edge_filter)};
} }
inline auto make_partition_view(const SharedDataIndex &index, const std::string &name) inline auto make_partition_view(const SharedDataIndex &index, const std::string &name)
@ -264,8 +261,7 @@ inline auto make_partition_view(const SharedDataIndex &index, const std::string
auto partition = make_vector_view<PartitionID>(index, name + "/partition"); auto partition = make_vector_view<PartitionID>(index, name + "/partition");
auto cell_to_children = make_vector_view<CellID>(index, name + "/cell_to_children"); auto cell_to_children = make_vector_view<CellID>(index, name + "/cell_to_children");
return partitioner::MultiLevelPartitionView{ return partitioner::MultiLevelPartitionView{level_data_ptr, partition, cell_to_children};
level_data_ptr, std::move(partition), std::move(cell_to_children)};
} }
inline auto make_timestamp_view(const SharedDataIndex &index, const std::string &name) inline auto make_timestamp_view(const SharedDataIndex &index, const std::string &name)
@ -280,10 +276,8 @@ inline auto make_cell_storage_view(const SharedDataIndex &index, const std::stri
auto cells = make_vector_view<partitioner::CellStorageView::CellData>(index, name + "/cells"); auto cells = make_vector_view<partitioner::CellStorageView::CellData>(index, name + "/cells");
auto level_offsets = make_vector_view<std::uint64_t>(index, name + "/level_to_cell_offset"); auto level_offsets = make_vector_view<std::uint64_t>(index, name + "/level_to_cell_offset");
return partitioner::CellStorageView{std::move(source_boundary), return partitioner::CellStorageView{
std::move(destination_boundary), source_boundary, destination_boundary, cells, level_offsets};
std::move(cells),
std::move(level_offsets)};
} }
inline auto make_filtered_cell_metric_view(const SharedDataIndex &index, inline auto make_filtered_cell_metric_view(const SharedDataIndex &index,
@ -301,8 +295,7 @@ inline auto make_filtered_cell_metric_view(const SharedDataIndex &index,
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id); auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
auto distances = make_vector_view<EdgeDistance>(index, distances_block_id); auto distances = make_vector_view<EdgeDistance>(index, distances_block_id);
return customizer::CellMetricView{ return customizer::CellMetricView{weights, durations, distances};
std::move(weights), std::move(durations), std::move(distances)};
} }
inline auto make_cell_metric_view(const SharedDataIndex &index, const std::string &name) inline auto make_cell_metric_view(const SharedDataIndex &index, const std::string &name)
@ -321,8 +314,7 @@ inline auto make_cell_metric_view(const SharedDataIndex &index, const std::strin
auto durations = make_vector_view<EdgeDuration>(index, durations_block_id); auto durations = make_vector_view<EdgeDuration>(index, durations_block_id);
auto distances = make_vector_view<EdgeDistance>(index, distances_block_id); auto distances = make_vector_view<EdgeDistance>(index, distances_block_id);
cell_metric_excludes.push_back(customizer::CellMetricView{ cell_metric_excludes.push_back(customizer::CellMetricView{weights, durations, distances});
std::move(weights), std::move(durations), std::move(distances)});
} }
return cell_metric_excludes; return cell_metric_excludes;
@ -342,14 +334,14 @@ inline auto make_multi_level_graph_view(const SharedDataIndex &index, const std:
auto is_forward_edge = make_vector_view<bool>(index, name + "/is_forward_edge"); auto is_forward_edge = make_vector_view<bool>(index, name + "/is_forward_edge");
auto is_backward_edge = make_vector_view<bool>(index, name + "/is_backward_edge"); auto is_backward_edge = make_vector_view<bool>(index, name + "/is_backward_edge");
return customizer::MultiLevelEdgeBasedGraphView(std::move(node_list), return customizer::MultiLevelEdgeBasedGraphView(node_list,
std::move(edge_list), edge_list,
std::move(node_to_offset), node_to_offset,
std::move(node_weights), node_weights,
std::move(node_durations), node_durations,
std::move(node_distances), node_distances,
std::move(is_forward_edge), is_forward_edge,
std::move(is_backward_edge)); is_backward_edge);
} }
inline auto make_maneuver_overrides_views(const SharedDataIndex &index, const std::string &name) inline auto make_maneuver_overrides_views(const SharedDataIndex &index, const std::string &name)

View File

@ -76,13 +76,13 @@ using NodeID = std::uint32_t;
using EdgeID = std::uint32_t; using EdgeID = std::uint32_t;
using NameID = std::uint32_t; using NameID = std::uint32_t;
using AnnotationID = std::uint32_t; using AnnotationID = std::uint32_t;
using PackedGeometryID = std::uint32_t;
using EdgeWeight = std::int32_t; using EdgeWeight = std::int32_t;
using EdgeDuration = std::int32_t; using EdgeDuration = std::int32_t;
using EdgeDistance = float; using EdgeDistance = float;
using SegmentWeight = std::uint32_t; using SegmentWeight = std::uint32_t;
using SegmentDuration = std::uint32_t; using SegmentDuration = std::uint32_t;
using TurnPenalty = std::int16_t; // turn penalty in 100ms units using TurnPenalty = std::int16_t; // turn penalty in 100ms units
using DataTimestamp = std::string;
static const std::size_t INVALID_INDEX = std::numeric_limits<std::size_t>::max(); static const std::size_t INVALID_INDEX = std::numeric_limits<std::size_t>::max();
@ -95,16 +95,13 @@ static const LaneDescriptionID INVALID_LANE_DESCRIPTIONID =
std::numeric_limits<LaneDescriptionID>::max(); std::numeric_limits<LaneDescriptionID>::max();
using BearingClassID = std::uint32_t; using BearingClassID = std::uint32_t;
static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits<BearingClassID>::max();
using DiscreteBearing = std::uint16_t; using DiscreteBearing = std::uint16_t;
using EntryClassID = std::uint16_t; using EntryClassID = std::uint16_t;
static const EntryClassID INVALID_ENTRY_CLASSID = std::numeric_limits<EntryClassID>::max();
static const NodeID SPECIAL_NODEID = std::numeric_limits<NodeID>::max(); static const NodeID SPECIAL_NODEID = std::numeric_limits<NodeID>::max();
static const NodeID SPECIAL_SEGMENTID = std::numeric_limits<NodeID>::max() >> 1; static const NodeID SPECIAL_SEGMENTID = std::numeric_limits<NodeID>::max() >> 1;
static const NodeID SPECIAL_GEOMETRYID = std::numeric_limits<NodeID>::max() >> 1; static const PackedGeometryID SPECIAL_GEOMETRYID =
std::numeric_limits<PackedGeometryID>::max() >> 1;
static const EdgeID SPECIAL_EDGEID = std::numeric_limits<EdgeID>::max(); static const EdgeID SPECIAL_EDGEID = std::numeric_limits<EdgeID>::max();
static const RestrictionID SPECIAL_RESTRICTIONID = std::numeric_limits<RestrictionID>::max(); static const RestrictionID SPECIAL_RESTRICTIONID = std::numeric_limits<RestrictionID>::max();
static const NameID INVALID_NAMEID = std::numeric_limits<NameID>::max(); static const NameID INVALID_NAMEID = std::numeric_limits<NameID>::max();
@ -123,13 +120,6 @@ static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max(); static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits<double>::max(); static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits<double>::max();
// FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent
// within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any
// min() / operator< checks due to the invalid truncation. In addition, using signed and unsigned
// weights produces problems. As a result we can only store 1 << 29 since the MSB is still reserved
// for the sign bit. See https://github.com/Project-OSRM/osrm-backend/issues/3677
static const EdgeWeight MAXIMAL_EDGE_DURATION_INT_30 = (1 << 29) - 1;
using DatasourceID = std::uint8_t; using DatasourceID = std::uint8_t;
using BisectionID = std::uint32_t; using BisectionID = std::uint32_t;
@ -158,11 +148,11 @@ struct SegmentID
*/ */
struct GeometryID struct GeometryID
{ {
GeometryID(const NodeID id_, const bool forward_) : id{id_}, forward{forward_} {} GeometryID(const PackedGeometryID id_, const bool forward_) : id{id_}, forward{forward_} {}
GeometryID() : id(std::numeric_limits<unsigned>::max() >> 1), forward(false) {} GeometryID() : id(std::numeric_limits<unsigned>::max() >> 1), forward(false) {}
NodeID id : 31; PackedGeometryID id : 31;
std::uint32_t forward : 1; std::uint32_t forward : 1;
}; };

View File

@ -105,7 +105,7 @@ int Contractor::Run()
std::tie(query_graph, edge_filters) = contractExcludableGraph( std::tie(query_graph, edge_filters) = contractExcludableGraph(
toContractorGraph(number_of_edge_based_nodes, std::move(edge_based_edge_list)), toContractorGraph(number_of_edge_based_nodes, std::move(edge_based_edge_list)),
std::move(node_weights), std::move(node_weights),
std::move(node_filters)); node_filters);
TIMER_STOP(contraction); TIMER_STOP(contraction);
util::Log() << "Contracted graph has " << query_graph.GetNumberOfEdges() << " edges."; util::Log() << "Contracted graph has " << query_graph.GetNumberOfEdges() << " edges.";
util::Log() << "Contraction took " << TIMER_SEC(contraction) << " sec"; util::Log() << "Contraction took " << TIMER_SEC(contraction) << " sec";

View File

@ -92,8 +92,7 @@ auto LoadAndUpdateEdgeExpandedGraph(const CustomizationConfig &config,
auto tidied = partitioner::prepareEdgesForUsageInGraph< auto tidied = partitioner::prepareEdgesForUsageInGraph<
typename partitioner::MultiLevelEdgeBasedGraph::InputEdge>(std::move(directed)); typename partitioner::MultiLevelEdgeBasedGraph::InputEdge>(std::move(directed));
auto edge_based_graph = auto edge_based_graph = partitioner::MultiLevelEdgeBasedGraph(mlp, num_nodes, tidied);
partitioner::MultiLevelEdgeBasedGraph(mlp, num_nodes, std::move(tidied));
return edge_based_graph; return edge_based_graph;
} }

View File

@ -279,8 +279,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
geometry.locations.begin() + offset); geometry.locations.begin() + offset);
geometry.annotations.erase(geometry.annotations.begin(), geometry.annotations.erase(geometry.annotations.begin(),
geometry.annotations.begin() + offset); geometry.annotations.begin() + offset);
geometry.osm_node_ids.erase(geometry.osm_node_ids.begin(), geometry.node_ids.erase(geometry.node_ids.begin(), geometry.node_ids.begin() + offset);
geometry.osm_node_ids.begin() + offset);
} }
auto const first_bearing = steps.front().maneuver.bearing_after; auto const first_bearing = steps.front().maneuver.bearing_after;
@ -377,7 +376,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
// remove all the last coordinates from the geometry // remove all the last coordinates from the geometry
geometry.locations.resize(geometry.segment_offsets.back() + 1); geometry.locations.resize(geometry.segment_offsets.back() + 1);
geometry.annotations.resize(geometry.segment_offsets.back()); geometry.annotations.resize(geometry.segment_offsets.back());
geometry.osm_node_ids.resize(geometry.segment_offsets.back() + 1); geometry.node_ids.resize(geometry.segment_offsets.back() + 1);
BOOST_ASSERT(geometry.segment_distances.back() <= 1); BOOST_ASSERT(geometry.segment_distances.back() <= 1);
geometry.segment_distances.pop_back(); geometry.segment_distances.pop_back();
@ -414,7 +413,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
// This can happen if the last coordinate snaps to a node in the unpacked geometry // This can happen if the last coordinate snaps to a node in the unpacked geometry
geometry.locations.pop_back(); geometry.locations.pop_back();
geometry.annotations.pop_back(); geometry.annotations.pop_back();
geometry.osm_node_ids.pop_back(); geometry.node_ids.pop_back();
geometry.segment_offsets.back()--; geometry.segment_offsets.back()--;
// since the last geometry includes the location of arrival, the arrival instruction // since the last geometry includes the location of arrival, the arrival instruction
// geometry overlaps with the previous segment // geometry overlaps with the previous segment
@ -436,7 +435,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
} }
BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.locations.size()); BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.locations.size());
BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.osm_node_ids.size()); BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.node_ids.size());
BOOST_ASSERT(geometry.segment_offsets.back() == geometry.annotations.size()); BOOST_ASSERT(geometry.segment_offsets.back() == geometry.annotations.size());
BOOST_ASSERT(steps.back().geometry_end == geometry.locations.size()); BOOST_ASSERT(steps.back().geometry_end == geometry.locations.size());
@ -541,7 +540,7 @@ std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps)
{ {
// End of road is a turn that helps to identify the location of a turn. If the turn does // End of road is a turn that helps to identify the location of a turn. If the turn does
// not pass by any oter intersections, the end-of-road characteristic does not improve // not pass by any other intersections, the end-of-road characteristic does not improve
// the instructions. // the instructions.
// Here we reduce the verbosity of our output by reducing end-of-road emissions in cases // Here we reduce the verbosity of our output by reducing end-of-road emissions in cases
// where no intersections have been passed in between. // where no intersections have been passed in between.

View File

@ -36,18 +36,7 @@ bool IsSupportedParameterCombination(const bool fixed_start,
const bool fixed_end, const bool fixed_end,
const bool roundtrip) const bool roundtrip)
{ {
if (fixed_start && fixed_end && !roundtrip) return roundtrip || fixed_start || fixed_end;
{
return true;
}
else if (roundtrip)
{
return true;
}
else
{
return false;
}
} }
// given the node order in which to visit, compute the actual route (with geometry, travel time and // given the node order in which to visit, compute the actual route (with geometry, travel time and
@ -142,6 +131,32 @@ void ManipulateTableForFSE(const std::size_t source_id,
//********* End of changes to table ************************************* //********* End of changes to table *************************************
} }
void ManipulateTableForNonRoundtripFS(const std::size_t source_id,
util::DistTableWrapper<EdgeWeight> &result_table)
{
// We can use the round-trip calculation to simulate non-round-trip fixed start
// by making all paths to the source location zero. Effectively finding an 'optimal'
// round-trip path that ignores the cost of getting back from any destination to the
// source.
for (const auto i : util::irange<size_t>(0, result_table.GetNumberOfNodes()))
{
result_table.SetValue(i, source_id, 0);
}
}
void ManipulateTableForNonRoundtripFE(const std::size_t destination_id,
util::DistTableWrapper<EdgeWeight> &result_table)
{
// We can use the round-trip calculation to simulate non-round-trip fixed end
// by making all paths from the destination to other locations zero.
// Effectively, finding an 'optimal' round-trip path that ignores the cost of getting
// from the destination to any source.
for (const auto i : util::irange<size_t>(0, result_table.GetNumberOfNodes()))
{
result_table.SetValue(destination_id, i, 0);
}
}
Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
const api::TripParameters &parameters, const api::TripParameters &parameters,
osrm::engine::api::ResultT &result) const osrm::engine::api::ResultT &result) const
@ -225,7 +240,7 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
return Status::Error; return Status::Error;
} }
const constexpr std::size_t BF_MAX_FEASABLE = 10; const constexpr std::size_t BF_MAX_FEASIBLE = 10;
BOOST_ASSERT_MSG(result_duration_table.size() == number_of_locations * number_of_locations, BOOST_ASSERT_MSG(result_duration_table.size() == number_of_locations * number_of_locations,
"Distance Table has wrong size"); "Distance Table has wrong size");
@ -238,11 +253,19 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
{ {
ManipulateTableForFSE(source_id, destination_id, result_duration_table); ManipulateTableForFSE(source_id, destination_id, result_duration_table);
} }
else if (!parameters.roundtrip && fixed_start)
{
ManipulateTableForNonRoundtripFS(source_id, result_duration_table);
}
else if (!parameters.roundtrip && fixed_end)
{
ManipulateTableForNonRoundtripFE(destination_id, result_duration_table);
}
std::vector<NodeID> duration_trip; std::vector<NodeID> duration_trip;
duration_trip.reserve(number_of_locations); duration_trip.reserve(number_of_locations);
// get an optimized order in which the destinations should be visited // get an optimized order in which the destinations should be visited
if (number_of_locations < BF_MAX_FEASABLE) if (number_of_locations < BF_MAX_FEASIBLE)
{ {
duration_trip = trip::BruteForceTrip(number_of_locations, result_duration_table); duration_trip = trip::BruteForceTrip(number_of_locations, result_duration_table);
} }
@ -251,20 +274,28 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
duration_trip = trip::FarthestInsertionTrip(number_of_locations, result_duration_table); duration_trip = trip::FarthestInsertionTrip(number_of_locations, result_duration_table);
} }
// rotate result such that roundtrip starts at node with index 0
// thist first if covers scenarios: !fixed_end || fixed_start || (fixed_start && fixed_end)
if (!fixed_end || fixed_start) if (!fixed_end || fixed_start)
{ {
// rotate result such that trip starts at node with index 0
auto desired_start_index = std::find(std::begin(duration_trip), std::end(duration_trip), 0); auto desired_start_index = std::find(std::begin(duration_trip), std::end(duration_trip), 0);
BOOST_ASSERT(desired_start_index != std::end(duration_trip)); BOOST_ASSERT(desired_start_index != std::end(duration_trip));
std::rotate(std::begin(duration_trip), desired_start_index, std::end(duration_trip)); std::rotate(std::begin(duration_trip), desired_start_index, std::end(duration_trip));
} }
else if (fixed_end && !fixed_start && parameters.roundtrip) else
{ { // fixed_end
auto desired_start_index = auto destination_index =
std::find(std::begin(duration_trip), std::end(duration_trip), destination_id); std::find(std::begin(duration_trip), std::end(duration_trip), destination_id);
BOOST_ASSERT(desired_start_index != std::end(duration_trip)); BOOST_ASSERT(destination_index != std::end(duration_trip));
std::rotate(std::begin(duration_trip), desired_start_index, std::end(duration_trip)); if (!parameters.roundtrip)
{
// We want the location after destination to be at the front
std::advance(destination_index, 1);
if (destination_index == std::end(duration_trip))
{
destination_index = std::begin(duration_trip);
}
}
std::rotate(std::begin(duration_trip), destination_index, std::end(duration_trip));
} }
// get the route when visiting all destinations in optimized order // get the route when visiting all destinations in optimized order

View File

@ -851,7 +851,7 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &sear
const auto extract_packed_path_from_heaps = [&](WeightedViaNode via) { const auto extract_packed_path_from_heaps = [&](WeightedViaNode via) {
auto packed_path = retrievePackedPathFromHeap(forward_heap, reverse_heap, via.node); auto packed_path = retrievePackedPathFromHeap(forward_heap, reverse_heap, via.node);
return WeightedViaNodePackedPath{std::move(via), std::move(packed_path)}; return WeightedViaNodePackedPath{via, std::move(packed_path)};
}; };
std::vector<WeightedViaNodePackedPath> weighted_packed_paths; std::vector<WeightedViaNodePackedPath> weighted_packed_paths;

View File

@ -71,7 +71,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const extractor::LaneDescriptionMap &lane_description_map) const extractor::LaneDescriptionMap &lane_description_map)
: m_edge_based_node_container(node_data_container), m_connectivity_checksum(0), : m_edge_based_node_container(node_data_container), m_connectivity_checksum(0),
m_number_of_edge_based_nodes(0), m_coordinates(coordinates), m_number_of_edge_based_nodes(0), m_coordinates(coordinates),
m_node_based_graph(std::move(node_based_graph)), m_barrier_nodes(barrier_nodes), m_node_based_graph(node_based_graph), m_barrier_nodes(barrier_nodes),
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container), m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
name_table(name_table), segregated_edges(segregated_edges), name_table(name_table), segregated_edges(segregated_edges),
lane_description_map(lane_description_map) lane_description_map(lane_description_map)

View File

@ -276,7 +276,7 @@ void ExtractionContainers::PrepareNodes()
continue; continue;
} }
BOOST_ASSERT(node_iter->node_id == *ref_iter); BOOST_ASSERT(node_iter->node_id == *ref_iter);
*used_nodes_iter = std::move(*ref_iter); *used_nodes_iter = *ref_iter;
used_nodes_iter++; used_nodes_iter++;
node_iter++; node_iter++;
ref_iter++; ref_iter++;

View File

@ -380,7 +380,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.pronunciation, parsed_way.pronunciation,
parsed_way.exits}; parsed_way.exits};
auto v = MapVal{name_id}; auto v = MapVal{name_id};
string_map.emplace(std::move(k), std::move(v)); string_map.emplace(std::move(k), v);
} }
else else
{ {
@ -441,8 +441,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.highway_turn_classification, parsed_way.highway_turn_classification,
parsed_way.access_turn_classification}}; parsed_way.access_turn_classification}};
external_memory.all_edges_list.push_back(InternalExtractorEdge( external_memory.all_edges_list.push_back(
std::move(edge), forward_weight_data, forward_duration_data, {})); InternalExtractorEdge(edge, forward_weight_data, forward_duration_data, {}));
}); });
} }
@ -475,8 +475,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.highway_turn_classification, parsed_way.highway_turn_classification,
parsed_way.access_turn_classification}}; parsed_way.access_turn_classification}};
external_memory.all_edges_list.push_back(InternalExtractorEdge( external_memory.all_edges_list.push_back(
std::move(edge), backward_weight_data, backward_duration_data, {})); InternalExtractorEdge(edge, backward_weight_data, backward_duration_data, {}));
}); });
} }

View File

@ -50,13 +50,13 @@ RestrictionParser::RestrictionParser(bool use_turn_restrictions_,
* in the corresponding profile. We use it for both namespacing restrictions, as in * in the corresponding profile. We use it for both namespacing restrictions, as in
* restriction:motorcar as well as whitelisting if its in except:motorcar. * restriction:motorcar as well as whitelisting if its in except:motorcar.
*/ */
boost::optional<InputTurnRestriction> std::vector<InputTurnRestriction>
RestrictionParser::TryParse(const osmium::Relation &relation) const RestrictionParser::TryParse(const osmium::Relation &relation) const
{ {
// return if turn restrictions should be ignored // return if turn restrictions should be ignored
if (!use_turn_restrictions) if (!use_turn_restrictions)
{ {
return boost::none; return {};
} }
osmium::tags::KeyFilter filter(false); osmium::tags::KeyFilter filter(false);
@ -85,17 +85,19 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
// if it's not a restriction, continue; // if it's not a restriction, continue;
if (std::distance(fi_begin, fi_end) == 0) if (std::distance(fi_begin, fi_end) == 0)
{ {
return boost::none; return {};
} }
// check if the restriction should be ignored // check if the restriction should be ignored
const char *except = relation.get_value_by_key("except"); const char *except = relation.get_value_by_key("except");
if (except != nullptr && ShouldIgnoreRestriction(except)) if (except != nullptr && ShouldIgnoreRestriction(except))
{ {
return boost::none; return {};
} }
bool is_only_restriction = false; bool is_only_restriction = false;
bool is_multi_from = false;
bool is_multi_to = false;
for (; fi_begin != fi_end; ++fi_begin) for (; fi_begin != fi_end; ++fi_begin)
{ {
@ -111,21 +113,26 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
else if (value.find("no_") == 0 && !boost::algorithm::ends_with(value, "_on_red")) else if (value.find("no_") == 0 && !boost::algorithm::ends_with(value, "_on_red"))
{ {
is_only_restriction = false; is_only_restriction = false;
if (boost::algorithm::starts_with(value, "no_exit"))
{
is_multi_to = true;
}
else if (boost::algorithm::starts_with(value, "no_entry"))
{
is_multi_from = true;
}
} }
else // unrecognized value type else // unrecognized value type
{ {
return boost::none; return {};
} }
} }
InputTurnRestriction restriction_container;
restriction_container.is_only = is_only_restriction;
constexpr auto INVALID_OSM_ID = std::numeric_limits<std::uint64_t>::max(); constexpr auto INVALID_OSM_ID = std::numeric_limits<std::uint64_t>::max();
auto from = INVALID_OSM_ID; std::vector<OSMWayID> from_ways;
auto via_node = INVALID_OSM_ID; auto via_node = INVALID_OSM_ID;
std::vector<OSMWayID> via_ways; std::vector<OSMWayID> via_ways;
auto to = INVALID_OSM_ID; std::vector<OSMWayID> to_ways;
bool is_node_restriction = true; bool is_node_restriction = true;
for (const auto &member : relation.members()) for (const auto &member : relation.members())
@ -157,11 +164,11 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
0 == strcmp("via", role)); 0 == strcmp("via", role));
if (0 == strcmp("from", role)) if (0 == strcmp("from", role))
{ {
from = static_cast<std::uint64_t>(member.ref()); from_ways.push_back({static_cast<std::uint64_t>(member.ref())});
} }
else if (0 == strcmp("to", role)) else if (0 == strcmp("to", role))
{ {
to = static_cast<std::uint64_t>(member.ref()); to_ways.push_back({static_cast<std::uint64_t>(member.ref())});
} }
else if (0 == strcmp("via", role)) else if (0 == strcmp("via", role))
{ {
@ -178,6 +185,7 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
} }
} }
std::vector<util::OpeningHours> condition;
// parse conditional tags // parse conditional tags
if (parse_conditionals) if (parse_conditionals)
{ {
@ -199,33 +207,55 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
std::vector<util::OpeningHours> hours = util::ParseOpeningHours(p.condition); std::vector<util::OpeningHours> hours = util::ParseOpeningHours(p.condition);
// found unrecognized condition, continue // found unrecognized condition, continue
if (hours.empty()) if (hours.empty())
return boost::none; return {};
restriction_container.condition = std::move(hours); condition = std::move(hours);
} }
} }
} }
if (from != INVALID_OSM_ID && (via_node != INVALID_OSM_ID || !via_ways.empty()) && std::vector<InputTurnRestriction> restriction_containers;
to != INVALID_OSM_ID) if (!from_ways.empty() && (via_node != INVALID_OSM_ID || !via_ways.empty()) && !to_ways.empty())
{ {
if (from_ways.size() > 1 && !is_multi_from)
{
util::Log(logDEBUG) << "Parsed restriction " << relation.id()
<< " unexpectedly contains " << from_ways.size()
<< " from ways, skipping...";
return {};
}
if (to_ways.size() > 1 && !is_multi_to)
{
util::Log(logDEBUG) << "Parsed restriction " << relation.id()
<< " unexpectedly contains " << to_ways.size()
<< " to ways, skipping...";
return {};
}
// Internally restrictions are represented with one 'from' and one 'to' way.
// Therefore we need to convert a multi from/to restriction into multiple restrictions.
for (const auto &from : from_ways)
{
for (const auto &to : to_ways)
{
InputTurnRestriction restriction;
restriction.is_only = is_only_restriction;
restriction.condition = condition;
if (is_node_restriction) if (is_node_restriction)
{ {
// template struct requires bracket for ID initialisation :( // template struct requires bracket for ID initialisation :(
restriction_container.node_or_way = InputNodeRestriction{{from}, {via_node}, {to}}; restriction.node_or_way = InputNodeRestriction{{from}, {via_node}, {to}};
} }
else else
{ {
// template struct requires bracket for ID initialisation :( // template struct requires bracket for ID initialisation :(
restriction_container.node_or_way = InputWayRestriction{{from}, via_ways, {to}}; restriction.node_or_way = InputWayRestriction{{from}, via_ways, {to}};
} }
return restriction_container; restriction_containers.push_back(std::move(restriction));
} }
else
{
return boost::none;
} }
} }
return restriction_containers;
}
bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const
{ {

View File

@ -909,13 +909,15 @@ void Sol2ScriptingEnvironment::ProcessElements(
case osmium::item_type::relation: case osmium::item_type::relation:
{ {
const auto &relation = static_cast<const osmium::Relation &>(*entity); const auto &relation = static_cast<const osmium::Relation &>(*entity);
if (auto result_res = restriction_parser.TryParse(relation)) auto results = restriction_parser.TryParse(relation);
if (!results.empty())
{ {
resulting_restrictions.push_back(*result_res); std::move(
results.begin(), results.end(), std::back_inserter(resulting_restrictions));
} }
else if (auto result_res = maneuver_override_parser.TryParse(relation)) else if (auto result_res = maneuver_override_parser.TryParse(relation))
{ {
resulting_maneuver_overrides.push_back(*result_res); resulting_maneuver_overrides.push_back(std::move(*result_res));
} }
} }
break; break;

View File

@ -10,6 +10,8 @@
#include "engine/engine_config.hpp" #include "engine/engine_config.hpp"
#include "engine/status.hpp" #include "engine/status.hpp"
#include <boost/algorithm/string/join.hpp>
#include <memory> #include <memory>
namespace osrm namespace osrm
@ -25,8 +27,11 @@ OSRM::OSRM(engine::EngineConfig &config)
// First, check that necessary core data is available // First, check that necessary core data is available
if (!config.use_shared_memory && !config.storage_config.IsValid()) if (!config.use_shared_memory && !config.storage_config.IsValid())
{ {
const auto &missingFiles = config.storage_config.GetMissingFiles();
throw util::exception("Required files are missing, cannot continue. Have all the " throw util::exception("Required files are missing, cannot continue. Have all the "
"pre-processing steps been run?"); "pre-processing steps been run? "
"Missing files: " +
boost::algorithm::join(missingFiles, ", "));
} }
// Now, check that the algorithm requested can be used with the data // Now, check that the algorithm requested can be used with the data

View File

@ -38,8 +38,8 @@ makeSpatialOrder(const BisectionGraphView &view, const double ratio, const doubl
{ {
struct NodeWithCoordinate struct NodeWithCoordinate
{ {
NodeWithCoordinate(NodeID nid_, util::Coordinate coordinate_) NodeWithCoordinate(NodeID nid_, const util::Coordinate &coordinate_)
: nid{nid_}, coordinate{std::move(coordinate_)} : nid{nid_}, coordinate{coordinate_}
{ {
} }

View File

@ -86,13 +86,13 @@ RecursiveBisection::RecursiveBisection(BisectionGraph &bisection_graph_,
TreeNode left_node{std::move(left_graph), node.depth + 1}; TreeNode left_node{std::move(left_graph), node.depth + 1};
if (!terminal(left_node)) if (!terminal(left_node))
feeder.add(std::move(left_node)); feeder.add(left_node);
BisectionGraphView right_graph{bisection_graph, center, node.graph.End()}; BisectionGraphView right_graph{bisection_graph, center, node.graph.End()};
TreeNode right_node{std::move(right_graph), node.depth + 1}; TreeNode right_node{std::move(right_graph), node.depth + 1};
if (!terminal(right_node)) if (!terminal(right_node))
feeder.add(std::move(right_node)); feeder.add(right_node);
}); });
TIMER_STOP(bisection); TIMER_STOP(bisection);

View File

@ -10,10 +10,11 @@ namespace osrm
{ {
namespace storage namespace storage
{ {
bool IOConfig::IsValid() const
{
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
bool IOConfig::IsValid() const
{
bool success = true; bool success = true;
for (auto &fileName : required_input_files) for (auto &fileName : required_input_files)
{ {
@ -26,5 +27,18 @@ bool IOConfig::IsValid() const
} }
return success; return success;
} }
std::vector<std::string> IOConfig::GetMissingFiles() const
{
std::vector<std::string> missingFiles;
for (auto &fileName : required_input_files)
{
if (!fs::is_regular_file(fs::path(base_path.string() + fileName.string())))
{
missingFiles.push_back(base_path.string() + fileName.string());
}
}
return missingFiles;
}
} // namespace storage } // namespace storage
} // namespace osrm } // namespace osrm

View File

@ -283,7 +283,7 @@ Coordinate interpolateLinear(double factor, const Coordinate from, const Coordin
FixedLatitude interpolated_lat{ FixedLatitude interpolated_lat{
static_cast<std::int32_t>(from_lat + factor * (to_lat - from_lat))}; static_cast<std::int32_t>(from_lat + factor * (to_lat - from_lat))};
return {std::move(interpolated_lon), std::move(interpolated_lat)}; return {interpolated_lon, interpolated_lat};
} }
// compute the signed area of a triangle // compute the signed area of a triangle

View File

@ -130,7 +130,7 @@ tables.forEach(function(annotation) {
}); });
test('table: ' + annotation + ' throws on invalid arguments', function(assert) { test('table: ' + annotation + ' throws on invalid arguments', function(assert) {
assert.plan(17); assert.plan(18);
var osrm = new OSRM(data_path); var osrm = new OSRM(data_path);
var options = {annotations: [annotation.slice(0,-1)]}; var options = {annotations: [annotation.slice(0,-1)]};
assert.throws(function() { osrm.table(options); }, assert.throws(function() { osrm.table(options); },
@ -190,6 +190,8 @@ tables.forEach(function(annotation) {
assert.throws(function() { osrm.route({coordinates: two_test_coordinates, generate_hints: null}, function(err, route) {}) }, assert.throws(function() { osrm.route({coordinates: two_test_coordinates, generate_hints: null}, function(err, route) {}) },
/generate_hints must be of type Boolean/); /generate_hints must be of type Boolean/);
assert.throws(function() { osrm.route({coordinates: two_test_coordinates, skip_waypoints: null}, function(err, route) {}) },
/skip_waypoints must be of type Boolean/);
}); });
test('table: throws on invalid arguments', function(assert) { test('table: throws on invalid arguments', function(assert) {
@ -239,6 +241,20 @@ tables.forEach(function(annotation) {
}); });
}); });
test('table: ' + annotation + ' table in Monaco without waypoints', function(assert) {
assert.plan(2);
var osrm = new OSRM(data_path);
var options = {
coordinates: two_test_coordinates,
skip_waypoints: true, // false is default
annotations: [annotation.slice(0,-1)]
};
osrm.table(options, function(err, table) {
assert.strictEqual(table.sources, undefined);
assert.strictEqual(table.destinations, undefined);
});
});
test('table: ' + annotation + ' table in Monaco without motorways', function(assert) { test('table: ' + annotation + ' table in Monaco without motorways', function(assert) {
assert.plan(2); assert.plan(2);
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'}); var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});

View File

@ -262,33 +262,19 @@ test('trip: routes Monaco with null hints', function(assert) {
}); });
test('trip: service combinations that are not implemented', function(assert) { test('trip: service combinations that are not implemented', function(assert) {
assert.plan(3); assert.plan(1);
var osrm = new OSRM(data_path); var osrm = new OSRM(data_path);
// fixed start, non-roundtrip // no fixed start, no fixed end, non-roundtrip
var options = { var options = {
coordinates: two_test_coordinates, coordinates: two_test_coordinates,
source: 'first', source: 'any',
destination: 'any',
roundtrip: false roundtrip: false
}; };
osrm.trip(options, function(err, second) { osrm.trip(options, function(err, second) {
assert.equal('NotImplemented', err.message); assert.equal('NotImplemented', err.message);
}); });
// fixed start, fixed end, non-roundtrip
options.source = 'any';
options.destination = 'any';
osrm.trip(options, function(err, second) {
assert.equal('NotImplemented', err.message);
});
// fixed end, non-roundtrip
delete options.source;
options.destination = 'last';
osrm.trip(options, function(err, second) {
assert.equal('NotImplemented', err.message);
});
}); });
test('trip: fixed start and end combinations', function(assert) { test('trip: fixed start and end combinations', function(assert) {
@ -302,16 +288,17 @@ test('trip: fixed start and end combinations', function(assert) {
geometries: 'geojson' geometries: 'geojson'
}; };
// fixed start and end, non-roundtrip // variations of non roundtrip
var nonRoundtripChecks = function(options) {
osrm.trip(options, function(err, fseTrip) { osrm.trip(options, function(err, fseTrip) {
assert.ifError(err); assert.ifError(err);
assert.equal(1, fseTrip.trips.length); assert.equal(1, fseTrip.trips.length);
var coordinates = fseTrip.trips[0].geometry.coordinates; var coordinates = fseTrip.trips[0].geometry.coordinates;
assert.notEqual(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1])); assert.notEqual(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1]));
}); });
};
// variations of roundtrip // variations of roundtrip
var roundtripChecks = function(options) { var roundtripChecks = function(options) {
osrm.trip(options, function(err, trip) { osrm.trip(options, function(err, trip) {
assert.ifError(err); assert.ifError(err);
@ -319,7 +306,20 @@ test('trip: fixed start and end combinations', function(assert) {
var coordinates = trip.trips[0].geometry.coordinates; var coordinates = trip.trips[0].geometry.coordinates;
assert.equal(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1])); assert.equal(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1]));
}); });
} };
// fixed start and end, non-roundtrip
nonRoundtripChecks(options);
// fixed start, non-roundtrip
delete options.destination;
options.source = 'first';
nonRoundtripChecks(options);
// fixed end, non-roundtrip
delete options.source;
options.destination = 'last';
nonRoundtripChecks(options);
// roundtrip, source and destination not specified // roundtrip, source and destination not specified
roundtripChecks({coordinates: options.coordinates, geometries: options.geometries}); roundtripChecks({coordinates: options.coordinates, geometries: options.geometries});
@ -327,6 +327,7 @@ test('trip: fixed start and end combinations', function(assert) {
// roundtrip, fixed destination // roundtrip, fixed destination
options.roundtrip = true; options.roundtrip = true;
delete options.source; delete options.source;
options.destination = 'last';
roundtripChecks(options); roundtripChecks(options);
//roundtrip, fixed source //roundtrip, fixed source

View File

@ -36,7 +36,7 @@ inline contractor::ContractorGraph makeGraph(const std::vector<TestEdge> &edges)
} }
std::sort(input_edges.begin(), input_edges.end()); std::sort(input_edges.begin(), input_edges.end());
return contractor::ContractorGraph{max_id + 1, std::move(input_edges)}; return contractor::ContractorGraph{max_id + 1, input_edges};
} }
} // namespace unit_test } // namespace unit_test
} // namespace osrm } // namespace osrm

View File

@ -19,8 +19,8 @@ BOOST_AUTO_TEST_CASE(unchanged_collapse_route_result)
PhantomNode target; PhantomNode target;
source.forward_segment_id = {1, true}; source.forward_segment_id = {1, true};
target.forward_segment_id = {6, true}; target.forward_segment_id = {6, true};
PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none};
PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none};
InternalRouteResult one_leg_result; InternalRouteResult one_leg_result;
one_leg_result.unpacked_path_segments = {{pathy, kathy}}; one_leg_result.unpacked_path_segments = {{pathy, kathy}};
one_leg_result.segment_end_coordinates = {PhantomNodes{source, target}}; one_leg_result.segment_end_coordinates = {PhantomNodes{source, target}};
@ -37,13 +37,11 @@ BOOST_AUTO_TEST_CASE(unchanged_collapse_route_result)
BOOST_AUTO_TEST_CASE(two_legs_to_one_leg) BOOST_AUTO_TEST_CASE(two_legs_to_one_leg)
{ {
// from_edge_based_node, turn_via_node, name_id, is_segregated, weight_until_turn, // from_edge_based_node, turn_via_node, weight_until_turn, weight_of_turn,
// weight_of_turn, // duration_until_turn, duration_of_turn, datasource_id, turn_edge
// duration_until_turn, duration_of_turn, turn_instruction, lane_data, travel_mode, classes, PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none};
// entry_class, datasource_id, pre_turn_bearing, post_turn_bearing, left_hand PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none};
PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none};
PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false};
PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false};
PhantomNode node_1; PhantomNode node_1;
PhantomNode node_2; PhantomNode node_2;
PhantomNode node_3; PhantomNode node_3;
@ -73,11 +71,11 @@ BOOST_AUTO_TEST_CASE(two_legs_to_one_leg)
BOOST_AUTO_TEST_CASE(three_legs_to_two_legs) BOOST_AUTO_TEST_CASE(three_legs_to_two_legs)
{ {
PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none};
PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none};
PathData qathy{0, 5, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PathData qathy{0, 5, 1, 2, 3, 4, 1, boost::none};
PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none};
PathData mathy{0, 4, 18, false, 8, 9, 13, 4, 2, {}, 4, 2, {}, 2, {3.0}, {1.0}, false}; PathData mathy{0, 4, 8, 9, 13, 4, 2, boost::none};
PhantomNode node_1; PhantomNode node_1;
PhantomNode node_2; PhantomNode node_2;
PhantomNode node_3; PhantomNode node_3;
@ -117,9 +115,9 @@ BOOST_AUTO_TEST_CASE(three_legs_to_two_legs)
BOOST_AUTO_TEST_CASE(two_legs_to_two_legs) BOOST_AUTO_TEST_CASE(two_legs_to_two_legs)
{ {
PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none};
PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none};
PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none};
PhantomNode node_1; PhantomNode node_1;
PhantomNode node_2; PhantomNode node_2;
PhantomNode node_3; PhantomNode node_3;

View File

@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
{FloatLongitude{-73.981495}, FloatLatitude{40.768275}}}; {FloatLongitude{-73.981495}, FloatLatitude{40.768275}}};
geometry.segment_offsets = {0, 2}; geometry.segment_offsets = {0, 2};
geometry.segment_distances = {1.9076601161280742}; geometry.segment_distances = {1.9076601161280742};
geometry.osm_node_ids = {OSMNodeID{0}, OSMNodeID{1}, OSMNodeID{2}}; geometry.node_ids = {NodeID{0}, NodeID{1}, NodeID{2}};
geometry.annotations = {{1.9076601161280742, 0.2, 0.2, 0}, {0, 0, 0, 0}}; geometry.annotations = {{1.9076601161280742, 0.2, 0.2, 0}, {0, 0, 0, 0}};
trimShortSegments(steps, geometry); trimShortSegments(steps, geometry);
@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
BOOST_CHECK_EQUAL(geometry.segment_offsets.back(), 1); BOOST_CHECK_EQUAL(geometry.segment_offsets.back(), 1);
BOOST_CHECK_EQUAL(geometry.annotations.size(), 1); BOOST_CHECK_EQUAL(geometry.annotations.size(), 1);
BOOST_CHECK_EQUAL(geometry.locations.size(), 2); BOOST_CHECK_EQUAL(geometry.locations.size(), 2);
BOOST_CHECK_EQUAL(geometry.osm_node_ids.size(), 2); BOOST_CHECK_EQUAL(geometry.node_ids.size(), 2);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -362,7 +362,7 @@ void test_tfse_illegal_parameters(bool use_json_only_api)
ResetParams(locations, params); ResetParams(locations, params);
params.source = TripParameters::SourceType::First; params.source = TripParameters::SourceType::First;
params.roundtrip = false; params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api); CheckOk(osrm, params, use_json_only_api);
ResetParams(locations, params); ResetParams(locations, params);
params.destination = TripParameters::DestinationType::Any; params.destination = TripParameters::DestinationType::Any;
@ -372,7 +372,7 @@ void test_tfse_illegal_parameters(bool use_json_only_api)
ResetParams(locations, params); ResetParams(locations, params);
params.destination = TripParameters::DestinationType::Last; params.destination = TripParameters::DestinationType::Last;
params.roundtrip = false; params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api); CheckOk(osrm, params, use_json_only_api);
// three parameters set // three parameters set
params.source = TripParameters::SourceType::Any; params.source = TripParameters::SourceType::Any;
@ -383,12 +383,12 @@ void test_tfse_illegal_parameters(bool use_json_only_api)
params.source = TripParameters::SourceType::Any; params.source = TripParameters::SourceType::Any;
params.destination = TripParameters::DestinationType::Last; params.destination = TripParameters::DestinationType::Last;
params.roundtrip = false; params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api); CheckOk(osrm, params, use_json_only_api);
params.source = TripParameters::SourceType::First; params.source = TripParameters::SourceType::First;
params.destination = TripParameters::DestinationType::Any; params.destination = TripParameters::DestinationType::Any;
params.roundtrip = false; params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api); CheckOk(osrm, params, use_json_only_api);
} }
BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_old_api) { test_tfse_illegal_parameters(true); } BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_old_api) { test_tfse_illegal_parameters(true); }
BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_new_api) { test_tfse_illegal_parameters(false); } BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_new_api) { test_tfse_illegal_parameters(false); }