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:
committed by
Patrick Niklaus
parent
d52d530cbe
commit
44739f2dc3
@@ -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(); }
|
||||
|
||||
// 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
|
||||
double forward_speed;
|
||||
double backward_speed;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef EXTRACTOR_CALLBACKS_HPP
|
||||
#define EXTRACTOR_CALLBACKS_HPP
|
||||
|
||||
#include "extractor/class_data.hpp"
|
||||
#include "extractor/guidance/turn_lane_types.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 MapVal = unsigned;
|
||||
std::unordered_map<MapKey, MapVal> string_map;
|
||||
guidance::LaneDescriptionMap lane_description_map;
|
||||
ExtractionContainers &external_memory;
|
||||
std::unordered_map<std::string, ClassData> &classes_map;
|
||||
guidance::LaneDescriptionMap &lane_description_map;
|
||||
bool fallback_to_duration;
|
||||
bool force_split_edges;
|
||||
|
||||
public:
|
||||
using ClassesMap = std::unordered_map<std::string, ClassData>;
|
||||
|
||||
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
||||
std::unordered_map<std::string, ClassData> &classes_map,
|
||||
guidance::LaneDescriptionMap &lane_description_map,
|
||||
const ProfileProperties &properties);
|
||||
|
||||
ExtractorCallbacks(const ExtractorCallbacks &) = delete;
|
||||
@@ -81,9 +87,6 @@ class ExtractorCallbacks
|
||||
|
||||
// warning: caller needs to take care of synchronization!
|
||||
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, // split edge
|
||||
TRAVEL_MODE_INACCESSIBLE,
|
||||
0,
|
||||
guidance::TurnLaneType::empty,
|
||||
guidance::RoadClassification()),
|
||||
weight_data(), duration_data()
|
||||
@@ -91,6 +92,7 @@ struct InternalExtractorEdge
|
||||
bool restricted,
|
||||
bool is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
LaneDescriptionID lane_description,
|
||||
guidance::RoadClassification road_classification,
|
||||
util::Coordinate source_coordinate)
|
||||
@@ -107,6 +109,7 @@ struct InternalExtractorEdge
|
||||
restricted,
|
||||
is_split,
|
||||
travel_mode,
|
||||
classes,
|
||||
lane_description,
|
||||
std::move(road_classification)),
|
||||
weight_data(std::move(weight_data)), duration_data(std::move(duration_data)),
|
||||
@@ -139,6 +142,7 @@ struct InternalExtractorEdge
|
||||
false, // local access only
|
||||
false, // split edge
|
||||
TRAVEL_MODE_INACCESSIBLE,
|
||||
0,
|
||||
INVALID_LANE_DESCRIPTIONID,
|
||||
guidance::RoadClassification(),
|
||||
util::Coordinate());
|
||||
@@ -158,6 +162,7 @@ struct InternalExtractorEdge
|
||||
false, // local access only
|
||||
false, // split edge
|
||||
TRAVEL_MODE_INACCESSIBLE,
|
||||
0,
|
||||
INVALID_LANE_DESCRIPTIONID,
|
||||
guidance::RoadClassification(),
|
||||
util::Coordinate());
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef NODE_BASED_EDGE_HPP
|
||||
#define NODE_BASED_EDGE_HPP
|
||||
|
||||
#include "extractor/class_data.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@@ -28,6 +29,7 @@ struct NodeBasedEdge
|
||||
bool restricted,
|
||||
bool is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
const LaneDescriptionID lane_description_id,
|
||||
guidance::RoadClassification road_classification);
|
||||
|
||||
@@ -46,6 +48,7 @@ struct NodeBasedEdge
|
||||
std::uint8_t restricted : 1; // 1
|
||||
std::uint8_t is_split : 1; // 1
|
||||
TravelMode travel_mode : 4; // 4
|
||||
ClassData classes; // 8 1
|
||||
LaneDescriptionID lane_description_id; // 16 2
|
||||
guidance::RoadClassification road_classification; // 16 2
|
||||
};
|
||||
@@ -65,6 +68,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
|
||||
bool restricted,
|
||||
bool is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
const LaneDescriptionID lane_description_id,
|
||||
guidance::RoadClassification road_classification);
|
||||
|
||||
@@ -95,12 +99,14 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
|
||||
bool restricted,
|
||||
bool is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
const LaneDescriptionID lane_description_id,
|
||||
guidance::RoadClassification road_classification)
|
||||
: source(source), target(target), name_id(name_id), weight(weight), duration(duration),
|
||||
forward(forward), backward(backward), roundabout(roundabout), circular(circular),
|
||||
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 is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
const LaneDescriptionID lane_description_id,
|
||||
guidance::RoadClassification road_classification)
|
||||
: NodeBasedEdge(SPECIAL_NODEID,
|
||||
@@ -149,6 +156,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
||||
restricted,
|
||||
is_split,
|
||||
travel_mode,
|
||||
classes,
|
||||
lane_description_id,
|
||||
std::move(road_classification)),
|
||||
osm_source_id(std::move(source)), osm_target_id(std::move(target))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
|
||||
#define OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
|
||||
|
||||
#include "extractor/class_data.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
@@ -41,16 +42,18 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
||||
EdgeBasedNodeDataContainerImpl() = default;
|
||||
|
||||
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,
|
||||
Vector<NameID> name_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)),
|
||||
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]; }
|
||||
|
||||
ClassData GetClassData(const NodeID node_id) const { return classes[node_id]; }
|
||||
|
||||
// Used by EdgeBasedGraphFactory to fill data structure
|
||||
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;
|
||||
name_ids[node_id] = name_id;
|
||||
travel_modes[node_id] = travel_mode;
|
||||
classes[node_id] = class_data;
|
||||
}
|
||||
|
||||
// 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(component_ids.begin(), component_ids.end(), permutation);
|
||||
util::inplacePermutation(travel_modes.begin(), travel_modes.end(), permutation);
|
||||
util::inplacePermutation(classes.begin(), classes.end(), permutation);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -98,6 +109,7 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
||||
Vector<NameID> name_ids;
|
||||
Vector<ComponentID> component_ids;
|
||||
Vector<TravelMode> travel_modes;
|
||||
Vector<ClassData> classes;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef PROFILE_PROPERTIES_HPP
|
||||
#define PROFILE_PROPERTIES_HPP
|
||||
|
||||
#include "extractor/class_data.hpp"
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -17,6 +19,7 @@ const constexpr auto DEFAULT_MAX_SPEED = 180 / 3.6; // 180kmph -> m/s
|
||||
struct ProfileProperties
|
||||
{
|
||||
static constexpr int MAX_WEIGHT_NAME_LENGTH = 255;
|
||||
static constexpr int MAX_CLASS_NAME_LENGTH = 255;
|
||||
|
||||
ProfileProperties()
|
||||
: traffic_signal_penalty(0), u_turn_penalty(0),
|
||||
@@ -66,6 +69,22 @@ struct ProfileProperties
|
||||
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 GetMaxTurnWeight() const
|
||||
@@ -86,6 +105,8 @@ struct ProfileProperties
|
||||
bool fallback_to_duration;
|
||||
//! stores the name of the weight (e.g. 'duration', 'distance', 'safety')
|
||||
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;
|
||||
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.component_ids);
|
||||
storage::serialization::read(reader, node_data_container.travel_modes);
|
||||
storage::serialization::read(reader, node_data_container.classes);
|
||||
}
|
||||
|
||||
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.component_ids);
|
||||
storage::serialization::write(writer, node_data_container.travel_modes);
|
||||
storage::serialization::write(writer, node_data_container.classes);
|
||||
}
|
||||
|
||||
// read/write for conditional turn restrictions file
|
||||
|
||||
Reference in New Issue
Block a user