1[/============================================================================ 2 Boost.Geometry Index 3 4 Copyright (c) 2011-2017 Adam Wulkiewicz. 5 6 Use, modification and distribution is subject to the Boost Software License, 7 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 8 http://www.boost.org/LICENSE_1_0.txt) 9=============================================================================/] 10 11[section Queries] 12 13Queries returns `__value__`s which meets some predicates. Currently supported are three types of predicates: 14 15* spatial predicates - spatial conditions that must be met by stored Value and some Geometry, 16* distance predicates - distance conditions that must be met by stored Value and some Geometry, 17* user-defined unary predicate - function, function object or lambda expression checking user-defined condition. 18 19For example queries may be used to retrieve Values: 20 21* intersecting some area but not within other area, 22* are nearest to some point, 23* overlapping a box and has user-defined property. 24 25[h4 Performing a query] 26 27There are various ways to perform a query. They are presented below. 28All of them returns `__value__`s intersecting some region defined as a `__box__`. 29 30Member function call 31 32 std::vector<__value__> returned_values; 33 __box__ box_region(...); 34 rt.query(bgi::intersects(box_region), std::back_inserter(returned_values)); 35 36Free function call 37 38 std::vector<__value__> returned_values; 39 __box__ box_region(...); 40 bgi::query(rt, bgi::intersects(box_region), std::back_inserter(returned_values)); 41 42Range generated by `operator|` 43 44 __box__ box_region(...); 45 BOOST_FOREACH(__value__ & v, rt | bgi::adaptors::queried(bgi::intersects(box_region))) 46 ; // do something with v 47 48Query iterators returned by member functions 49 50 std::vector<__value__> returned_values; 51 __box__ box_region(...); 52 std::copy(rt.qbegin(bgi::intersects(box_region)), rt.qend(), std::back_inserter(returned_values)); 53 54Query iterators returned by free functions 55 56 std::vector<__value__> returned_values; 57 __box__ box_region(...); 58 std::copy(bgi::qbegin(rt, bgi::intersects(box_region)), bgi::qend(rt), std::back_inserter(returned_values)); 59 60[h4 Spatial queries] 61 62Queries using spatial predicates returns `__value__`s which are related somehow to some Geometry - box, polygon, etc. 63Names of spatial predicates correspond to names of __boost_geometry__ algorithms (boolean operations). 64Examples of some basic queries may be found in the tables below. The query region and result `Value`s are orange. 65 66[table 67[[intersects(Box)] [covered_by(Box)] [disjoint(Box)] [overlaps(Box)] [within(Box)]] 68[[[$img/index/rtree/intersects.png]] [[$img/index/rtree/within.png]] [[$img/index/rtree/disjoint.png]] [[$img/index/rtree/overlaps.png]] [[$img/index/rtree/within.png]]] 69] 70 71[table 72[[intersects(Segment)] [intersects(Box)] [disjoint(Box)] [intersects(Box)] [disjoint(Box)]] 73[[[$img/index/rtree/intersects_segment.png]] [[$img/index/rtree/rtree_pt_intersects_box.png]] [[$img/index/rtree/rtree_pt_disjoint_box.png]] [[$img/index/rtree/rtree_seg_intersects_box.png]] [[$img/index/rtree/rtree_seg_disjoint_box.png]]] 74] 75 76[/table 77[[intersects(Ring)] [intersects(Polygon)] [intersects(MultiPolygon)] [intersects(Segment)] [intersects(Linestring)]] 78[[[$img/index/rtree/intersects_ring.png]] [[$img/index/rtree/intersects_poly.png]] [[$img/index/rtree/intersects_mpoly.png]] [[$img/index/rtree/intersects_segment.png]] [[$img/index/rtree/intersects_linestring.png]]] 79/] 80 81[/table 82[[intersects(Box)] [disjoint(Box)] [intersects(Box)] [disjoint(Box)]] 83[[[$img/index/rtree/rtree_pt_intersects_box.png]] [[$img/index/rtree/rtree_pt_disjoint_box.png]] [[$img/index/rtree/rtree_seg_intersects_box.png]] [[$img/index/rtree/rtree_seg_disjoint_box.png]]] 84/] 85 86Spatial predicates are generated by functions defined in `boost::geometry::index` namespace. 87 88 rt.query(index::contains(box), std::back_inserter(result)); 89 rt.query(index::covered_by(box), std::back_inserter(result)); 90 rt.query(index::covers(box), std::back_inserter(result)); 91 rt.query(index::disjont(box), std::back_inserter(result)); 92 rt.query(index::intersects(box), std::back_inserter(result)); 93 rt.query(index::overlaps(box), std::back_inserter(result)); 94 rt.query(index::within(box), std::back_inserter(result)); 95 96All spatial predicates may be negated, e.g.: 97 98 rt.query(!index::intersects(box), std::back_inserter(result)); 99 // the same as 100 rt.query(index::disjoint(box), std::back_inserter(result)); 101 102[h4 Nearest neighbours queries] 103 104Nearest neighbours queries returns `__value__`s which are closest to some Geometry. 105The examples of k-NN queries are presented below. 5 `__value__`s nearest to the Geometry are orange. 106 107[table 108[[nearest(Point, k)] [nearest(Box, k)] [nearest(Point, k)] [nearest(Box, k)]] 109[[[$img/index/rtree/knn_pt_box.png]] [[$img/index/rtree/knn_box_box.png]] [[$img/index/rtree/rtree_pt_knn_pt.png]] [[$img/index/rtree/rtree_pt_knn_box.png]]] 110] 111[table 112[[nearest(Segment, k)] 113 [nearest(Point, k)] [nearest(Box, k)] [nearest(Segment, k)] 114 [nearest(Segment, k)]] 115[[[$img/index/rtree/knn_seg_box.png]] 116 [[$img/index/rtree/rtree_seg_knn_pt.png]] [[$img/index/rtree/rtree_seg_knn_box.png]] [[$img/index/rtree/rtree_seg_knn_seg.png]] 117 [[$img/index/rtree/rtree_pt_knn_seg.png]]] 118] 119 120To perform the knn query one must pass the nearest predicate generated by the 121`nearest()` function defined in `boost::geometry::index` namespace. 122For non-point `__indexable__`s the shortest distance is calculated using `bg::comparable_distance()` function. 123The following query returns `k` `__value__`s closest to some Point in space. 124 125 std::vector<__value__> returned_values; 126 __point__ pt(/*...*/); 127 rt.query(bgi::nearest(pt, k), std::back_inserter(returned_values)); 128 129The same way different query Geometries can be used: 130 131 __box__ box(/*...*/); 132 rt.query(bgi::nearest(box, k), std::back_inserter(returned_values)); 133 134 Segment seg(/*...*/); 135 rt.query(bgi::nearest(seg, k), std::back_inserter(returned_values)); 136 137[note In case of k-NN queries performed with `query()` function it's not guaranteed that the returned values will be sorted according to the distance. 138 It's different in case of k-NN queries performed with query iterator returned by `qbegin()` function which guarantees the iteration over the closest `__value__`s first. ] 139 140[h4 User-defined unary predicate] 141 142The user may pass a `UnaryPredicate` - function, function object or lambda expression taking const reference to Value and returning bool. 143This object may be passed to the query in order to check if `__value__` should be returned by the query. To do it one 144may use `index::satisfies()` function like on the example below: 145 146 bool is_red(__value__ const& v) 147 { 148 return v.is_red(); 149 } 150 151 struct is_red_o 152 { 153 template <typename Value> 154 bool operator()(__value__ const& v) 155 { 156 return v.is_red(); 157 } 158 } 159 160 // ... 161 162 rt.query(index::intersects(box) && index::satisfies(is_red), 163 std::back_inserter(result)); 164 165 rt.query(index::intersects(box) && index::satisfies(is_red_o()), 166 std::back_inserter(result)); 167 168 #ifndef BOOST_NO_CXX11_LAMBDAS 169 rt.query(index::intersects(box) && index::satisfies([](__value__ const& v) { return v.is_red(); }), 170 std::back_inserter(result)); 171 #endif 172 173`satisfies()` may be negated, e.g.: 174 175 bool is_red(__value__ const& v) { return v.is_red(); } 176 bool is_not_red(__value__ const& v) { return !v.is_red(); } 177 178 // ... 179 180 rt.query(index::intersects(box) && index::satisfies(is_red), 181 std::back_inserter(result)); 182 // the same as 183 rt.query(index::intersects(box) && !index::satisfies(is_not_red), 184 std::back_inserter(result)); 185 186[h4 Passing set of predicates] 187 188It's possible to use some number of predicates in one query by connecting them with `operator&&` e.g. `Pred1 && Pred2 && Pred3 && ...`. 189 190These predicates are connected by logical AND. Passing all predicates together not only makes possible 191to construct advanced queries but is also faster than separate calls because the tree is traversed only once. 192Traversing is continued and `Value`s are returned only if all predicates are met. Predicates are checked 193left-to-right so placing most restrictive predicates first should accelerate the search. 194 195 rt.query(index::intersects(box1) && !index::within(box2), 196 std::back_inserter(result)); 197 198 rt.query(index::intersects(box1) && !index::within(box2) && index::overlaps(box3), 199 std::back_inserter(result)); 200 201It's possible to connect different types of predicates together. 202 203 index::query(rt, index::nearest(pt, k) && index::within(b), std::back_inserter(returned_values)); 204 205 BOOST_FOREACH(Value & v, rt | index::adaptors::queried(index::nearest(pt, k) && index::covered_by(b))) 206 ; // do something with v 207 208[h4 Iterative queries] 209 210The query performed using query iterators may be paused and resumed if needed, e.g. when the query takes too long, 211or may be stopped at some point, when all interesting values were gathered. The query iterator is returned by 212`qbegin()` member function which requires passing predicates, like `query()` member function. 213 214 for ( Rtree::const_query_iterator it = tree.qbegin(bgi::nearest(pt, 10000)) ; 215 it != tree.qend() ; ++it ) 216 { 217 // do something with value 218 if ( has_enough_nearest_values() ) 219 break; 220 } 221 222[warning The modification of the `rtree`, e.g. insertion or removal of `__value__`s may invalidate the iterators. ] 223 224[h4 Inserting query results into another R-tree] 225 226There are several ways of inserting Values returned by a query into another R-tree container. 227The most basic way is creating a temporary container for Values and insert them later. 228 229 namespace bgi = boost::geometry::index; 230 typedef std::pair<Box, int> __value__; 231 typedef bgi::rtree< __value__, bgi::linear<32, 8> > RTree; 232 233 RTree rt1; 234 /* some inserting into the tree */ 235 236 std::vector<Value> result; 237 rt1.query(bgi::intersects(Box(/*...*/)), std::back_inserter(result)); 238 RTree rt2(result.begin(), result.end()); 239 240However there are other ways. One of these methods is mentioned in the "Creation and modification" section. 241The insert iterator may be passed directly into the query. 242 243 RTree rt3; 244 rt1.query(bgi::intersects(Box(/*...*/))), bgi::inserter(rt3)); 245 246You may also pass the resulting Range directly into the constructor or `insert()` member function using Boost.Range adaptor syntax. 247 248 RTree rt4(rt1 | bgi::adaptors::queried(bgi::intersects(Box(/*...*/))))); 249 250[endsect] [/ Queries /] 251