// 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ENABLE_POINTS_AND_SEGMENTS namespace bg = boost::geometry; namespace bgi = bg::index; // used types typedef bg::model::point P; typedef bg::model::box

B; typedef bg::model::linestring

LS; typedef bg::model::segment

S; typedef bg::model::ring

R; typedef bg::model::polygon

Poly; typedef bg::model::multi_polygon MPoly; // containers variant template 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 values; std::vector result; }; boost::variant< containers #ifdef ENABLE_POINTS_AND_SEGMENTS , containers

, containers #endif > cont; // visitors template struct query_v : boost::static_visitor { Pred m_pred; query_v(Pred const& pred) : m_pred(pred) {} template size_t operator()(C & c) const { c.result.clear(); return c.tree.query(m_pred, std::back_inserter(c.result)); } }; template inline size_t query(Cont & cont, Pred const& pred) { return boost::apply_visitor(query_v(pred), cont); } struct print_result_v : boost::static_visitor<> { template 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 inline void print_result(Cont const& cont) { boost::apply_visitor(print_result_v(), cont); } struct bounds_v : boost::static_visitor { template B operator()(C & c) const { return c.tree.bounds(); } }; template inline B bounds(Cont const& cont) { return boost::apply_visitor(bounds_v(), cont); } struct depth_v : boost::static_visitor { template size_t operator()(C & c) const { return get(c.tree); } template static size_t get(RTree const& t) { return bgi::detail::rtree::utilities::view(t).depth(); } }; template inline size_t depth(Cont const& cont) { return boost::apply_visitor(depth_v(), cont); } struct draw_tree_v : boost::static_visitor<> { template void operator()(C & c) const { bgi::detail::rtree::utilities::gl_draw(c.tree); } }; template inline void draw_tree(Cont const& cont) { return boost::apply_visitor(draw_tree_v(), cont); } struct draw_result_v : boost::static_visitor<> { template 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 inline void draw_result(Cont const& cont) { return boost::apply_visitor(draw_result_v(), cont); } struct print_tree_v : boost::static_visitor<> { template void operator()(C & c) const { bgi::detail::rtree::utilities::print(std::cout, c.tree); } }; template 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(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 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 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 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 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 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 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 >(); else if ( query_mode == qm_i ) query< d::spatial_predicate >(); else if ( query_mode == qm_nd ) query< d::spatial_predicate >(); else if ( query_mode == qm_ni ) query< d::spatial_predicate >(); else if ( query_mode == qm_all ) query< d::spatial_predicate >(); #ifdef ENABLE_POINTS_AND_SEGMENTS else std::cout << "query disabled\n"; #else else if ( query_mode == qm_c ) query< d::spatial_predicate >(); else if ( query_mode == qm_o ) query< d::spatial_predicate >(); else if ( query_mode == qm_w ) query< d::spatial_predicate >(); else if ( query_mode == qm_nc ) query< d::spatial_predicate >(); else if ( query_mode == qm_no ) query< d::spatial_predicate >(); else if ( query_mode == qm_nw ) query< d::spatial_predicate >(); else if ( query_mode == qm_ri ) query_ring< d::spatial_predicate >(); else if ( query_mode == qm_pi ) query_poly< d::spatial_predicate >(); else if ( query_mode == qm_mpi ) query_multi_poly< d::spatial_predicate >(); else if ( query_mode == qm_si ) query_segment< d::spatial_predicate >(); else if ( query_mode == qm_lsi ) query_linestring< d::spatial_predicate >(); 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 void draw_box(Box const& box) { float x1 = boost::geometry::get(box); float y1 = boost::geometry::get(box); float x2 = boost::geometry::get(box); float y2 = boost::geometry::get(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 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 void draw_polygon(Polygon const& polygon) { draw_ring(polygon.outer()); BOOST_FOREACH(Poly::ring_type const& r, polygon.inners()) draw_ring(r); } template 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 void operator()(containers & 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 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 void operator()(containers & 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 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 void operator()(containers & 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 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 void operator()(containers & 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 void create(Tree & tree, Values const& values) const { Tree t(values); tree = boost::move(t); } }; template 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(); glutPostRedisplay(); } #ifdef ENABLE_POINTS_AND_SEGMENTS else if ( current_line == "storep" ) { cont = containers

(); glutPostRedisplay(); } else if ( current_line == "stores" ) { cont = containers(); 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; }