port getAnchors from -js

This commit is contained in:
Ansis Brammanis
2015-04-01 20:31:25 -07:00
parent 1d50485e5b
commit c49e1ac733
7 changed files with 99 additions and 82 deletions

View File

@@ -1,63 +0,0 @@
#include <mbgl/geometry/resample.hpp>
#include <mbgl/util/interpolate.hpp>
#include <cmath>
namespace mbgl {
const float minScale = 0.5f;
const std::array<std::vector<float>, 4> minScaleArrays = {{
/*1:*/ { minScale },
/*2:*/ { minScale, 2 },
/*4:*/ { minScale, 4, 2, 4 },
/*8:*/ { minScale, 8, 4, 8, 2, 8, 4, 8 }
}};
Anchors resample(const std::vector<Coordinate> &vertices, float spacing,
const float /*minScale*/, float maxScale, const float tilePixelRatio,
float offset) {
maxScale = std::round(std::fmax(std::fmin(8.0f, maxScale / 2.0f), 1.0f));
spacing *= tilePixelRatio / maxScale;
offset *= tilePixelRatio;
const size_t index = util::clamp<size_t>(std::floor(std::log(maxScale) / std::log(2)), 0, minScaleArrays.size() - 1);
const std::vector<float> &minScales = minScaleArrays[index];
const size_t len = minScales.size();
float distance = 0.0f;
float markedDistance = offset != 0.0f ? offset - spacing : offset;
int added = 0;
Anchors points;
auto end = vertices.end() - 1;
int i = 0;
for (auto it = vertices.begin(); it != end; it++, i++) {
const Coordinate &a = *(it), b = *(it + 1);
float segmentDist = util::dist<float>(a, b);
float angle = util::angle_to(b, a);
while (markedDistance + spacing < distance + segmentDist) {
markedDistance += spacing;
float t = (markedDistance - distance) / segmentDist,
x = util::interpolate(a.x, b.x, t),
y = util::interpolate(a.y, b.y, t),
s = minScales[added % len];
if (x >= 0 && x < 4096 && y >= 0 && y < 4096) {
points.emplace_back(x, y, angle, s, i);
}
added++;
}
distance += segmentDist;
}
return points;
}
}

View File

@@ -1,13 +0,0 @@
#ifndef MBGL_GEOMETRY_INTERPOLATE
#define MBGL_GEOMETRY_INTERPOLATE
#include <mbgl/geometry/anchor.hpp>
#include <mbgl/util/math.hpp>
namespace mbgl {
Anchors resample(const std::vector<Coordinate> &vertices, float spacing,
float minScale, float maxScale, float tilePixelRatio, float offset);
}
#endif

View File

