Conditional turn restriction support (#3841)

* optionally include condition and via node coords in InputRestrictionContainer

* only write conditionals to disk, custom serialization for restrictions

* conditional turn lookup, reuse timezone validation from
extract-conditionals

* adapt updater to use coordinates/osm ids, remove internal to external map

* add utc time now parameter to contraction

* only compile timezone code where libshp is found, adapt test running

* slight refactor, more tests

* catch invalid via nodes in restriction parsing, set default cucumber
origin to guinée

* add another run to test mld routed paths

* cosmetic review changes

* Simplify Timezoner for windows build

* Split declaration and parsing parts for opening hours

* adjust conditional tests to run without shapefiles

* always include parse conditionals option

* Adjust travis timeout

* Added dummy TZ shapefile with test timezone polygons

* [skip ci] update changelog
This commit is contained in:
Karen Shea
2017-05-11 12:13:52 +02:00
committed by GitHub
parent 12f47708cd
commit 799a677e7a
42 changed files with 2116 additions and 1310 deletions
+6 -9
View File
@@ -547,20 +547,17 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// If this edge is 'trivial' -- where the compressed edge corresponds
// exactly to an original OSM segment -- we can pull the turn's preceding
// node ID directly with `node_along_road_entering`; otherwise, we need to
// look
// up the node
// immediately preceding the turn from the compressed edge container.
// look up the node immediately preceding the turn from the compressed edge
// container.
const bool isTrivial = m_compressed_edge_container.IsTrivial(incoming_edge);
const auto &from_node =
isTrivial ? m_osm_node_ids[node_along_road_entering]
: m_osm_node_ids[m_compressed_edge_container.GetLastEdgeSourceID(
incoming_edge)];
isTrivial ? node_along_road_entering
: m_compressed_edge_container.GetLastEdgeSourceID(incoming_edge);
const auto &via_node =
m_osm_node_ids[m_compressed_edge_container.GetLastEdgeTargetID(
incoming_edge)];
m_compressed_edge_container.GetLastEdgeTargetID(incoming_edge);
const auto &to_node =
m_osm_node_ids[m_compressed_edge_container.GetFirstEdgeTargetID(turn.eid)];
m_compressed_edge_container.GetFirstEdgeTargetID(turn.eid);
lookup::TurnIndexBlock turn_index_block = {from_node, via_node, to_node};
+35 -14
View File
@@ -1,6 +1,8 @@
#include "extractor/extraction_containers.hpp"
#include "extractor/extraction_segment.hpp"
#include "extractor/extraction_way.hpp"
#include "extractor/restriction.hpp"
#include "extractor/serialization.hpp"
#include "util/coordinate_calculation.hpp"
@@ -134,7 +136,6 @@ void ExtractionContainers::FlushVectors()
all_edges_list.flush();
name_char_data.flush();
name_offsets.flush();
restrictions_list.flush();
way_start_end_id_list.flush();
}
@@ -142,7 +143,7 @@ void ExtractionContainers::FlushVectors()
* Processes the collected data and serializes it.
* At this point nodes are still referenced by their OSM id.
*
* - map start-end nodes of ways to ways used int restrictions to compute compressed
* - map start-end nodes of ways to ways used in restrictions to compute compressed
* trippe representation
* - filter nodes list to nodes that are referenced by ways
* - merge edges with nodes to include location of start/end points and serialize
@@ -630,7 +631,7 @@ void ExtractionContainers::WriteNodes(storage::io::FileWriter &file_out) const
util::Log() << "Processed " << max_internal_node_id << " nodes";
}
void ExtractionContainers::WriteRestrictions(const std::string &path) const
void ExtractionContainers::WriteRestrictions(const std::string &path)
{
// serialize restrictions
std::uint64_t written_restriction_count = 0;
@@ -645,13 +646,27 @@ void ExtractionContainers::WriteRestrictions(const std::string &path) const
SPECIAL_NODEID != restriction_container.restriction.via.node &&
SPECIAL_NODEID != restriction_container.restriction.to.node)
{
restrictions_out_file.WriteOne(restriction_container.restriction);
++written_restriction_count;
if (!restriction_container.restriction.condition.empty())
{
// write conditional turn restrictions to disk, for use in contractor later
extractor::serialization::write(restrictions_out_file,
restriction_container.restriction);
++written_restriction_count;
}
else
{
// save unconditional turn restriction to memory, for use in ebg later
unconditional_turn_restrictions.push_back(
std::move(restriction_container.restriction));
}
}
}
restrictions_out_file.SkipToBeginning();
restrictions_out_file.WriteElementCount64(written_restriction_count);
util::Log() << "usable restrictions: " << written_restriction_count;
util::Log() << "number of restrictions saved to memory: "
<< unconditional_turn_restrictions.size();
util::Log() << "number of conditional restrictions written to disk: "
<< written_restriction_count;
}
void ExtractionContainers::PrepareRestrictions()
@@ -672,10 +687,8 @@ void ExtractionContainers::PrepareRestrictions()
util::UnbufferedLog log;
log << "Sorting " << restrictions_list.size() << " restriction. by from... ";
TIMER_START(sort_restrictions);
stxxl::sort(restrictions_list.begin(),
restrictions_list.end(),
CmpRestrictionContainerByFrom(),
stxxl_memory);
std::sort(
restrictions_list.begin(), restrictions_list.end(), CmpRestrictionContainerByFrom());
TIMER_STOP(sort_restrictions);
log << "ok, after " << TIMER_SEC(sort_restrictions) << "s";
}
@@ -758,6 +771,11 @@ void ExtractionContainers::PrepareRestrictions()
}
restrictions_iterator->restriction.from.node = id_iter->second;
}
else
{
// if it's neither, this is an invalid restriction
restrictions_iterator->restriction.from.node = SPECIAL_NODEID;
}
++restrictions_iterator;
}
@@ -769,10 +787,8 @@ void ExtractionContainers::PrepareRestrictions()
util::UnbufferedLog log;
log << "Sorting restrictions. by to ... " << std::flush;
TIMER_START(sort_restrictions_to);
stxxl::sort(restrictions_list.begin(),
restrictions_list.end(),
CmpRestrictionContainerByTo(),
stxxl_memory);
std::sort(
restrictions_list.begin(), restrictions_list.end(), CmpRestrictionContainerByTo());
TIMER_STOP(sort_restrictions_to);
log << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s";
}
@@ -850,6 +866,11 @@ void ExtractionContainers::PrepareRestrictions()
}
restrictions_iterator->restriction.to.node = to_id_iter->second;
}
else
{
// if it's neither, this is an invalid restriction
restrictions_iterator->restriction.to.node = SPECIAL_NODEID;
}
++restrictions_iterator;
}
TIMER_STOP(fix_restriction_ends);
+194 -201
View File
@@ -115,208 +115,216 @@ transformTurnLaneMapIntoArrays(const guidance::LaneDescriptionMap &turn_lane_map
int Extractor::run(ScriptingEnvironment &scripting_environment)
{
util::LogPolicy::GetInstance().Unmute();
TIMER_START(extracting);
const unsigned recommended_num_threads = tbb::task_scheduler_init::default_num_threads();
const auto number_of_threads = std::min(recommended_num_threads, config.requested_num_threads);
tbb::task_scheduler_init init(number_of_threads ? number_of_threads
: tbb::task_scheduler_init::automatic);
auto turn_restrictions = ParseOSMData(scripting_environment, number_of_threads);
// Transform the node-based graph that OSM is based on into an edge-based graph
// that is better for routing. Every edge becomes a node, and every valid
// movement (e.g. turn from A->B, and B->A) becomes an edge
util::Log() << "Generating edge-expanded graph representation";
TIMER_START(expansion);
std::vector<EdgeBasedNode> edge_based_node_list;
util::DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
std::vector<bool> node_is_startpoint;
std::vector<EdgeWeight> edge_based_node_weights;
std::vector<util::Coordinate> coordinates;
extractor::PackedOSMIDs osm_node_ids;
auto graph_size = BuildEdgeExpandedGraph(scripting_environment,
coordinates,
osm_node_ids,
edge_based_node_list,
node_is_startpoint,
edge_based_node_weights,
edge_based_edge_list,
config.intersection_class_data_output_path,
turn_restrictions);
auto number_of_node_based_nodes = graph_size.first;
auto max_edge_id = graph_size.second;
TIMER_STOP(expansion);
util::Log() << "Saving edge-based node weights to file.";
TIMER_START(timer_write_node_weights);
{
util::Log() << "Input file: " << config.input_path.filename().string();
if (!config.profile_path.empty())
{
util::Log() << "Profile: " << config.profile_path.filename().string();
}
util::Log() << "Threads: " << number_of_threads;
const osmium::io::File input_file(config.input_path.string());
osmium::io::Reader reader(
input_file,
(config.use_metadata ? osmium::io::read_meta::yes : osmium::io::read_meta::no));
const osmium::io::Header header = reader.header();
unsigned number_of_nodes = 0;
unsigned number_of_ways = 0;
unsigned number_of_relations = 0;
util::Log() << "Parsing in progress..";
TIMER_START(parsing);
ExtractionContainers extraction_containers;
auto extractor_callbacks = std::make_unique<ExtractorCallbacks>(
extraction_containers, scripting_environment.GetProfileProperties());
// setup raster sources
scripting_environment.SetupSources();
std::string generator = header.get("generator");
if (generator.empty())
{
generator = "unknown tool";
}
util::Log() << "input file generated by " << generator;
// write .timestamp data file
std::string timestamp = header.get("osmosis_replication_timestamp");
if (timestamp.empty())
{
timestamp = "n/a";
}
util::Log() << "timestamp: " << timestamp;
storage::io::FileWriter timestamp_file(config.timestamp_file_name,
storage::io::FileWriter::GenerateFingerprint);
timestamp_file.WriteFrom(timestamp.c_str(), timestamp.length());
// initialize vectors holding parsed objects
tbb::concurrent_vector<std::pair<std::size_t, ExtractionNode>> resulting_nodes;
tbb::concurrent_vector<std::pair<std::size_t, ExtractionWay>> resulting_ways;
tbb::concurrent_vector<boost::optional<InputRestrictionContainer>> resulting_restrictions;
// setup restriction parser
const RestrictionParser restriction_parser(scripting_environment);
// create a vector of iterators into the buffer
for (std::vector<osmium::memory::Buffer::const_iterator> osm_elements;
const osmium::memory::Buffer buffer = reader.read();
osm_elements.clear())
{
for (auto iter = std::begin(buffer), end = std::end(buffer); iter != end; ++iter)
{
osm_elements.push_back(iter);
}
// clear resulting vectors
resulting_nodes.clear();
resulting_ways.clear();
resulting_restrictions.clear();
scripting_environment.ProcessElements(osm_elements,
restriction_parser,
resulting_nodes,
resulting_ways,
resulting_restrictions);
number_of_nodes += resulting_nodes.size();
// put parsed objects thru extractor callbacks
for (const auto &result : resulting_nodes)
{
extractor_callbacks->ProcessNode(
static_cast<const osmium::Node &>(*(osm_elements[result.first])),
result.second);
}
number_of_ways += resulting_ways.size();
for (const auto &result : resulting_ways)
{
extractor_callbacks->ProcessWay(
static_cast<const osmium::Way &>(*(osm_elements[result.first])), result.second);
}
number_of_relations += resulting_restrictions.size();
for (const auto &result : resulting_restrictions)
{
extractor_callbacks->ProcessRestriction(result);
}
}
TIMER_STOP(parsing);
util::Log() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds";
util::Log() << "Raw input contains " << number_of_nodes << " nodes, " << number_of_ways
<< " ways, and " << number_of_relations << " relations";
// take control over the turn lane map
turn_lane_map = extractor_callbacks->moveOutLaneDescriptionMap();
extractor_callbacks.reset();
if (extraction_containers.all_edges_list.empty())
{
throw util::exception(std::string("There are no edges remaining after parsing.") +
SOURCE_REF);
}
extraction_containers.PrepareData(scripting_environment,
config.output_file_name,
config.restriction_file_name,
config.names_file_name);
WriteProfileProperties(config.profile_properties_output_path,
scripting_environment.GetProfileProperties());
TIMER_STOP(extracting);
util::Log() << "extraction finished after " << TIMER_SEC(extracting) << "s";
storage::io::FileWriter writer(config.edge_based_node_weights_output_path,
storage::io::FileWriter::GenerateFingerprint);
storage::serialization::write(writer, edge_based_node_weights);
}
TIMER_STOP(timer_write_node_weights);
util::Log() << "Done writing. (" << TIMER_SEC(timer_write_node_weights) << ")";
{
// Transform the node-based graph that OSM is based on into an edge-based graph
// that is better for routing. Every edge becomes a node, and every valid
// movement (e.g. turn from A->B, and B->A) becomes an edge
util::Log() << "Generating edge-expanded graph representation";
util::Log() << "Computing strictly connected components ...";
FindComponents(max_edge_id, edge_based_edge_list, edge_based_node_list);
TIMER_START(expansion);
util::Log() << "Building r-tree ...";
TIMER_START(rtree);
BuildRTree(std::move(edge_based_node_list), std::move(node_is_startpoint), coordinates);
std::vector<EdgeBasedNode> edge_based_node_list;
util::DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
std::vector<bool> node_is_startpoint;
std::vector<EdgeWeight> edge_based_node_weights;
std::vector<util::Coordinate> coordinates;
extractor::PackedOSMIDs osm_node_ids;
TIMER_STOP(rtree);
auto graph_size = BuildEdgeExpandedGraph(scripting_environment,
coordinates,
osm_node_ids,
edge_based_node_list,
node_is_startpoint,
edge_based_node_weights,
edge_based_edge_list,
config.intersection_class_data_output_path);
util::Log() << "Writing node map ...";
files::writeNodes(config.node_output_path, coordinates, osm_node_ids);
auto number_of_node_based_nodes = graph_size.first;
auto max_edge_id = graph_size.second;
WriteEdgeBasedGraph(config.edge_graph_output_path, max_edge_id, edge_based_edge_list);
TIMER_STOP(expansion);
const auto nodes_per_second =
static_cast<std::uint64_t>(number_of_node_based_nodes / TIMER_SEC(expansion));
const auto edges_per_second =
static_cast<std::uint64_t>((max_edge_id + 1) / TIMER_SEC(expansion));
util::Log() << "Saving edge-based node weights to file.";
TIMER_START(timer_write_node_weights);
{
storage::io::FileWriter writer(config.edge_based_node_weights_output_path,
storage::io::FileWriter::GenerateFingerprint);
storage::serialization::write(writer, edge_based_node_weights);
}
TIMER_STOP(timer_write_node_weights);
util::Log() << "Done writing. (" << TIMER_SEC(timer_write_node_weights) << ")";
util::Log() << "Computing strictly connected components ...";
FindComponents(max_edge_id, edge_based_edge_list, edge_based_node_list);
util::Log() << "Building r-tree ...";
TIMER_START(rtree);
BuildRTree(std::move(edge_based_node_list), std::move(node_is_startpoint), coordinates);
TIMER_STOP(rtree);
util::Log() << "Writing node map ...";
files::writeNodes(config.node_output_path, coordinates, osm_node_ids);
WriteEdgeBasedGraph(config.edge_graph_output_path, max_edge_id, edge_based_edge_list);
const auto nodes_per_second =
static_cast<std::uint64_t>(number_of_node_based_nodes / TIMER_SEC(expansion));
const auto edges_per_second =
static_cast<std::uint64_t>((max_edge_id + 1) / TIMER_SEC(expansion));
util::Log() << "Expansion: " << nodes_per_second << " nodes/sec and " << edges_per_second
<< " edges/sec";
util::Log() << "To prepare the data for routing, run: "
<< "./osrm-contract " << config.output_file_name;
}
util::Log() << "Expansion: " << nodes_per_second << " nodes/sec and " << edges_per_second
<< " edges/sec";
util::Log() << "To prepare the data for routing, run: "
<< "./osrm-contract " << config.output_file_name;
return 0;
}
std::vector<TurnRestriction> Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
const unsigned number_of_threads)
{
TIMER_START(extracting);
util::Log() << "Input file: " << config.input_path.filename().string();
if (!config.profile_path.empty())
{
util::Log() << "Profile: " << config.profile_path.filename().string();
}
util::Log() << "Threads: " << number_of_threads;
const osmium::io::File input_file(config.input_path.string());
osmium::io::Reader reader(
input_file, (config.use_metadata ? osmium::io::read_meta::yes : osmium::io::read_meta::no));
const osmium::io::Header header = reader.header();
unsigned number_of_nodes = 0;
unsigned number_of_ways = 0;
unsigned number_of_relations = 0;
util::Log() << "Parsing in progress..";
TIMER_START(parsing);
ExtractionContainers extraction_containers;
auto extractor_callbacks = std::make_unique<ExtractorCallbacks>(
extraction_containers, scripting_environment.GetProfileProperties());
// setup raster sources
scripting_environment.SetupSources();
std::string generator = header.get("generator");
if (generator.empty())
{
generator = "unknown tool";
}
util::Log() << "input file generated by " << generator;
// write .timestamp data file
std::string timestamp = header.get("osmosis_replication_timestamp");
if (timestamp.empty())
{
timestamp = "n/a";
}
util::Log() << "timestamp: " << timestamp;
storage::io::FileWriter timestamp_file(config.timestamp_file_name,
storage::io::FileWriter::GenerateFingerprint);
timestamp_file.WriteFrom(timestamp.c_str(), timestamp.length());
// initialize vectors holding parsed objects
tbb::concurrent_vector<std::pair<std::size_t, ExtractionNode>> resulting_nodes;
tbb::concurrent_vector<std::pair<std::size_t, ExtractionWay>> resulting_ways;
tbb::concurrent_vector<boost::optional<InputRestrictionContainer>> resulting_restrictions;
std::vector<std::string> restrictions = scripting_environment.GetRestrictions();
// setup restriction parser
const RestrictionParser restriction_parser(
scripting_environment.GetProfileProperties().use_turn_restrictions,
config.parse_conditionals,
restrictions);
// create a vector of iterators into the buffer
for (std::vector<osmium::memory::Buffer::const_iterator> osm_elements;
const osmium::memory::Buffer buffer = reader.read();
osm_elements.clear())
{
for (auto iter = std::begin(buffer), end = std::end(buffer); iter != end; ++iter)
{
osm_elements.push_back(iter);
}
// clear resulting vectors
resulting_nodes.clear();
resulting_ways.clear();
resulting_restrictions.clear();
scripting_environment.ProcessElements(osm_elements,
restriction_parser,
resulting_nodes,
resulting_ways,
resulting_restrictions);
number_of_nodes += resulting_nodes.size();
// put parsed objects thru extractor callbacks
for (const auto &result : resulting_nodes)
{
extractor_callbacks->ProcessNode(
static_cast<const osmium::Node &>(*(osm_elements[result.first])), result.second);
}
number_of_ways += resulting_ways.size();
for (const auto &result : resulting_ways)
{
extractor_callbacks->ProcessWay(
static_cast<const osmium::Way &>(*(osm_elements[result.first])), result.second);
}
number_of_relations += resulting_restrictions.size();
for (const auto &result : resulting_restrictions)
{
extractor_callbacks->ProcessRestriction(result);
}
}
TIMER_STOP(parsing);
util::Log() << "Parsing finished after " << TIMER_SEC(parsing) << " seconds";
util::Log() << "Raw input contains " << number_of_nodes << " nodes, " << number_of_ways
<< " ways, and " << number_of_relations << " relations";
// take control over the turn lane map
turn_lane_map = extractor_callbacks->moveOutLaneDescriptionMap();
extractor_callbacks.reset();
if (extraction_containers.all_edges_list.empty())
{
throw util::exception(std::string("There are no edges remaining after parsing.") +
SOURCE_REF);
}
extraction_containers.PrepareData(scripting_environment,
config.output_file_name,
config.restriction_file_name,
config.names_file_name);
WriteProfileProperties(config.profile_properties_output_path,
scripting_environment.GetProfileProperties());
TIMER_STOP(extracting);
util::Log() << "extraction finished after " << TIMER_SEC(extracting) << "s";
return extraction_containers.unconditional_turn_restrictions;
}
void Extractor::WriteProfileProperties(const std::string &output_path,
const ProfileProperties &properties) const
{
@@ -384,22 +392,6 @@ void Extractor::FindComponents(unsigned max_edge_id,
}
}
/**
\brief Build load restrictions from .restriction file
*/
std::shared_ptr<RestrictionMap> Extractor::LoadRestrictionMap()
{
storage::io::FileReader file_reader(config.restriction_file_name,
storage::io::FileReader::VerifyFingerprint);
std::vector<TurnRestriction> restriction_list;
util::loadRestrictionsFromFile(file_reader, restriction_list);
util::Log() << " - " << restriction_list.size() << " restrictions.";
return std::make_shared<RestrictionMap>(restriction_list);
}
/**
\brief Load node based graph from .osrm file
*/
@@ -444,12 +436,13 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
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)
const std::string &intersection_class_output_file,
std::vector<TurnRestriction> &turn_restrictions)
{
std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights;
auto restriction_map = LoadRestrictionMap();
auto restriction_map = std::make_shared<RestrictionMap>(turn_restrictions);
auto node_based_graph =
LoadNodeBasedGraph(barrier_nodes, traffic_lights, coordinates, osm_node_ids);
+55 -6
View File
@@ -1,9 +1,9 @@
#include "extractor/restriction_parser.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/scripting_environment.hpp"
#include "extractor/external_memory_node.hpp"
#include "util/conditional_restrictions.hpp"
#include "util/log.hpp"
#include <boost/algorithm/string.hpp>
@@ -24,12 +24,14 @@ namespace osrm
namespace extractor
{
RestrictionParser::RestrictionParser(ScriptingEnvironment &scripting_environment)
: use_turn_restrictions(scripting_environment.GetProfileProperties().use_turn_restrictions)
RestrictionParser::RestrictionParser(bool use_turn_restrictions_,
bool parse_conditionals_,
std::vector<std::string> &restrictions_)
: use_turn_restrictions(use_turn_restrictions_), parse_conditionals(parse_conditionals_),
restrictions(restrictions_)
{
if (use_turn_restrictions)
{
restrictions = scripting_environment.GetRestrictions();
const unsigned count = restrictions.size();
if (count > 0)
{
@@ -54,9 +56,10 @@ RestrictionParser::RestrictionParser(ScriptingEnvironment &scripting_environment
* in the corresponding profile. We use it for both namespacing restrictions, as in
* restriction:motorcar as well as whitelisting if its in except:motorcar.
*/
boost::optional<InputRestrictionContainer>
std::vector<InputRestrictionContainer>
RestrictionParser::TryParse(const osmium::Relation &relation) const
{
std::vector<InputRestrictionContainer> parsed_restrictions;
// return if turn restrictions should be ignored
if (!use_turn_restrictions)
{
@@ -65,10 +68,21 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
osmium::tags::KeyFilter filter(false);
filter.add(true, "restriction");
if (parse_conditionals)
{
filter.add(true, "restriction:conditional");
for (const auto &namespaced : restrictions)
{
filter.add(true, "restriction:" + namespaced + ":conditional");
}
}
// Not only use restriction= but also e.g. restriction:motorcar=
// Include restriction:{mode}:conditional if flagged
for (const auto &namespaced : restrictions)
{
filter.add(true, "restriction:" + namespaced);
}
const osmium::TagList &tag_list = relation.tags();
@@ -160,7 +174,42 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
break;
}
}
return boost::make_optional(std::move(restriction_container));
// parse conditional tags
if (parse_conditionals)
{
osmium::tags::KeyFilter::iterator fi_begin(filter, tag_list.begin(), tag_list.end());
osmium::tags::KeyFilter::iterator fi_end(filter, tag_list.end(), tag_list.end());
for (; fi_begin != fi_end; ++fi_begin)
{
const std::string key(fi_begin->key());
const std::string value(fi_begin->value());
// Parse condition and add independent value/condition pairs
const auto &parsed = osrm::util::ParseConditionalRestrictions(value);
if (parsed.empty())
continue;
for (const auto &p : parsed)
{
std::vector<util::OpeningHours> hours = util::ParseOpeningHours(p.condition);
// found unrecognized condition, continue
if (hours.empty())
return {};
restriction_container.restriction.condition = std::move(hours);
}
}
}
// push back a copy of turn restriction
if (restriction_container.restriction.via.node != SPECIAL_NODEID &&
restriction_container.restriction.from.node != SPECIAL_NODEID &&
restriction_container.restriction.to.node != SPECIAL_NODEID)
parsed_restrictions.push_back(restriction_container);
return parsed_restrictions;
}
bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const
+8 -2
View File
@@ -498,6 +498,7 @@ void Sol2ScriptingEnvironment::ProcessElements(
[&](const tbb::blocked_range<std::size_t> &range) {
ExtractionNode result_node;
ExtractionWay result_way;
std::vector<InputRestrictionContainer> result_res;
auto &local_context = this->GetSol2Context();
for (auto x = range.begin(), end = range.end(); x != end; ++x)
@@ -525,8 +526,13 @@ void Sol2ScriptingEnvironment::ProcessElements(
resulting_ways.push_back(std::make_pair(x, std::move(result_way)));
break;
case osmium::item_type::relation:
resulting_restrictions.push_back(restriction_parser.TryParse(
static_cast<const osmium::Relation &>(*entity)));
result_res.clear();
result_res =
restriction_parser.TryParse(static_cast<const osmium::Relation &>(*entity));
for (const InputRestrictionContainer &r : result_res)
{
resulting_restrictions.push_back(r);
}
break;
default:
break;