intersection_pies.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Unit 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/timer.hpp>
  12. template <typename Polygon>
  13. inline void make_pie(Polygon& polygon,
  14. int count, int offset, int offset_y, double factor1, int total_segment_count = 36)
  15. {
  16. typedef typename bg::point_type<Polygon>::type p;
  17. typedef typename bg::select_most_precise
  18. <
  19. typename bg::coordinate_type<Polygon>::type,
  20. long double
  21. >::type coordinate_type;
  22. // Create pie
  23. coordinate_type cx = 2500.0;
  24. coordinate_type cy = 2500.0 + offset_y;
  25. bg::exterior_ring(polygon).push_back(bg::make<p>(int(cx), int(cy)));
  26. coordinate_type const dx = 5000.0;
  27. coordinate_type const dy = 5000.0;
  28. coordinate_type const half = 0.5;
  29. coordinate_type const two = 2.0;
  30. coordinate_type const a = coordinate_type(factor1) * half * dx;
  31. coordinate_type const b = coordinate_type(factor1) * half * dy;
  32. coordinate_type const pi = boost::math::constants::pi<long double>();
  33. coordinate_type const delta = pi * two / total_segment_count;
  34. coordinate_type angle = coordinate_type(offset) * delta;
  35. for (int i = 0; i < count; i++, angle += delta)
  36. {
  37. coordinate_type const s = sin(angle);
  38. coordinate_type const c = cos(angle);
  39. coordinate_type const x = cx + a * s;
  40. coordinate_type const y = cy + b * c;
  41. bg::exterior_ring(polygon).push_back(bg::make<p>(int(x), int(y)));
  42. }
  43. bg::exterior_ring(polygon).push_back(bg::make<p>(int(cx), int(cy)));
  44. bg::correct(polygon);
  45. }
  46. /*
  47. sql server
  48. TWO INNERS
  49. 1a) select geometry::STGeomFromText('POLYGON((0 0,0 10,10 10,10 0,0 0),(4 4,5 5,4 6,4 4),(6 6,5 5,6 4,6 6)) ', 0).STIsValid(); -> valid
  50. same:
  51. 1b) POLYGON((0 0,0 10,10 10,10 0,0 0),(4 4,5 5,6 4,6 6,5 5,4 6,4 4)) -> valid
  52. I-E tangency IET
  53. 2a) select geometry::STGeomFromText('POLYGON((0 0,0 10,10 10,10 0,0 0),(5 0,6 1,4 1,5 0))', 0).STIsValid(); -> valid
  54. same by Self tangency ST
  55. 2b) select geometry::STGeomFromText('POLYGON((0 0,0 10,10 10,10 0,5 0,6 1,4 1,5 0, 0 0))', 0).STIsValid(); -> valid
  56. Two inners all tangent
  57. 3a) POLYGON((0 0,0 10,10 10,10 0,0 0),(5 0,6 1,4 1,5 0),(5 1,6 2,4 2,5 1)) -> valid
  58. postgis:
  59. 1a) select ST_IsValid(ST_GeomFromText('POLYGON((0 0,0 10,10 10,10 0,0 0),(4 4,5 5,4 6,4 4),(6 6,5 5,6 4,6 6))', 0)); -> valid
  60. 1b) POLYGON((0 0,0 10,10 10,10 0,0 0),(4 4,5 5,6 4,6 6,5 5,4 6,4 4)) -> NOT valid
  61. 2a) POLYGON((0 0,0 10,10 10,10 0,0 0),(5 0,6 1,4 1,5 0)) -> valid
  62. 2b) POLYGON((0 0,0 10,10 10,10 0,5 0,6 1,4 1,5 0, 0 0)) -> NOT valid (?)
  63. 3a) POLYGON((0 0,0 10,10 10,10 0,0 0),(5 0,6 1,4 1,5 0),(5 1,6 2,4 2,5 1)) -> valid
  64. */
  65. template <typename Polygon>
  66. inline void holify(Polygon& polygon)
  67. {
  68. typedef typename bg::point_type<Polygon>::type point_type;
  69. Polygon p;
  70. bg::exterior_ring(p).push_back(bg::make<point_type>(0, 0));
  71. bg::exterior_ring(p).push_back(bg::make<point_type>(0, 5000));
  72. bg::exterior_ring(p).push_back(bg::make<point_type>(5000, 5000));
  73. bg::exterior_ring(p).push_back(bg::make<point_type>(5000, 0));
  74. bg::exterior_ring(p).push_back(bg::make<point_type>(0, 0));
  75. bg::interior_rings(p).push_back(bg::exterior_ring(polygon));
  76. bg::correct(p);
  77. polygon = p;
  78. }
  79. template <typename MultiPolygon>
  80. inline void holify_multi(MultiPolygon& multi_polygon)
  81. {
  82. typedef typename bg::point_type<MultiPolygon>::type point_type;
  83. typename boost::range_value<MultiPolygon>::type p;
  84. bg::exterior_ring(p).push_back(bg::make<point_type>(0, 0));
  85. bg::exterior_ring(p).push_back(bg::make<point_type>(0, 5000));
  86. bg::exterior_ring(p).push_back(bg::make<point_type>(5000, 5000));
  87. bg::exterior_ring(p).push_back(bg::make<point_type>(5000, 0));
  88. bg::exterior_ring(p).push_back(bg::make<point_type>(0, 0));
  89. for (int i = 0; i < multi_polygon.size(); i++)
  90. {
  91. bg::interior_rings(p).push_back(bg::exterior_ring(multi_polygon[i]));
  92. }
  93. bg::correct(p);
  94. multi_polygon.clear();
  95. multi_polygon.push_back(p);
  96. }
  97. template <typename T, bool Clockwise, bool Closed>
  98. void test_pie(int total_segment_count, T factor_p, T factor_q,
  99. bool multi, bool single_selftangent, p_q_settings const& settings)
  100. {
  101. boost::timer t;
  102. typedef bg::model::d2::point_xy<T> point_type;
  103. typedef bg::model::polygon<point_type, Clockwise, Closed> polygon;
  104. typedef bg::model::multi_polygon<polygon> multi_polygon;
  105. int good_count = 0;
  106. int bad_count = 0;
  107. for (int a = 2; a < total_segment_count; a++)
  108. {
  109. polygon p;
  110. make_pie(p, a, 0, 0, factor_p, total_segment_count);
  111. //holify(p);
  112. for (int b = 2; b < total_segment_count; b++)
  113. {
  114. for (int offset = 1; offset < total_segment_count; offset++)
  115. {
  116. //for (int y = 0; y <= 2500; y += 500)
  117. int y = 0;
  118. {
  119. polygon q;
  120. make_pie(q, b, offset, y, factor_q, total_segment_count);
  121. if (! multi)
  122. {
  123. //holify(q);
  124. std::ostringstream out;
  125. out << "pie_" << a << "_" << b << "_" << offset << "_" << y;
  126. if (test_overlay_p_q<polygon, T>(out.str(), p, q, settings))
  127. {
  128. good_count++;
  129. }
  130. else
  131. {
  132. bad_count++;
  133. }
  134. }
  135. else
  136. {
  137. int left = total_segment_count - b - 2;
  138. //std::cout << a << " " << b << " " << left << std::endl;
  139. for (int c = 2; c < left; c++)
  140. {
  141. polygon q2;
  142. make_pie(q2, c, offset + b + 1, y, factor_q, total_segment_count);
  143. std::ostringstream out;
  144. out << "pie_" << a << "_" << b << "_" << offset << "_" << y
  145. << "_" << c
  146. ;
  147. bool good = false;
  148. // Represent as either multi-polygon, or as single-self-touching-polygon (INVALID)
  149. if (single_selftangent)
  150. {
  151. polygon q1 = q;
  152. for (unsigned int i = 1; i < q2.outer().size(); i++)
  153. {
  154. q1.outer().push_back(q2.outer()[i]);
  155. }
  156. //holify(q1);
  157. good = test_overlay_p_q<polygon, T>(out.str(), p, q1, settings);
  158. }
  159. else
  160. {
  161. multi_polygon mq;
  162. mq.push_back(q);
  163. mq.push_back(q2);
  164. //holify_multi(mq);
  165. good = test_overlay_p_q<polygon, T>(out.str(), p, mq, settings);
  166. }
  167. if (good)
  168. {
  169. good_count++;
  170. }
  171. else
  172. {
  173. bad_count++;
  174. }
  175. }
  176. }
  177. }
  178. }
  179. }
  180. }
  181. std::cout
  182. << "Time: " << t.elapsed() << std::endl
  183. << "Good: " << good_count << std::endl
  184. << "Bad: " << bad_count << std::endl;
  185. }
  186. template <typename T, bool Clockwise, bool Closed>
  187. void test_all(bool multi, bool single_selftangent, p_q_settings const& settings)
  188. {
  189. test_pie<T, Clockwise, Closed>(24, 0.55, 0.45, multi, single_selftangent, settings);
  190. }
  191. int main(int argc, char** argv)
  192. {
  193. try
  194. {
  195. namespace po = boost::program_options;
  196. po::options_description description("=== intersection_pies ===\nAllowed options");
  197. p_q_settings settings;
  198. bool multi = false;
  199. bool ccw = false;
  200. bool open = false;
  201. bool single_selftangent = false; // keep false, true does not work!
  202. description.add_options()
  203. ("help", "Help message")
  204. ("multi", po::value<bool>(&multi)->default_value(false), "Multiple tangencies at one point")
  205. ("diff", po::value<bool>(&settings.also_difference)->default_value(false), "Include testing on difference")
  206. ("ccw", po::value<bool>(&ccw)->default_value(false), "Counter clockwise polygons")
  207. ("open", po::value<bool>(&open)->default_value(false), "Open polygons")
  208. ("wkt", po::value<bool>(&settings.wkt)->default_value(false), "Create a WKT of the inputs, for all tests")
  209. ("svg", po::value<bool>(&settings.svg)->default_value(false), "Create a SVG for all tests")
  210. ;
  211. po::variables_map varmap;
  212. po::store(po::parse_command_line(argc, argv, description), varmap);
  213. po::notify(varmap);
  214. if (varmap.count("help"))
  215. {
  216. std::cout << description << std::endl;
  217. return 1;
  218. }
  219. // template par's are: CoordinateType, Clockwise, Closed
  220. if (ccw && open)
  221. {
  222. test_all<double, false, false>(multi, single_selftangent, settings);
  223. }
  224. else if (ccw)
  225. {
  226. test_all<double, false, true>(multi, single_selftangent, settings);
  227. }
  228. else if (open)
  229. {
  230. test_all<double, true, false>(multi, single_selftangent, settings);
  231. }
  232. else
  233. {
  234. test_all<double, true, true>(multi, single_selftangent, settings);
  235. }
  236. //test_all<long double>();
  237. }
  238. catch(std::exception const& e)
  239. {
  240. std::cout << "Exception " << e.what() << std::endl;
  241. }
  242. catch(...)
  243. {
  244. std::cout << "Other exception" << std::endl;
  245. }
  246. return 0;
  247. }