Merge pull request #928 from mapbox/928-refactor-vend-geometry

refactor VectorTile to vend geometry
This commit is contained in:
Justin R. Miller
2015-03-10 12:09:11 -07:00
16 changed files with 268 additions and 448 deletions

View File

@@ -1,77 +0,0 @@
#ifndef MBGL_GEOMETRY_GEOMETRY
#define MBGL_GEOMETRY_GEOMETRY
#include <mbgl/util/pbf.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <cstdlib>
namespace mbgl {
class Geometry : private util::noncopyable {
public:
inline explicit Geometry(pbf& data);
enum command : uint8_t {
end = 0,
move_to = 1,
line_to = 2,
close = 7
};
inline command next(int32_t &rx, int32_t &ry);
private:
pbf& data;
uint8_t cmd;
uint32_t length;
int32_t x, y;
int32_t ox, oy;
};
Geometry::Geometry(pbf& data_)
: data(data_),
cmd(1),
length(0),
x(0), y(0),
ox(0), oy(0) {}
Geometry::command Geometry::next(int32_t &rx, int32_t &ry) {
if (data.data < data.end) {
if (length == 0) {
uint32_t cmd_length = static_cast<uint32_t>(data.varint());
cmd = cmd_length & 0x7;
length = cmd_length >> 3;
}
--length;
if (cmd == move_to || cmd == line_to) {
rx = (x += data.svarint());
ry = (y += data.svarint());
if (cmd == move_to) {
ox = x;
oy = y;
return move_to;
} else {
return line_to;
}
} else if (cmd == close) {
rx = ox;
ry = oy;
return close;
} else {
fprintf(stderr, "unknown command: %d\n", cmd);
// TODO: gracefully handle geometry parse failures
return end;
}
} else {
return end;
}
}
}
#endif

View File

@@ -1,5 +1,4 @@
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/map/vector_tile.hpp>
#include <mbgl/platform/gl.hpp>
#include <mbgl/platform/platform.hpp>

View File

@@ -0,0 +1,16 @@
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/style/filter_expression_private.hpp>
namespace mbgl {
mapbox::util::optional<Value> GeometryTileFeatureExtractor::getValue(const std::string& key) const {
if (key == "$type") {
return Value(uint64_t(feature.getType()));
}
return feature.getValue(key);
}
template bool evaluate(const FilterExpression&, const GeometryTileFeatureExtractor&);
}

View File

@@ -0,0 +1,62 @@
#ifndef MBGL_MAP_GEOMETRY_TILE
#define MBGL_MAP_GEOMETRY_TILE
#include <mbgl/style/filter_expression.hpp>
#include <mbgl/style/value.hpp>
#include <mbgl/text/glyph.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/ptr.hpp>
#include <mbgl/util/variant.hpp>
#include <mbgl/util/vec.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <cstdint>
#include <map>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <vector>
namespace mbgl {
enum class FeatureType : uint8_t {
Unknown = 0,
Point = 1,
LineString = 2,
Polygon = 3
};
typedef std::vector<std::vector<Coordinate>> GeometryCollection;
class GeometryTileFeature : public mbgl::util::noncopyable {
public:
virtual FeatureType getType() const = 0;
virtual mapbox::util::optional<Value> getValue(const std::string& key) const = 0;
virtual GeometryCollection getGeometries() const = 0;
};
class GeometryTileLayer : public mbgl::util::noncopyable {
public:
virtual std::size_t featureCount() const = 0;
virtual util::ptr<const GeometryTileFeature> feature(std::size_t i) const = 0;
};
class GeometryTile : public mbgl::util::noncopyable {
public:
virtual util::ptr<const GeometryTileLayer> getLayer(const std::string&) const = 0;
};
class GeometryTileFeatureExtractor {
public:
GeometryTileFeatureExtractor(const GeometryTileFeature& feature_)
: feature(feature_) {}
mapbox::util::optional<Value> getValue(const std::string& key) const;
private:
const GeometryTileFeature& feature;
};
}
#endif

