Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@101
|
3 // Copyright (c) 2011-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@16
|
4
|
Chris@16
|
5 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8
|
Chris@16
|
9 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
|
Chris@16
|
10 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
|
Chris@16
|
11
|
Chris@16
|
12 #include <vector>
|
Chris@16
|
13 #include <boost/range/algorithm/copy.hpp>
|
Chris@16
|
14 #include <boost/geometry/algorithms/assign.hpp>
|
Chris@16
|
15 #include <boost/geometry/core/coordinate_type.hpp>
|
Chris@16
|
16
|
Chris@16
|
17 namespace boost { namespace geometry
|
Chris@16
|
18 {
|
Chris@16
|
19
|
Chris@16
|
20 namespace detail { namespace partition
|
Chris@16
|
21 {
|
Chris@16
|
22
|
Chris@16
|
23 typedef std::vector<std::size_t> index_vector_type;
|
Chris@16
|
24
|
Chris@16
|
25 template <int Dimension, typename Box>
|
Chris@16
|
26 inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
|
Chris@16
|
27 {
|
Chris@16
|
28 typedef typename coordinate_type<Box>::type ctype;
|
Chris@16
|
29
|
Chris@16
|
30 // Divide input box into two parts, e.g. left/right
|
Chris@16
|
31 ctype two = 2;
|
Chris@16
|
32 ctype mid = (geometry::get<min_corner, Dimension>(box)
|
Chris@16
|
33 + geometry::get<max_corner, Dimension>(box)) / two;
|
Chris@16
|
34
|
Chris@16
|
35 lower_box = box;
|
Chris@16
|
36 upper_box = box;
|
Chris@16
|
37 geometry::set<max_corner, Dimension>(lower_box, mid);
|
Chris@16
|
38 geometry::set<min_corner, Dimension>(upper_box, mid);
|
Chris@16
|
39 }
|
Chris@16
|
40
|
Chris@16
|
41 // Divide collection into three subsets: lower, upper and oversized
|
Chris@101
|
42 // (not-fitting)
|
Chris@16
|
43 // (lower == left or bottom, upper == right or top)
|
Chris@16
|
44 template <typename OverlapsPolicy, typename InputCollection, typename Box>
|
Chris@101
|
45 inline void divide_into_subsets(Box const& lower_box,
|
Chris@16
|
46 Box const& upper_box,
|
Chris@16
|
47 InputCollection const& collection,
|
Chris@16
|
48 index_vector_type const& input,
|
Chris@16
|
49 index_vector_type& lower,
|
Chris@16
|
50 index_vector_type& upper,
|
Chris@16
|
51 index_vector_type& exceeding)
|
Chris@16
|
52 {
|
Chris@16
|
53 typedef boost::range_iterator
|
Chris@16
|
54 <
|
Chris@16
|
55 index_vector_type const
|
Chris@16
|
56 >::type index_iterator_type;
|
Chris@16
|
57
|
Chris@16
|
58 for(index_iterator_type it = boost::begin(input);
|
Chris@16
|
59 it != boost::end(input);
|
Chris@16
|
60 ++it)
|
Chris@16
|
61 {
|
Chris@16
|
62 bool const lower_overlapping = OverlapsPolicy::apply(lower_box,
|
Chris@16
|
63 collection[*it]);
|
Chris@16
|
64 bool const upper_overlapping = OverlapsPolicy::apply(upper_box,
|
Chris@16
|
65 collection[*it]);
|
Chris@16
|
66
|
Chris@16
|
67 if (lower_overlapping && upper_overlapping)
|
Chris@16
|
68 {
|
Chris@16
|
69 exceeding.push_back(*it);
|
Chris@16
|
70 }
|
Chris@16
|
71 else if (lower_overlapping)
|
Chris@16
|
72 {
|
Chris@16
|
73 lower.push_back(*it);
|
Chris@16
|
74 }
|
Chris@16
|
75 else if (upper_overlapping)
|
Chris@16
|
76 {
|
Chris@16
|
77 upper.push_back(*it);
|
Chris@16
|
78 }
|
Chris@16
|
79 else
|
Chris@16
|
80 {
|
Chris@101
|
81 // Is nowhere. That is (since 1.58) possible, it might be
|
Chris@101
|
82 // skipped by the OverlapsPolicy to enhance performance
|
Chris@16
|
83 }
|
Chris@16
|
84 }
|
Chris@16
|
85 }
|
Chris@16
|
86
|
Chris@101
|
87 template <typename ExpandPolicy, typename Box, typename InputCollection>
|
Chris@101
|
88 inline void expand_with_elements(Box& total,
|
Chris@101
|
89 InputCollection const& collection,
|
Chris@101
|
90 index_vector_type const& input)
|
Chris@101
|
91 {
|
Chris@101
|
92 typedef boost::range_iterator<index_vector_type const>::type it_type;
|
Chris@101
|
93 for(it_type it = boost::begin(input); it != boost::end(input); ++it)
|
Chris@101
|
94 {
|
Chris@101
|
95 ExpandPolicy::apply(total, collection[*it]);
|
Chris@101
|
96 }
|
Chris@101
|
97 }
|
Chris@101
|
98
|
Chris@101
|
99
|
Chris@16
|
100 // Match collection with itself
|
Chris@16
|
101 template <typename InputCollection, typename Policy>
|
Chris@101
|
102 inline void handle_one(InputCollection const& collection,
|
Chris@16
|
103 index_vector_type const& input,
|
Chris@16
|
104 Policy& policy)
|
Chris@16
|
105 {
|
Chris@101
|
106 if (boost::size(input) == 0)
|
Chris@101
|
107 {
|
Chris@101
|
108 return;
|
Chris@101
|
109 }
|
Chris@101
|
110
|
Chris@16
|
111 typedef boost::range_iterator<index_vector_type const>::type
|
Chris@16
|
112 index_iterator_type;
|
Chris@101
|
113
|
Chris@16
|
114 // Quadratic behaviour at lowest level (lowest quad, or all exceeding)
|
Chris@16
|
115 for(index_iterator_type it1 = boost::begin(input);
|
Chris@16
|
116 it1 != boost::end(input);
|
Chris@16
|
117 ++it1)
|
Chris@16
|
118 {
|
Chris@16
|
119 index_iterator_type it2 = it1;
|
Chris@16
|
120 for(++it2; it2 != boost::end(input); ++it2)
|
Chris@16
|
121 {
|
Chris@16
|
122 policy.apply(collection[*it1], collection[*it2]);
|
Chris@16
|
123 }
|
Chris@16
|
124 }
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127 // Match collection 1 with collection 2
|
Chris@101
|
128 template
|
Chris@101
|
129 <
|
Chris@101
|
130 typename InputCollection1,
|
Chris@101
|
131 typename InputCollection2,
|
Chris@101
|
132 typename Policy
|
Chris@101
|
133 >
|
Chris@101
|
134 inline void handle_two(
|
Chris@101
|
135 InputCollection1 const& collection1, index_vector_type const& input1,
|
Chris@101
|
136 InputCollection2 const& collection2, index_vector_type const& input2,
|
Chris@16
|
137 Policy& policy)
|
Chris@16
|
138 {
|
Chris@101
|
139 if (boost::size(input1) == 0 || boost::size(input2) == 0)
|
Chris@101
|
140 {
|
Chris@101
|
141 return;
|
Chris@101
|
142 }
|
Chris@101
|
143
|
Chris@16
|
144 typedef boost::range_iterator
|
Chris@16
|
145 <
|
Chris@16
|
146 index_vector_type const
|
Chris@16
|
147 >::type index_iterator_type;
|
Chris@16
|
148
|
Chris@16
|
149 for(index_iterator_type it1 = boost::begin(input1);
|
Chris@16
|
150 it1 != boost::end(input1);
|
Chris@16
|
151 ++it1)
|
Chris@16
|
152 {
|
Chris@16
|
153 for(index_iterator_type it2 = boost::begin(input2);
|
Chris@16
|
154 it2 != boost::end(input2);
|
Chris@16
|
155 ++it2)
|
Chris@16
|
156 {
|
Chris@16
|
157 policy.apply(collection1[*it1], collection2[*it2]);
|
Chris@16
|
158 }
|
Chris@16
|
159 }
|
Chris@16
|
160 }
|
Chris@16
|
161
|
Chris@101
|
162 inline bool recurse_ok(index_vector_type const& input,
|
Chris@101
|
163 std::size_t min_elements, std::size_t level)
|
Chris@101
|
164 {
|
Chris@101
|
165 return boost::size(input) >= min_elements
|
Chris@101
|
166 && level < 100;
|
Chris@101
|
167 }
|
Chris@101
|
168
|
Chris@101
|
169 inline bool recurse_ok(index_vector_type const& input1,
|
Chris@101
|
170 index_vector_type const& input2,
|
Chris@101
|
171 std::size_t min_elements, std::size_t level)
|
Chris@101
|
172 {
|
Chris@101
|
173 return boost::size(input1) >= min_elements
|
Chris@101
|
174 && recurse_ok(input2, min_elements, level);
|
Chris@101
|
175 }
|
Chris@101
|
176
|
Chris@101
|
177 inline bool recurse_ok(index_vector_type const& input1,
|
Chris@101
|
178 index_vector_type const& input2,
|
Chris@101
|
179 index_vector_type const& input3,
|
Chris@101
|
180 std::size_t min_elements, std::size_t level)
|
Chris@101
|
181 {
|
Chris@101
|
182 return boost::size(input1) >= min_elements
|
Chris@101
|
183 && recurse_ok(input2, input3, min_elements, level);
|
Chris@101
|
184 }
|
Chris@101
|
185
|
Chris@101
|
186 template
|
Chris@101
|
187 <
|
Chris@101
|
188 int Dimension,
|
Chris@101
|
189 typename Box,
|
Chris@101
|
190 typename OverlapsPolicy1,
|
Chris@101
|
191 typename OverlapsPolicy2,
|
Chris@101
|
192 typename ExpandPolicy1,
|
Chris@101
|
193 typename ExpandPolicy2,
|
Chris@101
|
194 typename VisitBoxPolicy
|
Chris@101
|
195 >
|
Chris@101
|
196 class partition_two_collections;
|
Chris@101
|
197
|
Chris@101
|
198
|
Chris@16
|
199 template
|
Chris@16
|
200 <
|
Chris@16
|
201 int Dimension,
|
Chris@16
|
202 typename Box,
|
Chris@16
|
203 typename OverlapsPolicy,
|
Chris@101
|
204 typename ExpandPolicy,
|
Chris@16
|
205 typename VisitBoxPolicy
|
Chris@16
|
206 >
|
Chris@16
|
207 class partition_one_collection
|
Chris@16
|
208 {
|
Chris@16
|
209 typedef std::vector<std::size_t> index_vector_type;
|
Chris@101
|
210
|
Chris@101
|
211 template <typename InputCollection>
|
Chris@101
|
212 static inline Box get_new_box(InputCollection const& collection,
|
Chris@101
|
213 index_vector_type const& input)
|
Chris@101
|
214 {
|
Chris@101
|
215 Box box;
|
Chris@101
|
216 geometry::assign_inverse(box);
|
Chris@101
|
217 expand_with_elements<ExpandPolicy>(box, collection, input);
|
Chris@101
|
218 return box;
|
Chris@101
|
219 }
|
Chris@16
|
220
|
Chris@16
|
221 template <typename InputCollection, typename Policy>
|
Chris@16
|
222 static inline void next_level(Box const& box,
|
Chris@16
|
223 InputCollection const& collection,
|
Chris@16
|
224 index_vector_type const& input,
|
Chris@101
|
225 std::size_t level, std::size_t min_elements,
|
Chris@16
|
226 Policy& policy, VisitBoxPolicy& box_policy)
|
Chris@16
|
227 {
|
Chris@101
|
228 if (recurse_ok(input, min_elements, level))
|
Chris@16
|
229 {
|
Chris@101
|
230 partition_one_collection
|
Chris@101
|
231 <
|
Chris@101
|
232 1 - Dimension,
|
Chris@101
|
233 Box,
|
Chris@101
|
234 OverlapsPolicy,
|
Chris@101
|
235 ExpandPolicy,
|
Chris@101
|
236 VisitBoxPolicy
|
Chris@101
|
237 >::apply(box, collection, input,
|
Chris@101
|
238 level + 1, min_elements, policy, box_policy);
|
Chris@101
|
239 }
|
Chris@101
|
240 else
|
Chris@101
|
241 {
|
Chris@101
|
242 handle_one(collection, input, policy);
|
Chris@101
|
243 }
|
Chris@101
|
244 }
|
Chris@101
|
245
|
Chris@101
|
246 // Function to switch to two collections if there are geometries exceeding
|
Chris@101
|
247 // the separation line
|
Chris@101
|
248 template <typename InputCollection, typename Policy>
|
Chris@101
|
249 static inline void next_level2(Box const& box,
|
Chris@101
|
250 InputCollection const& collection,
|
Chris@101
|
251 index_vector_type const& input1,
|
Chris@101
|
252 index_vector_type const& input2,
|
Chris@101
|
253 std::size_t level, std::size_t min_elements,
|
Chris@101
|
254 Policy& policy, VisitBoxPolicy& box_policy)
|
Chris@101
|
255 {
|
Chris@101
|
256
|
Chris@101
|
257 if (recurse_ok(input1, input2, min_elements, level))
|
Chris@101
|
258 {
|
Chris@101
|
259 partition_two_collections
|
Chris@101
|
260 <
|
Chris@101
|
261 1 - Dimension,
|
Chris@101
|
262 Box,
|
Chris@101
|
263 OverlapsPolicy, OverlapsPolicy,
|
Chris@101
|
264 ExpandPolicy, ExpandPolicy,
|
Chris@101
|
265 VisitBoxPolicy
|
Chris@101
|
266 >::apply(box, collection, input1, collection, input2,
|
Chris@101
|
267 level + 1, min_elements, policy, box_policy);
|
Chris@101
|
268 }
|
Chris@101
|
269 else
|
Chris@101
|
270 {
|
Chris@101
|
271 handle_two(collection, input1, collection, input2, policy);
|
Chris@16
|
272 }
|
Chris@16
|
273 }
|
Chris@16
|
274
|
Chris@16
|
275 public :
|
Chris@16
|
276 template <typename InputCollection, typename Policy>
|
Chris@16
|
277 static inline void apply(Box const& box,
|
Chris@16
|
278 InputCollection const& collection,
|
Chris@16
|
279 index_vector_type const& input,
|
Chris@101
|
280 std::size_t level,
|
Chris@16
|
281 std::size_t min_elements,
|
Chris@16
|
282 Policy& policy, VisitBoxPolicy& box_policy)
|
Chris@16
|
283 {
|
Chris@16
|
284 box_policy.apply(box, level);
|
Chris@16
|
285
|
Chris@16
|
286 Box lower_box, upper_box;
|
Chris@16
|
287 divide_box<Dimension>(box, lower_box, upper_box);
|
Chris@16
|
288
|
Chris@16
|
289 index_vector_type lower, upper, exceeding;
|
Chris@16
|
290 divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, collection,
|
Chris@16
|
291 input, lower, upper, exceeding);
|
Chris@16
|
292
|
Chris@16
|
293 if (boost::size(exceeding) > 0)
|
Chris@16
|
294 {
|
Chris@101
|
295 // Get the box of exceeding-only
|
Chris@101
|
296 Box exceeding_box = get_new_box(collection, exceeding);
|
Chris@101
|
297
|
Chris@101
|
298 // Recursively do exceeding elements only, in next dimension they
|
Chris@101
|
299 // will probably be less exceeding within the new box
|
Chris@101
|
300 next_level(exceeding_box, collection, exceeding, level,
|
Chris@101
|
301 min_elements, policy, box_policy);
|
Chris@101
|
302
|
Chris@101
|
303 // Switch to two collections, combine exceeding with lower resp upper
|
Chris@101
|
304 // but not lower/lower, upper/upper
|
Chris@101
|
305 next_level2(exceeding_box, collection, exceeding, lower, level,
|
Chris@101
|
306 min_elements, policy, box_policy);
|
Chris@101
|
307 next_level2(exceeding_box, collection, exceeding, upper, level,
|
Chris@101
|
308 min_elements, policy, box_policy);
|
Chris@16
|
309 }
|
Chris@16
|
310
|
Chris@16
|
311 // Recursively call operation both parts
|
Chris@16
|
312 next_level(lower_box, collection, lower, level, min_elements,
|
Chris@16
|
313 policy, box_policy);
|
Chris@16
|
314 next_level(upper_box, collection, upper, level, min_elements,
|
Chris@16
|
315 policy, box_policy);
|
Chris@16
|
316 }
|
Chris@16
|
317 };
|
Chris@16
|
318
|
Chris@16
|
319 template
|
Chris@16
|
320 <
|
Chris@16
|
321 int Dimension,
|
Chris@16
|
322 typename Box,
|
Chris@101
|
323 typename OverlapsPolicy1,
|
Chris@101
|
324 typename OverlapsPolicy2,
|
Chris@101
|
325 typename ExpandPolicy1,
|
Chris@101
|
326 typename ExpandPolicy2,
|
Chris@16
|
327 typename VisitBoxPolicy
|
Chris@16
|
328 >
|
Chris@16
|
329 class partition_two_collections
|
Chris@16
|
330 {
|
Chris@16
|
331 typedef std::vector<std::size_t> index_vector_type;
|
Chris@16
|
332
|
Chris@101
|
333 template
|
Chris@101
|
334 <
|
Chris@101
|
335 typename InputCollection1,
|
Chris@101
|
336 typename InputCollection2,
|
Chris@101
|
337 typename Policy
|
Chris@101
|
338 >
|
Chris@16
|
339 static inline void next_level(Box const& box,
|
Chris@101
|
340 InputCollection1 const& collection1,
|
Chris@16
|
341 index_vector_type const& input1,
|
Chris@101
|
342 InputCollection2 const& collection2,
|
Chris@16
|
343 index_vector_type const& input2,
|
Chris@101
|
344 std::size_t level, std::size_t min_elements,
|
Chris@16
|
345 Policy& policy, VisitBoxPolicy& box_policy)
|
Chris@16
|
346 {
|
Chris@101
|
347 partition_two_collections
|
Chris@101
|
348 <
|
Chris@101
|
349 1 - Dimension,
|
Chris@101
|
350 Box,
|
Chris@101
|
351 OverlapsPolicy1,
|
Chris@101
|
352 OverlapsPolicy2,
|
Chris@101
|
353 ExpandPolicy1,
|
Chris@101
|
354 ExpandPolicy2,
|
Chris@101
|
355 VisitBoxPolicy
|
Chris@101
|
356 >::apply(box, collection1, input1, collection2, input2,
|
Chris@101
|
357 level + 1, min_elements,
|
Chris@101
|
358 policy, box_policy);
|
Chris@101
|
359 }
|
Chris@101
|
360
|
Chris@101
|
361 template
|
Chris@101
|
362 <
|
Chris@101
|
363 typename ExpandPolicy,
|
Chris@101
|
364 typename InputCollection
|
Chris@101
|
365 >
|
Chris@101
|
366 static inline Box get_new_box(InputCollection const& collection,
|
Chris@101
|
367 index_vector_type const& input)
|
Chris@101
|
368 {
|
Chris@101
|
369 Box box;
|
Chris@101
|
370 geometry::assign_inverse(box);
|
Chris@101
|
371 expand_with_elements<ExpandPolicy>(box, collection, input);
|
Chris@101
|
372 return box;
|
Chris@101
|
373 }
|
Chris@101
|
374
|
Chris@101
|
375 template
|
Chris@101
|
376 <
|
Chris@101
|
377 typename InputCollection1,
|
Chris@101
|
378 typename InputCollection2
|
Chris@101
|
379 >
|
Chris@101
|
380 static inline Box get_new_box(InputCollection1 const& collection1,
|
Chris@101
|
381 index_vector_type const& input1,
|
Chris@101
|
382 InputCollection2 const& collection2,
|
Chris@101
|
383 index_vector_type const& input2)
|
Chris@101
|
384 {
|
Chris@101
|
385 Box box = get_new_box<ExpandPolicy1>(collection1, input1);
|
Chris@101
|
386 expand_with_elements<ExpandPolicy2>(box, collection2, input2);
|
Chris@101
|
387 return box;
|
Chris@16
|
388 }
|
Chris@16
|
389
|
Chris@16
|
390 public :
|
Chris@101
|
391 template
|
Chris@101
|
392 <
|
Chris@101
|
393 typename InputCollection1,
|
Chris@101
|
394 typename InputCollection2,
|
Chris@101
|
395 typename Policy
|
Chris@101
|
396 >
|
Chris@16
|
397 static inline void apply(Box const& box,
|
Chris@101
|
398 InputCollection1 const& collection1, index_vector_type const& input1,
|
Chris@101
|
399 InputCollection2 const& collection2, index_vector_type const& input2,
|
Chris@101
|
400 std::size_t level,
|
Chris@16
|
401 std::size_t min_elements,
|
Chris@16
|
402 Policy& policy, VisitBoxPolicy& box_policy)
|
Chris@16
|
403 {
|
Chris@16
|
404 box_policy.apply(box, level);
|
Chris@16
|
405
|
Chris@16
|
406 Box lower_box, upper_box;
|
Chris@16
|
407 divide_box<Dimension>(box, lower_box, upper_box);
|
Chris@16
|
408
|
Chris@16
|
409 index_vector_type lower1, upper1, exceeding1;
|
Chris@16
|
410 index_vector_type lower2, upper2, exceeding2;
|
Chris@101
|
411 divide_into_subsets<OverlapsPolicy1>(lower_box, upper_box, collection1,
|
Chris@16
|
412 input1, lower1, upper1, exceeding1);
|
Chris@101
|
413 divide_into_subsets<OverlapsPolicy2>(lower_box, upper_box, collection2,
|
Chris@16
|
414 input2, lower2, upper2, exceeding2);
|
Chris@16
|
415
|
Chris@16
|
416 if (boost::size(exceeding1) > 0)
|
Chris@16
|
417 {
|
Chris@16
|
418 // All exceeding from 1 with 2:
|
Chris@101
|
419
|
Chris@101
|
420 if (recurse_ok(exceeding1, exceeding2, min_elements, level))
|
Chris@101
|
421 {
|
Chris@101
|
422 Box exceeding_box = get_new_box(collection1, exceeding1,
|
Chris@101
|
423 collection2, exceeding2);
|
Chris@101
|
424 next_level(exceeding_box, collection1, exceeding1,
|
Chris@101
|
425 collection2, exceeding2, level,
|
Chris@101
|
426 min_elements, policy, box_policy);
|
Chris@101
|
427 }
|
Chris@101
|
428 else
|
Chris@101
|
429 {
|
Chris@101
|
430 handle_two(collection1, exceeding1, collection2, exceeding2,
|
Chris@101
|
431 policy);
|
Chris@101
|
432 }
|
Chris@16
|
433
|
Chris@16
|
434 // All exceeding from 1 with lower and upper of 2:
|
Chris@101
|
435
|
Chris@101
|
436 // (Check sizes of all three collections to avoid recurse into
|
Chris@101
|
437 // the same combinations again and again)
|
Chris@101
|
438 if (recurse_ok(lower2, upper2, exceeding1, min_elements, level))
|
Chris@101
|
439 {
|
Chris@101
|
440 Box exceeding_box
|
Chris@101
|
441 = get_new_box<ExpandPolicy1>(collection1, exceeding1);
|
Chris@101
|
442 next_level(exceeding_box, collection1, exceeding1,
|
Chris@101
|
443 collection2, lower2, level, min_elements, policy, box_policy);
|
Chris@101
|
444 next_level(exceeding_box, collection1, exceeding1,
|
Chris@101
|
445 collection2, upper2, level, min_elements, policy, box_policy);
|
Chris@101
|
446 }
|
Chris@101
|
447 else
|
Chris@101
|
448 {
|
Chris@101
|
449 handle_two(collection1, exceeding1, collection2, lower2, policy);
|
Chris@101
|
450 handle_two(collection1, exceeding1, collection2, upper2, policy);
|
Chris@101
|
451 }
|
Chris@16
|
452 }
|
Chris@101
|
453
|
Chris@16
|
454 if (boost::size(exceeding2) > 0)
|
Chris@16
|
455 {
|
Chris@16
|
456 // All exceeding from 2 with lower and upper of 1:
|
Chris@101
|
457 if (recurse_ok(lower1, upper1, exceeding2, min_elements, level))
|
Chris@101
|
458 {
|
Chris@101
|
459 Box exceeding_box
|
Chris@101
|
460 = get_new_box<ExpandPolicy2>(collection2, exceeding2);
|
Chris@101
|
461 next_level(exceeding_box, collection1, lower1,
|
Chris@101
|
462 collection2, exceeding2, level, min_elements, policy, box_policy);
|
Chris@101
|
463 next_level(exceeding_box, collection1, upper1,
|
Chris@101
|
464 collection2, exceeding2, level, min_elements, policy, box_policy);
|
Chris@101
|
465 }
|
Chris@101
|
466 else
|
Chris@101
|
467 {
|
Chris@101
|
468 handle_two(collection1, lower1, collection2, exceeding2, policy);
|
Chris@101
|
469 handle_two(collection1, upper1, collection2, exceeding2, policy);
|
Chris@101
|
470 }
|
Chris@16
|
471 }
|
Chris@16
|
472
|
Chris@101
|
473 if (recurse_ok(lower1, lower2, min_elements, level))
|
Chris@101
|
474 {
|
Chris@101
|
475 next_level(lower_box, collection1, lower1, collection2, lower2, level,
|
Chris@101
|
476 min_elements, policy, box_policy);
|
Chris@101
|
477 }
|
Chris@101
|
478 else
|
Chris@101
|
479 {
|
Chris@101
|
480 handle_two(collection1, lower1, collection2, lower2, policy);
|
Chris@101
|
481 }
|
Chris@101
|
482 if (recurse_ok(upper1, upper2, min_elements, level))
|
Chris@101
|
483 {
|
Chris@101
|
484 next_level(upper_box, collection1, upper1, collection2, upper2, level,
|
Chris@101
|
485 min_elements, policy, box_policy);
|
Chris@101
|
486 }
|
Chris@101
|
487 else
|
Chris@101
|
488 {
|
Chris@101
|
489 handle_two(collection1, upper1, collection2, upper2, policy);
|
Chris@101
|
490 }
|
Chris@16
|
491 }
|
Chris@16
|
492 };
|
Chris@16
|
493
|
Chris@16
|
494 struct visit_no_policy
|
Chris@16
|
495 {
|
Chris@16
|
496 template <typename Box>
|
Chris@101
|
497 static inline void apply(Box const&, std::size_t )
|
Chris@16
|
498 {}
|
Chris@16
|
499 };
|
Chris@16
|
500
|
Chris@101
|
501 struct include_all_policy
|
Chris@101
|
502 {
|
Chris@101
|
503 template <typename Item>
|
Chris@101
|
504 static inline bool apply(Item const&)
|
Chris@101
|
505 {
|
Chris@101
|
506 return true;
|
Chris@101
|
507 }
|
Chris@101
|
508 };
|
Chris@101
|
509
|
Chris@101
|
510
|
Chris@101
|
511 }} // namespace detail::partition
|
Chris@101
|
512
|
Chris@16
|
513 template
|
Chris@16
|
514 <
|
Chris@16
|
515 typename Box,
|
Chris@101
|
516 typename ExpandPolicy1,
|
Chris@101
|
517 typename OverlapsPolicy1,
|
Chris@101
|
518 typename ExpandPolicy2 = ExpandPolicy1,
|
Chris@101
|
519 typename OverlapsPolicy2 = OverlapsPolicy1,
|
Chris@101
|
520 typename IncludePolicy1 = detail::partition::include_all_policy,
|
Chris@101
|
521 typename IncludePolicy2 = detail::partition::include_all_policy,
|
Chris@101
|
522 typename VisitBoxPolicy = detail::partition::visit_no_policy
|
Chris@16
|
523 >
|
Chris@16
|
524 class partition
|
Chris@16
|
525 {
|
Chris@16
|
526 typedef std::vector<std::size_t> index_vector_type;
|
Chris@16
|
527
|
Chris@101
|
528 template <typename ExpandPolicy, typename IncludePolicy, typename InputCollection>
|
Chris@16
|
529 static inline void expand_to_collection(InputCollection const& collection,
|
Chris@16
|
530 Box& total, index_vector_type& index_vector)
|
Chris@16
|
531 {
|
Chris@16
|
532 std::size_t index = 0;
|
Chris@16
|
533 for(typename boost::range_iterator<InputCollection const>::type it
|
Chris@16
|
534 = boost::begin(collection);
|
Chris@16
|
535 it != boost::end(collection);
|
Chris@16
|
536 ++it, ++index)
|
Chris@16
|
537 {
|
Chris@101
|
538 if (IncludePolicy::apply(*it))
|
Chris@101
|
539 {
|
Chris@101
|
540 ExpandPolicy::apply(total, *it);
|
Chris@101
|
541 index_vector.push_back(index);
|
Chris@101
|
542 }
|
Chris@16
|
543 }
|
Chris@16
|
544 }
|
Chris@16
|
545
|
Chris@16
|
546 public :
|
Chris@16
|
547 template <typename InputCollection, typename VisitPolicy>
|
Chris@16
|
548 static inline void apply(InputCollection const& collection,
|
Chris@16
|
549 VisitPolicy& visitor,
|
Chris@16
|
550 std::size_t min_elements = 16,
|
Chris@101
|
551 VisitBoxPolicy box_visitor = detail::partition::visit_no_policy()
|
Chris@16
|
552 )
|
Chris@16
|
553 {
|
Chris@16
|
554 if (std::size_t(boost::size(collection)) > min_elements)
|
Chris@16
|
555 {
|
Chris@16
|
556 index_vector_type index_vector;
|
Chris@16
|
557 Box total;
|
Chris@16
|
558 assign_inverse(total);
|
Chris@101
|
559 expand_to_collection<ExpandPolicy1, IncludePolicy1>(collection,
|
Chris@101
|
560 total, index_vector);
|
Chris@16
|
561
|
Chris@16
|
562 detail::partition::partition_one_collection
|
Chris@16
|
563 <
|
Chris@16
|
564 0, Box,
|
Chris@101
|
565 OverlapsPolicy1,
|
Chris@101
|
566 ExpandPolicy1,
|
Chris@16
|
567 VisitBoxPolicy
|
Chris@16
|
568 >::apply(total, collection, index_vector, 0, min_elements,
|
Chris@16
|
569 visitor, box_visitor);
|
Chris@16
|
570 }
|
Chris@16
|
571 else
|
Chris@16
|
572 {
|
Chris@16
|
573 typedef typename boost::range_iterator
|
Chris@16
|
574 <
|
Chris@16
|
575 InputCollection const
|
Chris@16
|
576 >::type iterator_type;
|
Chris@16
|
577 for(iterator_type it1 = boost::begin(collection);
|
Chris@16
|
578 it1 != boost::end(collection);
|
Chris@16
|
579 ++it1)
|
Chris@16
|
580 {
|
Chris@16
|
581 iterator_type it2 = it1;
|
Chris@16
|
582 for(++it2; it2 != boost::end(collection); ++it2)
|
Chris@16
|
583 {
|
Chris@16
|
584 visitor.apply(*it1, *it2);
|
Chris@16
|
585 }
|
Chris@16
|
586 }
|
Chris@16
|
587 }
|
Chris@16
|
588 }
|
Chris@16
|
589
|
Chris@101
|
590 template
|
Chris@101
|
591 <
|
Chris@101
|
592 typename InputCollection1,
|
Chris@101
|
593 typename InputCollection2,
|
Chris@101
|
594 typename VisitPolicy
|
Chris@101
|
595 >
|
Chris@101
|
596 static inline void apply(InputCollection1 const& collection1,
|
Chris@101
|
597 InputCollection2 const& collection2,
|
Chris@16
|
598 VisitPolicy& visitor,
|
Chris@16
|
599 std::size_t min_elements = 16,
|
Chris@101
|
600 VisitBoxPolicy box_visitor = detail::partition::visit_no_policy()
|
Chris@16
|
601 )
|
Chris@16
|
602 {
|
Chris@16
|
603 if (std::size_t(boost::size(collection1)) > min_elements
|
Chris@16
|
604 && std::size_t(boost::size(collection2)) > min_elements)
|
Chris@16
|
605 {
|
Chris@16
|
606 index_vector_type index_vector1, index_vector2;
|
Chris@16
|
607 Box total;
|
Chris@16
|
608 assign_inverse(total);
|
Chris@101
|
609 expand_to_collection<ExpandPolicy1, IncludePolicy1>(collection1,
|
Chris@101
|
610 total, index_vector1);
|
Chris@101
|
611 expand_to_collection<ExpandPolicy2, IncludePolicy2>(collection2,
|
Chris@101
|
612 total, index_vector2);
|
Chris@16
|
613
|
Chris@16
|
614 detail::partition::partition_two_collections
|
Chris@16
|
615 <
|
Chris@101
|
616 0, Box, OverlapsPolicy1, OverlapsPolicy2,
|
Chris@101
|
617 ExpandPolicy1, ExpandPolicy2, VisitBoxPolicy
|
Chris@16
|
618 >::apply(total,
|
Chris@16
|
619 collection1, index_vector1,
|
Chris@16
|
620 collection2, index_vector2,
|
Chris@16
|
621 0, min_elements, visitor, box_visitor);
|
Chris@16
|
622 }
|
Chris@16
|
623 else
|
Chris@16
|
624 {
|
Chris@16
|
625 typedef typename boost::range_iterator
|
Chris@16
|
626 <
|
Chris@101
|
627 InputCollection1 const
|
Chris@101
|
628 >::type iterator_type1;
|
Chris@101
|
629 typedef typename boost::range_iterator
|
Chris@101
|
630 <
|
Chris@101
|
631 InputCollection2 const
|
Chris@101
|
632 >::type iterator_type2;
|
Chris@101
|
633 for(iterator_type1 it1 = boost::begin(collection1);
|
Chris@16
|
634 it1 != boost::end(collection1);
|
Chris@16
|
635 ++it1)
|
Chris@16
|
636 {
|
Chris@101
|
637 for(iterator_type2 it2 = boost::begin(collection2);
|
Chris@16
|
638 it2 != boost::end(collection2);
|
Chris@16
|
639 ++it2)
|
Chris@16
|
640 {
|
Chris@16
|
641 visitor.apply(*it1, *it2);
|
Chris@16
|
642 }
|
Chris@16
|
643 }
|
Chris@16
|
644 }
|
Chris@16
|
645 }
|
Chris@101
|
646 };
|
Chris@16
|
647
|
Chris@16
|
648
|
Chris@16
|
649 }} // namespace boost::geometry
|
Chris@16
|
650
|
Chris@16
|
651 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
|