@@ -6,7 +6,7 @@
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/geometry/anchor.hpp>
#include <mbgl/geometry/resample.hpp>
#include <mbgl/text/get_anchors.hpp>
#include <mbgl/renderer/painter.hpp>
#include <mbgl/text/glyph_store.hpp>
#include <mbgl/text/quads.hpp>
@@ -257,11 +257,11 @@ void SymbolBucket::addFeature(const std::vector<std::vector<Coordinate>> &lines,
const float fontScale = layout.text.max_size / glyphSize;
const float textBoxScale = collision.tilePixelRatio * fontScale;
const float iconBoxScale = collision.tilePixelRatio * layout.icon.max_size;
//const float symbolSpacing = collision.tilePixelRatio * layout.min_distance;
const float symbolSpacing = collision.tilePixelRatio * layout.min_distance;
const bool avoidEdges = layout.avoid_edges && layout.placement != PlacementType::Line;
const float textPadding = layout.text.padding * collision.tilePixelRatio;
const float iconPadding = layout.icon.padding * collision.tilePixelRatio;
//const float textMaxAngle = layout.text.max_angle * M_PI / 180;
const float textMaxAngle = layout.text.max_angle * M_PI / 180;
const bool textAlongLine =
layout.text.rotation_alignment == RotationAlignmentType::Map &&
layout.placement == PlacementType::Line;
@@ -276,7 +276,7 @@ void SymbolBucket::addFeature(const std::vector<std::vector<Coordinate>> &lines,
// Calculate the anchor points around which you want to place labels
Anchors anchors = layout.placement == PlacementType::Line ?
resample(line, layout.min_distance, minScale, 2.0f, collision.tilePixelRatio, 0.0f) :
getAnchors(line, symbolSpacing, textMaxAngle, shapedText.left, shapedText.right, glyphSize, textBoxScale, 1.0f) :
Anchors({ Anchor(float(line[0].x), float(line[0].y), 0, minScale) });

View File

@@ -0,0 +1,79 @@
#include <mbgl/text/get_anchors.hpp>
#include <mbgl/util/interpolate.hpp>
#include <cmath>
namespace mbgl {
Anchors resample(const std::vector<Coordinate> &line, const float offset, const float spacing,
const float angleWindowSize, const float maxAngle, const float labelLength, const bool placeAtMiddle) {
float distance = 0;
float markedDistance = offset != 0.0f ? offset - spacing : 0;
Anchors anchors;
auto end = line.end() - 1;
int i = 0;
for (auto it = line.begin(); it != end; it++, i++) {
const Coordinate &a = *(it);
const Coordinate &b = *(it + 1);
const float segmentDist = util::dist<float>(a, b);
const float angle = util::angle_to(b, a);
while (markedDistance + spacing < distance + segmentDist) {
markedDistance += spacing;
float t = (markedDistance - distance) / segmentDist,
x = util::interpolate(a.x, b.x, t),
y = util::interpolate(a.y, b.y, t);
if (x >= 0 && x < 4096 && y >= 0 && y < 4096) {
Anchor anchor(x, y, angle, 0.5f, i);
if (!angleWindowSize || true) {
anchors.push_back(anchor);
}
//if (!angleWindowSize || checkMaxAngle(line, anchor, labelLength, angleWindowSize, maxAngle)) {
}
}
distance += segmentDist;
}
if (!placeAtMiddle && !anchors.size()) {
// The first attempt at finding anchors at which labels can be placed failed.
// Try again, but this time just try placing one anchor at the middle of the line.
// This has the most effect for short lines in overscaled tiles, since the
// initial offset used in overscaled tiles is calculated to align labels with positions in
// parent tiles instead of placing the label as close to the beginning as possible.
anchors = std::move(resample(line, distance / 2, spacing, angleWindowSize, maxAngle, labelLength, true));
}
return anchors;
}
Anchors getAnchors(const std::vector<Coordinate> &line, float spacing,
const bool maxAngle, const float left, const float right,
const float glyphSize, const float boxScale, const float overscaling) {
// Resample a line to get anchor points for labels and check that each
// potential label passes text-max-angle check and has enough froom to fit
// on the line.
const float angleWindowSize = left - right != 0.0f ?
3 / 5 * glyphSize * boxScale :
0;
// Offset the first anchor by half the label length (or half the spacing distance for icons).
// Add a bit of extra offset to avoid collisions at T intersections.
const float labelLength = right - left ? right - left : spacing;
const float extraOffset = glyphSize * 2;
const float offset = std::fmod((labelLength / 2 + extraOffset) * boxScale * overscaling, spacing);
return resample(line, offset, spacing, angleWindowSize, maxAngle, labelLength * boxScale, false);
}
}

View File

@@ -0,0 +1,14 @@
#ifndef MBGL_TEXT_GETANCHORS
#define MBGL_TEXT_GETANCHORS
#include <mbgl/geometry/anchor.hpp>
#include <mbgl/util/math.hpp>
namespace mbgl {
Anchors getAnchors(const std::vector<Coordinate> &line, float spacing,
const bool maxAngle, const float left, const float right,
const float glyphSize, const float boxScale, const float overscaling);
}
#endif

View File

@@ -58,7 +58,7 @@ class Shaping {
public:
inline explicit Shaping() : top(0), bottom(0), left(0), right(0) {}
inline explicit Shaping(float x, float y)
: top(-y), bottom(y), left(-x), right(x) {}
: top(y), bottom(y), left(x), right(x) {}
std::vector<PositionedGlyph> positionedGlyphs;
int32_t top;
int32_t bottom;

View File

@@ -40,7 +40,7 @@ const Shaping FontStack::getShaping(const std::u32string &string, const float ma
const float spacing, const vec2<float> &translate) const {
std::lock_guard<std::mutex> lock(mtx);
Shaping shaping(translate.x, translate.y);
Shaping shaping(translate.x * 24, translate.y * 24);
// the y offset *should* be part of the font metadata
const int32_t yOffset = -17;