port minor collision code cleanup, fix #1705

https://github.com/mapbox/mapbox-gl-js/pull/1261
This commit is contained in:
Ansis Brammanis
2015-08-20 13:18:48 -04:00
parent 19c256e349
commit 99c5976498
11 changed files with 89 additions and 92 deletions

View File

@@ -25,9 +25,7 @@ LiveTileData::LiveTileData(const TileID& id_,
style_,
style_.layers,
state,
std::make_unique<CollisionTile>(id_.z, 4096,
source_.tile_size * id.overscaling,
0, 0, false)) {
std::make_unique<CollisionTile>(0, 0, false)) {
state = State::loaded;
if (!tile) {

View File

@@ -25,7 +25,7 @@ TileWorker::TileWorker(TileID id_,
maxZoom(maxZoom_),
style(style_),
state(state_),
collision(std::move(collision_)) {
collisionTile(std::move(collision_)) {
assert(style.sprite);
}
@@ -56,12 +56,11 @@ TileParseResult TileWorker::parse(const GeometryTile& geometryTile) {
}
void TileWorker::redoPlacement(float angle, float pitch, bool collisionDebug) {
collision->reset(angle, pitch);
collision->setDebug(collisionDebug);
collisionTile = std::make_unique<CollisionTile>(angle, pitch, collisionDebug);
for (auto i = layers.rbegin(); i != layers.rend(); i++) {
auto bucket = getBucket(**i);
if (bucket) {
bucket->placeFeatures();
bucket->placeFeatures(*collisionTile);
}
}
}
@@ -224,7 +223,7 @@ std::unique_ptr<Bucket> TileWorker::createCircleBucket(const GeometryTileLayer&
std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer& layer,
const StyleBucket& bucket_desc) {
auto bucket = std::make_unique<SymbolBucket>(*collision, id.overscaling);
auto bucket = std::make_unique<SymbolBucket>(id.overscaling, id.z);
const float z = id.z;
auto& layout = bucket->layout;
@@ -283,7 +282,7 @@ std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer&
}
bucket->addFeatures(reinterpret_cast<uintptr_t>(this), *style.spriteAtlas, *style.glyphAtlas,
*style.glyphStore);
*style.glyphStore, *collisionTile);
return bucket->hasData() ? std::move(bucket) : nullptr;
}

View File

@@ -75,7 +75,7 @@ private:
TriangleElementsBuffer triangleElementsBuffer;
LineElementsBuffer lineElementsBuffer;
std::unique_ptr<CollisionTile> collision;
std::unique_ptr<CollisionTile> collisionTile;
// Contains all the Bucket objects for the tile. Buckets are render
// objects and they get added to this map as they get processed.

View File

@@ -26,9 +26,7 @@ VectorTileData::VectorTileData(const TileID& id_,
style_,
style_.layers,
state,
std::make_unique<CollisionTile>(id_.z, 4096,
source_.tile_size * id.overscaling,
angle, pitch, collisionDebug)),
std::make_unique<CollisionTile>(angle, pitch, collisionDebug)),
source(source_),
lastAngle(angle),
currentAngle(angle) {

View File

@@ -12,6 +12,7 @@ namespace mbgl {
class Painter;
class StyleLayer;
class TileID;
class CollisionTile;
class Bucket : private util::noncopyable {
public:
@@ -29,7 +30,7 @@ public:
return !uploaded;
}
virtual void placeFeatures() {}
virtual void placeFeatures(CollisionTile&) {}
virtual void swapRenderData() {}
protected:

View File

@@ -53,8 +53,8 @@ SymbolInstance::SymbolInstance(Anchor &anchor, const std::vector<Coordinate> &li
iconCollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconAlongLine) {};
SymbolBucket::SymbolBucket(CollisionTile &collision_, float overscaling_)
: collision(collision_), overscaling(overscaling_) {
SymbolBucket::SymbolBucket(float overscaling_, float zoom_)
: overscaling(overscaling_), zoom(zoom_), tileSize(512 * overscaling_), tilePixelRatio(tileExtent / tileSize) {
}
SymbolBucket::~SymbolBucket() {
@@ -174,7 +174,8 @@ bool SymbolBucket::needsDependencies(const GeometryTileLayer& layer,
void SymbolBucket::addFeatures(uintptr_t tileUID,
SpriteAtlas& spriteAtlas,
GlyphAtlas& glyphAtlas,
GlyphStore& glyphStore) {
GlyphStore& glyphStore,
CollisionTile& collisionTile) {
float horizontalAlign = 0.5;
float verticalAlign = 0.5;
@@ -264,7 +265,7 @@ void SymbolBucket::addFeatures(uintptr_t tileUID,
features.clear();
placeFeatures(true);
placeFeatures(collisionTile, true);
}
@@ -275,13 +276,13 @@ void SymbolBucket::addFeature(const std::vector<std::vector<Coordinate>> &lines,
const float glyphSize = 24.0f;
const float fontScale = layout.text.size / glyphSize;
const float textBoxScale = collision.tilePixelRatio * fontScale;
const float textMaxBoxScale = collision.tilePixelRatio * layout.text.max_size / glyphSize;
const float iconBoxScale = collision.tilePixelRatio * layout.icon.size;
const float symbolSpacing = collision.tilePixelRatio * layout.spacing;
const float textBoxScale = tilePixelRatio * fontScale;
const float textMaxBoxScale = tilePixelRatio * layout.text.max_size / glyphSize;
const float iconBoxScale = tilePixelRatio * layout.icon.size;
const float symbolSpacing = tilePixelRatio * layout.spacing;
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 textPadding = layout.text.padding * tilePixelRatio;
const float iconPadding = layout.icon.padding * tilePixelRatio;
const float textMaxAngle = layout.text.max_angle * M_PI / 180;
const bool textAlongLine =
layout.text.rotation_alignment == RotationAlignmentType::Map &&
@@ -354,11 +355,11 @@ bool SymbolBucket::anchorIsTooClose(const std::u32string &text, const float repe
return false;
}
void SymbolBucket::placeFeatures() {
placeFeatures(false);
void SymbolBucket::placeFeatures(CollisionTile& collisionTile) {
placeFeatures(collisionTile, false);
}
void SymbolBucket::placeFeatures(bool swapImmediately) {
void SymbolBucket::placeFeatures(CollisionTile& collisionTile, bool swapImmediately) {
renderDataInProgress = std::make_unique<SymbolRenderData>();
@@ -380,8 +381,8 @@ void SymbolBucket::placeFeatures(bool swapImmediately) {
// Don't sort symbols that won't overlap because it isn't necessary and
// because it causes more labels to pop in and out when rotating.
if (mayOverlap) {
float sin = std::sin(collision.angle);
float cos = std::cos(collision.angle);
float sin = std::sin(collisionTile.angle);
float cos = std::cos(collisionTile.angle);
std::sort(symbolInstances.begin(), symbolInstances.end(), [sin, cos](SymbolInstance &a, SymbolInstance &b) {
const float aRotated = sin * a.x + cos * a.y;
@@ -401,9 +402,9 @@ void SymbolBucket::placeFeatures(bool swapImmediately) {
// 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;
collisionTile.placeFeature(symbolInstance.textCollisionFeature) : collisionTile.minScale;
float iconScale = hasIcon && !layout.icon.allow_overlap ?
collision.placeFeature(symbolInstance.iconCollisionFeature) : collision.minScale;
collisionTile.placeFeature(symbolInstance.iconCollisionFeature) : collisionTile.minScale;
// Combine the scales for icons and text.
@@ -421,33 +422,32 @@ void SymbolBucket::placeFeatures(bool swapImmediately) {
if (hasText) {
if (!layout.text.ignore_placement) {
collision.insertFeature(symbolInstance.textCollisionFeature, glyphScale);
collisionTile.insertFeature(symbolInstance.textCollisionFeature, glyphScale);
}
if (glyphScale < collision.maxScale) {
if (glyphScale < collisionTile.maxScale) {
addSymbols<SymbolRenderData::TextBuffer, TextElementGroup>(renderDataInProgress->text,
symbolInstance.glyphQuads, glyphScale, layout.text.keep_upright, textAlongLine);
symbolInstance.glyphQuads, glyphScale, layout.text.keep_upright, textAlongLine, collisionTile.angle);
}
}
if (hasIcon) {
if (!layout.icon.ignore_placement) {
collision.insertFeature(symbolInstance.iconCollisionFeature, iconScale);
collisionTile.insertFeature(symbolInstance.iconCollisionFeature, iconScale);
}
if (iconScale < collision.maxScale) {
if (iconScale < collisionTile.maxScale) {
addSymbols<SymbolRenderData::IconBuffer, IconElementGroup>(renderDataInProgress->icon,
symbolInstance.iconQuads, iconScale, layout.icon.keep_upright, iconAlongLine);
symbolInstance.iconQuads, iconScale, layout.icon.keep_upright, iconAlongLine, collisionTile.angle);
}
}
}
if (collision.getDebug()) addToDebugBuffers();
if (collisionTile.getDebug()) addToDebugBuffers(collisionTile);
if (swapImmediately) swapRenderData();
}
template <typename Buffer, typename GroupType>
void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale, const bool keepUpright, const bool alongLine) {
const float zoom = collision.zoom;
void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale, const bool keepUpright, const bool alongLine, const float placementAngle) {
const float placementZoom = ::fmax(std::log(scale) / std::log(2) + zoom, 0);
@@ -461,10 +461,10 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
float minZoom =
util::max(static_cast<float>(zoom + log(symbol.minScale) / log(2)), placementZoom);
float maxZoom = util::min(static_cast<float>(zoom + log(symbol.maxScale) / log(2)), 25.0f);
const auto &glyphAnchor = symbol.anchor;
const auto &anchorPoint = symbol.anchorPoint;
// drop upside down versions of glyphs
const float a = std::fmod(symbol.angle + collision.angle + M_PI, M_PI * 2);
const float a = std::fmod(symbol.angle + placementAngle + M_PI, M_PI * 2);
if (keepUpright && alongLine && (a <= M_PI / 2 || a > M_PI * 3 / 2)) continue;
@@ -491,13 +491,13 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
uint32_t triangleIndex = triangleGroup.vertex_length;
// coordinates (2 triangles)
buffer.vertices.add(glyphAnchor.x, glyphAnchor.y, tl.x, tl.y, tex.x, tex.y, minZoom,
buffer.vertices.add(anchorPoint.x, anchorPoint.y, tl.x, tl.y, tex.x, tex.y, minZoom,
maxZoom, placementZoom);
buffer.vertices.add(glyphAnchor.x, glyphAnchor.y, tr.x, tr.y, tex.x + tex.w, tex.y,
buffer.vertices.add(anchorPoint.x, anchorPoint.y, tr.x, tr.y, tex.x + tex.w, tex.y,
minZoom, maxZoom, placementZoom);
buffer.vertices.add(glyphAnchor.x, glyphAnchor.y, bl.x, bl.y, tex.x, tex.y + tex.h,
buffer.vertices.add(anchorPoint.x, anchorPoint.y, bl.x, bl.y, tex.x, tex.y + tex.h,
minZoom, maxZoom, placementZoom);
buffer.vertices.add(glyphAnchor.x, glyphAnchor.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h,
buffer.vertices.add(anchorPoint.x, anchorPoint.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h,
minZoom, maxZoom, placementZoom);
// add the two triangles, referencing the four coordinates we just inserted.
@@ -509,11 +509,10 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
}
}
void SymbolBucket::addToDebugBuffers() {
void SymbolBucket::addToDebugBuffers(CollisionTile &collisionTile) {
const float yStretch = collision.yStretch;
const float angle = collision.angle;
const float zoom = collision.zoom;
const float yStretch = collisionTile.yStretch;
const float angle = collisionTile.angle;
float angle_sin = std::sin(-angle);
float angle_cos = std::cos(-angle);
std::array<float, 4> matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};

View File

@@ -64,7 +64,7 @@ class SymbolBucket : public Bucket {
typedef ElementGroup<1> CollisionBoxElementGroup;
public:
SymbolBucket(CollisionTile &collision, float overscaling);
SymbolBucket(float overscaling, float zoom);
~SymbolBucket() override;
void upload() override;
@@ -77,7 +77,8 @@ public:
void addFeatures(uintptr_t tileUID,
SpriteAtlas&,
GlyphAtlas&,
GlyphStore&);
GlyphStore&,
CollisionTile&);
void drawGlyphs(SDFShader& shader);
void drawIcons(SDFShader& shader);
@@ -88,7 +89,7 @@ public:
const FilterExpression&,
GlyphStore&,
Sprite&);
void placeFeatures() override;
void placeFeatures(CollisionTile&) override;
private:
void addFeature(const std::vector<std::vector<Coordinate>> &lines,
@@ -97,22 +98,28 @@ private:
bool anchorIsTooClose(const std::u32string &text, const float repeatDistance, Anchor &anchor);
std::map<std::u32string, std::vector<Anchor>> compareText;
void addToDebugBuffers();
void addToDebugBuffers(CollisionTile &collisionTile);
void placeFeatures(bool swapImmediately);
void placeFeatures(CollisionTile& collisionTile, bool swapImmediately);
void swapRenderData() override;
// Adds placed items to the buffer.
template <typename Buffer, typename GroupType>
void addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale, const bool keepUpright, const bool alongLine);
void addSymbols(Buffer &buffer, const SymbolQuads &symbols, float scale,
const bool keepUpright, const bool alongLine, const float placementAngle);
public:
StyleLayoutSymbol layout;
bool sdfIcons = false;
private:
CollisionTile &collision;
const float overscaling;
const float zoom;
const float tileSize;
const float tileExtent = 4096.0f;
const float tilePixelRatio;
std::vector<SymbolInstance> symbolInstances;
std::vector<SymbolFeature> features;

View File

@@ -3,13 +3,13 @@
namespace mbgl {
void CollisionTile::reset(const float _angle, const float pitch) {
CollisionTile::CollisionTile(const float angle_, const float pitch, bool debug_) :
angle(angle_), debug(debug_) {
tree.clear();
angle = _angle;
// Compute the transformation matrix.
float angle_sin = std::sin(_angle);
float angle_cos = std::cos(_angle);
float angle_sin = std::sin(angle);
float angle_cos = std::cos(angle);
rotationMatrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};
// Stretch boxes in y direction to account for the map tilt.

View File

@@ -35,19 +35,14 @@ namespace mbgl {
class CollisionTile {
public:
inline explicit CollisionTile(float _zoom, float tileExtent, float tileSize, float angle_, float pitch_, bool debug_) :
zoom(_zoom), tilePixelRatio(tileExtent / tileSize), debug(debug_) { reset(angle_, pitch_); }
explicit CollisionTile(float angle_, float pitch_, bool debug_);
void reset(const float angle, const float pitch);
float placeFeature(const CollisionFeature &feature);
void insertFeature(CollisionFeature &feature, const float minPlacementScale);
void setDebug(bool debug_) { debug = debug_; }
bool getDebug() { return debug; }
const float zoom;
const float tilePixelRatio;
float angle = 0;
const float angle = 0;
const float minScale = 0.5f;
const float maxScale = 2.0f;

View File

@@ -50,12 +50,12 @@ SymbolQuads getIconQuads(Anchor &anchor, const PositionedIcon &shapedIcon,
}
struct GlyphInstance {
explicit GlyphInstance(const vec2<float> &anchor_) : anchor(anchor_) {}
explicit GlyphInstance(const vec2<float> &anchor_, float offset_, float minScale_, float maxScale_,
explicit GlyphInstance(const vec2<float> &anchorPoint_) : anchorPoint(anchorPoint_) {}
explicit GlyphInstance(const vec2<float> &anchorPoint_, float offset_, float minScale_, float maxScale_,
float angle_)
: anchor(anchor_), offset(offset_), minScale(minScale_), maxScale(maxScale_), angle(angle_) {}
: anchorPoint(anchorPoint_), offset(offset_), minScale(minScale_), maxScale(maxScale_), angle(angle_) {}
const vec2<float> anchor;
const vec2<float> anchorPoint;
const float offset = 0.0f;
const float minScale = globalMinScale;
const float maxScale = std::numeric_limits<float>::infinity();
@@ -65,19 +65,19 @@ struct GlyphInstance {
typedef std::vector<GlyphInstance> GlyphInstances;
void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor &anchor,
float offset, const std::vector<Coordinate> &line, int segment, int8_t direction) {
float offset, const std::vector<Coordinate> &line, int segment, bool forward) {
const bool upsideDown = direction < 0;
const bool upsideDown = !forward;
if (offset < 0)
direction *= -1;
forward = !forward;
if (direction > 0)
if (forward)
segment++;
assert((int)line.size() > segment);
vec2<float> end = line[segment];
vec2<float> newAnchor = anchor;
vec2<float> newAnchorPoint = anchor;
float prevscale = std::numeric_limits<float>::infinity();
offset = std::fabs(offset);
@@ -85,16 +85,16 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor &
const float placementScale = anchor.scale;
while (true) {
const float dist = util::dist<float>(newAnchor, end);
const float dist = util::dist<float>(newAnchorPoint, end);
const float scale = offset / dist;
float angle = std::atan2(end.y - newAnchor.y, end.x - newAnchor.x);
if (direction < 0)
float angle = std::atan2(end.y - newAnchorPoint.y, end.x - newAnchorPoint.x);
if (!forward)
angle += M_PI;
if (upsideDown)
angle += M_PI;
glyphs = GlyphInstance{
/* anchor */ newAnchor,
/* anchor */ newAnchorPoint,
/* offset */ static_cast<float>(upsideDown ? M_PI : 0.0),
/* minScale */ scale,
/* maxScale */ prevscale,
@@ -103,11 +103,11 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor &
if (scale <= placementScale)
break;
newAnchor = end;
newAnchorPoint = end;
// skip duplicate nodes
while (newAnchor == end) {
segment += direction;
while (newAnchorPoint == end) {
segment += forward ? 1 : -1;
if ((int)line.size() <= segment || segment < 0) {
anchor.scale = scale;
return;
@@ -115,8 +115,8 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor &
end = line[segment];
}
vec2<float> normal = util::normal<float>(newAnchor, end) * dist;
newAnchor = newAnchor - normal;
vec2<float> normal = util::normal<float>(newAnchorPoint, end) * dist;
newAnchorPoint = newAnchorPoint - normal;
prevscale = scale;
}
@@ -148,9 +148,9 @@ SymbolQuads getGlyphQuads(Anchor &anchor, const Shaping &shapedText,
GlyphInstances glyphInstances;
if (alongLine) {
getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, 1);
getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, true);
if (keepUpright)
getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, -1);
getSegmentGlyphs(std::back_inserter(glyphInstances), anchor, centerX, line, anchor.segment, false);
} else {
glyphInstances.emplace_back(GlyphInstance{anchor});
@@ -194,7 +194,7 @@ SymbolQuads getGlyphQuads(Anchor &anchor, const Shaping &shapedText,
const float glyphMinScale = std::max(instance.minScale, anchor.scale);
const float glyphAngle = std::fmod((anchor.angle + textRotate + instance.offset + 2 * M_PI), (2 * M_PI));
quads.emplace_back(tl, tr, bl, br, rect, glyphAngle, instance.anchor, glyphMinScale, instance.maxScale);
quads.emplace_back(tl, tr, bl, br, rect, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale);
}

View File

@@ -11,7 +11,7 @@ namespace mbgl {
struct SymbolQuad {
explicit SymbolQuad(const vec2<float> &tl_, const vec2<float> &tr_,
const vec2<float> &bl_, const vec2<float> &br_,
const Rect<uint16_t> &tex_, float angle_, const vec2<float> &anchor_,
const Rect<uint16_t> &tex_, float angle_, const vec2<float> &anchorPoint_,
float minScale_, float maxScale_)
: tl(tl_),
tr(tr_),
@@ -19,14 +19,14 @@ namespace mbgl {
br(br_),
tex(tex_),
angle(angle_),
anchor(anchor_),
anchorPoint(anchorPoint_),
minScale(minScale_),
maxScale(maxScale_) {}
vec2<float> tl, tr, bl, br;
Rect<uint16_t> tex;
float angle;
vec2<float> anchor;
vec2<float> anchorPoint;
float minScale, maxScale;
};