inline bool encode_geometry(mapnik::geometry::linear_ring<std::int64_t> const& ring, vector_tile::Tile_Feature & current_feature, int32_t & start_x, int32_t & start_y) { std::size_t ring_size = ring.size(); if (ring_size < 3) { return false; } unsigned line_to_length = static_cast<unsigned>(ring_size) - 1; unsigned count = 0; enum { move_to = 1, line_to = 2, coords = 3 } status = move_to; bool drop_last = false; if (ring.size() > 2 && ring.front() == ring.back()) { drop_last = true; line_to_length -= 1; if (line_to_length < 2) { return false; } } for (auto const& pt : ring) { if (status == move_to) { status = line_to; current_feature.add_geometry(9); // 1 | (move_to << 3) } else if (status == line_to) { status = coords; current_feature.add_geometry(encode_length(line_to_length)); } else if (drop_last && count == line_to_length + 1) { continue; } int32_t dx = pt.x - start_x; int32_t dy = pt.y - start_y; // Manual zigzag encoding. current_feature.add_geometry(protozero::encode_zigzag32(dx)); current_feature.add_geometry(protozero::encode_zigzag32(dy)); start_x = pt.x; start_y = pt.y; ++count; } current_feature.add_geometry(15); // close_path return true; }
inline bool encode_geometry(mapnik::geometry::point<std::int64_t> const& pt, vector_tile::Tile_Feature & current_feature, int32_t & start_x, int32_t & start_y) { current_feature.add_geometry(9); // 1 | (move_to << 3) int32_t dx = pt.x - start_x; int32_t dy = pt.y - start_y; // Manual zigzag encoding. current_feature.add_geometry(protozero::encode_zigzag32(dx)); current_feature.add_geometry(protozero::encode_zigzag32(dy)); start_x = pt.x; start_y = pt.y; return true; }
inline bool encode_geometry(mapnik::geometry::line_string<std::int64_t> const& line, vector_tile::Tile_Feature & current_feature, int32_t & start_x, int32_t & start_y) { std::size_t line_size = line.size(); if (line_size <= 0) { return false; } unsigned line_to_length = static_cast<unsigned>(line_size) - 1; enum { move_to = 1, line_to = 2, coords = 3 } status = move_to; for (auto const& pt : line) { if (status == move_to) { status = line_to; current_feature.add_geometry(9); // 1 | (move_to << 3) } else if (status == line_to) { status = coords; current_feature.add_geometry(encode_length(line_to_length)); } int32_t dx = pt.x - start_x; int32_t dy = pt.y - start_y; // Manual zigzag encoding. current_feature.add_geometry(protozero::encode_zigzag32(dx)); current_feature.add_geometry(protozero::encode_zigzag32(dy)); start_x = pt.x; start_y = pt.y; } return true; }
inline bool encode_geometry(mapnik::geometry::multi_point<std::int64_t> const& geom, vector_tile::Tile_Feature & current_feature, int32_t & start_x, int32_t & start_y) { std::size_t geom_size = geom.size(); if (geom_size <= 0) { return false; } current_feature.add_geometry(1u | (geom_size << 3)); // move_to | (len << 3) for (auto const& pt : geom) { int32_t dx = pt.x - start_x; int32_t dy = pt.y - start_y; // Manual zigzag encoding. current_feature.add_geometry(protozero::encode_zigzag32(dx)); current_feature.add_geometry(protozero::encode_zigzag32(dy)); start_x = pt.x; start_y = pt.y; } return true; }
// TEST_CASE("encoding pbf simple polygon") { mapnik::geometry::polygon<std::int64_t> p0; p0.exterior_ring.add_coord(0,0); p0.exterior_ring.add_coord(0,10); p0.exterior_ring.add_coord(-10,10); p0.exterior_ring.add_coord(-10,0); p0.exterior_ring.add_coord(0,0); std::int32_t x = 0; std::int32_t y = 0; std::string feature_str; protozero::pbf_writer feature_writer(feature_str); vector_tile::Tile_Feature feature; REQUIRE(mapnik::vector_tile_impl::encode_geometry_pbf(p0, feature_writer, x, y)); feature.ParseFromString(feature_str); REQUIRE(feature.type() == vector_tile::Tile_GeomType_POLYGON); // MoveTo, ParameterInteger, ParameterInteger // LineTo, ParameterInteger, ParameterInteger, ParameterInteger, ParameterInteger, ParameterInteger, ParameterInteger // Close // 3 commands + 8 Params = 11 REQUIRE(feature.geometry_size() == 11); // MoveTo(0,0) CHECK(feature.geometry(0) == ((1 << 3) | 1u)); // 9 CHECK(feature.geometry(1) == 0); CHECK(feature.geometry(2) == 0); // LineTo(0,10) CHECK(feature.geometry(3) == ((3 << 3) | 2u));
#include <mapnik/geometry.hpp> // libprotobuf #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wsign-conversion" #include "vector_tile.pb.h" #pragma GCC diagnostic pop // // Unit tests for geometry decoding of linestrings // TEST_CASE("decode simple linestring") { vector_tile::Tile_Feature feature; feature.set_type(vector_tile::Tile_GeomType_LINESTRING); // MoveTo(1,1) feature.add_geometry(9); // move_to | (1 << 3) feature.add_geometry(protozero::encode_zigzag32(1)); feature.add_geometry(protozero::encode_zigzag32(1)); // LineTo(2,2) feature.add_geometry((3 << 3u) | 2u); feature.add_geometry(protozero::encode_zigzag32(1)); feature.add_geometry(protozero::encode_zigzag32(1)); // LineTo(10,10) feature.add_geometry(protozero::encode_zigzag32(8)); feature.add_geometry(protozero::encode_zigzag32(8)); // LineTo(0,10) feature.add_geometry(protozero::encode_zigzag32(-10)); feature.add_geometry(protozero::encode_zigzag32(0));