rename Tile to TileData

This commit is contained in:
Konstantin Käfer
2014-03-04 17:53:16 +01:00
parent ba5070bf52
commit b0ddabd6ac
8 changed files with 352 additions and 325 deletions

View File

@@ -2,6 +2,7 @@
#define LLMR_MAP_MAP
#include <llmr/map/tile.hpp>
#include <llmr/map/tile_data.hpp>
#include <llmr/map/transform.hpp>
#include <llmr/style/style.hpp>
#include <llmr/renderer/painter.hpp>
@@ -64,8 +65,8 @@ private:
bool findLoadedChildren(const Tile::ID& id, int32_t maxCoveringZoom, std::forward_list<Tile::ID>& retain);
bool findLoadedParent(const Tile::ID& id, int32_t minCoveringZoom, std::forward_list<Tile::ID>& retain);
bool updateTiles();
std::shared_ptr<Tile> addTile(const Tile::ID& id);
std::shared_ptr<Tile> hasTile(const Tile::ID& id);
std::shared_ptr<TileData> addTile(const Tile::ID& id);
std::shared_ptr<TileData> hasTile(const Tile::ID& id);
void update();
@@ -81,8 +82,8 @@ private:
float pixel_ratio;
std::forward_list<std::shared_ptr<Tile>> tiles;
std::forward_list<std::shared_ptr<Tile>> historic_tiles;
std::forward_list<std::shared_ptr<TileData>> tiles;
std::forward_list<std::shared_ptr<TileData>> historic_tiles;
};
}

View File

