ticket_9081.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // Boost.Geometry (aka GGL, Generic Geometry Library) // Robustness Test
  2. // Copyright (c) 2013-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Use, modification and distribution is subject to the Boost Software License,
  4. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // Adapted from: the attachment of ticket 9081
  7. #define CHECK_SELF_INTERSECTIONS
  8. #define LIST_WKT
  9. #include <iomanip>
  10. #include <iostream>
  11. #include <vector>
  12. #include <boost/geometry.hpp>
  13. #include <boost/geometry/geometries/point_xy.hpp>
  14. #include <boost/geometry/geometries/polygon.hpp>
  15. #include <boost/geometry/geometries/register/point.hpp>
  16. #include <boost/geometry/geometries/register/ring.hpp>
  17. #include <boost/geometry/io/wkt/wkt.hpp>
  18. #include <boost/geometry/geometries/multi_polygon.hpp>
  19. #include <boost/foreach.hpp>
  20. #include <boost/timer.hpp>
  21. #include <boost/algorithm/string.hpp>
  22. #include <boost/geometry/io/svg/svg_mapper.hpp>
  23. #include <fstream>
  24. typedef boost::geometry::model::d2::point_xy<double> pt;
  25. typedef boost::geometry::model::polygon<pt> polygon;
  26. typedef boost::geometry::model::segment<pt> segment;
  27. typedef boost::geometry::model::multi_polygon<polygon> multi_polygon;
  28. template <typename Geometry>
  29. inline void debug_with_svg(int index, char method, Geometry const& a, Geometry const& b, std::string const& headera, std::string const& headerb)
  30. {
  31. multi_polygon output;
  32. try
  33. {
  34. switch(method)
  35. {
  36. case 'i': boost::geometry::intersection(a, b, output); break;
  37. case 'u': boost::geometry::union_(a, b, output); break;
  38. case 'd': boost::geometry::difference(a, b, output); break;
  39. case 'v': boost::geometry::difference(b, a, output); break;
  40. default : return;
  41. }
  42. }
  43. catch(...)
  44. {}
  45. std::ostringstream filename;
  46. filename << "ticket_9081_" << method << "_" << (1000000 + index) << ".svg";
  47. std::ofstream svg(filename.str().c_str());
  48. boost::geometry::svg_mapper<pt> mapper(svg, 400, 400);
  49. mapper.add(a);
  50. mapper.add(b);
  51. mapper.map(a, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
  52. mapper.map(b, "fill-opacity:0.3;fill:rgb(51,51,153);stroke:rgb(51,51,153);stroke-width:2");
  53. BOOST_FOREACH(polygon const& g, output)
  54. {
  55. mapper.map(g, "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
  56. }
  57. std::ostringstream out;
  58. out << headera << std::endl << headerb;
  59. mapper.map(boost::geometry::return_centroid<pt>(a), "fill:rgb(152,204,0);stroke:rgb(153,204,0);stroke-width:0.1", 3);
  60. mapper.map(boost::geometry::return_centroid<pt>(b), "fill:rgb(51,51,153);stroke:rgb(153,204,0);stroke-width:0.1", 3);
  61. mapper.text(boost::geometry::return_centroid<pt>(a), headera, "fill:rgb(0,0,0);font-family:Arial;font-size:10px");
  62. mapper.text(boost::geometry::return_centroid<pt>(b), headerb, "fill:rgb(0,0,0);font-family:Arial;font-size:10px");
  63. }
  64. int main()
  65. {
  66. int num_orig = 50;
  67. int num_rounds = 30000;
  68. srand(1234);
  69. std::cout << std::setprecision(16);
  70. std::map<int, std::string> genesis;
  71. int pj;
  72. std::string wkt1, wkt2, operation;
  73. try
  74. {
  75. boost::timer t;
  76. std::vector<multi_polygon> poly_list;
  77. for(int i=0;i<num_orig;i++)
  78. {
  79. multi_polygon mp;
  80. polygon p;
  81. for(int j=0;j<3;j++)
  82. {
  83. double x=(double)rand()/RAND_MAX;
  84. double y=(double)rand()/RAND_MAX;
  85. p.outer().push_back(pt(x,y));
  86. }
  87. boost::geometry::correct(p);
  88. mp.push_back(p);
  89. boost::geometry::detail::overlay::has_self_intersections(mp);
  90. std::ostringstream out;
  91. out << "original " << poly_list.size();
  92. genesis[poly_list.size()] = out.str();
  93. poly_list.push_back(mp);
  94. #ifdef LIST_WKT
  95. std::cout << "Original " << i << " " << boost::geometry::wkt(p) << std::endl;
  96. #endif
  97. }
  98. for(int j=0;j<num_rounds;j++)
  99. {
  100. if (j % 100 == 0) { std::cout << " " << j; }
  101. pj = j;
  102. int a = rand() % poly_list.size();
  103. int b = rand() % poly_list.size();
  104. debug_with_svg(j, 'i', poly_list[a], poly_list[b], genesis[a], genesis[b]);
  105. { std::ostringstream out; out << boost::geometry::wkt(poly_list[a]); wkt1 = out.str(); }
  106. { std::ostringstream out; out << boost::geometry::wkt(poly_list[b]); wkt2 = out.str(); }
  107. multi_polygon mp_i, mp_u, mp_d, mp_e;
  108. operation = "intersection";
  109. boost::geometry::intersection(poly_list[a],poly_list[b],mp_i);
  110. operation = "intersection";
  111. boost::geometry::union_(poly_list[a],poly_list[b],mp_u);
  112. operation = "difference";
  113. boost::geometry::difference(poly_list[a],poly_list[b],mp_d);
  114. boost::geometry::difference(poly_list[b],poly_list[a],mp_e);
  115. #ifdef LIST_WKT
  116. std::cout << j << std::endl;
  117. std::cout << " Genesis a " << genesis[a] << std::endl;
  118. std::cout << " Genesis b " << genesis[b] << std::endl;
  119. std::cout << " Intersection " << boost::geometry::wkt(mp_i) << std::endl;
  120. std::cout << " Difference a " << boost::geometry::wkt(mp_d) << std::endl;
  121. std::cout << " Difference b " << boost::geometry::wkt(mp_e) << std::endl;
  122. #endif
  123. #ifdef CHECK_SELF_INTERSECTIONS
  124. try
  125. {
  126. boost::geometry::detail::overlay::has_self_intersections(mp_i);
  127. }
  128. catch(...)
  129. {
  130. std::cout << "FAILED TO INTERSECT " << j << std::endl;
  131. std::cout << boost::geometry::wkt(poly_list[a]) << std::endl;
  132. std::cout << boost::geometry::wkt(poly_list[b]) << std::endl;
  133. std::cout << boost::geometry::wkt(mp_i) << std::endl;
  134. try
  135. {
  136. boost::geometry::detail::overlay::has_self_intersections(mp_i);
  137. }
  138. catch(...)
  139. {
  140. }
  141. break;
  142. }
  143. try
  144. {
  145. boost::geometry::detail::overlay::has_self_intersections(mp_d);
  146. }
  147. catch(...)
  148. {
  149. std::cout << "FAILED TO SUBTRACT " << j << std::endl;
  150. std::cout << boost::geometry::wkt(poly_list[a]) << std::endl;
  151. std::cout << boost::geometry::wkt(poly_list[b]) << std::endl;
  152. std::cout << boost::geometry::wkt(mp_d) << std::endl;
  153. break;
  154. }
  155. try
  156. {
  157. boost::geometry::detail::overlay::has_self_intersections(mp_e);
  158. }
  159. catch(...)
  160. {
  161. std::cout << "FAILED TO SUBTRACT " << j << std::endl;
  162. std::cout << boost::geometry::wkt(poly_list[b]) << std::endl;
  163. std::cout << boost::geometry::wkt(poly_list[a]) << std::endl;
  164. std::cout << boost::geometry::wkt(mp_e) << std::endl;
  165. break;
  166. }
  167. #endif
  168. if(boost::geometry::area(mp_i) > 0)
  169. {
  170. std::ostringstream out;
  171. out << j << " intersection(" << genesis[a] << " , " << genesis[b] << ")";
  172. genesis[poly_list.size()] = out.str();
  173. poly_list.push_back(mp_i);
  174. }
  175. if(boost::geometry::area(mp_d) > 0)
  176. {
  177. std::ostringstream out;
  178. out << j << " difference(" << genesis[a] << " - " << genesis[b] << ")";
  179. genesis[poly_list.size()] = out.str();
  180. poly_list.push_back(mp_d);
  181. }
  182. if(boost::geometry::area(mp_e) > 0)
  183. {
  184. std::ostringstream out;
  185. out << j << " difference(" << genesis[b] << " - " << genesis[a] << ")";
  186. genesis[poly_list.size()] = out.str();
  187. poly_list.push_back(mp_e);
  188. }
  189. }
  190. std::cout << "FINISHED " << t.elapsed() << std::endl;
  191. }
  192. catch(std::exception const& e)
  193. {
  194. std::cout << e.what()
  195. << " in " << operation << " at " << pj << std::endl
  196. << wkt1 << std::endl
  197. << wkt2 << std::endl
  198. << std::endl;
  199. }
  200. catch(...)
  201. {
  202. std::cout << "Other exception" << std::endl;
  203. }
  204. return 0;
  205. }