diff --git a/data_structures/restriction.hpp b/data_structures/restriction.hpp index ecab4f92197..f2e3cff2c8f 100644 --- a/data_structures/restriction.hpp +++ b/data_structures/restriction.hpp @@ -46,14 +46,14 @@ struct TurnRestriction struct Bits { // mostly unused Bits() - : is_only(false), uses_via_way(false), unused2(false), unused3(false), unused4(false), + : is_only(false), uses_via_way(false), ignore_write(false), unused3(false), unused4(false), unused5(false), unused6(false), unused7(false) { } bool is_only : 1; bool uses_via_way : 1; - bool unused2 : 1; + bool ignore_write : 1; bool unused3 : 1; bool unused4 : 1; bool unused5 : 1; @@ -79,7 +79,7 @@ struct TurnRestriction /** * This is just a wrapper around TurnRestriction used in the extractor. - * + * * Could be merged with TurnRestriction. For now the type-destiction makes sense * as the format in which the restriction is presented in the extractor and in the * preprocessing is different. (see restriction_parser.cpp) @@ -98,6 +98,7 @@ struct InputRestrictionContainer { restriction.from.way = SPECIAL_EDGEID; restriction.to.way = SPECIAL_EDGEID; + restriction.via.way = SPECIAL_EDGEID; restriction.via.node = SPECIAL_NODEID; restriction.flags.is_only = is_only; } @@ -131,4 +132,15 @@ struct CmpRestrictionContainerByTo value_type min_value() const { return InputRestrictionContainer::min_value(); } }; +struct CmpRestrictionContainerByVia +{ + using value_type = InputRestrictionContainer; + bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const + { + return a.restriction.via.way < b.restriction.via.way; + } + value_type max_value() const { return InputRestrictionContainer::max_value(); } + value_type min_value() const { return InputRestrictionContainer::min_value(); } +}; + #endif // RESTRICTION_HPP diff --git a/data_structures/restriction_map.cpp b/data_structures/restriction_map.cpp index eb685be80f0..de22f0010d4 100644 --- a/data_structures/restriction_map.cpp +++ b/data_structures/restriction_map.cpp @@ -29,51 +29,117 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. RestrictionMap::RestrictionMap(const std::vector &restriction_list) : m_count(0) { + RestrictionTarget via_way_target; + std::size_t via_way_index; + // 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) { - // 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(restriction.from.node < std::numeric_limits::max()); - BOOST_ASSERT(restriction.via.node < std::numeric_limits::max()); - m_restriction_start_nodes.insert(restriction.from.node); - m_no_turn_via_node_set.insert(restriction.via.node); - - // This explicit downcasting is also OK for the same reason. - RestrictionSource restriction_source = {static_cast(restriction.from.node), static_cast(restriction.via.node)}; - - std::size_t index; - auto restriction_iter = m_restriction_map.find(restriction_source); - if (restriction_iter == m_restriction_map.end()) + if (!restriction.flags.uses_via_way) { - index = m_restriction_bucket_list.size(); - m_restriction_bucket_list.resize(index + 1); - m_restriction_map.emplace(restriction_source, index); + // 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(restriction.from.node < std::numeric_limits::max()); + BOOST_ASSERT(restriction.via.node < std::numeric_limits::max()); + m_restriction_start_nodes.insert(restriction.from.node); + m_no_turn_via_node_set.insert(restriction.via.node); + + // This explicit downcasting is also OK for the same reason. + RestrictionSource restriction_source = {static_cast(restriction.from.node), static_cast(restriction.via.node)}; + + 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.flags.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; + BOOST_ASSERT(restriction.to.node < std::numeric_limits::max()); + m_restriction_bucket_list.at(index) + .emplace_back(restriction.to.node, restriction.flags.is_only); } else { - index = restriction_iter->second; - // Map already contains an is_only_*-restriction - if (m_restriction_bucket_list.at(index).begin()->is_only) + // We are parsing the restrictions from the file in order, so we keep track of + // one restriction (and its nodes) at a time (i.e. via_way_target) + if (IsFromWay(restriction)) + { + BOOST_ASSERT(via_way_target.via_nodes.size() == 0 && via_way_target.target_node == SPECIAL_NODEID); + + m_restriction_start_nodes.insert(restriction.from.node); + m_no_turn_via_node_set.insert(restriction.via.node); + + RestrictionSource restriction_source = {static_cast(restriction.from.node), static_cast(restriction.via.node)}; + + auto restriction_iter = m_restriction_map.find(restriction_source); + if (restriction_iter == m_restriction_map.end()) + { + via_way_index = m_restriction_bucket_list.size(); + m_restriction_bucket_list.resize(via_way_index + 1); + m_restriction_map.emplace(restriction_source, via_way_index); + } + } + else if (IsViaWay(restriction)) { - continue; + m_no_turn_via_node_set.insert(restriction.via.node); + via_way_target.via_nodes.push_back(restriction.via.node); } - else if (restriction.flags.is_only) + else if (IsToWay(restriction)) { - // 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(); + BOOST_ASSERT(via_way_targets.via_nodes.size() >= 1); + m_no_turn_via_node_set.insert(restriction.via.node); + m_no_turn_via_node_set.insert(restriction.to.node); + + via_way_target.via_nodes.push_back(restriction.via.node); + via_way_target.via_nodes.push_back(restriction.to.node); + m_restriction_bucket_list.at(via_way_index).push_back(via_way_target); + ++m_count; + via_way_target.reset(); } } - ++m_count; - BOOST_ASSERT(restriction.to.node < std::numeric_limits::max()); - m_restriction_bucket_list.at(index) - .emplace_back(restriction.to.node, restriction.flags.is_only); } } +bool RestrictionMap::IsFromWay(const TurnRestriction &restriction) const +{ + return restriction.from.node != SPECIAL_NODEID && + restriction.via.node != SPECIAL_NODEID && + restriction.to.node == SPECIAL_NODEID; +} + +bool RestrictionMap::IsViaWay(const TurnRestriction &restriction) const +{ + return restriction.from.node == SPECIAL_NODEID && + restriction.via.node != SPECIAL_NODEID && + restriction.to.node == SPECIAL_NODEID; +} + +bool RestrictionMap::IsToWay(const TurnRestriction &restriction) const +{ + return restriction.from.node == SPECIAL_NODEID && + restriction.via.node != SPECIAL_NODEID && + restriction.to.node != SPECIAL_NODEID; +} + bool RestrictionMap::IsViaNode(const NodeID node) const { return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end(); @@ -134,6 +200,37 @@ NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const No return SPECIAL_NODEID; } +// Checks if a turn restriction is a via way restriction and returns the nodes associated with +// each of the restriction. +std::vector> RestrictionMap::CheckForViaWayRestrictions(const NodeID node_u, + const NodeID node_v) const +{ + BOOST_ASSERT(node_u != SPECIAL_NODEID); + BOOST_ASSERT(node_v != SPECIAL_NODEID); + + std::vector> via_way_nodes_list; + + if (!IsSourceNode(node_u)) + { + return via_way_nodes_list; + } + + 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.via_nodes.size()) + { + via_way_nodes_list.push_back(restriction_target.via_nodes); + } + } + } + return via_way_nodes_list; +} + // Checks if turn is actually a turn restriction. bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, diff --git a/data_structures/restriction_map.hpp b/data_structures/restriction_map.hpp index dbca35651ff..7dc596d9942 100644 --- a/data_structures/restriction_map.hpp +++ b/data_structures/restriction_map.hpp @@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include struct RestrictionSource @@ -56,12 +57,30 @@ struct RestrictionTarget { NodeID target_node; bool is_only; + // If restriction is a via_way, via_nodes will be populated with nodes from restriction + std::vector via_nodes; explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only) {} + explicit RestrictionTarget() : target_node(SPECIAL_NODEID), is_only(false) {} + + void reset() + { + target_node = SPECIAL_NODEID; + is_only = false; + via_nodes.clear(); + } + friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs) { - return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only); + return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only) && + (lhs.via_nodes.size() == rhs.via_nodes.size()) && + (std::equal( + lhs.via_nodes.begin(), + lhs.via_nodes.begin() + lhs.via_nodes.size(), + rhs.via_nodes.begin() + ) + ); } }; @@ -135,15 +154,23 @@ class RestrictionMap for (RestrictionTarget &restriction_target : bucket) { + unsigned via_ways_length = restriction_target.via_ways.size(); if (node_v == restriction_target.target_node) { restriction_target.target_node = node_w; } + else if (via_ways_length && node_v == restriction_target.via_ways[via_ways_length - 1]) + { + restriction_target.via_ways[via_ways_length - 1] = node_w; + } } } } bool IsViaNode(const NodeID node) const; + bool IsFromWay(const TurnRestriction &restriction) const; + bool IsViaWay(const TurnRestriction &restriction) const; + bool IsToWay(const TurnRestriction &restriction) const; // Replaces start edge (v, w) with (u, w). Only start node changes. void @@ -156,6 +183,11 @@ class RestrictionMap bool CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const; + // Checks if a turn restriction is a via way restriction and returns the nodes associated with + // the restriction. + std::vector> + CheckForViaWayRestrictions(const NodeID node_u, const NodeID node_v) const; + std::size_t size() const { return m_count; } private: diff --git a/extractor/extraction_containers.cpp b/extractor/extraction_containers.cpp index 48a626b1c5a..766be69a968 100644 --- a/extractor/extraction_containers.cpp +++ b/extractor/extraction_containers.cpp @@ -103,6 +103,7 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, file_out_stream.close(); PrepareRestrictions(); + PrepareViaWayRestrictions(); WriteRestrictions(restrictions_file_name); WriteNames(name_file_name); @@ -570,6 +571,7 @@ void ExtractionContainers::WriteNodes(std::ofstream& file_out_stream) const void ExtractionContainers::WriteRestrictions(const std::string& path) const { + // serialize restrictions std::ofstream restrictions_out_stream; unsigned written_restriction_count = 0; @@ -581,9 +583,11 @@ void ExtractionContainers::WriteRestrictions(const std::string& path) const for (const auto &restriction_container : restrictions_list) { - if (SPECIAL_NODEID != restriction_container.restriction.from.node && + if (((SPECIAL_NODEID != restriction_container.restriction.from.node && SPECIAL_NODEID != restriction_container.restriction.via.node && - SPECIAL_NODEID != restriction_container.restriction.to.node) + SPECIAL_NODEID != restriction_container.restriction.to.node) || + restriction_container.restriction.flags.uses_via_way) && + !restriction_container.restriction.flags.ignore_write) { restrictions_out_stream.write((char *)&(restriction_container.restriction), sizeof(TurnRestriction)); @@ -596,6 +600,22 @@ void ExtractionContainers::WriteRestrictions(const std::string& path) const SimpleLogger().Write() << "usable restrictions: " << written_restriction_count; } +// Finds node ID that connects the end points of two ways. If no node connects the ends of the ways, this returns +// the SPECIAL_NODEID +NodeID ExtractionContainers::findConnectingNodeID(const std::vector &way_edges1, const std::vector &way_edges2) { + if ((way_edges1.front().result.source == way_edges2.front().result.source) || + (way_edges1.front().result.source == way_edges2.back().result.target)) + { + return way_edges1.front().result.source; + } + else if ((way_edges1.back().result.target == way_edges2.back().result.target) || + (way_edges1.back().result.target == way_edges2.front().result.source)) + { + return way_edges1.back().result.target; + } + return SPECIAL_NODEID; +} + void ExtractionContainers::PrepareRestrictions() { std::cout << "[extractor] Sorting used ways ... " << std::flush; @@ -623,6 +643,12 @@ void ExtractionContainers::PrepareRestrictions() while (way_start_and_end_iterator != way_start_end_id_list_end && restrictions_iterator != restrictions_list_end) { + // Skip via-way restrictions (we'll deal with these later) + if (restrictions_iterator->restriction.flags.uses_via_way) { + ++restrictions_iterator++; + continue; + } + if (way_start_and_end_iterator->way_id < OSMWayID(restrictions_iterator->restriction.from.way)) { ++way_start_and_end_iterator; @@ -691,6 +717,12 @@ void ExtractionContainers::PrepareRestrictions() while (way_start_and_end_iterator != way_start_end_id_list_end_ && restrictions_iterator != restrictions_list_end_) { + // Skip via-way restrictions (we'll deal with these later) + if (restrictions_iterator->restriction.flags.uses_via_way) { + ++restrictions_iterator; + continue; + } + if (way_start_and_end_iterator->way_id < OSMWayID(restrictions_iterator->restriction.to.way)) { ++way_start_and_end_iterator; @@ -737,3 +769,126 @@ void ExtractionContainers::PrepareRestrictions() TIMER_STOP(fix_restriction_ends); std::cout << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s" << std::endl; } + +/** +* Prepares via-way restrictions by unfolds them into multiple lines each (one for each node in the via way and +* two total for the from-way and to-way). +* For example, a via-way restriction a->b->c with nodes: +* a: [0,1,2], b:[2,3,4], c:[4,5,6] will be split into 3 restrictions (in order): +* +* Restriction# | from (node) | to (node) | via (node) +* -------------|------------------------|-----------------------|--------------------- +* 0 | 1 | SPECIAL_NODE_ID | 2 +* 1 | SPECIAL_NODE_ID | 3 | SPECIAL_NODE_ID +* 2 | SPECIAL_NODE_ID | 5 | 4 +* +*/ +void ExtractionContainers::PrepareViaWayRestrictions() +{ + std::cout << "[extractor] Sorting restrictions. by via way ... " << std::flush; + TIMER_START(sort_restrictions_via); + stxxl::sort(restrictions_list.begin(), restrictions_list.end(), + CmpRestrictionContainerByVia(), stxxl_memory); + TIMER_STOP(sort_restrictions_via); + std::cout << "ok, after " << TIMER_SEC(sort_restrictions_via) << "s" << std::endl; + + std::cout << "[extractor] Unfolding via-way restrictions ... " << std::flush; + TIMER_START(unfold_via_ways); + int unfolded_restrictions_count = 0; + auto restrictions_iterator = restrictions_list.begin(); + + while (restrictions_iterator != restrictions_list.end()) + { + if (!restrictions_iterator->restriction.flags.uses_via_way) { + ++restrictions_iterator; + continue; + } + + const std::vector from_edges = way_to_edges_map[OSMWayID(restrictions_iterator->restriction.from.way)]; + const std::vector via_edges = way_to_edges_map[OSMWayID(restrictions_iterator->restriction.via.way)]; + const std::vector to_edges = way_to_edges_map[OSMWayID(restrictions_iterator->restriction.to.way)]; + + if (from_edges.size() == 0 || via_edges.size() == 0 || to_edges.size() == 0) { + SimpleLogger().Write(LogLevel::logDEBUG) << "Invalid via-way restriction: " << restrictions_iterator->restriction.via.way; + ++restrictions_iterator; + continue; + } + + NodeID from_via_node_id = findConnectingNodeID(from_edges, via_edges); + NodeID via_to_node_id = findConnectingNodeID(via_edges, to_edges); + + if (from_via_node_id == SPECIAL_NODEID || via_to_node_id == SPECIAL_NODEID) + { + SimpleLogger().Write(LogLevel::logDEBUG) << "Invalid via-way restriction: " << restrictions_iterator->restriction.via.way; + ++restrictions_iterator; + continue; + } + + // Ensure the connecting nodes connect all the ways correctly + BOOST_ASSERT(from_edges.front().result.source == from_via_node_id || from_edges.back().result.target == from_via_node_id); + BOOST_ASSERT(via_edges.front().result.source == from_via_node_id || via_edges.back().result.target == from_via_node_id); + BOOST_ASSERT(via_edges.front().result.source == via_to_node_id || via_edges.back().result.target == via_to_node_id); + BOOST_ASSERT(to_edges.front().result.source == via_to_node_id || to_edges.back().result.target == via_to_node_id); + + InputRestrictionContainer from_restriction; + InputRestrictionContainer to_restriction; + from_restriction.restriction.flags.uses_via_way = true; + to_restriction.restriction.flags.uses_via_way = true; + + if (from_edges.front().result.source == from_via_node_id) { + from_restriction.restriction.from.node = from_edges.front().result.target; + from_restriction.restriction.via.node = from_via_node_id; + } + else { + from_restriction.restriction.from.node = from_edges.back().result.source; + from_restriction.restriction.via.node = from_via_node_id; + } + + if (to_edges.front().result.source == via_to_node_id) { + to_restriction.restriction.via.node = via_to_node_id; + to_restriction.restriction.to.node = to_edges.front().result.target; + } + else { + to_restriction.restriction.via.node = via_to_node_id; + to_restriction.restriction.to.node = to_edges.back().result.source; + } + + // Write the unfolded restriction to the restrictions_list + restrictions_list.push_back(from_restriction); + + // Traverse forwards + if (via_edges.front().result.source == from_via_node_id) { + for (auto edge_iterator = via_edges.begin(); edge_iterator != via_edges.end(); ++edge_iterator) { + if (edge_iterator->result.target == via_to_node_id) { + break; + } + InputRestrictionContainer via_restriction; + via_restriction.restriction.flags.uses_via_way = true; + via_restriction.restriction.via.node = edge_iterator->result.target; + restrictions_list.push_back(via_restriction); + } + } + // Traverse backwards + else { + for (auto edge_iterator = via_edges.end()-1; edge_iterator >= via_edges.begin(); --edge_iterator) { + if (edge_iterator->result.target == from_via_node_id) { + break; + } + InputRestrictionContainer via_restriction; + via_restriction.restriction.flags.uses_via_way = true; + via_restriction.restriction.via.node = edge_iterator->result.target; + restrictions_list.push_back(via_restriction); + } + } + + restrictions_list.push_back(to_restriction); + ++unfolded_restrictions_count; + + ++restrictions_iterator; + } + + TIMER_STOP(unfold_via_ways); + SimpleLogger().Write() << "ok, after " << TIMER_SEC(unfold_via_ways) << "s"; + + SimpleLogger().Write() << "Number of unfolded restrictions: " << unfolded_restrictions_count; +} \ No newline at end of file diff --git a/extractor/extraction_containers.hpp b/extractor/extraction_containers.hpp index 541ad35376e..051b7310e37 100644 --- a/extractor/extraction_containers.hpp +++ b/extractor/extraction_containers.hpp @@ -28,14 +28,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef EXTRACTION_CONTAINERS_HPP #define EXTRACTION_CONTAINERS_HPP -#include "internal_extractor_edge.hpp" #include "first_and_last_segment_of_way.hpp" #include "scripting_environment.hpp" +#include "internal_extractor_edge.hpp" + #include "../data_structures/external_memory_node.hpp" #include "../data_structures/restriction.hpp" #include #include +#include /** * Uses external memory containers from stxxl to store all the data that @@ -54,12 +56,16 @@ class ExtractionContainers #endif void PrepareNodes(); void PrepareRestrictions(); + void PrepareViaWayRestrictions(); void PrepareEdges(lua_State *segment_state); void WriteNodes(std::ofstream& file_out_stream) const; void WriteRestrictions(const std::string& restrictions_file_name) const; void WriteEdges(std::ofstream& file_out_stream) const; void WriteNames(const std::string& names_file_name) const; + + NodeID findConnectingNodeID(const std::vector &way_edges1, const std::vector &way_edges2); + public: using STXXLNodeIDVector = stxxl::vector; using STXXLNodeVector = stxxl::vector; @@ -73,8 +79,10 @@ class ExtractionContainers stxxl::vector name_char_data; stxxl::vector name_lengths; STXXLRestrictionsVector restrictions_list; + std::vector unfolded_restrictions_list; STXXLWayIDStartEndVector way_start_end_id_list; std::unordered_map external_to_internal_node_id_map; + std::unordered_map> way_to_edges_map; unsigned max_internal_node_id; ExtractionContainers(); diff --git a/extractor/extractor_callbacks.cpp b/extractor/extractor_callbacks.cpp index 2eb1a9b467c..8e0b8e36a5f 100644 --- a/extractor/extractor_callbacks.cpp +++ b/extractor/extractor_callbacks.cpp @@ -85,6 +85,8 @@ void ExtractorCallbacks::ProcessRestriction( * Takes the geometry contained in the ```input_way``` and the tags computed * by the lua profile inside ```parsed_way``` and computes all edge segments. * + * Updates the extraction container's datastructure: way_to_edges_map + * * Depending on the forward/backwards weights the edges are split into forward * and backward edges. * @@ -194,7 +196,17 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti OSMNodeID(first_node.ref()), OSMNodeID(last_node.ref()), name_id, backward_weight_data, true, false, parsed_way.roundabout, parsed_way.is_access_restricted, parsed_way.is_startpoint, - parsed_way.backward_travel_mode, false)); + parsed_way.backward_travel_mode, false + )); + + InternalExtractorEdge new_edge( + OSMNodeID(first_node.ref()), OSMNodeID(last_node.ref()), name_id, + backward_weight_data, true, false, parsed_way.roundabout, + parsed_way.is_access_restricted, parsed_way.is_startpoint, + parsed_way.backward_travel_mode, false); + new_edge.result.source = first_node.ref(); + new_edge.result.target = last_node.ref(); + external_memory.way_to_edges_map[OSMWayID(input_way.id())].push_back(new_edge); }); external_memory.way_start_end_id_list.push_back( @@ -216,10 +228,20 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti true, !forward_only, parsed_way.roundabout, parsed_way.is_access_restricted, parsed_way.is_startpoint, parsed_way.forward_travel_mode, split_edge)); + + InternalExtractorEdge new_edge( + OSMNodeID(first_node.ref()), OSMNodeID(last_node.ref()), name_id, forward_weight_data, + true, !forward_only, parsed_way.roundabout, + parsed_way.is_access_restricted, parsed_way.is_startpoint, parsed_way.forward_travel_mode, + split_edge); + new_edge.result.source = first_node.ref(); + new_edge.result.target = last_node.ref(); + external_memory.way_to_edges_map[OSMWayID(input_way.id())].push_back(new_edge); }); if (split_edge) { BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE); + osrm::for_each_pair( input_way.nodes().cbegin(), input_way.nodes().cend(), [&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) @@ -228,6 +250,15 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti OSMNodeID(first_node.ref()), OSMNodeID(last_node.ref()), name_id, backward_weight_data, false, true, parsed_way.roundabout, parsed_way.is_access_restricted, parsed_way.is_startpoint, parsed_way.backward_travel_mode, true)); + + InternalExtractorEdge new_edge( + OSMNodeID(first_node.ref()), OSMNodeID(last_node.ref()), name_id, backward_weight_data, false, + true, parsed_way.roundabout, parsed_way.is_access_restricted, + parsed_way.is_startpoint, parsed_way.backward_travel_mode, true); + + new_edge.result.source = first_node.ref(); + new_edge.result.target = last_node.ref(); + external_memory.way_to_edges_map[OSMWayID(input_way.id())].push_back(new_edge); }); } diff --git a/extractor/restriction_parser.cpp b/extractor/restriction_parser.cpp index afb194738fa..a6a3ccc8567 100644 --- a/extractor/restriction_parser.cpp +++ b/extractor/restriction_parser.cpp @@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../util/lua_util.hpp" #include "../util/osrm_exception.hpp" #include "../util/simple_logger.hpp" +#include "../typedefs.h" #include #include @@ -207,11 +208,18 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const { restriction_container.restriction.to.way = member.ref(); } - // else if (0 == strcmp("via", role)) - // { - // not yet suppported - // restriction_container.restriction.via.way = member.ref(); - // } + // For now we'll only deal with 3-member via-way turn restrictions. + else if (0 == strcmp("via", role)) + { + if (restriction_container.restriction.via.way == SPECIAL_EDGEID) { + restriction_container.restriction.flags.uses_via_way = true; + restriction_container.restriction.flags.ignore_write = true; + restriction_container.restriction.via.way = member.ref(); + } + else { + return boost::optional(); + } + } break; case osmium::item_type::relation: // not yet supported, but who knows what the future holds...