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
572 lines
17 KiB
C++
572 lines
17 KiB
C++
|
|
#include <test.hpp>
|
|
|
|
#include <vtzero/builder.hpp>
|
|
#include <vtzero/index.hpp>
|
|
#include <vtzero/output.hpp>
|
|
#include <vtzero/property_mapper.hpp>
|
|
|
|
#include <protozero/buffer_fixed.hpp>
|
|
#include <protozero/buffer_vector.hpp>
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <type_traits>
|
|
|
|
template <typename T>
|
|
struct movable_not_copyable {
|
|
constexpr static bool value = !std::is_copy_constructible<T>::value &&
|
|
!std::is_copy_assignable<T>::value &&
|
|
std::is_nothrow_move_constructible<T>::value &&
|
|
std::is_nothrow_move_assignable<T>::value;
|
|
};
|
|
|
|
static_assert(movable_not_copyable<vtzero::tile_builder>::value, "tile_builder should be nothrow movable, but not copyable");
|
|
static_assert(movable_not_copyable<vtzero::point_feature_builder>::value, "point_feature_builder should be nothrow movable, but not copyable");
|
|
static_assert(movable_not_copyable<vtzero::linestring_feature_builder>::value, "linestring_feature_builder should be nothrow movable, but not copyable");
|
|
static_assert(movable_not_copyable<vtzero::polygon_feature_builder>::value, "polygon_feature_builder should be nothrow movable, but not copyable");
|
|
static_assert(movable_not_copyable<vtzero::geometry_feature_builder>::value, "geometry_feature_builder should be nothrow movable, but not copyable");
|
|
|
|
TEST_CASE("Create tile from existing layers") {
|
|
const auto buffer = load_test_tile();
|
|
vtzero::vector_tile tile{buffer};
|
|
|
|
vtzero::tile_builder tbuilder;
|
|
|
|
SECTION("add_existing_layer(layer)") {
|
|
while (auto layer = tile.next_layer()) {
|
|
tbuilder.add_existing_layer(layer);
|
|
}
|
|
}
|
|
|
|
SECTION("add_existing_layer(data_view)") {
|
|
while (auto layer = tile.next_layer()) {
|
|
tbuilder.add_existing_layer(layer.data());
|
|
}
|
|
}
|
|
|
|
const std::string data = tbuilder.serialize();
|
|
|
|
REQUIRE(data == buffer);
|
|
}
|
|
|
|
TEST_CASE("Create layer based on existing layer") {
|
|
const auto orig_tile_buffer = load_test_tile();
|
|
vtzero::vector_tile tile{orig_tile_buffer};
|
|
const auto layer = tile.get_layer_by_name("place_label");
|
|
|
|
vtzero::tile_builder tbuilder;
|
|
vtzero::layer_builder lbuilder{tbuilder, layer};
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(42);
|
|
fbuilder.add_point(10, 20);
|
|
fbuilder.commit();
|
|
|
|
std::string data;
|
|
|
|
SECTION("use std::string buffer") {
|
|
data = tbuilder.serialize();
|
|
}
|
|
|
|
SECTION("use std::string buffer as parameter") {
|
|
tbuilder.serialize(data);
|
|
}
|
|
|
|
SECTION("use std::vector<char> buffer as parameter") {
|
|
std::vector<char> buffer;
|
|
tbuilder.serialize(buffer);
|
|
std::copy(buffer.cbegin(), buffer.cend(), std::back_inserter(data));
|
|
}
|
|
|
|
SECTION("use fixed size buffer on stack") {
|
|
std::array<char, 1000> buffer = {{0}};
|
|
protozero::fixed_size_buffer_adaptor adaptor{buffer};
|
|
tbuilder.serialize(adaptor);
|
|
std::copy_n(adaptor.data(), adaptor.size(), std::back_inserter(data));
|
|
}
|
|
|
|
SECTION("use fixed size buffer on heap") {
|
|
std::vector<char> buffer(1000);
|
|
protozero::fixed_size_buffer_adaptor adaptor{buffer};
|
|
tbuilder.serialize(adaptor);
|
|
std::copy_n(adaptor.data(), adaptor.size(), std::back_inserter(data));
|
|
}
|
|
|
|
vtzero::vector_tile new_tile{data};
|
|
const auto new_layer = new_tile.next_layer();
|
|
REQUIRE(std::string(new_layer.name()) == "place_label");
|
|
REQUIRE(new_layer.version() == 1);
|
|
REQUIRE(new_layer.extent() == 4096);
|
|
}
|
|
|
|
TEST_CASE("Create layer and add keys/values") {
|
|
vtzero::tile_builder tbuilder;
|
|
vtzero::layer_builder lbuilder{tbuilder, "name"};
|
|
|
|
const auto ki1 = lbuilder.add_key_without_dup_check("key1");
|
|
const auto ki2 = lbuilder.add_key("key2");
|
|
const auto ki3 = lbuilder.add_key("key1");
|
|
|
|
REQUIRE(ki1 != ki2);
|
|
REQUIRE(ki1 == ki3);
|
|
|
|
const auto vi1 = lbuilder.add_value_without_dup_check(vtzero::encoded_property_value{"value1"});
|
|
vtzero::encoded_property_value value2{"value2"};
|
|
const auto vi2 = lbuilder.add_value_without_dup_check(vtzero::property_value{value2.data()});
|
|
|
|
const auto vi3 = lbuilder.add_value(vtzero::encoded_property_value{"value1"});
|
|
const auto vi4 = lbuilder.add_value(vtzero::encoded_property_value{19});
|
|
const auto vi5 = lbuilder.add_value(vtzero::encoded_property_value{19.0});
|
|
const auto vi6 = lbuilder.add_value(vtzero::encoded_property_value{22});
|
|
vtzero::encoded_property_value nineteen{19};
|
|
const auto vi7 = lbuilder.add_value(vtzero::property_value{nineteen.data()});
|
|
|
|
REQUIRE(vi1 != vi2);
|
|
REQUIRE(vi1 == vi3);
|
|
REQUIRE(vi1 != vi4);
|
|
REQUIRE(vi1 != vi5);
|
|
REQUIRE(vi1 != vi6);
|
|
REQUIRE(vi4 != vi5);
|
|
REQUIRE(vi4 != vi6);
|
|
REQUIRE(vi4 == vi7);
|
|
}
|
|
|
|
TEST_CASE("Committing a feature succeeds after a geometry was added") {
|
|
vtzero::tile_builder tbuilder;
|
|
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
|
|
|
{ // explicit commit after geometry
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(1);
|
|
fbuilder.add_point(10, 10);
|
|
fbuilder.commit();
|
|
}
|
|
|
|
{ // explicit commit after properties
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(2);
|
|
fbuilder.add_point(10, 10);
|
|
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
|
fbuilder.commit();
|
|
}
|
|
|
|
{ // extra commits or rollbacks are okay but no other calls
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(3);
|
|
fbuilder.add_point(10, 10);
|
|
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
|
fbuilder.commit();
|
|
|
|
SECTION("superfluous commit()") {
|
|
fbuilder.commit();
|
|
}
|
|
SECTION("superfluous rollback()") {
|
|
fbuilder.rollback();
|
|
}
|
|
|
|
REQUIRE_THROWS_AS(fbuilder.set_id(10), assert_error);
|
|
REQUIRE_THROWS_AS(fbuilder.add_point(20, 20), assert_error);
|
|
REQUIRE_THROWS_AS(fbuilder.add_property("x", "y"), assert_error);
|
|
}
|
|
|
|
const std::string data = tbuilder.serialize();
|
|
|
|
vtzero::vector_tile tile{data};
|
|
auto layer = tile.next_layer();
|
|
|
|
uint64_t n = 1;
|
|
while (auto feature = layer.next_feature()) {
|
|
REQUIRE(feature.id() == n++);
|
|
}
|
|
|
|
REQUIRE(n == 4);
|
|
}
|
|
|
|
TEST_CASE("Committing a feature fails with assert if no geometry was added") {
|
|
vtzero::tile_builder tbuilder;
|
|
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
|
|
|
SECTION("explicit immediate commit") {
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
REQUIRE_THROWS_AS(fbuilder.commit(), assert_error);
|
|
}
|
|
|
|
SECTION("explicit commit after setting id") {
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(2);
|
|
REQUIRE_THROWS_AS(fbuilder.commit(), assert_error);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Rollback feature") {
|
|
vtzero::tile_builder tbuilder;
|
|
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
|
|
|
{
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(1);
|
|
fbuilder.add_point(10, 10);
|
|
fbuilder.commit();
|
|
}
|
|
|
|
{ // immediate rollback
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(2);
|
|
fbuilder.rollback();
|
|
}
|
|
|
|
{ // rollback after setting id
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(3);
|
|
fbuilder.rollback();
|
|
}
|
|
|
|
{ // rollback after geometry
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(4);
|
|
fbuilder.add_point(20, 20);
|
|
fbuilder.rollback();
|
|
}
|
|
|
|
{ // rollback after properties
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(5);
|
|
fbuilder.add_point(20, 20);
|
|
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
|
fbuilder.rollback();
|
|
}
|
|
|
|
{ // implicit rollback after geometry
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(6);
|
|
fbuilder.add_point(10, 10);
|
|
}
|
|
|
|
{ // implicit rollback after properties
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(7);
|
|
fbuilder.add_point(10, 10);
|
|
fbuilder.add_property("foo", vtzero::encoded_property_value{"bar"});
|
|
}
|
|
|
|
{
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(8);
|
|
fbuilder.add_point(30, 30);
|
|
fbuilder.commit();
|
|
}
|
|
|
|
const std::string data = tbuilder.serialize();
|
|
|
|
vtzero::vector_tile tile{data};
|
|
auto layer = tile.next_layer();
|
|
|
|
auto feature = layer.next_feature();
|
|
REQUIRE(feature.id() == 1);
|
|
|
|
feature = layer.next_feature();
|
|
REQUIRE(feature.id() == 8);
|
|
|
|
feature = layer.next_feature();
|
|
REQUIRE_FALSE(feature);
|
|
}
|
|
|
|
static vtzero::layer next_nonempty_layer(vtzero::vector_tile& tile) {
|
|
while (auto layer = tile.next_layer()) {
|
|
if (layer && !layer.empty()) {
|
|
return layer;
|
|
}
|
|
}
|
|
return vtzero::layer{};
|
|
}
|
|
|
|
static bool vector_tile_equal(const std::string& t1, const std::string& t2) {
|
|
vtzero::vector_tile vt1{t1};
|
|
vtzero::vector_tile vt2{t2};
|
|
|
|
for (auto l1 = next_nonempty_layer(vt1), l2 = next_nonempty_layer(vt2);
|
|
l1 || l2;
|
|
l1 = next_nonempty_layer(vt1), l2 = next_nonempty_layer(vt2)) {
|
|
|
|
if (!l1 ||
|
|
!l2 ||
|
|
l1.version() != l2.version() ||
|
|
l1.extent() != l2.extent() ||
|
|
l1.num_features() != l2.num_features() ||
|
|
l1.name() != l2.name()) {
|
|
return false;
|
|
}
|
|
|
|
for (auto f1 = l1.next_feature(), f2 = l2.next_feature();
|
|
f1 || f2;
|
|
f1 = l1.next_feature(), f2 = l2.next_feature()) {
|
|
if (!f1 ||
|
|
!f2 ||
|
|
f1.id() != f2.id() ||
|
|
f1.geometry_type() != f2.geometry_type() ||
|
|
f1.num_properties() != f2.num_properties() ||
|
|
f1.geometry().data() != f2.geometry().data()) {
|
|
return false;
|
|
}
|
|
for (auto p1 = f1.next_property(), p2 = f2.next_property();
|
|
p1 || p2;
|
|
p1 = f1.next_property(), p2 = f2.next_property()) {
|
|
if (!p1 ||
|
|
!p2 ||
|
|
p1.key() != p2.key() ||
|
|
p1.value() != p2.value()) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
TEST_CASE("vector_tile_equal") {
|
|
REQUIRE(vector_tile_equal("", ""));
|
|
|
|
const auto buffer = load_test_tile();
|
|
REQUIRE(buffer.size() == 269388);
|
|
REQUIRE(vector_tile_equal(buffer, buffer));
|
|
|
|
REQUIRE_FALSE(vector_tile_equal(buffer, ""));
|
|
}
|
|
|
|
TEST_CASE("Copy tile") {
|
|
const auto buffer = load_test_tile();
|
|
vtzero::vector_tile tile{buffer};
|
|
|
|
vtzero::tile_builder tbuilder;
|
|
|
|
while (auto layer = tile.next_layer()) {
|
|
vtzero::layer_builder lbuilder{tbuilder, layer};
|
|
while (auto feature = layer.next_feature()) {
|
|
lbuilder.add_feature(feature);
|
|
}
|
|
}
|
|
|
|
const std::string data = tbuilder.serialize();
|
|
REQUIRE(vector_tile_equal(buffer, data));
|
|
}
|
|
|
|
TEST_CASE("Copy tile using geometry_feature_builder") {
|
|
const auto buffer = load_test_tile();
|
|
vtzero::vector_tile tile{buffer};
|
|
|
|
vtzero::tile_builder tbuilder;
|
|
|
|
while (auto layer = tile.next_layer()) {
|
|
vtzero::layer_builder lbuilder{tbuilder, layer};
|
|
while (auto feature = layer.next_feature()) {
|
|
vtzero::geometry_feature_builder fbuilder{lbuilder};
|
|
fbuilder.copy_id(feature);
|
|
fbuilder.set_geometry(feature.geometry());
|
|
fbuilder.copy_properties(feature);
|
|
fbuilder.commit();
|
|
}
|
|
}
|
|
|
|
const std::string data = tbuilder.serialize();
|
|
REQUIRE(vector_tile_equal(buffer, data));
|
|
}
|
|
|
|
TEST_CASE("Copy tile using geometry_feature_builder and property_mapper") {
|
|
const auto buffer = load_test_tile();
|
|
vtzero::vector_tile tile{buffer};
|
|
|
|
vtzero::tile_builder tbuilder;
|
|
|
|
while (auto layer = tile.next_layer()) {
|
|
vtzero::layer_builder lbuilder{tbuilder, layer};
|
|
vtzero::property_mapper mapper{layer, lbuilder};
|
|
while (auto feature = layer.next_feature()) {
|
|
vtzero::geometry_feature_builder fbuilder{lbuilder};
|
|
fbuilder.copy_id(feature);
|
|
fbuilder.set_geometry(feature.geometry());
|
|
fbuilder.copy_properties(feature, mapper);
|
|
fbuilder.commit();
|
|
}
|
|
}
|
|
|
|
const std::string data = tbuilder.serialize();
|
|
REQUIRE(vector_tile_equal(buffer, data));
|
|
}
|
|
|
|
TEST_CASE("Copy only point geometries using geometry_feature_builder") {
|
|
const auto buffer = load_test_tile();
|
|
vtzero::vector_tile tile{buffer};
|
|
|
|
vtzero::tile_builder tbuilder;
|
|
|
|
int n = 0;
|
|
while (auto layer = tile.next_layer()) {
|
|
vtzero::layer_builder lbuilder{tbuilder, layer};
|
|
while (auto feature = layer.next_feature()) {
|
|
vtzero::geometry_feature_builder fbuilder{lbuilder};
|
|
fbuilder.set_id(feature.id());
|
|
if (feature.geometry().type() == vtzero::GeomType::POINT) {
|
|
fbuilder.set_geometry(feature.geometry());
|
|
while (auto property = feature.next_property()) {
|
|
fbuilder.add_property(property.key(), property.value());
|
|
}
|
|
fbuilder.commit();
|
|
++n;
|
|
} else {
|
|
fbuilder.rollback();
|
|
}
|
|
}
|
|
}
|
|
REQUIRE(n == 17);
|
|
|
|
const std::string data = tbuilder.serialize();
|
|
|
|
n = 0;
|
|
vtzero::vector_tile result_tile{data};
|
|
while (auto layer = result_tile.next_layer()) {
|
|
while (layer.next_feature()) {
|
|
++n;
|
|
}
|
|
}
|
|
|
|
REQUIRE(n == 17);
|
|
}
|
|
|
|
struct points_to_vector {
|
|
|
|
std::vector<vtzero::point> m_points{};
|
|
|
|
void points_begin(const uint32_t count) {
|
|
m_points.reserve(count);
|
|
}
|
|
|
|
void points_point(const vtzero::point point) {
|
|
m_points.push_back(point);
|
|
}
|
|
|
|
void points_end() const {
|
|
}
|
|
|
|
const std::vector<vtzero::point>& result() const {
|
|
return m_points;
|
|
}
|
|
|
|
}; // struct points_to_vector
|
|
|
|
TEST_CASE("Copy only point geometries using point_feature_builder") {
|
|
const auto buffer = load_test_tile();
|
|
vtzero::vector_tile tile{buffer};
|
|
|
|
vtzero::tile_builder tbuilder;
|
|
|
|
int n = 0;
|
|
while (auto layer = tile.next_layer()) {
|
|
vtzero::layer_builder lbuilder{tbuilder, layer};
|
|
while (auto feature = layer.next_feature()) {
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.copy_id(feature);
|
|
if (feature.geometry().type() == vtzero::GeomType::POINT) {
|
|
const auto points = decode_point_geometry(feature.geometry(), points_to_vector{});
|
|
fbuilder.add_points_from_container(points);
|
|
fbuilder.copy_properties(feature);
|
|
fbuilder.commit();
|
|
++n;
|
|
} else {
|
|
fbuilder.rollback();
|
|
}
|
|
}
|
|
}
|
|
REQUIRE(n == 17);
|
|
|
|
const std::string data = tbuilder.serialize();
|
|
|
|
n = 0;
|
|
vtzero::vector_tile result_tile{data};
|
|
while (auto layer = result_tile.next_layer()) {
|
|
while (layer.next_feature()) {
|
|
++n;
|
|
}
|
|
}
|
|
|
|
REQUIRE(n == 17);
|
|
}
|
|
|
|
TEST_CASE("Copy only point geometries using point_feature_builder using property_mapper") {
|
|
const auto buffer = load_test_tile();
|
|
vtzero::vector_tile tile{buffer};
|
|
|
|
vtzero::tile_builder tbuilder;
|
|
|
|
int n = 0;
|
|
while (auto layer = tile.next_layer()) {
|
|
vtzero::layer_builder lbuilder{tbuilder, layer};
|
|
vtzero::property_mapper mapper{layer, lbuilder};
|
|
while (auto feature = layer.next_feature()) {
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
fbuilder.copy_id(feature);
|
|
if (feature.geometry().type() == vtzero::GeomType::POINT) {
|
|
const auto points = decode_point_geometry(feature.geometry(), points_to_vector{});
|
|
fbuilder.add_points_from_container(points);
|
|
fbuilder.copy_properties(feature, mapper);
|
|
fbuilder.commit();
|
|
++n;
|
|
} else {
|
|
fbuilder.rollback();
|
|
}
|
|
}
|
|
}
|
|
REQUIRE(n == 17);
|
|
|
|
const std::string data = tbuilder.serialize();
|
|
|
|
n = 0;
|
|
vtzero::vector_tile result_tile{data};
|
|
while (auto layer = result_tile.next_layer()) {
|
|
while (layer.next_feature()) {
|
|
++n;
|
|
}
|
|
}
|
|
|
|
REQUIRE(n == 17);
|
|
}
|
|
|
|
TEST_CASE("Build point feature from container with too many points") {
|
|
|
|
// fake container pretending to contain too many points
|
|
struct test_container {
|
|
|
|
static std::size_t size() noexcept {
|
|
return 1UL << 29U;
|
|
}
|
|
|
|
static vtzero::point* begin() noexcept {
|
|
return nullptr;
|
|
}
|
|
|
|
static vtzero::point* end() noexcept {
|
|
return nullptr;
|
|
}
|
|
|
|
};
|
|
|
|
vtzero::tile_builder tbuilder;
|
|
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
|
|
fbuilder.set_id(1);
|
|
|
|
test_container tc;
|
|
REQUIRE_THROWS_AS(fbuilder.add_points_from_container(tc), vtzero::geometry_exception);
|
|
}
|
|
|
|
TEST_CASE("Moving a feature builder is allowed") {
|
|
vtzero::tile_builder tbuilder;
|
|
vtzero::layer_builder lbuilder{tbuilder, "test"};
|
|
vtzero::point_feature_builder fbuilder{lbuilder};
|
|
|
|
auto fbuilder2 = std::move(fbuilder);
|
|
vtzero::point_feature_builder fbuilder3{std::move(fbuilder2)};
|
|
}
|
|
|