diff options
Diffstat (limited to 'src/mbgl/text')
-rw-r--r-- | src/mbgl/text/collision_feature.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/text/get_anchors.cpp | 77 | ||||
-rw-r--r-- | src/mbgl/text/get_anchors.hpp | 10 | ||||
-rw-r--r-- | src/mbgl/text/quads.cpp | 2 |
4 files changed, 79 insertions, 15 deletions
diff --git a/src/mbgl/text/collision_feature.cpp b/src/mbgl/text/collision_feature.cpp index 9c934624d4..ac4dbff2af 100644 --- a/src/mbgl/text/collision_feature.cpp +++ b/src/mbgl/text/collision_feature.cpp @@ -16,7 +16,7 @@ CollisionFeature::CollisionFeature(const GeometryCoordinates& line, IndexedSubfeature indexedFeature_, const float overscaling) : indexedFeature(std::move(indexedFeature_)) - , alongLine(placement == style::SymbolPlacementType::Line) { + , alongLine(placement != style::SymbolPlacementType::Point) { if (top == 0 && bottom == 0 && left == 0 && right == 0) return; const float y1 = top * boxScale - padding; @@ -42,7 +42,8 @@ CollisionFeature::CollisionFeature(const GeometryCoordinates& line, void CollisionFeature::bboxifyLabel(const GeometryCoordinates& line, GeometryCoordinate& anchorPoint, const int segment, const float labelLength, const float boxSize, const float overscaling) { const float step = boxSize / 2; - const int nBoxes = std::floor(labelLength / step); + const int nBoxes = std::max(static_cast<int>(std::floor(labelLength / step)), 1); + // We calculate line collision circles out to 300% of what would normally be our // max size, to allow collision detection to work on labels that expand as // they move into the distance diff --git a/src/mbgl/text/get_anchors.cpp b/src/mbgl/text/get_anchors.cpp index d41faf2a71..160ee21edf 100644 --- a/src/mbgl/text/get_anchors.cpp +++ b/src/mbgl/text/get_anchors.cpp @@ -7,6 +7,20 @@ #include <cmath> namespace mbgl { + +float getAngleWindowSize(const float textLeft, const float textRight, const float glyphSize, const float boxScale) { + return (textLeft - textRight) != 0.0f ? + 3.0f / 5.0f * glyphSize * boxScale : + 0; +} + +float getLineLength(const GeometryCoordinates& line) { + float lineLength = 0; + for (auto it = line.begin(), end = line.end() - 1; it != end; it++) { + lineLength += util::dist<float>(*(it), *(it + 1)); + } + return lineLength; +} static Anchors resample(const GeometryCoordinates& line, const float offset, @@ -17,10 +31,7 @@ static Anchors resample(const GeometryCoordinates& line, const bool continuedLine, const bool placeAtMiddle) { const float halfLabelLength = labelLength / 2.0f; - float lineLength = 0; - for (auto it = line.begin(), end = line.end() - 1; it != end; it++) { - lineLength += util::dist<float>(*(it), *(it + 1)); - } + const float lineLength = getLineLength(line); float distance = 0; float markedDistance = offset - spacing; @@ -91,19 +102,18 @@ Anchors getAnchors(const GeometryCoordinates& line, // potential label passes text-max-angle check and has enough froom to fit // on the line. - const float angleWindowSize = (textLeft - textRight) != 0.0f ? - 3.0f / 5.0f * glyphSize * boxScale : - 0; + const float angleWindowSize = getAngleWindowSize(textLeft, textRight, glyphSize, boxScale); - const float labelLength = fmax(textRight - textLeft, iconRight - iconLeft); + const float shapedLabelLength = fmax(textRight - textLeft, iconRight - iconLeft); + const float labelLength = shapedLabelLength * boxScale; // Is the line continued from outside the tile boundary? const bool continuedLine = (line[0].x == 0 || line[0].x == util::EXTENT || line[0].y == 0 || line[0].y == util::EXTENT); // Is the label long, relative to the spacing? // If so, adjust the spacing so there is always a minimum space of `spacing / 4` between label edges. - if (spacing - labelLength * boxScale < spacing / 4) { - spacing = labelLength * boxScale + spacing / 4; + if (spacing - labelLength < spacing / 4) { + spacing = labelLength + spacing / 4; } // Offset the first anchor by: @@ -114,10 +124,53 @@ Anchors getAnchors(const GeometryCoordinates& line, const float fixedExtraOffset = glyphSize * 2; const float offset = !continuedLine ? - std::fmod((labelLength / 2 + fixedExtraOffset) * boxScale * overscaling, spacing) : + std::fmod((shapedLabelLength / 2 + fixedExtraOffset) * boxScale * overscaling, spacing) : std::fmod(spacing / 2 * overscaling, spacing); - return resample(line, offset, spacing, angleWindowSize, maxAngle, labelLength * boxScale, continuedLine, false); + return resample(line, offset, spacing, angleWindowSize, maxAngle, labelLength, continuedLine, false); +} + +optional<Anchor> getCenterAnchor(const GeometryCoordinates& line, + const float maxAngle, + const float textLeft, + const float textRight, + const float iconLeft, + const float iconRight, + const float glyphSize, + const float boxScale) { + if (line.empty()) { + return {}; + } + + const float angleWindowSize = getAngleWindowSize(textLeft, textRight, glyphSize, boxScale); + const float labelLength = fmax(textRight - textLeft, iconRight - iconLeft) * boxScale; + + float prevDistance = 0; + const float centerDistance = getLineLength(line) / 2; + + int i = 0; + for (auto it = line.begin(), end = line.end() - 1; it != end; it++, i++) { + const GeometryCoordinate& a = *(it); + const GeometryCoordinate& b = *(it + 1); + + const auto segmentDistance = util::dist<float>(a, b); + + if (prevDistance + segmentDistance > centerDistance) { + // The center is on this segment + float t = (centerDistance - prevDistance) / segmentDistance, + x = util::interpolate(float(a.x), float(b.x), t), + y = util::interpolate(float(a.y), float(b.y), t); + + Anchor anchor(::round(x), ::round(y), util::angle_to(b, a), 0.5f, i); + + if (!angleWindowSize || checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) { + return anchor; + } + } + + prevDistance += segmentDistance; + } + return {}; } } // namespace mbgl diff --git a/src/mbgl/text/get_anchors.hpp b/src/mbgl/text/get_anchors.hpp index 48f3013093..8fd22051a4 100644 --- a/src/mbgl/text/get_anchors.hpp +++ b/src/mbgl/text/get_anchors.hpp @@ -17,4 +17,14 @@ Anchors getAnchors(const GeometryCoordinates& line, const float boxScale, const float overscaling); +optional<Anchor> getCenterAnchor(const GeometryCoordinates& line, + const float maxAngle, + const float textLeft, + const float textRight, + const float iconLeft, + const float iconRight, + const float glyphSize, + const float boxScale); + + } // namespace mbgl diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp index 0014ae8d01..ec4461ac6d 100644 --- a/src/mbgl/text/quads.cpp +++ b/src/mbgl/text/quads.cpp @@ -117,7 +117,7 @@ SymbolQuads getGlyphQuads(const Shaping& shapedText, const float rectBuffer = 3.0f + glyphPadding; const float halfAdvance = glyph.metrics.advance / 2.0; - const bool alongLine = layout.get<TextRotationAlignment>() == AlignmentType::Map && placement == SymbolPlacementType::Line; + const bool alongLine = layout.get<TextRotationAlignment>() == AlignmentType::Map && placement != SymbolPlacementType::Point; const Point<float> glyphOffset = alongLine ? Point<float>{ positionedGlyph.x + halfAdvance, positionedGlyph.y } : |