port bboxifyLabel from -js

This commit is contained in:
Ansis Brammanis
2015-04-01 19:03:01 -07:00
parent c200053951
commit 1d50485e5b
5 changed files with 65 additions and 13 deletions

View File

@@ -17,10 +17,6 @@ struct Anchor {
explicit Anchor(float x_, float y_, float angle_, float scale_, int segment_)
: x(x_), y(y_), angle(angle_), scale(scale_), segment(segment_) {}
template <typename M>
inline Anchor matMul(const M &m) const {
return Anchor{m[0] * x + m[1] * y, m[2] * x + m[3] * y, angle, scale, segment};
}
};
typedef std::vector<Anchor> Anchors;

View File

@@ -1,4 +1,5 @@
#include <mbgl/text/collision_feature.hpp>
#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -24,10 +25,65 @@ CollisionFeature::CollisionFeature(const std::vector<Coordinate> &line, const An
}
void CollisionFeature::bboxifyLabel(const std::vector<Coordinate> &line,
const Anchor &anchor, const float length, const float height) {
const Anchor &anchor, const float labelLength, const float boxSize) {
if (length && height && line.size() && anchor.x) {
fprintf(stderr, "");
const float step = boxSize / 2;
const unsigned int nBoxes = std::floor(labelLength / step);
// offset the center of the first box by half a box so that the edge of the
// box is at the edge of the label.
const float firstBoxOffset = -boxSize / 2;
Coordinate anchorPoint = Coordinate{ (int16_t)anchor.x, (int16_t)anchor.y };
Coordinate &p = anchorPoint;
int index = anchor.segment + 1;
float anchorDistance = firstBoxOffset;
// move backwards along the line to the first segment the label appears on
while (anchorDistance > -labelLength / 2) {
index--;
// there isn't enough room for the label after the beginning of the line
// checkMaxAngle should have already caught this
if (index < 0) return;
anchorDistance -= util::dist<float>(line[index], p);
p = line[index];
}
float segmentLength = util::dist<float>(line[index], line[index + 1]);
for (unsigned int i = 0; i < nBoxes; i++) {
// the distance the box will be from the anchor
const float boxDistanceToAnchor = -labelLength / 2 + i * step;
// the box is not on the current segment. Move to the next segment.
while (anchorDistance + segmentLength < boxDistanceToAnchor) {
anchorDistance += segmentLength;
index++;
// There isn't enough room before the end of the line.
if (index + 1 >= (int)line.size()) return;
segmentLength = util::dist<float>(line[index], line[index + 1]);
}
// the distance the box will be from the beginning of the segment
const float segmentBoxDistance = boxDistanceToAnchor - anchorDistance;
const auto& p0 = line[index];
const auto& p1 = line[index + 1];
vec2<float> boxAnchor = {
p0.x + segmentBoxDistance / segmentLength * (p1.x - p0.x),
p0.y + segmentBoxDistance / segmentLength * (p1.y - p0.y)
};
const float distanceToInnerEdge = std::max(std::fabs(boxDistanceToAnchor - firstBoxOffset) - step / 2, 0.0f);
const float maxScale = labelLength / 2 / distanceToInnerEdge;
boxes.emplace_back(boxAnchor, -boxSize / 2, -boxSize / 2, boxSize / 2, boxSize / 2, maxScale);
}
}

View File

@@ -9,11 +9,11 @@
namespace mbgl {
class CollisionBox {
public:
explicit CollisionBox(const Anchor &_anchor, float _x1, float _y1, float _x2, float _y2, float _maxScale) :
explicit CollisionBox(const vec2<float> &_anchor, float _x1, float _y1, float _x2, float _y2, float _maxScale) :
anchor(_anchor), x1(_x1), y1(_y1), x2(_x2), y2(_y2), maxScale(_maxScale) {}
// the box is centered around the anchor point
const Anchor anchor;
const vec2<float> anchor;
// distances to the edges from the anchor
const float x1;

View File

@@ -25,14 +25,14 @@ float CollisionTile::placeFeature(const CollisionFeature &feature) {
float minPlacementScale = minScale;
for (auto& box : feature.boxes) {
const Anchor anchor = box.anchor.matMul(rotationMatrix);
const auto anchor = box.anchor.matMul(rotationMatrix);
std::vector<CollisionTreeBox> blockingBoxes;
tree.query(bgi::intersects(getTreeBox(anchor, box)), std::back_inserter(blockingBoxes));
for (auto& blockingTreeBox : blockingBoxes) {
const auto& blocking = std::get<1>(blockingTreeBox);
Anchor blockingAnchor = blocking.anchor.matMul(rotationMatrix);
auto blockingAnchor = blocking.anchor.matMul(rotationMatrix);
// Find the lowest scale at which the two boxes can fit side by side without overlapping.
// Original algorithm:
@@ -89,7 +89,7 @@ void CollisionTile::insertFeature(CollisionFeature &feature, const float minPlac
}
Box CollisionTile::getTreeBox(const Anchor &anchor, const CollisionBox &box) {
Box CollisionTile::getTreeBox(const vec2<float> &anchor, const CollisionBox &box) {
return Box{
Point{
anchor.x + box.x1,

View File

@@ -50,7 +50,7 @@ class CollisionTile {
private:
Box getTreeBox(const Anchor &anchor, const CollisionBox &box);
Box getTreeBox(const vec2<float> &anchor, const CollisionBox &box);
Tree tree;
std::array<float, 4> rotationMatrix;