diff options
author | Ansis Brammanis <brammanis@gmail.com> | 2015-04-01 19:03:01 -0700 |
---|---|---|
committer | Ansis Brammanis <brammanis@gmail.com> | 2015-04-01 19:03:01 -0700 |
commit | 1d50485e5b824d2608aeba2568f71ff5e4ec217d (patch) | |
tree | 5b53b5a0f12d880c4b33e492ac2bf323d812afcf /src/mbgl/text | |
parent | c200053951bc3e2b152d38fbf2f2c5e63ed5dddc (diff) | |
download | qtlocation-mapboxgl-1d50485e5b824d2608aeba2568f71ff5e4ec217d.tar.gz |
port bboxifyLabel from -js
Diffstat (limited to 'src/mbgl/text')
-rw-r--r-- | src/mbgl/text/collision_feature.cpp | 62 | ||||
-rw-r--r-- | src/mbgl/text/collision_feature.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/text/collision_tile.cpp | 6 | ||||
-rw-r--r-- | src/mbgl/text/collision_tile.hpp | 2 |
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; |