diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index 4d52b9e8e4..cce306501b 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -61,6 +61,7 @@ std::string const kMetadataFileName = "bm.json"; std::string const kSortingTypeProperty = "sortingType"; size_t const kMinCommonTypesCount = 3; double const kNearDistanceInMeters = 20 * 1000.0; +double const kMyPositionTrackSnapInMeters = 20.0; // Returns extension with a dot in a lower case. std::string GetFileExt(std::string const & filePath) @@ -1036,6 +1037,58 @@ ElevationInfo BookmarkManager::MakeElevationInfo(kml::TrackId trackId) const return ElevationInfo(*track); } +void BookmarkManager::UpdateElevationMyPosition(kml::TrackId const & trackId) +{ + CHECK_THREAD_CHECKER(m_threadChecker, ()); + + double myPositionDistance = TrackSelectionMark::kInvalidDistance; + if (m_myPositionMark->HasPosition()) + { + double const kEps = 1e-5; + if (m_lastElevationMyPosition.EqualDxDy(m_myPositionMark->GetPivot(), kEps)) + return; + m_lastElevationMyPosition = m_myPositionMark->GetPivot(); + + auto const snapRect = mercator::RectByCenterXYAndSizeInMeters(m_myPositionMark->GetPivot(), + kMyPositionTrackSnapInMeters); + auto const selectionInfo = FindNearestTrack( + snapRect, [trackId](Track const *track) { return track->GetId() == trackId; }); + if (selectionInfo.m_trackId != trackId) + myPositionDistance = selectionInfo.m_distanceInMeters; + } + else + { + m_lastElevationMyPosition = m2::PointD::Zero(); + } + + auto const markId = GetTrackSelectionMarkId(trackId); + auto es = GetEditSession(); + auto trackSelectionMark = es.GetMarkForEdit(markId); + + trackSelectionMark->SetMyPositionDistance(myPositionDistance); + if (m_elevationMyPositionChanged) + m_elevationMyPositionChanged(); +} + +double BookmarkManager::GetElevationMyPosition(kml::TrackId const & trackId) const +{ + CHECK_THREAD_CHECKER(m_threadChecker, ()); + + auto const markId = GetTrackSelectionMarkId(trackId); + CHECK(markId != kml::kInvalidMarkId, ()); + + auto const trackSelectionMark = GetMark(markId); + return trackSelectionMark->GetMyPositionDistance(); +} + +void BookmarkManager::SetElevationMyPositionChangedCallback( + ElevationMyPositionChangedCallback const & cb) +{ + CHECK_THREAD_CHECKER(m_threadChecker, ()); + + m_elevationMyPositionChanged = cb; +} + void BookmarkManager::SetElevationActivePoint(kml::TrackId const & trackId, double targetDistance) { CHECK_THREAD_CHECKER(m_threadChecker, ()); @@ -1067,7 +1120,8 @@ void BookmarkManager::SetElevationActivePointChangedCallback(ElevationActivePoin m_elevationActivePointChanged = cb; } -BookmarkManager::TrackSelectionInfo BookmarkManager::FindNearestTrack(m2::RectD const & touchRect) const +BookmarkManager::TrackSelectionInfo BookmarkManager::FindNearestTrack( + m2::RectD const & touchRect, TracksFilter const & tracksFilter) const { CHECK_THREAD_CHECKER(m_threadChecker, ()); TrackSelectionInfo selectionInfo; @@ -1082,6 +1136,9 @@ BookmarkManager::TrackSelectionInfo BookmarkManager::FindNearestTrack(m2::RectD for (auto trackId : category.GetUserLines()) { auto const track = GetTrack(trackId); + if (tracksFilter && !tracksFilter(track)) + continue; + auto const & trackRect = track->GetLimitRect(); if (!trackRect.IsIntersect(touchRect)) diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index 0aef23ca5e..95736cc439 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -60,6 +60,7 @@ public: using BookmarksChangedCallback = std::function; using ElevationActivePointChangedCallback = std::function; + using ElevationMyPositionChangedCallback = std::function; using AsyncLoadingStartedCallback = std::function; using AsyncLoadingFinishedCallback = std::function; @@ -452,10 +453,18 @@ public: static bool IsGuide(kml::AccessRules accessRules); ElevationInfo MakeElevationInfo(kml::TrackId trackId) const; + void SetElevationActivePoint(kml::TrackId const & trackId, double distanceInMeters); - // Returns distance from start of the track to active point in meters. + // Returns distance from the start of the track to active point in meters. double GetElevationActivePoint(kml::TrackId const & trackId) const; + + void UpdateElevationMyPosition(kml::TrackId const & trackId); + // Returns distance from the start of the track to my position in meters. + // Returns negative value if my position is not on the track. + double GetElevationMyPosition(kml::TrackId const & trackId) const; + void SetElevationActivePointChangedCallback(ElevationActivePointChangedCallback const & cb); + void SetElevationMyPositionChangedCallback(ElevationMyPositionChangedCallback const & cb); struct TrackSelectionInfo { @@ -471,7 +480,9 @@ public: double m_distanceInMeters = 0.0; }; - TrackSelectionInfo FindNearestTrack(m2::RectD const & touchRect) const; + using TracksFilter = std::function; + TrackSelectionInfo FindNearestTrack(m2::RectD const & touchRect, + TracksFilter const & tracksFilter = nullptr) const; TrackSelectionInfo GetTrackSelectionInfo(kml::TrackId const & trackId) const; void SelectTrack(TrackSelectionInfo const & trackSelectionInfo); @@ -766,6 +777,9 @@ private: BookmarksChangedCallback m_categoriesChangedCallback; ElevationActivePointChangedCallback m_elevationActivePointChanged; + ElevationMyPositionChangedCallback m_elevationMyPositionChanged; + m2::PointD m_lastElevationMyPosition = m2::PointD::Zero(); + AsyncLoadingCallbacks m_asyncLoadingCallbacks; std::atomic m_needTeardown; size_t m_openedEditSessionsCount = 0; diff --git a/map/framework.cpp b/map/framework.cpp index c987d250f8..f8c560d95f 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -326,6 +326,9 @@ IsolinesManager const & Framework::GetIsolinesManager() const void Framework::OnUserPositionChanged(m2::PointD const & position, bool hasPosition) { GetBookmarkManager().MyPositionMark().SetUserPosition(position, hasPosition); + if (m_currentPlacePageInfo && m_currentPlacePageInfo->GetTrackId() != kml::kInvalidTrackId) + GetBookmarkManager().UpdateElevationMyPosition(m_currentPlacePageInfo->GetTrackId()); + m_routingManager.SetUserCurrentPosition(position); m_trafficManager.UpdateMyPosition(TrafficManager::MyPosition(position)); } @@ -2418,6 +2421,8 @@ void Framework::OnTapEvent(place_page::BuildInfo const & buildInfo) if (placePageInfo) { + auto const prevTrackId = m_currentPlacePageInfo ? m_currentPlacePageInfo->GetTrackId() + : kml::kInvalidTrackId; m_currentPlacePageInfo = placePageInfo; // Log statistics events. @@ -2484,6 +2489,14 @@ void Framework::OnTapEvent(place_page::BuildInfo const & buildInfo) {{"provider", "booking.com"}}); } } + + if (m_currentPlacePageInfo->GetTrackId() != kml::kInvalidTrackId) + { + if (m_currentPlacePageInfo->GetTrackId() == prevTrackId) + return; + GetBookmarkManager().UpdateElevationMyPosition(m_currentPlacePageInfo->GetTrackId()); + } + ActivateMapSelection(m_currentPlacePageInfo); } else diff --git a/map/track_mark.cpp b/map/track_mark.cpp index f775fca6d6..7b174ebb5d 100644 --- a/map/track_mark.cpp +++ b/map/track_mark.cpp @@ -64,6 +64,11 @@ void TrackSelectionMark::SetDistance(double distance) m_distance = distance; } +void TrackSelectionMark::SetMyPositionDistance(double distance) +{ + m_myPositionDistance = distance; +} + drape_ptr TrackSelectionMark::GetSymbolNames() const { auto symbol = make_unique_dp(); diff --git a/map/track_mark.hpp b/map/track_mark.hpp index 20bfcdd145..3f9cb7fa1a 100644 --- a/map/track_mark.hpp +++ b/map/track_mark.hpp @@ -31,6 +31,8 @@ private: class TrackSelectionMark : public UserMark { public: + double static constexpr kInvalidDistance = -1.0; + explicit TrackSelectionMark(m2::PointD const & ptOrg); void SetPosition(m2::PointD const & ptOrg); @@ -41,9 +43,13 @@ public: void SetDistance(double distance); double GetDistance() const { return m_distance; } + void SetMyPositionDistance(double distance); + double GetMyPositionDistance() const { return m_myPositionDistance; } + drape_ptr GetSymbolNames() const override; private: double m_distance = 0.0; + double m_myPositionDistance = kInvalidDistance; kml::TrackId m_trackId = kml::kInvalidTrackId; };