Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
refs #928: 90% of way to genericizing VectorTile
Browse files Browse the repository at this point in the history
  • Loading branch information
incanus committed Mar 3, 2015
1 parent e1ff75a commit b3dab61
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 148 deletions.
29 changes: 29 additions & 0 deletions src/mbgl/map/geometry_tile.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/style/filter_expression_private.hpp>

#include <iostream>

using namespace mbgl;

std::ostream& mbgl::operator<<(std::ostream& os, const GeometryFeatureType& type) {
switch (type) {
case GeometryFeatureType::Unknown: return os << "Unknown";
case GeometryFeatureType::Point: return os << "Point";
case GeometryFeatureType::LineString: return os << "LineString";
case GeometryFeatureType::Polygon: return os << "Polygon";
default: return os << "Invalid";
}
}

GeometryTile& GeometryTile::operator=(GeometryTile&& other) {
if (this != &other) {
layers.swap(other.layers);
}
return *this;
}

template <typename T>
GeometryFilteredTileLayer<T>::iterator::iterator(const GeometryFilteredTileLayer<T>& parent_)
: parent(parent_) {
operator++();
}
105 changes: 105 additions & 0 deletions src/mbgl/map/geometry_tile.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#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 <cstdint>
#include <iosfwd>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>

namespace mbgl {

class GeometryTileLayer;

enum class GeometryFeatureType {
Unknown = 0,
Point = 1,
LineString = 2,
Polygon = 3
};

std::ostream& operator<<(std::ostream&, const GeometryFeatureType& type);

template <typename T>
class GeometryTileFeature {
public:
uint64_t id = 0;
GeometryFeatureType type = GeometryFeatureType::Unknown;
std::map<std::string, Value> properties;
T geometries;
};

template <typename T>
std::ostream& operator<<(std::ostream&, const GeometryTileFeature<T>& feature);

template <typename T>
class GeometryTileTagExtractor {
public:
GeometryTileTagExtractor(const GeometryTileLayer&);

void setTags(const T&);
virtual mapbox::util::optional<Value> getValue(const std::string &key) const;
inline void setType(GeometryFeatureType type_) { type = type_; }
GeometryFeatureType getType() const { return type; }

protected:
const GeometryTileLayer &layer;
GeometryFeatureType type = GeometryFeatureType::Unknown;
};


template <typename T>
class GeometryFilteredTileLayer {
public:
class iterator {
public:
iterator(const GeometryFilteredTileLayer&);
virtual void operator++();
virtual bool operator!=(const iterator& other) const;
virtual const T& operator*() const;

protected:
const GeometryFilteredTileLayer& parent;
bool valid = false;
};

public:
GeometryFilteredTileLayer(const GeometryTileLayer&, const FilterExpression&);

iterator begin() const;
iterator end() const;

public:
const GeometryTileLayer& layer;
const FilterExpression& filterExpression;
};

std::ostream& operator<<(std::ostream&, const PositionedGlyph&);

class GeometryTileLayer {
public:
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;
};

class GeometryTile {
public:
GeometryTile& operator=(GeometryTile&& other);

public:
std::map<std::string, const GeometryTileLayer> layers;
};

}

#endif
114 changes: 42 additions & 72 deletions src/mbgl/map/vector_tile.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
#include <mbgl/map/vector_tile.hpp>
#include <mbgl/style/filter_expression_private.hpp>

#include <algorithm>
#include <iostream>
#include <ostream>

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
Expand All @@ -43,28 +31,23 @@ VectorTileFeature::VectorTileFeature(pbf feature, const VectorTileLayer& layer)
}
}
} else if (feature.tag == 3) { // type
type = (FeatureType)feature.varint();
type = (GeometryFeatureType)feature.varint();
} else if (feature.tag == 4) { // geometry
geometry = feature.message();
geometries = feature.message();
} else {
feature.skip();
}
}
}


