diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | cmake/benchmark.cmake | 1 | ||||
-rw-r--r-- | cmake/core.cmake | 1 | ||||
-rw-r--r-- | src/mbgl/tile/vector_tile.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/tile/vector_tile_data.cpp | 252 | ||||
-rw-r--r-- | src/mbgl/tile/vector_tile_data.hpp | 57 |
6 files changed, 65 insertions, 252 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b62efb7d20..e84b3a6da2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ mason_use(polylabel VERSION 1.0.2 HEADER_ONLY) mason_use(wagyu VERSION 0.4.1 HEADER_ONLY) mason_use(shelf-pack VERSION 2.1.0 HEADER_ONLY) mason_use(cheap-ruler VERSION 2.5.1 HEADER_ONLY) +mason_use(vector-tile VERSION 1.0.0-rc6 HEADER_ONLY) add_definitions(-DRAPIDJSON_HAS_STDSTRING=1) diff --git a/cmake/benchmark.cmake b/cmake/benchmark.cmake index 174d0bc19c..f4c59fa01e 100644 --- a/cmake/benchmark.cmake +++ b/cmake/benchmark.cmake @@ -20,6 +20,7 @@ target_link_libraries(mbgl-benchmark target_add_mason_package(mbgl-benchmark PRIVATE benchmark) target_add_mason_package(mbgl-benchmark PRIVATE rapidjson) target_add_mason_package(mbgl-benchmark PRIVATE protozero) +target_add_mason_package(mbgl-benchmark PRIVATE vector-tile) mbgl_platform_benchmark() diff --git a/cmake/core.cmake b/cmake/core.cmake index 5671ab53b5..c4e4d2abc7 100644 --- a/cmake/core.cmake +++ b/cmake/core.cmake @@ -27,6 +27,7 @@ target_add_mason_package(mbgl-core PRIVATE protozero) target_add_mason_package(mbgl-core PRIVATE polylabel) target_add_mason_package(mbgl-core PRIVATE wagyu) target_add_mason_package(mbgl-core PRIVATE shelf-pack) +target_add_mason_package(mbgl-core PRIVATE vector-tile) mbgl_platform_core() diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp index 0e13b78a7d..e2e700b7b7 100644 --- a/src/mbgl/tile/vector_tile.cpp +++ b/src/mbgl/tile/vector_tile.cpp @@ -3,16 +3,13 @@ #include <mbgl/tile/tile_loader_impl.hpp> #include <mbgl/renderer/tile_parameters.hpp> -#include <memory> - namespace mbgl { VectorTile::VectorTile(const OverscaledTileID& id_, std::string sourceID_, const TileParameters& parameters, const Tileset& tileset) - : GeometryTile(id_, sourceID_, parameters), - loader(*this, id_, parameters, tileset) { + : GeometryTile(id_, sourceID_, parameters), loader(*this, id_, parameters, tileset) { } void VectorTile::setNecessity(Necessity necessity) { diff --git a/src/mbgl/tile/vector_tile_data.cpp b/src/mbgl/tile/vector_tile_data.cpp index 5eb199f482..bb8392f6d9 100644 --- a/src/mbgl/tile/vector_tile_data.cpp +++ b/src/mbgl/tile/vector_tile_data.cpp @@ -3,170 +3,78 @@ namespace mbgl { -Value parseValue(protozero::pbf_reader data) { - Value value; - while (data.next()) { - switch (data.tag()) { - case 1: // string_value - value = data.get_string(); - break; - case 2: // float_value - value = static_cast<double>(data.get_float()); - break; - case 3: // double_value - value = data.get_double(); - break; - case 4: // int_value - value = data.get_int64(); - break; - case 5: // uint_value - value = data.get_uint64(); - break; - case 6: // sint_value - value = data.get_sint64(); - break; - case 7: // bool_value - value = data.get_bool(); - break; - default: - data.skip(); - break; - } - } - return value; +VectorTileFeature::VectorTileFeature(const mapbox::vector_tile::layer& layer, + const protozero::data_view& view) + : feature(view, layer) { } -VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, std::shared_ptr<VectorTileLayerData> layerData_) - : layerData(std::move(layerData_)) { - while (feature_pbf.next()) { - switch (feature_pbf.tag()) { - case 1: // id - id = { feature_pbf.get_uint64() }; - break; - case 2: // tags - tags_iter = feature_pbf.get_packed_uint32(); - break; - case 3: // type - type = static_cast<FeatureType>(feature_pbf.get_enum()); - break; - case 4: // geometry - geometry_iter = feature_pbf.get_packed_uint32(); - break; - default: - feature_pbf.skip(); - break; - } +FeatureType VectorTileFeature::getType() const { + switch (feature.getType()) { + case mapbox::vector_tile::GeomType::POINT: + return FeatureType::Point; + case mapbox::vector_tile::GeomType::LINESTRING: + return FeatureType::LineString; + case mapbox::vector_tile::GeomType::POLYGON: + return FeatureType::Polygon; + default: + return FeatureType::Unknown; } } optional<Value> VectorTileFeature::getValue(const std::string& key) const { - auto keyIter = layerData->keysMap.find(key); - if (keyIter == layerData->keysMap.end()) { - return optional<Value>(); - } - - auto start_itr = tags_iter.begin(); - const auto & end_itr = tags_iter.end(); - while (start_itr != end_itr) { - auto tag_key = static_cast<uint32_t>(*start_itr++); - - if (layerData->keysMap.size() <= tag_key) { - throw std::runtime_error("feature referenced out of range key"); - } - - if (start_itr == end_itr) { - throw std::runtime_error("uneven number of feature tag ids"); - } - - auto tag_val = static_cast<uint32_t>(*start_itr++);; - if (layerData->values.size() <= tag_val) { - throw std::runtime_error("feature referenced out of range value"); - } - - if (tag_key == keyIter->second) { - return layerData->values[tag_val]; - } - } - - return optional<Value>(); + return feature.getValue(key); } -std::unordered_map<std::string,Value> VectorTileFeature::getProperties() const { - std::unordered_map<std::string,Value> properties; - auto start_itr = tags_iter.begin(); - const auto & end_itr = tags_iter.end(); - while (start_itr != end_itr) { - auto tag_key = static_cast<uint32_t>(*start_itr++); - if (start_itr == end_itr) { - throw std::runtime_error("uneven number of feature tag ids"); - } - auto tag_val = static_cast<uint32_t>(*start_itr++); - properties[layerData->keys.at(tag_key)] = layerData->values.at(tag_val); - } - return properties; +std::unordered_map<std::string, Value> VectorTileFeature::getProperties() const { + return feature.getProperties(); } optional<FeatureIdentifier> VectorTileFeature::getID() const { - return id; + return feature.getID(); } GeometryCollection VectorTileFeature::getGeometries() const { - uint8_t cmd = 1; - uint32_t length = 0; - int32_t x = 0; - int32_t y = 0; - const float scale = float(util::EXTENT) / layerData->extent; - - GeometryCollection lines; - - lines.emplace_back(); - GeometryCoordinates* line = &lines.back(); - - auto g_itr = geometry_iter.begin(); - while (g_itr != geometry_iter.end()) { - if (length == 0) { - auto cmd_length = static_cast<uint32_t>(*g_itr++); - cmd = cmd_length & 0x7; - length = cmd_length >> 3; - } - - --length; - - if (cmd == 1 || cmd == 2) { - x += protozero::decode_zigzag32(static_cast<uint32_t>(*g_itr++)); - y += protozero::decode_zigzag32(static_cast<uint32_t>(*g_itr++)); - - if (cmd == 1 && !line->empty()) { // moveTo - lines.emplace_back(); - line = &lines.back(); - } + const float scale = float(util::EXTENT) / feature.getExtent(); + auto lines = feature.getGeometries<GeometryCollection>(scale); + if (feature.getVersion() >= 2 || feature.getType() != mapbox::vector_tile::GeomType::POLYGON) { + return lines; + } else { + return fixupPolygons(lines); + } +} - line->emplace_back(::round(x * scale), ::round(y * scale)); +VectorTileLayer::VectorTileLayer(std::shared_ptr<const std::string> data_, + const protozero::data_view& view) + : data(std::move(data_)), layer(view) { +} - } else if (cmd == 7) { // closePolygon - if (!line->empty()) { - line->push_back((*line)[0]); - } +std::size_t VectorTileLayer::featureCount() const { + return layer.featureCount(); +} - } else { - throw std::runtime_error("unknown command"); - } - } +std::unique_ptr<GeometryTileFeature> VectorTileLayer::getFeature(std::size_t i) const { + return std::make_unique<VectorTileFeature>(layer, layer.getFeature(i)); +} - if (layerData->version >= 2 || type != FeatureType::Polygon) { - return lines; - } +std::string VectorTileLayer::getName() const { + return layer.getName(); +} - return fixupPolygons(lines); +VectorTileData::VectorTileData(std::shared_ptr<const std::string> data_) : data(std::move(data_)) { } -VectorTileData::VectorTileData(std::shared_ptr<const std::string> data_) - : data(std::move(data_)) { +std::unique_ptr<GeometryTileData> VectorTileData::clone() const { + return std::make_unique<VectorTileData>(data); } const GeometryTileLayer* VectorTileData::getLayer(const std::string& name) const { if (!parsed) { - parse(); + // We're parsing this lazily so that we can construct VectorTileData objects on the main + // thread without incurring the overhead of parsing immediately. + for (const auto& pair : mapbox::vector_tile::buffer(*data).getLayers()) { + layers.emplace(pair.first, VectorTileLayer{ data, pair.second }); + } + parsed = true; } auto it = layers.find(name); @@ -177,71 +85,7 @@ const GeometryTileLayer* VectorTileData::getLayer(const std::string& name) const } std::vector<std::string> VectorTileData::layerNames() const { - if (!parsed) { - parse(); - } - - std::vector<std::string> names; - names.reserve(layers.size()); - for (auto const& layer : layers) { - names.emplace_back(layer.first); - } - return names; -} - -void VectorTileData::parse() const { - parsed = true; - layers.clear(); - protozero::pbf_reader tile_pbf(*data); - while (tile_pbf.next(3)) { - VectorTileLayer layer(tile_pbf.get_message(), data); - layers.emplace(layer.name, std::move(layer)); - } -} - -VectorTileLayerData::VectorTileLayerData(std::shared_ptr<const std::string> pbfData) : - data(std::move(pbfData)) -{} - -VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf, std::shared_ptr<const std::string> pbfData) - : data(std::make_shared<VectorTileLayerData>(std::move(pbfData))) -{ - while (layer_pbf.next()) { - switch (layer_pbf.tag()) { - case 1: // name - name = layer_pbf.get_string(); - break; - case 2: // feature - features.push_back(layer_pbf.get_message()); - break; - case 3: // keys - { - auto iter = data->keysMap.emplace(layer_pbf.get_string(), data->keysMap.size()); - data->keys.emplace_back(std::reference_wrapper<const std::string>(iter.first->first)); - } - break; - case 4: // values - data->values.emplace_back(parseValue(layer_pbf.get_message())); - break; - case 5: // extent - data->extent = layer_pbf.get_uint32(); - break; - case 15: // version - data->version = layer_pbf.get_uint32(); - break; - default: - layer_pbf.skip(); - break; - } - } -} - -std::unique_ptr<GeometryTileFeature> VectorTileLayer::getFeature(std::size_t i) const { - return std::make_unique<VectorTileFeature>(features.at(i), data); -} - -std::string VectorTileLayer::getName() const { - return name; + return mapbox::vector_tile::buffer(*data).layerNames(); } } // namespace mbgl diff --git a/src/mbgl/tile/vector_tile_data.hpp b/src/mbgl/tile/vector_tile_data.hpp index 57b42ecd19..5ecb591273 100644 --- a/src/mbgl/tile/vector_tile_data.hpp +++ b/src/mbgl/tile/vector_tile_data.hpp @@ -1,5 +1,6 @@ #include <mbgl/tile/geometry_tile_data.hpp> +#include <mapbox/vector_tile.hpp> #include <protozero/pbf_reader.hpp> #include <unordered_map> @@ -8,75 +9,43 @@ namespace mbgl { -class VectorTileLayer; - -using packed_iter_type = protozero::iterator_range<protozero::pbf_reader::const_uint32_iterator>; - -struct VectorTileLayerData { - VectorTileLayerData(std::shared_ptr<const std::string>); - - // Hold a reference to the underlying pbf data that backs the lazily-built - // components of the owning VectorTileLayer and VectorTileFeature objects - std::shared_ptr<const std::string> data; - - uint32_t version = 1; - uint32_t extent = 4096; - std::unordered_map<std::string, uint32_t> keysMap; - std::vector<std::reference_wrapper<const std::string>> keys; - std::vector<Value> values; -}; - class VectorTileFeature : public GeometryTileFeature { public: - VectorTileFeature(protozero::pbf_reader, std::shared_ptr<VectorTileLayerData> layerData); + VectorTileFeature(const mapbox::vector_tile::layer&, const protozero::data_view&); - FeatureType getType() const override { return type; } - optional<Value> getValue(const std::string&) const override; - std::unordered_map<std::string,Value> getProperties() const override; + FeatureType getType() const override; + optional<Value> getValue(const std::string& key) const override; + std::unordered_map<std::string, Value> getProperties() const override; optional<FeatureIdentifier> getID() const override; GeometryCollection getGeometries() const override; private: - std::shared_ptr<VectorTileLayerData> layerData; - optional<FeatureIdentifier> id; - FeatureType type = FeatureType::Unknown; - packed_iter_type tags_iter; - packed_iter_type geometry_iter; + mapbox::vector_tile::feature feature; }; class VectorTileLayer : public GeometryTileLayer { public: - VectorTileLayer(protozero::pbf_reader, std::shared_ptr<const std::string>); + VectorTileLayer(std::shared_ptr<const std::string> data, const protozero::data_view&); - std::size_t featureCount() const override { return features.size(); } - std::unique_ptr<GeometryTileFeature> getFeature(std::size_t) const override; + std::size_t featureCount() const override; + std::unique_ptr<GeometryTileFeature> getFeature(std::size_t i) const override; std::string getName() const override; private: - friend class VectorTileData; - friend class VectorTileFeature; - - std::string name; - std::vector<protozero::pbf_reader> features; - std::shared_ptr<VectorTileLayerData> data; + std::shared_ptr<const std::string> data; + mapbox::vector_tile::layer layer; }; class VectorTileData : public GeometryTileData { public: VectorTileData(std::shared_ptr<const std::string> data); - std::unique_ptr<GeometryTileData> clone() const override { - return std::make_unique<VectorTileData>(*this); - } - - const GeometryTileLayer* getLayer(const std::string&) const override; + std::unique_ptr<GeometryTileData> clone() const override; + const GeometryTileLayer* getLayer(const std::string& name) const override; std::vector<std::string> layerNames() const; private: - void parse() const; - -private: std::shared_ptr<const std::string> data; mutable bool parsed = false; mutable std::unordered_map<std::string, VectorTileLayer> layers; |