voronoi_builder_test.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. // Boost.Polygon library voronoi_builder_test.cpp file
  2. // Copyright Andrii Sydorchuk 2010-2012.
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // See http://www.boost.org for updates, documentation, and revision history.
  7. #include "voronoi_test_helper.hpp"
  8. #include <boost/core/lightweight_test.hpp>
  9. #include <boost/polygon/polygon.hpp>
  10. #include <boost/polygon/voronoi.hpp>
  11. #include <boost/random/mersenne_twister.hpp>
  12. #include <limits>
  13. #include <list>
  14. #include <vector>
  15. #include <ctime>
  16. using boost::polygon::voronoi_builder;
  17. using boost::polygon::voronoi_diagram;
  18. typedef voronoi_diagram<double> vd_type;
  19. typedef vd_type::coordinate_type coordinate_type;
  20. typedef vd_type::edge_type voronoi_edge_type;
  21. typedef vd_type::const_cell_iterator const_cell_iterator;
  22. typedef vd_type::const_vertex_iterator const_vertex_iterator;
  23. #define CHECK_OUTPUT_SIZE(output, cells, vertices, edges) \
  24. BOOST_TEST_EQ(output.num_cells(), (std::size_t)cells); \
  25. BOOST_TEST_EQ(output.num_vertices(), (std::size_t)vertices); \
  26. BOOST_TEST_EQ(output.num_edges(), (std::size_t)edges)
  27. #define VERIFY_OUTPUT(output) \
  28. BOOST_TEST(voronoi_test_helper::verify_output(output, \
  29. voronoi_test_helper::CELL_CONVEXITY)); \
  30. BOOST_TEST(voronoi_test_helper::verify_output(output, \
  31. voronoi_test_helper::INCIDENT_EDGES_CCW_ORDER)); \
  32. BOOST_TEST(voronoi_test_helper::verify_output(output, \
  33. voronoi_test_helper::NO_HALF_EDGE_INTERSECTIONS))
  34. #define VERIFY_NO_HALF_EDGE_INTERSECTIONS(output) \
  35. BOOST_TEST(voronoi_test_helper::verify_output(output, \
  36. voronoi_test_helper::NO_HALF_EDGE_INTERSECTIONS))
  37. // Sites: (0, 0).
  38. void single_site_test()
  39. {
  40. std::vector< point_data<int> > points;
  41. points.push_back(point_data<int>(0, 0));
  42. vd_type test_output;
  43. construct_voronoi(points.begin(), points.end(), &test_output);
  44. VERIFY_OUTPUT(test_output);
  45. BOOST_TEST(test_output.cells().size() == 1);
  46. CHECK_OUTPUT_SIZE(test_output, 1, 0, 0);
  47. const_cell_iterator it = test_output.cells().begin();
  48. BOOST_TEST(it->incident_edge() == NULL);
  49. }
  50. // Sites: (0, 0), (0, 1).
  51. void collinear_sites_test1()
  52. {
  53. std::vector< point_data<int> > points;
  54. points.push_back(point_data<int>(0, 0));
  55. points.push_back(point_data<int>(0, 1));
  56. vd_type test_output;
  57. construct_voronoi(points.begin(), points.end(), &test_output);
  58. VERIFY_OUTPUT(test_output);
  59. CHECK_OUTPUT_SIZE(test_output, 2, 0, 2);
  60. const_cell_iterator cell_it = test_output.cells().begin();
  61. cell_it++;
  62. const voronoi_edge_type* edge1_1 = cell_it->incident_edge();
  63. const voronoi_edge_type* edge1_2 = edge1_1->twin();
  64. BOOST_TEST(edge1_1->twin() == edge1_2);
  65. BOOST_TEST(edge1_2->twin() == edge1_1);
  66. BOOST_TEST(edge1_1->next() == edge1_1);
  67. BOOST_TEST(edge1_1->prev() == edge1_1);
  68. BOOST_TEST(edge1_1->rot_next() == edge1_2);
  69. BOOST_TEST(edge1_1->rot_prev() == edge1_2);
  70. BOOST_TEST(edge1_2->next() == edge1_2);
  71. BOOST_TEST(edge1_2->prev() == edge1_2);
  72. BOOST_TEST(edge1_2->rot_next() == edge1_1);
  73. BOOST_TEST(edge1_2->rot_prev() == edge1_1);
  74. }
  75. // Sites: (0, 0), (1, 1), (2, 2).
  76. void collinear_sites_test2()
  77. {
  78. std::vector< point_data<int> > points;
  79. points.push_back(point_data<int>(0, 0));
  80. points.push_back(point_data<int>(1, 1));
  81. points.push_back(point_data<int>(2, 2));
  82. vd_type test_output;
  83. construct_voronoi(points.begin(), points.end(), &test_output);
  84. VERIFY_OUTPUT(test_output);
  85. CHECK_OUTPUT_SIZE(test_output, 3, 0, 4);
  86. const_cell_iterator cell_it = test_output.cells().begin();
  87. const voronoi_edge_type* edge1_1 = cell_it->incident_edge();
  88. const voronoi_edge_type* edge1_2 = edge1_1->twin();
  89. cell_it++;
  90. cell_it++;
  91. const voronoi_edge_type* edge2_2 = cell_it->incident_edge();
  92. const voronoi_edge_type* edge2_1 = edge2_2->twin();
  93. BOOST_TEST(edge1_1->twin() == edge1_2 && edge1_2->twin() == edge1_1);
  94. BOOST_TEST(edge2_1->twin() == edge2_2 && edge2_2->twin() == edge2_1);
  95. BOOST_TEST(edge1_1->next() == edge1_1 && edge1_1->prev() == edge1_1);
  96. BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1);
  97. BOOST_TEST(edge2_1->next() == edge1_2 && edge2_1->prev() == edge1_2);
  98. BOOST_TEST(edge2_2->next() == edge2_2 && edge2_2->prev() == edge2_2);
  99. BOOST_TEST(edge1_1->rot_next() == edge1_2 && edge1_1->rot_prev() == edge2_1);
  100. BOOST_TEST(edge1_2->rot_next() == edge2_2 && edge1_2->rot_prev() == edge1_1);
  101. BOOST_TEST(edge2_1->rot_next() == edge1_1 && edge2_1->rot_prev() == edge2_2);
  102. BOOST_TEST(edge2_2->rot_next() == edge2_1 && edge2_2->rot_prev() == edge1_2);
  103. BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1);
  104. BOOST_TEST(edge2_1->next() == edge1_2 && edge2_1->prev() == edge1_2);
  105. }
  106. // Sites: (0, 0), (0, 4), (2, 1).
  107. void triangle_test1()
  108. {
  109. point_data<int> point1(0, 0);
  110. point_data<int> point2(0, 4);
  111. point_data<int> point3(2, 1);
  112. std::vector< point_data<int> > points;
  113. points.push_back(point1);
  114. points.push_back(point2);
  115. points.push_back(point3);
  116. vd_type test_output;
  117. construct_voronoi(points.begin(), points.end(), &test_output);
  118. VERIFY_OUTPUT(test_output);
  119. CHECK_OUTPUT_SIZE(test_output, 3, 1, 6);
  120. const_vertex_iterator it = test_output.vertices().begin();
  121. BOOST_TEST_EQ(it->x(), 0.25);
  122. BOOST_TEST_EQ(it->y(), 2.0);
  123. const voronoi_edge_type* edge1_1 = it->incident_edge();
  124. const voronoi_edge_type* edge1_2 = edge1_1->twin();
  125. BOOST_TEST(edge1_1->cell()->source_index() == 1);
  126. BOOST_TEST(edge1_2->cell()->source_index() == 2);
  127. const voronoi_edge_type* edge2_1 = edge1_1->rot_prev();
  128. const voronoi_edge_type* edge2_2 = edge2_1->twin();
  129. BOOST_TEST(edge2_1->cell()->source_index() == 2);
  130. BOOST_TEST(edge2_2->cell()->source_index() == 0);
  131. const voronoi_edge_type* edge3_1 = edge2_1->rot_prev();
  132. const voronoi_edge_type* edge3_2 = edge3_1->twin();
  133. BOOST_TEST(edge3_1->cell()->source_index() == 0);
  134. BOOST_TEST(edge3_2->cell()->source_index() == 1);
  135. BOOST_TEST(edge1_2->twin() == edge1_1);
  136. BOOST_TEST(edge2_2->twin() == edge2_1);
  137. BOOST_TEST(edge3_2->twin() == edge3_1);
  138. BOOST_TEST(edge1_1->prev() == edge3_2 && edge1_1->next() == edge3_2);
  139. BOOST_TEST(edge2_1->prev() == edge1_2 && edge2_1->next() == edge1_2);
  140. BOOST_TEST(edge3_1->prev() == edge2_2 && edge3_1->next() == edge2_2);
  141. BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1);
  142. BOOST_TEST(edge2_2->next() == edge3_1 && edge2_2->prev() == edge3_1);
  143. BOOST_TEST(edge3_2->next() == edge1_1 && edge3_2->prev() == edge1_1);
  144. BOOST_TEST(edge1_1->rot_next() == edge3_1);
  145. BOOST_TEST(edge3_1->rot_next() == edge2_1);
  146. BOOST_TEST(edge2_1->rot_next() == edge1_1);
  147. BOOST_TEST(edge1_2->rot_next() == edge2_2);
  148. BOOST_TEST(edge2_2->rot_next() == edge3_2);
  149. BOOST_TEST(edge3_2->rot_next() == edge1_2);
  150. }
  151. // Sites: (0, 1), (2, 0), (2, 4).
  152. void triangle_test2()
  153. {
  154. point_data<int> point1(0, 1);
  155. point_data<int> point2(2, 0);
  156. point_data<int> point3(2, 4);
  157. std::vector< point_data<int> > points;
  158. points.push_back(point1);
  159. points.push_back(point2);
  160. points.push_back(point3);
  161. vd_type test_output;
  162. construct_voronoi(points.begin(), points.end(), &test_output);
  163. VERIFY_OUTPUT(test_output);
  164. CHECK_OUTPUT_SIZE(test_output, 3, 1, 6);
  165. const_vertex_iterator it = test_output.vertices().begin();
  166. BOOST_TEST_EQ(it->x(), 1.75);
  167. BOOST_TEST_EQ(it->y(), 2.0);
  168. const voronoi_edge_type* edge1_1 = it->incident_edge();
  169. const voronoi_edge_type* edge1_2 = edge1_1->twin();
  170. BOOST_TEST(edge1_1->cell()->source_index() == 2);
  171. BOOST_TEST(edge1_2->cell()->source_index() == 1);
  172. const voronoi_edge_type* edge2_1 = edge1_1->rot_prev();
  173. const voronoi_edge_type* edge2_2 = edge2_1->twin();
  174. BOOST_TEST(edge2_1->cell()->source_index() == 1);
  175. BOOST_TEST(edge2_2->cell()->source_index() == 0);
  176. const voronoi_edge_type* edge3_1 = edge2_1->rot_prev();
  177. const voronoi_edge_type* edge3_2 = edge3_1->twin();
  178. BOOST_TEST(edge3_1->cell()->source_index() == 0);
  179. BOOST_TEST(edge3_2->cell()->source_index() == 2);
  180. BOOST_TEST(edge1_2->twin() == edge1_1);
  181. BOOST_TEST(edge2_2->twin() == edge2_1);
  182. BOOST_TEST(edge3_2->twin() == edge3_1);
  183. BOOST_TEST(edge1_1->prev() == edge3_2 && edge1_1->next() == edge3_2);
  184. BOOST_TEST(edge2_1->prev() == edge1_2 && edge2_1->next() == edge1_2);
  185. BOOST_TEST(edge3_1->prev() == edge2_2 && edge3_1->next() == edge2_2);
  186. BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1);
  187. BOOST_TEST(edge2_2->next() == edge3_1 && edge2_2->prev() == edge3_1);
  188. BOOST_TEST(edge3_2->next() == edge1_1 && edge3_2->prev() == edge1_1);
  189. BOOST_TEST(edge1_1->rot_next() == edge3_1);
  190. BOOST_TEST(edge3_1->rot_next() == edge2_1);
  191. BOOST_TEST(edge2_1->rot_next() == edge1_1);
  192. BOOST_TEST(edge1_2->rot_next() == edge2_2);
  193. BOOST_TEST(edge2_2->rot_next() == edge3_2);
  194. BOOST_TEST(edge3_2->rot_next() == edge1_2);
  195. }
  196. // Sites: (0, 0), (0, 1), (1, 0), (1, 1).
  197. void square_test1()
  198. {
  199. point_data<int> point1(0, 0);
  200. point_data<int> point2(0, 1);
  201. point_data<int> point3(1, 0);
  202. point_data<int> point4(1, 1);
  203. std::vector< point_data<int> > points;
  204. points.push_back(point1);
  205. points.push_back(point2);
  206. points.push_back(point3);
  207. points.push_back(point4);
  208. vd_type test_output;
  209. construct_voronoi(points.begin(), points.end(), &test_output);
  210. VERIFY_OUTPUT(test_output);
  211. CHECK_OUTPUT_SIZE(test_output, 4, 1, 8);
  212. // Check voronoi vertex.
  213. const_vertex_iterator it = test_output.vertices().begin();
  214. BOOST_TEST_EQ(it->x(), 0.5);
  215. BOOST_TEST_EQ(it->y(), 0.5);
  216. // Check voronoi edges.
  217. const voronoi_edge_type* edge1_1 = it->incident_edge();
  218. const voronoi_edge_type* edge1_2 = edge1_1->twin();
  219. BOOST_TEST(edge1_1->cell()->source_index() == 3);
  220. BOOST_TEST(edge1_2->cell()->source_index() == 2);
  221. const voronoi_edge_type* edge2_1 = edge1_1->rot_prev();
  222. const voronoi_edge_type* edge2_2 = edge2_1->twin();
  223. BOOST_TEST(edge2_1->cell()->source_index() == 2);
  224. BOOST_TEST(edge2_2->cell()->source_index() == 0);
  225. const voronoi_edge_type* edge3_1 = edge2_1->rot_prev();
  226. const voronoi_edge_type* edge3_2 = edge3_1->twin();
  227. BOOST_TEST(edge3_1->cell()->source_index() == 0);
  228. BOOST_TEST(edge3_2->cell()->source_index() == 1);
  229. const voronoi_edge_type* edge4_1 = edge3_1->rot_prev();
  230. const voronoi_edge_type* edge4_2 = edge4_1->twin();
  231. BOOST_TEST(edge4_1->cell()->source_index() == 1);
  232. BOOST_TEST(edge4_2->cell()->source_index() == 3);
  233. BOOST_TEST(edge1_2->twin() == edge1_1);
  234. BOOST_TEST(edge2_2->twin() == edge2_1);
  235. BOOST_TEST(edge3_2->twin() == edge3_1);
  236. BOOST_TEST(edge4_2->twin() == edge4_1);
  237. BOOST_TEST(edge1_1->prev() == edge4_2 && edge1_1->next() == edge4_2);
  238. BOOST_TEST(edge2_1->prev() == edge1_2 && edge2_1->next() == edge1_2);
  239. BOOST_TEST(edge3_1->prev() == edge2_2 && edge3_1->next() == edge2_2);
  240. BOOST_TEST(edge4_1->prev() == edge3_2 && edge4_1->next() == edge3_2);
  241. BOOST_TEST(edge1_2->next() == edge2_1 && edge1_2->prev() == edge2_1);
  242. BOOST_TEST(edge2_2->next() == edge3_1 && edge2_2->prev() == edge3_1);
  243. BOOST_TEST(edge3_2->next() == edge4_1 && edge3_2->prev() == edge4_1);
  244. BOOST_TEST(edge4_2->next() == edge1_1 && edge4_2->prev() == edge1_1);
  245. BOOST_TEST(edge1_1->rot_next() == edge4_1);
  246. BOOST_TEST(edge4_1->rot_next() == edge3_1);
  247. BOOST_TEST(edge3_1->rot_next() == edge2_1);
  248. BOOST_TEST(edge2_1->rot_next() == edge1_1);
  249. BOOST_TEST(edge1_2->rot_next() == edge2_2);
  250. BOOST_TEST(edge2_2->rot_next() == edge3_2);
  251. BOOST_TEST(edge3_2->rot_next() == edge4_2);
  252. BOOST_TEST(edge4_2->rot_next() == edge1_2);
  253. }
  254. #ifdef NDEBUG
  255. void grid_test()
  256. {
  257. vd_type test_output_small, test_output_large;
  258. std::vector< point_data<int> > point_vec_small, point_vec_large;
  259. int grid_size[] = {10, 33, 101};
  260. int max_value[] = {10, 33, 101};
  261. int array_length = sizeof(grid_size) / sizeof(int);
  262. for (int k = 0; k < array_length; k++) {
  263. test_output_small.clear();
  264. test_output_large.clear();
  265. point_vec_small.clear();
  266. point_vec_large.clear();
  267. int koef = (std::numeric_limits<int>::max)() / max_value[k];
  268. for (int i = 0; i < grid_size[k]; i++) {
  269. for (int j = 0; j < grid_size[k]; j++) {
  270. point_vec_small.push_back(point_data<int>(i, j));
  271. point_vec_large.push_back(point_data<int>(koef * i, koef * j));
  272. }
  273. }
  274. construct_voronoi(point_vec_small.begin(), point_vec_small.end(), &test_output_small);
  275. construct_voronoi(point_vec_large.begin(), point_vec_large.end(), &test_output_large);
  276. VERIFY_OUTPUT(test_output_small);
  277. VERIFY_OUTPUT(test_output_large);
  278. unsigned int num_cells = grid_size[k] * grid_size[k];
  279. unsigned int num_vertices = num_cells - 2 * grid_size[k] + 1;
  280. unsigned int num_edges = 4 * num_cells - 4 * grid_size[k];
  281. CHECK_OUTPUT_SIZE(test_output_small, num_cells, num_vertices, num_edges);
  282. CHECK_OUTPUT_SIZE(test_output_large, num_cells, num_vertices, num_edges);
  283. }
  284. }
  285. #endif
  286. #ifdef NDEBUG
  287. void random_test()
  288. {
  289. boost::mt19937 gen(static_cast<unsigned int>(time(NULL)));
  290. vd_type test_output_small, test_output_large;
  291. std::vector< point_data<int> > point_vec_small, point_vec_large;
  292. int num_points[] = {10, 100, 1000, 10000};
  293. int num_runs[] = {1000, 100, 10, 1};
  294. int mod_koef[] = {10, 100, 100, 1000};
  295. int max_value[] = {5, 50, 50, 5000};
  296. int array_length = sizeof(num_points) / sizeof(int);
  297. for (int k = 0; k < array_length; k++) {
  298. int koef = (std::numeric_limits<int>::max)() / max_value[k];
  299. for (int i = 0; i < num_runs[k]; i++) {
  300. test_output_small.clear();
  301. test_output_large.clear();
  302. point_vec_small.clear();
  303. point_vec_large.clear();
  304. for (int j = 0; j < num_points[k]; j++) {
  305. int x = gen() % mod_koef[k] - mod_koef[k] / 2;
  306. int y = gen() % mod_koef[k] - mod_koef[k] / 2;
  307. point_vec_small.push_back(point_data<int>(x, y));
  308. point_vec_large.push_back(point_data<int>(koef * x, koef * y));
  309. }
  310. construct_voronoi(point_vec_small.begin(), point_vec_small.end(), &test_output_small);
  311. construct_voronoi(point_vec_large.begin(), point_vec_large.end(), &test_output_large);
  312. VERIFY_OUTPUT(test_output_small);
  313. VERIFY_OUTPUT(test_output_large);
  314. BOOST_TEST_EQ(test_output_small.num_cells(), test_output_large.num_cells());
  315. BOOST_TEST_EQ(test_output_small.num_vertices(), test_output_large.num_vertices());
  316. BOOST_TEST_EQ(test_output_small.num_edges(), test_output_large.num_edges());
  317. }
  318. }
  319. }
  320. #endif
  321. void segment_sites_test1()
  322. {
  323. vd_type test_output;
  324. std::vector< segment_data<int> > segments;
  325. point_data<int> point1(0, 0);
  326. point_data<int> point2(1, 1);
  327. segments.push_back(segment_data<int>(point1, point2));
  328. construct_voronoi(segments.begin(), segments.end(), &test_output);
  329. CHECK_OUTPUT_SIZE(test_output, 3, 0, 4);
  330. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  331. }
  332. void segment_sites_test2()
  333. {
  334. vd_type test_output;
  335. std::vector< point_data<int> > points;
  336. std::vector< segment_data<int> > segments;
  337. point_data<int> point1(0, 0);
  338. point_data<int> point2(4, 4);
  339. point_data<int> point3(3, 1);
  340. point_data<int> point4(1, 3);
  341. segments.push_back(segment_data<int>(point1, point2));
  342. points.push_back(point3);
  343. points.push_back(point4);
  344. construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
  345. CHECK_OUTPUT_SIZE(test_output, 5, 4, 16);
  346. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  347. }
  348. void segment_sites_test3()
  349. {
  350. vd_type test_output;
  351. std::vector< point_data<int> > points;
  352. std::vector< segment_data<int> > segments;
  353. point_data<int> point1(4, 0);
  354. point_data<int> point2(0, 4);
  355. point_data<int> point3(3, 3);
  356. point_data<int> point4(1, 1);
  357. segments.push_back(segment_data<int>(point1, point2));
  358. points.push_back(point3);
  359. points.push_back(point4);
  360. construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
  361. CHECK_OUTPUT_SIZE(test_output, 5, 4, 16);
  362. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  363. }
  364. void segment_sites_test4()
  365. {
  366. vd_type test_output;
  367. std::vector< point_data<int> > points;
  368. std::vector< segment_data<int> > segments;
  369. point_data<int> point1(4, 0);
  370. point_data<int> point2(0, 4);
  371. point_data<int> point3(3, 2);
  372. point_data<int> point4(2, 3);
  373. segments.push_back(segment_data<int>(point1, point2));
  374. points.push_back(point3);
  375. points.push_back(point4);
  376. construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
  377. CHECK_OUTPUT_SIZE(test_output, 5, 3, 14);
  378. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  379. }
  380. void segment_site_test5()
  381. {
  382. vd_type test_output;
  383. std::vector< point_data<int> > points;
  384. std::vector< segment_data<int> > segments;
  385. point_data<int> point1(0, 0);
  386. point_data<int> point2(0, 8);
  387. point_data<int> point3(-2, -2);
  388. point_data<int> point4(-2, 4);
  389. point_data<int> point5(-2, 10);
  390. segments.push_back(segment_data<int>(point1, point2));
  391. points.push_back(point3);
  392. points.push_back(point4);
  393. points.push_back(point5);
  394. construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
  395. CHECK_OUTPUT_SIZE(test_output, 6, 4, 18);
  396. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  397. }
  398. void segment_site_test6()
  399. {
  400. vd_type test_output;
  401. std::vector< point_data<int> > points;
  402. std::vector< segment_data<int> > segments;
  403. point_data<int> point1(-1, 1);
  404. point_data<int> point2(1, 0);
  405. point_data<int> point3(1, 2);
  406. segments.push_back(segment_data<int>(point2, point3));
  407. points.push_back(point1);
  408. construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
  409. CHECK_OUTPUT_SIZE(test_output, 4, 2, 10);
  410. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  411. }
  412. void segment_site_test7()
  413. {
  414. vd_type test_output;
  415. std::vector< segment_data<int> > segments;
  416. point_data<int> point1(0, 0);
  417. point_data<int> point2(4, 0);
  418. point_data<int> point3(0, 4);
  419. point_data<int> point4(4, 4);
  420. segments.push_back(segment_data<int>(point1, point2));
  421. segments.push_back(segment_data<int>(point2, point3));
  422. segments.push_back(segment_data<int>(point3, point4));
  423. construct_voronoi(segments.begin(), segments.end(), &test_output);
  424. CHECK_OUTPUT_SIZE(test_output, 7, 6, 24);
  425. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  426. }
  427. void segment_site_test8()
  428. {
  429. vd_type test_output;
  430. std::vector< segment_data<int> > segments;
  431. point_data<int> point1(0, 0);
  432. point_data<int> point2(4, 0);
  433. point_data<int> point3(4, 4);
  434. point_data<int> point4(0, 4);
  435. segments.push_back(segment_data<int>(point1, point2));
  436. segments.push_back(segment_data<int>(point2, point3));
  437. segments.push_back(segment_data<int>(point3, point4));
  438. segments.push_back(segment_data<int>(point4, point1));
  439. construct_voronoi(segments.begin(), segments.end(), &test_output);
  440. CHECK_OUTPUT_SIZE(test_output, 8, 5, 24);
  441. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  442. }
  443. void segment_site_test9()
  444. {
  445. vd_type test_output;
  446. std::vector< segment_data<int> > segments;
  447. point_data<int> point1(0, 0);
  448. point_data<int> point2(2, 0);
  449. point_data<int> point3(4, 0);
  450. segments.push_back(segment_data<int>(point1, point2));
  451. segments.push_back(segment_data<int>(point2, point3));
  452. construct_voronoi(segments.begin(), segments.end(), &test_output);
  453. CHECK_OUTPUT_SIZE(test_output, 5, 0, 8);
  454. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  455. }
  456. #ifdef NDEBUG
  457. void segment_grid_test()
  458. {
  459. vd_type test_output_small, test_output_large;
  460. std::vector< segment_data<int> > segments_small, segments_large;
  461. int grid_size[] = {10, 27, 53};
  462. int max_value[] = {100, 330, 1000};
  463. int array_length = sizeof(grid_size) / sizeof(int);
  464. for (int k = 0; k < array_length; k++) {
  465. test_output_small.clear();
  466. test_output_large.clear();
  467. segments_small.clear();
  468. segments_large.clear();
  469. int cur_sz = grid_size[k];
  470. int koef = (std::numeric_limits<int>::max)() / max_value[k];
  471. for (int i = 0; i < cur_sz + 1; i++)
  472. for (int j = 0; j < cur_sz; j++) {
  473. point_data<int> point1_1(10 * i, 10 * j);
  474. point_data<int> point1_2(koef * 10 * i, koef * 10 * j);
  475. point_data<int> point2_1(10 * i, 10 * j + 10);
  476. point_data<int> point2_2(koef * 10 * i, koef * (10 * j + 10));
  477. segments_small.push_back(segment_data<int>(point1_1, point2_1));
  478. segments_large.push_back(segment_data<int>(point1_2, point2_2));
  479. point_data<int> point3_1(10 * j, 10 * i);
  480. point_data<int> point3_2(koef * 10 * j, koef * 10 * i);
  481. point_data<int> point4_1(10 * j + 10, 10 * i);
  482. point_data<int> point4_2(koef * (10 * j + 10), koef * 10 * i);
  483. segments_small.push_back(segment_data<int>(point3_1, point4_1));
  484. segments_large.push_back(segment_data<int>(point3_2, point4_2));
  485. }
  486. construct_voronoi(segments_small.begin(), segments_small.end(), &test_output_small);
  487. construct_voronoi(segments_large.begin(), segments_large.end(), &test_output_large);
  488. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_small);
  489. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_large);
  490. BOOST_TEST_EQ(test_output_small.num_cells(), test_output_large.num_cells());
  491. BOOST_TEST_EQ(test_output_small.num_vertices(), test_output_large.num_vertices());
  492. BOOST_TEST_EQ(test_output_small.num_edges(), test_output_large.num_edges());
  493. }
  494. }
  495. #endif
  496. #ifdef NDEBUG
  497. void segment_random_test1()
  498. {
  499. boost::mt19937 gen(static_cast<unsigned int>(time(NULL)));
  500. vd_type test_output;
  501. std::vector< point_data<int> > points;
  502. std::vector< segment_data<int> > segments;
  503. int num_runs = 1000;
  504. int num_segments = 10;
  505. points.push_back(point_data<int>(-100, -100));
  506. points.push_back(point_data<int>(-100, 100));
  507. points.push_back(point_data<int>(100, -100));
  508. points.push_back(point_data<int>(100, 100));
  509. for (int i = 0; i < num_runs; i++) {
  510. test_output.clear();
  511. segments.clear();
  512. for (int j = 0; j < num_segments; j++) {
  513. int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
  514. while (x1 == x2 && y1 == y2) {
  515. x1 = (gen() % 100) - 50;
  516. y1 = (gen() % 100) - 50;
  517. x2 = (gen() % 100) - 50;
  518. y2 = (gen() % 100) - 50;
  519. }
  520. point_data<int> point1(x1, y1);
  521. point_data<int> point2(x2, y2);
  522. segments.push_back(segment_data<int>(point1, point2));
  523. }
  524. voronoi_test_helper::clean_segment_set(segments);
  525. construct_voronoi(points.begin(), points.end(), segments.begin(), segments.end(), &test_output);
  526. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output);
  527. }
  528. }
  529. #endif
  530. #ifdef NDEBUG
  531. void segment_random_test2()
  532. {
  533. boost::mt19937 gen(static_cast<unsigned int>(time(NULL)));
  534. vd_type test_output_small, test_output_large;
  535. std::vector< segment_data<int> > segments_small, segments_large;
  536. int num_segments[] = {5, 25, 125, 625};
  537. int num_runs[] = {1000, 100, 10, 1};
  538. int mod_koef1[] = {10, 100, 200, 300};
  539. int mod_koef2[] = {10, 20, 50, 100};
  540. int max_value[] = {10, 60, 125, 200};
  541. int array_length = sizeof(num_segments) / sizeof(int);
  542. for (int k = 0; k < array_length; k++) {
  543. int koef = (std::numeric_limits<int>::max)() / max_value[k];
  544. for (int i = 0; i < num_runs[k]; i++) {
  545. test_output_small.clear();
  546. test_output_large.clear();
  547. segments_small.clear();
  548. segments_large.clear();
  549. for (int j = 0; j < num_segments[k]; j++) {
  550. int x1 = (gen() % mod_koef1[k]) - mod_koef1[k] / 2;
  551. int y1 = (gen() % mod_koef1[k]) - mod_koef1[k] / 2;
  552. int dx = 0, dy = 0;
  553. while (dx == 0 && dy == 0) {
  554. dx = (gen() % mod_koef2[k]) - mod_koef2[k] / 2;
  555. dy = (gen() % mod_koef2[k]) - mod_koef2[k] / 2;
  556. }
  557. int x2 = x1 + dx;
  558. int y2 = y1 + dy;
  559. point_data<int> point1_small(x1, y1);
  560. point_data<int> point2_small(x2, y2);
  561. segments_small.push_back(segment_data<int>(point1_small, point2_small));
  562. }
  563. voronoi_test_helper::clean_segment_set(segments_small);
  564. for (std::vector< segment_data<int> >::iterator it = segments_small.begin();
  565. it != segments_small.end(); ++it) {
  566. int x1 = it->low().x() * koef;
  567. int y1 = it->low().y() * koef;
  568. int x2 = it->high().x() * koef;
  569. int y2 = it->high().y() * koef;
  570. point_data<int> point1_large(x1, y1);
  571. point_data<int> point2_large(x2, y2);
  572. segments_large.push_back(segment_data<int>(point1_large, point2_large));
  573. }
  574. construct_voronoi(segments_small.begin(), segments_small.end(), &test_output_small);
  575. construct_voronoi(segments_large.begin(), segments_large.end(), &test_output_large);
  576. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_small);
  577. VERIFY_NO_HALF_EDGE_INTERSECTIONS(test_output_large);
  578. BOOST_TEST_EQ(test_output_small.num_cells(), test_output_large.num_cells());
  579. BOOST_TEST_EQ(test_output_small.num_vertices(), test_output_large.num_vertices());
  580. BOOST_TEST_EQ(test_output_small.num_edges(), test_output_large.num_edges());
  581. }
  582. }
  583. }
  584. #endif
  585. int main()
  586. {
  587. single_site_test();
  588. collinear_sites_test1();
  589. collinear_sites_test2();
  590. triangle_test1();
  591. triangle_test2();
  592. square_test1();
  593. #ifdef NDEBUG
  594. grid_test();
  595. random_test();
  596. #endif
  597. segment_sites_test1();
  598. segment_sites_test2();
  599. segment_sites_test3();
  600. segment_sites_test4();
  601. segment_site_test5();
  602. segment_site_test6();
  603. segment_site_test7();
  604. segment_site_test8();
  605. segment_site_test9();
  606. #ifdef NDEBUG
  607. segment_grid_test();
  608. segment_random_test1();
  609. segment_random_test2();
  610. #endif
  611. return boost::report_errors();
  612. }