From 895f072425d7bbce6a58aadbf9c1e3c36c958f1c Mon Sep 17 00:00:00 2001 From: Denis Koronchik Date: Fri, 13 Oct 2017 19:05:04 +0300 Subject: [PATCH] Work on forward/backward ref's support --- features/car/route_relations.feature | 44 ++++----- include/extractor/extraction_way.hpp | 12 ++- include/extractor/extractor_callbacks.hpp | 3 +- profiles/car.lua | 30 +----- profiles/lib/relations.lua | 67 ++++++++++++- src/extractor/extractor_callbacks.cpp | 104 +++++++++++--------- src/extractor/scripting_environment_lua.cpp | 12 ++- 7 files changed, 162 insertions(+), 110 deletions(-) diff --git a/features/car/route_relations.feature b/features/car/route_relations.feature index d72ab7c64..3c27a495e 100644 --- a/features/car/route_relations.feature +++ b/features/car/route_relations.feature @@ -74,28 +74,28 @@ Feature: Car - route relations | c,d | eastbound,eastbound | I 80 $east; CO 93 $east,I 80 $east; CO 93 $east | -# Scenario: Forward/backward assignment on non-divided roads with role direction tag -# Given the node map -# """ -# a----------------b -# """ -# -# And the ways -# | nodes | name | highway | ref | oneway | -# | ab | mainroad | motorway | I 80 | no | -# -# And the relations -# | type | direction | way:forward | route | ref | network | -# | route | west | ab | road | 80 | US:I | -# -# And the relations -# | type | direction | way:backward | route | ref | network | -# | route | east | ab | road | 80 | US:I | -# -# When I route I should get -# | waypoints | route | ref | -# | b,a | mainroad,mainroad | I 80 $west,I 80 $west | -# | a,b | mainroad,mainroad | I 80 $east,I 80 $east | + Scenario: Forward/backward assignment on non-divided roads with role direction tag + Given the node map + """ + a----------------b + """ + + And the ways + | nodes | name | highway | ref | oneway | + | ab | mainroad | motorway | I 80 | no | + + And the relations + | type | direction | way:forward | route | ref | network | + | route | west | ab | road | 80 | US:I | + + And the relations + | type | direction | way:backward | route | ref | network | + | route | east | ab | road | 80 | US:I | + + When I route I should get + | waypoints | route | ref | + | a,b | mainroad,mainroad | I 80 $west,I 80 $west | + | b,a | mainroad,mainroad | I 80 $east,I 80 $east | Scenario: Conflict between role and direction diff --git a/include/extractor/extraction_way.hpp b/include/extractor/extraction_way.hpp index c03622c7d..9bdda5964 100644 --- a/include/extractor/extraction_way.hpp +++ b/include/extractor/extraction_way.hpp @@ -47,7 +47,8 @@ struct ExtractionWay duration = -1; weight = -1; name.clear(); - ref.clear(); + forward_ref.clear(); + backward_ref.clear(); pronunciation.clear(); destinations.clear(); exits.clear(); @@ -67,8 +68,10 @@ struct ExtractionWay // wrappers to allow assigning nil (nullptr) to string values void SetName(const char *value) { detail::maybeSetString(name, value); } const char *GetName() const { return name.c_str(); } - void SetRef(const char *value) { detail::maybeSetString(ref, value); } - const char *GetRef() const { return ref.c_str(); } + void SetForwardRef(const char *value) { detail::maybeSetString(forward_ref, value); } + const char *GetForwardRef() const { return forward_ref.c_str(); } + void SetBackwardRef(const char *value) { detail::maybeSetString(backward_ref, value); } + const char *GetBackwardRef() const { return backward_ref.c_str(); } void SetDestinations(const char *value) { detail::maybeSetString(destinations, value); } const char *GetDestinations() const { return destinations.c_str(); } void SetExits(const char *value) { detail::maybeSetString(exits, value); } @@ -101,7 +104,8 @@ struct ExtractionWay // weight of the whole way in both directions double weight; std::string name; - std::string ref; + std::string forward_ref; + std::string backward_ref; std::string pronunciation; std::string destinations; std::string exits; diff --git a/include/extractor/extractor_callbacks.hpp b/include/extractor/extractor_callbacks.hpp index 5819e4eff..fb4f599b1 100644 --- a/include/extractor/extractor_callbacks.hpp +++ b/include/extractor/extractor_callbacks.hpp @@ -63,7 +63,8 @@ class ExtractorCallbacks // actually maps to name ids using MapKey = std::tuple; using MapVal = unsigned; - std::unordered_map string_map; + using StringMap = std::unordered_map; + StringMap string_map; ExtractionContainers &external_memory; std::unordered_map &classes_map; guidance::LaneDescriptionMap &lane_description_map; diff --git a/profiles/car.lua b/profiles/car.lua index 261136742..57fbff161 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -402,35 +402,7 @@ function process_way(profile, way, result, relations) WayHandlers.run(profile, way, result, data, handlers, relations) - local parsed_rel_list = {} - local rel_id_list = relations:get_relations(way) - for i, rel_id in ipairs(rel_id_list) do - local rel = relations:relation(rel_id) - parsed_rel_list[i] = Relations.parse_route_relation(rel, way, relations) - end - - -- now process relations data - local matched_refs = nil; - if result.ref then - local match_res = Relations.match_to_ref(parsed_rel_list, result.ref) - - local ref = '' - for _, m in pairs(match_res) do - if ref ~= '' then - ref = ref .. '; ' - end - - if m.dir then - ref = ref .. m.ref .. ' $' .. m.dir - else - ref = ref .. m.ref - end - end - - -- print(result.name, ref) - - result.ref = ref - end + Relations.process_way_refs(way, relations, result) end function process_turn(profile, turn) diff --git a/profiles/lib/relations.lua b/profiles/lib/relations.lua index 86125eb43..d8c5b4531 100644 --- a/profiles/lib/relations.lua +++ b/profiles/lib/relations.lua @@ -41,7 +41,7 @@ function Relations.match_to_ref(relations, ref) local result_match = {} local order = {} for i, r in ipairs(references) do - result_match[r] = false + result_match[r] = { forward = nil, backward = nil } order[i] = r end @@ -81,7 +81,19 @@ function Relations.match_to_ref(relations, ref) find_best(ref_scores) if best_ref then - result_match[best_ref] = direction + local result_direction = result_match[best_ref] + + local is_forward = rel["route_forward"] + if is_forward == nil then + result_direction.forward = direction + result_direction.backward = direction + elseif is_forward == true then + result_direction.forward = direction + else + result_direction.backward = direction + end + + result_match[best_ref] = result_direction end end @@ -182,7 +194,6 @@ function Relations.parse_route_relation(rel, way, relations) local super_dir = get_direction_from_superrel(rel, relations) -- check if there are data error - if (result_direction ~= nil) and (super_dir ~= nil) and (result_direction ~= super_dir) then print('ERROR: conflicting relation directions found for way ' .. way:id() .. ' relation direction is ' .. result_direction .. ' superrelation direction is ' .. super_dir) @@ -192,11 +203,59 @@ function Relations.parse_route_relation(rel, way, relations) end result['route_direction'] = result_direction + + if role == 'forward' then + result['route_forward'] = true + elseif role == 'backward' then + result['route_forward'] = false + else + result['route_forward'] = nil + end + add_extra_data(m) end - return result end +function Relations.process_way_refs(way, relations, result) + local parsed_rel_list = {} + local rel_id_list = relations:get_relations(way) + for i, rel_id in ipairs(rel_id_list) do + local rel = relations:relation(rel_id) + parsed_rel_list[i] = Relations.parse_route_relation(rel, way, relations) + end + + -- now process relations data + local matched_refs = nil; + if result.ref then + local match_res = Relations.match_to_ref(parsed_rel_list, result.ref) + + function gen_ref(is_forward) + local ref = '' + for _, m in pairs(match_res) do + if ref ~= '' then + ref = ref .. '; ' + end + + local dir = m.dir.forward + if is_forward == false then + dir = m.dir.backward + end + + if dir then + ref = ref .. m.ref .. ' $' .. dir + else + ref = ref .. m.ref + end + end + + return ref + end + + result.forward_ref = gen_ref(true) + result.backward_ref = gen_ref(false) + end +end + return Relations \ No newline at end of file diff --git a/src/extractor/extractor_callbacks.cpp b/src/extractor/extractor_callbacks.cpp index 1527db8b7..aeb796afe 100644 --- a/src/extractor/extractor_callbacks.cpp +++ b/src/extractor/extractor_callbacks.cpp @@ -318,57 +318,64 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti road_classification.SetNumberOfLanes(std::max(road_deduced_num_lanes, // len(turn:lanes) road_classification.GetNumberOfLanes())); - // Get the unique identifier for the street name, destination, and ref - const auto name_iterator = string_map.find(MapKey(parsed_way.name, - parsed_way.destinations, - parsed_way.ref, - parsed_way.pronunciation, - parsed_way.exits)); - NameID name_id = EMPTY_NAMEID; - if (string_map.end() == name_iterator) - { - // name_offsets has a sentinel element with the total name data size - // take the sentinels index as the name id of the new name data pack - // (name [name_id], destination [+1], pronunciation [+2], ref [+3], exits [+4]) - name_id = external_memory.name_offsets.size() - 1; + const auto GetNameID = [this, &parsed_way](bool is_forward) -> NameID { + const std::string &ref = is_forward ? parsed_way.forward_ref : parsed_way.backward_ref; + // Get the unique identifier for the street name, destination, and ref + const auto name_iterator = string_map.find(MapKey(parsed_way.name, + parsed_way.destinations, + ref, + parsed_way.pronunciation, + parsed_way.exits)); - std::copy(parsed_way.name.begin(), - parsed_way.name.end(), - std::back_inserter(external_memory.name_char_data)); - external_memory.name_offsets.push_back(external_memory.name_char_data.size()); + NameID name_id = EMPTY_NAMEID; + if (string_map.end() == name_iterator) + { + // name_offsets has a sentinel element with the total name data size + // take the sentinels index as the name id of the new name data pack + // (name [name_id], destination [+1], pronunciation [+2], ref [+3], exits [+4]) + name_id = external_memory.name_offsets.size() - 1; - std::copy(parsed_way.destinations.begin(), - parsed_way.destinations.end(), - std::back_inserter(external_memory.name_char_data)); - external_memory.name_offsets.push_back(external_memory.name_char_data.size()); + std::copy(parsed_way.name.begin(), + parsed_way.name.end(), + std::back_inserter(external_memory.name_char_data)); + external_memory.name_offsets.push_back(external_memory.name_char_data.size()); - std::copy(parsed_way.pronunciation.begin(), - parsed_way.pronunciation.end(), - std::back_inserter(external_memory.name_char_data)); - external_memory.name_offsets.push_back(external_memory.name_char_data.size()); + std::copy(parsed_way.destinations.begin(), + parsed_way.destinations.end(), + std::back_inserter(external_memory.name_char_data)); + external_memory.name_offsets.push_back(external_memory.name_char_data.size()); - std::copy(parsed_way.ref.begin(), - parsed_way.ref.end(), - std::back_inserter(external_memory.name_char_data)); - external_memory.name_offsets.push_back(external_memory.name_char_data.size()); + std::copy(parsed_way.pronunciation.begin(), + parsed_way.pronunciation.end(), + std::back_inserter(external_memory.name_char_data)); + external_memory.name_offsets.push_back(external_memory.name_char_data.size()); - std::copy(parsed_way.exits.begin(), - parsed_way.exits.end(), - std::back_inserter(external_memory.name_char_data)); - external_memory.name_offsets.push_back(external_memory.name_char_data.size()); + std::copy(ref.begin(), ref.end(), std::back_inserter(external_memory.name_char_data)); + external_memory.name_offsets.push_back(external_memory.name_char_data.size()); - auto k = MapKey{parsed_way.name, - parsed_way.destinations, - parsed_way.ref, - parsed_way.pronunciation, - parsed_way.exits}; - auto v = MapVal{name_id}; - string_map.emplace(std::move(k), std::move(v)); - } - else - { - name_id = name_iterator->second; - } + std::copy(parsed_way.exits.begin(), + parsed_way.exits.end(), + std::back_inserter(external_memory.name_char_data)); + external_memory.name_offsets.push_back(external_memory.name_char_data.size()); + + auto k = MapKey{parsed_way.name, + parsed_way.destinations, + ref, + parsed_way.pronunciation, + parsed_way.exits}; + auto v = MapVal{name_id}; + string_map.emplace(std::move(k), std::move(v)); + } + else + { + name_id = name_iterator->second; + } + + return name_id; + }; + + const NameID forward_name_id = GetNameID(true); + const NameID backward_name_id = GetNameID(false); const bool in_forward_direction = (parsed_way.forward_speed > 0 || parsed_way.forward_rate > 0 || parsed_way.duration > 0 || @@ -386,12 +393,13 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti (force_split_edges || (parsed_way.forward_rate != parsed_way.backward_rate) || (parsed_way.forward_speed != parsed_way.backward_speed) || (parsed_way.forward_travel_mode != parsed_way.backward_travel_mode) || - (turn_lane_id_forward != turn_lane_id_backward) || (forward_classes != backward_classes)); + (turn_lane_id_forward != turn_lane_id_backward) || (forward_classes != backward_classes) || + (parsed_way.forward_ref != parsed_way.backward_ref)); if (in_forward_direction) { // add (forward) segments or (forward,backward) for non-split edges in backward direction const auto annotation_data_id = external_memory.all_edges_annotation_data_list.size(); - external_memory.all_edges_annotation_data_list.push_back({name_id, + external_memory.all_edges_annotation_data_list.push_back({forward_name_id, turn_lane_id_forward, forward_classes, parsed_way.forward_travel_mode, @@ -424,7 +432,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti if (in_backward_direction && (!in_forward_direction || split_edge)) { // add (backward) segments for split edges or not in forward direction const auto annotation_data_id = external_memory.all_edges_annotation_data_list.size(); - external_memory.all_edges_annotation_data_list.push_back({name_id, + external_memory.all_edges_annotation_data_list.push_back({backward_name_id, turn_lane_id_backward, backward_classes, parsed_way.backward_travel_mode, diff --git a/src/extractor/scripting_environment_lua.cpp b/src/extractor/scripting_environment_lua.cpp index fa0041d1d..444b272cb 100644 --- a/src/extractor/scripting_environment_lua.cpp +++ b/src/extractor/scripting_environment_lua.cpp @@ -369,8 +369,16 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context) &ExtractionWay::backward_rate, "name", sol::property(&ExtractionWay::GetName, &ExtractionWay::SetName), - "ref", - sol::property(&ExtractionWay::GetRef, &ExtractionWay::SetRef), + "ref", // backward compatibility + sol::property(&ExtractionWay::GetForwardRef, + [](ExtractionWay &way, const char *ref) { + way.SetForwardRef(ref); + way.SetBackwardRef(ref); + }), + "forward_ref", + sol::property(&ExtractionWay::GetForwardRef, &ExtractionWay::SetForwardRef), + "backward_ref", + sol::property(&ExtractionWay::GetBackwardRef, &ExtractionWay::SetBackwardRef), "pronunciation", sol::property(&ExtractionWay::GetPronunciation, &ExtractionWay::SetPronunciation), "destinations",