12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094 |
- // Boost.Geometry Index
- // OpenGL visualization
- // Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
- // Use, modification and distribution is subject to the Boost Software License,
- // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #include <GL/glut.h>
- #include <boost/foreach.hpp>
- #include <boost/geometry.hpp>
- #include <boost/geometry/index/rtree.hpp>
- #include <boost/geometry/geometries/linestring.hpp>
- #include <boost/geometry/geometries/segment.hpp>
- #include <boost/geometry/geometries/ring.hpp>
- #include <boost/geometry/geometries/polygon.hpp>
- #include <boost/geometry/geometries/multi_polygon.hpp>
- #include <boost/geometry/index/detail/rtree/utilities/gl_draw.hpp>
- #include <boost/geometry/index/detail/rtree/utilities/print.hpp>
- #include <boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp>
- #include <boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp>
- #include <boost/geometry/index/detail/rtree/utilities/statistics.hpp>
- #include <boost/variant.hpp>
- #define ENABLE_POINTS_AND_SEGMENTS
- namespace bg = boost::geometry;
- namespace bgi = bg::index;
- // used types
- typedef bg::model::point<float, 2, boost::geometry::cs::cartesian> P;
- typedef bg::model::box<P> B;
- typedef bg::model::linestring<P> LS;
- typedef bg::model::segment<P> S;
- typedef bg::model::ring<P> R;
- typedef bg::model::polygon<P> Poly;
- typedef bg::model::multi_polygon<Poly> MPoly;
- // containers variant
- template <typename V>
- struct containers
- {
- containers & operator=(containers const& c)
- {
- tree = c.tree;
- values = c.values;
- result = c.result;
- return *this;
- }
- bgi::rtree< V, bgi::rstar<4, 2> > tree;
- std::vector<V> values;
- std::vector<V> result;
- };
- boost::variant<
- containers<B>
- #ifdef ENABLE_POINTS_AND_SEGMENTS
- , containers<P>
- , containers<S>
- #endif
- > cont;
- // visitors
- template <typename Pred>
- struct query_v : boost::static_visitor<size_t>
- {
- Pred m_pred;
- query_v(Pred const& pred) : m_pred(pred) {}
- template <typename C>
- size_t operator()(C & c) const
- {
- c.result.clear();
- return c.tree.query(m_pred, std::back_inserter(c.result));
- }
- };
- template <typename Cont, typename Pred>
- inline size_t query(Cont & cont, Pred const& pred)
- {
- return boost::apply_visitor(query_v<Pred>(pred), cont);
- }
- struct print_result_v : boost::static_visitor<>
- {
- template <typename C>
- void operator()(C & c) const
- {
- for ( size_t i = 0 ; i < c.result.size() ; ++i )
- {
- bgi::detail::utilities::print_indexable(std::cout, c.result[i]);
- std::cout << '\n';
- }
- }
- };
- template <typename Cont>
- inline void print_result(Cont const& cont)
- {
- boost::apply_visitor(print_result_v(), cont);
- }
- struct bounds_v : boost::static_visitor<B>
- {
- template <typename C>
- B operator()(C & c) const
- {
- return c.tree.bounds();
- }
- };
- template <typename Cont>
- inline B bounds(Cont const& cont)
- {
- return boost::apply_visitor(bounds_v(), cont);
- }
- struct depth_v : boost::static_visitor<size_t>
- {
- template <typename C>
- size_t operator()(C & c) const
- {
- return get(c.tree);
- }
- template <typename RTree>
- static size_t get(RTree const& t)
- {
- return bgi::detail::rtree::utilities::view<RTree>(t).depth();
- }
- };
- template <typename Cont>
- inline size_t depth(Cont const& cont)
- {
- return boost::apply_visitor(depth_v(), cont);
- }
- struct draw_tree_v : boost::static_visitor<>
- {
- template <typename C>
- void operator()(C & c) const
- {
- bgi::detail::rtree::utilities::gl_draw(c.tree);
- }
- };
- template <typename Cont>
- inline void draw_tree(Cont const& cont)
- {
- return boost::apply_visitor(draw_tree_v(), cont);
- }
- struct draw_result_v : boost::static_visitor<>
- {
- template <typename C>
- void operator()(C & c) const
- {
- for ( size_t i = 0 ; i < c.result.size() ; ++i )
- {
- bgi::detail::utilities::gl_draw_indexable(c.result[i], depth_v::get(c.tree));
- }
- }
- };
- template <typename Cont>
- inline void draw_result(Cont const& cont)
- {
- return boost::apply_visitor(draw_result_v(), cont);
- }
- struct print_tree_v : boost::static_visitor<>
- {
- template <typename C>
- void operator()(C & c) const
- {
- bgi::detail::rtree::utilities::print(std::cout, c.tree);
- }
- };
- template <typename Cont>
- inline void print_tree(Cont const& cont)
- {
- return boost::apply_visitor(print_tree_v(), cont);
- }
- // globals used in querying
- size_t found_count = 0;
- size_t count = 5;
- P search_point;
- B search_box;
- R search_ring;
- Poly search_poly;
- MPoly search_multi_poly;
- S search_segment;
- LS search_linestring;
- LS search_path;
- enum query_mode_type {
- 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
- } query_mode = qm_knn;
- bool search_valid = false;
- // various queries
- void query_knn()
- {
- float x = ( rand() % 1000 ) / 10.0f;
- float y = ( rand() % 1000 ) / 10.0f;
- if ( query_mode == qm_knn )
- {
- search_point = P(x, y);
- found_count = query(cont, bgi::nearest(search_point, count));
- }
- else if ( query_mode == qm_knnb )
- {
- float w = 2 + ( rand() % 1000 ) / 500.0f;
- float h = 2 + ( rand() % 1000 ) / 500.0f;
- search_box = B(P(x - w, y - h), P(x + w, y + h));
- found_count = query(cont, bgi::nearest(search_box, count));
- }
- else if ( query_mode == qm_knns )
- {
- int signx = rand() % 2 ? 1 : -1;
- int signy = rand() % 2 ? 1 : -1;
- float w = (10 + ( rand() % 1000 ) / 100.0f) * signx;
- float h = (10 + ( rand() % 1000 ) / 100.0f) * signy;
- search_segment = S(P(x - w, y - h), P(x + w, y + h));
- found_count = query(cont, bgi::nearest(search_segment, count));
- }
- else
- {
- BOOST_ASSERT(false);
- }
- if ( found_count > 0 )
- {
- if ( query_mode == qm_knn )
- {
- std::cout << "search point: ";
- bgi::detail::utilities::print_indexable(std::cout, search_point);
- }
- else if ( query_mode == qm_knnb )
- {
- std::cout << "search box: ";
- bgi::detail::utilities::print_indexable(std::cout, search_box);
- }
- else if ( query_mode == qm_knns )
- {
- std::cout << "search segment: ";
- bgi::detail::utilities::print_indexable(std::cout, search_segment);
- }
- else
- {
- BOOST_ASSERT(false);
- }
- std::cout << "\nfound: ";
- print_result(cont);
- }
- else
- std::cout << "nearest not found\n";
- }
- #ifndef ENABLE_POINTS_AND_SEGMENTS
- void query_path()
- {
- float x = ( rand() % 1000 ) / 10.0f;
- float y = ( rand() % 1000 ) / 10.0f;
- float w = 20 + ( rand() % 1000 ) / 100.0f;
- float h = 20 + ( rand() % 1000 ) / 100.0f;
- search_path.resize(10);
- float yy = y-h;
- for ( int i = 0 ; i < 5 ; ++i, yy += h / 2 )
- {
- search_path[2 * i] = P(x-w, yy);
- search_path[2 * i + 1] = P(x+w, yy);
- }
-
- found_count = query(cont, bgi::detail::path<LS>(search_path, count));
- if ( found_count > 0 )
- {
- std::cout << "search path: ";
- BOOST_FOREACH(P const& p, search_path)
- bgi::detail::utilities::print_indexable(std::cout, p);
- std::cout << "\nfound: ";
- print_result(cont);
- }
- else
- std::cout << "values on path not found\n";
- }
- #endif
- template <typename Predicate>
- void query()
- {
- if ( query_mode != qm_all )
- {
- float x = ( rand() % 1000 ) / 10.0f;
- float y = ( rand() % 1000 ) / 10.0f;
- float w = 10 + ( rand() % 1000 ) / 100.0f;
- float h = 10 + ( rand() % 1000 ) / 100.0f;
- search_box = B(P(x - w, y - h), P(x + w, y + h));
- }
- else
- {
- search_box = bounds(cont);
- }
- found_count = query(cont, Predicate(search_box));
- if ( found_count > 0 )
- {
- std::cout << "search box: ";
- bgi::detail::utilities::print_indexable(std::cout, search_box);
- std::cout << "\nfound: ";
- print_result(cont);
- }
- else
- std::cout << "boxes not found\n";
- }
- template <typename Predicate>
- void query_ring()
- {
- float x = ( rand() % 1000 ) / 10.0f;
- float y = ( rand() % 1000 ) / 10.0f;
- float w = 10 + ( rand() % 1000 ) / 100.0f;
- float h = 10 + ( rand() % 1000 ) / 100.0f;
- search_ring.clear();
- search_ring.push_back(P(x - w, y - h));
- search_ring.push_back(P(x - w/2, y - h));
- search_ring.push_back(P(x, y - 3*h/2));
- search_ring.push_back(P(x + w/2, y - h));
- search_ring.push_back(P(x + w, y - h));
- search_ring.push_back(P(x + w, y - h/2));
- search_ring.push_back(P(x + 3*w/2, y));
- search_ring.push_back(P(x + w, y + h/2));
- search_ring.push_back(P(x + w, y + h));
- search_ring.push_back(P(x + w/2, y + h));
- search_ring.push_back(P(x, y + 3*h/2));
- search_ring.push_back(P(x - w/2, y + h));
- search_ring.push_back(P(x - w, y + h));
- search_ring.push_back(P(x - w, y + h/2));
- search_ring.push_back(P(x - 3*w/2, y));
- search_ring.push_back(P(x - w, y - h/2));
- search_ring.push_back(P(x - w, y - h));
-
- found_count = query(cont, Predicate(search_ring));
-
- if ( found_count > 0 )
- {
- std::cout << "search ring: ";
- BOOST_FOREACH(P const& p, search_ring)
- {
- bgi::detail::utilities::print_indexable(std::cout, p);
- std::cout << ' ';
- }
- std::cout << "\nfound: ";
- print_result(cont);
- }
- else
- std::cout << "boxes not found\n";
- }
- template <typename Predicate>
- void query_poly()
- {
- float x = ( rand() % 1000 ) / 10.0f;
- float y = ( rand() % 1000 ) / 10.0f;
- float w = 10 + ( rand() % 1000 ) / 100.0f;
- float h = 10 + ( rand() % 1000 ) / 100.0f;
- search_poly.clear();
- search_poly.outer().push_back(P(x - w, y - h));
- search_poly.outer().push_back(P(x - w/2, y - h));
- search_poly.outer().push_back(P(x, y - 3*h/2));
- search_poly.outer().push_back(P(x + w/2, y - h));
- search_poly.outer().push_back(P(x + w, y - h));
- search_poly.outer().push_back(P(x + w, y - h/2));
- search_poly.outer().push_back(P(x + 3*w/2, y));
- search_poly.outer().push_back(P(x + w, y + h/2));
- search_poly.outer().push_back(P(x + w, y + h));
- search_poly.outer().push_back(P(x + w/2, y + h));
- search_poly.outer().push_back(P(x, y + 3*h/2));
- search_poly.outer().push_back(P(x - w/2, y + h));
- search_poly.outer().push_back(P(x - w, y + h));
- search_poly.outer().push_back(P(x - w, y + h/2));
- search_poly.outer().push_back(P(x - 3*w/2, y));
- search_poly.outer().push_back(P(x - w, y - h/2));
- search_poly.outer().push_back(P(x - w, y - h));
- search_poly.inners().push_back(Poly::ring_type());
- search_poly.inners()[0].push_back(P(x - w/2, y - h/2));
- search_poly.inners()[0].push_back(P(x + w/2, y - h/2));
- search_poly.inners()[0].push_back(P(x + w/2, y + h/2));
- search_poly.inners()[0].push_back(P(x - w/2, y + h/2));
- search_poly.inners()[0].push_back(P(x - w/2, y - h/2));
- found_count = query(cont, Predicate(search_poly));
- if ( found_count > 0 )
- {
- std::cout << "search poly outer: ";
- BOOST_FOREACH(P const& p, search_poly.outer())
- {
- bgi::detail::utilities::print_indexable(std::cout, p);
- std::cout << ' ';
- }
- std::cout << "\nfound: ";
- print_result(cont);
- }
- else
- std::cout << "boxes not found\n";
- }
- template <typename Predicate>
- void query_multi_poly()
- {
- float x = ( rand() % 1000 ) / 10.0f;
- float y = ( rand() % 1000 ) / 10.0f;
- float w = 10 + ( rand() % 1000 ) / 100.0f;
- float h = 10 + ( rand() % 1000 ) / 100.0f;
- search_multi_poly.clear();
- search_multi_poly.push_back(Poly());
- search_multi_poly[0].outer().push_back(P(x - w, y - h));
- search_multi_poly[0].outer().push_back(P(x - w/2, y - h));
- search_multi_poly[0].outer().push_back(P(x, y - 3*h/2));
- search_multi_poly[0].outer().push_back(P(x + w/2, y - h));
- search_multi_poly[0].outer().push_back(P(x + w, y - h));
- search_multi_poly[0].outer().push_back(P(x + w, y - h/2));
- search_multi_poly[0].outer().push_back(P(x + 3*w/2, y));
- search_multi_poly[0].outer().push_back(P(x + w, y + h/2));
- search_multi_poly[0].outer().push_back(P(x + w, y + h));
- search_multi_poly[0].outer().push_back(P(x + w/2, y + h));
- search_multi_poly[0].outer().push_back(P(x, y + 3*h/2));
- search_multi_poly[0].outer().push_back(P(x - w/2, y + h));
- search_multi_poly[0].outer().push_back(P(x - w, y + h));
- search_multi_poly[0].outer().push_back(P(x - w, y + h/2));
- search_multi_poly[0].outer().push_back(P(x - 3*w/2, y));
- search_multi_poly[0].outer().push_back(P(x - w, y - h/2));
- search_multi_poly[0].outer().push_back(P(x - w, y - h));
- search_multi_poly[0].inners().push_back(Poly::ring_type());
- search_multi_poly[0].inners()[0].push_back(P(x - w/2, y - h/2));
- search_multi_poly[0].inners()[0].push_back(P(x + w/2, y - h/2));
- search_multi_poly[0].inners()[0].push_back(P(x + w/2, y + h/2));
- search_multi_poly[0].inners()[0].push_back(P(x - w/2, y + h/2));
- search_multi_poly[0].inners()[0].push_back(P(x - w/2, y - h/2));
- search_multi_poly.push_back(Poly());
- search_multi_poly[1].outer().push_back(P(x - 2*w, y - 2*h));
- search_multi_poly[1].outer().push_back(P(x - 6*w/5, y - 2*h));
- search_multi_poly[1].outer().push_back(P(x - 6*w/5, y - 6*h/5));
- search_multi_poly[1].outer().push_back(P(x - 2*w, y - 6*h/5));
- search_multi_poly[1].outer().push_back(P(x - 2*w, y - 2*h));
- search_multi_poly.push_back(Poly());
- search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 6*h/5));
- search_multi_poly[2].outer().push_back(P(x + 2*w, y + 6*h/5));
- search_multi_poly[2].outer().push_back(P(x + 2*w, y + 2*h));
- search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 2*h));
- search_multi_poly[2].outer().push_back(P(x + 6*w/5, y + 6*h/5));
- found_count = query(cont, Predicate(search_multi_poly));
-
- if ( found_count > 0 )
- {
- std::cout << "search multi_poly[0] outer: ";
- BOOST_FOREACH(P const& p, search_multi_poly[0].outer())
- {
- bgi::detail::utilities::print_indexable(std::cout, p);
- std::cout << ' ';
- }
- std::cout << "\nfound: ";
- print_result(cont);
- }
- else
- std::cout << "boxes not found\n";
- }
- template <typename Predicate>
- void query_segment()
- {
- float x = ( rand() % 1000 ) / 10.0f;
- float y = ( rand() % 1000 ) / 10.0f;
- float w = 10.0f - ( rand() % 1000 ) / 50.0f;
- float h = 10.0f - ( rand() % 1000 ) / 50.0f;
- w += 0 <= w ? 10 : -10;
- h += 0 <= h ? 10 : -10;
- boost::geometry::set<0, 0>(search_segment, x - w);
- boost::geometry::set<0, 1>(search_segment, y - h);
- boost::geometry::set<1, 0>(search_segment, x + w);
- boost::geometry::set<1, 1>(search_segment, y + h);
- found_count = query(cont, Predicate(search_segment));
-
- if ( found_count > 0 )
- {
- std::cout << "search segment: ";
- bgi::detail::utilities::print_indexable(std::cout, P(x-w, y-h));
- bgi::detail::utilities::print_indexable(std::cout, P(x+w, y+h));
- std::cout << "\nfound: ";
- print_result(cont);
- }
- else
- std::cout << "boxes not found\n";
- }
- template <typename Predicate>
- void query_linestring()
- {
- float x = ( rand() % 1000 ) / 10.0f;
- float y = ( rand() % 1000 ) / 10.0f;
- float w = 10 + ( rand() % 1000 ) / 100.0f;
- float h = 10 + ( rand() % 1000 ) / 100.0f;
- search_linestring.clear();
- float a = 0;
- float d = 0;
- for ( size_t i = 0 ; i < 300 ; ++i, a += 0.05, d += 0.005 )
- {
- float xx = x + w * d * ::cos(a);
- float yy = y + h * d * ::sin(a);
- search_linestring.push_back(P(xx, yy));
- }
- found_count = query(cont, Predicate(search_linestring));
-
- if ( found_count > 0 )
- {
- std::cout << "search linestring: ";
- BOOST_FOREACH(P const& p, search_linestring)
- {
- bgi::detail::utilities::print_indexable(std::cout, p);
- std::cout << ' ';
- }
- std::cout << "\nfound: ";
- print_result(cont);
- }
- else
- std::cout << "boxes not found\n";
- }
- // the function running the correct query based on the query_mode
- void search()
- {
- namespace d = bgi::detail;
- if ( query_mode == qm_knn || query_mode == qm_knnb || query_mode == qm_knns )
- query_knn();
- else if ( query_mode == qm_d )
- query< d::spatial_predicate<B, d::disjoint_tag, false> >();
- else if ( query_mode == qm_i )
- query< d::spatial_predicate<B, d::intersects_tag, false> >();
- else if ( query_mode == qm_nd )
- query< d::spatial_predicate<B, d::disjoint_tag, true> >();
- else if ( query_mode == qm_ni )
- query< d::spatial_predicate<B, d::intersects_tag, true> >();
- else if ( query_mode == qm_all )
- query< d::spatial_predicate<B, d::intersects_tag, false> >();
- #ifdef ENABLE_POINTS_AND_SEGMENTS
- else
- std::cout << "query disabled\n";
- #else
- else if ( query_mode == qm_c )
- query< d::spatial_predicate<B, d::covered_by_tag, false> >();
- else if ( query_mode == qm_o )
- query< d::spatial_predicate<B, d::overlaps_tag, false> >();
- else if ( query_mode == qm_w )
- query< d::spatial_predicate<B, d::within_tag, false> >();
- else if ( query_mode == qm_nc )
- query< d::spatial_predicate<B, d::covered_by_tag, true> >();
- else if ( query_mode == qm_no )
- query< d::spatial_predicate<B, d::overlaps_tag, true> >();
- else if ( query_mode == qm_nw )
- query< d::spatial_predicate<B, d::within_tag, true> >();
- else if ( query_mode == qm_ri )
- query_ring< d::spatial_predicate<R, d::intersects_tag, false> >();
- else if ( query_mode == qm_pi )
- query_poly< d::spatial_predicate<Poly, d::intersects_tag, false> >();
- else if ( query_mode == qm_mpi )
- query_multi_poly< d::spatial_predicate<MPoly, d::intersects_tag, false> >();
- else if ( query_mode == qm_si )
- query_segment< d::spatial_predicate<S, d::intersects_tag, false> >();
- else if ( query_mode == qm_lsi )
- query_linestring< d::spatial_predicate<LS, d::intersects_tag, false> >();
- else if ( query_mode == qm_path )
- query_path();
- #endif
- search_valid = true;
- }
- // various drawing functions
- void draw_point(P const& p)
- {
- float x = boost::geometry::get<0>(p);
- float y = boost::geometry::get<1>(p);
- float z = depth(cont);
- glBegin(GL_QUADS);
- glVertex3f(x+1, y, z);
- glVertex3f(x, y+1, z);
- glVertex3f(x-1, y, z);
- glVertex3f(x, y-1, z);
- glEnd();
- }
- void draw_knn_area(float min_distance, float max_distance)
- {
- float x = boost::geometry::get<0>(search_point);
- float y = boost::geometry::get<1>(search_point);
- float z = depth(cont);
- draw_point(search_point);
- // search min circle
- glBegin(GL_LINE_LOOP);
- for(float a = 0 ; a < 3.14158f * 2 ; a += 3.14158f / 180)
- glVertex3f(x + min_distance * ::cos(a), y + min_distance * ::sin(a), z);
- glEnd();
- // search max circle
- glBegin(GL_LINE_LOOP);
- for(float a = 0 ; a < 3.14158f * 2 ; a += 3.14158f / 180)
- glVertex3f(x + max_distance * ::cos(a), y + max_distance * ::sin(a), z);
- glEnd();
- }
- void draw_linestring(LS const& ls)
- {
- glBegin(GL_LINE_STRIP);
- BOOST_FOREACH(P const& p, ls)
- {
- float x = boost::geometry::get<0>(p);
- float y = boost::geometry::get<1>(p);
- float z = depth(cont);
- glVertex3f(x, y, z);
- }
- glEnd();
- }
- void draw_segment(S const& s)
- {
- float x1 = boost::geometry::get<0, 0>(s);
- float y1 = boost::geometry::get<0, 1>(s);
- float x2 = boost::geometry::get<1, 0>(s);
- float y2 = boost::geometry::get<1, 1>(s);
- float z = depth(cont);
- glBegin(GL_LINES);
- glVertex3f(x1, y1, z);
- glVertex3f(x2, y2, z);
- glEnd();
- }
- template <typename Box>
- void draw_box(Box const& box)
- {
- float x1 = boost::geometry::get<bg::min_corner, 0>(box);
- float y1 = boost::geometry::get<bg::min_corner, 1>(box);
- float x2 = boost::geometry::get<bg::max_corner, 0>(box);
- float y2 = boost::geometry::get<bg::max_corner, 1>(box);
- float z = depth(cont);
- // search box
- glBegin(GL_LINE_LOOP);
- glVertex3f(x1, y1, z);
- glVertex3f(x2, y1, z);
- glVertex3f(x2, y2, z);
- glVertex3f(x1, y2, z);
- glEnd();
- }
- template <typename Range>
- void draw_ring(Range const& range)
- {
- float z = depth(cont);
- // search box
- glBegin(GL_LINE_LOOP);
-
- BOOST_FOREACH(P const& p, range)
- {
- float x = boost::geometry::get<0>(p);
- float y = boost::geometry::get<1>(p);
- glVertex3f(x, y, z);
- }
- glEnd();
- }
- template <typename Polygon>
- void draw_polygon(Polygon const& polygon)
- {
- draw_ring(polygon.outer());
- BOOST_FOREACH(Poly::ring_type const& r, polygon.inners())
- draw_ring(r);
- }
- template <typename MultiPolygon>
- void draw_multi_polygon(MultiPolygon const& multi_polygon)
- {
- BOOST_FOREACH(Poly const& p, multi_polygon)
- draw_polygon(p);
- }
- // render the scene -> tree, if searching data available also the query geometry and result
- void render_scene(void)
- {
- glClear(GL_COLOR_BUFFER_BIT);
- draw_tree(cont);
- if ( search_valid )
- {
- glColor3f(1.0f, 0.25f, 0.0f);
- if ( query_mode == qm_knn )
- draw_knn_area(0, 0);
- else if ( query_mode == qm_knnb )
- draw_box(search_box);
- else if ( query_mode == qm_knns )
- draw_segment(search_segment);
- else if ( query_mode == qm_ri )
- draw_ring(search_ring);
- else if ( query_mode == qm_pi )
- draw_polygon(search_poly);
- else if ( query_mode == qm_mpi )
- draw_multi_polygon(search_multi_poly);
- else if ( query_mode == qm_si )
- draw_segment(search_segment);
- else if ( query_mode == qm_lsi )
- draw_linestring(search_linestring);
- else if ( query_mode == qm_path )
- draw_linestring(search_path);
- else
- draw_box(search_box);
- glColor3f(1.0f, 0.5f, 0.0f);
- draw_result(cont);
- }
- glFlush();
- }
- void resize(int w, int h)
- {
- if ( h == 0 )
- h = 1;
- //float ratio = float(w) / h;
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glViewport(0, 0, w, h);
- //gluPerspective(45, ratio, 1, 1000);
- glOrtho(-150, 150, -150, 150, -150, 150);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- /*gluLookAt(
- 120.0f, 120.0f, 120.0f,
- 50.0f, 50.0f, -1.0f,
- 0.0f, 1.0f, 0.0f);*/
- gluLookAt(
- 50.0f, 50.0f, 75.0f,
- 50.0f, 50.0f, -1.0f,
- 0.0f, 1.0f, 0.0f);
- glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- glLineWidth(1.5f);
- srand(1);
- }
- // randomize various indexables
- inline void rand_val(B & b)
- {
- float x = ( rand() % 100 );
- float y = ( rand() % 100 );
- float w = ( rand() % 2 ) + 1;
- float h = ( rand() % 2 ) + 1;
- b = B(P(x - w, y - h),P(x + w, y + h));
- }
- inline void rand_val(P & p)
- {
- float x = ( rand() % 100 );
- float y = ( rand() % 100 );
- p = P(x, y);
- }
- inline void rand_val(S & s)
- {
- float x = ( rand() % 100 );
- float y = ( rand() % 100 );
- float w = ( rand() % 2 + 1) * (rand() % 2 ? 1.0f : -1.0f);
- float h = ( rand() % 2 + 1) * (rand() % 2 ? 1.0f : -1.0f);
- s = S(P(x - w, y - h),P(x + w, y + h));
- }
- // more higher-level visitors
- struct insert_random_value_v : boost::static_visitor<>
- {
- template <typename V>
- void operator()(containers<V> & c) const
- {
- V v;
- rand_val(v);
-
- boost::geometry::index::insert(c.tree, v);
- c.values.push_back(v);
- std::cout << "inserted: ";
- bgi::detail::utilities::print_indexable(std::cout, v);
- std::cout << '\n';
- std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
- std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
- std::cout << "\n";
- }
- };
- template <typename Cont>
- inline void insert_random_value(Cont & cont)
- {
- return boost::apply_visitor(insert_random_value_v(), cont);
- }
- struct remove_random_value_v : boost::static_visitor<>
- {
- template <typename V>
- void operator()(containers<V> & c) const
- {
- if ( c.values.empty() )
- return;
- size_t i = rand() % c.values.size();
- V v = c.values[i];
- c.tree.remove(v);
- c.values.erase(c.values.begin() + i);
- std::cout << "removed: ";
- bgi::detail::utilities::print_indexable(std::cout, v);
- std::cout << '\n';
- std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
- std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
- std::cout << "\n";
- }
- };
- template <typename Cont>
- inline void remove_random_value(Cont & cont)
- {
- return boost::apply_visitor(remove_random_value_v(), cont);
- }
- // handle mouse input
- void mouse(int button, int state, int /*x*/, int /*y*/)
- {
- if ( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
- {
- insert_random_value(cont);
- search_valid = false;
- }
- else if ( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
- {
- remove_random_value(cont);
- search_valid = false;
- }
- else if ( button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN )
- {
- search();
- }
- glutPostRedisplay();
- }
- // more higher-level visitors
- struct insert_random_values_v : boost::static_visitor<>
- {
- template <typename V>
- void operator()(containers<V> & c) const
- {
- for ( size_t i = 0 ; i < 35 ; ++i )
- {
- V v;
- rand_val(v);
- c.tree.insert(v);
- c.values.push_back(v);
- std::cout << "inserted: ";
- bgi::detail::utilities::print_indexable(std::cout, v);
- std::cout << '\n';
- }
- std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
- std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
- std::cout << "\n";
- }
- };
- template <typename Cont>
- inline void insert_random_values(Cont & cont)
- {
- return boost::apply_visitor(insert_random_values_v(), cont);
- }
- struct bulk_insert_random_values_v : boost::static_visitor<>
- {
- template <typename V>
- void operator()(containers<V> & c) const
- {
- c.values.clear();
- for ( size_t i = 0 ; i < 35 ; ++i )
- {
- V v;
- rand_val(v);
- c.values.push_back(v);
- std::cout << "inserted: ";
- bgi::detail::utilities::print_indexable(std::cout, v);
- std::cout << '\n';
- }
- create(c.tree, c.values);
- std::cout << ( bgi::detail::rtree::utilities::are_boxes_ok(c.tree) ? "boxes OK\n" : "WRONG BOXES!\n" );
- std::cout << ( bgi::detail::rtree::utilities::are_levels_ok(c.tree) ? "levels OK\n" : "WRONG LEVELS!\n" );
- std::cout << "\n";
- }
- template <typename Tree, typename Values>
- void create(Tree & tree, Values const& values) const
- {
- Tree t(values);
- tree = boost::move(t);
- }
- };
- template <typename Cont>
- inline void bulk_insert_random_values(Cont & cont)
- {
- return boost::apply_visitor(bulk_insert_random_values_v(), cont);
- }
- // handle keyboard input
- std::string current_line;
- void keyboard(unsigned char key, int /*x*/, int /*y*/)
- {
- if ( key == '\r' || key == '\n' )
- {
- if ( current_line == "storeb" )
- {
- cont = containers<B>();
- glutPostRedisplay();
- }
- #ifdef ENABLE_POINTS_AND_SEGMENTS
- else if ( current_line == "storep" )
- {
- cont = containers<P>();
- glutPostRedisplay();
- }
- else if ( current_line == "stores" )
- {
- cont = containers<S>();
- glutPostRedisplay();
- }
- #endif
- else if ( current_line == "t" )
- {
- std::cout << "\n";
- print_tree(cont);
- std::cout << "\n";
- }
- else if ( current_line == "rand" )
- {
- insert_random_values(cont);
- search_valid = false;
- glutPostRedisplay();
- }
- else if ( current_line == "bulk" )
- {
- bulk_insert_random_values(cont);
- search_valid = false;
- glutPostRedisplay();
- }
- else
- {
- if ( current_line == "knn" )
- query_mode = qm_knn;
- else if ( current_line == "knnb" )
- query_mode = qm_knnb;
- else if ( current_line == "knns" )
- query_mode = qm_knns;
- else if ( current_line == "c" )
- query_mode = qm_c;
- else if ( current_line == "d" )
- query_mode = qm_d;
- else if ( current_line == "i" )
- query_mode = qm_i;
- else if ( current_line == "o" )
- query_mode = qm_o;
- else if ( current_line == "w" )
- query_mode = qm_w;
- else if ( current_line == "nc" )
- query_mode = qm_nc;
- else if ( current_line == "nd" )
- query_mode = qm_nd;
- else if ( current_line == "ni" )
- query_mode = qm_ni;
- else if ( current_line == "no" )
- query_mode = qm_no;
- else if ( current_line == "nw" )
- query_mode = qm_nw;
- else if ( current_line == "all" )
- query_mode = qm_all;
- else if ( current_line == "ri" )
- query_mode = qm_ri;
- else if ( current_line == "pi" )
- query_mode = qm_pi;
- else if ( current_line == "mpi" )
- query_mode = qm_mpi;
- else if ( current_line == "si" )
- query_mode = qm_si;
- else if ( current_line == "lsi" )
- query_mode = qm_lsi;
- else if ( current_line == "path" )
- query_mode = qm_path;
-
- search();
- glutPostRedisplay();
- }
- current_line.clear();
- std::cout << '\n';
- }
- else
- {
- current_line += key;
- std::cout << key;
- }
- }
- // main function
- int main(int argc, char **argv)
- {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
- glutInitWindowPosition(100,100);
- glutInitWindowSize(600, 600);
- glutCreateWindow("boost::geometry::index::rtree GLUT test");
- glutDisplayFunc(render_scene);
- glutReshapeFunc(resize);
- glutMouseFunc(mouse);
- glutKeyboardFunc(keyboard);
- glutMainLoop();
- return 0;
- }
|