summaryrefslogtreecommitdiff
path: root/src/mbgl/text
diff options
context:
space:
mode:
authorAnsis Brammanis <brammanis@gmail.com>2015-04-01 19:03:01 -0700
committerAnsis Brammanis <brammanis@gmail.com>2015-04-01 19:03:01 -0700
commit1d50485e5b824d2608aeba2568f71ff5e4ec217d (patch)
tree5b53b5a0f12d880c4b33e492ac2bf323d812afcf /src/mbgl/text
parentc200053951bc3e2b152d38fbf2f2c5e63ed5dddc (diff)
downloadqtlocation-mapboxgl-1d50485e5b824d2608aeba2568f71ff5e4ec217d.tar.gz
port bboxifyLabel from -js
Diffstat (limited to 'src/mbgl/text')
-rw-r--r--src/mbgl/text/collision_feature.cpp62
-rw-r--r--src/mbgl/text/collision_feature.hpp4
-rw-r--r--src/mbgl/text/collision_tile.cpp6
-rw-r--r--src/mbgl/text/collision_tile.hpp2
4 files changed, 65 insertions, 9 deletions
diff --git a/src/mbgl/text/collision_feature.cpp b/src/mbgl/text/collision_feature.cpp
index 610fefa205..f44e48c350 100644
--- a/src/mbgl/text/collision_feature.cpp
+++ b/src/mbgl/text/collision_feature.cpp
@@ -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);
}
}
diff --git a/src/mbgl/text/collision_feature.hpp b/src/mbgl/text/collision_feature.hpp
index a16f58c8ed..9d8a426625 100644
--- a/src/mbgl/text/collision_feature.hpp
+++ b/src/mbgl/text/collision_feature.hpp
@@ -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;
diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp
index 88a3c6bdd1..0d1b25af54 100644
--- a/src/mbgl/text/collision_tile.cpp
+++ b/src/mbgl/text/collision_tile.cpp
@@ -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,
diff --git a/src/mbgl/text/collision_tile.hpp b/src/mbgl/text/collision_tile.hpp
index b64fcdca30..a3f524ca92 100644
--- a/src/mbgl/text/collision_tile.hpp
+++ b/src/mbgl/text/collision_tile.hpp
@@ -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;