glut_vis.cpp 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  1. // Boost.Geometry Index
  2. // OpenGL visualization
  3. // Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
  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. #include <GL/glut.h>
  8. #include <boost/foreach.hpp>
  9. #include <boost/geometry.hpp>
  10. #include <boost/geometry/index/rtree.hpp>
  11. #include <boost/geometry/geometries/linestring.hpp>
  12. #include <boost/geometry/geometries/segment.hpp>
  13. #include <boost/geometry/geometries/ring.hpp>
  14. #include <boost/geometry/geometries/polygon.hpp>
  15. #include <boost/geometry/geometries/multi_polygon.hpp>
  16. #include <boost/geometry/index/detail/rtree/utilities/gl_draw.hpp>
  17. #include <boost/geometry/index/detail/rtree/utilities/print.hpp>
  18. #include <boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp>
  19. #include <boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp>
  20. #include <boost/geometry/index/detail/rtree/utilities/statistics.hpp>
  21. #include <boost/variant.hpp>
  22. #define ENABLE_POINTS_AND_SEGMENTS
  23. namespace bg = boost::geometry;
  24. namespace bgi = bg::index;
  25. // used types
  26. typedef bg::model::point<float, 2, boost::geometry::cs::cartesian> P;
  27. typedef bg::model::box<P> B;
  28. typedef bg::model::linestring<P> LS;
  29. typedef bg::model::segment<P> S;
  30. typedef bg::model::ring<P> R;
  31. typedef bg::model::polygon<P> Poly;
  32. typedef bg::model::multi_polygon<Poly> MPoly;
  33. // containers variant
  34. template <typename V>
  35. struct containers
  36. {
  37. containers & operator=(containers const& c)
  38. {
  39. tree = c.tree;
  40. values = c.values;
  41. result = c.result;
  42. return *this;
  43. }
  44. bgi::rtree< V, bgi::rstar<4, 2> > tree;
  45. std::vector<V> values;
  46. std::vector<V> result;
  47. };
  48. boost::variant<
  49. containers<B>
  50. #ifdef ENABLE_POINTS_AND_SEGMENTS
  51. , containers<P>
  52. , containers<S>
  53. #endif
  54. > cont;
  55. // visitors
  56. template <typename Pred>
  57. struct query_v : boost::static_visitor<size_t>
  58. {
  59. Pred m_pred;
  60. query_v(Pred const& pred) : m_pred(pred) {}
  61. template <typename C>
  62. size_t operator()(C & c) const
  63. {
  64. c.result.clear();
  65. return c.tree.query(m_pred, std::back_inserter(c.result));
  66. }
  67. };
  68. template <typename Cont, typename Pred>
  69. inline size_t query(Cont & cont, Pred const& pred)
  70. {
  71. return boost::apply_visitor(query_v<Pred>(pred), cont);
  72. }
  73. struct print_result_v : boost::static_visitor<>
  74. {
  75. template <typename C>
  76. void operator()(C & c) const
  77. {
  78. for ( size_t i = 0 ; i < c.result.size() ; ++i )
  79. {
  80. bgi::detail::utilities::print_indexable(std::cout, c.result[i]);
  81. std::cout << '\n';
  82. }
  83. }
  84. };
  85. template <typename Cont>
  86. inline void print_result(Cont const& cont)
  87. {
  88. boost::apply_visitor(print_result_v(), cont);
  89. }
  90. struct bounds_v : boost::static_visitor<B>
  91. {
  92. template <typename C>
  93. B operator()(C & c) const
  94. {
  95. return c.tree.bounds();
  96. }
  97. };
  98. template <typename Cont>
  99. inline B bounds(Cont const& cont)
  100. {
  101. return boost::apply_visitor(bounds_v(), cont);
  102. }
  103. struct depth_v : boost::static_visitor<size_t>
  104. {
  105. template <typename C>
  106. size_t operator()(C & c) const
  107. {
  108. return get(c.tree);
  109. }
  110. template <typename RTree>
  111. static size_t get(RTree const& t)
  112. {
  113. return bgi::detail::rtree::utilities::view<RTree>(t).depth();
  114. }
  115. };
  116. template <typename Cont>
  117. inline size_t depth(Cont const& cont)
  118. {
  119. return boost::apply_visitor(depth_v(), cont);
  120. }
  121. struct draw_tree_v : boost::static_visitor<>
  122. {
  123. template <typename C>
  124. void operator()(C & c) const
  125. {
  126. bgi::detail::rtree::utilities::gl_draw(c.tree);
  127. }
  128. };
  129. template <typename Cont>
  130. inline void draw_tree(Cont const& cont)
  131. {
  132. return boost::apply_visitor(draw_tree_v(), cont);
  133. }
  134. struct draw_result_v : boost::static_visitor<>
  135. {
  136. template <typename C>
  137. void operator()(C & c) const
  138. {
  139. for ( size_t i = 0 ; i < c.result.size() ; ++i )
  140. {
  141. bgi::detail::utilities::gl_draw_indexable(c.result[i], depth_v::get(c.tree));
  142. }
  143. }
  144. };
  145. template <typename Cont>
  146. inline void draw_result(Cont const& cont)
  147. {
  148. return boost::apply_visitor(draw_result_v(), cont);
  149. }
  150. struct print_tree_v : boost::static_visitor<>
  151. {
  152. template <typename C>
  153. void operator()(C & c) const
  154. {
  155. bgi::detail::rtree::utilities::print(std::cout, c.tree);
  156. }
  157. };
  158. template <typename Cont>
  159. inline void print_tree(Cont const& cont)
  160. {
  161. return boost::apply_visitor(print_tree_v(), cont);
  162. }
  163. // globals used in querying
  164. size_t found_count = 0;
  165. size_t count = 5;
  166. P search_point;
  167. B search_box;
  168. R search_ring;
  169. Poly search_poly;
  170. MPoly search_multi_poly;
  171. S search_segment;
  172. LS search_linestring;
  173. LS search_path;
  174. enum query_mode_type {
  175. qm_knn, qm_knnb, qm_knns, qm_c, qm_d, qm_i, qm_o, qm_w, qm_nc, qm_nd, qm_ni, qm_no, qm_nw, qm_all, qm_ri, qm_pi, qm_mpi, qm_si, qm_lsi, qm_path
  176. } query_mode = qm_knn;
  177. bool search_valid = false;
  178. // various queries
  179. void query_knn()
  180. {
  181. float x = ( rand() % 1000 ) / 10.0f;
  182. float y = ( rand() % 1000 ) / 10.0f;
  183. if ( query_mode == qm_knn )
  184. {
  185. search_point = P(x, y);
  186. found_count = query(cont, bgi::nearest(search_point, count));
  187. }
  188. else if ( query_mode == qm_knnb )
  189. {
  190. float w = 2 + ( rand() % 1000 ) / 500.0f;
  191. float h = 2 + ( rand() % 1000 ) / 500.0f;
  192. search_box = B(P(x - w, y - h), P(x + w, y + h));
  193. found_count = query(cont, bgi::nearest(search_box, count));
  194. }
  195. else if ( query_mode == qm_knns )
  196. {
  197. int signx = rand() % 2 ? 1 : -1;
  198. int signy = rand() % 2 ? 1 : -1;
  199. float w = (10 + ( rand() % 1000 ) / 100.0f) * signx;
  200. float h = (10 + ( rand() % 1000 ) / 100.0f) * signy;
  201. search_segment = S(P(x - w, y - h), P(x + w, y + h));
  202. found_count = query(cont, bgi::nearest(search_segment, count));
  203. }
  204. else
  205. {
  206. BOOST_ASSERT(false);
  207. }
  208. if ( found_count > 0 )
  209. {
  210. if ( query_mode == qm_knn )
  211. {
  212. std::cout << "search point: ";
  213. bgi::detail::utilities::print_indexable(std::cout, search_point);
  214. }
  215. else if ( query_mode == qm_knnb )
  216. {
  217. std::cout << "search box: ";
  218. bgi::detail::utilities::print_indexable(std::cout, search_box);
  219. }
  220. else if ( query_mode == qm_knns )
  221. {
  222. std::cout << "search segment: ";
  223. bgi::detail::utilities::print_indexable(std::cout, search_segment);
  224. }
  225. else
  226. {
  227. BOOST_ASSERT(false);
  228. }
  229. std::cout << "\nfound: ";
  230. print_result(cont);
  231. }
  232. else
  233. std::cout << "nearest not found\n";
  234. }
  235. #ifndef ENABLE_POINTS_AND_SEGMENTS
  236. void query_path()
  237. {
  238. float x = ( rand() % 1000 ) / 10.0f;
  239. float y = ( rand() % 1000 ) / 10.0f;
  240. float w = 20 + ( rand() % 1000 ) / 100.0f;
  241. float h = 20 + ( rand() % 1000 ) / 100.0f;
  242. search_path.resize(10);
  243. float yy = y-h;
  244. for ( int i = 0 ; i < 5 ; ++i, yy += h / 2 )
  245. {
  246. search_path[2 * i] = P(x-w, yy);
  247. search_path[2 * i + 1] = P(x+w, yy);
  248. }
  249. found_count = query(cont, bgi::detail::path<LS>(search_path, count));
  250. if ( found_count > 0 )
  251. {
  252. std::cout << "search path: ";
  253. BOOST_FOREACH(P const& p, search_path)
  254. bgi::detail::utilities::print_indexable(std::cout, p);
  255. std::cout << "\nfound: ";
  256. print_result(cont);
  257. }
  258. else
  259. std::cout << "values on path not found\n";
  260. }
  261. #endif
  262. template <typename Predicate>
  263. void query()
  264. {
  265. if ( query_mode != qm_all )
  266. {
  267. float x = ( rand() % 1000 ) / 10.0f;
  268. float y = ( rand() % 1000 ) / 10.0f;
  269. float w = 10 + ( rand() % 1000 ) / 100.0f;
  270. float h = 10 + ( rand() % 1000 ) / 100.0f;
  271. search_box = B(P(x - w, y - h), P(x + w, y + h));
  272. }
  273. else
  274. {
  275. search_box = bounds(cont);
  276. }
  277. found_count = query(cont, Predicate(search_box));
  278. if ( found_count > 0 )
  279. {
  280. std::cout << "search box: ";
  281. bgi::detail::utilities::print_indexable(std::cout, search_box);
  282. std::cout << "\nfound: ";
  283. print_result(cont);
  284. }
  285. else
  286. std::cout << "boxes not found\n";
  287. }
  288. template <typename Predicate>
  289. void query_ring()
  290. {
  291. float x = ( rand() % 1000 ) / 10.0f;
  292. float y = ( rand() % 1000 ) / 10.0f;
  293. float w = 10 + ( rand() % 1000 ) / 100.0f;
  294. float h = 10 + ( rand() % 1000 ) / 100.0f;
  295. search_ring.clear();
  296. search_ring.push_back(P(x - w, y - h));
  297. search_ring.push_back(P(x - w/2, y - h));
  298. search_ring.push_back(P(x, y - 3*h/2));
  299. search_ring.push_back(P(x + w/2, y - h));
  300. search_ring.push_back(P(x + w, y - h));
  301. search_ring.push_back(P(x + w, y - h/2));
  302. search_ring.push_back(P(x + 3*w/2, y));
  303. search_ring.push_back(P(x + w, y + h/2));
  304. search_ring.push_back(P(x + w, y + h));
  305. search_ring.push_back(P(x + w/2, y + h));
  306. search_ring.push_back(P(x, y + 3*h/2));
  307. search_ring.push_back(P(x - w/2, y + h));
  308. search_ring.push_back(P(x - w, y + h));
  309. search_ring.push_back(P(x - w, y + h/2));
  310. search_ring.push_back(P(x - 3*w/2, y));
  311. search_ring.push_back(P(x - w, y - h/2));
  312. search_ring.push_back(P(x - w, y - h));
  313. found_count = query(cont, Predicate(search_ring));
  314. if ( found_count > 0 )
  315. {
  316. std::cout << "search ring: ";
  317. BOOST_FOREACH(P const& p, search_ring)
  318. {
  319. bgi::detail::utilities::print_indexable(std::cout, p);
  320. std::cout << ' ';
  321. }
  322. std::cout << "\nfound: ";
  323. print_result(cont);
  324. }
  325. else
  326. std::cout << "boxes not found\n";
  327. }
  328. template <typename Predicate>
  329. void query_poly()
  330. {
  331. float x = ( rand() % 1000 ) / 10.0f;
  332. float y = ( rand() % 1000 ) / 10.0f;
  333. float w = 10 + ( rand() % 1000 ) / 100.0f;
  334. float h = 10 + ( rand() % 1000 ) / 100.0f;
  335. search_poly.clear();
  336. search_poly.outer().push_back(P(x - w, y - h));
  337. search_poly.outer().push_back(P(x - w/2, y - h));
  338. search_poly.outer().push_back(P(x, y - 3*h/2));
  339. search_poly.outer().push_back(P(x + w/2, y - h));
  340. search_poly.outer().push_back(P(x + w, y - h));
  341. search_poly.outer().push_back(P(x + w, y - h/2));
  342. search_poly.outer().push_back(P(x + 3*w/2, y));
  343. search_poly.outer().push_back(P(x + w, y + h/2));
  344. search_poly.outer().push_back(P(x + w, y + h));
  345. search_poly.outer().push_back(P(x + w/2, y + h));
  346. search_poly.outer().push_back(P(x, y + 3*h/2));
  347. search_poly.outer().push_back(P(x - w/2, y + h));
  348. search_poly.outer().push_back(P(x - w, y + h));
  349. search_poly.outer().push_back(P(x - w, y + h/2));
  350. search_poly.outer().push_back(P(x - 3*w/2, y));
  351. search_poly.outer().push_back(P(x - w, y - h/2));
  352. search_poly.outer().push_back(P(x - w, y - h));
  353. search_poly.inners().push_back(Poly::ring_type());
  354. search_poly.inners()[0].push_back(P(x - w/2, y - h/2));
  355. search_poly.inners()[0].push_back(P(x + w/2, y - h/2));
  356. search_poly.inners()[0].push_back(P(x + w/2, y + h/2));
  357. search_poly.inners()[0].push_back(P(x - w/2, y + h/2));
  358. search_poly.inners()[0].push_back(P(x - w/2, y - h/2));
  359. found_count = query(cont, Predicate(search_poly));
  360. if ( found_count > 0 )
  361. {
  362. std::cout << "search poly outer: ";
  363. BOOST_FOREACH(P const& p, search_poly.outer())
  364. {
  365. bgi::detail::utilities::print_indexable(std::cout, p);
  366. std::cout << ' ';
  367. }
  368. std::cout << "\nfound: ";
  369. print_result(cont);
  370. }
  371. else
  372. std::cout << "boxes not found\n";
  373. }
  374. template <typename Predicate>
  375. void query_multi_poly()
  376. {
  377. float x = ( rand() % 1000 ) / 10.0f;
  378. float y = ( rand() % 1000 ) / 10.0f;
  379. float w = 10 + ( rand() % 1000 ) / 100.0f;
  380. float h = 10 + ( rand() % 1000 ) / 100.0f;
  381. search_multi_poly.clear();
  382. search_multi_poly.push_back(Poly());
  383. search_multi_poly[0].outer().push_back(P(x - w, y - h));
  384. search_multi_poly[0].outer().push_back(P(x - w/2, y - h));
  385. search_multi_poly[0].outer().push_back(P(x, y - 3*h/2));
  386. search_multi_poly[0].outer().push_back(P(x + w/2, y - h));
  387. search_multi_poly[0].outer().push_back(P(x + w, y - h));
  388. search_multi_poly[0].outer().push_back(P(x + w, y - h/2));
  389. search_multi_poly[0].outer().push_back(P(x + 3*w/2, y));
  390. search_multi_poly[0].outer().push_back(P(x + w, y + h/2));
  391. search_multi_poly[0].outer().push_back(P(x + w, y + h));
  392. search_multi_poly[0].outer().push_back(P(x + w/2, y + h));
  393. search_multi_poly[0].outer().push_back(P(x, y + 3*h/2));
  394. search_multi_poly[0].outer().push_back(P(x - w/2, y + h));
  395. search_multi_poly[0].outer().push_back(P(x - w, y + h));
  396. search_multi_poly[0].outer().push_back(P(x - w, y + h/2));
  397. search_multi_poly[0].outer().push_back(P(x - 3*w/2, y));
  398. search_multi_poly[0].outer().push_back(P(x - w, y - h/2));
  399. search_multi_poly[0].outer().push_back(P(x - w, y - h));
  400. search_multi_poly[0].inners().push_back(Poly::ring_type());
  401. search_multi_poly[0].inners()[0].push_back(P(x - w/2, y - h/2));
  402. search_multi_poly[0].inners()[0].push_back(P(x + w/2, y - h/2));
  403. search_multi_poly[0].inners()[0].push_back(P(x + w/2, y + h/2));
  404. search_multi_poly[0].inners()[0].push_back(P(x - w/2, y + h/2));
  405. search_multi_poly[0].inners()[0].push_back(P(x - w/2, y - h/2));
  406. search_multi_poly.push_back(Poly());
  407. search_multi_poly[1].outer().push_back(P(x - 2*w, y - 2*h));
  408. search_multi_poly[1].outer().push_back(P(x - 6*w/5, y - 2*h));
  409. search_multi_poly[1].outer().push_back(P(x - 6*w/5, y - 6*h/5));
  410. search_multi_poly[1].outer().push_back(P(x - 2*w, y - 6*h/5));
  411. search_multi_poly[1].outer().push_back(P(x - 2*w, y - 2*h));
  412. search_multi_poly.push_back(Poly());
  413. search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 6*h/5));
  414. search_multi_poly[2].outer().push_back(P(x + 2*w, y + 6*h/5));
  415. search_multi_poly[2].outer().push_back(P(x + 2*w, y + 2*h));
  416. search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 2*h));
  417. search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 6*h/5));
  418. found_count = query(cont, Predicate(search_multi_poly));
  419. if ( found_count > 0 )
  420. {
  421. std::cout << "search multi_poly[0] outer: ";
  422. BOOST_FOREACH(P const& p, search_multi_poly[0].outer())
  423. {
  424. bgi::detail::utilities::print_indexable(std::cout, p);
  425. std::cout << ' ';
  426. }
  427. std::cout << "\nfound: ";
  428. print_result(cont);
  429. }
  430. else
  431. std::cout << "boxes not found\n";
  432. }
  433. template <typename Predicate>
  434. void query_segment()
  435. {
  436. float x = ( rand() % 1000 ) / 10.0f;
  437. float y = ( rand() % 1000 ) / 10.0f;
  438. float w = 10.0f - ( rand() % 1000 ) / 50.0f;
  439. float h = 10.0f - ( rand() % 1000 ) / 50.0f;
  440. w += 0 <= w ? 10 : -10;
  441. h += 0 <= h ? 10 : -10;
  442. boost::geometry::set<0, 0>(search_segment, x - w);
  443. boost::geometry::set<0, 1>(search_segment, y - h);
  444. boost::geometry::set<1, 0>(search_segment, x + w);
  445. boost::geometry::set<1, 1>(search_segment, y + h);
  446. found_count = query(cont, Predicate(search_segment));
  447. if ( found_count > 0 )
  448. {
  449. std::cout << "search segment: ";
  450. bgi::detail::utilities::print_indexable(std::cout, P(x-w, y-h));
  451. bgi::detail::utilities::print_indexable(std::cout, P(x+w, y+h));
  452. std::cout << "\nfound: ";
  453. print_result(cont);
  454. }
  455. else
  456. std::cout << "boxes not found\n";
  457. }
  458. template <typename Predicate>
  459. void query_linestring()
  460. {
  461. float x = ( rand() % 1000 ) / 10.0f;
  462. float y = ( rand() % 1000 ) / 10.0f;
  463. float w = 10 + ( rand() % 1000 ) / 100.0f;
  464. float h = 10 + ( rand() % 1000 ) / 100.0f;
  465. search_linestring.clear();
  466. float a = 0;
  467. float d = 0;
  468. for ( size_t i = 0 ; i < 300 ; ++i, a += 0.05, d += 0.005 )
  469. {
  470. float xx = x + w * d * ::cos(a);
  471. float yy = y + h * d * ::sin(a);
  472. search_linestring.push_back(P(xx, yy));
  473. }
  474. found_count = query(cont, Predicate(search_linestring));
  475. if ( found_count > 0 )
  476. {
  477. std::cout << "search linestring: ";
  478. BOOST_FOREACH(P const& p, search_linestring)
  479. {
  480. bgi::detail::utilities::print_indexable(std::cout, p);
  481. std::cout << ' ';
  482. }
  483. std::cout << "\nfound: ";
  484. print_result(cont);
  485. }
  486. else
  487. std::cout << "boxes not found\n";
  488. }
  489. // the function running the correct query based on the query_mode
  490. void search()
  491. {
  492. namespace d = bgi::detail;
  493. if ( query_mode == qm_knn || query_mode == qm_knnb || query_mode == qm_knns )
  494. query_knn();
  495. else if ( query_mode == qm_d )
  496. query< d::spatial_predicate<B, d::disjoint_tag, false> >();
  497. else if ( query_mode == qm_i )
  498. query< d::spatial_predicate<B, d::intersects_tag, false> >();
  499. else if ( query_mode == qm_nd )
  500. query< d::spatial_predicate<B, d::disjoint_tag, true> >();
  501. else if ( query_mode == qm_ni )
  502. query< d::spatial_predicate<B, d::intersects_tag, true> >();
  503. else if ( query_mode == qm_all )
  504. query< d::spatial_predicate<B, d::intersects_tag, false> >();
  505. #ifdef ENABLE_POINTS_AND_SEGMENTS
  506. else
  507. std::cout << "query disabled\n";
  508. #else
  509. else if ( query_mode == qm_c )
  510. query< d::spatial_predicate<B, d::covered_by_tag, false> >();
  511. else if ( query_mode == qm_o )
  512. query< d::spatial_predicate<B, d::overlaps_tag, false> >();
  513. else if ( query_mode == qm_w )
  514. query< d::spatial_predicate<B, d::within_tag, false> >();
  515. else if ( query_mode == qm_nc )
  516. query< d::spatial_predicate<B, d::covered_by_tag, true> >();
  517. else if ( query_mode == qm_no )
  518. query< d::spatial_predicate<B, d::overlaps_tag, true> >();
  519. else if ( query_mode == qm_nw )
  520. query< d::spatial_predicate<B, d::within_tag, true> >();
  521. else if ( query_mode == qm_ri )
  522. query_ring< d::spatial_predicate<R, d::intersects_tag, false> >();
  523. else if ( query_mode == qm_pi )
  524. query_poly< d::spatial_predicate<Poly, d::intersects_tag, false> >();
  525. else if ( query_mode == qm_mpi )
  526. query_multi_poly< d::spatial_predicate<MPoly, d::intersects_tag, false> >();
  527. else if ( query_mode == qm_si )
  528. query_segment< d::spatial_predicate<S, d::intersects_tag, false> >();
  529. else if ( query_mode == qm_lsi )
  530. query_linestring< d::spatial_predicate<LS, d::intersects_tag, false> >();
  531. else if ( query_mode == qm_path )
  532. query_path();
  533. #endif
  534. search_valid = true;
  535. }
  536. // various drawing functions
  537. void draw_point(P const& p)
  538. {
  539. float x = boost::geometry::get<0>(p);
  540. float y = boost::geometry::get<1>(p);
  541. float z = depth(cont);
  542. glBegin(GL_QUADS);
  543. glVertex3f(x+1, y, z);
  544. glVertex3f(x, y+1, z);
  545. glVertex3f(x-1, y, z);
  546. glVertex3f(x, y-1, z);
  547. glEnd();
  548. }
  549. void draw_knn_area(float min_distance, float max_distance)
  550. {
  551. float x = boost::geometry::get<0>(search_point);
  552. float y = boost::geometry::get<1>(search_point);
  553. float z = depth(cont);
  554. draw_point(search_point);
  555. // search min circle
  556. glBegin(GL_LINE_LOOP);
  557. for(float a = 0 ; a < 3.14158f * 2 ; a += 3.14158f / 180)
  558. glVertex3f(x + min_distance * ::cos(a), y + min_distance * ::sin(a), z);
  559. glEnd();
  560. // search max circle
  561. glBegin(GL_LINE_LOOP);
  562. for(float a = 0 ; a < 3.14158f * 2 ; a += 3.14158f / 180)
  563. glVertex3f(x + max_distance * ::cos(a), y + max_distance * ::sin(a), z);
  564. glEnd();
  565. }
  566. void draw_linestring(LS const& ls)
  567. {
  568. glBegin(GL_LINE_STRIP);
  569. BOOST_FOREACH(P const& p, ls)
  570. {
  571. float x = boost::geometry::get<0>(p);
  572. float y = boost::geometry::get<1>(p);
  573. float z = depth(cont);
  574. glVertex3f(x, y, z);
  575. }
  576. glEnd();
  577. }
  578. void draw_segment(S const& s)
  579. {
  580. float x1 = boost::geometry::get<0, 0>(s);
  581. float y1 = boost::geometry::get<0, 1>(s);
  582. float x2 = boost::geometry::get<1, 0>(s);
  583. float y2 = boost::geometry::get<1, 1>(s);
  584. float z = depth(cont);
  585. glBegin(GL_LINES);
  586. glVertex3f(x1, y1, z);
  587. glVertex3f(x2, y2, z);
  588. glEnd();
  589. }
  590. template <typename Box>
  591. void draw_box(Box const& box)
  592. {
  593. float x1 = boost::geometry::get<bg::min_corner, 0>(box);
  594. float y1 = boost::geometry::get<bg::min_corner, 1>(box);
  595. float x2 = boost::geometry::get<bg::max_corner, 0>(box);
  596. float y2 = boost::geometry::get<bg::max_corner, 1>(box);
  597. float z = depth(cont);
  598. // search box
  599. glBegin(GL_LINE_LOOP);
  600. glVertex3f(x1, y1, z);
  601. glVertex3f(x2, y1, z);
  602. glVertex3f(x2, y2, z);
  603. glVertex3f(x1, y2, z);
  604. glEnd();
  605. }
  606. template <typename Range>
  607. void draw_ring(Range const& range)
  608. {
  609. float z = depth(cont);
  610. // search box
  611. glBegin(GL_LINE_LOOP);
  612. BOOST_FOREACH(P const& p, range)
  613. {
  614. float x = boost::geometry::get<0>(p);
  615. float y = boost::geometry::get<1>(p);
  616. glVertex3f(x, y, z);
  617. }
  618. glEnd();
  619. }
  620. template <typename Polygon>
  621. void draw_polygon(Polygon const& polygon)
  622. {
  623. draw_ring(polygon.outer());
  624. BOOST_FOREACH(Poly::ring_type const& r, polygon.inners())
  625. draw_ring(r);
  626. }
  627. template <typename MultiPolygon>
  628. void draw_multi_polygon(MultiPolygon const& multi_polygon)
  629. {
  630. BOOST_FOREACH(Poly const& p, multi_polygon)
  631. draw_polygon(p);
  632. }
  633. // render the scene -> tree, if searching data available also the query geometry and result
  634. void render_scene(void)
  635. {
  636. glClear(GL_COLOR_BUFFER_BIT);
  637. draw_tree(cont);
  638. if ( search_valid )
  639. {
  640. glColor3f(1.0f, 0.25f, 0.0f);
  641. if ( query_mode == qm_knn )
  642. draw_knn_area(0, 0);
  643. else if ( query_mode == qm_knnb )
  644. draw_box(search_box);
  645. else if ( query_mode == qm_knns )
  646. draw_segment(search_segment);
  647. else if ( query_mode == qm_ri )
  648. draw_ring(search_ring);
  649. else if ( query_mode == qm_pi )
  650. draw_polygon(search_poly);
  651. else if ( query_mode == qm_mpi )
  652. draw_multi_polygon(search_multi_poly);
  653. else if ( query_mode == qm_si )
  654. draw_segment(search_segment);
  655. else if ( query_mode == qm_lsi )
  656. draw_linestring(search_linestring);
  657. else if ( query_mode == qm_path )
  658. draw_linestring(search_path);
  659. else
  660. draw_box(search_box);
  661. glColor3f(1.0f, 0.5f, 0.0f);
  662. draw_result(cont);
  663. }
  664. glFlush();
  665. }
  666. void resize(int w, int h)
  667. {
  668. if ( h == 0 )
  669. h = 1;
  670. //float ratio = float(w) / h;
  671. glMatrixMode(GL_PROJECTION);
  672. glLoadIdentity();
  673. glViewport(0, 0, w, h);
  674. //gluPerspective(45, ratio, 1, 1000);
  675. glOrtho(-150, 150, -150, 150, -150, 150);
  676. glMatrixMode(GL_MODELVIEW);
  677. glLoadIdentity();
  678. /*gluLookAt(
  679. 120.0f, 120.0f, 120.0f,
  680. 50.0f, 50.0f, -1.0f,
  681. 0.0f, 1.0f, 0.0f);*/
  682. gluLookAt(
  683. 50.0f, 50.0f, 75.0f,
  684. 50.0f, 50.0f, -1.0f,
  685. 0.0f, 1.0f, 0.0f);
  686. glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  687. glLineWidth(1.5f);
  688. srand(1);
  689. }
  690. // randomize various indexables
  691. inline void rand_val(B & b)
  692. {
  693. float x = ( rand() % 100 );
  694. float y = ( rand() % 100 );
  695. float w = ( rand() % 2 ) + 1;
  696. float h = ( rand() % 2 ) + 1;
  697. b = B(P(x - w, y - h),P(x + w, y + h));
  698. }
  699. inline void rand_val(P & p)
  700. {
  701. float x = ( rand() % 100 );
  702. float y = ( rand() % 100 );
  703. p = P(x, y);
  704. }
  705. inline void rand_val(S & s)
  706. {
  707. float x = ( rand() % 100 );
  708. float y = ( rand() % 100 );
  709. float w = ( rand() % 2 + 1) * (rand() % 2 ? 1.0f : -1.0f);
  710. float h = ( rand() % 2 + 1) * (rand() % 2 ? 1.0f : -1.0f);
  711. s = S(P(x - w, y - h),P(x + w, y + h));
  712. }
  713. // more higher-level visitors
  714. struct insert_random_value_v : boost::static_visitor<>
  715. {
  716. template <typename V>
  717. void operator()(containers<V> & c) const
  718. {
  719. V v;
  720. rand_val(v);
  721. boost::geometry::index::insert(c.tree, v);
  722. c.values.push_back(v);
  723. std::cout << "inserted: ";
  724. bgi::detail::utilities::print_indexable(std::cout, v);
  725. std::cout << '\n';
  726. std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
  727. std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
  728. std::cout << "\n";
  729. }
  730. };
  731. template <typename Cont>
  732. inline void insert_random_value(Cont & cont)
  733. {
  734. return boost::apply_visitor(insert_random_value_v(), cont);
  735. }
  736. struct remove_random_value_v : boost::static_visitor<>
  737. {
  738. template <typename V>
  739. void operator()(containers<V> & c) const
  740. {
  741. if ( c.values.empty() )
  742. return;
  743. size_t i = rand() % c.values.size();
  744. V v = c.values[i];
  745. c.tree.remove(v);
  746. c.values.erase(c.values.begin() + i);
  747. std::cout << "removed: ";
  748. bgi::detail::utilities::print_indexable(std::cout, v);
  749. std::cout << '\n';
  750. std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
  751. std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
  752. std::cout << "\n";
  753. }
  754. };
  755. template <typename Cont>
  756. inline void remove_random_value(Cont & cont)
  757. {
  758. return boost::apply_visitor(remove_random_value_v(), cont);
  759. }
  760. // handle mouse input
  761. void mouse(int button, int state, int /*x*/, int /*y*/)
  762. {
  763. if ( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
  764. {
  765. insert_random_value(cont);
  766. search_valid = false;
  767. }
  768. else if ( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
  769. {
  770. remove_random_value(cont);
  771. search_valid = false;
  772. }
  773. else if ( button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN )
  774. {
  775. search();
  776. }
  777. glutPostRedisplay();
  778. }
  779. // more higher-level visitors
  780. struct insert_random_values_v : boost::static_visitor<>
  781. {
  782. template <typename V>
  783. void operator()(containers<V> & c) const
  784. {
  785. for ( size_t i = 0 ; i < 35 ; ++i )
  786. {
  787. V v;
  788. rand_val(v);
  789. c.tree.insert(v);
  790. c.values.push_back(v);
  791. std::cout << "inserted: ";
  792. bgi::detail::utilities::print_indexable(std::cout, v);
  793. std::cout << '\n';
  794. }
  795. std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
  796. std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
  797. std::cout << "\n";
  798. }
  799. };
  800. template <typename Cont>
  801. inline void insert_random_values(Cont & cont)
  802. {
  803. return boost::apply_visitor(insert_random_values_v(), cont);
  804. }
  805. struct bulk_insert_random_values_v : boost::static_visitor<>
  806. {
  807. template <typename V>
  808. void operator()(containers<V> & c) const
  809. {
  810. c.values.clear();
  811. for ( size_t i = 0 ; i < 35 ; ++i )
  812. {
  813. V v;
  814. rand_val(v);
  815. c.values.push_back(v);
  816. std::cout << "inserted: ";
  817. bgi::detail::utilities::print_indexable(std::cout, v);
  818. std::cout << '\n';
  819. }
  820. create(c.tree, c.values);
  821. std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
  822. std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
  823. std::cout << "\n";
  824. }
  825. template <typename Tree, typename Values>
  826. void create(Tree & tree, Values const& values) const
  827. {
  828. Tree t(values);
  829. tree = boost::move(t);
  830. }
  831. };
  832. template <typename Cont>
  833. inline void bulk_insert_random_values(Cont & cont)
  834. {
  835. return boost::apply_visitor(bulk_insert_random_values_v(), cont);
  836. }
  837. // handle keyboard input
  838. std::string current_line;
  839. void keyboard(unsigned char key, int /*x*/, int /*y*/)
  840. {
  841. if ( key == '\r' || key == '\n' )
  842. {
  843. if ( current_line == "storeb" )
  844. {
  845. cont = containers<B>();
  846. glutPostRedisplay();
  847. }
  848. #ifdef ENABLE_POINTS_AND_SEGMENTS
  849. else if ( current_line == "storep" )
  850. {
  851. cont = containers<P>();
  852. glutPostRedisplay();
  853. }
  854. else if ( current_line == "stores" )
  855. {
  856. cont = containers<S>();
  857. glutPostRedisplay();
  858. }
  859. #endif
  860. else if ( current_line == "t" )
  861. {
  862. std::cout << "\n";
  863. print_tree(cont);
  864. std::cout << "\n";
  865. }
  866. else if ( current_line == "rand" )
  867. {
  868. insert_random_values(cont);
  869. search_valid = false;
  870. glutPostRedisplay();
  871. }
  872. else if ( current_line == "bulk" )
  873. {
  874. bulk_insert_random_values(cont);
  875. search_valid = false;
  876. glutPostRedisplay();
  877. }
  878. else
  879. {
  880. if ( current_line == "knn" )
  881. query_mode = qm_knn;
  882. else if ( current_line == "knnb" )
  883. query_mode = qm_knnb;
  884. else if ( current_line == "knns" )
  885. query_mode = qm_knns;
  886. else if ( current_line == "c" )
  887. query_mode = qm_c;
  888. else if ( current_line == "d" )
  889. query_mode = qm_d;
  890. else if ( current_line == "i" )
  891. query_mode = qm_i;
  892. else if ( current_line == "o" )
  893. query_mode = qm_o;
  894. else if ( current_line == "w" )
  895. query_mode = qm_w;
  896. else if ( current_line == "nc" )
  897. query_mode = qm_nc;
  898. else if ( current_line == "nd" )
  899. query_mode = qm_nd;
  900. else if ( current_line == "ni" )
  901. query_mode = qm_ni;
  902. else if ( current_line == "no" )
  903. query_mode = qm_no;
  904. else if ( current_line == "nw" )
  905. query_mode = qm_nw;
  906. else if ( current_line == "all" )
  907. query_mode = qm_all;
  908. else if ( current_line == "ri" )
  909. query_mode = qm_ri;
  910. else if ( current_line == "pi" )
  911. query_mode = qm_pi;
  912. else if ( current_line == "mpi" )
  913. query_mode = qm_mpi;
  914. else if ( current_line == "si" )
  915. query_mode = qm_si;
  916. else if ( current_line == "lsi" )
  917. query_mode = qm_lsi;
  918. else if ( current_line == "path" )
  919. query_mode = qm_path;
  920. search();
  921. glutPostRedisplay();
  922. }
  923. current_line.clear();
  924. std::cout << '\n';
  925. }
  926. else
  927. {
  928. current_line += key;
  929. std::cout << key;
  930. }
  931. }
  932. // main function
  933. int main(int argc, char **argv)
  934. {
  935. glutInit(&argc, argv);
  936. glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
  937. glutInitWindowPosition(100,100);
  938. glutInitWindowSize(600, 600);
  939. glutCreateWindow("boost::geometry::index::rtree GLUT test");
  940. glutDisplayFunc(render_scene);
  941. glutReshapeFunc(resize);
  942. glutMouseFunc(mouse);
  943. glutKeyboardFunc(keyboard);
  944. glutMainLoop();
  945. return 0;
  946. }