diff --git a/routing/routing.pro b/routing/routing.pro index 3738007772..18312ccd16 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -18,6 +18,7 @@ SOURCES += \ road_graph_router.cpp \ dijkstra_router.cpp \ features_road_graph.cpp \ + vehicle_model.cpp \ HEADERS += \ route.hpp \ @@ -29,3 +30,4 @@ HEADERS += \ road_graph_router.hpp \ dijkstra_router.hpp \ features_road_graph.hpp \ + vehicle_model.hpp \ diff --git a/routing/routing_tests/routing_tests.pro b/routing/routing_tests/routing_tests.pro index e9b6522fc1..84e5a9dfb0 100644 --- a/routing/routing_tests/routing_tests.pro +++ b/routing/routing_tests/routing_tests.pro @@ -19,6 +19,7 @@ SOURCES += \ road_graph_builder.cpp \ road_graph_builder_test.cpp \ dijkstra_router_test.cpp \ + vehicle_model_test.cpp \ HEADERS += \ road_graph_builder.hpp \ diff --git a/routing/routing_tests/vehicle_model_test.cpp b/routing/routing_tests/vehicle_model_test.cpp new file mode 100644 index 0000000000..66b884fcf2 --- /dev/null +++ b/routing/routing_tests/vehicle_model_test.cpp @@ -0,0 +1,131 @@ +#include "../../testing/testing.hpp" + +#include "../vehicle_model.hpp" +#include "../../indexer/classificator.hpp" +#include "../../indexer/feature.hpp" +#include "../../base/macros.hpp" + +namespace +{ + +routing::VehicleModel::SpeedForType s_testLimits[] = { + { {"highway", "trunk"}, 150 }, + { {"highway", "primary"}, 120 }, + { {"highway", "secondary"}, 80 }, + { {"highway", "residential"}, 50 }, +}; + +class TestVehicleModel : public routing::VehicleModel +{ +public: + TestVehicleModel() + : VehicleModel(classif(), vector(s_testLimits, s_testLimits + ARRAY_SIZE(s_testLimits))) + { + } +}; + +uint32_t GetType(char const * s0, char const * s1 = 0, char const * s2 = 0) +{ + char const * const t[] = {s0, s1, s2}; + size_t const size = (s0 != 0) + size_t(s1 != 0) + size_t(s2 != 0); + return classif().GetTypeByPath(vector(t, t + size)); + +} + +void CheckSpeed(vector types, double expectedSpeed) +{ + TestVehicleModel vehicleModel; + feature::TypesHolder h; + for (size_t i = 0; i < types.size(); ++i) + h(types[i]); + TEST_EQUAL(vehicleModel.GetSpeed(h), expectedSpeed, ()); +} + +void CheckOneWay(vector types, bool expectedValue) +{ + TestVehicleModel vehicleModel; + feature::TypesHolder h; + for (size_t i = 0; i < types.size(); ++i) + h(types[i]); + TEST_EQUAL(vehicleModel.IsOneWay(h), expectedValue, ()); +} + + +} + +UNIT_TEST(VehicleModel_MaxSpeed) +{ + TestVehicleModel vehicleModel; + TEST_EQUAL(vehicleModel.GetMaxSpeed(), 150, ()); +} + +UNIT_TEST(VehicleModel_Speed) +{ + CheckSpeed(vector(1, GetType("highway", "secondary", "bridge")), 80.0); + CheckSpeed(vector(1, GetType("highway", "secondary", "tunnel")), 80.0); + CheckSpeed(vector(1, GetType("highway", "secondary")), 80.0); + CheckSpeed(vector(1, GetType("highway")), 0.0); + + CheckSpeed(vector(1, GetType("highway", "trunk")), 150.0); + CheckSpeed(vector(1, GetType("highway", "primary")), 120.0); + CheckSpeed(vector(1, GetType("highway", "residential")), 50.0); +} + +UNIT_TEST(VehicleModel_Speed_MultiTypes) +{ + uint32_t const typeTunnel = GetType("highway", "secondary", "tunnel"); + uint32_t const typeSecondary = GetType("highway", "secondary"); + uint32_t const typeHighway = GetType("highway"); + { + uint32_t types[] = { typeTunnel, typeSecondary }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 80.0); + } + { + uint32_t types[] = { typeTunnel, typeHighway }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 80.0); + } + { + uint32_t types[] = { typeHighway, typeTunnel }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 80.0); + } + { + uint32_t types[] = { typeHighway, typeHighway }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 0.0); + } +} + +UNIT_TEST(VehicleModel_OneWay) +{ + { + uint32_t types[] = { GetType("highway", "secondary", "bridge"), GetType("oneway") }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 80.0); + CheckOneWay(vector(types, types + ARRAY_SIZE(types)), true); + } + { + uint32_t types[] = { GetType("oneway"), GetType("highway", "secondary", "bridge") }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 80.0); + CheckOneWay(vector(types, types + ARRAY_SIZE(types)), true); + } + { + uint32_t types[] = { GetType("oneway") }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 0.0); + CheckOneWay(vector(types, types + ARRAY_SIZE(types)), true); + } +} + +UNIT_TEST(VehicleModel_DifferentSpeeds) +{ + { + uint32_t types[] = { GetType("highway", "secondary"), GetType("highway", "primary") }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 80.0); + } + { + uint32_t types[] = { GetType("highway", "primary"), GetType("highway", "secondary") }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 80.0); + } + { + uint32_t types[] = { GetType("highway", "primary"), GetType("oneway"), GetType("highway", "secondary") }; + CheckSpeed(vector(types, types + ARRAY_SIZE(types)), 80.0); + CheckOneWay(vector(types, types + ARRAY_SIZE(types)), true); + } +} diff --git a/routing/vehicle_model.cpp b/routing/vehicle_model.cpp new file mode 100644 index 0000000000..0e62aafc3c --- /dev/null +++ b/routing/vehicle_model.cpp @@ -0,0 +1,85 @@ +#include "vehicle_model.hpp" +#include "../indexer/classificator.hpp" +#include "../indexer/feature.hpp" +#include "../indexer/ftypes_matcher.hpp" +#include "../base/macros.hpp" +#include "../std/limits.hpp" + +namespace routing +{ + +VehicleModel::SpeedForType const s_carLimits[] = { + { {"highway", "motorway"}, 90 }, + { {"highway", "trunk"}, 85 }, + { {"highway", "motorway_link"}, 75 }, + { {"highway", "trunk_link"}, 70 }, + { {"highway", "primary"}, 65 }, + { {"highway", "primary_link"}, 60 }, + { {"highway", "secondary"}, 55 }, + { {"highway", "secondary_link"}, 50 }, + { {"highway", "tertiary"}, 40 }, + { {"highway", "tertiary_link"}, 30 }, + { {"highway", "residential"}, 25 }, + { {"highway", "pedestrian"}, 25 }, + { {"highway", "unclassified"}, 25 }, + { {"highway", "service"}, 15 }, + { {"highway", "living_street"}, 10 }, + { {"highway", "road"}, 10 }, + { {"highway", "track"}, 5 }, + /// @todo: Add to classificator + //{ {"highway", "shuttle_train"}, 10 }, + //{ {"highway", "ferry"}, 5 }, + //{ {"highway", "default"}, 10 }, + /// @todo: check type + //{ {"highway", "construction"}, 40 }, +}; + + +CarModel::CarModel() + : VehicleModel(classif(), vector(s_carLimits, s_carLimits + ARRAY_SIZE(s_carLimits))) +{ +} + +VehicleModel::VehicleModel(Classificator const & c, vector const & speedLimits) : m_maxSpeed(0) +{ + m_onewayType = c.GetTypeByPath(vector(1, "oneway")); + + for (size_t i = 0; i < speedLimits.size(); ++i) + { + m_maxSpeed = max(m_maxSpeed, speedLimits[i].m_speed); + m_types[c.GetTypeByPath(vector(speedLimits[i].m_types, speedLimits[i].m_types + 2))] = speedLimits[i]; + } +} + +double VehicleModel::GetSpeed(FeatureType const & f) const +{ + return GetSpeed(feature::TypesHolder(f)); +} + +double VehicleModel::GetSpeed(feature::TypesHolder const & types) const +{ + double speed = m_maxSpeed * 2; + for (size_t i = 0; i < types.Size(); ++i) + { + uint32_t const type = ftypes::BaseChecker::PrepareFeatureTypeToMatch(types[i]); + TypesT::const_iterator it = m_types.find(type); + if (it != m_types.end()) + speed = min(speed, it->second.m_speed); + } + if (speed <= m_maxSpeed) + return speed; + + return 0.0; +} + +bool VehicleModel::IsOneWay(FeatureType const & f) const +{ + return IsOneWay(feature::TypesHolder(f)); +} + +bool VehicleModel::IsOneWay(feature::TypesHolder const & types) const +{ + return types.Has(m_onewayType); +} + +} diff --git a/routing/vehicle_model.hpp b/routing/vehicle_model.hpp new file mode 100644 index 0000000000..3c5595cd34 --- /dev/null +++ b/routing/vehicle_model.hpp @@ -0,0 +1,55 @@ +#pragma once +#include "../std/unordered_map.hpp" +#include "../std/utility.hpp" +#include "../std/vector.hpp" + +class Classificator; +class FeatureType; + +namespace feature { class TypesHolder; } + +namespace routing +{ + +class IVehicleModel +{ +public: + virtual ~IVehicleModel() {} + + virtual double GetSpeed(FeatureType const & f) const = 0; + virtual double GetMaxSpeed() const = 0; + virtual bool IsOneWay(FeatureType const & f) const = 0; +}; + +class VehicleModel : public IVehicleModel +{ +public: + struct SpeedForType + { + char const * m_types[2]; + double m_speed; + }; + + VehicleModel(Classificator const & c, vector const & speedLimits); + + virtual double GetSpeed(FeatureType const & f) const; + virtual double GetMaxSpeed() const { return m_maxSpeed; } + virtual bool IsOneWay(FeatureType const & f) const; + + double GetSpeed(feature::TypesHolder const & types) const; + bool IsOneWay(feature::TypesHolder const & types) const; + +private: + double m_maxSpeed; + typedef unordered_map TypesT; + TypesT m_types; + uint32_t m_onewayType; +}; + +class CarModel : public VehicleModel +{ +public: + CarModel(); +}; + +}