diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData+Core.h b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData+Core.h index 1e06ec342e..ed5dbfc063 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData+Core.h +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData+Core.h @@ -6,7 +6,6 @@ NS_ASSUME_NONNULL_BEGIN @interface PlacePagePreviewData (Core) -- (instancetype)initWithElevationInfo:(ElevationInfo const &)elevationInfo; - (instancetype)initWithRawData:(place_page::Info const &)rawData; @end diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData.mm b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData.mm index c5d6ef3451..18d1eb5502 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData.mm +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePagePreviewData.mm @@ -1,6 +1,7 @@ #import "PlacePagePreviewData+Core.h" #include "3party/opening_hours/opening_hours.hpp" +#include "kml/types.hpp" static PlacePageDataSchedule convertOpeningHours(std::string_view rawOH) { @@ -50,14 +51,6 @@ static PlacePageDataSchedule convertOpeningHours(std::string_view rawOH) @implementation PlacePagePreviewData (Core) -- (instancetype)initWithElevationInfo:(ElevationInfo const &)elevationInfo { - self = [super init]; - if (self) { - _title = @(elevationInfo.GetName().c_str()); - } - return self; -} - - (instancetype)initWithRawData:(place_page::Info const &)rawData { self = [super init]; if (self) { @@ -69,6 +62,13 @@ static PlacePageDataSchedule convertOpeningHours(std::string_view rawOH) _isMyPosition = rawData.IsMyPosition(); //_isPopular = rawData.GetPopularity() > 0; _schedule = convertOpeningHours(rawData.GetOpeningHours()); + + if (rawData.IsTrack()) { + _coordinates = nullptr; + _address = nullptr; + _isMyPosition = false; + _schedule = convertOpeningHours(""); + } } return self; } diff --git a/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm b/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm index c6e4e25f66..52b41a82fa 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm +++ b/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm @@ -63,16 +63,16 @@ static PlacePageRoadType convertRoadType(RoadWarningMarkType roadType) { } if (rawData().IsTrack()) { - auto const &bm = GetFramework().GetBookmarkManager(); - auto const &trackId = rawData().GetTrackId(); - auto const &elevationInfo = bm.MakeElevationInfo(trackId); - _elevationProfileData = [[ElevationProfileData alloc] initWithElevationInfo:elevationInfo - activePoint:bm.GetElevationActivePoint(trackId) - myPosition:bm.GetElevationMyPosition(trackId)]; - _previewData = [[PlacePagePreviewData alloc] initWithElevationInfo:elevationInfo]; - } else { - _previewData = [[PlacePagePreviewData alloc] initWithRawData:rawData()]; + auto const & bm = GetFramework().GetBookmarkManager(); + auto const & trackId = rawData().GetTrackId(); + if (bm.GetTrack(trackId)->HasAltitudes()) { + auto const & elevationInfo = bm.MakeElevationInfo(trackId); + _elevationProfileData = [[ElevationProfileData alloc] initWithElevationInfo:elevationInfo + activePoint:bm.GetElevationActivePoint(trackId) + myPosition:bm.GetElevationMyPosition(trackId)]; + } } + _previewData = [[PlacePagePreviewData alloc] initWithRawData:rawData()]; auto const &countryId = rawData().GetCountryId(); if (!countryId.empty()) { diff --git a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageElevationLayout.swift b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageElevationLayout.swift index 3b49316114..eaeb1cdebf 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageElevationLayout.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageElevationLayout.swift @@ -22,11 +22,17 @@ class PlacePageElevationLayout: IPlacePageLayout { return PlacePageHeaderBuilder.build(data: placePageData.previewData, delegate: interactor, headerType: .fixed) } () - lazy var elevationMapViewController: ElevationProfileViewController = { - let vc = ElevationProfileBuilder.build(data: placePageData, delegate: interactor) + lazy var bookmarkViewController: PlacePageBookmarkViewController = { + let vc = storyboard.instantiateViewController(ofType: PlacePageBookmarkViewController.self) + vc.view.isHidden = true + vc.delegate = interactor return vc } () + lazy var elevationMapViewController: ElevationProfileViewController = { + return ElevationProfileBuilder.build(data: placePageData, delegate: interactor) + } () + init(interactor: PlacePageInteractor, storyboard: UIStoryboard, data: PlacePageData) { self.interactor = interactor self.storyboard = storyboard @@ -35,6 +41,13 @@ class PlacePageElevationLayout: IPlacePageLayout { private func configureViewControllers() -> [UIViewController] { var viewControllers = [UIViewController]() + + viewControllers.append(bookmarkViewController) + if let bookmarkData = placePageData.bookmarkData { + bookmarkViewController.bookmarkData = bookmarkData + bookmarkViewController.view.isHidden = false + } + viewControllers.append(elevationMapViewController) return viewControllers diff --git a/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm b/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm index 8101db24af..68551340cd 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm +++ b/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm @@ -204,6 +204,12 @@ using namespace storage; [[MapViewController sharedController].navigationController pushViewController:editBookmarkController animated:YES]; } +- (void)editBookmark:(PlacePageData *)data { + EditTrackViewController * editTrackController = [[EditTrackViewController alloc] init]; + [editBookmarkController configureWithPlacePageData:data]; + [[MapViewController sharedController].navigationController pushViewController:editBookmarkController animated:YES]; +} + - (void)showPlaceDescription:(NSString *)htmlString { [self.ownerViewController openFullPlaceDescriptionWithHtml:htmlString]; diff --git a/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManagerHelper.mm b/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManagerHelper.mm index f6b78cdd17..15826dfdfa 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManagerHelper.mm +++ b/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManagerHelper.mm @@ -156,6 +156,10 @@ [[MWMMapViewControlsManager manager].placePageManager editBookmark:data]; } ++ (void)editTrack:(PlacePageData *)data { + [[MWMMapViewControlsManager manager].placePageManager editTrack:data]; +} + + (void)searchBookingHotels:(PlacePageData *)data { [[MWMMapViewControlsManager manager].placePageManager searchBookingHotels:data]; } diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index a40b96e72a..dc17fc805e 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -930,7 +930,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); @@ -1037,13 +1037,21 @@ 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); - CHECK_NOT_EQUAL(markId, kml::kInvalidMarkId, ()); +// 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); +// trackSelectionMark->SetPosition(trackSelectionInfo.m_trackPoint); +// trackSelectionMark->SetDistance(trackSelectionInfo.m_distFromBegM); + SetTrackSelectionMark(trackSelectionInfo.m_trackId, trackSelectionInfo.m_trackPoint, trackSelectionInfo.m_distFromBegM); - auto trackSelectionMark = GetMarkForEdit(markId); - trackSelectionMark->SetPosition(trackSelectionInfo.m_trackPoint); - trackSelectionMark->SetDistance(trackSelectionInfo.m_distFromBegM); if (notifyListeners && m_elevationActivePointChanged != nullptr) m_elevationActivePointChanged(); @@ -1092,8 +1100,8 @@ void BookmarkManager::OnTrackDeselected() auto es = GetEditSession(); auto * trackSelectionMark = GetMarkForEdit(markId); - auto const isVisible = IsVisible(GetTrack(m_selectedTrackId)->GetGroupId()); - trackSelectionMark->SetIsVisible(isVisible); +// auto const isVisible = IsVisible(GetTrack(m_selectedTrackId)->GetGroupId()); + trackSelectionMark->SetIsVisible(false); m_selectedTrackId = kml::kInvalidTrackId; } diff --git a/map/elevation_info.cpp b/map/elevation_info.cpp index 006c35daf6..89e64fee9e 100644 --- a/map/elevation_info.cpp +++ b/map/elevation_info.cpp @@ -34,38 +34,41 @@ ElevationInfo::ElevationInfo(Track const & track) , m_name(track.GetName()) { // (Distance, Elevation) chart doesn't have a sence for multiple track's geometry. + auto const & trackData = track.GetData(); + ASSERT_EQUAL(trackData.m_geometry.m_lines.size(), 1, ()); auto const & points = track.GetSingleGeometry(); if (points.empty()) return; m_points.reserve(points.size()); - m_points.emplace_back(0, points[0].GetAltitude()); + + auto const & baseAltitude = points[0].GetAltitude(); + m_points.emplace_back(0, baseAltitude); + double distance = 0.0; + for (size_t i = 1; i < points.size(); ++i) { distance += mercator::DistanceOnEarth(points[i - 1].GetPoint(), points[i].GetPoint()); m_points.emplace_back(distance, points[i].GetAltitude()); + + auto const & pt1 = points[i - 1].GetPoint(); + auto const & pt2 = points[i].GetPoint(); + auto const deltaAltitude = points[i].GetAltitude() - points[i - 1].GetAltitude(); + if (deltaAltitude > 0) + m_ascent += deltaAltitude; + else + m_descent -= deltaAltitude; + + if (m_minAltitude == geometry::kInvalidAltitude || points[i].GetAltitude() < m_minAltitude) + m_minAltitude = points[i].GetAltitude(); + if (m_maxAltitude == geometry::kInvalidAltitude || points[i].GetAltitude() > m_maxAltitude) + m_maxAltitude = points[i].GetAltitude(); } - auto const & properties = track.GetData().m_properties; - - FillProperty(properties, kAscentKey, m_ascent); - FillProperty(properties, kDescentKey, m_descent); - FillProperty(properties, kLowestPointKey, m_minAltitude); - FillProperty(properties, kHighestPointKey, m_maxAltitude); - - uint8_t difficulty; - FillProperty(properties, kDifficultyKey, difficulty); - - if (difficulty > kMaxDifficulty) - { - LOG(LWARNING, ("Invalid difficulty value", m_difficulty, "in track", track.GetName())); - m_difficulty = Difficulty ::Unknown; - } - else - { - m_difficulty = static_cast(difficulty); - } - - FillProperty(properties, kDurationKey, m_duration); + auto const & timestamps = trackData.m_geometry.m_timestamps[0]; + m_duration = timestamps.back() - timestamps.front(); + ASSERT_GREATER(m_duration, 0, ("Track duration is less than zero", GetId())); + + m_difficulty = Difficulty::Unknown; } diff --git a/map/elevation_info.hpp b/map/elevation_info.hpp index 95010ac208..bc9246d9c4 100644 --- a/map/elevation_info.hpp +++ b/map/elevation_info.hpp @@ -39,10 +39,10 @@ public: std::string const & GetName() const { return m_name; } size_t GetSize() const { return m_points.size(); }; Points const & GetPoints() const { return m_points; }; - uint16_t GetAscent() const { return m_ascent; } - uint16_t GetDescent() const { return m_descent; } - uint16_t GetMinAltitude() const { return m_minAltitude; } - uint16_t GetMaxAltitude() const { return m_maxAltitude; } + geometry::Altitude GetAscent() const { return m_ascent; } + geometry::Altitude GetDescent() const { return m_descent; } + geometry::Altitude GetMinAltitude() const { return m_minAltitude; } + geometry::Altitude GetMaxAltitude() const { return m_maxAltitude; } uint8_t GetDifficulty() const { return m_difficulty; } uint32_t GetDuration() const { return m_duration; } @@ -52,13 +52,13 @@ private: // Points with distance from start of the track and altitude. Points m_points; // Ascent in meters. - uint16_t m_ascent = 0; + geometry::Altitude m_ascent = 0; // Descent in meters. - uint16_t m_descent = 0; + geometry::Altitude m_descent = 0; // Altitude in meters. - uint16_t m_minAltitude = 0; + geometry::Altitude m_minAltitude = 0; // Altitude in meters. - uint16_t m_maxAltitude = 0; + geometry::Altitude m_maxAltitude = 0; // Some digital difficulty level with value in range [0-kMaxDifficulty] // or kInvalidDifficulty when difficulty is not found or incorrect. Difficulty m_difficulty = Difficulty::Unknown; diff --git a/map/framework.cpp b/map/framework.cpp index 5eb0fb6178..d05eae4e60 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -622,7 +622,6 @@ void Framework::FillUserMarkInfo(UserMark const * mark, place_page::Info & outIn void Framework::FillBookmarkInfo(Bookmark const & bmk, place_page::Info & info) const { info.SetBookmarkCategoryName(GetBookmarkManager().GetCategoryName(bmk.GetGroupId())); - info.SetBookmarkData(bmk.GetData()); info.SetBookmarkId(bmk.GetId()); info.SetBookmarkCategoryId(bmk.GetGroupId()); auto const description = GetPreferredBookmarkStr(info.GetBookmarkData().m_description); @@ -649,6 +648,7 @@ void Framework::FillTrackInfo(Track const & track, m2::PointD const & trackPoint info.SetTrackId(track.GetId()); info.SetBookmarkCategoryId(track.GetGroupId()); info.SetMercator(trackPoint); + info.SetCustomName(track.GetName()); } search::ReverseGeocoder::Address Framework::GetAddressAtPoint(m2::PointD const & pt) const @@ -888,8 +888,8 @@ void Framework::ShowTrack(kml::TrackId trackId) auto es = GetBookmarkManager().GetEditSession(); es.SetIsVisible(track->GetGroupId(), true /* visible */); - if (track->IsInteractive()) - bm.SetDefaultTrackSelection(trackId, true /* showInfoSign */); +// if (track->IsInteractive()) +// bm.SetDefaultTrackSelection(trackId, true /* showInfoSign */); } void Framework::ShowBookmarkCategory(kml::MarkGroupId categoryId, bool animation) @@ -908,13 +908,13 @@ void Framework::ShowBookmarkCategory(kml::MarkGroupId categoryId, bool animation 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; - } +// for (auto trackId : trackIds) +// { +// if (!bm.GetTrack(trackId)->IsInteractive()) +// continue; +// bm.SetDefaultTrackSelection(trackId, true /* showInfoSign */); +// break; +// } } void Framework::ShowFeature(FeatureID const & featureId) @@ -2219,8 +2219,8 @@ place_page::Info Framework::BuildPlacePageInfo(place_page::BuildInfo const & bui auto const isFeatureMatchingEnabled = buildInfo.IsFeatureMatchingEnabled(); // Using VisualParams inside FindTrackInTapPosition/GetDefaultTapRect requires drapeEngine. - if (m_drapeEngine != nullptr && buildInfo.IsTrackMatchingEnabled() && - !(isFeatureMatchingEnabled && selectedFeature.IsValid())) + if (m_drapeEngine != nullptr && buildInfo.IsTrackMatchingEnabled() && isFeatureMatchingEnabled + /*!(isFeatureMatchingEnabled && selectedFeature.IsValid())*/) { auto const trackSelectionInfo = FindTrackInTapPosition(buildInfo); if (trackSelectionInfo.m_trackId != kml::kInvalidTrackId) diff --git a/map/track.cpp b/map/track.cpp index b44153c1d4..b4762d6168 100644 --- a/map/track.cpp +++ b/map/track.cpp @@ -68,7 +68,7 @@ Track::Track(kml::TrackData && data, bool interactive) { m_data.m_id = GetId(); CHECK(m_data.m_geometry.IsValid(), ()); - if (interactive && HasAltitudes()) + if (interactive) CacheDataForInteraction(); } @@ -161,6 +161,19 @@ double Track::GetLengthMeters() const return len; } +double Track::GetDurationInSeconds() const +{ + ASSERT(m_data.m_geometry.HasTimestamps(), ()); + double duration = 0.0; + 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; +} + double Track::GetLengthMetersImpl(kml::MultiGeometry::LineT const & line, size_t ptIdx) const { if (m_interactionData) diff --git a/map/track.hpp b/map/track.hpp index 32b9c43c9e..9b10a9df83 100644 --- a/map/track.hpp +++ b/map/track.hpp @@ -27,6 +27,7 @@ public: m2::RectD GetLimitRect() const; double GetLengthMeters() const; + double GetDurationInSeconds() const; bool IsInteractive() const; std::pair GetCenterPoint() const; @@ -67,13 +68,15 @@ public: /// @name This functions are valid only for the single line geometry. /// @{ kml::MultiGeometry::LineT const & GetSingleGeometry() const; + + bool HasAltitudes() const; + private: std::vector GetLengthsImpl() const; /// @} m2::RectD GetLimitRectImpl() const; void CacheDataForInteraction(); - bool HasAltitudes() const; double GetLengthMetersImpl(kml::MultiGeometry::LineT const & line, size_t ptIdx) const;