diff --git a/routing_common/bicycle_model.cpp b/routing_common/bicycle_model.cpp index 07fe417f2b..40823be067 100644 --- a/routing_common/bicycle_model.cpp +++ b/routing_common/bicycle_model.cpp @@ -49,7 +49,8 @@ HighwayBasedSpeeds const kDefaultSpeeds = { {HighwayType::HighwayCycleway, InOutCitySpeedKMpH(SpeedKMpH(30.0, 20.0))}, {HighwayType::HighwayResidential, InOutCitySpeedKMpH(SpeedKMpH(8.0, 10.0))}, {HighwayType::HighwayLivingStreet, InOutCitySpeedKMpH(SpeedKMpH(7.0, 8.0))}, - {HighwayType::HighwaySteps, InOutCitySpeedKMpH(SpeedKMpH(1.0, 5.0))}, + // Steps have obvious inconvenience of a bike in hands. + {HighwayType::HighwaySteps, InOutCitySpeedKMpH(SpeedKMpH(1.0, 1.0))}, {HighwayType::HighwayPedestrian, InOutCitySpeedKMpH(SpeedKMpH(5.0))}, {HighwayType::HighwayFootway, InOutCitySpeedKMpH(SpeedKMpH(7.0, 5.0))}, {HighwayType::ManMadePier, InOutCitySpeedKMpH(SpeedKMpH(7.0))}, @@ -400,16 +401,33 @@ void BicycleModel::Init() { initializer_list hwtagYesBicycle = {"hwtag", "yesbicycle"}; - m_noBicycleType = classif().GetTypeByPath({"hwtag", "nobicycle"}); - m_yesBicycleType = classif().GetTypeByPath(hwtagYesBicycle); - m_bidirBicycleType = classif().GetTypeByPath({"hwtag", "bidir_bicycle"}); - m_onedirBicycleType = classif().GetTypeByPath({"hwtag", "onedir_bicycle"}); - vector const additionalTags = { - {hwtagYesBicycle, m_maxModelSpeed}, - {{"route", "ferry"}, bicycle_model::kDefaultSpeeds.at(HighwayType::RouteFerry)}, - {{"man_made", "pier"}, bicycle_model::kDefaultSpeeds.at(HighwayType::ManMadePier)}}; + auto const & cl = classif(); + m_noBicycleType = cl.GetTypeByPath({"hwtag", "nobicycle"}); + m_yesBicycleType = cl.GetTypeByPath(hwtagYesBicycle); + m_bidirBicycleType = cl.GetTypeByPath({"hwtag", "bidir_bicycle"}); + m_onedirBicycleType = cl.GetTypeByPath({"hwtag", "onedir_bicycle"}); - SetAdditionalRoadTypes(classif(), additionalTags); + { + vector const tags = { + {hwtagYesBicycle, m_maxModelSpeed}, + {{"route", "ferry"}, bicycle_model::kDefaultSpeeds.at(HighwayType::RouteFerry)}, + {{"man_made", "pier"}, bicycle_model::kDefaultSpeeds.at(HighwayType::ManMadePier)}}; + + AddAdditionalRoadTypes(cl, tags); + } + + { + // Small dismount speed with obvious inconvenience of a bike in hands. + InOutCitySpeedKMpH const dismountSpeed(SpeedKMpH(2.0, 2.0)); + + vector const tags = { + {hwtagYesBicycle, m_maxModelSpeed}, + {{"highway", "footway"}, dismountSpeed}, + {{"highway", "pedestrian"}, dismountSpeed}, + {{"highway", "steps"}, dismountSpeed}}; + + AddAdditionalRoadTypes(cl, tags); + } } VehicleModelInterface::RoadAvailability BicycleModel::GetRoadAvailability(feature::TypesHolder const & types) const diff --git a/routing_common/car_model.cpp b/routing_common/car_model.cpp index e7a84fadac..6acd233eea 100644 --- a/routing_common/car_model.cpp +++ b/routing_common/car_model.cpp @@ -178,7 +178,7 @@ void CarModel::Init() m_noCarType = classif().GetTypeByPath({"hwtag", "nocar"}); m_yesCarType = classif().GetTypeByPath({"hwtag", "yescar"}); - SetAdditionalRoadTypes(classif(), car_model::kAdditionalTags); + AddAdditionalRoadTypes(classif(), car_model::kAdditionalTags); } VehicleModelInterface::RoadAvailability CarModel::GetRoadAvailability(feature::TypesHolder const & types) const diff --git a/routing_common/pedestrian_model.cpp b/routing_common/pedestrian_model.cpp index 8c5e30ff87..a65b4b971b 100644 --- a/routing_common/pedestrian_model.cpp +++ b/routing_common/pedestrian_model.cpp @@ -52,8 +52,9 @@ HighwayBasedSpeeds const kDefaultSpeeds = { {HighwayType::HighwaySteps, InOutCitySpeedKMpH(SpeedKMpH(3.0))}, {HighwayType::HighwayPedestrian, InOutCitySpeedKMpH(SpeedKMpH(5.0))}, {HighwayType::HighwayFootway, InOutCitySpeedKMpH(SpeedKMpH(5.0))}, - {HighwayType::ManMadePier, InOutCitySpeedKMpH(SpeedKMpH(7.0))}, - {HighwayType::RouteFerry, InOutCitySpeedKMpH(SpeedKMpH(1.0, 20.0))}, + {HighwayType::ManMadePier, InOutCitySpeedKMpH(SpeedKMpH(5.0))}, + /// @todo Set the same speed as a ferry for bicycle. At the same time, a car ferry has {10, 10}. + {HighwayType::RouteFerry, InOutCitySpeedKMpH(SpeedKMpH(3.0, 20.0))}, }; SpeedKMpH constexpr kSpeedOffroadKMpH = {3.0 /* weight */, 3.0 /* eta */}; @@ -300,7 +301,7 @@ void PedestrianModel::Init() {{"route", "ferry"}, pedestrian_model::kDefaultSpeeds.at(HighwayType::RouteFerry)}, {{"man_made", "pier"}, pedestrian_model::kDefaultSpeeds.at(HighwayType::ManMadePier)}}; - SetAdditionalRoadTypes(classif(), additionalTags); + AddAdditionalRoadTypes(classif(), additionalTags); } VehicleModelInterface::RoadAvailability PedestrianModel::GetRoadAvailability(feature::TypesHolder const & types) const diff --git a/routing_common/vehicle_model.cpp b/routing_common/vehicle_model.cpp index f9c0aaa2ff..5e778cfa8a 100644 --- a/routing_common/vehicle_model.cpp +++ b/routing_common/vehicle_model.cpp @@ -44,30 +44,25 @@ HighwayType GetHighwayTypeKey(HighwayType type) namespace routing { -VehicleModel::AdditionalRoadType::AdditionalRoadType(Classificator const & c, - AdditionalRoadTags const & tag) - : m_type(c.GetTypeByPath(tag.m_hwtag)) - , m_speed(tag.m_speed) -{ -} VehicleModel::VehicleModel(Classificator const & c, LimitsInitList const & featureTypeLimits, SurfaceInitList const & featureTypeSurface, HighwayBasedInfo const & info) : m_onewayType(c.GetTypeByPath({"hwtag", "oneway"})), m_highwayBasedInfo(info) { - CHECK_EQUAL(m_surfaceFactors.size(), 4, + ASSERT_EQUAL(m_surfaceFactors.size(), 4, ("If you want to change the size of the container please take into account that it's " "used with algorithm find() with linear complexity.")); - CHECK_EQUAL(featureTypeSurface.size(), m_surfaceFactors.size(), ()); + ASSERT_EQUAL(featureTypeSurface.size(), m_surfaceFactors.size(), ()); for (auto const & v : featureTypeLimits) { auto const classificatorType = c.GetTypeByPath(v.m_types); auto const highwayType = static_cast(c.GetIndexForType(classificatorType)); auto const speedIt = info.m_speeds.find(highwayType); - CHECK(speedIt != info.m_speeds.cend(), ("Can't found speed for", highwayType)); - // TODO: Consider using not only highway class speed but max sped * max speed factor. + ASSERT(speedIt != info.m_speeds.cend(), ("Can't found speed for", highwayType)); + + /// @todo Consider using not only highway class speed but max_speed * max_speed_factor. m_maxModelSpeed = Max(m_maxModelSpeed, speedIt->second); m_roadTypes.emplace(classificatorType, RoadType(highwayType, v.m_isPassThroughAllowed)); } @@ -76,21 +71,24 @@ VehicleModel::VehicleModel(Classificator const & c, LimitsInitList const & featu for (auto const & v : featureTypeSurface) { auto const & speedFactor = v.m_factor; - CHECK_LESS_OR_EQUAL(speedFactor.m_weight, 1.0, ()); - CHECK_LESS_OR_EQUAL(speedFactor.m_eta, 1.0, ()); - CHECK_GREATER(speedFactor.m_weight, 0.0, ()); - CHECK_GREATER(speedFactor.m_eta, 0.0, ()); + ASSERT_LESS_OR_EQUAL(speedFactor.m_weight, 1.0, ()); + ASSERT_LESS_OR_EQUAL(speedFactor.m_eta, 1.0, ()); + ASSERT_GREATER(speedFactor.m_weight, 0.0, ()); + ASSERT_GREATER(speedFactor.m_eta, 0.0, ()); m_surfaceFactors[i++] = {c.GetTypeByPath(v.m_types), v.m_factor}; } } -void VehicleModel::SetAdditionalRoadTypes(Classificator const & c, - vector const & additionalTags) +void VehicleModel::AddAdditionalRoadTypes(Classificator const & c, AdditionalTagsT const & tags) { - for (auto const & tag : additionalTags) + for (auto const & tag : tags) { - m_addRoadTypes.emplace_back(c, tag); - m_maxModelSpeed = Max(m_maxModelSpeed, tag.m_speed); + uint32_t const type = c.GetTypeByPath(tag.m_hwtag); + if (m_roadTypes.find(type) == m_roadTypes.end()) + { + m_addRoadTypes.emplace_back(AdditionalRoadType{type, tag.m_speed}); + m_maxModelSpeed = Max(m_maxModelSpeed, tag.m_speed); + } } } diff --git a/routing_common/vehicle_model.hpp b/routing_common/vehicle_model.hpp index 796fee8bf2..ea116ae435 100644 --- a/routing_common/vehicle_model.hpp +++ b/routing_common/vehicle_model.hpp @@ -284,13 +284,15 @@ public: VehicleModel(Classificator const & c, LimitsInitList const & featureTypeLimits, SurfaceInitList const & featureTypeSurface, HighwayBasedInfo const & info); - /// VehicleModelInterface overrides: + /// @name VehicleModelInterface overrides. + /// @{ SpeedKMpH GetSpeed(FeatureType & f, SpeedParams const & speedParams) const override; HighwayType GetHighwayType(FeatureType & f) const override; double GetMaxWeightSpeed() const override; bool IsOneWay(FeatureType & f) const override; bool IsRoad(FeatureType & f) const override; bool IsPassThroughAllowed(FeatureType & f) const override; + /// @} public: /// @returns true if |m_highwayTypes| or |m_addRoadTypes| contains |type| and false otherwise. @@ -318,8 +320,8 @@ protected: virtual RoadAvailability GetRoadAvailability(feature::TypesHolder const & types) const; /// Used in derived class constructors only. Not for public use. - void SetAdditionalRoadTypes(Classificator const & c, - std::vector const & additionalTags); + using AdditionalTagsT = std::vector; + void AddAdditionalRoadTypes(Classificator const & c, AdditionalTagsT const & tags); static uint32_t PrepareToMatchType(uint32_t type); @@ -343,12 +345,10 @@ protected: private: struct AdditionalRoadType final { - AdditionalRoadType(Classificator const & c, AdditionalRoadTags const & tag); - bool operator==(AdditionalRoadType const & rhs) const { return m_type == rhs.m_type; } - uint32_t const m_type; - InOutCitySpeedKMpH const m_speed; + uint32_t m_type; + InOutCitySpeedKMpH m_speed; }; class RoadType final @@ -359,7 +359,7 @@ private: { } - bool IsPassThroughAllowed() const { return m_isPassThroughAllowed; }; + bool IsPassThroughAllowed() const { return m_isPassThroughAllowed; } HighwayType GetHighwayType() const { return m_highwayType; } bool operator==(RoadType const & rhs) const { @@ -396,6 +396,7 @@ private: // Note. It's an array (not map or unordered_map) because of perfomance reasons. std::array m_surfaceFactors; + /// @todo Do we really need a separate vector of road types or can merge with the m_roadTypes map? std::vector m_addRoadTypes; uint32_t m_onewayType;