diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index 0843f04b19..4c829ec807 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -473,7 +473,7 @@ void BookmarkManager::DeleteCompilations(kml::GroupIdCollection const & compilat Track * BookmarkManager::CreateTrack(kml::TrackData && trackData) { CHECK_THREAD_CHECKER(m_threadChecker, ()); - return AddTrack(std::make_unique(std::move(trackData), false /* interactive */)); + return AddTrack(std::make_unique(std::move(trackData))); } Track const * BookmarkManager::GetTrack(kml::TrackId trackId) const @@ -838,6 +838,9 @@ void BookmarkManager::UpdateElevationMyPosition(kml::TrackId const & trackId) } auto const markId = GetTrackSelectionMarkId(trackId); + if (markId == kml::kInvalidTrackId) + return; + auto es = GetEditSession(); auto trackSelectionMark = GetMarkForEdit(markId); @@ -870,16 +873,13 @@ void BookmarkManager::SetElevationMyPositionChangedCallback( m_elevationMyPositionChanged = cb; } -void BookmarkManager::SetElevationActivePoint(kml::TrackId const & trackId, double targetDistance) +void BookmarkManager::SetElevationActivePoint(kml::TrackId const & trackId, m2::PointD pt, double targetDistance) { CHECK_THREAD_CHECKER(m_threadChecker, ()); auto const track = GetTrack(trackId); CHECK(track != nullptr, ()); - m2::PointD pt; - VERIFY(track->GetPoint(targetDistance, pt), (trackId, targetDistance)); - SetTrackSelectionInfo({trackId, pt, targetDistance}, false /* notifyListeners */); m_drapeEngine.SafeCall(&df::DrapeEngine::SelectObject, @@ -921,7 +921,7 @@ Track::TrackSelectionInfo BookmarkManager::FindNearestTrack( for (auto trackId : category.GetUserLines()) { auto const track = GetTrack(trackId); - if (!track->IsInteractive() || (tracksFilter && !tracksFilter(track))) + if (tracksFilter && !tracksFilter(track)) continue; track->UpdateSelectionInfo(touchRect, selectionInfo); @@ -1028,8 +1028,14 @@ void BookmarkManager::SetTrackSelectionInfo(Track::TrackSelectionInfo const & tr CHECK_THREAD_CHECKER(m_threadChecker, ()); CHECK_NOT_EQUAL(trackSelectionInfo.m_trackId, kml::kInvalidTrackId, ()); - auto es = GetEditSession(); auto const markId = GetTrackSelectionMarkId(trackSelectionInfo.m_trackId); + if (markId == kml::kInvalidMarkId) + { + SetTrackSelectionMark(trackSelectionInfo.m_trackId, + trackSelectionInfo.m_trackPoint, + trackSelectionInfo.m_distFromBegM); + return; + } CHECK_NOT_EQUAL(markId, kml::kInvalidMarkId, ()); auto trackSelectionMark = GetMarkForEdit(markId); @@ -1040,22 +1046,6 @@ void BookmarkManager::SetTrackSelectionInfo(Track::TrackSelectionInfo const & tr m_elevationActivePointChanged(); } -void BookmarkManager::SetDefaultTrackSelection(kml::TrackId trackId, bool showInfoSign) -{ - CHECK_THREAD_CHECKER(m_threadChecker, ()); - - auto track = GetTrack(trackId); - CHECK(track != nullptr, ()); - CHECK(track->IsInteractive(), ()); - - auto const [pt, distance] = track->GetCenterPoint(); - - auto es = GetEditSession(); - if (showInfoSign) - SetTrackInfoMark(trackId, pt); - SetTrackSelectionMark(trackId, pt, distance); -} - void BookmarkManager::OnTrackSelected(kml::TrackId trackId) { CHECK_THREAD_CHECKER(m_threadChecker, ()); @@ -2820,12 +2810,10 @@ void BookmarkManager::CreateCategories(KMLDataCollection && dataCollection, bool } for (auto & trackData : fileData.m_tracksData) { - auto track = std::make_unique(std::move(trackData), group->HasElevationProfile()); + auto track = std::make_unique(std::move(trackData)); auto * t = AddTrack(std::move(track)); t->Attach(groupId); group->m_tracks.insert(t->GetId()); - if (t->IsInteractive()) - SetDefaultTrackSelection(t->GetId(), false /* showInfoSign */); } UpdateTrackMarksVisibility(groupId); UserMarkIdStorage::Instance().EnableSaving(true); diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index 654fb79f82..4847f69eee 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -407,7 +407,7 @@ public: static std::string GetSortedByTimeBlockName(SortedByTimeBlockType blockType); std::string GetLocalizedRegionAddress(m2::PointD const & pt); - void SetElevationActivePoint(kml::TrackId const & trackId, double distanceInMeters); + void SetElevationActivePoint(kml::TrackId const & trackId, m2::PointD pt, double distanceInMeters); // Returns distance from the start of the track to active point in meters. double GetElevationActivePoint(kml::TrackId const & trackId) const; @@ -425,7 +425,6 @@ public: Track::TrackSelectionInfo GetTrackSelectionInfo(kml::TrackId const & trackId) const; void SetTrackSelectionInfo(Track::TrackSelectionInfo const & trackSelectionInfo, bool notifyListeners); - void SetDefaultTrackSelection(kml::TrackId trackId, bool showInfoSign); void OnTrackSelected(kml::TrackId trackId); void OnTrackDeselected(); diff --git a/map/framework.cpp b/map/framework.cpp index 782c7ce216..b788526cc0 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -885,20 +885,25 @@ void Framework::ShowTrack(kml::TrackId trackId) { auto & bm = GetBookmarkManager(); auto const track = bm.GetTrack(trackId); - if (track == nullptr) - return; + + StopLocationFollow(); auto rect = track->GetLimitRect(); ExpandRectForPreview(rect); - StopLocationFollow(); - ShowRect(rect); + place_page::BuildInfo info; + info.m_trackId = trackId; + info.m_mercator = rect.Center(); - auto es = GetBookmarkManager().GetEditSession(); + m_currentPlacePageInfo = BuildPlacePageInfo(info); + + auto es = bm.GetEditSession(); es.SetIsVisible(track->GetGroupId(), true /* visible */); - if (track->IsInteractive()) - bm.SetDefaultTrackSelection(trackId, true /* showInfoSign */); + if (m_drapeEngine) + m_drapeEngine->SetModelViewCenter(rect.Center(), scales::GetScaleLevel(rect), true /* isAnim */, true /* trackVisibleViewport */); + + ActivateMapSelection(); } void Framework::ShowBookmarkCategory(kml::MarkGroupId categoryId, bool animation) @@ -915,15 +920,6 @@ void Framework::ShowBookmarkCategory(kml::MarkGroupId categoryId, bool animation auto es = bm.GetEditSession(); es.SetIsVisible(categoryId, true /* visible */); - - auto const & trackIds = bm.GetTrackIds(categoryId); - for (auto trackId : trackIds) - { - if (!bm.GetTrack(trackId)->IsInteractive()) - continue; - bm.SetDefaultTrackSelection(trackId, true /* showInfoSign */); - break; - } } void Framework::ShowFeature(FeatureID const & featureId) @@ -2229,11 +2225,22 @@ place_page::Info Framework::BuildPlacePageInfo(place_page::BuildInfo const & bui FeatureID selectedFeature = buildInfo.m_featureId; auto const isFeatureMatchingEnabled = buildInfo.IsFeatureMatchingEnabled(); + // @TODO: (KK) Enable track selection. + // The isTrackSelectionEnabled should be removed to enable the track selection when the UI will be implemented. + const bool isTrackSelectionEnabled = false; // Using VisualParams inside FindTrackInTapPosition/GetDefaultTapRect requires drapeEngine. - if (m_drapeEngine != nullptr && buildInfo.IsTrackMatchingEnabled() && + if (isTrackSelectionEnabled && m_drapeEngine != nullptr && buildInfo.IsTrackMatchingEnabled() && !(isFeatureMatchingEnabled && selectedFeature.IsValid())) { - auto const trackSelectionInfo = FindTrackInTapPosition(buildInfo); + Track::TrackSelectionInfo trackSelectionInfo; + if (buildInfo.m_trackId != kml::kInvalidTrackId) + { + auto const & track = *GetBookmarkManager().GetTrack(buildInfo.m_trackId); + auto rect = track.GetLimitRect(); + track.UpdateSelectionInfo(track.GetLimitRect(), trackSelectionInfo); + } + else + trackSelectionInfo = FindTrackInTapPosition(buildInfo); if (trackSelectionInfo.m_trackId != kml::kInvalidTrackId) { BuildTrackPlacePage(trackSelectionInfo, outInfo); diff --git a/map/track.cpp b/map/track.cpp index b44153c1d4..2aeb6218df 100644 --- a/map/track.cpp +++ b/map/track.cpp @@ -10,42 +10,6 @@ namespace { -bool GetTrackPoint(std::vector const & points, - std::vector const & lengths, double distanceInMeters, m2::PointD & pt) -{ - CHECK_GREATER_OR_EQUAL(distanceInMeters, 0.0, ()); - CHECK_EQUAL(points.size(), lengths.size(), ()); - - double const kEpsMeters = 1e-2; - if (base::AlmostEqualAbs(distanceInMeters, lengths.front(), kEpsMeters)) - { - pt = points.front().GetPoint(); - return true; - } - - if (base::AlmostEqualAbs(distanceInMeters, lengths.back(), kEpsMeters)) - { - pt = points.back().GetPoint(); - return true; - } - - auto const it = std::lower_bound(lengths.begin(), lengths.end(), distanceInMeters); - if (it == lengths.end()) - return false; - - auto const pointIndex = std::distance(lengths.begin(), it); - auto const length = *it; - - auto const segmentLength = length - lengths[pointIndex - 1]; - auto const k = (segmentLength - (length - distanceInMeters)) / segmentLength; - - auto const & pt1 = points[pointIndex - 1].GetPoint(); - auto const & pt2 = points[pointIndex].GetPoint(); - pt = pt1 + (pt2 - pt1) * k; - - return true; -} - double GetLengthInMeters(kml::MultiGeometry::LineT const & points, size_t pointIndex) { CHECK_LESS(pointIndex, points.size(), (pointIndex, points.size())); @@ -62,17 +26,15 @@ double GetLengthInMeters(kml::MultiGeometry::LineT const & points, size_t pointI } } // namespace -Track::Track(kml::TrackData && data, bool interactive) +Track::Track(kml::TrackData && data) : Base(data.m_id == kml::kInvalidTrackId ? UserMarkIdStorage::Instance().GetNextTrackId() : data.m_id) , m_data(std::move(data)) { m_data.m_id = GetId(); CHECK(m_data.m_geometry.IsValid(), ()); - if (interactive && HasAltitudes()) - CacheDataForInteraction(); } -void Track::CacheDataForInteraction() +void Track::CacheDataForInteraction() const { m_interactionData = InteractionData(); m_interactionData->m_lengths = GetLengthsImpl(); @@ -81,14 +43,19 @@ void Track::CacheDataForInteraction() std::vector Track::GetLengthsImpl() const { - auto const & line = GetSingleGeometry(); - std::vector lengths(line.size(), 0.0); - for (size_t i = 1; i < line.size(); ++i) + auto const & lines = GetData().m_geometry.m_lines; + std::vector lengths; + lengths.emplace_back(0.0); + for (size_t i = 0; i < lines.size(); ++i) { - auto const & pt1 = line[i - 1].GetPoint(); - auto const & pt2 = line[i].GetPoint(); - auto const segmentLength = mercator::DistanceOnEarth(pt1, pt2); - lengths[i] = lengths[i - 1] + segmentLength; + auto const & line = lines[i]; + for (size_t j = 1; j < line.size(); ++j) + { + auto const & pt1 = line[j - 1].GetPoint(); + auto const & pt2 = line[j].GetPoint(); + auto const segmentLength = mercator::DistanceOnEarth(pt1, pt2); + lengths.emplace_back(lengths.back() + segmentLength); + } } return lengths; } @@ -163,18 +130,10 @@ double Track::GetLengthMeters() const double Track::GetLengthMetersImpl(kml::MultiGeometry::LineT const & line, size_t ptIdx) const { - if (m_interactionData) - { - CHECK_LESS(ptIdx, m_interactionData->m_lengths.size(), ()); - return m_interactionData->m_lengths[ptIdx]; - } - - return GetLengthInMeters(line, ptIdx); -} - -bool Track::IsInteractive() const -{ - return m_interactionData.has_value(); + if (!m_interactionData) + CacheDataForInteraction(); + CHECK_LESS(ptIdx, m_interactionData->m_lengths.size(), ()); + return m_interactionData->m_lengths[ptIdx]; } std::pair Track::GetCenterPoint() const @@ -272,16 +231,36 @@ void Track::Detach() m_groupID = kml::kInvalidMarkGroupId; } -bool Track::GetPoint(double distanceInMeters, m2::PointD & pt) const +kml::MultiGeometry::LineT Track::GetGeometry() const { - if (m_interactionData) - return GetTrackPoint(GetSingleGeometry(), m_interactionData->m_lengths, distanceInMeters, pt); - - return GetTrackPoint(GetSingleGeometry(), GetLengthsImpl(), distanceInMeters, pt); + kml::MultiGeometry::LineT geometry; + for (auto const & line : m_data.m_geometry.m_lines) + { + for (size_t i = 0; i < line.size(); ++i) + geometry.emplace_back(line[i]); + } + return geometry; } -kml::MultiGeometry::LineT const & Track::GetSingleGeometry() const +std::optional Track::GetElevationInfo() const { - ASSERT_EQUAL(m_data.m_geometry.m_lines.size(), 1, ()); - return m_data.m_geometry.m_lines[0]; + if (!HasAltitudes()) + return std::nullopt; + if (!m_elevationInfo) + m_elevationInfo = ElevationInfo(GetData().m_geometry); + return m_elevationInfo; +} + +double Track::GetDurationInSeconds() const +{ + double duration = 0.0; + if (!m_data.m_geometry.HasTimestamps()) + return duration; + for (size_t i = 0; i < m_data.m_geometry.m_timestamps.size(); ++i) + { + ASSERT(m_data.m_geometry.HasTimestampsFor(i), ()); + auto const & timestamps = m_data.m_geometry.m_timestamps[i]; + duration += timestamps.back() - timestamps.front(); + } + return duration; } diff --git a/map/track.hpp b/map/track.hpp index 32b9c43c9e..bb62806190 100644 --- a/map/track.hpp +++ b/map/track.hpp @@ -2,6 +2,8 @@ #include "kml/types.hpp" +#include "map/elevation_info.hpp" + #include "drape_frontend/user_marks_provider.hpp" #include @@ -11,7 +13,7 @@ class Track : public df::UserLineMark using Base = df::UserLineMark; public: - Track(kml::TrackData && data, bool interactive); + Track(kml::TrackData && data); kml::MarkGroupId GetGroupId() const override { return m_groupID; } @@ -27,8 +29,8 @@ public: m2::RectD GetLimitRect() const; double GetLengthMeters() const; - bool IsInteractive() const; - + double GetDurationInSeconds() const; + std::optional GetElevationInfo() const; std::pair GetCenterPoint() const; struct TrackSelectionInfo @@ -66,26 +68,29 @@ public: /// @name This functions are valid only for the single line geometry. /// @{ - kml::MultiGeometry::LineT const & GetSingleGeometry() const; + kml::MultiGeometry::LineT GetGeometry() const; + + bool HasAltitudes() const; + private: std::vector GetLengthsImpl() const; /// @} m2::RectD GetLimitRectImpl() const; - void CacheDataForInteraction(); - bool HasAltitudes() const; + void CacheDataForInteraction() const; double GetLengthMetersImpl(kml::MultiGeometry::LineT const & line, size_t ptIdx) const; kml::TrackData m_data; kml::MarkGroupId m_groupID = kml::kInvalidMarkGroupId; + mutable std::optional m_elevationInfo; struct InteractionData { std::vector m_lengths; m2::RectD m_limitRect; }; - std::optional m_interactionData; + mutable std::optional m_interactionData; mutable bool m_isDirty = true; };