Allow specifing a weight for routing that is independent of duration
This commit is contained in:
parent
e463733138
commit
279f8aabfb
@ -1,3 +1,10 @@
|
|||||||
|
# 6.0.0
|
||||||
|
- Profiles:
|
||||||
|
- `turn_function` now does not return an integer but takes in a `turn` object and modifies it
|
||||||
|
- `uturn_penalty` is deprecated set it over the `turn_function`
|
||||||
|
- traffic light penalties now need to be set over the node function, `traffic_light_penalty` is deprecated:
|
||||||
|
result.weight_penalty and result.duration_penalty
|
||||||
|
|
||||||
# 5.6.0
|
# 5.6.0
|
||||||
- Changes from 5.5
|
- Changes from 5.5
|
||||||
- Bugfixes
|
- Bugfixes
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
@routing @speed @traffic
|
|
||||||
Feature: Traffic - speeds
|
|
||||||
|
|
||||||
Background: Use specific speeds
|
|
||||||
|
|
||||||
Scenario: Weighting based on speed file
|
|
||||||
Given the node locations
|
|
||||||
| node | lat | lon |
|
|
||||||
| a | 0.1 | 0.1 |
|
|
||||||
| b | 0.05 | 0.1 |
|
|
||||||
| c | 0.0 | 0.1 |
|
|
||||||
| d | 0.05 | 0.03 |
|
|
||||||
| e | 0.05 | 0.066 |
|
|
||||||
| f | 0.075 | 0.066 |
|
|
||||||
| g | 0.075 | 0.1 |
|
|
||||||
And the ways
|
|
||||||
| nodes | highway |
|
|
||||||
| ab | primary |
|
|
||||||
| ad | primary |
|
|
||||||
| bc | primary |
|
|
||||||
| dc | primary |
|
|
||||||
| de | primary |
|
|
||||||
| eb | primary |
|
|
||||||
| df | primary |
|
|
||||||
| fb | primary |
|
|
||||||
Given the profile "testbot"
|
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
|
||||||
Given the contract extra arguments "--segment-speed-file {speeds_file}"
|
|
||||||
Given the speed file
|
|
||||||
"""
|
|
||||||
1,2,0
|
|
||||||
2,1,0
|
|
||||||
2,3,27
|
|
||||||
3,2,27
|
|
||||||
1,4,27
|
|
||||||
4,1,27
|
|
||||||
"""
|
|
||||||
And I route I should get
|
|
||||||
| from | to | route | speed |
|
|
||||||
| a | b | ad,de,eb,eb | 30 km/h |
|
|
||||||
| a | c | ad,dc,dc | 31 km/h |
|
|
||||||
| b | c | bc,bc | 27 km/h |
|
|
||||||
| a | d | ad,ad | 27 km/h |
|
|
||||||
| d | c | dc,dc | 36 km/h |
|
|
||||||
| g | b | fb,fb | 36 km/h |
|
|
||||||
| a | g | ad,df,fb,fb | 30 km/h |
|
|
||||||
|
|
||||||
|
|
||||||
Scenario: Speeds that isolate a single node (a)
|
|
||||||
Given the node locations
|
|
||||||
| node | lat | lon |
|
|
||||||
| a | 0.1 | 0.1 |
|
|
||||||
| b | 0.05 | 0.1 |
|
|
||||||
| c | 0.0 | 0.1 |
|
|
||||||
| d | 0.05 | 0.03 |
|
|
||||||
| e | 0.05 | 0.066 |
|
|
||||||
| f | 0.075 | 0.066 |
|
|
||||||
| g | 0.075 | 0.1 |
|
|
||||||
| h | 2.075 | 19.1 |
|
|
||||||
And the ways
|
|
||||||
| nodes | highway |
|
|
||||||
| ab | primary |
|
|
||||||
| ad | primary |
|
|
||||||
| bc | primary |
|
|
||||||
| dc | primary |
|
|
||||||
| de | primary |
|
|
||||||
| eb | primary |
|
|
||||||
| df | primary |
|
|
||||||
| fb | primary |
|
|
||||||
Given the profile "testbot"
|
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
|
||||||
Given the contract extra arguments "--segment-speed-file {speeds_file}"
|
|
||||||
Given the speed file
|
|
||||||
"""
|
|
||||||
1,2,0
|
|
||||||
2,1,0
|
|
||||||
2,3,27
|
|
||||||
3,2,27
|
|
||||||
1,4,0
|
|
||||||
4,1,0
|
|
||||||
"""
|
|
||||||
And I route I should get
|
|
||||||
| from | to | route | speed |
|
|
||||||
| a | b | fb,fb | 36 km/h |
|
|
||||||
| a | c | fb,bc,bc | 30 km/h |
|
|
||||||
| b | c | bc,bc | 27 km/h |
|
|
||||||
| a | d | fb,df,df | 36 km/h |
|
|
||||||
| d | c | dc,dc | 36 km/h |
|
|
||||||
| g | b | fb,fb | 36 km/h |
|
|
||||||
| a | g | fb,fb | 36 km/h |
|
|
||||||
|
|
||||||
Scenario: Verify that negative values cause an error, they're not valid at all
|
|
||||||
Given the node locations
|
|
||||||
| node | lat | lon |
|
|
||||||
| a | 0.1 | 0.1 |
|
|
||||||
| b | 0.05 | 0.1 |
|
|
||||||
| c | 0.0 | 0.1 |
|
|
||||||
| d | 0.05 | 0.03 |
|
|
||||||
| e | 0.05 | 0.066 |
|
|
||||||
| f | 0.075 | 0.066 |
|
|
||||||
| g | 0.075 | 0.1 |
|
|
||||||
| h | 1.075 | 10.1 |
|
|
||||||
And the ways
|
|
||||||
| nodes | highway |
|
|
||||||
| ab | primary |
|
|
||||||
| ad | primary |
|
|
||||||
| bc | primary |
|
|
||||||
| dc | primary |
|
|
||||||
| de | primary |
|
|
||||||
| eb | primary |
|
|
||||||
| df | primary |
|
|
||||||
| fb | primary |
|
|
||||||
Given the profile "testbot"
|
|
||||||
Given the extract extra arguments "--generate-edge-lookup"
|
|
||||||
Given the speed file
|
|
||||||
"""
|
|
||||||
1,2,-10
|
|
||||||
2,1,-20
|
|
||||||
2,3,27
|
|
||||||
3,2,27
|
|
||||||
1,4,-3
|
|
||||||
4,1,-5
|
|
||||||
"""
|
|
||||||
And the data has been extracted
|
|
||||||
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
|
||||||
And stderr should contain "malformed"
|
|
||||||
And it should exit with an error
|
|
@ -24,5 +24,5 @@ Feature: osrm-contract command line options: invalid options
|
|||||||
Scenario: osrm-contract - Someone forgot --generate-edge-lookup on osrm-extract
|
Scenario: osrm-contract - Someone forgot --generate-edge-lookup on osrm-extract
|
||||||
When I try to run "osrm-contract --segment-speed-file /dev/null {processed_file}"
|
When I try to run "osrm-contract --segment-speed-file /dev/null {processed_file}"
|
||||||
Then stderr should contain "Error while trying to mmap"
|
Then stderr should contain "Error while trying to mmap"
|
||||||
Then stderr should contain ".osrm.edge_penalties"
|
Then stderr should contain ".osrm.turn_penalties_index"
|
||||||
And it should exit with an error
|
And it should exit with an error
|
||||||
|
@ -27,7 +27,7 @@ end
|
|||||||
Scenario: Out-bound API version
|
Scenario: Out-bound API version
|
||||||
Given the profile file
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
api_version = 2
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
@ -55,6 +55,7 @@ properties.max_speed_for_map_matching = 180/3.6
|
|||||||
properties.use_turn_restrictions = true
|
properties.use_turn_restrictions = true
|
||||||
properties.continue_straight_at_waypoint = true
|
properties.continue_straight_at_waypoint = true
|
||||||
properties.left_hand_driving = false
|
properties.left_hand_driving = false
|
||||||
|
properties.weight_name = 'duration'
|
||||||
|
|
||||||
function node_function (node, result)
|
function node_function (node, result)
|
||||||
print ('node_function ' .. node:id())
|
print ('node_function ' .. node:id())
|
||||||
@ -71,7 +72,7 @@ end
|
|||||||
|
|
||||||
function turn_function (angle)
|
function turn_function (angle)
|
||||||
print('turn_function ' .. angle)
|
print('turn_function ' .. angle)
|
||||||
return angle == 0 and 0 or 42
|
return angle == 0 and 0 or 17
|
||||||
end
|
end
|
||||||
|
|
||||||
function segment_function (source, target, distance, weight)
|
function segment_function (source, target, distance, weight)
|
||||||
@ -101,6 +102,6 @@ end
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | time |
|
||||||
| a | b | ac,cb,cb | 19.2s |
|
| a | b | ac,cb,cb | 16.7s |
|
||||||
| a | d | ac,cd,cd | 19.2s |
|
| a | d | ac,cd,cd | 16.7s |
|
||||||
| a | e | ac,ce,ce | 20s |
|
| a | e | ac,ce,ce | 20s |
|
||||||
|
66
features/options/profiles/version1.feature
Normal file
66
features/options/profiles/version1.feature
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
Feature: Profile API version 1
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given a grid size of 100 meters
|
||||||
|
|
||||||
|
Scenario: Basic profile function calls and property values
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
|
||||||
|
-- set profile properties
|
||||||
|
properties.max_speed_for_map_matching = 180/3.6
|
||||||
|
properties.use_turn_restrictions = true
|
||||||
|
properties.continue_straight_at_waypoint = true
|
||||||
|
properties.weight_name = 'test_version1'
|
||||||
|
|
||||||
|
function node_function (node, result)
|
||||||
|
print ('node_function ' .. node:id())
|
||||||
|
end
|
||||||
|
|
||||||
|
function way_function(way, result)
|
||||||
|
result.name = way:get_value_by_key('name')
|
||||||
|
result.weight = 10
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.forward_speed = 36
|
||||||
|
result.backward_speed = 36
|
||||||
|
print ('way_function ' .. way:id() .. ' ' .. result.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function turn_function (turn)
|
||||||
|
print('turn_function', turn.angle, turn.turn_type, turn.direction_modifier, turn.has_traffic_light)
|
||||||
|
turn.weight = turn.angle == 0 and 0 or 4.2
|
||||||
|
turn.duration = turn.weight
|
||||||
|
end
|
||||||
|
|
||||||
|
function segment_function (segment)
|
||||||
|
print ('segment_function ' .. segment.source.lon .. ' ' .. segment.source.lat)
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a
|
||||||
|
bcd
|
||||||
|
e
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ac |
|
||||||
|
| cb |
|
||||||
|
| cd |
|
||||||
|
| ce |
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
|
Then it should exit successfully
|
||||||
|
And stdout should contain "node_function"
|
||||||
|
And stdout should contain "way_function"
|
||||||
|
And stdout should contain "turn_function"
|
||||||
|
And stdout should contain "segment_function"
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | time |
|
||||||
|
| a | b | ac,cb,cb | 19.2s |
|
||||||
|
| a | d | ac,cd,cd | 19.2s |
|
||||||
|
| a | e | ac,ce,ce | 20s |
|
@ -164,15 +164,21 @@ module.exports = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.annotationList = (instructions) => {
|
this.annotationList = (instructions) => {
|
||||||
function zip(list_1, list_2, list_3)
|
if (!('annotation' in instructions.legs[0]))
|
||||||
|
return '';
|
||||||
|
|
||||||
|
function zip(list_1, list_2, list_3, list_4)
|
||||||
{
|
{
|
||||||
let tuples = [];
|
let tuples = [];
|
||||||
for (let i = 0; i < list_1.length; ++i) {
|
for (let i = 0; i < list_1.length; ++i) {
|
||||||
tuples.push([list_1[i], list_2[i], list_3[i]]);
|
tuples.push([list_1[i], list_2[i], list_3[i], list_4[i]]);
|
||||||
}
|
}
|
||||||
return tuples;
|
return tuples;
|
||||||
}
|
}
|
||||||
return instructions.legs.map(l => {return zip(l.annotation.duration, l.annotation.distance, l.annotation.datasources).map(p => { return p.join(':'); }).join(','); }).join(',');
|
return instructions.legs.map(l => {
|
||||||
|
const values = zip( l.annotation.weight, l.annotation.duration, l.annotation.distance, l.annotation.datasources);
|
||||||
|
return values.map(p => { return p.join(':'); }).join(',');
|
||||||
|
}).join(',');
|
||||||
};
|
};
|
||||||
|
|
||||||
this.OSMIDList = (instructions) => {
|
this.OSMIDList = (instructions) => {
|
||||||
@ -250,4 +256,12 @@ module.exports = function () {
|
|||||||
this.distanceList = (instructions) => {
|
this.distanceList = (instructions) => {
|
||||||
return this.extractInstructionList(instructions, s => s.distance + 'm');
|
return this.extractInstructionList(instructions, s => s.distance + 'm');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.weightName = (instructions) => {
|
||||||
|
return instructions ? instructions.weight_name : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
this.weightList = (instructions) => {
|
||||||
|
return this.extractInstructionList(instructions, s => s.weight);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,7 @@ module.exports = function () {
|
|||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
if (body && body.length) {
|
if (body && body.length) {
|
||||||
let destinations, pronunciations, instructions, refs, bearings, turns, modes, times,
|
let destinations, pronunciations, instructions, refs, bearings, turns, modes, times,
|
||||||
distances, summary, intersections, lanes, locations;
|
distances, summary, intersections, lanes, locations, annotation, weight_name, weights;
|
||||||
|
|
||||||
let json = JSON.parse(body);
|
let json = JSON.parse(body);
|
||||||
|
|
||||||
@ -55,6 +55,9 @@ module.exports = function () {
|
|||||||
lanes = this.lanesList(json.routes[0]);
|
lanes = this.lanesList(json.routes[0]);
|
||||||
summary = this.summary(json.routes[0]);
|
summary = this.summary(json.routes[0]);
|
||||||
locations = this.locations(json.routes[0]);
|
locations = this.locations(json.routes[0]);
|
||||||
|
annotation = this.annotationList(json.routes[0]);
|
||||||
|
weight_name = this.weightName(json.routes[0]);
|
||||||
|
weights = this.weightList(json.routes[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.has('status')) {
|
if (headers.has('status')) {
|
||||||
@ -130,6 +133,10 @@ module.exports = function () {
|
|||||||
got.locations = (locations || '').trim();
|
got.locations = (locations || '').trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headers.has('annotation')){
|
||||||
|
got.annotation = (annotation || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
var putValue = (key, value) => {
|
var putValue = (key, value) => {
|
||||||
if (headers.has(key)) got[key] = instructions ? value : '';
|
if (headers.has(key)) got[key] = instructions ? value : '';
|
||||||
};
|
};
|
||||||
@ -142,6 +149,8 @@ module.exports = function () {
|
|||||||
putValue('distances', distances);
|
putValue('distances', distances);
|
||||||
putValue('pronunciations', pronunciations);
|
putValue('pronunciations', pronunciations);
|
||||||
putValue('destinations', destinations);
|
putValue('destinations', destinations);
|
||||||
|
putValue('weight_name', weight_name);
|
||||||
|
putValue('weights', weights);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in row) {
|
for (var key in row) {
|
||||||
|
@ -142,8 +142,8 @@ Feature: Basic Map Matching
|
|||||||
|
|
||||||
When I match I should get
|
When I match I should get
|
||||||
| trace | matchings | annotation |
|
| trace | matchings | annotation |
|
||||||
| abeh | abeh | 1:10.008842:1,0:0:0,1:10.008842:0,1:10.008842:0,1:10.008842:0,0:0:0,2:19.906475:0,1:10.008842:0 |
|
| abeh | abeh | 1:1:10.008842:1,0:0:0:0,1:1:10.008842:0,1:1:10.008842:0,1:1:10.008842:0,0:0:0:0,2:2:19.906475:0,1:1:10.008842:0 |
|
||||||
| abci | abci | 1:10.008842:1,0:0:0,1:10.008842:0,0:0:0,1:10.010367:0 |
|
| abci | abci | 1:1:10.008842:1,0:0:0:0,1:1:10.008842:0,0:0:0:0,1:1:10.010367:0 |
|
||||||
|
|
||||||
# The following is the same as the above, but separated for readability (line length)
|
# The following is the same as the above, but separated for readability (line length)
|
||||||
When I match I should get
|
When I match I should get
|
||||||
@ -337,4 +337,3 @@ Feature: Basic Map Matching
|
|||||||
| trace | OSM IDs |
|
| trace | OSM IDs |
|
||||||
| 12 | 1,2,3,4,5,6 |
|
| 12 | 1,2,3,4,5,6 |
|
||||||
| 21 | 6,5,4,3,2,1 |
|
| 21 | 6,5,4,3,2,1 |
|
||||||
|
|
||||||
|
@ -9,13 +9,10 @@ Feature: Testbot - side bias
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: Left hand bias
|
Scenario: Left hand bias
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file "car" extended with
|
||||||
"""
|
"""
|
||||||
properties.left_hand_driving = true
|
properties.left_hand_driving = true
|
||||||
function turn_function (angle)
|
turn_bias = properties.left_hand_driving and 1/1.075 or 1.075
|
||||||
local k = 10 * angle * angle * 50 / (90.0 * 90.0)
|
|
||||||
return (angle >= 0) and k * 1.2 or k / 1.2
|
|
||||||
end
|
|
||||||
"""
|
"""
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@ -31,17 +28,14 @@ Feature: Testbot - side bias
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | time |
|
||||||
| d | a | bd,ab,ab | 82s +-1 |
|
| d | a | bd,ab,ab | 29s +-1 |
|
||||||
| d | c | bd,bc,bc | 100s +-1 |
|
| d | c | bd,bc,bc | 33s +-1 |
|
||||||
|
|
||||||
Scenario: Right hand bias
|
Scenario: Right hand bias
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file "car" extended with
|
||||||
"""
|
"""
|
||||||
properties.left_hand_driving = false
|
properties.left_hand_driving = false
|
||||||
function turn_function (angle)
|
turn_bias = properties.left_hand_driving and 1/1.075 or 1.075
|
||||||
local k = 10 * angle * angle * 50 / (90.0 * 90.0)
|
|
||||||
return (angle >= 0) and k / 1.2 or k * 1.2
|
|
||||||
end
|
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
@ -57,8 +51,8 @@ Feature: Testbot - side bias
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | time |
|
||||||
| d | a | bd,ab,ab | 100s +-1 |
|
| d | a | bd,ab,ab | 33s +-1 |
|
||||||
| d | c | bd,bc,bc | 82s +-1 |
|
| d | c | bd,bc,bc | 29s +-1 |
|
||||||
|
|
||||||
Scenario: Roundabout exit counting for left sided driving
|
Scenario: Roundabout exit counting for left sided driving
|
||||||
And a grid size of 10 meters
|
And a grid size of 10 meters
|
||||||
|
132
features/testbot/traffic_speeds.feature
Normal file
132
features/testbot/traffic_speeds.feature
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
@routing @speed @traffic
|
||||||
|
Feature: Traffic - speeds
|
||||||
|
|
||||||
|
Background: Use specific speeds
|
||||||
|
Given the node locations
|
||||||
|
| node | lat | lon |
|
||||||
|
| a | 0.1 | 0.1 |
|
||||||
|
| b | 0.05 | 0.1 |
|
||||||
|
| c | 0.0 | 0.1 |
|
||||||
|
| d | 0.05 | 0.03 |
|
||||||
|
| e | 0.05 | 0.066 |
|
||||||
|
| f | 0.075 | 0.066 |
|
||||||
|
| g | 0.075 | 0.1 |
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| ab | primary |
|
||||||
|
| ad | primary |
|
||||||
|
| bc | primary |
|
||||||
|
| dc | primary |
|
||||||
|
| de | primary |
|
||||||
|
| eb | primary |
|
||||||
|
| df | primary |
|
||||||
|
| fb | primary |
|
||||||
|
And the profile "testbot"
|
||||||
|
And the extract extra arguments "--generate-edge-lookup"
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Weighting based on speed file
|
||||||
|
Given the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
Given the speed file
|
||||||
|
"""
|
||||||
|
1,2,0
|
||||||
|
2,1,0
|
||||||
|
2,3,27
|
||||||
|
3,2,27
|
||||||
|
1,4,27
|
||||||
|
4,1,27
|
||||||
|
"""
|
||||||
|
And I route I should get
|
||||||
|
| from | to | route | speed | weights |
|
||||||
|
| a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 |
|
||||||
|
| a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 |
|
||||||
|
| b | c | bc,bc | 27 km/h | 741.5,0 |
|
||||||
|
| a | d | ad,ad | 27 km/h | 1275.7,0 |
|
||||||
|
| d | c | dc,dc | 36 km/h | 956.8,0 |
|
||||||
|
| g | b | fb,fb | 36 km/h | 164.7,0 |
|
||||||
|
| a | g | ad,df,fb,fb | 30 km/h | 1275.7,487.5,304.7,0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Weighting based on speed file weights, ETA based on file durations
|
||||||
|
Given the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
Given the speed file
|
||||||
|
"""
|
||||||
|
1,2,1,200207
|
||||||
|
2,1,1,200207
|
||||||
|
2,3,27,7415
|
||||||
|
3,2,27,7415
|
||||||
|
1,4,27,12757
|
||||||
|
4,1,27,12757
|
||||||
|
"""
|
||||||
|
And I route I should get
|
||||||
|
| from | to | route | speed | weights |
|
||||||
|
| a | b | ad,de,eb,eb | 30 km/h | 1275.7,400.4,378.2,0 |
|
||||||
|
| a | c | ad,dc,dc | 31 km/h | 1275.7,956.8,0 |
|
||||||
|
| b | c | bc,bc | 27 km/h | 741.5,0 |
|
||||||
|
| a | d | ad,ad | 27 km/h | 1275.7,0 |
|
||||||
|
| d | c | dc,dc | 36 km/h | 956.8,0 |
|
||||||
|
| g | b | ab,ab | 1 km/h | 10010.4,0 |
|
||||||
|
| a | g | ab,ab | 1 km/h | 10010.3,0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Weighting based on speed file weights, ETA based on file durations
|
||||||
|
Given the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
Given the speed file
|
||||||
|
"""
|
||||||
|
1,2,1,200207
|
||||||
|
2,1,1,200207
|
||||||
|
2,3,27,7415
|
||||||
|
3,2,27,7415
|
||||||
|
1,4,1,344450
|
||||||
|
4,1,1,344450
|
||||||
|
"""
|
||||||
|
And I route I should get
|
||||||
|
| from | to | route | speed | weights |
|
||||||
|
| a | b | ab,ab | 1 km/h | 20020.7,0 |
|
||||||
|
| a | c | ab,bc,bc | 2 km/h | 20020.7,741.5,0 |
|
||||||
|
| b | c | bc,bc | 27 km/h | 741.5,0 |
|
||||||
|
| a | d | ab,eb,de,de | 2 km/h | 20020.7,378.2,400.4,0 |
|
||||||
|
| d | c | dc,dc | 36 km/h | 956.8,0 |
|
||||||
|
| g | b | ab,ab | 1 km/h | 10010.4,0 |
|
||||||
|
| a | g | ab,ab | 1 km/h | 10010.3,0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Speeds that isolate a single node (a)
|
||||||
|
Given the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the node locations
|
||||||
|
| node | lat | lon |
|
||||||
|
| h | 2.075 | 19.1 |
|
||||||
|
Given the speed file
|
||||||
|
"""
|
||||||
|
1,2,0
|
||||||
|
2,1,0
|
||||||
|
2,3,27
|
||||||
|
3,2,27
|
||||||
|
1,4,0
|
||||||
|
4,1,0
|
||||||
|
"""
|
||||||
|
And I route I should get
|
||||||
|
| from | to | route | speed | weights |
|
||||||
|
| a | b | fb,fb | 36 km/h | 329.4,0 |
|
||||||
|
| a | c | fb,bc,bc | 30 km/h | 329.4,741.5,0 |
|
||||||
|
| b | c | bc,bc | 27 km/h | 741.5,0 |
|
||||||
|
| a | d | fb,df,df | 36 km/h | 140,487.5,0 |
|
||||||
|
| d | c | dc,dc | 36 km/h | 956.8,0 |
|
||||||
|
| g | b | fb,fb | 36 km/h | 164.7,0 |
|
||||||
|
| a | g | fb,fb | 36 km/h | 164.7,0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Verify that negative values cause an error, they're not valid at all
|
||||||
|
Given the speed file
|
||||||
|
"""
|
||||||
|
1,2,-10
|
||||||
|
2,1,-20
|
||||||
|
2,3,27
|
||||||
|
3,2,27
|
||||||
|
1,4,-3
|
||||||
|
4,1,-5
|
||||||
|
"""
|
||||||
|
And the data has been extracted
|
||||||
|
When I try to run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
|
||||||
|
And stderr should contain "malformed"
|
||||||
|
And it should exit with an error
|
@ -37,7 +37,7 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
|
|||||||
Given the turn penalty file
|
Given the turn penalty file
|
||||||
"""
|
"""
|
||||||
1,2,5,0,comment
|
1,2,5,0,comment
|
||||||
3,4,7,-20
|
3,4,7,-30
|
||||||
"""
|
"""
|
||||||
And the contract extra arguments "--turn-penalty-file {penalties_file}"
|
And the contract extra arguments "--turn-penalty-file {penalties_file}"
|
||||||
When I route I should get
|
When I route I should get
|
||||||
@ -46,5 +46,21 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
|
|||||||
| 1 | e | ab,be,be | 36 km/h | 30s +-1 |
|
| 1 | e | ab,be,be | 36 km/h | 30s +-1 |
|
||||||
| b | f | bc,cf,cf | 36 km/h | 40s +-1 |
|
| b | f | bc,cf,cf | 36 km/h | 40s +-1 |
|
||||||
| 2 | f | bc,cf,cf | 36 km/h | 30s +-1 |
|
| 2 | f | bc,cf,cf | 36 km/h | 30s +-1 |
|
||||||
| c | g | cd,dg,dg | 71 km/h | 20s +-1 |
|
| c | g | cd,dg,dg | 144 km/h | 10s +-1 |
|
||||||
| 3 | g | cd,dg,dg | 54 km/h | 20s +-1 |
|
| 3 | g | cd,dg,dg | 54 km/h | 20s +-1 |
|
||||||
|
|
||||||
|
Scenario: Weighting based on turn penalty file with weights
|
||||||
|
Given the turn penalty file
|
||||||
|
"""
|
||||||
|
1,2,5,0,-3.33,comment
|
||||||
|
3,4,7,-30,100.75
|
||||||
|
"""
|
||||||
|
And the contract extra arguments "--turn-penalty-file {penalties_file}"
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | speed | time | weights |
|
||||||
|
| a | e | ab,be,be | 36 km/h | 40s +-1 | 16.7,20,0 |
|
||||||
|
| 1 | e | ab,be,be | 36 km/h | 30s +-1 | 6.7,20,0 |
|
||||||
|
| b | f | bc,cf,cf | 36 km/h | 40s +-1 | 20,20,0 |
|
||||||
|
| 2 | f | bc,cf,cf | 36 km/h | 30s +-1 | 10,20,0 |
|
||||||
|
| c | g | cd,dg,dg | 144 km/h | 10s +-1 | 120.8,20,0 |
|
||||||
|
| 3 | g | cd,dg,dg | 54 km/h | 20s +-1 | 110.8,20,0 |
|
||||||
|
262
features/testbot/weight.feature
Normal file
262
features/testbot/weight.feature
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
@testbot
|
||||||
|
Feature: Weight tests
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
Given a grid size of 10 meters
|
||||||
|
Given the extract extra arguments "--generate-edge-lookup"
|
||||||
|
Given the query options
|
||||||
|
| geometries | geojson |
|
||||||
|
|
||||||
|
Scenario: Weight details
|
||||||
|
Given the query options
|
||||||
|
| annotations | true |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
s
|
||||||
|
·
|
||||||
|
a---b---c
|
||||||
|
|
|
||||||
|
d
|
||||||
|
|··t
|
||||||
|
e
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
| cde |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | annotation |
|
||||||
|
| s,t | abc,cde,cde | 1.1:1.1:10.008843:0,2:2:20.017686:0,2:2:20.020734:0,1:1:10.010367:0 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | times | weight_name | weights |
|
||||||
|
| s,t | abc,cde,cde | 3.1s,3s,0s | duration | 3.1,3,0 |
|
||||||
|
|
||||||
|
# FIXME include/engine/guidance/assemble_geometry.hpp:95
|
||||||
|
@todo
|
||||||
|
Scenario: Start and target on the same edge
|
||||||
|
Given the query options
|
||||||
|
| annotations | true |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-------b
|
||||||
|
· ·
|
||||||
|
s t
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distances | weights | times | annotation |
|
||||||
|
| s,t | abc,abc | 20m,0m | 20,0 | 2s,0s | 29:2.9:20.017685:0 |
|
||||||
|
| t,s | abc,abc | 20m,0m | 20,0 | 2s,0s | 29:2.9:20.017685:0 |
|
||||||
|
|
||||||
|
# FIXME include/engine/guidance/assemble_geometry.hpp:95
|
||||||
|
@todo
|
||||||
|
Scenario: Start and target on adjacent edges
|
||||||
|
Given the query options
|
||||||
|
| annotations | true |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-------b-------c
|
||||||
|
· ·
|
||||||
|
s t
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distances | weights | times | annotation |
|
||||||
|
| s,t | abc,abc | 30m,0m | 31,0 | 3.1s,0s | 31:3.1:30.026527:0 |
|
||||||
|
| t,s | abc,abc | 30m,0m | 31,0 | 3.1s,0s | 31:3.1:30.026527:0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Step weights -- way_function: fail if no weight or weight_per_meter property
|
||||||
|
Given the profile file "testbot" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
properties.traffic_signal_penalty = 0
|
||||||
|
properties.u_turn_penalty = 0
|
||||||
|
properties.weight_name = 'steps'
|
||||||
|
function way_function(way, result)
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.forward_speed = 42
|
||||||
|
result.backward_speed = 42
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a---b
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I try to run "osrm-extract {osm_file} --profile {profile_file}"
|
||||||
|
Then stderr should contain "There are no edges"
|
||||||
|
And it should exit with an error
|
||||||
|
|
||||||
|
Scenario: Step weights -- way_function: second way wins
|
||||||
|
Given the profile file "testbot" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
properties.traffic_signal_penalty = 0
|
||||||
|
properties.u_turn_penalty = 0
|
||||||
|
properties.weight_name = 'steps'
|
||||||
|
function way_function(way, result)
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.duration = 42
|
||||||
|
result.weight = 35
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a---b---c---d---e---f---g---h
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcdef |
|
||||||
|
| abcdefgh |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distance | weights | times |
|
||||||
|
| a,f | , | 100m | 25,0 | 30s,0s |
|
||||||
|
| f,a | , | 100m | 25,0 | 30s,0s |
|
||||||
|
| a,h | , | 140m +-1 | 35,0 | 42s,0s |
|
||||||
|
| h,a | , | 140m +-1 | 35,0 | 42s,0s |
|
||||||
|
|
||||||
|
Scenario: Step weights -- way_function: higher weight_per_meter is preferred
|
||||||
|
Given the profile file "testbot" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
properties.traffic_signal_penalty = 0
|
||||||
|
properties.u_turn_penalty = 0
|
||||||
|
properties.weight_name = 'steps'
|
||||||
|
function way_function(way, result)
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.duration = 42
|
||||||
|
result.forward_rate = 1
|
||||||
|
result.backward_rate = 0.5
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a---b---c---d---e---f---g---h
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcdefgh |
|
||||||
|
| abcdef |
|
||||||
|
| fgh |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distance | weights | times |
|
||||||
|
| a,f | , | 100m | 99.9,0 | 30s,0s |
|
||||||
|
| f,a | , | 100m | 199.8,0 | 30s,0s |
|
||||||
|
| a,h | , | 140m | 139.9,0 | 42s,0s |
|
||||||
|
| h,a | , | 140m | 279.8,0 | 42s,0s |
|
||||||
|
| f,h | , | 40m | 40,0 | 12s,0s |
|
||||||
|
| h,f | , | 40m | 80,0 | 12s,0s |
|
||||||
|
|
||||||
|
Scenario: Step weights -- segment_function
|
||||||
|
Given the profile file "testbot" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
properties.traffic_signal_penalty = 0
|
||||||
|
properties.u_turn_penalty = 0
|
||||||
|
properties.weight_name = 'steps'
|
||||||
|
function way_function(way, result)
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.weight = 42
|
||||||
|
result.duration = 3
|
||||||
|
end
|
||||||
|
function segment_function (segment)
|
||||||
|
segment.weight = 1
|
||||||
|
segment.duration = 11
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a---b---c---d---e---f---g---h
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcdefgh |
|
||||||
|
| abcdef |
|
||||||
|
| fgh |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distance | weights | times |
|
||||||
|
| a,f | , | 100m | 5,0 | 55s,0s |
|
||||||
|
| f,a | , | 100m | 5,0 | 55s,0s |
|
||||||
|
| a,h | , | 140m +-1 | 7,0 | 77s,0s |
|
||||||
|
| h,a | , | 140m +-1 | 7,0 | 77s,0s |
|
||||||
|
| f,h | , | 40m +-1 | 2,0 | 22s,0s |
|
||||||
|
| h,f | , | 40m +-1 | 2,0 | 22s,0s |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Step weights -- segment_function and turn_function with weight precision
|
||||||
|
Given the profile file "testbot" extended with
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
properties.traffic_signal_penalty = 0
|
||||||
|
properties.u_turn_penalty = 0
|
||||||
|
properties.weight_name = 'steps'
|
||||||
|
properties.weight_precision = 3
|
||||||
|
function way_function(way, result)
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.weight = 42
|
||||||
|
result.duration = 3
|
||||||
|
end
|
||||||
|
function segment_function (segment)
|
||||||
|
segment.weight = 1.11
|
||||||
|
segment.duration = 100
|
||||||
|
end
|
||||||
|
function turn_function (turn)
|
||||||
|
print (turn.angle)
|
||||||
|
turn.weight = turn.angle / 100
|
||||||
|
turn.duration = turn.angle
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a---b---c---d
|
||||||
|
⋮
|
||||||
|
e
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcd |
|
||||||
|
| ce |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | distance | weights | times |
|
||||||
|
| a,c | , | 40m +-.1 | 3.119,0 | 289.9s,0s |
|
||||||
|
| a,e | ,, | 60m +-.1 | 3.119,1.11,0 | 289.9s,100s,0s |
|
||||||
|
| e,a | ,, | 60m +-.1 | 0.211,2.22,0 | 10.1s,200s,0s |
|
||||||
|
| e,d | ,, | 40m +-.1 | 2.009,1.11,0 | 189.9s,100s,0s |
|
||||||
|
| d,e | ,, | 40m +-.1 | 0.211,1.11,0 | 10.1s,100s,0s |
|
@ -82,7 +82,9 @@ class Contractor
|
|||||||
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
|
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
|
||||||
std::vector<EdgeWeight> &node_weights,
|
std::vector<EdgeWeight> &node_weights,
|
||||||
const std::string &edge_segment_lookup_path,
|
const std::string &edge_segment_lookup_path,
|
||||||
const std::string &edge_penalty_path,
|
const std::string &turn_weight_penalties_path,
|
||||||
|
const std::string &turn_duration_penalties_path,
|
||||||
|
const std::string &turn_penalties_index_path,
|
||||||
const std::vector<std::string> &segment_speed_path,
|
const std::vector<std::string> &segment_speed_path,
|
||||||
const std::vector<std::string> &turn_penalty_path,
|
const std::vector<std::string> &turn_penalty_path,
|
||||||
const std::string &nodes_filename,
|
const std::string &nodes_filename,
|
||||||
|
@ -49,7 +49,9 @@ struct ContractorConfig
|
|||||||
graph_output_path = osrm_input_path.string() + ".hsgr";
|
graph_output_path = osrm_input_path.string() + ".hsgr";
|
||||||
edge_based_graph_path = osrm_input_path.string() + ".ebg";
|
edge_based_graph_path = osrm_input_path.string() + ".ebg";
|
||||||
edge_segment_lookup_path = osrm_input_path.string() + ".edge_segment_lookup";
|
edge_segment_lookup_path = osrm_input_path.string() + ".edge_segment_lookup";
|
||||||
edge_penalty_path = osrm_input_path.string() + ".edge_penalties";
|
turn_weight_penalties_path = osrm_input_path.string() + ".turn_weight_penalties";
|
||||||
|
turn_duration_penalties_path = osrm_input_path.string() + ".turn_duration_penalties";
|
||||||
|
turn_penalties_index_path = osrm_input_path.string() + ".turn_penalties_index";
|
||||||
node_based_graph_path = osrm_input_path.string() + ".nodes";
|
node_based_graph_path = osrm_input_path.string() + ".nodes";
|
||||||
geometry_path = osrm_input_path.string() + ".geometry";
|
geometry_path = osrm_input_path.string() + ".geometry";
|
||||||
rtree_leaf_path = osrm_input_path.string() + ".fileIndex";
|
rtree_leaf_path = osrm_input_path.string() + ".fileIndex";
|
||||||
@ -66,7 +68,9 @@ struct ContractorConfig
|
|||||||
std::string edge_based_graph_path;
|
std::string edge_based_graph_path;
|
||||||
|
|
||||||
std::string edge_segment_lookup_path;
|
std::string edge_segment_lookup_path;
|
||||||
std::string edge_penalty_path;
|
std::string turn_weight_penalties_path;
|
||||||
|
std::string turn_duration_penalties_path;
|
||||||
|
std::string turn_penalties_index_path;
|
||||||
std::string node_based_graph_path;
|
std::string node_based_graph_path;
|
||||||
std::string geometry_path;
|
std::string geometry_path;
|
||||||
std::string rtree_leaf_path;
|
std::string rtree_leaf_path;
|
||||||
|
@ -16,7 +16,7 @@ struct ContractorEdgeData
|
|||||||
is_original_via_node_ID(false)
|
is_original_via_node_ID(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ContractorEdgeData(unsigned weight,
|
ContractorEdgeData(EdgeWeight weight,
|
||||||
unsigned original_edges,
|
unsigned original_edges,
|
||||||
unsigned id,
|
unsigned id,
|
||||||
bool shortcut,
|
bool shortcut,
|
||||||
@ -26,7 +26,7 @@ struct ContractorEdgeData
|
|||||||
shortcut(shortcut), forward(forward), backward(backward), is_original_via_node_ID(false)
|
shortcut(shortcut), forward(forward), backward(backward), is_original_via_node_ID(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
unsigned weight;
|
EdgeWeight weight;
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned originalEdges : 28;
|
unsigned originalEdges : 28;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
|
@ -18,8 +18,11 @@ struct ContractorHeapData
|
|||||||
bool target = false;
|
bool target = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ContractorHeap = util::
|
using ContractorHeap = util::BinaryHeap<NodeID,
|
||||||
BinaryHeap<NodeID, NodeID, int, ContractorHeapData, util::XORFastHashStorage<NodeID, NodeID>>;
|
NodeID,
|
||||||
|
EdgeWeight,
|
||||||
|
ContractorHeapData,
|
||||||
|
util::XORFastHashStorage<NodeID, NodeID>>;
|
||||||
|
|
||||||
} // namespace contractor
|
} // namespace contractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -200,7 +200,7 @@ class GraphContractor
|
|||||||
|
|
||||||
dijkstra.Clear();
|
dijkstra.Clear();
|
||||||
dijkstra.Insert(source, 0, ContractorHeapData{});
|
dijkstra.Insert(source, 0, ContractorHeapData{});
|
||||||
int max_weight = 0;
|
EdgeWeight max_weight = 0;
|
||||||
unsigned number_of_targets = 0;
|
unsigned number_of_targets = 0;
|
||||||
|
|
||||||
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||||
@ -294,8 +294,8 @@ class GraphContractor
|
|||||||
const NodeID target = contractor_graph->GetTarget(out_edge);
|
const NodeID target = contractor_graph->GetTarget(out_edge);
|
||||||
if (target == node)
|
if (target == node)
|
||||||
continue;
|
continue;
|
||||||
const int path_weight = in_data.weight + out_data.weight;
|
const EdgeWeight path_weight = in_data.weight + out_data.weight;
|
||||||
const int weight = dijkstra.GetKey(target);
|
const EdgeWeight weight = dijkstra.GetKey(target);
|
||||||
if (path_weight < weight)
|
if (path_weight < weight)
|
||||||
{
|
{
|
||||||
if (RUNSIMULATION)
|
if (RUNSIMULATION)
|
||||||
|
@ -32,7 +32,7 @@ std::vector<ContractorEdge> adaptToContractorInput(InputEdgeContainer input_edge
|
|||||||
#endif
|
#endif
|
||||||
edges.emplace_back(input_edge.source,
|
edges.emplace_back(input_edge.source,
|
||||||
input_edge.target,
|
input_edge.target,
|
||||||
static_cast<unsigned int>(std::max(input_edge.weight, 1)),
|
std::max(input_edge.weight, 1),
|
||||||
1,
|
1,
|
||||||
input_edge.edge_id,
|
input_edge.edge_id,
|
||||||
false,
|
false,
|
||||||
@ -41,7 +41,7 @@ std::vector<ContractorEdge> adaptToContractorInput(InputEdgeContainer input_edge
|
|||||||
|
|
||||||
edges.emplace_back(input_edge.target,
|
edges.emplace_back(input_edge.target,
|
||||||
input_edge.source,
|
input_edge.source,
|
||||||
static_cast<unsigned int>(std::max(input_edge.weight, 1)),
|
std::max(input_edge.weight, 1),
|
||||||
1,
|
1,
|
||||||
input_edge.edge_id,
|
input_edge.edge_id,
|
||||||
false,
|
false,
|
||||||
|
@ -31,7 +31,7 @@ struct QueryEdge
|
|||||||
// node. Otherwise we see the edge based node to access node data.
|
// node. Otherwise we see the edge based node to access node data.
|
||||||
NodeID id : 31;
|
NodeID id : 31;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
int weight : 30;
|
EdgeWeight weight : 30;
|
||||||
bool forward : 1;
|
bool forward : 1;
|
||||||
bool backward : 1;
|
bool backward : 1;
|
||||||
} data;
|
} data;
|
||||||
|
@ -87,7 +87,8 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo
|
|||||||
|
|
||||||
util::json::Object makeRoute(const guidance::Route &route,
|
util::json::Object makeRoute(const guidance::Route &route,
|
||||||
util::json::Array legs,
|
util::json::Array legs,
|
||||||
boost::optional<util::json::Value> geometry);
|
boost::optional<util::json::Value> geometry,
|
||||||
|
const char *weight_name);
|
||||||
|
|
||||||
// Creates a Waypoint without Hint, see the Hint overload below
|
// Creates a Waypoint without Hint, see the Hint overload below
|
||||||
util::json::Object makeWaypoint(const util::Coordinate location, std::string name);
|
util::json::Object makeWaypoint(const util::Coordinate location, std::string name);
|
||||||
|
@ -221,21 +221,24 @@ class RouteAPI : public BaseAPI
|
|||||||
{
|
{
|
||||||
util::json::Array durations;
|
util::json::Array durations;
|
||||||
util::json::Array distances;
|
util::json::Array distances;
|
||||||
|
util::json::Array weights;
|
||||||
util::json::Array nodes;
|
util::json::Array nodes;
|
||||||
util::json::Array datasources;
|
util::json::Array datasources;
|
||||||
auto &leg_geometry = leg_geometries[idx];
|
auto &leg_geometry = leg_geometries[idx];
|
||||||
|
|
||||||
durations.values.reserve(leg_geometry.annotations.size());
|
durations.values.reserve(leg_geometry.annotations.size());
|
||||||
distances.values.reserve(leg_geometry.annotations.size());
|
distances.values.reserve(leg_geometry.annotations.size());
|
||||||
|
weights.values.reserve(leg_geometry.annotations.size());
|
||||||
nodes.values.reserve(leg_geometry.osm_node_ids.size());
|
nodes.values.reserve(leg_geometry.osm_node_ids.size());
|
||||||
datasources.values.reserve(leg_geometry.annotations.size());
|
datasources.values.reserve(leg_geometry.annotations.size());
|
||||||
|
|
||||||
std::for_each(leg_geometry.annotations.begin(),
|
std::for_each(leg_geometry.annotations.begin(),
|
||||||
leg_geometry.annotations.end(),
|
leg_geometry.annotations.end(),
|
||||||
[this, &durations, &distances, &datasources](
|
[this, &durations, &distances, &weights, &datasources](
|
||||||
const guidance::LegGeometry::Annotation &step) {
|
const guidance::LegGeometry::Annotation &step) {
|
||||||
durations.values.push_back(step.duration);
|
durations.values.push_back(step.duration);
|
||||||
distances.values.push_back(step.distance);
|
distances.values.push_back(step.distance);
|
||||||
|
weights.values.push_back(step.weight);
|
||||||
datasources.values.push_back(step.datasource);
|
datasources.values.push_back(step.datasource);
|
||||||
});
|
});
|
||||||
std::for_each(leg_geometry.osm_node_ids.begin(),
|
std::for_each(leg_geometry.osm_node_ids.begin(),
|
||||||
@ -246,6 +249,7 @@ class RouteAPI : public BaseAPI
|
|||||||
util::json::Object annotation;
|
util::json::Object annotation;
|
||||||
annotation.values["distance"] = std::move(distances);
|
annotation.values["distance"] = std::move(distances);
|
||||||
annotation.values["duration"] = std::move(durations);
|
annotation.values["duration"] = std::move(durations);
|
||||||
|
annotation.values["weight"] = std::move(weights);
|
||||||
annotation.values["nodes"] = std::move(nodes);
|
annotation.values["nodes"] = std::move(nodes);
|
||||||
annotation.values["datasources"] = std::move(datasources);
|
annotation.values["datasources"] = std::move(datasources);
|
||||||
annotations.push_back(std::move(annotation));
|
annotations.push_back(std::move(annotation));
|
||||||
@ -256,7 +260,8 @@ class RouteAPI : public BaseAPI
|
|||||||
json::makeRouteLegs(std::move(legs),
|
json::makeRouteLegs(std::move(legs),
|
||||||
std::move(step_geometries),
|
std::move(step_geometries),
|
||||||
std::move(annotations)),
|
std::move(annotations)),
|
||||||
std::move(json_overview));
|
std::move(json_overview),
|
||||||
|
facade.GetWeightName());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -88,10 +88,14 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
|
|||||||
util::ShM<NodeID, true>::vector m_geometry_node_list;
|
util::ShM<NodeID, true>::vector m_geometry_node_list;
|
||||||
util::ShM<EdgeWeight, true>::vector m_geometry_fwd_weight_list;
|
util::ShM<EdgeWeight, true>::vector m_geometry_fwd_weight_list;
|
||||||
util::ShM<EdgeWeight, true>::vector m_geometry_rev_weight_list;
|
util::ShM<EdgeWeight, true>::vector m_geometry_rev_weight_list;
|
||||||
|
util::ShM<EdgeWeight, true>::vector m_geometry_fwd_duration_list;
|
||||||
|
util::ShM<EdgeWeight, true>::vector m_geometry_rev_duration_list;
|
||||||
util::ShM<bool, true>::vector m_is_core_node;
|
util::ShM<bool, true>::vector m_is_core_node;
|
||||||
util::ShM<DatasourceID, true>::vector m_datasource_list;
|
util::ShM<DatasourceID, true>::vector m_datasource_list;
|
||||||
util::ShM<std::uint32_t, true>::vector m_lane_description_offsets;
|
util::ShM<std::uint32_t, true>::vector m_lane_description_offsets;
|
||||||
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector m_lane_description_masks;
|
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector m_lane_description_masks;
|
||||||
|
util::ShM<TurnPenalty, true>::vector m_turn_weight_penalties;
|
||||||
|
util::ShM<TurnPenalty, true>::vector m_turn_duration_penalties;
|
||||||
|
|
||||||
util::ShM<char, true>::vector m_datasource_name_data;
|
util::ShM<char, true>::vector m_datasource_name_data;
|
||||||
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
|
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
|
||||||
@ -311,6 +315,29 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
|
|||||||
m_is_core_node = std::move(is_core_node);
|
m_is_core_node = std::move(is_core_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InitializeTurnPenalties(storage::DataLayout &data_layout, char *memory_block)
|
||||||
|
{
|
||||||
|
auto turn_weight_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
|
||||||
|
memory_block, storage::DataLayout::TURN_WEIGHT_PENALTIES);
|
||||||
|
m_turn_weight_penalties = util::ShM<TurnPenalty, true>::vector(
|
||||||
|
turn_weight_penalties_ptr,
|
||||||
|
data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]);
|
||||||
|
if (data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES] == 0)
|
||||||
|
{ // Fallback to turn weight penalties that are turn duration penalties in deciseconds
|
||||||
|
m_turn_duration_penalties = util::ShM<TurnPenalty, true>::vector(
|
||||||
|
turn_weight_penalties_ptr,
|
||||||
|
data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto turn_duration_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
|
||||||
|
memory_block, storage::DataLayout::TURN_DURATION_PENALTIES);
|
||||||
|
m_turn_duration_penalties = util::ShM<TurnPenalty, true>::vector(
|
||||||
|
turn_duration_penalties_ptr,
|
||||||
|
data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void InitializeGeometryPointers(storage::DataLayout &data_layout, char *memory_block)
|
void InitializeGeometryPointers(storage::DataLayout &data_layout, char *memory_block)
|
||||||
{
|
{
|
||||||
auto geometries_index_ptr =
|
auto geometries_index_ptr =
|
||||||
@ -346,6 +373,20 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
|
|||||||
datasources_list_ptr, data_layout.num_entries[storage::DataLayout::DATASOURCES_LIST]);
|
datasources_list_ptr, data_layout.num_entries[storage::DataLayout::DATASOURCES_LIST]);
|
||||||
m_datasource_list = std::move(datasources_list);
|
m_datasource_list = std::move(datasources_list);
|
||||||
|
|
||||||
|
auto geometries_fwd_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||||
|
memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST);
|
||||||
|
util::ShM<EdgeWeight, true>::vector geometry_fwd_duration_list(
|
||||||
|
geometries_fwd_duration_list_ptr,
|
||||||
|
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]);
|
||||||
|
m_geometry_fwd_duration_list = std::move(geometry_fwd_duration_list);
|
||||||
|
|
||||||
|
auto geometries_rev_duration_list_ptr = data_layout.GetBlockPtr<EdgeWeight>(
|
||||||
|
memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST);
|
||||||
|
util::ShM<EdgeWeight, true>::vector geometry_rev_duration_list(
|
||||||
|
geometries_rev_duration_list_ptr,
|
||||||
|
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]);
|
||||||
|
m_geometry_rev_duration_list = std::move(geometry_rev_duration_list);
|
||||||
|
|
||||||
auto datasource_name_data_ptr =
|
auto datasource_name_data_ptr =
|
||||||
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::DATASOURCE_NAME_DATA);
|
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::DATASOURCE_NAME_DATA);
|
||||||
util::ShM<char, true>::vector datasource_name_data(
|
util::ShM<char, true>::vector datasource_name_data(
|
||||||
@ -406,6 +447,7 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
|
|||||||
InitializeGraphPointer(data_layout, memory_block);
|
InitializeGraphPointer(data_layout, memory_block);
|
||||||
InitializeChecksumPointer(data_layout, memory_block);
|
InitializeChecksumPointer(data_layout, memory_block);
|
||||||
InitializeNodeAndEdgeInformationPointers(data_layout, memory_block);
|
InitializeNodeAndEdgeInformationPointers(data_layout, memory_block);
|
||||||
|
InitializeTurnPenalties(data_layout, memory_block);
|
||||||
InitializeGeometryPointers(data_layout, memory_block);
|
InitializeGeometryPointers(data_layout, memory_block);
|
||||||
InitializeTimestampPointer(data_layout, memory_block);
|
InitializeTimestampPointer(data_layout, memory_block);
|
||||||
InitializeViaNodeListPointer(data_layout, memory_block);
|
InitializeViaNodeListPointer(data_layout, memory_block);
|
||||||
@ -535,6 +577,55 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
|
|||||||
return result_nodes;
|
return result_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual std::vector<EdgeWeight>
|
||||||
|
GetUncompressedForwardDurations(const EdgeID id) const override final
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* EdgeWeights's for geometries are stored in one place for
|
||||||
|
* both forward and reverse segments along the same bi-
|
||||||
|
* directional edge. The m_geometry_indices stores
|
||||||
|
* refences to where to find the beginning of the bi-
|
||||||
|
* directional edge in the m_geometry_fwd_weight_list vector.
|
||||||
|
* */
|
||||||
|
const unsigned begin = m_geometry_indices.at(id) + 1;
|
||||||
|
const unsigned end = m_geometry_indices.at(id + 1);
|
||||||
|
|
||||||
|
std::vector<EdgeWeight> result_durations;
|
||||||
|
result_durations.resize(end - begin);
|
||||||
|
|
||||||
|
std::copy(m_geometry_fwd_duration_list.begin() + begin,
|
||||||
|
m_geometry_fwd_duration_list.begin() + end,
|
||||||
|
result_durations.begin());
|
||||||
|
|
||||||
|
return result_durations;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::vector<EdgeWeight>
|
||||||
|
GetUncompressedReverseDurations(const EdgeID id) const override final
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* EdgeWeights for geometries are stored in one place for
|
||||||
|
* both forward and reverse segments along the same bi-
|
||||||
|
* directional edge. The m_geometry_indices stores
|
||||||
|
* refences to where to find the beginning of the bi-
|
||||||
|
* directional edge in the m_geometry_rev_weight_list vector. For
|
||||||
|
* reverse durations of bi-directional edges, edges 1 to
|
||||||
|
* n-1 of that edge need to be read in reverse.
|
||||||
|
*/
|
||||||
|
const unsigned begin = m_geometry_indices.at(id);
|
||||||
|
const unsigned end = m_geometry_indices.at(id + 1) - 1;
|
||||||
|
|
||||||
|
std::vector<EdgeWeight> result_durations;
|
||||||
|
result_durations.resize(end - begin);
|
||||||
|
|
||||||
|
std::copy(
|
||||||
|
m_geometry_rev_duration_list.rbegin() + (m_geometry_rev_duration_list.size() - end),
|
||||||
|
m_geometry_rev_duration_list.rbegin() + (m_geometry_rev_duration_list.size() - begin),
|
||||||
|
result_durations.begin());
|
||||||
|
|
||||||
|
return result_durations;
|
||||||
|
}
|
||||||
|
|
||||||
virtual std::vector<EdgeWeight>
|
virtual std::vector<EdgeWeight>
|
||||||
GetUncompressedForwardWeights(const EdgeID id) const override final
|
GetUncompressedForwardWeights(const EdgeID id) const override final
|
||||||
{
|
{
|
||||||
@ -588,6 +679,18 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
|
|||||||
return m_via_geometry_list.at(id);
|
return m_via_geometry_list.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_turn_weight_penalties.size() > id);
|
||||||
|
return m_turn_weight_penalties[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual TurnPenalty GetDurationPenaltyForEdgeID(const unsigned id) const override final
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_turn_duration_penalties.size() > id);
|
||||||
|
return m_turn_duration_penalties[id];
|
||||||
|
}
|
||||||
|
|
||||||
extractor::guidance::TurnInstruction
|
extractor::guidance::TurnInstruction
|
||||||
GetTurnInstructionForEdgeID(const EdgeID id) const override final
|
GetTurnInstructionForEdgeID(const EdgeID id) const override final
|
||||||
{
|
{
|
||||||
@ -886,6 +989,13 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
|
|||||||
return m_profile_properties->max_speed_for_map_matching;
|
return m_profile_properties->max_speed_for_map_matching;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *GetWeightName() const override final { return m_profile_properties->weight_name; }
|
||||||
|
|
||||||
|
unsigned GetWeightPrecision() const override final
|
||||||
|
{
|
||||||
|
return m_profile_properties->weight_precision;
|
||||||
|
}
|
||||||
|
|
||||||
BearingClassID GetBearingClassID(const NodeID id) const override final
|
BearingClassID GetBearingClassID(const NodeID id) const override final
|
||||||
{
|
{
|
||||||
return m_bearing_class_id_table.at(id);
|
return m_bearing_class_id_table.at(id);
|
||||||
|
@ -85,12 +85,20 @@ class BaseDataFacade
|
|||||||
|
|
||||||
virtual std::vector<NodeID> GetUncompressedReverseGeometry(const EdgeID id) const = 0;
|
virtual std::vector<NodeID> GetUncompressedReverseGeometry(const EdgeID id) const = 0;
|
||||||
|
|
||||||
|
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const = 0;
|
||||||
|
|
||||||
|
virtual TurnPenalty GetDurationPenaltyForEdgeID(const unsigned id) const = 0;
|
||||||
|
|
||||||
// Gets the weight values for each segment in an uncompressed geometry.
|
// Gets the weight values for each segment in an uncompressed geometry.
|
||||||
// Should always be 1 shorter than GetUncompressedGeometry
|
// Should always be 1 shorter than GetUncompressedGeometry
|
||||||
virtual std::vector<EdgeWeight> GetUncompressedForwardWeights(const EdgeID id) const = 0;
|
virtual std::vector<EdgeWeight> GetUncompressedForwardWeights(const EdgeID id) const = 0;
|
||||||
|
|
||||||
virtual std::vector<EdgeWeight> GetUncompressedReverseWeights(const EdgeID id) const = 0;
|
virtual std::vector<EdgeWeight> GetUncompressedReverseWeights(const EdgeID id) const = 0;
|
||||||
|
|
||||||
|
// Gets the duration values for each segment in an uncompressed geometry.
|
||||||
|
// Should always be 1 shorter than GetUncompressedGeometry
|
||||||
|
virtual std::vector<EdgeWeight> GetUncompressedForwardDurations(const EdgeID id) const = 0;
|
||||||
|
virtual std::vector<EdgeWeight> GetUncompressedReverseDurations(const EdgeID id) const = 0;
|
||||||
|
|
||||||
// Returns the data source ids that were used to supply the edge
|
// Returns the data source ids that were used to supply the edge
|
||||||
// weights. Will return an empty array when only the base profile is used.
|
// weights. Will return an empty array when only the base profile is used.
|
||||||
virtual std::vector<DatasourceID> GetUncompressedForwardDatasources(const EdgeID id) const = 0;
|
virtual std::vector<DatasourceID> GetUncompressedForwardDatasources(const EdgeID id) const = 0;
|
||||||
@ -177,6 +185,10 @@ class BaseDataFacade
|
|||||||
|
|
||||||
virtual double GetMapMatchingMaxSpeed() const = 0;
|
virtual double GetMapMatchingMaxSpeed() const = 0;
|
||||||
|
|
||||||
|
virtual const char *GetWeightName() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetWeightPrecision() const = 0;
|
||||||
|
|
||||||
virtual BearingClassID GetBearingClassID(const NodeID id) const = 0;
|
virtual BearingClassID GetBearingClassID(const NodeID id) const = 0;
|
||||||
|
|
||||||
virtual util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0;
|
virtual util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0;
|
||||||
|
@ -369,19 +369,24 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
// Find the node-based-edge that this belongs to, and directly
|
// Find the node-based-edge that this belongs to, and directly
|
||||||
// calculate the forward_weight, forward_offset, reverse_weight, reverse_offset
|
// calculate the forward_weight, forward_offset, reverse_weight, reverse_offset
|
||||||
|
|
||||||
int forward_offset = 0, forward_weight = 0;
|
EdgeWeight forward_offset = 0, forward_weight = 0, forward_duration = 0;
|
||||||
int reverse_offset = 0, reverse_weight = 0;
|
EdgeWeight reverse_offset = 0, reverse_weight = 0, reverse_duration = 0;
|
||||||
|
|
||||||
const std::vector<EdgeWeight> forward_weight_vector =
|
const std::vector<EdgeWeight> forward_weight_vector =
|
||||||
datafacade.GetUncompressedForwardWeights(data.packed_geometry_id);
|
datafacade.GetUncompressedForwardWeights(data.packed_geometry_id);
|
||||||
const std::vector<EdgeWeight> reverse_weight_vector =
|
const std::vector<EdgeWeight> reverse_weight_vector =
|
||||||
datafacade.GetUncompressedReverseWeights(data.packed_geometry_id);
|
datafacade.GetUncompressedReverseWeights(data.packed_geometry_id);
|
||||||
|
const std::vector<EdgeWeight> forward_duration_vector =
|
||||||
|
datafacade.GetUncompressedForwardDurations(data.packed_geometry_id);
|
||||||
|
const std::vector<EdgeWeight> reverse_duration_vector =
|
||||||
|
datafacade.GetUncompressedReverseDurations(data.packed_geometry_id);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < data.fwd_segment_position; i++)
|
for (std::size_t i = 0; i < data.fwd_segment_position; i++)
|
||||||
{
|
{
|
||||||
forward_offset += forward_weight_vector[i];
|
forward_offset += forward_weight_vector[i];
|
||||||
}
|
}
|
||||||
forward_weight = forward_weight_vector[data.fwd_segment_position];
|
forward_weight = forward_weight_vector[data.fwd_segment_position];
|
||||||
|
forward_duration = forward_duration_vector[data.fwd_segment_position];
|
||||||
|
|
||||||
BOOST_ASSERT(data.fwd_segment_position < reverse_weight_vector.size());
|
BOOST_ASSERT(data.fwd_segment_position < reverse_weight_vector.size());
|
||||||
|
|
||||||
@ -392,22 +397,27 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
}
|
}
|
||||||
reverse_weight =
|
reverse_weight =
|
||||||
reverse_weight_vector[reverse_weight_vector.size() - data.fwd_segment_position - 1];
|
reverse_weight_vector[reverse_weight_vector.size() - data.fwd_segment_position - 1];
|
||||||
|
reverse_duration =
|
||||||
|
reverse_duration_vector[reverse_duration_vector.size() - data.fwd_segment_position - 1];
|
||||||
|
|
||||||
ratio = std::min(1.0, std::max(0.0, ratio));
|
ratio = std::min(1.0, std::max(0.0, ratio));
|
||||||
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
|
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
|
||||||
{
|
{
|
||||||
forward_weight *= ratio;
|
forward_weight = static_cast<EdgeWeight>(forward_weight * ratio);
|
||||||
|
forward_duration = static_cast<EdgeWeight>(forward_duration * ratio);
|
||||||
}
|
}
|
||||||
if (data.reverse_segment_id.id != SPECIAL_SEGMENTID)
|
if (data.reverse_segment_id.id != SPECIAL_SEGMENTID)
|
||||||
{
|
{
|
||||||
const EdgeWeight difference = reverse_weight * ratio;
|
reverse_weight -= static_cast<EdgeWeight>(reverse_weight * ratio);
|
||||||
reverse_weight -= difference;
|
reverse_duration -= static_cast<EdgeWeight>(reverse_duration * ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
|
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
|
||||||
forward_weight,
|
forward_weight,
|
||||||
forward_offset,
|
|
||||||
reverse_weight,
|
reverse_weight,
|
||||||
|
forward_duration,
|
||||||
|
reverse_duration,
|
||||||
|
forward_offset,
|
||||||
reverse_offset,
|
reverse_offset,
|
||||||
point_on_segment,
|
point_on_segment,
|
||||||
input_coordinate},
|
input_coordinate},
|
||||||
|
@ -75,8 +75,11 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|||||||
}
|
}
|
||||||
|
|
||||||
prev_coordinate = coordinate;
|
prev_coordinate = coordinate;
|
||||||
geometry.annotations.emplace_back(LegGeometry::Annotation{
|
geometry.annotations.emplace_back(
|
||||||
current_distance, path_point.duration_until_turn / 10., path_point.datasource_id});
|
LegGeometry::Annotation{current_distance,
|
||||||
|
path_point.duration_until_turn / 10.,
|
||||||
|
path_point.weight_until_turn / 10.,
|
||||||
|
path_point.datasource_id});
|
||||||
geometry.locations.push_back(std::move(coordinate));
|
geometry.locations.push_back(std::move(coordinate));
|
||||||
geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(path_point.turn_via_node));
|
geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(path_point.turn_via_node));
|
||||||
}
|
}
|
||||||
@ -89,10 +92,14 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|||||||
const std::vector<DatasourceID> forward_datasources =
|
const std::vector<DatasourceID> forward_datasources =
|
||||||
facade.GetUncompressedForwardDatasources(target_node.packed_geometry_id);
|
facade.GetUncompressedForwardDatasources(target_node.packed_geometry_id);
|
||||||
|
|
||||||
|
// FIXME this is wrong. We need to check for traversal direction here
|
||||||
|
// and for the case of a local path (target and source on the same edge)
|
||||||
geometry.annotations.emplace_back(
|
geometry.annotations.emplace_back(
|
||||||
LegGeometry::Annotation{current_distance,
|
LegGeometry::Annotation{current_distance,
|
||||||
|
target_node.forward_duration / 10.,
|
||||||
target_node.forward_weight / 10.,
|
target_node.forward_weight / 10.,
|
||||||
forward_datasources[target_node.fwd_segment_position]});
|
forward_datasources[target_node.fwd_segment_position]});
|
||||||
|
|
||||||
geometry.segment_offsets.push_back(geometry.locations.size());
|
geometry.segment_offsets.push_back(geometry.locations.size());
|
||||||
geometry.locations.push_back(target_node.location);
|
geometry.locations.push_back(target_node.location);
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const std::vector<PathDa
|
|||||||
return NamedSegment{point.duration_until_turn, index++, point.name_id};
|
return NamedSegment{point.duration_until_turn, index++, point.name_id};
|
||||||
});
|
});
|
||||||
const auto target_duration =
|
const auto target_duration =
|
||||||
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
|
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
|
||||||
if (target_duration > 1)
|
if (target_duration > 1)
|
||||||
segments.push_back({target_duration, index++, target_node.name_id});
|
segments.push_back({target_duration, index++, target_node.name_id});
|
||||||
// this makes sure that the segment with the lowest position comes first
|
// this makes sure that the segment with the lowest position comes first
|
||||||
@ -130,18 +130,14 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
|||||||
const bool needs_summary)
|
const bool needs_summary)
|
||||||
{
|
{
|
||||||
const auto target_duration =
|
const auto target_duration =
|
||||||
(target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight) /
|
(target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration);
|
||||||
10.;
|
|
||||||
|
|
||||||
auto distance = std::accumulate(
|
auto distance = std::accumulate(
|
||||||
leg_geometry.segment_distances.begin(), leg_geometry.segment_distances.end(), 0.);
|
leg_geometry.segment_distances.begin(), leg_geometry.segment_distances.end(), 0.);
|
||||||
auto duration = std::accumulate(route_data.begin(),
|
auto duration = std::accumulate(
|
||||||
route_data.end(),
|
route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) {
|
||||||
0.,
|
|
||||||
[](const double sum, const PathData &data) {
|
|
||||||
return sum + data.duration_until_turn;
|
return sum + data.duration_until_turn;
|
||||||
}) /
|
});
|
||||||
10.;
|
|
||||||
|
|
||||||
// s
|
// s
|
||||||
// |
|
// |
|
||||||
@ -155,10 +151,10 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
|||||||
// The duration of the turn (a,c) -> (c,e) will be the duration of (a,c) (e.g. the duration
|
// The duration of the turn (a,c) -> (c,e) will be the duration of (a,c) (e.g. the duration
|
||||||
// of (a,b,c)).
|
// of (a,b,c)).
|
||||||
// The phantom node of s will contain:
|
// The phantom node of s will contain:
|
||||||
// `forward_weight`: duration of (a,s)
|
// `forward_duration`: duration of (a,s)
|
||||||
// `forward_offset`: 0 (its the first segment)
|
// `forward_offset`: 0 (its the first segment)
|
||||||
// The phantom node of t will contain:
|
// The phantom node of t will contain:
|
||||||
// `forward_weight`: duration of (d,t)
|
// `forward_duration`: duration of (d,t)
|
||||||
// `forward_offset`: duration of (c, d)
|
// `forward_offset`: duration of (c, d)
|
||||||
// path_data will have entries for (s,b), (b, c), (c, d) but (d, t) is only
|
// path_data will have entries for (s,b), (b, c), (c, d) but (d, t) is only
|
||||||
// caputed by the phantom node. So we need to add the target duration here.
|
// caputed by the phantom node. So we need to add the target duration here.
|
||||||
@ -167,9 +163,8 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
|||||||
duration = duration + target_duration;
|
duration = duration + target_duration;
|
||||||
if (route_data.empty())
|
if (route_data.empty())
|
||||||
{
|
{
|
||||||
duration -= (target_traversed_in_reverse ? source_node.reverse_weight
|
duration -= (target_traversed_in_reverse ? source_node.reverse_duration
|
||||||
: source_node.forward_weight) /
|
: source_node.forward_duration);
|
||||||
10.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string summary;
|
std::string summary;
|
||||||
@ -201,7 +196,7 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
|
|||||||
summary = boost::algorithm::join(summary_names, ", ");
|
summary = boost::algorithm::join(summary_names, ", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
return RouteLeg{duration, distance, summary, {}};
|
return RouteLeg{duration / 10., distance, summary, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
|
@ -41,14 +41,20 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
const bool source_traversed_in_reverse,
|
const bool source_traversed_in_reverse,
|
||||||
const bool target_traversed_in_reverse)
|
const bool target_traversed_in_reverse)
|
||||||
{
|
{
|
||||||
const double constexpr ZERO_DURATION = 0., ZERO_DISTANCE = 0.;
|
const double weight_multiplier = std::pow(10., facade.GetWeightPrecision());
|
||||||
|
|
||||||
|
const double constexpr ZERO_DURATION = 0., ZERO_DISTANCE = 0., ZERO_WEIGHT = 0;
|
||||||
const constexpr char *NO_ROTARY_NAME = "";
|
const constexpr char *NO_ROTARY_NAME = "";
|
||||||
const EdgeWeight source_duration =
|
const EdgeWeight source_weight =
|
||||||
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
|
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
|
||||||
|
const EdgeWeight source_duration =
|
||||||
|
source_traversed_in_reverse ? source_node.reverse_duration : source_node.forward_duration;
|
||||||
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
|
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
|
||||||
: source_node.forward_travel_mode;
|
: source_node.forward_travel_mode;
|
||||||
|
|
||||||
const EdgeWeight target_duration =
|
const EdgeWeight target_duration =
|
||||||
|
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
|
||||||
|
const EdgeWeight target_weight =
|
||||||
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
|
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
|
||||||
const auto target_mode = target_traversed_in_reverse ? target_node.backward_travel_mode
|
const auto target_mode = target_traversed_in_reverse ? target_node.backward_travel_mode
|
||||||
: target_node.forward_travel_mode;
|
: target_node.forward_travel_mode;
|
||||||
@ -84,7 +90,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
// but a RouteStep is with regard to the segment after the turn.
|
// but a RouteStep is with regard to the segment after the turn.
|
||||||
// We need to skip the first segment because it is already covered by the
|
// We need to skip the first segment because it is already covered by the
|
||||||
// initial start of a route
|
// initial start of a route
|
||||||
int segment_duration = 0;
|
EdgeWeight segment_duration = 0;
|
||||||
|
EdgeWeight segment_weight = 0;
|
||||||
|
|
||||||
// some name changes are not announced in our processing. For these, we have to keep the
|
// some name changes are not announced in our processing. For these, we have to keep the
|
||||||
// first name on the segment
|
// first name on the segment
|
||||||
@ -93,11 +100,12 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
{
|
{
|
||||||
const auto &path_point = leg_data[leg_data_index];
|
const auto &path_point = leg_data[leg_data_index];
|
||||||
segment_duration += path_point.duration_until_turn;
|
segment_duration += path_point.duration_until_turn;
|
||||||
|
segment_weight += path_point.weight_until_turn;
|
||||||
|
|
||||||
// all changes to this check have to be matched with assemble_geometry
|
// all changes to this check have to be matched with assemble_geometry
|
||||||
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
|
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(segment_duration >= 0);
|
BOOST_ASSERT(segment_weight >= 0);
|
||||||
const auto name = facade.GetNameForID(step_name_id);
|
const auto name = facade.GetNameForID(step_name_id);
|
||||||
const auto ref = facade.GetRefForID(step_name_id);
|
const auto ref = facade.GetRefForID(step_name_id);
|
||||||
const auto pronunciation = facade.GetPronunciationForID(step_name_id);
|
const auto pronunciation = facade.GetPronunciationForID(step_name_id);
|
||||||
@ -111,8 +119,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
destinations.to_string(),
|
destinations.to_string(),
|
||||||
NO_ROTARY_NAME,
|
NO_ROTARY_NAME,
|
||||||
NO_ROTARY_NAME,
|
NO_ROTARY_NAME,
|
||||||
segment_duration / 10.0,
|
segment_duration / 10.,
|
||||||
distance,
|
distance,
|
||||||
|
segment_weight / weight_multiplier,
|
||||||
path_point.travel_mode,
|
path_point.travel_mode,
|
||||||
maneuver,
|
maneuver,
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
@ -173,10 +182,12 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
0};
|
0};
|
||||||
segment_index++;
|
segment_index++;
|
||||||
segment_duration = 0;
|
segment_duration = 0;
|
||||||
|
segment_weight = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto distance = leg_geometry.segment_distances[segment_index];
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
||||||
const int duration = segment_duration + target_duration;
|
const EdgeWeight duration = segment_duration + target_duration;
|
||||||
|
const EdgeWeight weight = segment_weight + target_weight;
|
||||||
BOOST_ASSERT(duration >= 0);
|
BOOST_ASSERT(duration >= 0);
|
||||||
steps.push_back(RouteStep{step_name_id,
|
steps.push_back(RouteStep{step_name_id,
|
||||||
facade.GetNameForID(step_name_id).to_string(),
|
facade.GetNameForID(step_name_id).to_string(),
|
||||||
@ -187,6 +198,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
NO_ROTARY_NAME,
|
NO_ROTARY_NAME,
|
||||||
duration / 10.,
|
duration / 10.,
|
||||||
distance,
|
distance,
|
||||||
|
weight / weight_multiplier,
|
||||||
target_mode,
|
target_mode,
|
||||||
maneuver,
|
maneuver,
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
@ -202,7 +214,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
// |---| source_duration
|
// |---| source_duration
|
||||||
// |---------| target_duration
|
// |---------| target_duration
|
||||||
|
|
||||||
int duration = target_duration - source_duration;
|
const EdgeWeight duration = target_duration - source_duration;
|
||||||
|
const EdgeWeight weight = target_weight - source_weight;
|
||||||
BOOST_ASSERT(duration >= 0);
|
BOOST_ASSERT(duration >= 0);
|
||||||
|
|
||||||
steps.push_back(RouteStep{source_node.name_id,
|
steps.push_back(RouteStep{source_node.name_id,
|
||||||
@ -214,6 +227,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
NO_ROTARY_NAME,
|
NO_ROTARY_NAME,
|
||||||
duration / 10.,
|
duration / 10.,
|
||||||
leg_geometry.segment_distances[segment_index],
|
leg_geometry.segment_distances[segment_index],
|
||||||
|
weight / weight_multiplier,
|
||||||
source_mode,
|
source_mode,
|
||||||
std::move(maneuver),
|
std::move(maneuver),
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
@ -251,6 +265,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
NO_ROTARY_NAME,
|
NO_ROTARY_NAME,
|
||||||
ZERO_DURATION,
|
ZERO_DURATION,
|
||||||
ZERO_DISTANCE,
|
ZERO_DISTANCE,
|
||||||
|
ZERO_WEIGHT,
|
||||||
target_mode,
|
target_mode,
|
||||||
std::move(maneuver),
|
std::move(maneuver),
|
||||||
leg_geometry.locations.size() - 1,
|
leg_geometry.locations.size() - 1,
|
||||||
|
@ -37,8 +37,9 @@ struct LegGeometry
|
|||||||
// Per-coordinate metadata
|
// Per-coordinate metadata
|
||||||
struct Annotation
|
struct Annotation
|
||||||
{
|
{
|
||||||
double distance;
|
double distance; // distance in meters
|
||||||
double duration;
|
double duration; // duration in seconds
|
||||||
|
double weight; // weight value
|
||||||
DatasourceID datasource;
|
DatasourceID datasource;
|
||||||
};
|
};
|
||||||
std::vector<Annotation> annotations;
|
std::vector<Annotation> annotations;
|
||||||
|
@ -64,8 +64,9 @@ struct RouteStep
|
|||||||
std::string destinations;
|
std::string destinations;
|
||||||
std::string rotary_name;
|
std::string rotary_name;
|
||||||
std::string rotary_pronunciation;
|
std::string rotary_pronunciation;
|
||||||
double duration;
|
double duration; // duration in seconds
|
||||||
double distance;
|
double distance; // distance in meters
|
||||||
|
double weight; // weight value
|
||||||
extractor::TravelMode mode;
|
extractor::TravelMode mode;
|
||||||
StepManeuver maneuver;
|
StepManeuver maneuver;
|
||||||
// indices into the locations array stored the LegGeometry
|
// indices into the locations array stored the LegGeometry
|
||||||
@ -117,6 +118,7 @@ inline void RouteStep::Invalidate()
|
|||||||
rotary_pronunciation.clear();
|
rotary_pronunciation.clear();
|
||||||
duration = 0;
|
duration = 0;
|
||||||
distance = 0;
|
distance = 0;
|
||||||
|
weight = 0;
|
||||||
mode = TRAVEL_MODE_INACCESSIBLE;
|
mode = TRAVEL_MODE_INACCESSIBLE;
|
||||||
maneuver = getInvalidStepManeuver();
|
maneuver = getInvalidStepManeuver();
|
||||||
geometry_begin = 0;
|
geometry_begin = 0;
|
||||||
@ -132,6 +134,7 @@ inline RouteStep &RouteStep::AddInFront(const RouteStep &preceeding_step)
|
|||||||
BOOST_ASSERT(mode == preceeding_step.mode);
|
BOOST_ASSERT(mode == preceeding_step.mode);
|
||||||
duration += preceeding_step.duration;
|
duration += preceeding_step.duration;
|
||||||
distance += preceeding_step.distance;
|
distance += preceeding_step.distance;
|
||||||
|
weight += preceeding_step.weight;
|
||||||
|
|
||||||
geometry_begin = preceeding_step.geometry_begin;
|
geometry_begin = preceeding_step.geometry_begin;
|
||||||
intersections.insert(intersections.begin(),
|
intersections.insert(intersections.begin(),
|
||||||
@ -148,6 +151,7 @@ inline RouteStep &RouteStep::ElongateBy(const RouteStep &following_step)
|
|||||||
BOOST_ASSERT(mode == following_step.mode);
|
BOOST_ASSERT(mode == following_step.mode);
|
||||||
duration += following_step.duration;
|
duration += following_step.duration;
|
||||||
distance += following_step.distance;
|
distance += following_step.distance;
|
||||||
|
weight += following_step.weight;
|
||||||
|
|
||||||
geometry_end = following_step.geometry_end;
|
geometry_end = following_step.geometry_end;
|
||||||
intersections.insert(intersections.end(),
|
intersections.insert(intersections.end(),
|
||||||
|
@ -63,8 +63,8 @@ struct Hint
|
|||||||
friend std::ostream &operator<<(std::ostream &, const Hint &);
|
friend std::ostream &operator<<(std::ostream &, const Hint &);
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(Hint) == 56 + 4, "Hint is bigger than expected");
|
static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
|
||||||
constexpr std::size_t ENCODED_HINT_SIZE = 80;
|
constexpr std::size_t ENCODED_HINT_SIZE = 92;
|
||||||
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
|
||||||
"ENCODED_HINT_SIZE does not match size of Hint");
|
"ENCODED_HINT_SIZE does not match size of Hint");
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ struct PathData
|
|||||||
NodeID turn_via_node;
|
NodeID turn_via_node;
|
||||||
// name of the street that leads to the turn
|
// name of the street that leads to the turn
|
||||||
unsigned name_id;
|
unsigned name_id;
|
||||||
|
// weight that is traveled on the segment until the turn is reached
|
||||||
|
EdgeWeight weight_until_turn;
|
||||||
// duration that is traveled on the segment until the turn is reached
|
// duration that is traveled on the segment until the turn is reached
|
||||||
EdgeWeight duration_until_turn;
|
EdgeWeight duration_until_turn;
|
||||||
// instruction to execute at the turn
|
// instruction to execute at the turn
|
||||||
|
@ -49,10 +49,12 @@ struct PhantomNode
|
|||||||
PhantomNode(SegmentID forward_segment_id,
|
PhantomNode(SegmentID forward_segment_id,
|
||||||
SegmentID reverse_segment_id,
|
SegmentID reverse_segment_id,
|
||||||
unsigned name_id,
|
unsigned name_id,
|
||||||
int forward_weight,
|
EdgeWeight forward_weight,
|
||||||
int reverse_weight,
|
EdgeWeight reverse_weight,
|
||||||
int forward_offset,
|
EdgeWeight forward_duration,
|
||||||
int reverse_offset,
|
EdgeWeight reverse_duration,
|
||||||
|
EdgeWeight forward_offset,
|
||||||
|
EdgeWeight reverse_offset,
|
||||||
unsigned packed_geometry_id_,
|
unsigned packed_geometry_id_,
|
||||||
bool is_tiny_component,
|
bool is_tiny_component,
|
||||||
unsigned component_id,
|
unsigned component_id,
|
||||||
@ -63,6 +65,7 @@ struct PhantomNode
|
|||||||
extractor::TravelMode backward_travel_mode)
|
extractor::TravelMode backward_travel_mode)
|
||||||
: forward_segment_id(forward_segment_id), reverse_segment_id(reverse_segment_id),
|
: forward_segment_id(forward_segment_id), reverse_segment_id(reverse_segment_id),
|
||||||
name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight),
|
name_id(name_id), forward_weight(forward_weight), reverse_weight(reverse_weight),
|
||||||
|
forward_duration(forward_duration), reverse_duration(reverse_duration),
|
||||||
forward_offset(forward_offset), reverse_offset(reverse_offset),
|
forward_offset(forward_offset), reverse_offset(reverse_offset),
|
||||||
packed_geometry_id(packed_geometry_id_), component{component_id, is_tiny_component},
|
packed_geometry_id(packed_geometry_id_), component{component_id, is_tiny_component},
|
||||||
location(std::move(location)), input_location(std::move(input_location)),
|
location(std::move(location)), input_location(std::move(input_location)),
|
||||||
@ -75,20 +78,21 @@ struct PhantomNode
|
|||||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
||||||
reverse_segment_id{SPECIAL_SEGMENTID, false},
|
reverse_segment_id{SPECIAL_SEGMENTID, false},
|
||||||
name_id(std::numeric_limits<unsigned>::max()), forward_weight(INVALID_EDGE_WEIGHT),
|
name_id(std::numeric_limits<unsigned>::max()), forward_weight(INVALID_EDGE_WEIGHT),
|
||||||
reverse_weight(INVALID_EDGE_WEIGHT), forward_offset(0), reverse_offset(0),
|
reverse_weight(INVALID_EDGE_WEIGHT), forward_duration(INVALID_EDGE_WEIGHT),
|
||||||
|
reverse_duration(INVALID_EDGE_WEIGHT), forward_offset(0), reverse_offset(0),
|
||||||
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
|
packed_geometry_id(SPECIAL_GEOMETRYID), component{INVALID_COMPONENTID, false},
|
||||||
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
fwd_segment_position(0), forward_travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||||
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
backward_travel_mode(TRAVEL_MODE_INACCESSIBLE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetForwardWeightPlusOffset() const
|
EdgeWeight GetForwardWeightPlusOffset() const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(forward_segment_id.enabled);
|
BOOST_ASSERT(forward_segment_id.enabled);
|
||||||
return forward_offset + forward_weight;
|
return forward_offset + forward_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetReverseWeightPlusOffset() const
|
EdgeWeight GetReverseWeightPlusOffset() const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(reverse_segment_id.enabled);
|
BOOST_ASSERT(reverse_segment_id.enabled);
|
||||||
return reverse_offset + reverse_weight;
|
return reverse_offset + reverse_weight;
|
||||||
@ -102,6 +106,8 @@ struct PhantomNode
|
|||||||
(reverse_segment_id.id < number_of_nodes)) &&
|
(reverse_segment_id.id < number_of_nodes)) &&
|
||||||
((forward_weight != INVALID_EDGE_WEIGHT) ||
|
((forward_weight != INVALID_EDGE_WEIGHT) ||
|
||||||
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
||||||
|
((forward_duration != INVALID_EDGE_WEIGHT) ||
|
||||||
|
(reverse_duration != INVALID_EDGE_WEIGHT)) &&
|
||||||
(component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID);
|
(component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,19 +122,22 @@ struct PhantomNode
|
|||||||
|
|
||||||
template <class OtherT>
|
template <class OtherT>
|
||||||
explicit PhantomNode(const OtherT &other,
|
explicit PhantomNode(const OtherT &other,
|
||||||
int forward_weight_,
|
EdgeWeight forward_weight,
|
||||||
int forward_offset_,
|
EdgeWeight reverse_weight,
|
||||||
int reverse_weight_,
|
EdgeWeight forward_duration,
|
||||||
int reverse_offset_,
|
EdgeWeight reverse_duration,
|
||||||
const util::Coordinate location_,
|
EdgeWeight forward_offset,
|
||||||
const util::Coordinate input_location_)
|
EdgeWeight reverse_offset,
|
||||||
|
const util::Coordinate location,
|
||||||
|
const util::Coordinate input_location)
|
||||||
: forward_segment_id{other.forward_segment_id},
|
: forward_segment_id{other.forward_segment_id},
|
||||||
reverse_segment_id{other.reverse_segment_id}, name_id{other.name_id},
|
reverse_segment_id{other.reverse_segment_id}, name_id{other.name_id},
|
||||||
forward_weight{forward_weight_}, reverse_weight{reverse_weight_},
|
forward_weight{forward_weight}, reverse_weight{reverse_weight},
|
||||||
forward_offset{forward_offset_}, reverse_offset{reverse_offset_},
|
forward_duration{forward_duration}, reverse_duration{reverse_duration},
|
||||||
|
forward_offset{forward_offset}, reverse_offset{reverse_offset},
|
||||||
packed_geometry_id{other.packed_geometry_id},
|
packed_geometry_id{other.packed_geometry_id},
|
||||||
component{other.component.id, other.component.is_tiny}, location{location_},
|
component{other.component.id, other.component.is_tiny}, location{location},
|
||||||
input_location{input_location_}, fwd_segment_position{other.fwd_segment_position},
|
input_location{input_location}, fwd_segment_position{other.fwd_segment_position},
|
||||||
forward_travel_mode{other.forward_travel_mode},
|
forward_travel_mode{other.forward_travel_mode},
|
||||||
backward_travel_mode{other.backward_travel_mode}
|
backward_travel_mode{other.backward_travel_mode}
|
||||||
{
|
{
|
||||||
@ -137,10 +146,12 @@ struct PhantomNode
|
|||||||
SegmentID forward_segment_id;
|
SegmentID forward_segment_id;
|
||||||
SegmentID reverse_segment_id;
|
SegmentID reverse_segment_id;
|
||||||
unsigned name_id;
|
unsigned name_id;
|
||||||
int forward_weight;
|
EdgeWeight forward_weight;
|
||||||
int reverse_weight;
|
EdgeWeight reverse_weight;
|
||||||
int forward_offset;
|
EdgeWeight forward_duration;
|
||||||
int reverse_offset;
|
EdgeWeight reverse_duration;
|
||||||
|
EdgeWeight forward_offset;
|
||||||
|
EdgeWeight reverse_offset;
|
||||||
unsigned packed_geometry_id;
|
unsigned packed_geometry_id;
|
||||||
struct ComponentType
|
struct ComponentType
|
||||||
{
|
{
|
||||||
@ -158,7 +169,7 @@ struct PhantomNode
|
|||||||
extractor::TravelMode backward_travel_mode;
|
extractor::TravelMode backward_travel_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(PhantomNode) == 56, "PhantomNode has more padding then expected");
|
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
|
||||||
|
|
||||||
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;
|
||||||
|
|
||||||
@ -188,6 +199,8 @@ inline std::ostream &operator<<(std::ostream &out, const PhantomNode &pn)
|
|||||||
<< "name: " << pn.name_id << ", "
|
<< "name: " << pn.name_id << ", "
|
||||||
<< "fwd-w: " << pn.forward_weight << ", "
|
<< "fwd-w: " << pn.forward_weight << ", "
|
||||||
<< "rev-w: " << pn.reverse_weight << ", "
|
<< "rev-w: " << pn.reverse_weight << ", "
|
||||||
|
<< "fwd-d: " << pn.forward_duration << ", "
|
||||||
|
<< "rev-d: " << pn.reverse_duration << ", "
|
||||||
<< "fwd-o: " << pn.forward_offset << ", "
|
<< "fwd-o: " << pn.forward_offset << ", "
|
||||||
<< "rev-o: " << pn.reverse_offset << ", "
|
<< "rev-o: " << pn.reverse_offset << ", "
|
||||||
<< "geom: " << pn.packed_geometry_id << ", "
|
<< "geom: " << pn.packed_geometry_id << ", "
|
||||||
|
@ -91,7 +91,7 @@ class AlternativeRouting final : private BasicRoutingInterface
|
|||||||
QueryHeap &heap1,
|
QueryHeap &heap1,
|
||||||
QueryHeap &heap2,
|
QueryHeap &heap2,
|
||||||
NodeID *middle_node,
|
NodeID *middle_node,
|
||||||
int *upper_bound_to_shortest_path_weight,
|
EdgeWeight *upper_bound_to_shortest_path_weight,
|
||||||
std::vector<NodeID> &search_space_intersection,
|
std::vector<NodeID> &search_space_intersection,
|
||||||
std::vector<SearchSpaceEdge> &search_space,
|
std::vector<SearchSpaceEdge> &search_space,
|
||||||
const EdgeWeight min_edge_offset) const
|
const EdgeWeight min_edge_offset) const
|
||||||
@ -100,14 +100,14 @@ class AlternativeRouting final : private BasicRoutingInterface
|
|||||||
QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1);
|
QueryHeap &reverse_heap = (is_forward_directed ? heap2 : heap1);
|
||||||
|
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
const int weight = forward_heap.GetKey(node);
|
const EdgeWeight weight = forward_heap.GetKey(node);
|
||||||
// const NodeID parentnode = forward_heap.GetData(node).parent;
|
// const NodeID parentnode = forward_heap.GetData(node).parent;
|
||||||
// util::Log() << (is_forward_directed ? "[fwd] " : "[rev] ") << "settled
|
// util::Log() << (is_forward_directed ? "[fwd] " : "[rev] ") << "settled
|
||||||
// edge ("
|
// edge ("
|
||||||
// << parentnode << "," << node << "), dist: " << weight;
|
// << parentnode << "," << node << "), dist: " << weight;
|
||||||
|
|
||||||
const int scaled_weight =
|
const auto scaled_weight =
|
||||||
static_cast<int>((weight + min_edge_offset) / (1. + VIAPATH_EPSILON));
|
static_cast<EdgeWeight>((weight + min_edge_offset) / (1. + VIAPATH_EPSILON));
|
||||||
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_weight) &&
|
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_weight) &&
|
||||||
(scaled_weight > *upper_bound_to_shortest_path_weight))
|
(scaled_weight > *upper_bound_to_shortest_path_weight))
|
||||||
{
|
{
|
||||||
@ -120,7 +120,7 @@ class AlternativeRouting final : private BasicRoutingInterface
|
|||||||
if (reverse_heap.WasInserted(node))
|
if (reverse_heap.WasInserted(node))
|
||||||
{
|
{
|
||||||
search_space_intersection.emplace_back(node);
|
search_space_intersection.emplace_back(node);
|
||||||
const int new_weight = reverse_heap.GetKey(node) + weight;
|
const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
|
||||||
if (new_weight < *upper_bound_to_shortest_path_weight)
|
if (new_weight < *upper_bound_to_shortest_path_weight)
|
||||||
{
|
{
|
||||||
if (new_weight >= 0)
|
if (new_weight >= 0)
|
||||||
@ -139,7 +139,7 @@ class AlternativeRouting final : private BasicRoutingInterface
|
|||||||
{
|
{
|
||||||
// check whether there is a loop present at the node
|
// check whether there is a loop present at the node
|
||||||
const auto loop_weight = super::GetLoopWeight(facade, node);
|
const auto loop_weight = super::GetLoopWeight(facade, node);
|
||||||
const int new_weight_with_loop = new_weight + loop_weight;
|
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
||||||
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
||||||
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
||||||
{
|
{
|
||||||
@ -158,10 +158,10 @@ class AlternativeRouting final : private BasicRoutingInterface
|
|||||||
if (edge_is_forward_directed)
|
if (edge_is_forward_directed)
|
||||||
{
|
{
|
||||||
const NodeID to = facade->GetTarget(edge);
|
const NodeID to = facade->GetTarget(edge);
|
||||||
const int edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
|
||||||
BOOST_ASSERT(edge_weight > 0);
|
BOOST_ASSERT(edge_weight > 0);
|
||||||
const int to_weight = weight + edge_weight;
|
const EdgeWeight to_weight = weight + edge_weight;
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!forward_heap.WasInserted(to))
|
if (!forward_heap.WasInserted(to))
|
||||||
|
@ -76,10 +76,10 @@ class ManyToManyRouting final : public BasicRoutingInterface
|
|||||||
if (direction_flag)
|
if (direction_flag)
|
||||||
{
|
{
|
||||||
const NodeID to = facade->GetTarget(edge);
|
const NodeID to = facade->GetTarget(edge);
|
||||||
const int edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
const int to_weight = weight + edge_weight;
|
const EdgeWeight to_weight = weight + edge_weight;
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!query_heap.WasInserted(to))
|
if (!query_heap.WasInserted(to))
|
||||||
@ -111,7 +111,7 @@ class ManyToManyRouting final : public BasicRoutingInterface
|
|||||||
if (reverse_flag)
|
if (reverse_flag)
|
||||||
{
|
{
|
||||||
const NodeID to = facade->GetTarget(edge);
|
const NodeID to = facade->GetTarget(edge);
|
||||||
const int edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
if (query_heap.WasInserted(to))
|
if (query_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
|
@ -122,12 +122,15 @@ class BasicRoutingInterface
|
|||||||
|
|
||||||
const auto geometry_index = facade->GetGeometryIndexForEdgeID(edge_data.id);
|
const auto geometry_index = facade->GetGeometryIndexForEdgeID(edge_data.id);
|
||||||
std::vector<NodeID> id_vector;
|
std::vector<NodeID> id_vector;
|
||||||
|
|
||||||
std::vector<EdgeWeight> weight_vector;
|
std::vector<EdgeWeight> weight_vector;
|
||||||
|
std::vector<EdgeWeight> duration_vector;
|
||||||
std::vector<DatasourceID> datasource_vector;
|
std::vector<DatasourceID> datasource_vector;
|
||||||
if (geometry_index.forward)
|
if (geometry_index.forward)
|
||||||
{
|
{
|
||||||
id_vector = facade->GetUncompressedForwardGeometry(geometry_index.id);
|
id_vector = facade->GetUncompressedForwardGeometry(geometry_index.id);
|
||||||
weight_vector = facade->GetUncompressedForwardWeights(geometry_index.id);
|
weight_vector = facade->GetUncompressedForwardWeights(geometry_index.id);
|
||||||
|
duration_vector = facade->GetUncompressedForwardDurations(geometry_index.id);
|
||||||
datasource_vector =
|
datasource_vector =
|
||||||
facade->GetUncompressedForwardDatasources(geometry_index.id);
|
facade->GetUncompressedForwardDatasources(geometry_index.id);
|
||||||
}
|
}
|
||||||
@ -135,17 +138,14 @@ class BasicRoutingInterface
|
|||||||
{
|
{
|
||||||
id_vector = facade->GetUncompressedReverseGeometry(geometry_index.id);
|
id_vector = facade->GetUncompressedReverseGeometry(geometry_index.id);
|
||||||
weight_vector = facade->GetUncompressedReverseWeights(geometry_index.id);
|
weight_vector = facade->GetUncompressedReverseWeights(geometry_index.id);
|
||||||
|
duration_vector = facade->GetUncompressedReverseDurations(geometry_index.id);
|
||||||
datasource_vector =
|
datasource_vector =
|
||||||
facade->GetUncompressedReverseDatasources(geometry_index.id);
|
facade->GetUncompressedReverseDatasources(geometry_index.id);
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(id_vector.size() > 0);
|
BOOST_ASSERT(id_vector.size() > 0);
|
||||||
BOOST_ASSERT(weight_vector.size() > 0);
|
|
||||||
BOOST_ASSERT(datasource_vector.size() > 0);
|
BOOST_ASSERT(datasource_vector.size() > 0);
|
||||||
|
|
||||||
const auto total_weight =
|
|
||||||
std::accumulate(weight_vector.begin(), weight_vector.end(), 0);
|
|
||||||
|
|
||||||
BOOST_ASSERT(weight_vector.size() == id_vector.size() - 1);
|
BOOST_ASSERT(weight_vector.size() == id_vector.size() - 1);
|
||||||
|
BOOST_ASSERT(duration_vector.size() == id_vector.size() - 1);
|
||||||
const bool is_first_segment = unpacked_path.empty();
|
const bool is_first_segment = unpacked_path.empty();
|
||||||
|
|
||||||
const std::size_t start_index =
|
const std::size_t start_index =
|
||||||
@ -165,6 +165,7 @@ class BasicRoutingInterface
|
|||||||
PathData{id_vector[segment_idx + 1],
|
PathData{id_vector[segment_idx + 1],
|
||||||
name_index,
|
name_index,
|
||||||
weight_vector[segment_idx],
|
weight_vector[segment_idx],
|
||||||
|
duration_vector[segment_idx],
|
||||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||||
travel_mode,
|
travel_mode,
|
||||||
@ -179,7 +180,10 @@ class BasicRoutingInterface
|
|||||||
|
|
||||||
unpacked_path.back().entry_classid = facade->GetEntryClassID(edge_data.id);
|
unpacked_path.back().entry_classid = facade->GetEntryClassID(edge_data.id);
|
||||||
unpacked_path.back().turn_instruction = turn_instruction;
|
unpacked_path.back().turn_instruction = turn_instruction;
|
||||||
unpacked_path.back().duration_until_turn += (edge_data.weight - total_weight);
|
unpacked_path.back().duration_until_turn +=
|
||||||
|
facade->GetDurationPenaltyForEdgeID(edge_data.id);
|
||||||
|
unpacked_path.back().weight_until_turn +=
|
||||||
|
facade->GetWeightPenaltyForEdgeID(edge_data.id);
|
||||||
unpacked_path.back().pre_turn_bearing = facade->PreTurnBearing(edge_data.id);
|
unpacked_path.back().pre_turn_bearing = facade->PreTurnBearing(edge_data.id);
|
||||||
unpacked_path.back().post_turn_bearing = facade->PostTurnBearing(edge_data.id);
|
unpacked_path.back().post_turn_bearing = facade->PostTurnBearing(edge_data.id);
|
||||||
});
|
});
|
||||||
@ -187,6 +191,7 @@ class BasicRoutingInterface
|
|||||||
std::size_t start_index = 0, end_index = 0;
|
std::size_t start_index = 0, end_index = 0;
|
||||||
std::vector<unsigned> id_vector;
|
std::vector<unsigned> id_vector;
|
||||||
std::vector<EdgeWeight> weight_vector;
|
std::vector<EdgeWeight> weight_vector;
|
||||||
|
std::vector<EdgeWeight> duration_vector;
|
||||||
std::vector<DatasourceID> datasource_vector;
|
std::vector<DatasourceID> datasource_vector;
|
||||||
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
|
const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id ==
|
||||||
phantom_node_pair.target_phantom.packed_geometry_id) &&
|
phantom_node_pair.target_phantom.packed_geometry_id) &&
|
||||||
@ -200,6 +205,9 @@ class BasicRoutingInterface
|
|||||||
weight_vector = facade->GetUncompressedReverseWeights(
|
weight_vector = facade->GetUncompressedReverseWeights(
|
||||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||||
|
|
||||||
|
duration_vector = facade->GetUncompressedReverseDurations(
|
||||||
|
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||||
|
|
||||||
datasource_vector = facade->GetUncompressedReverseDatasources(
|
datasource_vector = facade->GetUncompressedReverseDatasources(
|
||||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||||
|
|
||||||
@ -225,6 +233,9 @@ class BasicRoutingInterface
|
|||||||
weight_vector = facade->GetUncompressedForwardWeights(
|
weight_vector = facade->GetUncompressedForwardWeights(
|
||||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||||
|
|
||||||
|
duration_vector = facade->GetUncompressedForwardDurations(
|
||||||
|
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||||
|
|
||||||
datasource_vector = facade->GetUncompressedForwardDatasources(
|
datasource_vector = facade->GetUncompressedForwardDatasources(
|
||||||
phantom_node_pair.target_phantom.packed_geometry_id);
|
phantom_node_pair.target_phantom.packed_geometry_id);
|
||||||
}
|
}
|
||||||
@ -245,6 +256,7 @@ class BasicRoutingInterface
|
|||||||
id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
|
id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
|
||||||
phantom_node_pair.target_phantom.name_id,
|
phantom_node_pair.target_phantom.name_id,
|
||||||
weight_vector[segment_idx],
|
weight_vector[segment_idx],
|
||||||
|
duration_vector[segment_idx],
|
||||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||||
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
|
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
|
||||||
@ -260,6 +272,9 @@ class BasicRoutingInterface
|
|||||||
const auto source_weight = start_traversed_in_reverse
|
const auto source_weight = start_traversed_in_reverse
|
||||||
? phantom_node_pair.source_phantom.reverse_weight
|
? phantom_node_pair.source_phantom.reverse_weight
|
||||||
: phantom_node_pair.source_phantom.forward_weight;
|
: phantom_node_pair.source_phantom.forward_weight;
|
||||||
|
const auto source_duration = start_traversed_in_reverse
|
||||||
|
? phantom_node_pair.source_phantom.reverse_duration
|
||||||
|
: phantom_node_pair.source_phantom.forward_duration;
|
||||||
// The above code will create segments for (v, w), (w,x), (x, y) and (y, Z).
|
// The above code will create segments for (v, w), (w,x), (x, y) and (y, Z).
|
||||||
// However the first segment duration needs to be adjusted to the fact that the source
|
// However the first segment duration needs to be adjusted to the fact that the source
|
||||||
// phantom is in the middle of the segment. We do this by subtracting v--s from the
|
// phantom is in the middle of the segment. We do this by subtracting v--s from the
|
||||||
@ -273,8 +288,10 @@ class BasicRoutingInterface
|
|||||||
// TODO this creates a scenario where it's possible the duration from a phantom
|
// TODO this creates a scenario where it's possible the duration from a phantom
|
||||||
// node to the first turn would be the same as from end to end of a segment,
|
// node to the first turn would be the same as from end to end of a segment,
|
||||||
// which is obviously incorrect and not ideal...
|
// which is obviously incorrect and not ideal...
|
||||||
|
unpacked_path.front().weight_until_turn =
|
||||||
|
std::max(unpacked_path.front().weight_until_turn - source_weight, 0);
|
||||||
unpacked_path.front().duration_until_turn =
|
unpacked_path.front().duration_until_turn =
|
||||||
std::max(unpacked_path.front().duration_until_turn - source_weight, 0);
|
std::max(unpacked_path.front().duration_until_turn - source_duration, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// there is no equivalent to a node-based node in an edge-expanded graph.
|
// there is no equivalent to a node-based node in an edge-expanded graph.
|
||||||
|
@ -19,8 +19,8 @@ struct HeapData
|
|||||||
|
|
||||||
struct SearchEngineData
|
struct SearchEngineData
|
||||||
{
|
{
|
||||||
using QueryHeap =
|
using QueryHeap = util::
|
||||||
util::BinaryHeap<NodeID, NodeID, int, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
BinaryHeap<NodeID, NodeID, EdgeWeight, HeapData, util::UnorderedMapStorage<NodeID, int>>;
|
||||||
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||||
|
|
||||||
static SearchEngineHeapPtr forward_heap_1;
|
static SearchEngineHeapPtr forward_heap_1;
|
||||||
|
@ -21,6 +21,7 @@ class CompressedEdgeContainer
|
|||||||
public:
|
public:
|
||||||
NodeID node_id; // refers to an internal node-based-node
|
NodeID node_id; // refers to an internal node-based-node
|
||||||
EdgeWeight weight; // the weight of the edge leading to this node
|
EdgeWeight weight; // the weight of the edge leading to this node
|
||||||
|
EdgeWeight duration; // the duration of the edge leading to this node
|
||||||
};
|
};
|
||||||
|
|
||||||
using OnewayEdgeBucket = std::vector<OnewayCompressedEdge>;
|
using OnewayEdgeBucket = std::vector<OnewayCompressedEdge>;
|
||||||
@ -31,10 +32,14 @@ class CompressedEdgeContainer
|
|||||||
const NodeID via_node_id,
|
const NodeID via_node_id,
|
||||||
const NodeID target_node,
|
const NodeID target_node,
|
||||||
const EdgeWeight weight1,
|
const EdgeWeight weight1,
|
||||||
const EdgeWeight weight2);
|
const EdgeWeight weight2,
|
||||||
|
const EdgeWeight duration1,
|
||||||
|
const EdgeWeight duration2);
|
||||||
|
|
||||||
void
|
void AddUncompressedEdge(const EdgeID edge_id,
|
||||||
AddUncompressedEdge(const EdgeID edge_id, const NodeID target_node, const EdgeWeight weight);
|
const NodeID target_node,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
const EdgeWeight duration);
|
||||||
|
|
||||||
void InitializeBothwayVector();
|
void InitializeBothwayVector();
|
||||||
unsigned ZipEdges(const unsigned f_edge_pos, const unsigned r_edge_pos);
|
unsigned ZipEdges(const unsigned f_edge_pos, const unsigned r_edge_pos);
|
||||||
@ -62,6 +67,8 @@ class CompressedEdgeContainer
|
|||||||
std::vector<NodeID> m_compressed_geometry_nodes;
|
std::vector<NodeID> m_compressed_geometry_nodes;
|
||||||
std::vector<EdgeWeight> m_compressed_geometry_fwd_weights;
|
std::vector<EdgeWeight> m_compressed_geometry_fwd_weights;
|
||||||
std::vector<EdgeWeight> m_compressed_geometry_rev_weights;
|
std::vector<EdgeWeight> m_compressed_geometry_rev_weights;
|
||||||
|
std::vector<EdgeWeight> m_compressed_geometry_fwd_durations;
|
||||||
|
std::vector<EdgeWeight> m_compressed_geometry_rev_durations;
|
||||||
std::vector<unsigned> m_free_list;
|
std::vector<unsigned> m_free_list;
|
||||||
std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map;
|
||||||
std::unordered_map<EdgeID, unsigned> m_forward_edge_id_to_zipped_index_map;
|
std::unordered_map<EdgeID, unsigned> m_forward_edge_id_to_zipped_index_map;
|
||||||
|
@ -30,9 +30,13 @@ struct EdgeBasedEdge
|
|||||||
NodeID target;
|
NodeID target;
|
||||||
NodeID edge_id;
|
NodeID edge_id;
|
||||||
EdgeWeight weight : 30;
|
EdgeWeight weight : 30;
|
||||||
bool forward : 1;
|
std::uint32_t forward : 1;
|
||||||
bool backward : 1;
|
std::uint32_t backward : 1;
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(extractor::EdgeBasedEdge) == 16,
|
||||||
|
"Size of extractor::EdgeBasedEdge type is "
|
||||||
|
"bigger than expected. This will influence "
|
||||||
|
"memory consumption.");
|
||||||
|
|
||||||
// Impl.
|
// Impl.
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "extractor/compressed_edge_container.hpp"
|
#include "extractor/compressed_edge_container.hpp"
|
||||||
#include "extractor/edge_based_edge.hpp"
|
#include "extractor/edge_based_edge.hpp"
|
||||||
#include "extractor/edge_based_node.hpp"
|
#include "extractor/edge_based_node.hpp"
|
||||||
|
#include "extractor/extraction_turn.hpp"
|
||||||
#include "extractor/original_edge_data.hpp"
|
#include "extractor/original_edge_data.hpp"
|
||||||
#include "extractor/profile_properties.hpp"
|
#include "extractor/profile_properties.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
@ -65,15 +66,25 @@ struct SegmentBlock
|
|||||||
static_assert(sizeof(SegmentBlock) == 20, "SegmentBlock is not packed correctly");
|
static_assert(sizeof(SegmentBlock) == 20, "SegmentBlock is not packed correctly");
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct PenaltyBlock
|
struct TurnPenaltiesHeader
|
||||||
|
{
|
||||||
|
//! the number of penalties in each block
|
||||||
|
std::uint64_t number_of_penalties;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
static_assert(std::is_trivial<TurnPenaltiesHeader>::value, "TurnPenaltiesHeader is not trivial");
|
||||||
|
static_assert(sizeof(TurnPenaltiesHeader) == 8, "TurnPenaltiesHeader is not packed correctly");
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct TurnIndexBlock
|
||||||
{
|
{
|
||||||
std::uint32_t fixed_penalty;
|
|
||||||
OSMNodeID from_id;
|
OSMNodeID from_id;
|
||||||
OSMNodeID via_id;
|
OSMNodeID via_id;
|
||||||
OSMNodeID to_id;
|
OSMNodeID to_id;
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
static_assert(sizeof(PenaltyBlock) == 28, "PenaltyBlock is not packed correctly");
|
static_assert(std::is_trivial<TurnIndexBlock>::value, "TurnIndexBlock is not trivial");
|
||||||
|
static_assert(sizeof(TurnIndexBlock) == 24, "TurnIndexBlock is not packed correctly");
|
||||||
}
|
}
|
||||||
|
|
||||||
class EdgeBasedGraphFactory
|
class EdgeBasedGraphFactory
|
||||||
@ -98,7 +109,9 @@ class EdgeBasedGraphFactory
|
|||||||
const std::string &original_edge_data_filename,
|
const std::string &original_edge_data_filename,
|
||||||
const std::string &turn_lane_data_filename,
|
const std::string &turn_lane_data_filename,
|
||||||
const std::string &edge_segment_lookup_filename,
|
const std::string &edge_segment_lookup_filename,
|
||||||
const std::string &edge_penalty_filename,
|
const std::string &turn_weight_penalties_filename,
|
||||||
|
const std::string &turn_duration_penalties_filename,
|
||||||
|
const std::string &turn_penalties_index_filename,
|
||||||
const bool generate_edge_lookup);
|
const bool generate_edge_lookup);
|
||||||
|
|
||||||
// The following get access functions destroy the content in the factory
|
// The following get access functions destroy the content in the factory
|
||||||
@ -157,14 +170,15 @@ class EdgeBasedGraphFactory
|
|||||||
std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks;
|
std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks;
|
||||||
guidance::LaneDescriptionMap &lane_description_map;
|
guidance::LaneDescriptionMap &lane_description_map;
|
||||||
|
|
||||||
void CompressGeometry();
|
|
||||||
unsigned RenumberEdges();
|
unsigned RenumberEdges();
|
||||||
void GenerateEdgeExpandedNodes();
|
void GenerateEdgeExpandedNodes();
|
||||||
void GenerateEdgeExpandedEdges(ScriptingEnvironment &scripting_environment,
|
void GenerateEdgeExpandedEdges(ScriptingEnvironment &scripting_environment,
|
||||||
const std::string &original_edge_data_filename,
|
const std::string &original_edge_data_filename,
|
||||||
const std::string &turn_lane_data_filename,
|
const std::string &turn_lane_data_filename,
|
||||||
const std::string &edge_segment_lookup_filename,
|
const std::string &edge_segment_lookup_filename,
|
||||||
const std::string &edge_fixed_penalties_filename,
|
const std::string &turn_weight_penalties_filename,
|
||||||
|
const std::string &turn_duration_penalties_filename,
|
||||||
|
const std::string &turn_penalties_index_filename,
|
||||||
const bool generate_edge_lookup);
|
const bool generate_edge_lookup);
|
||||||
|
|
||||||
void InsertEdgeBasedNode(const NodeID u, const NodeID v);
|
void InsertEdgeBasedNode(const NodeID u, const NodeID v);
|
||||||
|
32
include/extractor/extraction_segment.hpp
Normal file
32
include/extractor/extraction_segment.hpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef OSRM_EXTRACTION_SEGMENT_HPP
|
||||||
|
#define OSRM_EXTRACTION_SEGMENT_HPP
|
||||||
|
|
||||||
|
#include <util/coordinate.hpp>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ExtractionSegment
|
||||||
|
{
|
||||||
|
ExtractionSegment(const osrm::util::Coordinate source_,
|
||||||
|
const osrm::util::Coordinate target_,
|
||||||
|
double distance_,
|
||||||
|
double weight_,
|
||||||
|
double duration_)
|
||||||
|
: source(source_), target(target_), distance(distance_), weight(weight_),
|
||||||
|
duration(duration_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const osrm::util::Coordinate source;
|
||||||
|
const osrm::util::Coordinate target;
|
||||||
|
const double distance;
|
||||||
|
double weight;
|
||||||
|
double duration;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
34
include/extractor/extraction_turn.hpp
Normal file
34
include/extractor/extraction_turn.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef OSRM_EXTRACTION_TURN_HPP
|
||||||
|
#define OSRM_EXTRACTION_TURN_HPP
|
||||||
|
|
||||||
|
#include <boost/numeric/conversion/cast.hpp>
|
||||||
|
|
||||||
|
#include <extractor/guidance/intersection.hpp>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ExtractionTurn
|
||||||
|
{
|
||||||
|
ExtractionTurn(const guidance::ConnectedRoad &turn, bool has_traffic_light)
|
||||||
|
: angle(180. - turn.angle), turn_type(turn.instruction.type),
|
||||||
|
direction_modifier(turn.instruction.direction_modifier),
|
||||||
|
has_traffic_light(has_traffic_light), weight(0.), duration(0.)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const double angle;
|
||||||
|
const guidance::TurnType::Enum turn_type;
|
||||||
|
const guidance::DirectionModifier::Enum direction_modifier;
|
||||||
|
const bool has_traffic_light;
|
||||||
|
double weight;
|
||||||
|
double duration;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -42,7 +42,10 @@ struct ExtractionWay
|
|||||||
{
|
{
|
||||||
forward_speed = -1;
|
forward_speed = -1;
|
||||||
backward_speed = -1;
|
backward_speed = -1;
|
||||||
|
forward_rate = -1;
|
||||||
|
backward_rate = -1;
|
||||||
duration = -1;
|
duration = -1;
|
||||||
|
weight = -1;
|
||||||
roundabout = false;
|
roundabout = false;
|
||||||
circular = false;
|
circular = false;
|
||||||
is_startpoint = true;
|
is_startpoint = true;
|
||||||
@ -84,9 +87,16 @@ struct ExtractionWay
|
|||||||
}
|
}
|
||||||
const char *GetTurnLanesBackward() const { return turn_lanes_backward.c_str(); }
|
const char *GetTurnLanesBackward() const { return turn_lanes_backward.c_str(); }
|
||||||
|
|
||||||
|
// speed in km/h
|
||||||
double forward_speed;
|
double forward_speed;
|
||||||
double backward_speed;
|
double backward_speed;
|
||||||
|
// weight per meter
|
||||||
|
double forward_rate;
|
||||||
|
double backward_rate;
|
||||||
|
// duration of the whole way in both directions
|
||||||
double duration;
|
double duration;
|
||||||
|
// weight of the whole way in both directions
|
||||||
|
double weight;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string ref;
|
std::string ref;
|
||||||
std::string pronunciation;
|
std::string pronunciation;
|
||||||
|
@ -43,6 +43,7 @@ class ExtractionContainers;
|
|||||||
struct InputRestrictionContainer;
|
struct InputRestrictionContainer;
|
||||||
struct ExtractionNode;
|
struct ExtractionNode;
|
||||||
struct ExtractionWay;
|
struct ExtractionWay;
|
||||||
|
struct ProfileProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used by the extractor with the results of the
|
* This class is used by the extractor with the results of the
|
||||||
@ -61,9 +62,11 @@ class ExtractorCallbacks
|
|||||||
std::unordered_map<MapKey, MapVal> string_map;
|
std::unordered_map<MapKey, MapVal> string_map;
|
||||||
guidance::LaneDescriptionMap lane_description_map;
|
guidance::LaneDescriptionMap lane_description_map;
|
||||||
ExtractionContainers &external_memory;
|
ExtractionContainers &external_memory;
|
||||||
|
bool fallback_to_duration;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers);
|
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
||||||
|
const ProfileProperties &properties);
|
||||||
|
|
||||||
ExtractorCallbacks(const ExtractorCallbacks &) = delete;
|
ExtractorCallbacks(const ExtractorCallbacks &) = delete;
|
||||||
ExtractorCallbacks &operator=(const ExtractorCallbacks &) = delete;
|
ExtractorCallbacks &operator=(const ExtractorCallbacks &) = delete;
|
||||||
|
@ -71,7 +71,9 @@ struct ExtractorConfig
|
|||||||
rtree_nodes_output_path = basepath + ".osrm.ramIndex";
|
rtree_nodes_output_path = basepath + ".osrm.ramIndex";
|
||||||
rtree_leafs_output_path = basepath + ".osrm.fileIndex";
|
rtree_leafs_output_path = basepath + ".osrm.fileIndex";
|
||||||
edge_segment_lookup_path = basepath + ".osrm.edge_segment_lookup";
|
edge_segment_lookup_path = basepath + ".osrm.edge_segment_lookup";
|
||||||
edge_penalty_path = basepath + ".osrm.edge_penalties";
|
turn_duration_penalties_path = basepath + ".osrm.turn_duration_penalties";
|
||||||
|
turn_weight_penalties_path = basepath + ".osrm.turn_weight_penalties";
|
||||||
|
turn_penalties_index_path = basepath + ".osrm.turn_penalties_index";
|
||||||
edge_based_node_weights_output_path = basepath + ".osrm.enw";
|
edge_based_node_weights_output_path = basepath + ".osrm.enw";
|
||||||
profile_properties_output_path = basepath + ".osrm.properties";
|
profile_properties_output_path = basepath + ".osrm.properties";
|
||||||
intersection_class_data_output_path = basepath + ".osrm.icd";
|
intersection_class_data_output_path = basepath + ".osrm.icd";
|
||||||
@ -95,12 +97,14 @@ struct ExtractorConfig
|
|||||||
std::string rtree_leafs_output_path;
|
std::string rtree_leafs_output_path;
|
||||||
std::string profile_properties_output_path;
|
std::string profile_properties_output_path;
|
||||||
std::string intersection_class_data_output_path;
|
std::string intersection_class_data_output_path;
|
||||||
|
std::string turn_weight_penalties_path;
|
||||||
|
std::string turn_duration_penalties_path;
|
||||||
|
|
||||||
unsigned requested_num_threads;
|
unsigned requested_num_threads;
|
||||||
unsigned small_component_size;
|
unsigned small_component_size;
|
||||||
|
|
||||||
bool generate_edge_lookup;
|
bool generate_edge_lookup;
|
||||||
std::string edge_penalty_path;
|
std::string turn_penalties_index_path;
|
||||||
std::string edge_segment_lookup_path;
|
std::string edge_segment_lookup_path;
|
||||||
|
|
||||||
bool use_metadata;
|
bool use_metadata;
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
#ifndef INTERNAL_EXTRACTOR_EDGE_HPP
|
#ifndef INTERNAL_EXTRACTOR_EDGE_HPP
|
||||||
#define INTERNAL_EXTRACTOR_EDGE_HPP
|
#define INTERNAL_EXTRACTOR_EDGE_HPP
|
||||||
|
|
||||||
|
#include "extractor/guidance/road_classification.hpp"
|
||||||
|
#include "extractor/guidance/turn_lane_types.hpp"
|
||||||
#include "extractor/node_based_edge.hpp"
|
#include "extractor/node_based_edge.hpp"
|
||||||
#include "extractor/travel_mode.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
|
#include "osrm/coordinate.hpp"
|
||||||
|
#include "util/strong_typedef.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <mapbox/variant.hpp>
|
||||||
#include "extractor/guidance/road_classification.hpp"
|
|
||||||
#include "extractor/guidance/turn_lane_types.hpp"
|
|
||||||
#include "osrm/coordinate.hpp"
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@ -17,31 +18,37 @@ namespace osrm
|
|||||||
namespace extractor
|
namespace extractor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
// these are used for duration based mode of transportations like ferries
|
||||||
|
OSRM_STRONG_TYPEDEF(double, ValueByEdge)
|
||||||
|
OSRM_STRONG_TYPEDEF(double, ValueByMeter)
|
||||||
|
using ByEdgeOrByMeterValue = mapbox::util::variant<detail::ValueByEdge, detail::ValueByMeter>;
|
||||||
|
|
||||||
|
struct ToValueByEdge
|
||||||
|
{
|
||||||
|
ToValueByEdge(double distance_) : distance(distance_) {}
|
||||||
|
|
||||||
|
ValueByEdge operator()(const ValueByMeter by_meter) const
|
||||||
|
{
|
||||||
|
return ValueByEdge{distance / static_cast<double>(by_meter)};
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueByEdge operator()(const ValueByEdge by_edge) const { return by_edge; }
|
||||||
|
|
||||||
|
double distance;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
struct InternalExtractorEdge
|
struct InternalExtractorEdge
|
||||||
{
|
{
|
||||||
// specify the type of the weight data
|
using WeightData = detail::ByEdgeOrByMeterValue;
|
||||||
enum class WeightType : char
|
using DurationData = detail::ByEdgeOrByMeterValue;
|
||||||
{
|
|
||||||
INVALID,
|
|
||||||
SPEED,
|
|
||||||
EDGE_DURATION,
|
|
||||||
WAY_DURATION,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WeightData
|
|
||||||
{
|
|
||||||
WeightData() : duration(0.0), type(WeightType::INVALID) {}
|
|
||||||
|
|
||||||
union {
|
|
||||||
double duration;
|
|
||||||
double speed;
|
|
||||||
};
|
|
||||||
WeightType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit InternalExtractorEdge()
|
explicit InternalExtractorEdge()
|
||||||
: result(MIN_OSM_NODEID,
|
: result(MIN_OSM_NODEID,
|
||||||
MIN_OSM_NODEID,
|
MIN_OSM_NODEID,
|
||||||
|
SPECIAL_NODEID,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
false, // forward
|
false, // forward
|
||||||
@ -52,7 +59,8 @@ struct InternalExtractorEdge
|
|||||||
TRAVEL_MODE_INACCESSIBLE,
|
TRAVEL_MODE_INACCESSIBLE,
|
||||||
false,
|
false,
|
||||||
guidance::TurnLaneType::empty,
|
guidance::TurnLaneType::empty,
|
||||||
guidance::RoadClassification())
|
guidance::RoadClassification()),
|
||||||
|
weight_data(detail::ValueByMeter{0.0}), duration_data(detail::ValueByMeter{0.0})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +68,7 @@ struct InternalExtractorEdge
|
|||||||
OSMNodeID target,
|
OSMNodeID target,
|
||||||
NodeID name_id,
|
NodeID name_id,
|
||||||
WeightData weight_data,
|
WeightData weight_data,
|
||||||
|
DurationData duration_data,
|
||||||
bool forward,
|
bool forward,
|
||||||
bool backward,
|
bool backward,
|
||||||
bool roundabout,
|
bool roundabout,
|
||||||
@ -68,11 +77,13 @@ struct InternalExtractorEdge
|
|||||||
TravelMode travel_mode,
|
TravelMode travel_mode,
|
||||||
bool is_split,
|
bool is_split,
|
||||||
LaneDescriptionID lane_description,
|
LaneDescriptionID lane_description,
|
||||||
guidance::RoadClassification road_classification)
|
guidance::RoadClassification road_classification,
|
||||||
|
util::Coordinate source_coordinate)
|
||||||
: result(source,
|
: result(source,
|
||||||
target,
|
target,
|
||||||
name_id,
|
name_id,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
forward,
|
forward,
|
||||||
backward,
|
backward,
|
||||||
roundabout,
|
roundabout,
|
||||||
@ -82,7 +93,8 @@ struct InternalExtractorEdge
|
|||||||
is_split,
|
is_split,
|
||||||
lane_description,
|
lane_description,
|
||||||
std::move(road_classification)),
|
std::move(road_classification)),
|
||||||
weight_data(std::move(weight_data))
|
weight_data(std::move(weight_data)), duration_data(std::move(duration_data)),
|
||||||
|
source_coordinate(std::move(source_coordinate))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +102,8 @@ struct InternalExtractorEdge
|
|||||||
NodeBasedEdgeWithOSM result;
|
NodeBasedEdgeWithOSM result;
|
||||||
// intermediate edge weight
|
// intermediate edge weight
|
||||||
WeightData weight_data;
|
WeightData weight_data;
|
||||||
|
// intermediate edge duration
|
||||||
|
DurationData duration_data;
|
||||||
// coordinate of the source node
|
// coordinate of the source node
|
||||||
util::Coordinate source_coordinate;
|
util::Coordinate source_coordinate;
|
||||||
|
|
||||||
@ -98,8 +112,9 @@ struct InternalExtractorEdge
|
|||||||
{
|
{
|
||||||
return InternalExtractorEdge(MIN_OSM_NODEID,
|
return InternalExtractorEdge(MIN_OSM_NODEID,
|
||||||
MIN_OSM_NODEID,
|
MIN_OSM_NODEID,
|
||||||
0,
|
SPECIAL_NODEID,
|
||||||
WeightData(),
|
detail::ValueByMeter{0.0},
|
||||||
|
detail::ValueByMeter{0.0},
|
||||||
false, // forward
|
false, // forward
|
||||||
false, // backward
|
false, // backward
|
||||||
false, // roundabout
|
false, // roundabout
|
||||||
@ -108,14 +123,16 @@ struct InternalExtractorEdge
|
|||||||
TRAVEL_MODE_INACCESSIBLE,
|
TRAVEL_MODE_INACCESSIBLE,
|
||||||
false,
|
false,
|
||||||
INVALID_LANE_DESCRIPTIONID,
|
INVALID_LANE_DESCRIPTIONID,
|
||||||
guidance::RoadClassification());
|
guidance::RoadClassification(),
|
||||||
|
util::Coordinate());
|
||||||
}
|
}
|
||||||
static InternalExtractorEdge max_osm_value()
|
static InternalExtractorEdge max_osm_value()
|
||||||
{
|
{
|
||||||
return InternalExtractorEdge(MAX_OSM_NODEID,
|
return InternalExtractorEdge(MAX_OSM_NODEID,
|
||||||
MAX_OSM_NODEID,
|
MAX_OSM_NODEID,
|
||||||
SPECIAL_NODEID,
|
SPECIAL_NODEID,
|
||||||
WeightData(),
|
detail::ValueByMeter{0.0},
|
||||||
|
detail::ValueByMeter{0.0},
|
||||||
false, // forward
|
false, // forward
|
||||||
false, // backward
|
false, // backward
|
||||||
false, // roundabout
|
false, // roundabout
|
||||||
@ -124,7 +141,8 @@ struct InternalExtractorEdge
|
|||||||
TRAVEL_MODE_INACCESSIBLE,
|
TRAVEL_MODE_INACCESSIBLE,
|
||||||
false,
|
false,
|
||||||
INVALID_LANE_DESCRIPTIONID,
|
INVALID_LANE_DESCRIPTIONID,
|
||||||
guidance::RoadClassification());
|
guidance::RoadClassification(),
|
||||||
|
util::Coordinate());
|
||||||
}
|
}
|
||||||
|
|
||||||
static InternalExtractorEdge min_internal_value()
|
static InternalExtractorEdge min_internal_value()
|
||||||
|
@ -19,6 +19,7 @@ struct NodeBasedEdge
|
|||||||
NodeID target,
|
NodeID target,
|
||||||
NodeID name_id,
|
NodeID name_id,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
|
EdgeWeight duration,
|
||||||
bool forward,
|
bool forward,
|
||||||
bool backward,
|
bool backward,
|
||||||
bool roundabout,
|
bool roundabout,
|
||||||
@ -35,12 +36,13 @@ struct NodeBasedEdge
|
|||||||
NodeID target;
|
NodeID target;
|
||||||
NodeID name_id;
|
NodeID name_id;
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
bool forward : 1;
|
EdgeWeight duration;
|
||||||
bool backward : 1;
|
std::uint8_t forward : 1;
|
||||||
bool roundabout : 1;
|
std::uint8_t backward : 1;
|
||||||
bool circular : 1;
|
std::uint8_t roundabout : 1;
|
||||||
bool startpoint : 1;
|
std::uint8_t circular : 1;
|
||||||
bool is_split : 1;
|
std::uint8_t startpoint : 1;
|
||||||
|
std::uint8_t is_split : 1;
|
||||||
TravelMode travel_mode : 4;
|
TravelMode travel_mode : 4;
|
||||||
LaneDescriptionID lane_description_id;
|
LaneDescriptionID lane_description_id;
|
||||||
guidance::RoadClassification road_classification;
|
guidance::RoadClassification road_classification;
|
||||||
@ -52,6 +54,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
|
|||||||
OSMNodeID target,
|
OSMNodeID target,
|
||||||
NodeID name_id,
|
NodeID name_id,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
|
EdgeWeight duration,
|
||||||
bool forward,
|
bool forward,
|
||||||
bool backward,
|
bool backward,
|
||||||
bool roundabout,
|
bool roundabout,
|
||||||
@ -69,9 +72,10 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
|
|||||||
// Impl.
|
// Impl.
|
||||||
|
|
||||||
inline NodeBasedEdge::NodeBasedEdge()
|
inline NodeBasedEdge::NodeBasedEdge()
|
||||||
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), forward(false),
|
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), duration(0),
|
||||||
backward(false), roundabout(false), circular(false), startpoint(true), is_split(false),
|
forward(false), backward(false), roundabout(false), circular(false), startpoint(true),
|
||||||
travel_mode(false), lane_description_id(INVALID_LANE_DESCRIPTIONID)
|
is_split(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||||
|
lane_description_id(INVALID_LANE_DESCRIPTIONID)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +83,7 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
|
|||||||
NodeID target,
|
NodeID target,
|
||||||
NodeID name_id,
|
NodeID name_id,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
|
EdgeWeight duration,
|
||||||
bool forward,
|
bool forward,
|
||||||
bool backward,
|
bool backward,
|
||||||
bool roundabout,
|
bool roundabout,
|
||||||
@ -88,10 +93,10 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
|
|||||||
bool is_split,
|
bool is_split,
|
||||||
const LaneDescriptionID lane_description_id,
|
const LaneDescriptionID lane_description_id,
|
||||||
guidance::RoadClassification road_classification)
|
guidance::RoadClassification road_classification)
|
||||||
: source(source), target(target), name_id(name_id), weight(weight), forward(forward),
|
: source(source), target(target), name_id(name_id), weight(weight), duration(duration),
|
||||||
backward(backward), roundabout(roundabout), circular(circular), startpoint(startpoint),
|
forward(forward), backward(backward), roundabout(roundabout), circular(circular),
|
||||||
is_split(is_split), travel_mode(travel_mode), lane_description_id(lane_description_id),
|
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode),
|
||||||
road_classification(std::move(road_classification))
|
lane_description_id(lane_description_id), road_classification(std::move(road_classification))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +121,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
|||||||
OSMNodeID target,
|
OSMNodeID target,
|
||||||
NodeID name_id,
|
NodeID name_id,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
|
EdgeWeight duration,
|
||||||
bool forward,
|
bool forward,
|
||||||
bool backward,
|
bool backward,
|
||||||
bool roundabout,
|
bool roundabout,
|
||||||
@ -129,6 +135,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
|||||||
SPECIAL_NODEID,
|
SPECIAL_NODEID,
|
||||||
name_id,
|
name_id,
|
||||||
weight,
|
weight,
|
||||||
|
duration,
|
||||||
forward,
|
forward,
|
||||||
backward,
|
backward,
|
||||||
roundabout,
|
roundabout,
|
||||||
@ -142,6 +149,11 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assert(sizeof(extractor::NodeBasedEdge) == 28,
|
||||||
|
"Size of extractor::NodeBasedEdge type is "
|
||||||
|
"bigger than expected. This will influence "
|
||||||
|
"memory consumption.");
|
||||||
|
|
||||||
} // ns extractor
|
} // ns extractor
|
||||||
} // ns osrm
|
} // ns osrm
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef PROFILE_PROPERTIES_HPP
|
#ifndef PROFILE_PROPERTIES_HPP
|
||||||
#define PROFILE_PROPERTIES_HPP
|
#define PROFILE_PROPERTIES_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/numeric/conversion/cast.hpp>
|
#include <boost/numeric/conversion/cast.hpp>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@ -12,11 +14,18 @@ const constexpr auto DEFAULT_MAX_SPEED = 180 / 3.6; // 180kmph -> m/s
|
|||||||
|
|
||||||
struct ProfileProperties
|
struct ProfileProperties
|
||||||
{
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MAX_WEIGHT_NAME_LENGTH = 255
|
||||||
|
};
|
||||||
|
|
||||||
ProfileProperties()
|
ProfileProperties()
|
||||||
: traffic_signal_penalty(0), u_turn_penalty(0),
|
: traffic_signal_penalty(0), u_turn_penalty(0),
|
||||||
max_speed_for_map_matching(DEFAULT_MAX_SPEED), continue_straight_at_waypoint(true),
|
max_speed_for_map_matching(DEFAULT_MAX_SPEED), continue_straight_at_waypoint(true),
|
||||||
use_turn_restrictions(false), left_hand_driving(false)
|
use_turn_restrictions(false), left_hand_driving(false), fallback_to_duration(true),
|
||||||
|
weight_name{"duration"}
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(weight_name[MAX_WEIGHT_NAME_LENGTH] == '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetUturnPenalty() const { return u_turn_penalty / 10.; }
|
double GetUturnPenalty() const { return u_turn_penalty / 10.; }
|
||||||
@ -40,14 +49,38 @@ struct ProfileProperties
|
|||||||
max_speed_for_map_matching = max_speed_for_map_matching_;
|
max_speed_for_map_matching = max_speed_for_map_matching_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetWeightName(const std::string &name)
|
||||||
|
{
|
||||||
|
auto count = std::min<std::size_t>(name.length(), MAX_WEIGHT_NAME_LENGTH) + 1;
|
||||||
|
std::copy_n(name.c_str(), count, weight_name);
|
||||||
|
// Make sure this is always zero terminated
|
||||||
|
BOOST_ASSERT(weight_name[count - 1] == '\0');
|
||||||
|
BOOST_ASSERT(weight_name[MAX_WEIGHT_NAME_LENGTH] == '\0');
|
||||||
|
// Set lazy fallback flag
|
||||||
|
fallback_to_duration = name == "duration";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetWeightName() const
|
||||||
|
{
|
||||||
|
// Make sure this is always zero terminated
|
||||||
|
BOOST_ASSERT(weight_name[MAX_WEIGHT_NAME_LENGTH] == '\0');
|
||||||
|
return std::string(weight_name);
|
||||||
|
}
|
||||||
|
|
||||||
//! penalty to cross a traffic light in deci-seconds
|
//! penalty to cross a traffic light in deci-seconds
|
||||||
int traffic_signal_penalty;
|
std::int32_t traffic_signal_penalty;
|
||||||
//! penalty to do a uturn in deci-seconds
|
//! penalty to do a uturn in deci-seconds
|
||||||
int u_turn_penalty;
|
std::int32_t u_turn_penalty;
|
||||||
double max_speed_for_map_matching;
|
double max_speed_for_map_matching;
|
||||||
|
//! depending on the profile, force the routing to always continue in the same direction
|
||||||
bool continue_straight_at_waypoint;
|
bool continue_straight_at_waypoint;
|
||||||
|
//! flag used for restriction parser (e.g. used for the walk profile)
|
||||||
bool use_turn_restrictions;
|
bool use_turn_restrictions;
|
||||||
bool left_hand_driving;
|
bool left_hand_driving;
|
||||||
|
bool fallback_to_duration;
|
||||||
|
//! stores the name of the weight (e.g. 'duration', 'distance', 'safety')
|
||||||
|
char weight_name[MAX_WEIGHT_NAME_LENGTH + 1];
|
||||||
|
unsigned weight_precision = 1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ namespace extractor
|
|||||||
class RestrictionParser;
|
class RestrictionParser;
|
||||||
struct ExtractionNode;
|
struct ExtractionNode;
|
||||||
struct ExtractionWay;
|
struct ExtractionWay;
|
||||||
|
struct ExtractionTurn;
|
||||||
|
struct ExtractionSegment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class that handles processing osmium ways, nodes and relation objects by applying
|
* Abstract class that handles processing osmium ways, nodes and relation objects by applying
|
||||||
@ -53,11 +55,9 @@ class ScriptingEnvironment
|
|||||||
virtual std::vector<std::string> GetNameSuffixList() = 0;
|
virtual std::vector<std::string> GetNameSuffixList() = 0;
|
||||||
virtual std::vector<std::string> GetRestrictions() = 0;
|
virtual std::vector<std::string> GetRestrictions() = 0;
|
||||||
virtual void SetupSources() = 0;
|
virtual void SetupSources() = 0;
|
||||||
virtual int32_t GetTurnPenalty(double angle) = 0;
|
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
|
||||||
virtual void ProcessSegment(const osrm::util::Coordinate &source,
|
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
|
||||||
const osrm::util::Coordinate &target,
|
|
||||||
double distance,
|
|
||||||
InternalExtractorEdge::WeightData &weight) = 0;
|
|
||||||
virtual void
|
virtual void
|
||||||
ProcessElements(const std::vector<osmium::memory::Buffer::const_iterator> &osm_elements,
|
ProcessElements(const std::vector<osmium::memory::Buffer::const_iterator> &osm_elements,
|
||||||
const RestrictionParser &restriction_parser,
|
const RestrictionParser &restriction_parser,
|
||||||
|
@ -45,7 +45,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const constexpr int SUPPORTED_MIN_API_VERSION = 0;
|
static const constexpr int SUPPORTED_MIN_API_VERSION = 0;
|
||||||
static const constexpr int SUPPORTED_MAX_API_VERSION = 0;
|
static const constexpr int SUPPORTED_MAX_API_VERSION = 1;
|
||||||
|
|
||||||
explicit Sol2ScriptingEnvironment(const std::string &file_name);
|
explicit Sol2ScriptingEnvironment(const std::string &file_name);
|
||||||
~Sol2ScriptingEnvironment() override = default;
|
~Sol2ScriptingEnvironment() override = default;
|
||||||
@ -57,11 +57,9 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
|
|||||||
std::vector<std::string> GetNameSuffixList() override;
|
std::vector<std::string> GetNameSuffixList() override;
|
||||||
std::vector<std::string> GetRestrictions() override;
|
std::vector<std::string> GetRestrictions() override;
|
||||||
void SetupSources() override;
|
void SetupSources() override;
|
||||||
int32_t GetTurnPenalty(double angle) override;
|
void ProcessTurn(ExtractionTurn &turn) override;
|
||||||
void ProcessSegment(const osrm::util::Coordinate &source,
|
void ProcessSegment(ExtractionSegment &segment) override;
|
||||||
const osrm::util::Coordinate &target,
|
|
||||||
double distance,
|
|
||||||
InternalExtractorEdge::WeightData &weight) override;
|
|
||||||
void
|
void
|
||||||
ProcessElements(const std::vector<osmium::memory::Buffer::const_iterator> &osm_elements,
|
ProcessElements(const std::vector<osmium::memory::Buffer::const_iterator> &osm_elements,
|
||||||
const RestrictionParser &restriction_parser,
|
const RestrictionParser &restriction_parser,
|
||||||
|
@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef TRAVEL_MODE_HPP
|
#ifndef TRAVEL_MODE_HPP
|
||||||
#define TRAVEL_MODE_HPP
|
#define TRAVEL_MODE_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace extractor
|
namespace extractor
|
||||||
@ -35,7 +37,7 @@ namespace extractor
|
|||||||
|
|
||||||
// This is a char instead of a typed enum, so that we can
|
// This is a char instead of a typed enum, so that we can
|
||||||
// pack it into e.g. a "TravelMode mode : 4" packed bitfield
|
// pack it into e.g. a "TravelMode mode : 4" packed bitfield
|
||||||
using TravelMode = unsigned char;
|
using TravelMode = std::uint8_t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "util/exception_utils.hpp"
|
#include "util/exception_utils.hpp"
|
||||||
#include "util/log.hpp"
|
#include "util/log.hpp"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@ -33,6 +35,8 @@ const constexpr char *block_id_to_name[] = {"NAME_OFFSETS",
|
|||||||
"GEOMETRIES_NODE_LIST",
|
"GEOMETRIES_NODE_LIST",
|
||||||
"GEOMETRIES_FWD_WEIGHT_LIST",
|
"GEOMETRIES_FWD_WEIGHT_LIST",
|
||||||
"GEOMETRIES_REV_WEIGHT_LIST",
|
"GEOMETRIES_REV_WEIGHT_LIST",
|
||||||
|
"GEOMETRIES_FWD_DURATION_LIST",
|
||||||
|
"GEOMETRIES_REV_DURATION_LIST",
|
||||||
"HSGR_CHECKSUM",
|
"HSGR_CHECKSUM",
|
||||||
"TIMESTAMP",
|
"TIMESTAMP",
|
||||||
"FILE_INDEX_PATH",
|
"FILE_INDEX_PATH",
|
||||||
@ -52,7 +56,9 @@ const constexpr char *block_id_to_name[] = {"NAME_OFFSETS",
|
|||||||
"POST_TURN_BEARING",
|
"POST_TURN_BEARING",
|
||||||
"TURN_LANE_DATA",
|
"TURN_LANE_DATA",
|
||||||
"LANE_DESCRIPTION_OFFSETS",
|
"LANE_DESCRIPTION_OFFSETS",
|
||||||
"LANE_DESCRIPTION_MASKS"};
|
"LANE_DESCRIPTION_MASKS",
|
||||||
|
"TURN_WEIGHT_PENALTIES",
|
||||||
|
"TURN_DURATION_PENALTIES"};
|
||||||
|
|
||||||
struct DataLayout
|
struct DataLayout
|
||||||
{
|
{
|
||||||
@ -75,6 +81,8 @@ struct DataLayout
|
|||||||
GEOMETRIES_NODE_LIST,
|
GEOMETRIES_NODE_LIST,
|
||||||
GEOMETRIES_FWD_WEIGHT_LIST,
|
GEOMETRIES_FWD_WEIGHT_LIST,
|
||||||
GEOMETRIES_REV_WEIGHT_LIST,
|
GEOMETRIES_REV_WEIGHT_LIST,
|
||||||
|
GEOMETRIES_FWD_DURATION_LIST,
|
||||||
|
GEOMETRIES_REV_DURATION_LIST,
|
||||||
HSGR_CHECKSUM,
|
HSGR_CHECKSUM,
|
||||||
TIMESTAMP,
|
TIMESTAMP,
|
||||||
FILE_INDEX_PATH,
|
FILE_INDEX_PATH,
|
||||||
@ -95,6 +103,8 @@ struct DataLayout
|
|||||||
TURN_LANE_DATA,
|
TURN_LANE_DATA,
|
||||||
LANE_DESCRIPTION_OFFSETS,
|
LANE_DESCRIPTION_OFFSETS,
|
||||||
LANE_DESCRIPTION_MASKS,
|
LANE_DESCRIPTION_MASKS,
|
||||||
|
TURN_WEIGHT_PENALTIES,
|
||||||
|
TURN_DURATION_PENALTIES,
|
||||||
NUM_BLOCKS
|
NUM_BLOCKS
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -127,6 +137,7 @@ struct DataLayout
|
|||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
for (auto i = 0; i < NUM_BLOCKS; i++)
|
for (auto i = 0; i < NUM_BLOCKS; i++)
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(entry_align[i] > 0);
|
||||||
result += 2 * sizeof(CANARY) + GetBlockSize((BlockID)i) + entry_align[i];
|
result += 2 * sizeof(CANARY) + GetBlockSize((BlockID)i) + entry_align[i];
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -60,6 +60,8 @@ struct StorageConfig final
|
|||||||
boost::filesystem::path core_data_path;
|
boost::filesystem::path core_data_path;
|
||||||
boost::filesystem::path geometries_path;
|
boost::filesystem::path geometries_path;
|
||||||
boost::filesystem::path timestamp_path;
|
boost::filesystem::path timestamp_path;
|
||||||
|
boost::filesystem::path turn_weight_penalties_path;
|
||||||
|
boost::filesystem::path turn_duration_penalties_path;
|
||||||
boost::filesystem::path datasource_names_path;
|
boost::filesystem::path datasource_names_path;
|
||||||
boost::filesystem::path datasource_indexes_path;
|
boost::filesystem::path datasource_indexes_path;
|
||||||
boost::filesystem::path names_data_path;
|
boost::filesystem::path names_data_path;
|
||||||
|
@ -12,9 +12,8 @@ namespace util
|
|||||||
{
|
{
|
||||||
|
|
||||||
// implements a singleton, i.e. there is one and only one conviguration object
|
// implements a singleton, i.e. there is one and only one conviguration object
|
||||||
class FingerPrint
|
struct FingerPrint
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
static FingerPrint GetValid();
|
static FingerPrint GetValid();
|
||||||
|
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
@ -36,6 +35,7 @@ class FingerPrint
|
|||||||
|
|
||||||
static_assert(sizeof(FingerPrint) == 8, "FingerPrint has unexpected size");
|
static_assert(sizeof(FingerPrint) == 8, "FingerPrint has unexpected size");
|
||||||
static_assert(std::is_trivial<FingerPrint>::value, "FingerPrint needs to be trivial.");
|
static_assert(std::is_trivial<FingerPrint>::value, "FingerPrint needs to be trivial.");
|
||||||
|
static_assert(std::is_pod<FingerPrint>::value, "FingerPrint needs to be a POD.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,14 +18,15 @@ namespace util
|
|||||||
struct NodeBasedEdgeData
|
struct NodeBasedEdgeData
|
||||||
{
|
{
|
||||||
NodeBasedEdgeData()
|
NodeBasedEdgeData()
|
||||||
: distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID),
|
: weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID),
|
||||||
name_id(std::numeric_limits<unsigned>::max()), reversed(false), roundabout(false),
|
name_id(std::numeric_limits<unsigned>::max()), reversed(false), roundabout(false),
|
||||||
circular(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
circular(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
|
||||||
lane_description_id(INVALID_LANE_DESCRIPTIONID)
|
lane_description_id(INVALID_LANE_DESCRIPTIONID)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeBasedEdgeData(int distance,
|
NodeBasedEdgeData(EdgeWeight weight,
|
||||||
|
EdgeWeight duration,
|
||||||
unsigned edge_id,
|
unsigned edge_id,
|
||||||
unsigned name_id,
|
unsigned name_id,
|
||||||
bool reversed,
|
bool reversed,
|
||||||
@ -34,13 +35,14 @@ struct NodeBasedEdgeData
|
|||||||
bool startpoint,
|
bool startpoint,
|
||||||
extractor::TravelMode travel_mode,
|
extractor::TravelMode travel_mode,
|
||||||
const LaneDescriptionID lane_description_id)
|
const LaneDescriptionID lane_description_id)
|
||||||
: distance(distance), edge_id(edge_id), name_id(name_id), reversed(reversed),
|
: weight(weight), duration(duration), edge_id(edge_id), name_id(name_id),
|
||||||
roundabout(roundabout), circular(circular), startpoint(startpoint),
|
reversed(reversed), roundabout(roundabout), circular(circular), startpoint(startpoint),
|
||||||
travel_mode(travel_mode), lane_description_id(lane_description_id)
|
travel_mode(travel_mode), lane_description_id(lane_description_id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int distance;
|
EdgeWeight weight;
|
||||||
|
EdgeWeight duration;
|
||||||
unsigned edge_id;
|
unsigned edge_id;
|
||||||
unsigned name_id;
|
unsigned name_id;
|
||||||
bool reversed : 1;
|
bool reversed : 1;
|
||||||
@ -78,9 +80,8 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
|
|||||||
input_edge_list,
|
input_edge_list,
|
||||||
[](NodeBasedDynamicGraph::InputEdge &output_edge,
|
[](NodeBasedDynamicGraph::InputEdge &output_edge,
|
||||||
const extractor::NodeBasedEdge &input_edge) {
|
const extractor::NodeBasedEdge &input_edge) {
|
||||||
output_edge.data.distance = static_cast<int>(input_edge.weight);
|
output_edge.data.weight = input_edge.weight;
|
||||||
BOOST_ASSERT(output_edge.data.distance > 0);
|
output_edge.data.duration = input_edge.duration;
|
||||||
|
|
||||||
output_edge.data.roundabout = input_edge.roundabout;
|
output_edge.data.roundabout = input_edge.roundabout;
|
||||||
output_edge.data.circular = input_edge.circular;
|
output_edge.data.circular = input_edge.circular;
|
||||||
output_edge.data.name_id = input_edge.name_id;
|
output_edge.data.name_id = input_edge.name_id;
|
||||||
@ -88,6 +89,9 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
|
|||||||
output_edge.data.startpoint = input_edge.startpoint;
|
output_edge.data.startpoint = input_edge.startpoint;
|
||||||
output_edge.data.road_classification = input_edge.road_classification;
|
output_edge.data.road_classification = input_edge.road_classification;
|
||||||
output_edge.data.lane_description_id = input_edge.lane_description_id;
|
output_edge.data.lane_description_id = input_edge.lane_description_id;
|
||||||
|
|
||||||
|
BOOST_ASSERT(output_edge.data.weight > 0);
|
||||||
|
BOOST_ASSERT(output_edge.data.duration > 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
||||||
|
@ -58,6 +58,7 @@ using NodeID = std::uint32_t;
|
|||||||
using EdgeID = std::uint32_t;
|
using EdgeID = std::uint32_t;
|
||||||
using NameID = std::uint32_t;
|
using NameID = std::uint32_t;
|
||||||
using EdgeWeight = std::int32_t;
|
using EdgeWeight = std::int32_t;
|
||||||
|
using TurnPenalty = std::int16_t; // turn penalty in 100ms units
|
||||||
|
|
||||||
using LaneID = std::uint8_t;
|
using LaneID = std::uint8_t;
|
||||||
static const LaneID INVALID_LANEID = std::numeric_limits<LaneID>::max();
|
static const LaneID INVALID_LANEID = std::numeric_limits<LaneID>::max();
|
||||||
@ -83,6 +84,7 @@ static const NameID INVALID_NAMEID = std::numeric_limits<NameID>::max();
|
|||||||
static const NameID EMPTY_NAMEID = 0;
|
static const NameID EMPTY_NAMEID = 0;
|
||||||
static const unsigned INVALID_COMPONENTID = 0;
|
static const unsigned INVALID_COMPONENTID = 0;
|
||||||
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
|
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
|
||||||
|
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
|
||||||
|
|
||||||
using DatasourceID = std::uint8_t;
|
using DatasourceID = std::uint8_t;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
api_version = 0
|
api_version = 1
|
||||||
|
|
||||||
-- Bicycle profile
|
-- Bicycle profile
|
||||||
|
|
||||||
@ -92,14 +92,16 @@ surface_speeds = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- these need to be global because they are accesed externaly
|
-- these need to be global because they are accesed externaly
|
||||||
properties.traffic_signal_penalty = 2
|
|
||||||
properties.u_turn_penalty = 20
|
|
||||||
properties.max_speed_for_map_matching = 110/3.6 -- kmph -> m/s
|
properties.max_speed_for_map_matching = 110/3.6 -- kmph -> m/s
|
||||||
properties.use_turn_restrictions = false
|
properties.use_turn_restrictions = false
|
||||||
properties.continue_straight_at_waypoint = false
|
properties.continue_straight_at_waypoint = false
|
||||||
|
properties.weight_name = 'duration'
|
||||||
|
--properties.weight_name = 'cyclability'
|
||||||
|
|
||||||
local obey_oneway = true
|
local obey_oneway = true
|
||||||
local ignore_areas = true
|
local ignore_areas = true
|
||||||
|
local traffic_light_penalty = 2
|
||||||
|
local u_turn_penalty = 20
|
||||||
local turn_penalty = 6
|
local turn_penalty = 6
|
||||||
local turn_bias = 1.4
|
local turn_bias = 1.4
|
||||||
-- reduce the driving speed by 30% for unsafe roads
|
-- reduce the driving speed by 30% for unsafe roads
|
||||||
@ -272,10 +274,6 @@ function way_function (way, result)
|
|||||||
-- regular ways
|
-- regular ways
|
||||||
result.forward_speed = bicycle_speeds[highway]
|
result.forward_speed = bicycle_speeds[highway]
|
||||||
result.backward_speed = bicycle_speeds[highway]
|
result.backward_speed = bicycle_speeds[highway]
|
||||||
if safety_penalty < 1 and unsafe_highway_list[highway] then
|
|
||||||
result.forward_speed = result.forward_speed * safety_penalty
|
|
||||||
result.backward_speed = result.backward_speed * safety_penalty
|
|
||||||
end
|
|
||||||
elseif access and access_tag_whitelist[access] then
|
elseif access and access_tag_whitelist[access] then
|
||||||
-- unknown way, but valid access tag
|
-- unknown way, but valid access tag
|
||||||
result.forward_speed = default_speed
|
result.forward_speed = default_speed
|
||||||
@ -399,15 +397,45 @@ function way_function (way, result)
|
|||||||
|
|
||||||
-- maxspeed
|
-- maxspeed
|
||||||
limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
|
limit( result, maxspeed, maxspeed_forward, maxspeed_backward )
|
||||||
end
|
|
||||||
|
|
||||||
function turn_function (angle)
|
-- convert duration into cyclability
|
||||||
-- compute turn penalty as angle^2, with a left/right bias
|
local is_unsafe = safety_penalty < 1 and unsafe_highway_list[highway]
|
||||||
-- multiplying by 10 converts to deci-seconds see issue #1318
|
if result.forward_speed > 0 then
|
||||||
k = 10*turn_penalty/(90.0*90.0)
|
-- convert from km/h to m/s
|
||||||
if angle>=0 then
|
result.forward_rate = result.forward_speed / 3.6;
|
||||||
return angle*angle*k/turn_bias
|
if is_unsafe then
|
||||||
else
|
result.forward_rate = result.forward_rate * safety_penalty
|
||||||
return angle*angle*k*turn_bias
|
end
|
||||||
|
end
|
||||||
|
if result.backward_speed > 0 then
|
||||||
|
-- convert from km/h to m/s
|
||||||
|
result.backward_rate = result.backward_speed / 3.6;
|
||||||
|
if is_unsafe then
|
||||||
|
result.backward_rate = result.backward_rate * safety_penalty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if result.duration > 0 then
|
||||||
|
result.weight = result.duration;
|
||||||
|
if is_unsafe then
|
||||||
|
result.weight = result.weight * (1+safety_penalty)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function turn_function(turn)
|
||||||
|
-- compute turn penalty as angle^2, with a left/right bias
|
||||||
|
local normalized_angle = turn.angle / 90.0
|
||||||
|
if normalized_angle >= 0.0 then
|
||||||
|
turn.duration = normalized_angle * normalized_angle * turn_penalty / turn_bias
|
||||||
|
else
|
||||||
|
turn.duration = normalized_angle * normalized_angle * turn_penalty * turn_bias
|
||||||
|
end
|
||||||
|
|
||||||
|
if turn.direction_modifier == direction_modifier.uturn then
|
||||||
|
turn.duration = turn.duration + u_turn_penalty
|
||||||
|
end
|
||||||
|
|
||||||
|
if turn.has_traffic_light then
|
||||||
|
turn.duration = turn.duration + traffic_light_penalty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
api_version = 0
|
api_version = 1
|
||||||
|
|
||||||
-- Car profile
|
-- Car profile
|
||||||
local find_access_tag = require("lib/access").find_access_tag
|
local find_access_tag = require("lib/access").find_access_tag
|
||||||
@ -190,16 +190,19 @@ maxspeed_table = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- set profile properties
|
-- set profile properties
|
||||||
properties.u_turn_penalty = 20
|
|
||||||
properties.traffic_signal_penalty = 2
|
|
||||||
properties.max_speed_for_map_matching = 180/3.6 -- 180kmph -> m/s
|
properties.max_speed_for_map_matching = 180/3.6 -- 180kmph -> m/s
|
||||||
properties.use_turn_restrictions = true
|
properties.use_turn_restrictions = true
|
||||||
properties.continue_straight_at_waypoint = true
|
properties.continue_straight_at_waypoint = true
|
||||||
properties.left_hand_driving = false
|
properties.left_hand_driving = false
|
||||||
|
-- this will use the duration and {forward/backward}_speed values as weight
|
||||||
|
properties.weight_name = 'duration'
|
||||||
|
--properties.weight_name = 'distance'
|
||||||
|
|
||||||
local side_road_speed_multiplier = 0.8
|
local side_road_speed_multiplier = 0.8
|
||||||
|
|
||||||
local turn_penalty = 7.5
|
local turn_penalty = 7.5
|
||||||
|
local traffic_light_penalty = 2
|
||||||
|
local u_turn_penalty = 20
|
||||||
|
|
||||||
-- Note: this biases right-side driving. Should be
|
-- Note: this biases right-side driving. Should be
|
||||||
-- inverted for left-driving countries.
|
-- inverted for left-driving countries.
|
||||||
local turn_bias = properties.left_hand_driving and 1/1.075 or 1.075
|
local turn_bias = properties.left_hand_driving and 1/1.075 or 1.075
|
||||||
@ -456,8 +459,7 @@ end
|
|||||||
-- reduce speed on special side roads
|
-- reduce speed on special side roads
|
||||||
function handle_side_roads(way,result)
|
function handle_side_roads(way,result)
|
||||||
local sideway = way:get_value_by_key("side_road")
|
local sideway = way:get_value_by_key("side_road")
|
||||||
if "yes" == sideway or
|
if "yes" == sideway or "rotary" == sideway then
|
||||||
"rotary" == sideway then
|
|
||||||
result.forward_speed = result.forward_speed * side_road_speed_multiplier
|
result.forward_speed = result.forward_speed * side_road_speed_multiplier
|
||||||
result.backward_speed = result.backward_speed * side_road_speed_multiplier
|
result.backward_speed = result.backward_speed * side_road_speed_multiplier
|
||||||
end
|
end
|
||||||
@ -728,14 +730,30 @@ function way_function(way, result)
|
|||||||
if handle_names(way,result) == false then return end
|
if handle_names(way,result) == false then return end
|
||||||
end
|
end
|
||||||
|
|
||||||
function turn_function (angle)
|
function turn_function (turn)
|
||||||
-- Use a sigmoid function to return a penalty that maxes out at turn_penalty
|
-- Use a sigmoid function to return a penalty that maxes out at turn_penalty
|
||||||
-- over the space of 0-180 degrees. Values here were chosen by fitting
|
-- over the space of 0-180 degrees. Values here were chosen by fitting
|
||||||
-- the function to some turn penalty samples from real driving.
|
-- the function to some turn penalty samples from real driving.
|
||||||
-- multiplying by 10 converts to deci-seconds see issue #1318
|
if turn.turn_type ~= turn_type.no_turn then
|
||||||
if angle>=0 then
|
if turn.angle >= 0 then
|
||||||
return 10 * turn_penalty / (1 + 2.718 ^ - ((13 / turn_bias) * angle/180 - 6.5*turn_bias))
|
turn.duration = turn_penalty / (1 + math.exp( -((13 / turn_bias) * turn.angle/180 - 6.5*turn_bias)))
|
||||||
else
|
else
|
||||||
return 10 * turn_penalty / (1 + 2.718 ^ - ((13 * turn_bias) * - angle/180 - 6.5/turn_bias))
|
turn.duration = turn_penalty / (1 + math.exp( -((13 * turn_bias) * -turn.angle/180 - 6.5/turn_bias)))
|
||||||
|
end
|
||||||
|
|
||||||
|
if turn.direction_modifier == direction_modifier.u_turn then
|
||||||
|
turn.duration = turn.duration + u_turn_penalty
|
||||||
|
end
|
||||||
|
|
||||||
|
if turn.has_traffic_light then
|
||||||
|
turn.duration = turn.duration + traffic_light_penalty
|
||||||
|
end
|
||||||
|
|
||||||
|
-- for distance based routing we don't want to have penalties based on turn angle
|
||||||
|
if properties.weight_name == 'distance' then
|
||||||
|
turn.weight = 0
|
||||||
|
else
|
||||||
|
turn.weight = turn.duration
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -36,7 +36,6 @@ obey_oneway = true
|
|||||||
use_restrictions = true
|
use_restrictions = true
|
||||||
ignore_areas = true -- future feature
|
ignore_areas = true -- future feature
|
||||||
traffic_signal_penalty = 7 -- seconds
|
traffic_signal_penalty = 7 -- seconds
|
||||||
u_turn_penalty = 20
|
|
||||||
|
|
||||||
-- nodes processing, called from OSRM
|
-- nodes processing, called from OSRM
|
||||||
function node_function(node)
|
function node_function(node)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
api_version = 0
|
api_version = 1
|
||||||
|
|
||||||
-- Foot profile
|
-- Foot profile
|
||||||
local find_access_tag = require("lib/access").find_access_tag
|
local find_access_tag = require("lib/access").find_access_tag
|
||||||
@ -103,11 +103,13 @@ leisure_speeds = {
|
|||||||
track = walking_speed
|
track = walking_speed
|
||||||
}
|
}
|
||||||
|
|
||||||
properties.traffic_signal_penalty = 2
|
|
||||||
properties.u_turn_penalty = 2
|
|
||||||
properties.max_speed_for_map_matching = 40/3.6 -- kmph -> m/s
|
properties.max_speed_for_map_matching = 40/3.6 -- kmph -> m/s
|
||||||
properties.use_turn_restrictions = false
|
properties.use_turn_restrictions = false
|
||||||
properties.continue_straight_at_waypoint = false
|
properties.continue_straight_at_waypoint = false
|
||||||
|
properties.weight_name = 'duration'
|
||||||
|
|
||||||
|
local traffic_light_penalty = 2
|
||||||
|
local u_turn_penalty = 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -497,3 +499,15 @@ function way_function(way, result)
|
|||||||
-- set name, ref and pronunciation
|
-- set name, ref and pronunciation
|
||||||
if handle_names(way,result) == false then return end
|
if handle_names(way,result) == false then return end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function turn_function (turn)
|
||||||
|
turn.duration = 0.
|
||||||
|
|
||||||
|
if turn.direction_modifier == direction_modifier.u_turn then
|
||||||
|
turn.duration = turn.duration + u_turn_penalty
|
||||||
|
end
|
||||||
|
|
||||||
|
if turn.has_traffic_light then
|
||||||
|
turn.duration = traffic_light_penalty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
api_version = 0
|
api_version = 1
|
||||||
-- Rasterbot profile
|
-- Rasterbot profile
|
||||||
|
|
||||||
-- Minimalist node_ and way_functions in order to test source_ and segment_functions
|
-- Minimalist node_ and way_functions in order to test source_ and segment_functions
|
||||||
@ -37,18 +37,25 @@ function source_function ()
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function segment_function (source, target, distance, weight)
|
function segment_function (segment)
|
||||||
local sourceData = sources:query(raster_source, source.lon, source.lat)
|
local sourceData = sources:query(raster_source, segment.source.lon, segment.source.lat)
|
||||||
local targetData = sources:query(raster_source, target.lon, target.lat)
|
local targetData = sources:query(raster_source, segment.target.lon, segment.target.lat)
|
||||||
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
||||||
local invalid = sourceData.invalid_data()
|
local invalid = sourceData.invalid_data()
|
||||||
|
local scaled_weight = segment.weight
|
||||||
|
local scaled_duration = segment.duration
|
||||||
|
|
||||||
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
||||||
local slope = math.abs(sourceData.datum - targetData.datum) / distance
|
local slope = math.abs(sourceData.datum - targetData.datum) / segment.distance
|
||||||
|
scaled_weight = scaled_weight / (1.0 - (slope * 5.0))
|
||||||
|
scaled_duration = scaled_duration / (1.0 - (slope * 5.0))
|
||||||
io.write(" slope: " .. slope .. "\n")
|
io.write(" slope: " .. slope .. "\n")
|
||||||
io.write(" was speed: " .. weight.speed .. "\n")
|
io.write(" was weight: " .. segment.weight .. "\n")
|
||||||
|
io.write(" new weight: " .. scaled_weight .. "\n")
|
||||||
weight.speed = weight.speed * (1 - (slope * 5))
|
io.write(" was duration: " .. segment.duration .. "\n")
|
||||||
io.write(" new speed: " .. weight.speed .. "\n")
|
io.write(" new duration: " .. scaled_duration .. "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
segment.weight = scaled_weight
|
||||||
|
segment.duration = scaled_duration
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
api_version = 0
|
api_version = 1
|
||||||
-- Rasterbot profile
|
-- Rasterbot profile
|
||||||
|
|
||||||
-- Minimalist node_ and way_functions in order to test source_ and segment_functions
|
-- Minimalist node_ and way_functions in order to test source_ and segment_functions
|
||||||
@ -37,18 +37,25 @@ function source_function ()
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function segment_function (source, target, distance, weight)
|
function segment_function (segment)
|
||||||
local sourceData = sources:interpolate(raster_source, source.lon, source.lat)
|
local sourceData = sources:interpolate(raster_source, segment.source.lon, segment.source.lat)
|
||||||
local targetData = sources:interpolate(raster_source, target.lon, target.lat)
|
local targetData = sources:interpolate(raster_source, segment.target.lon, segment.target.lat)
|
||||||
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
||||||
local invalid = sourceData.invalid_data()
|
local invalid = sourceData.invalid_data()
|
||||||
|
local scaled_weight = segment.weight
|
||||||
|
local scaled_duration = segment.duration
|
||||||
|
|
||||||
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
||||||
local slope = math.abs(sourceData.datum - targetData.datum) / distance
|
local slope = math.abs(sourceData.datum - targetData.datum) / segment.distance
|
||||||
io.write(" slope: " .. slope .. "\n")
|
io.write(" slope: " .. slope .. "\n")
|
||||||
io.write(" was speed: " .. weight.speed .. "\n")
|
io.write(" was weight: " .. segment.weight .. "\n")
|
||||||
|
io.write(" was speed: " .. segment.duration .. "\n")
|
||||||
|
|
||||||
weight.speed = weight.speed * (1 - (slope * 5))
|
scaled_weight = scaled_weight / (1 - (slope * 5))
|
||||||
io.write(" new speed: " .. weight.speed .. "\n")
|
io.write(" new weight: " .. scaled_weight .. "\n")
|
||||||
|
scaled_duration = scaled_duration / (1 - (slope * 5))
|
||||||
|
io.write(" new speed: " .. scaled_duration .. "\n")
|
||||||
end
|
end
|
||||||
|
segment.weight = scaled_weight
|
||||||
|
segment.duration = scaled_duration
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
api_version = 0
|
api_version = 1
|
||||||
-- Testbot profile
|
-- Testbot profile
|
||||||
|
|
||||||
-- Moves at fixed, well-known speeds, practical for testing speed and travel times:
|
-- Moves at fixed, well-known speeds, practical for testing speed and travel times:
|
||||||
@ -19,9 +19,11 @@ speed_profile = {
|
|||||||
|
|
||||||
properties.continue_straight_at_waypoint = true
|
properties.continue_straight_at_waypoint = true
|
||||||
properties.use_turn_restrictions = true
|
properties.use_turn_restrictions = true
|
||||||
properties.traffic_signal_penalty = 7 -- seconds
|
|
||||||
properties.u_turn_penalty = 20
|
|
||||||
properties.max_speed_for_map_matching = 30/3.6 --km -> m/s
|
properties.max_speed_for_map_matching = 30/3.6 --km -> m/s
|
||||||
|
properties.weight_name = 'duration'
|
||||||
|
|
||||||
|
local uturn_penalty = 20
|
||||||
|
local traffic_light_penalty = 7 -- seconds
|
||||||
|
|
||||||
function limit_speed(speed, limits)
|
function limit_speed(speed, limits)
|
||||||
-- don't use ipairs(), since it stops at the first nil value
|
-- don't use ipairs(), since it stops at the first nil value
|
||||||
@ -114,3 +116,13 @@ function way_function (way, result)
|
|||||||
result.roundabout = true
|
result.roundabout = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function turn_function (turn)
|
||||||
|
if turn.direction_modifier == direction_modifier.uturn then
|
||||||
|
turn.duration = uturn_penalty
|
||||||
|
turn.weight = uturn_penalty
|
||||||
|
end
|
||||||
|
if turn.has_traffic_light then
|
||||||
|
turn.duration = turn.duration + traffic_light_penalty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
api_version = 0
|
api_version = 1
|
||||||
|
|
||||||
-- Testbot, with turn penalty
|
-- Testbot, with turn penalty
|
||||||
-- Used for testing turn penalties
|
-- Used for testing turn penalties
|
||||||
|
|
||||||
require 'testbot'
|
require 'testbot'
|
||||||
|
|
||||||
function turn_function (angle)
|
function turn_function (turn)
|
||||||
-- multiplying by 10 converts to deci-seconds see issue #1318
|
turn.duration = 20 * math.abs(turn.angle) / 180
|
||||||
return 10*20*math.abs(angle)/180
|
|
||||||
end
|
end
|
||||||
|
@ -74,7 +74,9 @@ struct Segment final
|
|||||||
|
|
||||||
struct SpeedSource final
|
struct SpeedSource final
|
||||||
{
|
{
|
||||||
|
SpeedSource() : speed(0), weight(INVALID_EDGE_WEIGHT) {}
|
||||||
unsigned speed;
|
unsigned speed;
|
||||||
|
EdgeWeight weight;
|
||||||
std::uint8_t source;
|
std::uint8_t source;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -86,7 +88,7 @@ struct Turn final
|
|||||||
: from(from), via(via), to(to)
|
: from(from), via(via), to(to)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Turn(const osrm::extractor::lookup::PenaltyBlock &turn)
|
Turn(const osrm::extractor::lookup::TurnIndexBlock &turn)
|
||||||
: from(static_cast<std::uint64_t>(turn.from_id)),
|
: from(static_cast<std::uint64_t>(turn.from_id)),
|
||||||
via(static_cast<std::uint64_t>(turn.via_id)), to(static_cast<std::uint64_t>(turn.to_id))
|
via(static_cast<std::uint64_t>(turn.via_id)), to(static_cast<std::uint64_t>(turn.to_id))
|
||||||
{
|
{
|
||||||
@ -103,7 +105,9 @@ struct Turn final
|
|||||||
|
|
||||||
struct PenaltySource final
|
struct PenaltySource final
|
||||||
{
|
{
|
||||||
double penalty;
|
PenaltySource() : duration(0.), weight(std::numeric_limits<double>::quiet_NaN()) {}
|
||||||
|
double duration;
|
||||||
|
double weight;
|
||||||
std::uint8_t source;
|
std::uint8_t source;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -115,11 +119,15 @@ template <typename T> inline bool is_aligned(const void *pointer)
|
|||||||
} // anon ns
|
} // anon ns
|
||||||
|
|
||||||
BOOST_FUSION_ADAPT_STRUCT(Segment, (decltype(Segment::from), from)(decltype(Segment::to), to))
|
BOOST_FUSION_ADAPT_STRUCT(Segment, (decltype(Segment::from), from)(decltype(Segment::to), to))
|
||||||
BOOST_FUSION_ADAPT_STRUCT(SpeedSource, (decltype(SpeedSource::speed), speed))
|
BOOST_FUSION_ADAPT_STRUCT(SpeedSource,
|
||||||
|
(decltype(SpeedSource::speed), speed)(decltype(SpeedSource::weight),
|
||||||
|
weight))
|
||||||
BOOST_FUSION_ADAPT_STRUCT(Turn,
|
BOOST_FUSION_ADAPT_STRUCT(Turn,
|
||||||
(decltype(Turn::from), from)(decltype(Turn::via), via)(decltype(Turn::to),
|
(decltype(Turn::from), from)(decltype(Turn::via), via)(decltype(Turn::to),
|
||||||
to))
|
to))
|
||||||
BOOST_FUSION_ADAPT_STRUCT(PenaltySource, (decltype(PenaltySource::penalty), penalty))
|
BOOST_FUSION_ADAPT_STRUCT(PenaltySource,
|
||||||
|
(decltype(PenaltySource::duration),
|
||||||
|
duration)(decltype(PenaltySource::weight), weight))
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@ -240,29 +248,37 @@ inline EdgeWeight ConvertToDuration(double distance_in_meters, double speed_in_k
|
|||||||
BOOST_ASSERT(speed_in_kmh > 0);
|
BOOST_ASSERT(speed_in_kmh > 0);
|
||||||
const double speed_in_ms = speed_in_kmh / 3.6;
|
const double speed_in_ms = speed_in_kmh / 3.6;
|
||||||
const double duration = distance_in_meters / speed_in_ms;
|
const double duration = distance_in_meters / speed_in_ms;
|
||||||
return std::max<EdgeWeight>(1, static_cast<EdgeWeight>(std::round(duration * 10)));
|
return std::max<EdgeWeight>(1, static_cast<EdgeWeight>(std::round(duration * 10.)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns updated edge weight
|
// Returns updated edge weight
|
||||||
EdgeWeight GetNewWeight(const SpeedSource &value,
|
void GetNewWeight(const SpeedSource &value,
|
||||||
const double &segment_length,
|
const double &segment_length,
|
||||||
const std::vector<std::string> &segment_speed_filenames,
|
const std::vector<std::string> &segment_speed_filenames,
|
||||||
const EdgeWeight old_weight,
|
const EdgeWeight current_duration,
|
||||||
const double log_edge_updates_factor,
|
const double log_edge_updates_factor,
|
||||||
const OSMNodeID &from,
|
const OSMNodeID from,
|
||||||
const OSMNodeID &to)
|
const OSMNodeID to,
|
||||||
|
EdgeWeight &new_segment_weight,
|
||||||
|
EdgeWeight &new_segment_duration)
|
||||||
{
|
{
|
||||||
const auto new_segment_weight =
|
// Update the edge duration as distance/speed
|
||||||
|
new_segment_duration =
|
||||||
(value.speed > 0) ? ConvertToDuration(segment_length, value.speed) : INVALID_EDGE_WEIGHT;
|
(value.speed > 0) ? ConvertToDuration(segment_length, value.speed) : INVALID_EDGE_WEIGHT;
|
||||||
// the check here is enabled by the `--edge-weight-updates-over-factor` flag it logs
|
|
||||||
// a warning if the new weight exceeds a heuristic of what a reasonable weight update is
|
// Update the edge weight or fallback to the new edge duration
|
||||||
if (log_edge_updates_factor > 0 && old_weight != 0)
|
new_segment_weight =
|
||||||
|
(value.weight == INVALID_EDGE_WEIGHT) ? new_segment_duration : value.weight;
|
||||||
|
|
||||||
|
// The check here is enabled by the `--edge-weight-updates-over-factor` flag it logs a warning
|
||||||
|
// if the new duration exceeds a heuristic of what a reasonable duration update is
|
||||||
|
if (log_edge_updates_factor > 0 && current_duration != 0)
|
||||||
{
|
{
|
||||||
auto new_secs = new_segment_weight / 10.0;
|
if (current_duration >= (new_segment_duration * log_edge_updates_factor))
|
||||||
auto old_secs = old_weight / 10.0;
|
{
|
||||||
|
auto new_secs = new_segment_duration / 10.;
|
||||||
|
auto old_secs = current_duration / 10.;
|
||||||
auto approx_original_speed = (segment_length / old_secs) * 3.6;
|
auto approx_original_speed = (segment_length / old_secs) * 3.6;
|
||||||
if (old_weight >= (new_segment_weight * log_edge_updates_factor))
|
|
||||||
{
|
|
||||||
auto speed_file = segment_speed_filenames.at(value.source - 1);
|
auto speed_file = segment_speed_filenames.at(value.source - 1);
|
||||||
util::Log(logWARNING) << "[weight updates] Edge weight update from " << old_secs
|
util::Log(logWARNING) << "[weight updates] Edge weight update from " << old_secs
|
||||||
<< "s to " << new_secs << "s New speed: " << value.speed
|
<< "s to " << new_secs << "s New speed: " << value.speed
|
||||||
@ -273,21 +289,10 @@ EdgeWeight GetNewWeight(const SpeedSource &value,
|
|||||||
<< speed_file;
|
<< speed_file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_segment_weight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Contractor::Run()
|
int Contractor::Run()
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
|
||||||
#pragma message("Memory consumption on Windows can be higher due to different bit packing")
|
|
||||||
#else
|
|
||||||
static_assert(sizeof(extractor::NodeBasedEdge) == 24,
|
|
||||||
"changing extractor::NodeBasedEdge type has influence on memory consumption!");
|
|
||||||
static_assert(sizeof(extractor::EdgeBasedEdge) == 16,
|
|
||||||
"changing EdgeBasedEdge type has influence on memory consumption!");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (config.core_factor > 1.0 || config.core_factor < 0)
|
if (config.core_factor > 1.0 || config.core_factor < 0)
|
||||||
{
|
{
|
||||||
throw util::exception("Core factor must be between 0.0 to 1.0 (inclusive)" + SOURCE_REF);
|
throw util::exception("Core factor must be between 0.0 to 1.0 (inclusive)" + SOURCE_REF);
|
||||||
@ -314,7 +319,9 @@ int Contractor::Run()
|
|||||||
edge_based_edge_list,
|
edge_based_edge_list,
|
||||||
node_weights,
|
node_weights,
|
||||||
config.edge_segment_lookup_path,
|
config.edge_segment_lookup_path,
|
||||||
config.edge_penalty_path,
|
config.turn_weight_penalties_path,
|
||||||
|
config.turn_duration_penalties_path,
|
||||||
|
config.turn_penalties_index_path,
|
||||||
config.segment_speed_lookup_paths,
|
config.segment_speed_lookup_paths,
|
||||||
config.turn_penalty_lookup_paths,
|
config.turn_penalty_lookup_paths,
|
||||||
config.node_based_graph_path,
|
config.node_based_graph_path,
|
||||||
@ -377,7 +384,9 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
|
std::vector<extractor::EdgeBasedEdge> &edge_based_edge_list,
|
||||||
std::vector<EdgeWeight> &node_weights,
|
std::vector<EdgeWeight> &node_weights,
|
||||||
const std::string &edge_segment_lookup_filename,
|
const std::string &edge_segment_lookup_filename,
|
||||||
const std::string &edge_penalty_filename,
|
const std::string &turn_weight_penalties_filename,
|
||||||
|
const std::string &turn_duration_penalties_filename,
|
||||||
|
const std::string &turn_penalties_index_filename,
|
||||||
const std::vector<std::string> &segment_speed_filenames,
|
const std::vector<std::string> &segment_speed_filenames,
|
||||||
const std::vector<std::string> &turn_penalty_filenames,
|
const std::vector<std::string> &turn_penalty_filenames,
|
||||||
const std::string &nodes_filename,
|
const std::string &nodes_filename,
|
||||||
@ -393,15 +402,14 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
|
|
||||||
util::Log() << "Opening " << edge_based_graph_filename;
|
util::Log() << "Opening " << edge_based_graph_filename;
|
||||||
|
|
||||||
auto mmap_file = [](const std::string &filename) {
|
auto mmap_file = [](const std::string &filename, boost::interprocess::mode_t mode) {
|
||||||
using boost::interprocess::file_mapping;
|
using boost::interprocess::file_mapping;
|
||||||
using boost::interprocess::mapped_region;
|
using boost::interprocess::mapped_region;
|
||||||
using boost::interprocess::read_only;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const file_mapping mapping{filename.c_str(), read_only};
|
const file_mapping mapping{filename.c_str(), mode};
|
||||||
mapped_region region{mapping, read_only};
|
mapped_region region{mapping, mode};
|
||||||
region.advise(mapped_region::advice_sequential);
|
region.advise(mapped_region::advice_sequential);
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
@ -412,15 +420,16 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto edge_based_graph_region = mmap_file(edge_based_graph_filename);
|
const auto edge_based_graph_region =
|
||||||
|
mmap_file(edge_based_graph_filename, boost::interprocess::read_only);
|
||||||
|
|
||||||
const bool update_edge_weights = !segment_speed_filenames.empty();
|
const bool update_edge_weights = !segment_speed_filenames.empty();
|
||||||
const bool update_turn_penalties = !turn_penalty_filenames.empty();
|
const bool update_turn_penalties = !turn_penalty_filenames.empty();
|
||||||
|
|
||||||
const auto edge_penalty_region = [&] {
|
const auto turn_penalties_index_region = [&] {
|
||||||
if (update_edge_weights || update_turn_penalties)
|
if (update_edge_weights || update_turn_penalties)
|
||||||
{
|
{
|
||||||
return mmap_file(edge_penalty_filename);
|
return mmap_file(turn_penalties_index_filename, boost::interprocess::read_only);
|
||||||
}
|
}
|
||||||
return boost::interprocess::mapped_region();
|
return boost::interprocess::mapped_region();
|
||||||
}();
|
}();
|
||||||
@ -428,7 +437,7 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
const auto edge_segment_region = [&] {
|
const auto edge_segment_region = [&] {
|
||||||
if (update_edge_weights || update_turn_penalties)
|
if (update_edge_weights || update_turn_penalties)
|
||||||
{
|
{
|
||||||
return mmap_file(edge_segment_lookup_filename);
|
return mmap_file(edge_segment_lookup_filename, boost::interprocess::read_only);
|
||||||
}
|
}
|
||||||
return boost::interprocess::mapped_region();
|
return boost::interprocess::mapped_region();
|
||||||
}();
|
}();
|
||||||
@ -474,12 +483,13 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
util::Log() << "Reading " << graph_header.number_of_edges << " edges from the edge based graph";
|
util::Log() << "Reading " << graph_header.number_of_edges << " edges from the edge based graph";
|
||||||
|
|
||||||
auto segment_speed_lookup = CSVFilesParser<Segment, SpeedSource>(
|
auto segment_speed_lookup = CSVFilesParser<Segment, SpeedSource>(
|
||||||
1, qi::ulong_long >> ',' >> qi::ulong_long, qi::uint_)(segment_speed_filenames);
|
1, qi::ulong_long >> ',' >> qi::ulong_long, qi::uint_ >> -(',' >> qi::uint_))(
|
||||||
|
segment_speed_filenames);
|
||||||
|
|
||||||
auto turn_penalty_lookup = CSVFilesParser<Turn, PenaltySource>(
|
auto turn_penalty_lookup = CSVFilesParser<Turn, PenaltySource>(
|
||||||
1 + segment_speed_filenames.size(),
|
1 + segment_speed_filenames.size(),
|
||||||
qi::ulong_long >> ',' >> qi::ulong_long >> ',' >> qi::ulong_long,
|
qi::ulong_long >> ',' >> qi::ulong_long >> ',' >> qi::ulong_long,
|
||||||
qi::double_)(turn_penalty_filenames);
|
qi::double_ >> -(',' >> qi::double_))(turn_penalty_filenames);
|
||||||
|
|
||||||
// If we update the edge weights, this file will hold the datasource information for each
|
// If we update the edge weights, this file will hold the datasource information for each
|
||||||
// segment; the other files will also be conditionally filled concurrently if we make an update
|
// segment; the other files will also be conditionally filled concurrently if we make an update
|
||||||
@ -490,9 +500,11 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
std::vector<NodeID> geometry_node_list;
|
std::vector<NodeID> geometry_node_list;
|
||||||
std::vector<EdgeWeight> geometry_fwd_weight_list;
|
std::vector<EdgeWeight> geometry_fwd_weight_list;
|
||||||
std::vector<EdgeWeight> geometry_rev_weight_list;
|
std::vector<EdgeWeight> geometry_rev_weight_list;
|
||||||
|
std::vector<EdgeWeight> geometry_fwd_duration_list;
|
||||||
|
std::vector<EdgeWeight> geometry_rev_duration_list;
|
||||||
|
|
||||||
const auto maybe_load_internal_to_external_node_map = [&] {
|
const auto maybe_load_internal_to_external_node_map = [&] {
|
||||||
if (!(update_edge_weights || update_turn_penalties))
|
if (!update_edge_weights)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
storage::io::FileReader nodes_file(nodes_filename,
|
storage::io::FileReader nodes_file(nodes_filename,
|
||||||
@ -503,7 +515,7 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto maybe_load_geometries = [&] {
|
const auto maybe_load_geometries = [&] {
|
||||||
if (!(update_edge_weights || update_turn_penalties))
|
if (!update_edge_weights)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
storage::io::FileReader geometry_file(geometry_filename,
|
storage::io::FileReader geometry_file(geometry_filename,
|
||||||
@ -518,6 +530,8 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
geometry_node_list.resize(number_of_compressed_geometries);
|
geometry_node_list.resize(number_of_compressed_geometries);
|
||||||
geometry_fwd_weight_list.resize(number_of_compressed_geometries);
|
geometry_fwd_weight_list.resize(number_of_compressed_geometries);
|
||||||
geometry_rev_weight_list.resize(number_of_compressed_geometries);
|
geometry_rev_weight_list.resize(number_of_compressed_geometries);
|
||||||
|
geometry_fwd_duration_list.resize(number_of_compressed_geometries);
|
||||||
|
geometry_rev_duration_list.resize(number_of_compressed_geometries);
|
||||||
|
|
||||||
if (number_of_compressed_geometries > 0)
|
if (number_of_compressed_geometries > 0)
|
||||||
{
|
{
|
||||||
@ -526,13 +540,17 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
number_of_compressed_geometries);
|
number_of_compressed_geometries);
|
||||||
geometry_file.ReadInto(geometry_rev_weight_list.data(),
|
geometry_file.ReadInto(geometry_rev_weight_list.data(),
|
||||||
number_of_compressed_geometries);
|
number_of_compressed_geometries);
|
||||||
|
geometry_file.ReadInto(geometry_fwd_duration_list.data(),
|
||||||
|
number_of_compressed_geometries);
|
||||||
|
geometry_file.ReadInto(geometry_rev_duration_list.data(),
|
||||||
|
number_of_compressed_geometries);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Folds all our actions into independently concurrently executing lambdas
|
// Folds all our actions into independently concurrently executing lambdas
|
||||||
tbb::parallel_invoke(maybe_load_internal_to_external_node_map, maybe_load_geometries);
|
tbb::parallel_invoke(maybe_load_internal_to_external_node_map, maybe_load_geometries);
|
||||||
|
|
||||||
if (update_edge_weights || update_turn_penalties)
|
if (update_edge_weights)
|
||||||
{
|
{
|
||||||
// Here, we have to update the compressed geometry weights
|
// Here, we have to update the compressed geometry weights
|
||||||
// First, we need the external-to-internal node lookup table
|
// First, we need the external-to-internal node lookup table
|
||||||
@ -552,7 +570,7 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
|
|
||||||
using boost::interprocess::mapped_region;
|
using boost::interprocess::mapped_region;
|
||||||
|
|
||||||
auto region = mmap_file(rtree_leaf_filename.c_str());
|
auto region = mmap_file(rtree_leaf_filename.c_str(), boost::interprocess::read_only);
|
||||||
region.advise(mapped_region::advice_willneed);
|
region.advise(mapped_region::advice_willneed);
|
||||||
BOOST_ASSERT(is_aligned<LeafNode>(region.get_address()));
|
BOOST_ASSERT(is_aligned<LeafNode>(region.get_address()));
|
||||||
|
|
||||||
@ -589,32 +607,38 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
auto fwd_source = LUA_SOURCE, rev_source = LUA_SOURCE;
|
auto fwd_source = LUA_SOURCE, rev_source = LUA_SOURCE;
|
||||||
if (auto value = segment_speed_lookup({u.node_id, v.node_id}))
|
if (auto value = segment_speed_lookup({u.node_id, v.node_id}))
|
||||||
{
|
{
|
||||||
const auto current_fwd_weight = geometry_fwd_weight_list[u_index];
|
EdgeWeight new_segment_weight, new_segment_duration;
|
||||||
const auto new_segment_weight = GetNewWeight(*value,
|
GetNewWeight(*value,
|
||||||
segment_length,
|
segment_length,
|
||||||
segment_speed_filenames,
|
segment_speed_filenames,
|
||||||
current_fwd_weight,
|
geometry_fwd_duration_list[u_index],
|
||||||
log_edge_updates_factor,
|
log_edge_updates_factor,
|
||||||
u.node_id,
|
u.node_id,
|
||||||
v.node_id);
|
v.node_id,
|
||||||
|
new_segment_weight,
|
||||||
|
new_segment_duration);
|
||||||
|
|
||||||
geometry_fwd_weight_list[v_index] = new_segment_weight;
|
geometry_fwd_weight_list[v_index] = new_segment_weight;
|
||||||
|
geometry_fwd_duration_list[v_index] = new_segment_duration;
|
||||||
geometry_datasource[v_index] = value->source;
|
geometry_datasource[v_index] = value->source;
|
||||||
fwd_source = value->source;
|
fwd_source = value->source;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto value = segment_speed_lookup({v.node_id, u.node_id}))
|
if (auto value = segment_speed_lookup({v.node_id, u.node_id}))
|
||||||
{
|
{
|
||||||
const auto current_rev_weight = geometry_rev_weight_list[u_index];
|
EdgeWeight new_segment_weight, new_segment_duration;
|
||||||
const auto new_segment_weight = GetNewWeight(*value,
|
GetNewWeight(*value,
|
||||||
segment_length,
|
segment_length,
|
||||||
segment_speed_filenames,
|
segment_speed_filenames,
|
||||||
current_rev_weight,
|
geometry_rev_duration_list[u_index],
|
||||||
log_edge_updates_factor,
|
log_edge_updates_factor,
|
||||||
v.node_id,
|
v.node_id,
|
||||||
u.node_id);
|
u.node_id,
|
||||||
|
new_segment_weight,
|
||||||
|
new_segment_duration);
|
||||||
|
|
||||||
geometry_rev_weight_list[u_index] = new_segment_weight;
|
geometry_rev_weight_list[u_index] = new_segment_weight;
|
||||||
|
geometry_rev_duration_list[u_index] = new_segment_duration;
|
||||||
geometry_datasource[u_index] = value->source;
|
geometry_datasource[u_index] = value->source;
|
||||||
rev_source = value->source;
|
rev_source = value->source;
|
||||||
}
|
}
|
||||||
@ -652,7 +676,7 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto maybe_save_geometries = [&] {
|
const auto maybe_save_geometries = [&] {
|
||||||
if (!(update_edge_weights || update_turn_penalties))
|
if (!update_edge_weights)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Now save out the updated compressed geometries
|
// Now save out the updated compressed geometries
|
||||||
@ -675,6 +699,10 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
number_of_compressed_geometries * sizeof(EdgeWeight));
|
number_of_compressed_geometries * sizeof(EdgeWeight));
|
||||||
geometry_stream.write(reinterpret_cast<char *>(&(geometry_rev_weight_list[0])),
|
geometry_stream.write(reinterpret_cast<char *>(&(geometry_rev_weight_list[0])),
|
||||||
number_of_compressed_geometries * sizeof(EdgeWeight));
|
number_of_compressed_geometries * sizeof(EdgeWeight));
|
||||||
|
geometry_stream.write(reinterpret_cast<char *>(&(geometry_fwd_duration_list[0])),
|
||||||
|
number_of_compressed_geometries * sizeof(EdgeWeight));
|
||||||
|
geometry_stream.write(reinterpret_cast<char *>(&(geometry_rev_duration_list[0])),
|
||||||
|
number_of_compressed_geometries * sizeof(EdgeWeight));
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto save_datasource_indexes = [&] {
|
const auto save_datasource_indexes = [&] {
|
||||||
@ -716,17 +744,47 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
|
|
||||||
tbb::parallel_invoke(maybe_save_geometries, save_datasource_indexes, save_datastore_names);
|
tbb::parallel_invoke(maybe_save_geometries, save_datasource_indexes, save_datastore_names);
|
||||||
|
|
||||||
auto turn_penalty_blocks_ptr = reinterpret_cast<const extractor::lookup::PenaltyBlock *>(
|
std::vector<TurnPenalty> turn_weight_penalties;
|
||||||
edge_penalty_region.get_address());
|
std::vector<TurnPenalty> turn_duration_penalties;
|
||||||
BOOST_ASSERT(is_aligned<extractor::lookup::PenaltyBlock>(turn_penalty_blocks_ptr));
|
|
||||||
|
|
||||||
auto edge_based_edge_ptr = reinterpret_cast<extractor::EdgeBasedEdge *>(
|
const auto maybe_load_turn_weight_penalties = [&] {
|
||||||
|
if (!update_edge_weights && !update_turn_penalties)
|
||||||
|
return;
|
||||||
|
using storage::io::FileReader;
|
||||||
|
FileReader file(turn_weight_penalties_filename, FileReader::HasNoFingerprint);
|
||||||
|
file.DeserializeVector(turn_weight_penalties);
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto maybe_load_turn_duration_penalties = [&] {
|
||||||
|
if (!update_turn_penalties)
|
||||||
|
return;
|
||||||
|
using storage::io::FileReader;
|
||||||
|
FileReader file(turn_duration_penalties_filename, FileReader::HasNoFingerprint);
|
||||||
|
file.DeserializeVector(turn_duration_penalties);
|
||||||
|
};
|
||||||
|
|
||||||
|
tbb::parallel_invoke(maybe_load_turn_weight_penalties, maybe_load_turn_duration_penalties);
|
||||||
|
|
||||||
|
if (update_turn_penalties && turn_duration_penalties.empty())
|
||||||
|
{ // Copy-on-write for duration penalties as turn weight penalties
|
||||||
|
turn_duration_penalties = turn_weight_penalties;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mapped file pointer for turn indices
|
||||||
|
const extractor::lookup::TurnIndexBlock *turn_index_blocks =
|
||||||
|
reinterpret_cast<const extractor::lookup::TurnIndexBlock *>(
|
||||||
|
turn_penalties_index_region.get_address());
|
||||||
|
BOOST_ASSERT(is_aligned<extractor::lookup::TurnIndexBlock>(turn_index_blocks));
|
||||||
|
|
||||||
|
// Mapped file pointers for edge-based graph edges
|
||||||
|
auto edge_based_edge_ptr = reinterpret_cast<const extractor::EdgeBasedEdge *>(
|
||||||
reinterpret_cast<char *>(edge_based_graph_region.get_address()) +
|
reinterpret_cast<char *>(edge_based_graph_region.get_address()) +
|
||||||
sizeof(EdgeBasedGraphHeader));
|
sizeof(EdgeBasedGraphHeader));
|
||||||
BOOST_ASSERT(is_aligned<extractor::EdgeBasedEdge>(edge_based_edge_ptr));
|
BOOST_ASSERT(is_aligned<extractor::EdgeBasedEdge>(edge_based_edge_ptr));
|
||||||
|
|
||||||
auto edge_segment_byte_ptr = reinterpret_cast<const char *>(edge_segment_region.get_address());
|
auto edge_segment_byte_ptr = reinterpret_cast<const char *>(edge_segment_region.get_address());
|
||||||
|
|
||||||
|
bool fallback_to_duration = true;
|
||||||
for (std::uint64_t edge_index = 0; edge_index < graph_header.number_of_edges; ++edge_index)
|
for (std::uint64_t edge_index = 0; edge_index < graph_header.number_of_edges; ++edge_index)
|
||||||
{
|
{
|
||||||
// Make a copy of the data from the memory map
|
// Make a copy of the data from the memory map
|
||||||
@ -759,7 +817,10 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
if (value->speed == 0)
|
if (value->speed == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
segment_weight = ConvertToDuration(segment.segment_length, value->speed);
|
segment_weight =
|
||||||
|
value->weight == INVALID_EDGE_WEIGHT
|
||||||
|
? ConvertToDuration(segment.segment_length, value->speed)
|
||||||
|
: value->weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the edge weight and the next OSM node ID
|
// Update the edge weight and the next OSM node ID
|
||||||
@ -779,30 +840,61 @@ Contractor::LoadEdgeExpandedGraph(std::string const &edge_based_graph_filename,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get the turn penalty and update to the new value if required
|
// Get the turn penalty and update to the new value if required
|
||||||
const auto &turn_block = turn_penalty_blocks_ptr[edge_index];
|
const auto &turn_index = turn_index_blocks[edge_index];
|
||||||
EdgeWeight new_turn_penalty = turn_block.fixed_penalty;
|
auto turn_weight_penalty = turn_weight_penalties[edge_index];
|
||||||
if (auto value = turn_penalty_lookup(turn_block))
|
if (auto value = turn_penalty_lookup(turn_index))
|
||||||
{
|
{
|
||||||
new_turn_penalty = static_cast<EdgeWeight>(value->penalty * 10);
|
auto turn_duration_penalty =
|
||||||
|
boost::numeric_cast<TurnPenalty>(std::round(value->duration * 10.));
|
||||||
|
turn_weight_penalty =
|
||||||
|
std::isfinite(value->weight)
|
||||||
|
? boost::numeric_cast<TurnPenalty>(std::round(value->weight * 10))
|
||||||
|
: turn_duration_penalty;
|
||||||
|
|
||||||
if (new_weight + new_turn_penalty < static_cast<EdgeWeight>(header->num_osm_nodes))
|
const auto weight_min_value = static_cast<EdgeWeight>(header->num_osm_nodes);
|
||||||
|
if (turn_weight_penalty + new_weight < weight_min_value)
|
||||||
{
|
{
|
||||||
util::Log(logWARNING)
|
util::Log(logWARNING) << "turn penalty " << turn_weight_penalty << " for turn "
|
||||||
<< "turn penalty " << value->penalty << " for turn " << turn_block.from_id
|
<< turn_index.from_id << ", " << turn_index.via_id << ", "
|
||||||
<< "," << turn_block.via_id << "," << turn_block.to_id
|
<< turn_index.to_id
|
||||||
<< " is too negative: clamping turn weight to " << header->num_osm_nodes;
|
<< " is too negative: clamping turn weight to "
|
||||||
|
<< weight_min_value;
|
||||||
|
|
||||||
new_turn_penalty = header->num_osm_nodes - new_weight;
|
turn_weight_penalty = weight_min_value - new_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
turn_duration_penalties[edge_index] = turn_duration_penalty;
|
||||||
|
turn_weight_penalties[edge_index] = turn_weight_penalty;
|
||||||
|
|
||||||
|
// Is fallback of duration to weight values allowed
|
||||||
|
fallback_to_duration &= (turn_duration_penalty == turn_weight_penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update edge weight
|
// Update edge weight
|
||||||
inbuffer.weight = new_weight + new_turn_penalty;
|
inbuffer.weight = new_weight + turn_weight_penalty;
|
||||||
}
|
}
|
||||||
|
|
||||||
edge_based_edge_list.emplace_back(std::move(inbuffer));
|
edge_based_edge_list.emplace_back(std::move(inbuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (update_turn_penalties)
|
||||||
|
{
|
||||||
|
if (fallback_to_duration)
|
||||||
|
{ // Turn duration penalties are identical to turn weight penalties
|
||||||
|
// Save empty data vector, so turn weight penalties will be used by data facade.
|
||||||
|
turn_duration_penalties.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto save_penalties = [](const auto &filename, const auto &data) -> void {
|
||||||
|
storage::io::FileWriter file(filename, storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
file.SerializeVector(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
tbb::parallel_invoke(
|
||||||
|
[&] { save_penalties(turn_weight_penalties_filename, turn_weight_penalties); },
|
||||||
|
[&] { save_penalties(turn_duration_penalties_filename, turn_duration_penalties); });
|
||||||
|
}
|
||||||
|
|
||||||
util::Log() << "Done reading edges";
|
util::Log() << "Done reading edges";
|
||||||
return graph_header.max_edge_id;
|
return graph_header.max_edge_id;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ ContractorDijkstra::ContractorDijkstra(const std::size_t heap_size) : heap(heap_
|
|||||||
|
|
||||||
void ContractorDijkstra::Run(const unsigned number_of_targets,
|
void ContractorDijkstra::Run(const unsigned number_of_targets,
|
||||||
const int node_limit,
|
const int node_limit,
|
||||||
const int weight_limit,
|
const EdgeWeight weight_limit,
|
||||||
const NodeID forbidden_node,
|
const NodeID forbidden_node,
|
||||||
const ContractorGraph &graph)
|
const ContractorGraph &graph)
|
||||||
{
|
{
|
||||||
@ -43,7 +43,7 @@ void ContractorDijkstra::Run(const unsigned number_of_targets,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ContractorDijkstra::RelaxNode(const NodeID node,
|
void ContractorDijkstra::RelaxNode(const NodeID node,
|
||||||
const int node_weight,
|
const EdgeWeight node_weight,
|
||||||
const NodeID forbidden_node,
|
const NodeID forbidden_node,
|
||||||
const ContractorGraph &graph)
|
const ContractorGraph &graph)
|
||||||
{
|
{
|
||||||
@ -60,7 +60,7 @@ void ContractorDijkstra::RelaxNode(const NodeID node,
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const int to_weight = node_weight + data.weight;
|
const EdgeWeight to_weight = node_weight + data.weight;
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!heap.WasInserted(to))
|
if (!heap.WasInserted(to))
|
||||||
|
@ -242,6 +242,7 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo
|
|||||||
util::json::Object route_step;
|
util::json::Object route_step;
|
||||||
route_step.values["distance"] = std::round(step.distance * 10) / 10.;
|
route_step.values["distance"] = std::round(step.distance * 10) / 10.;
|
||||||
route_step.values["duration"] = std::round(step.duration * 10) / 10.;
|
route_step.values["duration"] = std::round(step.duration * 10) / 10.;
|
||||||
|
route_step.values["weight"] = step.weight; // We should round to weight_precision here
|
||||||
route_step.values["name"] = std::move(step.name);
|
route_step.values["name"] = std::move(step.name);
|
||||||
if (!step.ref.empty())
|
if (!step.ref.empty())
|
||||||
route_step.values["ref"] = std::move(step.ref);
|
route_step.values["ref"] = std::move(step.ref);
|
||||||
@ -275,9 +276,11 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo
|
|||||||
|
|
||||||
util::json::Object makeRoute(const guidance::Route &route,
|
util::json::Object makeRoute(const guidance::Route &route,
|
||||||
util::json::Array legs,
|
util::json::Array legs,
|
||||||
boost::optional<util::json::Value> geometry)
|
boost::optional<util::json::Value> geometry,
|
||||||
|
const char *weight_name)
|
||||||
{
|
{
|
||||||
util::json::Object json_route;
|
util::json::Object json_route;
|
||||||
|
json_route.values["weight_name"] = weight_name;
|
||||||
json_route.values["distance"] = std::round(route.distance * 10) / 10.;
|
json_route.values["distance"] = std::round(route.distance * 10) / 10.;
|
||||||
json_route.values["duration"] = std::round(route.duration * 10) / 10.;
|
json_route.values["duration"] = std::round(route.duration * 10) / 10.;
|
||||||
json_route.values["legs"] = std::move(legs);
|
json_route.values["legs"] = std::move(legs);
|
||||||
|
@ -26,7 +26,7 @@ void AlternativeRouting::operator()(const std::shared_ptr<const datafacade::Base
|
|||||||
QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2);
|
QueryHeap &forward_heap2 = *(engine_working_data.forward_heap_2);
|
||||||
QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2);
|
QueryHeap &reverse_heap2 = *(engine_working_data.reverse_heap_2);
|
||||||
|
|
||||||
int upper_bound_to_shortest_path_weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight upper_bound_to_shortest_path_weight = INVALID_EDGE_WEIGHT;
|
||||||
NodeID middle_node = SPECIAL_NODEID;
|
NodeID middle_node = SPECIAL_NODEID;
|
||||||
const EdgeWeight min_edge_offset =
|
const EdgeWeight min_edge_offset =
|
||||||
std::min(phantom_node_pair.source_phantom.forward_segment_id.enabled
|
std::min(phantom_node_pair.source_phantom.forward_segment_id.enabled
|
||||||
@ -599,7 +599,7 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const int T_threshold = static_cast<int>(VIAPATH_EPSILON * length_of_shortest_path);
|
const int T_threshold = static_cast<int>(VIAPATH_EPSILON * length_of_shortest_path);
|
||||||
int unpacked_until_weight = 0;
|
EdgeWeight unpacked_until_weight = 0;
|
||||||
|
|
||||||
std::stack<SearchSpaceEdge> unpack_stack;
|
std::stack<SearchSpaceEdge> unpack_stack;
|
||||||
// Traverse path s-->v
|
// Traverse path s-->v
|
||||||
@ -607,7 +607,7 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest(
|
|||||||
{
|
{
|
||||||
const EdgeID current_edge_id =
|
const EdgeID current_edge_id =
|
||||||
facade->FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]);
|
facade->FindEdgeInEitherDirection(packed_s_v_path[i - 1], packed_s_v_path[i]);
|
||||||
const int length_of_current_edge = facade->GetEdgeData(current_edge_id).weight;
|
const EdgeWeight length_of_current_edge = facade->GetEdgeData(current_edge_id).weight;
|
||||||
if ((length_of_current_edge + unpacked_until_weight) >= T_threshold)
|
if ((length_of_current_edge + unpacked_until_weight) >= T_threshold)
|
||||||
{
|
{
|
||||||
unpack_stack.emplace(packed_s_v_path[i - 1], packed_s_v_path[i]);
|
unpack_stack.emplace(packed_s_v_path[i - 1], packed_s_v_path[i]);
|
||||||
@ -660,7 +660,7 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int t_test_path_length = unpacked_until_weight;
|
EdgeWeight t_test_path_length = unpacked_until_weight;
|
||||||
unpacked_until_weight = 0;
|
unpacked_until_weight = 0;
|
||||||
// Traverse path s-->v
|
// Traverse path s-->v
|
||||||
BOOST_ASSERT(!packed_v_t_path.empty());
|
BOOST_ASSERT(!packed_v_t_path.empty());
|
||||||
@ -727,7 +727,7 @@ bool AlternativeRouting::ViaNodeCandidatePassesTTest(
|
|||||||
|
|
||||||
QueryHeap &forward_heap3 = *engine_working_data.forward_heap_3;
|
QueryHeap &forward_heap3 = *engine_working_data.forward_heap_3;
|
||||||
QueryHeap &reverse_heap3 = *engine_working_data.reverse_heap_3;
|
QueryHeap &reverse_heap3 = *engine_working_data.reverse_heap_3;
|
||||||
int upper_bound = INVALID_EDGE_WEIGHT;
|
EdgeWeight upper_bound = INVALID_EDGE_WEIGHT;
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
|
|
||||||
forward_heap3.Insert(s_P, 0, s_P);
|
forward_heap3.Insert(s_P, 0, s_P);
|
||||||
|
@ -128,7 +128,7 @@ void ManyToManyRouting::ForwardRoutingStep(
|
|||||||
std::vector<EdgeWeight> &result_table) const
|
std::vector<EdgeWeight> &result_table) const
|
||||||
{
|
{
|
||||||
const NodeID node = query_heap.DeleteMin();
|
const NodeID node = query_heap.DeleteMin();
|
||||||
const int source_weight = query_heap.GetKey(node);
|
const EdgeWeight source_weight = query_heap.GetKey(node);
|
||||||
|
|
||||||
// check if each encountered node has an entry
|
// check if each encountered node has an entry
|
||||||
const auto bucket_iterator = search_space_with_buckets.find(node);
|
const auto bucket_iterator = search_space_with_buckets.find(node);
|
||||||
@ -140,14 +140,14 @@ void ManyToManyRouting::ForwardRoutingStep(
|
|||||||
{
|
{
|
||||||
// get target id from bucket entry
|
// get target id from bucket entry
|
||||||
const unsigned column_idx = current_bucket.target_id;
|
const unsigned column_idx = current_bucket.target_id;
|
||||||
const int target_weight = current_bucket.weight;
|
const EdgeWeight target_weight = current_bucket.weight;
|
||||||
auto ¤t_weight = result_table[row_idx * number_of_targets + column_idx];
|
auto ¤t_weight = result_table[row_idx * number_of_targets + column_idx];
|
||||||
// check if new weight is better
|
// check if new weight is better
|
||||||
const EdgeWeight new_weight = source_weight + target_weight;
|
const EdgeWeight new_weight = source_weight + target_weight;
|
||||||
if (new_weight < 0)
|
if (new_weight < 0)
|
||||||
{
|
{
|
||||||
const EdgeWeight loop_weight = super::GetLoopWeight(facade, node);
|
const EdgeWeight loop_weight = super::GetLoopWeight(facade, node);
|
||||||
const int new_weight_with_loop = new_weight + loop_weight;
|
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
||||||
if (loop_weight != INVALID_EDGE_WEIGHT && new_weight_with_loop >= 0)
|
if (loop_weight != INVALID_EDGE_WEIGHT && new_weight_with_loop >= 0)
|
||||||
{
|
{
|
||||||
current_weight = std::min(current_weight, new_weight_with_loop);
|
current_weight = std::min(current_weight, new_weight_with_loop);
|
||||||
@ -173,7 +173,7 @@ void ManyToManyRouting::BackwardRoutingStep(
|
|||||||
SearchSpaceWithBuckets &search_space_with_buckets) const
|
SearchSpaceWithBuckets &search_space_with_buckets) const
|
||||||
{
|
{
|
||||||
const NodeID node = query_heap.DeleteMin();
|
const NodeID node = query_heap.DeleteMin();
|
||||||
const int target_weight = query_heap.GetKey(node);
|
const EdgeWeight target_weight = query_heap.GetKey(node);
|
||||||
|
|
||||||
// store settled nodes in search space bucket
|
// store settled nodes in search space bucket
|
||||||
search_space_with_buckets[node].emplace_back(column_idx, target_weight);
|
search_space_with_buckets[node].emplace_back(column_idx, target_weight);
|
||||||
|
@ -12,19 +12,19 @@ void BasicRoutingInterface::RoutingStep(
|
|||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
NodeID &middle_node_id,
|
NodeID &middle_node_id,
|
||||||
std::int32_t &upper_bound,
|
EdgeWeight &upper_bound,
|
||||||
std::int32_t min_edge_offset,
|
EdgeWeight min_edge_offset,
|
||||||
const bool forward_direction,
|
const bool forward_direction,
|
||||||
const bool stalling,
|
const bool stalling,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse) const
|
const bool force_loop_reverse) const
|
||||||
{
|
{
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
const std::int32_t weight = forward_heap.GetKey(node);
|
const EdgeWeight weight = forward_heap.GetKey(node);
|
||||||
|
|
||||||
if (reverse_heap.WasInserted(node))
|
if (reverse_heap.WasInserted(node))
|
||||||
{
|
{
|
||||||
const std::int32_t new_weight = reverse_heap.GetKey(node) + weight;
|
const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
|
||||||
if (new_weight < upper_bound)
|
if (new_weight < upper_bound)
|
||||||
{
|
{
|
||||||
// if loops are forced, they are so at the source
|
// if loops are forced, they are so at the source
|
||||||
@ -45,7 +45,7 @@ void BasicRoutingInterface::RoutingStep(
|
|||||||
if (to == node)
|
if (to == node)
|
||||||
{
|
{
|
||||||
const EdgeWeight edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
const std::int32_t loop_weight = new_weight + edge_weight;
|
const EdgeWeight loop_weight = new_weight + edge_weight;
|
||||||
if (loop_weight >= 0 && loop_weight < upper_bound)
|
if (loop_weight >= 0 && loop_weight < upper_bound)
|
||||||
{
|
{
|
||||||
middle_node_id = node;
|
middle_node_id = node;
|
||||||
@ -109,7 +109,7 @@ void BasicRoutingInterface::RoutingStep(
|
|||||||
const EdgeWeight edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
const int to_weight = weight + edge_weight;
|
const EdgeWeight to_weight = weight + edge_weight;
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!forward_heap.WasInserted(to))
|
if (!forward_heap.WasInserted(to))
|
||||||
@ -216,14 +216,14 @@ void BasicRoutingInterface::RetrievePackedPathFromSingleHeap(
|
|||||||
void BasicRoutingInterface::Search(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
|
void BasicRoutingInterface::Search(const std::shared_ptr<const datafacade::BaseDataFacade> facade,
|
||||||
SearchEngineData::QueryHeap &forward_heap,
|
SearchEngineData::QueryHeap &forward_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
std::int32_t &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
const int duration_upper_bound) const
|
const EdgeWeight weight_upper_bound) const
|
||||||
{
|
{
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
weight = duration_upper_bound;
|
weight = weight_upper_bound;
|
||||||
|
|
||||||
// get offset to account for offsets on phantom nodes on compressed edges
|
// get offset to account for offsets on phantom nodes on compressed edges
|
||||||
const auto min_edge_offset = std::min(0, forward_heap.MinKey());
|
const auto min_edge_offset = std::min(0, forward_heap.MinKey());
|
||||||
@ -264,7 +264,7 @@ void BasicRoutingInterface::Search(const std::shared_ptr<const datafacade::BaseD
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No path found for both target nodes?
|
// No path found for both target nodes?
|
||||||
if (duration_upper_bound <= weight || SPECIAL_NODEID == middle)
|
if (weight_upper_bound <= weight || SPECIAL_NODEID == middle)
|
||||||
{
|
{
|
||||||
weight = INVALID_EDGE_WEIGHT;
|
weight = INVALID_EDGE_WEIGHT;
|
||||||
return;
|
return;
|
||||||
@ -301,14 +301,14 @@ void BasicRoutingInterface::SearchWithCore(
|
|||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
SearchEngineData::QueryHeap &forward_core_heap,
|
SearchEngineData::QueryHeap &forward_core_heap,
|
||||||
SearchEngineData::QueryHeap &reverse_core_heap,
|
SearchEngineData::QueryHeap &reverse_core_heap,
|
||||||
int &weight,
|
EdgeWeight &weight,
|
||||||
std::vector<NodeID> &packed_leg,
|
std::vector<NodeID> &packed_leg,
|
||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
int duration_upper_bound) const
|
EdgeWeight weight_upper_bound) const
|
||||||
{
|
{
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
weight = duration_upper_bound;
|
weight = weight_upper_bound;
|
||||||
|
|
||||||
using CoreEntryPoint = std::tuple<NodeID, EdgeWeight, NodeID>;
|
using CoreEntryPoint = std::tuple<NodeID, EdgeWeight, NodeID>;
|
||||||
std::vector<CoreEntryPoint> forward_entry_points;
|
std::vector<CoreEntryPoint> forward_entry_points;
|
||||||
@ -328,7 +328,7 @@ void BasicRoutingInterface::SearchWithCore(
|
|||||||
if (facade->IsCoreNode(forward_heap.Min()))
|
if (facade->IsCoreNode(forward_heap.Min()))
|
||||||
{
|
{
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
const int key = forward_heap.GetKey(node);
|
const EdgeWeight key = forward_heap.GetKey(node);
|
||||||
forward_entry_points.emplace_back(node, key, forward_heap.GetData(node).parent);
|
forward_entry_points.emplace_back(node, key, forward_heap.GetData(node).parent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -350,7 +350,7 @@ void BasicRoutingInterface::SearchWithCore(
|
|||||||
if (facade->IsCoreNode(reverse_heap.Min()))
|
if (facade->IsCoreNode(reverse_heap.Min()))
|
||||||
{
|
{
|
||||||
const NodeID node = reverse_heap.DeleteMin();
|
const NodeID node = reverse_heap.DeleteMin();
|
||||||
const int key = reverse_heap.GetKey(node);
|
const EdgeWeight key = reverse_heap.GetKey(node);
|
||||||
reverse_entry_points.emplace_back(node, key, reverse_heap.GetData(node).parent);
|
reverse_entry_points.emplace_back(node, key, reverse_heap.GetData(node).parent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -392,7 +392,7 @@ void BasicRoutingInterface::SearchWithCore(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get offset to account for offsets on phantom nodes on compressed edges
|
// get offset to account for offsets on phantom nodes on compressed edges
|
||||||
int min_core_edge_offset = 0;
|
EdgeWeight min_core_edge_offset = 0;
|
||||||
if (forward_core_heap.Size() > 0)
|
if (forward_core_heap.Size() > 0)
|
||||||
{
|
{
|
||||||
min_core_edge_offset = std::min(min_core_edge_offset, forward_core_heap.MinKey());
|
min_core_edge_offset = std::min(min_core_edge_offset, forward_core_heap.MinKey());
|
||||||
@ -432,7 +432,7 @@ void BasicRoutingInterface::SearchWithCore(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No path found for both target nodes?
|
// No path found for both target nodes?
|
||||||
if (duration_upper_bound <= weight || SPECIAL_NODEID == middle)
|
if (weight_upper_bound <= weight || SPECIAL_NODEID == middle)
|
||||||
{
|
{
|
||||||
weight = INVALID_EDGE_WEIGHT;
|
weight = INVALID_EDGE_WEIGHT;
|
||||||
return;
|
return;
|
||||||
@ -567,7 +567,7 @@ double BasicRoutingInterface::GetNetworkDistanceWithCore(
|
|||||||
SearchEngineData::QueryHeap &reverse_core_heap,
|
SearchEngineData::QueryHeap &reverse_core_heap,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
int duration_upper_bound) const
|
EdgeWeight weight_upper_bound) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(forward_heap.Empty());
|
BOOST_ASSERT(forward_heap.Empty());
|
||||||
BOOST_ASSERT(reverse_heap.Empty());
|
BOOST_ASSERT(reverse_heap.Empty());
|
||||||
@ -601,21 +601,21 @@ double BasicRoutingInterface::GetNetworkDistanceWithCore(
|
|||||||
const bool constexpr DO_NOT_FORCE_LOOPS =
|
const bool constexpr DO_NOT_FORCE_LOOPS =
|
||||||
false; // prevents forcing of loops, since offsets are set correctly
|
false; // prevents forcing of loops, since offsets are set correctly
|
||||||
|
|
||||||
int duration = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
SearchWithCore(facade,
|
SearchWithCore(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
forward_core_heap,
|
forward_core_heap,
|
||||||
reverse_core_heap,
|
reverse_core_heap,
|
||||||
duration,
|
weight,
|
||||||
packed_path,
|
packed_path,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
duration_upper_bound);
|
weight_upper_bound);
|
||||||
|
|
||||||
double distance = std::numeric_limits<double>::max();
|
double distance = std::numeric_limits<double>::max();
|
||||||
if (duration != INVALID_EDGE_WEIGHT)
|
if (weight != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
return GetPathDistance(facade, packed_path, source_phantom, target_phantom);
|
return GetPathDistance(facade, packed_path, source_phantom, target_phantom);
|
||||||
}
|
}
|
||||||
@ -631,7 +631,7 @@ double BasicRoutingInterface::GetNetworkDistance(
|
|||||||
SearchEngineData::QueryHeap &reverse_heap,
|
SearchEngineData::QueryHeap &reverse_heap,
|
||||||
const PhantomNode &source_phantom,
|
const PhantomNode &source_phantom,
|
||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
int duration_upper_bound) const
|
EdgeWeight weight_upper_bound) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(forward_heap.Empty());
|
BOOST_ASSERT(forward_heap.Empty());
|
||||||
BOOST_ASSERT(reverse_heap.Empty());
|
BOOST_ASSERT(reverse_heap.Empty());
|
||||||
@ -665,18 +665,18 @@ double BasicRoutingInterface::GetNetworkDistance(
|
|||||||
const bool constexpr DO_NOT_FORCE_LOOPS =
|
const bool constexpr DO_NOT_FORCE_LOOPS =
|
||||||
false; // prevents forcing of loops, since offsets are set correctly
|
false; // prevents forcing of loops, since offsets are set correctly
|
||||||
|
|
||||||
int duration = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
Search(facade,
|
Search(facade,
|
||||||
forward_heap,
|
forward_heap,
|
||||||
reverse_heap,
|
reverse_heap,
|
||||||
duration,
|
weight,
|
||||||
packed_path,
|
packed_path,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
DO_NOT_FORCE_LOOPS,
|
DO_NOT_FORCE_LOOPS,
|
||||||
duration_upper_bound);
|
weight_upper_bound);
|
||||||
|
|
||||||
if (duration == INVALID_EDGE_WEIGHT)
|
if (weight == INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
return std::numeric_limits<double>::max();
|
return std::numeric_limits<double>::max();
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,14 @@ void CompressedEdgeContainer::SerializeInternalVector(const std::string &path) c
|
|||||||
// write compressed geometry reverse weights
|
// write compressed geometry reverse weights
|
||||||
geometry_out_stream.write((char *)(m_compressed_geometry_rev_weights.data()),
|
geometry_out_stream.write((char *)(m_compressed_geometry_rev_weights.data()),
|
||||||
sizeof(EdgeWeight) * m_compressed_geometry_rev_weights.size());
|
sizeof(EdgeWeight) * m_compressed_geometry_rev_weights.size());
|
||||||
|
|
||||||
|
// write compressed geometry forward durations
|
||||||
|
geometry_out_stream.write((char *)(m_compressed_geometry_fwd_durations.data()),
|
||||||
|
sizeof(EdgeWeight) * m_compressed_geometry_fwd_durations.size());
|
||||||
|
|
||||||
|
// write compressed geometry reverse durations
|
||||||
|
geometry_out_stream.write((char *)(m_compressed_geometry_rev_durations.data()),
|
||||||
|
sizeof(EdgeWeight) * m_compressed_geometry_rev_durations.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds info for a compressed edge to the container. edge_id_2
|
// Adds info for a compressed edge to the container. edge_id_2
|
||||||
@ -111,12 +119,15 @@ void CompressedEdgeContainer::SerializeInternalVector(const std::string &path) c
|
|||||||
// edge_id_1 edge_id_2
|
// edge_id_1 edge_id_2
|
||||||
// ----------> via_node_id -----------> target_node_id
|
// ----------> via_node_id -----------> target_node_id
|
||||||
// weight_1 weight_2
|
// weight_1 weight_2
|
||||||
|
// duration_1 duration_2
|
||||||
void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
||||||
const EdgeID edge_id_2,
|
const EdgeID edge_id_2,
|
||||||
const NodeID via_node_id,
|
const NodeID via_node_id,
|
||||||
const NodeID target_node_id,
|
const NodeID target_node_id,
|
||||||
const EdgeWeight weight1,
|
const EdgeWeight weight1,
|
||||||
const EdgeWeight weight2)
|
const EdgeWeight weight2,
|
||||||
|
const EdgeWeight duration1,
|
||||||
|
const EdgeWeight duration2)
|
||||||
{
|
{
|
||||||
// remove super-trivial geometries
|
// remove super-trivial geometries
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
|
BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1);
|
||||||
@ -161,7 +172,7 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
|||||||
// weight1 is the distance to the (currently) last coordinate in the bucket
|
// weight1 is the distance to the (currently) last coordinate in the bucket
|
||||||
if (edge_bucket_list1.empty())
|
if (edge_bucket_list1.empty())
|
||||||
{
|
{
|
||||||
edge_bucket_list1.emplace_back(OnewayCompressedEdge{via_node_id, weight1});
|
edge_bucket_list1.emplace_back(OnewayCompressedEdge{via_node_id, weight1, duration1});
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
BOOST_ASSERT(0 < edge_bucket_list1.size());
|
||||||
@ -192,13 +203,14 @@ void CompressedEdgeContainer::CompressEdge(const EdgeID edge_id_1,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we are certain that the second edge is atomic.
|
// we are certain that the second edge is atomic.
|
||||||
edge_bucket_list1.emplace_back(OnewayCompressedEdge{target_node_id, weight2});
|
edge_bucket_list1.emplace_back(OnewayCompressedEdge{target_node_id, weight2, duration2});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressedEdgeContainer::AddUncompressedEdge(const EdgeID edge_id,
|
void CompressedEdgeContainer::AddUncompressedEdge(const EdgeID edge_id,
|
||||||
const NodeID target_node_id,
|
const NodeID target_node_id,
|
||||||
const EdgeWeight weight)
|
const EdgeWeight weight,
|
||||||
|
const EdgeWeight duration)
|
||||||
{
|
{
|
||||||
// remove super-trivial geometries
|
// remove super-trivial geometries
|
||||||
BOOST_ASSERT(SPECIAL_EDGEID != edge_id);
|
BOOST_ASSERT(SPECIAL_EDGEID != edge_id);
|
||||||
@ -234,7 +246,7 @@ void CompressedEdgeContainer::AddUncompressedEdge(const EdgeID edge_id,
|
|||||||
// Don't re-add this if it's already in there.
|
// Don't re-add this if it's already in there.
|
||||||
if (edge_bucket_list.empty())
|
if (edge_bucket_list.empty())
|
||||||
{
|
{
|
||||||
edge_bucket_list.emplace_back(OnewayCompressedEdge{target_node_id, weight});
|
edge_bucket_list.emplace_back(OnewayCompressedEdge{target_node_id, weight, duration});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +256,8 @@ void CompressedEdgeContainer::InitializeBothwayVector()
|
|||||||
m_compressed_geometry_nodes.reserve(m_compressed_oneway_geometries.size());
|
m_compressed_geometry_nodes.reserve(m_compressed_oneway_geometries.size());
|
||||||
m_compressed_geometry_fwd_weights.reserve(m_compressed_oneway_geometries.size());
|
m_compressed_geometry_fwd_weights.reserve(m_compressed_oneway_geometries.size());
|
||||||
m_compressed_geometry_rev_weights.reserve(m_compressed_oneway_geometries.size());
|
m_compressed_geometry_rev_weights.reserve(m_compressed_oneway_geometries.size());
|
||||||
|
m_compressed_geometry_fwd_durations.reserve(m_compressed_oneway_geometries.size());
|
||||||
|
m_compressed_geometry_rev_durations.reserve(m_compressed_oneway_geometries.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID r_edge_id)
|
unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID r_edge_id)
|
||||||
@ -264,6 +278,8 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID
|
|||||||
m_compressed_geometry_nodes.emplace_back(first_node.node_id);
|
m_compressed_geometry_nodes.emplace_back(first_node.node_id);
|
||||||
m_compressed_geometry_fwd_weights.emplace_back(INVALID_EDGE_WEIGHT);
|
m_compressed_geometry_fwd_weights.emplace_back(INVALID_EDGE_WEIGHT);
|
||||||
m_compressed_geometry_rev_weights.emplace_back(first_node.weight);
|
m_compressed_geometry_rev_weights.emplace_back(first_node.weight);
|
||||||
|
m_compressed_geometry_fwd_durations.emplace_back(INVALID_EDGE_WEIGHT);
|
||||||
|
m_compressed_geometry_rev_durations.emplace_back(first_node.duration);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < forward_bucket.size() - 1; ++i)
|
for (std::size_t i = 0; i < forward_bucket.size() - 1; ++i)
|
||||||
{
|
{
|
||||||
@ -275,6 +291,8 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID
|
|||||||
m_compressed_geometry_nodes.emplace_back(fwd_node.node_id);
|
m_compressed_geometry_nodes.emplace_back(fwd_node.node_id);
|
||||||
m_compressed_geometry_fwd_weights.emplace_back(fwd_node.weight);
|
m_compressed_geometry_fwd_weights.emplace_back(fwd_node.weight);
|
||||||
m_compressed_geometry_rev_weights.emplace_back(rev_node.weight);
|
m_compressed_geometry_rev_weights.emplace_back(rev_node.weight);
|
||||||
|
m_compressed_geometry_fwd_durations.emplace_back(fwd_node.duration);
|
||||||
|
m_compressed_geometry_rev_durations.emplace_back(rev_node.duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &last_node = forward_bucket.back();
|
const auto &last_node = forward_bucket.back();
|
||||||
@ -282,6 +300,8 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID
|
|||||||
m_compressed_geometry_nodes.emplace_back(last_node.node_id);
|
m_compressed_geometry_nodes.emplace_back(last_node.node_id);
|
||||||
m_compressed_geometry_fwd_weights.emplace_back(last_node.weight);
|
m_compressed_geometry_fwd_weights.emplace_back(last_node.weight);
|
||||||
m_compressed_geometry_rev_weights.emplace_back(INVALID_EDGE_WEIGHT);
|
m_compressed_geometry_rev_weights.emplace_back(INVALID_EDGE_WEIGHT);
|
||||||
|
m_compressed_geometry_fwd_durations.emplace_back(last_node.duration);
|
||||||
|
m_compressed_geometry_rev_durations.emplace_back(INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
return zipped_geometry_id;
|
return zipped_geometry_id;
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,9 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
|
|||||||
const std::string &original_edge_data_filename,
|
const std::string &original_edge_data_filename,
|
||||||
const std::string &turn_lane_data_filename,
|
const std::string &turn_lane_data_filename,
|
||||||
const std::string &edge_segment_lookup_filename,
|
const std::string &edge_segment_lookup_filename,
|
||||||
const std::string &edge_penalty_filename,
|
const std::string &turn_weight_penalties_filename,
|
||||||
|
const std::string &turn_duration_penalties_filename,
|
||||||
|
const std::string &turn_penalties_index_filename,
|
||||||
const bool generate_edge_lookup)
|
const bool generate_edge_lookup)
|
||||||
{
|
{
|
||||||
TIMER_START(renumber);
|
TIMER_START(renumber);
|
||||||
@ -207,7 +209,9 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
|
|||||||
original_edge_data_filename,
|
original_edge_data_filename,
|
||||||
turn_lane_data_filename,
|
turn_lane_data_filename,
|
||||||
edge_segment_lookup_filename,
|
edge_segment_lookup_filename,
|
||||||
edge_penalty_filename,
|
turn_weight_penalties_filename,
|
||||||
|
turn_duration_penalties_filename,
|
||||||
|
turn_penalties_index_filename,
|
||||||
generate_edge_lookup);
|
generate_edge_lookup);
|
||||||
|
|
||||||
TIMER_STOP(generate_edges);
|
TIMER_STOP(generate_edges);
|
||||||
@ -237,11 +241,7 @@ unsigned EdgeBasedGraphFactory::RenumberEdges()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// oneway streets always require this self-loop. Other streets only if a u-turn plus
|
m_edge_based_node_weights.push_back(edge_data.weight);
|
||||||
// traversal
|
|
||||||
// of the street takes longer than the loop
|
|
||||||
m_edge_based_node_weights.push_back(edge_data.distance +
|
|
||||||
profile_properties.u_turn_penalty);
|
|
||||||
|
|
||||||
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
|
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
|
||||||
edge_data.edge_id = numbered_edges_count;
|
edge_data.edge_id = numbered_edges_count;
|
||||||
@ -311,7 +311,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
const std::string &original_edge_data_filename,
|
const std::string &original_edge_data_filename,
|
||||||
const std::string &turn_lane_data_filename,
|
const std::string &turn_lane_data_filename,
|
||||||
const std::string &edge_segment_lookup_filename,
|
const std::string &edge_segment_lookup_filename,
|
||||||
const std::string &edge_fixed_penalties_filename,
|
const std::string &turn_weight_penalties_filename,
|
||||||
|
const std::string &turn_duration_penalties_filename,
|
||||||
|
const std::string &turn_penalties_index_filename,
|
||||||
const bool generate_edge_lookup)
|
const bool generate_edge_lookup)
|
||||||
{
|
{
|
||||||
util::Log() << "Generating edge-expanded edges ";
|
util::Log() << "Generating edge-expanded edges ";
|
||||||
@ -324,12 +326,12 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
|
|
||||||
std::ofstream edge_data_file(original_edge_data_filename.c_str(), std::ios::binary);
|
std::ofstream edge_data_file(original_edge_data_filename.c_str(), std::ios::binary);
|
||||||
std::ofstream edge_segment_file;
|
std::ofstream edge_segment_file;
|
||||||
std::ofstream edge_penalty_file;
|
std::ofstream turn_penalties_index_file;
|
||||||
|
|
||||||
if (generate_edge_lookup)
|
if (generate_edge_lookup)
|
||||||
{
|
{
|
||||||
edge_segment_file.open(edge_segment_lookup_filename.c_str(), std::ios::binary);
|
edge_segment_file.open(edge_segment_lookup_filename.c_str(), std::ios::binary);
|
||||||
edge_penalty_file.open(edge_fixed_penalties_filename.c_str(), std::ios::binary);
|
turn_penalties_index_file.open(turn_penalties_index_filename.c_str(), std::ios::binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes a dummy value at the front that is updated later with the total length
|
// Writes a dummy value at the front that is updated later with the total length
|
||||||
@ -364,6 +366,13 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
|
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
|
||||||
std::numeric_limits<std::uint32_t>::max());
|
std::numeric_limits<std::uint32_t>::max());
|
||||||
|
|
||||||
|
// FIXME these need to be tuned in pre-allocated size
|
||||||
|
std::vector<TurnPenalty> turn_weight_penalties;
|
||||||
|
std::vector<TurnPenalty> turn_duration_penalties;
|
||||||
|
|
||||||
|
const auto weight_multiplier =
|
||||||
|
std::pow(10, scripting_environment.GetProfileProperties().weight_precision);
|
||||||
|
|
||||||
{
|
{
|
||||||
util::UnbufferedLog log;
|
util::UnbufferedLog log;
|
||||||
|
|
||||||
@ -474,28 +483,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
BOOST_ASSERT(!edge_data2.reversed);
|
BOOST_ASSERT(!edge_data2.reversed);
|
||||||
|
|
||||||
// the following is the core of the loop.
|
// the following is the core of the loop.
|
||||||
unsigned distance = edge_data1.distance;
|
|
||||||
if (m_traffic_lights.find(node_at_center_of_intersection) !=
|
|
||||||
m_traffic_lights.end())
|
|
||||||
{
|
|
||||||
distance += profile_properties.traffic_signal_penalty;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int32_t turn_penalty =
|
|
||||||
scripting_environment.GetTurnPenalty(180. - turn.angle);
|
|
||||||
|
|
||||||
const auto turn_instruction = turn.instruction;
|
|
||||||
if (turn_instruction.direction_modifier == guidance::DirectionModifier::UTurn)
|
|
||||||
{
|
|
||||||
distance += profile_properties.u_turn_penalty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't add turn penalty if it is not an actual turn. This heuristic is
|
|
||||||
// necessary
|
|
||||||
// since OSRM cannot handle looping roads/parallel roads
|
|
||||||
if (turn_instruction.type != guidance::TurnType::NoTurn)
|
|
||||||
distance += turn_penalty;
|
|
||||||
|
|
||||||
const bool is_encoded_forwards =
|
const bool is_encoded_forwards =
|
||||||
m_compressed_edge_container.HasZippedEntryForForwardID(incoming_edge);
|
m_compressed_edge_container.HasZippedEntryForForwardID(incoming_edge);
|
||||||
const bool is_encoded_backwards =
|
const bool is_encoded_backwards =
|
||||||
@ -509,7 +496,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
true},
|
true},
|
||||||
edge_data1.name_id,
|
edge_data1.name_id,
|
||||||
turn.lane_data_id,
|
turn.lane_data_id,
|
||||||
turn_instruction,
|
turn.instruction,
|
||||||
entry_class_id,
|
entry_class_id,
|
||||||
edge_data1.travel_mode,
|
edge_data1.travel_mode,
|
||||||
util::guidance::TurnBearing(intersection[0].bearing),
|
util::guidance::TurnBearing(intersection[0].bearing),
|
||||||
@ -523,7 +510,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
false},
|
false},
|
||||||
edge_data1.name_id,
|
edge_data1.name_id,
|
||||||
turn.lane_data_id,
|
turn.lane_data_id,
|
||||||
turn_instruction,
|
turn.instruction,
|
||||||
entry_class_id,
|
entry_class_id,
|
||||||
edge_data1.travel_mode,
|
edge_data1.travel_mode,
|
||||||
util::guidance::TurnBearing(intersection[0].bearing),
|
util::guidance::TurnBearing(intersection[0].bearing),
|
||||||
@ -531,26 +518,46 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
}
|
}
|
||||||
|
|
||||||
++original_edges_counter;
|
++original_edges_counter;
|
||||||
|
|
||||||
if (original_edge_data_vector.size() > 1024 * 1024 * 10)
|
if (original_edge_data_vector.size() > 1024 * 1024 * 10)
|
||||||
{
|
{
|
||||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compute weight and duration penalties
|
||||||
|
auto is_traffic_light = m_traffic_lights.count(node_at_center_of_intersection);
|
||||||
|
ExtractionTurn extracted_turn(turn, is_traffic_light);
|
||||||
|
scripting_environment.ProcessTurn(extracted_turn);
|
||||||
|
|
||||||
|
// turn penalties are limited to [-2^15, 2^15) which roughly
|
||||||
|
// translates to 54 minutes and fits signed 16bit deci-seconds
|
||||||
|
auto weight_penalty =
|
||||||
|
boost::numeric_cast<TurnPenalty>(extracted_turn.weight * weight_multiplier);
|
||||||
|
auto duration_penalty =
|
||||||
|
boost::numeric_cast<TurnPenalty>(extracted_turn.duration * 10.);
|
||||||
|
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edge_id);
|
BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edge_id);
|
||||||
BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edge_id);
|
BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edge_id);
|
||||||
|
|
||||||
// NOTE: potential overflow here if we hit 2^32 routable edges
|
// NOTE: potential overflow here if we hit 2^32 routable edges
|
||||||
BOOST_ASSERT(m_edge_based_edge_list.size() <=
|
BOOST_ASSERT(m_edge_based_edge_list.size() <=
|
||||||
std::numeric_limits<NodeID>::max());
|
std::numeric_limits<NodeID>::max());
|
||||||
m_edge_based_edge_list.emplace_back(edge_data1.edge_id,
|
auto turn_id = m_edge_based_edge_list.size();
|
||||||
edge_data2.edge_id,
|
auto weight =
|
||||||
m_edge_based_edge_list.size(),
|
boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty);
|
||||||
distance,
|
m_edge_based_edge_list.emplace_back(
|
||||||
true,
|
edge_data1.edge_id, edge_data2.edge_id, turn_id, weight, true, false);
|
||||||
false);
|
|
||||||
BOOST_ASSERT(original_edges_counter == m_edge_based_edge_list.size());
|
BOOST_ASSERT(original_edges_counter == m_edge_based_edge_list.size());
|
||||||
|
|
||||||
|
BOOST_ASSERT(turn_weight_penalties.size() == turn_id);
|
||||||
|
turn_weight_penalties.push_back(weight_penalty);
|
||||||
|
|
||||||
|
// the weight and the duration are not the same thing
|
||||||
|
if (!profile_properties.fallback_to_duration)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(turn_duration_penalties.size() == turn_id);
|
||||||
|
turn_duration_penalties.push_back(duration_penalty);
|
||||||
|
}
|
||||||
|
|
||||||
// Here is where we write out the mapping between the edge-expanded edges, and
|
// Here is where we write out the mapping between the edge-expanded edges, and
|
||||||
// the node-based edges that are originally used to calculate the `distance`
|
// the node-based edges that are originally used to calculate the `distance`
|
||||||
// for the edge-expanded edges. About 40 lines back, there is:
|
// for the edge-expanded edges. About 40 lines back, there is:
|
||||||
@ -618,17 +625,46 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
m_node_info_list[m_compressed_edge_container.GetFirstEdgeTargetID(
|
m_node_info_list[m_compressed_edge_container.GetFirstEdgeTargetID(
|
||||||
turn.eid)];
|
turn.eid)];
|
||||||
|
|
||||||
const unsigned fixed_penalty = distance - edge_data1.distance;
|
lookup::TurnIndexBlock turn_index_block = {
|
||||||
lookup::PenaltyBlock penaltyblock = {
|
from_node.node_id, via_node.node_id, to_node.node_id};
|
||||||
fixed_penalty, from_node.node_id, via_node.node_id, to_node.node_id};
|
BOOST_ASSERT(turn_penalties_index_file.tellp() /
|
||||||
edge_penalty_file.write(reinterpret_cast<const char *>(&penaltyblock),
|
(sizeof(turn_index_block)) ==
|
||||||
sizeof(penaltyblock));
|
turn_id);
|
||||||
|
turn_penalties_index_file.write(
|
||||||
|
reinterpret_cast<const char *>(&turn_index_block),
|
||||||
|
sizeof(turn_index_block));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write weight penalties per turn
|
||||||
|
std::ofstream turn_weight_penalties_file(turn_weight_penalties_filename.c_str(),
|
||||||
|
std::ios::binary);
|
||||||
|
lookup::TurnPenaltiesHeader turn_weight_penalties_header{turn_weight_penalties.size()};
|
||||||
|
turn_weight_penalties_file.write(reinterpret_cast<const char *>(&turn_weight_penalties_header),
|
||||||
|
sizeof(turn_weight_penalties_header));
|
||||||
|
turn_weight_penalties_file.write(reinterpret_cast<const char *>(turn_weight_penalties.data()),
|
||||||
|
sizeof(decltype(turn_weight_penalties)::value_type) *
|
||||||
|
turn_weight_penalties.size());
|
||||||
|
|
||||||
|
// write duration penalties per turn if we need them
|
||||||
|
BOOST_ASSERT(!profile_properties.fallback_to_duration || turn_duration_penalties.size() == 0);
|
||||||
|
std::ofstream turn_duration_penalties_file(turn_duration_penalties_filename.c_str(),
|
||||||
|
std::ios::binary);
|
||||||
|
lookup::TurnPenaltiesHeader turn_duration_penalties_header{turn_duration_penalties.size()};
|
||||||
|
turn_duration_penalties_file.write(
|
||||||
|
reinterpret_cast<const char *>(&turn_duration_penalties_header),
|
||||||
|
sizeof(turn_duration_penalties_header));
|
||||||
|
if (!profile_properties.fallback_to_duration)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(turn_weight_penalties.size() == turn_duration_penalties.size());
|
||||||
|
turn_duration_penalties_file.write(
|
||||||
|
reinterpret_cast<const char *>(turn_duration_penalties.data()),
|
||||||
|
sizeof(decltype(turn_duration_penalties)::value_type) * turn_duration_penalties.size());
|
||||||
|
}
|
||||||
|
|
||||||
util::Log() << "Created " << entry_class_hash.size() << " entry classes and "
|
util::Log() << "Created " << entry_class_hash.size() << " entry classes and "
|
||||||
<< bearing_class_hash.size() << " Bearing Classes";
|
<< bearing_class_hash.size() << " Bearing Classes";
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "extractor/extraction_containers.hpp"
|
#include "extractor/extraction_containers.hpp"
|
||||||
|
#include "extractor/extraction_segment.hpp"
|
||||||
#include "extractor/extraction_way.hpp"
|
#include "extractor/extraction_way.hpp"
|
||||||
|
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
@ -390,6 +391,9 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
|||||||
const auto all_edges_list_end_ = all_edges_list.end();
|
const auto all_edges_list_end_ = all_edges_list.end();
|
||||||
const auto all_nodes_list_end_ = all_nodes_list.end();
|
const auto all_nodes_list_end_ = all_nodes_list.end();
|
||||||
|
|
||||||
|
const auto weight_multiplier =
|
||||||
|
std::pow(10, scripting_environment.GetProfileProperties().weight_precision);
|
||||||
|
|
||||||
while (edge_iterator != all_edges_list_end_ && node_iterator != all_nodes_list_end_)
|
while (edge_iterator != all_edges_list_end_ && node_iterator != all_nodes_list_end_)
|
||||||
{
|
{
|
||||||
// skip all invalid edges
|
// skip all invalid edges
|
||||||
@ -414,44 +418,28 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(edge_iterator->result.osm_target_id == node_iterator->node_id);
|
BOOST_ASSERT(edge_iterator->result.osm_target_id == node_iterator->node_id);
|
||||||
BOOST_ASSERT(edge_iterator->weight_data.speed >= 0);
|
|
||||||
BOOST_ASSERT(edge_iterator->source_coordinate.lat !=
|
BOOST_ASSERT(edge_iterator->source_coordinate.lat !=
|
||||||
util::FixedLatitude{std::numeric_limits<std::int32_t>::min()});
|
util::FixedLatitude{std::numeric_limits<std::int32_t>::min()});
|
||||||
BOOST_ASSERT(edge_iterator->source_coordinate.lon !=
|
BOOST_ASSERT(edge_iterator->source_coordinate.lon !=
|
||||||
util::FixedLongitude{std::numeric_limits<std::int32_t>::min()});
|
util::FixedLongitude{std::numeric_limits<std::int32_t>::min()});
|
||||||
|
|
||||||
|
const util::Coordinate target_coord{node_iterator->lon, node_iterator->lat};
|
||||||
const double distance = util::coordinate_calculation::greatCircleDistance(
|
const double distance = util::coordinate_calculation::greatCircleDistance(
|
||||||
edge_iterator->source_coordinate,
|
edge_iterator->source_coordinate, target_coord);
|
||||||
util::Coordinate(node_iterator->lon, node_iterator->lat));
|
|
||||||
|
|
||||||
scripting_environment.ProcessSegment(edge_iterator->source_coordinate,
|
double weight = static_cast<double>(mapbox::util::apply_visitor(
|
||||||
*node_iterator,
|
detail::ToValueByEdge(distance), edge_iterator->weight_data));
|
||||||
distance,
|
double duration = static_cast<double>(mapbox::util::apply_visitor(
|
||||||
edge_iterator->weight_data);
|
detail::ToValueByEdge(distance), edge_iterator->duration_data));
|
||||||
|
|
||||||
const double weight = [distance, edge_iterator, node_iterator](
|
ExtractionSegment extracted_segment(
|
||||||
const InternalExtractorEdge::WeightData &data) {
|
edge_iterator->source_coordinate, target_coord, distance, weight, duration);
|
||||||
switch (data.type)
|
scripting_environment.ProcessSegment(extracted_segment);
|
||||||
{
|
|
||||||
case InternalExtractorEdge::WeightType::EDGE_DURATION:
|
|
||||||
case InternalExtractorEdge::WeightType::WAY_DURATION:
|
|
||||||
return data.duration * 10.;
|
|
||||||
break;
|
|
||||||
case InternalExtractorEdge::WeightType::SPEED:
|
|
||||||
return (distance * 10.) / (data.speed / 3.6);
|
|
||||||
break;
|
|
||||||
case InternalExtractorEdge::WeightType::INVALID:
|
|
||||||
std::stringstream coordstring;
|
|
||||||
coordstring << edge_iterator->source_coordinate << " to " << node_iterator->lon
|
|
||||||
<< "," << node_iterator->lat;
|
|
||||||
util::exception("Encountered invalid weight at segment " + coordstring.str() +
|
|
||||||
SOURCE_REF);
|
|
||||||
}
|
|
||||||
return -1.0;
|
|
||||||
}(edge_iterator->weight_data);
|
|
||||||
|
|
||||||
auto &edge = edge_iterator->result;
|
auto &edge = edge_iterator->result;
|
||||||
edge.weight = std::max(1, static_cast<int>(std::floor(weight + .5)));
|
edge.weight =
|
||||||
|
std::max<EdgeWeight>(1, std::round(extracted_segment.weight * weight_multiplier));
|
||||||
|
edge.duration = std::max<EdgeWeight>(1, std::round(extracted_segment.duration * 10.));
|
||||||
|
|
||||||
// assign new node id
|
// assign new node id
|
||||||
auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
|
auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
|
||||||
@ -499,7 +487,7 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
|||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(all_edges_list.size() > 0);
|
BOOST_ASSERT(all_edges_list.size() > 0);
|
||||||
for (unsigned i = 0; i < all_edges_list.size();)
|
for (std::size_t i = 0; i < all_edges_list.size();)
|
||||||
{
|
{
|
||||||
// only invalid edges left
|
// only invalid edges left
|
||||||
if (all_edges_list[i].result.source == SPECIAL_NODEID)
|
if (all_edges_list[i].result.source == SPECIAL_NODEID)
|
||||||
@ -513,42 +501,44 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned start_idx = i;
|
std::size_t start_idx = i;
|
||||||
NodeID source = all_edges_list[i].result.source;
|
NodeID source = all_edges_list[i].result.source;
|
||||||
NodeID target = all_edges_list[i].result.target;
|
NodeID target = all_edges_list[i].result.target;
|
||||||
|
|
||||||
int min_forward_weight = std::numeric_limits<int>::max();
|
auto min_forward = std::make_pair(std::numeric_limits<EdgeWeight>::max(),
|
||||||
int min_backward_weight = std::numeric_limits<int>::max();
|
std::numeric_limits<EdgeWeight>::max());
|
||||||
unsigned min_forward_idx = std::numeric_limits<unsigned>::max();
|
auto min_backward = std::make_pair(std::numeric_limits<EdgeWeight>::max(),
|
||||||
unsigned min_backward_idx = std::numeric_limits<unsigned>::max();
|
std::numeric_limits<EdgeWeight>::max());
|
||||||
|
std::size_t min_forward_idx = std::numeric_limits<std::size_t>::max();
|
||||||
|
std::size_t min_backward_idx = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
// find minimal edge in both directions
|
// find minimal edge in both directions
|
||||||
while (all_edges_list[i].result.source == source &&
|
while (i < all_edges_list.size() && all_edges_list[i].result.source == source &&
|
||||||
all_edges_list[i].result.target == target)
|
all_edges_list[i].result.target == target)
|
||||||
{
|
{
|
||||||
if (all_edges_list[i].result.forward &&
|
const auto &result = all_edges_list[i].result;
|
||||||
all_edges_list[i].result.weight < min_forward_weight)
|
const auto value = std::make_pair(result.weight, result.duration);
|
||||||
|
if (result.forward && value < min_forward)
|
||||||
{
|
{
|
||||||
min_forward_idx = i;
|
min_forward_idx = i;
|
||||||
min_forward_weight = all_edges_list[i].result.weight;
|
min_forward = value;
|
||||||
}
|
}
|
||||||
if (all_edges_list[i].result.backward &&
|
if (result.backward && value < min_backward)
|
||||||
all_edges_list[i].result.weight < min_backward_weight)
|
|
||||||
{
|
{
|
||||||
min_backward_idx = i;
|
min_backward_idx = i;
|
||||||
min_backward_weight = all_edges_list[i].result.weight;
|
min_backward = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this also increments the outer loop counter!
|
// this also increments the outer loop counter!
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(min_forward_idx == std::numeric_limits<unsigned>::max() ||
|
BOOST_ASSERT(min_forward_idx == std::numeric_limits<std::size_t>::max() ||
|
||||||
min_forward_idx < i);
|
min_forward_idx < i);
|
||||||
BOOST_ASSERT(min_backward_idx == std::numeric_limits<unsigned>::max() ||
|
BOOST_ASSERT(min_backward_idx == std::numeric_limits<std::size_t>::max() ||
|
||||||
min_backward_idx < i);
|
min_backward_idx < i);
|
||||||
BOOST_ASSERT(min_backward_idx != std::numeric_limits<unsigned>::max() ||
|
BOOST_ASSERT(min_backward_idx != std::numeric_limits<std::size_t>::max() ||
|
||||||
min_forward_idx != std::numeric_limits<unsigned>::max());
|
min_forward_idx != std::numeric_limits<std::size_t>::max());
|
||||||
|
|
||||||
if (min_backward_idx == min_forward_idx)
|
if (min_backward_idx == min_forward_idx)
|
||||||
{
|
{
|
||||||
@ -558,8 +548,8 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool has_forward = min_forward_idx != std::numeric_limits<unsigned>::max();
|
bool has_forward = min_forward_idx != std::numeric_limits<std::size_t>::max();
|
||||||
bool has_backward = min_backward_idx != std::numeric_limits<unsigned>::max();
|
bool has_backward = min_backward_idx != std::numeric_limits<std::size_t>::max();
|
||||||
if (has_forward)
|
if (has_forward)
|
||||||
{
|
{
|
||||||
all_edges_list[min_forward_idx].result.forward = true;
|
all_edges_list[min_forward_idx].result.forward = true;
|
||||||
@ -577,7 +567,7 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
|||||||
}
|
}
|
||||||
|
|
||||||
// invalidate all unused edges
|
// invalidate all unused edges
|
||||||
for (unsigned j = start_idx; j < i; j++)
|
for (std::size_t j = start_idx; j < i; j++)
|
||||||
{
|
{
|
||||||
if (j == min_forward_idx || j == min_backward_idx)
|
if (j == min_forward_idx || j == min_backward_idx)
|
||||||
{
|
{
|
||||||
|
@ -126,9 +126,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
}
|
}
|
||||||
util::Log() << "Threads: " << number_of_threads;
|
util::Log() << "Threads: " << number_of_threads;
|
||||||
|
|
||||||
ExtractionContainers extraction_containers;
|
|
||||||
auto extractor_callbacks = std::make_unique<ExtractorCallbacks>(extraction_containers);
|
|
||||||
|
|
||||||
const osmium::io::File input_file(config.input_path.string());
|
const osmium::io::File input_file(config.input_path.string());
|
||||||
|
|
||||||
osmium::io::Reader reader(
|
osmium::io::Reader reader(
|
||||||
@ -144,6 +141,10 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
util::Log() << "Parsing in progress..";
|
util::Log() << "Parsing in progress..";
|
||||||
TIMER_START(parsing);
|
TIMER_START(parsing);
|
||||||
|
|
||||||
|
ExtractionContainers extraction_containers;
|
||||||
|
auto extractor_callbacks = std::make_unique<ExtractorCallbacks>(
|
||||||
|
extraction_containers, scripting_environment.GetProfileProperties());
|
||||||
|
|
||||||
// setup raster sources
|
// setup raster sources
|
||||||
scripting_environment.SetupSources();
|
scripting_environment.SetupSources();
|
||||||
|
|
||||||
@ -496,7 +497,9 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
|||||||
config.edge_output_path,
|
config.edge_output_path,
|
||||||
config.turn_lane_data_file_name,
|
config.turn_lane_data_file_name,
|
||||||
config.edge_segment_lookup_path,
|
config.edge_segment_lookup_path,
|
||||||
config.edge_penalty_path,
|
config.turn_weight_penalties_path,
|
||||||
|
config.turn_duration_penalties_path,
|
||||||
|
config.turn_penalties_index_path,
|
||||||
config.generate_edge_lookup);
|
config.generate_edge_lookup);
|
||||||
|
|
||||||
WriteTurnLaneData(config.turn_lane_descriptions_file_name);
|
WriteTurnLaneData(config.turn_lane_descriptions_file_name);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "extractor/extraction_node.hpp"
|
#include "extractor/extraction_node.hpp"
|
||||||
#include "extractor/extraction_way.hpp"
|
#include "extractor/extraction_way.hpp"
|
||||||
#include "extractor/guidance/road_classification.hpp"
|
#include "extractor/guidance/road_classification.hpp"
|
||||||
|
#include "extractor/profile_properties.hpp"
|
||||||
#include "extractor/restriction.hpp"
|
#include "extractor/restriction.hpp"
|
||||||
|
|
||||||
#include "util/for_each_pair.hpp"
|
#include "util/for_each_pair.hpp"
|
||||||
@ -18,6 +19,7 @@
|
|||||||
|
|
||||||
#include "osrm/coordinate.hpp"
|
#include "osrm/coordinate.hpp"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -31,8 +33,9 @@ namespace extractor
|
|||||||
using TurnLaneDescription = guidance::TurnLaneDescription;
|
using TurnLaneDescription = guidance::TurnLaneDescription;
|
||||||
namespace TurnLaneType = guidance::TurnLaneType;
|
namespace TurnLaneType = guidance::TurnLaneType;
|
||||||
|
|
||||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers)
|
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers_,
|
||||||
: external_memory(extraction_containers)
|
const ProfileProperties &properties)
|
||||||
|
: external_memory(extraction_containers_), fallback_to_duration(properties.fallback_to_duration)
|
||||||
{
|
{
|
||||||
// we reserved 0, 1, 2, 3 for the empty case
|
// we reserved 0, 1, 2, 3 for the empty case
|
||||||
string_map[MapKey("", "", "", "")] = 0;
|
string_map[MapKey("", "", "", "")] = 0;
|
||||||
@ -80,16 +83,18 @@ void ExtractorCallbacks::ProcessRestriction(
|
|||||||
*/
|
*/
|
||||||
void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const ExtractionWay &parsed_way)
|
void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const ExtractionWay &parsed_way)
|
||||||
{
|
{
|
||||||
if (((0 >= parsed_way.forward_speed) ||
|
if ((parsed_way.forward_travel_mode == TRAVEL_MODE_INACCESSIBLE &&
|
||||||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) &&
|
parsed_way.backward_travel_mode == TRAVEL_MODE_INACCESSIBLE) ||
|
||||||
((0 >= parsed_way.backward_speed) ||
|
(parsed_way.forward_speed <= 0 && parsed_way.backward_speed <= 0 &&
|
||||||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) &&
|
parsed_way.duration <= 0) ||
|
||||||
(0 >= parsed_way.duration))
|
(!fallback_to_duration && parsed_way.forward_rate <= 0 && parsed_way.backward_rate <= 0 &&
|
||||||
|
parsed_way.weight <= 0))
|
||||||
{ // Only true if the way is specified by the speed profile
|
{ // Only true if the way is specified by the speed profile
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input_way.nodes().size() <= 1)
|
const auto &nodes = input_way.nodes();
|
||||||
|
if (nodes.size() <= 1)
|
||||||
{ // safe-guard against broken data
|
{ // safe-guard against broken data
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -97,46 +102,63 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
if (std::numeric_limits<decltype(input_way.id())>::max() == input_way.id())
|
if (std::numeric_limits<decltype(input_way.id())>::max() == input_way.id())
|
||||||
{
|
{
|
||||||
util::Log(logDEBUG) << "found bogus way with id: " << input_way.id() << " of size "
|
util::Log(logDEBUG) << "found bogus way with id: " << input_way.id() << " of size "
|
||||||
<< input_way.nodes().size();
|
<< nodes.size();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InternalExtractorEdge::DurationData forward_duration_data;
|
||||||
|
InternalExtractorEdge::DurationData backward_duration_data;
|
||||||
InternalExtractorEdge::WeightData forward_weight_data;
|
InternalExtractorEdge::WeightData forward_weight_data;
|
||||||
InternalExtractorEdge::WeightData backward_weight_data;
|
InternalExtractorEdge::WeightData backward_weight_data;
|
||||||
|
|
||||||
if (0 < parsed_way.duration)
|
const auto toValueByEdgeOrByMeter =
|
||||||
|
[&nodes](const double by_way, const double by_meter) -> detail::ByEdgeOrByMeterValue {
|
||||||
|
if (by_way > 0)
|
||||||
{
|
{
|
||||||
const unsigned num_edges = (input_way.nodes().size() - 1);
|
// FIXME We divide by the number of edges here, but should rather consider
|
||||||
// FIXME We devide by the numer of nodes here, but should rather consider
|
// the length of each segment. We would either have to compute the length
|
||||||
// the length of each segment. We would eigther have to compute the length
|
|
||||||
// of the whole way here (we can't: no node coordinates) or push that back
|
// of the whole way here (we can't: no node coordinates) or push that back
|
||||||
// to the container and keep a reference to the way.
|
// to the container and keep a reference to the way.
|
||||||
forward_weight_data.duration = parsed_way.duration / num_edges;
|
const unsigned num_edges = (nodes.size() - 1);
|
||||||
forward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION;
|
return detail::ValueByEdge{by_way / num_edges};
|
||||||
backward_weight_data.duration = parsed_way.duration / num_edges;
|
|
||||||
backward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (parsed_way.forward_speed > 0 &&
|
return detail::ValueByMeter{by_meter};
|
||||||
parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
|
||||||
{
|
|
||||||
forward_weight_data.speed = parsed_way.forward_speed;
|
|
||||||
forward_weight_data.type = InternalExtractorEdge::WeightType::SPEED;
|
|
||||||
}
|
|
||||||
if (parsed_way.backward_speed > 0 &&
|
|
||||||
parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
|
||||||
{
|
|
||||||
backward_weight_data.speed = parsed_way.backward_speed;
|
|
||||||
backward_weight_data.type = InternalExtractorEdge::WeightType::SPEED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (forward_weight_data.type == InternalExtractorEdge::WeightType::INVALID &&
|
if (parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
||||||
backward_weight_data.type == InternalExtractorEdge::WeightType::INVALID)
|
|
||||||
{
|
{
|
||||||
util::Log(logDEBUG) << "found way with bogus speed, id: " << input_way.id();
|
BOOST_ASSERT(parsed_way.duration > 0 || parsed_way.forward_speed > 0);
|
||||||
return;
|
forward_duration_data =
|
||||||
|
toValueByEdgeOrByMeter(parsed_way.duration, parsed_way.forward_speed / 3.6);
|
||||||
|
// fallback to duration as weight
|
||||||
|
if (parsed_way.weight > 0 || parsed_way.forward_rate > 0)
|
||||||
|
{
|
||||||
|
forward_weight_data =
|
||||||
|
toValueByEdgeOrByMeter(parsed_way.weight, parsed_way.forward_rate);
|
||||||
|
}
|
||||||
|
else if (fallback_to_duration)
|
||||||
|
{
|
||||||
|
forward_weight_data = forward_duration_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(parsed_way.duration > 0 || parsed_way.backward_speed > 0);
|
||||||
|
backward_duration_data =
|
||||||
|
toValueByEdgeOrByMeter(parsed_way.duration, parsed_way.backward_speed / 3.6);
|
||||||
|
// fallback to duration as weight
|
||||||
|
if (parsed_way.weight > 0 || parsed_way.backward_rate > 0)
|
||||||
|
{
|
||||||
|
backward_weight_data =
|
||||||
|
toValueByEdgeOrByMeter(parsed_way.weight, parsed_way.backward_rate);
|
||||||
|
}
|
||||||
|
else if (fallback_to_duration)
|
||||||
|
{
|
||||||
|
backward_weight_data = backward_duration_data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto laneStringToDescription = [](const std::string &lane_string) -> TurnLaneDescription {
|
const auto laneStringToDescription = [](const std::string &lane_string) -> TurnLaneDescription {
|
||||||
@ -237,27 +259,23 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
|
|
||||||
const auto road_classification = parsed_way.road_classification;
|
const auto road_classification = parsed_way.road_classification;
|
||||||
|
|
||||||
const constexpr auto MAX_STRING_LENGTH = 255u;
|
const constexpr std::size_t MAX_STRING_LENGTH = 255u;
|
||||||
// Get the unique identifier for the street name, destination, and ref
|
// Get the unique identifier for the street name, destination, and ref
|
||||||
const auto name_iterator = string_map.find(
|
const auto name_iterator = string_map.find(
|
||||||
MapKey(parsed_way.name, parsed_way.destinations, parsed_way.ref, parsed_way.pronunciation));
|
MapKey(parsed_way.name, parsed_way.destinations, parsed_way.ref, parsed_way.pronunciation));
|
||||||
unsigned name_id = EMPTY_NAMEID;
|
auto name_id = EMPTY_NAMEID;
|
||||||
if (string_map.end() == name_iterator)
|
if (string_map.end() == name_iterator)
|
||||||
{
|
{
|
||||||
const auto name_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.name.size());
|
const auto name_length = std::min(MAX_STRING_LENGTH, parsed_way.name.size());
|
||||||
const auto destinations_length =
|
const auto destinations_length =
|
||||||
std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.destinations.size());
|
std::min(MAX_STRING_LENGTH, parsed_way.destinations.size());
|
||||||
const auto pronunciation_length =
|
const auto pronunciation_length =
|
||||||
std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.pronunciation.size());
|
std::min(MAX_STRING_LENGTH, parsed_way.pronunciation.size());
|
||||||
const auto ref_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.ref.size());
|
const auto ref_length = std::min(MAX_STRING_LENGTH, parsed_way.ref.size());
|
||||||
|
|
||||||
// name_offsets already has an offset of a new name, take the offset index as the name id
|
// name_offsets already has an offset of a new name, take the offset index as the name id
|
||||||
name_id = external_memory.name_offsets.size() - 1;
|
name_id = external_memory.name_offsets.size() - 1;
|
||||||
|
|
||||||
external_memory.name_char_data.reserve(external_memory.name_char_data.size() + name_length +
|
|
||||||
destinations_length + pronunciation_length +
|
|
||||||
ref_length);
|
|
||||||
|
|
||||||
std::copy(parsed_way.name.c_str(),
|
std::copy(parsed_way.name.c_str(),
|
||||||
parsed_way.name.c_str() + name_length,
|
parsed_way.name.c_str() + name_length,
|
||||||
std::back_inserter(external_memory.name_char_data));
|
std::back_inserter(external_memory.name_char_data));
|
||||||
@ -288,114 +306,85 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
name_id = name_iterator->second;
|
name_id = name_iterator->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool split_edge = (parsed_way.forward_speed > 0) &&
|
const bool in_forward_direction =
|
||||||
(TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) &&
|
(parsed_way.forward_speed > 0 || parsed_way.forward_rate > 0 || parsed_way.duration > 0 ||
|
||||||
(parsed_way.backward_speed > 0) &&
|
parsed_way.weight > 0) &&
|
||||||
(TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) &&
|
(parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
||||||
((parsed_way.forward_speed != parsed_way.backward_speed) ||
|
|
||||||
|
const bool in_backward_direction =
|
||||||
|
(parsed_way.backward_speed > 0 || parsed_way.backward_rate > 0 || parsed_way.duration > 0 ||
|
||||||
|
parsed_way.weight > 0) &&
|
||||||
|
(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
||||||
|
|
||||||
|
const bool split_edge = in_forward_direction && in_backward_direction &&
|
||||||
|
((parsed_way.forward_rate != parsed_way.backward_rate) ||
|
||||||
|
(parsed_way.forward_speed != parsed_way.backward_speed) ||
|
||||||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode) ||
|
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode) ||
|
||||||
(turn_lane_id_forward != turn_lane_id_backward));
|
(turn_lane_id_forward != turn_lane_id_backward));
|
||||||
|
|
||||||
external_memory.used_node_id_list.reserve(external_memory.used_node_id_list.size() +
|
if (in_forward_direction)
|
||||||
input_way.nodes().size());
|
|
||||||
|
|
||||||
std::transform(input_way.nodes().begin(),
|
|
||||||
input_way.nodes().end(),
|
|
||||||
std::back_inserter(external_memory.used_node_id_list),
|
|
||||||
[](const osmium::NodeRef &ref) {
|
|
||||||
return OSMNodeID{static_cast<std::uint64_t>(ref.ref())};
|
|
||||||
});
|
|
||||||
|
|
||||||
const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode;
|
|
||||||
|
|
||||||
// traverse way in reverse in this case
|
|
||||||
if (is_opposite_way)
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(split_edge == false);
|
|
||||||
BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
|
||||||
util::for_each_pair(
|
util::for_each_pair(
|
||||||
input_way.nodes().crbegin(),
|
nodes.cbegin(),
|
||||||
input_way.nodes().crend(),
|
nodes.cend(),
|
||||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
|
||||||
external_memory.all_edges_list.push_back(
|
|
||||||
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
|
||||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
|
||||||
name_id,
|
|
||||||
backward_weight_data,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
parsed_way.roundabout,
|
|
||||||
parsed_way.circular,
|
|
||||||
parsed_way.is_startpoint,
|
|
||||||
parsed_way.backward_travel_mode,
|
|
||||||
false,
|
|
||||||
turn_lane_id_backward,
|
|
||||||
road_classification));
|
|
||||||
});
|
|
||||||
|
|
||||||
external_memory.way_start_end_id_list.push_back(
|
|
||||||
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
|
|
||||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes().back().ref())},
|
|
||||||
OSMNodeID{
|
|
||||||
static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())},
|
|
||||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[1].ref())},
|
|
||||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const bool forward_only =
|
|
||||||
split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode;
|
|
||||||
util::for_each_pair(
|
|
||||||
input_way.nodes().cbegin(),
|
|
||||||
input_way.nodes().cend(),
|
|
||||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
||||||
external_memory.all_edges_list.push_back(
|
external_memory.all_edges_list.push_back(
|
||||||
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
||||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||||
name_id,
|
name_id,
|
||||||
forward_weight_data,
|
forward_weight_data,
|
||||||
|
forward_duration_data,
|
||||||
true,
|
true,
|
||||||
!forward_only,
|
in_backward_direction && !split_edge,
|
||||||
parsed_way.roundabout,
|
parsed_way.roundabout,
|
||||||
parsed_way.circular,
|
parsed_way.circular,
|
||||||
parsed_way.is_startpoint,
|
parsed_way.is_startpoint,
|
||||||
parsed_way.forward_travel_mode,
|
parsed_way.forward_travel_mode,
|
||||||
split_edge,
|
split_edge,
|
||||||
turn_lane_id_forward,
|
turn_lane_id_forward,
|
||||||
road_classification));
|
road_classification,
|
||||||
|
{}));
|
||||||
});
|
});
|
||||||
if (split_edge)
|
}
|
||||||
|
|
||||||
|
if (in_backward_direction || split_edge)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
|
||||||
util::for_each_pair(
|
util::for_each_pair(
|
||||||
input_way.nodes().cbegin(),
|
nodes.cbegin(),
|
||||||
input_way.nodes().cend(),
|
nodes.cend(),
|
||||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
||||||
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
external_memory.all_edges_list.push_back(
|
||||||
OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
||||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||||
name_id,
|
name_id,
|
||||||
backward_weight_data,
|
backward_weight_data,
|
||||||
|
backward_duration_data,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
parsed_way.roundabout,
|
parsed_way.roundabout,
|
||||||
parsed_way.circular,
|
parsed_way.circular,
|
||||||
parsed_way.is_startpoint,
|
parsed_way.is_startpoint,
|
||||||
parsed_way.backward_travel_mode,
|
parsed_way.backward_travel_mode,
|
||||||
true,
|
split_edge,
|
||||||
turn_lane_id_backward,
|
turn_lane_id_backward,
|
||||||
road_classification));
|
road_classification,
|
||||||
|
{}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::transform(nodes.begin(),
|
||||||
|
nodes.end(),
|
||||||
|
std::back_inserter(external_memory.used_node_id_list),
|
||||||
|
[](const osmium::NodeRef &ref) {
|
||||||
|
return OSMNodeID{static_cast<std::uint64_t>(ref.ref())};
|
||||||
|
});
|
||||||
|
|
||||||
external_memory.way_start_end_id_list.push_back(
|
external_memory.way_start_end_id_list.push_back(
|
||||||
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
|
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
|
||||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes().back().ref())},
|
OSMNodeID{static_cast<std::uint64_t>(nodes[0].ref())},
|
||||||
OSMNodeID{
|
OSMNodeID{static_cast<std::uint64_t>(nodes[1].ref())},
|
||||||
static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())},
|
OSMNodeID{static_cast<std::uint64_t>(nodes[nodes.size() - 2].ref())},
|
||||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[1].ref())},
|
OSMNodeID{static_cast<std::uint64_t>(nodes.back().ref())}});
|
||||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guidance::LaneDescriptionMap &&ExtractorCallbacks::moveOutLaneDescriptionMap()
|
guidance::LaneDescriptionMap &&ExtractorCallbacks::moveOutLaneDescriptionMap()
|
||||||
|
@ -119,22 +119,30 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
if (has_node_penalty)
|
if (has_node_penalty)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get distances before graph is modified
|
// Get weights before graph is modified
|
||||||
const int forward_weight1 = graph.GetEdgeData(forward_e1).distance;
|
const EdgeWeight forward_weight1 = fwd_edge_data1.weight;
|
||||||
const int forward_weight2 = graph.GetEdgeData(forward_e2).distance;
|
const EdgeWeight forward_weight2 = fwd_edge_data2.weight;
|
||||||
|
const EdgeWeight forward_duration1 = fwd_edge_data1.duration;
|
||||||
|
const EdgeWeight forward_duration2 = fwd_edge_data2.duration;
|
||||||
|
|
||||||
BOOST_ASSERT(0 != forward_weight1);
|
BOOST_ASSERT(0 != forward_weight1);
|
||||||
BOOST_ASSERT(0 != forward_weight2);
|
BOOST_ASSERT(0 != forward_weight2);
|
||||||
|
|
||||||
const int reverse_weight1 = graph.GetEdgeData(reverse_e1).distance;
|
const EdgeWeight reverse_weight1 = rev_edge_data1.weight;
|
||||||
const int reverse_weight2 = graph.GetEdgeData(reverse_e2).distance;
|
const EdgeWeight reverse_weight2 = rev_edge_data2.weight;
|
||||||
|
const EdgeWeight reverse_duration1 = rev_edge_data1.duration;
|
||||||
|
const EdgeWeight reverse_duration2 = rev_edge_data2.duration;
|
||||||
|
|
||||||
BOOST_ASSERT(0 != reverse_weight1);
|
BOOST_ASSERT(0 != reverse_weight1);
|
||||||
BOOST_ASSERT(0 != reverse_weight2);
|
BOOST_ASSERT(0 != reverse_weight2);
|
||||||
|
|
||||||
// add weight of e2's to e1
|
// add weight of e2's to e1
|
||||||
graph.GetEdgeData(forward_e1).distance += fwd_edge_data2.distance;
|
graph.GetEdgeData(forward_e1).weight += forward_weight2;
|
||||||
graph.GetEdgeData(reverse_e1).distance += rev_edge_data2.distance;
|
graph.GetEdgeData(reverse_e1).weight += reverse_weight2;
|
||||||
|
|
||||||
|
// add duration of e2's to e1
|
||||||
|
graph.GetEdgeData(forward_e1).duration += forward_duration2;
|
||||||
|
graph.GetEdgeData(reverse_e1).duration += reverse_duration2;
|
||||||
|
|
||||||
// extend e1's to targets of e2's
|
// extend e1's to targets of e2's
|
||||||
graph.SetTarget(forward_e1, node_w);
|
graph.SetTarget(forward_e1, node_w);
|
||||||
@ -196,10 +204,22 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
restriction_map.FixupArrivingTurnRestriction(node_w, node_v, node_u, graph);
|
restriction_map.FixupArrivingTurnRestriction(node_w, node_v, node_u, graph);
|
||||||
|
|
||||||
// store compressed geometry in container
|
// store compressed geometry in container
|
||||||
geometry_compressor.CompressEdge(
|
geometry_compressor.CompressEdge(forward_e1,
|
||||||
forward_e1, forward_e2, node_v, node_w, forward_weight1, forward_weight2);
|
forward_e2,
|
||||||
geometry_compressor.CompressEdge(
|
node_v,
|
||||||
reverse_e1, reverse_e2, node_v, node_u, reverse_weight1, reverse_weight2);
|
node_w,
|
||||||
|
forward_weight1,
|
||||||
|
forward_weight2,
|
||||||
|
forward_duration1,
|
||||||
|
forward_duration2);
|
||||||
|
geometry_compressor.CompressEdge(reverse_e1,
|
||||||
|
reverse_e2,
|
||||||
|
node_v,
|
||||||
|
node_u,
|
||||||
|
reverse_weight1,
|
||||||
|
reverse_weight2,
|
||||||
|
reverse_duration1,
|
||||||
|
reverse_duration2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,7 +235,7 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
{
|
{
|
||||||
const EdgeData &data = graph.GetEdgeData(edge_id);
|
const EdgeData &data = graph.GetEdgeData(edge_id);
|
||||||
const NodeID target = graph.GetTarget(edge_id);
|
const NodeID target = graph.GetTarget(edge_id);
|
||||||
geometry_compressor.AddUncompressedEdge(edge_id, target, data.distance);
|
geometry_compressor.AddUncompressedEdge(edge_id, target, data.weight, data.duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ bool findPreviousIntersection(const NodeID node_v,
|
|||||||
* PREVIOUS_ID. To verify that find, we check the intersection using our PREVIOUS_ID candidate
|
* PREVIOUS_ID. To verify that find, we check the intersection using our PREVIOUS_ID candidate
|
||||||
* to check the intersection at NODE for via_edge
|
* to check the intersection at NODE for via_edge
|
||||||
*/
|
*/
|
||||||
const constexpr double COMBINE_DISTANCE_CUTOFF = 30;
|
const constexpr double COMBINE_WEIGHT_CUTOFF = 30;
|
||||||
|
|
||||||
const auto coordinate_extractor = intersection_generator.GetCoordinateExtractor();
|
const auto coordinate_extractor = intersection_generator.GetCoordinateExtractor();
|
||||||
const auto coordinates_along_via_edge =
|
const auto coordinates_along_via_edge =
|
||||||
@ -53,7 +53,7 @@ bool findPreviousIntersection(const NodeID node_v,
|
|||||||
|
|
||||||
// we check if via-edge is too short. In this case the previous turn cannot influence the turn
|
// we check if via-edge is too short. In this case the previous turn cannot influence the turn
|
||||||
// at via_edge and the intersection at NODE_W
|
// at via_edge and the intersection at NODE_W
|
||||||
if (via_edge_length > COMBINE_DISTANCE_CUTOFF)
|
if (via_edge_length > COMBINE_WEIGHT_CUTOFF)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Node -> Via_Edge -> Intersection[0 == UTURN] -> reverse_of(via_edge) -> Intersection at
|
// Node -> Via_Edge -> Intersection[0 == UTURN] -> reverse_of(via_edge) -> Intersection at
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include "extractor/external_memory_node.hpp"
|
#include "extractor/external_memory_node.hpp"
|
||||||
#include "extractor/extraction_helper_functions.hpp"
|
#include "extractor/extraction_helper_functions.hpp"
|
||||||
#include "extractor/extraction_node.hpp"
|
#include "extractor/extraction_node.hpp"
|
||||||
|
#include "extractor/extraction_segment.hpp"
|
||||||
|
#include "extractor/extraction_turn.hpp"
|
||||||
#include "extractor/extraction_way.hpp"
|
#include "extractor/extraction_way.hpp"
|
||||||
#include "extractor/internal_extractor_edge.hpp"
|
#include "extractor/internal_extractor_edge.hpp"
|
||||||
#include "extractor/profile_properties.hpp"
|
#include "extractor/profile_properties.hpp"
|
||||||
@ -140,6 +142,80 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
"connectivity",
|
"connectivity",
|
||||||
extractor::guidance::RoadPriorityClass::CONNECTIVITY);
|
extractor::guidance::RoadPriorityClass::CONNECTIVITY);
|
||||||
|
|
||||||
|
context.state.new_enum("turn_type",
|
||||||
|
"invalid",
|
||||||
|
extractor::guidance::TurnType::Invalid,
|
||||||
|
"new_name",
|
||||||
|
extractor::guidance::TurnType::NewName,
|
||||||
|
"continue",
|
||||||
|
extractor::guidance::TurnType::Continue,
|
||||||
|
"turn",
|
||||||
|
extractor::guidance::TurnType::Turn,
|
||||||
|
"merge",
|
||||||
|
extractor::guidance::TurnType::Merge,
|
||||||
|
"on_ramp",
|
||||||
|
extractor::guidance::TurnType::OnRamp,
|
||||||
|
"off_ramp",
|
||||||
|
extractor::guidance::TurnType::OffRamp,
|
||||||
|
"fork",
|
||||||
|
extractor::guidance::TurnType::Fork,
|
||||||
|
"end_of_road",
|
||||||
|
extractor::guidance::TurnType::EndOfRoad,
|
||||||
|
"notification",
|
||||||
|
extractor::guidance::TurnType::Notification,
|
||||||
|
"enter_roundabout",
|
||||||
|
extractor::guidance::TurnType::EnterRoundabout,
|
||||||
|
"enter_and_exit_roundabout",
|
||||||
|
extractor::guidance::TurnType::EnterAndExitRoundabout,
|
||||||
|
"enter_rotary",
|
||||||
|
extractor::guidance::TurnType::EnterRotary,
|
||||||
|
"enter_and_exit_rotary",
|
||||||
|
extractor::guidance::TurnType::EnterAndExitRotary,
|
||||||
|
"enter_roundabout_intersection",
|
||||||
|
extractor::guidance::TurnType::EnterRoundaboutIntersection,
|
||||||
|
"enter_and_exit_roundabout_intersection",
|
||||||
|
extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection,
|
||||||
|
"use_lane",
|
||||||
|
extractor::guidance::TurnType::UseLane,
|
||||||
|
"no_turn",
|
||||||
|
extractor::guidance::TurnType::NoTurn,
|
||||||
|
"suppressed",
|
||||||
|
extractor::guidance::TurnType::Suppressed,
|
||||||
|
"enter_roundabout_at_exit",
|
||||||
|
extractor::guidance::TurnType::EnterRoundaboutAtExit,
|
||||||
|
"exit_roundabout",
|
||||||
|
extractor::guidance::TurnType::ExitRoundabout,
|
||||||
|
"enter_rotary_at_exit",
|
||||||
|
extractor::guidance::TurnType::EnterRotaryAtExit,
|
||||||
|
"exit_rotary",
|
||||||
|
extractor::guidance::TurnType::ExitRotary,
|
||||||
|
"enter_roundabout_intersection_at_exit",
|
||||||
|
extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit,
|
||||||
|
"exit_roundabout_intersection",
|
||||||
|
extractor::guidance::TurnType::ExitRoundaboutIntersection,
|
||||||
|
"stay_on_roundabout",
|
||||||
|
extractor::guidance::TurnType::StayOnRoundabout,
|
||||||
|
"sliproad",
|
||||||
|
extractor::guidance::TurnType::Sliproad);
|
||||||
|
|
||||||
|
context.state.new_enum("direction_modifier",
|
||||||
|
"u_turn",
|
||||||
|
extractor::guidance::DirectionModifier::UTurn,
|
||||||
|
"sharp_right",
|
||||||
|
extractor::guidance::DirectionModifier::SharpRight,
|
||||||
|
"right",
|
||||||
|
extractor::guidance::DirectionModifier::Right,
|
||||||
|
"slight_right",
|
||||||
|
extractor::guidance::DirectionModifier::SlightRight,
|
||||||
|
"straight",
|
||||||
|
extractor::guidance::DirectionModifier::Straight,
|
||||||
|
"slight_left",
|
||||||
|
extractor::guidance::DirectionModifier::SlightLeft,
|
||||||
|
"left",
|
||||||
|
extractor::guidance::DirectionModifier::Left,
|
||||||
|
"sharp_left",
|
||||||
|
extractor::guidance::DirectionModifier::SharpLeft);
|
||||||
|
|
||||||
context.state.new_usertype<SourceContainer>("sources",
|
context.state.new_usertype<SourceContainer>("sources",
|
||||||
"load",
|
"load",
|
||||||
&SourceContainer::LoadRasterSource,
|
&SourceContainer::LoadRasterSource,
|
||||||
@ -156,8 +232,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
sol::property(&ProfileProperties::GetTrafficSignalPenalty,
|
sol::property(&ProfileProperties::GetTrafficSignalPenalty,
|
||||||
&ProfileProperties::SetTrafficSignalPenalty),
|
&ProfileProperties::SetTrafficSignalPenalty),
|
||||||
"u_turn_penalty",
|
"u_turn_penalty",
|
||||||
sol::property(&ProfileProperties::GetUturnPenalty, //
|
sol::property(&ProfileProperties::GetUturnPenalty, &ProfileProperties::SetUturnPenalty),
|
||||||
&ProfileProperties::SetUturnPenalty),
|
|
||||||
"max_speed_for_map_matching",
|
"max_speed_for_map_matching",
|
||||||
sol::property(&ProfileProperties::GetMaxSpeedForMapMatching,
|
sol::property(&ProfileProperties::GetMaxSpeedForMapMatching,
|
||||||
&ProfileProperties::SetMaxSpeedForMapMatching),
|
&ProfileProperties::SetMaxSpeedForMapMatching),
|
||||||
@ -166,7 +241,11 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
"use_turn_restrictions",
|
"use_turn_restrictions",
|
||||||
&ProfileProperties::use_turn_restrictions,
|
&ProfileProperties::use_turn_restrictions,
|
||||||
"left_hand_driving",
|
"left_hand_driving",
|
||||||
&ProfileProperties::left_hand_driving);
|
&ProfileProperties::left_hand_driving,
|
||||||
|
"weight_precision",
|
||||||
|
&ProfileProperties::weight_precision,
|
||||||
|
"weight_name",
|
||||||
|
sol::property(&ProfileProperties::SetWeightName, &ProfileProperties::GetWeightName));
|
||||||
|
|
||||||
context.state.new_usertype<std::vector<std::string>>(
|
context.state.new_usertype<std::vector<std::string>>(
|
||||||
"vector",
|
"vector",
|
||||||
@ -233,6 +312,10 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
&ExtractionWay::forward_speed,
|
&ExtractionWay::forward_speed,
|
||||||
"backward_speed",
|
"backward_speed",
|
||||||
&ExtractionWay::backward_speed,
|
&ExtractionWay::backward_speed,
|
||||||
|
"forward_rate",
|
||||||
|
&ExtractionWay::forward_rate,
|
||||||
|
"backward_rate",
|
||||||
|
&ExtractionWay::backward_rate,
|
||||||
"name",
|
"name",
|
||||||
sol::property(&ExtractionWay::GetName, &ExtractionWay::SetName),
|
sol::property(&ExtractionWay::GetName, &ExtractionWay::SetName),
|
||||||
"ref",
|
"ref",
|
||||||
@ -253,6 +336,8 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
&ExtractionWay::is_startpoint,
|
&ExtractionWay::is_startpoint,
|
||||||
"duration",
|
"duration",
|
||||||
&ExtractionWay::duration,
|
&ExtractionWay::duration,
|
||||||
|
"weight",
|
||||||
|
&ExtractionWay::weight,
|
||||||
"road_classification",
|
"road_classification",
|
||||||
&ExtractionWay::road_classification,
|
&ExtractionWay::road_classification,
|
||||||
"forward_mode",
|
"forward_mode",
|
||||||
@ -260,17 +345,45 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
"backward_mode",
|
"backward_mode",
|
||||||
sol::property(&ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode));
|
sol::property(&ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode));
|
||||||
|
|
||||||
|
context.state.new_usertype<ExtractionSegment>("ExtractionSegment",
|
||||||
|
"source",
|
||||||
|
&ExtractionSegment::source,
|
||||||
|
"target",
|
||||||
|
&ExtractionSegment::target,
|
||||||
|
"distance",
|
||||||
|
&ExtractionSegment::distance,
|
||||||
|
"weight",
|
||||||
|
&ExtractionSegment::weight,
|
||||||
|
"duration",
|
||||||
|
&ExtractionSegment::duration);
|
||||||
|
|
||||||
|
context.state.new_usertype<ExtractionTurn>("ExtractionTurn",
|
||||||
|
"angle",
|
||||||
|
&ExtractionTurn::angle,
|
||||||
|
"turn_type",
|
||||||
|
&ExtractionTurn::turn_type,
|
||||||
|
"direction_modifier",
|
||||||
|
&ExtractionTurn::direction_modifier,
|
||||||
|
"has_traffic_light",
|
||||||
|
&ExtractionTurn::has_traffic_light,
|
||||||
|
"weight",
|
||||||
|
&ExtractionTurn::weight,
|
||||||
|
"duration",
|
||||||
|
&ExtractionTurn::duration);
|
||||||
|
|
||||||
// Keep in mind .location is undefined since we're not using libosmium's location cache
|
// Keep in mind .location is undefined since we're not using libosmium's location cache
|
||||||
context.state.new_usertype<osmium::NodeRef>("NodeRef", "id", &osmium::NodeRef::ref);
|
context.state.new_usertype<osmium::NodeRef>("NodeRef", "id", &osmium::NodeRef::ref);
|
||||||
|
|
||||||
context.state.new_usertype<InternalExtractorEdge>("EdgeSource",
|
context.state.new_usertype<InternalExtractorEdge>("EdgeSource",
|
||||||
"source_coordinate",
|
"source_coordinate",
|
||||||
&InternalExtractorEdge::source_coordinate,
|
&InternalExtractorEdge::source_coordinate,
|
||||||
"weight_data",
|
"weight",
|
||||||
&InternalExtractorEdge::weight_data);
|
&InternalExtractorEdge::weight_data,
|
||||||
|
"duration",
|
||||||
|
&InternalExtractorEdge::duration_data);
|
||||||
|
|
||||||
context.state.new_usertype<InternalExtractorEdge::WeightData>(
|
// context.state.new_usertype<InternalExtractorEdge::WeightData>(
|
||||||
"WeightData", "speed", &InternalExtractorEdge::WeightData::speed);
|
// "WeightData", "weight", &InternalExtractorEdge::WeightData::weight_data);
|
||||||
|
|
||||||
context.state.new_usertype<ExternalMemoryNode>("EdgeTarget",
|
context.state.new_usertype<ExternalMemoryNode>("EdgeTarget",
|
||||||
"lon",
|
"lon",
|
||||||
@ -307,6 +420,8 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
context.has_node_function = node_function.valid();
|
context.has_node_function = node_function.valid();
|
||||||
context.has_way_function = way_function.valid();
|
context.has_way_function = way_function.valid();
|
||||||
context.has_segment_function = segment_function.valid();
|
context.has_segment_function = segment_function.valid();
|
||||||
|
|
||||||
|
// Check profile API version
|
||||||
auto maybe_version = context.state.get<sol::optional<int>>("api_version");
|
auto maybe_version = context.state.get<sol::optional<int>>("api_version");
|
||||||
if (maybe_version)
|
if (maybe_version)
|
||||||
{
|
{
|
||||||
@ -321,6 +436,18 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
" to " + std::to_string(SUPPORTED_MAX_API_VERSION) +
|
" to " + std::to_string(SUPPORTED_MAX_API_VERSION) +
|
||||||
" are supported." + SOURCE_REF);
|
" are supported." + SOURCE_REF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert that version-dependent properties were not changed by profile
|
||||||
|
switch (context.api_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
BOOST_ASSERT(context.properties.GetUturnPenalty() == 0);
|
||||||
|
BOOST_ASSERT(context.properties.GetTrafficSignalPenalty() == 0);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
BOOST_ASSERT(context.properties.GetWeightName() == "duration");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProfileProperties &Sol2ScriptingEnvironment::GetProfileProperties()
|
const ProfileProperties &Sol2ScriptingEnvironment::GetProfileProperties()
|
||||||
@ -437,37 +564,73 @@ void Sol2ScriptingEnvironment::SetupSources()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Sol2ScriptingEnvironment::GetTurnPenalty(const double angle)
|
void Sol2ScriptingEnvironment::ProcessTurn(ExtractionTurn &turn)
|
||||||
{
|
{
|
||||||
auto &context = GetSol2Context();
|
auto &context = GetSol2Context();
|
||||||
|
|
||||||
sol::function turn_function = context.state["turn_function"];
|
sol::function turn_function = context.state["turn_function"];
|
||||||
|
switch (context.api_version)
|
||||||
if (turn_function.valid())
|
|
||||||
{
|
{
|
||||||
const double penalty = turn_function(angle);
|
case 1:
|
||||||
|
if (context.has_turn_penalty_function)
|
||||||
|
{
|
||||||
|
turn_function(turn);
|
||||||
|
|
||||||
BOOST_ASSERT(penalty < std::numeric_limits<int32_t>::max());
|
// Turn weight falls back to the duration value in deciseconds
|
||||||
BOOST_ASSERT(penalty > std::numeric_limits<int32_t>::min());
|
// or uses the extracted unit-less weight value
|
||||||
|
if (context.properties.fallback_to_duration)
|
||||||
return penalty;
|
turn.weight = turn.duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
break;
|
||||||
|
case 0:
|
||||||
|
if (context.has_turn_penalty_function)
|
||||||
|
{
|
||||||
|
if (turn.turn_type != guidance::TurnType::NoTurn)
|
||||||
|
{
|
||||||
|
// Get turn duration and convert deci-seconds to seconds
|
||||||
|
turn.duration = static_cast<double>(turn_function(turn.angle)) / 10.;
|
||||||
|
BOOST_ASSERT(turn.weight == 0);
|
||||||
|
|
||||||
|
// add U-turn penalty
|
||||||
|
if (turn.direction_modifier == guidance::DirectionModifier::UTurn)
|
||||||
|
turn.duration += context.properties.GetUturnPenalty();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use zero turn penalty if it is not an actual turn. This heuristic is necessary
|
||||||
|
// since OSRM cannot handle looping roads/parallel roads
|
||||||
|
turn.duration = 0.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add traffic light penalty, back-compatibility of api_version=0
|
||||||
|
if (turn.has_traffic_light)
|
||||||
|
turn.duration += context.properties.GetTrafficSignalPenalty();
|
||||||
|
|
||||||
|
// Turn weight falls back to the duration value in deciseconds
|
||||||
|
turn.weight = turn.duration;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sol2ScriptingEnvironment::ProcessSegment(const osrm::util::Coordinate &source,
|
void Sol2ScriptingEnvironment::ProcessSegment(ExtractionSegment &segment)
|
||||||
const osrm::util::Coordinate &target,
|
|
||||||
double distance,
|
|
||||||
InternalExtractorEdge::WeightData &weight)
|
|
||||||
{
|
{
|
||||||
auto &context = GetSol2Context();
|
auto &context = GetSol2Context();
|
||||||
|
|
||||||
sol::function segment_function = context.state["segment_function"];
|
if (context.has_segment_function)
|
||||||
|
|
||||||
if (segment_function.valid())
|
|
||||||
{
|
{
|
||||||
segment_function(source, target, distance, weight);
|
sol::function segment_function = context.state["segment_function"];
|
||||||
|
switch (context.api_version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
segment_function(segment);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
segment_function(segment.source, segment.target, segment.distance, segment.duration);
|
||||||
|
segment.weight = segment.duration; // back-compatibility fallback to duration
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +279,22 @@ void Storage::PopulateLayout(DataLayout &layout)
|
|||||||
layout.SetBlockSize<unsigned>(DataLayout::CORE_MARKER, number_of_core_markers);
|
layout.SetBlockSize<unsigned>(DataLayout::CORE_MARKER, number_of_core_markers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load turn weight penalties
|
||||||
|
{
|
||||||
|
io::FileReader turn_weight_penalties_file(config.turn_weight_penalties_path,
|
||||||
|
io::FileReader::HasNoFingerprint);
|
||||||
|
const auto number_of_penalties = turn_weight_penalties_file.ReadElementCount64();
|
||||||
|
layout.SetBlockSize<TurnPenalty>(DataLayout::TURN_WEIGHT_PENALTIES, number_of_penalties);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load turn duration penalties
|
||||||
|
{
|
||||||
|
io::FileReader turn_duration_penalties_file(config.turn_duration_penalties_path,
|
||||||
|
io::FileReader::HasNoFingerprint);
|
||||||
|
const auto number_of_penalties = turn_duration_penalties_file.ReadElementCount64();
|
||||||
|
layout.SetBlockSize<TurnPenalty>(DataLayout::TURN_DURATION_PENALTIES, number_of_penalties);
|
||||||
|
}
|
||||||
|
|
||||||
// load coordinate size
|
// load coordinate size
|
||||||
{
|
{
|
||||||
io::FileReader node_file(config.nodes_data_path, io::FileReader::HasNoFingerprint);
|
io::FileReader node_file(config.nodes_data_path, io::FileReader::HasNoFingerprint);
|
||||||
@ -307,6 +323,10 @@ void Storage::PopulateLayout(DataLayout &layout)
|
|||||||
number_of_compressed_geometries);
|
number_of_compressed_geometries);
|
||||||
layout.SetBlockSize<EdgeWeight>(DataLayout::GEOMETRIES_REV_WEIGHT_LIST,
|
layout.SetBlockSize<EdgeWeight>(DataLayout::GEOMETRIES_REV_WEIGHT_LIST,
|
||||||
number_of_compressed_geometries);
|
number_of_compressed_geometries);
|
||||||
|
layout.SetBlockSize<EdgeWeight>(DataLayout::GEOMETRIES_FWD_DURATION_LIST,
|
||||||
|
number_of_compressed_geometries);
|
||||||
|
layout.SetBlockSize<EdgeWeight>(DataLayout::GEOMETRIES_REV_DURATION_LIST,
|
||||||
|
number_of_compressed_geometries);
|
||||||
}
|
}
|
||||||
|
|
||||||
// load datasource sizes. This file is optional, and it's non-fatal if it doesn't
|
// load datasource sizes. This file is optional, and it's non-fatal if it doesn't
|
||||||
@ -582,6 +602,18 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
|||||||
BOOST_ASSERT(geometry_node_lists_count ==
|
BOOST_ASSERT(geometry_node_lists_count ==
|
||||||
layout.num_entries[DataLayout::GEOMETRIES_REV_WEIGHT_LIST]);
|
layout.num_entries[DataLayout::GEOMETRIES_REV_WEIGHT_LIST]);
|
||||||
geometry_input_file.ReadInto(geometries_rev_weight_list_ptr, geometry_node_lists_count);
|
geometry_input_file.ReadInto(geometries_rev_weight_list_ptr, geometry_node_lists_count);
|
||||||
|
|
||||||
|
const auto geometries_fwd_duration_list_ptr = layout.GetBlockPtr<EdgeWeight, true>(
|
||||||
|
memory_ptr, DataLayout::GEOMETRIES_FWD_DURATION_LIST);
|
||||||
|
BOOST_ASSERT(geometry_node_lists_count ==
|
||||||
|
layout.num_entries[DataLayout::GEOMETRIES_FWD_DURATION_LIST]);
|
||||||
|
geometry_input_file.ReadInto(geometries_fwd_duration_list_ptr, geometry_node_lists_count);
|
||||||
|
|
||||||
|
const auto geometries_rev_duration_list_ptr = layout.GetBlockPtr<EdgeWeight, true>(
|
||||||
|
memory_ptr, DataLayout::GEOMETRIES_REV_DURATION_LIST);
|
||||||
|
BOOST_ASSERT(geometry_node_lists_count ==
|
||||||
|
layout.num_entries[DataLayout::GEOMETRIES_REV_DURATION_LIST]);
|
||||||
|
geometry_input_file.ReadInto(geometries_rev_duration_list_ptr, geometry_node_lists_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -666,6 +698,26 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
|||||||
layout.num_entries[DataLayout::COORDINATE_LIST]);
|
layout.num_entries[DataLayout::COORDINATE_LIST]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load turn weight penalties
|
||||||
|
{
|
||||||
|
io::FileReader turn_weight_penalties_file(config.turn_weight_penalties_path,
|
||||||
|
io::FileReader::HasNoFingerprint);
|
||||||
|
const auto number_of_penalties = turn_weight_penalties_file.ReadElementCount64();
|
||||||
|
const auto turn_weight_penalties_ptr =
|
||||||
|
layout.GetBlockPtr<TurnPenalty, true>(memory_ptr, DataLayout::TURN_WEIGHT_PENALTIES);
|
||||||
|
turn_weight_penalties_file.ReadInto(turn_weight_penalties_ptr, number_of_penalties);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load turn duration penalties
|
||||||
|
{
|
||||||
|
io::FileReader turn_duration_penalties_file(config.turn_duration_penalties_path,
|
||||||
|
io::FileReader::HasNoFingerprint);
|
||||||
|
const auto number_of_penalties = turn_duration_penalties_file.ReadElementCount64();
|
||||||
|
const auto turn_duration_penalties_ptr =
|
||||||
|
layout.GetBlockPtr<TurnPenalty, true>(memory_ptr, DataLayout::TURN_DURATION_PENALTIES);
|
||||||
|
turn_duration_penalties_file.ReadInto(turn_duration_penalties_ptr, number_of_penalties);
|
||||||
|
}
|
||||||
|
|
||||||
// store timestamp
|
// store timestamp
|
||||||
{
|
{
|
||||||
io::FileReader timestamp_file(config.timestamp_path, io::FileReader::HasNoFingerprint);
|
io::FileReader timestamp_file(config.timestamp_path, io::FileReader::HasNoFingerprint);
|
||||||
|
@ -13,6 +13,8 @@ StorageConfig::StorageConfig(const boost::filesystem::path &base)
|
|||||||
hsgr_data_path{base.string() + ".hsgr"}, nodes_data_path{base.string() + ".nodes"},
|
hsgr_data_path{base.string() + ".hsgr"}, nodes_data_path{base.string() + ".nodes"},
|
||||||
edges_data_path{base.string() + ".edges"}, core_data_path{base.string() + ".core"},
|
edges_data_path{base.string() + ".edges"}, core_data_path{base.string() + ".core"},
|
||||||
geometries_path{base.string() + ".geometry"}, timestamp_path{base.string() + ".timestamp"},
|
geometries_path{base.string() + ".geometry"}, timestamp_path{base.string() + ".timestamp"},
|
||||||
|
turn_weight_penalties_path{base.string() + ".turn_weight_penalties"},
|
||||||
|
turn_duration_penalties_path{base.string() + ".turn_duration_penalties"},
|
||||||
datasource_names_path{base.string() + ".datasource_names"},
|
datasource_names_path{base.string() + ".datasource_names"},
|
||||||
datasource_indexes_path{base.string() + ".datasource_indexes"},
|
datasource_indexes_path{base.string() + ".datasource_indexes"},
|
||||||
names_data_path{base.string() + ".names"}, properties_path{base.string() + ".properties"},
|
names_data_path{base.string() + ".names"}, properties_path{base.string() + ".properties"},
|
||||||
@ -23,7 +25,7 @@ StorageConfig::StorageConfig(const boost::filesystem::path &base)
|
|||||||
|
|
||||||
bool StorageConfig::IsValid() const
|
bool StorageConfig::IsValid() const
|
||||||
{
|
{
|
||||||
const constexpr auto num_files = 13;
|
const constexpr auto num_files = 15;
|
||||||
const boost::filesystem::path paths[num_files] = {ram_index_path,
|
const boost::filesystem::path paths[num_files] = {ram_index_path,
|
||||||
file_index_path,
|
file_index_path,
|
||||||
hsgr_data_path,
|
hsgr_data_path,
|
||||||
@ -32,6 +34,8 @@ bool StorageConfig::IsValid() const
|
|||||||
core_data_path,
|
core_data_path,
|
||||||
geometries_path,
|
geometries_path,
|
||||||
timestamp_path,
|
timestamp_path,
|
||||||
|
turn_weight_penalties_path,
|
||||||
|
turn_duration_penalties_path,
|
||||||
datasource_indexes_path,
|
datasource_indexes_path,
|
||||||
datasource_indexes_path,
|
datasource_indexes_path,
|
||||||
names_data_path,
|
names_data_path,
|
||||||
|
@ -42,6 +42,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
|
|||||||
"",
|
"",
|
||||||
0.2,
|
0.2,
|
||||||
1.9076601161280742,
|
1.9076601161280742,
|
||||||
|
0.2,
|
||||||
TRAVEL_MODE_DRIVING,
|
TRAVEL_MODE_DRIVING,
|
||||||
{{FloatLongitude{-73.981492}, FloatLatitude{40.768258}},
|
{{FloatLongitude{-73.981492}, FloatLatitude{40.768258}},
|
||||||
329,
|
329,
|
||||||
@ -61,6 +62,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
|
|||||||
"",
|
"",
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
TRAVEL_MODE_DRIVING,
|
TRAVEL_MODE_DRIVING,
|
||||||
{{FloatLongitude{-73.981495}, FloatLatitude{40.768275}},
|
{{FloatLongitude{-73.981495}, FloatLatitude{40.768275}},
|
||||||
0,
|
0,
|
||||||
@ -79,7 +81,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
|
|||||||
geometry.segment_offsets = {0, 2};
|
geometry.segment_offsets = {0, 2};
|
||||||
geometry.segment_distances = {1.9076601161280742};
|
geometry.segment_distances = {1.9076601161280742};
|
||||||
geometry.osm_node_ids = {OSMNodeID{0}, OSMNodeID{1}, OSMNodeID{2}};
|
geometry.osm_node_ids = {OSMNodeID{0}, OSMNodeID{1}, OSMNodeID{2}};
|
||||||
geometry.annotations = {{1.9076601161280742, 0.2, 0}, {0, 0, 0}};
|
geometry.annotations = {{1.9076601161280742, 0.2, 0.2, 0}, {0, 0, 0, 0}};
|
||||||
|
|
||||||
trimShortSegments(steps, geometry);
|
trimShortSegments(steps, geometry);
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
|
|||||||
CompressedEdgeContainer container;
|
CompressedEdgeContainer container;
|
||||||
|
|
||||||
// compress 0---1---2 to 0---2
|
// compress 0---1---2 to 0---2
|
||||||
container.CompressEdge(0, 1, 1, 2, 1, 1);
|
container.CompressEdge(0, 1, 1, 2, 1, 1, 11, 11);
|
||||||
BOOST_CHECK(container.HasEntryForID(0));
|
BOOST_CHECK(container.HasEntryForID(0));
|
||||||
BOOST_CHECK(!container.HasEntryForID(1));
|
BOOST_CHECK(!container.HasEntryForID(1));
|
||||||
BOOST_CHECK(!container.HasEntryForID(2));
|
BOOST_CHECK(!container.HasEntryForID(2));
|
||||||
@ -25,7 +25,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
|
|||||||
BOOST_CHECK_EQUAL(container.GetLastEdgeSourceID(0), 1);
|
BOOST_CHECK_EQUAL(container.GetLastEdgeSourceID(0), 1);
|
||||||
|
|
||||||
// compress 2---3---4 to 2---4
|
// compress 2---3---4 to 2---4
|
||||||
container.CompressEdge(2, 3, 3, 4, 1, 1);
|
container.CompressEdge(2, 3, 3, 4, 1, 1, 11, 11);
|
||||||
BOOST_CHECK(container.HasEntryForID(0));
|
BOOST_CHECK(container.HasEntryForID(0));
|
||||||
BOOST_CHECK(!container.HasEntryForID(1));
|
BOOST_CHECK(!container.HasEntryForID(1));
|
||||||
BOOST_CHECK(container.HasEntryForID(2));
|
BOOST_CHECK(container.HasEntryForID(2));
|
||||||
@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
|
|||||||
BOOST_CHECK_EQUAL(container.GetLastEdgeSourceID(2), 3);
|
BOOST_CHECK_EQUAL(container.GetLastEdgeSourceID(2), 3);
|
||||||
|
|
||||||
// compress 0---2---4 to 0---4
|
// compress 0---2---4 to 0---4
|
||||||
container.CompressEdge(0, 2, 2, 4, 2, 2);
|
container.CompressEdge(0, 2, 2, 4, 2, 2, 22, 22);
|
||||||
BOOST_CHECK(container.HasEntryForID(0));
|
BOOST_CHECK(container.HasEntryForID(0));
|
||||||
BOOST_CHECK(!container.HasEntryForID(1));
|
BOOST_CHECK(!container.HasEntryForID(1));
|
||||||
BOOST_CHECK(!container.HasEntryForID(2));
|
BOOST_CHECK(!container.HasEntryForID(2));
|
||||||
@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE(t_crossing)
|
|||||||
CompressedEdgeContainer container;
|
CompressedEdgeContainer container;
|
||||||
|
|
||||||
// compress 0---1---2 to 0---2
|
// compress 0---1---2 to 0---2
|
||||||
container.CompressEdge(0, 1, 1, 2, 1, 1);
|
container.CompressEdge(0, 1, 1, 2, 1, 1, 11, 11);
|
||||||
BOOST_CHECK(container.HasEntryForID(0));
|
BOOST_CHECK(container.HasEntryForID(0));
|
||||||
BOOST_CHECK(!container.HasEntryForID(1));
|
BOOST_CHECK(!container.HasEntryForID(1));
|
||||||
BOOST_CHECK(!container.HasEntryForID(2));
|
BOOST_CHECK(!container.HasEntryForID(2));
|
||||||
@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE(t_crossing)
|
|||||||
BOOST_CHECK_EQUAL(container.GetLastEdgeSourceID(0), 1);
|
BOOST_CHECK_EQUAL(container.GetLastEdgeSourceID(0), 1);
|
||||||
|
|
||||||
// compress 2---5---6 to 2---6
|
// compress 2---5---6 to 2---6
|
||||||
container.CompressEdge(4, 5, 5, 6, 1, 1);
|
container.CompressEdge(4, 5, 5, 6, 1, 1, 11, 11);
|
||||||
BOOST_CHECK(container.HasEntryForID(0));
|
BOOST_CHECK(container.HasEntryForID(0));
|
||||||
BOOST_CHECK(!container.HasEntryForID(1));
|
BOOST_CHECK(!container.HasEntryForID(1));
|
||||||
BOOST_CHECK(!container.HasEntryForID(2));
|
BOOST_CHECK(!container.HasEntryForID(2));
|
||||||
@ -76,7 +76,7 @@ BOOST_AUTO_TEST_CASE(t_crossing)
|
|||||||
BOOST_CHECK_EQUAL(container.GetLastEdgeSourceID(4), 5);
|
BOOST_CHECK_EQUAL(container.GetLastEdgeSourceID(4), 5);
|
||||||
|
|
||||||
// compress 2---3---4 to 2---4
|
// compress 2---3---4 to 2---4
|
||||||
container.CompressEdge(2, 3, 3, 4, 1, 1);
|
container.CompressEdge(2, 3, 3, 4, 1, 1, 11, 11);
|
||||||
BOOST_CHECK(container.HasEntryForID(0));
|
BOOST_CHECK(container.HasEntryForID(0));
|
||||||
BOOST_CHECK(!container.HasEntryForID(1));
|
BOOST_CHECK(!container.HasEntryForID(1));
|
||||||
BOOST_CHECK(container.HasEntryForID(2));
|
BOOST_CHECK(container.HasEntryForID(2));
|
||||||
|
@ -28,6 +28,7 @@ inline InputEdge MakeUnitEdge(const NodeID from, const NodeID to)
|
|||||||
1,
|
1,
|
||||||
SPECIAL_EDGEID,
|
SPECIAL_EDGEID,
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
@ -50,6 +50,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
|
|||||||
json::Array{{json::Object{
|
json::Array{{json::Object{
|
||||||
{{"distance", 0.},
|
{{"distance", 0.},
|
||||||
{"duration", 0.},
|
{"duration", 0.},
|
||||||
|
{"weight_name", "duration"},
|
||||||
{"geometry", "yw_jGupkl@??"},
|
{"geometry", "yw_jGupkl@??"},
|
||||||
{"legs",
|
{"legs",
|
||||||
json::Array{{json::Object{
|
json::Array{{json::Object{
|
||||||
@ -59,6 +60,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
|
|||||||
{"steps",
|
{"steps",
|
||||||
json::Array{{{json::Object{{{"duration", 0.},
|
json::Array{{{json::Object{{{"duration", 0.},
|
||||||
{"distance", 0.},
|
{"distance", 0.},
|
||||||
|
{"weight", 0.},
|
||||||
{"geometry", "yw_jGupkl@??"},
|
{"geometry", "yw_jGupkl@??"},
|
||||||
{"name", "Boulevard du Larvotto"},
|
{"name", "Boulevard du Larvotto"},
|
||||||
{"mode", "driving"},
|
{"mode", "driving"},
|
||||||
@ -78,6 +80,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
|
|||||||
|
|
||||||
json::Object{{{"duration", 0.},
|
json::Object{{{"duration", 0.},
|
||||||
{"distance", 0.},
|
{"distance", 0.},
|
||||||
|
{"weight", 0.},
|
||||||
{"geometry", "yw_jGupkl@"},
|
{"geometry", "yw_jGupkl@"},
|
||||||
{"name", "Boulevard du Larvotto"},
|
{"name", "Boulevard du Larvotto"},
|
||||||
{"mode", "driving"},
|
{"mode", "driving"},
|
||||||
|
@ -68,6 +68,14 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
|
|||||||
{
|
{
|
||||||
return GeometryID{SPECIAL_GEOMETRYID, false};
|
return GeometryID{SPECIAL_GEOMETRYID, false};
|
||||||
}
|
}
|
||||||
|
TurnPenalty GetWeightPenaltyForEdgeID(const unsigned /* id */) const override final
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
TurnPenalty GetDurationPenaltyForEdgeID(const unsigned /* id */) const override final
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID /* id */) const override
|
std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID /* id */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
@ -83,12 +91,17 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
|
|||||||
result_weights[0] = 1;
|
result_weights[0] = 1;
|
||||||
return result_weights;
|
return result_weights;
|
||||||
}
|
}
|
||||||
std::vector<EdgeWeight> GetUncompressedReverseWeights(const EdgeID /* id */) const override
|
std::vector<EdgeWeight> GetUncompressedReverseWeights(const EdgeID id) const override
|
||||||
{
|
{
|
||||||
std::vector<EdgeWeight> result_weights;
|
return GetUncompressedForwardWeights(id);
|
||||||
result_weights.resize(1);
|
}
|
||||||
result_weights[0] = 1;
|
std::vector<EdgeWeight> GetUncompressedForwardDurations(const EdgeID id) const override
|
||||||
return result_weights;
|
{
|
||||||
|
return GetUncompressedForwardWeights(id);
|
||||||
|
}
|
||||||
|
std::vector<EdgeWeight> GetUncompressedReverseDurations(const EdgeID id) const override
|
||||||
|
{
|
||||||
|
return GetUncompressedForwardWeights(id);
|
||||||
}
|
}
|
||||||
std::vector<DatasourceID> GetUncompressedForwardDatasources(const EdgeID /*id*/) const override
|
std::vector<DatasourceID> GetUncompressedForwardDatasources(const EdgeID /*id*/) const override
|
||||||
{
|
{
|
||||||
@ -211,6 +224,8 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
|
|||||||
std::string GetTimestamp() const override { return ""; }
|
std::string GetTimestamp() const override { return ""; }
|
||||||
bool GetContinueStraightDefault() const override { return true; }
|
bool GetContinueStraightDefault() const override { return true; }
|
||||||
double GetMapMatchingMaxSpeed() const override { return 180 / 3.6; }
|
double GetMapMatchingMaxSpeed() const override { return 180 / 3.6; }
|
||||||
|
const char *GetWeightName() const override final { return "duration"; }
|
||||||
|
unsigned GetWeightPrecision() const override final { return 1; }
|
||||||
BearingClassID GetBearingClassID(const NodeID /*id*/) const override { return 0; }
|
BearingClassID GetBearingClassID(const NodeID /*id*/) const override { return 0; }
|
||||||
EntryClassID GetEntryClassID(const EdgeID /*id*/) const override { return 0; }
|
EntryClassID GetEntryClassID(const EdgeID /*id*/) const override { return 0; }
|
||||||
|
|
||||||
|
@ -81,8 +81,9 @@ BOOST_AUTO_TEST_CASE(invalid_table_urls)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(valid_route_hint)
|
BOOST_AUTO_TEST_CASE(valid_route_hint)
|
||||||
{
|
{
|
||||||
auto hint = engine::Hint::FromBase64(
|
auto hint = engine::Hint::FromBase64("XAYAgP___3-QAAAABAAAACEAAAA_"
|
||||||
"XAYAgP___3-QAAAABAAAACEAAAA_AAAAHgAAAHsFAAAUAAAAaWhxALeCmwI7aHEAy4KbAgUAAQE0h8Z2");
|
"AAAAHgAAAHsFAAAUAAAAaWhxALeCmwI7aHEAy4KbAjtocQDLgpsCAAAAA"
|
||||||
|
"KCQXlw=");
|
||||||
BOOST_CHECK_EQUAL(
|
BOOST_CHECK_EQUAL(
|
||||||
hint.phantom.input_location,
|
hint.phantom.input_location,
|
||||||
util::Coordinate(util::FloatLongitude{7.432251}, util::FloatLatitude{43.745995}));
|
util::Coordinate(util::FloatLongitude{7.432251}, util::FloatLatitude{43.745995}));
|
||||||
@ -151,12 +152,12 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
CHECK_EQUAL_RANGE(reference_3.hints, result_3->hints);
|
CHECK_EQUAL_RANGE(reference_3.hints, result_3->hints);
|
||||||
|
|
||||||
std::vector<boost::optional<engine::Hint>> hints_4 = {
|
std::vector<boost::optional<engine::Hint>> hints_4 = {
|
||||||
engine::Hint::FromBase64(
|
engine::Hint::FromBase64("0QkAgFcLAIBFAAAADAAAACcAAAA0AAAANAAAAB4AAAAmAAAAGA0AAL8QAAARAAAAJ"
|
||||||
"XAYAgP___3-QAAAABAAAACEAAAA_AAAAHgAAAHsFAAAUAAAAaWhxALeCmwI7aHEAy4KbAgUAAQE0h8Z2"),
|
"ipxAP1ImwIfKnEABUmbAgIAAQFy"),
|
||||||
engine::Hint::FromBase64(
|
engine::Hint::FromBase64("YwsAgP___3-fAAAAEQAAACcAAAAnAAAAJwAAABYAAAAxAAAA3wEAAOQBAAARAAAA-"
|
||||||
"lgQAgP___3-QAAAADwAAABMAAAAoAAAALAAAADQAAAAUAAAAmWFxAL1zmwLcYXEAu3ObAgQAAQE0h8Z2"),
|
"DlxAGBcmwLLOXEAfVybAgEAAQFy"),
|
||||||
engine::Hint::FromBase64(
|
engine::Hint::FromBase64("awQAgDIJAID7AQAAAAAAAB0AAAAdAAAAHQAAAP4DAAABAQAADwsAAMULAAARAAAAd"
|
||||||
"OAUAgMUFAIAAAAAADwAAAAIAAAAAAAAAnQAAALwEAAAUAAAAgz5xAE9WmwKIPnEAUFabAgAAAQE0h8Z2")};
|
"T5yADqVmwIAtMQEAAAAABUAAQFy")};
|
||||||
RouteParameters reference_4{false,
|
RouteParameters reference_4{false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@ -169,9 +170,12 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
std::vector<boost::optional<engine::Bearing>>{}};
|
std::vector<boost::optional<engine::Bearing>>{}};
|
||||||
auto result_4 = parseParameters<RouteParameters>(
|
auto result_4 = parseParameters<RouteParameters>(
|
||||||
"1,2;3,4?steps=false&hints="
|
"1,2;3,4?steps=false&hints="
|
||||||
"XAYAgP___3-QAAAABAAAACEAAAA_AAAAHgAAAHsFAAAUAAAAaWhxALeCmwI7aHEAy4KbAgUAAQE0h8Z2;"
|
"0QkAgFcLAIBFAAAADAAAACcAAAA0AAAANAAAAB4AAAAmAAAAGA0AAL8QAAARAAAAJipxAP1ImwIfKnEABUmbAgIAAQ"
|
||||||
"lgQAgP___3-QAAAADwAAABMAAAAoAAAALAAAADQAAAAUAAAAmWFxAL1zmwLcYXEAu3ObAgQAAQE0h8Z2;"
|
"Fy;"
|
||||||
"OAUAgMUFAIAAAAAADwAAAAIAAAAAAAAAnQAAALwEAAAUAAAAgz5xAE9WmwKIPnEAUFabAgAAAQE0h8Z2");
|
"YwsAgP___3-fAAAAEQAAACcAAAAnAAAAJwAAABYAAAAxAAAA3wEAAOQBAAARAAAA-"
|
||||||
|
"DlxAGBcmwLLOXEAfVybAgEAAQFy;"
|
||||||
|
"awQAgDIJAID7AQAAAAAAAB0AAAAdAAAAHQAAAP4DAAABAQAADwsAAMULAAARAAAAdT5yADqVmwIAtMQEAAAAABUAAQ"
|
||||||
|
"Fy");
|
||||||
BOOST_CHECK(result_4);
|
BOOST_CHECK(result_4);
|
||||||
BOOST_CHECK_EQUAL(reference_4.steps, result_4->steps);
|
BOOST_CHECK_EQUAL(reference_4.steps, result_4->steps);
|
||||||
BOOST_CHECK_EQUAL(reference_4.alternatives, result_4->alternatives);
|
BOOST_CHECK_EQUAL(reference_4.alternatives, result_4->alternatives);
|
||||||
@ -266,11 +270,11 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
{util::FloatLongitude{5}, util::FloatLatitude{6}},
|
{util::FloatLongitude{5}, util::FloatLatitude{6}},
|
||||||
{util::FloatLongitude{7}, util::FloatLatitude{8}}};
|
{util::FloatLongitude{7}, util::FloatLatitude{8}}};
|
||||||
std::vector<boost::optional<engine::Hint>> hints_10 = {
|
std::vector<boost::optional<engine::Hint>> hints_10 = {
|
||||||
engine::Hint::FromBase64(
|
engine::Hint::FromBase64("0QkAgFcLAIBFAAAADAAAACcAAAA0AAAANAAAAB4AAAAmAAAAGA0AAL8QAAARAAAAJ"
|
||||||
"XAYAgP___3-QAAAABAAAACEAAAA_AAAAHgAAAHsFAAAUAAAAaWhxALeCmwI7aHEAy4KbAgUAAQE0h8Z2"),
|
"ipxAP1ImwIfKnEABUmbAgIAAQFy"),
|
||||||
boost::none,
|
boost::none,
|
||||||
engine::Hint::FromBase64(
|
engine::Hint::FromBase64("awQAgDIJAID7AQAAAAAAAB0AAAAdAAAAHQAAAP4DAAABAQAADwsAAMULAAARAAAAd"
|
||||||
"lgQAgP___3-QAAAADwAAABMAAAAoAAAALAAAADQAAAAUAAAAmWFxAL1zmwLcYXEAu3ObAgQAAQE0h8Z2"),
|
"T5yADqVmwIAtMQEAAAAABUAAQFy"),
|
||||||
boost::none};
|
boost::none};
|
||||||
RouteParameters reference_10{false,
|
RouteParameters reference_10{false,
|
||||||
false,
|
false,
|
||||||
@ -282,10 +286,12 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
|
|||||||
hints_10,
|
hints_10,
|
||||||
std::vector<boost::optional<double>>{},
|
std::vector<boost::optional<double>>{},
|
||||||
std::vector<boost::optional<engine::Bearing>>{}};
|
std::vector<boost::optional<engine::Bearing>>{}};
|
||||||
auto result_10 = parseParameters<RouteParameters>(
|
auto result_10 =
|
||||||
"1,2;3,4;5,6;7,8?steps=false&hints="
|
parseParameters<RouteParameters>("1,2;3,4;5,6;7,8?steps=false&hints="
|
||||||
"XAYAgP___3-QAAAABAAAACEAAAA_AAAAHgAAAHsFAAAUAAAAaWhxALeCmwI7aHEAy4KbAgUAAQE0h8Z2;;"
|
"0QkAgFcLAIBFAAAADAAAACcAAAA0AAAANAAAAB4AAAAmAAAAGA0AAL8QA"
|
||||||
"lgQAgP___3-QAAAADwAAABMAAAAoAAAALAAAADQAAAAUAAAAmWFxAL1zmwLcYXEAu3ObAgQAAQE0h8Z2"
|
"AARAAAAJipxAP1ImwIfKnEABUmbAgIAAQFy;;"
|
||||||
|
"awQAgDIJAID7AQAAAAAAAB0AAAAdAAAAHQAAAP4DAAABAQAADwsAAMULA"
|
||||||
|
"AARAAAAdT5yADqVmwIAtMQEAAAAABUAAQFy"
|
||||||
";");
|
";");
|
||||||
BOOST_CHECK(result_10);
|
BOOST_CHECK(result_10);
|
||||||
BOOST_CHECK_EQUAL(reference_10.steps, result_10->steps);
|
BOOST_CHECK_EQUAL(reference_10.steps, result_10->steps);
|
||||||
|
Loading…
Reference in New Issue
Block a user