@@ -2,104 +2,19 @@
#define LLMR_MAP_TILE
#include <llmr/util/vec.hpp>
#include <llmr/util/mat4.hpp>
#include <llmr/util/noncopyable.hpp>
#include <llmr/geometry/debug_font_buffer.hpp>
#include <llmr/geometry/vao.hpp>
#include <llmr/platform/platform.hpp>
#include <cstdint>
#include <forward_list>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <atomic>
namespace llmr {
class Style;
class Bucket;
class LayerDescription;
class BucketDescription;
class VectorTile;
class VectorTileLayer;
class FillVertexBuffer;
class LineVertexBuffer;
class PointVertexBuffer;
class TriangleElementsBuffer;
class LineElementsBuffer;
class PointElementsBuffer;
class PlainShader;
class Tile : public std::enable_shared_from_this<Tile>,
private util::noncopyable {
class Tile {
public:
struct exception : std::exception {};
struct geometry_too_long_exception : exception {};
public:
typedef std::shared_ptr<Tile> Ptr;
typedef vec3<int32_t> ID;
enum state {
initial,
loading,
loaded,
parsed,
obsolete
};
public:
Tile(ID id, const Style& style);
~Tile();
// Start loading the tile.
void request();
// Other functions
bool parse();
void parseStyleLayers(const VectorTile& tile, const std::vector<LayerDescription>& layers);
std::shared_ptr<Bucket> createBucket(const VectorTile& tile, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createFillBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createLineBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createPointBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc);
void cancel();
const std::string toString() const;
static ID parent(const ID& id, int32_t z);
static std::forward_list<ID> children(const ID& id, int32_t z);
public:
const ID id;
uint8_t clip_id;
std::atomic<state> state;
// Holds the actual geometries in this tile.
DebugFontBuffer debugFontBuffer;
VertexArrayObject debugFontArray;
std::shared_ptr<FillVertexBuffer> fillVertexBuffer;
std::shared_ptr<LineVertexBuffer> lineVertexBuffer;
std::shared_ptr<PointVertexBuffer> pointVertexBuffer;
std::shared_ptr<TriangleElementsBuffer> triangleElementsBuffer;
std::shared_ptr<LineElementsBuffer> lineElementsBuffer;
std::shared_ptr<PointElementsBuffer> pointElementsBuffer;
// Holds the buckets of this tile.
// They contain the location offsets in the buffers stored above
std::map<std::string, std::shared_ptr<Bucket>> buckets;
mat4 matrix;
private:
// Source data
std::string data;
const Style& style;
platform::Request *req = nullptr;
};
}

View File

@@ -0,0 +1,103 @@
#ifndef LLMR_MAP_TILE_DATA
#define LLMR_MAP_TILE_DATA
#include <llmr/map/tile.hpp>
#include <llmr/util/vec.hpp>
#include <llmr/util/mat4.hpp>
#include <llmr/util/noncopyable.hpp>
#include <llmr/geometry/debug_font_buffer.hpp>
#include <llmr/geometry/vao.hpp>
#include <llmr/platform/platform.hpp>
#include <cstdint>
#include <forward_list>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <atomic>
namespace llmr {
class Style;
class Bucket;
class LayerDescription;
class BucketDescription;
class VectorTile;
class VectorTileLayer;
class FillVertexBuffer;
class LineVertexBuffer;
class PointVertexBuffer;
class TriangleElementsBuffer;
class LineElementsBuffer;
class PointElementsBuffer;
class PlainShader;
class TileData : public std::enable_shared_from_this<TileData>,
private util::noncopyable {
public:
struct exception : std::exception {};
struct geometry_too_long_exception : exception {};
public:
typedef std::shared_ptr<TileData> Ptr;
enum state {
initial,
loading,
loaded,
parsed,
obsolete
};
public:
TileData(Tile::ID id, const Style& style);
~TileData();
// Start loading the tile.
void request();
// Other functions
bool parse();
void parseStyleLayers(const VectorTile& tile, const std::vector<LayerDescription>& layers);
std::shared_ptr<Bucket> createBucket(const VectorTile& tile, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createFillBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createLineBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createPointBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc);
void cancel();
const std::string toString() const;
public:
const Tile::ID id;
uint8_t clip_id;
std::atomic<state> state;
// Holds the actual geometries in this tile.
DebugFontBuffer debugFontBuffer;
VertexArrayObject debugFontArray;
std::shared_ptr<FillVertexBuffer> fillVertexBuffer;
std::shared_ptr<LineVertexBuffer> lineVertexBuffer;
std::shared_ptr<PointVertexBuffer> pointVertexBuffer;
std::shared_ptr<TriangleElementsBuffer> triangleElementsBuffer;
std::shared_ptr<LineElementsBuffer> lineElementsBuffer;
std::shared_ptr<PointElementsBuffer> pointElementsBuffer;
// Holds the buckets of this tile.
// They contain the location offsets in the buffers stored above
std::map<std::string, std::shared_ptr<Bucket>> buckets;
mat4 matrix;
private:
// Source data
std::string data;
const Style& style;
platform::Request *req = nullptr;
};
}
#endif

View File

@@ -1,7 +1,7 @@
#ifndef LLMR_RENDERER_PAINTER
#define LLMR_RENDERER_PAINTER
#include <llmr/map/tile.hpp>
#include <llmr/map/tile_data.hpp>
#include <llmr/geometry/vao.hpp>
#include <llmr/geometry/vertex_buffer.hpp>
#include <llmr/util/mat4.hpp>
@@ -33,7 +33,7 @@ public:
void setup();
void clear();
void changeMatrix();
void render(const std::shared_ptr<Tile>& tile);
void render(const std::shared_ptr<TileData>& tile);
void renderMatte();
void renderBackground();
void renderFill(FillBucket& bucket, const std::string& layer_name, const Tile::ID& id);
@@ -45,8 +45,8 @@ public:
void finishClippingMask();
private:
void setupShaders();
void renderLayers(const std::shared_ptr<Tile>& tile, const std::vector<LayerDescription>& layers);
void renderDebug(const std::shared_ptr<Tile>& tile);
void renderLayers(const std::shared_ptr<TileData>& tile, const std::vector<LayerDescription>& layers);
void renderDebug(const std::shared_ptr<TileData>& tile);
void useProgram(uint32_t program);
void lineWidth(float lineWidth);

View File

@@ -238,22 +238,22 @@ void Map::update() {
}
Tile::Ptr Map::hasTile(const Tile::ID& id) {
for (Tile::Ptr& tile : tiles) {
TileData::Ptr Map::hasTile(const Tile::ID& id) {
for (TileData::Ptr& tile : tiles) {
if (tile->id == id) {
return tile;
}
}
return Tile::Ptr();
return TileData::Ptr();
}
Tile::Ptr Map::addTile(const Tile::ID& id) {
Tile::Ptr tile = hasTile(id);
TileData::Ptr Map::addTile(const Tile::ID& id) {
TileData::Ptr tile = hasTile(id);
if (!tile.get()) {
// We couldn't find the tile in the list. Create a new one.
tile = std::make_shared<Tile>(id, style);
tile = std::make_shared<TileData>(id, style);
assert(tile);
// std::cerr << "init " << id.z << "/" << id.x << "/" << id.y << std::endl;
// std::cerr << "add " << tile->toString() << std::endl;
@@ -278,8 +278,8 @@ bool Map::findLoadedChildren(const Tile::ID& id, int32_t maxCoveringZoom, std::f
auto ids = Tile::children(id, z + 1);
for (const Tile::ID& child_id : ids) {
const Tile::Ptr& tile = hasTile(child_id);
if (tile && tile->state == Tile::parsed) {
const TileData::Ptr& tile = hasTile(child_id);
if (tile && tile->state == TileData::parsed) {
assert(tile);
retain.emplace_front(tile->id);
} else {
@@ -305,8 +305,8 @@ bool Map::findLoadedChildren(const Tile::ID& id, int32_t maxCoveringZoom, std::f
bool Map::findLoadedParent(const Tile::ID& id, int32_t minCoveringZoom, std::forward_list<Tile::ID>& retain) {
for (int32_t z = id.z - 1; z >= minCoveringZoom; --z) {
const Tile::ID parent_id = Tile::parent(id, z);
const Tile::Ptr tile = hasTile(parent_id);
if (tile && tile->state == Tile::parsed) {
const TileData::Ptr tile = hasTile(parent_id);
if (tile && tile->state == TileData::parsed) {
assert(tile);
retain.emplace_front(tile->id);
return true;
@@ -344,10 +344,10 @@ bool Map::updateTiles() {
// Add existing child/parent tiles if the actual tile is not yet loaded
for (const Tile::ID& id : required) {
Tile::Ptr tile = addTile(id);
TileData::Ptr tile = addTile(id);
assert(tile);
if (tile->state != Tile::parsed) {
if (tile->state != TileData::parsed) {
// The tile we require is not yet loaded. Try to find a parent or
// child tile that we already have.
@@ -362,7 +362,7 @@ bool Map::updateTiles() {
}
}
if (tile->state == Tile::initial) {
if (tile->state == TileData::initial) {
// If the tile is new, we have to make sure to load it.
tile->request();
changed = true;
@@ -371,7 +371,7 @@ bool Map::updateTiles() {
// Remove tiles that we definitely don't need, i.e. tiles that are not on
// the required list.
tiles.remove_if([&retain, &changed](const Tile::Ptr& tile) {
tiles.remove_if([&retain, &changed](const TileData::Ptr& tile) {
assert(tile);
bool obsolete = std::find(retain.begin(), retain.end(), tile->id) == retain.end();
if (obsolete) {
@@ -384,7 +384,7 @@ bool Map::updateTiles() {
// Sort tiles by zoom level, front to back.
// We're painting front-to-back, so we want to draw more detailed tiles first
// before filling in other parts with lower zoom levels.
tiles.sort([](const Tile::Ptr& a, const Tile::Ptr& b) {
tiles.sort([](const TileData::Ptr& a, const TileData::Ptr& b) {
return a->id.z > b->id.z;
});
@@ -406,9 +406,9 @@ bool Map::render() {
// the stencil buffer.
uint8_t i = 1;
painter.prepareClippingMask();
for (Tile::Ptr& tile : tiles) {
for (TileData::Ptr& tile : tiles) {
assert(tile);
if (tile->state == Tile::parsed) {
if (tile->state == TileData::parsed) {
// The position matrix.
transform.matrixFor(tile->matrix, tile->id);
matrix::multiply(tile->matrix, painter.projMatrix, tile->matrix);
@@ -418,8 +418,8 @@ bool Map::render() {
}
painter.finishClippingMask();
for (Tile::Ptr& tile : tiles) {
if (tile->state == Tile::parsed) {
for (TileData::Ptr& tile : tiles) {
if (tile->state == TileData::parsed) {
painter.render(tile);
}
}

View File

@@ -1,18 +1,6 @@
#include <llmr/map/tile.hpp>
#include <llmr/style/style.hpp>
#include <llmr/map/vector_tile.hpp>
#include <llmr/geometry/fill_buffer.hpp>
#include <llmr/geometry/line_buffer.hpp>
#include <llmr/geometry/point_buffer.hpp>
#include <llmr/geometry/elements_buffer.hpp>
#include <llmr/renderer/fill_bucket.hpp>
#include <llmr/renderer/line_bucket.hpp>
#include <llmr/renderer/point_bucket.hpp>
#include <llmr/util/pbf.hpp>
#include <llmr/util/string.hpp>
#include <chrono>
#include <cassert>
using namespace llmr;
@@ -41,198 +29,3 @@ std::forward_list<Tile::ID> Tile::children(const ID& id, int32_t z) {
return children;
}
Tile::Tile(ID id, const Style& style)
: id(id),
state(initial),
fillVertexBuffer(std::make_shared<FillVertexBuffer>()),
lineVertexBuffer(std::make_shared<LineVertexBuffer>()),
pointVertexBuffer(std::make_shared<PointVertexBuffer>()),
triangleElementsBuffer(std::make_shared<TriangleElementsBuffer>()),
lineElementsBuffer(std::make_shared<LineElementsBuffer>()),
pointElementsBuffer(std::make_shared<PointElementsBuffer>()),
style(style) {
// Initialize tile debug coordinates
char coord[32];
snprintf(coord, sizeof(coord), "%d/%d/%d", id.z, id.x, id.y);
debugFontBuffer.addText(coord, 50, 200, 5);
}
Tile::~Tile() {
}
const std::string Tile::toString() const {
return util::sprintf("[tile %d/%d/%d]", id.z, id.x, id.y);
}
void Tile::request() {
state = Tile::loading;
// Create http request
std::string url = util::sprintf(kTileURL,
id.z, id.x, id.y);
// Note: Somehow this feels slower than the change to request_http()
std::shared_ptr<Tile> tile = shared_from_this();
platform::Request *request = platform::request_http(url, [=](platform::Response& res) {
if (res.code == 200 && tile->state != obsolete) {
tile->state = Tile::loaded;
tile->data.swap(res.body);
tile->parse();
} else if (tile->state != obsolete) {
fprintf(stderr, "tile loading failed\n");
}
}, []() {
platform::restart();
});
req = request;
}
void Tile::cancel() {
// TODO: thread safety
if (state != obsolete) {
state = obsolete;
platform::cancel_request_http(req);
} else {
assert((!"logic error? multiple cancelleations"));
}
}
bool Tile::parse() {
// std::lock_guard<std::mutex> lock(mtx);
if (state != loaded) {
return false;
}
try {
VectorTile tile(pbf((const uint8_t *)data.data(), data.size()));
parseStyleLayers(tile, style.layers);
} catch (const std::exception& ex) {
fprintf(stderr, "[%p] exception [%d/%d/%d]... failed: %s\n", this, id.z, id.x, id.y, ex.what());
cancel();
return false;
}
if (state == obsolete) {
return false;
} else {
state = parsed;
}
return true;
}
void Tile::parseStyleLayers(const VectorTile& tile, const std::vector<LayerDescription>& layers) {
for (const LayerDescription& layer_desc : layers) {
if (layer_desc.child_layer.size()) {
// This is a layer group.
// TODO: create framebuffer
parseStyleLayers(tile, layer_desc.child_layer);
// TODO: render framebuffer on previous framebuffer
} else {
// This is a singular layer. Check if this bucket already exists. If not,
// parse this bucket.
auto bucket_it = buckets.find(layer_desc.bucket_name);
if (bucket_it == buckets.end()) {
auto bucket_it = style.buckets.find(layer_desc.bucket_name);
if (bucket_it != style.buckets.end()) {
// Only create the new bucket if we have an actual specification
// for it.
std::shared_ptr<Bucket> bucket = createBucket(tile, bucket_it->second);
if (bucket) {
// Bucket creation might fail because the data tile may not
// contain any data that falls into this bucket.
buckets[layer_desc.bucket_name] = bucket;
}
} else {
// There is no proper specification for this bucket, even though
// it is referenced in the stylesheet.
fprintf(stderr, "Stylesheet specifies bucket %s, but it is not defined\n", layer_desc.bucket_name.c_str());
}
}
}
}
}
std::shared_ptr<Bucket> Tile::createBucket(const VectorTile& tile, const BucketDescription& bucket_desc) {
auto layer_it = tile.layers.find(bucket_desc.source_layer);
if (layer_it != tile.layers.end()) {
const VectorTileLayer& layer = layer_it->second;
if (bucket_desc.type == BucketType::Fill) {
return createFillBucket(layer, bucket_desc);
} else if (bucket_desc.type == BucketType::Line) {
return createLineBucket(layer, bucket_desc);
} else if (bucket_desc.type == BucketType::Point) {
return createPointBucket(layer, bucket_desc);
} else {
// TODO: create other bucket types.
}
} else {
// The layer specified in the bucket does not exist. Do nothing.
}
return nullptr;
}
std::shared_ptr<Bucket> Tile::createFillBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<FillBucket> bucket = std::make_shared<FillBucket>(fillVertexBuffer, triangleElementsBuffer, lineElementsBuffer, bucket_desc);
// auto init_start = std::chrono::high_resolution_clock::now();
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (pbf feature : filtered_layer) {
while (feature.next(4)) { // geometry
pbf geometry_pbf = feature.message();
if (geometry_pbf) {
bucket->addGeometry(geometry_pbf);
bucket->tessellate();
}
}
}
// auto init_end = std::chrono::high_resolution_clock::now();
// auto init = (double)std::chrono::duration_cast<std::chrono::microseconds>(init_end - init_start).count() / 1000.0;
// auto tess_start = std::chrono::high_resolution_clock::now();
// auto tess_end = std::chrono::high_resolution_clock::now();
// auto tess = (double)std::chrono::duration_cast<std::chrono::microseconds>(tess_end - tess_start).count() / 1000.0;
// fprintf(stderr, "%s/%s init: %f tess: %f\n", bucket_desc.source_layer.c_str(), bucket_desc.source_field.c_str(), init, tess);
return bucket;
}
std::shared_ptr<Bucket> Tile::createLineBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<LineBucket> bucket = std::make_shared<LineBucket>(lineVertexBuffer, triangleElementsBuffer, pointElementsBuffer, bucket_desc);
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (pbf feature : filtered_layer) {
while (feature.next(4)) { // geometry
pbf geometry_pbf = feature.message();
if (geometry_pbf) {
bucket->addGeometry(geometry_pbf);
}
}
}
return bucket;
}
std::shared_ptr<Bucket> Tile::createPointBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<PointBucket> bucket = std::make_shared<PointBucket>(pointVertexBuffer, bucket_desc);
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (pbf feature : filtered_layer) {
while (feature.next(4)) { // geometry
pbf geometry_pbf = feature.message();
if (geometry_pbf) {
bucket->addGeometry(geometry_pbf);
}
}
}
return bucket;
}

215
src/map/tile_data.cpp Normal file
View File

@@ -0,0 +1,215 @@
#include <llmr/map/tile_data.hpp>
#include <llmr/style/style.hpp>
#include <llmr/map/vector_tile.hpp>
#include <llmr/geometry/fill_buffer.hpp>
#include <llmr/geometry/line_buffer.hpp>
#include <llmr/geometry/point_buffer.hpp>
#include <llmr/geometry/elements_buffer.hpp>
#include <llmr/renderer/fill_bucket.hpp>
#include <llmr/renderer/line_bucket.hpp>
#include <llmr/renderer/point_bucket.hpp>
#include <llmr/util/pbf.hpp>
#include <llmr/util/string.hpp>
#include <chrono>
using namespace llmr;
TileData::TileData(Tile::ID id, const Style& style)
: id(id),
state(initial),
fillVertexBuffer(std::make_shared<FillVertexBuffer>()),
lineVertexBuffer(std::make_shared<LineVertexBuffer>()),
pointVertexBuffer(std::make_shared<PointVertexBuffer>()),
triangleElementsBuffer(std::make_shared<TriangleElementsBuffer>()),
lineElementsBuffer(std::make_shared<LineElementsBuffer>()),
pointElementsBuffer(std::make_shared<PointElementsBuffer>()),
style(style) {
// Initialize tile debug coordinates
char coord[32];
snprintf(coord, sizeof(coord), "%d/%d/%d", id.z, id.x, id.y);
debugFontBuffer.addText(coord, 50, 200, 5);
}
TileData::~TileData() {
}
const std::string TileData::toString() const {
return util::sprintf("[tile %d/%d/%d]", id.z, id.x, id.y);
}
void TileData::request() {
state = loading;
// Create http request
std::string url = util::sprintf(kTileURL,
id.z, id.x, id.y);
// Note: Somehow this feels slower than the change to request_http()
std::shared_ptr<TileData> tile = shared_from_this();
platform::Request *request = platform::request_http(url, [=](platform::Response& res) {
if (res.code == 200 && tile->state != obsolete) {
tile->state = loaded;
tile->data.swap(res.body);
tile->parse();
} else if (tile->state != obsolete) {
fprintf(stderr, "tile loading failed\n");
}
}, []() {
platform::restart();
});
req = request;
}
void TileData::cancel() {
if (state != obsolete) {
state = obsolete;
platform::cancel_request_http(req);
} else {
assert((!"logic error? multiple cancelleations"));
}
}
bool TileData::parse() {
if (state != loaded) {
return false;
}
try {
double parse_time_start = platform::time();
VectorTile tile(pbf((const uint8_t *)data.data(), data.size()));
parseStyleLayers(tile, style.layers);
double parse_time = (platform::time() - parse_time_start) * 1000.0;
if (state == obsolete) {
fprintf(stderr, "[%p] parsing [%d/%d/%d] cancelled after %8.3fms\n", this, id.z, id.x, id.y, parse_time);
} else {
fprintf(stderr, "[%p] parsing [%d/%d/%d] took %8.3fms\n", this, id.z, id.x, id.y, parse_time);
}
} catch (const std::exception& ex) {
fprintf(stderr, "[%p] exception [%d/%d/%d]... failed: %s\n", this, id.z, id.x, id.y, ex.what());
cancel();
return false;
}
if (state == obsolete) {
return false;
} else {
state = parsed;
}
return true;
}
void TileData::parseStyleLayers(const VectorTile& tile, const std::vector<LayerDescription>& layers) {
for (const LayerDescription& layer_desc : layers) {
// Cancel early when parsing.
if (state == obsolete) {
return;
}
if (layer_desc.child_layer.size()) {
// This is a layer group.
// TODO: create framebuffer
parseStyleLayers(tile, layer_desc.child_layer);
// TODO: render framebuffer on previous framebuffer
} else {
// This is a singular layer. Check if this bucket already exists. If not,
// parse this bucket.
auto bucket_it = buckets.find(layer_desc.bucket_name);
if (bucket_it == buckets.end()) {
auto bucket_it = style.buckets.find(layer_desc.bucket_name);
if (bucket_it != style.buckets.end()) {
// Only create the new bucket if we have an actual specification
// for it.
std::shared_ptr<Bucket> bucket = createBucket(tile, bucket_it->second);
if (bucket) {
// Bucket creation might fail because the data tile may not
// contain any data that falls into this bucket.
buckets[layer_desc.bucket_name] = bucket;
}
} else {
// There is no proper specification for this bucket, even though
// it is referenced in the stylesheet.
fprintf(stderr, "Stylesheet specifies bucket %s, but it is not defined\n", layer_desc.bucket_name.c_str());
}
}
}
}
}
std::shared_ptr<Bucket> TileData::createBucket(const VectorTile& tile, const BucketDescription& bucket_desc) {
auto layer_it = tile.layers.find(bucket_desc.source_layer);
if (layer_it != tile.layers.end()) {
const VectorTileLayer& layer = layer_it->second;
if (bucket_desc.type == BucketType::Fill) {
return createFillBucket(layer, bucket_desc);
} else if (bucket_desc.type == BucketType::Line) {
return createLineBucket(layer, bucket_desc);
} else if (bucket_desc.type == BucketType::Point) {
return createPointBucket(layer, bucket_desc);
} else {
// TODO: create other bucket types.
}
} else {
// The layer specified in the bucket does not exist. Do nothing.
}
return nullptr;
}
std::shared_ptr<Bucket> TileData::createFillBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<FillBucket> bucket = std::make_shared<FillBucket>(fillVertexBuffer, triangleElementsBuffer, lineElementsBuffer, bucket_desc);
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (pbf feature : filtered_layer) {
if (state == obsolete) return nullptr;
while (feature.next(4)) { // geometry
pbf geometry_pbf = feature.message();
if (geometry_pbf) {
bucket->addGeometry(geometry_pbf);
bucket->tessellate();
}
}
}
return bucket;
}
std::shared_ptr<Bucket> TileData::createLineBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<LineBucket> bucket = std::make_shared<LineBucket>(lineVertexBuffer, triangleElementsBuffer, pointElementsBuffer, bucket_desc);
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (pbf feature : filtered_layer) {
if (state == obsolete) return nullptr;
while (feature.next(4)) { // geometry
pbf geometry_pbf = feature.message();
if (geometry_pbf) {
bucket->addGeometry(geometry_pbf);
}
}
}
return bucket;
}
std::shared_ptr<Bucket> TileData::createPointBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<PointBucket> bucket = std::make_shared<PointBucket>(pointVertexBuffer, bucket_desc);
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (pbf feature : filtered_layer) {
if (state == obsolete) return nullptr;
while (feature.next(4)) { // geometry
pbf geometry_pbf = feature.message();
if (geometry_pbf) {
bucket->addGeometry(geometry_pbf);
}
}
}
return bucket;
}

View File

@@ -130,8 +130,8 @@ void Painter::clear() {
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Painter::render(const Tile::Ptr& tile) {
if (tile->state != Tile::parsed) {
void Painter::render(const TileData::Ptr& tile) {
if (tile->state != TileData::parsed) {
return;
}
@@ -147,7 +147,7 @@ void Painter::render(const Tile::Ptr& tile) {
renderBackground();
}
void Painter::renderLayers(const std::shared_ptr<Tile>& tile, const std::vector<LayerDescription>& layers) {
void Painter::renderLayers(const std::shared_ptr<TileData>& tile, const std::vector<LayerDescription>& layers) {
// Render everything top-to-bottom by using reverse iterators
typedef std::vector<LayerDescription>::const_reverse_iterator iterator;
for (iterator it = layers.rbegin(), end = layers.rend(); it != end; ++it) {
@@ -423,7 +423,7 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co
bucket.drawPoints(*pointShader);
}
void Painter::renderDebug(const Tile::Ptr& tile) {
void Painter::renderDebug(const TileData::Ptr& tile) {
// Disable depth test and don't count this towards the depth buffer,
// but *don't* disable stencil test, as we want to clip the red tile border
// to the tile viewport.