test_set_ops_pointlike.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014-2015, Oracle and/or its affiliates.
  3. // Licensed under the Boost Software License version 1.0.
  4. // http://www.boost.org/users/license.html
  5. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  6. #ifndef BOOST_GEOMETRY_TEST_SET_OPS_POINTLIKE_HPP
  7. #define BOOST_GEOMETRY_TEST_SET_OPS_POINTLIKE_HPP
  8. #include <boost/geometry/geometry.hpp>
  9. namespace bg = ::boost::geometry;
  10. #include <from_wkt.hpp>
  11. #include <to_svg.hpp>
  12. #include <algorithm>
  13. #include <fstream>
  14. #include <boost/core/ignore_unused.hpp>
  15. #include <boost/typeof/typeof.hpp>
  16. #include <boost/geometry/policies/compare.hpp>
  17. #include <boost/geometry/algorithms/equals.hpp>
  18. #include <boost/geometry/algorithms/union.hpp>
  19. #include <boost/geometry/algorithms/difference.hpp>
  20. #include <boost/geometry/algorithms/intersection.hpp>
  21. #include <boost/geometry/algorithms/sym_difference.hpp>
  22. #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
  23. //==================================================================
  24. //==================================================================
  25. // svg output
  26. //==================================================================
  27. //==================================================================
  28. template <typename Output, typename G1, typename G2>
  29. void set_operation_output(std::string const& set_op_id,
  30. std::string const& caseid,
  31. G1 const& g1, G2 const& g2,
  32. Output const& output)
  33. {
  34. boost::ignore_unused(set_op_id, caseid, g1, g2, output);
  35. #if defined(TEST_WITH_SVG)
  36. typedef typename bg::coordinate_type<G1>::type coordinate_type;
  37. typedef typename bg::point_type<G1>::type point_type;
  38. std::ostringstream filename;
  39. filename << "svgs/" << set_op_id << "_" << caseid << ".svg";
  40. std::ofstream svg(filename.str().c_str());
  41. bg::svg_mapper<point_type> mapper(svg, 500, 500);
  42. mapper.add(g1);
  43. mapper.add(g2);
  44. mapper.map(g2, "stroke-opacity:1;stroke:rgb(153,204,0);stroke-width:4");
  45. mapper.map(g1, "stroke-opacity:1;stroke:rgb(51,51,153);stroke-width:2");
  46. BOOST_AUTO_TPL(it, output.begin());
  47. for (; it != output.end(); ++it)
  48. {
  49. mapper.map(*it,
  50. "fill:rgb(255,0,255);stroke:rgb(0,0,0);stroke-width:1",
  51. 4);
  52. }
  53. #endif
  54. }
  55. //==================================================================
  56. //==================================================================
  57. // testing equality of multi-points
  58. //==================================================================
  59. //==================================================================
  60. struct equals
  61. {
  62. template <typename MultiPoint1, typename MultiPoint2>
  63. static inline bool apply(MultiPoint1 const& multipoint1,
  64. MultiPoint2 const& multipoint2)
  65. {
  66. MultiPoint1 mp1(multipoint1);
  67. MultiPoint2 mp2(multipoint2);
  68. std::sort(mp1.begin(), mp1.end(),
  69. bg::less<typename bg::point_type<MultiPoint1>::type>());
  70. std::sort(mp2.begin(), mp2.end(),
  71. bg::less<typename bg::point_type<MultiPoint2>::type>());
  72. if ( boost::size(mp1) != boost::size(mp2) )
  73. {
  74. return false;
  75. }
  76. BOOST_AUTO_TPL(it1, boost::begin(mp1));
  77. BOOST_AUTO_TPL(it2, boost::begin(mp2));
  78. for (; it1 != boost::end(mp1); ++it1, ++it2)
  79. {
  80. if ( !bg::equals(*it1, *it2) )
  81. {
  82. return false;
  83. }
  84. }
  85. return true;
  86. }
  87. };
  88. //==================================================================
  89. //==================================================================
  90. // struct for calling the appropriate set op function
  91. //==================================================================
  92. //==================================================================
  93. template <bg::overlay_type OverlayType> struct set_op;
  94. template<>
  95. struct set_op<bg::overlay_difference>
  96. {
  97. static inline std::string name() { return "difference"; }
  98. template <typename Geometry1, typename Geometry2, typename GeometryOut>
  99. static inline void apply(Geometry1 const& g1,
  100. Geometry2 const& g2,
  101. GeometryOut& gout)
  102. {
  103. bg::difference(g1, g2, gout);
  104. }
  105. };
  106. template<>
  107. struct set_op<bg::overlay_union>
  108. {
  109. static inline std::string name() { return "union"; }
  110. template <typename Geometry1, typename Geometry2, typename GeometryOut>
  111. static inline void apply(Geometry1 const& g1,
  112. Geometry2 const& g2,
  113. GeometryOut& gout)
  114. {
  115. bg::union_(g1, g2, gout);
  116. }
  117. };
  118. template<>
  119. struct set_op<bg::overlay_intersection>
  120. {
  121. static inline std::string name() { return "intersection"; }
  122. template <typename Geometry1, typename Geometry2, typename GeometryOut>
  123. static inline void apply(Geometry1 const& g1,
  124. Geometry2 const& g2,
  125. GeometryOut& gout)
  126. {
  127. bg::intersection(g1, g2, gout);
  128. }
  129. };
  130. template
  131. <
  132. typename Geometry,
  133. typename Tag = typename bg::tag<Geometry>::type
  134. > struct geometry_info
  135. {};
  136. template <typename Point>
  137. struct geometry_info<Point, bg::point_tag>
  138. {
  139. static std::size_t const topological_dimension = 0;
  140. static inline char const* name() { return "P"; }
  141. };
  142. template <typename MultiPoint>
  143. struct geometry_info<MultiPoint, bg::multi_point_tag>
  144. {
  145. static std::size_t const topological_dimension = 0;
  146. static inline char const* name() { return "MP"; }
  147. };
  148. template <typename Linestring>
  149. struct geometry_info<Linestring, bg::linestring_tag>
  150. {
  151. static std::size_t const topological_dimension = 1;
  152. static inline char const* name() { return "L"; }
  153. };
  154. template <typename MultiLinestring>
  155. struct geometry_info<MultiLinestring, bg::multi_linestring_tag>
  156. {
  157. static std::size_t const topological_dimension = 1;
  158. static inline char const* name() { return "ML"; }
  159. };
  160. template <typename Segment>
  161. struct geometry_info<Segment, bg::segment_tag>
  162. {
  163. static std::size_t const topological_dimension = 1;
  164. static inline char const* name() { return "S"; }
  165. };
  166. //==================================================================
  167. //==================================================================
  168. // test the set operation of (point-like) geometries
  169. //==================================================================
  170. //==================================================================
  171. template
  172. <
  173. typename Geometry1,
  174. typename Geometry2,
  175. typename MultiPoint,
  176. bg::overlay_type OverlayType
  177. >
  178. class test_set_op_of_pointlike_geometries
  179. {
  180. private:
  181. template <bool Enable, typename Dummy = void>
  182. struct base_test
  183. {
  184. template <typename G1, typename G2, typename MP>
  185. static inline void apply(std::string const& case_id,
  186. G1 const& geometry1,
  187. G2 const& geometry2,
  188. MP const& mp_expected)
  189. {
  190. MultiPoint mp_output;
  191. set_op<OverlayType>::apply(geometry1, geometry2, mp_output);
  192. std::string op_name = set_op<OverlayType>::name();
  193. BOOST_CHECK_MESSAGE(equals::apply(mp_expected, mp_output),
  194. "case ID: " << case_id << ", "
  195. << op_name << " "
  196. << geometry_info<G1>::name() << "/"
  197. << geometry_info<G2>::name() << ": "
  198. << bg::wkt(geometry1)
  199. << " " << bg::wkt(geometry2)
  200. << " -> Expected: " << bg::wkt(mp_expected)
  201. << " computed: " << bg::wkt(mp_output) );
  202. set_operation_output(op_name, case_id,
  203. geometry1, geometry2, mp_output);
  204. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  205. std::cout << "Geometry #1: " << bg::wkt(geometry1) << std::endl;
  206. std::cout << "Geometry #2: " << bg::wkt(geometry2) << std::endl;
  207. std::cout << "expected " << op_name << " : "
  208. << bg::wkt(mp_expected) << std::endl;
  209. std::cout << op_name << " : " << bg::wkt(mp_output) << std::endl;
  210. std::cout << std::endl;
  211. std::cout << "************************************" << std::endl;
  212. std::cout << std::endl;
  213. std::cout << std::endl;
  214. #endif
  215. }
  216. };
  217. template <typename Dummy>
  218. struct base_test<false, Dummy>
  219. {
  220. template <typename G1, typename G2, typename MP>
  221. static inline void apply(std::string const&, G1 const&, G2 const&,
  222. MP const&)
  223. {
  224. }
  225. };
  226. public:
  227. static inline void apply(std::string const& case_id,
  228. Geometry1 const& geometry1,
  229. Geometry2 const& geometry2,
  230. MultiPoint const& mp_expected12,
  231. MultiPoint const& mp_expected21)
  232. {
  233. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  234. std::cout << "test case: " << case_id << std::endl;
  235. #endif
  236. base_test<true>::apply(case_id, geometry1, geometry2, mp_expected12);
  237. // try the same set operation with the arguments' order
  238. // reversed only if the two geometries are of the same
  239. // topological dimension
  240. base_test
  241. <
  242. (geometry_info<Geometry1>::topological_dimension
  243. == geometry_info<Geometry2>::topological_dimension)
  244. >::apply(case_id, geometry2, geometry1, mp_expected21);
  245. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  246. std::cout << std::endl;
  247. std::cout << std::endl;
  248. #endif
  249. }
  250. static inline void apply(std::string const& case_id,
  251. Geometry1 const& geometry1,
  252. Geometry2 const& geometry2,
  253. MultiPoint const& mp_expected)
  254. {
  255. apply(case_id, geometry1, geometry2, mp_expected, mp_expected);
  256. }
  257. };
  258. #endif // BOOST_GEOMETRY_TEST_SET_OPS_POINTLIKE_HPP