diff --git a/CHANGELOG.md b/CHANGELOG.md index 92685ab9c..15aa5babc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,15 @@ - BREAKING: modifies the file format with new internal identifiers - API: - - paramater `annotate` was renamed to `annotations`. - - `annotation` as accidentally placed in `Route` instead of `RouteLeg` + - paramater `annotate` was renamed to `annotations`. + - `annotation` as accidentally placed in `Route` instead of `RouteLeg` + - Support for destination signs. New member `destinations` in `RouteStep`, based on `destination` and `destination:ref`. + + - Profile changes: + - `result.destinations` allows you to set a way's destinations - Infrastructure - - BREAKING: Changed the on-disk encoding of the StaticRTree to reduce ramIndex file size. This breaks the **data format** + - BREAKING: Changed the on-disk encoding of the StaticRTree to reduce ramIndex file size. This breaks the **data format** - Bugfixes - fixed broken summaries for very short routes diff --git a/docs/http.md b/docs/http.md index 6c7428e1f..b2605b3ac 100644 --- a/docs/http.md +++ b/docs/http.md @@ -437,6 +437,7 @@ step. - `name`: The name of the way along which travel proceeds. - `pronunciation`: The pronunciation hint of the way name. Will be `undefined` if there is no pronunciation hit. +- `destinations`: The destinations of the way. Will be `undefined` if there are no destinations. - `mode`: A string signifying the mode of transportation. - `maneuver`: A `StepManeuver` object representing the maneuver. - `intersections`: A list of `Intersections` that are passed along the segment, the very first belonging to the StepManeuver diff --git a/features/guidance/destination-signs.feature b/features/guidance/destination-signs.feature index e2bbaeaae..3c5aa4e69 100644 --- a/features/guidance/destination-signs.feature +++ b/features/guidance/destination-signs.feature @@ -29,13 +29,13 @@ Feature: Destination Signs | qr | QR | | | A1;A2 | yes | | When I route I should get - | from | to | route | # | - | a | b | AB (E1),AB (E1) | | - | c | d | CD (Berlin),CD (Berlin) | | - | e | f | EF (A1: Berlin),EF (A1: Berlin) | | - | g | h | , | | - | i | j | , | | - | k | l | KL (E1),KL (E1) | | - | m | n | MN (A1, A2: Berlin, Hamburg),MN (A1, A2: Berlin, Hamburg) | | - | o | p | OP,OP | guard against mis-tagging | - | q | r | QR (A1, A2),QR (A1, A2) | | + | from | to | route | destinations | # | + | a | b | AB (E1),AB (E1) | , | | + | c | d | CD (Berlin),CD (Berlin) | Berlin,Berlin | | + | e | f | EF (A1: Berlin),EF (A1: Berlin) | A1: Berlin,A1: Berlin | | + | g | h | , | A1: Berlin,A1: Berlin | | + | i | j | , | Berlin,Berlin | | + | k | l | KL (E1),KL (E1) | A1: Berlin,A1: Berlin | | + | m | n | MN (A1, A2: Berlin, Hamburg),MN (A1, A2: Berlin, Hamburg) | A1, A2: Berlin, Hamburg,A1, A2: Berlin, Hamburg | | + | o | p | OP,OP | , | guard against mis-tagging | + | q | r | QR (A1, A2),QR (A1, A2) | A1, A2,A1, A2 | | diff --git a/features/support/route.js b/features/support/route.js index d309f54c8..1801250c7 100644 --- a/features/support/route.js +++ b/features/support/route.js @@ -143,6 +143,10 @@ module.exports = function () { return this.extractInstructionList(instructions, s => s.pronunciation || ''); }; + this.destinationsList = (instructions) => { + return this.extractInstructionList(instructions, s => s.destinations || ''); + }; + this.bearingList = (instructions) => { return this.extractInstructionList(instructions, s => s.maneuver.bearing_before + '->' + s.maneuver.bearing_after); }; diff --git a/features/support/shared_steps.js b/features/support/shared_steps.js index 66649a8f0..a6783bf96 100644 --- a/features/support/shared_steps.js +++ b/features/support/shared_steps.js @@ -33,7 +33,7 @@ module.exports = function () { var afterRequest = (err, res, body) => { if (err) return cb(err); if (body && body.length) { - let pronunciations, instructions, bearings, turns, modes, times, distances, summary, intersections; + let destinations, pronunciations, instructions, bearings, turns, modes, times, distances, summary, intersections; let json = JSON.parse(body); @@ -42,6 +42,7 @@ module.exports = function () { if (hasRoute) { instructions = this.wayList(json.routes[0]); pronunciations = this.pronunciationList(json.routes[0]); + destinations = this.destinationsList(json.routes[0]); bearings = this.bearingList(json.routes[0]); turns = this.turnList(json.routes[0]); intersections = this.intersectionList(json.routes[0]); @@ -126,6 +127,7 @@ module.exports = function () { putValue('times', times); putValue('distances', distances); putValue('pronunciations', pronunciations); + putValue('destinations', destinations); } var ok = true; diff --git a/include/engine/datafacade/datafacade_base.hpp b/include/engine/datafacade/datafacade_base.hpp index 6d3c0b4ed..411f4c311 100644 --- a/include/engine/datafacade/datafacade_base.hpp +++ b/include/engine/datafacade/datafacade_base.hpp @@ -147,6 +147,8 @@ class BaseDataFacade virtual std::string GetPronunciationForID(const unsigned name_id) const = 0; + virtual std::string GetDestinationsForID(const unsigned name_id) const = 0; + virtual std::size_t GetCoreSize() const = 0; virtual std::string GetTimestamp() const = 0; diff --git a/include/engine/datafacade/internal_datafacade.hpp b/include/engine/datafacade/internal_datafacade.hpp index 9ae0c78ee..c6c341a30 100644 --- a/include/engine/datafacade/internal_datafacade.hpp +++ b/include/engine/datafacade/internal_datafacade.hpp @@ -593,9 +593,19 @@ class InternalDataFacade final : public BaseDataFacade std::string GetPronunciationForID(const unsigned name_id) const override final { - // We store the pronounciation directly after the name of a street. + // We store the pronounciation after the name and destination of a street. // We do this to get around the street length limit of 255 which would hit - // if we concatenate these. + // if we concatenate these. Order (see extractor_callbacks): + // name (0), destination (1), pronunciation (2) + return GetNameForID(name_id + 2); + } + + std::string GetDestinationsForID(const unsigned name_id) const override final + { + // We store the destination after the name of a street. + // We do this to get around the street length limit of 255 which would hit + // if we concatenate these. Order (see extractor_callbacks): + // name (0), destination (1), pronunciation (2) return GetNameForID(name_id + 1); } diff --git a/include/engine/datafacade/shared_datafacade.hpp b/include/engine/datafacade/shared_datafacade.hpp index a43725fb5..28ec34b6b 100644 --- a/include/engine/datafacade/shared_datafacade.hpp +++ b/include/engine/datafacade/shared_datafacade.hpp @@ -662,6 +662,19 @@ class SharedDataFacade final : public BaseDataFacade std::string GetPronunciationForID(const unsigned name_id) const override final { + // We store the pronounciation after the name and destination of a street. + // We do this to get around the street length limit of 255 which would hit + // if we concatenate these. Order (see extractor_callbacks): + // name (0), destination (1), pronunciation (2) + return GetNameForID(name_id + 2); + } + + std::string GetDestinationsForID(const unsigned name_id) const override final + { + // We store the destination after the name of a street. + // We do this to get around the street length limit of 255 which would hit + // if we concatenate these. Order (see extractor_callbacks): + // name (0), destination (1), pronunciation (2) return GetNameForID(name_id + 1); } diff --git a/include/engine/guidance/assemble_steps.hpp b/include/engine/guidance/assemble_steps.hpp index 7dc2bc5a7..c793f3618 100644 --- a/include/engine/guidance/assemble_steps.hpp +++ b/include/engine/guidance/assemble_steps.hpp @@ -99,11 +99,13 @@ std::vector assembleSteps(const DataFacadeT &facade, BOOST_ASSERT(segment_duration >= 0); const auto name = facade.GetNameForID(step_name_id); const auto pronunciation = facade.GetPronunciationForID(step_name_id); + const auto destinations = facade.GetDestinationsForID(step_name_id); const auto distance = leg_geometry.segment_distances[segment_index]; steps.push_back(RouteStep{step_name_id, std::move(name), std::move(pronunciation), + std::move(destinations), NO_ROTARY_NAME, segment_duration / 10.0, distance, @@ -155,6 +157,7 @@ std::vector assembleSteps(const DataFacadeT &facade, steps.push_back(RouteStep{step_name_id, facade.GetNameForID(step_name_id), facade.GetPronunciationForID(step_name_id), + facade.GetDestinationsForID(step_name_id), NO_ROTARY_NAME, duration / 10., distance, @@ -179,6 +182,7 @@ std::vector assembleSteps(const DataFacadeT &facade, steps.push_back(RouteStep{source_node.name_id, facade.GetNameForID(source_node.name_id), facade.GetPronunciationForID(source_node.name_id), + facade.GetDestinationsForID(source_node.name_id), NO_ROTARY_NAME, duration / 10., leg_geometry.segment_distances[segment_index], @@ -209,6 +213,7 @@ std::vector assembleSteps(const DataFacadeT &facade, steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id), facade.GetPronunciationForID(target_node.name_id), + facade.GetDestinationsForID(target_node.name_id), NO_ROTARY_NAME, ZERO_DURATION, ZERO_DISTANCE, diff --git a/include/engine/guidance/route_step.hpp b/include/engine/guidance/route_step.hpp index e34da5dbc..16876984a 100644 --- a/include/engine/guidance/route_step.hpp +++ b/include/engine/guidance/route_step.hpp @@ -50,6 +50,7 @@ struct RouteStep unsigned name_id; std::string name; std::string pronunciation; + std::string destinations; std::string rotary_name; double duration; double distance; @@ -67,6 +68,7 @@ inline RouteStep getInvalidRouteStep() "", "", "", + "", 0, 0, TRAVEL_MODE_INACCESSIBLE, diff --git a/include/extractor/extraction_way.hpp b/include/extractor/extraction_way.hpp index acb787645..437d17c11 100644 --- a/include/extractor/extraction_way.hpp +++ b/include/extractor/extraction_way.hpp @@ -32,6 +32,7 @@ struct ExtractionWay is_access_restricted = false; name.clear(); pronunciation.clear(); + destinations.clear(); forward_travel_mode = TRAVEL_MODE_INACCESSIBLE; backward_travel_mode = TRAVEL_MODE_INACCESSIBLE; } @@ -48,6 +49,7 @@ struct ExtractionWay double duration; std::string name; std::string pronunciation; + std::string destinations; bool roundabout; bool is_access_restricted; bool is_startpoint; diff --git a/include/extractor/extractor_callbacks.hpp b/include/extractor/extractor_callbacks.hpp index 9beb67d2f..23e5d0050 100644 --- a/include/extractor/extractor_callbacks.hpp +++ b/include/extractor/extractor_callbacks.hpp @@ -3,6 +3,7 @@ #include "util/typedefs.hpp" #include +#include #include #include @@ -34,7 +35,9 @@ class ExtractorCallbacks { private: // used to deduplicate street names and street destinations: actually maps to name ids - std::unordered_map string_map; + using MapKey = std::pair; + using MapVal = unsigned; + std::unordered_map> string_map; ExtractionContainers &external_memory; public: diff --git a/profiles/car.lua b/profiles/car.lua index 87dac1aec..fe066b19d 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -407,6 +407,8 @@ function way_function (way, result) if has_destination and has_name and not has_ref then result.name = name .. " (" .. destination .. ")" end + + result.destinations = destination end end diff --git a/src/engine/api/json_factory.cpp b/src/engine/api/json_factory.cpp index 8e94b9107..5d5693753 100644 --- a/src/engine/api/json_factory.cpp +++ b/src/engine/api/json_factory.cpp @@ -198,6 +198,8 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo route_step.values["name"] = std::move(step.name); if (!step.pronunciation.empty()) route_step.values["pronunciation"] = std::move(step.pronunciation); + if (!step.destinations.empty()) + route_step.values["destinations"] = std::move(step.destinations); if (!step.rotary_name.empty()) route_step.values["rotary_name"] = std::move(step.rotary_name); diff --git a/src/extractor/extractor_callbacks.cpp b/src/extractor/extractor_callbacks.cpp index 950d72892..3e5a71092 100644 --- a/src/extractor/extractor_callbacks.cpp +++ b/src/extractor/extractor_callbacks.cpp @@ -27,7 +27,7 @@ namespace extractor ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers) : external_memory(extraction_containers) { - string_map[""] = 0; + string_map[MapKey("", "")] = 0; } /** @@ -146,25 +146,38 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti const constexpr auto MAX_STRING_LENGTH = 255u; // Get the unique identifier for the street name - const auto name_iterator = string_map.find(parsed_way.name); + // Get the unique identifier for the street name and destination + const auto name_iterator = string_map.find(MapKey(parsed_way.name, parsed_way.destinations)); unsigned name_id = external_memory.name_lengths.size(); if (string_map.end() == name_iterator) { auto name_length = std::min(MAX_STRING_LENGTH, parsed_way.name.size()); + auto destinations_length = std::min(MAX_STRING_LENGTH, parsed_way.destinations.size()); + auto pronunciation_length = std::min(MAX_STRING_LENGTH, parsed_way.pronunciation.size()); + + + external_memory.name_char_data.reserve(name_id + name_length + destinations_length + pronunciation_length); - external_memory.name_char_data.reserve(name_id + name_length); std::copy(parsed_way.name.c_str(), parsed_way.name.c_str() + name_length, std::back_inserter(external_memory.name_char_data)); - external_memory.name_lengths.push_back(name_length); - - auto pronunciation_length = std::min(255u, parsed_way.pronunciation.size()); - std::copy(parsed_way.pronunciation.c_str(), parsed_way.pronunciation.c_str() + pronunciation_length, + std::copy(parsed_way.destinations.c_str(), + parsed_way.destinations.c_str() + destinations_length, std::back_inserter(external_memory.name_char_data)); + + + std::copy(parsed_way.pronunciation.c_str(), + parsed_way.pronunciation.c_str() + pronunciation_length, + std::back_inserter(external_memory.name_char_data)); + + external_memory.name_lengths.push_back(name_length); + external_memory.name_lengths.push_back(destinations_length); external_memory.name_lengths.push_back(pronunciation_length); - string_map.insert(std::make_pair(parsed_way.name, name_id)); + auto k = MapKey{parsed_way.name, parsed_way.destinations}; + auto v = MapVal{name_id}; + string_map.emplace(std::move(k), std::move(v)); } else { diff --git a/src/extractor/scripting_environment.cpp b/src/extractor/scripting_environment.cpp index 63ad07899..cfdbb5745 100644 --- a/src/extractor/scripting_environment.cpp +++ b/src/extractor/scripting_environment.cpp @@ -136,6 +136,7 @@ void ScriptingEnvironment::InitContext(ScriptingEnvironment::Context &context) .def_readwrite("backward_speed", &ExtractionWay::backward_speed) .def_readwrite("name", &ExtractionWay::name) .def_readwrite("pronunciation", &ExtractionWay::pronunciation) + .def_readwrite("destinations", &ExtractionWay::destinations) .def_readwrite("roundabout", &ExtractionWay::roundabout) .def_readwrite("is_access_restricted", &ExtractionWay::is_access_restricted) .def_readwrite("is_startpoint", &ExtractionWay::is_startpoint) diff --git a/unit_tests/mocks/mock_datafacade.hpp b/unit_tests/mocks/mock_datafacade.hpp index 478f11b60..230e782a6 100644 --- a/unit_tests/mocks/mock_datafacade.hpp +++ b/unit_tests/mocks/mock_datafacade.hpp @@ -172,6 +172,7 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade unsigned GetNameIndexFromEdgeID(const unsigned /* id */) const override { return 0; } std::string GetNameForID(const unsigned /* name_id */) const override { return ""; } std::string GetPronunciationForID(const unsigned /* name_id */) const override { return ""; } + std::string GetDestinationsForID(const unsigned /* name_id */) const override { return ""; } std::size_t GetCoreSize() const override { return 0; } std::string GetTimestamp() const override { return ""; } bool GetContinueStraightDefault() const override { return true; }