Merge commit '6bee8866de99a602039feef463c22c972f0f86aa' as 'third_party/vtzero'
This commit is contained in:
+88
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user