TEST_CASE("vector tile from simplified geojson")
{
    unsigned tile_size = 256 * 100;
    mapnik::Map map(256,256,"+init=epsg:3857");
    mapnik::layer lyr("layer","+init=epsg:4326");
    std::shared_ptr<mapnik::memory_datasource> ds = testing::build_geojson_ds("./test/data/poly.geojson");
    ds->set_envelope(mapnik::box2d<double>(160.147311,11.047284,160.662858,11.423830));
    lyr.set_datasource(ds);
    map.add_layer(lyr);
    mapnik::vector_tile_impl::processor ren(map);
    mapnik::vector_tile_impl::tile out_tile = ren.create_tile(0,0,0,tile_size);
    CHECK(out_tile.is_painted() == true);
    CHECK(out_tile.is_empty() == false);
    
    vector_tile::Tile tile;
    tile.ParseFromString(out_tile.get_buffer());
    REQUIRE(1 == tile.layers_size());
    vector_tile::Tile_Layer const& layer = tile.layers(0);
    CHECK(std::string("layer") == layer.name());
    REQUIRE(1 == layer.features_size());
    vector_tile::Tile_Feature const& f = layer.features(0);
    unsigned z = 0;
    unsigned x = 0;
    unsigned y = 0;
    double resolution = mapnik::EARTH_CIRCUMFERENCE/(1 << z);
    double tile_x = -0.5 * mapnik::EARTH_CIRCUMFERENCE + x * resolution;
    double tile_y =  0.5 * mapnik::EARTH_CIRCUMFERENCE - y * resolution;
    double scale = static_cast<double>(layer.extent())/resolution;
    protozero::pbf_reader layer_reader;
    out_tile.layer_reader(0, layer_reader);
#pragma GCC diagnostic ignored "-Wsign-conversion"
#include "vector_tile.pb.h"
#pragma GCC diagnostic pop

TEST_CASE("pbf vector tile input")
{
    unsigned tile_size = 4096;
    mapnik::Map map(256,256,"+init=epsg:3857");
    mapnik::layer lyr("layer",map.srs());
    lyr.set_datasource(testing::build_ds(0,0));
    map.add_layer(lyr);
    mapnik::vector_tile_impl::processor ren(map);
    mapnik::vector_tile_impl::tile out_tile = ren.create_tile(0,0,0,tile_size);
    CHECK(out_tile.is_painted() == true);
    CHECK(out_tile.is_empty() == false);
    vector_tile::Tile tile;
    tile.ParseFromString(out_tile.get_buffer());
    // serialize to message
    std::string buffer;
    CHECK(tile.SerializeToString(&buffer));
    CHECK(147 == buffer.size());
    // now create new objects
    mapnik::Map map2(256,256,"+init=epsg:3857");
    vector_tile::Tile tile2;
    CHECK(tile2.ParseFromString(buffer));
    CHECK(1 == tile2.layers_size());
    vector_tile::Tile_Layer const& layer2 = tile2.layers(0);
    CHECK(std::string("layer") == layer2.name());
    CHECK(1 == layer2.features_size());

    mapnik::layer lyr2("layer",map.srs());
Beispiel #3
0
void OutputTile(bool verbose, vector_tile::Tile& tile)
{
	if (!verbose) {
		std::cout << "layers: " << static_cast<std::size_t>(tile.layers_size()) << "\n";
		for (std::size_t i = 0; i<static_cast<std::size_t>(tile.layers_size()); ++i)
		{
			vector_tile::Tile_Layer const& layer = tile.layers(i);
			const double tileScale = 1.0 / layer.extent();

			std::cout << layer.name() << ":\n";
			std::cout << "  version: " << layer.version() << "\n";
			std::cout << "  extent: " << layer.extent() << "\n";
			std::cout << "  features: " << static_cast<std::size_t>(layer.features_size()) << "\n";
			std::cout << "  keys: " << static_cast<std::size_t>(layer.keys_size()) << "\n";
			std::cout << "  values: " << static_cast<std::size_t>(layer.values_size()) << "\n";
			unsigned total_repeated = 0;
			unsigned num_commands = 0;
			unsigned num_move_to = 0;
			unsigned num_line_to = 0;
			unsigned num_close = 0;
			unsigned num_empty = 0;
			unsigned degenerate = 0;

			vector<Polygon> polygons;
			vector<TPolygon2D<double>> lineStrings;
			uint64_t lastFeatureId = 0;
			for (std::size_t j = 0; j<static_cast<std::size_t>(layer.features_size()); ++j)
			{
				int32_t cursorX = 0;
				int32_t cursorY = 0;
				vector_tile::Tile_Feature const & f = layer.features(j);
				total_repeated += f.geometry_size();
				int cmd = -1;
				const int cmd_bits = 3;
				unsigned length = 0;
				unsigned g_length = 0;
				vector<TPolygon2D<int32_t>> polys;
				TPolygon2D<int32_t> poly;
				for (int k = 0; k < f.geometry_size();)
				{
					if (!length) {
						unsigned cmd_length = f.geometry(k++);
						cmd = cmd_length & ((1 << cmd_bits) - 1);
						length = cmd_length >> cmd_bits;
						if (length <= 0) num_empty++;
						num_commands++;
					}
					if (length > 0) {
						length--;
						if (cmd == SEG_MOVETO || cmd == SEG_LINETO)
						{
							uint32_t xZigZag = f.geometry(k++);
							uint32_t yZigZag = f.geometry(k++);
							int32_t xRel = ZigZagUint32ToInt32(xZigZag);
							int32_t yRel = ZigZagUint32ToInt32(yZigZag);
							cursorX += xRel;
							cursorY += yRel;

							g_length++;
							if (cmd == SEG_MOVETO)
							{
								if (poly.GetNumVertices() > 0)
								{
									polys.push_back(move(poly));
									poly = TPolygon2D<int32_t>();
									poly.ReserveNumVertices(10);
								}

								num_move_to++;
							}
							else if (cmd == SEG_LINETO)
							{
								num_line_to++;
							}

							poly.AddVertex(TVector2D<int32_t>(cursorX, cursorY));
						}
						else if (cmd == (SEG_CLOSE & ((1 << cmd_bits) - 1)))
						{
							if (g_length <= 2) degenerate++;
							g_length = 0;
							num_close++;

							polys.push_back(move(poly));
							poly = TPolygon2D<int32_t>();
							poly.ReserveNumVertices(10);
						}
						else
						{
							std::stringstream s;
							s << "Unknown command type: " << cmd;
							throw std::runtime_error(s.str());
						}
					}
				}

				if (f.type() == vector_tile::Tile_GeomType_POLYGON)
				{
					size_t polyStartIndex = 0;
					for (size_t p = 0; p < polys.size(); p++)
					{
						int64_t polyArea = polys[p].ComputeArea<int64_t>();
						if (p > polyStartIndex && polyArea < 0) // test for multipolygons including interior polys
						{
							auto& poly = polys[polyStartIndex];
							const auto* nextPoly = &polys[polyStartIndex + 1];
							Polygon polygon(f.id(), tileScale, poly,
								(polyStartIndex + 1 < polys.size() ) ? nextPoly : NULL,
								(uint32_t)(p - polyStartIndex - 1));
							polygons.push_back(move(polygon));

							polyStartIndex = p;
						}
					}
					if (polyStartIndex < polys.size())
					{
						Polygon polygon(f.id(), tileScale, polys[polyStartIndex],
							(polyStartIndex + 1 < polys.size()) ? &polys[polyStartIndex + 1] : NULL,
							(uint32_t)(polys.size() - 1 - polyStartIndex));
						polygons.push_back(move(polygon));
					}
				}
				else if (f.type() == vector_tile::Tile_GeomType_LINESTRING)
				{
					polys.push_back(move(poly));

					for (const auto& p : polys)
					{
						lineStrings.push_back(move(p.Clone<double>(tileScale)));
					}
				}
			}
			std::cout << "  geometry summary:\n";
			std::cout << "    total: " << total_repeated << "\n";
			std::cout << "    commands: " << num_commands << "\n";
			std::cout << "    move_to: " << num_move_to << "\n";
			std::cout << "    line_to: " << num_line_to << "\n";
			std::cout << "    close: " << num_close << "\n";
			std::cout << "    degenerate polygons: " << degenerate << "\n";
			std::cout << "    empty geoms: " << num_empty << "\n";
			std::cout << "    NUM POLYGONS: " << polygons.size() << "\n";
			std::cout << "    NUM LINE STRINGS: " << lineStrings.size() << "\n";
		}