From bc3665d1c690cee82ef921a7cfb56fce9c94d995 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Tue, 20 Dec 2016 14:58:57 +0300 Subject: [PATCH] Tuned two-way roads offset in traffic rendering --- drape_frontend/rule_drawer.cpp | 24 ++++++++++++++---------- drape_frontend/rule_drawer.hpp | 1 + drape_frontend/traffic_renderer.cpp | 28 ++++++++++++++++++++++++++-- drape_frontend/traffic_renderer.hpp | 3 ++- drape_frontend/visual_params.cpp | 15 ++++++++++----- drape_frontend/visual_params.hpp | 6 ++++++ 6 files changed, 59 insertions(+), 18 deletions(-) diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index eb794cdcd5..92989c3bf2 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -58,13 +58,10 @@ void ExtractTrafficGeometry(FeatureType const & f, df::RoadClass const & roadCla auto const & regionData = f.GetID().m_mwmId.GetInfo()->GetRegionData(); bool const isLeftHandTraffic = regionData.Get(feature::RegionData::RD_DRIVING) == "l"; - // Calculate road offset for two-way roads. The offset is available since a zoom level in - // kMinOffsetZoomLevels. + // Calculate offset between road lines in mercator for two-way roads. double twoWayOffset = 0.0; - static vector const kMinOffsetZoomLevels = { 13, 11, 10 }; - bool const needTwoWayOffset = !oneWay && zoomLevel > kMinOffsetZoomLevels[static_cast(roadClass)]; - if (needTwoWayOffset) - twoWayOffset = pixelToGlobalScale * 0.5 * df::TrafficRenderer::GetPixelWidth(roadClass, zoomLevel); + if (!oneWay) + twoWayOffset = pixelToGlobalScale * df::TrafficRenderer::GetTwoWayOffset(roadClass, zoomLevel); static vector directions = {traffic::TrafficInfo::RoadSegmentId::kForwardDirection, traffic::TrafficInfo::RoadSegmentId::kReverseDirection}; @@ -93,7 +90,7 @@ void ExtractTrafficGeometry(FeatureType const & f, df::RoadClass const & roadCla if (segment[0].EqualDxDy(segment[1], kEps)) break; - if (needTwoWayOffset) + if (!oneWay) { m2::PointD const tangent = (segment[1] - segment[0]).Normalize(); m2::PointD const normal = isLeftHandTraffic ? m2::PointD(-tangent.y, tangent.x) : @@ -134,13 +131,21 @@ RuleDrawer::RuleDrawer(TDrawerCallback const & fn, m_globalRect = m_context->GetTileKey().GetGlobalRect(); - int32_t tileSize = df::VisualParams::Instance().GetTileSize(); + auto & vparams = df::VisualParams::Instance(); + int32_t tileSize = vparams.GetTileSize(); m2::RectD const r = m_context->GetTileKey().GetGlobalRect(false /* clipByDataMaxZoom */); ScreenBase geometryConvertor; geometryConvertor.OnSize(0, 0, tileSize, tileSize); geometryConvertor.SetFromRect(m2::AnyRectD(r)); m_currentScaleGtoP = 1.0f / geometryConvertor.GetScale(); + // Here we support only two virtual tile size: 2048 px for high resolution and 1024 px for others. + // It helps to render traffic the same on wide range of devices. + uint32_t const kTrafficTileSize = vparams.GetVisualScale() < df::VisualParams::kXxhdpiScale ? 1024 : 2048; + geometryConvertor.OnSize(0, 0, kTrafficTileSize, kTrafficTileSize); + geometryConvertor.SetFromRect(m2::AnyRectD(r)); + m_trafficScalePtoG = geometryConvertor.GetScale(); + int const kAverageOverlaysCount = 200; m_mapShapes[df::OverlayType].reserve(kAverageOverlaysCount); } @@ -342,7 +347,6 @@ void RuleDrawer::operator()(FeatureType const & f) bool const oneWay = ftypes::IsOneWayChecker::Instance()(f); auto const highwayClass = ftypes::GetHighwayClass(f); - double const pixelToGlobalScale = 1.0 / m_currentScaleGtoP; for (size_t i = 0; i < ARRAY_SIZE(checkers); ++i) { auto const & classes = checkers[i].m_highwayClasses; @@ -355,7 +359,7 @@ void RuleDrawer::operator()(FeatureType const & f) f.ForEachPoint([&points](m2::PointD const & p) { points.emplace_back(p); }, FeatureType::BEST_GEOMETRY); ExtractTrafficGeometry(f, checkers[i].m_roadClass, m2::PolylineD(points), oneWay, - zoomLevel, pixelToGlobalScale, m_trafficGeometry); + zoomLevel, m_trafficScalePtoG, m_trafficGeometry); break; } } diff --git a/drape_frontend/rule_drawer.hpp b/drape_frontend/rule_drawer.hpp index 4b1c9c293d..c5bcf356b8 100644 --- a/drape_frontend/rule_drawer.hpp +++ b/drape_frontend/rule_drawer.hpp @@ -46,6 +46,7 @@ private: ref_ptr m_context; m2::RectD m_globalRect; double m_currentScaleGtoP; + double m_trafficScalePtoG; bool const m_is3dBuidings; diff --git a/drape_frontend/traffic_renderer.cpp b/drape_frontend/traffic_renderer.cpp index 6e781f72d6..634a2f899a 100644 --- a/drape_frontend/traffic_renderer.cpp +++ b/drape_frontend/traffic_renderer.cpp @@ -31,7 +31,7 @@ float const kLeftWidthInPixel[] = // 1 2 3 4 5 6 7 8 9 10 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, //11 12 13 14 15 16 17 18 19 20 - 0.5f, 0.5f, 0.5f, 0.5f, 2.0f, 2.5f, 3.0f, 4.0f, 4.0f, 4.0f + 0.5f, 0.5f, 0.5f, 0.5f, 0.7f, 2.5f, 3.0f, 4.0f, 4.0f, 4.0f }; float const kRightWidthInPixel[] = @@ -39,7 +39,7 @@ float const kRightWidthInPixel[] = // 1 2 3 4 5 6 7 8 9 10 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 3.0f, 3.0f, //11 12 13 14 15 16 17 18 19 20 - 3.0f, 3.0f, 4.0f, 4.0f, 2.0f, 2.5f, 3.0f, 4.0f, 4.0f, 4.0f + 3.0f, 3.0f, 4.0f, 4.0f, 3.8f, 2.5f, 3.0f, 4.0f, 4.0f, 4.0f }; float const kRoadClass1WidthScalar[] = @@ -58,6 +58,14 @@ float const kRoadClass2WidthScalar[] = 0.3f, 0.3f, 0.3f, 0.3f, 0.5f, 0.5f, 0.5f, 0.8f, 0.9f, 1.0f }; +float const kTwoWayOffsetInPixel[] = +{ + // 1 2 3 4 5 6 7 8 9 10 + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + //11 12 13 14 15 16 17 18 19 20 + 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 2.5f, 2.5f, 2.5f, 2.5f, 2.5f +}; + vector const kLineDrawerRoadClass1 = {12, 13, 14}; vector const kLineDrawerRoadClass2 = {15, 16}; @@ -237,6 +245,22 @@ void TrafficRenderer::Clear(MwmSet::MwmId const & mwmId) m_renderData.erase(remove_if(m_renderData.begin(), m_renderData.end(), removePredicate), m_renderData.end()); } +// static +float TrafficRenderer::GetTwoWayOffset(RoadClass const & roadClass, int zoomLevel) +{ + // There is no offset for class-0 roads, the offset for them is created by + // kLeftWidthInPixel and kRightWidthInPixel. + int const kRoadClass0MinZoomLevel = 14; + if (roadClass == RoadClass::Class0 && zoomLevel <= kRoadClass0MinZoomLevel) + return 0.0f; + + ASSERT_GREATER(zoomLevel, 1, ()); + ASSERT_LESS_OR_EQUAL(zoomLevel, scales::GetUpperStyleScale(), ()); + int const index = zoomLevel - 1; + float const halfWidth = 0.5f * df::TrafficRenderer::GetPixelWidth(roadClass, zoomLevel); + return halfWidth + kTwoWayOffsetInPixel[index] * VisualParams::Instance().GetVisualScale(); +} + // static float TrafficRenderer::GetPixelWidth(RoadClass const & roadClass, int zoomLevel) { diff --git a/drape_frontend/traffic_renderer.hpp b/drape_frontend/traffic_renderer.hpp index b6cf3c78ad..222a271538 100644 --- a/drape_frontend/traffic_renderer.hpp +++ b/drape_frontend/traffic_renderer.hpp @@ -36,10 +36,11 @@ public: buffer_vector const & tilesToDelete); void OnGeometryReady(int currentZoomLevel); - static float GetPixelWidth(RoadClass const & roadClass, int zoomLevel); + static float GetTwoWayOffset(RoadClass const & roadClass, int zoomLevel); static bool CanBeRendereredAsLine(RoadClass const & roadClass, int zoomLevel, int & width); private: + static float GetPixelWidth(RoadClass const & roadClass, int zoomLevel); static float GetPixelWidthInternal(RoadClass const & roadClass, int zoomLevel); vector m_renderData; diff --git a/drape_frontend/visual_params.cpp b/drape_frontend/visual_params.cpp index df0509ee61..d4b449ee9d 100644 --- a/drape_frontend/visual_params.cpp +++ b/drape_frontend/visual_params.cpp @@ -32,6 +32,11 @@ static bool g_isInited = false; #define ASSERT_INITED #endif +double const VisualParams::kMdpiScale = 1.0; +double const VisualParams::kHdpiScale = 1.5; +double const VisualParams::kXhdpiScale = 2.0; +double const VisualParams::k6plusScale = 2.4; +double const VisualParams::kXxhdpiScale = 3.0; void VisualParams::Init(double vs, uint32_t tileSize) { @@ -77,11 +82,11 @@ string const & VisualParams::GetResourcePostfix(double visualScale) { static visual_scale_t postfixes[] = { - make_pair("mdpi", 1.0), - make_pair("hdpi", 1.5), - make_pair("xhdpi", 2.0), - make_pair("xxhdpi", 3.0), - make_pair("6plus", 2.4), + make_pair("mdpi", kMdpiScale), + make_pair("hdpi", kHdpiScale), + make_pair("xhdpi", kXhdpiScale), + make_pair("xxhdpi", kXxhdpiScale), + make_pair("6plus", k6plusScale), }; // Looking for the nearest available scale. diff --git a/drape_frontend/visual_params.hpp b/drape_frontend/visual_params.hpp index 5d07162d3f..493fd452c8 100644 --- a/drape_frontend/visual_params.hpp +++ b/drape_frontend/visual_params.hpp @@ -13,6 +13,12 @@ namespace df class VisualParams : private noncopyable { public: + static double const kMdpiScale; + static double const kHdpiScale; + static double const kXhdpiScale; + static double const k6plusScale; + static double const kXxhdpiScale; + static void Init(double vs, uint32_t tileSize); static VisualParams & Instance();