summaryrefslogtreecommitdiff
path: root/src/mbgl/text
diff options
context:
space:
mode:
authorChris Loer <chris.loer@gmail.com>2018-07-06 13:09:15 -0700
committerChris Loer <chris.loer@mapbox.com>2018-07-23 13:33:27 -0700
commitf9b36f9f5b4cf09e08c2ff0181b339b53e8d0014 (patch)
treec1dbbdd657d7f5edee1defb239773576e43d27d0 /src/mbgl/text
parent870d7fda4d5b65d9a4993f35322678bc6f50767c (diff)
downloadqtlocation-mapboxgl-f9b36f9f5b4cf09e08c2ff0181b339b53e8d0014.tar.gz
[core] Add `symbol-placement: line-center`
- Remove unused/vestigial 'maxCameraDistance' - Create a single collision circle for line labels that are less than half the width of a collision circle
Diffstat (limited to 'src/mbgl/text')
-rw-r--r--src/mbgl/text/collision_feature.cpp5
-rw-r--r--src/mbgl/text/get_anchors.cpp77
-rw-r--r--src/mbgl/text/get_anchors.hpp10
-rw-r--r--src/mbgl/text/quads.cpp2
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 } :