diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index d4cd9d8a30..96f15c0451 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -331,9 +331,9 @@ void BackendRenderer::AcceptMessage(ref_ptr message) break; } - case Message::AddTrafficSegments: + case Message::CacheTrafficSegments: { - ref_ptr msg = message; + ref_ptr msg = message; for (auto const & segment : msg->GetSegments()) m_trafficGenerator->AddSegment(segment.first, segment.second); break; @@ -342,7 +342,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) case Message::UpdateTraffic: { ref_ptr msg = message; - auto segments = m_trafficGenerator->GetSegmentsToUpdate(msg->GetSegmentsData()); + auto segments = m_trafficGenerator->GetSegmentsToUpdate(msg->GetSegmentsColoring()); if (!segments.empty()) { m_commutator->PostMessage(ThreadsCommutator::RenderThread, @@ -350,10 +350,10 @@ void BackendRenderer::AcceptMessage(ref_ptr message) MessagePriority::Normal); } - if (segments.size() < msg->GetSegmentsData().size()) + if (segments.size() < msg->GetSegmentsColoring().size()) { vector data; - m_trafficGenerator->GetTrafficGeom(m_texMng, msg->GetSegmentsData(), data); + m_trafficGenerator->GetTrafficGeom(m_texMng, msg->GetSegmentsColoring(), data); m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp(move(data)), MessagePriority::Normal); diff --git a/drape_frontend/color_constants.cpp b/drape_frontend/color_constants.cpp index 4d64b1bd0b..23a50d0e95 100644 --- a/drape_frontend/color_constants.cpp +++ b/drape_frontend/color_constants.cpp @@ -24,9 +24,14 @@ unordered_map> kColorConstants = { TrackCarSpeed, dp::Color(21, 121, 244, 255) }, { TrackPlaneSpeed, dp::Color(10, 196, 255, 255) }, { TrackUnknownDistance, dp::Color(97, 97, 97, 255) }, - { TrafficNormal, dp::Color(60, 170, 60, 255) }, - { TrafficSlow, dp::Color(255, 219, 88, 255) }, - { TrafficVerySlow, dp::Color(227, 38, 54, 255) }, + { TrafficG0, dp::Color(60, 170, 60, 255) }, + { TrafficG1, dp::Color(60, 170, 60, 255) }, + { TrafficG2, dp::Color(227, 38, 54, 255) }, + { TrafficG3, dp::Color(100, 100, 100, 255) }, + { TrafficG4, dp::Color(100, 100, 100, 255) }, + { TrafficG5, dp::Color(100, 100, 100, 255) }, + { TrafficTempBlock, dp::Color(0, 0, 0, 255) }, + { TrafficUnknown, dp::Color(0, 0, 0, 0) }, } }, { MapStyleDark, @@ -43,9 +48,14 @@ unordered_map> kColorConstants = { TrackCarSpeed, dp::Color(255, 202, 40, 255) }, { TrackPlaneSpeed, dp::Color(255, 245, 160, 255) }, { TrackUnknownDistance, dp::Color(150, 150, 150, 255) }, - { TrafficNormal, dp::Color(60, 170, 60, 255) }, - { TrafficSlow, dp::Color(255, 219, 88, 255) }, - { TrafficVerySlow, dp::Color(227, 38, 54, 255) }, + { TrafficG0, dp::Color(60, 170, 60, 255) }, + { TrafficG1, dp::Color(60, 170, 60, 255) }, + { TrafficG2, dp::Color(227, 38, 54, 255) }, + { TrafficG3, dp::Color(100, 100, 100, 255) }, + { TrafficG4, dp::Color(100, 100, 100, 255) }, + { TrafficG5, dp::Color(100, 100, 100, 255) }, + { TrafficTempBlock, dp::Color(0, 0, 0, 255) }, + { TrafficUnknown, dp::Color(0, 0, 0, 0) }, } }, }; diff --git a/drape_frontend/color_constants.hpp b/drape_frontend/color_constants.hpp index 214ddc76f2..c982fb72e3 100644 --- a/drape_frontend/color_constants.hpp +++ b/drape_frontend/color_constants.hpp @@ -21,9 +21,14 @@ enum ColorConstant TrackCarSpeed, TrackPlaneSpeed, TrackUnknownDistance, - TrafficNormal, - TrafficSlow, - TrafficVerySlow + TrafficG0, + TrafficG1, + TrafficG2, + TrafficG3, + TrafficG4, + TrafficG5, + TrafficTempBlock, + TrafficUnknown, }; dp::Color GetColorConstant(MapStyle style, ColorConstant constant); diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 8a02c7ecab..fc873eccd2 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -533,20 +533,31 @@ void DrapeEngine::RequestSymbolsSize(vector const & symbols, MessagePriority::Normal); } -void DrapeEngine::AddTrafficSegments(vector> const & segments) +void DrapeEngine::CacheTrafficSegmentsGeometry(TrafficSegmentsGeometry const & segments) { + if (segments.empty()) + return; + m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(segments), + make_unique_dp(segments), MessagePriority::Normal); } -void DrapeEngine::UpdateTraffic(vector const & segmentsData) +void DrapeEngine::UpdateTraffic(TrafficSegmentsColoring const & segmentsColoring) { + if (segmentsColoring.empty()) + return; + m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(segmentsData), + make_unique_dp(segmentsColoring), MessagePriority::Normal); } +void DrapeEngine::ClearTrafficCache(MwmSet::MwmId const & mwmId) +{ + // TODO(@rokuz): implement +} + void DrapeEngine::SetFontScaleFactor(double scaleFactor) { double const kMinScaleFactor = 0.5; diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index d9a9b12df8..00d5445224 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -162,8 +162,9 @@ public: void RequestSymbolsSize(vector const & symbols, TRequestSymbolsSizeCallback const & callback); - void AddTrafficSegments(vector> const & segments); - void UpdateTraffic(vector const & segmentsData); + void CacheTrafficSegmentsGeometry(TrafficSegmentsGeometry const & segments); + void UpdateTraffic(TrafficSegmentsColoring const & segmentsColoring); + void ClearTrafficCache(MwmSet::MwmId const & mwmId); void SetFontScaleFactor(double scaleFactor); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 5e079c0e72..a2288f8bd7 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -742,7 +742,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::UpdateTraffic: { ref_ptr msg = message; - m_trafficRenderer->UpdateTraffic(msg->GetSegmentsData()); + m_trafficRenderer->UpdateTraffic(msg->GetSegmentsColoring()); break; } diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index a2e7fb7d16..7c6d351920 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -65,7 +65,7 @@ public: RequestSymbolsSize, RecoverGLResources, SetVisibleViewport, - AddTrafficSegments, + CacheTrafficSegments, SetTrafficTexCoords, UpdateTraffic, FlushTrafficData, diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index dc8e65d4d2..6d45e9cac4 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -977,46 +977,46 @@ private: TRequestSymbolsSizeCallback m_callback; }; -class AddTrafficSegmentsMessage : public Message +class CacheTrafficSegmentsMessage : public Message { public: - explicit AddTrafficSegmentsMessage(vector> const & segments) + explicit CacheTrafficSegmentsMessage(TrafficSegmentsGeometry const & segments) : m_segments(segments) {} - Type GetType() const override { return Message::AddTrafficSegments; } - vector> const & GetSegments() const { return m_segments; } + Type GetType() const override { return Message::CacheTrafficSegments; } + TrafficSegmentsGeometry const & GetSegments() const { return m_segments; } private: - vector> m_segments; + TrafficSegmentsGeometry m_segments; }; class SetTrafficTexCoordsMessage : public Message { public: - explicit SetTrafficTexCoordsMessage(unordered_map && texCoords) + explicit SetTrafficTexCoordsMessage(TrafficTexCoords && texCoords) : m_texCoords(move(texCoords)) {} Type GetType() const override { return Message::SetTrafficTexCoords; } - unordered_map && AcceptTexCoords() { return move(m_texCoords); } + TrafficTexCoords && AcceptTexCoords() { return move(m_texCoords); } private: - unordered_map m_texCoords; + TrafficTexCoords m_texCoords; }; class UpdateTrafficMessage : public Message { public: - explicit UpdateTrafficMessage(vector const & segmentsData) - : m_segmentsData(segmentsData) + explicit UpdateTrafficMessage(TrafficSegmentsColoring const & segmentsColoring) + : m_segmentsColoring(segmentsColoring) {} Type GetType() const override { return Message::UpdateTraffic; } - vector const & GetSegmentsData() const { return m_segmentsData; } + TrafficSegmentsColoring const & GetSegmentsColoring() const { return m_segmentsColoring; } private: - vector m_segmentsData; + TrafficSegmentsColoring m_segmentsColoring; }; class FlushTrafficDataMessage : public Message diff --git a/drape_frontend/traffic_generator.cpp b/drape_frontend/traffic_generator.cpp index a91368e7f5..6fb79e1996 100644 --- a/drape_frontend/traffic_generator.cpp +++ b/drape_frontend/traffic_generator.cpp @@ -86,7 +86,8 @@ void GenerateCapTriangles(glsl::vec3 const & pivot, vector const & n } // namespace -TrafficHandle::TrafficHandle(uint64_t segmentId, glsl::vec2 const & texCoord, size_t verticesCount) +TrafficHandle::TrafficHandle(TrafficSegmentID const & segmentId, glsl::vec2 const & texCoord, + size_t verticesCount) : OverlayHandle(FeatureID(), dp::Anchor::Center, 0, false) , m_segmentId(segmentId) , m_needUpdate(false) @@ -148,26 +149,26 @@ void TrafficHandle::SetTexCoord(glsl::vec2 const & texCoord) m_needUpdate = true; } -uint64_t TrafficHandle::GetSegmentId() const +TrafficSegmentID TrafficHandle::GetSegmentId() const { return m_segmentId; } -void TrafficGenerator::AddSegment(uint64_t segmentId, m2::PolylineD const & polyline) +void TrafficGenerator::AddSegment(TrafficSegmentID const & segmentId, m2::PolylineD const & polyline) { m_segments.insert(make_pair(segmentId, polyline)); } void TrafficGenerator::ClearCache() { - m_colorsCache.clear(); + m_colorsCacheValid = false; m_segmentsCache.clear(); } -vector TrafficGenerator::GetSegmentsToUpdate(vector const & trafficData) const +TrafficSegmentsColoring TrafficGenerator::GetSegmentsToUpdate(TrafficSegmentsColoring const & trafficColoring) const { - vector result; - for (TrafficSegmentData const & segment : trafficData) + TrafficSegmentsColoring result; + for (auto const & segment : trafficColoring) { if (m_segmentsCache.find(segment.m_id) != m_segmentsCache.end()) result.push_back(segment); @@ -176,21 +177,22 @@ vector TrafficGenerator::GetSegmentsToUpdate(vector textures, - vector const & trafficData, + TrafficSegmentsColoring const & trafficColoring, vector & data) { FillColorsCache(textures); dp::GLState state(gpu::TRAFFIC_PROGRAM, dp::GLState::GeometryLayer); - state.SetColorTexture(m_colorsCache[TrafficSpeedBucket::Normal].GetTexture()); + ASSERT(m_colorsCacheValid, ()); + state.SetColorTexture(m_colorsCache[static_cast(traffic::SpeedGroup::G0)].GetTexture()); state.SetMaskTexture(textures->GetTrafficArrowTexture()); int const kZoomLevel = 10; uint32_t const kBatchSize = 5000; using TSegIter = TSegmentCollection::iterator; - map>> segmentsByTiles; - for (TrafficSegmentData const & segment : trafficData) + map>> segmentsByTiles; + for (auto const & segment : trafficColoring) { // Check if a segment hasn't been added. auto it = m_segments.find(segment.m_id); @@ -203,7 +205,7 @@ void TrafficGenerator::GetTrafficGeom(ref_ptr textures, m_segmentsCache.insert(segment.m_id); TileKey const tileKey = GetTileKeyByPoint(it->second.GetLimitRect().Center(), kZoomLevel); - segmentsByTiles[tileKey].emplace_back(make_pair(it, segment.m_speedBucket)); + segmentsByTiles[tileKey].emplace_back(make_pair(it, segment.m_speedGroup)); } for (auto const & s : segmentsByTiles) @@ -221,7 +223,8 @@ void TrafficGenerator::GetTrafficGeom(ref_ptr textures, for (auto const & segmentPair : s.second) { TSegIter it = segmentPair.first; - dp::TextureManager::ColorRegion const & colorRegion = m_colorsCache[segmentPair.second]; + ASSERT(m_colorsCacheValid, ()); + dp::TextureManager::ColorRegion const & colorRegion = m_colorsCache[static_cast(segmentPair.second)]; m2::PolylineD const & polyline = it->second; vector staticGeometry; @@ -324,28 +327,38 @@ void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & c void TrafficGenerator::FillColorsCache(ref_ptr textures) { - if (m_colorsCache.empty()) + size_t constexpr kSpeedGroupsCount = static_cast(traffic::SpeedGroup::Count); + static array const colorMap + {{ + df::TrafficG0, + df::TrafficG1, + df::TrafficG2, + df::TrafficG3, + df::TrafficG4, + df::TrafficG5, + df::TrafficTempBlock, + df::TrafficUnknown, + }}; + + if (!m_colorsCacheValid) { auto const & style = GetStyleReader().GetCurrentStyle(); - dp::TextureManager::ColorRegion colorRegion; - textures->GetColorRegion(df::GetColorConstant(style, df::TrafficVerySlow), colorRegion); - m_colorsCache[TrafficSpeedBucket::VerySlow] = colorRegion; - - textures->GetColorRegion(df::GetColorConstant(style, df::TrafficSlow), colorRegion); - m_colorsCache[TrafficSpeedBucket::Slow] = colorRegion; - - textures->GetColorRegion(df::GetColorConstant(style, df::TrafficNormal), colorRegion); - m_colorsCache[TrafficSpeedBucket::Normal] = colorRegion; - + for (size_t i = 0; i < colorMap.size(); i++) + { + dp::TextureManager::ColorRegion colorRegion; + textures->GetColorRegion(df::GetColorConstant(style, colorMap[i]), colorRegion); + m_colorsCache[i] = colorRegion; + } + m_colorsCacheValid = true; m_colorsCacheRefreshed = true; } } -unordered_map TrafficGenerator::ProcessCacheRefreshing() +TrafficTexCoords TrafficGenerator::ProcessCacheRefreshing() { - unordered_map result; - for (auto it = m_colorsCache.begin(); it != m_colorsCache.end(); ++it) - result[it->first] = glsl::ToVec2(it->second.GetTexRect().Center()); + TrafficTexCoords result; + for (size_t i = 0; i < m_colorsCache.size(); i++) + result[i] = glsl::ToVec2(m_colorsCache[i].GetTexRect().Center()); m_colorsCacheRefreshed = false; return result; } diff --git a/drape_frontend/traffic_generator.hpp b/drape_frontend/traffic_generator.hpp index 6c36b8bcd4..eec4aaf286 100644 --- a/drape_frontend/traffic_generator.hpp +++ b/drape_frontend/traffic_generator.hpp @@ -9,8 +9,13 @@ #include "drape/render_bucket.hpp" #include "drape/texture_manager.hpp" +#include "traffic/traffic_info.hpp" + +#include "indexer/feature_decl.hpp" + #include "geometry/polyline2d.hpp" +#include "std/array.hpp" #include "std/map.hpp" #include "std/set.hpp" #include "std/string.hpp" @@ -20,25 +25,47 @@ namespace df { -enum TrafficSpeedBucket +struct TrafficSegmentID { - Normal = 3, - Slow = 2, - VerySlow = 1 + MwmSet::MwmId m_mwmId; + traffic::TrafficInfo::RoadSegmentId m_segmentId; + + TrafficSegmentID(MwmSet::MwmId const & mwmId, + traffic::TrafficInfo::RoadSegmentId const & segmentId) + : m_mwmId(mwmId) + , m_segmentId(segmentId) + {} + + inline bool operator<(TrafficSegmentID const & r) const + { + if (m_mwmId == r.m_mwmId) + return m_segmentId < r.m_segmentId; + return m_mwmId < r.m_mwmId; + } + + inline bool operator==(TrafficSegmentID const & r) const + { + return (m_mwmId == r.m_mwmId && m_segmentId == r.m_segmentId); + } + + inline bool operator!=(TrafficSegmentID const & r) const { return !(*this == r); } }; -struct TrafficSegmentData -{ - uint64_t m_id; - TrafficSpeedBucket m_speedBucket; +using TrafficSegmentsGeometry = vector>; - TrafficSegmentData() = default; - TrafficSegmentData(uint64_t id, TrafficSpeedBucket const & speedBucket) +struct TrafficSegmentColoring +{ + TrafficSegmentID m_id; + traffic::SpeedGroup m_speedGroup; + + TrafficSegmentColoring(TrafficSegmentID const & id, traffic::SpeedGroup const & speedGroup) : m_id(id) - , m_speedBucket(speedBucket) + , m_speedGroup(speedGroup) {} }; +using TrafficSegmentsColoring = vector; + struct TrafficRenderData { dp::GLState m_state; @@ -79,7 +106,7 @@ class TrafficHandle : public dp::OverlayHandle using TBase = dp::OverlayHandle; public: - TrafficHandle(uint64_t segmentId, glsl::vec2 const & texCoord, size_t verticesCount); + TrafficHandle(TrafficSegmentID const & segmentId, glsl::vec2 const & texCoord, size_t verticesCount); void GetAttributeMutation(ref_ptr mutator) const override; bool Update(ScreenBase const & screen) override; @@ -88,34 +115,36 @@ public: void GetPixelShape(ScreenBase const & screen, bool perspective, Rects & rects) const override; void SetTexCoord(glsl::vec2 const & texCoord); - uint64_t GetSegmentId() const; + TrafficSegmentID GetSegmentId() const; private: - uint64_t m_segmentId; + TrafficSegmentID m_segmentId; vector m_buffer; mutable bool m_needUpdate; }; +using TrafficTexCoords = unordered_map; + class TrafficGenerator final { public: TrafficGenerator() = default; - void AddSegment(uint64_t segmentId, m2::PolylineD const & polyline); + void AddSegment(TrafficSegmentID const & segmentId, m2::PolylineD const & polyline); - vector GetSegmentsToUpdate(vector const & trafficData) const; + TrafficSegmentsColoring GetSegmentsToUpdate(TrafficSegmentsColoring const & trafficColoring) const; void GetTrafficGeom(ref_ptr textures, - vector const & trafficData, + TrafficSegmentsColoring const & trafficColoring, vector & data); void ClearCache(); bool IsColorsCacheRefreshed() const { return m_colorsCacheRefreshed; } - unordered_map ProcessCacheRefreshing(); + TrafficTexCoords ProcessCacheRefreshing(); private: - using TSegmentCollection = map; + using TSegmentCollection = map; void GenerateSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, @@ -125,8 +154,9 @@ private: TSegmentCollection m_segments; - set m_segmentsCache; - unordered_map m_colorsCache; + set m_segmentsCache; + array(traffic::SpeedGroup::Count)> m_colorsCache; + bool m_colorsCacheValid = false; bool m_colorsCacheRefreshed = false; }; diff --git a/drape_frontend/traffic_renderer.cpp b/drape_frontend/traffic_renderer.cpp index b3f1872bd5..c8d1d9906b 100644 --- a/drape_frontend/traffic_renderer.cpp +++ b/drape_frontend/traffic_renderer.cpp @@ -81,11 +81,11 @@ void TrafficRenderer::AddRenderData(ref_ptr mng, } } -void TrafficRenderer::UpdateTraffic(vector const & trafficData) +void TrafficRenderer::UpdateTraffic(TrafficSegmentsColoring const & trafficColoring) { - for (TrafficSegmentData const & segment : trafficData) + for (auto const & segment : trafficColoring) { - auto it = m_texCoords.find(segment.m_speedBucket); + auto it = m_texCoords.find(static_cast(segment.m_speedGroup)); if (it == m_texCoords.end()) continue; @@ -124,7 +124,7 @@ void TrafficRenderer::RenderTraffic(ScreenBase const & screen, int zoomLevel, } } -void TrafficRenderer::SetTexCoords(unordered_map && texCoords) +void TrafficRenderer::SetTexCoords(TrafficTexCoords && texCoords) { m_texCoords = move(texCoords); } diff --git a/drape_frontend/traffic_renderer.hpp b/drape_frontend/traffic_renderer.hpp index f060928712..e385d8231a 100644 --- a/drape_frontend/traffic_renderer.hpp +++ b/drape_frontend/traffic_renderer.hpp @@ -11,7 +11,6 @@ #include "std/map.hpp" #include "std/vector.hpp" -#include "std/unordered_map.hpp" namespace df { @@ -24,9 +23,9 @@ public: void AddRenderData(ref_ptr mng, vector && renderData); - void SetTexCoords(unordered_map && texCoords); + void SetTexCoords(TrafficTexCoords && texCoords); - void UpdateTraffic(vector const & trafficData); + void UpdateTraffic(TrafficSegmentsColoring const & trafficColoring); void RenderTraffic(ScreenBase const & screen, int zoomLevel, ref_ptr mng, @@ -36,8 +35,8 @@ public: private: vector m_renderData; - unordered_map m_texCoords; - unordered_map m_handles; + TrafficTexCoords m_texCoords; + map m_handles; }; } // namespace df diff --git a/geometry/polyline2d.hpp b/geometry/polyline2d.hpp index 40b4a99da6..86dfe69972 100644 --- a/geometry/polyline2d.hpp +++ b/geometry/polyline2d.hpp @@ -115,6 +115,15 @@ public: return m_points.back(); } + Polyline ExtractSegment(size_t segmentIndex, bool reversed) + { + if (segmentIndex + 1 >= m_points.size()) + return Polyline(); + + return reversed ? Polyline(vector>{m_points[segmentIndex + 1], m_points[segmentIndex]}) : + Polyline(vector>{m_points[segmentIndex], m_points[segmentIndex + 1]}); + } + vector > const & GetPoints() const { return m_points; } friend string DebugPrint(Polyline const & p) { return ::DebugPrint(p.m_points); } }; diff --git a/map/framework.cpp b/map/framework.cpp index 4d33f96e79..77bb757c4d 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -171,6 +171,7 @@ pair Framework::RegisterMap( void Framework::OnLocationError(TLocationError /*error*/) { + m_trafficManager.UpdateMyPosition(TrafficManager::MyPosition()); CallDrapeFunction(bind(&df::DrapeEngine::LoseLocation, _1)); } @@ -251,6 +252,8 @@ void Framework::OnUserPositionChanged(m2::PointD const & position) if (IsRoutingActive()) m_routingSession.SetUserCurrentPosition(position); + + m_trafficManager.UpdateMyPosition(TrafficManager::MyPosition(position)); } void Framework::OnViewportChanged(ScreenBase const & screen) @@ -261,6 +264,8 @@ void Framework::OnViewportChanged(ScreenBase const & screen) m_currentModelView = screen; + m_trafficManager.UpdateViewport(m_currentModelView); + if (m_viewportChanged != nullptr) m_viewportChanged(screen); } @@ -336,6 +341,7 @@ Framework::Framework() , m_isRenderingEnabled(true) , m_trackingReporter(platform::CreateSocket(), TRACKING_REALTIME_HOST, TRACKING_REALTIME_PORT, tracking::Reporter::kPushDelayMs) + , m_trafficManager(m_model.GetIndex()) , m_displacementModeManager([this](bool show) { int const mode = show ? dp::displacement::kHotelMode : dp::displacement::kDefaultMode; CallDrapeFunction(bind(&df::DrapeEngine::SetDisplacementMode, _1, mode)); @@ -434,6 +440,7 @@ Framework::Framework() Framework::~Framework() { + m_trafficManager.SetDrapeEngine(nullptr); m_drapeApi.SetEngine(nullptr); m_drapeEngine.reset(); @@ -1659,6 +1666,7 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, }); m_drapeApi.SetEngine(make_ref(m_drapeEngine)); + m_trafficManager.SetDrapeEngine(make_ref(m_drapeEngine)); } void Framework::UpdateDrapeEngine(int width, int height) diff --git a/map/framework.hpp b/map/framework.hpp index 1288ad071d..bc4027944e 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -8,6 +8,7 @@ #include "map/mwm_url.hpp" #include "map/place_page_info.hpp" #include "map/track.hpp" +#include "map/traffic_manager.hpp" #include "drape_frontend/gui/skin.hpp" #include "drape_frontend/drape_api.hpp" @@ -168,6 +169,8 @@ protected: bool m_isRenderingEnabled; tracking::Reporter m_trackingReporter; + TrafficManager m_trafficManager; + /// This function will be called by m_storage when latest local files /// is downloaded. void OnCountryFileDownloaded(storage::TCountryId const & countryId, storage::Storage::TLocalFilePtr const localFile); diff --git a/map/map.pro b/map/map.pro index 264f744590..abb6f171db 100644 --- a/map/map.pro +++ b/map/map.pro @@ -28,6 +28,7 @@ HEADERS += \ mwm_url.hpp \ place_page_info.hpp \ track.hpp \ + traffic_manager.hpp \ user_mark.hpp \ user_mark_container.hpp \ @@ -51,6 +52,7 @@ SOURCES += \ mwm_url.cpp \ place_page_info.cpp \ track.cpp \ + traffic_manager.cpp \ user_mark.cpp \ user_mark_container.cpp \ diff --git a/map/traffic_manager.cpp b/map/traffic_manager.cpp new file mode 100644 index 0000000000..6f6c91af2d --- /dev/null +++ b/map/traffic_manager.cpp @@ -0,0 +1,95 @@ +#include "map/traffic_manager.hpp" + +#include "routing/routing_helpers.hpp" + +#include "drape_frontend/drape_engine.hpp" + +#include "indexer/scales.hpp" + +void TrafficManager::SetDrapeEngine(ref_ptr engine) +{ + m_drapeEngine = engine; +} + +void TrafficManager::UpdateViewport(ScreenBase const & screen) +{ + // 1. Determine mwm's inside viewport. + + // 2. Request traffic for this mwm's. + + // 3. Cache geometry for rendering if it's necessary. + //MwmSet::MwmId mwmId; + //if (m_mwmIds.find(mwmId) == m_mwmIds.end()) + //{ + // df::TrafficSegmentsGeometry geometry; + // traffic::TrafficInfo info; + // CalculateSegmentsGeometry(info, geometry); + // m_mwmIds.insert(mwmId); + // m_drapeEngine->CacheTrafficSegmentsGeometry(geometry); + //} + + // 4. Update traffic colors. + //df::TrafficSegmentsColoring coloring; + //traffic::TrafficInfo info; + //CalculateSegmentsColoring(info, coloring); + //m_drapeEngine->UpdateTraffic(coloring); + + // 5. Remove some mwm's from cache. + //MwmSet::MwmId mwmId; + //m_drapeEngine->ClearTrafficCache(mwmId); +} + +void TrafficManager::UpdateMyPosition(MyPosition const & myPosition) +{ + // 1. Determine mwm's nearby "my position". + + // 2. Request traffic for this mwm's. + + // 3. Do all routing stuff. +} + +void TrafficManager::CalculateSegmentsGeometry(traffic::TrafficInfo const & trafficInfo, + df::TrafficSegmentsGeometry & output) const +{ + size_t const coloringSize = trafficInfo.GetColoring().size(); + output.reserve(coloringSize); + + vector features; + features.reserve(coloringSize); + for (auto const & c : trafficInfo.GetColoring()) + features.emplace_back(trafficInfo.GetMwmId(), c.first.m_fid); + + int constexpr kScale = scales::GetUpperScale(); + unordered_map polylines; + auto featureReader = [&polylines](FeatureType & ft) + { + uint32_t const fid = ft.GetID().m_index; + if (polylines.find(fid) != polylines.end()) + return; + + if (routing::IsRoad(feature::TypesHolder(ft))) + { + m2::PolylineD polyline; + ft.ForEachPoint([&polyline](m2::PointD const & pt) { polyline.Add(pt); }, kScale); + polylines[fid] = polyline; + } + }; + m_index.ReadFeatures(featureReader, features); + + for (auto const & c : trafficInfo.GetColoring()) + { + output.push_back(make_pair(df::TrafficSegmentID(trafficInfo.GetMwmId(), c.first), + polylines[c.first.m_fid].ExtractSegment(c.first.m_idx, + c.first.m_dir == 1))); + } +} + +void TrafficManager::CalculateSegmentsColoring(traffic::TrafficInfo const & trafficInfo, + df::TrafficSegmentsColoring & output) const +{ + for (auto const & c : trafficInfo.GetColoring()) + { + df::TrafficSegmentID const sid (trafficInfo.GetMwmId(), c.first); + output.emplace_back(sid, c.second); + } +} diff --git a/map/traffic_manager.hpp b/map/traffic_manager.hpp new file mode 100644 index 0000000000..93982ba898 --- /dev/null +++ b/map/traffic_manager.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "traffic/traffic_info.hpp" + +#include "drape_frontend/traffic_generator.hpp" + +#include "drape/pointers.hpp" + +#include "geometry/point2d.hpp" +#include "geometry/polyline2d.hpp" +#include "geometry/screenbase.hpp" + +#include "indexer/index.hpp" + +#include "std/set.hpp" + +namespace df +{ +class DrapeEngine; +} // namespace df + +class TrafficManager +{ +public: + struct MyPosition + { + m2::PointD m_position = m2::PointD(0.0, 0.0); + bool m_knownPosition = false; + + MyPosition() = default; + MyPosition(m2::PointD const & position) + : m_position(position), + m_knownPosition(true) + {} + }; + + TrafficManager(Index const & index) + : m_index(index) + {} + + void UpdateViewport(ScreenBase const & screen); + void UpdateMyPosition(MyPosition const & myPosition); + + void SetDrapeEngine(ref_ptr engine); + +private: + void CalculateSegmentsGeometry(traffic::TrafficInfo const & trafficInfo, + df::TrafficSegmentsGeometry & output) const; + void CalculateSegmentsColoring(traffic::TrafficInfo const & trafficInfo, + df::TrafficSegmentsColoring & output) const; + + Index const & m_index; + ref_ptr m_drapeEngine; + m2::PointD m_myPosition; + set m_mwmIds; +}; diff --git a/traffic/traffic_info.hpp b/traffic/traffic_info.hpp index 90bcdab50f..23309cd8ca 100644 --- a/traffic/traffic_info.hpp +++ b/traffic/traffic_info.hpp @@ -21,6 +21,11 @@ public: RoadSegmentId(uint32_t fid, uint16_t idx, uint8_t dir); + bool operator==(RoadSegmentId const & o) const + { + return m_fid == o.m_fid && m_idx == o.m_idx && m_dir == o.m_dir; + } + bool operator<(RoadSegmentId const & o) const { if (m_fid != o.m_fid) @@ -58,6 +63,9 @@ public: // Returns the latest known speed group by a feature segment's id. SpeedGroup GetSpeedGroup(RoadSegmentId const & id) const; + MwmSet::MwmId const & GetMwmId() const { return m_mwmId; } + Coloring const & GetColoring() const { return m_coloring; } + static void SerializeTrafficData(Coloring const & coloring, vector & result); static void DeserializeTrafficData(vector const & data, Coloring & coloring);