recursive_polygons.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Robustness Test
  3. // Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
  4. // Use, modification and distribution is subject to the Boost Software License,
  5. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #define BOOST_GEOMETRY_REPORT_OVERLAY_ERROR
  8. #define BOOST_GEOMETRY_NO_BOOST_TEST
  9. #include <test_overlay_p_q.hpp>
  10. #include <boost/program_options.hpp>
  11. #include <boost/random/linear_congruential.hpp>
  12. #include <boost/random/uniform_int.hpp>
  13. #include <boost/random/uniform_real.hpp>
  14. #include <boost/random/variate_generator.hpp>
  15. #include <boost/timer.hpp>
  16. template <typename Polygon, typename Generator>
  17. inline void make_polygon(Polygon& polygon, Generator& generator, bool triangular)
  18. {
  19. typedef typename bg::point_type<Polygon>::type point_type;
  20. typedef typename bg::coordinate_type<Polygon>::type coordinate_type;
  21. coordinate_type x, y;
  22. x = generator();
  23. y = generator();
  24. typename bg::ring_type<Polygon>::type& ring = bg::exterior_ring(polygon);
  25. point_type p;
  26. bg::set<0>(p, x); bg::set<1>(p, y); ring.push_back(p);
  27. bg::set<0>(p, x); bg::set<1>(p, y + 1); ring.push_back(p);
  28. bg::set<0>(p, x + 1); bg::set<1>(p, y + 1); ring.push_back(p);
  29. bg::set<0>(p, x + 1); bg::set<1>(p, y); ring.push_back(p);
  30. bg::set<0>(p, x); bg::set<1>(p, y); ring.push_back(p);
  31. if (triangular)
  32. {
  33. // Remove a point depending on generator
  34. int c = generator() % 4;
  35. if (c >= 1 && c <= 3)
  36. {
  37. ring.erase(ring.begin() + c);
  38. }
  39. }
  40. }
  41. template <typename MultiPolygon, typename Generator>
  42. bool test_recursive_boxes(MultiPolygon& result, int& index,
  43. Generator& generator,
  44. int level, bool triangular, p_q_settings const& settings)
  45. {
  46. MultiPolygon p, q;
  47. // Generate two boxes
  48. if (level == 0)
  49. {
  50. p.resize(1);
  51. q.resize(1);
  52. make_polygon(p.front(), generator, triangular);
  53. make_polygon(q.front(), generator, triangular);
  54. bg::correct(p);
  55. bg::correct(q);
  56. }
  57. else
  58. {
  59. bg::correct(p);
  60. bg::correct(q);
  61. if (! test_recursive_boxes(p, index, generator, level - 1, triangular, settings)
  62. || ! test_recursive_boxes(q, index, generator, level - 1, triangular, settings))
  63. {
  64. return false;
  65. }
  66. }
  67. typedef typename boost::range_value<MultiPolygon>::type polygon;
  68. std::ostringstream out;
  69. out << "recursive_box_" << index++ << "_" << level;
  70. if (! test_overlay_p_q
  71. <
  72. polygon,
  73. typename bg::coordinate_type<MultiPolygon>::type
  74. >(out.str(), p, q, settings))
  75. {
  76. return false;
  77. }
  78. MultiPolygon mp;
  79. bg::detail::union_::union_insert
  80. <
  81. polygon
  82. >(p, q, std::back_inserter(mp));
  83. bg::unique(mp);
  84. bg::simplify(mp, result, 0.01);
  85. bg::correct(mp);
  86. return true;
  87. }
  88. template <typename T, bool Clockwise, bool Closed>
  89. void test_all(int seed, int count, int field_size, int level, bool triangular, p_q_settings const& settings)
  90. {
  91. boost::timer t;
  92. typedef boost::minstd_rand base_generator_type;
  93. base_generator_type generator(seed);
  94. boost::uniform_int<> random_coordinate(0, field_size - 1);
  95. boost::variate_generator<base_generator_type&, boost::uniform_int<> >
  96. coordinate_generator(generator, random_coordinate);
  97. typedef bg::model::polygon
  98. <
  99. bg::model::d2::point_xy<T>, Clockwise, Closed
  100. > polygon;
  101. typedef bg::model::multi_polygon<polygon> mp;
  102. int index = 0;
  103. for(int i = 0; i < count; i++)
  104. {
  105. mp p;
  106. test_recursive_boxes<mp>(p, index, coordinate_generator, level, triangular, settings);
  107. }
  108. std::cout
  109. << "polygons: " << index
  110. << " type: " << string_from_type<T>::name()
  111. << " time: " << t.elapsed() << std::endl;
  112. }
  113. int main(int argc, char** argv)
  114. {
  115. try
  116. {
  117. namespace po = boost::program_options;
  118. po::options_description description("=== recursive_polygons ===\nAllowed options");
  119. int count = 1;
  120. int seed = static_cast<unsigned int>(std::time(0));
  121. int level = 3;
  122. int field_size = 10;
  123. bool ccw = false;
  124. bool open = false;
  125. p_q_settings settings;
  126. std::string form = "box";
  127. description.add_options()
  128. ("help", "Help message")
  129. ("seed", po::value<int>(&seed), "Initialization seed for random generator")
  130. ("count", po::value<int>(&count)->default_value(1), "Number of tests")
  131. ("diff", po::value<bool>(&settings.also_difference)->default_value(false), "Include testing on difference")
  132. ("validity", po::value<bool>(&settings.validity)->default_value(true), "Include testing on validity")
  133. ("level", po::value<int>(&level)->default_value(3), "Level to reach (higher->slower)")
  134. ("size", po::value<int>(&field_size)->default_value(10), "Size of the field")
  135. ("form", po::value<std::string>(&form)->default_value("box"), "Form of the polygons (box, triangle)")
  136. ("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
  137. ("open", po::value<bool>(&open)->default_value(false), "Open polygons")
  138. ("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
  139. ("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
  140. ;
  141. po::variables_map varmap;
  142. po::store(po::parse_command_line(argc, argv, description), varmap);
  143. po::notify(varmap);
  144. if (varmap.count("help")
  145. || (form != "box" && form != "triangle"))
  146. {
  147. std::cout << description << std::endl;
  148. return 1;
  149. }
  150. bool triangular = form != "box";
  151. if (ccw && open)
  152. {
  153. test_all<double, false, false>(seed, count, field_size, level, triangular, settings);
  154. }
  155. else if (ccw)
  156. {
  157. test_all<double, false, true>(seed, count, field_size, level, triangular, settings);
  158. }
  159. else if (open)
  160. {
  161. test_all<double, true, false>(seed, count, field_size, level, triangular, settings);
  162. }
  163. else
  164. {
  165. test_all<double, true, true>(seed, count, field_size, level, triangular, settings);
  166. }
  167. #if defined(HAVE_TTMATH)
  168. // test_all<ttmath_big, true, true>(seed, count, max, svg, level);
  169. #endif
  170. }
  171. catch(std::exception const& e)
  172. {
  173. std::cout << "Exception " << e.what() << std::endl;
  174. }
  175. catch(...)
  176. {
  177. std::cout << "Other exception" << std::endl;
  178. }
  179. return 0;
  180. }