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,
performance-*,
-performance-noexcept-move-constructor,
-performance-move-const-arg,
-performance-no-int-to-ptr,
readability-*,
-readability-avoid-const-params-in-decls,

View File

@ -68,12 +68,12 @@ jobs:
./scripts/format.sh && ./scripts/error_on_dirty.sh
node ./scripts/validate_changelog.js
npm run docs && ./scripts/error_on_dirty.sh
docker-image:
needs: format-taginfo-docs
runs-on: ubuntu-22.04
continue-on-error: false
steps:
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Enable osm.pbf cache
@ -85,7 +85,7 @@ jobs:
v1-berlin-osm-pbf
- name: Docker build
run: |
docker build -t osrm-backend-local -f docker/Dockerfile .
docker build -t osrm-backend-local -f docker/Dockerfile .
- name: Test Docker image
run: |
if [ ! -f "${PWD}/berlin-latest.osm.pbf" ]; then
@ -428,7 +428,7 @@ jobs:
CXXCOMPILER: ${{ matrix.CXXCOMPILER }}
CXXFLAGS: ${{ matrix.CXXFLAGS }}
ENABLE_ASSERTIONS: ${{ matrix.ENABLE_ASSERTIONS }}
ENABLE_CLANG_TIDY: ${{ matrix.ENABLE_CLANG_TIDY }}
ENABLE_CLANG_TIDY: ${{ matrix.ENABLE_CLANG_TIDY }}
ENABLE_COVERAGE: ${{ matrix.ENABLE_COVERAGE }}
ENABLE_GLIBC_WORKAROUND: ${{ matrix.ENABLE_GLIBC_WORKAROUND }}
ENABLE_CONAN: ${{ matrix.ENABLE_CONAN }}
@ -469,9 +469,9 @@ jobs:
uses: actions/cache@v2
with:
path: ${{github.workspace}}/test/cache
key: v2-test-${{ matrix.name }}-${{ github.sha }}
key: v3-test-${{ matrix.name }}-${{ github.sha }}
restore-keys: |
v2-test-${{ matrix.name }}-
v3-test-${{ matrix.name }}-
- name: Prepare environment
run: |
@ -668,7 +668,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
ci-complete:
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04
needs: [build-test-publish, docker-image, windows]
steps:
- run: echo "CI complete"

View File

@ -1,17 +1,23 @@
# Unreleased
- Changes from 5.26.0
- 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: 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:
- 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)
- 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)
- 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: 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:
- 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: 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)
@ -34,6 +40,11 @@
- 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 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
- Changes from 5.25.0

View File

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

View File

