parse feature objects so that we can access all tags

This commit is contained in:
Konstantin Käfer
2014-03-11 16:36:21 +01:00
parent 117078270d
commit a26ddf8bce
5 changed files with 128 additions and 15 deletions

View File

@@ -65,10 +65,10 @@ public:
void parseStyleLayers(const VectorTile& tile, const std::vector<LayerDescription>& layers);
std::shared_ptr<Bucket> createBucket(const VectorTile& tile, const BucketDescription& bucket_desc);
template <class Bucket> void addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, 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);
std::shared_ptr<Bucket> createTextBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createFillBucket(const VectorTile& tile, const VectorTileLayer& layer, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createLineBucket(const VectorTile& tile, const VectorTileLayer& layer, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createPointBucket(const VectorTile& tile, const VectorTileLayer& layer, const BucketDescription& bucket_desc);
std::shared_ptr<Bucket> createTextBucket(const VectorTile& tile, const VectorTileLayer& layer, const BucketDescription& bucket_desc);
void cancel();

View File

@@ -33,6 +33,27 @@ struct Coordinate {
}
};
enum class FeatureType {
Unknown = 0,
Point = 1,
LineString = 2,
Polygon = 3
};
std::ostream& operator<<(std::ostream&, const FeatureType& type);
class VectorTileFeature {
public:
VectorTileFeature(pbf feature, const VectorTileLayer& layer);
uint64_t id = 0;
FeatureType type = FeatureType::Unknown;
std::map<std::string, Value> properties;
pbf geometry;
};
std::ostream& operator<<(std::ostream&, const VectorTileFeature& feature);
/*
* Allows iterating over the features of a VectorTileLayer using a
* BucketDescription as filter. Only features matching the descriptions will

View File

@@ -12,7 +12,8 @@ enum class BucketType {
None = 0,
Fill = 1,
Line = 2,
Point = 3
Point = 3,
Text = 4
};
enum class CapType {

View File

@@ -14,6 +14,7 @@
#include <llmr/util/string.hpp>
#include <chrono>
#include <iostream>
using namespace llmr;
@@ -85,7 +86,7 @@ bool TileData::parse() {
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;
// double parse_time = (platform::time() - parse_time_start) * 1000.0;
if (state == State::obsolete) {
// fprintf(stderr, "[%p] parsing [%d/%d/%d] cancelled after %8.3fms\n", this, id.z, id.x, id.y, parse_time);
} else {
@@ -148,11 +149,13 @@ std::shared_ptr<Bucket> TileData::createBucket(const VectorTile& tile, const Buc
if (layer_it != tile.layers.end()) {
const VectorTileLayer& layer = layer_it->second;
if (bucket_desc.type == BucketType::Fill) {
return createFillBucket(layer, bucket_desc);
return createFillBucket(tile, layer, bucket_desc);
} else if (bucket_desc.type == BucketType::Line) {
return createLineBucket(layer, bucket_desc);
return createLineBucket(tile, layer, bucket_desc);
} else if (bucket_desc.type == BucketType::Point) {
return createPointBucket(layer, bucket_desc);
return createPointBucket(tile, layer, bucket_desc);
} else if (bucket_desc.type == BucketType::Text) {
return createTextBucket(tile, layer, bucket_desc);
} else {
// TODO: create other bucket types.
}
@@ -178,26 +181,52 @@ void TileData::addBucketFeatures(Bucket& bucket, const VectorTileLayer& layer, c
}
}
std::shared_ptr<Bucket> TileData::createFillBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<Bucket> TileData::createFillBucket(const VectorTile& tile, const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<FillBucket> bucket = std::make_shared<FillBucket>(fillVertexBuffer, triangleElementsBuffer, lineElementsBuffer, bucket_desc);
addBucketFeatures(bucket, layer, bucket_desc);
return state == State::obsolete ? nullptr : bucket;
}
std::shared_ptr<Bucket> TileData::createLineBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<Bucket> TileData::createLineBucket(const VectorTile& tile, const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<LineBucket> bucket = std::make_shared<LineBucket>(lineVertexBuffer, triangleElementsBuffer, pointElementsBuffer, bucket_desc);
addBucketFeatures(bucket, layer, bucket_desc);
return state == State::obsolete ? nullptr : bucket;
}
std::shared_ptr<Bucket> TileData::createPointBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<Bucket> TileData::createPointBucket(const VectorTile& tile, const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<PointBucket> bucket = std::make_shared<PointBucket>(pointVertexBuffer, bucket_desc);
addBucketFeatures(bucket, layer, bucket_desc);
return state == State::obsolete ? nullptr : bucket;
}
std::shared_ptr<Bucket> TileData::createTextBucket(const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
std::shared_ptr<Bucket> TileData::createTextBucket(const VectorTile& tile, const VectorTileLayer& layer, const BucketDescription& bucket_desc) {
// Determine the correct text stack.
if (!layer.shaping.size()) {
return nullptr;
}
// TODO: currently hardcoded to use the first font stack.
const std::map<Value, std::vector<VectorTilePlacement>>& stack = layer.shaping.begin()->second;
std::vector<const VectorTileFace *> faces;
for (const std::string& face : layer.faces) {
auto it = tile.faces.find(face);
if (it == tile.faces.end()) {
// This layer references an unknown face.
return nullptr;
}
faces.push_back(&it->second);
}
std::shared_ptr<TextBucket> bucket = std::make_shared<TextBucket>(textVertexBuffer, triangleElementsBuffer, bucket_desc);
addBucketFeatures(bucket, layer, bucket_desc);
return state == State::obsolete ? nullptr : bucket;
FilteredVectorTileLayer filtered_layer(layer, bucket_desc);
for (pbf feature_pbf : filtered_layer) {
if (state == State::obsolete) return nullptr;
const VectorTileFeature feature(feature_pbf, layer);
std::cerr << feature;
}
return bucket;
}

View File

@@ -6,6 +6,68 @@
using namespace llmr;
std::ostream& llmr::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
// tags are packed varints. They should have an even length.
pbf tags = feature.message();
while (tags) {
uint32_t tag_key = tags.varint();
if (layer.keys.size() <= tag_key) {
// TODO: Throw correct exception
fprintf(stderr, "feature referenced out of range key\n");
break;
}
if (tags) {
uint32_t tag_val = tags.varint();
if (layer.values.size() <= tag_val) {
// TODO: Throw correct exception
fprintf(stderr, "feature referenced out of range value\n");
break;
}
properties.emplace(layer.keys[tag_key], layer.values[tag_val]);
} else {
// TODO: Throw correct exception
fprintf(stderr, "uneven number of feature tag ids\n");
break;
}
}
} else if (feature.tag == 3) { // type
type = (FeatureType)feature.varint();
} else if (feature.tag == 4) { // geometry
geometry = feature.message();
} else {
feature.skip();
}
}
}
std::ostream& llmr::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;
}
return os;
}
VectorTile::VectorTile() {}