std::ostream& mbgl::operator<<(std::ostream& os, const VectorTileFeature& feature) {
std::ostream& mbgl::operator<<(std::ostream& os, const GeometryTileFeature<pbf>& 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() {}


VectorTile::VectorTile(pbf tile) {
while (tile.next()) {
if (tile.tag == 3) { // layer
Expand All @@ -76,16 +59,7 @@ VectorTile::VectorTile(pbf tile) {
}
}

VectorTile& VectorTile::operator=(VectorTile && other) {
if (this != &other) {
layers.swap(other.layers);
}
return *this;
}

VectorTileLayer::VectorTileLayer(pbf layer) : data(layer) {
std::vector<std::string> stacks;

VectorTileLayer::VectorTileLayer(pbf layer) : layer_pbf(layer) {
while (layer.next()) {
if (layer.tag == 1) { // name
name = layer.string();
Expand All @@ -102,61 +76,61 @@ VectorTileLayer::VectorTileLayer(pbf layer) : data(layer) {
}
}

FilteredVectorTileLayer::FilteredVectorTileLayer(const VectorTileLayer& layer_, const FilterExpression &filterExpression_)
: layer(layer_),
filterExpression(filterExpression_) {
}
FilteredVectorTileLayer::FilteredVectorTileLayer(const VectorTileLayer& layer_, const FilterExpression& filterExpression_)
: GeometryFilteredTileLayer<pbf>(layer_, filterExpression_) {}

FilteredVectorTileLayer::iterator FilteredVectorTileLayer::begin() const {
return iterator(*this, layer.data);
const VectorTileLayer *layer_ = static_cast<const VectorTileLayer *>(&layer);

return FilteredVectorTileLayer::iterator(*this, layer_->layer_pbf);
}

FilteredVectorTileLayer::iterator FilteredVectorTileLayer::end() const {
return iterator(*this, pbf(layer.data.end, 0));
}
const VectorTileLayer *layer_ = static_cast<const VectorTileLayer *>(&layer);

FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& parent_, const pbf& data_)
: parent(parent_),
feature(pbf()),
data(data_) {
operator++();
return FilteredVectorTileLayer::iterator(*this, pbf(layer_->layer_pbf.end, 0));
}

VectorTileTagExtractor::VectorTileTagExtractor(const VectorTileLayer &layer) : layer_(layer) {}
FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& parent_, const pbf& data_pbf_)
: GeometryFilteredTileLayer<pbf>::iterator(parent_),
feature_pbf(pbf()),
data_pbf(data_pbf_) {}

VectorTileTagExtractor::VectorTileTagExtractor(const VectorTileLayer& layer_)
: GeometryTileTagExtractor(layer_) {}

void VectorTileTagExtractor::setTags(const pbf &pbf) {
tags_ = pbf;
void VectorTileTagExtractor::setTags(const pbf& pbf) {
tags_pbf = pbf;
}

mapbox::util::optional<Value> VectorTileTagExtractor::getValue(const std::string &key) const {
mapbox::util::optional<Value> VectorTileTagExtractor::getValue(const std::string& key) const {
if (key == "$type") {
return Value(uint64_t(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()) {
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_;
pbf tags_pbf_ = tags_pbf;
uint32_t tag_key, tag_val;
while (tags_pbf) {
tag_key = tags_pbf.varint();
if (!tags_pbf) {
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;
}
// Note: We need to run this command in all cases, even if the keys don't match.
tag_val = tags_pbf.varint();
tag_val = tags_pbf_.varint();

if (tag_key == filter_key) {
if (layer_.values.size() > tag_val) {
value = layer_.values[tag_val];
if (layer.values.size() > tag_val) {
value = layer.values[tag_val];
} else {
fprintf(stderr, "[WARNING] feature references out of range value\n");
break;
Expand All @@ -168,31 +142,27 @@ mapbox::util::optional<Value> VectorTileTagExtractor::getValue(const std::string
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;
while (data_pbf.next(2)) { // feature
feature_pbf = data_pbf.message();
pbf feature_pbf_ = feature_pbf;

VectorTileTagExtractor extractor(parent.layer);
GeometryTileTagExtractor<pbf> extractor(parent.layer);

// Retrieve the basic information
while (feature_pbf.next()) {
if (feature_pbf.tag == 2) { // tags
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 if (feature_pbf_.tag == 3) { // geometry type
extractor.setType(GeometryFeatureType(feature_pbf_.varint()));
} else {
feature_pbf.skip();
feature_pbf_.skip();
}
}

Expand All @@ -206,9 +176,9 @@ void FilteredVectorTileLayer::iterator::operator++() {
}

bool FilteredVectorTileLayer::iterator::operator!=(const iterator& other) const {
return !(data.data == other.data.data && data.end == other.data.end && valid == other.valid);
return !(data_pbf.data == other.data_pbf.data && data_pbf.end == other.data_pbf.end && valid == other.valid);
}

const pbf& FilteredVectorTileLayer::iterator:: operator*() const {
return feature;
return feature_pbf;
}
Loading

0 comments on commit b3dab61

Please sign in to comment.