cf89d56ac Release 1.1.0 6defc33ea Update changelog 8480ce447 Use basic_pbf_builder to make buffer type configurable 25fbe0caf Travis: Disable test that fails with out of memory error f6741c19a Travis: Test on different architectures 598031339 Explicitly return 0 or 1 in example code, don't use std::exit dd8d315ea Remove virtual inheritance in builder f8511cc9e Fix another unused variable 4002414f0 Switch to catch2 for testing 9bb27a31f Avoid unused variable warning b04163da6 Use std::array instead of C array 4701b6a57 Make string non-const so the return doesn't copy 454f7d711 Fix clang-tidy config 6105d7a62 "Modernize" travis config 7fefbf932 Use try/catch in main() b3a62df21 Various fixes based on clang-tidy reports 83f784641 Use uppercase letters for numeric literals 23fd5f5c9 CMake config: Also look for newer clang-tidy versions 25ba7a7f6 Remove unnecessary ref qualifier f1cc1728a Doxygen: Remove config settings not available in newer versions 0a0afc97d Fix doc. 630dc80bc fix docs e022ba387 Call commit on finished features. 5d3f6eaf9 Remember version in layer_builder_impl. Add accessor functions. bc9d5f977 Remove comment that doesn't apply (any more). e1618d063 Update appveyor config to use more recent visual studio version. e6f9e3e62 Remove unnecessary workaround in Appveyor config. e1df3894c Remove xcode6.4 build soon to be removed from travis. 808a7b6a1 Release 1.0.3 d4faa2fb0 catch exceptions in vtzero-stats 291572505 Add overload of copy_properties function using a property_manager. 189caf4b8 Use new copy_id() function in advanced documentation. 184bb33e1 Add feature::for_each_property_indexes() member function. 3e296a36f Bugfix: Wrong iterator was checked in assert. 1115c0910 Update submodule to use newest mvt-fixtures. f32e73893 Explicitly initialize member (needed by older GCCs). 8d37928ca More tests. bf68443be Add copy_properties() helper function to feature builders. 96ed8cbd7 Add copy_id() helper function to builders. b166fcc3a Document that layer class uses mutable. 8609cdf96 Add missing word 3484299f2 Release 1.0.2 6d3dd8940 Bugfix: layer_builder::add_feature() now commits features it adds. 8da72723f Update links in change log. git-subtree-dir: third_party/vtzero git-subtree-split: cf89d56ac22eee0a252aab8d2e87344e4ce73d70
113 lines
5.2 KiB
Markdown
113 lines
5.2 KiB
Markdown
|
|
# Advanced vtzero topics
|
|
|
|
## Differences between the protocol buffer specification and the vtzero implementation
|
|
|
|
The [protobuf specification
|
|
says](https://developers.google.com/protocol-buffers/docs/encoding#optional)
|
|
that a decoder library must handle repeated *non-packed* fields if repeated
|
|
*packed* fields are expected and it must handle multiple repeated packed fields
|
|
as if the items are concatenated. Encoders should never encode fields in this
|
|
way, though, so it is very unlikely that this would ever happen. For
|
|
performance reasons vtzero doesn't handle this case.
|
|
|
|
## Differences between the vector tile specification and the vtzero implementation
|
|
|
|
The [vector tile specification](https://github.com/mapbox/vector-tile-spec/blob/master/2.1/README.md#41-layers)
|
|
clearly says that you can not have two layers with the same
|
|
name in a vector tile. For performance reasons this is neither checked on
|
|
reading nor on writing.
|
|
|
|
## The `create_vtzero_point` customization point
|
|
|
|
The vtzero builder classes have several functions which take a `vtzero::point`
|
|
as argument. But chances are that you are using a different point type in your
|
|
code. That's why these functions have overloads taking any type `TPoint` that
|
|
can be converted to a `vtzero::point`. This conversion is done by calling the
|
|
function `create_vtzero_point()`. Vtzero supplies a version of this function
|
|
which will work with any type with members `x` and `y`:
|
|
|
|
```cpp
|
|
template <typename TPoint>
|
|
vtzero::point create_vtzero_point(TPoint p) noexcept {
|
|
return {p.x, p.y};
|
|
}
|
|
```
|
|
|
|
You can define your own overload of that function taking your own point type
|
|
as parameter and returning a `vtzero::point`. Vtzero will find your function
|
|
using [ADL](http://en.cppreference.com/w/cpp/language/adl) which magically
|
|
makes the vtzero builders work with your point type.
|
|
|
|
## Using the `property_mapper` class when copying layers
|
|
|
|
Sometimes you want to copy some features of a layer into a new layer. Because
|
|
you only copy some features (and/or only some properties of the features), the
|
|
key and value tables in the layer have to be rebuilt. This is where the
|
|
`property_mapper` class helps you. It keeps the mapping between the index
|
|
values of the old and the new table adding property keys and values as needed
|
|
to the new table.
|
|
|
|
Here is some code that shows you how to use it:
|
|
|
|
```cpp
|
|
#include <vtzero/property_mapper.hpp> // you have to include this
|
|
|
|
vtzero::layer layer = ...; // layer you got from an existing tile
|
|
vtzero::layer_builder layer_builder{...}; // create new layer
|
|
|
|
// instantiate the property mapper with the old and new layers
|
|
vtzero::property_mapper mapper{layer, layer_builder};
|
|
|
|
// you'll probably want to iterate over all features in the old layer...
|
|
while (auto feature = layer.next_feature()) {
|
|
// ... and decide somehow which ones you want to keep
|
|
if (keep_feature(feature)) {
|
|
// instantiate a feature builder as usual and copy id and geometry
|
|
vtzero::geometry_feature_builder feature_builder{layer_builder};
|
|
feature_builder.copy_id(feature);
|
|
feature_builder.set_geometry(feature.geometry());
|
|
|
|
// now iterate over all properties...
|
|
while (auto idxs = feature.next_property_indexes()) {
|
|
// ... decide which ones to keep,
|
|
if (keep_property(idxs)) {
|
|
// ... and add them to the new layer using the mapper
|
|
feature_builder.add_property(mapper(idxs));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Protection against huge memory use
|
|
|
|
When decoding a vector tile we got from an unknown source, we don't know what
|
|
surprises it might contain. Building data structures based on the vector tile
|
|
sometimes means we have to allocate memory and in the worst case this might be
|
|
quite a lot of memory. Vtzero usually doesn't allocate any memory when decoding
|
|
a tile, except when reading properties, when there is space for lookup tables
|
|
allocated. The memory use for these lookup tables is `sizeof(data_view)` times
|
|
the number of entries in the key/value table. In the worst case, when a vector
|
|
tile basically only contains such a table, memory use is proportional to the
|
|
size of the vector tile. But memory use can be an order of magnitude larger
|
|
than the tile size! If you are concerned about memory use, limit the size
|
|
of the vector tiles you give to vtzero.
|
|
|
|
When reading geometries from vector tiles, vtzero doesn't need much memory
|
|
itself, but the users of vtzero might. In a typical case you might reserve
|
|
enough memory to store, say, a linestring, and then fill that memory. To allow
|
|
you to do this, vtzero tells you about the number of points in the linestring.
|
|
This number comes from the tile and it might be rather large. Vtzero does a
|
|
consistency check comparing the number of points the geometry says it has with
|
|
the number of bytes used for the geometry and it will throw an exception if the
|
|
numbers can't fit. So you are protected against tiny tiles pretending to
|
|
contain a huge geometry. But there still could be a medium-sized tile which
|
|
gets "blown up" into a huge memory hog. Your representation of a linestring
|
|
can be an order of magnitude larger than the minimum 2 bytes per point
|
|
needed in the encoded tile.
|
|
|
|
So again: If you are concerned about memory use, limit the size of the vector
|
|
tiles you give to vtzero.
|
|
|