Allow users to specify a class for each way
This adds the ability to mark ways with a user-defined class in the profile. This class information will be included in the response as property of the RouteStep object.
This commit is contained in:
parent
d52d530cbe
commit
44739f2dc3
@ -5,8 +5,11 @@
|
|||||||
- Plugins supported: `table`
|
- Plugins supported: `table`
|
||||||
- API:
|
- API:
|
||||||
- Support for exits numbers and names. New member `exits` in `RouteStep`, based on `junction:ref` on ways
|
- Support for exits numbers and names. New member `exits` in `RouteStep`, based on `junction:ref` on ways
|
||||||
|
- `RouteStep` now has new parameter `classes` that can be set in the profile on each way.
|
||||||
- Profiles:
|
- Profiles:
|
||||||
- `result.exits` allows you to set a way's exit numbers and names, see [`junction:ref`](http://wiki.openstreetmap.org/wiki/Proposed_features/junction_details)
|
- `result.exits` allows you to set a way's exit numbers and names, see [`junction:ref`](http://wiki.openstreetmap.org/wiki/Proposed_features/junction_details)
|
||||||
|
- `ExtractionWay` now as new property `forward_classes` and `backward_classes` that can set in the `way_function`.
|
||||||
|
The maximum number of classes is 8.
|
||||||
|
|
||||||
# 5.8.0
|
# 5.8.0
|
||||||
- Changes from 5.7
|
- Changes from 5.7
|
||||||
|
@ -583,6 +583,7 @@ step.
|
|||||||
- `destinations`: The destinations of the way. Will be `undefined` if there are no destinations.
|
- `destinations`: The destinations of the way. Will be `undefined` if there are no destinations.
|
||||||
- `exits`: The exit numbers or names of the way. Will be `undefined` if there are no exit numbers or names.
|
- `exits`: The exit numbers or names of the way. Will be `undefined` if there are no exit numbers or names.
|
||||||
- `mode`: A string signifying the mode of transportation.
|
- `mode`: A string signifying the mode of transportation.
|
||||||
|
- `classes`: An array of strings signifying the classes of the road as specified in the profile.
|
||||||
- `maneuver`: A `StepManeuver` object representing the maneuver.
|
- `maneuver`: A `StepManeuver` object representing the maneuver.
|
||||||
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
|
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
|
||||||
- `rotary_name`: The name for the rotary. Optionally included, if the step is a rotary and a rotary name is available.
|
- `rotary_name`: The name for the rotary. Optionally included, if the step is a rotary and a rotary name is available.
|
||||||
@ -596,6 +597,7 @@ step.
|
|||||||
"mode" : "driving",
|
"mode" : "driving",
|
||||||
"duration" : 15.6,
|
"duration" : 15.6,
|
||||||
"weight" : 15.6,
|
"weight" : 15.6,
|
||||||
|
"classes": ["toll", "restricted"],
|
||||||
"intersections" : [
|
"intersections" : [
|
||||||
{ "bearings" : [ 10, 92, 184, 270 ],
|
{ "bearings" : [ 10, 92, 184, 270 ],
|
||||||
"lanes" : [
|
"lanes" : [
|
||||||
@ -660,7 +662,7 @@ step.
|
|||||||
| `roundabout` | traverse roundabout, has additional property `exit` with NR if the roundabout is left. The modifier specifies the direction of entering the roundabout. |
|
| `roundabout` | traverse roundabout, has additional property `exit` with NR if the roundabout is left. The modifier specifies the direction of entering the roundabout. |
|
||||||
| `rotary` | a traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name` and/or `rotary_pronunciation` parameters (located in the RouteStep object) in addition to the `exit` parameter (located on the StepManeuver object). |
|
| `rotary` | a traffic circle. While very similar to a larger version of a roundabout, it does not necessarily follow roundabout rules for right of way. It can offer `rotary_name` and/or `rotary_pronunciation` parameters (located in the RouteStep object) in addition to the `exit` parameter (located on the StepManeuver object). |
|
||||||
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
|
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
|
||||||
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode. If the road takes a turn itself, the `modifier` describes the direction |
|
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode or classes. If the road takes a turn itself, the `modifier` describes the direction |
|
||||||
|
|
||||||
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
|
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
|
||||||
between all instructions. They only offer a fallback in case nothing else is to report.
|
between all instructions. They only offer a fallback in case nothing else is to report.
|
||||||
|
@ -56,6 +56,8 @@ forward_rate | Float | Routing weight, expressed a
|
|||||||
backward_rate | Float | " "
|
backward_rate | Float | " "
|
||||||
forward_mode | Enum | Mode of travel (e.g. `car`, `ferry`). Mandatory. Defined in `include/extractor/travel_mode.hpp`.
|
forward_mode | Enum | Mode of travel (e.g. `car`, `ferry`). Mandatory. Defined in `include/extractor/travel_mode.hpp`.
|
||||||
backward_mode | Enum | " "
|
backward_mode | Enum | " "
|
||||||
|
forward_classes | Table | Mark this way as being of a specific class, e.g. `result.classes["toll"] = true`. This will be exposed in the API as `classes` on each `RouteStep`.
|
||||||
|
backward_classes | Table | " "
|
||||||
duration | Float | Alternative setter for duration of the whole way in both directions
|
duration | Float | Alternative setter for duration of the whole way in both directions
|
||||||
weight | Float | Alternative setter for weight of the whole way in both directions
|
weight | Float | Alternative setter for weight of the whole way in both directions
|
||||||
turn_lanes_forward | String | Directions for individual lanes (normalised OSM `turn:lanes` value)
|
turn_lanes_forward | String | Directions for individual lanes (normalised OSM `turn:lanes` value)
|
||||||
|
101
features/car/classes.feature
Normal file
101
features/car/classes.feature
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
@routing @car @mode
|
||||||
|
Feature: Car - Mode flag
|
||||||
|
Background:
|
||||||
|
Given the profile "car"
|
||||||
|
|
||||||
|
Scenario: Car - We tag ferries with a class
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | route |
|
||||||
|
| ab | primary | |
|
||||||
|
| bc | | ferry |
|
||||||
|
| cd | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | classes |
|
||||||
|
| a | d | ab,bc,cd,cd | depart,notification right,notification left,arrive | ,ferry,, |
|
||||||
|
| d | a | cd,bc,ab,ab | depart,notification right,notification left,arrive | ,ferry,, |
|
||||||
|
| c | a | bc,ab,ab | depart,notification left,arrive | ferry,, |
|
||||||
|
| d | b | cd,bc,bc | depart,notification right,arrive | ,ferry,ferry |
|
||||||
|
| a | c | ab,bc,bc | depart,notification right,arrive | ,ferry,ferry |
|
||||||
|
| b | d | bc,cd,cd | depart,notification left,arrive | ferry,, |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Car - We tag motorways with a class
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| ab | primary |
|
||||||
|
| bc | motorway|
|
||||||
|
| cd | primary |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | classes | # |
|
||||||
|
| a | d | ab,bc,cd | depart,notification right,arrive | ,motorway, | |
|
||||||
|
| a | c | ab,bc,bc | depart,notification right,arrive | ,motorway,motorway | |
|
||||||
|
| b | d | bc,cd | depart,arrive | motorway, | we don't announce when we leave the highway |
|
||||||
|
|
||||||
|
Scenario: Car - We tag motorway_link with a class
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| ab | primary |
|
||||||
|
| bc | motorway_link |
|
||||||
|
| cd | primary |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | classes | # |
|
||||||
|
| a | d | ab,bc,cd | depart,on ramp right,arrive | ,motorway, | notification replaced by on-ramp |
|
||||||
|
| a | c | ab,bc,bc | depart,on ramp right,arrive | ,motorway,motorway | " " |
|
||||||
|
| b | d | bc,cd | depart,arrive | motorway, | no announcement |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Car - We tag restricted with a class
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | access |
|
||||||
|
| ab | primary | private |
|
||||||
|
| bc | motorway| private |
|
||||||
|
| cd | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | classes |
|
||||||
|
| a | d | ab,bc,cd | depart,notification right,arrive| restricted,motorway;restricted, |
|
||||||
|
|
||||||
|
Scenario: Car - We toll restricted with a class
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b
|
||||||
|
c d
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | toll |
|
||||||
|
| ab | primary | yes |
|
||||||
|
| bc | motorway| yes |
|
||||||
|
| cd | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | classes |
|
||||||
|
| a | d | ab,bc,cd | depart,notification right,arrive | toll,motorway;toll, |
|
||||||
|
|
@ -23,11 +23,11 @@ Feature: Car - Destination only, no passing through
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | b | ab,ab |
|
| a | b | ab,ab |
|
||||||
| a | c | ab,bcd |
|
| a | c | ab,bcd,bcd |
|
||||||
| a | d | ab,bcd,bcd |
|
| a | d | ab,bcd,bcd |
|
||||||
| a | e | axye,axye |
|
| a | e | axye,axye |
|
||||||
| e | d | de,de |
|
| e | d | de,de |
|
||||||
| e | c | de,bcd |
|
| e | c | de,bcd,bcd |
|
||||||
| e | b | de,bcd,bcd |
|
| e | b | de,bcd,bcd |
|
||||||
| e | a | axye,axye |
|
| e | a | axye,axye |
|
||||||
|
|
||||||
@ -51,12 +51,12 @@ Feature: Car - Destination only, no passing through
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | b | ab,ab |
|
| a | b | ab,ab |
|
||||||
| a | c | ab,bc |
|
| a | c | ab,bc,bc |
|
||||||
| a | d | ab,cd |
|
| a | d | ab,bc,cd |
|
||||||
| a | e | axye,axye |
|
| a | e | axye,axye |
|
||||||
| e | d | de,de |
|
| e | d | de,de |
|
||||||
| e | c | de,cd |
|
| e | c | de,cd,cd |
|
||||||
| e | b | de,bc |
|
| e | b | de,cd,bc |
|
||||||
| e | a | axye,axye |
|
| e | a | axye,axye |
|
||||||
|
|
||||||
Scenario: Car - Routing inside a destination only area
|
Scenario: Car - Routing inside a destination only area
|
||||||
|
@ -260,6 +260,10 @@ module.exports = function () {
|
|||||||
return this.extractInstructionList(instructions, s => s.mode);
|
return this.extractInstructionList(instructions, s => s.mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.classesList = (instructions) => {
|
||||||
|
return this.extractInstructionList(instructions, s => s.classes ? s.classes.join(';') : '');
|
||||||
|
};
|
||||||
|
|
||||||
this.timeList = (instructions) => {
|
this.timeList = (instructions) => {
|
||||||
return this.extractInstructionList(instructions, s => s.duration + 's');
|
return this.extractInstructionList(instructions, s => s.duration + 's');
|
||||||
};
|
};
|
||||||
|
@ -34,7 +34,7 @@ module.exports = function () {
|
|||||||
var afterRequest = (err, res, body) => {
|
var afterRequest = (err, res, body) => {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
if (body && body.length) {
|
if (body && body.length) {
|
||||||
let destinations, exits, pronunciations, instructions, refs, bearings, turns, modes, times,
|
let destinations, exits, pronunciations, instructions, refs, bearings, turns, modes, times, classes,
|
||||||
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches;
|
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches;
|
||||||
|
|
||||||
let json = JSON.parse(body);
|
let json = JSON.parse(body);
|
||||||
@ -53,6 +53,7 @@ module.exports = function () {
|
|||||||
turns = this.turnList(json.routes[0]);
|
turns = this.turnList(json.routes[0]);
|
||||||
intersections = this.intersectionList(json.routes[0]);
|
intersections = this.intersectionList(json.routes[0]);
|
||||||
modes = this.modeList(json.routes[0]);
|
modes = this.modeList(json.routes[0]);
|
||||||
|
classes = this.classesList(json.routes[0]);
|
||||||
times = this.timeList(json.routes[0]);
|
times = this.timeList(json.routes[0]);
|
||||||
distances = this.distanceList(json.routes[0]);
|
distances = this.distanceList(json.routes[0]);
|
||||||
lanes = this.lanesList(json.routes[0]);
|
lanes = this.lanesList(json.routes[0]);
|
||||||
@ -174,6 +175,7 @@ module.exports = function () {
|
|||||||
putValue('bearing', bearings);
|
putValue('bearing', bearings);
|
||||||
putValue('turns', turns);
|
putValue('turns', turns);
|
||||||
putValue('modes', modes);
|
putValue('modes', modes);
|
||||||
|
putValue('classes', classes);
|
||||||
putValue('times', times);
|
putValue('times', times);
|
||||||
putValue('distances', distances);
|
putValue('distances', distances);
|
||||||
putValue('pronunciations', pronunciations);
|
putValue('pronunciations', pronunciations);
|
||||||
|
@ -318,7 +318,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
|
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
|
||||||
char *memory_ptr)
|
char *memory_ptr)
|
||||||
{
|
{
|
||||||
auto via_geometry_list_ptr =
|
const auto via_geometry_list_ptr =
|
||||||
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::GEOMETRY_ID_LIST);
|
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::GEOMETRY_ID_LIST);
|
||||||
util::vector_view<GeometryID> geometry_ids(
|
util::vector_view<GeometryID> geometry_ids(
|
||||||
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::GEOMETRY_ID_LIST]);
|
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::GEOMETRY_ID_LIST]);
|
||||||
@ -338,10 +338,16 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
util::vector_view<extractor::TravelMode> travel_modes(
|
util::vector_view<extractor::TravelMode> travel_modes(
|
||||||
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
|
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
|
||||||
|
|
||||||
|
const auto classes_list_ptr =
|
||||||
|
layout.GetBlockPtr<extractor::ClassData>(memory_ptr, storage::DataLayout::CLASSES_LIST);
|
||||||
|
util::vector_view<extractor::ClassData> classes(
|
||||||
|
classes_list_ptr, layout.num_entries[storage::DataLayout::CLASSES_LIST]);
|
||||||
|
|
||||||
edge_based_node_data = extractor::EdgeBasedNodeDataView(std::move(geometry_ids),
|
edge_based_node_data = extractor::EdgeBasedNodeDataView(std::move(geometry_ids),
|
||||||
std::move(name_ids),
|
std::move(name_ids),
|
||||||
std::move(component_ids),
|
std::move(component_ids),
|
||||||
std::move(travel_modes));
|
std::move(travel_modes),
|
||||||
|
std::move(classes));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
|
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
|
||||||
@ -783,6 +789,22 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
return edge_based_node_data.GetTravelMode(id);
|
return edge_based_node_data.GetTravelMode(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extractor::ClassData GetClassData(const NodeID id) const override final
|
||||||
|
{
|
||||||
|
return edge_based_node_data.GetClassData(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GetClasses(const extractor::ClassData class_data) const override final
|
||||||
|
{
|
||||||
|
auto indexes = extractor::getClassIndexes(class_data);
|
||||||
|
std::vector<std::string> classes(indexes.size());
|
||||||
|
std::transform(indexes.begin(), indexes.end(), classes.begin(), [this](const auto index) {
|
||||||
|
return m_profile_properties->GetClassName(index);
|
||||||
|
});
|
||||||
|
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
NameID GetNameIndex(const NodeID id) const override final
|
NameID GetNameIndex(const NodeID id) const override final
|
||||||
{
|
{
|
||||||
return edge_based_node_data.GetNameID(id);
|
return edge_based_node_data.GetNameID(id);
|
||||||
|
@ -3,14 +3,19 @@
|
|||||||
|
|
||||||
// Exposes all data access interfaces to the algorithms via base class ptr
|
// Exposes all data access interfaces to the algorithms via base class ptr
|
||||||
|
|
||||||
|
#include "engine/approach.hpp"
|
||||||
|
#include "engine/phantom_node.hpp"
|
||||||
|
|
||||||
#include "contractor/query_edge.hpp"
|
#include "contractor/query_edge.hpp"
|
||||||
|
|
||||||
|
#include "extractor/class_data.hpp"
|
||||||
#include "extractor/edge_based_node_segment.hpp"
|
#include "extractor/edge_based_node_segment.hpp"
|
||||||
#include "extractor/external_memory_node.hpp"
|
#include "extractor/external_memory_node.hpp"
|
||||||
#include "extractor/guidance/turn_instruction.hpp"
|
#include "extractor/guidance/turn_instruction.hpp"
|
||||||
#include "extractor/guidance/turn_lane_types.hpp"
|
#include "extractor/guidance/turn_lane_types.hpp"
|
||||||
#include "extractor/original_edge_data.hpp"
|
#include "extractor/original_edge_data.hpp"
|
||||||
#include "engine/approach.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
#include "engine/phantom_node.hpp"
|
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
#include "util/guidance/bearing_class.hpp"
|
#include "util/guidance/bearing_class.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
@ -87,6 +92,10 @@ class BaseDataFacade
|
|||||||
|
|
||||||
virtual extractor::TravelMode GetTravelMode(const NodeID id) const = 0;
|
virtual extractor::TravelMode GetTravelMode(const NodeID id) const = 0;
|
||||||
|
|
||||||
|
virtual extractor::ClassData GetClassData(const NodeID id) const = 0;
|
||||||
|
|
||||||
|
virtual std::vector<std::string> GetClasses(const extractor::ClassData class_data) const = 0;
|
||||||
|
|
||||||
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
virtual std::vector<RTreeLeaf> GetEdgesInBox(const util::Coordinate south_west,
|
||||||
const util::Coordinate north_east) const = 0;
|
const util::Coordinate north_east) const = 0;
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
: source_node.forward_segment_id.id;
|
: source_node.forward_segment_id.id;
|
||||||
const auto source_name_id = facade.GetNameIndex(source_node_id);
|
const auto source_name_id = facade.GetNameIndex(source_node_id);
|
||||||
const auto source_mode = facade.GetTravelMode(source_node_id);
|
const auto source_mode = facade.GetTravelMode(source_node_id);
|
||||||
|
auto source_classes = facade.GetClasses(facade.GetClassData(source_node_id));
|
||||||
|
|
||||||
const EdgeWeight target_duration =
|
const EdgeWeight target_duration =
|
||||||
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
|
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
|
||||||
@ -62,6 +63,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
: target_node.forward_segment_id.id;
|
: target_node.forward_segment_id.id;
|
||||||
const auto target_name_id = facade.GetNameIndex(target_node_id);
|
const auto target_name_id = facade.GetNameIndex(target_node_id);
|
||||||
const auto target_mode = facade.GetTravelMode(target_node_id);
|
const auto target_mode = facade.GetTravelMode(target_node_id);
|
||||||
|
auto target_classes = facade.GetClasses(facade.GetClassData(target_node_id));
|
||||||
|
|
||||||
const auto number_of_segments = leg_geometry.GetNumberOfSegments();
|
const auto number_of_segments = leg_geometry.GetNumberOfSegments();
|
||||||
|
|
||||||
@ -116,6 +118,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
const auto destinations = facade.GetDestinationsForID(step_name_id);
|
const auto destinations = facade.GetDestinationsForID(step_name_id);
|
||||||
const auto exits = facade.GetExitsForID(step_name_id);
|
const auto exits = facade.GetExitsForID(step_name_id);
|
||||||
const auto distance = leg_geometry.segment_distances[segment_index];
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
||||||
|
auto classes = facade.GetClasses(path_point.classes);
|
||||||
|
|
||||||
steps.push_back(RouteStep{step_name_id,
|
steps.push_back(RouteStep{step_name_id,
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
@ -132,7 +135,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
maneuver,
|
maneuver,
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
leg_geometry.BackIndex(segment_index) + 1,
|
leg_geometry.BackIndex(segment_index) + 1,
|
||||||
{intersection}});
|
{intersection},
|
||||||
|
std::move(classes)});
|
||||||
|
|
||||||
if (leg_data_index + 1 < leg_data.size())
|
if (leg_data_index + 1 < leg_data.size())
|
||||||
{
|
{
|
||||||
@ -208,7 +212,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
maneuver,
|
maneuver,
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
leg_geometry.BackIndex(segment_index) + 1,
|
leg_geometry.BackIndex(segment_index) + 1,
|
||||||
{intersection}});
|
{intersection},
|
||||||
|
std::move(target_classes)});
|
||||||
}
|
}
|
||||||
// In this case the source + target are on the same edge segment
|
// In this case the source + target are on the same edge segment
|
||||||
else
|
else
|
||||||
@ -250,7 +255,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
std::move(maneuver),
|
std::move(maneuver),
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
leg_geometry.BackIndex(segment_index) + 1,
|
leg_geometry.BackIndex(segment_index) + 1,
|
||||||
{intersection}});
|
{intersection},
|
||||||
|
std::move(source_classes)});
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
||||||
@ -289,7 +295,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
std::move(maneuver),
|
std::move(maneuver),
|
||||||
leg_geometry.locations.size() - 1,
|
leg_geometry.locations.size() - 1,
|
||||||
leg_geometry.locations.size(),
|
leg_geometry.locations.size(),
|
||||||
{intersection}});
|
{intersection},
|
||||||
|
std::move(target_classes)});
|
||||||
|
|
||||||
BOOST_ASSERT(steps.front().intersections.size() == 1);
|
BOOST_ASSERT(steps.front().intersections.size() == 1);
|
||||||
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
||||||
|
@ -74,6 +74,7 @@ struct RouteStep
|
|||||||
std::size_t geometry_begin;
|
std::size_t geometry_begin;
|
||||||
std::size_t geometry_end;
|
std::size_t geometry_end;
|
||||||
std::vector<IntermediateIntersection> intersections;
|
std::vector<IntermediateIntersection> intersections;
|
||||||
|
std::vector<std::string> classes;
|
||||||
|
|
||||||
// remove all information from the route step, marking it as invalid (used to indicate empty
|
// remove all information from the route step, marking it as invalid (used to indicate empty
|
||||||
// steps to be removed).
|
// steps to be removed).
|
||||||
@ -127,6 +128,7 @@ inline void RouteStep::Invalidate()
|
|||||||
geometry_end = 0;
|
geometry_end = 0;
|
||||||
intersections.clear();
|
intersections.clear();
|
||||||
intersections.push_back(getInvalidIntersection());
|
intersections.push_back(getInvalidIntersection());
|
||||||
|
classes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elongate by another step in front
|
// Elongate by another step in front
|
||||||
|
@ -33,6 +33,8 @@ struct PathData
|
|||||||
util::guidance::LaneTupleIdPair lane_data;
|
util::guidance::LaneTupleIdPair lane_data;
|
||||||
// travel mode of the street that leads to the turn
|
// travel mode of the street that leads to the turn
|
||||||
extractor::TravelMode travel_mode : 4;
|
extractor::TravelMode travel_mode : 4;
|
||||||
|
// user defined classed of the street that leads to the turn
|
||||||
|
extractor::ClassData classes;
|
||||||
// entry class of the turn, indicating possibility of turns
|
// entry class of the turn, indicating possibility of turns
|
||||||
util::guidance::EntryClass entry_class;
|
util::guidance::EntryClass entry_class;
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ void annotatePath(const FacadeT &facade,
|
|||||||
const auto name_index = facade.GetNameIndex(node_id);
|
const auto name_index = facade.GetNameIndex(node_id);
|
||||||
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
|
const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id);
|
||||||
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
|
const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id);
|
||||||
|
const auto classes = facade.GetClassData(node_id);
|
||||||
|
|
||||||
const auto geometry_index = facade.GetGeometryIndex(node_id);
|
const auto geometry_index = facade.GetGeometryIndex(node_id);
|
||||||
std::vector<NodeID> id_vector;
|
std::vector<NodeID> id_vector;
|
||||||
@ -186,6 +187,7 @@ void annotatePath(const FacadeT &facade,
|
|||||||
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,
|
||||||
|
classes,
|
||||||
EMPTY_ENTRY_CLASS,
|
EMPTY_ENTRY_CLASS,
|
||||||
datasource_vector[segment_idx],
|
datasource_vector[segment_idx],
|
||||||
util::guidance::TurnBearing(0),
|
util::guidance::TurnBearing(0),
|
||||||
@ -261,6 +263,7 @@ void annotatePath(const FacadeT &facade,
|
|||||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
|
||||||
facade.GetTravelMode(target_node_id),
|
facade.GetTravelMode(target_node_id),
|
||||||
|
facade.GetClassData(target_node_id),
|
||||||
EMPTY_ENTRY_CLASS,
|
EMPTY_ENTRY_CLASS,
|
||||||
datasource_vector[segment_idx],
|
datasource_vector[segment_idx],
|
||||||
util::guidance::TurnBearing(0),
|
util::guidance::TurnBearing(0),
|
||||||
|
22
include/extractor/class_data.hpp
Normal file
22
include/extractor/class_data.hpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef OSRM_EXTRACTOR_CLASSES_DATA_HPP
|
||||||
|
#define OSRM_EXTRACTOR_CLASSES_DATA_HPP
|
||||||
|
|
||||||
|
#include "util/bit_range.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
using ClassData = std::uint8_t;
|
||||||
|
static const std::uint8_t MAX_CLASS_INDEX = 8 - 1;
|
||||||
|
|
||||||
|
inline bool isSubset(const ClassData lhs, const ClassData rhs) { return (lhs & rhs) == lhs; }
|
||||||
|
|
||||||
|
inline auto getClassIndexes(const ClassData data) { return util::makeBitRange<ClassData>(data); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -85,6 +85,10 @@ struct ExtractionWay
|
|||||||
}
|
}
|
||||||
const char *GetTurnLanesBackward() const { return turn_lanes_backward.c_str(); }
|
const char *GetTurnLanesBackward() const { return turn_lanes_backward.c_str(); }
|
||||||
|
|
||||||
|
// markers for determining user-defined classes for each way
|
||||||
|
std::unordered_map<std::string, bool> forward_classes;
|
||||||
|
std::unordered_map<std::string, bool> backward_classes;
|
||||||
|
|
||||||
// speed in km/h
|
// speed in km/h
|
||||||
double forward_speed;
|
double forward_speed;
|
||||||
double backward_speed;
|
double backward_speed;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef EXTRACTOR_CALLBACKS_HPP
|
#ifndef EXTRACTOR_CALLBACKS_HPP
|
||||||
#define EXTRACTOR_CALLBACKS_HPP
|
#define EXTRACTOR_CALLBACKS_HPP
|
||||||
|
|
||||||
|
#include "extractor/class_data.hpp"
|
||||||
#include "extractor/guidance/turn_lane_types.hpp"
|
#include "extractor/guidance/turn_lane_types.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
@ -61,13 +62,18 @@ class ExtractorCallbacks
|
|||||||
using MapKey = std::tuple<std::string, std::string, std::string, std::string, std::string>;
|
using MapKey = std::tuple<std::string, std::string, std::string, std::string, std::string>;
|
||||||
using MapVal = unsigned;
|
using MapVal = unsigned;
|
||||||
std::unordered_map<MapKey, MapVal> string_map;
|
std::unordered_map<MapKey, MapVal> string_map;
|
||||||
guidance::LaneDescriptionMap lane_description_map;
|
|
||||||
ExtractionContainers &external_memory;
|
ExtractionContainers &external_memory;
|
||||||
|
std::unordered_map<std::string, ClassData> &classes_map;
|
||||||
|
guidance::LaneDescriptionMap &lane_description_map;
|
||||||
bool fallback_to_duration;
|
bool fallback_to_duration;
|
||||||
bool force_split_edges;
|
bool force_split_edges;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using ClassesMap = std::unordered_map<std::string, ClassData>;
|
||||||
|
|
||||||
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
||||||
|
std::unordered_map<std::string, ClassData> &classes_map,
|
||||||
|
guidance::LaneDescriptionMap &lane_description_map,
|
||||||
const ProfileProperties &properties);
|
const ProfileProperties &properties);
|
||||||
|
|
||||||
ExtractorCallbacks(const ExtractorCallbacks &) = delete;
|
ExtractorCallbacks(const ExtractorCallbacks &) = delete;
|
||||||
@ -81,9 +87,6 @@ class ExtractorCallbacks
|
|||||||
|
|
||||||
// warning: caller needs to take care of synchronization!
|
// warning: caller needs to take care of synchronization!
|
||||||
void ProcessWay(const osmium::Way ¤t_way, const ExtractionWay &result_way);
|
void ProcessWay(const osmium::Way ¤t_way, const ExtractionWay &result_way);
|
||||||
|
|
||||||
// destroys the internal laneDescriptionMap
|
|
||||||
guidance::LaneDescriptionMap &&moveOutLaneDescriptionMap();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,7 @@ struct InternalExtractorEdge
|
|||||||
false, // local access only
|
false, // local access only
|
||||||
false, // split edge
|
false, // split edge
|
||||||
TRAVEL_MODE_INACCESSIBLE,
|
TRAVEL_MODE_INACCESSIBLE,
|
||||||
|
0,
|
||||||
guidance::TurnLaneType::empty,
|
guidance::TurnLaneType::empty,
|
||||||
guidance::RoadClassification()),
|
guidance::RoadClassification()),
|
||||||
weight_data(), duration_data()
|
weight_data(), duration_data()
|
||||||
@ -91,6 +92,7 @@ struct InternalExtractorEdge
|
|||||||
bool restricted,
|
bool restricted,
|
||||||
bool is_split,
|
bool is_split,
|
||||||
TravelMode travel_mode,
|
TravelMode travel_mode,
|
||||||
|
ClassData classes,
|
||||||
LaneDescriptionID lane_description,
|
LaneDescriptionID lane_description,
|
||||||
guidance::RoadClassification road_classification,
|
guidance::RoadClassification road_classification,
|
||||||
util::Coordinate source_coordinate)
|
util::Coordinate source_coordinate)
|
||||||
@ -107,6 +109,7 @@ struct InternalExtractorEdge
|
|||||||
restricted,
|
restricted,
|
||||||
is_split,
|
is_split,
|
||||||
travel_mode,
|
travel_mode,
|
||||||
|
classes,
|
||||||
lane_description,
|
lane_description,
|
||||||
std::move(road_classification)),
|
std::move(road_classification)),
|
||||||
weight_data(std::move(weight_data)), duration_data(std::move(duration_data)),
|
weight_data(std::move(weight_data)), duration_data(std::move(duration_data)),
|
||||||
@ -139,6 +142,7 @@ struct InternalExtractorEdge
|
|||||||
false, // local access only
|
false, // local access only
|
||||||
false, // split edge
|
false, // split edge
|
||||||
TRAVEL_MODE_INACCESSIBLE,
|
TRAVEL_MODE_INACCESSIBLE,
|
||||||
|
0,
|
||||||
INVALID_LANE_DESCRIPTIONID,
|
INVALID_LANE_DESCRIPTIONID,
|
||||||
guidance::RoadClassification(),
|
guidance::RoadClassification(),
|
||||||
util::Coordinate());
|
util::Coordinate());
|
||||||
@ -158,6 +162,7 @@ struct InternalExtractorEdge
|
|||||||
false, // local access only
|
false, // local access only
|
||||||
false, // split edge
|
false, // split edge
|
||||||
TRAVEL_MODE_INACCESSIBLE,
|
TRAVEL_MODE_INACCESSIBLE,
|
||||||
|
0,
|
||||||
INVALID_LANE_DESCRIPTIONID,
|
INVALID_LANE_DESCRIPTIONID,
|
||||||
guidance::RoadClassification(),
|
guidance::RoadClassification(),
|
||||||
util::Coordinate());
|
util::Coordinate());
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef NODE_BASED_EDGE_HPP
|
#ifndef NODE_BASED_EDGE_HPP
|
||||||
#define NODE_BASED_EDGE_HPP
|
#define NODE_BASED_EDGE_HPP
|
||||||
|
|
||||||
|
#include "extractor/class_data.hpp"
|
||||||
#include "extractor/travel_mode.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ struct NodeBasedEdge
|
|||||||
bool restricted,
|
bool restricted,
|
||||||
bool is_split,
|
bool is_split,
|
||||||
TravelMode travel_mode,
|
TravelMode travel_mode,
|
||||||
|
ClassData classes,
|
||||||
const LaneDescriptionID lane_description_id,
|
const LaneDescriptionID lane_description_id,
|
||||||
guidance::RoadClassification road_classification);
|
guidance::RoadClassification road_classification);
|
||||||
|
|
||||||
@ -46,6 +48,7 @@ struct NodeBasedEdge
|
|||||||
std::uint8_t restricted : 1; // 1
|
std::uint8_t restricted : 1; // 1
|
||||||
std::uint8_t is_split : 1; // 1
|
std::uint8_t is_split : 1; // 1
|
||||||
TravelMode travel_mode : 4; // 4
|
TravelMode travel_mode : 4; // 4
|
||||||
|
ClassData classes; // 8 1
|
||||||
LaneDescriptionID lane_description_id; // 16 2
|
LaneDescriptionID lane_description_id; // 16 2
|
||||||
guidance::RoadClassification road_classification; // 16 2
|
guidance::RoadClassification road_classification; // 16 2
|
||||||
};
|
};
|
||||||
@ -65,6 +68,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
|
|||||||
bool restricted,
|
bool restricted,
|
||||||
bool is_split,
|
bool is_split,
|
||||||
TravelMode travel_mode,
|
TravelMode travel_mode,
|
||||||
|
ClassData classes,
|
||||||
const LaneDescriptionID lane_description_id,
|
const LaneDescriptionID lane_description_id,
|
||||||
guidance::RoadClassification road_classification);
|
guidance::RoadClassification road_classification);
|
||||||
|
|
||||||
@ -95,12 +99,14 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
|
|||||||
bool restricted,
|
bool restricted,
|
||||||
bool is_split,
|
bool is_split,
|
||||||
TravelMode travel_mode,
|
TravelMode travel_mode,
|
||||||
|
ClassData classes,
|
||||||
const LaneDescriptionID lane_description_id,
|
const LaneDescriptionID lane_description_id,
|
||||||
guidance::RoadClassification road_classification)
|
guidance::RoadClassification road_classification)
|
||||||
: source(source), target(target), name_id(name_id), weight(weight), duration(duration),
|
: source(source), target(target), name_id(name_id), weight(weight), duration(duration),
|
||||||
forward(forward), backward(backward), roundabout(roundabout), circular(circular),
|
forward(forward), backward(backward), roundabout(roundabout), circular(circular),
|
||||||
startpoint(startpoint), restricted(restricted), is_split(is_split), travel_mode(travel_mode),
|
startpoint(startpoint), restricted(restricted), is_split(is_split), travel_mode(travel_mode),
|
||||||
lane_description_id(lane_description_id), road_classification(std::move(road_classification))
|
classes(classes), lane_description_id(lane_description_id),
|
||||||
|
road_classification(std::move(road_classification))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +140,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
|||||||
bool restricted,
|
bool restricted,
|
||||||
bool is_split,
|
bool is_split,
|
||||||
TravelMode travel_mode,
|
TravelMode travel_mode,
|
||||||
|
ClassData classes,
|
||||||
const LaneDescriptionID lane_description_id,
|
const LaneDescriptionID lane_description_id,
|
||||||
guidance::RoadClassification road_classification)
|
guidance::RoadClassification road_classification)
|
||||||
: NodeBasedEdge(SPECIAL_NODEID,
|
: NodeBasedEdge(SPECIAL_NODEID,
|
||||||
@ -149,6 +156,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
|||||||
restricted,
|
restricted,
|
||||||
is_split,
|
is_split,
|
||||||
travel_mode,
|
travel_mode,
|
||||||
|
classes,
|
||||||
lane_description_id,
|
lane_description_id,
|
||||||
std::move(road_classification)),
|
std::move(road_classification)),
|
||||||
osm_source_id(std::move(source)), osm_target_id(std::move(target))
|
osm_source_id(std::move(source)), osm_target_id(std::move(target))
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
|
#ifndef OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
|
||||||
#define OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
|
#define OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
|
||||||
|
|
||||||
|
#include "extractor/class_data.hpp"
|
||||||
#include "extractor/travel_mode.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
|
|
||||||
#include "storage/io_fwd.hpp"
|
#include "storage/io_fwd.hpp"
|
||||||
@ -41,16 +42,18 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
|||||||
EdgeBasedNodeDataContainerImpl() = default;
|
EdgeBasedNodeDataContainerImpl() = default;
|
||||||
|
|
||||||
EdgeBasedNodeDataContainerImpl(std::size_t size)
|
EdgeBasedNodeDataContainerImpl(std::size_t size)
|
||||||
: geometry_ids(size), name_ids(size), component_ids(size), travel_modes(size)
|
: geometry_ids(size), name_ids(size), component_ids(size), travel_modes(size), classes(size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeBasedNodeDataContainerImpl(Vector<GeometryID> geometry_ids,
|
EdgeBasedNodeDataContainerImpl(Vector<GeometryID> geometry_ids,
|
||||||
Vector<NameID> name_ids,
|
Vector<NameID> name_ids,
|
||||||
Vector<ComponentID> component_ids,
|
Vector<ComponentID> component_ids,
|
||||||
Vector<TravelMode> travel_modes)
|
Vector<TravelMode> travel_modes,
|
||||||
|
Vector<ClassData> classes)
|
||||||
: geometry_ids(std::move(geometry_ids)), name_ids(std::move(name_ids)),
|
: geometry_ids(std::move(geometry_ids)), name_ids(std::move(name_ids)),
|
||||||
component_ids(std::move(component_ids)), travel_modes(std::move(travel_modes))
|
component_ids(std::move(component_ids)), travel_modes(std::move(travel_modes)),
|
||||||
|
classes(std::move(classes))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,13 +65,20 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
|||||||
|
|
||||||
ComponentID GetComponentID(const NodeID node_id) const { return component_ids[node_id]; }
|
ComponentID GetComponentID(const NodeID node_id) const { return component_ids[node_id]; }
|
||||||
|
|
||||||
|
ClassData GetClassData(const NodeID node_id) const { return classes[node_id]; }
|
||||||
|
|
||||||
// Used by EdgeBasedGraphFactory to fill data structure
|
// Used by EdgeBasedGraphFactory to fill data structure
|
||||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||||
void SetData(NodeID node_id, GeometryID geometry_id, NameID name_id, TravelMode travel_mode)
|
void SetData(NodeID node_id,
|
||||||
|
GeometryID geometry_id,
|
||||||
|
NameID name_id,
|
||||||
|
TravelMode travel_mode,
|
||||||
|
ClassData class_data)
|
||||||
{
|
{
|
||||||
geometry_ids[node_id] = geometry_id;
|
geometry_ids[node_id] = geometry_id;
|
||||||
name_ids[node_id] = name_id;
|
name_ids[node_id] = name_id;
|
||||||
travel_modes[node_id] = travel_mode;
|
travel_modes[node_id] = travel_mode;
|
||||||
|
classes[node_id] = class_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by EdgeBasedGraphFactory to fill data structure
|
// Used by EdgeBasedGraphFactory to fill data structure
|
||||||
@ -91,6 +101,7 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
|||||||
util::inplacePermutation(name_ids.begin(), name_ids.end(), permutation);
|
util::inplacePermutation(name_ids.begin(), name_ids.end(), permutation);
|
||||||
util::inplacePermutation(component_ids.begin(), component_ids.end(), permutation);
|
util::inplacePermutation(component_ids.begin(), component_ids.end(), permutation);
|
||||||
util::inplacePermutation(travel_modes.begin(), travel_modes.end(), permutation);
|
util::inplacePermutation(travel_modes.begin(), travel_modes.end(), permutation);
|
||||||
|
util::inplacePermutation(classes.begin(), classes.end(), permutation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -98,6 +109,7 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
|||||||
Vector<NameID> name_ids;
|
Vector<NameID> name_ids;
|
||||||
Vector<ComponentID> component_ids;
|
Vector<ComponentID> component_ids;
|
||||||
Vector<TravelMode> travel_modes;
|
Vector<TravelMode> travel_modes;
|
||||||
|
Vector<ClassData> classes;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef PROFILE_PROPERTIES_HPP
|
#ifndef PROFILE_PROPERTIES_HPP
|
||||||
#define PROFILE_PROPERTIES_HPP
|
#define PROFILE_PROPERTIES_HPP
|
||||||
|
|
||||||
|
#include "extractor/class_data.hpp"
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -17,6 +19,7 @@ const constexpr auto DEFAULT_MAX_SPEED = 180 / 3.6; // 180kmph -> m/s
|
|||||||
struct ProfileProperties
|
struct ProfileProperties
|
||||||
{
|
{
|
||||||
static constexpr int MAX_WEIGHT_NAME_LENGTH = 255;
|
static constexpr int MAX_WEIGHT_NAME_LENGTH = 255;
|
||||||
|
static constexpr int MAX_CLASS_NAME_LENGTH = 255;
|
||||||
|
|
||||||
ProfileProperties()
|
ProfileProperties()
|
||||||
: traffic_signal_penalty(0), u_turn_penalty(0),
|
: traffic_signal_penalty(0), u_turn_penalty(0),
|
||||||
@ -66,6 +69,22 @@ struct ProfileProperties
|
|||||||
return std::string(weight_name);
|
return std::string(weight_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetClassName(std::size_t index, const std::string &name)
|
||||||
|
{
|
||||||
|
char *name_ptr = class_names[index];
|
||||||
|
auto count = std::min<std::size_t>(name.length(), MAX_CLASS_NAME_LENGTH) + 1;
|
||||||
|
std::copy_n(name.c_str(), count, name_ptr);
|
||||||
|
// Make sure this is always zero terminated
|
||||||
|
BOOST_ASSERT(class_names[index][count - 1] == '\0');
|
||||||
|
BOOST_ASSERT(class_names[index][MAX_CLASS_NAME_LENGTH] == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetClassName(std::size_t index) const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(index <= MAX_CLASS_INDEX);
|
||||||
|
return std::string(class_names[index]);
|
||||||
|
}
|
||||||
|
|
||||||
double GetWeightMultiplier() const { return std::pow(10., weight_precision); }
|
double GetWeightMultiplier() const { return std::pow(10., weight_precision); }
|
||||||
|
|
||||||
double GetMaxTurnWeight() const
|
double GetMaxTurnWeight() const
|
||||||
@ -86,6 +105,8 @@ struct ProfileProperties
|
|||||||
bool fallback_to_duration;
|
bool fallback_to_duration;
|
||||||
//! stores the name of the weight (e.g. 'duration', 'distance', 'safety')
|
//! stores the name of the weight (e.g. 'duration', 'distance', 'safety')
|
||||||
char weight_name[MAX_WEIGHT_NAME_LENGTH + 1];
|
char weight_name[MAX_WEIGHT_NAME_LENGTH + 1];
|
||||||
|
//! stores the names of each class
|
||||||
|
std::array<char[MAX_CLASS_NAME_LENGTH + 1], MAX_CLASS_INDEX + 1> class_names;
|
||||||
unsigned weight_precision = 1;
|
unsigned weight_precision = 1;
|
||||||
bool force_split_edges = false;
|
bool force_split_edges = false;
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ inline void read(storage::io::FileReader &reader,
|
|||||||
storage::serialization::read(reader, node_data_container.name_ids);
|
storage::serialization::read(reader, node_data_container.name_ids);
|
||||||
storage::serialization::read(reader, node_data_container.component_ids);
|
storage::serialization::read(reader, node_data_container.component_ids);
|
||||||
storage::serialization::read(reader, node_data_container.travel_modes);
|
storage::serialization::read(reader, node_data_container.travel_modes);
|
||||||
|
storage::serialization::read(reader, node_data_container.classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <storage::Ownership Ownership>
|
template <storage::Ownership Ownership>
|
||||||
@ -131,6 +132,7 @@ inline void write(storage::io::FileWriter &writer,
|
|||||||
storage::serialization::write(writer, node_data_container.name_ids);
|
storage::serialization::write(writer, node_data_container.name_ids);
|
||||||
storage::serialization::write(writer, node_data_container.component_ids);
|
storage::serialization::write(writer, node_data_container.component_ids);
|
||||||
storage::serialization::write(writer, node_data_container.travel_modes);
|
storage::serialization::write(writer, node_data_container.travel_modes);
|
||||||
|
storage::serialization::write(writer, node_data_container.classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// read/write for conditional turn restrictions file
|
// read/write for conditional turn restrictions file
|
||||||
|
@ -23,6 +23,7 @@ const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA",
|
|||||||
"NAME_ID_LIST",
|
"NAME_ID_LIST",
|
||||||
"COMPONENT_ID_LIST",
|
"COMPONENT_ID_LIST",
|
||||||
"TRAVEL_MODE_LIST",
|
"TRAVEL_MODE_LIST",
|
||||||
|
"CLASSES_LIST",
|
||||||
"CH_GRAPH_NODE_LIST",
|
"CH_GRAPH_NODE_LIST",
|
||||||
"CH_GRAPH_EDGE_LIST",
|
"CH_GRAPH_EDGE_LIST",
|
||||||
"COORDINATE_LIST",
|
"COORDINATE_LIST",
|
||||||
@ -79,6 +80,7 @@ struct DataLayout
|
|||||||
NAME_ID_LIST,
|
NAME_ID_LIST,
|
||||||
COMPONENT_ID_LIST,
|
COMPONENT_ID_LIST,
|
||||||
TRAVEL_MODE_LIST,
|
TRAVEL_MODE_LIST,
|
||||||
|
CLASSES_LIST,
|
||||||
CH_GRAPH_NODE_LIST,
|
CH_GRAPH_NODE_LIST,
|
||||||
CH_GRAPH_EDGE_LIST,
|
CH_GRAPH_EDGE_LIST,
|
||||||
COORDINATE_LIST,
|
COORDINATE_LIST,
|
||||||
|
99
include/util/bit_range.hpp
Normal file
99
include/util/bit_range.hpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#ifndef OSRM_UTIL_BIT_RANGE_HPP
|
||||||
|
#define OSRM_UTIL_BIT_RANGE_HPP
|
||||||
|
|
||||||
|
#include "util/msb.hpp"
|
||||||
|
|
||||||
|
#include <boost/iterator/iterator_facade.hpp>
|
||||||
|
#include <boost/range/iterator_range.hpp>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <typename T> std::size_t countOnes(T value)
|
||||||
|
{
|
||||||
|
static_assert(std::is_unsigned<T>::value, "Only unsigned types allowed");
|
||||||
|
std::size_t number_of_ones = 0;
|
||||||
|
while (value > 0)
|
||||||
|
{
|
||||||
|
auto index = msb(value);
|
||||||
|
value = value & ~(T{1} << index);
|
||||||
|
number_of_ones++;
|
||||||
|
}
|
||||||
|
return number_of_ones;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__))
|
||||||
|
inline std::size_t countOnes(std::uint8_t value)
|
||||||
|
{
|
||||||
|
return __builtin_popcount(std::uint32_t{value});
|
||||||
|
}
|
||||||
|
inline std::size_t countOnes(std::uint16_t value)
|
||||||
|
{
|
||||||
|
return __builtin_popcount(std::uint32_t{value});
|
||||||
|
}
|
||||||
|
inline std::size_t countOnes(unsigned int value) { return __builtin_popcount(value); }
|
||||||
|
inline std::size_t countOnes(unsigned long value) { return __builtin_popcountl(value); }
|
||||||
|
inline std::size_t countOnes(unsigned long long value) { return __builtin_popcountll(value); }
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Investigate if we can replace this with
|
||||||
|
// http://www.boost.org/doc/libs/1_64_0/libs/dynamic_bitset/dynamic_bitset.html
|
||||||
|
template <typename DataT>
|
||||||
|
class BitIterator : public boost::iterator_facade<BitIterator<DataT>,
|
||||||
|
const std::size_t,
|
||||||
|
boost::forward_traversal_tag,
|
||||||
|
const std::size_t>
|
||||||
|
{
|
||||||
|
typedef boost::iterator_facade<BitIterator<DataT>,
|
||||||
|
const std::size_t,
|
||||||
|
boost::forward_traversal_tag,
|
||||||
|
const std::size_t>
|
||||||
|
base_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename base_t::value_type value_type;
|
||||||
|
typedef typename base_t::difference_type difference_type;
|
||||||
|
typedef typename base_t::reference reference;
|
||||||
|
typedef std::random_access_iterator_tag iterator_category;
|
||||||
|
|
||||||
|
explicit BitIterator() : m_value(0) {}
|
||||||
|
explicit BitIterator(const DataT x) : m_value(std::move(x)) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void increment()
|
||||||
|
{
|
||||||
|
auto index = msb(m_value);
|
||||||
|
m_value = m_value & ~(DataT{1} << index);
|
||||||
|
}
|
||||||
|
|
||||||
|
difference_type distance_to(const BitIterator &other) const
|
||||||
|
{
|
||||||
|
return detail::countOnes(m_value) - detail::countOnes(other.m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool equal(const BitIterator &other) const { return m_value == other.m_value; }
|
||||||
|
|
||||||
|
reference dereference() const
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(m_value > 0);
|
||||||
|
return msb(m_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class ::boost::iterator_core_access;
|
||||||
|
DataT m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns range over all 1 bits of value
|
||||||
|
template <typename T> auto makeBitRange(const T value)
|
||||||
|
{
|
||||||
|
return boost::make_iterator_range(BitIterator<T>{value}, BitIterator<T>{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -26,16 +27,24 @@ template <typename T> std::size_t msb(T value)
|
|||||||
return msb - 1;
|
return msb - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)) && __x86_64__
|
#if (defined(__clang__) || defined(__GNUC__) || defined(__GNUG__))
|
||||||
inline std::size_t msb(std::uint64_t v)
|
inline std::size_t msb(unsigned long long v)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(v > 0);
|
BOOST_ASSERT(v > 0);
|
||||||
return 63UL - __builtin_clzl(v);
|
constexpr auto MSB_INDEX = CHAR_BIT * sizeof(unsigned long long) - 1;
|
||||||
|
return MSB_INDEX - __builtin_clzll(v);
|
||||||
}
|
}
|
||||||
inline std::size_t msb(std::uint32_t v)
|
inline std::size_t msb(unsigned long v)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(v > 0);
|
BOOST_ASSERT(v > 0);
|
||||||
return 31UL - __builtin_clz(v);
|
constexpr auto MSB_INDEX = CHAR_BIT * sizeof(unsigned long) - 1;
|
||||||
|
return MSB_INDEX - __builtin_clzl(v);
|
||||||
|
}
|
||||||
|
inline std::size_t msb(unsigned int v)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(v > 0);
|
||||||
|
constexpr auto MSB_INDEX = CHAR_BIT * sizeof(unsigned int) - 1;
|
||||||
|
return MSB_INDEX - __builtin_clz(v);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef NODE_BASED_GRAPH_HPP
|
#ifndef NODE_BASED_GRAPH_HPP
|
||||||
#define NODE_BASED_GRAPH_HPP
|
#define NODE_BASED_GRAPH_HPP
|
||||||
|
|
||||||
|
#include "extractor/class_data.hpp"
|
||||||
#include "extractor/guidance/road_classification.hpp"
|
#include "extractor/guidance/road_classification.hpp"
|
||||||
#include "extractor/node_based_edge.hpp"
|
#include "extractor/node_based_edge.hpp"
|
||||||
#include "util/dynamic_graph.hpp"
|
#include "util/dynamic_graph.hpp"
|
||||||
@ -35,10 +36,12 @@ struct NodeBasedEdgeData
|
|||||||
bool startpoint,
|
bool startpoint,
|
||||||
bool restricted,
|
bool restricted,
|
||||||
extractor::TravelMode travel_mode,
|
extractor::TravelMode travel_mode,
|
||||||
|
extractor::ClassData classes,
|
||||||
const LaneDescriptionID lane_description_id)
|
const LaneDescriptionID lane_description_id)
|
||||||
: weight(weight), duration(duration), edge_id(edge_id), name_id(name_id),
|
: weight(weight), duration(duration), edge_id(edge_id), name_id(name_id),
|
||||||
reversed(reversed), roundabout(roundabout), circular(circular), startpoint(startpoint),
|
reversed(reversed), roundabout(roundabout), circular(circular), startpoint(startpoint),
|
||||||
restricted(restricted), travel_mode(travel_mode), lane_description_id(lane_description_id)
|
restricted(restricted), travel_mode(travel_mode), classes(classes),
|
||||||
|
lane_description_id(lane_description_id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +55,7 @@ struct NodeBasedEdgeData
|
|||||||
bool startpoint : 1;
|
bool startpoint : 1;
|
||||||
bool restricted : 1;
|
bool restricted : 1;
|
||||||
extractor::TravelMode travel_mode : 4;
|
extractor::TravelMode travel_mode : 4;
|
||||||
|
extractor::ClassData classes;
|
||||||
LaneDescriptionID lane_description_id;
|
LaneDescriptionID lane_description_id;
|
||||||
extractor::guidance::RoadClassification road_classification;
|
extractor::guidance::RoadClassification road_classification;
|
||||||
|
|
||||||
@ -59,7 +63,7 @@ struct NodeBasedEdgeData
|
|||||||
{
|
{
|
||||||
return (reversed == other.reversed) && (roundabout == other.roundabout) &&
|
return (reversed == other.reversed) && (roundabout == other.roundabout) &&
|
||||||
(circular == other.circular) && (startpoint == other.startpoint) &&
|
(circular == other.circular) && (startpoint == other.startpoint) &&
|
||||||
(travel_mode == other.travel_mode) &&
|
(travel_mode == other.travel_mode) && (classes == other.classes) &&
|
||||||
(road_classification == other.road_classification) &&
|
(road_classification == other.road_classification) &&
|
||||||
(restricted == other.restricted);
|
(restricted == other.restricted);
|
||||||
}
|
}
|
||||||
@ -89,6 +93,7 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
|
|||||||
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;
|
||||||
output_edge.data.travel_mode = input_edge.travel_mode;
|
output_edge.data.travel_mode = input_edge.travel_mode;
|
||||||
|
output_edge.data.classes = input_edge.classes;
|
||||||
output_edge.data.startpoint = input_edge.startpoint;
|
output_edge.data.startpoint = input_edge.startpoint;
|
||||||
output_edge.data.restricted = input_edge.restricted;
|
output_edge.data.restricted = input_edge.restricted;
|
||||||
output_edge.data.road_classification = input_edge.road_classification;
|
output_edge.data.road_classification = input_edge.road_classification;
|
||||||
|
@ -366,6 +366,9 @@ function way_function(way, result)
|
|||||||
'handle_maxspeed',
|
'handle_maxspeed',
|
||||||
'handle_penalties',
|
'handle_penalties',
|
||||||
|
|
||||||
|
-- compute class labels
|
||||||
|
'handle_classes',
|
||||||
|
|
||||||
-- handle turn lanes and road classification, used for guidance
|
-- handle turn lanes and road classification, used for guidance
|
||||||
'handle_turn_lanes',
|
'handle_turn_lanes',
|
||||||
'handle_classification',
|
'handle_classification',
|
||||||
|
@ -277,6 +277,38 @@ function Handlers.handle_speed(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- add class information
|
||||||
|
function Handlers.handle_classes(way,result,data,profile)
|
||||||
|
local forward_toll, backward_toll = Tags.get_forward_backward_by_key(way, data, "toll")
|
||||||
|
local forward_route, backward_route = Tags.get_forward_backward_by_key(way, data, "route")
|
||||||
|
|
||||||
|
if forward_toll == "yes" then
|
||||||
|
result.forward_classes["toll"] = true
|
||||||
|
end
|
||||||
|
if backward_toll == "yes" then
|
||||||
|
result.backward_classes["toll"] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if forward_route == "ferry" then
|
||||||
|
result.forward_classes["ferry"] = true
|
||||||
|
end
|
||||||
|
if backward_route == "ferry" then
|
||||||
|
result.backward_classes["ferry"] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if result.forward_restricted then
|
||||||
|
result.forward_classes["restricted"] = true
|
||||||
|
end
|
||||||
|
if result.backward_restricted then
|
||||||
|
result.backward_classes["restricted"] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if data.highway == "motorway" or data.highway == "motorway_link" then
|
||||||
|
result.forward_classes["motorway"] = true
|
||||||
|
result.backward_classes["motorway"] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- reduce speed on bad surfaces
|
-- reduce speed on bad surfaces
|
||||||
function Handlers.handle_surface(way,result,data,profile)
|
function Handlers.handle_surface(way,result,data,profile)
|
||||||
local surface = way:get_value_by_key("surface")
|
local surface = way:get_value_by_key("surface")
|
||||||
|
@ -265,6 +265,18 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo
|
|||||||
route_step.values["maneuver"] = makeStepManeuver(std::move(step.maneuver));
|
route_step.values["maneuver"] = makeStepManeuver(std::move(step.maneuver));
|
||||||
route_step.values["geometry"] = std::move(geometry);
|
route_step.values["geometry"] = std::move(geometry);
|
||||||
|
|
||||||
|
if (!step.classes.empty())
|
||||||
|
{
|
||||||
|
util::json::Array classes;
|
||||||
|
classes.values.reserve(step.classes.size());
|
||||||
|
std::transform(
|
||||||
|
step.classes.begin(),
|
||||||
|
step.classes.end(),
|
||||||
|
std::back_inserter(classes.values),
|
||||||
|
[](const std::string &class_name) { return util::json::String{class_name}; });
|
||||||
|
route_step.values["classes"] = std::move(classes);
|
||||||
|
}
|
||||||
|
|
||||||
util::json::Array intersections;
|
util::json::Array intersections;
|
||||||
intersections.values.reserve(step.intersections.size());
|
intersections.values.reserve(step.intersections.size());
|
||||||
std::transform(step.intersections.begin(),
|
std::transform(step.intersections.begin(),
|
||||||
|
@ -486,6 +486,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
|||||||
auto &new_next_to_last = *(steps.end() - 2);
|
auto &new_next_to_last = *(steps.end() - 2);
|
||||||
next_to_last_step.AdaptStepSignage(new_next_to_last);
|
next_to_last_step.AdaptStepSignage(new_next_to_last);
|
||||||
next_to_last_step.mode = new_next_to_last.mode;
|
next_to_last_step.mode = new_next_to_last.mode;
|
||||||
|
next_to_last_step.classes = new_next_to_last.classes;
|
||||||
// the geometry indices of the last step are already correct;
|
// the geometry indices of the last step are already correct;
|
||||||
}
|
}
|
||||||
else if (util::coordinate_calculation::haversineDistance(
|
else if (util::coordinate_calculation::haversineDistance(
|
||||||
|
@ -148,13 +148,15 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
|
|||||||
m_edge_based_node_container.SetData(forward_data.edge_id,
|
m_edge_based_node_container.SetData(forward_data.edge_id,
|
||||||
GeometryID{packed_geometry_id, true},
|
GeometryID{packed_geometry_id, true},
|
||||||
forward_data.name_id,
|
forward_data.name_id,
|
||||||
forward_data.travel_mode);
|
forward_data.travel_mode,
|
||||||
|
forward_data.classes);
|
||||||
if (reverse_data.edge_id != SPECIAL_EDGEID)
|
if (reverse_data.edge_id != SPECIAL_EDGEID)
|
||||||
{
|
{
|
||||||
m_edge_based_node_container.SetData(reverse_data.edge_id,
|
m_edge_based_node_container.SetData(reverse_data.edge_id,
|
||||||
GeometryID{packed_geometry_id, false},
|
GeometryID{packed_geometry_id, false},
|
||||||
reverse_data.name_id,
|
reverse_data.name_id,
|
||||||
reverse_data.travel_mode);
|
reverse_data.travel_mode,
|
||||||
|
reverse_data.classes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add segments of edge-based nodes
|
// Add segments of edge-based nodes
|
||||||
|
@ -63,6 +63,21 @@ namespace osrm
|
|||||||
namespace extractor
|
namespace extractor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// Converts the class name map into a fixed mapping of index to name
|
||||||
|
void SetClassNames(const ExtractorCallbacks::ClassesMap &classes_map,
|
||||||
|
ProfileProperties &profile_properties)
|
||||||
|
{
|
||||||
|
for (const auto &pair : classes_map)
|
||||||
|
{
|
||||||
|
auto range = getClassIndexes(pair.second);
|
||||||
|
BOOST_ASSERT(range.size() == 1);
|
||||||
|
profile_properties.SetClassName(range.front(), pair.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Refactor this function into smaller functions for better readability.
|
* TODO: Refactor this function into smaller functions for better readability.
|
||||||
*
|
*
|
||||||
@ -201,8 +216,13 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
|
|||||||
TIMER_START(parsing);
|
TIMER_START(parsing);
|
||||||
|
|
||||||
ExtractionContainers extraction_containers;
|
ExtractionContainers extraction_containers;
|
||||||
auto extractor_callbacks = std::make_unique<ExtractorCallbacks>(
|
ExtractorCallbacks::ClassesMap classes_map;
|
||||||
extraction_containers, scripting_environment.GetProfileProperties());
|
guidance::LaneDescriptionMap turn_lane_map;
|
||||||
|
auto extractor_callbacks =
|
||||||
|
std::make_unique<ExtractorCallbacks>(extraction_containers,
|
||||||
|
classes_map,
|
||||||
|
turn_lane_map,
|
||||||
|
scripting_environment.GetProfileProperties());
|
||||||
|
|
||||||
// setup raster sources
|
// setup raster sources
|
||||||
scripting_environment.SetupSources();
|
scripting_environment.SetupSources();
|
||||||
@ -304,10 +324,6 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
|
|||||||
util::Log() << "Raw input contains " << number_of_nodes << " nodes, " << number_of_ways
|
util::Log() << "Raw input contains " << number_of_nodes << " nodes, " << number_of_ways
|
||||||
<< " ways, and " << number_of_relations << " relations";
|
<< " ways, and " << number_of_relations << " relations";
|
||||||
|
|
||||||
// take control over the turn lane map
|
|
||||||
guidance::LaneDescriptionMap turn_lane_map;
|
|
||||||
turn_lane_map.data = extractor_callbacks->moveOutLaneDescriptionMap().data;
|
|
||||||
|
|
||||||
extractor_callbacks.reset();
|
extractor_callbacks.reset();
|
||||||
|
|
||||||
if (extraction_containers.all_edges_list.empty())
|
if (extraction_containers.all_edges_list.empty())
|
||||||
@ -321,8 +337,9 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
|
|||||||
config.restriction_file_name,
|
config.restriction_file_name,
|
||||||
config.names_file_name);
|
config.names_file_name);
|
||||||
|
|
||||||
files::writeProfileProperties(config.profile_properties_output_path,
|
auto profile_properties = scripting_environment.GetProfileProperties();
|
||||||
scripting_environment.GetProfileProperties());
|
SetClassNames(classes_map, profile_properties);
|
||||||
|
files::writeProfileProperties(config.profile_properties_output_path, profile_properties);
|
||||||
|
|
||||||
TIMER_STOP(extracting);
|
TIMER_STOP(extracting);
|
||||||
util::Log() << "extraction finished after " << TIMER_SEC(extracting) << "s";
|
util::Log() << "extraction finished after " << TIMER_SEC(extracting) << "s";
|
||||||
|
@ -34,8 +34,11 @@ using TurnLaneDescription = guidance::TurnLaneDescription;
|
|||||||
namespace TurnLaneType = guidance::TurnLaneType;
|
namespace TurnLaneType = guidance::TurnLaneType;
|
||||||
|
|
||||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers_,
|
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers_,
|
||||||
|
std::unordered_map<std::string, ClassData> &classes_map,
|
||||||
|
guidance::LaneDescriptionMap &lane_description_map,
|
||||||
const ProfileProperties &properties)
|
const ProfileProperties &properties)
|
||||||
: external_memory(extraction_containers_),
|
: external_memory(extraction_containers_), classes_map(classes_map),
|
||||||
|
lane_description_map(lane_description_map),
|
||||||
fallback_to_duration(properties.fallback_to_duration),
|
fallback_to_duration(properties.fallback_to_duration),
|
||||||
force_split_edges(properties.force_split_edges)
|
force_split_edges(properties.force_split_edges)
|
||||||
{
|
{
|
||||||
@ -175,6 +178,38 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto classStringToMask = [this](const std::string &class_name) {
|
||||||
|
auto iter = classes_map.find(class_name);
|
||||||
|
if (iter == classes_map.end())
|
||||||
|
{
|
||||||
|
if (classes_map.size() > MAX_CLASS_INDEX)
|
||||||
|
{
|
||||||
|
throw util::exception("Maximum number of classes if " +
|
||||||
|
std::to_string(MAX_CLASS_INDEX + 1));
|
||||||
|
}
|
||||||
|
ClassData class_mask = 1u << classes_map.size();
|
||||||
|
classes_map[class_name] = class_mask;
|
||||||
|
return class_mask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const auto classesToMask = [&](const auto &classes) {
|
||||||
|
ClassData mask = 0;
|
||||||
|
for (const auto &name_and_flag : classes)
|
||||||
|
{
|
||||||
|
if (name_and_flag.second)
|
||||||
|
{
|
||||||
|
mask |= classStringToMask(name_and_flag.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
};
|
||||||
|
const ClassData forward_classes = classesToMask(parsed_way.forward_classes);
|
||||||
|
const ClassData backward_classes = classesToMask(parsed_way.backward_classes);
|
||||||
|
|
||||||
const auto laneStringToDescription = [](const std::string &lane_string) -> TurnLaneDescription {
|
const auto laneStringToDescription = [](const std::string &lane_string) -> TurnLaneDescription {
|
||||||
if (lane_string.empty())
|
if (lane_string.empty())
|
||||||
return {};
|
return {};
|
||||||
@ -330,7 +365,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
(force_split_edges || (parsed_way.forward_rate != parsed_way.backward_rate) ||
|
(force_split_edges || (parsed_way.forward_rate != parsed_way.backward_rate) ||
|
||||||
(parsed_way.forward_speed != parsed_way.backward_speed) ||
|
(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) || (forward_classes != backward_classes));
|
||||||
|
|
||||||
if (in_forward_direction)
|
if (in_forward_direction)
|
||||||
{ // add (forward) segments or (forward,backward) for non-split edges in backward direction
|
{ // add (forward) segments or (forward,backward) for non-split edges in backward direction
|
||||||
@ -352,6 +387,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
parsed_way.forward_restricted,
|
parsed_way.forward_restricted,
|
||||||
split_edge,
|
split_edge,
|
||||||
parsed_way.forward_travel_mode,
|
parsed_way.forward_travel_mode,
|
||||||
|
forward_classes,
|
||||||
turn_lane_id_forward,
|
turn_lane_id_forward,
|
||||||
road_classification,
|
road_classification,
|
||||||
{}));
|
{}));
|
||||||
@ -378,6 +414,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
parsed_way.backward_restricted,
|
parsed_way.backward_restricted,
|
||||||
split_edge,
|
split_edge,
|
||||||
parsed_way.backward_travel_mode,
|
parsed_way.backward_travel_mode,
|
||||||
|
backward_classes,
|
||||||
turn_lane_id_backward,
|
turn_lane_id_backward,
|
||||||
road_classification,
|
road_classification,
|
||||||
{}));
|
{}));
|
||||||
@ -399,9 +436,5 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
OSMNodeID{static_cast<std::uint64_t>(nodes.back().ref())}});
|
OSMNodeID{static_cast<std::uint64_t>(nodes.back().ref())}});
|
||||||
}
|
}
|
||||||
|
|
||||||
guidance::LaneDescriptionMap &&ExtractorCallbacks::moveOutLaneDescriptionMap()
|
|
||||||
{
|
|
||||||
return std::move(lane_description_map);
|
|
||||||
}
|
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -75,9 +75,6 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
|||||||
const ConnectedRoad &road) const
|
const ConnectedRoad &road) const
|
||||||
{
|
{
|
||||||
const auto type = findBasicTurnType(via_edge, road);
|
const auto type = findBasicTurnType(via_edge, road);
|
||||||
// handle travel modes:
|
|
||||||
const auto in_mode = node_based_graph.GetEdgeData(via_edge).travel_mode;
|
|
||||||
const auto out_mode = node_based_graph.GetEdgeData(road.eid).travel_mode;
|
|
||||||
if (type == TurnType::OnRamp)
|
if (type == TurnType::OnRamp)
|
||||||
{
|
{
|
||||||
return {TurnType::OnRamp, getTurnDirection(road.angle)};
|
return {TurnType::OnRamp, getTurnDirection(road.angle)};
|
||||||
@ -87,6 +84,15 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
|||||||
{
|
{
|
||||||
return {TurnType::Continue, DirectionModifier::UTurn};
|
return {TurnType::Continue, DirectionModifier::UTurn};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle travel modes:
|
||||||
|
const auto in_mode = node_based_graph.GetEdgeData(via_edge).travel_mode;
|
||||||
|
const auto out_mode = node_based_graph.GetEdgeData(road.eid).travel_mode;
|
||||||
|
const auto in_classes = node_based_graph.GetEdgeData(via_edge).classes;
|
||||||
|
const auto out_classes = node_based_graph.GetEdgeData(road.eid).classes;
|
||||||
|
// if we just lose class flags we don't want to notify
|
||||||
|
const auto needs_notification = in_mode != out_mode || !isSubset(out_classes, in_classes);
|
||||||
|
|
||||||
if (type == TurnType::Turn)
|
if (type == TurnType::Turn)
|
||||||
{
|
{
|
||||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||||
@ -141,14 +147,14 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return {in_mode == out_mode ? TurnType::NewName : TurnType::Notification,
|
return {needs_notification ? TurnType::Notification : TurnType::NewName,
|
||||||
getTurnDirection(road.angle)};
|
getTurnDirection(road.angle)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// name has not changed, suppress a turn here or indicate mode change
|
// name has not changed, suppress a turn here or indicate mode change
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (in_mode != out_mode)
|
if (needs_notification)
|
||||||
return {TurnType::Notification, getTurnDirection(road.angle)};
|
return {TurnType::Notification, getTurnDirection(road.angle)};
|
||||||
else
|
else
|
||||||
return {num_roads == 2 ? TurnType::NoTurn : TurnType::Suppressed,
|
return {num_roads == 2 ? TurnType::NoTurn : TurnType::Suppressed,
|
||||||
@ -156,7 +162,7 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(type == TurnType::Continue);
|
BOOST_ASSERT(type == TurnType::Continue);
|
||||||
if (in_mode != out_mode)
|
if (needs_notification)
|
||||||
{
|
{
|
||||||
return {TurnType::Notification, getTurnDirection(road.angle)};
|
return {TurnType::Notification, getTurnDirection(road.angle)};
|
||||||
}
|
}
|
||||||
|
@ -342,6 +342,10 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
&ExtractionWay::weight,
|
&ExtractionWay::weight,
|
||||||
"road_classification",
|
"road_classification",
|
||||||
&ExtractionWay::road_classification,
|
&ExtractionWay::road_classification,
|
||||||
|
"forward_classes",
|
||||||
|
&ExtractionWay::forward_classes,
|
||||||
|
"backward_classes",
|
||||||
|
&ExtractionWay::backward_classes,
|
||||||
"forward_mode",
|
"forward_mode",
|
||||||
sol::property([](const ExtractionWay &way) { return way.forward_travel_mode; },
|
sol::property([](const ExtractionWay &way) { return way.forward_travel_mode; },
|
||||||
[](ExtractionWay &way, TravelMode mode) { way.forward_travel_mode = mode; }),
|
[](ExtractionWay &way, TravelMode mode) { way.forward_travel_mode = mode; }),
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "customizer/edge_based_graph.hpp"
|
#include "customizer/edge_based_graph.hpp"
|
||||||
|
|
||||||
|
#include "extractor/class_data.hpp"
|
||||||
#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/files.hpp"
|
#include "extractor/files.hpp"
|
||||||
@ -253,6 +254,7 @@ void Storage::PopulateLayout(DataLayout &layout)
|
|||||||
layout.SetBlockSize<NameID>(DataLayout::NAME_ID_LIST, nodes_number);
|
layout.SetBlockSize<NameID>(DataLayout::NAME_ID_LIST, nodes_number);
|
||||||
layout.SetBlockSize<ComponentID>(DataLayout::COMPONENT_ID_LIST, nodes_number);
|
layout.SetBlockSize<ComponentID>(DataLayout::COMPONENT_ID_LIST, nodes_number);
|
||||||
layout.SetBlockSize<extractor::TravelMode>(DataLayout::TRAVEL_MODE_LIST, nodes_number);
|
layout.SetBlockSize<extractor::TravelMode>(DataLayout::TRAVEL_MODE_LIST, nodes_number);
|
||||||
|
layout.SetBlockSize<extractor::ClassData>(DataLayout::CLASSES_LIST, nodes_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boost::filesystem::exists(config.hsgr_data_path))
|
if (boost::filesystem::exists(config.hsgr_data_path))
|
||||||
@ -614,10 +616,16 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
|||||||
util::vector_view<extractor::TravelMode> travel_modes(
|
util::vector_view<extractor::TravelMode> travel_modes(
|
||||||
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
|
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
|
||||||
|
|
||||||
|
auto classes_list_ptr = layout.GetBlockPtr<extractor::ClassData, true>(
|
||||||
|
memory_ptr, storage::DataLayout::CLASSES_LIST);
|
||||||
|
util::vector_view<extractor::ClassData> classes(
|
||||||
|
classes_list_ptr, layout.num_entries[storage::DataLayout::CLASSES_LIST]);
|
||||||
|
|
||||||
extractor::EdgeBasedNodeDataView node_data(std::move(geometry_ids),
|
extractor::EdgeBasedNodeDataView node_data(std::move(geometry_ids),
|
||||||
std::move(name_ids),
|
std::move(name_ids),
|
||||||
std::move(component_ids),
|
std::move(component_ids),
|
||||||
std::move(travel_modes));
|
std::move(travel_modes),
|
||||||
|
std::move(classes));
|
||||||
|
|
||||||
extractor::files::readNodeData(config.edge_based_nodes_data_path, node_data);
|
extractor::files::readNodeData(config.edge_based_nodes_data_path, node_data);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,8 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
|
|||||||
0},
|
0},
|
||||||
0,
|
0,
|
||||||
3,
|
3,
|
||||||
{intersection1}},
|
{intersection1},
|
||||||
|
{}},
|
||||||
{324,
|
{324,
|
||||||
"Central Park West",
|
"Central Park West",
|
||||||
"",
|
"",
|
||||||
@ -74,7 +75,8 @@ BOOST_AUTO_TEST_CASE(trim_short_segments)
|
|||||||
0},
|
0},
|
||||||
2,
|
2,
|
||||||
3,
|
3,
|
||||||
{intersection2}}};
|
{intersection2},
|
||||||
|
{}}};
|
||||||
|
|
||||||
LegGeometry geometry;
|
LegGeometry geometry;
|
||||||
geometry.locations = {{FloatLongitude{-73.981492}, FloatLatitude{40.768258}},
|
geometry.locations = {{FloatLongitude{-73.981492}, FloatLatitude{40.768258}},
|
||||||
|
@ -36,6 +36,7 @@ inline InputEdge MakeUnitEdge(const NodeID from, const NodeID to)
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
TRAVEL_MODE_INACCESSIBLE,
|
TRAVEL_MODE_INACCESSIBLE,
|
||||||
|
0,
|
||||||
INVALID_LANE_DESCRIPTIONID};
|
INVALID_LANE_DESCRIPTIONID};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,15 @@
|
|||||||
// implements all data storage when shared memory _IS_ used
|
// implements all data storage when shared memory _IS_ used
|
||||||
|
|
||||||
#include "contractor/query_edge.hpp"
|
#include "contractor/query_edge.hpp"
|
||||||
|
#include "extractor/class_data.hpp"
|
||||||
#include "extractor/guidance/turn_instruction.hpp"
|
#include "extractor/guidance/turn_instruction.hpp"
|
||||||
#include "extractor/guidance/turn_lane_types.hpp"
|
#include "extractor/guidance/turn_lane_types.hpp"
|
||||||
|
#include "extractor/travel_mode.hpp"
|
||||||
|
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
#include "engine/datafacade/algorithm_datafacade.hpp"
|
#include "engine/datafacade/algorithm_datafacade.hpp"
|
||||||
#include "engine/datafacade/datafacade_base.hpp"
|
#include "engine/datafacade/datafacade_base.hpp"
|
||||||
|
|
||||||
#include "util/guidance/bearing_class.hpp"
|
#include "util/guidance/bearing_class.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
#include "util/guidance/turn_bearing.hpp"
|
||||||
@ -195,6 +199,14 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
|||||||
{
|
{
|
||||||
return TRAVEL_MODE_INACCESSIBLE;
|
return TRAVEL_MODE_INACCESSIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extractor::ClassData GetClassData(const NodeID /*id*/) const override final { return 0; }
|
||||||
|
|
||||||
|
std::vector<std::string> GetClasses(const extractor::ClassData /*data*/) const override final
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
NameID GetNameIndex(const NodeID /* id */) const override { return 0; }
|
NameID GetNameIndex(const NodeID /* id */) const override { return 0; }
|
||||||
|
|
||||||
StringView GetNameForID(const NameID) const override final { return {}; }
|
StringView GetNameForID(const NameID) const override final { return {}; }
|
||||||
|
73
unit_tests/util/bit_range.cpp
Normal file
73
unit_tests/util/bit_range.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include "util/bit_range.hpp"
|
||||||
|
|
||||||
|
#include "../common/range_tools.hpp"
|
||||||
|
|
||||||
|
#include <boost/test/test_case_template.hpp>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(bit_range_test)
|
||||||
|
|
||||||
|
using namespace osrm;
|
||||||
|
using namespace osrm::util;
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(bit_range_8bit_test)
|
||||||
|
{
|
||||||
|
std::uint8_t value_1 = (1UL << 0) | (1UL << 1) | (1UL << 5) | (1UL << 7);
|
||||||
|
std::uint8_t value_2 = (1UL << 0);
|
||||||
|
std::uint8_t value_3 =
|
||||||
|
(1UL << 0) | (1UL << 1) | (1UL << 2) | (1UL << 3) | (1UL << 4) | (1UL << 5);
|
||||||
|
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint8_t>(value_1), 7, 5, 1, 0);
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint8_t>(value_2), 0);
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint8_t>(value_3), 5, 4, 3, 2, 1, 0);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(makeBitRange<std::uint8_t>(value_3).size(), 6);
|
||||||
|
BOOST_CHECK_EQUAL(makeBitRange<std::uint8_t>(0).size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(bit_range_16bit_test)
|
||||||
|
{
|
||||||
|
std::uint16_t value_1 = (1UL << 0) | (1UL << 1) | (1UL << 9) | (1UL << 15);
|
||||||
|
std::uint16_t value_2 = (1UL << 0);
|
||||||
|
std::uint16_t value_3 =
|
||||||
|
(1UL << 0) | (1UL << 1) | (1UL << 2) | (1UL << 3) | (1UL << 4) | (1UL << 5);
|
||||||
|
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint16_t>(value_1), 15, 9, 1, 0);
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint16_t>(value_2), 0);
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint16_t>(value_3), 5, 4, 3, 2, 1, 0);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(makeBitRange<std::uint16_t>(value_3).size(), 6);
|
||||||
|
BOOST_CHECK_EQUAL(makeBitRange<std::uint16_t>(0).size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(bit_range_32bit_test)
|
||||||
|
{
|
||||||
|
std::uint32_t value_1 = (1UL << 0) | (1UL << 1) | (1UL << 17) | (1UL << 31);
|
||||||
|
std::uint32_t value_2 = (1UL << 0);
|
||||||
|
std::uint32_t value_3 =
|
||||||
|
(1UL << 0) | (1UL << 1) | (1UL << 2) | (1UL << 3) | (1UL << 4) | (1UL << 5);
|
||||||
|
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint32_t>(value_1), 31, 17, 1, 0);
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint32_t>(value_2), 0);
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint32_t>(value_3), 5, 4, 3, 2, 1, 0);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(makeBitRange<std::uint32_t>(value_3).size(), 6);
|
||||||
|
BOOST_CHECK_EQUAL(makeBitRange<std::uint32_t>(0).size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(bit_range_64bit_test)
|
||||||
|
{
|
||||||
|
std::uint64_t value_1 = (1ULL << 0) | (1ULL << 1) | (1ULL << 33) | (1ULL << 63);
|
||||||
|
std::uint64_t value_2 = (1ULL << 0);
|
||||||
|
std::uint64_t value_3 =
|
||||||
|
(1ULL << 0) | (1ULL << 1) | (1ULL << 2) | (1ULL << 3) | (1ULL << 4) | (1ULL << 5);
|
||||||
|
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint64_t>(value_1), 63, 33, 1, 0);
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint64_t>(value_2), 0);
|
||||||
|
CHECK_EQUAL_RANGE(makeBitRange<std::uint64_t>(value_3), 5, 4, 3, 2, 1, 0);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(makeBitRange<std::uint64_t>(value_3).size(), 6);
|
||||||
|
BOOST_CHECK_EQUAL(makeBitRange<std::uint64_t>(0).size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in New Issue
Block a user