From f14b8d06174ea6bc54409e39f465944bd2d57f97 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Wed, 28 Jun 2017 17:55:33 +0300 Subject: [PATCH] Fixed shields rendering on roads without name --- drape_frontend/apply_feature_functors.cpp | 100 +++++++++++++++------- drape_frontend/apply_feature_functors.hpp | 1 + indexer/road_shields_parser.hpp | 10 +-- 3 files changed, 73 insertions(+), 38 deletions(-) diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index 811af3e533..21ea452406 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -364,6 +364,25 @@ m2::PointF GetShieldOffset(dp::Anchor anchor, double borderWidth, double borderH offset.y = -static_cast(borderHeight); return offset; } + +void CalculateRoadShieldPositions(std::vector const & offsets, + m2::SharedSpline const & spline, + std::vector & shieldPositions) +{ + ASSERT(!offsets.empty(), ()); + if (offsets.size() == 1) + { + shieldPositions.push_back(spline->GetPoint(0.5 * spline->GetLength()).m_pos); + } + else + { + for (size_t i = 0; i + 1 < offsets.size(); i++) + { + double const p = 0.5 * (offsets[i] + offsets[i + 1]); + shieldPositions.push_back(spline->GetPoint(p).m_pos); + } + } +} } // namespace BaseApplyFeature::BaseApplyFeature(TileKey const & tileKey, TInsertShapeFn const & insertShape, @@ -954,6 +973,8 @@ void ApplyLineFeatureAdditional::GetRoadShieldsViewParams(ref_ptrGetSymbolRegion(poiParams.m_symbolName, region); float const symBorderWidth = (region.GetPixelSize().x - textLayout.GetPixelLength()) * 0.5f; float const symBorderHeight = (region.GetPixelSize().y - textLayout.GetPixelHeight()) * 0.5f; - textParams.m_primaryOffset = shieldOffset + GetShieldOffset(anchor, symBorderWidth, symBorderHeight); - shieldPixelSize = m2::PointD(symBorderWidth, symBorderHeight); + textParams.m_primaryOffset = poiParams.m_offset + GetShieldOffset(anchor, symBorderWidth, symBorderHeight); + shieldPixelSize = region.GetPixelSize(); - if (!symbolName.empty() && !shield.m_additionalText.empty() && - (anchor & dp::Top || anchor & dp::Center)) - { - textParams.m_secondaryText = shield.m_additionalText; - textParams.m_secondaryTextFont = textParams.m_primaryTextFont; - textParams.m_secondaryTextFont.m_color = df::GetColorConstant(kRoadShieldBlackTextColor); - textParams.m_secondaryTextFont.m_outlineColor = df::GetColorConstant(kRoadShieldWhiteTextColor); - textParams.m_secondaryTextFont.m_size *= 0.9f; - textParams.m_secondaryOffset = m2::PointD(0.0f, 3.0 * mainScale); - } + needAdditionalText = !symbolName.empty() && !shield.m_additionalText.empty() && + (anchor & dp::Top || anchor & dp::Center); + } + + if (needAdditionalText) + { + textParams.m_secondaryText = shield.m_additionalText; + textParams.m_secondaryTextFont = textParams.m_primaryTextFont; + textParams.m_secondaryTextFont.m_color = df::GetColorConstant(kRoadShieldBlackTextColor); + textParams.m_secondaryTextFont.m_outlineColor = df::GetColorConstant(kRoadShieldWhiteTextColor); + textParams.m_secondaryTextFont.m_size *= 0.9f; + textParams.m_secondaryOffset = m2::PointD(0.0f, 3.0 * mainScale); } } bool ApplyLineFeatureAdditional::CheckShieldsNearby(m2::PointD const & shieldPos, m2::PointD const & shieldPixelSize, + uint32_t minDistanceInPixels, std::vector & shields) { // Here we calculate extended rect to skip the same shields nearby. - static double const kExtension = 5.0; - m2::PointD const shieldMercatorHalfSize = shieldPixelSize / m_currentScaleGtoP * 0.5; + m2::PointD const skippingArea(2 * minDistanceInPixels, 2 * minDistanceInPixels); + m2::PointD const extendedPixelSize = shieldPixelSize + skippingArea; + m2::PointD const shieldMercatorHalfSize = extendedPixelSize / m_currentScaleGtoP * 0.5; m2::RectD shieldRect(shieldPos - shieldMercatorHalfSize, shieldPos + shieldMercatorHalfSize); - shieldRect.Scale(kExtension); for (auto const & r : shields) { if (r.IsIntersect(shieldRect)) @@ -1039,6 +1066,8 @@ void ApplyLineFeatureAdditional::Finish(ref_ptr texMng, if (m_clippedSplines.empty()) return; + float const vs = static_cast(df::VisualParams::Instance().GetVisualScale()); + std::vector shieldPositions; if (m_shieldRule != nullptr && !roadShields.empty()) shieldPositions.reserve(m_clippedSplines.size() * 3); @@ -1067,31 +1096,36 @@ void ApplyLineFeatureAdditional::Finish(ref_ptr texMng, continue; if (m_shieldRule != nullptr && !roadShields.empty()) - { - auto const & offsets = shape->GetOffsets(); - ASSERT(!offsets.empty(), ()); - if (offsets.size() == 1) - { - shieldPositions.push_back(spline->GetPoint(0.5 * spline->GetLength()).m_pos); - } - else - { - for (size_t i = 0; i + 1 < offsets.size(); i++) - { - double const p = 0.5 * (offsets[i] + offsets[i + 1]); - shieldPositions.push_back(spline->GetPoint(p).m_pos); - } - } - } + CalculateRoadShieldPositions(shape->GetOffsets(), spline, shieldPositions); m_insertShape(std::move(shape)); baseTextIndex += kPathTextBaseTextStep; } } + else if (m_shieldRule != nullptr && !roadShields.empty()) + { + for (auto const & spline : m_clippedSplines) + { + float const pixelLength = 300.0f * vs; + std::vector offsets; + PathTextLayout::CalculatePositions(static_cast(spline->GetLength()), + m_currentScaleGtoP, pixelLength, offsets); + if (!offsets.empty()) + CalculateRoadShieldPositions(offsets, spline, shieldPositions); + } + } if (shieldPositions.empty()) return; + ASSERT(m_shieldRule != nullptr, ()); + int constexpr kDefaultMinDistance = 50; + int minDistance = m_shieldRule->has_min_distance() ? m_shieldRule->min_distance() + : kDefaultMinDistance; + if (minDistance < 0) + minDistance = kDefaultMinDistance; + uint32_t const scaledMinDistance = static_cast(vs * minDistance); + uint8_t shieldIndex = 0; for (ftypes::RoadShield const & shield : roadShields) { @@ -1107,7 +1141,7 @@ void ApplyLineFeatureAdditional::Finish(ref_ptr texMng, uint32_t textIndex = kShieldBaseTextIndex * (++shieldIndex); for (auto const & shieldPos : shieldPositions) { - if (!CheckShieldsNearby(shieldPos, shieldPixelSize, generatedShieldRects)) + if (!CheckShieldsNearby(shieldPos, shieldPixelSize, scaledMinDistance, generatedShieldRects)) continue; m_insertShape(make_unique_dp(shieldPos, textParams, m_tileKey, true /* hasPOI */, diff --git a/drape_frontend/apply_feature_functors.hpp b/drape_frontend/apply_feature_functors.hpp index de80970114..9f4a01da76 100644 --- a/drape_frontend/apply_feature_functors.hpp +++ b/drape_frontend/apply_feature_functors.hpp @@ -196,6 +196,7 @@ private: m2::PointD & shieldPixelSize); bool CheckShieldsNearby(m2::PointD const & shieldPos, m2::PointD const & shieldPixelSize, + uint32_t minDistanceInPixels, std::vector & shields); std::vector m_clippedSplines; diff --git a/indexer/road_shields_parser.hpp b/indexer/road_shields_parser.hpp index 1fd01aa001..d68691b2f9 100644 --- a/indexer/road_shields_parser.hpp +++ b/indexer/road_shields_parser.hpp @@ -42,13 +42,13 @@ struct RoadShield inline bool operator<(RoadShield const & other) const { - if (m_type == other.m_type) + if (m_additionalText == other.m_additionalText) { - if (m_name == other.m_name) - return m_additionalText < other.m_additionalText; - return m_name < other.m_name; + if (m_type == other.m_type) + return m_name < other.m_name; + return m_type < other.m_type; } - return m_type < other.m_type; + return m_additionalText < other.m_additionalText; } };