Merge commit '6bee8866de99a602039feef463c22c972f0f86aa' as 'third_party/vtzero'

This commit is contained in:
Michael Krasnyk
2018-04-19 22:03:52 +03:00
75 changed files with 28148 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
#-----------------------------------------------------------------------------
#
# CMake config
#
# vtzero examples
#
#-----------------------------------------------------------------------------
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/include-external")
set(TEST_FILE "${CMAKE_SOURCE_DIR}/test/data/mapbox-streets-v6-14-8714-8017.mvt")
add_executable(vtzero-check vtzero-check.cpp utils.cpp)
add_executable(vtzero-create vtzero-create.cpp utils.cpp)
add_executable(vtzero-encode-geom vtzero-encode-geom.cpp utils.cpp)
add_executable(vtzero-stats vtzero-stats.cpp utils.cpp)
add_executable(vtzero-streets vtzero-streets.cpp utils.cpp)
#-------------------------------------------------------------
add_executable(vtzero-filter vtzero-filter.cpp utils.cpp)
add_test(NAME vtzero-filter-empty
COMMAND vtzero-filter)
set_tests_properties(vtzero-filter-empty PROPERTIES
PASS_REGULAR_EXPRESSION "^Error in command line: Missing file name of vector tile to read")
add_test(NAME vtzero-filter-help
COMMAND vtzero-filter -h)
set_tests_properties(vtzero-filter-help PROPERTIES
PASS_REGULAR_EXPRESSION "^usage:\n vtzero-filter")
add_test(NAME vtzero-filter-layer
COMMAND vtzero-filter -o ${CMAKE_CURRENT_BINARY_DIR}/bridges.mvt ${TEST_FILE} bridge)
add_test(NAME vtzero-filter-feature
COMMAND vtzero-filter -o ${CMAKE_CURRENT_BINARY_DIR}/bridges.mvt ${TEST_FILE} waterway_label 221925711)
add_test(NAME vtzero-filter-invalid-id
COMMAND vtzero-filter -o ${CMAKE_CURRENT_BINARY_DIR}/bridges.mvt ${TEST_FILE} waterway_label abc)
set_tests_properties(vtzero-filter-invalid-id PROPERTIES
WILL_FAIL true)
#-------------------------------------------------------------
add_executable(vtzero-show vtzero-show.cpp utils.cpp)
add_test(NAME vtzero-show-empty
COMMAND vtzero-show)
set_tests_properties(vtzero-show-empty PROPERTIES
PASS_REGULAR_EXPRESSION "^Error in command line: Missing file name of vector tile to read")
add_test(NAME vtzero-show-help
COMMAND vtzero-show -h)
set_tests_properties(vtzero-show-help PROPERTIES
PASS_REGULAR_EXPRESSION "^usage:\n vtzero-show")
add_test(NAME vtzero-show-layers
COMMAND vtzero-show -l ${TEST_FILE})
set_tests_properties(vtzero-show-layers PROPERTIES
PASS_REGULAR_EXPRESSION "^landuse 78\nwaterway 327\n.*\nwaterway_label 4\n$")
add_test(NAME vtzero-show-layer-num
COMMAND vtzero-show ${TEST_FILE} 2)
set_tests_properties(vtzero-show-layer-num PROPERTIES
PASS_REGULAR_EXPRESSION "layer: [0-9]+\n name: water\n")
add_test(NAME vtzero-show-layer-name
COMMAND vtzero-show ${CMAKE_SOURCE_DIR}/test/data/mapbox-streets-v6-14-8714-8017.mvt water)
set_tests_properties(vtzero-show-layer-name PROPERTIES
PASS_REGULAR_EXPRESSION "layer: [0-9]+\n name: water\n")
#-------------------------------------------------------------
file(GLOB ext_tests RELATIVE ${CMAKE_SOURCE_DIR}/test/data/ ${CMAKE_SOURCE_DIR}/test/data/*.mvt)
foreach(_test IN LISTS ext_tests)
message(STATUS "Adding ext test: ${_test}")
add_test(NAME ext-tests-${_test}
COMMAND vtzero-show ${CMAKE_SOURCE_DIR}/test/data/${_test})
endforeach()
#-----------------------------------------------------------------------------
+100
View File
@@ -0,0 +1,100 @@
/*****************************************************************************
Utility functions for vtzero example programs.
*****************************************************************************/
#include "utils.hpp"
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <limits>
#include <stdexcept>
#include <string>
/**
* Read complete contents of a file into a string.
*
* The file is read in binary mode.
*
* @param filename The file name. Can be empty or "-" to read from STDIN.
* @returns a string with the contents of the file.
* @throws various exceptions if there is an error
*/
std::string read_file(const std::string& filename) {
if (filename.empty() || (filename.size() == 1 && filename[0] == '-')) {
return std::string{std::istreambuf_iterator<char>(std::cin.rdbuf()),
std::istreambuf_iterator<char>()};
}
std::ifstream stream{filename, std::ios_base::in | std::ios_base::binary};
if (!stream) {
throw std::runtime_error{std::string{"Can not open file '"} + filename + "'"};
}
stream.exceptions(std::ifstream::failbit);
std::string buffer{std::istreambuf_iterator<char>(stream.rdbuf()),
std::istreambuf_iterator<char>()};
stream.close();
return buffer;
}
/**
* Write contents of a buffer into a file.
*
* The file is written in binary mode.
*
* @param buffer The data to be written.
* @param filename The file name.
* @throws various exceptions if there is an error
*/
void write_data_to_file(const std::string& buffer, const std::string& filename) {
std::ofstream stream{filename, std::ios_base::out | std::ios_base::binary};
if (!stream) {
throw std::runtime_error{std::string{"Can not open file '"} + filename + "'"};
}
stream.exceptions(std::ifstream::failbit);
stream.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
stream.close();
}
/**
* Get a specific layer from a vector tile. The layer can be specified as a
* number n in which case the nth layer in this tile is returned. Or it can
* be specified as text, in which case the layer with that name is returned.
*
* Calls exit(1) if there is an error.
*
* @param tile The vector tile.
* @param layer_name_or_num specifies the layer.
*/
vtzero::layer get_layer(const vtzero::vector_tile& tile, const std::string& layer_name_or_num) {
vtzero::layer layer;
char* str_end = nullptr;
const long num = std::strtol(layer_name_or_num.c_str(), &str_end, 10); // NOLINT(google-runtime-int)
if (str_end == layer_name_or_num.data() + layer_name_or_num.size()) {
if (num >= 0 && num < std::numeric_limits<long>::max()) { // NOLINT(google-runtime-int)
layer = tile.get_layer(static_cast<std::size_t>(num));
if (!layer) {
std::cerr << "No such layer: " << num << '\n';
std::exit(1);
}
return layer;
}
}
layer = tile.get_layer_by_name(layer_name_or_num);
if (!layer) {
std::cerr << "No layer named '" << layer_name_or_num << "'.\n";
std::exit(1);
}
return layer;
}
+11
View File
@@ -0,0 +1,11 @@
#include <vtzero/vector_tile.hpp>
#include <string>
std::string read_file(const std::string& filename);
void write_data_to_file(const std::string& buffer, const std::string& filename);
vtzero::layer get_layer(const vtzero::vector_tile& tile, const std::string& layer_name_or_num);
+225
View File
@@ -0,0 +1,225 @@
/*****************************************************************************
Example program for vtzero library.
vtzero-check - Check vector tiles for validity
*****************************************************************************/
#include "utils.hpp"
#include <vtzero/vector_tile.hpp>
#include <iostream>
#include <set>
#include <stdexcept>
#include <string>
class result {
int m_return_code = 0;
public:
void has_warning() noexcept {
if (m_return_code < 1) {
m_return_code = 1;
}
}
void has_error() noexcept {
if (m_return_code < 2) {
m_return_code = 2;
}
}
void has_fatal_error() noexcept {
if (m_return_code < 3) {
m_return_code = 3;
}
}
int return_code() const noexcept {
return m_return_code;
}
} result;
class CheckGeomHandler {
vtzero::point m_prev_point{};
int m_layer_num;
int m_feature_num;
int64_t m_extent;
bool m_is_first_point = false;
int m_count = 0;
void print_context() const {
std::cerr << " in layer " << m_layer_num
<< " in feature " << m_feature_num
<< " in geometry " << m_count
<< ": ";
}
void print_error(const char* message) const {
result.has_error();
std::cerr << "Error";
print_context();
std::cerr << message << '\n';
}
void print_warning(const char* message) const {
result.has_warning();
std::cerr << "Warning";
print_context();
std::cerr << message << '\n';
}
void check_point_location(const vtzero::point point) const {
if (point.x < -m_extent ||
point.y < -m_extent ||
point.x > 2 * m_extent ||
point.y > 2 * m_extent) {
print_warning("point waaaay beyond the extent");
}
}
public:
CheckGeomHandler(uint32_t extent, int layer_num, int feature_num) :
m_layer_num(layer_num),
m_feature_num(feature_num),
m_extent(static_cast<int64_t>(extent)) {
}
// ----------------------------------------------------------------------
void points_begin(const uint32_t /*count*/) const {
}
void points_point(const vtzero::point point) const {
check_point_location(point);
}
void points_end() const {
}
// ----------------------------------------------------------------------
void linestring_begin(const uint32_t count) {
if (count < 2) {
print_error("Not enough points in linestring");
}
m_is_first_point = true;
}
void linestring_point(const vtzero::point point) {
if (m_is_first_point) {
m_is_first_point = false;
} else {
if (point == m_prev_point) {
print_error("Duplicate point in linestring");
}
}
m_prev_point = point;
check_point_location(point);
}
void linestring_end() {
++m_count;
}
// ----------------------------------------------------------------------
void ring_begin(const uint32_t count) {
if (count < 4) {
print_error("Not enough points in ring");
}
m_is_first_point = true;
}
void ring_point(const vtzero::point point) {
if (m_is_first_point) {
m_is_first_point = false;
} else {
if (point == m_prev_point) {
print_error("Duplicate point in ring");
}
}
m_prev_point = point;
check_point_location(point);
}
void ring_end(const vtzero::ring_type rt) {
if (rt == vtzero::ring_type::invalid) {
print_error("Invalid ring with area 0");
}
if (m_count == 0 && rt != vtzero::ring_type::outer) {
print_error("First ring isn't an outer ring");
}
++m_count;
}
}; // class CheckGeomHandler
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " TILE\n";
return 1;
}
std::string input_file{argv[1]};
const auto data = read_file(input_file);
std::set<std::string> layer_names;
vtzero::vector_tile tile{data};
int layer_num = 0;
int feature_num = -1;
try {
while (auto layer = tile.next_layer()) {
if (layer.name().empty()) {
std::cerr << "Error in layer " << layer_num << ": name is empty (spec 4.1)\n";
result.has_error();
}
std::string name(layer.name());
if (layer_names.count(name) > 0) {
std::cerr << "Error in layer " << layer_num << ": name is duplicate of previous layer ('" << name << "') (spec 4.1)\n";
result.has_error();
}
layer_names.insert(name);
feature_num = 0;
while (auto feature = layer.next_feature()) {
CheckGeomHandler handler{layer.extent(), layer_num, feature_num};
vtzero::decode_geometry(feature.geometry(), handler);
++feature_num;
}
if (feature_num == 0) {
std::cerr << "Warning: No features in layer " << layer_num << " (spec 4.1)\n";
result.has_warning();
}
feature_num = -1;
++layer_num;
}
if (layer_num == 0) {
std::cerr << "Warning: No layers in vector tile (spec 4.1)\n";
result.has_warning();
}
} catch (const std::exception& e) {
std::cerr << "Fatal error in layer " << layer_num;
if (feature_num >= 0) {
std::cerr << " in feature " << feature_num;
}
std::cerr << ": " << e.what() << '\n';
result.has_fatal_error();
}
return result.return_code();
}
+101
View File
@@ -0,0 +1,101 @@
/*****************************************************************************
Example program for vtzero library.
vtzero-create - Create a vector tile
*****************************************************************************/
#include "utils.hpp"
#include <vtzero/builder.hpp>
#include <vtzero/index.hpp>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
int main() {
vtzero::tile_builder tile;
vtzero::layer_builder layer_points{tile, "points"};
vtzero::layer_builder layer_lines{tile, "lines"};
vtzero::layer_builder layer_polygons{tile, "polygons"};
vtzero::key_index<std::unordered_map> idx{layer_points};
{
vtzero::point_feature_builder feature{layer_points};
feature.set_id(1);
feature.add_points(1);
feature.set_point(10, 10);
feature.add_property("foo", "bar");
feature.add_property("x", "y");
feature.rollback();
}
const auto some = idx("some");
{
vtzero::point_feature_builder feature{layer_points};
feature.set_id(2);
feature.add_point(20, 20);
feature.add_property(some, "attr");
}
{
vtzero::point_feature_builder feature{layer_points};
feature.set_id(3);
feature.add_point(20, 20);
feature.add_property(idx("some"), "attr");
}
{
vtzero::point_feature_builder feature{layer_points};
feature.set_id(4);
feature.add_point(20, 20);
feature.add_property(idx("some"), "otherattr");
}
vtzero::point_feature_builder feature1{layer_points};
feature1.set_id(5);
feature1.add_point(vtzero::point{20, 20});
feature1.add_property("otherkey", "attr");
feature1.commit();
vtzero::value_index<vtzero::sint_value_type, int32_t, std::unordered_map> maxspeed_index{layer_lines};
{
vtzero::linestring_feature_builder feature{layer_lines};
feature.set_id(6);
feature.add_linestring(3);
feature.set_point(10, 10);
feature.set_point(10, 20);
feature.set_point(vtzero::point{20, 20});
std::vector<vtzero::point> points = {{11, 11}, {12, 13}};
feature.add_linestring_from_container(points);
feature.add_property("highway", "primary");
feature.add_property(std::string{"maxspeed"}, maxspeed_index(50));
}
{
vtzero::polygon_feature_builder feature{layer_polygons};
feature.set_id(7);
feature.add_ring(5);
feature.set_point(0, 0);
feature.set_point(10, 0);
feature.set_point(10, 10);
feature.set_point(0, 10);
feature.set_point(0, 0);
feature.add_ring(4);
feature.set_point(3, 3);
feature.set_point(3, 5);
feature.set_point(5, 5);
feature.close_ring();
feature.add_property("natural", "wood");
feature.add_property("number_of_trees", vtzero::sint_value_type{23402752});
}
const auto data = tile.serialize();
write_data_to_file(data, "test.mvt");
}
+142
View File
@@ -0,0 +1,142 @@
/*****************************************************************************
Example program for vtzero library.
vtzero-encode-geom - Encode geometry on command line
This can be used for debugging. Uses internals of vtzero!
*****************************************************************************/
#include "utils.hpp"
#include <vtzero/geometry.hpp>
#include <cctype>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
int64_t get_int(const char* arg) {
char* endptr = nullptr;
const int64_t value = std::strtoll(arg, &endptr, 10);
if (*endptr == '\0') {
return value;
}
throw std::runtime_error{"not a valid number"};
}
uint32_t move_to(const char* arg) {
if (!std::isdigit(arg[0])) {
throw std::runtime_error{"need count after M command"};
}
const auto scount = get_int(arg);
if (scount <= 0) {
throw std::runtime_error{"count after M command must be 1 or larger"};
}
const auto count = static_cast<uint32_t>(scount);
std::cout << "MOVE_TO(" << count << ")\t" << vtzero::detail::command_move_to(count) << '\n';
return vtzero::detail::command_move_to(count);
}
uint32_t line_to(const char* arg) {
if (!std::isdigit(arg[0])) {
throw std::runtime_error{"need count after L command"};
}
const auto scount = get_int(arg);
if (scount <= 0) {
throw std::runtime_error{"count after L command must be 1 or larger"};
}
const auto count = static_cast<uint32_t>(scount);
std::cout << "LINE_TO(" << count << ")\t" << vtzero::detail::command_line_to(count) << '\n';
return vtzero::detail::command_line_to(count);
}
uint32_t close_path(const char* arg) {
if (arg[0] != '\0') {
throw std::runtime_error{"extra data after C command"};
}
std::cout << "CLOSE_PATH\t" << vtzero::detail::command_close_path() << '\n';
return vtzero::detail::command_close_path();
}
uint32_t number(const char* arg) {
const auto num = static_cast<int32_t>(get_int(arg));
std::cout << "number(" << num << ")\t" << protozero::encode_zigzag32(num) << '\n';
return protozero::encode_zigzag32(num);
}
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " GEOMETRY ELEMENTS...\n"
<< "GEOMETRY ELEMENTS are:\n"
<< " M[count] -- MOVE_TO count\n"
<< " L[count] -- LINE_TO count\n"
<< " C -- CLOSE_PATH\n"
<< " [number] -- number that will be zigzag encoded\n";
return 1;
}
std::vector<uint32_t> values;
std::cout << "raw data\tencoded\n-----------------------------------\n";
for (int i = 1; i < argc; ++i) {
try {
switch (argv[i][0]) {
case '\0':
break;
case 'M':
values.push_back(move_to(argv[i] + 1));
break;
case 'L':
values.push_back(line_to(argv[i] + 1));
break;
case 'C':
values.push_back(close_path(argv[i] + 1));
break;
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
values.push_back(number(argv[i]));
break;
default:
throw std::runtime_error{std::string{"unknown data: "} + argv[i]};
return 1;
}
} catch (const std::runtime_error& e) {
std::cerr << "error(" << i << "): " << e.what() << '\n';
return 1;
}
}
std::string out{"["};
for (auto value : values) {
out += ' ';
out += std::to_string(value);
out += ',';
}
out.back() = ' ';
std::cout << '\n' << out << "]\n";
}
+101
View File
@@ -0,0 +1,101 @@
/*****************************************************************************
Example program for vtzero library.
vtzero-filter - Copy parts of a vector tile into a new tile.
*****************************************************************************/
#include "utils.hpp"
#include <vtzero/builder.hpp>
#include <vtzero/vector_tile.hpp>
#include <clara.hpp>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <limits>
#include <string>
int main(int argc, char* argv[]) {
std::string filename;
std::string layer_num_or_name;
std::string idstr;
std::string output_file{"filtered.mvt"};
bool help = false;
const auto cli
= clara::Opt(output_file, "FILE")
["-o"]["--output"]
("write output to FILE")
| clara::Help(help)
| clara::Arg(filename, "FILENAME").required()
("vector tile")
| clara::Arg(layer_num_or_name, "LAYER-NUM|LAYER-NAME").required()
("layer")
| clara::Arg(idstr, "ID")
("feature_id");
const auto result = cli.parse(clara::Args(argc, argv));
if (!result) {
std::cerr << "Error in command line: " << result.errorMessage() << '\n';
return 1;
}
if (help) {
std::cout << cli
<< "\nFilter contents of vector tile.\n";
return 0;
}
if (filename.empty()) {
std::cerr << "Error in command line: Missing file name of vector tile to read\n";
return 1;
}
if (layer_num_or_name.empty()) {
std::cerr << "Error in command line: Missing layer number or name\n";
return 1;
}
const auto data = read_file(filename);
vtzero::vector_tile tile{data};
auto layer = get_layer(tile, layer_num_or_name);
std::cerr << "Found layer: " << std::string(layer.name()) << "\n";
vtzero::tile_builder tb;
if (idstr.empty()) {
tb.add_existing_layer(layer);
} else {
char* str_end = nullptr;
const int64_t id = std::strtoll(idstr.c_str(), &str_end, 10);
if (str_end != idstr.c_str() + idstr.size()) {
std::cerr << "Feature ID must be numeric.\n";
return 1;
}
if (id < 0) {
std::cerr << "Feature ID must be >= 0.\n";
return 1;
}
const auto feature = layer.get_feature_by_id(static_cast<uint64_t>(id));
if (!feature.valid()) {
std::cerr << "No feature with that id: " << id << '\n';
return 1;
}
vtzero::layer_builder layer_builder{tb, layer};
layer_builder.add_feature(feature);
}
std::string output = tb.serialize();
write_data_to_file(output, output_file);
}
+242
View File
@@ -0,0 +1,242 @@
/*****************************************************************************
Example program for vtzero library.
vtzero-show - Show content of vector tile
*****************************************************************************/
#include "utils.hpp"
#include <vtzero/vector_tile.hpp>
#include <clara.hpp>
#include <cstdint>
#include <exception>
#include <iostream>
#include <string>
class geom_handler {
std::string output{};
public:
void points_begin(const uint32_t /*count*/) const noexcept {
}
void points_point(const vtzero::point point) const {
std::cout << " POINT(" << point.x << ',' << point.y << ")\n";
}
void points_end() const noexcept {
}
void linestring_begin(const uint32_t count) {
output = " LINESTRING[count=";
output += std::to_string(count);
output += "](";
}
void linestring_point(const vtzero::point point) {
output += std::to_string(point.x);
output += ' ';
output += std::to_string(point.y);
output += ',';
}
void linestring_end() {
if (output.empty()) {
return;
}
if (output.back() == ',') {
output.resize(output.size() - 1);
}
output += ")\n";
std::cout << output;
}
void ring_begin(const uint32_t count) {
output = " RING[count=";
output += std::to_string(count);
output += "](";
}
void ring_point(const vtzero::point point) {
output += std::to_string(point.x);
output += ' ';
output += std::to_string(point.y);
output += ',';
}
void ring_end(const vtzero::ring_type rt) {
if (output.empty()) {
return;
}
if (output.back() == ',') {
output.back() = ')';
}
switch (rt) {
case vtzero::ring_type::outer:
output += "[OUTER]\n";
break;
case vtzero::ring_type::inner:
output += "[INNER]\n";
break;
default:
output += "[INVALID]\n";
}
std::cout << output;
}
}; // class geom_handler
template <typename TChar, typename TTraits>
std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, vtzero::data_view value) {
out.write(value.data(), static_cast<std::streamsize>(value.size()));
return out;
}
struct print_value {
template <typename T>
void operator()(T value) const {
std::cout << value;
}
void operator()(const vtzero::data_view value) const {
std::cout << '"' << value << '"';
}
}; // struct print_value
static void print_layer(vtzero::layer& layer, bool print_tables, bool print_value_types, int& layer_num, int& feature_num) {
std::cout << "=============================================================\n"
<< "layer: " << layer_num << '\n'
<< " name: " << std::string(layer.name()) << '\n'
<< " version: " << layer.version() << '\n'
<< " extent: " << layer.extent() << '\n';
if (print_tables) {
std::cout << " keys:\n";
int n = 0;
for (const auto& key : layer.key_table()) {
std::cout << " " << n++ << ": " << key << '\n';
}
std::cout << " values:\n";
n = 0;
for (const vtzero::property_value& value : layer.value_table()) {
std::cout << " " << n++ << ": ";
vtzero::apply_visitor(print_value{}, value);
if (print_value_types) {
std::cout << " [" << vtzero::property_value_type_name(value.type()) << "]\n";
} else {
std::cout << '\n';
}
}
}
feature_num = 0;
while (auto feature = layer.next_feature()) {
std::cout << " feature: " << feature_num << '\n'
<< " id: ";
if (feature.has_id()) {
std::cout << feature.id() << '\n';
} else {
std::cout << "(none)\n";
}
std::cout << " geomtype: " << vtzero::geom_type_name(feature.geometry_type()) << '\n'
<< " geometry:\n";
vtzero::decode_geometry(feature.geometry(), geom_handler{});
std::cout << " properties:\n";
while (auto property = feature.next_property()) {
std::cout << " " << property.key() << '=';
vtzero::apply_visitor(print_value{}, property.value());
if (print_value_types) {
std::cout << " [" << vtzero::property_value_type_name(property.value().type()) << "]\n";
} else {
std::cout << '\n';
}
}
++feature_num;
}
}
static void print_layer_overview(const vtzero::layer& layer) {
std::cout << layer.name() << ' ' << layer.num_features() << '\n';
}
int main(int argc, char* argv[]) {
std::string filename;
std::string layer_num_or_name;
bool layer_overview = false;
bool print_tables = false;
bool print_value_types = false;
bool help = false;
const auto cli
= clara::Opt(layer_overview)
["-l"]["--layers"]
("show layer overview with feature count")
| clara::Opt(print_tables)
["-t"]["--tables"]
("also print key/value tables")
| clara::Opt(print_value_types)
["-T"]["--value-types"]
("also show value types")
| clara::Help(help)
| clara::Arg(filename, "FILENAME").required()
("vector tile")
| clara::Arg(layer_num_or_name, "LAYER-NUM|LAYER-NAME")
("layer");
const auto result = cli.parse(clara::Args(argc, argv));
if (!result) {
std::cerr << "Error in command line: " << result.errorMessage() << '\n';
return 1;
}
if (help) {
std::cout << cli
<< "\nShow contents of vector tile FILENAME.\n";
return 0;
}
if (filename.empty()) {
std::cerr << "Error in command line: Missing file name of vector tile to read\n";
return 1;
}
int layer_num = 0;
int feature_num = 0;
try {
const auto data = read_file(filename);
vtzero::vector_tile tile{data};
if (layer_num_or_name.empty()) {
while (auto layer = tile.next_layer()) {
if (layer_overview) {
print_layer_overview(layer);
} else {
print_layer(layer, print_tables, print_value_types, layer_num, feature_num);
}
++layer_num;
}
} else {
auto layer = get_layer(tile, layer_num_or_name);
if (layer_overview) {
print_layer_overview(layer);
} else {
print_layer(layer, print_tables, print_value_types, layer_num, feature_num);
}
}
} catch (const std::exception& e) {
std::cerr << "Error in layer " << layer_num << " (feature " << feature_num << "): " << e.what() << '\n';
return 1;
}
return 0;
}
+36
View File
@@ -0,0 +1,36 @@
/*****************************************************************************
Example program for vtzero library.
vtzero-stats - Output some stats on layers
*****************************************************************************/
#include "utils.hpp"
#include <vtzero/vector_tile.hpp>
#include <iostream>
#include <stdexcept>
#include <string>
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " TILE\n";
return 1;
}
std::string input_file{argv[1]};
const auto data = read_file(input_file);
vtzero::vector_tile tile{data};
while (const auto layer = tile.next_layer()) {
std::cout.write(layer.name().data(), static_cast<std::streamsize>(layer.name().size()));
std::cout << ' '
<< layer.num_features() << ' '
<< layer.key_table().size() << ' '
<< layer.value_table().size() << '\n';
}
}
+79
View File
@@ -0,0 +1,79 @@
/*****************************************************************************
Example program for vtzero library.
vtzero-streets - Copy features from road_label layer if they have property
class="street". Output is always in file "streets.mvt".
*****************************************************************************/
#include "utils.hpp"
#include <vtzero/builder.hpp>
#include <vtzero/property_mapper.hpp>
#include <vtzero/vector_tile.hpp>
#include <iostream>
#include <string>
static bool keep_feature(const vtzero::feature& feature) {
static const std::string key{"class"};
static const std::string val{"street"};
bool found = false;
feature.for_each_property([&](const vtzero::property& prop) {
found = key == prop.key() && val == prop.value().string_value();
return !found;
});
return found;
}
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " TILE\n";
return 1;
}
std::string input_file{argv[1]};
std::string output_file{"streets.mvt"};
const auto data = read_file(input_file);
try {
vtzero::vector_tile tile{data};
auto layer = get_layer(tile, "road_label");
if (!layer) {
std::cerr << "No 'road_label' layer found\n";
return 1;
}
vtzero::tile_builder tb;
vtzero::layer_builder layer_builder{tb, layer};
vtzero::property_mapper mapper{layer, layer_builder};
while (auto feature = layer.next_feature()) {
if (keep_feature(feature)) {
vtzero::geometry_feature_builder feature_builder{layer_builder};
if (feature.has_id()) {
feature_builder.set_id(feature.id());
}
feature_builder.set_geometry(feature.geometry());
while (auto idxs = feature.next_property_indexes()) {
feature_builder.add_property(mapper(idxs));
}
}
}
std::string output = tb.serialize();
write_data_to_file(output, output_file);
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << '\n';
return 1;
}
}