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());
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"; }