From b7c23e7c46433befe482ce9eb06210db66215d0a Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Tue, 15 Sep 2015 14:27:03 +0300 Subject: [PATCH 01/12] Speedcam routing time computation engine. --- generator/osm2meta.hpp | 15 ++ generator/osm_translator.hpp | 2 +- indexer/feature_meta.hpp | 1 + indexer/ftypes_matcher.cpp | 12 ++ indexer/ftypes_matcher.hpp | 8 ++ map/framework.hpp | 2 +- platform/location.hpp | 4 + routing/route.cpp | 22 ++- routing/route.hpp | 19 ++- routing/routing.pro | 2 + routing/routing_mapping.hpp | 1 + routing/routing_session.cpp | 136 +++++++++++------- routing/routing_session.hpp | 4 +- routing/routing_settings.hpp | 7 +- routing/speed_camera.cpp | 67 +++++++++ routing/speed_camera.hpp | 15 ++ .../routing/routing.xcodeproj/project.pbxproj | 8 ++ 17 files changed, 263 insertions(+), 62 deletions(-) create mode 100644 routing/speed_camera.cpp create mode 100644 routing/speed_camera.hpp diff --git a/generator/osm2meta.hpp b/generator/osm2meta.hpp index 474b9ea722..0297a29435 100644 --- a/generator/osm2meta.hpp +++ b/generator/osm2meta.hpp @@ -39,6 +39,12 @@ public: if (!value.empty()) md.Add(Metadata::FMD_PHONE_NUMBER, value); } + else if (k == "maxspeed") + { + string const & value = ValidateAndFormat_maxspeed(v); + if (!value.empty()) + md.Add(Metadata::FMD_MAXSPEED, value); + } else if (k == "stars") { string const & value = ValidateAndFormat_stars(v); @@ -117,6 +123,15 @@ public: protected: /// Validation and formatting functions + string ValidateAndFormat_maxspeed(string const & v) const + { + static ftypes::IsSpeedCamChecker const IsSpeedCam; + if (!IsSpeedCam(m_params.m_Types)) + return string(); + + return v; + } + string ValidateAndFormat_stars(string const & v) const { if (v.empty()) diff --git a/generator/osm_translator.hpp b/generator/osm_translator.hpp index d9fbe7f26c..51886e4a99 100644 --- a/generator/osm_translator.hpp +++ b/generator/osm_translator.hpp @@ -142,7 +142,7 @@ protected: for (auto const & p : e.tags) { // Store only this tags to use it in railway stations processing for the particular city. - if (p.first == "network" || p.first == "operator" || p.first == "route") + if (p.first == "network" || p.first == "operator" || p.first == "route" || p.first == "maxspeed") if (!TBase::IsKeyTagExists(p.first)) TBase::m_current->AddTag(p.first, p.second); } diff --git a/indexer/feature_meta.hpp b/indexer/feature_meta.hpp index f81ef76198..13f447e0b9 100644 --- a/indexer/feature_meta.hpp +++ b/indexer/feature_meta.hpp @@ -35,6 +35,7 @@ namespace feature FMD_EMAIL = 14, FMD_POSTCODE = 15, FMD_WIKIPEDIA = 16, + FMD_MAXSPEED = 17, FMD_COUNT }; diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp index b52cb4fb0d..6527dc8347 100644 --- a/indexer/ftypes_matcher.cpp +++ b/indexer/ftypes_matcher.cpp @@ -70,6 +70,18 @@ IsATMChecker const & IsATMChecker::Instance() return inst; } +IsSpeedCamChecker::IsSpeedCamChecker() +{ + Classificator const & c = classif(); + m_types.push_back(c.GetTypeByPath({ "highway", "speed_camera"})); +} + +IsSpeedCamChecker const & IsSpeedCamChecker::Instance() +{ + static const IsSpeedCamChecker inst; + return inst; +} + IsFuelStationChecker::IsFuelStationChecker() { Classificator const & c = classif(); diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index 0e8b4ada31..6a2a98b698 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -46,6 +46,14 @@ public: static IsATMChecker const & Instance(); }; +class IsSpeedCamChecker : public BaseChecker +{ +public: + IsSpeedCamChecker(); + + static IsSpeedCamChecker const & Instance(); +}; + class IsFuelStationChecker : public BaseChecker { public: diff --git a/map/framework.hpp b/map/framework.hpp index 2d30557cd8..a91f31afbc 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -595,7 +595,7 @@ public: void SetRouteProgressListener(TRouteProgressCallback const & progressCallback) { m_progressCallback = progressCallback; } void FollowRoute(); void CloseRouting(); - void GetRouteFollowingInfo(location::FollowingInfo & info) const { m_routingSession.GetRouteFollowingInfo(info); } + void GetRouteFollowingInfo(location::FollowingInfo & info) const { m_routingSession.GetRouteFollowingInfo(info, m_model.GetIndex()); } m2::PointD GetRouteEndPoint() const { return m_routingSession.GetEndPoint(); } void SetLastUsedRouter(routing::RouterType type); /// Returns the most situable router engine type. Bases on distance and the last used router. diff --git a/platform/location.hpp b/platform/location.hpp index 65e14dd2dc..6132896dd0 100644 --- a/platform/location.hpp +++ b/platform/location.hpp @@ -101,6 +101,7 @@ namespace location m_exitNum(0), m_time(0), m_completionPercent(0), + m_speedWarningSignal(false), m_pedestrianTurn(routing::turns::PedestrianDirection::None), m_pedestrianDirectionPos(0., 0.) { @@ -156,6 +157,9 @@ namespace location // Percentage of the route completion. double m_completionPercent; + // Speed cam warning signal. + bool m_speedWarningSignal; + /// @name Pedestrian direction information //@{ routing::turns::PedestrianDirection m_pedestrianTurn; diff --git a/routing/route.cpp b/routing/route.cpp index 602ff31dac..c12e42a721 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -1,5 +1,6 @@ #include "route.hpp" #include "turns_generator.hpp" +#include "speed_camera.hpp" #include "indexer/mercator.hpp" @@ -27,7 +28,7 @@ double constexpr kOnEndToleranceM = 10.0; Route::Route(string const & router, vector const & points, string const & name) : m_router(router), m_routingSettings(GetCarRoutingSettings()), - m_name(name), m_poly(points.begin(), points.end()) + m_name(name), m_poly(points.begin(), points.end()),m_lastCheckedCamera(0) { Update(); } @@ -43,6 +44,7 @@ void Route::Swap(Route & rhs) swap(m_turns, rhs.m_turns); swap(m_times, rhs.m_times); m_absentCountries.swap(rhs.m_absentCountries); + m_lastCheckedCamera = rhs.m_lastCheckedCamera; } double Route::GetTotalDistanceMeters() const @@ -148,6 +150,24 @@ Route::TTurns::const_iterator Route::GetCurrentTurn() const }); } +double Route::GetCurrentCam(SpeedCameraRestriction & camera, Index const & index) const +{ + size_t current_index = max(m_poly.GetCurrentIter().m_ind, m_lastCheckedCamera); + SpeedCameraRestriction cam(static_cast(current_index), 0 /* maxspeed */); + for (size_t i = current_index; i < m_poly.GetPolyline().GetSize(); ++i) + { + uint8_t speed = CheckCameraInPoint(m_poly.GetPolyline().GetPoint(i), index); + if (speed != kNoSpeedCamera) + { + camera = SpeedCameraRestriction(static_cast(i), speed); + m_lastCheckedCamera = i; + return m_poly.GetDistanceM(m_poly.GetCurrentIter(), m_poly.GetIterToIndex(i)); + } + } + m_lastCheckedCamera = m_poly.GetPolyline().GetSize(); + return kInvalidSpeedCameraDistance; +} + bool Route::GetCurrentTurn(double & distanceToTurnMeters, turns::TurnItem & turn) const { auto it = GetCurrentTurn(); diff --git a/routing/route.hpp b/routing/route.hpp index e2347f6ebe..7260282922 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -17,9 +17,20 @@ namespace location class RouteMatchingInfo; } +class Index; + namespace routing { +/// Speed cameras structure. First is reference to point, second is a speed limit. +struct SpeedCameraRestriction +{ + uint32_t m_index; + uint8_t m_maxSpeed; + + SpeedCameraRestriction(uint32_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeed(maxSpeed) {} +}; + class Route { public: @@ -27,12 +38,15 @@ public: typedef pair TTimeItem; typedef vector TTimes; + static double constexpr kInvalidSpeedCameraDistance = -1; + explicit Route(string const & router) : m_router(router), m_routingSettings(GetCarRoutingSettings()) {} template Route(string const & router, TIter beg, TIter end) - : m_router(router), m_routingSettings(GetCarRoutingSettings()), m_poly(beg, end) + : m_router(router), m_routingSettings(GetCarRoutingSettings()), m_poly(beg, end), + m_lastCheckedCamera(0) { Update(); } @@ -85,6 +99,8 @@ public: /// \brief Extract information about zero, one or two nearest turns depending on current position. /// @return true if its parameter is filled with correct result. (At least with one element.) bool GetNextTurns(vector & turns) const; + /// Returns nearest speed camera and distance to it. + double GetCurrentCam(SpeedCameraRestriction & camera, Index const & index) const; void GetCurrentDirectionPoint(m2::PointD & pt) const; @@ -131,6 +147,7 @@ private: TTimes m_times; mutable double m_currentTime; + mutable size_t m_lastCheckedCamera; }; } // namespace routing diff --git a/routing/routing.pro b/routing/routing.pro index 79cb3c65df..9d904325b6 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -36,6 +36,7 @@ SOURCES += \ routing_algorithm.cpp \ routing_mapping.cpp \ routing_session.cpp \ + speed_camera.cpp \ turns.cpp \ turns_generator.cpp \ turns_sound.cpp \ @@ -71,6 +72,7 @@ HEADERS += \ routing_mapping.hpp \ routing_session.hpp \ routing_settings.hpp \ + speed_camera.hpp \ turns.hpp \ turns_generator.hpp \ turns_sound.hpp \ diff --git a/routing/routing_mapping.hpp b/routing/routing_mapping.hpp index 866de8ea9b..c3efddf621 100644 --- a/routing/routing_mapping.hpp +++ b/routing/routing_mapping.hpp @@ -3,6 +3,7 @@ #include "osrm2feature_map.hpp" #include "osrm_data_facade.hpp" #include "router.hpp" +#include "speed_camera.hpp" #include "indexer/index.hpp" diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index c5bb64c5fd..c0e2f50d61 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -27,6 +27,12 @@ double constexpr kShowTheTurnAfterTheNextM = 500.; // @todo(kshalnev) The distance may depend on the current speed. double constexpr kShowPedestrianTurnInMeters = 5.; +// Minimal distance to speed camera to make sound bell on overspeed. +double constexpr kSpeedCameraMinimalWarningMeters = 200.; +// Seconds to warning user before speed camera for driving with current speed. +double constexpr kSpeedCameraWarningSeconds = 30; + +double constexpr kMpsToKmh = 1000. / 3600.; } // namespace namespace routing @@ -37,6 +43,7 @@ RoutingSession::RoutingSession() m_route(string()), m_state(RoutingNotActive), m_endPoint(m2::PointD::Zero()), + m_speedMpS(0), m_passedDistanceOnRouteMeters(0.0) { } @@ -123,6 +130,7 @@ void RoutingSession::Reset() m_turnsSound.Reset(); m_passedDistanceOnRouteMeters = 0.0; + m_lastWarnedSpeedCamera = 0; } RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const & position, @@ -140,6 +148,7 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const ASSERT(m_route.IsValid(), ()); m_turnsSound.SetSpeedMetersPerSecond(info.m_speed); + m_speedMpS = info.m_speed; if (m_route.MoveIterator(info)) { @@ -185,7 +194,7 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const return m_state; } -void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const +void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info, Index const & index) const { auto formatDistFn = [](double dist, string & value, string & suffix) { @@ -201,73 +210,89 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const threads::MutexGuard guard(m_routeSessionMutex); UNUSED_VALUE(guard); - if (m_route.IsValid() && IsNavigable()) + if (!m_route.IsValid() || !IsNavigable()) { - formatDistFn(m_route.GetCurrentDistanceToEndMeters(), info.m_distToTarget, info.m_targetUnitsSuffix); + // nothing should be displayed on the screen about turns if these lines are executed + info = FollowingInfo(); + return; + } - double distanceToTurnMeters = 0., distanceToNextTurnMeters = 0.; - turns::TurnItem turn; - turns::TurnItem nextTurn; - m_route.GetCurrentTurn(distanceToTurnMeters, turn); - formatDistFn(distanceToTurnMeters, info.m_distToTurn, info.m_turnUnitsSuffix); - info.m_turn = turn.m_turn; + formatDistFn(m_route.GetCurrentDistanceToEndMeters(), info.m_distToTarget, info.m_targetUnitsSuffix); - // The turn after the next one. - if (m_route.GetNextTurn(distanceToNextTurnMeters, nextTurn)) + double distanceToTurnMeters = 0., distanceToNextTurnMeters = 0.; + turns::TurnItem turn; + turns::TurnItem nextTurn; + m_route.GetCurrentTurn(distanceToTurnMeters, turn); + formatDistFn(distanceToTurnMeters, info.m_distToTurn, info.m_turnUnitsSuffix); + info.m_turn = turn.m_turn; + + // The turn after the next one. + if (m_route.GetNextTurn(distanceToNextTurnMeters, nextTurn)) + { + double const distBetweenTurnsM = distanceToNextTurnMeters - distanceToTurnMeters; + ASSERT_LESS_OR_EQUAL(0, distBetweenTurnsM, ()); + + if (m_routingSettings.m_showTurnAfterNext && + distanceToTurnMeters < kShowTheTurnAfterTheNextM && distBetweenTurnsM < turns::kMaxTurnDistM) { - double const distBetweenTurnsM = distanceToNextTurnMeters - distanceToTurnMeters; - ASSERT_LESS_OR_EQUAL(0, distBetweenTurnsM, ()); - - if (m_routingSettings.m_showTurnAfterNext && - distanceToTurnMeters < kShowTheTurnAfterTheNextM && distBetweenTurnsM < turns::kMaxTurnDistM) - { - info.m_nextTurn = nextTurn.m_turn; - } - else - { - info.m_nextTurn = routing::turns::TurnDirection::NoTurn; - } + info.m_nextTurn = nextTurn.m_turn; } else { info.m_nextTurn = routing::turns::TurnDirection::NoTurn; } - info.m_exitNum = turn.m_exitNum; - info.m_time = m_route.GetCurrentTimeToEndSec(); - info.m_sourceName = turn.m_sourceName; - info.m_targetName = turn.m_targetName; - info.m_completionPercent = 100.0 * - (m_passedDistanceOnRouteMeters + m_route.GetCurrentDistanceFromBeginMeters()) / - (m_passedDistanceOnRouteMeters + m_route.GetTotalDistanceMeters()); - - // Lane information. - if (distanceToTurnMeters < kShowLanesDistInMeters) - { - // There are two nested loops below. Outer one is for lanes and inner one (ctor of - // SingleLaneInfo) is - // for each lane's directions. The size of turn.m_lanes is relatively small. Less than 10 in - // most cases. - info.m_lanes.clear(); - for (size_t j = 0; j < turn.m_lanes.size(); ++j) - info.m_lanes.emplace_back(turn.m_lanes[j]); - } - else - { - info.m_lanes.clear(); - } - - // Pedestrian info - m2::PointD pos; - m_route.GetCurrentDirectionPoint(pos); - info.m_pedestrianDirectionPos = MercatorBounds::ToLatLon(pos); - info.m_pedestrianTurn = - (distanceToTurnMeters < kShowPedestrianTurnInMeters) ? turn.m_pedestrianTurn : turns::PedestrianDirection::None; } else { - // nothing should be displayed on the screen about turns if these lines are executed - info = FollowingInfo(); + info.m_nextTurn = routing::turns::TurnDirection::NoTurn; } + info.m_exitNum = turn.m_exitNum; + info.m_time = m_route.GetCurrentTimeToEndSec(); + info.m_sourceName = turn.m_sourceName; + info.m_targetName = turn.m_targetName; + info.m_completionPercent = 100.0 * + (m_passedDistanceOnRouteMeters + m_route.GetCurrentDistanceFromBeginMeters()) / + (m_passedDistanceOnRouteMeters + m_route.GetTotalDistanceMeters()); + + // Lane information. + if (distanceToTurnMeters < kShowLanesDistInMeters) + { + // There are two nested loops below. Outer one is for lanes and inner one (ctor of + // SingleLaneInfo) is + // for each lane's directions. The size of turn.m_lanes is relatively small. Less than 10 in + // most cases. + info.m_lanes.clear(); + for (size_t j = 0; j < turn.m_lanes.size(); ++j) + info.m_lanes.emplace_back(turn.m_lanes[j]); + } + else + { + info.m_lanes.clear(); + } + + // Warning signals checks + if (m_routingSettings.m_speedCameraWarning) + { + double const warningDistanceM = max(kSpeedCameraMinimalWarningMeters, + m_speedMpS * kSpeedCameraWarningSeconds); + SpeedCameraRestriction cam(0, 0); + double const camDistance = m_route.GetCurrentCam(cam, index); + if (Route::kInvalidSpeedCameraDistance != camDistance && camDistance < warningDistanceM) + { + if (cam.m_index > m_lastWarnedSpeedCamera && m_speedMpS > cam.m_maxSpeed * kMpsToKmh) + { + info.m_speedWarningSignal = true; + m_lastWarnedSpeedCamera = cam.m_index; + } + } + } + + // Pedestrian info + m2::PointD pos; + m_route.GetCurrentDirectionPoint(pos); + info.m_pedestrianDirectionPos = MercatorBounds::ToLatLon(pos); + info.m_pedestrianTurn = + (distanceToTurnMeters < kShowPedestrianTurnInMeters) ? turn.m_pedestrianTurn : turns::PedestrianDirection::None; } void RoutingSession::GenerateTurnSound(vector & turnNotifications) @@ -305,6 +330,7 @@ void RoutingSession::AssignRoute(Route & route, IRouter::ResultCode e) route.SetRoutingSettings(m_routingSettings); m_route.Swap(route); + m_lastWarnedSpeedCamera = 0; } void RoutingSession::SetRouter(unique_ptr && router, diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index e251291289..f6880f944b 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -78,7 +78,7 @@ public: void Reset(); State OnLocationPositionChanged(m2::PointD const & position, location::GpsInfo const & info); - void GetRouteFollowingInfo(location::FollowingInfo & info) const; + void GetRouteFollowingInfo(location::FollowingInfo & info, Index const & index) const; void MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo) const; @@ -124,6 +124,8 @@ private: Route m_route; State m_state; m2::PointD m_endPoint; + double m_speedMpS; + mutable size_t m_lastWarnedSpeedCamera; mutable threads::Mutex m_routeSessionMutex; diff --git a/routing/routing_settings.hpp b/routing/routing_settings.hpp index bbf408d4d1..1eba59bb9f 100644 --- a/routing/routing_settings.hpp +++ b/routing/routing_settings.hpp @@ -32,19 +32,22 @@ struct RoutingSettings /// \brief if m_showTurnAfterNext is equal to true end users see a notification /// about the turn after the next in some cases. bool m_showTurnAfterNext; + + /// \brief m_speedCameraWarning is a flag for enabling user notifications about speed cameras. + bool m_speedCameraWarning; }; inline RoutingSettings GetPedestrianRoutingSettings() { return RoutingSettings({ false /* m_matchRoute */, false /* m_soundDirection */, 20. /* m_matchingThresholdM */, true /* m_keepPedestrianInfo */, - false /* m_showTurnAfterNext */}); + false /* m_showTurnAfterNext */, false /* m_speedCameraWarning*/}); } inline RoutingSettings GetCarRoutingSettings() { return RoutingSettings({ true /* m_matchRoute */, true /* m_soundDirection */, 50. /* m_matchingThresholdM */, false /* m_keepPedestrianInfo */, - true /* m_showTurnAfterNext */}); + true /* m_showTurnAfterNext */, true /* m_speedCameraWarning*/}); } } // namespace routing diff --git a/routing/speed_camera.cpp b/routing/speed_camera.cpp new file mode 100644 index 0000000000..ed72b88832 --- /dev/null +++ b/routing/speed_camera.cpp @@ -0,0 +1,67 @@ +#include "speed_camera.hpp" + +#include "indexer/classificator.hpp" +#include "indexer/ftypes_matcher.hpp" +#include "indexer/index.hpp" +#include "indexer/scales.hpp" + +#include "coding/reader.hpp" +#include "coding/writer.hpp" +#include "coding/read_write_utils.hpp" + +#include "base/string_utils.hpp" + +namespace +{ +double constexpr kMwmReadingRadiusMeters = 2.0; +} // namespace + +namespace routing +{ +uint8_t ReadCamRestriction(FeatureType & ft) +{ + using feature::Metadata; + ft.ParseMetadata(); + feature::Metadata const & mt = ft.GetMetadata(); + string const & speed = mt.Get(Metadata::FMD_MAXSPEED); + if (!speed.length()) + return 0; + int result; + strings::to_int(speed, result); + return result; +} + +uint8_t CheckCameraInPoint(m2::PointD const & point, Index const & index) +{ + Classificator & c = classif(); + uint32_t const req = c.GetTypeByPath({"highway", "speed_camera"}); + + uint32_t speedLimit = kNoSpeedCamera; + + auto const f = [&req, &c, &point, &speedLimit](FeatureType & ft) + { + if (ft.GetFeatureType() != feature::GEOM_POINT) + return; + + feature::TypesHolder hl = ft; + for (uint32_t t : hl) + { + uint32_t const type = ftypes::BaseChecker::PrepareToMatch(t, 2); + if (type == req) + { + ft.ParseGeometry(FeatureType::BEST_GEOMETRY); + if (ft.GetCenter() == point) + { + speedLimit = ReadCamRestriction(ft); + return; + } + } + } + }; + + index.ForEachInRect(f, + MercatorBounds::RectByCenterXYAndSizeInMeters(point, kMwmReadingRadiusMeters), + scales::GetUpperScale()); + return speedLimit; +} +} // namespace routing diff --git a/routing/speed_camera.hpp b/routing/speed_camera.hpp new file mode 100644 index 0000000000..693048d231 --- /dev/null +++ b/routing/speed_camera.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "geometry/point2d.hpp" + +#include "base/base.hpp" + +#include "std/limits.hpp" + +class Index; + +namespace routing +{ +uint8_t constexpr kNoSpeedCamera = numeric_limits::max(); +uint8_t CheckCameraInPoint(m2::PointD const & point, Index const & index); +} // namespace routing diff --git a/xcode/routing/routing.xcodeproj/project.pbxproj b/xcode/routing/routing.xcodeproj/project.pbxproj index c604234f33..fb25ed31db 100644 --- a/xcode/routing/routing.xcodeproj/project.pbxproj +++ b/xcode/routing/routing.xcodeproj/project.pbxproj @@ -70,6 +70,8 @@ A1616E2B1B6B60AB003F078E /* router_delegate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1616E291B6B60AB003F078E /* router_delegate.cpp */; }; A1616E2C1B6B60AB003F078E /* router_delegate.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A1616E2A1B6B60AB003F078E /* router_delegate.hpp */; }; A1616E2E1B6B60B3003F078E /* astar_progress.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A1616E2D1B6B60B3003F078E /* astar_progress.hpp */; }; + A1876BC61BB19C4300C9C743 /* speed_camera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1876BC41BB19C4300C9C743 /* speed_camera.cpp */; settings = {ASSET_TAGS = (); }; }; + A1876BC71BB19C4300C9C743 /* speed_camera.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A1876BC51BB19C4300C9C743 /* speed_camera.hpp */; settings = {ASSET_TAGS = (); }; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -138,6 +140,8 @@ A1616E291B6B60AB003F078E /* router_delegate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = router_delegate.cpp; sourceTree = ""; }; A1616E2A1B6B60AB003F078E /* router_delegate.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = router_delegate.hpp; sourceTree = ""; }; A1616E2D1B6B60B3003F078E /* astar_progress.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = astar_progress.hpp; sourceTree = ""; }; + A1876BC41BB19C4300C9C743 /* speed_camera.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = speed_camera.cpp; sourceTree = ""; }; + A1876BC51BB19C4300C9C743 /* speed_camera.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = speed_camera.hpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -182,6 +186,8 @@ 675343FA1A3F640D00A0A8C3 /* routing */ = { isa = PBXGroup; children = ( + A1876BC41BB19C4300C9C743 /* speed_camera.cpp */, + A1876BC51BB19C4300C9C743 /* speed_camera.hpp */, 671F58BA1B874EA20032311E /* base */, 67AB92E01B7B3E6E00AB5194 /* routing_mapping.hpp */, 67AB92E11B7B3E6E00AB5194 /* turns_tts_text.cpp */, @@ -281,6 +287,7 @@ 6753441D1A3F644F00A0A8C3 /* router.hpp in Headers */, A1616E2E1B6B60B3003F078E /* astar_progress.hpp in Headers */, 670EE5721B664796001E8064 /* directions_engine.hpp in Headers */, + A1876BC71BB19C4300C9C743 /* speed_camera.hpp in Headers */, 67C7D42A1B4EB48F00FE41AA /* car_model.hpp in Headers */, 670D049F1B0B4A970013A7AC /* nearest_edge_finder.hpp in Headers */, A120B34F1B4A7C0A002F3808 /* online_absent_fetcher.hpp in Headers */, @@ -359,6 +366,7 @@ 674F9BD61B0A580E00704FFA /* turns_generator.cpp in Sources */, 675344171A3F644F00A0A8C3 /* osrm_router.cpp in Sources */, 674F9BD21B0A580E00704FFA /* road_graph_router.cpp in Sources */, + A1876BC61BB19C4300C9C743 /* speed_camera.cpp in Sources */, 671F58BD1B874EC80032311E /* followed_polyline.cpp in Sources */, 670EE55D1B6001E7001E8064 /* routing_session.cpp in Sources */, A120B3451B4A7BE5002F3808 /* cross_mwm_road_graph.cpp in Sources */, From 4d479d9dd8f403d84fa6e6a754c42ef81211f24d Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Fri, 25 Sep 2015 15:51:45 +0300 Subject: [PATCH 02/12] Remove old reset of the routing session on map deletion. --- map/framework.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/map/framework.cpp b/map/framework.cpp index 13b2e222f6..251cc808fb 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -396,9 +396,6 @@ void Framework::DeleteCountry(storage::TIndex const & index, MapOptions opt) { InvalidateRect(GetCountryBounds(countryFile.GetNameWithoutExt()), true /* doForceUpdate */); } - // TODO (@ldragunov, @gorshenin): rewrite routing session to use MwmHandles. Thus, - // it won' be needed to reset it after maps update. - m_routingSession.Reset(); return; } case MapOptions::CarRouting: From 4e02b29ed50f0f2f0d794e6ee5d70c572f0dcdec Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Fri, 25 Sep 2015 16:40:19 +0300 Subject: [PATCH 03/12] PR fixes. --- routing/route.cpp | 5 ++--- routing/speed_camera.cpp | 24 +++++++----------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/routing/route.cpp b/routing/route.cpp index c12e42a721..bcfa78f873 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -152,9 +152,8 @@ Route::TTurns::const_iterator Route::GetCurrentTurn() const double Route::GetCurrentCam(SpeedCameraRestriction & camera, Index const & index) const { - size_t current_index = max(m_poly.GetCurrentIter().m_ind, m_lastCheckedCamera); - SpeedCameraRestriction cam(static_cast(current_index), 0 /* maxspeed */); - for (size_t i = current_index; i < m_poly.GetPolyline().GetSize(); ++i) + size_t const currentIndex = max(m_poly.GetCurrentIter().m_ind, m_lastCheckedCamera); + for (size_t i = currentIndex; i < m_poly.GetPolyline().GetSize(); ++i) { uint8_t speed = CheckCameraInPoint(m_poly.GetPolyline().GetPoint(i), index); if (speed != kNoSpeedCamera) diff --git a/routing/speed_camera.cpp b/routing/speed_camera.cpp index ed72b88832..0d1ab450f0 100644 --- a/routing/speed_camera.cpp +++ b/routing/speed_camera.cpp @@ -33,30 +33,20 @@ uint8_t ReadCamRestriction(FeatureType & ft) uint8_t CheckCameraInPoint(m2::PointD const & point, Index const & index) { - Classificator & c = classif(); - uint32_t const req = c.GetTypeByPath({"highway", "speed_camera"}); - uint32_t speedLimit = kNoSpeedCamera; - auto const f = [&req, &c, &point, &speedLimit](FeatureType & ft) + auto const f = [&point, &speedLimit](FeatureType & ft) { if (ft.GetFeatureType() != feature::GEOM_POINT) return; feature::TypesHolder hl = ft; - for (uint32_t t : hl) - { - uint32_t const type = ftypes::BaseChecker::PrepareToMatch(t, 2); - if (type == req) - { - ft.ParseGeometry(FeatureType::BEST_GEOMETRY); - if (ft.GetCenter() == point) - { - speedLimit = ReadCamRestriction(ft); - return; - } - } - } + if (!ftypes::IsSpeedCamChecker::Instance()(hl)) + return; + + ft.ParseGeometry(FeatureType::BEST_GEOMETRY); + if (ft.GetCenter() == point) + speedLimit = ReadCamRestriction(ft); }; index.ForEachInRect(f, From 2391ba6399e0548d81a9116816a8f48dd15b0b12 Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Fri, 25 Sep 2015 19:15:40 +0300 Subject: [PATCH 04/12] PR fixes. --- indexer/ftypes_matcher.cpp | 7 ++++--- routing/route.cpp | 4 ++-- routing/route.hpp | 10 +++++++--- routing/routing_session.cpp | 5 +++-- routing/speed_camera.cpp | 4 ++-- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/indexer/ftypes_matcher.cpp b/indexer/ftypes_matcher.cpp index 6527dc8347..b453836636 100644 --- a/indexer/ftypes_matcher.cpp +++ b/indexer/ftypes_matcher.cpp @@ -73,13 +73,14 @@ IsATMChecker const & IsATMChecker::Instance() IsSpeedCamChecker::IsSpeedCamChecker() { Classificator const & c = classif(); - m_types.push_back(c.GetTypeByPath({ "highway", "speed_camera"})); + m_types.push_back(c.GetTypeByPath({"highway", "speed_camera"})); } +// static IsSpeedCamChecker const & IsSpeedCamChecker::Instance() { - static const IsSpeedCamChecker inst; - return inst; + static const IsSpeedCamChecker instance; + return instance; } IsFuelStationChecker::IsFuelStationChecker() diff --git a/routing/route.cpp b/routing/route.cpp index bcfa78f873..856cfb907b 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -28,7 +28,7 @@ double constexpr kOnEndToleranceM = 10.0; Route::Route(string const & router, vector const & points, string const & name) : m_router(router), m_routingSettings(GetCarRoutingSettings()), - m_name(name), m_poly(points.begin(), points.end()),m_lastCheckedCamera(0) + m_name(name), m_poly(points.begin(), points.end()), m_lastCheckedCamera(0) { Update(); } @@ -44,7 +44,7 @@ void Route::Swap(Route & rhs) swap(m_turns, rhs.m_turns); swap(m_times, rhs.m_times); m_absentCountries.swap(rhs.m_absentCountries); - m_lastCheckedCamera = rhs.m_lastCheckedCamera; + swap(m_lastCheckedCamera, rhs.m_lastCheckedCamera); } double Route::GetTotalDistanceMeters() const diff --git a/routing/route.hpp b/routing/route.hpp index 7260282922..cdf5822a6d 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -22,11 +22,10 @@ class Index; namespace routing { -/// Speed cameras structure. First is reference to point, second is a speed limit. struct SpeedCameraRestriction { - uint32_t m_index; - uint8_t m_maxSpeed; + uint32_t m_index; // Index of a polyline point where camera is located. + uint8_t m_maxSpeed; // Maximum speed allowed by the camera. SpeedCameraRestriction(uint32_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeed(maxSpeed) {} }; @@ -90,6 +89,11 @@ public: /// \param distanceToTurnMeters is a distance from current position to the nearest turn. /// \param turn is information about the nearest turn. bool GetCurrentTurn(double & distanceToTurnMeters, turns::TurnItem & turn) const; + + /// Returns a nearest speed camera record on your way and distance to it. + /// Returns kInvalidSpeedCameraDistance if there is no cameras on your way. + double GetCurrentCam(SpeedCameraRestriction & camera, Index const & index) const; + /// @return true if GetNextTurn() returns a valid result in parameters, false otherwise. /// \param distanceToTurnMeters is a distance from current position to the second turn. /// \param turn is information about the second turn. diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index c0e2f50d61..b366ad0a81 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -32,7 +32,7 @@ double constexpr kSpeedCameraMinimalWarningMeters = 200.; // Seconds to warning user before speed camera for driving with current speed. double constexpr kSpeedCameraWarningSeconds = 30; -double constexpr kMpsToKmh = 1000. / 3600.; +double constexpr kMpsToKmh = 3600. / 1000.; } // namespace namespace routing @@ -219,7 +219,8 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info, Index const & i formatDistFn(m_route.GetCurrentDistanceToEndMeters(), info.m_distToTarget, info.m_targetUnitsSuffix); - double distanceToTurnMeters = 0., distanceToNextTurnMeters = 0.; + double distanceToTurnMeters = 0.; + double distanceToNextTurnMeters = 0.; turns::TurnItem turn; turns::TurnItem nextTurn; m_route.GetCurrentTurn(distanceToTurnMeters, turn); diff --git a/routing/speed_camera.cpp b/routing/speed_camera.cpp index 0d1ab450f0..099dc39f81 100644 --- a/routing/speed_camera.cpp +++ b/routing/speed_camera.cpp @@ -22,8 +22,8 @@ uint8_t ReadCamRestriction(FeatureType & ft) { using feature::Metadata; ft.ParseMetadata(); - feature::Metadata const & mt = ft.GetMetadata(); - string const & speed = mt.Get(Metadata::FMD_MAXSPEED); + feature::Metadata const & md = ft.GetMetadata(); + string const & speed = md.Get(Metadata::FMD_MAXSPEED); if (!speed.length()) return 0; int result; From 513a61ea0c7868b636eebb705ea6097cdb6deea2 Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Sat, 26 Sep 2015 13:15:23 +0300 Subject: [PATCH 05/12] Move a speedcam calculation to the OnPositionChanged method. --- map/framework.cpp | 2 +- map/framework.hpp | 2 +- routing/routing_session.cpp | 48 +++++++++++++++++++++---------------- routing/routing_session.hpp | 12 ++++++---- 4 files changed, 38 insertions(+), 26 deletions(-) diff --git a/map/framework.cpp b/map/framework.cpp index 251cc808fb..b894790e99 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2290,7 +2290,7 @@ void Framework::CheckLocationForRouting(GpsInfo const & info) return; m2::PointD const & position = GetLocationState()->Position(); - if (m_routingSession.OnLocationPositionChanged(position, info) == RoutingSession::RouteNeedRebuild) + if (m_routingSession.OnLocationPositionChanged(position, info, m_model.GetIndex()) == RoutingSession::RouteNeedRebuild) { auto readyCallback = [this](Route const & route, IRouter::ResultCode code) { diff --git a/map/framework.hpp b/map/framework.hpp index a91f31afbc..2d30557cd8 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -595,7 +595,7 @@ public: void SetRouteProgressListener(TRouteProgressCallback const & progressCallback) { m_progressCallback = progressCallback; } void FollowRoute(); void CloseRouting(); - void GetRouteFollowingInfo(location::FollowingInfo & info) const { m_routingSession.GetRouteFollowingInfo(info, m_model.GetIndex()); } + void GetRouteFollowingInfo(location::FollowingInfo & info) const { m_routingSession.GetRouteFollowingInfo(info); } m2::PointD GetRouteEndPoint() const { return m_routingSession.GetEndPoint(); } void SetLastUsedRouter(routing::RouterType type); /// Returns the most situable router engine type. Bases on distance and the last used router. diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index b366ad0a81..8045f1ab83 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -43,7 +43,8 @@ RoutingSession::RoutingSession() m_route(string()), m_state(RoutingNotActive), m_endPoint(m2::PointD::Zero()), - m_speedMpS(0), + m_lastWarnedSpeedCamera(0), + m_speedWarningSignal(false), m_passedDistanceOnRouteMeters(0.0) { } @@ -131,10 +132,12 @@ void RoutingSession::Reset() m_passedDistanceOnRouteMeters = 0.0; m_lastWarnedSpeedCamera = 0; + m_speedWarningSignal = false; } RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const & position, - GpsInfo const & info) + GpsInfo const & info, + Index const & index) { ASSERT(m_state != RoutingNotActive, ()); ASSERT(m_router != nullptr, ()); @@ -148,7 +151,6 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const ASSERT(m_route.IsValid(), ()); m_turnsSound.SetSpeedMetersPerSecond(info.m_speed); - m_speedMpS = info.m_speed; if (m_route.MoveIterator(info)) { @@ -165,7 +167,26 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const alohalytics::LogEvent("RouteTracking_ReachedDestination", params); } else + { m_state = OnRoute; + + // Warning signals checks + if (m_routingSettings.m_speedCameraWarning && !m_speedWarningSignal) + { + double const warningDistanceM = max(kSpeedCameraMinimalWarningMeters, + info.m_speed * kSpeedCameraWarningSeconds); + SpeedCameraRestriction cam(0, 0); + double const camDistance = m_route.GetCurrentCam(cam, index); + if (Route::kInvalidSpeedCameraDistance != camDistance && camDistance < warningDistanceM) + { + if (cam.m_index > m_lastWarnedSpeedCamera && info.m_speed > cam.m_maxSpeed * kMpsToKmh) + { + m_speedWarningSignal = true; + m_lastWarnedSpeedCamera = cam.m_index; + } + } + } + } m_lastGoodPosition = position; } else @@ -194,7 +215,7 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const return m_state; } -void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info, Index const & index) const +void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const { auto formatDistFn = [](double dist, string & value, string & suffix) { @@ -271,22 +292,9 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info, Index const & i info.m_lanes.clear(); } - // Warning signals checks - if (m_routingSettings.m_speedCameraWarning) - { - double const warningDistanceM = max(kSpeedCameraMinimalWarningMeters, - m_speedMpS * kSpeedCameraWarningSeconds); - SpeedCameraRestriction cam(0, 0); - double const camDistance = m_route.GetCurrentCam(cam, index); - if (Route::kInvalidSpeedCameraDistance != camDistance && camDistance < warningDistanceM) - { - if (cam.m_index > m_lastWarnedSpeedCamera && m_speedMpS > cam.m_maxSpeed * kMpsToKmh) - { - info.m_speedWarningSignal = true; - m_lastWarnedSpeedCamera = cam.m_index; - } - } - } + // Speedcam signal information. + info.m_speedWarningSignal = m_speedWarningSignal; + m_speedWarningSignal = false; // Pedestrian info m2::PointD pos; diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index f6880f944b..ab12c7214d 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -77,8 +77,9 @@ public: bool IsOnRoute() const { return (m_state == OnRoute); } void Reset(); - State OnLocationPositionChanged(m2::PointD const & position, location::GpsInfo const & info); - void GetRouteFollowingInfo(location::FollowingInfo & info, Index const & index) const; + State OnLocationPositionChanged(m2::PointD const & position, location::GpsInfo const & info, + Index const & index); + void GetRouteFollowingInfo(location::FollowingInfo & info) const; void MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo) const; @@ -124,8 +125,11 @@ private: Route m_route; State m_state; m2::PointD m_endPoint; - double m_speedMpS; - mutable size_t m_lastWarnedSpeedCamera; + size_t m_lastWarnedSpeedCamera; + // TODO (ldragunov) Rewrite UI interop to message queue and avoid mutable. + /// It is mutable, because a speed warning ring must be only one time per camera. So we need + /// to modify it in a getter. + mutable bool m_speedWarningSignal; mutable threads::Mutex m_routeSessionMutex; From 37d22d29373bf0c8b5dc8d08ea1075f640cccfab Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Mon, 28 Sep 2015 11:51:05 +0300 Subject: [PATCH 06/12] More PR fixes. --- generator/osm2meta.hpp | 2 +- indexer/ftypes_matcher.hpp | 2 +- routing/route.cpp | 2 +- routing/routing_session.cpp | 4 ++-- routing/routing_session.hpp | 4 ++-- routing/speed_camera.cpp | 13 ++++++++----- routing/speed_camera.hpp | 2 +- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/generator/osm2meta.hpp b/generator/osm2meta.hpp index 0297a29435..b94efcc01a 100644 --- a/generator/osm2meta.hpp +++ b/generator/osm2meta.hpp @@ -125,7 +125,7 @@ protected: string ValidateAndFormat_maxspeed(string const & v) const { - static ftypes::IsSpeedCamChecker const IsSpeedCam; + static ftypes::IsSpeedCamChecker const & IsSpeedCam = ftypes::IsSpeedCamChecker::Instance(); if (!IsSpeedCam(m_params.m_Types)) return string(); diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index 6a2a98b698..9d985fe0d5 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -48,9 +48,9 @@ public: class IsSpeedCamChecker : public BaseChecker { -public: IsSpeedCamChecker(); +public: static IsSpeedCamChecker const & Instance(); }; diff --git a/routing/route.cpp b/routing/route.cpp index 856cfb907b..282fc2f1aa 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -1,6 +1,6 @@ #include "route.hpp" -#include "turns_generator.hpp" #include "speed_camera.hpp" +#include "turns_generator.hpp" #include "indexer/mercator.hpp" diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index 8045f1ab83..c6cf6e413c 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -32,7 +32,7 @@ double constexpr kSpeedCameraMinimalWarningMeters = 200.; // Seconds to warning user before speed camera for driving with current speed. double constexpr kSpeedCameraWarningSeconds = 30; -double constexpr kMpsToKmh = 3600. / 1000.; +double constexpr kKmhToMps = 1000. / 3600.; } // namespace namespace routing @@ -179,7 +179,7 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const double const camDistance = m_route.GetCurrentCam(cam, index); if (Route::kInvalidSpeedCameraDistance != camDistance && camDistance < warningDistanceM) { - if (cam.m_index > m_lastWarnedSpeedCamera && info.m_speed > cam.m_maxSpeed * kMpsToKmh) + if (cam.m_index > m_lastWarnedSpeedCamera && info.m_speed > cam.m_maxSpeed * kKmhToMps) { m_speedWarningSignal = true; m_lastWarnedSpeedCamera = cam.m_index; diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index ab12c7214d..858c922f81 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -127,8 +127,8 @@ private: m2::PointD m_endPoint; size_t m_lastWarnedSpeedCamera; // TODO (ldragunov) Rewrite UI interop to message queue and avoid mutable. - /// It is mutable, because a speed warning ring must be only one time per camera. So we need - /// to modify it in a getter. + /// This field is mutable because it's modified in a constant getter. Note that the notification + /// about camera will be sent at most once. mutable bool m_speedWarningSignal; mutable threads::Mutex m_routeSessionMutex; diff --git a/routing/speed_camera.cpp b/routing/speed_camera.cpp index 099dc39f81..76248b0fcd 100644 --- a/routing/speed_camera.cpp +++ b/routing/speed_camera.cpp @@ -5,20 +5,22 @@ #include "indexer/index.hpp" #include "indexer/scales.hpp" +#include "coding/read_write_utils.hpp" #include "coding/reader.hpp" #include "coding/writer.hpp" -#include "coding/read_write_utils.hpp" #include "base/string_utils.hpp" namespace { -double constexpr kMwmReadingRadiusMeters = 2.0; +double constexpr kCameraCheckRadiusMeters = 2.0; } // namespace namespace routing { -uint8_t ReadCamRestriction(FeatureType & ft) +uint8_t const kNoSpeedCamera = numeric_limits::max(); + +uint8_t ReadCameraRestriction(FeatureType & ft) { using feature::Metadata; ft.ParseMetadata(); @@ -46,11 +48,12 @@ uint8_t CheckCameraInPoint(m2::PointD const & point, Index const & index) ft.ParseGeometry(FeatureType::BEST_GEOMETRY); if (ft.GetCenter() == point) - speedLimit = ReadCamRestriction(ft); + speedLimit = ReadCameraRestriction(ft); }; index.ForEachInRect(f, - MercatorBounds::RectByCenterXYAndSizeInMeters(point, kMwmReadingRadiusMeters), + MercatorBounds::RectByCenterXYAndSizeInMeters(point, + kCameraCheckRadiusMeters), scales::GetUpperScale()); return speedLimit; } diff --git a/routing/speed_camera.hpp b/routing/speed_camera.hpp index 693048d231..ec0135adf6 100644 --- a/routing/speed_camera.hpp +++ b/routing/speed_camera.hpp @@ -10,6 +10,6 @@ class Index; namespace routing { -uint8_t constexpr kNoSpeedCamera = numeric_limits::max(); +extern uint8_t const kNoSpeedCamera; uint8_t CheckCameraInPoint(m2::PointD const & point, Index const & index); } // namespace routing From 41be2c71da413d654fdff23f23edc2c4b9e02cbc Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Wed, 30 Sep 2015 20:11:08 +0300 Subject: [PATCH 07/12] Extract GetCurrentCam method to the routing session. --- routing/route.cpp | 4 +--- routing/route.hpp | 22 +++------------------ routing/routing_mapping.hpp | 1 - routing/routing_session.cpp | 38 ++++++++++++++++++++++++++++++++++--- routing/routing_session.hpp | 7 +++++++ 5 files changed, 46 insertions(+), 26 deletions(-) diff --git a/routing/route.cpp b/routing/route.cpp index 282fc2f1aa..cdd8e3c471 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -1,5 +1,4 @@ #include "route.hpp" -#include "speed_camera.hpp" #include "turns_generator.hpp" #include "indexer/mercator.hpp" @@ -28,7 +27,7 @@ double constexpr kOnEndToleranceM = 10.0; Route::Route(string const & router, vector const & points, string const & name) : m_router(router), m_routingSettings(GetCarRoutingSettings()), - m_name(name), m_poly(points.begin(), points.end()), m_lastCheckedCamera(0) + m_name(name), m_poly(points.begin(), points.end()) { Update(); } @@ -44,7 +43,6 @@ void Route::Swap(Route & rhs) swap(m_turns, rhs.m_turns); swap(m_times, rhs.m_times); m_absentCountries.swap(rhs.m_absentCountries); - swap(m_lastCheckedCamera, rhs.m_lastCheckedCamera); } double Route::GetTotalDistanceMeters() const diff --git a/routing/route.hpp b/routing/route.hpp index cdf5822a6d..eb3ca74801 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -17,19 +17,9 @@ namespace location class RouteMatchingInfo; } -class Index; - namespace routing { -struct SpeedCameraRestriction -{ - uint32_t m_index; // Index of a polyline point where camera is located. - uint8_t m_maxSpeed; // Maximum speed allowed by the camera. - - SpeedCameraRestriction(uint32_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeed(maxSpeed) {} -}; - class Route { public: @@ -37,15 +27,12 @@ public: typedef pair TTimeItem; typedef vector TTimes; - static double constexpr kInvalidSpeedCameraDistance = -1; - explicit Route(string const & router) : m_router(router), m_routingSettings(GetCarRoutingSettings()) {} template Route(string const & router, TIter beg, TIter end) - : m_router(router), m_routingSettings(GetCarRoutingSettings()), m_poly(beg, end), - m_lastCheckedCamera(0) + : m_router(router), m_routingSettings(GetCarRoutingSettings()), m_poly(beg, end) { Update(); } @@ -73,6 +60,8 @@ public: uint32_t GetTotalTimeSec() const; uint32_t GetCurrentTimeToEndSec() const; + FollowedPolyline const & GetFollowedPolyline() const {return m_poly;} + string const & GetRouterId() const { return m_router; } m2::PolylineD const & GetPoly() const { return m_poly.GetPolyline(); } TTurns const & GetTurns() const { return m_turns; } @@ -90,10 +79,6 @@ public: /// \param turn is information about the nearest turn. bool GetCurrentTurn(double & distanceToTurnMeters, turns::TurnItem & turn) const; - /// Returns a nearest speed camera record on your way and distance to it. - /// Returns kInvalidSpeedCameraDistance if there is no cameras on your way. - double GetCurrentCam(SpeedCameraRestriction & camera, Index const & index) const; - /// @return true if GetNextTurn() returns a valid result in parameters, false otherwise. /// \param distanceToTurnMeters is a distance from current position to the second turn. /// \param turn is information about the second turn. @@ -151,7 +136,6 @@ private: TTimes m_times; mutable double m_currentTime; - mutable size_t m_lastCheckedCamera; }; } // namespace routing diff --git a/routing/routing_mapping.hpp b/routing/routing_mapping.hpp index c3efddf621..866de8ea9b 100644 --- a/routing/routing_mapping.hpp +++ b/routing/routing_mapping.hpp @@ -3,7 +3,6 @@ #include "osrm2feature_map.hpp" #include "osrm_data_facade.hpp" #include "router.hpp" -#include "speed_camera.hpp" #include "indexer/index.hpp" diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index c6cf6e413c..66b4054193 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -1,4 +1,6 @@ -#include "routing/routing_session.hpp" +#include "routing_session.hpp" + +#include "speed_camera.hpp" #include "indexer/mercator.hpp" @@ -33,10 +35,19 @@ double constexpr kSpeedCameraMinimalWarningMeters = 200.; double constexpr kSpeedCameraWarningSeconds = 30; double constexpr kKmhToMps = 1000. / 3600.; + +static double constexpr kInvalidSpeedCameraDistance = -1; } // namespace namespace routing { +struct SpeedCameraRestriction +{ + uint32_t m_index; // Index of a polyline point where camera is located. + uint8_t m_maxSpeed; // Maximum speed allowed by the camera. + + SpeedCameraRestriction(uint32_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeed(maxSpeed) {} +}; RoutingSession::RoutingSession() : m_router(nullptr), @@ -44,6 +55,7 @@ RoutingSession::RoutingSession() m_state(RoutingNotActive), m_endPoint(m2::PointD::Zero()), m_lastWarnedSpeedCamera(0), + m_lastCheckedCamera(0), m_speedWarningSignal(false), m_passedDistanceOnRouteMeters(0.0) { @@ -132,6 +144,7 @@ void RoutingSession::Reset() m_passedDistanceOnRouteMeters = 0.0; m_lastWarnedSpeedCamera = 0; + m_lastCheckedCamera = 0; m_speedWarningSignal = false; } @@ -176,8 +189,8 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const double const warningDistanceM = max(kSpeedCameraMinimalWarningMeters, info.m_speed * kSpeedCameraWarningSeconds); SpeedCameraRestriction cam(0, 0); - double const camDistance = m_route.GetCurrentCam(cam, index); - if (Route::kInvalidSpeedCameraDistance != camDistance && camDistance < warningDistanceM) + double const camDistance = GetCurrentCam(cam, index); + if (kInvalidSpeedCameraDistance != camDistance && camDistance < warningDistanceM) { if (cam.m_index > m_lastWarnedSpeedCamera && info.m_speed > cam.m_maxSpeed * kKmhToMps) { @@ -340,6 +353,7 @@ void RoutingSession::AssignRoute(Route & route, IRouter::ResultCode e) route.SetRoutingSettings(m_routingSettings); m_route.Swap(route); m_lastWarnedSpeedCamera = 0; + m_lastCheckedCamera = 0; } void RoutingSession::SetRouter(unique_ptr && router, @@ -418,4 +432,22 @@ string RoutingSession::GetTurnNotificationsLocale() const UNUSED_VALUE(guard); return m_turnsSound.GetLocale(); } + +double RoutingSession::GetCurrentCam(SpeedCameraRestriction & camera, Index const & index) +{ + auto const & m_poly = m_route.GetFollowedPolyline(); + size_t const currentIndex = max(m_poly.GetCurrentIter().m_ind, m_lastCheckedCamera); + for (size_t i = currentIndex; i < m_poly.GetPolyline().GetSize(); ++i) + { + uint8_t speed = CheckCameraInPoint(m_poly.GetPolyline().GetPoint(i), index); + if (speed != kNoSpeedCamera) + { + camera = SpeedCameraRestriction(static_cast(i), speed); + m_lastCheckedCamera = i; + return m_poly.GetDistanceM(m_poly.GetCurrentIter(), m_poly.GetIterToIndex(i)); + } + } + m_lastCheckedCamera = m_poly.GetPolyline().GetSize(); + return kInvalidSpeedCameraDistance; +} } // namespace routing diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index 858c922f81..04b3fef8c5 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -23,6 +23,8 @@ class RouteMatchingInfo; namespace routing { +struct SpeedCameraRestriction; + class RoutingSession { public: @@ -116,6 +118,10 @@ private: void AssignRoute(Route & route, IRouter::ResultCode e); + /// Returns a nearest speed camera record on your way and distance to it. + /// Returns kInvalidSpeedCameraDistance if there is no cameras on your way. + double GetCurrentCam(SpeedCameraRestriction & camera, Index const & index); + /// RemoveRoute removes m_route and resets route attributes (m_state, m_lastDistance, m_moveAwayCounter). void RemoveRoute(); void RemoveRouteImpl(); @@ -126,6 +132,7 @@ private: State m_state; m2::PointD m_endPoint; size_t m_lastWarnedSpeedCamera; + size_t m_lastCheckedCamera; // TODO (ldragunov) Rewrite UI interop to message queue and avoid mutable. /// This field is mutable because it's modified in a constant getter. Note that the notification /// about camera will be sent at most once. From d9f39989f3ef06ad60f7a2463258a0765b4d810d Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Thu, 1 Oct 2015 17:39:20 +0300 Subject: [PATCH 08/12] PR fixes. --- routing/route.hpp | 2 +- routing/routing_session.cpp | 34 +++++++++++++++++----------------- routing/routing_session.hpp | 6 +++--- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/routing/route.hpp b/routing/route.hpp index eb3ca74801..fe3f56f14c 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -60,7 +60,7 @@ public: uint32_t GetTotalTimeSec() const; uint32_t GetCurrentTimeToEndSec() const; - FollowedPolyline const & GetFollowedPolyline() const {return m_poly;} + FollowedPolyline const & GetFollowedPolyline() const { return m_poly; } string const & GetRouterId() const { return m_router; } m2::PolylineD const & GetPoly() const { return m_poly.GetPolyline(); } diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index 66b4054193..60a73af604 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -34,9 +34,9 @@ double constexpr kSpeedCameraMinimalWarningMeters = 200.; // Seconds to warning user before speed camera for driving with current speed. double constexpr kSpeedCameraWarningSeconds = 30; -double constexpr kKmhToMps = 1000. / 3600.; +double constexpr kKmHToMps = 1000. / 3600.; -static double constexpr kInvalidSpeedCameraDistance = -1; +double constexpr kInvalidSpeedCameraDistance = -1; } // namespace namespace routing @@ -44,9 +44,9 @@ namespace routing struct SpeedCameraRestriction { uint32_t m_index; // Index of a polyline point where camera is located. - uint8_t m_maxSpeed; // Maximum speed allowed by the camera. + uint8_t m_maxSpeedKmH; // Maximum speed allowed by the camera. - SpeedCameraRestriction(uint32_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeed(maxSpeed) {} + SpeedCameraRestriction(uint32_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeedKmH(maxSpeed) {} }; RoutingSession::RoutingSession() @@ -54,8 +54,8 @@ RoutingSession::RoutingSession() m_route(string()), m_state(RoutingNotActive), m_endPoint(m2::PointD::Zero()), - m_lastWarnedSpeedCamera(0), - m_lastCheckedCamera(0), + m_lastWarnedSpeedCameraIndex(0), + m_lastCheckedCameraIndex(0), m_speedWarningSignal(false), m_passedDistanceOnRouteMeters(0.0) { @@ -143,8 +143,8 @@ void RoutingSession::Reset() m_turnsSound.Reset(); m_passedDistanceOnRouteMeters = 0.0; - m_lastWarnedSpeedCamera = 0; - m_lastCheckedCamera = 0; + m_lastWarnedSpeedCameraIndex = 0; + m_lastCheckedCameraIndex = 0; m_speedWarningSignal = false; } @@ -189,13 +189,13 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const double const warningDistanceM = max(kSpeedCameraMinimalWarningMeters, info.m_speed * kSpeedCameraWarningSeconds); SpeedCameraRestriction cam(0, 0); - double const camDistance = GetCurrentCam(cam, index); + double const camDistance = GetDistanceToCurrentCamM(cam, index); if (kInvalidSpeedCameraDistance != camDistance && camDistance < warningDistanceM) { - if (cam.m_index > m_lastWarnedSpeedCamera && info.m_speed > cam.m_maxSpeed * kKmhToMps) + if (cam.m_index > m_lastWarnedSpeedCameraIndex && info.m_speed > cam.m_maxSpeedKmH * kKmHToMps) { m_speedWarningSignal = true; - m_lastWarnedSpeedCamera = cam.m_index; + m_lastWarnedSpeedCameraIndex = cam.m_index; } } } @@ -352,8 +352,8 @@ void RoutingSession::AssignRoute(Route & route, IRouter::ResultCode e) route.SetRoutingSettings(m_routingSettings); m_route.Swap(route); - m_lastWarnedSpeedCamera = 0; - m_lastCheckedCamera = 0; + m_lastWarnedSpeedCameraIndex = 0; + m_lastCheckedCameraIndex = 0; } void RoutingSession::SetRouter(unique_ptr && router, @@ -433,21 +433,21 @@ string RoutingSession::GetTurnNotificationsLocale() const return m_turnsSound.GetLocale(); } -double RoutingSession::GetCurrentCam(SpeedCameraRestriction & camera, Index const & index) +double RoutingSession::GetDistanceToCurrentCamM(SpeedCameraRestriction & camera, Index const & index) { auto const & m_poly = m_route.GetFollowedPolyline(); - size_t const currentIndex = max(m_poly.GetCurrentIter().m_ind, m_lastCheckedCamera); + size_t const currentIndex = max(m_poly.GetCurrentIter().m_ind, m_lastCheckedCameraIndex); for (size_t i = currentIndex; i < m_poly.GetPolyline().GetSize(); ++i) { uint8_t speed = CheckCameraInPoint(m_poly.GetPolyline().GetPoint(i), index); if (speed != kNoSpeedCamera) { camera = SpeedCameraRestriction(static_cast(i), speed); - m_lastCheckedCamera = i; + m_lastCheckedCameraIndex = i; return m_poly.GetDistanceM(m_poly.GetCurrentIter(), m_poly.GetIterToIndex(i)); } } - m_lastCheckedCamera = m_poly.GetPolyline().GetSize(); + m_lastCheckedCameraIndex = m_poly.GetPolyline().GetSize(); return kInvalidSpeedCameraDistance; } } // namespace routing diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index 04b3fef8c5..35ed0fe38f 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -120,7 +120,7 @@ private: /// Returns a nearest speed camera record on your way and distance to it. /// Returns kInvalidSpeedCameraDistance if there is no cameras on your way. - double GetCurrentCam(SpeedCameraRestriction & camera, Index const & index); + double GetDistanceToCurrentCamM(SpeedCameraRestriction & camera, Index const & index); /// RemoveRoute removes m_route and resets route attributes (m_state, m_lastDistance, m_moveAwayCounter). void RemoveRoute(); @@ -131,8 +131,8 @@ private: Route m_route; State m_state; m2::PointD m_endPoint; - size_t m_lastWarnedSpeedCamera; - size_t m_lastCheckedCamera; + size_t m_lastWarnedSpeedCameraIndex; + size_t m_lastCheckedCameraIndex; // TODO (ldragunov) Rewrite UI interop to message queue and avoid mutable. /// This field is mutable because it's modified in a constant getter. Note that the notification /// about camera will be sent at most once. From e481c43dedcea9914b1f77f1a6db8e1ed451e2ed Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Fri, 2 Oct 2015 12:57:57 +0300 Subject: [PATCH 09/12] Speed camera point equality fix. --- generator/osm2meta.hpp | 3 +-- routing/routing_session.cpp | 1 + routing/speed_camera.cpp | 9 +++++++-- routing/speed_camera.hpp | 5 ++--- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/generator/osm2meta.hpp b/generator/osm2meta.hpp index b94efcc01a..825ca8dfce 100644 --- a/generator/osm2meta.hpp +++ b/generator/osm2meta.hpp @@ -125,8 +125,7 @@ protected: string ValidateAndFormat_maxspeed(string const & v) const { - static ftypes::IsSpeedCamChecker const & IsSpeedCam = ftypes::IsSpeedCamChecker::Instance(); - if (!IsSpeedCam(m_params.m_Types)) + if (!ftypes::IsSpeedCamChecker::Instance()(m_params.m_Types)) return string(); return v; diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index 60a73af604..a89acb5311 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -297,6 +297,7 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const // for each lane's directions. The size of turn.m_lanes is relatively small. Less than 10 in // most cases. info.m_lanes.clear(); + info.m_lanes.reserve(turn.m_lanes.size()); for (size_t j = 0; j < turn.m_lanes.size(); ++j) info.m_lanes.emplace_back(turn.m_lanes[j]); } diff --git a/routing/speed_camera.cpp b/routing/speed_camera.cpp index 76248b0fcd..ba679770b7 100644 --- a/routing/speed_camera.cpp +++ b/routing/speed_camera.cpp @@ -10,10 +10,14 @@ #include "coding/writer.hpp" #include "base/string_utils.hpp" +#include "base/math.hpp" + +#include "std/limits.hpp" namespace { double constexpr kCameraCheckRadiusMeters = 2.0; +double constexpr kCoordinateEqualityDelta = 0.000001; } // namespace namespace routing @@ -26,7 +30,7 @@ uint8_t ReadCameraRestriction(FeatureType & ft) ft.ParseMetadata(); feature::Metadata const & md = ft.GetMetadata(); string const & speed = md.Get(Metadata::FMD_MAXSPEED); - if (!speed.length()) + if (speed.empty()) return 0; int result; strings::to_int(speed, result); @@ -47,7 +51,8 @@ uint8_t CheckCameraInPoint(m2::PointD const & point, Index const & index) return; ft.ParseGeometry(FeatureType::BEST_GEOMETRY); - if (ft.GetCenter() == point) + if (my::AlmostEqualAbs(ft.GetCenter().x, point.x, kCoordinateEqualityDelta) && + my::AlmostEqualAbs(ft.GetCenter().y, point.y, kCoordinateEqualityDelta)) speedLimit = ReadCameraRestriction(ft); }; diff --git a/routing/speed_camera.hpp b/routing/speed_camera.hpp index ec0135adf6..29e76635f3 100644 --- a/routing/speed_camera.hpp +++ b/routing/speed_camera.hpp @@ -2,14 +2,13 @@ #include "geometry/point2d.hpp" -#include "base/base.hpp" - -#include "std/limits.hpp" +#include "std/cstdint.hpp" class Index; namespace routing { extern uint8_t const kNoSpeedCamera; + uint8_t CheckCameraInPoint(m2::PointD const & point, Index const & index); } // namespace routing From 2bc9bf11918092df7fede99a39e4176a535d0d6b Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Fri, 2 Oct 2015 15:32:59 +0300 Subject: [PATCH 10/12] Reduce speedcam geometry index reading. --- routing/routing_session.cpp | 29 ++++++++++++++--------------- routing/routing_session.hpp | 12 ++++++++++-- routing/speed_camera.cpp | 1 - 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index a89acb5311..a00e116fd1 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -41,21 +41,12 @@ double constexpr kInvalidSpeedCameraDistance = -1; namespace routing { -struct SpeedCameraRestriction -{ - uint32_t m_index; // Index of a polyline point where camera is located. - uint8_t m_maxSpeedKmH; // Maximum speed allowed by the camera. - - SpeedCameraRestriction(uint32_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeedKmH(maxSpeed) {} -}; - RoutingSession::RoutingSession() : m_router(nullptr), m_route(string()), m_state(RoutingNotActive), m_endPoint(m2::PointD::Zero()), m_lastWarnedSpeedCameraIndex(0), - m_lastCheckedCameraIndex(0), m_speedWarningSignal(false), m_passedDistanceOnRouteMeters(0.0) { @@ -144,7 +135,7 @@ void RoutingSession::Reset() m_passedDistanceOnRouteMeters = 0.0; m_lastWarnedSpeedCameraIndex = 0; - m_lastCheckedCameraIndex = 0; + m_lastCheckedCamera = SpeedCameraRestriction(); m_speedWarningSignal = false; } @@ -354,7 +345,7 @@ void RoutingSession::AssignRoute(Route & route, IRouter::ResultCode e) route.SetRoutingSettings(m_routingSettings); m_route.Swap(route); m_lastWarnedSpeedCameraIndex = 0; - m_lastCheckedCameraIndex = 0; + m_lastCheckedCamera = SpeedCameraRestriction(); } void RoutingSession::SetRouter(unique_ptr && router, @@ -437,18 +428,26 @@ string RoutingSession::GetTurnNotificationsLocale() const double RoutingSession::GetDistanceToCurrentCamM(SpeedCameraRestriction & camera, Index const & index) { auto const & m_poly = m_route.GetFollowedPolyline(); - size_t const currentIndex = max(m_poly.GetCurrentIter().m_ind, m_lastCheckedCameraIndex); + auto const & currentIter = m_poly.GetCurrentIter(); + if (currentIter.m_ind < m_lastCheckedCamera.m_index && + m_lastCheckedCamera.m_index < m_poly.GetPolyline().GetSize()) + { + camera = m_lastCheckedCamera; + return m_poly.GetDistanceM(currentIter, m_poly.GetIterToIndex(camera.m_index)); + } + size_t const currentIndex = max(static_cast(currentIter.m_ind), + static_cast(m_lastCheckedCamera.m_index) + 1); for (size_t i = currentIndex; i < m_poly.GetPolyline().GetSize(); ++i) { uint8_t speed = CheckCameraInPoint(m_poly.GetPolyline().GetPoint(i), index); if (speed != kNoSpeedCamera) { camera = SpeedCameraRestriction(static_cast(i), speed); - m_lastCheckedCameraIndex = i; - return m_poly.GetDistanceM(m_poly.GetCurrentIter(), m_poly.GetIterToIndex(i)); + m_lastCheckedCamera = camera; + return m_poly.GetDistanceM(currentIter, m_poly.GetIterToIndex(i)); } } - m_lastCheckedCameraIndex = m_poly.GetPolyline().GetSize(); + m_lastCheckedCamera.m_index = m_poly.GetPolyline().GetSize(); return kInvalidSpeedCameraDistance; } } // namespace routing diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index 35ed0fe38f..880a66e790 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -14,6 +14,7 @@ #include "base/deferred_task.hpp" #include "base/mutex.hpp" +#include "std/limits.hpp" #include "std/unique_ptr.hpp" namespace location @@ -23,7 +24,14 @@ class RouteMatchingInfo; namespace routing { -struct SpeedCameraRestriction; +struct SpeedCameraRestriction +{ + uint32_t m_index; // Index of a polyline point where camera is located. + uint8_t m_maxSpeedKmH; // Maximum speed allowed by the camera. + + SpeedCameraRestriction(uint32_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeedKmH(maxSpeed) {} + SpeedCameraRestriction() : m_index(0), m_maxSpeedKmH(numeric_limits::max()) {} +}; class RoutingSession { @@ -132,7 +140,7 @@ private: State m_state; m2::PointD m_endPoint; size_t m_lastWarnedSpeedCameraIndex; - size_t m_lastCheckedCameraIndex; + SpeedCameraRestriction m_lastCheckedCamera; // TODO (ldragunov) Rewrite UI interop to message queue and avoid mutable. /// This field is mutable because it's modified in a constant getter. Note that the notification /// about camera will be sent at most once. diff --git a/routing/speed_camera.cpp b/routing/speed_camera.cpp index ba679770b7..5127ff023c 100644 --- a/routing/speed_camera.cpp +++ b/routing/speed_camera.cpp @@ -50,7 +50,6 @@ uint8_t CheckCameraInPoint(m2::PointD const & point, Index const & index) if (!ftypes::IsSpeedCamChecker::Instance()(hl)) return; - ft.ParseGeometry(FeatureType::BEST_GEOMETRY); if (my::AlmostEqualAbs(ft.GetCenter().x, point.x, kCoordinateEqualityDelta) && my::AlmostEqualAbs(ft.GetCenter().y, point.y, kCoordinateEqualityDelta)) speedLimit = ReadCameraRestriction(ft); From 86b1328a3500f2d8a65da1f753923a71892ae07a Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Wed, 7 Oct 2015 15:27:26 +0300 Subject: [PATCH 11/12] Fixes after rabase. --- routing/route.cpp | 17 ----------------- routing/route.hpp | 2 -- 2 files changed, 19 deletions(-) diff --git a/routing/route.cpp b/routing/route.cpp index cdd8e3c471..602ff31dac 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -148,23 +148,6 @@ Route::TTurns::const_iterator Route::GetCurrentTurn() const }); } -double Route::GetCurrentCam(SpeedCameraRestriction & camera, Index const & index) const -{ - size_t const currentIndex = max(m_poly.GetCurrentIter().m_ind, m_lastCheckedCamera); - for (size_t i = currentIndex; i < m_poly.GetPolyline().GetSize(); ++i) - { - uint8_t speed = CheckCameraInPoint(m_poly.GetPolyline().GetPoint(i), index); - if (speed != kNoSpeedCamera) - { - camera = SpeedCameraRestriction(static_cast(i), speed); - m_lastCheckedCamera = i; - return m_poly.GetDistanceM(m_poly.GetCurrentIter(), m_poly.GetIterToIndex(i)); - } - } - m_lastCheckedCamera = m_poly.GetPolyline().GetSize(); - return kInvalidSpeedCameraDistance; -} - bool Route::GetCurrentTurn(double & distanceToTurnMeters, turns::TurnItem & turn) const { auto it = GetCurrentTurn(); diff --git a/routing/route.hpp b/routing/route.hpp index fe3f56f14c..86f199aedd 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -88,8 +88,6 @@ public: /// \brief Extract information about zero, one or two nearest turns depending on current position. /// @return true if its parameter is filled with correct result. (At least with one element.) bool GetNextTurns(vector & turns) const; - /// Returns nearest speed camera and distance to it. - double GetCurrentCam(SpeedCameraRestriction & camera, Index const & index) const; void GetCurrentDirectionPoint(m2::PointD & pt) const; From 27c2967271dd550af145c18ff1dd38670ad78fd4 Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Wed, 7 Oct 2015 16:51:44 +0300 Subject: [PATCH 12/12] PR fixes. --- routing/routing_session.cpp | 4 ++-- routing/routing_session.hpp | 4 ++-- routing/speed_camera.cpp | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index a00e116fd1..5bd4681135 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -435,8 +435,8 @@ double RoutingSession::GetDistanceToCurrentCamM(SpeedCameraRestriction & camera, camera = m_lastCheckedCamera; return m_poly.GetDistanceM(currentIter, m_poly.GetIterToIndex(camera.m_index)); } - size_t const currentIndex = max(static_cast(currentIter.m_ind), - static_cast(m_lastCheckedCamera.m_index) + 1); + size_t const currentIndex = max(currentIter.m_ind, + m_lastCheckedCamera.m_index + 1); for (size_t i = currentIndex; i < m_poly.GetPolyline().GetSize(); ++i) { uint8_t speed = CheckCameraInPoint(m_poly.GetPolyline().GetPoint(i), index); diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index 880a66e790..3ff1de6bb4 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -26,10 +26,10 @@ namespace routing { struct SpeedCameraRestriction { - uint32_t m_index; // Index of a polyline point where camera is located. + size_t m_index; // Index of a polyline point where camera is located. uint8_t m_maxSpeedKmH; // Maximum speed allowed by the camera. - SpeedCameraRestriction(uint32_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeedKmH(maxSpeed) {} + SpeedCameraRestriction(size_t index, uint8_t maxSpeed) : m_index(index), m_maxSpeedKmH(maxSpeed) {} SpeedCameraRestriction() : m_index(0), m_maxSpeedKmH(numeric_limits::max()) {} }; diff --git a/routing/speed_camera.cpp b/routing/speed_camera.cpp index 5127ff023c..d65f7137e5 100644 --- a/routing/speed_camera.cpp +++ b/routing/speed_camera.cpp @@ -33,8 +33,9 @@ uint8_t ReadCameraRestriction(FeatureType & ft) if (speed.empty()) return 0; int result; - strings::to_int(speed, result); - return result; + if (strings::to_int(speed, result)) + return result; + return 0; } uint8_t CheckCameraInPoint(m2::PointD const & point, Index const & index)