diff --git a/test/unit/serialization/wkb_test.cpp b/test/unit/serialization/wkb_test.cpp new file mode 100644 index 000000000..f82c4f32f --- /dev/null +++ b/test/unit/serialization/wkb_test.cpp @@ -0,0 +1,113 @@ +#include "catch.hpp" +// mapnik +#include +#include +#include +#include +#include +// bool +#include +#include +#include +// stl +#include "parse_hex.hpp" +#include +#include +#include +#include + +namespace { + +struct spatially_equal_visitor +{ + using result_type = bool; + + result_type operator() (mapnik::geometry::geometry_empty, mapnik::geometry::geometry_empty) const + { + return true; + } + + result_type operator() (mapnik::geometry::geometry_collection const& lhs, mapnik::geometry::geometry_collection const& rhs) const + { + std::size_t size0 = lhs.size(); + std::size_t size1 = rhs.size(); + if (size0 != size1) return false; + for (std::size_t index = 0; index < size0 ; ++index) + { + if (!mapnik::util::apply_visitor(*this, lhs[index], rhs[index])) + return false; + } + return true; + } + + result_type operator() (mapnik::geometry::multi_point const& lhs, mapnik::geometry::multi_point const& rhs) const + { + std::size_t size0 = lhs.size(); + std::size_t size1 = rhs.size(); + if (size0 != size1) return false; + auto tmp0 = lhs; + auto tmp1 = rhs; + std::sort(tmp0.begin(), tmp0.end(), boost::geometry::less>()); + std::sort(tmp1.begin(), tmp1.end(), boost::geometry::less>()); + for (std::size_t index = 0; index < size0 ; ++index) + { + if (!boost::geometry::equals(tmp0[index], tmp1[index])) return false; + } + return true; + } + + template + result_type operator() (T const& lhs, T const& rhs) const + { + if (mapnik::geometry::is_empty(lhs) && mapnik::geometry::is_empty(rhs)) + return true; //Empty geometries of the same type are considered to be spatially equal + return boost::geometry::equals(lhs, rhs); + } + + template + result_type operator() (T0 const& lhs, T1 const& rhs) const + { + return false; + } + +}; + +template +bool spatially_equal(mapnik::geometry::geometry const& g0, mapnik::geometry::geometry const& g1) +{ + return mapnik::util::apply_visitor(spatially_equal_visitor(), g0, g1); +} + +} + +TEST_CASE("Well-known-geometries") +{ + SECTION("wkb") + { + std::string filename("test/unit/data/well-known-geometries.test"); + std::ifstream is(filename.c_str(),std::ios_base::in | std::ios_base::binary); + if (!is) throw std::runtime_error("could not open: '" + filename + "'"); + + for (std::string line; std::getline(is, line,'\n');) + { + std::vector columns; + boost::split(columns, line, boost::is_any_of(";")); + REQUIRE(columns.size() == 3); + std::vector wkb, twkb; + REQUIRE(mapnik::util::parse_hex(columns[1], wkb)); + REQUIRE(mapnik::util::parse_hex(columns[2], twkb)); + mapnik::geometry::geometry geom_0 = mapnik::geometry_utils::from_wkb(wkb.data(), wkb.size(), mapnik::wkbAuto); + mapnik::geometry::geometry geom_1 = mapnik::geometry_utils::from_twkb(twkb.data(), twkb.size()); + // compare WKTs + std::string wkt0, wkt1; + REQUIRE(mapnik::util::to_wkt(wkt0, geom_0)); + REQUIRE(mapnik::util::to_wkt(wkt1, geom_1)); + if (!mapnik::geometry::is_empty(geom_0) && !mapnik::geometry::is_empty(geom_1)) + { + REQUIRE(wkt0 == wkt1); + // compare spatially (NOTE: GeometryCollection comparison also enforces strict order) + REQUIRE(spatially_equal(geom_0, geom_1)); + } + } + } +}