diff --git a/doc/html/img/index/rtree/path.png b/doc/html/img/index/rtree/path.png new file mode 100644 index 000000000..fa393abff Binary files /dev/null and b/doc/html/img/index/rtree/path.png differ diff --git a/doc/index/rtree/experimental.qbk b/doc/index/rtree/experimental.qbk index e007281a1..65a0dc959 100644 --- a/doc/index/rtree/experimental.qbk +++ b/doc/index/rtree/experimental.qbk @@ -31,12 +31,26 @@ a relation object instead of a Point to the nearest predicate, as follows: /* caluclate distance to the Indexables' furthest points */ rtree.query(index::nearest(index::to_furthest(pt), k), std::back_inserter(returned_values)); +[heading Path query] + +Path query returns `k` first `__value__`s intersecting a path defined by a `Linestring`. Query returning first 5 +values intersecting a path is presented below. Path's flow is denoted by blue arrows, returned values are orange. + +[$img/index/rtree/path.png] + +To perform this query one may pass a `path()` predicate taking a `Linestring` and maximum number of `__value__`s which +should be returned: + + rtree.query(index::path(linestring, k), std::back_inserter(returned_values)); + +[warning Only one distance predicate may be used in a query. This means that there can be only one `nearest()` or `path()` predicate passed. Passing more of them will result in compile-time error.] + [heading Incremental queries] Sometimes there is a need to brake querying at some desired point because it depends on objects already returned or to pause it in order to resume later. For this purpose iterators may be used. -In this library incremental queries are implemented as input (single pass) const iterators, relatively +Currently incremental queries are implemented as input (single pass) const iterators, relatively big fat-iterators storing stack used in the tree-traversing process. Because the type of predicates passed to the query varies, the type of the iterator varies as well. diff --git a/index/example/benchmark_experimental.cpp b/index/example/benchmark_experimental.cpp index 7b8a7cbe6..8bd7b90c0 100644 --- a/index/example/benchmark_experimental.cpp +++ b/index/example/benchmark_experimental.cpp @@ -17,12 +17,14 @@ #include #include +#include namespace bg = boost::geometry; namespace bgi = bg::index; typedef bg::model::point P; typedef bg::model::box

B; +typedef bg::model::linestring

LS; template void mycopy(I1 first, I2 last, O o) @@ -40,14 +42,16 @@ int main() size_t queries_count = 100000; size_t nearest_queries_count = 10000; unsigned neighbours_count = 10; + size_t path_queries_count = 1000; + unsigned path_values_count = 10; + float max_val = static_cast(values_count / 2); std::vector< std::pair > coords; //randomize values { boost::mt19937 rng; //rng.seed(static_cast(std::time(0))); - float max_val = static_cast(values_count / 2); boost::uniform_real range(-max_val, max_val); boost::variate_generator > rnd(rng, range); @@ -242,7 +246,7 @@ int main() { clock_t::time_point start = clock_t::now(); size_t temp = 0; - for (size_t i = 0 ; i < queries_count ; ++i ) + for (size_t i = 0 ; i < nearest_queries_count ; ++i ) { float x = coords[i].first; float y = coords[i].second; @@ -255,9 +259,32 @@ int main() dur_t time = clock_t::now() - start; std::cout << time << " - type-erased qbegin(nearest(P, " << neighbours_count << ")) qend(n) " << nearest_queries_count << " found " << temp << '\n'; } -#endif #endif + { + LS ls; + ls.resize(6); + + clock_t::time_point start = clock_t::now(); + size_t temp = 0; + for (size_t i = 0 ; i < path_queries_count ; ++i ) + { + float x = coords[i].first; + float y = coords[i].second; + for ( int i = 0 ; i < 3 ; ++i ) + { + float foo = i*max_val/300; + ls[2*i] = P(x, y+foo); + ls[2*i+1] = P(x+max_val/100, y+foo); + } + result.clear(); + t.query(bgi::path(ls, path_values_count), std::back_inserter(result)); + temp += result.size(); + } + dur_t time = clock_t::now() - start; + std::cout << time << " - query(path(LS, " << path_values_count << ")) " << path_queries_count << " found " << temp << '\n'; + } +#endif { clock_t::time_point start = clock_t::now(); for (size_t i = 0 ; i < values_count / 10 ; ++i ) diff --git a/index/example/glut_vis.cpp b/index/example/glut_vis.cpp index d65f293b1..c311d65d2 100644 --- a/index/example/glut_vis.cpp +++ b/index/example/glut_vis.cpp @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -30,6 +31,7 @@ namespace bgi = bg::index; typedef bg::model::point P; typedef bg::model::box

B; //bgi::rtree t(2, 1); +typedef bg::model::linestring

LS; typedef bg::model::ring

R; typedef bg::model::polygon

Poly; typedef bg::model::multi_polygon MPoly; @@ -48,14 +50,15 @@ B search_box; R search_ring; Poly search_poly; MPoly search_multi_poly; +LS search_path; enum query_mode_type { - qm_knn, 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_knn, 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_path } query_mode = qm_knn; bool search_valid = false; -void knn() +void query_knn() { float x = ( rand() % 1000 ) / 10.0f; float y = ( rand() % 1000 ) / 10.0f; @@ -82,6 +85,43 @@ void knn() std::cout << "nearest not found\n"; } +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); + } + + nearest_boxes.clear(); + found_count = t.query( + bgi::detail::path(search_path, count), + std::back_inserter(nearest_boxes) + ); + + if ( found_count > 0 ) + { + std::cout << "search path: "; + BOOST_FOREACH(P const& p, search_path) + bgi::detail::rtree::visitors::detail::print_indexable(std::cout, p); + std::cout << "\nfound: "; + for ( size_t i = 0 ; i < nearest_boxes.size() ; ++i ) + { + bgi::detail::rtree::visitors::detail::print_indexable(std::cout, nearest_boxes[i]); + std::cout << '\n'; + } + } + else + std::cout << "values on path not found\n"; +} + template void query() { @@ -298,7 +338,7 @@ void query_multi_poly() void search() { if ( query_mode == qm_knn ) - knn(); + query_knn(); else if ( query_mode == qm_c ) query< bgi::detail::covered_by >(); else if ( query_mode == qm_d ) @@ -327,6 +367,8 @@ void search() query_poly< bgi::detail::intersects >(); else if ( query_mode == qm_mpi ) query_multi_poly< bgi::detail::intersects >(); + else if ( query_mode == qm_path ) + query_path(); search_valid = true; } @@ -359,6 +401,21 @@ void draw_knn_area(float min_distance, float max_distance) glEnd(); } +void draw_path(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 = t.depth(); + glVertex3f(x, y, z); + } + + glEnd(); +} + template void draw_box(Box const& box) { @@ -428,6 +485,8 @@ void render_scene(void) draw_polygon(search_poly); else if ( query_mode == qm_mpi ) draw_multi_polygon(search_multi_poly); + else if ( query_mode == qm_path ) + draw_path(search_path); else draw_box(search_box); @@ -591,6 +650,8 @@ void keyboard(unsigned char key, int x, int y) query_mode = qm_pi; else if ( current_line == "mpi" ) query_mode = qm_mpi; + else if ( current_line == "path" ) + query_mode = qm_path; search(); glutPostRedisplay();