diff --git a/include/mapnik/quad_tree.hpp b/include/mapnik/quad_tree.hpp index c99d32a5c..86a342f2d 100644 --- a/include/mapnik/quad_tree.hpp +++ b/include/mapnik/quad_tree.hpp @@ -30,6 +30,7 @@ // stl #include #include +#include namespace mapnik { @@ -172,6 +173,8 @@ public: template void write(OutputStream & out) { + static_assert(std::is_standard_layout::value, + "Values stored in quad-tree must be standard layout types to allow serialisation"); char header[16]; std::memset(header,0,16); header[0]='m'; diff --git a/include/mapnik/util/spatial_index.hpp b/include/mapnik/util/spatial_index.hpp index bc348f85d..e79012f90 100644 --- a/include/mapnik/util/spatial_index.hpp +++ b/include/mapnik/util/spatial_index.hpp @@ -23,10 +23,13 @@ #ifndef MAPNIK_UTIL_SPATIAL_INDEX_HPP #define MAPNIK_UTIL_SPATIAL_INDEX_HPP +//mapnik #include #include #include #include +// stl +#include using mapnik::box2d; using mapnik::query; @@ -43,16 +46,17 @@ private: spatial_index(); ~spatial_index(); - spatial_index(const spatial_index&); - spatial_index& operator=(const spatial_index&); + spatial_index(spatial_index const&); + spatial_index& operator=(spatial_index const&); static int read_ndr_integer(InputStream& in); static void read_envelope(InputStream& in, box2d& envelope); - static void query_node(const Filter& filter, InputStream& in, std::vector & results); + static void query_node(Filter const& filter, InputStream& in, std::vector & results); }; template box2d spatial_index::bounding_box(InputStream& in) { + static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout type"); in.seekg(16 + 4, std::ios::beg); box2d box; read_envelope(in, box); @@ -63,6 +67,7 @@ box2d spatial_index::bounding_box(InputStrea template void spatial_index::query(Filter const& filter, InputStream& in, std::vector& results) { + static_assert(std::is_standard_layout::value, "Values stored in quad-tree must be standard layout types"); in.seekg(16, std::ios::beg); query_node(filter, in, results); } @@ -83,7 +88,7 @@ void spatial_index::query_node(Filter const& filter, for (int i = 0; i < num_shapes; ++i) { Value item; - in >> item; + in.read(reinterpret_cast(&item), sizeof(Value)); results.push_back(std::move(item)); } diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp index 0aace027c..c8e4d7e60 100644 --- a/plugins/input/csv/csv_datasource.cpp +++ b/plugins/input/csv/csv_datasource.cpp @@ -610,6 +610,7 @@ mapnik::featureset_ptr csv_datasource::features(mapnik::query const& q) const } else if (has_disk_index_) { + std::cerr << "DISK_INDEX" << std::endl; mapnik::filter_in_box filter(q.get_bbox()); return std::make_shared(filename_, filter, locator_, separator_, headers_, ctx_); } diff --git a/plugins/input/csv/csv_index_featureset.hpp b/plugins/input/csv/csv_index_featureset.hpp index bcca22c99..7c7c39714 100644 --- a/plugins/input/csv/csv_index_featureset.hpp +++ b/plugins/input/csv/csv_index_featureset.hpp @@ -35,18 +35,9 @@ #include #endif -using value_type = std::pair; -namespace std { -template -InputStream & operator>>(InputStream & in, value_type & value) -{ - in.read(reinterpret_cast(&value), sizeof(value_type)); - return in; -} -} - class csv_index_featureset : public mapnik::Featureset { + using value_type = std::pair; using locator_type = detail::geometry_column_locator; public: diff --git a/test/unit/datasource/spatial_index.cpp b/test/unit/datasource/spatial_index.cpp index 94a123f71..410487e28 100644 --- a/test/unit/datasource/spatial_index.cpp +++ b/test/unit/datasource/spatial_index.cpp @@ -20,17 +20,21 @@ * *****************************************************************************/ +#include +#include + #include "catch.hpp" -#include #include +#include TEST_CASE("spatial_index") { SECTION("mapnik::quad_tree") { - // value type to store inside index (must provide operator<< + operator>>) - using value_type = std::size_t; + // value_type must have standard layout (http://en.cppreference.com/w/cpp/types/is_standard_layout) + using value_type = std::int32_t; + using mapnik::filter_in_box; mapnik::box2d extent(0,0,100,100); mapnik::quad_tree tree(extent); REQUIRE(tree.extent() == extent); @@ -38,7 +42,33 @@ TEST_CASE("spatial_index") tree.insert(1, mapnik::box2d(10,10,20,20)); tree.insert(2, mapnik::box2d(30,30,40,40)); tree.insert(3, mapnik::box2d(30,10,40,20)); - REQUIRE(tree.count() == 3); - REQUIRE(tree.count_items() == 3); + tree.insert(4, mapnik::box2d(1,1,2,2)); + tree.trim(); + + REQUIRE(tree.count() == 10); + REQUIRE(tree.count_items() == 4); + + // serialise + std::ostringstream out(std::ios::binary); + tree.write(out); + out.flush(); + + REQUIRE(out.str().length() == 472); + REQUIRE(out.str().at(0) == 'm'); + + // read bounding box + std::istringstream in(out.str(), std::ios::binary); + auto box = mapnik::util::spatial_index::bounding_box(in); + REQUIRE(box == tree.extent()); + // bounding box query + std::vector results; + filter_in_box filter(box); + mapnik::util::spatial_index::query(filter, in, results); + + REQUIRE(results[0] == 1); + REQUIRE(results[1] == 4); + REQUIRE(results[2] == 3); + REQUIRE(results[3] == 2); + REQUIRE(results.size() == 4); } }