// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2014-2015, Oracle and/or its affiliates. // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle #ifndef BOOST_GEOMETRY_TEST_SET_OPS_POINTLIKE_HPP #define BOOST_GEOMETRY_TEST_SET_OPS_POINTLIKE_HPP #include namespace bg = ::boost::geometry; #include #include #include #include #include #include #include #include #include #include #include #include #include //================================================================== //================================================================== // svg output //================================================================== //================================================================== template void set_operation_output(std::string const& set_op_id, std::string const& caseid, G1 const& g1, G2 const& g2, Output const& output) { boost::ignore_unused(set_op_id, caseid, g1, g2, output); #if defined(TEST_WITH_SVG) typedef typename bg::coordinate_type::type coordinate_type; typedef typename bg::point_type::type point_type; std::ostringstream filename; filename << "svgs/" << set_op_id << "_" << caseid << ".svg"; std::ofstream svg(filename.str().c_str()); bg::svg_mapper mapper(svg, 500, 500); mapper.add(g1); mapper.add(g2); mapper.map(g2, "stroke-opacity:1;stroke:rgb(153,204,0);stroke-width:4"); mapper.map(g1, "stroke-opacity:1;stroke:rgb(51,51,153);stroke-width:2"); BOOST_AUTO_TPL(it, output.begin()); for (; it != output.end(); ++it) { mapper.map(*it, "fill:rgb(255,0,255);stroke:rgb(0,0,0);stroke-width:1", 4); } #endif } //================================================================== //================================================================== // testing equality of multi-points //================================================================== //================================================================== struct equals { template static inline bool apply(MultiPoint1 const& multipoint1, MultiPoint2 const& multipoint2) { MultiPoint1 mp1(multipoint1); MultiPoint2 mp2(multipoint2); std::sort(mp1.begin(), mp1.end(), bg::less::type>()); std::sort(mp2.begin(), mp2.end(), bg::less::type>()); if ( boost::size(mp1) != boost::size(mp2) ) { return false; } BOOST_AUTO_TPL(it1, boost::begin(mp1)); BOOST_AUTO_TPL(it2, boost::begin(mp2)); for (; it1 != boost::end(mp1); ++it1, ++it2) { if ( !bg::equals(*it1, *it2) ) { return false; } } return true; } }; //================================================================== //================================================================== // struct for calling the appropriate set op function //================================================================== //================================================================== template struct set_op; template<> struct set_op { static inline std::string name() { return "difference"; } template static inline void apply(Geometry1 const& g1, Geometry2 const& g2, GeometryOut& gout) { bg::difference(g1, g2, gout); } }; template<> struct set_op { static inline std::string name() { return "union"; } template static inline void apply(Geometry1 const& g1, Geometry2 const& g2, GeometryOut& gout) { bg::union_(g1, g2, gout); } }; template<> struct set_op { static inline std::string name() { return "intersection"; } template static inline void apply(Geometry1 const& g1, Geometry2 const& g2, GeometryOut& gout) { bg::intersection(g1, g2, gout); } }; template < typename Geometry, typename Tag = typename bg::tag::type > struct geometry_info {}; template struct geometry_info { static std::size_t const topological_dimension = 0; static inline char const* name() { return "P"; } }; template struct geometry_info { static std::size_t const topological_dimension = 0; static inline char const* name() { return "MP"; } }; template struct geometry_info { static std::size_t const topological_dimension = 1; static inline char const* name() { return "L"; } }; template struct geometry_info { static std::size_t const topological_dimension = 1; static inline char const* name() { return "ML"; } }; template struct geometry_info { static std::size_t const topological_dimension = 1; static inline char const* name() { return "S"; } }; //================================================================== //================================================================== // test the set operation of (point-like) geometries //================================================================== //================================================================== template < typename Geometry1, typename Geometry2, typename MultiPoint, bg::overlay_type OverlayType > class test_set_op_of_pointlike_geometries { private: template struct base_test { template static inline void apply(std::string const& case_id, G1 const& geometry1, G2 const& geometry2, MP const& mp_expected) { MultiPoint mp_output; set_op::apply(geometry1, geometry2, mp_output); std::string op_name = set_op::name(); BOOST_CHECK_MESSAGE(equals::apply(mp_expected, mp_output), "case ID: " << case_id << ", " << op_name << " " << geometry_info::name() << "/" << geometry_info::name() << ": " << bg::wkt(geometry1) << " " << bg::wkt(geometry2) << " -> Expected: " << bg::wkt(mp_expected) << " computed: " << bg::wkt(mp_output) ); set_operation_output(op_name, case_id, geometry1, geometry2, mp_output); #ifdef BOOST_GEOMETRY_TEST_DEBUG std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl; std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl; std::cout << "expected " << op_name << " : " << bg::wkt(mp_expected) << std::endl; std::cout << op_name << " : " << bg::wkt(mp_output) << std::endl; std::cout << std::endl; std::cout << "************************************" << std::endl; std::cout << std::endl; std::cout << std::endl; #endif } }; template struct base_test { template static inline void apply(std::string const&, G1 const&, G2 const&, MP const&) { } }; public: static inline void apply(std::string const& case_id, Geometry1 const& geometry1, Geometry2 const& geometry2, MultiPoint const& mp_expected12, MultiPoint const& mp_expected21) { #ifdef BOOST_GEOMETRY_TEST_DEBUG std::cout << "test case: " << case_id << std::endl; #endif base_test::apply(case_id, geometry1, geometry2, mp_expected12); // try the same set operation with the arguments' order // reversed only if the two geometries are of the same // topological dimension base_test < (geometry_info::topological_dimension == geometry_info::topological_dimension) >::apply(case_id, geometry2, geometry1, mp_expected21); #ifdef BOOST_GEOMETRY_TEST_DEBUG std::cout << std::endl; std::cout << std::endl; #endif } static inline void apply(std::string const& case_id, Geometry1 const& geometry1, Geometry2 const& geometry2, MultiPoint const& mp_expected) { apply(case_id, geometry1, geometry2, mp_expected, mp_expected); } }; #endif // BOOST_GEOMETRY_TEST_SET_OPS_POINTLIKE_HPP