@ -1008,3 +1008,123 @@ Feature: Car - Turn restrictions
| from | to | route |
| d | x | bd,abc,xa,xa |
| 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 |
| 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
Given the node locations
| node | lat | lon |
@ -78,3 +103,30 @@ Feature: Locating Nearest node on a Way - pick closest way
| x | a |
| y | b |
| 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();
}
if (headers.has('data_version')) {
got.data_version = json.data_version || '';
}
// if header matches 'a:*', parse out the values for *
// and return in that header
headers.forEach((k) => {

View File

@ -8,6 +8,7 @@ module.exports = function () {
this.reprocessAndLoadData((e) => {
if (e) return callback(e);
var testRow = (row, ri, cb) => {
var inNode = this.findNodeByName(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) => {
if (err) return cb(err);
var coord;
var headers = new Set(table.raw()[0]);
if (response.statusCode === 200 && response.body.length) {
var json = JSON.parse(response.body);
@ -25,6 +27,10 @@ module.exports = function () {
var got = { in: row.in, out: row.out };
if (headers.has('data_version')) {
got.data_version = json.data_version || '';
}
Object.keys(row).forEach((key) => {
if (key === 'out') {
if (this.FuzzyMatch.matchLocation(coord, outNode)) {

View File

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

View File

@ -726,4 +726,5 @@ Feature: Basic Distance Matrix
| | 1 | 2 | 3 |
| 1 | 0 | 1000.1 | 1400.1 |
| 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 |
When I match I should get
| trace | timestamps | matchings |
| ab1d | 0 1 2 3 | ad |
| trace | timestamps | matchings | data_version |
| 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
Given the node map
@ -792,4 +811,5 @@ Feature: Basic Map Matching
When I match I should get
| trace | geometry | a:distance | a:duration | a:weight | duration |
| 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 |
When I route I should get
| from | to | route |
| 1 | b | adb,adb |
| 2 | b | adb,adb |
| 6 | b | aub,aub |
| 7 | b | aub,aub |
| from | to | route | data_version |
| 1 | b | adb,adb | |
| 2 | b | adb,adb | |
| 6 | 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
Given the node map
@ -182,4 +202,4 @@ Feature: Snap start/end point to the nearest way
| x | m | xe,xe |
| x | n | xf,xf |
| x | o | xg,xg |
| x | p | xh,xh |
| x | p | xh,xh |

View File

@ -5,7 +5,7 @@ Feature: Basic trip planning
Given the profile "testbot"
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
"""
a b
@ -20,8 +20,46 @@ Feature: Basic trip planning
| da |
When I plan a trip I should get
| waypoints | trips |
| a | aa |
| waypoints | trips | code |
| 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)
Given the node map
@ -38,9 +76,9 @@ Feature: Basic trip planning
| da |
When I plan a trip I should get
| waypoints | trips | durations |
| a,b,c,d | abcda | 7.6 |
| d,b,c,a | dbcad | 7.6 |
| waypoints | trips | durations | code |
| a,b,c,d | abcda | 7.6 | Ok |
| d,b,c,a | dbcad | 7.6 | Ok |
Scenario: Testbot - Trip: Roundtrip waypoints (more than 10)
Given the node map
@ -69,36 +107,37 @@ Feature: Basic trip planning
| waypoints | trips |
| a,b,c,d,e,f,g,h,i,j,k,l | alkjihgfedcba |
Scenario: Testbot - Trip: Roundtrip FS waypoints (more 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)
Scenario: Testbot - Trip: FS waypoints (less than 10)
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
"""
a b c d
@ -122,8 +161,67 @@ Feature: Basic trip planning
| la |
When I plan a trip I should get
| waypoints | trips |
| a,b,c,d,e,f,g,h,i,j,k,l | lkjihgfedcbal |
| waypoints | trips | roundtrip | durations |
| 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)
Given the node map
@ -274,7 +372,7 @@ Feature: Basic trip planning
| 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
"""
a 1 b
@ -370,4 +468,4 @@ Feature: Basic trip planning
When I plan a trip I should get
| waypoints | trips | durations | geometry |
| a,b,c,d | abcda | 7.6 | 1,1,1,1.00009,0.99991,1,1,1.00009,1,1,0.99991,1.00009,1,1 |
| d,b,c,a | dbcad | 7.6 | 0.99991,1.00009,1,1,1,1.00009,0.99991,1,1,1.00009,1,1,0.99991,1.00009 |
| d,b,c,a | dbcad | 7.6 | 0.99991,1.00009,1,1,1,1.00009,0.99991,1,1,1.00009,1,1,0.99991,1.00009 |

View File

@ -187,5 +187,5 @@ Feature: Check zero speed updates
When I plan a trip I should get
| waypoints | trips | code |
| a,b,c,d | abcda | NoTrips |
| d,b,c,a | dbcad | NoTrips |
| a,b,c,d | | 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));
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_,
@ -91,7 +91,7 @@ inline auto contractExcludableGraph(ContractorGraph contractor_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()};
}
} // namespace contractor

View File

@ -58,8 +58,8 @@ struct QueryEdge
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
QueryEdge(NodeID source, NodeID target, EdgeData data)
: source(source), target(target), data(std::move(data))
QueryEdge(NodeID source, NodeID target, const EdgeData &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["code"] = "Ok";
auto data_timestamp = facade.GetTimestamp();
if (!data_timestamp.empty())
{
response.values["data_version"] = data_timestamp;
}
}
protected:

View File

@ -116,6 +116,11 @@ class NearestAPI final : public BaseAPI
}
response.values["code"] = "Ok";
auto data_timestamp = facade.GetTimestamp();
if (!data_timestamp.empty())
{
response.values["data_version"] = data_timestamp;
}
}
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
// if annotations property was set manually after default construction
auto requested_annotations = parameters.annotations_type;
if ((parameters.annotations == true) &&
if (parameters.annotations &&
(parameters.annotations_type == RouteParameters::AnnotationsType::None))
{
requested_annotations = RouteParameters::AnnotationsType::All;
@ -497,10 +497,10 @@ class RouteAPI : public BaseAPI
std::vector<uint32_t> nodes;
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
{
nodes.reserve(leg_geometry.osm_node_ids.size());
for (const auto node_id : leg_geometry.osm_node_ids)
nodes.reserve(leg_geometry.node_ids.size());
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);
@ -515,7 +515,7 @@ class RouteAPI : public BaseAPI
{
const auto name = facade.GetDatasourceName(i);
// Length of 0 indicates the first empty name, so we can stop here
if (name.size() == 0)
if (name.empty())
break;
names.emplace_back(
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
// if annotations property was set manually after default construction
auto requested_annotations = parameters.annotations_type;
if ((parameters.annotations == true) &&
if (parameters.annotations &&
(parameters.annotations_type == RouteParameters::AnnotationsType::None))
{
requested_annotations = RouteParameters::AnnotationsType::All;
@ -825,10 +825,11 @@ class RouteAPI : public BaseAPI
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
{
util::json::Array nodes;
nodes.values.reserve(leg_geometry.osm_node_ids.size());
for (const auto node_id : leg_geometry.osm_node_ids)
nodes.values.reserve(leg_geometry.node_ids.size());
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);
}
@ -842,7 +843,7 @@ class RouteAPI : public BaseAPI
{
const auto name = facade.GetDatasourceName(i);
// Length of 0 indicates the first empty name, so we can stop here
if (name.size() == 0)
if (name.empty())
break;
datasource_names.values.push_back(std::string(facade.GetDatasourceName(i)));
}
@ -888,81 +889,92 @@ class RouteAPI : public BaseAPI
const bool reversed_source = source_traversed_in_reverse[idx];
const bool reversed_target = target_traversed_in_reverse[idx];
auto leg_geometry = guidance::assembleGeometry(BaseAPI::facade,
path_data,
phantoms.source_phantom,
phantoms.target_phantom,
reversed_source,
reversed_target);
auto leg = guidance::assembleLeg(facade,
path_data,
leg_geometry,
phantoms.source_phantom,
phantoms.target_phantom,
reversed_target,
parameters.steps);
reversed_target);
util::Log(logDEBUG) << "Assembling steps " << std::endl;
if (parameters.steps)
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)
{
auto steps = guidance::assembleSteps(BaseAPI::facade,
path_data,
leg_geometry,
phantoms.source_phantom,
phantoms.target_phantom,
reversed_source,
reversed_target);
// Apply maneuver overrides before any other post
// processing is performed
guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry);
leg_geometry = guidance::assembleGeometry(BaseAPI::facade,
path_data,
phantoms.source_phantom,
phantoms.target_phantom,
reversed_source,
reversed_target);
// Collapse segregated steps before others
steps = guidance::collapseSegregatedTurnInstructions(std::move(steps));
util::Log(logDEBUG) << "Assembling steps " << std::endl;
if (parameters.steps)
{
leg.summary = guidance::assembleSummary(
facade, path_data, phantoms.target_phantom, reversed_target);
/* Perform step-based post-processing.
*
* 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.
* We can only emit the exit nr/intersections up to/starting at a part of the leg.
* If a roundabout is not terminated in a leg, we will end up with a
*enter-roundabout
* and exit-roundabout-nr where the exit nr is out of sync with the previous enter.
*
* | S |
* * *
* ----* * ----
* T
* ----* * ----
* V * *
* | |
* | |
*
* Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say to
*take
* 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 enter a
*roundabout
* 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
* - handleRoundabouts must be called before collapseTurnInstructions that
* expects post-processed roundabouts
*/
auto steps = guidance::assembleSteps(BaseAPI::facade,
path_data,
leg_geometry,
phantoms.source_phantom,
phantoms.target_phantom,
reversed_source,
reversed_target);
guidance::trimShortSegments(steps, leg_geometry);
leg.steps = guidance::handleRoundabouts(std::move(steps));
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
leg.steps = guidance::anticipateLaneChange(std::move(leg.steps));
leg.steps = guidance::buildIntersections(std::move(leg.steps));
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
leg_geometry,
phantoms.source_phantom,
phantoms.target_phantom);
leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps);
// Apply maneuver overrides before any other post
// processing is performed
guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry);
// Collapse segregated steps before others
steps = guidance::collapseSegregatedTurnInstructions(std::move(steps));
/* Perform step-based post-processing.
*
* 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.
* We can only emit the exit nr/intersections up to/starting at a part of the
*leg. If a roundabout is not terminated in a leg, we will end up with a
*enter-roundabout
* and exit-roundabout-nr where the exit nr is out of sync with the previous
*enter.
*
* | S |
* * *
* ----* * ----
* T
* ----* * ----
* V * *
* | |
* | |
*
* Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say
*to take 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
*enter a roundabout 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
* - handleRoundabouts must be called before collapseTurnInstructions that
* expects post-processed roundabouts
*/
guidance::trimShortSegments(steps, leg_geometry);
leg.steps = guidance::handleRoundabouts(std::move(steps));
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
leg.steps = guidance::anticipateLaneChange(std::move(leg.steps));
leg.steps = guidance::buildIntersections(std::move(leg.steps));
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps),
leg_geometry,
phantoms.source_phantom,
phantoms.target_phantom);
leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps);
}
}
leg_geometries.push_back(std::move(leg_geometry));

View File

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

View File

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

View File

@ -36,24 +36,27 @@ template <> class AlgorithmDataFacade<CH>
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
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
FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const = 0;
virtual EdgeID FindEdgeIndicateIfReverse(const NodeID edge_based_node_from,
const NodeID edge_based_node_to,
bool &result) const = 0;
virtual EdgeID FindSmallestEdge(const NodeID from,
const NodeID to,
virtual EdgeID FindSmallestEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to,
const std::function<bool(EdgeData)> filter) const = 0;
};
@ -70,23 +73,24 @@ template <> class AlgorithmDataFacade<MLD>
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;
@ -94,10 +98,12 @@ template <> class AlgorithmDataFacade<MLD>
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
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 engine

View File

@ -73,45 +73,52 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
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); }
const EdgeData &GetEdgeData(const EdgeID e) const override final
NodeID GetTarget(const EdgeID edge_based_edge_id) 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
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
FindEdgeIndicateIfReverse(const NodeID from, const NodeID to, bool &result) const override final
EdgeID FindEdgeIndicateIfReverse(const NodeID edge_based_node_from,
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,
const NodeID to,
EdgeID FindSmallestEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to,
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:
using super = BaseDataFacade;
using IndexBlock = util::RangeTable<16, storage::Ownership::View>::BlockT;
using RTreeLeaf = super::RTreeLeaf;
using SharedRTree = util::StaticRTree<RTreeLeaf, storage::Ownership::View>;
using SharedGeospatialQuery = GeospatialQuery<SharedRTree, BaseDataFacade>;
using RTreeNode = SharedRTree::TreeNode;
extractor::ClassData exclude_mask;
extractor::ProfileProperties *m_profile_properties;
@ -231,76 +236,80 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
}
// 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);
}
NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const override final
NodeReverseRange GetUncompressedReverseGeometry(const PackedGeometryID id) const override final
{
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);
}
DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const override final
DurationReverseRange
GetUncompressedReverseDurations(const PackedGeometryID id) const override final
{
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);
}
WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const override final
WeightReverseRange GetUncompressedReverseWeights(const PackedGeometryID id) const override final
{
return segment_data.GetReverseWeights(id);
}
// Returns the data source ids that were used to supply the edge
// weights.
DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const override final
DatasourceForwardRange
GetUncompressedForwardDatasources(const PackedGeometryID id) const override final
{
return segment_data.GetForwardDatasources(id);
}
// Returns the data source ids that were used to supply the edge
// weights.
DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const override final
DatasourceReverseRange
GetUncompressedReverseDatasources(const PackedGeometryID id) const override final
{
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);
return m_turn_weight_penalties[id];
BOOST_ASSERT(m_turn_weight_penalties.size() > edge_based_edge_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);
return m_turn_duration_penalties[id];
BOOST_ASSERT(m_turn_duration_penalties.size() > edge_based_edge_id);
return m_turn_duration_penalties[edge_based_edge_id];
}
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,
@ -444,29 +453,29 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
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
@ -480,9 +489,9 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
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
@ -537,32 +546,37 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
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);
}
bool HasLaneData(const EdgeID id) const override final { return turn_data.HasLaneData(id); }
util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const override final
bool HasLaneData(const EdgeID edge_based_edge_id) const override final
{
BOOST_ASSERT(HasLaneData(id));
return m_lane_tupel_id_pairs.at(turn_data.GetLaneDataID(id));
return turn_data.HasLaneData(edge_based_edge_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
@ -577,15 +591,15 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
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
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>
@ -691,57 +705,62 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
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); }
const EdgeData &GetEdgeData(const EdgeID e) const override final
NodeID GetTarget(const EdgeID edge_based_edge_id) 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
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;
// 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 NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const = 0;
virtual NodeForwardRange GetUncompressedForwardGeometry(const PackedGeometryID 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.
// Should always be 1 shorter than GetUncompressedGeometry
virtual WeightForwardRange GetUncompressedForwardWeights(const EdgeID id) const = 0;
virtual WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const = 0;
virtual WeightForwardRange GetUncompressedForwardWeights(const PackedGeometryID id) const = 0;
virtual WeightReverseRange GetUncompressedReverseWeights(const PackedGeometryID id) const = 0;
// Gets the duration values for each segment in an uncompressed geometry.
// Should always be 1 shorter than GetUncompressedGeometry
virtual DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const = 0;
virtual DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const = 0;
virtual DurationForwardRange
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
// weights. Will return an empty array when only the base profile is used.
virtual DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const = 0;
virtual DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const = 0;
virtual DatasourceForwardRange
GetUncompressedForwardDatasources(const PackedGeometryID id) const = 0;
virtual DatasourceReverseRange
GetUncompressedReverseDatasources(const PackedGeometryID id) const = 0;
// Gets the name of a datasource
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;
@ -182,12 +187,12 @@ class BaseDataFacade
const Approach approach,
const bool use_all_edges = false) const = 0;
virtual bool HasLaneData(const EdgeID id) const = 0;
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
virtual bool HasLaneData(const EdgeID edge_based_edge_id) const = 0;
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID edge_based_edge_id) const = 0;
virtual extractor::TurnLaneDescription
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;
@ -209,16 +214,16 @@ class BaseDataFacade
virtual double GetWeightMultiplier() const = 0;
virtual osrm::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0;
virtual osrm::guidance::TurnBearing PostTurnBearing(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 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>
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 = facade.GetUncompressedForwardGeometry(source_geometry_id);
geometry.osm_node_ids.push_back(
facade.GetOSMNodeIDOfNode(source_geometry(source_segment_start_coordinate)));
geometry.node_ids.push_back(source_geometry(source_segment_start_coordinate));
auto cumulative_distance = 0.;
auto current_distance = 0.;
@ -71,7 +70,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
cumulative_distance += current_distance;
// 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_offsets.push_back(geometry.locations.size());
@ -79,11 +81,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
}
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 (osm_node_id != geometry.osm_node_ids.back() ||
path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn)
if (node_id != geometry.node_ids.back() ||
turn_instruction.type != osrm::guidance::TurnType::NoTurn)
{
geometry.annotations.emplace_back(LegGeometry::Annotation{
current_distance,
@ -98,8 +99,8 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
(path_point.weight_until_turn - path_point.weight_of_turn) /
facade.GetWeightMultiplier(),
path_point.datasource_id});
geometry.locations.push_back(std::move(coordinate));
geometry.osm_node_ids.push_back(osm_node_id);
geometry.locations.push_back(coordinate);
geometry.node_ids.push_back(node_id);
}
}
current_distance =
@ -158,8 +159,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
const auto target_segment_end_coordinate =
target_node.fwd_segment_position + (reversed_target ? 0 : 1);
const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id);
geometry.osm_node_ids.push_back(
facade.GetOSMNodeIDOfNode(target_geometry(target_segment_end_coordinate)));
geometry.node_ids.push_back(target_geometry(target_segment_end_coordinate));
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());

View File

@ -75,10 +75,14 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
std::vector<NamedSegment> segments(route_data.size());
std::uint32_t index = 0;
std::transform(
route_data.begin(), route_data.end(), segments.begin(), [&index](const PathData &point) {
return NamedSegment{point.duration_until_turn, index++, point.name_id};
});
std::transform(route_data.begin(),
route_data.end(),
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 =
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
const auto target_node_id = target_traversed_in_reverse ? target_node.reverse_segment_id.id
@ -124,21 +128,59 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
}
} // 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,
const std::vector<PathData> &route_data,
const LegGeometry &leg_geometry,
const PhantomNode &source_node,
const PhantomNode &target_node,
const bool target_traversed_in_reverse,
const bool needs_summary)
const bool target_traversed_in_reverse)
{
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 =
(target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration);
const auto target_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(
route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) {
return sum + data.duration_until_turn;
@ -182,39 +224,10 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
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.,
duration / 10.,
weight / facade.GetWeightMultiplier(),
summary,
"",
{}};
}

View File

@ -19,6 +19,7 @@
#include <boost/optional.hpp>
#include <cstddef>
#include <guidance/turn_bearing.hpp>
#include <vector>
namespace osrm
@ -96,7 +97,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
{},
source_classes};
if (leg_data.size() > 0)
if (!leg_data.empty())
{
// PathData saves the information we need of the segment _before_ 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;
// 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);
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 distance = leg_geometry.segment_distances[segment_index];
// 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,
step_name_id,
@ -140,17 +150,19 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
segment_duration / 10.,
distance,
segment_weight / weight_multiplier,
path_point.travel_mode,
travel_mode,
maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1,
{intersection},
path_point.is_left_hand_driving});
is_left_hand_driving});
if (leg_data_index + 1 < leg_data.size())
{
step_name_id = leg_data[leg_data_index + 1].name_id;
is_segregated = leg_data[leg_data_index + 1].is_segregated;
step_name_id =
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
{
@ -159,20 +171,33 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
}
// extract bearings
bearings = std::make_pair<std::uint16_t, std::uint16_t>(
path_point.pre_turn_bearing.Get(), path_point.post_turn_bearing.Get());
auto pre_turn_bearing = path_point.turn_edge
? 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);
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.out = bearing_class.findMatchingBearing(bearings.second);
intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
intersection.bearings.clear();
intersection.bearings.reserve(bearing_data.size());
intersection.lanes = path_point.lane_data.first;
intersection.lane_description =
path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID
? facade.GetTurnDescription(path_point.lane_data.second)
: extractor::TurnLaneDescription();
intersection.lanes = lane_data.first;
intersection.lane_description = lane_data.second != INVALID_LANE_DESCRIPTIONID
? facade.GetTurnDescription(lane_data.second)
: extractor::TurnLaneDescription();
// Lanes in turn are bound by total number of lanes at the location
BOOST_ASSERT(intersection.lanes.lanes_in_turn <=
@ -183,20 +208,23 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
(!intersection.lane_description.empty() &&
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(),
bearing_data.end(),
std::back_inserter(intersection.bearings));
intersection.entry.clear();
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 =
util::bearing::reverse(std::round(bearings.first));
maneuver = {intersection.location,
bearing_in_driving_direction,
bearings.second,
path_point.turn_instruction,
turn_instruction,
WaypointType::None,
0};
segment_index++;
@ -269,7 +297,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
leg_geometry.segment_distances[segment_index],
weight / weight_multiplier,
source_mode,
std::move(maneuver),
maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1,
{intersection},
@ -312,7 +340,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
ZERO_DISTANCE,
ZERO_WEIGHT,
target_mode,
std::move(maneuver),
maneuver,
leg_geometry.locations.size() - 1,
leg_geometry.locations.size(),
{intersection},

View File

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

View File

@ -15,6 +15,7 @@
#include "util/integer_range.hpp"
#include "util/typedefs.hpp"
#include <boost/optional.hpp>
#include <vector>
namespace osrm
@ -28,43 +29,22 @@ struct PathData
NodeID from_edge_based_node;
// the internal OSRM id of the OSM node id that is the via node of the turn
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
// including the turn weight, if one exists
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.
EdgeWeight weight_of_turn;
// 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;
// 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.
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
DatasourceID datasource_id;
// bearing (as seen from the intersection) pre-turn
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;
// If segment precedes a turn, ID of the turn itself
boost::optional<EdgeID> turn_edge;
};
struct InternalRouteResult

View File

@ -176,11 +176,6 @@ void annotatePath(const FacadeT &facade,
const auto &edge_data = facade.GetEdgeData(*edge);
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 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);
get_segment_geometry(geometry_index);
@ -206,45 +201,29 @@ void annotatePath(const FacadeT &facade,
}
const std::size_t end_index = weight_vector.size();
bool is_left_hand_driving = facade.IsLeftHandDriving(node_id);
BOOST_ASSERT(start_index < end_index);
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
{
unpacked_path.push_back(
PathData{*node_from,
PathData{node_id,
id_vector[segment_idx + 1],
name_index,
is_segregated,
static_cast<EdgeWeight>(weight_vector[segment_idx]),
0,
static_cast<EdgeDuration>(duration_vector[segment_idx]),
0,
guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
travel_mode,
classes,
EMPTY_ENTRY_CLASS,
datasource_vector[segment_idx],
osrm::guidance::TurnBearing(0),
osrm::guidance::TurnBearing(0),
is_left_hand_driving});
boost::none});
}
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_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_of_turn = turn_duration;
unpacked_path.back().weight_until_turn += turn_weight;
unpacked_path.back().weight_of_turn = turn_weight;
unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(turn_id);
unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(turn_id);
unpacked_path.back().turn_edge = turn_id;
}
std::size_t start_index = 0, end_index = 0;
@ -280,33 +259,22 @@ void annotatePath(const FacadeT &facade,
// t: fwd_segment 3
// -> (U, v), (v, w), (w, x)
// 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;
(start_index < end_index ? ++segment_idx : --segment_idx))
{
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(
PathData{target_node_id,
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]),
0,
static_cast<EdgeDuration>(duration_vector[segment_idx]),
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],
guidance::TurnBearing(0),
guidance::TurnBearing(0),
is_target_left_hand_driving});
boost::none});
}
if (unpacked_path.size() > 0)
if (!unpacked_path.empty())
{
const auto source_weight = start_traversed_in_reverse
? phantom_node_pair.source_phantom.reverse_weight

View File

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

View File

@ -44,7 +44,7 @@ class RestrictionParser
RestrictionParser(bool use_turn_restrictions,
bool parse_conditionals,
std::vector<std::string> &restrictions);
boost::optional<InputTurnRestriction> TryParse(const osmium::Relation &relation) const;
std::vector<InputTurnRestriction> TryParse(const osmium::Relation &relation) const;
private:
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();
}
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())
{
v8::Local<v8::Value> exclude =

View File

@ -24,9 +24,10 @@ namespace partitioner
// located at for use in the inertial flow sorting by slope.
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)
: 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 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

View File

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

View File

@ -59,7 +59,7 @@ class BaseDataLayout
public:
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
{

View File

@ -77,7 +77,7 @@ inline auto make_name_table_view(const SharedDataIndex &index, const std::string
auto 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};
}
@ -156,14 +156,14 @@ inline auto make_segment_data_view(const SharedDataIndex &index, const std::stri
auto rev_datasources_list =
make_vector_view<DatasourceID>(index, name + "/reverse_data_sources");
return extractor::SegmentDataView{std::move(geometry_begin_indices),
std::move(node_list),
std::move(fwd_weight_list),
std::move(rev_weight_list),
std::move(fwd_duration_list),
std::move(rev_duration_list),
std::move(fwd_datasources_list),
std::move(rev_datasources_list)};
return extractor::SegmentDataView{geometry_begin_indices,
node_list,
fwd_weight_list,
rev_weight_list,
fwd_duration_list,
rev_duration_list,
fwd_datasources_list,
rev_datasources_list};
}
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>{
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)
@ -225,13 +225,11 @@ inline auto make_intersection_bearings_view(const SharedDataIndex &index, const
index, name + "/class_id_to_ranges/diff_blocks");
auto bearing_values = make_vector_view<DiscreteBearing>(index, name + "/bearing_values");
util::RangeTable<16, storage::Ownership::View> bearing_range_table(
std::move(bearing_offsets),
std::move(bearing_blocks),
static_cast<unsigned>(bearing_values.size()));
bearing_offsets, bearing_blocks, static_cast<unsigned>(bearing_values.size()));
auto bearing_class_id = make_vector_view<BearingClassID>(index, name + "/node_to_class_id");
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)
@ -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));
}));
return contractor::ContractedMetricView{{std::move(node_list), std::move(edge_list)},
std::move(edge_filter)};
return contractor::ContractedMetricView{{node_list, edge_list}, std::move(edge_filter)};
}
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 cell_to_children = make_vector_view<CellID>(index, name + "/cell_to_children");
return partitioner::MultiLevelPartitionView{
level_data_ptr, std::move(partition), std::move(cell_to_children)};
return partitioner::MultiLevelPartitionView{level_data_ptr, partition, cell_to_children};
}
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 level_offsets = make_vector_view<std::uint64_t>(index, name + "/level_to_cell_offset");
return partitioner::CellStorageView{std::move(source_boundary),
std::move(destination_boundary),
std::move(cells),
std::move(level_offsets)};
return partitioner::CellStorageView{
source_boundary, destination_boundary, cells, level_offsets};
}
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 distances = make_vector_view<EdgeDistance>(index, distances_block_id);
return customizer::CellMetricView{
std::move(weights), std::move(durations), std::move(distances)};
return customizer::CellMetricView{weights, durations, distances};
}
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 distances = make_vector_view<EdgeDistance>(index, distances_block_id);
cell_metric_excludes.push_back(customizer::CellMetricView{
std::move(weights), std::move(durations), std::move(distances)});
cell_metric_excludes.push_back(customizer::CellMetricView{weights, durations, distances});
}
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_backward_edge = make_vector_view<bool>(index, name + "/is_backward_edge");
return customizer::MultiLevelEdgeBasedGraphView(std::move(node_list),
std::move(edge_list),
std::move(node_to_offset),
std::move(node_weights),
std::move(node_durations),
std::move(node_distances),
std::move(is_forward_edge),
std::move(is_backward_edge));
return customizer::MultiLevelEdgeBasedGraphView(node_list,
edge_list,
node_to_offset,
node_weights,
node_durations,
node_distances,
is_forward_edge,
is_backward_edge);
}
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 NameID = std::uint32_t;
using AnnotationID = std::uint32_t;
using PackedGeometryID = std::uint32_t;
using EdgeWeight = std::int32_t;
using EdgeDuration = std::int32_t;
using EdgeDistance = float;
using SegmentWeight = std::uint32_t;
using SegmentDuration = std::uint32_t;
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();
@ -95,16 +95,13 @@ static const LaneDescriptionID INVALID_LANE_DESCRIPTIONID =
std::numeric_limits<LaneDescriptionID>::max();
using BearingClassID = std::uint32_t;
static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits<BearingClassID>::max();
using DiscreteBearing = 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_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 RestrictionID SPECIAL_RESTRICTIONID = std::numeric_limits<RestrictionID>::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_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 BisectionID = std::uint32_t;
@ -158,11 +148,11 @@ struct SegmentID
*/
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) {}
NodeID id : 31;
PackedGeometryID id : 31;
std::uint32_t forward : 1;
};

View File

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

View File

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

View File

@ -279,8 +279,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
geometry.locations.begin() + offset);
geometry.annotations.erase(geometry.annotations.begin(),
geometry.annotations.begin() + offset);
geometry.osm_node_ids.erase(geometry.osm_node_ids.begin(),
geometry.osm_node_ids.begin() + offset);
geometry.node_ids.erase(geometry.node_ids.begin(), geometry.node_ids.begin() + offset);
}
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
geometry.locations.resize(geometry.segment_offsets.back() + 1);
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);
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
geometry.locations.pop_back();
geometry.annotations.pop_back();
geometry.osm_node_ids.pop_back();
geometry.node_ids.pop_back();
geometry.segment_offsets.back()--;
// since the last geometry includes the location of arrival, the arrival instruction
// 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.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(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
// 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.
// Here we reduce the verbosity of our output by reducing end-of-road emissions in cases
// 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 roundtrip)
{
if (fixed_start && fixed_end && !roundtrip)
{
return true;
}
else if (roundtrip)
{
return true;
}
else
{
return false;
}
return roundtrip || fixed_start || fixed_end;
}
// 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 *************************************
}
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,
const api::TripParameters &parameters,
osrm::engine::api::ResultT &result) const
@ -225,7 +240,7 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
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,
"Distance Table has wrong size");
@ -238,11 +253,19 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
{
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;
duration_trip.reserve(number_of_locations);
// 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);
}
@ -251,20 +274,28 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
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)
{
// 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);
BOOST_ASSERT(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)
{
auto desired_start_index =
else
{ // fixed_end
auto destination_index =
std::find(std::begin(duration_trip), std::end(duration_trip), destination_id);
BOOST_ASSERT(desired_start_index != std::end(duration_trip));
std::rotate(std::begin(duration_trip), desired_start_index, std::end(duration_trip));
BOOST_ASSERT(destination_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

View File

@ -851,7 +851,7 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &sear
const auto extract_packed_path_from_heaps = [&](WeightedViaNode via) {
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;

View File

@ -71,7 +71,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const extractor::LaneDescriptionMap &lane_description_map)
: m_edge_based_node_container(node_data_container), m_connectivity_checksum(0),
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),
name_table(name_table), segregated_edges(segregated_edges),
lane_description_map(lane_description_map)

View File

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

View File

@ -380,7 +380,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.pronunciation,
parsed_way.exits};
auto v = MapVal{name_id};
string_map.emplace(std::move(k), std::move(v));
string_map.emplace(std::move(k), v);
}
else
{
@ -441,8 +441,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.highway_turn_classification,
parsed_way.access_turn_classification}};
external_memory.all_edges_list.push_back(InternalExtractorEdge(
std::move(edge), forward_weight_data, forward_duration_data, {}));
external_memory.all_edges_list.push_back(
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.access_turn_classification}};
external_memory.all_edges_list.push_back(InternalExtractorEdge(
std::move(edge), backward_weight_data, backward_duration_data, {}));
external_memory.all_edges_list.push_back(
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
* restriction:motorcar as well as whitelisting if its in except:motorcar.
*/
boost::optional<InputTurnRestriction>
std::vector<InputTurnRestriction>
RestrictionParser::TryParse(const osmium::Relation &relation) const
{
// return if turn restrictions should be ignored
if (!use_turn_restrictions)
{
return boost::none;
return {};
}
osmium::tags::KeyFilter filter(false);
@ -85,17 +85,19 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
// if it's not a restriction, continue;
if (std::distance(fi_begin, fi_end) == 0)
{
return boost::none;
return {};
}
// check if the restriction should be ignored
const char *except = relation.get_value_by_key("except");
if (except != nullptr && ShouldIgnoreRestriction(except))
{
return boost::none;
return {};
}
bool is_only_restriction = false;
bool is_multi_from = false;
bool is_multi_to = false;
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"))
{
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
{
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();
auto from = INVALID_OSM_ID;
std::vector<OSMWayID> from_ways;
auto via_node = INVALID_OSM_ID;
std::vector<OSMWayID> via_ways;
auto to = INVALID_OSM_ID;
std::vector<OSMWayID> to_ways;
bool is_node_restriction = true;
for (const auto &member : relation.members())
@ -157,11 +164,11 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
0 == strcmp("via", 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))
{
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))
{
@ -178,6 +185,7 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
}
}
std::vector<util::OpeningHours> condition;
// parse conditional tags
if (parse_conditionals)
{
@ -199,32 +207,54 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
std::vector<util::OpeningHours> hours = util::ParseOpeningHours(p.condition);
// found unrecognized condition, continue
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()) &&
to != INVALID_OSM_ID)
std::vector<InputTurnRestriction> restriction_containers;
if (!from_ways.empty() && (via_node != INVALID_OSM_ID || !via_ways.empty()) && !to_ways.empty())
{
if (is_node_restriction)
if (from_ways.size() > 1 && !is_multi_from)
{
// template struct requires bracket for ID initialisation :(
restriction_container.node_or_way = InputNodeRestriction{{from}, {via_node}, {to}};
util::Log(logDEBUG) << "Parsed restriction " << relation.id()
<< " unexpectedly contains " << from_ways.size()
<< " from ways, skipping...";
return {};
}
else
if (to_ways.size() > 1 && !is_multi_to)
{
// template struct requires bracket for ID initialisation :(
restriction_container.node_or_way = InputWayRestriction{{from}, via_ways, {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)
{
// template struct requires bracket for ID initialisation :(
restriction.node_or_way = InputNodeRestriction{{from}, {via_node}, {to}};
}
else
{
// template struct requires bracket for ID initialisation :(
restriction.node_or_way = InputWayRestriction{{from}, via_ways, {to}};
}
restriction_containers.push_back(std::move(restriction));
}
}
return restriction_container;
}
else
{
return boost::none;
}
return restriction_containers;
}
bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const

View File

@ -909,13 +909,15 @@ void Sol2ScriptingEnvironment::ProcessElements(
case osmium::item_type::relation:
{
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))
{
resulting_maneuver_overrides.push_back(*result_res);
resulting_maneuver_overrides.push_back(std::move(*result_res));
}
}
break;

View File

@ -10,6 +10,8 @@
#include "engine/engine_config.hpp"
#include "engine/status.hpp"
#include <boost/algorithm/string/join.hpp>
#include <memory>
namespace osrm
@ -25,8 +27,11 @@ OSRM::OSRM(engine::EngineConfig &config)
// First, check that necessary core data is available
if (!config.use_shared_memory && !config.storage_config.IsValid())
{
throw util::exception("Required files are missing, cannot continue. Have all the "
"pre-processing steps been run?");
const auto &missingFiles = config.storage_config.GetMissingFiles();
throw util::exception("Required files are missing, cannot continue. Have all the "
"pre-processing steps been run? "
"Missing files: " +
boost::algorithm::join(missingFiles, ", "));
}
// 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
{
NodeWithCoordinate(NodeID nid_, util::Coordinate coordinate_)
: nid{nid_}, coordinate{std::move(coordinate_)}
NodeWithCoordinate(NodeID nid_, const util::Coordinate &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};
if (!terminal(left_node))
feeder.add(std::move(left_node));
feeder.add(left_node);
BisectionGraphView right_graph{bisection_graph, center, node.graph.End()};
TreeNode right_node{std::move(right_graph), node.depth + 1};
if (!terminal(right_node))
feeder.add(std::move(right_node));
feeder.add(right_node);
});
TIMER_STOP(bisection);

View File

@ -10,10 +10,11 @@ namespace osrm
{
namespace storage
{
namespace fs = boost::filesystem;
bool IOConfig::IsValid() const
{
namespace fs = boost::filesystem;
bool success = true;
for (auto &fileName : required_input_files)
{
@ -26,5 +27,18 @@ bool IOConfig::IsValid() const
}
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 osrm

View File

@ -283,7 +283,7 @@ Coordinate interpolateLinear(double factor, const Coordinate from, const Coordin
FixedLatitude interpolated_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

View File

@ -130,7 +130,7 @@ tables.forEach(function(annotation) {
});
test('table: ' + annotation + ' throws on invalid arguments', function(assert) {
assert.plan(17);
assert.plan(18);
var osrm = new OSRM(data_path);
var options = {annotations: [annotation.slice(0,-1)]};
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) {}) },
/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) {
@ -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) {
assert.plan(2);
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) {
assert.plan(3);
assert.plan(1);
var osrm = new OSRM(data_path);
// fixed start, non-roundtrip
// no fixed start, no fixed end, non-roundtrip
var options = {
coordinates: two_test_coordinates,
source: 'first',
source: 'any',
destination: 'any',
roundtrip: false
};
osrm.trip(options, function(err, second) {
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) {
@ -302,16 +288,17 @@ test('trip: fixed start and end combinations', function(assert) {
geometries: 'geojson'
};
// fixed start and end, non-roundtrip
osrm.trip(options, function(err, fseTrip) {
assert.ifError(err);
assert.equal(1, fseTrip.trips.length);
var coordinates = fseTrip.trips[0].geometry.coordinates;
assert.notEqual(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1]));
});
// variations of non roundtrip
var nonRoundtripChecks = function(options) {
osrm.trip(options, function(err, fseTrip) {
assert.ifError(err);
assert.equal(1, fseTrip.trips.length);
var coordinates = fseTrip.trips[0].geometry.coordinates;
assert.notEqual(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1]));
});
};
// variations of roundtrip
var roundtripChecks = function(options) {
osrm.trip(options, function(err, trip) {
assert.ifError(err);
@ -319,7 +306,20 @@ test('trip: fixed start and end combinations', function(assert) {
var coordinates = trip.trips[0].geometry.coordinates;
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
roundtripChecks({coordinates: options.coordinates, geometries: options.geometries});
@ -327,6 +327,7 @@ test('trip: fixed start and end combinations', function(assert) {
// roundtrip, fixed destination
options.roundtrip = true;
delete options.source;
options.destination = 'last';
roundtripChecks(options);
//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());
return contractor::ContractorGraph{max_id + 1, std::move(input_edges)};
return contractor::ContractorGraph{max_id + 1, input_edges};
}
} // namespace unit_test
} // namespace osrm

View File

@ -19,8 +19,8 @@ BOOST_AUTO_TEST_CASE(unchanged_collapse_route_result)
PhantomNode target;
source.forward_segment_id = {1, 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 kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false};
PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none};
PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none};
InternalRouteResult one_leg_result;
one_leg_result.unpacked_path_segments = {{pathy, kathy}};
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)
{
// from_edge_based_node, turn_via_node, name_id, is_segregated, weight_until_turn,
// weight_of_turn,
// duration_until_turn, duration_of_turn, turn_instruction, lane_data, travel_mode, classes,
// entry_class, datasource_id, pre_turn_bearing, post_turn_bearing, left_hand
PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false};
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};
// from_edge_based_node, turn_via_node, weight_until_turn, weight_of_turn,
// duration_until_turn, duration_of_turn, datasource_id, turn_edge
PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none};
PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none};
PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none};
PhantomNode node_1;
PhantomNode node_2;
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)
{
PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false};
PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false};
PathData qathy{0, 5, 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};
PathData mathy{0, 4, 18, false, 8, 9, 13, 4, 2, {}, 4, 2, {}, 2, {3.0}, {1.0}, false};
PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none};
PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none};
PathData qathy{0, 5, 1, 2, 3, 4, 1, boost::none};
PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none};
PathData mathy{0, 4, 8, 9, 13, 4, 2, boost::none};
PhantomNode node_1;
PhantomNode node_2;
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)
{
PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false};
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};
PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none};
PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none};
PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none};
PhantomNode node_1;
PhantomNode node_2;
PhantomNode node_3;

View File

@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
{FloatLongitude{-73.981495}, FloatLatitude{40.768275}}};
geometry.segment_offsets = {0, 2};
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}};
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.annotations.size(), 1);
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()

View File

@ -362,7 +362,7 @@ void test_tfse_illegal_parameters(bool use_json_only_api)
ResetParams(locations, params);
params.source = TripParameters::SourceType::First;
params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api);
CheckOk(osrm, params, use_json_only_api);
ResetParams(locations, params);
params.destination = TripParameters::DestinationType::Any;
@ -372,7 +372,7 @@ void test_tfse_illegal_parameters(bool use_json_only_api)
ResetParams(locations, params);
params.destination = TripParameters::DestinationType::Last;
params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api);
CheckOk(osrm, params, use_json_only_api);
// three parameters set
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.destination = TripParameters::DestinationType::Last;
params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api);
CheckOk(osrm, params, use_json_only_api);
params.source = TripParameters::SourceType::First;
params.destination = TripParameters::DestinationType::Any;
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_new_api) { test_tfse_illegal_parameters(false); }