From f17783b6e4a8d2726480985a7a17d683531832b1 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Thu, 25 Oct 2018 13:45:58 +0300 Subject: [PATCH] [routing] Maxspeed converter implementation and tests. --- generator/camera_node_processor.cpp | 4 +- generator/category_to_speed.cpp | 13 +- generator/category_to_speed.hpp | 25 +- .../generator_tests/speed_cameras_test.cpp | 1 + generator/maxspeed_builder.cpp | 2 +- platform/platform_tests/measurement_tests.cpp | 4 +- routing/maxspeed_conversion.cpp | 218 ++++++++++++++++++ routing/maxspeed_conversion.hpp | 197 +++++++++++++++- routing/routing_tests/CMakeLists.txt | 1 + routing/routing_tests/maxspeed_tests.cpp | 54 +++++ 10 files changed, 482 insertions(+), 37 deletions(-) create mode 100644 routing/routing_tests/maxspeed_tests.cpp diff --git a/generator/camera_node_processor.cpp b/generator/camera_node_processor.cpp index 252feaa17c..1471724650 100644 --- a/generator/camera_node_processor.cpp +++ b/generator/camera_node_processor.cpp @@ -2,6 +2,8 @@ #include "generator/category_to_speed.hpp" +#include "routing/maxspeed_conversion.hpp" + #include "platform/measurement_utils.hpp" #include "base/assert.hpp" @@ -114,7 +116,7 @@ void CameraNodeIntermediateDataProcessor::ProcessWay(uint64_t id, WayElement con std::string CameraNodeIntermediateDataProcessor::ValidateMaxSpeedString(std::string const & maxSpeedString) { - SpeedInUnits speed; + routing::SpeedInUnits speed; if (!MaxspeedValueToSpeed(maxSpeedString, speed) || !speed.IsNumeric()) return std::string(); diff --git a/generator/category_to_speed.cpp b/generator/category_to_speed.cpp index 65b3b2556f..b9a046bcb6 100644 --- a/generator/category_to_speed.cpp +++ b/generator/category_to_speed.cpp @@ -1,15 +1,16 @@ #include "generator/category_to_speed.hpp" +#include "platform/measurement_utils.hpp" + #include "base/string_utils.hpp" #include -#include #include namespace { -using namespace generator; using namespace measurement_utils; +using namespace routing; using namespace std; unordered_map const kRoadCategoryToSpeed = { @@ -205,12 +206,4 @@ bool MaxspeedValueToSpeed(string const & maxspeedValue, SpeedInUnits & speed) return false; } - -string DebugPrint(SpeedInUnits const & speed) -{ - ostringstream oss; - oss << "SpeedInUnits [ m_speed == " << speed.m_speed - << ", m_units == " << DebugPrint(speed.m_units) << " ]"; - return oss.str(); -} } // generator diff --git a/generator/category_to_speed.hpp b/generator/category_to_speed.hpp index ff6442692a..9c78b8ed5b 100644 --- a/generator/category_to_speed.hpp +++ b/generator/category_to_speed.hpp @@ -1,29 +1,12 @@ #pragma once -#include "platform/measurement_utils.hpp" +#include "routing/maxspeed_conversion.hpp" #include -#include #include namespace generator { -uint16_t constexpr kNoneMaxSpeed = std::numeric_limits::max(); -uint16_t constexpr kWalkMaxSpeed = std::numeric_limits::max() - 1; - -struct SpeedInUnits -{ - SpeedInUnits() = default; - SpeedInUnits(uint16_t speed, measurement_utils::Units units) noexcept : m_speed(speed), m_units(units) {} - - bool operator==(SpeedInUnits const & s) const { return m_speed == s.m_speed && m_units == s.m_units; } - - bool IsNumeric() const { return m_speed != kNoneMaxSpeed && m_speed != kWalkMaxSpeed; } - - uint16_t m_speed = 0; // Speed in km per hour or mile per hour depends on m_units value. - measurement_utils::Units m_units = measurement_utils::Units::Metric; -}; - /// \brief Obtains |speed| and |units| by road category based on /// the table in https://wiki.openstreetmap.org/wiki/Speed_limits /// This method should be updated regularly. Last update: 23.10.18. @@ -33,14 +16,12 @@ struct SpeedInUnits /// speed = 60 and units = Units::Metric. /// \note If the method returns true the field |speed| may be filled with |kNoneMaxSpeed| value. /// It means no speed limits for the |category|. It's currently actual for Germany. -bool RoadCategoryToSpeed(std::string const & category, SpeedInUnits & speed); +bool RoadCategoryToSpeed(std::string const & category, routing::SpeedInUnits & speed); /// \brief Tries to convert the value of tag maxspeed to speed in appropriate units. /// \returns false in case of error and true if the conversion is successful. /// \note speed.m_speed will be filled with kNoneMaxSpeed or kWalkMaxSpeed if /// maxspeedValue is equal to "none" or "walk". The value of speed.m_units does not /// matter in this case. -bool MaxspeedValueToSpeed(std::string const & maxspeedValue, SpeedInUnits & speed); - -std::string DebugPrint(SpeedInUnits const & speed); +bool MaxspeedValueToSpeed(std::string const & maxspeedValue, routing::SpeedInUnits & speed); } // generator diff --git a/generator/generator_tests/speed_cameras_test.cpp b/generator/generator_tests/speed_cameras_test.cpp index 28d2b585d7..1459170798 100644 --- a/generator/generator_tests/speed_cameras_test.cpp +++ b/generator/generator_tests/speed_cameras_test.cpp @@ -10,6 +10,7 @@ #include "generator/metalines_builder.hpp" #include "generator/osm_source.hpp" +#include "routing/maxspeed_conversion.hpp" #include "routing/speed_camera_ser_des.hpp" #include "indexer/classificator_loader.hpp" diff --git a/generator/maxspeed_builder.cpp b/generator/maxspeed_builder.cpp index 7f4ab23de8..511cc853ff 100644 --- a/generator/maxspeed_builder.cpp +++ b/generator/maxspeed_builder.cpp @@ -1,6 +1,6 @@ #include "generator/maxspeed_builder.hpp" -#include "routing/maxspeed_serialization.hpp" +#include "routing/maxspeed_conversion.hpp" namespace generator { diff --git a/platform/platform_tests/measurement_tests.cpp b/platform/platform_tests/measurement_tests.cpp index 41a449e22d..47aced3b81 100644 --- a/platform/platform_tests/measurement_tests.cpp +++ b/platform/platform_tests/measurement_tests.cpp @@ -201,8 +201,8 @@ UNIT_TEST(ConversionUnits) TEST(base::AlmostEqualAbs(MilesToMeters(1.0), 1609.344, kEps), ()); TEST(base::AlmostEqualAbs(MphToKmph(KmphToMph(100.0)), 100.0, kEps), ()); - TEST(base::AlmostEqualAbs(MphToKmph(100.0), 160.934, kEps), ()); + TEST(base::AlmostEqualAbs(MphToKmph(100.0), 160.9344, kEps), (MphToKmph(100.0))); - TEST(base::AlmostEqualAbs(ToSpeedKmPH(100.0, Units::Imperial), 160.934, kEps), ()); + TEST(base::AlmostEqualAbs(ToSpeedKmPH(100.0, Units::Imperial), 160.9344, kEps), ()); TEST(base::AlmostEqualAbs(ToSpeedKmPH(100.0, Units::Metric), 100.0, kEps), ()); } diff --git a/routing/maxspeed_conversion.cpp b/routing/maxspeed_conversion.cpp index d57f5ea153..f2c697c8b2 100644 --- a/routing/maxspeed_conversion.cpp +++ b/routing/maxspeed_conversion.cpp @@ -1,5 +1,223 @@ #include "routing/maxspeed_conversion.hpp" +#include +#include +#include + namespace routing { +using namespace measurement_utils; + +// SpeedInUnits ------------------------------------------------------------------------------------ +bool SpeedInUnits::operator==(SpeedInUnits const & s) const +{ + return m_speed == s.m_speed && m_units == s.m_units; +} + +bool SpeedInUnits::operator<(SpeedInUnits const & s) const +{ + if (m_speed != s.m_speed) + return m_speed < s.m_speed; + return m_units < s.m_units; +} + +bool SpeedInUnits::IsNumeric() const +{ + return m_speed != kNoneMaxSpeed && m_speed != kWalkMaxSpeed && m_speed != kInvalidSpeed; +} + +// MaxspeedConverter ------------------------------------------------------------------------------- +MaxspeedConverter::MaxspeedConverter() +{ + // Special values. + m_macroToSpeed[static_cast(Maxspeed::Undefined)] = SpeedInUnits(kInvalidSpeed, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::None)] = SpeedInUnits(kNoneMaxSpeed, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Walk)] = SpeedInUnits(kWalkMaxSpeed, Units::Metric); + + // Km per hour. + m_macroToSpeed[static_cast(Maxspeed::Speed1kph)] = SpeedInUnits(1, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed2kph)] = SpeedInUnits(2, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed3kph)] = SpeedInUnits(3, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed4kph)] = SpeedInUnits(4, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed5kph)] = SpeedInUnits(5, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed6kph)] = SpeedInUnits(6, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed7kph)] = SpeedInUnits(7, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed8kph)] = SpeedInUnits(8, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed9kph)] = SpeedInUnits(9, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed10kph)] = SpeedInUnits(10, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed11kph)] = SpeedInUnits(11, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed12kph)] = SpeedInUnits(12, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed13kph)] = SpeedInUnits(13, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed14kph)] = SpeedInUnits(14, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed15kph)] = SpeedInUnits(15, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed16kph)] = SpeedInUnits(16, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed18kph)] = SpeedInUnits(18, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed20kph)] = SpeedInUnits(20, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed22kph)] = SpeedInUnits(22, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed25kph)] = SpeedInUnits(25, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed24kph)] = SpeedInUnits(24, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed28kph)] = SpeedInUnits(28, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed30kph)] = SpeedInUnits(30, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed32kph)] = SpeedInUnits(32, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed35kph)] = SpeedInUnits(35, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed36kph)] = SpeedInUnits(36, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed39kph)] = SpeedInUnits(39, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed40kph)] = SpeedInUnits(40, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed45kph)] = SpeedInUnits(45, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed50kph)] = SpeedInUnits(50, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed55kph)] = SpeedInUnits(55, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed56kph)] = SpeedInUnits(56, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed60kph)] = SpeedInUnits(60, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed64kph)] = SpeedInUnits(64, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed65kph)] = SpeedInUnits(65, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed70kph)] = SpeedInUnits(70, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed72kph)] = SpeedInUnits(72, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed75kph)] = SpeedInUnits(75, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed80kph)] = SpeedInUnits(80, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed82kph)] = SpeedInUnits(82, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed85kph)] = SpeedInUnits(85, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed89kph)] = SpeedInUnits(89, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed90kph)] = SpeedInUnits(90, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed93kph)] = SpeedInUnits(93, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed95kph)] = SpeedInUnits(95, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed96kph)] = SpeedInUnits(96, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed100kph)] = SpeedInUnits(100, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed104kph)] = SpeedInUnits(104, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed105kph)] = SpeedInUnits(105, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed106kph)] = SpeedInUnits(106, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed110kph)] = SpeedInUnits(110, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed112kph)] = SpeedInUnits(112, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed115kph)] = SpeedInUnits(115, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed120kph)] = SpeedInUnits(120, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed125kph)] = SpeedInUnits(125, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed127kph)] = SpeedInUnits(127, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed130kph)] = SpeedInUnits(130, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed135kph)] = SpeedInUnits(135, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed140kph)] = SpeedInUnits(140, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed141kph)] = SpeedInUnits(141, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed145kph)] = SpeedInUnits(145, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed150kph)] = SpeedInUnits(150, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed155kph)] = SpeedInUnits(155, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed160kph)] = SpeedInUnits(160, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed165kph)] = SpeedInUnits(165, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed170kph)] = SpeedInUnits(170, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed177kph)] = SpeedInUnits(177, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed180kph)] = SpeedInUnits(180, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed185kph)] = SpeedInUnits(185, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed190kph)] = SpeedInUnits(190, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed193kph)] = SpeedInUnits(193, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed195kph)] = SpeedInUnits(195, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed200kph)] = SpeedInUnits(200, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed201kph)] = SpeedInUnits(201, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed210kph)] = SpeedInUnits(210, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed217kph)] = SpeedInUnits(217, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed220kph)] = SpeedInUnits(220, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed230kph)] = SpeedInUnits(230, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed240kph)] = SpeedInUnits(240, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed250kph)] = SpeedInUnits(250, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed260kph)] = SpeedInUnits(260, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed270kph)] = SpeedInUnits(270, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed275kph)] = SpeedInUnits(275, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed280kph)] = SpeedInUnits(280, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed285kph)] = SpeedInUnits(285, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed300kph)] = SpeedInUnits(300, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed305kph)] = SpeedInUnits(305, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed310kph)] = SpeedInUnits(310, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed320kph)] = SpeedInUnits(320, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed350kph)] = SpeedInUnits(350, Units::Metric); + m_macroToSpeed[static_cast(Maxspeed::Speed380kph)] = SpeedInUnits(380, Units::Metric); + + // Mile per hours. + m_macroToSpeed[static_cast(Maxspeed::Speed3mph)] = SpeedInUnits(3, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed4mph)] = SpeedInUnits(4, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed5mph)] = SpeedInUnits(5, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed6mph)] = SpeedInUnits(6, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed7mph)] = SpeedInUnits(7, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed8mph)] = SpeedInUnits(8, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed9mph)] = SpeedInUnits(9, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed10mph)] = SpeedInUnits(10, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed12mph)] = SpeedInUnits(12, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed13mph)] = SpeedInUnits(13, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed14mph)] = SpeedInUnits(14, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed15mph)] = SpeedInUnits(15, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed17mph)] = SpeedInUnits(17, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed18mph)] = SpeedInUnits(18, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed19mph)] = SpeedInUnits(19, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed20mph)] = SpeedInUnits(20, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed24mph)] = SpeedInUnits(24, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed25mph)] = SpeedInUnits(25, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed30mph)] = SpeedInUnits(30, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed35mph)] = SpeedInUnits(35, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed40mph)] = SpeedInUnits(40, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed45mph)] = SpeedInUnits(45, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed50mph)] = SpeedInUnits(50, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed55mph)] = SpeedInUnits(55, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed59mph)] = SpeedInUnits(59, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed60mph)] = SpeedInUnits(60, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed65mph)] = SpeedInUnits(65, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed70mph)] = SpeedInUnits(70, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed75mph)] = SpeedInUnits(75, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed79mph)] = SpeedInUnits(79, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed80mph)] = SpeedInUnits(80, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed85mph)] = SpeedInUnits(85, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed90mph)] = SpeedInUnits(90, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed95mph)] = SpeedInUnits(95, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed100mph)] = SpeedInUnits(100, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed105mph)] = SpeedInUnits(105, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed110mph)] = SpeedInUnits(110, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed115mph)] = SpeedInUnits(115, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed120mph)] = SpeedInUnits(120, Units::Imperial); + m_macroToSpeed[static_cast(Maxspeed::Speed125mph)] = SpeedInUnits(125, Units::Imperial); + + m_speedToMacro.insert(std::make_pair(SpeedInUnits(kInvalidSpeed, Units::Metric), Maxspeed::Undefined)); + for (size_t i = 1; i < std::numeric_limits::max(); ++i) + { + auto const & speed = m_macroToSpeed[i]; + if (!speed.IsValid()) + continue; + + m_speedToMacro.insert(std::make_pair(speed, static_cast(i))); + } +} + +SpeedInUnits MaxspeedConverter::MacroToSpeed(Maxspeed macro) const +{ + return m_macroToSpeed[static_cast(macro)]; +} + +Maxspeed MaxspeedConverter::SpeedToMacro(SpeedInUnits const & speed) const +{ + auto const it = m_speedToMacro.find(speed); + if (it == m_speedToMacro.cend()) + return Maxspeed::Undefined; + + return it->second; +} + +bool MaxspeedConverter::IsValidMacro(uint8_t macro) const +{ + return m_macroToSpeed[macro].IsValid(); +} + +MaxspeedConverter const & GetMaxspeedConverter() +{ + static const MaxspeedConverter inst; + return inst; +} + +std::string DebugPrint(SpeedInUnits const & speed) +{ + std::ostringstream oss; + oss << "SpeedInUnits [ m_speed == " << speed.m_speed + << ", m_units == " << DebugPrint(speed.m_units) << " ]"; + return oss.str(); +} + +std::string DebugPrint(Maxspeed maxspeed) +{ + std::ostringstream oss; + oss << "Maxspeed:" << static_cast(maxspeed) << " Decoded:" + << DebugPrint(GetMaxspeedConverter().MacroToSpeed(maxspeed)); + return oss.str(); +} } // namespace routing diff --git a/routing/maxspeed_conversion.hpp b/routing/maxspeed_conversion.hpp index d7ffeeed78..55865dfd35 100644 --- a/routing/maxspeed_conversion.hpp +++ b/routing/maxspeed_conversion.hpp @@ -1,8 +1,203 @@ #pragma once -#include +#include "platform/measurement_utils.hpp" + +#include +#include +#include +#include namespace routing { +/// \brief This enum class contains most popular maxspeed value according to +/// https://taginfo.openstreetmap.org/keys/maxspeed#values. +/// \note Value of this enum is saved to mwm. So they should not be change because of backward +/// compatibility. But it's possible to add some value to this enum. +enum class Maxspeed : uint8_t +{ + // Special values. + Undefined, + None, // No maxspeed restriction (E.g. a motorway in Germany). + Walk, // Driver should move as a walking person. + // Km per hour. + Speed1kph = 10, + Speed2kph, + Speed3kph, + Speed4kph, + Speed5kph, + Speed6kph, + Speed7kph, + Speed8kph, + Speed9kph, + Speed10kph, + Speed11kph, + Speed12kph, + Speed13kph, + Speed14kph, + Speed15kph, + Speed16kph, + Speed18kph, + Speed20kph, + Speed22kph, + Speed25kph, + Speed24kph, + Speed28kph, + Speed30kph, + Speed32kph, + Speed35kph, + Speed36kph, + Speed39kph, + Speed40kph, + Speed45kph, + Speed50kph, + Speed55kph, + Speed56kph, + Speed60kph, + Speed64kph, + Speed65kph, + Speed70kph, + Speed72kph, + Speed75kph, + Speed80kph, + Speed82kph, + Speed85kph, + Speed89kph, + Speed90kph, + Speed93kph, + Speed95kph, + Speed96kph, + Speed100kph, + Speed104kph, + Speed105kph, + Speed106kph, + Speed110kph, + Speed112kph, + Speed115kph, + Speed120kph, + Speed125kph, + Speed127kph, + Speed130kph, + Speed135kph, + Speed140kph, + Speed141kph, + Speed145kph, + Speed150kph, + Speed155kph, + Speed160kph, + Speed165kph, + Speed170kph, + Speed177kph, + Speed180kph, + Speed185kph, + Speed190kph, + Speed193kph, + Speed195kph, + Speed200kph, + Speed201kph, + Speed210kph, + Speed217kph, + Speed220kph, + Speed230kph, + Speed240kph, + Speed250kph, + Speed260kph, + Speed270kph, + Speed275kph, + Speed280kph, + Speed285kph, + Speed300kph, + Speed305kph, + Speed310kph, + Speed320kph, + Speed350kph, + Speed380kph, + + // Mile per hours. + Speed3mph = 110, + Speed4mph, + Speed5mph, + Speed6mph, + Speed7mph, + Speed8mph, + Speed9mph, + Speed10mph, + Speed12mph, + Speed13mph, + Speed14mph, + Speed15mph, + Speed17mph, + Speed18mph, + Speed19mph, + Speed20mph, + Speed24mph, + Speed25mph, + Speed30mph, + Speed35mph, + Speed40mph, + Speed45mph, + Speed50mph, + Speed55mph, + Speed59mph, + Speed60mph, + Speed65mph, + Speed70mph, + Speed75mph, + Speed79mph, + Speed80mph, + Speed85mph, + Speed90mph, + Speed95mph, + Speed100mph, + Speed105mph, + Speed110mph, + Speed115mph, + Speed120mph, + Speed125mph, +}; + +uint16_t constexpr kInvalidSpeed = std::numeric_limits::max(); +uint16_t constexpr kNoneMaxSpeed = std::numeric_limits::max() - 1; +uint16_t constexpr kWalkMaxSpeed = std::numeric_limits::max() - 2; + +struct SpeedInUnits +{ + SpeedInUnits() = default; + SpeedInUnits(uint16_t speed, measurement_utils::Units units) noexcept : m_speed(speed), m_units(units) {} + + bool operator==(SpeedInUnits const & s) const; + /// \note While comparing speeds are not converted to the same units. So according to + /// this compare operator 80 km per hour is more then 79 mile per hour. + bool operator<(SpeedInUnits const & s) const; + + bool IsNumeric() const; + bool IsValid() const { return m_speed != kInvalidSpeed; } + + uint16_t m_speed = kInvalidSpeed; // Speed in km per hour or mile per hour depends on m_units value. + measurement_utils::Units m_units = measurement_utils::Units::Metric; +}; + +class MaxspeedConverter +{ + friend MaxspeedConverter const & GetMaxspeedConverter(); +public: + MaxspeedConverter(); + + SpeedInUnits MacroToSpeed(Maxspeed macro) const ; + Maxspeed SpeedToMacro(SpeedInUnits const & speed) const; + + /// \returns true if |macro| can be cast to a valid value of Maxspeed emum class. + /// \note Maxspeed::Undefined value and all value from 0 to 256 is no present in the enum + /// are considered as an invalid. + bool IsValidMacro(uint8_t macro) const; + +private: + std::array::max()> m_macroToSpeed; + std::map m_speedToMacro; +}; + +MaxspeedConverter const & GetMaxspeedConverter(); + +std::string DebugPrint(SpeedInUnits const & speed); +std::string DebugPrint(Maxspeed maxspeed); } // namespace routing diff --git a/routing/routing_tests/CMakeLists.txt b/routing/routing_tests/CMakeLists.txt index d33ca76b8a..c15f61a0b5 100644 --- a/routing/routing_tests/CMakeLists.txt +++ b/routing/routing_tests/CMakeLists.txt @@ -16,6 +16,7 @@ set( index_graph_test.cpp index_graph_tools.cpp index_graph_tools.hpp + maxspeed_tests.cpp nearest_edge_finder_tests.cpp online_cross_fetcher_test.cpp restriction_test.cpp diff --git a/routing/routing_tests/maxspeed_tests.cpp b/routing/routing_tests/maxspeed_tests.cpp new file mode 100644 index 0000000000..ba869d02a1 --- /dev/null +++ b/routing/routing_tests/maxspeed_tests.cpp @@ -0,0 +1,54 @@ +#include "testing/testing.hpp" + +#include "routing/maxspeed_conversion.hpp" + +#include "platform/measurement_utils.hpp" + +#include +#include + +namespace +{ +using namespace measurement_utils; +using namespace routing; +using namespace std; + +UNIT_TEST(MaxspeedConverter) +{ + auto const & conv = GetMaxspeedConverter(); + + // All maxspeed limits conversion test. + for (size_t i = 0; i < numeric_limits::max(); ++i) + { + auto const macro = static_cast(i); + auto const speed = conv.MacroToSpeed(macro); + auto const backToMacro = conv.SpeedToMacro(speed); + if (speed.IsValid()) + TEST_EQUAL(backToMacro, macro, (i)); + else + TEST_EQUAL(backToMacro, Maxspeed::Undefined, (i)); + } + + // Test on conversion some maxspeed value to macro. + TEST_EQUAL(conv.SpeedToMacro(SpeedInUnits(kInvalidSpeed, Units::Metric)), Maxspeed::Undefined, ()); + TEST_EQUAL(conv.SpeedToMacro(SpeedInUnits(kNoneMaxSpeed, Units::Metric)), Maxspeed::None, ()); + TEST_EQUAL(conv.SpeedToMacro(SpeedInUnits(kWalkMaxSpeed, Units::Metric)), Maxspeed::Walk, ()); + TEST_EQUAL(conv.SpeedToMacro(SpeedInUnits(60, Units::Metric)), Maxspeed::Speed60kph, ()); + TEST_EQUAL(conv.SpeedToMacro(SpeedInUnits(90, Units::Metric)), Maxspeed::Speed90kph, ()); + TEST_EQUAL(conv.SpeedToMacro(SpeedInUnits(30, Units::Imperial)), Maxspeed::Speed30mph, ()); + TEST_EQUAL(conv.SpeedToMacro(SpeedInUnits(33, Units::Metric)), Maxspeed::Undefined, ()); + + // Test on conversion some maxspeed to macro to value. + TEST_EQUAL(conv.MacroToSpeed(Maxspeed::Undefined), SpeedInUnits(kInvalidSpeed, Units::Metric), ()); + TEST_EQUAL(conv.MacroToSpeed(Maxspeed::None), SpeedInUnits(kNoneMaxSpeed, Units::Metric), ()); + TEST_EQUAL(conv.MacroToSpeed(Maxspeed::Walk), SpeedInUnits(kWalkMaxSpeed, Units::Metric), ()); + TEST_EQUAL(conv.MacroToSpeed(Maxspeed::Speed60kph), SpeedInUnits(60, Units::Metric), ()); + TEST_EQUAL(conv.MacroToSpeed(Maxspeed::Speed90kph), SpeedInUnits(90, Units::Metric), ()); + TEST_EQUAL(conv.MacroToSpeed(Maxspeed::Speed30mph), SpeedInUnits(30, Units::Imperial), ()); + + // Test on IsValidMacro() method. + TEST(!conv.IsValidMacro(0), ()); + TEST(conv.IsValidMacro(1), ()); // static_cast(None) == 1 + TEST(!conv.IsValidMacro(9), ()); // A value which is undefined in Maxspeed enum class. +} +} // namespace