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));
Example #6
0
#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));