#ifndef MAPNIK_UNIT_GEOMETRY_EQUAL #define MAPNIK_UNIT_GEOMETRY_EQUAL #include "catch.hpp" // boost #include #include #include MAPNIK_DISABLE_WARNING_PUSH #include #include #include #include MAPNIK_DISABLE_WARNING_POP // helper namespace to ensure correct functionality namespace aux{ namespace adl{ using std::begin; using std::end; template auto do_begin(T& v) -> decltype(begin(v)); template auto do_end(T& v) -> decltype(end(v)); } // adl:: template using zipper_it = boost::zip_iterator>; template T const& as_const(T const& v){ return v; } } // aux:: template auto zip_begin(Conts&... conts) -> aux::zipper_it { using std::begin; return {boost::make_tuple(begin(conts)...)}; } template auto zip_end(Conts&... conts) -> aux::zipper_it { using std::end; return {boost::make_tuple(end(conts)...)}; } template auto zip_range(Conts&... conts) -> boost::iterator_range { return {zip_begin(conts...), zip_end(conts...)}; } // for const access template auto zip_cbegin(Conts&... conts) -> decltype(zip_begin(aux::as_const(conts)...)) { using std::begin; return zip_begin(aux::as_const(conts)...); } template auto zip_cend(Conts&... conts) -> decltype(zip_end(aux::as_const(conts)...)) { using std::end; return zip_end(aux::as_const(conts)...); } template auto zip_crange(Conts&... conts) -> decltype(zip_range(aux::as_const(conts)...)) { return zip_range(aux::as_const(conts)...); } // mapnik #include #include using mapnik::geometry::geometry; using mapnik::geometry::geometry_empty; using mapnik::geometry::point; using mapnik::geometry::line_string; using mapnik::geometry::polygon; using mapnik::geometry::multi_point; using mapnik::geometry::multi_line_string; using mapnik::geometry::multi_polygon; using mapnik::geometry::geometry_collection; template void assert_g_equal(geometry const& g1, geometry const& g2); struct geometry_equal_visitor { template void operator() (T1 const&, T2 const&) const { // comparing two different types! REQUIRE(false); } template void operator() (geometry_empty const&, geometry_empty const&) const { REQUIRE(true); } template void operator() (point const& p1, point const& p2) const { REQUIRE(p1.x == Approx(p2.x)); REQUIRE(p1.y == Approx(p2.y)); } template void operator() (std::vector> const& ls1, std::vector> const& ls2) const { if (ls1.size() != ls2.size()) { REQUIRE(false); } for(auto const& p : zip_crange(ls1, ls2)) { REQUIRE(p.template get<0>().x == Approx(p.template get<1>().x)); REQUIRE(p.template get<0>().y == Approx(p.template get<1>().y)); } } template void operator() (polygon const& p1, polygon const& p2) const { if (p1.size() != p2.size()) { REQUIRE(false); } for (auto const& p : zip_crange(p1, p2)) { (*this)(static_cast> const&>(p.template get<0>()), static_cast> const&>(p.template get<1>())); } } template void operator() (line_string const& ls1, line_string const& ls2) const { (*this)(static_cast> const&>(ls1), static_cast> const&>(ls2)); } template void operator() (multi_point const& mp1, multi_point const& mp2) const { (*this)(static_cast> const&>(mp1), static_cast> const&>(mp2)); } template void operator() (multi_line_string const& mls1, multi_line_string const& mls2) const { if (mls1.size() != mls2.size()) { REQUIRE(false); } for (auto const& ls : zip_crange(mls1, mls2)) { (*this)(ls.template get<0>(),ls.template get<1>()); } } template void operator() (multi_polygon const& mpoly1, multi_polygon const& mpoly2) const { if (mpoly1.size() != mpoly2.size()) { REQUIRE(false); } for (auto const& poly : zip_crange(mpoly1, mpoly2)) { (*this)(poly.template get<0>(),poly.template get<1>()); } } template void operator() (mapnik::util::recursive_wrapper > const& c1_, mapnik::util::recursive_wrapper > const& c2_) const { geometry_collection const& c1 = static_cast const&>(c1_); geometry_collection const& c2 = static_cast const&>(c2_); if (c1.size() != c2.size()) { REQUIRE(false); } for (auto const& g : zip_crange(c1, c2)) { assert_g_equal(g.template get<0>(),g.template get<1>()); } } template void operator() (geometry_collection const& c1, geometry_collection const& c2) const { if (c1.size() != c2.size()) { REQUIRE(false); } for (auto const& g : zip_crange(c1, c2)) { assert_g_equal(g.template get<0>(),g.template get<1>()); } } }; template void assert_g_equal(geometry const& g1, geometry const& g2) { return mapnik::util::apply_visitor(geometry_equal_visitor(), g1, g2); } template void assert_g_equal(T const& g1, T const& g2) { return geometry_equal_visitor()(g1,g2); } #endif // MAPNIK_UNIT_GEOMETRY_EQUAL