handle conditional via-way restrictions
- refactor conditional restriction handling to not use external data (first OSM nodes on ways) - BREAKING: changes internal file format of osrm.restrictions - add support for general conditional penalties based on edge-based nodes (requires unique edges between nodes)
This commit is contained in:
parent
f34320a89b
commit
93299d6651
@ -1,5 +1,7 @@
|
||||
# 5.11.0
|
||||
- Changes from 5.10:
|
||||
- Features
|
||||
- BREAKING: Added support for conditional via-way instructions. This features changes the file format of osrm.restrictions and requires re-extraction
|
||||
|
||||
# 5.10.0
|
||||
- Changes from 5.9:
|
||||
|
@ -72,6 +72,75 @@ Feature: Car - Turn restrictions
|
||||
| n | m | nj,pjm,pjm |
|
||||
| s | m | js,pjm,pjm |
|
||||
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - Restriction With Compressed Geometry
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
|
|
||||
i
|
||||
|
|
||||
j-k-l-m
|
||||
|
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| nij |
|
||||
| js |
|
||||
| jklm |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | nij | jklm | j | no_left_turn @ (Mo-Fr 07:00-10:30) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| n | m | nij,js,js,jklm,jklm |
|
||||
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - Restriction With Compressed Geometry and Traffic Signal
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 10am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493719200"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
n
|
||||
|
|
||||
i
|
||||
|
|
||||
j-k-l-m
|
||||
|
|
||||
s
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| nij |
|
||||
| js |
|
||||
| jklm |
|
||||
|
||||
And the nodes
|
||||
| node | highway |
|
||||
| i | traffic_signal |
|
||||
| k | traffic_signal |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | nij | jklm | j | no_left_turn @ (Mo-Fr 07:00-10:30) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| n | m | nij,js,js,jklm,jklm |
|
||||
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - ignores except restriction
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
@ -530,6 +599,81 @@ Feature: Car - Turn restrictions
|
||||
| n | p | nj,js,js,jp,jp |
|
||||
| m | p | mj,jp,jp |
|
||||
|
||||
@restriction-way
|
||||
Scenario: Car - prohibit turn
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 5pm Wed 02 May, 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
c
|
||||
|
|
||||
| f
|
||||
| |
|
||||
b---e
|
||||
| |
|
||||
a d
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| be |
|
||||
| de |
|
||||
| ef |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:via | way:to | restriction:conditional |
|
||||
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | turns | locations |
|
||||
| a | d | ab,be,ef,ef,de,de | depart,turn right,turn left,continue uturn,new name straight,arrive | a,b,e,f,e,d |
|
||||
| a | f | ab,be,ef,ef | depart,turn right,turn left,arrive | a,b,e,f |
|
||||
| c | d | bc,be,de,de | depart,turn left,turn right,arrive | c,b,e,d |
|
||||
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
|
||||
|
||||
# condition is off
|
||||
@restriction-way
|
||||
Scenario: Car - prohibit turn
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# time stamp for 12am on Tues, 02 May 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493726400"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493726400"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
c
|
||||
|
|
||||
| f
|
||||
| |
|
||||
b---e
|
||||
| |
|
||||
a d
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| be |
|
||||
| de |
|
||||
| ef |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:via | way:to | restriction:conditional |
|
||||
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | d | ab,be,de,de |
|
||||
| a | f | ab,be,ef,ef |
|
||||
| c | d | bc,be,de,de |
|
||||
| c | f | bc,be,ef,ef |
|
||||
|
||||
# https://www.openstreetmap.org/#map=18/38.91099/-77.00888
|
||||
@no_turning @conditionals
|
||||
Scenario: Car - DC North capitol situation, two on one off
|
||||
@ -769,15 +913,145 @@ Feature: Car - Turn restrictions
|
||||
| dg |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | way:via | restriction:conditional |
|
||||
| restriction | ab | be | ef | no_uturn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
|
||||
| type | way:from | way:via | way:to | restriction:conditional |
|
||||
| restriction | ab | be | ef | no_uturn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction:conditional |
|
||||
| restriction | ed | dg | d | no_uturn @ (Mo-Fr 07:00-11:00,16:00-18:30) |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | # |
|
||||
| a | f | ab,be,ef,ef | currently we do not handle conditional via-ways, this test will have to change when we do |
|
||||
| f | 1 | ef,eh,gh,dg,dg | |
|
||||
| from | to | route |
|
||||
| a | f | ab,bc,bc,be,ef,ef |
|
||||
| f | 1 | ef,eh,gh,dg,dg |
|
||||
|
||||
@restriction-way @overlap
|
||||
Scenario: Car - prohibit turn
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 5pm Wed 02 May, 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
c
|
||||
|
|
||||
| f
|
||||
| |
|
||||
b---e
|
||||
| |
|
||||
a d
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| be |
|
||||
| de |
|
||||
| ef |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:via | way:to | restriction:conditional |
|
||||
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 07:00-11:00) |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:via | way:to | restriction |
|
||||
| restriction | ab | be | de | no_right_turn |
|
||||
|
||||
# condition is off, but the general restriction should take precedence
|
||||
When I route I should get
|
||||
| from | to | route | turns | locations |
|
||||
| a | d | ab,be,ef,ef,de,de | depart,turn right,turn left,continue uturn,new name straight,arrive | a,b,e,f,e,d |
|
||||
| a | f | ab,be,ef,ef | depart,turn right,turn left,arrive | a,b,e,f |
|
||||
| c | d | bc,be,de,de | depart,turn left,turn right,arrive | c,b,e,d |
|
||||
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
|
||||
|
||||
@restriction-way @overlap
|
||||
Scenario: Car - prohibit turn
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 5pm Wed 02 May, 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
c
|
||||
|
|
||||
| f
|
||||
| |
|
||||
b---e
|
||||
| |
|
||||
| d
|
||||
|
|
||||
a
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| be |
|
||||
| de |
|
||||
| ef |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:via | way:to | restriction:conditional |
|
||||
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 07:00-11:00) |
|
||||
|
||||
And the relations
|
||||
| type | way:from | node:via | way:to | restriction:conditional |
|
||||
| restriction | be | e | de | no_right_turn @ (Mo-Fr 16:00-18:00) |
|
||||
|
||||
# way restriction is off, node-restriction is on
|
||||
When I route I should get
|
||||
| from | to | route | turns | locations |
|
||||
| a | d | ab,be,ef,ef,de,de | depart,turn right,turn left,continue uturn,new name straight,arrive | a,b,e,f,e,d |
|
||||
| a | f | ab,be,ef,ef | depart,turn right,turn left,arrive | a,b,e,f |
|
||||
| c | d | bc,be,ef,ef,de,de | depart,turn left,turn left,continue uturn,new name straight,arrive | c,b,e,f,e,d |
|
||||
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
|
||||
|
||||
@restriction-way @overlap
|
||||
Scenario: Car - prohibit turn
|
||||
Given the extract extra arguments "--parse-conditional-restrictions"
|
||||
# 5pm Wed 02 May, 2017 GMT
|
||||
Given the contract extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
Given the customize extra arguments "--time-zone-file=test/data/tz/{timezone_names}/guinea.geojson --parse-conditionals-from-now=1493744400"
|
||||
|
||||
Given the node map
|
||||
"""
|
||||
c
|
||||
|
|
||||
| f
|
||||
| |
|
||||
b---e
|
||||
| |
|
||||
| d
|
||||
|
|
||||
a
|
||||
"""
|
||||
|
||||
And the ways
|
||||
| nodes |
|
||||
| ab |
|
||||
| bc |
|
||||
| be |
|
||||
| de |
|
||||
| ef |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:via | way:to | restriction:conditional |
|
||||
| restriction | ab | be | de | no_right_turn @ (Mo-Fr 16:00-18:00) |
|
||||
|
||||
And the relations
|
||||
| type | way:from | node:via | way:to | restriction:conditional |
|
||||
| restriction | be | e | de | no_right_turn @ (Mo-Fr 07:00-11:00) |
|
||||
|
||||
# node restrictino is off, way restriction is on
|
||||
When I route I should get
|
||||
| from | to | route | turns | locations |
|
||||
| a | d | ab,be,ef,ef,de,de | depart,turn right,turn left,continue uturn,new name straight,arrive | a,b,e,f,e,d |
|
||||
| a | f | ab,be,ef,ef | depart,turn right,turn left,arrive | a,b,e,f |
|
||||
| c | d | bc,be,de,de | depart,turn left,turn right,arrive | c,b,e,d |
|
||||
| c | f | bc,be,ef,ef | depart,turn left,turn left,arrive | c,b,e,f |
|
||||
|
||||
|
28
include/extractor/conditional_turn_penalty.hpp
Normal file
28
include/extractor/conditional_turn_penalty.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef OSRM_EXTRACTOR_CONDITIONAL_TURN_PENALTY_HPP_
|
||||
#define OSRM_EXTRACTOR_CONDITIONAL_TURN_PENALTY_HPP_
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/opening_hours.hpp"
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace osrm
|
||||
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
struct ConditionalTurnPenalty
|
||||
{
|
||||
// offset into the sequential list of turn penalties (see TurnIndexBlock for reference);
|
||||
std::uint64_t turn_offset;
|
||||
util::Coordinate location;
|
||||
std::vector<util::OpeningHours> conditions;
|
||||
};
|
||||
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_CONDITIONAL_TURN_PENALTY_HPP_
|
@ -4,6 +4,7 @@
|
||||
#define EDGE_BASED_GRAPH_FACTORY_HPP_
|
||||
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/conditional_turn_penalty.hpp"
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/edge_based_node_segment.hpp"
|
||||
#include "extractor/extraction_turn.hpp"
|
||||
@ -16,7 +17,7 @@
|
||||
#include "extractor/packed_osm_ids.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/restriction_map.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/way_restriction_map.hpp"
|
||||
|
||||
#include "util/concurrent_id_map.hpp"
|
||||
@ -92,7 +93,9 @@ class EdgeBasedGraphFactory
|
||||
const std::string &turn_duration_penalties_filename,
|
||||
const std::string &turn_penalties_index_filename,
|
||||
const std::string &cnbg_ebg_mapping_path,
|
||||
const std::string &conditional_penalties_filename,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const ConditionalRestrictionMap &conditional_restriction_map,
|
||||
const WayRestrictionMap &way_restriction_map);
|
||||
|
||||
// The following get access functions destroy the content in the factory
|
||||
@ -124,6 +127,18 @@ class EdgeBasedGraphFactory
|
||||
private:
|
||||
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
|
||||
|
||||
struct Conditional
|
||||
{
|
||||
// the edge based nodes allow for a unique identification of conditionals
|
||||
NodeID from_node;
|
||||
NodeID to_node;
|
||||
ConditionalTurnPenalty penalty;
|
||||
};
|
||||
|
||||
// assign the correct index to the penalty value stored in the conditional
|
||||
std::vector<ConditionalTurnPenalty>
|
||||
IndexConditionals(std::vector<Conditional> &&conditionals) const;
|
||||
|
||||
//! maps index from m_edge_based_node_list to ture/false if the node is an entry point to the
|
||||
//! graph
|
||||
std::vector<bool> m_edge_based_node_is_startpoint;
|
||||
@ -173,7 +188,9 @@ class EdgeBasedGraphFactory
|
||||
const std::string &turn_weight_penalties_filename,
|
||||
const std::string &turn_duration_penalties_filename,
|
||||
const std::string &turn_penalties_index_filename,
|
||||
const std::string &conditional_turn_penalties_filename,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const ConditionalRestrictionMap &conditional_restriction_map,
|
||||
const WayRestrictionMap &way_restriction_map);
|
||||
|
||||
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
|
||||
|
@ -27,7 +27,6 @@ class ExtractionContainers
|
||||
void PrepareEdges(ScriptingEnvironment &scripting_environment);
|
||||
|
||||
void WriteNodes(storage::io::FileWriter &file_out) const;
|
||||
void WriteConditionalRestrictions(const std::string &restrictions_file_name);
|
||||
void WriteEdges(storage::io::FileWriter &file_out) const;
|
||||
void WriteCharData(const std::string &file_name);
|
||||
|
||||
@ -65,7 +64,6 @@ class ExtractionContainers
|
||||
|
||||
void PrepareData(ScriptingEnvironment &scripting_environment,
|
||||
const std::string &osrm_path,
|
||||
const std::string &restrictions_file_name,
|
||||
const std::string &names_data_path);
|
||||
};
|
||||
}
|
||||
|
@ -56,7 +56,9 @@ class Extractor
|
||||
private:
|
||||
ExtractorConfig config;
|
||||
|
||||
std::tuple<guidance::LaneDescriptionMap, std::vector<TurnRestriction>>
|
||||
std::tuple<guidance::LaneDescriptionMap,
|
||||
std::vector<TurnRestriction>,
|
||||
std::vector<ConditionalTurnRestriction>>
|
||||
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
|
||||
|
||||
std::pair<std::size_t, EdgeID>
|
||||
@ -70,6 +72,7 @@ class Extractor
|
||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||
const std::string &intersection_class_output_file,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
guidance::LaneDescriptionMap &turn_lane_map);
|
||||
void FindComponents(unsigned max_edge_id,
|
||||
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
|
||||
@ -89,6 +92,10 @@ class Extractor
|
||||
static void WriteCompressedNodeBasedGraph(const std::string &path,
|
||||
const util::NodeBasedDynamicGraph &graph,
|
||||
const std::vector<util::Coordinate> &coordiantes);
|
||||
|
||||
void WriteConditionalRestrictions(
|
||||
const std::string &path,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ class GraphCompressor
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
util::NodeBasedDynamicGraph &graph,
|
||||
CompressedEdgeContainer &geometry_compressor);
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/intersection_normalization_operation.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/restriction_map.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "util/attributes.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
@ -116,14 +116,6 @@ class IntersectionGenerator
|
||||
|
||||
// own state, used to find the correct coordinates along a road
|
||||
const CoordinateExtractor coordinate_extractor;
|
||||
|
||||
// check turn restrictions to find a node that is the only allowed target when coming from a
|
||||
// node to an intersection
|
||||
// d
|
||||
// |
|
||||
// a - b - c and `only_straight_on ab | bc would return `c` for `a,b`
|
||||
boost::optional<NodeID> GetOnlyAllowedTurnIfExistent(const NodeID coming_from_node,
|
||||
const NodeID node_at_intersection) const;
|
||||
};
|
||||
|
||||
} // namespace guidance
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include "extractor/guidance/turn_classification.hpp"
|
||||
#include "extractor/guidance/turn_handler.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/restriction_map.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/suffix_table.hpp"
|
||||
|
||||
#include "util/attributes.hpp"
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef OSRM_EXTRACTOR_RESTRICTION_COMPRESSOR_HPP_
|
||||
#define OSRM_EXTRACTOR_RESTRICTION_COMPRESSOR_HPP_
|
||||
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
@ -26,7 +27,8 @@ struct TurnRestriction;
|
||||
class RestrictionCompressor
|
||||
{
|
||||
public:
|
||||
RestrictionCompressor(std::vector<TurnRestriction> &restrictions);
|
||||
RestrictionCompressor(std::vector<TurnRestriction> &restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
||||
|
||||
// account for the compression of `from-via-to` into `from-to`
|
||||
void Compress(const NodeID from, const NodeID via, const NodeID to);
|
||||
|
@ -14,8 +14,9 @@ namespace extractor
|
||||
// To avoid handling invalid restrictions / creating unnecessary duplicate nodes for via-ways, we do
|
||||
// a pre-flight check for restrictions and remove all invalid restrictions from the data. Use as
|
||||
// `restrictions = removeInvalidRestrictions(std::move(restrictions))`
|
||||
std::vector<TurnRestriction> removeInvalidRestrictions(std::vector<TurnRestriction>,
|
||||
const util::NodeBasedDynamicGraph &);
|
||||
std::vector<ConditionalTurnRestriction>
|
||||
removeInvalidRestrictions(std::vector<ConditionalTurnRestriction>,
|
||||
const util::NodeBasedDynamicGraph &);
|
||||
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
101
include/extractor/restriction_index.hpp
Normal file
101
include/extractor/restriction_index.hpp
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef OSRM_EXTRACTOR_RESTRICTION_INDEX_HPP_
|
||||
#define OSRM_EXTRACTOR_RESTRICTION_INDEX_HPP_
|
||||
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
// allows easy check for whether a node intersection is present at a given intersection
|
||||
template <typename restriction_type> class RestrictionIndex
|
||||
{
|
||||
public:
|
||||
using value_type = restriction_type;
|
||||
|
||||
template <typename extractor_type>
|
||||
RestrictionIndex(std::vector<restriction_type> &restrictions, extractor_type extractor);
|
||||
|
||||
bool IsIndexed(NodeID first, NodeID second) const;
|
||||
|
||||
auto Restrictions(NodeID first, NodeID second) const
|
||||
{
|
||||
return restriction_hash.equal_range(std::make_pair(first, second));
|
||||
};
|
||||
|
||||
auto Size() const { return restriction_hash.size(); }
|
||||
|
||||
private:
|
||||
boost::unordered_multimap<std::pair<NodeID, NodeID>, restriction_type *> restriction_hash;
|
||||
};
|
||||
|
||||
template <typename restriction_type>
|
||||
template <typename extractor_type>
|
||||
RestrictionIndex<restriction_type>::RestrictionIndex(std::vector<restriction_type> &restrictions,
|
||||
extractor_type extractor)
|
||||
{
|
||||
// build a multi-map
|
||||
for (auto &restriction : restrictions)
|
||||
restriction_hash.insert(std::make_pair(extractor(restriction), &restriction));
|
||||
}
|
||||
|
||||
template <typename restriction_type>
|
||||
bool RestrictionIndex<restriction_type>::IsIndexed(const NodeID first, const NodeID second) const
|
||||
{
|
||||
return restriction_hash.count(std::make_pair(first, second));
|
||||
}
|
||||
|
||||
struct IndexNodeByFromAndVia
|
||||
{
|
||||
std::pair<NodeID, NodeID> operator()(const TurnRestriction &restriction)
|
||||
{
|
||||
const auto &node = restriction.AsNodeRestriction();
|
||||
return std::make_pair(node.from, node.via);
|
||||
};
|
||||
};
|
||||
|
||||
// check wheter a turn is restricted within a restriction_index
|
||||
template <typename restriction_map_type>
|
||||
std::pair<bool, typename restriction_map_type::value_type *>
|
||||
isRestricted(const NodeID from,
|
||||
const NodeID via,
|
||||
const NodeID to,
|
||||
const restriction_map_type &restriction_map)
|
||||
{
|
||||
const auto range = restriction_map.Restrictions(from, via);
|
||||
|
||||
// check if a given node_restriction is targeting node
|
||||
const auto to_is_restricted = [to](const auto &pair) {
|
||||
const auto &restriction = *pair.second;
|
||||
if (restriction.Type() == RestrictionType::NODE_RESTRICTION)
|
||||
{
|
||||
auto const &as_node = restriction.AsNodeRestriction();
|
||||
auto const restricted = restriction.is_only ? (to != as_node.to) : (to == as_node.to);
|
||||
|
||||
return restricted;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto itr = std::find_if(range.first, range.second, to_is_restricted);
|
||||
|
||||
if (itr != range.second)
|
||||
return {true, itr->second};
|
||||
else
|
||||
return {false, NULL};
|
||||
}
|
||||
|
||||
using RestrictionMap = RestrictionIndex<TurnRestriction>;
|
||||
using ConditionalRestrictionMap = RestrictionIndex<ConditionalTurnRestriction>;
|
||||
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_RESTRICTION_INDEX_HPP_
|
@ -1,110 +0,0 @@
|
||||
#ifndef RESTRICTION_MAP_HPP
|
||||
#define RESTRICTION_MAP_HPP
|
||||
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "util/std_hash.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
struct RestrictionSource
|
||||
{
|
||||
NodeID start_node;
|
||||
NodeID via_node;
|
||||
|
||||
RestrictionSource(NodeID start, NodeID via) : start_node(start), via_node(via) {}
|
||||
|
||||
friend inline bool operator==(const RestrictionSource &lhs, const RestrictionSource &rhs)
|
||||
{
|
||||
return (lhs.start_node == rhs.start_node && lhs.via_node == rhs.via_node);
|
||||
}
|
||||
};
|
||||
|
||||
struct RestrictionTarget
|
||||
{
|
||||
NodeID target_node;
|
||||
bool is_only;
|
||||
|
||||
explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only) {}
|
||||
|
||||
friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs)
|
||||
{
|
||||
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<osrm::extractor::RestrictionSource>
|
||||
{
|
||||
size_t operator()(const osrm::extractor::RestrictionSource &r_source) const
|
||||
{
|
||||
return hash_val(r_source.start_node, r_source.via_node);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct hash<osrm::extractor::RestrictionTarget>
|
||||
{
|
||||
size_t operator()(const osrm::extractor::RestrictionTarget &r_target) const
|
||||
{
|
||||
return hash_val(r_target.target_node, r_target.is_only);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
/**
|
||||
\brief Efficent look up if an edge is the start + via node of a TurnRestriction
|
||||
EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
|
||||
*/
|
||||
class RestrictionMap
|
||||
{
|
||||
public:
|
||||
RestrictionMap() : m_count(0) {}
|
||||
RestrictionMap(const std::vector<TurnRestriction> &restriction_list);
|
||||
|
||||
bool IsViaNode(const NodeID node) const;
|
||||
|
||||
// Check if edge (u, v) is the start of any turn restriction.
|
||||
// If so returns id of first target node.
|
||||
NodeID CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const;
|
||||
// Checks if turn <u,v,w> is actually a turn restriction.
|
||||
bool
|
||||
CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const;
|
||||
|
||||
std::size_t size() const { return m_count; }
|
||||
|
||||
private:
|
||||
// check of node is the start of any restriction
|
||||
bool IsSourceNode(const NodeID node) const;
|
||||
|
||||
using EmanatingRestrictionsVector = std::vector<RestrictionTarget>;
|
||||
|
||||
std::size_t m_count;
|
||||
//! index -> list of (target, isOnly)
|
||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||
//! maps (start, via) -> bucket index
|
||||
std::unordered_map<RestrictionSource, unsigned> m_restriction_map;
|
||||
std::unordered_set<NodeID> m_restriction_start_nodes;
|
||||
std::unordered_set<NodeID> m_no_turn_via_node_set;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RESTRICTION_MAP_HPP
|
@ -1,6 +1,7 @@
|
||||
#ifndef OSRM_EXTRACTOR_IO_HPP
|
||||
#define OSRM_EXTRACTOR_IO_HPP
|
||||
|
||||
#include "conditional_turn_penalty.hpp"
|
||||
#include "extractor/datasources.hpp"
|
||||
#include "extractor/intersection_bearings_container.hpp"
|
||||
#include "extractor/nbg_to_ebg.hpp"
|
||||
@ -273,6 +274,54 @@ inline void write(storage::io::FileWriter &writer,
|
||||
};
|
||||
std::for_each(restrictions.begin(), restrictions.end(), write_restriction);
|
||||
}
|
||||
|
||||
inline void read(storage::io::FileReader &reader, ConditionalTurnPenalty &turn_penalty)
|
||||
{
|
||||
reader.ReadInto(turn_penalty.turn_offset);
|
||||
reader.ReadInto(turn_penalty.location.lat);
|
||||
reader.ReadInto(turn_penalty.location.lon);
|
||||
auto const num_conditions = reader.ReadElementCount64();
|
||||
turn_penalty.conditions.resize(num_conditions);
|
||||
for (auto &condition : turn_penalty.conditions)
|
||||
{
|
||||
reader.ReadInto(condition.modifier);
|
||||
storage::serialization::read(reader, condition.times);
|
||||
storage::serialization::read(reader, condition.weekdays);
|
||||
storage::serialization::read(reader, condition.monthdays);
|
||||
}
|
||||
}
|
||||
|
||||
inline void write(storage::io::FileWriter &writer, const ConditionalTurnPenalty &turn_penalty)
|
||||
{
|
||||
writer.WriteOne(turn_penalty.turn_offset);
|
||||
writer.WriteOne(static_cast<util::FixedLatitude::value_type>(turn_penalty.location.lat));
|
||||
writer.WriteOne(static_cast<util::FixedLongitude::value_type>(turn_penalty.location.lon));
|
||||
writer.WriteElementCount64(turn_penalty.conditions.size());
|
||||
for (const auto &c : turn_penalty.conditions)
|
||||
{
|
||||
writer.WriteOne(c.modifier);
|
||||
storage::serialization::write(writer, c.times);
|
||||
storage::serialization::write(writer, c.weekdays);
|
||||
storage::serialization::write(writer, c.monthdays);
|
||||
}
|
||||
}
|
||||
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const std::vector<ConditionalTurnPenalty> &conditional_penalties)
|
||||
{
|
||||
writer.WriteElementCount64(conditional_penalties.size());
|
||||
for (const auto &penalty : conditional_penalties)
|
||||
write(writer, penalty);
|
||||
}
|
||||
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
std::vector<ConditionalTurnPenalty> &conditional_penalties)
|
||||
{
|
||||
auto const num_elements = reader.ReadElementCount64();
|
||||
conditional_penalties.resize(num_elements);
|
||||
for (auto &penalty : conditional_penalties)
|
||||
read(reader, penalty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@ -18,6 +19,8 @@ namespace osrm
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
// The WayRestrictionMap uses ConditionalTurnRestrictions in general. Most restrictions will have
|
||||
// empty conditions, though.
|
||||
class WayRestrictionMap
|
||||
{
|
||||
public:
|
||||
@ -26,7 +29,7 @@ class WayRestrictionMap
|
||||
NodeID from;
|
||||
NodeID to;
|
||||
};
|
||||
WayRestrictionMap(const std::vector<TurnRestriction> &turn_restrictions);
|
||||
WayRestrictionMap(const std::vector<ConditionalTurnRestriction> &conditional_restrictions);
|
||||
|
||||
// Check if an edge between two nodes is a restricted turn. The check needs to be performed to
|
||||
// find duplicated nodes during the creation of edge-based-edges
|
||||
@ -43,10 +46,13 @@ class WayRestrictionMap
|
||||
std::vector<ViaWay> DuplicatedNodeRepresentatives() const;
|
||||
|
||||
// Access all duplicated NodeIDs for a set of nodes indicating a via way
|
||||
util::range<DuplicatedNodeID> DuplicatedNodeIDs(const NodeID from, const NodeID to) const;
|
||||
std::vector<DuplicatedNodeID> DuplicatedNodeIDs(const NodeID from, const NodeID to) const;
|
||||
|
||||
// check whether a turn onto a given node is restricted, when coming from a duplicated node
|
||||
bool IsRestricted(DuplicatedNodeID duplicated_node, const NodeID to) const;
|
||||
// Get the restriction resulting in ^ IsRestricted. Requires IsRestricted to evaluate to true
|
||||
const ConditionalTurnRestriction &GetRestriction(DuplicatedNodeID duplicated_node,
|
||||
const NodeID to) const;
|
||||
|
||||
// changes edge_based_node to the correct duplicated_node_id in case node_based_from,
|
||||
// node_based_via, node_based_to can be identified with a restriction group
|
||||
@ -76,11 +82,8 @@ class WayRestrictionMap
|
||||
// EBN: 0 . | 2 | 3 | 4 ...
|
||||
// duplicated node groups: ... | 5 | 7 | ...
|
||||
std::vector<DuplicatedNodeID> duplicated_node_groups;
|
||||
|
||||
boost::unordered_multimap<std::pair<NodeID, NodeID>, RestrictionID> restriction_starts;
|
||||
boost::unordered_multimap<std::pair<NodeID, NodeID>, RestrictionID> restriction_ends;
|
||||
|
||||
std::vector<TurnRestriction> restriction_data;
|
||||
std::vector<ConditionalTurnRestriction> restriction_data;
|
||||
RestrictionIndex<ConditionalTurnRestriction> restriction_starts;
|
||||
};
|
||||
|
||||
} // namespace extractor
|
||||
|
@ -97,7 +97,7 @@ template <typename T> void write(io::FileWriter &writer, const std::vector<T> &d
|
||||
{
|
||||
const auto count = data.size();
|
||||
writer.WriteElementCount64(count);
|
||||
return writer.WriteFrom(data.data(), count);
|
||||
writer.WriteFrom(data.data(), count);
|
||||
}
|
||||
|
||||
template <typename T> void read(io::FileReader &reader, util::vector_view<T> &data)
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "extractor/edge_based_graph_factory.hpp"
|
||||
#include "extractor/conditional_turn_penalty.hpp"
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/files.hpp"
|
||||
#include "extractor/guidance/turn_analysis.hpp"
|
||||
@ -6,6 +7,7 @@
|
||||
#include "extractor/scripting_environment.hpp"
|
||||
#include "extractor/suffix_table.hpp"
|
||||
|
||||
#include "extractor/serialization.hpp"
|
||||
#include "storage/io.hpp"
|
||||
|
||||
#include "util/assert.hpp"
|
||||
@ -20,8 +22,10 @@
|
||||
#include "util/timing_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include "boost/unordered_map.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
@ -35,12 +39,26 @@
|
||||
#include <tbb/pipeline.h>
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<std::pair<NodeID, NodeID>>
|
||||
{
|
||||
std::size_t operator()(const std::pair<NodeID, NodeID> &mk) const noexcept
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, mk.first);
|
||||
boost::hash_combine(seed, mk.second);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
// Configuration to find representative candidate for turn angle calculations
|
||||
|
||||
// Configuration to find representative candidate for turn angle calculations
|
||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
|
||||
CompressedEdgeContainer &compressed_edge_container,
|
||||
@ -199,7 +217,9 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
|
||||
const std::string &turn_duration_penalties_filename,
|
||||
const std::string &turn_penalties_index_filename,
|
||||
const std::string &cnbg_ebg_mapping_path,
|
||||
const std::string &conditional_penalties_filename,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const ConditionalRestrictionMap &conditional_node_restriction_map,
|
||||
const WayRestrictionMap &way_restriction_map)
|
||||
{
|
||||
TIMER_START(renumber);
|
||||
@ -220,7 +240,9 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
|
||||
turn_weight_penalties_filename,
|
||||
turn_duration_penalties_filename,
|
||||
turn_penalties_index_filename,
|
||||
conditional_penalties_filename,
|
||||
node_restriction_map,
|
||||
conditional_node_restriction_map,
|
||||
way_restriction_map);
|
||||
|
||||
TIMER_STOP(generate_edges);
|
||||
@ -384,7 +406,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
const std::string &turn_weight_penalties_filename,
|
||||
const std::string &turn_duration_penalties_filename,
|
||||
const std::string &turn_penalties_index_filename,
|
||||
const std::string &conditional_penalties_filename,
|
||||
const RestrictionMap &node_restriction_map,
|
||||
const ConditionalRestrictionMap &conditional_restriction_map,
|
||||
const WayRestrictionMap &way_restriction_map)
|
||||
{
|
||||
|
||||
@ -427,6 +451,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
const auto weight_multiplier =
|
||||
scripting_environment.GetProfileProperties().GetWeightMultiplier();
|
||||
|
||||
// filled in during next stage, kept alive through following scope
|
||||
std::vector<Conditional> conditionals;
|
||||
// The following block generates the edge-based-edges using a parallel processing
|
||||
// pipeline. Sets of intersection IDs are batched in groups of GRAINSIZE (100)
|
||||
// `generator_stage`,
|
||||
@ -482,7 +508,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
};
|
||||
|
||||
// same as IntersectionData, but grouped with edge to allow sorting after creating. Edges
|
||||
// are out of order
|
||||
// can be out of order
|
||||
struct EdgeWithData
|
||||
{
|
||||
EdgeBasedEdge edge;
|
||||
@ -497,10 +523,14 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
std::size_t nodes_processed = 0;
|
||||
IntersectionData continuous_data;
|
||||
std::vector<EdgeWithData> delayed_data;
|
||||
std::vector<Conditional> conditionals;
|
||||
};
|
||||
|
||||
// Generate edges for either artificial nodes or the main graph
|
||||
const auto generate_edge = [this, &scripting_environment, weight_multiplier](
|
||||
const auto generate_edge = [this,
|
||||
&scripting_environment,
|
||||
weight_multiplier,
|
||||
&conditional_restriction_map](
|
||||
// what nodes will be used? In most cases this will be the id stored in the edge_data.
|
||||
// In case of duplicated nodes (e.g. due to via-way restrictions), one/both of these
|
||||
// might refer to a newly added edge based node
|
||||
@ -514,6 +544,24 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
const auto &intersection,
|
||||
const auto &turn,
|
||||
const auto entry_class_id) {
|
||||
|
||||
const auto node_restricted = isRestricted(node_along_road_entering,
|
||||
node_at_center_of_intersection,
|
||||
m_node_based_graph->GetTarget(turn.eid),
|
||||
conditional_restriction_map);
|
||||
|
||||
boost::optional<Conditional> conditional = boost::none;
|
||||
if (node_restricted.first)
|
||||
{
|
||||
auto const &conditions = node_restricted.second->condition;
|
||||
// get conditions of the restriction limiting the node
|
||||
conditional = {{edge_based_node_from,
|
||||
edge_based_node_to,
|
||||
{static_cast<std::uint64_t>(-1),
|
||||
m_coordinates[node_at_center_of_intersection],
|
||||
conditions}}};
|
||||
}
|
||||
|
||||
const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(node_based_edge_from);
|
||||
const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(node_based_edge_to);
|
||||
|
||||
@ -573,15 +621,16 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
const auto &from_node =
|
||||
isTrivial ? node_along_road_entering
|
||||
: m_compressed_edge_container.GetLastEdgeSourceID(node_based_edge_from);
|
||||
const auto &via_node =
|
||||
m_compressed_edge_container.GetLastEdgeTargetID(node_based_edge_from);
|
||||
const auto &to_node = m_compressed_edge_container.GetFirstEdgeTargetID(turn.eid);
|
||||
|
||||
lookup::TurnIndexBlock turn_index_block = {from_node, via_node, to_node};
|
||||
lookup::TurnIndexBlock turn_index_block = {
|
||||
from_node, node_at_center_of_intersection, to_node};
|
||||
|
||||
// insert data into the designated buffer
|
||||
return EdgeWithData{
|
||||
edge_based_edge, turn_index_block, weight_penalty, duration_penalty, turn_data};
|
||||
return std::make_pair(
|
||||
EdgeWithData{
|
||||
edge_based_edge, turn_index_block, weight_penalty, duration_penalty, turn_data},
|
||||
conditional);
|
||||
};
|
||||
|
||||
// Second part of the pipeline is where the intersection analysis is done for
|
||||
@ -720,7 +769,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
m_number_of_edge_based_nodes);
|
||||
|
||||
{ // scope to forget edge_with_data after
|
||||
const auto edge_with_data =
|
||||
const auto edge_with_data_and_condition =
|
||||
generate_edge(edge_data1.edge_id,
|
||||
target_id,
|
||||
node_along_road_entering,
|
||||
@ -731,15 +780,21 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
turn,
|
||||
entry_class_id);
|
||||
|
||||
buffer->continuous_data.edges_list.push_back(edge_with_data.edge);
|
||||
buffer->continuous_data.edges_list.push_back(
|
||||
edge_with_data_and_condition.first.edge);
|
||||
buffer->continuous_data.turn_indexes.push_back(
|
||||
edge_with_data.turn_index);
|
||||
edge_with_data_and_condition.first.turn_index);
|
||||
buffer->continuous_data.turn_weight_penalties.push_back(
|
||||
edge_with_data.turn_weight_penalty);
|
||||
edge_with_data_and_condition.first.turn_weight_penalty);
|
||||
buffer->continuous_data.turn_duration_penalties.push_back(
|
||||
edge_with_data.turn_duration_penalty);
|
||||
edge_with_data_and_condition.first.turn_duration_penalty);
|
||||
buffer->continuous_data.turn_data_container.push_back(
|
||||
edge_with_data.turn_data);
|
||||
edge_with_data_and_condition.first.turn_data);
|
||||
if (edge_with_data_and_condition.second)
|
||||
{
|
||||
buffer->conditionals.push_back(
|
||||
*edge_with_data_and_condition.second);
|
||||
}
|
||||
}
|
||||
|
||||
// when turning off a a via-way turn restriction, we need to not only
|
||||
@ -764,25 +819,73 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
auto const node_at_end_of_turn =
|
||||
m_node_based_graph->GetTarget(turn.eid);
|
||||
|
||||
const auto is_restricted = way_restriction_map.IsRestricted(
|
||||
const auto is_way_restricted = way_restriction_map.IsRestricted(
|
||||
duplicated_node_id, node_at_end_of_turn);
|
||||
|
||||
if (is_restricted)
|
||||
continue;
|
||||
if (is_way_restricted)
|
||||
{
|
||||
|
||||
// add into delayed data
|
||||
auto edge_with_data = generate_edge(
|
||||
NodeID(from_id),
|
||||
m_node_based_graph->GetEdgeData(turn.eid).edge_id,
|
||||
node_along_road_entering,
|
||||
incoming_edge,
|
||||
node_at_center_of_intersection,
|
||||
turn.eid,
|
||||
intersection,
|
||||
turn,
|
||||
entry_class_id);
|
||||
auto const restriction = way_restriction_map.GetRestriction(
|
||||
duplicated_node_id, node_at_end_of_turn);
|
||||
|
||||
buffer->delayed_data.push_back(std::move(edge_with_data));
|
||||
if (restriction.condition.empty())
|
||||
continue;
|
||||
|
||||
// add into delayed data
|
||||
auto edge_with_data_and_condition = generate_edge(
|
||||
NodeID(from_id),
|
||||
m_node_based_graph->GetEdgeData(turn.eid).edge_id,
|
||||
node_along_road_entering,
|
||||
incoming_edge,
|
||||
node_at_center_of_intersection,
|
||||
turn.eid,
|
||||
intersection,
|
||||
turn,
|
||||
entry_class_id);
|
||||
|
||||
buffer->delayed_data.push_back(
|
||||
std::move(edge_with_data_and_condition.first));
|
||||
|
||||
if (edge_with_data_and_condition.second)
|
||||
{
|
||||
buffer->conditionals.push_back(
|
||||
*edge_with_data_and_condition.second);
|
||||
}
|
||||
|
||||
// also add the conditions for the way
|
||||
if (is_way_restricted && !restriction.condition.empty())
|
||||
{
|
||||
// add a new conditional for the edge we just created
|
||||
buffer->conditionals.push_back(
|
||||
{NodeID(from_id),
|
||||
m_node_based_graph->GetEdgeData(turn.eid).edge_id,
|
||||
{static_cast<std::uint64_t>(-1),
|
||||
m_coordinates[node_at_center_of_intersection],
|
||||
restriction.condition}});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto edge_with_data_and_condition = generate_edge(
|
||||
NodeID(from_id),
|
||||
m_node_based_graph->GetEdgeData(turn.eid).edge_id,
|
||||
node_along_road_entering,
|
||||
incoming_edge,
|
||||
node_at_center_of_intersection,
|
||||
turn.eid,
|
||||
intersection,
|
||||
turn,
|
||||
entry_class_id);
|
||||
|
||||
buffer->delayed_data.push_back(
|
||||
std::move(edge_with_data_and_condition.first));
|
||||
|
||||
if (edge_with_data_and_condition.second)
|
||||
{
|
||||
buffer->conditionals.push_back(
|
||||
*edge_with_data_and_condition.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -827,6 +930,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
data.turn_indexes.begin(),
|
||||
data.turn_indexes.end());
|
||||
|
||||
conditionals.insert(
|
||||
conditionals.end(), buffer->conditionals.begin(), buffer->conditionals.end());
|
||||
|
||||
// Buffer writes to reduce syscall count
|
||||
if (turn_indexes_write_buffer.size() >= TURN_INDEX_WRITE_BUFFER_SIZE)
|
||||
{
|
||||
@ -879,6 +985,20 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
}
|
||||
});
|
||||
|
||||
// re-hash conditionals to ocnnect to their respective edge-based edges. Due to the
|
||||
// ordering, we
|
||||
// do not really have a choice but to index the conditional penalties and walk over all
|
||||
// edge-based-edges to find the ID of the edge
|
||||
auto const indexed_conditionals = IndexConditionals(std::move(conditionals));
|
||||
{
|
||||
util::Log() << "Writing " << indexed_conditionals.size()
|
||||
<< " conditional turn penalties...";
|
||||
// write conditional turn penalties into the restrictions file
|
||||
storage::io::FileWriter writer(conditional_penalties_filename,
|
||||
storage::io::FileWriter::GenerateFingerprint);
|
||||
extractor::serialization::write(writer, indexed_conditionals);
|
||||
}
|
||||
|
||||
// write weight penalties per turn
|
||||
BOOST_ASSERT(turn_weight_penalties.size() == turn_duration_penalties.size());
|
||||
{
|
||||
@ -918,11 +1038,36 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
util::Log() << " contains " << m_edge_based_edge_list.size() << " edges";
|
||||
util::Log() << " skips " << restricted_turns_counter << " turns, "
|
||||
"defined by "
|
||||
<< node_restriction_map.size() << " restrictions";
|
||||
<< node_restriction_map.Size() << " restrictions";
|
||||
util::Log() << " skips " << skipped_uturns_counter << " U turns";
|
||||
util::Log() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
|
||||
}
|
||||
|
||||
std::vector<ConditionalTurnPenalty>
|
||||
EdgeBasedGraphFactory::IndexConditionals(std::vector<Conditional> &&conditionals) const
|
||||
{
|
||||
boost::unordered_multimap<std::pair<NodeID, NodeID>, ConditionalTurnPenalty *> index;
|
||||
|
||||
// build and index of all conditional restrictions
|
||||
for (auto &conditional : conditionals)
|
||||
index.insert(std::make_pair(std::make_pair(conditional.from_node, conditional.to_node),
|
||||
&conditional.penalty));
|
||||
|
||||
std::vector<ConditionalTurnPenalty> indexed_restrictions;
|
||||
|
||||
for (auto const &edge : m_edge_based_edge_list)
|
||||
{
|
||||
auto const range = index.equal_range(std::make_pair(edge.source, edge.target));
|
||||
for (auto itr = range.first; itr != range.second; ++itr)
|
||||
{
|
||||
itr->second->turn_offset = edge.data.turn_id;
|
||||
indexed_restrictions.push_back(*itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
return indexed_restrictions;
|
||||
}
|
||||
|
||||
std::vector<util::guidance::BearingClass> EdgeBasedGraphFactory::GetBearingClasses() const
|
||||
{
|
||||
std::vector<util::guidance::BearingClass> result(bearing_class_hash.data.size());
|
||||
|
@ -126,7 +126,6 @@ ExtractionContainers::ExtractionContainers()
|
||||
*/
|
||||
void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environment,
|
||||
const std::string &osrm_path,
|
||||
const std::string &restrictions_file_name,
|
||||
const std::string &name_file_name)
|
||||
{
|
||||
storage::io::FileWriter file_out(osrm_path, storage::io::FileWriter::GenerateFingerprint);
|
||||
@ -139,7 +138,6 @@ void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environme
|
||||
WriteEdges(file_out);
|
||||
|
||||
PrepareRestrictions();
|
||||
WriteConditionalRestrictions(restrictions_file_name);
|
||||
WriteCharData(name_file_name);
|
||||
}
|
||||
|
||||
@ -633,16 +631,6 @@ void ExtractionContainers::WriteNodes(storage::io::FileWriter &file_out) const
|
||||
util::Log() << "Processed " << max_internal_node_id << " nodes";
|
||||
}
|
||||
|
||||
void ExtractionContainers::WriteConditionalRestrictions(const std::string &path)
|
||||
{
|
||||
std::uint64_t written_restriction_count = conditional_turn_restrictions.size();
|
||||
storage::io::FileWriter restrictions_out_file(path,
|
||||
storage::io::FileWriter::GenerateFingerprint);
|
||||
serialization::write(restrictions_out_file, conditional_turn_restrictions);
|
||||
util::Log() << "number of conditional restrictions written to disk: "
|
||||
<< written_restriction_count;
|
||||
}
|
||||
|
||||
void ExtractionContainers::PrepareRestrictions()
|
||||
{
|
||||
|
||||
@ -837,7 +825,8 @@ void ExtractionContainers::PrepareRestrictions()
|
||||
const auto transform_into_internal_types =
|
||||
[&](const InputConditionalTurnRestriction &external_restriction) {
|
||||
// unconditional restriction
|
||||
if (external_restriction.condition.empty())
|
||||
if (external_restriction.condition.empty() &&
|
||||
external_restriction.Type() == RestrictionType::NODE_RESTRICTION)
|
||||
{
|
||||
TurnRestriction restriction;
|
||||
restriction.is_only = external_restriction.is_only;
|
||||
@ -851,7 +840,9 @@ void ExtractionContainers::PrepareRestrictions()
|
||||
restriction.is_only = external_restriction.is_only;
|
||||
restriction.condition = std::move(external_restriction.condition);
|
||||
if (transform(external_restriction, restriction))
|
||||
{
|
||||
conditional_turn_restrictions.push_back(std::move(restriction));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "util/timing_util.hpp"
|
||||
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/restriction_map.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/way_restriction_map.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/static_rtree.hpp"
|
||||
@ -110,7 +110,8 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
||||
|
||||
guidance::LaneDescriptionMap turn_lane_map;
|
||||
std::vector<TurnRestriction> turn_restrictions;
|
||||
std::tie(turn_lane_map, turn_restrictions) =
|
||||
std::vector<ConditionalTurnRestriction> conditional_turn_restrictions;
|
||||
std::tie(turn_lane_map, turn_restrictions, conditional_turn_restrictions) =
|
||||
ParseOSMData(scripting_environment, number_of_threads);
|
||||
|
||||
// Transform the node-based graph that OSM is based on into an edge-based graph
|
||||
@ -138,6 +139,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
||||
edge_based_edge_list,
|
||||
config.GetPath(".osrm.icd").string(),
|
||||
turn_restrictions,
|
||||
conditional_turn_restrictions,
|
||||
turn_lane_map);
|
||||
|
||||
auto number_of_node_based_nodes = graph_size.first;
|
||||
@ -190,7 +192,9 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::tuple<guidance::LaneDescriptionMap, std::vector<TurnRestriction>>
|
||||
std::tuple<guidance::LaneDescriptionMap,
|
||||
std::vector<TurnRestriction>,
|
||||
std::vector<ConditionalTurnRestriction>>
|
||||
Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
|
||||
const unsigned number_of_threads)
|
||||
{
|
||||
@ -333,7 +337,6 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
|
||||
|
||||
extraction_containers.PrepareData(scripting_environment,
|
||||
config.GetPath(".osrm").string(),
|
||||
config.GetPath(".osrm.restrictions").string(),
|
||||
config.GetPath(".osrm.names").string());
|
||||
|
||||
auto profile_properties = scripting_environment.GetProfileProperties();
|
||||
@ -344,7 +347,8 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
|
||||
util::Log() << "extraction finished after " << TIMER_SEC(extracting) << "s";
|
||||
|
||||
return std::make_tuple(std::move(turn_lane_map),
|
||||
std::move(extraction_containers.unconditional_turn_restrictions));
|
||||
std::move(extraction_containers.unconditional_turn_restrictions),
|
||||
std::move(extraction_containers.conditional_turn_restrictions));
|
||||
}
|
||||
|
||||
void Extractor::FindComponents(unsigned max_edge_id,
|
||||
@ -440,18 +444,19 @@ Extractor::LoadNodeBasedGraph(std::unordered_set<NodeID> &barriers,
|
||||
/**
|
||||
\brief Building an edge-expanded graph from node-based input and turn restrictions
|
||||
*/
|
||||
std::pair<std::size_t, EdgeID>
|
||||
Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
extractor::PackedOSMIDs &osm_node_ids,
|
||||
EdgeBasedNodeDataContainer &edge_based_nodes_container,
|
||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||
std::vector<bool> &node_is_startpoint,
|
||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||
const std::string &intersection_class_output_file,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
guidance::LaneDescriptionMap &turn_lane_map)
|
||||
std::pair<std::size_t, EdgeID> Extractor::BuildEdgeExpandedGraph(
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
extractor::PackedOSMIDs &osm_node_ids,
|
||||
EdgeBasedNodeDataContainer &edge_based_nodes_container,
|
||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||
std::vector<bool> &node_is_startpoint,
|
||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||
const std::string &intersection_class_output_file,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
guidance::LaneDescriptionMap &turn_lane_map)
|
||||
{
|
||||
std::unordered_set<NodeID> barrier_nodes;
|
||||
std::unordered_set<NodeID> traffic_signals;
|
||||
@ -465,10 +470,12 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
traffic_signals,
|
||||
scripting_environment,
|
||||
turn_restrictions,
|
||||
conditional_turn_restrictions,
|
||||
*node_based_graph,
|
||||
compressed_edge_container);
|
||||
|
||||
turn_restrictions = removeInvalidRestrictions(std::move(turn_restrictions), *node_based_graph);
|
||||
conditional_turn_restrictions =
|
||||
removeInvalidRestrictions(std::move(conditional_turn_restrictions), *node_based_graph);
|
||||
|
||||
util::NameTable name_table(config.GetPath(".osrm.names").string());
|
||||
|
||||
@ -484,8 +491,20 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
|
||||
const auto create_edge_based_edges = [&]() {
|
||||
// scoped to relase intermediate datastructures right after the call
|
||||
RestrictionMap via_node_restriction_map(turn_restrictions);
|
||||
WayRestrictionMap via_way_restriction_map(turn_restrictions);
|
||||
std::vector<TurnRestriction> node_restrictions;
|
||||
for (auto const &t : turn_restrictions)
|
||||
if (t.Type() == RestrictionType::NODE_RESTRICTION)
|
||||
node_restrictions.push_back(t);
|
||||
|
||||
std::vector<ConditionalTurnRestriction> conditional_node_restrictions;
|
||||
for (auto const &t : conditional_turn_restrictions)
|
||||
if (t.Type() == RestrictionType::NODE_RESTRICTION)
|
||||
conditional_node_restrictions.push_back(t);
|
||||
|
||||
RestrictionMap via_node_restriction_map(node_restrictions, IndexNodeByFromAndVia());
|
||||
WayRestrictionMap via_way_restriction_map(conditional_turn_restrictions);
|
||||
ConditionalRestrictionMap conditional_node_restriction_map(conditional_node_restrictions,
|
||||
IndexNodeByFromAndVia());
|
||||
turn_restrictions.clear();
|
||||
turn_restrictions.shrink_to_fit();
|
||||
|
||||
@ -496,13 +515,14 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
config.GetPath(".osrm.turn_duration_penalties").string(),
|
||||
config.GetPath(".osrm.turn_penalties_index").string(),
|
||||
config.GetPath(".osrm.cnbg_to_ebg").string(),
|
||||
config.GetPath(".osrm.restrictions").string(),
|
||||
via_node_restriction_map,
|
||||
conditional_node_restriction_map,
|
||||
via_way_restriction_map);
|
||||
return edge_based_graph_factory.GetNumberOfEdgeBasedNodes();
|
||||
};
|
||||
|
||||
const auto number_of_edge_based_nodes = create_edge_based_edges();
|
||||
|
||||
compressed_edge_container.PrintStatistics();
|
||||
|
||||
// The osrm-partition tool requires the compressed node based graph with an embedding.
|
||||
|
@ -20,17 +20,19 @@ namespace osrm
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_signals,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
util::NodeBasedDynamicGraph &graph,
|
||||
CompressedEdgeContainer &geometry_compressor)
|
||||
void GraphCompressor::Compress(
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_signals,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
util::NodeBasedDynamicGraph &graph,
|
||||
CompressedEdgeContainer &geometry_compressor)
|
||||
{
|
||||
const unsigned original_number_of_nodes = graph.GetNumberOfNodes();
|
||||
const unsigned original_number_of_edges = graph.GetNumberOfEdges();
|
||||
|
||||
RestrictionCompressor restriction_compressor(turn_restrictions);
|
||||
RestrictionCompressor restriction_compressor(turn_restrictions, conditional_turn_restrictions);
|
||||
|
||||
// we do not compress turn restrictions on degree two nodes. These nodes are usually used to
|
||||
// indicated `directed` barriers
|
||||
@ -51,6 +53,9 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
}
|
||||
};
|
||||
std::for_each(turn_restrictions.begin(), turn_restrictions.end(), remember_via_nodes);
|
||||
std::for_each(conditional_turn_restrictions.begin(),
|
||||
conditional_turn_restrictions.end(),
|
||||
remember_via_nodes);
|
||||
|
||||
{
|
||||
const auto weight_multiplier =
|
||||
|
@ -236,8 +236,25 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
||||
{
|
||||
const auto node_at_intersection = node_based_graph.GetTarget(entering_via_edge);
|
||||
|
||||
// check if there is a single valid turn entering the current intersection
|
||||
const auto only_valid_turn = GetOnlyAllowedTurnIfExistent(previous_node, node_at_intersection);
|
||||
// request all turn restrictions
|
||||
auto const restrictions = restriction_map.Restrictions(previous_node, node_at_intersection);
|
||||
|
||||
// check turn restrictions to find a node that is the only allowed target when coming from a
|
||||
// node to an intersection
|
||||
// d
|
||||
// |
|
||||
// a - b - c and `only_straight_on ab | bc would return `c` for `a,b`
|
||||
const auto find_only_valid_turn = [&]() -> boost::optional<NodeID> {
|
||||
const auto itr = std::find_if(restrictions.first, restrictions.second, [](auto pair) {
|
||||
return pair.second->is_only;
|
||||
});
|
||||
if (itr != restrictions.second)
|
||||
return {itr->second->AsNodeRestriction().to};
|
||||
else
|
||||
return boost::none;
|
||||
};
|
||||
|
||||
const auto only_valid_turn = find_only_valid_turn();
|
||||
|
||||
// barriers change our behaviour regarding u-turns
|
||||
const bool is_barrier_node = barrier_nodes.find(node_at_intersection) != barrier_nodes.end();
|
||||
@ -258,12 +275,14 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
||||
|
||||
const auto is_restricted = [&](const NodeID destination) {
|
||||
// check if we have a dedicated destination
|
||||
if (only_valid_turn && *only_valid_turn != destination)
|
||||
return true;
|
||||
if (only_valid_turn)
|
||||
return *only_valid_turn != destination;
|
||||
|
||||
// not explicitly forbidden
|
||||
return restriction_map.CheckIfTurnIsRestricted(
|
||||
previous_node, node_at_intersection, destination);
|
||||
// check if explicitly forbidden
|
||||
return restrictions.second !=
|
||||
std::find_if(restrictions.first, restrictions.second, [&](const auto &restriction) {
|
||||
return restriction.second->AsNodeRestriction().to == destination;
|
||||
});
|
||||
};
|
||||
|
||||
const auto is_allowed_turn = [&](const IntersectionShapeData &road) {
|
||||
@ -396,21 +415,6 @@ IntersectionView IntersectionGenerator::TransformIntersectionShapeIntoView(
|
||||
return intersection_view;
|
||||
}
|
||||
|
||||
boost::optional<NodeID>
|
||||
IntersectionGenerator::GetOnlyAllowedTurnIfExistent(const NodeID coming_from_node,
|
||||
const NodeID node_at_intersection) const
|
||||
{
|
||||
// If only restrictions refer to invalid ways somewhere far away, we rather ignore the
|
||||
// restriction than to not route over the intersection at all.
|
||||
const auto only_restriction_to_node =
|
||||
restriction_map.CheckForEmanatingIsOnlyTurn(coming_from_node, node_at_intersection);
|
||||
if (only_restriction_to_node != SPECIAL_NODEID)
|
||||
return only_restriction_to_node;
|
||||
|
||||
// Ignore broken only restrictions.
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
const CoordinateExtractor &IntersectionGenerator::GetCoordinateExtractor() const
|
||||
{
|
||||
return coordinate_extractor;
|
||||
|
@ -10,7 +10,9 @@ namespace osrm
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
RestrictionCompressor::RestrictionCompressor(std::vector<TurnRestriction> &restrictions)
|
||||
RestrictionCompressor::RestrictionCompressor(
|
||||
std::vector<TurnRestriction> &restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions)
|
||||
{
|
||||
// add a node restriction ptr to the starts/ends maps, needs to be a reference!
|
||||
auto index = [&](auto &element) {
|
||||
@ -35,6 +37,9 @@ RestrictionCompressor::RestrictionCompressor(std::vector<TurnRestriction> &restr
|
||||
|
||||
// add all restrictions as their respective startend pointers
|
||||
std::for_each(restrictions.begin(), restrictions.end(), index_starts_and_ends);
|
||||
std::for_each(conditional_turn_restrictions.begin(),
|
||||
conditional_turn_restrictions.end(),
|
||||
index_starts_and_ends);
|
||||
}
|
||||
|
||||
void RestrictionCompressor::Compress(const NodeID from, const NodeID via, const NodeID to)
|
||||
|
@ -10,8 +10,8 @@ namespace osrm
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
std::vector<TurnRestriction>
|
||||
removeInvalidRestrictions(std::vector<TurnRestriction> restrictions,
|
||||
std::vector<ConditionalTurnRestriction>
|
||||
removeInvalidRestrictions(std::vector<ConditionalTurnRestriction> restrictions,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph)
|
||||
{
|
||||
// definition of what we presume to be a valid via-node restriction
|
||||
|
@ -1,138 +0,0 @@
|
||||
#include "extractor/restriction_map.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
RestrictionMap::RestrictionMap(const std::vector<TurnRestriction> &restriction_list) : m_count(0)
|
||||
{
|
||||
// decompose restriction consisting of a start, via and end node into a
|
||||
// a pair of starting edge and a list of all end nodes
|
||||
for (auto &restriction : restriction_list)
|
||||
{
|
||||
// only handle node restrictions here
|
||||
if (restriction.Type() == RestrictionType::WAY_RESTRICTION)
|
||||
continue;
|
||||
|
||||
const auto &node_restriction = restriction.AsNodeRestriction();
|
||||
BOOST_ASSERT(node_restriction.Valid());
|
||||
// This downcasting is OK because when this is called, the node IDs have been
|
||||
// renumbered into internal values, which should be well under 2^32
|
||||
// This will be a problem if we have more than 2^32 actual restrictions
|
||||
BOOST_ASSERT(node_restriction.from < std::numeric_limits<NodeID>::max());
|
||||
BOOST_ASSERT(node_restriction.via < std::numeric_limits<NodeID>::max());
|
||||
m_restriction_start_nodes.insert(node_restriction.from);
|
||||
m_no_turn_via_node_set.insert(node_restriction.via);
|
||||
|
||||
// This explicit downcasting is also OK for the same reason.
|
||||
RestrictionSource restriction_source = {static_cast<NodeID>(node_restriction.from),
|
||||
static_cast<NodeID>(node_restriction.via)};
|
||||
|
||||
std::size_t index;
|
||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if (restriction_iter == m_restriction_map.end())
|
||||
{
|
||||
index = m_restriction_bucket_list.size();
|
||||
m_restriction_bucket_list.resize(index + 1);
|
||||
m_restriction_map.emplace(restriction_source, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = restriction_iter->second;
|
||||
// Map already contains an is_only_*-restriction
|
||||
if (m_restriction_bucket_list.at(index).begin()->is_only)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (restriction.is_only)
|
||||
{
|
||||
// We are going to insert an is_only_*-restriction. There can be only one.
|
||||
m_count -= m_restriction_bucket_list.at(index).size();
|
||||
m_restriction_bucket_list.at(index).clear();
|
||||
}
|
||||
}
|
||||
++m_count;
|
||||
m_restriction_bucket_list.at(index).emplace_back(node_restriction.to, restriction.is_only);
|
||||
}
|
||||
}
|
||||
|
||||
bool RestrictionMap::IsViaNode(const NodeID node) const
|
||||
{
|
||||
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
|
||||
}
|
||||
|
||||
// Check if edge (u, v) is the start of any turn restriction.
|
||||
// If so returns id of first target node.
|
||||
NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const NodeID node_v) const
|
||||
{
|
||||
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||
|
||||
if (!IsSourceNode(node_u))
|
||||
{
|
||||
return SPECIAL_NODEID;
|
||||
}
|
||||
|
||||
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
|
||||
if (restriction_iter != m_restriction_map.end())
|
||||
{
|
||||
const unsigned index = restriction_iter->second;
|
||||
const auto &bucket = m_restriction_bucket_list.at(index);
|
||||
for (const RestrictionTarget &restriction_target : bucket)
|
||||
{
|
||||
if (restriction_target.is_only)
|
||||
{
|
||||
return restriction_target.target_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SPECIAL_NODEID;
|
||||
}
|
||||
|
||||
// Checks if turn <u,v,w> is actually a turn restriction.
|
||||
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
|
||||
const NodeID node_v,
|
||||
const NodeID node_w) const
|
||||
{
|
||||
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(node_v != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(node_w != SPECIAL_NODEID);
|
||||
|
||||
if (!IsSourceNode(node_u))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto restriction_iter = m_restriction_map.find({node_u, node_v});
|
||||
if (restriction_iter == m_restriction_map.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned index = restriction_iter->second;
|
||||
const auto &bucket = m_restriction_bucket_list.at(index);
|
||||
|
||||
for (const RestrictionTarget &restriction_target : bucket)
|
||||
{
|
||||
if (node_w == restriction_target.target_node && // target found
|
||||
!restriction_target.is_only) // and not an only_-restr.
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// We could be tempted to check for `only` restrictions here as well. However, that check is
|
||||
// actually perfomed in intersection generation where we can also verify if the only
|
||||
// restriction is valid at all.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// check of node is the start of any restriction
|
||||
bool RestrictionMap::IsSourceNode(const NodeID node) const
|
||||
{
|
||||
return m_restriction_start_nodes.find(node) != m_restriction_start_nodes.end();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#include "extractor/way_restriction_map.hpp"
|
||||
#include "util/for_each_pair.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
@ -28,12 +29,46 @@ struct FindViaWay
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
WayRestrictionMap::WayRestrictionMap(const std::vector<TurnRestriction> &turn_restrictions)
|
||||
template <typename restriction_type> auto asDuplicatedNode(const restriction_type &restriction)
|
||||
{
|
||||
// get all way restrictions
|
||||
const auto extract_restrictions = [this](const auto &turn_restriction) {
|
||||
auto &way = restriction.AsWayRestriction();
|
||||
// group restrictions by the via-way. On same via-ways group by from
|
||||
return std::tie(way.in_restriction.via, way.out_restriction.via, way.in_restriction.from);
|
||||
};
|
||||
|
||||
template <typename restriction_type> struct CompareByDuplicatedNode
|
||||
{
|
||||
bool operator()(const ConditionalTurnRestriction &lhs, const ConditionalTurnRestriction &rhs)
|
||||
{
|
||||
if (asDuplicatedNode(lhs) < asDuplicatedNode(rhs))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (asDuplicatedNode(rhs) < asDuplicatedNode(lhs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto lhs_to = lhs.AsWayRestriction().out_restriction.to;
|
||||
const auto rhs_to = rhs.AsWayRestriction().out_restriction.to;
|
||||
|
||||
const bool has_conditions_lhs = !lhs.condition.empty();
|
||||
const bool has_conditions_rhs = !rhs.condition.empty();
|
||||
|
||||
return std::tie(lhs_to, lhs.is_only, has_conditions_lhs) <
|
||||
std::tie(rhs_to, rhs.is_only, has_conditions_rhs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename restriction_type>
|
||||
std::vector<restriction_type>
|
||||
extractRestrictions(const std::vector<restriction_type> &turn_restrictions)
|
||||
{
|
||||
std::vector<restriction_type> result;
|
||||
for (const auto &turn_restriction : turn_restrictions)
|
||||
{
|
||||
if (turn_restriction.Type() == RestrictionType::WAY_RESTRICTION)
|
||||
{
|
||||
const auto &way = turn_restriction.AsWayRestriction();
|
||||
@ -41,32 +76,32 @@ WayRestrictionMap::WayRestrictionMap(const std::vector<TurnRestriction> &turn_re
|
||||
// so far we can only handle restrictions that are not interrupted
|
||||
if (way.in_restriction.via == way.out_restriction.from &&
|
||||
way.in_restriction.to == way.out_restriction.via)
|
||||
restriction_data.push_back(turn_restriction);
|
||||
result.push_back(turn_restriction);
|
||||
}
|
||||
};
|
||||
std::for_each(turn_restrictions.begin(), turn_restrictions.end(), extract_restrictions);
|
||||
}
|
||||
std::sort(result.begin(), result.end(), CompareByDuplicatedNode<restriction_type>());
|
||||
auto new_end = std::unique(result.begin(), result.end());
|
||||
result.erase(new_end, result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
const auto as_duplicated_node = [](auto const &restriction) {
|
||||
auto &way = restriction.AsWayRestriction();
|
||||
// group restrictions by the via-way. On same via-ways group by from
|
||||
return std::tie(way.in_restriction.via, way.out_restriction.via, way.in_restriction.from);
|
||||
};
|
||||
|
||||
const auto by_duplicated_node = [&](auto const &lhs, auto const &rhs) {
|
||||
return as_duplicated_node(lhs) < as_duplicated_node(rhs);
|
||||
};
|
||||
|
||||
std::sort(restriction_data.begin(), restriction_data.end(), by_duplicated_node);
|
||||
|
||||
// map all way restrictions into access containers
|
||||
for (RestrictionID index = 0; index < restriction_data.size(); ++index)
|
||||
template <typename restriction_type> struct ByInFromAndVia
|
||||
{
|
||||
std::pair<NodeID, NodeID> operator()(const restriction_type &restriction)
|
||||
{
|
||||
const auto &restriction = restriction_data[index];
|
||||
const auto &way = restriction.AsWayRestriction();
|
||||
restriction_starts.insert(
|
||||
std::make_pair(std::make_pair(way.in_restriction.from, way.in_restriction.via), index));
|
||||
};
|
||||
return std::make_pair(way.in_restriction.from, way.in_restriction.via);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// get all way restrictions
|
||||
WayRestrictionMap::WayRestrictionMap(
|
||||
const std::vector<ConditionalTurnRestriction> &turn_restrictions_)
|
||||
: restriction_data(extractRestrictions(turn_restrictions_)),
|
||||
restriction_starts(restriction_data, ByInFromAndVia<ConditionalTurnRestriction>())
|
||||
{
|
||||
std::size_t offset = 1;
|
||||
// the first group starts at 0
|
||||
if (!restriction_data.empty())
|
||||
@ -74,8 +109,10 @@ WayRestrictionMap::WayRestrictionMap(const std::vector<TurnRestriction> &turn_re
|
||||
|
||||
auto const add_offset_on_new_groups = [&](auto const &lhs, auto const &rhs) {
|
||||
BOOST_ASSERT(rhs == restriction_data[offset]);
|
||||
BOOST_ASSERT(lhs.Type() == RestrictionType::WAY_RESTRICTION);
|
||||
BOOST_ASSERT(rhs.Type() == RestrictionType::WAY_RESTRICTION);
|
||||
// add a new lower bound for rhs
|
||||
if (as_duplicated_node(lhs) != as_duplicated_node(rhs))
|
||||
if (asDuplicatedNode(lhs) != asDuplicatedNode(rhs))
|
||||
duplicated_node_groups.push_back(offset);
|
||||
++offset;
|
||||
};
|
||||
@ -115,7 +152,7 @@ DuplicatedNodeID WayRestrictionMap::AsDuplicatedNodeID(const RestrictionID restr
|
||||
return distance_to_upper_bound - 1;
|
||||
}
|
||||
|
||||
util::range<DuplicatedNodeID> WayRestrictionMap::DuplicatedNodeIDs(const NodeID from,
|
||||
std::vector<DuplicatedNodeID> WayRestrictionMap::DuplicatedNodeIDs(const NodeID from,
|
||||
const NodeID to) const
|
||||
{
|
||||
const auto duplicated_node_range_itr = std::equal_range(
|
||||
@ -125,9 +162,13 @@ util::range<DuplicatedNodeID> WayRestrictionMap::DuplicatedNodeIDs(const NodeID
|
||||
return std::distance(restriction_data.begin(), itr);
|
||||
};
|
||||
|
||||
return util::irange<DuplicatedNodeID>(
|
||||
AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.first)),
|
||||
AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.second)));
|
||||
auto first = AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.first));
|
||||
auto end = AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.second));
|
||||
|
||||
std::vector<DuplicatedNodeID> result(end - first);
|
||||
std::iota(result.begin(), result.end(), first);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool WayRestrictionMap::IsRestricted(DuplicatedNodeID duplicated_node, const NodeID to) const
|
||||
@ -138,6 +179,7 @@ bool WayRestrictionMap::IsRestricted(DuplicatedNodeID duplicated_node, const Nod
|
||||
restriction_index != duplicated_node_groups[duplicated_node + 1];
|
||||
++restriction_index)
|
||||
{
|
||||
BOOST_ASSERT(restriction_index < restriction_data.size());
|
||||
const auto &restriction = restriction_data[restriction_index];
|
||||
const auto &way = restriction.AsWayRestriction();
|
||||
|
||||
@ -149,6 +191,32 @@ bool WayRestrictionMap::IsRestricted(DuplicatedNodeID duplicated_node, const Nod
|
||||
return false;
|
||||
}
|
||||
|
||||
ConditionalTurnRestriction const &
|
||||
WayRestrictionMap::GetRestriction(DuplicatedNodeID duplicated_node, const NodeID to) const
|
||||
{
|
||||
// loop over all restrictions associated with the node. Mark as restricted based on
|
||||
// is_only/restricted targets
|
||||
for (RestrictionID restriction_index = duplicated_node_groups[duplicated_node];
|
||||
restriction_index != duplicated_node_groups[duplicated_node + 1];
|
||||
++restriction_index)
|
||||
{
|
||||
BOOST_ASSERT(restriction_index < restriction_data.size());
|
||||
const auto &restriction = restriction_data[restriction_index];
|
||||
const auto &way = restriction.AsWayRestriction();
|
||||
|
||||
if (restriction.is_only && (way.out_restriction.to != to))
|
||||
{
|
||||
return restriction;
|
||||
}
|
||||
else if (!restriction.is_only && (to == way.out_restriction.to))
|
||||
{
|
||||
return restriction;
|
||||
}
|
||||
}
|
||||
throw("Asking for the restriction of an unrestricted turn. Check with `IsRestricted` before "
|
||||
"calling GetRestriction");
|
||||
}
|
||||
|
||||
std::vector<WayRestrictionMap::ViaWay> WayRestrictionMap::DuplicatedNodeRepresentatives() const
|
||||
{
|
||||
std::vector<ViaWay> result;
|
||||
@ -169,19 +237,19 @@ NodeID WayRestrictionMap::RemapIfRestricted(const NodeID edge_based_node,
|
||||
const NodeID node_based_to,
|
||||
const NodeID number_of_edge_based_nodes) const
|
||||
{
|
||||
auto range = restriction_starts.equal_range(std::make_pair(node_based_from, node_based_via));
|
||||
auto range = restriction_starts.Restrictions(node_based_from, node_based_via);
|
||||
|
||||
// returns true if the ID saved in an iterator belongs to a turn restriction that references
|
||||
// node_based_to as destination of the `in_restriction`
|
||||
const auto restriction_targets_to = [node_based_to, this](const auto &pair) {
|
||||
return restriction_data[pair.second].AsWayRestriction().in_restriction.to == node_based_to;
|
||||
return pair.second->AsWayRestriction().in_restriction.to == node_based_to;
|
||||
};
|
||||
const auto itr = std::find_if(range.first, range.second, restriction_targets_to);
|
||||
|
||||
// in case we found a matching restriction, we can remap the edge_based_node
|
||||
if (itr != range.second)
|
||||
return number_of_edge_based_nodes - NumberOfDuplicatedNodes() +
|
||||
AsDuplicatedNodeID(itr->second);
|
||||
AsDuplicatedNodeID(itr->second - &restriction_data[0]);
|
||||
else
|
||||
return edge_based_node;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "extractor/node_based_edge.hpp"
|
||||
#include "extractor/packed_osm_ids.hpp"
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "extractor/serialization.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
|
||||
@ -443,20 +444,16 @@ updateTurnPenalties(const UpdaterConfig &config,
|
||||
return updated_turns;
|
||||
}
|
||||
|
||||
bool IsRestrictionValid(const Timezoner &tz_handler,
|
||||
const extractor::ConditionalTurnRestriction &turn,
|
||||
const std::vector<util::Coordinate> &coordinates)
|
||||
bool IsRestrictionValid(const Timezoner &tz_handler, const extractor::ConditionalTurnPenalty &turn)
|
||||
{
|
||||
BOOST_ASSERT(!turn.condition.empty());
|
||||
BOOST_ASSERT(!turn.conditions.empty());
|
||||
|
||||
// we utilize the via node (first on ways) to represent the turn restriction
|
||||
auto const via = turn.Type() == extractor::RestrictionType::WAY_RESTRICTION
|
||||
? turn.AsWayRestriction().in_restriction.to
|
||||
: turn.AsNodeRestriction().via;
|
||||
auto const via = turn.location;
|
||||
|
||||
const auto lon = static_cast<double>(toFloating(coordinates[via].lon));
|
||||
const auto lat = static_cast<double>(toFloating(coordinates[via].lat));
|
||||
const auto &condition = turn.condition;
|
||||
const auto lon = static_cast<double>(toFloating(via.lon));
|
||||
const auto lat = static_cast<double>(toFloating(via.lat));
|
||||
const auto &conditions = turn.conditions;
|
||||
|
||||
// Get local time of the restriction
|
||||
const auto &local_time = tz_handler(point_t{lon, lat});
|
||||
@ -469,85 +466,27 @@ bool IsRestrictionValid(const Timezoner &tz_handler,
|
||||
// TODO: parsing will fail for combined conditions, e.g. Sa-Su AND weight>7
|
||||
// http://wiki.openstreetmap.org/wiki/Conditional_restrictions#Combined_conditions:_AND
|
||||
|
||||
if (osrm::util::CheckOpeningHours(condition, *local_time))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return osrm::util::CheckOpeningHours(conditions, *local_time);
|
||||
}
|
||||
|
||||
std::vector<std::uint64_t>
|
||||
updateConditionalTurns(const UpdaterConfig &config,
|
||||
std::vector<TurnPenalty> &turn_weight_penalties,
|
||||
const std::vector<extractor::ConditionalTurnRestriction> &conditional_turns,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
updateConditionalTurns(std::vector<TurnPenalty> &turn_weight_penalties,
|
||||
const std::vector<extractor::ConditionalTurnPenalty> &conditional_turns,
|
||||
Timezoner time_zone_handler)
|
||||
{
|
||||
// Mapped file pointer for turn indices
|
||||
boost::iostreams::mapped_file_source turn_index_region;
|
||||
auto turn_index_blocks = util::mmapFile<extractor::lookup::TurnIndexBlock>(
|
||||
config.GetPath(".osrm.turn_penalties_index"), turn_index_region);
|
||||
|
||||
std::vector<std::uint64_t> updated_turns;
|
||||
if (conditional_turns.size() == 0)
|
||||
return updated_turns;
|
||||
|
||||
// TODO make this into a function
|
||||
LookupTable<std::tuple<NodeID, NodeID>, NodeID> is_only_lookup;
|
||||
std::unordered_set<std::tuple<NodeID, NodeID, NodeID>,
|
||||
std::hash<std::tuple<NodeID, NodeID, NodeID>>>
|
||||
is_no_set;
|
||||
for (const auto &node_or_way : conditional_turns)
|
||||
for (const auto &penalty : conditional_turns)
|
||||
{
|
||||
// TODO handle conditional turn restrictions for via-ways (look-up doesn't work here)
|
||||
// https://github.com/Project-OSRM/osrm-backend/issues/2681#issuecomment-313376385
|
||||
if (node_or_way.Type() == extractor::RestrictionType::WAY_RESTRICTION)
|
||||
continue;
|
||||
|
||||
if (!IsRestrictionValid(time_zone_handler, node_or_way, coordinates))
|
||||
continue;
|
||||
|
||||
// TODO get rid of this, when we can handle way restrictions
|
||||
const auto &c = node_or_way.AsNodeRestriction();
|
||||
|
||||
// only add restrictions to the lookups if the restriction is valid now
|
||||
|
||||
if (node_or_way.is_only)
|
||||
if (IsRestrictionValid(time_zone_handler, penalty))
|
||||
{
|
||||
is_only_lookup.lookup.push_back({std::make_tuple(c.from, c.via), c.to});
|
||||
}
|
||||
else
|
||||
{
|
||||
is_no_set.insert({std::make_tuple(c.from, c.via, c.to)});
|
||||
std::cout << "Disabling: " << penalty.turn_offset << std::endl;
|
||||
turn_weight_penalties[penalty.turn_offset] = INVALID_TURN_PENALTY;
|
||||
updated_turns.push_back(penalty.turn_offset);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::uint64_t edge_index = 0; edge_index < turn_weight_penalties.size(); ++edge_index)
|
||||
{
|
||||
const extractor::lookup::TurnIndexBlock internal_turn = turn_index_blocks[edge_index];
|
||||
|
||||
const auto is_no_tuple =
|
||||
std::make_tuple(internal_turn.from_id, internal_turn.via_id, internal_turn.to_id);
|
||||
const auto is_only_tuple = std::make_tuple(internal_turn.from_id, internal_turn.via_id);
|
||||
// turn has a no_* restriction
|
||||
if (is_no_set.find(is_no_tuple) != is_no_set.end())
|
||||
{
|
||||
util::Log(logDEBUG) << "Conditional penalty set on edge: " << edge_index;
|
||||
turn_weight_penalties[edge_index] = INVALID_TURN_PENALTY;
|
||||
updated_turns.push_back(edge_index);
|
||||
}
|
||||
// turn has an only_* restriction
|
||||
else if (is_only_lookup(is_only_tuple))
|
||||
{
|
||||
// with only_* restrictions, the turn on which the restriction is tagged is valid
|
||||
if (*is_only_lookup(is_only_tuple) == internal_turn.to_id)
|
||||
continue;
|
||||
|
||||
util::Log(logDEBUG) << "Conditional penalty set on edge: " << edge_index;
|
||||
turn_weight_penalties[edge_index] = INVALID_TURN_PENALTY;
|
||||
updated_turns.push_back(edge_index);
|
||||
}
|
||||
}
|
||||
|
||||
return updated_turns;
|
||||
}
|
||||
}
|
||||
@ -638,7 +577,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
load_profile_properties);
|
||||
}
|
||||
|
||||
std::vector<extractor::ConditionalTurnRestriction> conditional_turns;
|
||||
std::vector<extractor::ConditionalTurnPenalty> conditional_turns;
|
||||
if (update_conditional_turns)
|
||||
{
|
||||
using storage::io::FileReader;
|
||||
@ -696,8 +635,8 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
|
||||
}
|
||||
const Timezoner time_zone_handler = Timezoner(config.tz_file_path, config.valid_now);
|
||||
|
||||
auto updated_turn_penalties = updateConditionalTurns(
|
||||
config, turn_weight_penalties, conditional_turns, coordinates, time_zone_handler);
|
||||
auto updated_turn_penalties =
|
||||
updateConditionalTurns(turn_weight_penalties, conditional_turns, time_zone_handler);
|
||||
const auto offset = updated_segments.size();
|
||||
updated_segments.resize(offset + updated_turn_penalties.size());
|
||||
// we need to re-compute all edges that have updated turn penalties.
|
||||
|
@ -56,6 +56,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
|
||||
std::unordered_set<NodeID> barrier_nodes;
|
||||
std::unordered_set<NodeID> traffic_lights;
|
||||
std::vector<TurnRestriction> restrictions;
|
||||
std::vector<ConditionalTurnRestriction> conditional_restrictions;
|
||||
CompressedEdgeContainer container;
|
||||
test::MockScriptingEnvironment scripting_environment;
|
||||
|
||||
@ -73,8 +74,13 @@ BOOST_AUTO_TEST_CASE(long_road_test)
|
||||
BOOST_ASSERT(edges[4].data.IsCompatibleTo(edges[6].data));
|
||||
|
||||
Graph graph(5, edges);
|
||||
compressor.Compress(
|
||||
barrier_nodes, traffic_lights, scripting_environment, restrictions, graph, container);
|
||||
compressor.Compress(barrier_nodes,
|
||||
traffic_lights,
|
||||
scripting_environment,
|
||||
restrictions,
|
||||
conditional_restrictions,
|
||||
graph,
|
||||
container);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.FindEdge(0, 1), SPECIAL_EDGEID);
|
||||
BOOST_CHECK_EQUAL(graph.FindEdge(1, 2), SPECIAL_EDGEID);
|
||||
@ -95,6 +101,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
|
||||
std::unordered_set<NodeID> barrier_nodes;
|
||||
std::unordered_set<NodeID> traffic_lights;
|
||||
std::vector<TurnRestriction> restrictions;
|
||||
std::vector<ConditionalTurnRestriction> conditional_restrictions;
|
||||
CompressedEdgeContainer container;
|
||||
test::MockScriptingEnvironment scripting_environment;
|
||||
|
||||
@ -125,8 +132,13 @@ BOOST_AUTO_TEST_CASE(loop_test)
|
||||
BOOST_ASSERT(edges[10].data.IsCompatibleTo(edges[11].data));
|
||||
|
||||
Graph graph(6, edges);
|
||||
compressor.Compress(
|
||||
barrier_nodes, traffic_lights, scripting_environment, restrictions, graph, container);
|
||||
compressor.Compress(barrier_nodes,
|
||||
traffic_lights,
|
||||
scripting_environment,
|
||||
restrictions,
|
||||
conditional_restrictions,
|
||||
graph,
|
||||
container);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.FindEdge(5, 0), SPECIAL_EDGEID);
|
||||
BOOST_CHECK_EQUAL(graph.FindEdge(0, 1), SPECIAL_EDGEID);
|
||||
@ -149,6 +161,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
|
||||
std::unordered_set<NodeID> barrier_nodes;
|
||||
std::unordered_set<NodeID> traffic_lights;
|
||||
std::vector<TurnRestriction> restrictions;
|
||||
std::vector<ConditionalTurnRestriction> conditional_restrictions;
|
||||
CompressedEdgeContainer container;
|
||||
test::MockScriptingEnvironment scripting_environment;
|
||||
|
||||
@ -166,8 +179,13 @@ BOOST_AUTO_TEST_CASE(t_intersection)
|
||||
BOOST_ASSERT(edges[4].data.IsCompatibleTo(edges[5].data));
|
||||
|
||||
Graph graph(4, edges);
|
||||
compressor.Compress(
|
||||
barrier_nodes, traffic_lights, scripting_environment, restrictions, graph, container);
|
||||
compressor.Compress(barrier_nodes,
|
||||
traffic_lights,
|
||||
scripting_environment,
|
||||
restrictions,
|
||||
conditional_restrictions,
|
||||
graph,
|
||||
container);
|
||||
|
||||
BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID);
|
||||
BOOST_CHECK(graph.FindEdge(1, 2) != SPECIAL_EDGEID);
|
||||
@ -184,6 +202,7 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
|
||||
std::unordered_set<NodeID> barrier_nodes;
|
||||
std::unordered_set<NodeID> traffic_lights;
|
||||
std::vector<TurnRestriction> restrictions;
|
||||
std::vector<ConditionalTurnRestriction> conditional_restrictions;
|
||||
CompressedEdgeContainer container;
|
||||
test::MockScriptingEnvironment scripting_environment;
|
||||
|
||||
@ -195,8 +214,13 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
|
||||
BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[3].data));
|
||||
|
||||
Graph graph(5, edges);
|
||||
compressor.Compress(
|
||||
barrier_nodes, traffic_lights, scripting_environment, restrictions, graph, container);
|
||||
compressor.Compress(barrier_nodes,
|
||||
traffic_lights,
|
||||
scripting_environment,
|
||||
restrictions,
|
||||
conditional_restrictions,
|
||||
graph,
|
||||
container);
|
||||
|
||||
BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID);
|
||||
BOOST_CHECK(graph.FindEdge(1, 2) != SPECIAL_EDGEID);
|
||||
@ -212,6 +236,7 @@ BOOST_AUTO_TEST_CASE(direction_changes)
|
||||
std::unordered_set<NodeID> barrier_nodes;
|
||||
std::unordered_set<NodeID> traffic_lights;
|
||||
std::vector<TurnRestriction> restrictions;
|
||||
std::vector<ConditionalTurnRestriction> conditional_restrictions;
|
||||
CompressedEdgeContainer container;
|
||||
test::MockScriptingEnvironment scripting_environment;
|
||||
|
||||
@ -221,8 +246,13 @@ BOOST_AUTO_TEST_CASE(direction_changes)
|
||||
edges[1].data.reversed = true;
|
||||
|
||||
Graph graph(5, edges);
|
||||
compressor.Compress(
|
||||
barrier_nodes, traffic_lights, scripting_environment, restrictions, graph, container);
|
||||
compressor.Compress(barrier_nodes,
|
||||
traffic_lights,
|
||||
scripting_environment,
|
||||
restrictions,
|
||||
conditional_restrictions,
|
||||
graph,
|
||||
container);
|
||||
|
||||
BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID);
|
||||
BOOST_CHECK(graph.FindEdge(1, 2) != SPECIAL_EDGEID);
|
||||
|
Loading…
Reference in New Issue
Block a user