port SymbolBucket::placeFeatures

This commit is contained in:
Ansis Brammanis
2015-04-01 15:14:49 -07:00
parent fd526ae68e
commit e1059e7125
7 changed files with 74 additions and 38 deletions

View File

@@ -14,7 +14,7 @@
#include <mbgl/util/token.hpp>
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/text/glyph_store.hpp>
#include <mbgl/text/collision.hpp>
#include <mbgl/text/collision_tile.hpp>
#include <mbgl/text/glyph.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/util/std.hpp>
@@ -43,7 +43,7 @@ TileParser::TileParser(const GeometryTile& geometryTile_,
glyphStore(glyphStore_),
spriteAtlas(spriteAtlas_),
sprite(sprite_),
collision(util::make_unique<Collision>(tile.id.z, 4096, tile.source.tile_size, tile.depth)) {
collision(util::make_unique<CollisionTile>(tile.id.z, 4096, tile.source.tile_size)) {
assert(style);
assert(sprite);
assert(collision);

View File

@@ -30,7 +30,7 @@ class StyleLayoutLine;
class StyleLayoutSymbol;
class StyleLayerGroup;
class VectorTileData;
class Collision;
class CollisionTile;
class TileParser : private util::noncopyable {
public:
@@ -69,7 +69,7 @@ private:
SpriteAtlas& spriteAtlas;
util::ptr<Sprite> sprite;
std::unique_ptr<Collision> collision;
std::unique_ptr<CollisionTile> collision;
};
}

View File

@@ -11,7 +11,7 @@
#include <mbgl/text/glyph_store.hpp>
#include <mbgl/text/quads.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/text/collision.hpp>
#include <mbgl/text/collision_tile.hpp>
#include <mbgl/map/sprite.hpp>
#include <mbgl/util/utf.hpp>
@@ -46,7 +46,7 @@ SymbolInstance::SymbolInstance(Anchor &anchor, const std::vector<Coordinate> &li
iconCollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconAlongLine) {};
SymbolBucket::SymbolBucket(std::unique_ptr<const StyleLayoutSymbol> styleLayout_, Collision &collision_)
SymbolBucket::SymbolBucket(std::unique_ptr<const StyleLayoutSymbol> styleLayout_, CollisionTile &collision_)
: styleLayout(std::move(styleLayout_)), collision(collision_) {
assert(styleLayout);
}
@@ -263,10 +263,10 @@ void SymbolBucket::addFeature(const std::vector<std::vector<Coordinate>> &lines,
const float iconPadding = layout.icon.padding * collision.tilePixelRatio;
//const float textMaxAngle = layout.text.max_angle * M_PI / 180;
const bool textAlongLine =
layout.text.rotation_alignment != RotationAlignmentType::Viewport &&
layout.text.rotation_alignment == RotationAlignmentType::Map &&
layout.placement == PlacementType::Line;
const bool iconAlongLine =
layout.icon.rotation_alignment != RotationAlignmentType::Viewport &&
layout.icon.rotation_alignment == RotationAlignmentType::Map &&
layout.placement == PlacementType::Line;
// TODO clip lines here
@@ -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, collision.maxPlacementScale, collision.tilePixelRatio, 0.0f) :
resample(line, layout.min_distance, minScale, 2.0f, collision.tilePixelRatio, 0.0f) :
Anchors({ Anchor(float(line[0].x), float(line[0].y), 0, minScale) });
@@ -297,33 +297,67 @@ void SymbolBucket::addFeature(const std::vector<std::vector<Coordinate>> &lines,
void SymbolBucket::placeFeatures() {
//auto &layout = *styleLayout;
// Calculate which labels can be shown and when they can be shown and
// create the bufers used for rendering.
auto &layout = *styleLayout;
/*
const bool textAlongLine =
layout.text.rotation_alignment == RotationAlignmentType::Map &&
layout.placement == PlacementType::Line;
const bool iconAlongLine =
layout.icon.rotation_alignment == RotationAlignmentType::Map &&
layout.placement == PlacementType::Line;
*/
for (SymbolInstance &symbolInstance : symbolInstances) {
const bool hasText = symbolInstance.hasText;
const bool hasIcon = symbolInstance.hasIcon;
float glyphScale = 0.5f;
float iconScale = 0.5f;
const bool iconWithoutText = layout.text.optional || !hasText;
const bool textWithoutIcon = layout.icon.optional || !hasIcon;
/*
if (!iconWithoutText && !textWithoutIcon) {
iconScale = glyphScale = util::max(iconScale, glyphScale);
} else if (!textWithoutIcon && glyphScale) {
glyphScale = util::max(iconScale, glyphScale);
} else if (!iconWithoutText && iconScale) {
iconScale = util::max(iconScale, glyphScale);
}
*/
// Insert final placement into collision tree and add glyphs/icons to buffers
if (hasText && std::isfinite(glyphScale)) {
addSymbols<TextBuffer, TextElementGroup>(text, symbolInstance.glyphQuads, glyphScale);
// Calculate the scales at which the text and icon can be placed without collision.
float glyphScale = hasText && !layout.text.allow_overlap ?
collision.placeFeature(symbolInstance.textCollisionFeature) : collision.minScale;
float iconScale = hasIcon && !layout.icon.allow_overlap ?
collision.placeFeature(symbolInstance.iconCollisionFeature) : collision.minScale;
//if (glyphScale) fprintf(stderr, "glyphScale %f\n", glyphScale);
// Combine the scales for icons and text.
if (!iconWithoutText && !textWithoutIcon) {
iconScale = glyphScale = util::max(iconScale, glyphScale);
} else if (!textWithoutIcon && glyphScale) {
glyphScale = util::max(iconScale, glyphScale);
} else if (!iconWithoutText && iconScale) {
iconScale = util::max(iconScale, glyphScale);
}
if (hasIcon && std::isfinite(iconScale)) {
addSymbols<IconBuffer, IconElementGroup>(icon, symbolInstance.iconQuads, iconScale);
// Insert final placement into collision tree and add glyphs/icons to buffers
if (hasText) {
if (!layout.text.ignore_placement) {
collision.insertFeature(symbolInstance.textCollisionFeature, glyphScale);
}
if (glyphScale < collision.maxScale) {
addSymbols<TextBuffer, TextElementGroup>(text, symbolInstance.glyphQuads, glyphScale);
}
}
if (hasIcon) {
if (!layout.icon.ignore_placement) {
collision.insertFeature(symbolInstance.iconCollisionFeature, iconScale);
}
if (iconScale < collision.maxScale) {
addSymbols<IconBuffer, IconElementGroup>(icon, symbolInstance.iconQuads, iconScale);
}
}
}

View File

@@ -27,7 +27,7 @@ class SDFShader;
class IconShader;
class CollisionBoxShader;
class DotShader;
class Collision;
class CollisionTile;
class SpriteAtlas;
class Sprite;
class GlyphAtlas;
@@ -55,8 +55,8 @@ class SymbolInstance {
const bool hasIcon;
const PlacedGlyphs glyphQuads;
const PlacedGlyphs iconQuads;
const CollisionFeature textCollisionFeature;
const CollisionFeature iconCollisionFeature;
CollisionFeature textCollisionFeature;
CollisionFeature iconCollisionFeature;
};
class SymbolBucket : public Bucket {
@@ -65,7 +65,7 @@ class SymbolBucket : public Bucket {
typedef ElementGroup<1> CollisionBoxElementGroup;
public:
SymbolBucket(std::unique_ptr<const StyleLayoutSymbol> styleLayout, Collision &collision);
SymbolBucket(std::unique_ptr<const StyleLayoutSymbol> styleLayout, CollisionTile &collision);
~SymbolBucket() override;
void render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id,
@@ -109,7 +109,7 @@ public:
bool sdfIcons = false;
private:
Collision &collision;
CollisionTile &collision;
std::vector<SymbolInstance> symbolInstances;
struct TextBuffer {

View File

@@ -6,6 +6,8 @@ CollisionFeature::CollisionFeature(const std::vector<Coordinate> &line, const An
const float top, const float bottom, const float left, const float right,
const float boxScale, const float padding, const bool alongLine) {
if (top == 0 && bottom == 0 && left == 0 && right == 0) return;
const float y1 = top * boxScale - padding;
const float y2 = bottom * boxScale + padding;
const float x1 = left * boxScale - padding;

View File

@@ -3,9 +3,6 @@
namespace mbgl {
const float minScale = 0.5f;
const float maxScale = 2.0f;
void CollisionTile::reset(const float _angle, const float pitch) {
tree.clear();
angle = _angle;
@@ -23,7 +20,7 @@ void CollisionTile::reset(const float _angle, const float pitch) {
yStretch = std::pow(_yStretch, 1.3);
}
float CollisionTile::placeFeature(CollisionFeature &feature) {
float CollisionTile::placeFeature(const CollisionFeature &feature) {
float minPlacementScale = minScale;
@@ -47,7 +44,7 @@ float CollisionTile::placeFeature(CollisionFeature &feature) {
if (std::isnan(s1) || std::isnan(s2)) s1 = s2 = 1;
if (std::isnan(s3) || std::isnan(s4)) s3 = s4 = 1;
float collisionFreeScale = std::fmin(std::fmax(s1, s3), std::fmax(s3, s4));
float collisionFreeScale = std::fmin(std::fmax(s1, s2), std::fmax(s3, s4));
if (collisionFreeScale > blocking.maxScale) {
// After a box's maxScale the label has shrunk enough that the box is no longer needed to cover it,

View File

@@ -35,16 +35,19 @@ class CollisionTile {
public:
inline explicit CollisionTile(float _zoom, float tileExtent, float tileSize) :
zoom(_zoom), tilePixelRatio(tileExtent / tileSize) {}
zoom(_zoom), tilePixelRatio(tileExtent / tileSize) { reset(0, 0); }
void reset(const float angle, const float pitch);
float placeFeature(CollisionFeature &feature);
float placeFeature(const CollisionFeature &feature);
void insertFeature(CollisionFeature &feature, const float minPlacementScale);
const float zoom;
const float tilePixelRatio;
float angle = 0;
const float minScale = 0.5f;
const float maxScale = 2.0f;
private:
Box getTreeBox(const Anchor &anchor, const CollisionBox &box);