View File

@@ -187,15 +187,14 @@ std::unique_ptr<Bucket> TileParser::createBucket(const StyleBucket &bucketDesc)
if (tile.id.z >= std::ceil(bucketDesc.max_zoom)) return nullptr;
if (bucketDesc.visibility == mbgl::VisibilityType::None) return nullptr;
auto layer_it = vectorTile.layers.find(bucketDesc.source_layer);
if (layer_it != vectorTile.layers.end()) {
const VectorTileLayer &layer = layer_it->second;
auto layer = vectorTile.getLayer(bucketDesc.source_layer);
if (layer) {
if (bucketDesc.type == StyleLayerType::Fill) {
return createFillBucket(layer, bucketDesc);
return createFillBucket(*layer, bucketDesc);
} else if (bucketDesc.type == StyleLayerType::Line) {
return createLineBucket(layer, bucketDesc);
return createLineBucket(*layer, bucketDesc);
} else if (bucketDesc.type == StyleLayerType::Symbol) {
return createSymbolBucket(layer, bucketDesc);
return createSymbolBucket(*layer, bucketDesc);
} else if (bucketDesc.type == StyleLayerType::Raster) {
return nullptr;
} else {
@@ -213,25 +212,23 @@ std::unique_ptr<Bucket> TileParser::createBucket(const StyleBucket &bucketDesc)
}
template <class Bucket>
void TileParser::addBucketGeometries(Bucket& bucket, const VectorTileLayer& layer, const FilterExpression &filter) {
FilteredVectorTileLayer filtered_layer(layer, filter);
for (pbf feature : filtered_layer) {
void TileParser::addBucketGeometries(Bucket& bucket, const GeometryTileLayer& layer, const FilterExpression &filter) {
for (std::size_t i = 0; i < layer.featureCount(); i++) {
auto feature = layer.feature(i);
if (obsolete())
return;
while (feature.next(4)) { // geometry
pbf geometry_pbf = feature.message();
if (geometry_pbf) {
bucket->addGeometry(geometry_pbf);
} else if (debug::tileParseWarnings) {
fprintf(stderr, "[WARNING] geometry is empty\n");
}
}
GeometryTileFeatureExtractor extractor(*feature);
if (!evaluate(filter, extractor))
continue;
bucket->addGeometry(feature->getGeometries());
}
}
std::unique_ptr<Bucket> TileParser::createFillBucket(const VectorTileLayer &layer,
const StyleBucket &bucket_desc) {
std::unique_ptr<Bucket> TileParser::createFillBucket(const GeometryTileLayer& layer,
const StyleBucket& bucket_desc) {
auto fill = parseStyleLayoutFill(bucket_desc, tile.id.z);
auto bucket = util::make_unique<FillBucket>(std::move(fill),
tile.fillVertexBuffer,
@@ -241,8 +238,8 @@ std::unique_ptr<Bucket> TileParser::createFillBucket(const VectorTileLayer &laye
return obsolete() ? nullptr : std::move(bucket);
}
std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer &layer,
const StyleBucket &bucket_desc) {
std::unique_ptr<Bucket> TileParser::createLineBucket(const GeometryTileLayer& layer,
const StyleBucket& bucket_desc) {
auto line = parseStyleLayoutLine(bucket_desc, tile.id.z);
auto bucket = util::make_unique<LineBucket>(std::move(line),
tile.lineVertexBuffer,
@@ -252,8 +249,8 @@ std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer &laye
return obsolete() ? nullptr : std::move(bucket);
}
std::unique_ptr<Bucket> TileParser::createSymbolBucket(const VectorTileLayer &layer,
const StyleBucket &bucket_desc) {
std::unique_ptr<Bucket> TileParser::createSymbolBucket(const GeometryTileLayer& layer,
const StyleBucket& bucket_desc) {
auto symbol = parseStyleLayoutSymbol(bucket_desc, tile.id.z);
auto bucket = util::make_unique<SymbolBucket>(std::move(symbol), *collision);
bucket->addFeatures(

View File

@@ -1,6 +1,7 @@
#ifndef MBGL_MAP_TILE_PARSER
#define MBGL_MAP_TILE_PARSER
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/map/vector_tile.hpp>
#include <mbgl/style/filter_expression.hpp>
#include <mbgl/style/class_properties.hpp>
@@ -51,12 +52,13 @@ private:
bool obsolete() const;
void parseStyleLayers(util::ptr<const StyleLayerGroup> group);
std::unique_ptr<Bucket> createBucket(const StyleBucket& bucketDesc);
std::unique_ptr<Bucket> createFillBucket(const VectorTileLayer& layer, const StyleBucket& bucketDesc);
std::unique_ptr<Bucket> createLineBucket(const VectorTileLayer& layer, const StyleBucket& bucketDesc);
std::unique_ptr<Bucket> createSymbolBucket(const VectorTileLayer& layer, const StyleBucket& bucketDesc);
std::unique_ptr<Bucket> createBucket(const StyleBucket&);
std::unique_ptr<Bucket> createFillBucket(const GeometryTileLayer&, const StyleBucket&);
std::unique_ptr<Bucket> createLineBucket(const GeometryTileLayer&, const StyleBucket&);
std::unique_ptr<Bucket> createSymbolBucket(const GeometryTileLayer&, const StyleBucket&);
template <class Bucket> void addBucketGeometries(Bucket& bucket, const VectorTileLayer& layer, const FilterExpression& filter);
template <class Bucket>
void addBucketGeometries(Bucket&, const GeometryTileLayer&, const FilterExpression&);
private:
const VectorTile vectorTile;

View File

@@ -1,30 +1,14 @@
#include <mbgl/map/vector_tile.hpp>
#include <mbgl/style/filter_expression_private.hpp>
#include <mbgl/util/variant_io.hpp>
#include <algorithm>
#include <iostream>
using namespace mbgl;
std::ostream& mbgl::operator<<(std::ostream& os, const FeatureType& type) {
switch (type) {
case FeatureType::Unknown: return os << "Unknown";
case FeatureType::Point: return os << "Point";
case FeatureType::LineString: return os << "LineString";
case FeatureType::Polygon: return os << "Polygon";
default: return os << "Invalid";
}
}
VectorTileFeature::VectorTileFeature(pbf feature, const VectorTileLayer& layer) {
while (feature.next()) {
if (feature.tag == 1) { // id
id = feature.varint<uint64_t>();
} else if (feature.tag == 2) { // tags
VectorTileFeature::VectorTileFeature(pbf feature_pbf, const VectorTileLayer& layer) {
while (feature_pbf.next()) {
if (feature_pbf.tag == 1) { // id
id = feature_pbf.varint<uint64_t>();
} else if (feature_pbf.tag == 2) { // tags
// tags are packed varints. They should have an even length.
pbf tags = feature.message();
pbf tags = feature_pbf.message();
while (tags) {
uint32_t tag_key = tags.varint();
@@ -43,173 +27,106 @@ VectorTileFeature::VectorTileFeature(pbf feature, const VectorTileLayer& layer)
throw std::runtime_error("uneven number of feature tag ids");
}
}
} else if (feature.tag == 3) { // type
type = (FeatureType)feature.varint();
} else if (feature.tag == 4) { // geometry
geometry = feature.message();
} else if (feature_pbf.tag == 3) { // type
type = (FeatureType)feature_pbf.varint();
} else if (feature_pbf.tag == 4) { // geometry
geometry_pbf = feature_pbf.message();
} else {
feature.skip();
feature_pbf.skip();
}
}
}
std::ostream& mbgl::operator<<(std::ostream& os, const VectorTileFeature& feature) {
os << "Feature(" << feature.id << "): " << feature.type << std::endl;
for (const auto& prop : feature.properties) {
os << " - " << prop.first << ": " << prop.second << std::endl;
mapbox::util::optional<Value> VectorTileFeature::getValue(const std::string& key) const {
auto it = properties.find(key);
if (it != properties.end()) {
return it->second;
}
return os;
return mapbox::util::optional<Value>();
}
GeometryCollection VectorTileFeature::getGeometries() const {
pbf data(geometry_pbf);
uint8_t cmd = 1;
uint32_t length = 0;
int32_t x = 0;
int32_t y = 0;
VectorTile::VectorTile() {}
GeometryCollection lines;
lines.emplace_back();
std::vector<Coordinate>* line = &lines.back();
VectorTile::VectorTile(pbf tile) {
while (tile.next()) {
if (tile.tag == 3) { // layer
VectorTileLayer layer(tile.message());
layers.emplace(layer.name, std::forward<VectorTileLayer>(layer));
} else {
tile.skip();
while (data.data < data.end) {
if (length == 0) {
uint32_t cmd_length = data.varint();
cmd = cmd_length & 0x7;
length = cmd_length >> 3;
}
}
}
VectorTile& VectorTile::operator=(VectorTile && other) {
if (this != &other) {
layers.swap(other.layers);
}
return *this;
}
--length;
VectorTileLayer::VectorTileLayer(pbf layer) : data(layer) {
std::vector<std::string> stacks;
if (cmd == 1 || cmd == 2) {
x += data.svarint();
y += data.svarint();
while (layer.next()) {
if (layer.tag == 1) { // name
name = layer.string();
} else if (layer.tag == 3) { // keys
keys.emplace_back(layer.string());
key_index.emplace(keys.back(), keys.size() - 1);
} else if (layer.tag == 4) { // values
values.emplace_back(std::move(parseValue(layer.message())));
} else if (layer.tag == 5) { // extent
extent = layer.varint();
} else {
layer.skip();
}
}
}
FilteredVectorTileLayer::FilteredVectorTileLayer(const VectorTileLayer& layer_, const FilterExpression &filterExpression_)
: layer(layer_),
filterExpression(filterExpression_) {
}
FilteredVectorTileLayer::iterator FilteredVectorTileLayer::begin() const {
return iterator(*this, layer.data);
}
FilteredVectorTileLayer::iterator FilteredVectorTileLayer::end() const {
return iterator(*this, pbf(layer.data.end, 0));
}
FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& parent_, const pbf& data_)
: parent(parent_),
feature(pbf()),
data(data_) {
operator++();
}
VectorTileTagExtractor::VectorTileTagExtractor(const VectorTileLayer &layer) : layer_(layer) {}
void VectorTileTagExtractor::setTags(const pbf &pbf) {
tags_ = pbf;
}
mapbox::util::optional<Value> VectorTileTagExtractor::getValue(const std::string &key) const {
if (key == "$type") {
return Value(uint64_t(type_));
}
mapbox::util::optional<Value> value;
auto field_it = layer_.key_index.find(key);
if (field_it != layer_.key_index.end()) {
const uint32_t filter_key = field_it->second;
// Now loop through all the key/value pair tags.
// tags are packed varints. They should have an even length.
pbf tags_pbf = tags_;
uint32_t tag_key, tag_val;
while (tags_pbf) {
tag_key = tags_pbf.varint();
if (!tags_pbf) {
// This should not happen; otherwise the vector tile is invalid.
fprintf(stderr, "[WARNING] uneven number of feature tag ids\n");
return value;
if (cmd == 1 && !line->empty()) { // moveTo
lines.emplace_back();
line = &lines.back();
}
// Note: We need to run this command in all cases, even if the keys don't match.
tag_val = tags_pbf.varint();
if (tag_key == filter_key) {
if (layer_.values.size() > tag_val) {
value = layer_.values[tag_val];
} else {
fprintf(stderr, "[WARNING] feature references out of range value\n");
break;
}
line->emplace_back(x, y);
} else if (cmd == 7) { // closePolygon
if (!line->empty()) {
line->push_back((*line)[0]);
}
}
}
return value;
}
void VectorTileTagExtractor::setType(FeatureType type) {
type_ = type;
}
template bool mbgl::evaluate(const FilterExpression&, const VectorTileTagExtractor&);
void FilteredVectorTileLayer::iterator::operator++() {
valid = false;
const FilterExpression &expression = parent.filterExpression;
while (data.next(2)) { // feature
feature = data.message();
pbf feature_pbf = feature;
VectorTileTagExtractor extractor(parent.layer);
// Retrieve the basic information
while (feature_pbf.next()) {
if (feature_pbf.tag == 2) { // tags
extractor.setTags(feature_pbf.message());
} else if (feature_pbf.tag == 3) { // geometry type
extractor.setType(FeatureType(feature_pbf.varint()));
} else {
feature_pbf.skip();
}
}
if (evaluate(expression, extractor)) {
valid = true;
return; // data loop
} else {
valid = false;
throw std::runtime_error("unknown command");
}
}
return lines;
}
VectorTile::VectorTile(pbf tile_pbf) {
while (tile_pbf.next()) {
if (tile_pbf.tag == 3) { // layer
util::ptr<VectorTileLayer> layer = std::make_shared<VectorTileLayer>(tile_pbf.message());
layers.emplace(layer->name, layer);
} else {
tile_pbf.skip();
}
}
}
bool FilteredVectorTileLayer::iterator::operator!=(const iterator& other) const {
return !(data.data == other.data.data && data.end == other.data.end && valid == other.valid);
util::ptr<const GeometryTileLayer> VectorTile::getLayer(const std::string& name) const {
auto layer_it = layers.find(name);
if (layer_it != layers.end()) {
return layer_it->second;
}
return nullptr;
}
const pbf& FilteredVectorTileLayer::iterator:: operator*() const {
return feature;
VectorTileLayer::VectorTileLayer(pbf layer_pbf) {
while (layer_pbf.next()) {
if (layer_pbf.tag == 1) { // name
name = layer_pbf.string();
} else if (layer_pbf.tag == 2) { // feature
features.push_back(layer_pbf.message());
} else if (layer_pbf.tag == 3) { // keys
keys.emplace_back(layer_pbf.string());
} else if (layer_pbf.tag == 4) { // values
values.emplace_back(std::move(parseValue(layer_pbf.message())));
} else if (layer_pbf.tag == 5) { // extent
extent = layer_pbf.varint();
} else {
layer_pbf.skip();
}
}
}
util::ptr<const GeometryTileFeature> VectorTileLayer::feature(std::size_t i) const {
return std::make_shared<VectorTileFeature>(features.at(i), *this);
}

View File

@@ -1,118 +1,56 @@
#ifndef MBGL_MAP_VECTOR_TILE
#define MBGL_MAP_VECTOR_TILE
#include <mbgl/style/filter_expression.hpp>
#include <mbgl/style/value.hpp>
#include <mbgl/text/glyph.hpp>
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/util/pbf.hpp>
#include <mbgl/util/optional.hpp>
#include <cstdint>
#include <iosfwd>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
namespace mbgl {
class VectorTileLayer;
enum class FeatureType {
Unknown = 0,
Point = 1,
LineString = 2,
Polygon = 3
};
std::ostream& operator<<(std::ostream&, const FeatureType& type);
class VectorTileFeature {
class VectorTileFeature : public GeometryTileFeature {
public:
VectorTileFeature(pbf feature, const VectorTileLayer& layer);
VectorTileFeature(pbf, const VectorTileLayer&);
FeatureType getType() const override { return type; }
mapbox::util::optional<Value> getValue(const std::string&) const override;
GeometryCollection getGeometries() const override;
private:
uint64_t id = 0;
FeatureType type = FeatureType::Unknown;
std::map<std::string, Value> properties;
pbf geometry;
pbf geometry_pbf;
};
std::ostream& operator<<(std::ostream&, const VectorTileFeature& feature);
class VectorTileTagExtractor {
class VectorTileLayer : public GeometryTileLayer {
public:
VectorTileTagExtractor(const VectorTileLayer &layer);
VectorTileLayer(pbf);
void setTags(const pbf &pbf);
mapbox::util::optional<Value> getValue(const std::string &key) const;
void setType(FeatureType type);
FeatureType getType() const;
std::size_t featureCount() const override { return features.size(); }
util::ptr<const GeometryTileFeature> feature(std::size_t) const override;
private:
const VectorTileLayer &layer_;
pbf tags_;
FeatureType type_ = FeatureType::Unknown;
};
friend class VectorTile;
friend class VectorTileFeature;
/*
* Allows iterating over the features of a VectorTileLayer using a
* BucketDescription as filter. Only features matching the descriptions will
* be returned (as pbf).
*/
class FilteredVectorTileLayer {
public:
class iterator {
public:
iterator(const FilteredVectorTileLayer& filter, const pbf& data);
void operator++();
bool operator!=(const iterator& other) const;
const pbf& operator*() const;
private:
const FilteredVectorTileLayer& parent;
bool valid = false;
pbf feature;
pbf data;
};
public:
FilteredVectorTileLayer(const VectorTileLayer& layer, const FilterExpression &filterExpression);
iterator begin() const;
iterator end() const;
private:
const VectorTileLayer& layer;
const FilterExpression& filterExpression;
};
std::ostream& operator<<(std::ostream&, const PositionedGlyph& placement);
class VectorTileLayer {
public:
VectorTileLayer(pbf data);
const pbf data;
std::string name;
uint32_t extent = 4096;
std::vector<std::string> keys;
std::unordered_map<std::string, uint32_t> key_index;
std::vector<Value> values;
std::map<std::string, std::map<Value, Shaping>> shaping;
std::vector<pbf> features;
};
class VectorTile {
class VectorTile : public GeometryTile {
public:
VectorTile();
VectorTile(pbf data);
VectorTile& operator=(VectorTile&& other);
VectorTile(pbf);
std::map<std::string, const VectorTileLayer> layers;
util::ptr<const GeometryTileLayer> getLayer(const std::string&) const override;
private:
std::map<std::string, util::ptr<const GeometryTileLayer>> layers;
};
}
#endif

View File

@@ -1,17 +1,12 @@
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/geometry/fill_buffer.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/geometry.hpp>
#include <mbgl/renderer/painter.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layout.hpp>
#include <mbgl/map/vector_tile.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/platform/gl.hpp>
#include <cassert>
struct geometry_too_long_exception : std::exception {};
@@ -69,27 +64,16 @@ FillBucket::~FillBucket() {
}
}
void FillBucket::addGeometry(pbf& geom) {
Geometry::command cmd;
Coordinate coord;
Geometry geometry(geom);
int32_t x, y;
while ((cmd = geometry.next(x, y)) != Geometry::end) {
if (cmd == Geometry::move_to) {
if (line.size()) {
clipper.AddPath(line, ClipperLib::ptSubject, true);
line.clear();
hasVertices = true;
}
void FillBucket::addGeometry(const GeometryCollection& geometryCollection) {
for (auto& line_ : geometryCollection) {
for (auto& v : line_) {
line.emplace_back(v.x, v.y);
}
if (line.size()) {
clipper.AddPath(line, ClipperLib::ptSubject, true);
line.clear();
hasVertices = true;
}
line.emplace_back(x, y);
}
if (line.size()) {
clipper.AddPath(line, ClipperLib::ptSubject, true);
line.clear();
hasVertices = true;
}
tessellate();

View File

@@ -2,6 +2,7 @@
#define MBGL_RENDERER_FILLBUCKET
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/fill_buffer.hpp>
#include <mbgl/style/style_bucket.hpp>
@@ -27,7 +28,6 @@ class BucketDescription;
class OutlineShader;
class PlainShader;
class PatternShader;
struct pbf;
class FillBucket : public Bucket {
@@ -49,7 +49,7 @@ public:
const mat4 &matrix) override;
bool hasData() const override;
void addGeometry(pbf& data);
void addGeometry(const GeometryCollection&);
void tessellate();
void drawElements(PlainShader& shader);

View File

@@ -1,12 +1,9 @@
#include <mbgl/renderer/line_bucket.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/geometry.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/renderer/painter.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layout.hpp>
#include <mbgl/map/vector_tile.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/platform/gl.hpp>
@@ -37,28 +34,6 @@ LineBucket::~LineBucket() {
// Do not remove. header file only contains forward definitions to unique pointers.
}
void LineBucket::addGeometry(pbf& geom) {
std::vector<Coordinate> line;
Geometry::command cmd;
Coordinate coord;
Geometry geometry(geom);
int32_t x, y;
while ((cmd = geometry.next(x, y)) != Geometry::end) {
if (cmd == Geometry::move_to) {
if (!line.empty()) {
addGeometry(line);
line.clear();
}
}
line.emplace_back(x, y);
}
if (line.size()) {
addGeometry(line);
}
}
struct TriangleElement {
TriangleElement(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {}
uint16_t a, b, c;
@@ -66,6 +41,12 @@ struct TriangleElement {
typedef uint16_t PointElement;
void LineBucket::addGeometry(const GeometryCollection& geometryCollection) {
for (auto& line : geometryCollection) {
addGeometry(line);
}
}
void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
auto &layout = *styleLayout;
// TODO: use roundLimit

View File

@@ -2,6 +2,7 @@
#define MBGL_RENDERER_LINEBUCKET
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/geometry/vao.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/line_buffer.hpp>
@@ -20,7 +21,6 @@ class LineShader;
class LinejoinShader;
class LineSDFShader;
class LinepatternShader;
struct pbf;
class LineBucket : public Bucket {
typedef ElementGroup<3> triangle_group_type;
@@ -37,7 +37,7 @@ public:
const mat4 &matrix) override;
bool hasData() const override;
void addGeometry(pbf& data);
void addGeometry(const GeometryCollection&);
void addGeometry(const std::vector<Coordinate>& line);
bool hasPoints() const;

View File

@@ -1,10 +1,10 @@
#include <mbgl/style/style_layout.hpp>
#include <mbgl/renderer/symbol_bucket.hpp>
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/style/style_layout.hpp>
#include <mbgl/geometry/text_buffer.hpp>
#include <mbgl/geometry/icon_buffer.hpp>
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/geometry/geometry.hpp>
#include <mbgl/geometry/anchor.hpp>
#include <mbgl/geometry/resample.hpp>
#include <mbgl/renderer/painter.hpp>
@@ -18,6 +18,7 @@
#include <mbgl/util/token.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/merge_lines.hpp>
#include <mbgl/util/std.hpp>
namespace mbgl {
@@ -47,8 +48,8 @@ void SymbolBucket::addGlyphsToAtlas(uint64_t tileid, const std::string stackname
glyphAtlas.addGlyphs(tileid, text, stackname, fontStack,face);
}
std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &layer,
const FilterExpression &filter,
std::vector<SymbolFeature> SymbolBucket::processFeatures(const GeometryTileLayer& layer,
const FilterExpression& filter,
GlyphStore &glyphStore,
const Sprite &sprite) {
auto &layout = *styleLayout;
@@ -64,14 +65,22 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
// Determine and load glyph ranges
std::set<GlyphRange> ranges;
FilteredVectorTileLayer filtered_layer(layer, filter);
for (const pbf &feature_pbf : filtered_layer) {
const VectorTileFeature feature{feature_pbf, layer};
for (std::size_t i = 0; i < layer.featureCount(); i++) {
auto feature = layer.feature(i);
GeometryTileFeatureExtractor extractor(*feature);
if (!evaluate(filter, extractor))
continue;
SymbolFeature ft;
auto getValue = [&feature](const std::string& key) -> std::string {
auto value = feature->getValue(key);
return value ? toString(*value) : std::string();
};
if (has_text) {
std::string u8string = util::replaceTokens(layout.text.field, feature.properties);
std::string u8string = util::replaceTokens(layout.text.field, getValue);
if (layout.text.transform == TextTransformType::Uppercase) {
u8string = platform::uppercase(u8string);
@@ -90,25 +99,19 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
}
if (has_icon) {
ft.sprite = util::replaceTokens(layout.icon.image, feature.properties);
ft.sprite = util::replaceTokens(layout.icon.image, getValue);
}
if (ft.label.length() || ft.sprite.length()) {
auto &multiline = ft.geometry;
// Decode line
Geometry::command cmd;
pbf geom(feature.geometry);
Geometry geometry(geom);
bool first = true;
int32_t x, y;
while ((cmd = geometry.next(x, y)) != Geometry::end) {
if (first || cmd == Geometry::move_to) {
multiline.emplace_back();
first = false;
GeometryCollection geometryCollection = feature->getGeometries();
for (auto& line : geometryCollection) {
multiline.emplace_back();
for (auto& point : line) {
multiline.back().emplace_back(point.x, point.y);
}
multiline.back().emplace_back(x, y);
}
features.push_back(std::move(ft));
@@ -125,7 +128,8 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
return features;
}
void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpression &filter,
void SymbolBucket::addFeatures(const GeometryTileLayer& layer,
const FilterExpression& filter,
const Tile::ID &id, SpriteAtlas &spriteAtlas, Sprite &sprite,
GlyphAtlas & glyphAtlas, GlyphStore &glyphStore) {
auto &layout = *styleLayout;

View File

@@ -2,14 +2,15 @@
#define MBGL_RENDERER_SYMBOLBUCKET
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/geometry/vao.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/text_buffer.hpp>
#include <mbgl/geometry/icon_buffer.hpp>
#include <mbgl/map/vector_tile.hpp>
#include <mbgl/text/types.hpp>
#include <mbgl/text/glyph.hpp>
#include <mbgl/style/style_bucket.hpp>
#include <mbgl/util/ptr.hpp>
#include <memory>
#include <map>
@@ -64,9 +65,13 @@ public:
bool hasTextData() const;
bool hasIconData() const;
void addFeatures(const VectorTileLayer &layer, const FilterExpression &filter,
const Tile::ID &id, SpriteAtlas &spriteAtlas, Sprite &sprite,
GlyphAtlas &glyphAtlas, GlyphStore &glyphStore);
void addFeatures(const GeometryTileLayer&,
const FilterExpression&,
const Tile::ID&,
SpriteAtlas&,
Sprite&,
GlyphAtlas&,
GlyphStore&);
void addGlyphs(const PlacedGlyphs &glyphs, float placementZoom, PlacementRange placementRange,
float zoom);
@@ -76,13 +81,13 @@ public:
void drawIcons(IconShader& shader);
private:
std::vector<SymbolFeature> processFeatures(const VectorTileLayer &layer, const FilterExpression &filter, GlyphStore &glyphStore, const Sprite &sprite);
std::vector<SymbolFeature> processFeatures(const GeometryTileLayer&,
const FilterExpression&,
GlyphStore&,
const Sprite&);
void addFeature(const std::vector<Coordinate> &line, const Shaping &shaping, const GlyphPositions &face, const Rect<uint16_t> &image);
// Adds placed items to the buffer.
template <typename Buffer, typename GroupType>
void addSymbols(Buffer &buffer, const PlacedGlyphs &symbols, float scale, PlacementRange placementRange);

View File

@@ -1,4 +1,4 @@
#include <mbgl/map/vector_tile.hpp>
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/platform/log.hpp>
namespace mbgl {

View File

@@ -38,14 +38,6 @@ std::string replaceTokens(const std::string &source, const Lookup &lookup) {
return result;
}
template <typename T>
inline std::string replaceTokens(const std::string &source, const std::map<std::string, T> &properties) {
return replaceTokens(source, [&properties](const std::string &token) -> std::string {
const auto it_prop = properties.find(token);
return it_prop != properties.end() ? toString(it_prop->second) : "";
});
}
} // end namespace util
} // end namespace mbgl