From d195eee7c47543564769dbd2bc0f4b8f2a207750 Mon Sep 17 00:00:00 2001 From: "Daniel J. Hofmann" Date: Mon, 25 Jul 2016 11:43:35 +0200 Subject: [PATCH] Lane Handling for multiple indications per lane as in left;left|, fixes #2694 Before we asserted on unique lane indications per lane. Turns out the OSM data contains lane strings such as: left;left|right Which represents two lanes as in: << > || | The two left indications _on a single lane_ look like data issue. And we can't represent this with our enum-approach at the moment. We don't want to crash there, so silently swallow this and generate a single left|right for it. --- features/guidance/turn-lanes.feature | 14 ++++++++ src/extractor/extractor_callbacks.cpp | 50 ++++++++++++++++----------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/features/guidance/turn-lanes.feature b/features/guidance/turn-lanes.feature index 0a8e0e705..189a7fe08 100644 --- a/features/guidance/turn-lanes.feature +++ b/features/guidance/turn-lanes.feature @@ -736,4 +736,18 @@ Feature: Turn Lane Guidance | x,d | road,road | depart,arrive | , | + Scenario: Lane Parsing Issue #2694 + Given the node map + | | c | + | a | b | + | | d | + And the ways + | nodes | highway | turn:lanes:forward | + | ab | primary | left;left\|right | + | bc | primary | | + | bd | primary | | + + When I route I should get + | waypoints | route | turns | lanes | + | a,c | ab,bc,bc | depart,turn left,arrive | ,left:true right:false, | diff --git a/src/extractor/extractor_callbacks.cpp b/src/extractor/extractor_callbacks.cpp index 4287255be..7d98804e8 100644 --- a/src/extractor/extractor_callbacks.cpp +++ b/src/extractor/extractor_callbacks.cpp @@ -193,7 +193,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti for (auto token_itr = inner_tokens.begin(); token_itr != inner_tokens.end(); ++token_itr) { - auto position = std::find(osm_lane_strings, osm_lane_strings + num_osm_tags, *token_itr); + auto position = + std::find(osm_lane_strings, osm_lane_strings + num_osm_tags, *token_itr); const auto translated_mask = masks_by_osm_string[std::distance(osm_lane_strings, position)]; if (translated_mask == TurnLaneType::empty) @@ -203,7 +204,10 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti << *token_itr << "\""; return {}; } - BOOST_ASSERT((lane_mask & translated_mask) == 0); // make sure the mask is valid + + // In case of multiple times the same lane indicators withn a lane, as in + // "left;left|.." or-ing the masks generates a single "left" enum. + // Which is fine since this is data issue and we can't represent it anyway. lane_mask |= translated_mask; } // add the lane to the description @@ -265,8 +269,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti // name_offsets already has an offset of a new name, take the offset index as the name id name_id = external_memory.name_offsets.size() - 1; - external_memory.name_char_data.reserve(external_memory.name_char_data.size() + name_length - + destinations_length + pronunciation_length); + external_memory.name_char_data.reserve(external_memory.name_char_data.size() + name_length + + destinations_length + pronunciation_length); std::copy(parsed_way.name.c_str(), parsed_way.name.c_str() + name_length, @@ -306,7 +310,9 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti std::transform(input_way.nodes().begin(), input_way.nodes().end(), std::back_inserter(external_memory.used_node_id_list), - [](const osmium::NodeRef &ref) { return OSMNodeID{static_cast(ref.ref())}; }); + [](const osmium::NodeRef &ref) { + return OSMNodeID{static_cast(ref.ref())}; + }); const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode; @@ -338,7 +344,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti external_memory.way_start_end_id_list.push_back( {OSMWayID{static_cast(input_way.id())}, OSMNodeID{static_cast(input_way.nodes().back().ref())}, - OSMNodeID{static_cast(input_way.nodes()[input_way.nodes().size() - 2].ref())}, + OSMNodeID{ + static_cast(input_way.nodes()[input_way.nodes().size() - 2].ref())}, OSMNodeID{static_cast(input_way.nodes()[1].ref())}, OSMNodeID{static_cast(input_way.nodes()[0].ref())}}); } @@ -372,27 +379,28 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti input_way.nodes().cbegin(), input_way.nodes().cend(), [&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) { - external_memory.all_edges_list.push_back( - InternalExtractorEdge(OSMNodeID{static_cast(first_node.ref())}, - OSMNodeID{static_cast(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, - turn_lane_id_backward, - road_classification)); + external_memory.all_edges_list.push_back(InternalExtractorEdge( + OSMNodeID{static_cast(first_node.ref())}, + OSMNodeID{static_cast(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, + turn_lane_id_backward, + road_classification)); }); } external_memory.way_start_end_id_list.push_back( {OSMWayID{static_cast(input_way.id())}, OSMNodeID{static_cast(input_way.nodes().back().ref())}, - OSMNodeID{static_cast(input_way.nodes()[input_way.nodes().size() - 2].ref())}, + OSMNodeID{ + static_cast(input_way.nodes()[input_way.nodes().size() - 2].ref())}, OSMNodeID{static_cast(input_way.nodes()[1].ref())}, OSMNodeID{static_cast(input_way.nodes()[0].ref())}}); }