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