This is an automated email from the git hooks/post-receive script. sebastic pushed a commit to branch master in repository mapnik-vector-tile.
commit 7208ca5315b5effd700a34467b2222ea4ce329f1 Author: Bas Couwenberg <sebas...@xs4all.nl> Date: Fri Sep 11 22:55:30 2015 +0200 Imported Upstream version 0.9.1+dfsg --- CHANGELOG.md | 4 ++ CONTRIBUTING.md | 3 +- package.json | 2 +- src/vector_tile_util.hpp | 1 + src/vector_tile_util.ipp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ test/vector_tile.cpp | 37 ++++++++++++++++++ test/vector_tile_pbf.cpp | 21 +++++++---- 7 files changed, 157 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79e0380..76c85ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.9.1 + + - Added `is_solid_extent` implementation based on protozero decoder + ## 0.9.0 - Upgraded to protozero v1.0.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ad498ac..bdfe804 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,7 @@ To release a new node-mapnik version: - Make sure that all tests as passing (including travis and appveyor tests). - Update the CHANGELOG.md - Make a "bump commit" by updating the version in `package.json` and adding a commit like `-m "bump to v0.8.5"` - - Create a github tag like `git tag -a v0.8.5 -m "v0.8.5"` + - Create a github tag like `git tag -a v0.8.5 -m "v0.8.5" && git push --tags` + - Ensure travis tests are passing - Ensure you have a clean checkout (no extra files in your check that are not known by git). You need to be careful, for instance, to avoid a large accidental file being packaged by npm. You can get a view of what npm will publish by running `make testpack` - Then publish the module to npm repositories by running `npm publish` diff --git a/package.json b/package.json index 849d896..fb3cda9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mapnik-vector-tile", - "version": "0.9.0", + "version": "0.9.1", "description": "Mapnik vector tile API", "main": "./package.json", "repository" : { diff --git a/src/vector_tile_util.hpp b/src/vector_tile_util.hpp index 800db92..fae87dd 100644 --- a/src/vector_tile_util.hpp +++ b/src/vector_tile_util.hpp @@ -12,6 +12,7 @@ namespace vector_tile { namespace mapnik { namespace vector_tile_impl { MAPNIK_VECTOR_INLINE bool is_solid_extent(vector_tile::Tile const& tile, std::string & key); + MAPNIK_VECTOR_INLINE bool is_solid_extent(std::string const& tile, std::string & key); }} diff --git a/src/vector_tile_util.ipp b/src/vector_tile_util.ipp index f7dfe44..4f5976c 100644 --- a/src/vector_tile_util.ipp +++ b/src/vector_tile_util.ipp @@ -7,6 +7,11 @@ #include <mapnik/vertex.hpp> #include <mapnik/box2d.hpp> #include <mapnik/geometry.hpp> + +#include "vector_tile_geometry_decoder.hpp" + +#include <protozero/pbf_reader.hpp> + #include <stdexcept> #include <string> #include <sstream> @@ -162,4 +167,97 @@ namespace mapnik { namespace vector_tile_impl { return true; } + bool is_solid_extent(std::string const& tile, std::string & key) + { + protozero::pbf_reader item(tile.data(),tile.size()); + unsigned i = 0; + while (item.next()) { + if (item.tag() == 3) { + protozero::pbf_reader layer_msg = item.get_message(); + unsigned extent = 0; + std::string name; + std::vector<protozero::pbf_reader> feature_collection; + while (layer_msg.next()) + { + switch(layer_msg.tag()) + { + case 1: + name = layer_msg.get_string(); + break; + case 2: + feature_collection.push_back(layer_msg.get_message()); + break; + case 5: + extent = layer_msg.get_uint32(); + break; + default: + layer_msg.skip(); + break; + } + } + unsigned side = extent - 1; + mapnik::box2d<int> container(2, 2, extent-2, extent-2); + double extent_area = side * side; + for (auto & features : feature_collection) + { + while (features.next()) { + if (features.tag() == 4) { + mapnik::vector_tile_impl::GeometryPBF paths(features.get_packed_uint32(), 0, 0, 1, 1); + mapnik::vector_tile_impl::GeometryPBF::command cmd; + double x0, y0, x1, y1; + mapnik::box2d<int> box; + bool first = true; + while ((cmd = paths.next(x1, y1)) != mapnik::vector_tile_impl::GeometryPBF::end) + { + if (cmd == mapnik::vector_tile_impl::GeometryPBF::move_to || cmd == mapnik::vector_tile_impl::GeometryPBF::line_to) + { + if ((x1 > 0 && x1 < static_cast<int>(side)) && (y1 > 0 && y1 < static_cast<int>(side))) + { + // We can abort early if this feature has a vertex that is + // inside the bbox. + return false; + } + else if (!first && line_intersects_box(x0,y0,x1,y1,container)) + { + // or if the last line segment intersects with the expected bounding rectangle + return false; + } + x0 = x1; + y0 = y1; + if (first) + { + box.init(x1,y1,x1,y1); + first = false; + } + else + { + box.expand_to_include(x1,y1); + } + } + } + // Once we have only one clipped result polygon, we can compare the + // areas and return early if they don't match. + int geom_area = box.width() * box.height(); + if (geom_area < (extent_area - 32) ) + { + return false; + } + if (i == 0) { + key = name; + } else if (i > 0) { + key += std::string("-") + name; + } + } else { + features.skip(); + } + } + } + ++i; + } else { + item.skip(); + } + } + return true; + } + }} // end ns \ No newline at end of file diff --git a/test/vector_tile.cpp b/test/vector_tile.cpp index 3276242..6f34979 100644 --- a/test/vector_tile.cpp +++ b/test/vector_tile.cpp @@ -133,6 +133,8 @@ TEST_CASE( "vector tile output 1", "should create vector tile with two points" ) std::string buffer; CHECK(tile.SerializeToString(&buffer)); CHECK(194 == buffer.size()); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); } TEST_CASE( "vector tile output 2", "adding empty layers should result in empty tile" ) { @@ -154,6 +156,10 @@ TEST_CASE( "vector tile output 2", "adding empty layers should result in empty t CHECK(true == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); CHECK(0 == tile.layers_size()); + std::string buffer; + CHECK(tile.SerializeToString(&buffer)); + CHECK(true == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); } TEST_CASE( "vector tile output 3", "adding layers with geometries outside rendering extent should not add layer" ) { @@ -187,6 +193,10 @@ TEST_CASE( "vector tile output 3", "adding layers with geometries outside render CHECK(true == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); CHECK(0 == tile.layers_size()); + std::string buffer; + CHECK(tile.SerializeToString(&buffer)); + CHECK(true == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); } TEST_CASE( "vector tile output 4", "adding layers with degenerate geometries should not add layer" ) { @@ -214,6 +224,10 @@ TEST_CASE( "vector tile output 4", "adding layers with degenerate geometries sho CHECK(true == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); CHECK(0 == tile.layers_size()); + std::string buffer; + CHECK(tile.SerializeToString(&buffer)); + CHECK(true == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); } TEST_CASE( "vector tile input", "should be able to parse message and render point" ) { @@ -243,6 +257,9 @@ TEST_CASE( "vector tile input", "should be able to parse message and render poin std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile2,key)); CHECK("" == key); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); + CHECK(1 == tile2.layers_size()); vector_tile::Tile_Layer const& layer2 = tile2.layers(0); CHECK(std::string("layer") == layer2.name()); @@ -308,6 +325,10 @@ TEST_CASE( "vector tile datasource", "should filter features outside extent" ) { std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); + std::string buffer; + CHECK(tile.SerializeToString(&buffer)); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); REQUIRE(1 == tile.layers_size()); vector_tile::Tile_Layer const& layer = tile.layers(0); CHECK(std::string("layer") == layer.name()); @@ -432,6 +453,10 @@ TEST_CASE( "encoding multi line as one path", "should maintain second move_to co std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); + std::string buffer; + CHECK(tile.SerializeToString(&buffer)); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); REQUIRE(1 == tile.layers_size()); vector_tile::Tile_Layer const& layer = tile.layers(0); CHECK(1 == layer.features_size()); @@ -501,6 +526,10 @@ TEST_CASE( "encoding single line 1", "should maintain start/end vertex" ) { std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); + std::string buffer; + CHECK(tile.SerializeToString(&buffer)); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); REQUIRE(1 == tile.layers_size()); vector_tile::Tile_Layer const& layer = tile.layers(0); CHECK(1 == layer.features_size()); @@ -578,6 +607,10 @@ TEST_CASE( "encoding single line 2", "should maintain start/end vertex" ) { std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); + std::string buffer; + CHECK(tile.SerializeToString(&buffer)); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); REQUIRE(1 == tile.layers_size()); vector_tile::Tile_Layer const& layer = tile.layers(0); CHECK(1 == layer.features_size()); @@ -1112,6 +1145,8 @@ TEST_CASE( "vector tile transform", "should not throw on coords outside merc ran std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile2,key)); CHECK("" == key); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); CHECK(1 == tile2.layers_size()); vector_tile::Tile_Layer const& layer2 = tile2.layers(0); CHECK(std::string("layer") == layer2.name()); @@ -1188,6 +1223,8 @@ TEST_CASE( "vector tile transform2", "should not throw reprojected data from loc std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile2,key)); CHECK("" == key); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); CHECK(1 == tile2.layers_size()); vector_tile::Tile_Layer const& layer2 = tile2.layers(0); CHECK(std::string("layer") == layer2.name()); diff --git a/test/vector_tile_pbf.cpp b/test/vector_tile_pbf.cpp index ef5ccf9..fb33e4b 100644 --- a/test/vector_tile_pbf.cpp +++ b/test/vector_tile_pbf.cpp @@ -72,6 +72,8 @@ TEST_CASE( "pbf vector tile input", "should be able to parse message and render std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile2,key)); CHECK("" == key); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); CHECK(1 == tile2.layers_size()); vector_tile::Tile_Layer const& layer2 = tile2.layers(0); CHECK(std::string("layer") == layer2.name()); @@ -144,6 +146,10 @@ TEST_CASE( "pbf vector tile datasource", "should filter features outside extent" std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); + std::string buffer; + tile.SerializeToString(&buffer); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); REQUIRE(1 == tile.layers_size()); vector_tile::Tile_Layer const& layer = tile.layers(0); CHECK(std::string("layer") == layer.name()); @@ -155,8 +161,6 @@ TEST_CASE( "pbf vector tile datasource", "should filter features outside extent" CHECK(4096 == f.geometry(1)); CHECK(4096 == f.geometry(2)); - std::string buffer; - tile.SerializeToString(&buffer); protozero::pbf_reader pbf_tile(buffer.c_str(), buffer.size()); pbf_tile.next(); protozero::pbf_reader layer2 = pbf_tile.get_message(); @@ -261,6 +265,10 @@ TEST_CASE( "pbf encoding multi line as one path", "should maintain second move_t std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); + std::string buffer; + tile.SerializeToString(&buffer); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); REQUIRE(1 == tile.layers_size()); vector_tile::Tile_Layer const& layer = tile.layers(0); REQUIRE(1 == layer.features_size()); @@ -282,9 +290,6 @@ TEST_CASE( "pbf encoding multi line as one path", "should maintain second move_t mapnik::featureset_ptr fs; mapnik::feature_ptr f_ptr; - - std::string buffer; - tile.SerializeToString(&buffer); protozero::pbf_reader pbf_tile(buffer.c_str(), buffer.size()); pbf_tile.next(); protozero::pbf_reader layer2 = pbf_tile.get_message(); @@ -343,6 +348,10 @@ TEST_CASE( "pbf decoding some truncated buffers", "should throw exception" ) { std::string key(""); CHECK(false == mapnik::vector_tile_impl::is_solid_extent(tile,key)); CHECK("" == key); + std::string buffer; + tile.SerializeToString(&buffer); + CHECK(false == mapnik::vector_tile_impl::is_solid_extent(buffer,key)); + CHECK("" == key); REQUIRE(1 == tile.layers_size()); vector_tile::Tile_Layer const& layer = tile.layers(0); CHECK(std::string("layer") == layer.name()); @@ -358,8 +367,6 @@ TEST_CASE( "pbf decoding some truncated buffers", "should throw exception" ) { // We will test truncating the generated protobuf at every increment. // Most cases should fail, except for the lucky bites where we chop // it off at a point that would be valid anyway. - std::string buffer; - tile.SerializeToString(&buffer); for (std::size_t i=1; i< buffer.size(); ++i) { CHECK_THROWS({ -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/mapnik-vector-tile.git _______________________________________________ Pkg-grass-devel mailing list Pkg-grass-devel@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-grass-devel