Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/geometry/index/detail/rtree/pack_create.hpp @ 101:c530137014c0
Update Boost headers (1.58.0)
author | Chris Cannam |
---|---|
date | Mon, 07 Sep 2015 11:12:49 +0100 |
parents | 2665513ce2d3 |
children |
comparison
equal
deleted
inserted
replaced
100:793467b5e61c | 101:c530137014c0 |
---|---|
1 // Boost.Geometry Index | 1 // Boost.Geometry Index |
2 // | 2 // |
3 // R-tree initial packing | 3 // R-tree initial packing |
4 // | 4 // |
5 // Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland. | 5 // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. |
6 // | 6 // |
7 // Use, modification and distribution is subject to the Boost Software License, | 7 // Use, modification and distribution is subject to the Boost Software License, |
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | 8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
9 // http://www.boost.org/LICENSE_1_0.txt) | 9 // http://www.boost.org/LICENSE_1_0.txt) |
10 | 10 |
53 return geometry::get<I>(e1.first) < geometry::get<I>(e2.first); | 53 return geometry::get<I>(e1.first) < geometry::get<I>(e2.first); |
54 } | 54 } |
55 }; | 55 }; |
56 | 56 |
57 template <std::size_t I, std::size_t Dimension> | 57 template <std::size_t I, std::size_t Dimension> |
58 struct partial_sort_and_half_boxes | 58 struct nth_element_and_half_boxes |
59 { | 59 { |
60 template <typename EIt, typename Box> | 60 template <typename EIt, typename Box> |
61 static inline void apply(EIt first, EIt median, EIt last, Box const& box, Box & left, Box & right, std::size_t dim_index) | 61 static inline void apply(EIt first, EIt median, EIt last, Box const& box, Box & left, Box & right, std::size_t dim_index) |
62 { | 62 { |
63 if ( I == dim_index ) | 63 if ( I == dim_index ) |
64 { | 64 { |
65 std::partial_sort(first, median, last, point_entries_comparer<I>()); | 65 std::nth_element(first, median, last, point_entries_comparer<I>()); |
66 | 66 |
67 geometry::convert(box, left); | 67 geometry::convert(box, left); |
68 geometry::convert(box, right); | 68 geometry::convert(box, right); |
69 typename coordinate_type<Box>::type edge_len | 69 typename coordinate_type<Box>::type edge_len |
70 = geometry::get<max_corner, I>(box) - geometry::get<min_corner, I>(box); | 70 = geometry::get<max_corner, I>(box) - geometry::get<min_corner, I>(box); |
72 = geometry::get<min_corner, I>(box) + edge_len / 2; | 72 = geometry::get<min_corner, I>(box) + edge_len / 2; |
73 geometry::set<max_corner, I>(left, median); | 73 geometry::set<max_corner, I>(left, median); |
74 geometry::set<min_corner, I>(right, median); | 74 geometry::set<min_corner, I>(right, median); |
75 } | 75 } |
76 else | 76 else |
77 partial_sort_and_half_boxes<I+1, Dimension>::apply(first, median, last, box, left, right, dim_index); | 77 nth_element_and_half_boxes<I+1, Dimension>::apply(first, median, last, box, left, right, dim_index); |
78 } | 78 } |
79 }; | 79 }; |
80 | 80 |
81 template <std::size_t Dimension> | 81 template <std::size_t Dimension> |
82 struct partial_sort_and_half_boxes<Dimension, Dimension> | 82 struct nth_element_and_half_boxes<Dimension, Dimension> |
83 { | 83 { |
84 template <typename EIt, typename Box> | 84 template <typename EIt, typename Box> |
85 static inline void apply(EIt , EIt , EIt , Box const& , Box & , Box & , std::size_t ) {} | 85 static inline void apply(EIt , EIt , EIt , Box const& , Box & , Box & , std::size_t ) {} |
86 }; | 86 }; |
87 | 87 |
120 typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node; | 120 typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node; |
121 typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node; | 121 typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node; |
122 typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf; | 122 typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf; |
123 | 123 |
124 typedef typename Allocators::node_pointer node_pointer; | 124 typedef typename Allocators::node_pointer node_pointer; |
125 typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr; | 125 typedef rtree::subtree_destroyer<Value, Options, Translator, Box, Allocators> subtree_destroyer; |
126 typedef typename Allocators::size_type size_type; | 126 typedef typename Allocators::size_type size_type; |
127 | 127 |
128 typedef typename traits::point_type<Box>::type point_type; | 128 typedef typename geometry::point_type<Box>::type point_type; |
129 typedef typename traits::coordinate_type<point_type>::type coordinate_type; | 129 typedef typename geometry::coordinate_type<point_type>::type coordinate_type; |
130 typedef typename detail::default_content_result<Box>::type content_type; | 130 typedef typename detail::default_content_result<Box>::type content_type; |
131 typedef typename Options::parameters_type parameters_type; | 131 typedef typename Options::parameters_type parameters_type; |
132 static const std::size_t dimension = traits::dimension<point_type>::value; | 132 static const std::size_t dimension = geometry::dimension<point_type>::value; |
133 | 133 |
134 typedef typename rtree::container_from_elements_type< | 134 typedef typename rtree::container_from_elements_type< |
135 typename rtree::elements_type<leaf>::type, | 135 typename rtree::elements_type<leaf>::type, |
136 std::size_t | 136 std::size_t |
137 >::type values_counts_container; | 137 >::type values_counts_container; |
159 | 159 |
160 Box hint_box; | 160 Box hint_box; |
161 geometry::assign_inverse(hint_box); | 161 geometry::assign_inverse(hint_box); |
162 for ( ; first != last ; ++first ) | 162 for ( ; first != last ; ++first ) |
163 { | 163 { |
164 geometry::expand(hint_box, translator(*first)); | 164 // NOTE: support for iterators not returning true references adapted |
165 // to Geometry concept and default translator returning true reference | |
166 // An alternative would be to dereference the iterator and translate | |
167 // in one expression each time the indexable was needed. | |
168 typename std::iterator_traits<InIt>::reference in_ref = *first; | |
169 typename Translator::result_type indexable = translator(in_ref); | |
170 | |
171 // NOTE: added for consistency with insert() | |
172 // CONSIDER: alternative - ignore invalid indexable or throw an exception | |
173 BOOST_GEOMETRY_INDEX_ASSERT(detail::is_valid(indexable), "Indexable is invalid"); | |
174 | |
175 geometry::expand(hint_box, indexable); | |
165 | 176 |
166 point_type pt; | 177 point_type pt; |
167 geometry::centroid(translator(*first), pt); | 178 geometry::centroid(indexable, pt); |
168 entries.push_back(std::make_pair(pt, first)); | 179 entries.push_back(std::make_pair(pt, first)); |
169 } | 180 } |
170 | 181 |
171 subtree_elements_counts subtree_counts = calculate_subtree_elements_counts(values_count, parameters, leafs_level); | 182 subtree_elements_counts subtree_counts = calculate_subtree_elements_counts(values_count, parameters, leafs_level); |
172 internal_element el = per_level(entries.begin(), entries.end(), hint_box, values_count, subtree_counts, | 183 internal_element el = per_level(entries.begin(), entries.end(), hint_box, values_count, subtree_counts, |
185 | 196 |
186 template <typename EIt> inline static | 197 template <typename EIt> inline static |
187 internal_element per_level(EIt first, EIt last, Box const& hint_box, std::size_t values_count, subtree_elements_counts const& subtree_counts, | 198 internal_element per_level(EIt first, EIt last, Box const& hint_box, std::size_t values_count, subtree_elements_counts const& subtree_counts, |
188 parameters_type const& parameters, Translator const& translator, Allocators & allocators) | 199 parameters_type const& parameters, Translator const& translator, Allocators & allocators) |
189 { | 200 { |
190 BOOST_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count); | 201 BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count, |
202 "unexpected parameters"); | |
191 | 203 |
192 if ( subtree_counts.maxc <= 1 ) | 204 if ( subtree_counts.maxc <= 1 ) |
193 { | 205 { |
194 // ROOT or LEAF | 206 // ROOT or LEAF |
195 BOOST_ASSERT(values_count <= parameters.get_max_elements()); | 207 BOOST_GEOMETRY_INDEX_ASSERT(values_count <= parameters.get_max_elements(), |
208 "too big number of elements"); | |
196 // if !root check m_parameters.get_min_elements() <= count | 209 // if !root check m_parameters.get_min_elements() <= count |
197 | 210 |
198 // create new leaf node | 211 // create new leaf node |
199 node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A) | 212 node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A) |
200 node_auto_ptr auto_remover(n, allocators); | 213 subtree_destroyer auto_remover(n, allocators); |
201 leaf & l = rtree::get<leaf>(*n); | 214 leaf & l = rtree::get<leaf>(*n); |
202 | 215 |
203 // reserve space for values | 216 // reserve space for values |
204 rtree::elements(l).reserve(values_count); // MAY THROW (A) | 217 rtree::elements(l).reserve(values_count); // MAY THROW (A) |
205 // calculate values box and copy values | 218 // calculate values box and copy values |
206 Box elements_box; | 219 Box elements_box; |
207 geometry::assign_inverse(elements_box); | 220 geometry::assign_inverse(elements_box); |
208 for ( ; first != last ; ++first ) | 221 for ( ; first != last ; ++first ) |
209 { | 222 { |
223 // NOTE: push_back() must be called at the end in order to support move_iterator. | |
224 // The iterator is dereferenced 2x (no temporary reference) to support | |
225 // non-true reference types and move_iterator without boost::forward<>. | |
226 geometry::expand(elements_box, translator(*(first->second))); | |
210 rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C) | 227 rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C) |
211 geometry::expand(elements_box, translator(*(first->second))); | |
212 } | 228 } |
213 | 229 |
214 auto_remover.release(); | 230 auto_remover.release(); |
215 return internal_element(elements_box, n); | 231 return internal_element(elements_box, n); |
216 } | 232 } |
220 next_subtree_counts.maxc /= parameters.get_max_elements(); | 236 next_subtree_counts.maxc /= parameters.get_max_elements(); |
221 next_subtree_counts.minc /= parameters.get_max_elements(); | 237 next_subtree_counts.minc /= parameters.get_max_elements(); |
222 | 238 |
223 // create new internal node | 239 // create new internal node |
224 node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A) | 240 node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A) |
225 node_auto_ptr auto_remover(n, allocators); | 241 subtree_destroyer auto_remover(n, allocators); |
226 internal_node & in = rtree::get<internal_node>(*n); | 242 internal_node & in = rtree::get<internal_node>(*n); |
227 | 243 |
228 // reserve space for values | 244 // reserve space for values |
229 std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts); | 245 std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts); |
230 rtree::elements(in).reserve(nodes_count); // MAY THROW (A) | 246 rtree::elements(in).reserve(nodes_count); // MAY THROW (A) |
246 subtree_elements_counts const& subtree_counts, | 262 subtree_elements_counts const& subtree_counts, |
247 subtree_elements_counts const& next_subtree_counts, | 263 subtree_elements_counts const& next_subtree_counts, |
248 internal_elements & elements, Box & elements_box, | 264 internal_elements & elements, Box & elements_box, |
249 parameters_type const& parameters, Translator const& translator, Allocators & allocators) | 265 parameters_type const& parameters, Translator const& translator, Allocators & allocators) |
250 { | 266 { |
251 BOOST_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count); | 267 BOOST_GEOMETRY_INDEX_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count, |
252 | 268 "unexpected parameters"); |
253 BOOST_ASSERT_MSG( subtree_counts.minc <= values_count, "too small number of elements"); | 269 |
270 BOOST_GEOMETRY_INDEX_ASSERT(subtree_counts.minc <= values_count, | |
271 "too small number of elements"); | |
254 | 272 |
255 // only one packet | 273 // only one packet |
256 if ( values_count <= subtree_counts.maxc ) | 274 if ( values_count <= subtree_counts.maxc ) |
257 { | 275 { |
258 // the end, move to the next level | 276 // the end, move to the next level |
260 parameters, translator, allocators); | 278 parameters, translator, allocators); |
261 | 279 |
262 // in case if push_back() do throw here | 280 // in case if push_back() do throw here |
263 // and even if this is not probable (previously reserved memory, nonthrowing pairs copy) | 281 // and even if this is not probable (previously reserved memory, nonthrowing pairs copy) |
264 // this case is also tested by exceptions test. | 282 // this case is also tested by exceptions test. |
265 node_auto_ptr auto_remover(el.second, allocators); | 283 subtree_destroyer auto_remover(el.second, allocators); |
266 // this container should have memory allocated, reserve() called outside | 284 // this container should have memory allocated, reserve() called outside |
267 elements.push_back(el); // MAY THROW (A?,C) - however in normal conditions shouldn't | 285 elements.push_back(el); // MAY THROW (A?,C) - however in normal conditions shouldn't |
268 auto_remover.release(); | 286 auto_remover.release(); |
269 | 287 |
270 geometry::expand(elements_box, el.first); | 288 geometry::expand(elements_box, el.first); |
276 | 294 |
277 coordinate_type greatest_length; | 295 coordinate_type greatest_length; |
278 std::size_t greatest_dim_index = 0; | 296 std::size_t greatest_dim_index = 0; |
279 pack_utils::biggest_edge<dimension>::apply(hint_box, greatest_length, greatest_dim_index); | 297 pack_utils::biggest_edge<dimension>::apply(hint_box, greatest_length, greatest_dim_index); |
280 Box left, right; | 298 Box left, right; |
281 pack_utils::partial_sort_and_half_boxes<0, dimension> | 299 pack_utils::nth_element_and_half_boxes<0, dimension> |
282 ::apply(first, median, last, hint_box, left, right, greatest_dim_index); | 300 ::apply(first, median, last, hint_box, left, right, greatest_dim_index); |
283 | 301 |
284 per_level_packets(first, median, left, | 302 per_level_packets(first, median, left, |
285 median_count, subtree_counts, next_subtree_counts, | 303 median_count, subtree_counts, next_subtree_counts, |
286 elements, elements_box, | 304 elements, elements_box, |
292 } | 310 } |
293 | 311 |
294 inline static | 312 inline static |
295 subtree_elements_counts calculate_subtree_elements_counts(std::size_t elements_count, parameters_type const& parameters, size_type & leafs_level) | 313 subtree_elements_counts calculate_subtree_elements_counts(std::size_t elements_count, parameters_type const& parameters, size_type & leafs_level) |
296 { | 314 { |
297 (void)parameters; | 315 boost::ignore_unused_variable_warning(parameters); |
298 | 316 |
299 subtree_elements_counts res(1, 1); | 317 subtree_elements_counts res(1, 1); |
300 leafs_level = 0; | 318 leafs_level = 0; |
301 | 319 |
302 std::size_t smax = parameters.get_max_elements(); | 320 std::size_t smax = parameters.get_max_elements(); |
341 | 359 |
342 if ( 0 != r ) // e.g. 0 != 2 | 360 if ( 0 != r ) // e.g. 0 != 2 |
343 { | 361 { |
344 if ( subtree_counts.minc <= r ) // e.g. 10 <= 2 == false | 362 if ( subtree_counts.minc <= r ) // e.g. 10 <= 2 == false |
345 { | 363 { |
346 //BOOST_ASSERT_MSG(0 < n, "unexpected value"); | 364 //BOOST_GEOMETRY_INDEX_ASSERT(0 < n, "unexpected value"); |
347 median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((2+1)/2) * 25 which would be ok, but not in all cases | 365 median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((2+1)/2) * 25 which would be ok, but not in all cases |
348 } | 366 } |
349 else // r < subtree_counts.second // e.g. 2 < 10 == true | 367 else // r < subtree_counts.second // e.g. 2 < 10 == true |
350 { | 368 { |
351 std::size_t count_minus_min = count - subtree_counts.minc; // e.g. 52 - 10 = 42 | 369 std::size_t count_minus_min = count - subtree_counts.minc; // e.g. 52 - 10 = 42 |
352 n = count_minus_min / subtree_counts.maxc; // e.g. 42 / 25 = 1 | 370 n = count_minus_min / subtree_counts.maxc; // e.g. 42 / 25 = 1 |
353 r = count_minus_min % subtree_counts.maxc; // e.g. 42 % 25 = 17 | 371 r = count_minus_min % subtree_counts.maxc; // e.g. 42 % 25 = 17 |
354 if ( r == 0 ) // e.g. false | 372 if ( r == 0 ) // e.g. false |
355 { | 373 { |
356 // n can't be equal to 0 because then there wouldn't be any element in the other node | 374 // n can't be equal to 0 because then there wouldn't be any element in the other node |
357 //BOOST_ASSERT_MSG(0 < n, "unexpected value"); | 375 //BOOST_GEOMETRY_INDEX_ASSERT(0 < n, "unexpected value"); |
358 median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((1+1)/2) * 25 which would be ok, but not in all cases | 376 median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((1+1)/2) * 25 which would be ok, but not in all cases |
359 } | 377 } |
360 else | 378 else |
361 { | 379 { |
362 if ( n == 0 ) // e.g. false | 380 if ( n == 0 ) // e.g. false |