From a4b01a3c6fe7fc8a051915f82c005637b5acd848 Mon Sep 17 00:00:00 2001 From: Daria Volvenkova Date: Mon, 27 Nov 2017 17:32:49 +0300 Subject: [PATCH] Refactoring of transit route processing. --- drape_frontend/color_constants.cpp | 3 - drape_frontend/drape_engine.cpp | 1 - drape_frontend/render_group.cpp | 2 +- drape_frontend/user_mark_shapes.cpp | 6 +- drape_frontend/user_mark_shapes.hpp | 1 - drape_frontend/user_marks_provider.hpp | 2 - map/CMakeLists.txt | 6 +- map/map.pro | 6 +- map/routing_manager.cpp | 611 +----------------------- map/routing_manager.hpp | 57 +-- map/routing_mark.cpp | 13 - map/routing_mark.hpp | 4 - map/transit/transit_display.cpp | 579 ++++++++++++++++++++++ map/transit/transit_display.hpp | 129 +++++ map/{ => transit}/transit_reader.cpp | 2 +- map/{ => transit}/transit_reader.hpp | 0 map/user_mark.hpp | 1 - xcode/map/map.xcodeproj/project.pbxproj | 32 +- 18 files changed, 765 insertions(+), 690 deletions(-) create mode 100644 map/transit/transit_display.cpp create mode 100644 map/transit/transit_display.hpp rename map/{ => transit}/transit_reader.cpp (99%) rename map/{ => transit}/transit_reader.hpp (100%) diff --git a/drape_frontend/color_constants.cpp b/drape_frontend/color_constants.cpp index d25a5ac851..1ce41f1c3c 100644 --- a/drape_frontend/color_constants.cpp +++ b/drape_frontend/color_constants.cpp @@ -32,10 +32,7 @@ public: auto const & colors = isDarkStyle ? m_nightColors : m_clearColors; auto const it = colors.find(name); if (it == colors.cend()) - { - LOG(LWARNING, ("Requested transit color '" + name + "' is not found")); return dp::Color(); - } return it->second; } diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 53fab55799..3b755aac3f 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -241,7 +241,6 @@ void DrapeEngine::UpdateUserMarksGroup(MarkGroupID groupId, UserMarksProvider * renderInfo->m_pivot = mark->GetPivot(); renderInfo->m_pixelOffset = mark->GetPixelOffset(); renderInfo->m_titleDecl = mark->GetTitleDecl(); - renderInfo->m_symbolSizes = mark->GetSymbolSizes(); renderInfo->m_symbolNames = mark->GetSymbolNames(); renderInfo->m_coloredSymbols = mark->GetColoredSymbols(); renderInfo->m_hasSymbolPriority = mark->HasSymbolPriority(); diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index 64e16d9931..5f807984c7 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -101,7 +101,7 @@ void RenderGroup::Render(ScreenBase const & screen) int const programIndex = m_state.GetProgramIndex(); int const program3dIndex = m_state.GetProgram3dIndex(); - if (IsOverlay() || GetDepthLayer(m_state) == RenderState::TransitMarkLayer) + if (IsOverlay()) { if (programIndex == gpu::COLORED_SYMBOL_PROGRAM || programIndex == gpu::COLORED_SYMBOL_BILLBOARD_PROGRAM) diff --git a/drape_frontend/user_mark_shapes.cpp b/drape_frontend/user_mark_shapes.cpp index 579cf5a348..d7b3d71d4c 100644 --- a/drape_frontend/user_mark_shapes.cpp +++ b/drape_frontend/user_mark_shapes.cpp @@ -201,11 +201,7 @@ void CacheUserMarks(TileKey const & tileKey, ref_ptr texture buffer.emplace_back(pos, right + up + offset, glsl::ToVec2(texRect.RightBottom()), runAnim); } - if (renderInfo.m_symbolSizes != nullptr) - { - symbolSize = renderInfo.m_symbolSizes->at(static_cast(tileKey.m_zoomLevel - 1)) * vs; - } - else if (!symbolName.empty()) + if (!symbolName.empty()) { textures->GetSymbolRegion(symbolName, region); symbolSize.x = max(region.GetPixelSize().x, symbolSize.x); diff --git a/drape_frontend/user_mark_shapes.hpp b/drape_frontend/user_mark_shapes.hpp index b325b6ae92..d00f38e930 100644 --- a/drape_frontend/user_mark_shapes.hpp +++ b/drape_frontend/user_mark_shapes.hpp @@ -20,7 +20,6 @@ struct UserMarkRenderParams m2::PointD m_pivot = m2::PointD(0.0, 0.0); m2::PointD m_pixelOffset = m2::PointD(0.0, 0.0); dp::Anchor m_anchor = dp::Center; - drape_ptr m_symbolSizes; drape_ptr m_coloredSymbols; drape_ptr m_symbolNames; drape_ptr m_titleDecl; diff --git a/drape_frontend/user_marks_provider.hpp b/drape_frontend/user_marks_provider.hpp index b9892aad2f..cc0374e92d 100644 --- a/drape_frontend/user_marks_provider.hpp +++ b/drape_frontend/user_marks_provider.hpp @@ -41,7 +41,6 @@ class UserPointMark public: using ColoredSymbolZoomInfo = std::map; using SymbolNameZoomInfo = std::map; - using SymbolSizesZoomInfo = std::vector; using TitlesInfo = std::vector; UserPointMark(); @@ -59,7 +58,6 @@ public: virtual RenderState::DepthLayer GetDepthLayer() const = 0; virtual bool IsVisible() const = 0; virtual drape_ptr GetTitleDecl() const = 0; - virtual drape_ptr GetSymbolSizes() const = 0; virtual drape_ptr GetSymbolNames() const = 0; virtual drape_ptr GetColoredSymbols() const = 0; virtual uint16_t GetPriority() const = 0; diff --git a/map/CMakeLists.txt b/map/CMakeLists.txt index c0bc29deda..8a998c946e 100644 --- a/map/CMakeLists.txt +++ b/map/CMakeLists.txt @@ -77,8 +77,10 @@ set( track.hpp traffic_manager.cpp traffic_manager.hpp - transit_reader.cpp - transit_reader.hpp + transit/transit_display.cpp + transit/transit_display.hpp + transit/transit_reader.cpp + transit/transit_reader.hpp user.cpp user.hpp user_mark_container.cpp diff --git a/map/map.pro b/map/map.pro index 35f4a66de8..85adaa9989 100644 --- a/map/map.pro +++ b/map/map.pro @@ -45,7 +45,8 @@ HEADERS += \ taxi_delegate.hpp \ track.hpp \ traffic_manager.hpp \ - transit_reader.hpp \ + transit/transit_display.hpp \ + transit/transit_reader.hpp \ user.hpp \ user_mark.hpp \ user_mark_container.hpp \ @@ -86,7 +87,8 @@ SOURCES += \ taxi_delegate.cpp \ track.cpp \ traffic_manager.cpp \ - transit_reader.cpp \ + transit/transit_display.cpp \ + transit/transit_reader.cpp \ user.cpp \ user_mark.cpp \ user_mark_container.cpp \ diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index a831394e84..b30a44675c 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -17,9 +17,7 @@ #include "routing_common/num_mwm_id.hpp" -#include "drape_frontend/color_constants.hpp" #include "drape_frontend/drape_engine.hpp" -#include "drape_frontend/visual_params.hpp" #include "indexer/map_style_reader.hpp" #include "indexer/scales.hpp" @@ -57,33 +55,11 @@ namespace char const kRouterTypeKey[] = "router"; double const kRouteScaleMultiplier = 1.5; -float const kStopMarkerScale = 2.2f; -float const kTransferMarkerScale = 4.0f; string const kRoutePointsFile = "route_points.dat"; uint32_t constexpr kInvalidTransactionId = 0; -map const kTransitSymbols = { - { TransitType::Subway, "transit_subway" }, - { TransitType::LightRail, "transit_light_rail" }, - { TransitType::Monorail, "transit_monorail" }, - { TransitType::Train, "transit_train" } -}; - -TransitType GetTransitType(string const & type) -{ - if (type == "subway") - return TransitType::Subway; - if (type == "light_rail") - return TransitType::LightRail; - if (type == "monorail") - return TransitType::Monorail; - - ASSERT_EQUAL(type, "train", ()); - return TransitType::Train; -} - void FillTurnsDistancesForRendering(vector const & segments, double baseDistance, vector & turns) { @@ -114,493 +90,6 @@ void FillTrafficForRendering(vector const & segments, traffic.push_back(s.GetTraffic()); } -struct TransitTitle -{ - TransitTitle() = default; - TransitTitle(string const & text, df::ColorConstant const & color) : m_text(text), m_color(color) {} - - string m_text; - df::ColorConstant m_color; -}; - -struct TransitMarkInfo -{ - enum class Type - { - Stop, - KeyStop, - Transfer, - Gate - }; - Type m_type = Type::Stop; - m2::PointD m_point; - vector m_titles; - std::string m_symbolName; - df::ColorConstant m_color; - FeatureID m_featureId; -}; - -using GetMwmIdFn = function; -void CollectTransitDisplayInfo(vector const & segments, GetMwmIdFn const & getMwmIdFn, - TransitDisplayInfos & transitDisplayInfos) -{ - for (auto const & s : segments) - { - if (!s.HasTransitInfo()) - continue; - - auto const mwmId = getMwmIdFn(s.GetSegment().GetMwmId()); - - auto & mwmTransit = transitDisplayInfos[mwmId]; - if (mwmTransit == nullptr) - mwmTransit = my::make_unique(); - - TransitInfo const & transitInfo = s.GetTransitInfo(); - switch (transitInfo.GetType()) - { - case TransitInfo::Type::Edge: - { - auto const & edge = transitInfo.GetEdge(); - - mwmTransit->m_stops[edge.m_stop1Id] = {}; - mwmTransit->m_stops[edge.m_stop2Id] = {}; - mwmTransit->m_lines[edge.m_lineId] = {}; - for (auto const &shapeId : edge.m_shapeIds) - mwmTransit->m_shapes[shapeId] = {}; - break; - } - case TransitInfo::Type::Transfer: - { - auto const & transfer = transitInfo.GetTransfer(); - mwmTransit->m_stops[transfer.m_stop1Id] = {}; - mwmTransit->m_stops[transfer.m_stop2Id] = {}; - break; - } - case TransitInfo::Type::Gate: - { - auto const & gate = transitInfo.GetGate(); - if (gate.m_featureId != transit::kInvalidFeatureId) - { - auto const featureId = FeatureID(mwmId, gate.m_featureId); - TransitFeatureInfo featureInfo; - featureInfo.m_isGate = true; - mwmTransit->m_features[featureId] = featureInfo; - } - break; - } - } - } -} - -void AddTransitGateSegment(m2::PointD const & destPoint, df::ColorConstant const & color, df::Subroute & subroute) -{ - ASSERT_GREATER(subroute.m_polyline.GetSize(), 0, ()); - df::SubrouteStyle style(color, df::RoutePattern(4.0, 2.0)); - style.m_startIndex = subroute.m_polyline.GetSize() - 1; - auto const vec = destPoint - subroute.m_polyline.Back(); - subroute.m_polyline.Add(destPoint); - style.m_endIndex = subroute.m_polyline.GetSize() - 1; - subroute.AddStyle(style); -} - -void AddTransitPedestrianSegment(m2::PointD const & destPoint, df::Subroute & subroute) -{ - ASSERT_GREATER(subroute.m_polyline.GetSize(), 0, ()); - df::SubrouteStyle style(df::kRoutePedestrian, df::RoutePattern(4.0, 2.0)); - style.m_startIndex = subroute.m_polyline.GetSize() - 1; - subroute.m_polyline.Add(destPoint); - style.m_endIndex = subroute.m_polyline.GetSize() - 1; - subroute.AddStyle(style); -} - -void AddTransitShapes(std::vector const & shapeIds, TransitShapesInfo const & shapes, - df::ColorConstant const & color, bool isInverted, df::Subroute & subroute) -{ - ASSERT_GREATER(subroute.m_polyline.GetSize(), 0, ()); - df::SubrouteStyle style(color); - style.m_startIndex = subroute.m_polyline.GetSize() - 1; - - for (auto it = shapeIds.crbegin(); it != shapeIds.crend(); ++it) - { - auto const & shapePolyline = shapes.at(*it).GetPolyline(); - if (isInverted) - subroute.m_polyline.Append(shapePolyline.crbegin(), shapePolyline.crend()); - else - subroute.m_polyline.Append(shapePolyline.cbegin(), shapePolyline.cend()); - } - - style.m_endIndex = subroute.m_polyline.GetSize() - 1; - subroute.AddStyle(style); -} - -uint32_t ColorToARGB(df::ColorConstant const & colorConstant) -{ - auto const color = df::GetColorConstant(colorConstant); - return color.GetAlpha() << 24 | color.GetRed() << 16 | color.GetGreen() << 8 | color.GetBlue(); -} - -void FillTransitStyleForRendering(vector const & segments, TransitReadManager & transitReadManager, - GetMwmIdFn const & getMwmIdFn, - RoutingManager::Callbacks::GetStringsBundleFn const & getStringsBundleFn, - df::Subroute & subroute, vector & transitMarks, - TransitRouteInfo & routeInfo) -{ - TransitDisplayInfos transitDisplayInfos; - CollectTransitDisplayInfo(segments, getMwmIdFn, transitDisplayInfos); - - // Read transit display info. - if (!transitReadManager.GetTransitDisplayInfo(transitDisplayInfos)) - return; - - subroute.m_styleType = df::SubrouteStyleType::Multiple; - subroute.m_style.clear(); - subroute.m_style.reserve(segments.size()); - - df::ColorConstant lastColor; - m2::PointD lastDir; - - df::SubrouteMarker marker; - TransitMarkInfo transitMarkInfo; - TransitType transitType = TransitType::Pedestrian; - - double prevDistance = routeInfo.m_totalDistInMeters; - double prevTime = routeInfo.m_totalTimeInSec; - - bool pendingEntrance = false; - - for (auto const & s : segments) - { - auto const time = static_cast(ceil(s.GetTimeFromBeginningSec() - prevTime)); - auto const distance = s.GetDistFromBeginningMeters() - prevDistance; - prevDistance = s.GetDistFromBeginningMeters(); - prevTime = s.GetTimeFromBeginningSec(); - - if (!s.HasTransitInfo()) - { - routeInfo.AddStep(TransitStepInfo(TransitType::Pedestrian, distance, time)); - - AddTransitPedestrianSegment(s.GetJunction().GetPoint(), subroute); - lastColor = ""; - transitType = TransitType::Pedestrian; - continue; - } - - auto const mwmId = getMwmIdFn(s.GetSegment().GetMwmId()); - - auto const & transitInfo = s.GetTransitInfo(); - auto const & displayInfo = *transitDisplayInfos.at(mwmId).get(); - - if (transitInfo.GetType() == TransitInfo::Type::Edge) - { - auto const & edge = transitInfo.GetEdge(); - - auto const & line = displayInfo.m_lines.at(edge.m_lineId); - auto const currentColor = df::GetTransitColorName(line.GetColor()); - transitType = GetTransitType(line.GetType()); - - routeInfo.AddStep(TransitStepInfo(transitType, distance, time, - line.GetNumber(), ColorToARGB(currentColor))); - - auto const & stop1 = displayInfo.m_stops.at(edge.m_stop1Id); - auto const & stop2 = displayInfo.m_stops.at(edge.m_stop2Id); - bool const isTransfer1 = stop1.GetTransferId() != transit::kInvalidTransferId; - bool const isTransfer2 = stop2.GetTransferId() != transit::kInvalidTransferId; - - marker.m_distance = prevDistance; - marker.m_scale = kStopMarkerScale; - marker.m_innerColor = currentColor; - if (isTransfer1) - { - auto const & transferData = displayInfo.m_transfers.at(stop1.GetTransferId()); - marker.m_position = transferData.GetPoint(); - } - else - { - marker.m_position = stop1.GetPoint(); - } - transitMarkInfo.m_point = marker.m_position; - - if (pendingEntrance) - { - transitMarkInfo.m_type = TransitMarkInfo::Type::KeyStop; - transitMarkInfo.m_symbolName = kTransitSymbols.at(transitType); - transitMarkInfo.m_color = currentColor; - AddTransitGateSegment(marker.m_position, currentColor, subroute); - pendingEntrance = false; - } - - auto const id1 = isTransfer1 ? stop1.GetTransferId() : stop1.GetId(); - auto const id2 = isTransfer2 ? stop2.GetTransferId() : stop2.GetId(); - bool const isInverted = id1 > id2; - - AddTransitShapes(edge.m_shapeIds, displayInfo.m_shapes, currentColor, isInverted, subroute); - - ASSERT_GREATER(subroute.m_polyline.GetSize(), 1, ()); - auto const & p1 = *(subroute.m_polyline.End() - 2); - auto const & p2 = *(subroute.m_polyline.End() - 1); - m2::PointD currentDir = (p2 - p1).Normalize(); - - if (lastColor != currentColor) - { - if (!lastColor.empty()) - { - marker.m_scale = kTransferMarkerScale; - transitMarkInfo.m_type = TransitMarkInfo::Type::Transfer; - } - marker.m_colors.push_back(currentColor); - - if (stop1.GetFeatureId() != transit::kInvalidFeatureId) - { - auto const fid = FeatureID(mwmId, stop1.GetFeatureId()); - transitMarkInfo.m_featureId = fid; - transitMarkInfo.m_titles.emplace_back(displayInfo.m_features.at(fid).m_title, - df::GetTransitTextColorName(line.GetColor())); - } - } - lastColor = currentColor; - - if (marker.m_colors.size() > 1) - { - marker.m_innerColor = df::kTransitOutlineColor; - marker.m_up = (currentDir - lastDir).Normalize(); - if (m2::CrossProduct(marker.m_up, -lastDir) < 0) - marker.m_up = -marker.m_up; - } - - subroute.m_markers.push_back(marker); - marker = df::SubrouteMarker(); - - transitMarks.push_back(transitMarkInfo); - transitMarkInfo = TransitMarkInfo(); - - lastDir = currentDir; - - marker.m_distance = s.GetDistFromBeginningMeters(); - marker.m_scale = kStopMarkerScale; - marker.m_innerColor = currentColor; - marker.m_colors.push_back(currentColor); - - if (isTransfer2) - { - auto const & transferData = displayInfo.m_transfers.at(stop2.GetTransferId()); - marker.m_position = transferData.GetPoint(); - } - else - { - marker.m_position = stop2.GetPoint(); - } - - transitMarkInfo.m_point = marker.m_position; - if (stop2.GetFeatureId() != transit::kInvalidFeatureId) - { - auto const fid = FeatureID(mwmId, stop2.GetFeatureId()); - transitMarkInfo.m_featureId = fid; - transitMarkInfo.m_titles.push_back(TransitTitle(displayInfo.m_features.at(fid).m_title, - df::GetTransitTextColorName(line.GetColor()))); - } - } - else if (transitInfo.GetType() == TransitInfo::Type::Gate) - { - auto const & gate = transitInfo.GetGate(); - if (!lastColor.empty()) - { - routeInfo.AddStep(TransitStepInfo(TransitType::Pedestrian, distance, time)); - - AddTransitGateSegment(s.GetJunction().GetPoint(), lastColor, subroute); - - subroute.m_markers.push_back(marker); - marker = df::SubrouteMarker(); - - transitMarkInfo.m_type = TransitMarkInfo::Type::KeyStop; - transitMarkInfo.m_symbolName = kTransitSymbols.at(transitType); - transitMarkInfo.m_color = lastColor; - transitMarks.push_back(transitMarkInfo); - transitMarkInfo = TransitMarkInfo(); - } - else - { - pendingEntrance = true; - } - - auto gateMarkInfo = TransitMarkInfo(); - gateMarkInfo.m_point = pendingEntrance ? subroute.m_polyline.Back() : s.GetJunction().GetPoint(); - gateMarkInfo.m_type = TransitMarkInfo::Type::Gate; - if (gate.m_featureId != transit::kInvalidFeatureId) - { - auto const fid = FeatureID(mwmId, gate.m_featureId); - auto const & featureInfo = displayInfo.m_features.at(fid); - auto symbolName = featureInfo.m_gateSymbolName; - if (strings::EndsWith(symbolName, "-s") || - strings::EndsWith(symbolName, "-m") || - strings::EndsWith(symbolName, "-l")) - { - symbolName = symbolName.substr(0, symbolName.length() - 2); - } - - gateMarkInfo.m_featureId = fid; - gateMarkInfo.m_symbolName = symbolName; - auto const title = getStringsBundleFn().GetString(pendingEntrance ? "entrance" : "exit"); - gateMarkInfo.m_titles.push_back(TransitTitle(title, df::GetTransitTextColorName("default"))); - } - - transitMarks.push_back(gateMarkInfo); - } - } - - routeInfo.m_totalDistInMeters = prevDistance; - routeInfo.m_totalTimeInSec = static_cast(ceil(prevTime)); -} - -vector GetTransitMarkerSizes(float markerScale) -{ - vector markerSizes; - markerSizes.reserve(df::kRouteHalfWidthInPixelTransit.size()); - for (auto const halfWidth : df::kRouteHalfWidthInPixelTransit) - { - float const d = 2 * halfWidth * markerScale; - markerSizes.push_back(m2::PointF(d, d)); - } - return markerSizes; -} - -void CreateTransitMarks(vector const & transitMarks, std::map symbolSizes, - UserMarksController & marksController) -{ - static vector const kTransferMarkerSizes = GetTransitMarkerSizes(kTransferMarkerScale); - static vector const kStopMarkerSizes = GetTransitMarkerSizes(kStopMarkerScale); - - static const int kSmallIconZoom = 1; - static const int kMediumIconZoom = 10; - static const int kLargeIconZoom = 15; - static const int kMinStopTitleZoom = 14; - static const float kGateBgScale = 1.2f; - static const int kTransferTitleOffset = 1; - static const int kStopTitleOffset = 0; - static const int kGateTitleOffset = 0; - - auto const vs = df::VisualParams::Instance().GetVisualScale(); - for (size_t i = 0; i < transitMarks.size(); ++i) - { - auto const &mark = transitMarks[i]; - - auto userMark = marksController.CreateUserMark(mark.m_point); - ASSERT(dynamic_cast(userMark) != nullptr, ()); - auto transitMark = static_cast(userMark); - dp::TitleDecl titleDecl; - - transitMark->SetFeatureId(mark.m_featureId); - - if (mark.m_type == TransitMarkInfo::Type::Gate) - { - if (!mark.m_titles.empty()) - { - TransitMark::GetDefaultTransitTitle(titleDecl); - titleDecl.m_primaryText = mark.m_titles.front().m_text; - titleDecl.m_primaryOffset.y = kGateTitleOffset; - titleDecl.m_anchor = dp::Anchor::Top; - titleDecl.m_primaryOptional = true; - transitMark->AddTitle(titleDecl); - } - df::UserPointMark::SymbolNameZoomInfo symbolNames; - symbolNames[kSmallIconZoom] = mark.m_symbolName + "-s"; - symbolNames[kMediumIconZoom] = mark.m_symbolName + "-m"; - symbolNames[kLargeIconZoom] = mark.m_symbolName + "-l"; - transitMark->SetSymbolNames(symbolNames); - transitMark->SetPriority(UserMark::Priority::Transit_Gate); - } - else if (mark.m_type == TransitMarkInfo::Type::Transfer) - { - if (mark.m_titles.size() > 1) - { - TransitMark::GetDefaultTransitTitle(titleDecl); - titleDecl.m_primaryText = mark.m_titles.front().m_text; - titleDecl.m_primaryTextFont.m_color = df::GetColorConstant(mark.m_titles.front().m_color); - titleDecl.m_primaryOffset.y = -kTransferTitleOffset; - titleDecl.m_anchor = dp::Anchor::Bottom; - titleDecl.m_primaryOptional = true; - transitMark->AddTitle(titleDecl); - - titleDecl.m_primaryText = mark.m_titles.back().m_text; - titleDecl.m_primaryTextFont.m_color = df::GetColorConstant(mark.m_titles.back().m_color); - titleDecl.m_primaryOffset.y = kTransferTitleOffset; - titleDecl.m_anchor = dp::Anchor::Top; - titleDecl.m_primaryOptional = true; - transitMark->AddTitle(titleDecl); - } - df::UserPointMark::ColoredSymbolZoomInfo coloredSymbol; - for (size_t sizeIndex = 0; sizeIndex < kTransferMarkerSizes.size(); ++sizeIndex) - { - auto const zoomLevel = sizeIndex + 1; - auto const & sz = kTransferMarkerSizes[sizeIndex]; - df::ColoredSymbolViewParams params; - params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * vs / 2.0); - params.m_color = dp::Color::Transparent(); - if (coloredSymbol.empty() || coloredSymbol.rbegin()->second.m_radiusInPixels != params.m_radiusInPixels) - coloredSymbol.insert(make_pair(zoomLevel, params)); - } - transitMark->SetColoredSymbols(coloredSymbol); - transitMark->SetPriority(UserMark::Priority::Transit_Transfer); - } - else - { - if (!mark.m_titles.empty()) - { - TransitMark::GetDefaultTransitTitle(titleDecl); - titleDecl.m_primaryText = mark.m_titles.front().m_text; - titleDecl.m_primaryTextFont.m_color = df::GetColorConstant(mark.m_titles.front().m_color); - titleDecl.m_primaryOffset.y = kStopTitleOffset; - titleDecl.m_anchor = dp::Anchor::Top; - titleDecl.m_primaryOptional = true; - transitMark->AddTitle(titleDecl); - } - if (mark.m_type == TransitMarkInfo::Type::KeyStop) - { - df::UserPointMark::SymbolNameZoomInfo symbolNames; - symbolNames[kSmallIconZoom] = mark.m_symbolName + "-s"; - symbolNames[kMediumIconZoom] = mark.m_symbolName + "-m"; - symbolNames[kLargeIconZoom] = mark.m_symbolName + "-l"; - transitMark->SetSymbolNames(symbolNames); - - df::UserPointMark::ColoredSymbolZoomInfo coloredSymbol; - df::ColoredSymbolViewParams params; - params.m_color = df::GetColorConstant(mark.m_color); - - auto sz = symbolSizes[symbolNames[kSmallIconZoom]]; - params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * kGateBgScale / 2.0); - coloredSymbol[kSmallIconZoom] = params; - - sz = symbolSizes[symbolNames[kMediumIconZoom]]; - params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * kGateBgScale / 2.0); - coloredSymbol[kMediumIconZoom] = params; - - sz = symbolSizes[symbolNames[kLargeIconZoom]]; - params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * kGateBgScale / 2.0); - coloredSymbol[kLargeIconZoom] = params; - - transitMark->SetColoredSymbols(coloredSymbol); - transitMark->SetPriority(UserMark::Priority::Transit_KeyStop); - } - else - { - df::UserPointMark::ColoredSymbolZoomInfo coloredSymbol; - for (size_t sizeIndex = 0; sizeIndex < kStopMarkerSizes.size(); ++sizeIndex) - { - auto const zoomLevel = sizeIndex + 1; - auto const & sz = kStopMarkerSizes[sizeIndex]; - df::ColoredSymbolViewParams params; - params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * vs / 2.0); - params.m_color = dp::Color::Transparent(); - if (coloredSymbol.empty() || coloredSymbol.rbegin()->second.m_radiusInPixels != params.m_radiusInPixels) - coloredSymbol.insert(make_pair(zoomLevel, params)); - } - transitMark->SetColoredSymbols(coloredSymbol); - transitMark->SetPriority(UserMark::Priority::Transit_Stop); - transitMark->SetMinTitleZoom(kMinStopTitleZoom); - } - } - } -} - RouteMarkData GetLastPassedPoint(BookmarkManager * bmManager, vector const & points) { ASSERT_GREATER_OR_EQUAL(points.size(), 2, ()); @@ -734,59 +223,6 @@ namespace marketing char const * const kRoutingCalculatingRoute = "Routing_CalculatingRoute"; } // namespace marketing -TransitStepInfo::TransitStepInfo(TransitType type, double distance, int time, - std::string const & number, uint32_t color, - int intermediateIndex) - : m_type(type) - , m_distanceInMeters(distance) - , m_timeInSec(time) - , m_number(number) - , m_colorARGB(color) - , m_intermediateIndex(intermediateIndex) -{} - -bool TransitStepInfo::IsEqualType(TransitStepInfo const & ts) const -{ - if (m_type != ts.m_type) - return false; - - if (m_type != TransitType::Pedestrian && m_type != TransitType::IntermediatePoint) - return m_number == ts.m_number && m_colorARGB == ts.m_colorARGB; - return true; -} - -void TransitRouteInfo::AddStep(TransitStepInfo const & step) -{ - if (!m_steps.empty() && m_steps.back().IsEqualType(step)) - { - m_steps.back().m_distanceInMeters += step.m_distanceInMeters; - m_steps.back().m_timeInSec += step.m_timeInSec; - } - else - { - m_steps.push_back(step); - } - - if (step.m_type == TransitType::Pedestrian) - { - m_totalPedestrianDistInMeters += step.m_distanceInMeters; - m_totalPedestrianTimeInSec += step.m_timeInSec; - } -} - -void TransitRouteInfo::UpdateDistanceStrings() -{ - if (m_steps.empty()) - return; - for (auto & step : m_steps) - { - FormatDistance(step.m_distanceInMeters, step.m_distanceStr, step.m_distanceUnitsSuffix); - } - FormatDistance(m_totalDistInMeters, m_totalDistanceStr, m_totalDistanceUnitsSuffix); - FormatDistance(m_totalPedestrianDistInMeters, m_totalPedestrianDistanceStr, - m_totalPedestrianUnitsSuffix); -} - RoutingManager::RoutingManager(Callbacks && callbacks, Delegate & delegate) : m_callbacks(move(callbacks)) , m_delegate(delegate) @@ -1008,10 +444,24 @@ void RoutingManager::InsertRoute(Route const & route) // TODO: Now we always update whole route, so we need to remove previous one. RemoveRoute(false /* deactivateFollowing */); + std::unique_ptr transitRouteDisplay; + auto numMwmIds = make_shared(); + if (m_currentRouterType == RouterType::Transit) + { + m_delegate.RegisterCountryFilesOnRoute(numMwmIds); + auto getMwmId = [this, &numMwmIds](routing::NumMwmId numMwmId) + { + return m_callbacks.m_indexGetter().GetMwmIdByCountryFile(numMwmIds->GetFile(numMwmId)); + }; + transitRouteDisplay = make_unique(m_transitReadManager, getMwmId, + m_callbacks.m_stringsBundleGetter, + m_bmManager, m_transitSymbolSizes); + } + vector segments; vector points; double distance = 0.0; - TransitRouteInfo transitRouteInfo; + auto const subroutesCount = route.GetSubrouteCount(); for (size_t subrouteIndex = route.GetCurrentSubrouteIdx(); subrouteIndex < subroutesCount; ++subrouteIndex) { @@ -1057,35 +507,13 @@ void RoutingManager::InsertRoute(Route const & route) case RouterType::Transit: { subroute->m_routeType = df::RouteType::Transit; - - auto numMwmIds = make_shared(); - m_delegate.RegisterCountryFilesOnRoute(numMwmIds); - auto getMwmIdFn = [this, &numMwmIds](routing::NumMwmId numMwmId) - { - return m_callbacks.m_indexGetter().GetMwmIdByCountryFile(numMwmIds->GetFile(numMwmId)); - }; - - vector transitMarks; - if (subrouteIndex > 0) - { - TransitStepInfo step; - step.m_type = TransitType::IntermediatePoint; - step.m_intermediateIndex = static_cast(subrouteIndex - 1); - transitRouteInfo.AddStep(step); - } - - FillTransitStyleForRendering(segments, m_transitReadManager, getMwmIdFn, m_callbacks.m_stringsBundleGetter, - *subroute.get(), transitMarks, transitRouteInfo); + transitRouteDisplay->ProcessSubroute(segments, *subroute.get()); if (subroute->m_polyline.GetSize() < 2) { LOG(LWARNING, ("Invalid transit subroute. Points number =", subroute->m_polyline.GetSize())); continue; } - - auto & marksController = m_bmManager->GetUserMarksController(UserMark::Type::TRANSIT); - CreateTransitMarks(transitMarks, m_transitSymbolSizes, marksController); - marksController.NotifyChanges(); break; } case RouterType::Pedestrian: @@ -1106,12 +534,13 @@ void RoutingManager::InsertRoute(Route const & route) // TODO: we will send subrouteId to routing subsystem when we can partly update route. //route.SetSubrouteUid(subrouteIndex, static_cast(subrouteId)); - lock_guard lock(m_drapeSubroutesMutex); m_drapeSubroutes.push_back(subrouteId); - transitRouteInfo.UpdateDistanceStrings(); - m_transitRouteInfo = transitRouteInfo; } + + lock_guard lock(m_drapeSubroutesMutex); + m_transitRouteInfo = m_currentRouterType == RouterType::Transit ? transitRouteDisplay->GetRouteInfo() + : TransitRouteInfo(); } void RoutingManager::FollowRoute() diff --git a/map/routing_manager.hpp b/map/routing_manager.hpp index 97411b01a9..f19a4573fd 100644 --- a/map/routing_manager.hpp +++ b/map/routing_manager.hpp @@ -2,7 +2,8 @@ #include "map/bookmark_manager.hpp" #include "map/routing_mark.hpp" -#include "map/transit_reader.hpp" +#include "map/transit/transit_display.hpp" +#include "map/transit/transit_reader.hpp" #include "routing/route.hpp" #include "routing/routing_session.hpp" @@ -50,60 +51,6 @@ struct RoutePointInfo m2::PointD m_position; }; -enum class TransitType: uint32_t -{ - // Do not change the order! - IntermediatePoint, - Pedestrian, - Subway, - Train, - LightRail, - Monorail -}; - -struct TransitStepInfo -{ - TransitStepInfo() = default; - TransitStepInfo(TransitType type, double distance, int time, - std::string const & number = "", uint32_t color = 0, - int intermediateIndex = 0); - - bool IsEqualType(TransitStepInfo const & ts) const; - - TransitType m_type = TransitType::Pedestrian; - - double m_distanceInMeters = 0.0; - int m_timeInSec = 0; - - std::string m_distanceStr; - std::string m_distanceUnitsSuffix; - - // Is valid for TransitType::Subway - std::string m_number; - uint32_t m_colorARGB = 0; - - // Is valid for TransitType::IntermediatePoint - int m_intermediateIndex = 0; -}; - -struct TransitRouteInfo -{ - double m_totalDistInMeters = 0.0; - double m_totalPedestrianDistInMeters = 0.0; - int m_totalTimeInSec = 0; - int m_totalPedestrianTimeInSec = 0; - - std::string m_totalDistanceStr; - std::string m_totalDistanceUnitsSuffix; - std::string m_totalPedestrianDistanceStr; - std::string m_totalPedestrianUnitsSuffix; - - std::vector m_steps; - - void AddStep(TransitStepInfo const & step); - void UpdateDistanceStrings(); -}; - class RoutingManager final { public: diff --git a/map/routing_mark.cpp b/map/routing_mark.cpp index 1ceec7b412..831b3fc743 100644 --- a/map/routing_mark.cpp +++ b/map/routing_mark.cpp @@ -425,12 +425,6 @@ void TransitMark::SetSymbolNames(std::map const & symbolNames) m_symbolNames = symbolNames; } -void TransitMark::SetSymbolSizes(std::vector const & symbolSizes) -{ - SetDirty(); - m_symbolSizes = symbolSizes; -} - void TransitMark::SetColoredSymbols(std::map const & symbolParams) { SetDirty(); @@ -444,13 +438,6 @@ drape_ptr TransitMark::GetColoredSymbo return make_unique_dp(m_coloredSymbols); } -drape_ptr TransitMark::GetSymbolSizes() const -{ - if (m_symbolSizes.empty()) - return nullptr; - return make_unique_dp(m_symbolSizes); -} - drape_ptr TransitMark::GetSymbolNames() const { if (m_symbolNames.empty()) diff --git a/map/routing_mark.hpp b/map/routing_mark.hpp index 93d7db3900..b1054b7adb 100644 --- a/map/routing_mark.hpp +++ b/map/routing_mark.hpp @@ -126,9 +126,6 @@ public: void SetMinTitleZoom(int minTitleZoom); int GetMinTitleZoom() const override { return m_minTitleZoom; } - void SetSymbolSizes(SymbolSizesZoomInfo const & symbolSizes); - drape_ptr GetSymbolSizes() const override; - void SetColoredSymbols(ColoredSymbolZoomInfo const & symbolParams); drape_ptr GetColoredSymbols() const override; @@ -146,7 +143,6 @@ private: Priority m_priority; FeatureID m_featureId; TitlesInfo m_titles; - SymbolSizesZoomInfo m_symbolSizes; SymbolNameZoomInfo m_symbolNames; ColoredSymbolZoomInfo m_coloredSymbols; }; \ No newline at end of file diff --git a/map/transit/transit_display.cpp b/map/transit/transit_display.cpp new file mode 100644 index 0000000000..ac0b8b3d49 --- /dev/null +++ b/map/transit/transit_display.cpp @@ -0,0 +1,579 @@ +#include "transit_display.hpp" + +#include "drape_frontend/route_renderer.hpp" +#include "drape_frontend/visual_params.hpp" + +#include "routing/routing_session.hpp" + +using namespace std; +using namespace routing; + +map const kTransitSymbols = { + {TransitType::Subway, "transit_subway"}, + {TransitType::LightRail, "transit_light_rail"}, + {TransitType::Monorail, "transit_monorail"}, + {TransitType::Train, "transit_train"} +}; + +namespace +{ +float const kStopMarkerScale = 2.2f; +float const kTransferMarkerScale = 4.0f; +const float kGateBgScale = 1.2f; + +const int kSmallIconZoom = 1; +const int kMediumIconZoom = 10; +const int kLargeIconZoom = 15; + +const int kMinStopTitleZoom = 14; + +const int kTransferTitleOffset = 1; +const int kStopTitleOffset = 0; +const int kGateTitleOffset = 0; + +TransitType GetTransitType(string const &type) +{ + if (type == "subway") + return TransitType::Subway; + if (type == "light_rail") + return TransitType::LightRail; + if (type == "monorail") + return TransitType::Monorail; + + ASSERT_EQUAL(type, "train", ()); + return TransitType::Train; +} + +uint32_t ColorToARGB(df::ColorConstant const & colorConstant) +{ + auto const color = df::GetColorConstant(colorConstant); + return color.GetAlpha() << 24 | color.GetRed() << 16 | color.GetGreen() << 8 | color.GetBlue(); +} + +vector GetTransitMarkerSizes(float markerScale) +{ + vector markerSizes; + markerSizes.reserve(df::kRouteHalfWidthInPixelTransit.size()); + for (auto const halfWidth : df::kRouteHalfWidthInPixelTransit) + { + float const d = 2 * halfWidth * markerScale; + markerSizes.push_back(m2::PointF(d, d)); + } + return markerSizes; +} +} // namespace + +TransitStepInfo::TransitStepInfo(TransitType type, double distance, int time, + std::string const & number, uint32_t color, + int intermediateIndex) + : m_type(type) + , m_distanceInMeters(distance) + , m_timeInSec(time) + , m_number(number) + , m_colorARGB(color) + , m_intermediateIndex(intermediateIndex) +{} + +bool TransitStepInfo::IsEqualType(TransitStepInfo const & ts) const +{ + if (m_type != ts.m_type) + return false; + + if (m_type != TransitType::Pedestrian && m_type != TransitType::IntermediatePoint) + return m_number == ts.m_number && m_colorARGB == ts.m_colorARGB; + return true; +} + +void TransitRouteInfo::AddStep(TransitStepInfo const & step) +{ + if (!m_steps.empty() && m_steps.back().IsEqualType(step)) + { + m_steps.back().m_distanceInMeters += step.m_distanceInMeters; + m_steps.back().m_timeInSec += step.m_timeInSec; + } + else + { + m_steps.push_back(step); + } + + if (step.m_type == TransitType::Pedestrian) + { + m_totalPedestrianDistInMeters += step.m_distanceInMeters; + m_totalPedestrianTimeInSec += step.m_timeInSec; + } +} + +void TransitRouteInfo::UpdateDistanceStrings() +{ + if (m_steps.empty()) + return; + for (auto & step : m_steps) + { + FormatDistance(step.m_distanceInMeters, step.m_distanceStr, step.m_distanceUnitsSuffix); + } + FormatDistance(m_totalDistInMeters, m_totalDistanceStr, m_totalDistanceUnitsSuffix); + FormatDistance(m_totalPedestrianDistInMeters, m_totalPedestrianDistanceStr, + m_totalPedestrianUnitsSuffix); +} + +void AddTransitGateSegment(m2::PointD const & destPoint, df::ColorConstant const & color, df::Subroute & subroute) +{ + ASSERT_GREATER(subroute.m_polyline.GetSize(), 0, ()); + df::SubrouteStyle style(color, df::RoutePattern(4.0, 2.0)); + style.m_startIndex = subroute.m_polyline.GetSize() - 1; + auto const vec = destPoint - subroute.m_polyline.Back(); + subroute.m_polyline.Add(destPoint); + style.m_endIndex = subroute.m_polyline.GetSize() - 1; + subroute.AddStyle(style); +} + +void AddTransitPedestrianSegment(m2::PointD const & destPoint, df::Subroute & subroute) +{ + ASSERT_GREATER(subroute.m_polyline.GetSize(), 0, ()); + df::SubrouteStyle style(df::kRoutePedestrian, df::RoutePattern(4.0, 2.0)); + style.m_startIndex = subroute.m_polyline.GetSize() - 1; + subroute.m_polyline.Add(destPoint); + style.m_endIndex = subroute.m_polyline.GetSize() - 1; + subroute.AddStyle(style); +} + +void AddTransitShapes(std::vector const & shapeIds, TransitShapesInfo const & shapes, + df::ColorConstant const & color, bool isInverted, df::Subroute & subroute) +{ + ASSERT_GREATER(subroute.m_polyline.GetSize(), 0, ()); + df::SubrouteStyle style(color); + style.m_startIndex = subroute.m_polyline.GetSize() - 1; + + for (auto it = shapeIds.crbegin(); it != shapeIds.crend(); ++it) + { + auto const & shapePolyline = shapes.at(*it).GetPolyline(); + if (isInverted) + subroute.m_polyline.Append(shapePolyline.crbegin(), shapePolyline.crend()); + else + subroute.m_polyline.Append(shapePolyline.cbegin(), shapePolyline.cend()); + } + + style.m_endIndex = subroute.m_polyline.GetSize() - 1; + subroute.AddStyle(style); +} + +TransitRouteDisplay::TransitRouteDisplay(TransitReadManager & transitReadManager, GetMwmIdFn const & getMwmIdFn, + GetStringsBundleFn const & getStringsBundleFn, BookmarkManager * bmManager, + std::map const & transitSymbolSizes) + : m_transitReadManager(transitReadManager) + , m_getMwmIdFn(getMwmIdFn) + , m_getStringsBundleFn(getStringsBundleFn) + , m_bmManager(bmManager) + , m_symbolSizes(transitSymbolSizes) +{ +} + +TransitRouteInfo const & TransitRouteDisplay::GetRouteInfo() +{ + m_routeInfo.UpdateDistanceStrings(); + return m_routeInfo; +} + +void TransitRouteDisplay::ProcessSubroute(vector const & segments, df::Subroute & subroute) +{ + if (m_subrouteIndex > 0) + { + TransitStepInfo step; + step.m_type = TransitType::IntermediatePoint; + step.m_intermediateIndex = m_subrouteIndex - 1; + m_routeInfo.AddStep(step); + } + ++m_subrouteIndex; + + TransitDisplayInfos transitDisplayInfos; + CollectTransitDisplayInfo(segments, transitDisplayInfos); + + // Read transit display info. + if (!m_transitReadManager.GetTransitDisplayInfo(transitDisplayInfos)) + return; + + std::vector transitMarks; + + subroute.m_styleType = df::SubrouteStyleType::Multiple; + subroute.m_style.clear(); + subroute.m_style.reserve(segments.size()); + + df::ColorConstant lastColor; + m2::PointD lastDir; + + df::SubrouteMarker marker; + TransitMarkInfo transitMarkInfo; + TransitType transitType = TransitType::Pedestrian; + + double prevDistance = m_routeInfo.m_totalDistInMeters; + double prevTime = m_routeInfo.m_totalTimeInSec; + + bool pendingEntrance = false; + + for (auto const & s : segments) + { + auto const time = static_cast(ceil(s.GetTimeFromBeginningSec() - prevTime)); + auto const distance = s.GetDistFromBeginningMeters() - prevDistance; + prevDistance = s.GetDistFromBeginningMeters(); + prevTime = s.GetTimeFromBeginningSec(); + + if (!s.HasTransitInfo()) + { + m_routeInfo.AddStep(TransitStepInfo(TransitType::Pedestrian, distance, time)); + + AddTransitPedestrianSegment(s.GetJunction().GetPoint(), subroute); + lastColor = ""; + transitType = TransitType::Pedestrian; + continue; + } + + auto const mwmId = m_getMwmIdFn(s.GetSegment().GetMwmId()); + + auto const & transitInfo = s.GetTransitInfo(); + auto const & displayInfo = *transitDisplayInfos.at(mwmId).get(); + + if (transitInfo.GetType() == TransitInfo::Type::Edge) + { + auto const & edge = transitInfo.GetEdge(); + + auto const & line = displayInfo.m_lines.at(edge.m_lineId); + auto const currentColor = df::GetTransitColorName(line.GetColor()); + transitType = GetTransitType(line.GetType()); + + m_routeInfo.AddStep(TransitStepInfo(transitType, distance, time, + line.GetNumber(), ColorToARGB(currentColor))); + + auto const & stop1 = displayInfo.m_stops.at(edge.m_stop1Id); + auto const & stop2 = displayInfo.m_stops.at(edge.m_stop2Id); + bool const isTransfer1 = stop1.GetTransferId() != transit::kInvalidTransferId; + bool const isTransfer2 = stop2.GetTransferId() != transit::kInvalidTransferId; + + marker.m_distance = prevDistance; + marker.m_scale = kStopMarkerScale; + marker.m_innerColor = currentColor; + if (isTransfer1) + { + auto const & transferData = displayInfo.m_transfers.at(stop1.GetTransferId()); + marker.m_position = transferData.GetPoint(); + } + else + { + marker.m_position = stop1.GetPoint(); + } + transitMarkInfo.m_point = marker.m_position; + + if (pendingEntrance) + { + transitMarkInfo.m_type = TransitMarkInfo::Type::KeyStop; + transitMarkInfo.m_symbolName = kTransitSymbols.at(transitType); + transitMarkInfo.m_color = currentColor; + AddTransitGateSegment(marker.m_position, currentColor, subroute); + pendingEntrance = false; + } + + auto const id1 = isTransfer1 ? stop1.GetTransferId() : stop1.GetId(); + auto const id2 = isTransfer2 ? stop2.GetTransferId() : stop2.GetId(); + bool const isInverted = id1 > id2; + + AddTransitShapes(edge.m_shapeIds, displayInfo.m_shapes, currentColor, isInverted, subroute); + + ASSERT_GREATER(subroute.m_polyline.GetSize(), 1, ()); + auto const & p1 = *(subroute.m_polyline.End() - 2); + auto const & p2 = *(subroute.m_polyline.End() - 1); + m2::PointD currentDir = (p2 - p1).Normalize(); + + if (lastColor != currentColor) + { + if (!lastColor.empty()) + { + marker.m_scale = kTransferMarkerScale; + transitMarkInfo.m_type = TransitMarkInfo::Type::Transfer; + } + marker.m_colors.push_back(currentColor); + + if (stop1.GetFeatureId() != transit::kInvalidFeatureId) + { + auto const fid = FeatureID(mwmId, stop1.GetFeatureId()); + transitMarkInfo.m_featureId = fid; + transitMarkInfo.m_titles.emplace_back(displayInfo.m_features.at(fid).m_title, + df::GetTransitTextColorName(line.GetColor())); + } + } + lastColor = currentColor; + + if (marker.m_colors.size() > 1) + { + marker.m_innerColor = df::kTransitOutlineColor; + marker.m_up = (currentDir - lastDir).Normalize(); + if (m2::CrossProduct(marker.m_up, -lastDir) < 0) + marker.m_up = -marker.m_up; + } + + subroute.m_markers.push_back(marker); + marker = df::SubrouteMarker(); + + transitMarks.push_back(transitMarkInfo); + transitMarkInfo = TransitMarkInfo(); + + lastDir = currentDir; + + marker.m_distance = s.GetDistFromBeginningMeters(); + marker.m_scale = kStopMarkerScale; + marker.m_innerColor = currentColor; + marker.m_colors.push_back(currentColor); + + if (isTransfer2) + { + auto const & transferData = displayInfo.m_transfers.at(stop2.GetTransferId()); + marker.m_position = transferData.GetPoint(); + } + else + { + marker.m_position = stop2.GetPoint(); + } + + transitMarkInfo.m_point = marker.m_position; + if (stop2.GetFeatureId() != transit::kInvalidFeatureId) + { + auto const fid = FeatureID(mwmId, stop2.GetFeatureId()); + transitMarkInfo.m_featureId = fid; + transitMarkInfo.m_titles.push_back(TransitTitle(displayInfo.m_features.at(fid).m_title, + df::GetTransitTextColorName(line.GetColor()))); + } + } + else if (transitInfo.GetType() == TransitInfo::Type::Gate) + { + auto const & gate = transitInfo.GetGate(); + if (!lastColor.empty()) + { + m_routeInfo.AddStep(TransitStepInfo(TransitType::Pedestrian, distance, time)); + + AddTransitGateSegment(s.GetJunction().GetPoint(), lastColor, subroute); + + subroute.m_markers.push_back(marker); + marker = df::SubrouteMarker(); + + transitMarkInfo.m_type = TransitMarkInfo::Type::KeyStop; + transitMarkInfo.m_symbolName = kTransitSymbols.at(transitType); + transitMarkInfo.m_color = lastColor; + transitMarks.push_back(transitMarkInfo); + transitMarkInfo = TransitMarkInfo(); + } + else + { + pendingEntrance = true; + } + + auto gateMarkInfo = TransitMarkInfo(); + gateMarkInfo.m_point = pendingEntrance ? subroute.m_polyline.Back() : s.GetJunction().GetPoint(); + gateMarkInfo.m_type = TransitMarkInfo::Type::Gate; + if (gate.m_featureId != transit::kInvalidFeatureId) + { + auto const fid = FeatureID(mwmId, gate.m_featureId); + auto const & featureInfo = displayInfo.m_features.at(fid); + auto symbolName = featureInfo.m_gateSymbolName; + if (strings::EndsWith(symbolName, "-s") || + strings::EndsWith(symbolName, "-m") || + strings::EndsWith(symbolName, "-l")) + { + symbolName = symbolName.substr(0, symbolName.length() - 2); + } + + gateMarkInfo.m_featureId = fid; + gateMarkInfo.m_symbolName = symbolName; + auto const title = m_getStringsBundleFn().GetString(pendingEntrance ? "entrance" : "exit"); + gateMarkInfo.m_titles.push_back(TransitTitle(title, df::GetTransitTextColorName("default"))); + } + + transitMarks.push_back(gateMarkInfo); + } + } + + m_routeInfo.m_totalDistInMeters = prevDistance; + m_routeInfo.m_totalTimeInSec = static_cast(ceil(prevTime)); + + CreateTransitMarks(transitMarks); +} + +void TransitRouteDisplay::CollectTransitDisplayInfo(vector const & segments, + TransitDisplayInfos & transitDisplayInfos) +{ + for (auto const & s : segments) + { + if (!s.HasTransitInfo()) + continue; + + auto const mwmId = m_getMwmIdFn(s.GetSegment().GetMwmId()); + + auto & mwmTransit = transitDisplayInfos[mwmId]; + if (mwmTransit == nullptr) + mwmTransit = my::make_unique(); + + TransitInfo const & transitInfo = s.GetTransitInfo(); + switch (transitInfo.GetType()) + { + case TransitInfo::Type::Edge: + { + auto const & edge = transitInfo.GetEdge(); + + mwmTransit->m_stops[edge.m_stop1Id] = {}; + mwmTransit->m_stops[edge.m_stop2Id] = {}; + mwmTransit->m_lines[edge.m_lineId] = {}; + for (auto const &shapeId : edge.m_shapeIds) + mwmTransit->m_shapes[shapeId] = {}; + break; + } + case TransitInfo::Type::Transfer: + { + auto const & transfer = transitInfo.GetTransfer(); + mwmTransit->m_stops[transfer.m_stop1Id] = {}; + mwmTransit->m_stops[transfer.m_stop2Id] = {}; + break; + } + case TransitInfo::Type::Gate: + { + auto const & gate = transitInfo.GetGate(); + if (gate.m_featureId != transit::kInvalidFeatureId) + { + auto const featureId = FeatureID(mwmId, gate.m_featureId); + TransitFeatureInfo featureInfo; + featureInfo.m_isGate = true; + mwmTransit->m_features[featureId] = featureInfo; + } + break; + } + } + } +} + +void TransitRouteDisplay::CreateTransitMarks(std::vector const & transitMarks) +{ + static vector const kTransferMarkerSizes = GetTransitMarkerSizes(kTransferMarkerScale); + static vector const kStopMarkerSizes = GetTransitMarkerSizes(kStopMarkerScale); + + auto & marksController = m_bmManager->GetUserMarksController(UserMark::Type::TRANSIT); + + auto const vs = df::VisualParams::Instance().GetVisualScale(); + for (size_t i = 0; i < transitMarks.size(); ++i) + { + auto const &mark = transitMarks[i]; + + auto userMark = marksController.CreateUserMark(mark.m_point); + ASSERT(dynamic_cast(userMark) != nullptr, ()); + auto transitMark = static_cast(userMark); + dp::TitleDecl titleDecl; + + transitMark->SetFeatureId(mark.m_featureId); + + if (mark.m_type == TransitMarkInfo::Type::Gate) + { + if (!mark.m_titles.empty()) + { + TransitMark::GetDefaultTransitTitle(titleDecl); + titleDecl.m_primaryText = mark.m_titles.front().m_text; + titleDecl.m_primaryOffset.y = kGateTitleOffset; + titleDecl.m_anchor = dp::Anchor::Top; + titleDecl.m_primaryOptional = true; + transitMark->AddTitle(titleDecl); + } + df::UserPointMark::SymbolNameZoomInfo symbolNames; + symbolNames[kSmallIconZoom] = mark.m_symbolName + "-s"; + symbolNames[kMediumIconZoom] = mark.m_symbolName + "-m"; + symbolNames[kLargeIconZoom] = mark.m_symbolName + "-l"; + transitMark->SetSymbolNames(symbolNames); + transitMark->SetPriority(UserMark::Priority::Transit_Gate); + } + else if (mark.m_type == TransitMarkInfo::Type::Transfer) + { + if (mark.m_titles.size() > 1) + { + TransitMark::GetDefaultTransitTitle(titleDecl); + titleDecl.m_primaryText = mark.m_titles.front().m_text; + titleDecl.m_primaryTextFont.m_color = df::GetColorConstant(mark.m_titles.front().m_color); + titleDecl.m_primaryOffset.y = -kTransferTitleOffset; + titleDecl.m_anchor = dp::Anchor::Bottom; + titleDecl.m_primaryOptional = true; + transitMark->AddTitle(titleDecl); + + titleDecl.m_primaryText = mark.m_titles.back().m_text; + titleDecl.m_primaryTextFont.m_color = df::GetColorConstant(mark.m_titles.back().m_color); + titleDecl.m_primaryOffset.y = kTransferTitleOffset; + titleDecl.m_anchor = dp::Anchor::Top; + titleDecl.m_primaryOptional = true; + transitMark->AddTitle(titleDecl); + } + df::UserPointMark::ColoredSymbolZoomInfo coloredSymbol; + for (size_t sizeIndex = 0; sizeIndex < kTransferMarkerSizes.size(); ++sizeIndex) + { + auto const zoomLevel = sizeIndex + 1; + auto const & sz = kTransferMarkerSizes[sizeIndex]; + df::ColoredSymbolViewParams params; + params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * vs / 2.0); + params.m_color = dp::Color::Transparent(); + if (coloredSymbol.empty() || coloredSymbol.rbegin()->second.m_radiusInPixels != params.m_radiusInPixels) + coloredSymbol.insert(make_pair(zoomLevel, params)); + } + transitMark->SetColoredSymbols(coloredSymbol); + transitMark->SetPriority(UserMark::Priority::Transit_Transfer); + } + else + { + if (!mark.m_titles.empty()) + { + TransitMark::GetDefaultTransitTitle(titleDecl); + titleDecl.m_primaryText = mark.m_titles.front().m_text; + titleDecl.m_primaryTextFont.m_color = df::GetColorConstant(mark.m_titles.front().m_color); + titleDecl.m_primaryOffset.y = kStopTitleOffset; + titleDecl.m_anchor = dp::Anchor::Top; + titleDecl.m_primaryOptional = true; + transitMark->AddTitle(titleDecl); + } + if (mark.m_type == TransitMarkInfo::Type::KeyStop) + { + df::UserPointMark::SymbolNameZoomInfo symbolNames; + symbolNames[kSmallIconZoom] = mark.m_symbolName + "-s"; + symbolNames[kMediumIconZoom] = mark.m_symbolName + "-m"; + symbolNames[kLargeIconZoom] = mark.m_symbolName + "-l"; + transitMark->SetSymbolNames(symbolNames); + + df::UserPointMark::ColoredSymbolZoomInfo coloredSymbol; + df::ColoredSymbolViewParams params; + params.m_color = df::GetColorConstant(mark.m_color); + + auto sz = m_symbolSizes.at(symbolNames[kSmallIconZoom]); + params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * kGateBgScale / 2.0); + coloredSymbol[kSmallIconZoom] = params; + + sz = m_symbolSizes.at(symbolNames[kMediumIconZoom]); + params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * kGateBgScale / 2.0); + coloredSymbol[kMediumIconZoom] = params; + + sz = m_symbolSizes.at(symbolNames[kLargeIconZoom]); + params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * kGateBgScale / 2.0); + coloredSymbol[kLargeIconZoom] = params; + + transitMark->SetColoredSymbols(coloredSymbol); + transitMark->SetPriority(UserMark::Priority::Transit_KeyStop); + } + else + { + df::UserPointMark::ColoredSymbolZoomInfo coloredSymbol; + for (size_t sizeIndex = 0; sizeIndex < kStopMarkerSizes.size(); ++sizeIndex) + { + auto const zoomLevel = sizeIndex + 1; + auto const & sz = kStopMarkerSizes[sizeIndex]; + df::ColoredSymbolViewParams params; + params.m_radiusInPixels = static_cast(max(sz.x, sz.y) * vs / 2.0); + params.m_color = dp::Color::Transparent(); + if (coloredSymbol.empty() || coloredSymbol.rbegin()->second.m_radiusInPixels != params.m_radiusInPixels) + coloredSymbol.insert(make_pair(zoomLevel, params)); + } + transitMark->SetColoredSymbols(coloredSymbol); + transitMark->SetPriority(UserMark::Priority::Transit_Stop); + transitMark->SetMinTitleZoom(kMinStopTitleZoom); + } + } + } + + marksController.NotifyChanges(); +} diff --git a/map/transit/transit_display.hpp b/map/transit/transit_display.hpp new file mode 100644 index 0000000000..1ec1242dd4 --- /dev/null +++ b/map/transit/transit_display.hpp @@ -0,0 +1,129 @@ +#pragma once + +#include "map/transit/transit_reader.hpp" + +#include "map/bookmark_manager.hpp" +#include "map/routing_mark.hpp" + +#include "drape_frontend/color_constants.hpp" +#include "drape_frontend/route_shape.hpp" + +#include "routing/route.hpp" + +#include +#include +#include +#include + +enum class TransitType: uint32_t +{ + // Do not change the order! + IntermediatePoint, + Pedestrian, + Subway, + Train, + LightRail, + Monorail +}; + +extern std::map const kTransitSymbols; + +struct TransitStepInfo +{ + TransitStepInfo() = default; + TransitStepInfo(TransitType type, double distance, int time, + std::string const & number = "", uint32_t color = 0, + int intermediateIndex = 0); + + bool IsEqualType(TransitStepInfo const & ts) const; + + TransitType m_type = TransitType::Pedestrian; + + double m_distanceInMeters = 0.0; + int m_timeInSec = 0; + + std::string m_distanceStr; + std::string m_distanceUnitsSuffix; + + // Is valid for all types except TransitType::IntermediatePoint and TransitType::Pedestrian + std::string m_number; + uint32_t m_colorARGB = 0; + + // Is valid for TransitType::IntermediatePoint + int m_intermediateIndex = 0; +}; + +struct TransitRouteInfo +{ + void AddStep(TransitStepInfo const & step); + void UpdateDistanceStrings(); + + double m_totalDistInMeters = 0.0; + double m_totalPedestrianDistInMeters = 0.0; + int m_totalTimeInSec = 0; + int m_totalPedestrianTimeInSec = 0; + + std::string m_totalDistanceStr; + std::string m_totalDistanceUnitsSuffix; + std::string m_totalPedestrianDistanceStr; + std::string m_totalPedestrianUnitsSuffix; + + std::vector m_steps; +}; + +struct TransitTitle +{ + TransitTitle() = default; + TransitTitle(string const & text, df::ColorConstant const & color) : m_text(text), m_color(color) {} + + string m_text; + df::ColorConstant m_color; +}; + +struct TransitMarkInfo +{ + enum class Type + { + Stop, + KeyStop, + Transfer, + Gate + }; + Type m_type = Type::Stop; + m2::PointD m_point; + std::vector m_titles; + std::string m_symbolName; + df::ColorConstant m_color; + FeatureID m_featureId; +}; + +class TransitRouteDisplay +{ +public: + using GetMwmIdFn = std::function; + using GetStringsBundleFn = std::function; + + TransitRouteDisplay(TransitReadManager & transitReadManager, GetMwmIdFn const & getMwmIdFn, + GetStringsBundleFn const & getStringsBundleFn, BookmarkManager * bmManager, + std::map const & transitSymbolSizes); + + void ProcessSubroute(std::vector const & segments, df::Subroute & subroute); + + + TransitRouteInfo const & GetRouteInfo(); + +private: + void CollectTransitDisplayInfo(std::vector const & segments, + TransitDisplayInfos & transitDisplayInfos); + void CreateTransitMarks(std::vector const & transitMarks); + + TransitReadManager & m_transitReadManager; + GetMwmIdFn m_getMwmIdFn; + GetStringsBundleFn m_getStringsBundleFn; + BookmarkManager * m_bmManager; + std::map const & m_symbolSizes; + + TransitRouteInfo m_routeInfo; + + int m_subrouteIndex = 0; +}; \ No newline at end of file diff --git a/map/transit_reader.cpp b/map/transit/transit_reader.cpp similarity index 99% rename from map/transit_reader.cpp rename to map/transit/transit_reader.cpp index d18b35bb81..3e896138c8 100644 --- a/map/transit_reader.cpp +++ b/map/transit/transit_reader.cpp @@ -1,4 +1,4 @@ -#include "map/transit_reader.hpp" +#include "map/transit/transit_reader.hpp" #include "indexer/drawing_rules.hpp" #include "indexer/drules_include.hpp" diff --git a/map/transit_reader.hpp b/map/transit/transit_reader.hpp similarity index 100% rename from map/transit_reader.hpp rename to map/transit/transit_reader.hpp diff --git a/map/user_mark.hpp b/map/user_mark.hpp index 14926099aa..1e739b3785 100644 --- a/map/user_mark.hpp +++ b/map/user_mark.hpp @@ -51,7 +51,6 @@ public: float GetDepth() const override; df::RenderState::DepthLayer GetDepthLayer() const override; drape_ptr GetTitleDecl() const override { return nullptr; } - drape_ptr GetSymbolSizes() const override { return nullptr; } drape_ptr GetColoredSymbols() const override { return nullptr; } uint16_t GetPriority() const override { return static_cast(Priority::Default); } bool HasSymbolPriority() const override { return false; } diff --git a/xcode/map/map.xcodeproj/project.pbxproj b/xcode/map/map.xcodeproj/project.pbxproj index 90c622afe6..57609953c2 100644 --- a/xcode/map/map.xcodeproj/project.pbxproj +++ b/xcode/map/map.xcodeproj/project.pbxproj @@ -117,9 +117,11 @@ 67F183811BD5049500AB1840 /* libagg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67F1837D1BD5049500AB1840 /* libagg.a */; }; 67F183831BD5049500AB1840 /* libminizip.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67F1837F1BD5049500AB1840 /* libminizip.a */; }; 67F183841BD5049500AB1840 /* libtess2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 67F183801BD5049500AB1840 /* libtess2.a */; }; - BB25B1A31FB320B2007276FA /* transit_reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB25B1A11FB320B1007276FA /* transit_reader.cpp */; }; - BB25B1A41FB320B2007276FA /* transit_reader.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BB25B1A21FB320B2007276FA /* transit_reader.hpp */; }; BB421D6C1E8C0031005BFA4D /* transliteration_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB421D6A1E8C0026005BFA4D /* transliteration_test.cpp */; }; + BB4E5F251FCC664A00A77250 /* transit_display.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB4E5F211FCC664A00A77250 /* transit_display.cpp */; }; + BB4E5F261FCC664A00A77250 /* transit_display.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BB4E5F221FCC664A00A77250 /* transit_display.hpp */; }; + BB4E5F271FCC664A00A77250 /* transit_reader.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BB4E5F231FCC664A00A77250 /* transit_reader.hpp */; }; + BB4E5F281FCC664A00A77250 /* transit_reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB4E5F241FCC664A00A77250 /* transit_reader.cpp */; }; BBD9E2C61EE9D01900DF189A /* routing_mark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBD9E2C41EE9D01900DF189A /* routing_mark.cpp */; }; BBD9E2C71EE9D01900DF189A /* routing_mark.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BBD9E2C51EE9D01900DF189A /* routing_mark.hpp */; }; F627BFC41E8E89B600B1CBF4 /* librouting_common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F627BFC31E8E89B600B1CBF4 /* librouting_common.a */; }; @@ -275,9 +277,11 @@ 67F183801BD5049500AB1840 /* libtess2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtess2.a; path = "../../../omim-xcode-build/Debug/libtess2.a"; sourceTree = ""; }; 67F183851BD504ED00AB1840 /* libsystem_configuration.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsystem_configuration.tbd; path = usr/lib/system/libsystem_configuration.tbd; sourceTree = SDKROOT; }; 67F183871BD5050900AB1840 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; - BB25B1A11FB320B1007276FA /* transit_reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transit_reader.cpp; sourceTree = ""; }; - BB25B1A21FB320B2007276FA /* transit_reader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = transit_reader.hpp; sourceTree = ""; }; BB421D6A1E8C0026005BFA4D /* transliteration_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = transliteration_test.cpp; sourceTree = ""; }; + BB4E5F211FCC664A00A77250 /* transit_display.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = transit_display.cpp; path = transit/transit_display.cpp; sourceTree = ""; }; + BB4E5F221FCC664A00A77250 /* transit_display.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = transit_display.hpp; path = transit/transit_display.hpp; sourceTree = ""; }; + BB4E5F231FCC664A00A77250 /* transit_reader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = transit_reader.hpp; path = transit/transit_reader.hpp; sourceTree = ""; }; + BB4E5F241FCC664A00A77250 /* transit_reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = transit_reader.cpp; path = transit/transit_reader.cpp; sourceTree = ""; }; BBD9E2C41EE9D01900DF189A /* routing_mark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = routing_mark.cpp; sourceTree = ""; }; BBD9E2C51EE9D01900DF189A /* routing_mark.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = routing_mark.hpp; sourceTree = ""; }; F627BFC31E8E89B600B1CBF4 /* librouting_common.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = librouting_common.a; path = "/Users/v.mikhaylenko/mapsme/omim/xcode/routing_common/../../../omim-build/xcode/Debug/librouting_common.a"; sourceTree = ""; }; @@ -481,6 +485,7 @@ 675345BD1A4054AD00A0A8C3 /* map */ = { isa = PBXGroup; children = ( + BB4E5F201FCC663700A77250 /* transit */, F6FC3CB11FC323420001D929 /* discovery */, 3D4E999F1FB4A6400025B48C /* booking_filter_cache.cpp */, 3D4E999E1FB4A6400025B48C /* booking_filter_cache.hpp */, @@ -548,8 +553,6 @@ 6753462D1A4054E800A0A8C3 /* track.hpp */, 347B60741DD9926D0050FA24 /* traffic_manager.cpp */, 347B60751DD9926D0050FA24 /* traffic_manager.hpp */, - BB25B1A11FB320B1007276FA /* transit_reader.cpp */, - BB25B1A21FB320B2007276FA /* transit_reader.hpp */, 6753462E1A4054E800A0A8C3 /* user_mark_container.cpp */, 6753462F1A4054E800A0A8C3 /* user_mark_container.hpp */, 674C385F1BFF3095000D603B /* user_mark.cpp */, @@ -562,6 +565,17 @@ path = ../../map; sourceTree = ""; }; + BB4E5F201FCC663700A77250 /* transit */ = { + isa = PBXGroup; + children = ( + BB4E5F211FCC664A00A77250 /* transit_display.cpp */, + BB4E5F221FCC664A00A77250 /* transit_display.hpp */, + BB4E5F241FCC664A00A77250 /* transit_reader.cpp */, + BB4E5F231FCC664A00A77250 /* transit_reader.hpp */, + ); + name = transit; + sourceTree = ""; + }; F6FC3CB11FC323420001D929 /* discovery */ = { isa = PBXGroup; children = ( @@ -579,10 +593,10 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + BB4E5F261FCC664A00A77250 /* transit_display.hpp in Headers */, 347B60771DD9926D0050FA24 /* traffic_manager.hpp in Headers */, 45F6EE9E1FB1C77600019892 /* mwm_tree.hpp in Headers */, 6753466B1A4054E800A0A8C3 /* geourl_process.hpp in Headers */, - BB25B1A41FB320B2007276FA /* transit_reader.hpp in Headers */, F6B283081C1B03320081957A /* gps_track_storage.hpp in Headers */, 675346671A4054E800A0A8C3 /* ge0_parser.hpp in Headers */, 675346A21A4054E800A0A8C3 /* user_mark.hpp in Headers */, @@ -596,6 +610,7 @@ 6753464B1A4054E800A0A8C3 /* bookmark.hpp in Headers */, 3D47B2941F054BC5000828D2 /* taxi_delegate.hpp in Headers */, 3D47B2C81F20EF06000828D2 /* displayed_categories_modifiers.hpp in Headers */, + BB4E5F271FCC664A00A77250 /* transit_reader.hpp in Headers */, 348AB57D1D7EE0C6009F8301 /* chart_generator.hpp in Headers */, 45A2D9D61F7556EB003310A0 /* user.hpp in Headers */, F63421F91DF9BF9100A96868 /* reachable_by_taxi_checker.hpp in Headers */, @@ -725,6 +740,7 @@ F6B283051C1B03320081957A /* gps_track_filter.cpp in Sources */, 675346481A4054E800A0A8C3 /* bookmark_manager.cpp in Sources */, 45F6EE9F1FB1C77600019892 /* search_api.cpp in Sources */, + BB4E5F251FCC664A00A77250 /* transit_display.cpp in Sources */, 3D47B2931F054BC5000828D2 /* taxi_delegate.cpp in Sources */, 675346741A4054E800A0A8C3 /* mwm_url.cpp in Sources */, 347B60761DD9926D0050FA24 /* traffic_manager.cpp in Sources */, @@ -738,6 +754,7 @@ 6753469D1A4054E800A0A8C3 /* user_mark_container.cpp in Sources */, 674C38621BFF3095000D603B /* user_mark.cpp in Sources */, 675346641A4054E800A0A8C3 /* framework.cpp in Sources */, + BB4E5F281FCC664A00A77250 /* transit_reader.cpp in Sources */, 454649F11F2728CE00EF4064 /* local_ads_mark.cpp in Sources */, F63421F81DF9BF9100A96868 /* reachable_by_taxi_checker.cpp in Sources */, 6753466A1A4054E800A0A8C3 /* geourl_process.cpp in Sources */, @@ -745,7 +762,6 @@ 342D833A1D5233E8000D8AEA /* displacement_mode_manager.cpp in Sources */, 3D47B2C71F20EF06000828D2 /* displayed_categories_modifiers.cpp in Sources */, 45201E931CE4AC90008A4842 /* api_mark_point.cpp in Sources */, - BB25B1A31FB320B2007276FA /* transit_reader.cpp in Sources */, F6FC3CB61FC323430001D929 /* discovery_manager.cpp in Sources */, 675346661A4054E800A0A8C3 /* ge0_parser.cpp in Sources */, F6D2CE7E1EDEB7F500636DFD /* routing_manager.cpp in Sources */,