assemble.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Unit Test
  3. // Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
  4. // This file was modified by Oracle on 2019.
  5. // Modifications copyright (c) 2019, Oracle and/or its affiliates.
  6. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #include <iostream>
  11. #include <iomanip>
  12. #include <string>
  13. #include <geometry_test_common.hpp>
  14. #include <boost/foreach.hpp>
  15. #include <boost/geometry/algorithms/correct.hpp>
  16. #include <boost/geometry/algorithms/intersection.hpp>
  17. #include <boost/geometry/algorithms/union.hpp>
  18. #include <boost/geometry/algorithms/difference.hpp>
  19. #include <boost/geometry/algorithms/intersects.hpp>
  20. #include <boost/geometry/algorithms/within.hpp>
  21. #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
  22. #include <boost/geometry/geometries/geometries.hpp>
  23. #include <boost/geometry/geometries/point_xy.hpp>
  24. #include <boost/geometry/strategies/strategies.hpp>
  25. #include <boost/geometry/io/wkt/read.hpp>
  26. #include <boost/geometry/io/wkt/write.hpp>
  27. #if defined(TEST_WITH_SVG)
  28. # include <boost/geometry/io/svg/svg_mapper.hpp>
  29. #endif
  30. template <typename Geometry>
  31. inline void test_assemble(std::string const& id, Geometry const& p, Geometry const& q, char operation = 'i')
  32. {
  33. std::vector<Geometry> u, i, d1, d2;
  34. bg::detail::union_::union_insert<Geometry>(p, q, std::back_inserter(u));
  35. bg::detail::intersection::intersection_insert<Geometry>(p, q, std::back_inserter(i));
  36. bg::detail::difference::difference_insert<Geometry>(p, q, std::back_inserter(d1));
  37. bg::detail::difference::difference_insert<Geometry>(q, p, std::back_inserter(d2));
  38. if (operation == 'i')
  39. {
  40. typedef typename bg::default_area_result<Geometry>::type type;
  41. type area_p = bg::area(p);
  42. type area_q = bg::area(q);
  43. type area_i = 0, area_u = 0, area_d1 = 0, area_d2 = 0;
  44. BOOST_FOREACH(Geometry const& g, u)
  45. {
  46. area_u += bg::area(g);
  47. }
  48. BOOST_FOREACH(Geometry const& g, i)
  49. {
  50. area_i += bg::area(g);
  51. }
  52. BOOST_FOREACH(Geometry const& g, d1)
  53. {
  54. area_d1 += bg::area(g);
  55. }
  56. BOOST_FOREACH(Geometry const& g, d2)
  57. {
  58. area_d2 += bg::area(g);
  59. }
  60. type diff = (area_p + area_q) - area_u - area_i;
  61. type diff_d1 = (area_u - area_q) - area_d1;
  62. type diff_d2 = (area_u - area_p) - area_d2;
  63. bool ok = bg::math::abs(diff) < 0.001
  64. && bg::math::abs(diff_d1) < 0.001
  65. && bg::math::abs(diff_d2) < 0.001;
  66. BOOST_CHECK_MESSAGE(ok,
  67. id << " diff: "
  68. << diff << " d1: "
  69. << diff_d1 << " d2: "
  70. << diff_d2);
  71. }
  72. #if defined(TEST_WITH_SVG)
  73. {
  74. std::ostringstream filename;
  75. filename << "assemble_" << id << "_" << operation << ".svg";
  76. std::ofstream svg(filename.str().c_str());
  77. bg::svg_mapper<typename bg::point_type<Geometry>::type> mapper(svg, 500, 500);
  78. mapper.add(p);
  79. mapper.add(q);
  80. mapper.map(p, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:3");
  81. mapper.map(q, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:3");
  82. std::string linestyle = "opacity:0.7;fill:none;stroke-opacity:1;stroke-miterlimit:4;";
  83. std::vector<Geometry> const& v = operation == 'i' ? i
  84. : operation == 'u' ? u
  85. : operation == 'd' ? d1
  86. : d2
  87. ;
  88. BOOST_FOREACH(Geometry const& geometry, v)
  89. {
  90. mapper.map(geometry,
  91. linestyle + "stroke-width:3;stroke-linejoin:round;stroke-linecap:square;stroke-dasharray:12,12;stroke:rgb(255,0,0);");
  92. }
  93. }
  94. #endif
  95. }
  96. template <typename Polygon>
  97. inline bool int_ok(Polygon const& poly)
  98. {
  99. typename bg::point_type<Polygon>::type const& pi =
  100. bg::interior_rings(poly)[0].front();
  101. return bg::within(pi, bg::exterior_ring(poly));
  102. }
  103. template <typename T>
  104. void generate()
  105. {
  106. static std::string exteriors[4] = {
  107. "(0 0,0 10,10 10,10 0,0 0)",
  108. "(1 1,1 9,8 9,8 1,1 1)",
  109. "(2 0.5, 0.5 2,0.5 8,2 9.5,6 9.5,8.5 8,8.5 2,7 0.5,2 0.5)",
  110. "(3 3,3 7,6 7,6 3,3 3)"
  111. };
  112. static std::string interiors[4] = {
  113. "(2 2,2 8,7 8,7 2,2 2)",
  114. "(8.5 1,8.5 2,9.5 2,9.5 1,8.5 1)",
  115. "(4 4,4 5,5 5,5 4,4 4)",
  116. "(6 4,6 5,9 5,9 4,6 4)"
  117. };
  118. for (int pe = 0; pe < 4; pe++)
  119. {
  120. for (int qe = 0; qe < 4; qe++)
  121. {
  122. for (int pi = 0; pi < 4; pi++)
  123. {
  124. for (int qi = 0; qi < 4; qi++)
  125. {
  126. std::string ps = "POLYGON(" + exteriors[pe] + "," + interiors[pi] + ")";
  127. std::string qs = "POLYGON(" + exteriors[qe] + "," + interiors[qi] + ")";
  128. typedef bg::model::d2::point_xy<T> point_type;
  129. bg::model::polygon<point_type> p, q;
  130. bg::read_wkt(ps, p);
  131. bg::read_wkt(qs, q);
  132. bg::correct(p);
  133. bg::correct(q);
  134. if (! bg::intersects(p)
  135. && ! bg::intersects(q)
  136. && int_ok(p)
  137. && int_ok(q)
  138. )
  139. {
  140. std::ostringstream out;
  141. out << pe << qe << pi << qi;
  142. test_assemble(out.str(), p, q);
  143. #if defined(TEST_WITH_SVG)
  144. test_assemble(out.str(), p, q, 'u');
  145. test_assemble(out.str(), p, q, 'd');
  146. test_assemble(out.str(), p, q, 'r');
  147. #endif
  148. }
  149. }
  150. }
  151. }
  152. }
  153. }
  154. #if ! defined(GEOMETRY_TEST_MULTI)
  155. int test_main(int, char* [])
  156. {
  157. generate<double>();
  158. return 0;
  159. }
  160. #endif