]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/algorithms/detail/partition.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / partition.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
5
6 // This file was modified by Oracle on 2015, 2017, 2018, 2019.
7 // Modifications copyright (c) 2015-2019 Oracle and/or its affiliates.
8
9 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
10 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11
12 // Use, modification and distribution is subject to the Boost Software License,
13 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
14 // http://www.boost.org/LICENSE_1_0.txt)
15
16 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
17 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
18
19 #include <cstddef>
20 #include <vector>
21 #include <boost/range.hpp>
22 #include <boost/type_traits/is_integral.hpp>
23
24 #include <boost/geometry/core/access.hpp>
25 #include <boost/geometry/core/coordinate_type.hpp>
26 #include <boost/geometry/algorithms/assign.hpp>
27
28
29 namespace boost { namespace geometry
30 {
31
32 namespace detail { namespace partition
33 {
34
35 template <typename T, bool IsIntegral = boost::is_integral<T>::value>
36 struct divide_interval
37 {
38 static inline T apply(T const& mi, T const& ma)
39 {
40 static T const two = 2;
41 return (mi + ma) / two;
42 }
43 };
44
45 template <typename T>
46 struct divide_interval<T, true>
47 {
48 static inline T apply(T const& mi, T const& ma)
49 {
50 // avoid overflow
51 return mi / 2 + ma / 2 + (mi % 2 + ma % 2) / 2;
52 }
53 };
54
55 template <int Dimension, typename Box>
56 inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
57 {
58 typedef typename coordinate_type<Box>::type ctype;
59
60 // Divide input box into two parts, e.g. left/right
61 ctype mid = divide_interval<ctype>::apply(
62 geometry::get<min_corner, Dimension>(box),
63 geometry::get<max_corner, Dimension>(box));
64
65 lower_box = box;
66 upper_box = box;
67 geometry::set<max_corner, Dimension>(lower_box, mid);
68 geometry::set<min_corner, Dimension>(upper_box, mid);
69 }
70
71 // Divide forward_range into three subsets: lower, upper and oversized
72 // (not-fitting)
73 // (lower == left or bottom, upper == right or top)
74 template <typename Box, typename IteratorVector, typename OverlapsPolicy>
75 inline void divide_into_subsets(Box const& lower_box,
76 Box const& upper_box,
77 IteratorVector const& input,
78 IteratorVector& lower,
79 IteratorVector& upper,
80 IteratorVector& exceeding,
81 OverlapsPolicy const& overlaps_policy)
82 {
83 typedef typename boost::range_iterator
84 <
85 IteratorVector const
86 >::type it_type;
87
88 for(it_type it = boost::begin(input); it != boost::end(input); ++it)
89 {
90 bool const lower_overlapping = overlaps_policy.apply(lower_box, **it);
91 bool const upper_overlapping = overlaps_policy.apply(upper_box, **it);
92
93 if (lower_overlapping && upper_overlapping)
94 {
95 exceeding.push_back(*it);
96 }
97 else if (lower_overlapping)
98 {
99 lower.push_back(*it);
100 }
101 else if (upper_overlapping)
102 {
103 upper.push_back(*it);
104 }
105 else
106 {
107 // Is nowhere. That is (since 1.58) possible, it might be
108 // skipped by the OverlapsPolicy to enhance performance
109 }
110 }
111 }
112
113 template
114 <
115 typename Box,
116 typename IteratorVector,
117 typename ExpandPolicy
118 >
119 inline void expand_with_elements(Box& total, IteratorVector const& input,
120 ExpandPolicy const& expand_policy)
121 {
122 typedef typename boost::range_iterator<IteratorVector const>::type it_type;
123 for(it_type it = boost::begin(input); it != boost::end(input); ++it)
124 {
125 expand_policy.apply(total, **it);
126 }
127 }
128
129
130 // Match forward_range with itself
131 template <typename IteratorVector, typename VisitPolicy>
132 inline bool handle_one(IteratorVector const& input, VisitPolicy& visitor)
133 {
134 if (boost::empty(input))
135 {
136 return true;
137 }
138
139 typedef typename boost::range_iterator<IteratorVector const>::type it_type;
140
141 // Quadratic behaviour at lowest level (lowest quad, or all exceeding)
142 for (it_type it1 = boost::begin(input); it1 != boost::end(input); ++it1)
143 {
144 it_type it2 = it1;
145 for (++it2; it2 != boost::end(input); ++it2)
146 {
147 if (! visitor.apply(**it1, **it2))
148 {
149 return false; // interrupt
150 }
151 }
152 }
153
154 return true;
155 }
156
157 // Match forward range 1 with forward range 2
158 template
159 <
160 typename IteratorVector1,
161 typename IteratorVector2,
162 typename VisitPolicy
163 >
164 inline bool handle_two(IteratorVector1 const& input1,
165 IteratorVector2 const& input2,
166 VisitPolicy& visitor)
167 {
168 typedef typename boost::range_iterator
169 <
170 IteratorVector1 const
171 >::type iterator_type1;
172
173 typedef typename boost::range_iterator
174 <
175 IteratorVector2 const
176 >::type iterator_type2;
177
178 if (boost::empty(input1) || boost::empty(input2))
179 {
180 return true;
181 }
182
183 for(iterator_type1 it1 = boost::begin(input1);
184 it1 != boost::end(input1);
185 ++it1)
186 {
187 for(iterator_type2 it2 = boost::begin(input2);
188 it2 != boost::end(input2);
189 ++it2)
190 {
191 if (! visitor.apply(**it1, **it2))
192 {
193 return false; // interrupt
194 }
195 }
196 }
197
198 return true;
199 }
200
201 template <typename IteratorVector>
202 inline bool recurse_ok(IteratorVector const& input,
203 std::size_t min_elements, std::size_t level)
204 {
205 return boost::size(input) >= min_elements
206 && level < 100;
207 }
208
209 template <typename IteratorVector1, typename IteratorVector2>
210 inline bool recurse_ok(IteratorVector1 const& input1,
211 IteratorVector2 const& input2,
212 std::size_t min_elements, std::size_t level)
213 {
214 return boost::size(input1) >= min_elements
215 && recurse_ok(input2, min_elements, level);
216 }
217
218 template
219 <
220 typename IteratorVector1,
221 typename IteratorVector2,
222 typename IteratorVector3
223 >
224 inline bool recurse_ok(IteratorVector1 const& input1,
225 IteratorVector2 const& input2,
226 IteratorVector3 const& input3,
227 std::size_t min_elements, std::size_t level)
228 {
229 return boost::size(input1) >= min_elements
230 && recurse_ok(input2, input3, min_elements, level);
231 }
232
233
234 template <int Dimension, typename Box>
235 class partition_two_ranges;
236
237
238 template <int Dimension, typename Box>
239 class partition_one_range
240 {
241 template <typename IteratorVector, typename ExpandPolicy>
242 static inline Box get_new_box(IteratorVector const& input,
243 ExpandPolicy const& expand_policy)
244 {
245 Box box;
246 geometry::assign_inverse(box);
247 expand_with_elements(box, input, expand_policy);
248 return box;
249 }
250
251 template
252 <
253 typename IteratorVector,
254 typename VisitPolicy,
255 typename ExpandPolicy,
256 typename OverlapsPolicy,
257 typename VisitBoxPolicy
258 >
259 static inline bool next_level(Box const& box,
260 IteratorVector const& input,
261 std::size_t level, std::size_t min_elements,
262 VisitPolicy& visitor,
263 ExpandPolicy const& expand_policy,
264 OverlapsPolicy const& overlaps_policy,
265 VisitBoxPolicy& box_policy)
266 {
267 if (recurse_ok(input, min_elements, level))
268 {
269 return partition_one_range
270 <
271 1 - Dimension,
272 Box
273 >::apply(box, input, level + 1, min_elements,
274 visitor, expand_policy, overlaps_policy, box_policy);
275 }
276 else
277 {
278 return handle_one(input, visitor);
279 }
280 }
281
282 // Function to switch to two forward ranges if there are
283 // geometries exceeding the separation line
284 template
285 <
286 typename IteratorVector,
287 typename VisitPolicy,
288 typename ExpandPolicy,
289 typename OverlapsPolicy,
290 typename VisitBoxPolicy
291 >
292 static inline bool next_level2(Box const& box,
293 IteratorVector const& input1,
294 IteratorVector const& input2,
295 std::size_t level, std::size_t min_elements,
296 VisitPolicy& visitor,
297 ExpandPolicy const& expand_policy,
298 OverlapsPolicy const& overlaps_policy,
299 VisitBoxPolicy& box_policy)
300 {
301 if (recurse_ok(input1, input2, min_elements, level))
302 {
303 return partition_two_ranges
304 <
305 1 - Dimension, Box
306 >::apply(box, input1, input2, level + 1, min_elements,
307 visitor, expand_policy, overlaps_policy,
308 expand_policy, overlaps_policy, box_policy);
309 }
310 else
311 {
312 return handle_two(input1, input2, visitor);
313 }
314 }
315
316 public :
317 template
318 <
319 typename IteratorVector,
320 typename VisitPolicy,
321 typename ExpandPolicy,
322 typename OverlapsPolicy,
323 typename VisitBoxPolicy
324 >
325 static inline bool apply(Box const& box,
326 IteratorVector const& input,
327 std::size_t level,
328 std::size_t min_elements,
329 VisitPolicy& visitor,
330 ExpandPolicy const& expand_policy,
331 OverlapsPolicy const& overlaps_policy,
332 VisitBoxPolicy& box_policy)
333 {
334 box_policy.apply(box, level);
335
336 Box lower_box, upper_box;
337 divide_box<Dimension>(box, lower_box, upper_box);
338
339 IteratorVector lower, upper, exceeding;
340 divide_into_subsets(lower_box, upper_box,
341 input, lower, upper, exceeding,
342 overlaps_policy);
343
344 if (! boost::empty(exceeding))
345 {
346 // Get the box of exceeding-only
347 Box exceeding_box = get_new_box(exceeding, expand_policy);
348
349 // Recursively do exceeding elements only, in next dimension they
350 // will probably be less exceeding within the new box
351 if (! (next_level(exceeding_box, exceeding, level, min_elements,
352 visitor, expand_policy, overlaps_policy, box_policy)
353 // Switch to two forward ranges, combine exceeding with
354 // lower resp upper, but not lower/lower, upper/upper
355 && next_level2(exceeding_box, exceeding, lower, level, min_elements,
356 visitor, expand_policy, overlaps_policy, box_policy)
357 && next_level2(exceeding_box, exceeding, upper, level, min_elements,
358 visitor, expand_policy, overlaps_policy, box_policy)) )
359 {
360 return false; // interrupt
361 }
362 }
363
364 // Recursively call operation both parts
365 return next_level(lower_box, lower, level, min_elements,
366 visitor, expand_policy, overlaps_policy, box_policy)
367 && next_level(upper_box, upper, level, min_elements,
368 visitor, expand_policy, overlaps_policy, box_policy);
369 }
370 };
371
372 template
373 <
374 int Dimension,
375 typename Box
376 >
377 class partition_two_ranges
378 {
379 template
380 <
381 typename IteratorVector1,
382 typename IteratorVector2,
383 typename VisitPolicy,
384 typename ExpandPolicy1,
385 typename OverlapsPolicy1,
386 typename ExpandPolicy2,
387 typename OverlapsPolicy2,
388 typename VisitBoxPolicy
389 >
390 static inline bool next_level(Box const& box,
391 IteratorVector1 const& input1,
392 IteratorVector2 const& input2,
393 std::size_t level, std::size_t min_elements,
394 VisitPolicy& visitor,
395 ExpandPolicy1 const& expand_policy1,
396 OverlapsPolicy1 const& overlaps_policy1,
397 ExpandPolicy2 const& expand_policy2,
398 OverlapsPolicy2 const& overlaps_policy2,
399 VisitBoxPolicy& box_policy)
400 {
401 return partition_two_ranges
402 <
403 1 - Dimension, Box
404 >::apply(box, input1, input2, level + 1, min_elements,
405 visitor, expand_policy1, overlaps_policy1,
406 expand_policy2, overlaps_policy2, box_policy);
407 }
408
409 template <typename IteratorVector, typename ExpandPolicy>
410 static inline Box get_new_box(IteratorVector const& input,
411 ExpandPolicy const& expand_policy)
412 {
413 Box box;
414 geometry::assign_inverse(box);
415 expand_with_elements(box, input, expand_policy);
416 return box;
417 }
418
419 template
420 <
421 typename IteratorVector1, typename IteratorVector2,
422 typename ExpandPolicy1, typename ExpandPolicy2
423 >
424 static inline Box get_new_box(IteratorVector1 const& input1,
425 IteratorVector2 const& input2,
426 ExpandPolicy1 const& expand_policy1,
427 ExpandPolicy2 const& expand_policy2)
428 {
429 Box box = get_new_box(input1, expand_policy1);
430 expand_with_elements(box, input2, expand_policy2);
431 return box;
432 }
433
434 public :
435 template
436 <
437 typename IteratorVector1,
438 typename IteratorVector2,
439 typename VisitPolicy,
440 typename ExpandPolicy1,
441 typename OverlapsPolicy1,
442 typename ExpandPolicy2,
443 typename OverlapsPolicy2,
444 typename VisitBoxPolicy
445 >
446 static inline bool apply(Box const& box,
447 IteratorVector1 const& input1,
448 IteratorVector2 const& input2,
449 std::size_t level,
450 std::size_t min_elements,
451 VisitPolicy& visitor,
452 ExpandPolicy1 const& expand_policy1,
453 OverlapsPolicy1 const& overlaps_policy1,
454 ExpandPolicy2 const& expand_policy2,
455 OverlapsPolicy2 const& overlaps_policy2,
456 VisitBoxPolicy& box_policy)
457 {
458 box_policy.apply(box, level);
459
460 Box lower_box, upper_box;
461 divide_box<Dimension>(box, lower_box, upper_box);
462
463 IteratorVector1 lower1, upper1, exceeding1;
464 IteratorVector2 lower2, upper2, exceeding2;
465 divide_into_subsets(lower_box, upper_box,
466 input1, lower1, upper1, exceeding1,
467 overlaps_policy1);
468 divide_into_subsets(lower_box, upper_box,
469 input2, lower2, upper2, exceeding2,
470 overlaps_policy2);
471
472 if (! boost::empty(exceeding1))
473 {
474 // All exceeding from 1 with 2:
475
476 if (recurse_ok(exceeding1, exceeding2, min_elements, level))
477 {
478 Box exceeding_box = get_new_box(exceeding1, exceeding2,
479 expand_policy1, expand_policy2);
480 if (! next_level(exceeding_box, exceeding1, exceeding2, level,
481 min_elements, visitor, expand_policy1, overlaps_policy1,
482 expand_policy2, overlaps_policy2, box_policy))
483 {
484 return false; // interrupt
485 }
486 }
487 else
488 {
489 if (! handle_two(exceeding1, exceeding2, visitor))
490 {
491 return false; // interrupt
492 }
493 }
494
495 // All exceeding from 1 with lower and upper of 2:
496
497 // (Check sizes of all three forward ranges to avoid recurse into
498 // the same combinations again and again)
499 if (recurse_ok(lower2, upper2, exceeding1, min_elements, level))
500 {
501 Box exceeding_box = get_new_box(exceeding1, expand_policy1);
502 if (! (next_level(exceeding_box, exceeding1, lower2, level,
503 min_elements, visitor, expand_policy1, overlaps_policy1,
504 expand_policy2, overlaps_policy2, box_policy)
505 && next_level(exceeding_box, exceeding1, upper2, level,
506 min_elements, visitor, expand_policy1, overlaps_policy1,
507 expand_policy2, overlaps_policy2, box_policy)) )
508 {
509 return false; // interrupt
510 }
511 }
512 else
513 {
514 if (! (handle_two(exceeding1, lower2, visitor)
515 && handle_two(exceeding1, upper2, visitor)) )
516 {
517 return false; // interrupt
518 }
519 }
520 }
521
522 if (! boost::empty(exceeding2))
523 {
524 // All exceeding from 2 with lower and upper of 1:
525 if (recurse_ok(lower1, upper1, exceeding2, min_elements, level))
526 {
527 Box exceeding_box = get_new_box(exceeding2, expand_policy2);
528 if (! (next_level(exceeding_box, lower1, exceeding2, level,
529 min_elements, visitor, expand_policy1, overlaps_policy1,
530 expand_policy2, overlaps_policy2, box_policy)
531 && next_level(exceeding_box, upper1, exceeding2, level,
532 min_elements, visitor, expand_policy1, overlaps_policy1,
533 expand_policy2, overlaps_policy2, box_policy)) )
534 {
535 return false; // interrupt
536 }
537 }
538 else
539 {
540 if (! (handle_two(lower1, exceeding2, visitor)
541 && handle_two(upper1, exceeding2, visitor)) )
542 {
543 return false; // interrupt
544 }
545 }
546 }
547
548 if (recurse_ok(lower1, lower2, min_elements, level))
549 {
550 if (! next_level(lower_box, lower1, lower2, level,
551 min_elements, visitor, expand_policy1, overlaps_policy1,
552 expand_policy2, overlaps_policy2, box_policy) )
553 {
554 return false; // interrupt
555 }
556 }
557 else
558 {
559 if (! handle_two(lower1, lower2, visitor))
560 {
561 return false; // interrupt
562 }
563 }
564
565 if (recurse_ok(upper1, upper2, min_elements, level))
566 {
567 if (! next_level(upper_box, upper1, upper2, level,
568 min_elements, visitor, expand_policy1, overlaps_policy1,
569 expand_policy2, overlaps_policy2, box_policy) )
570 {
571 return false; // interrupt
572 }
573 }
574 else
575 {
576 if (! handle_two(upper1, upper2, visitor))
577 {
578 return false; // interrupt
579 }
580 }
581
582 return true;
583 }
584 };
585
586 struct visit_no_policy
587 {
588 template <typename Box>
589 static inline void apply(Box const&, std::size_t )
590 {}
591 };
592
593 struct include_all_policy
594 {
595 template <typename Item>
596 static inline bool apply(Item const&)
597 {
598 return true;
599 }
600 };
601
602
603 }} // namespace detail::partition
604
605 template
606 <
607 typename Box,
608 typename IncludePolicy1 = detail::partition::include_all_policy,
609 typename IncludePolicy2 = detail::partition::include_all_policy
610 >
611 class partition
612 {
613 static const std::size_t default_min_elements = 16;
614
615 template
616 <
617 typename IncludePolicy,
618 typename ForwardRange,
619 typename IteratorVector,
620 typename ExpandPolicy
621 >
622 static inline void expand_to_range(ForwardRange const& forward_range,
623 Box& total,
624 IteratorVector& iterator_vector,
625 ExpandPolicy const& expand_policy)
626 {
627 for(typename boost::range_iterator<ForwardRange const>::type
628 it = boost::begin(forward_range);
629 it != boost::end(forward_range);
630 ++it)
631 {
632 if (IncludePolicy::apply(*it))
633 {
634 expand_policy.apply(total, *it);
635 iterator_vector.push_back(it);
636 }
637 }
638 }
639
640 public:
641 template
642 <
643 typename ForwardRange,
644 typename VisitPolicy,
645 typename ExpandPolicy,
646 typename OverlapsPolicy
647 >
648 static inline bool apply(ForwardRange const& forward_range,
649 VisitPolicy& visitor,
650 ExpandPolicy const& expand_policy,
651 OverlapsPolicy const& overlaps_policy)
652 {
653 return apply(forward_range, visitor, expand_policy, overlaps_policy,
654 default_min_elements, detail::partition::visit_no_policy());
655 }
656
657 template
658 <
659 typename ForwardRange,
660 typename VisitPolicy,
661 typename ExpandPolicy,
662 typename OverlapsPolicy
663 >
664 static inline bool apply(ForwardRange const& forward_range,
665 VisitPolicy& visitor,
666 ExpandPolicy const& expand_policy,
667 OverlapsPolicy const& overlaps_policy,
668 std::size_t min_elements)
669 {
670 return apply(forward_range, visitor, expand_policy, overlaps_policy,
671 min_elements, detail::partition::visit_no_policy());
672 }
673
674 template
675 <
676 typename ForwardRange,
677 typename VisitPolicy,
678 typename ExpandPolicy,
679 typename OverlapsPolicy,
680 typename VisitBoxPolicy
681 >
682 static inline bool apply(ForwardRange const& forward_range,
683 VisitPolicy& visitor,
684 ExpandPolicy const& expand_policy,
685 OverlapsPolicy const& overlaps_policy,
686 std::size_t min_elements,
687 VisitBoxPolicy box_visitor)
688 {
689 typedef typename boost::range_iterator
690 <
691 ForwardRange const
692 >::type iterator_type;
693
694 if (std::size_t(boost::size(forward_range)) > min_elements)
695 {
696 std::vector<iterator_type> iterator_vector;
697 Box total;
698 assign_inverse(total);
699 expand_to_range<IncludePolicy1>(forward_range, total,
700 iterator_vector, expand_policy);
701
702 return detail::partition::partition_one_range
703 <
704 0, Box
705 >::apply(total, iterator_vector, 0, min_elements,
706 visitor, expand_policy, overlaps_policy, box_visitor);
707 }
708 else
709 {
710 for(iterator_type it1 = boost::begin(forward_range);
711 it1 != boost::end(forward_range);
712 ++it1)
713 {
714 iterator_type it2 = it1;
715 for(++it2; it2 != boost::end(forward_range); ++it2)
716 {
717 if (! visitor.apply(*it1, *it2))
718 {
719 return false; // interrupt
720 }
721 }
722 }
723 }
724
725 return true;
726 }
727
728 template
729 <
730 typename ForwardRange1,
731 typename ForwardRange2,
732 typename VisitPolicy,
733 typename ExpandPolicy1,
734 typename OverlapsPolicy1
735 >
736 static inline bool apply(ForwardRange1 const& forward_range1,
737 ForwardRange2 const& forward_range2,
738 VisitPolicy& visitor,
739 ExpandPolicy1 const& expand_policy1,
740 OverlapsPolicy1 const& overlaps_policy1)
741 {
742 return apply(forward_range1, forward_range2, visitor,
743 expand_policy1, overlaps_policy1, expand_policy1, overlaps_policy1,
744 default_min_elements, detail::partition::visit_no_policy());
745 }
746
747 template
748 <
749 typename ForwardRange1,
750 typename ForwardRange2,
751 typename VisitPolicy,
752 typename ExpandPolicy1,
753 typename OverlapsPolicy1,
754 typename ExpandPolicy2,
755 typename OverlapsPolicy2
756 >
757 static inline bool apply(ForwardRange1 const& forward_range1,
758 ForwardRange2 const& forward_range2,
759 VisitPolicy& visitor,
760 ExpandPolicy1 const& expand_policy1,
761 OverlapsPolicy1 const& overlaps_policy1,
762 ExpandPolicy2 const& expand_policy2,
763 OverlapsPolicy2 const& overlaps_policy2)
764 {
765 return apply(forward_range1, forward_range2, visitor,
766 expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy2,
767 default_min_elements, detail::partition::visit_no_policy());
768 }
769
770 template
771 <
772 typename ForwardRange1,
773 typename ForwardRange2,
774 typename VisitPolicy,
775 typename ExpandPolicy1,
776 typename OverlapsPolicy1,
777 typename ExpandPolicy2,
778 typename OverlapsPolicy2
779 >
780 static inline bool apply(ForwardRange1 const& forward_range1,
781 ForwardRange2 const& forward_range2,
782 VisitPolicy& visitor,
783 ExpandPolicy1 const& expand_policy1,
784 OverlapsPolicy1 const& overlaps_policy1,
785 ExpandPolicy2 const& expand_policy2,
786 OverlapsPolicy2 const& overlaps_policy2,
787 std::size_t min_elements)
788 {
789 return apply(forward_range1, forward_range2, visitor,
790 expand_policy1, overlaps_policy1, expand_policy2, overlaps_policy2,
791 min_elements, detail::partition::visit_no_policy());
792 }
793
794 template
795 <
796 typename ForwardRange1,
797 typename ForwardRange2,
798 typename VisitPolicy,
799 typename ExpandPolicy1,
800 typename OverlapsPolicy1,
801 typename ExpandPolicy2,
802 typename OverlapsPolicy2,
803 typename VisitBoxPolicy
804 >
805 static inline bool apply(ForwardRange1 const& forward_range1,
806 ForwardRange2 const& forward_range2,
807 VisitPolicy& visitor,
808 ExpandPolicy1 const& expand_policy1,
809 OverlapsPolicy1 const& overlaps_policy1,
810 ExpandPolicy2 const& expand_policy2,
811 OverlapsPolicy2 const& overlaps_policy2,
812 std::size_t min_elements,
813 VisitBoxPolicy box_visitor)
814 {
815 typedef typename boost::range_iterator
816 <
817 ForwardRange1 const
818 >::type iterator_type1;
819
820 typedef typename boost::range_iterator
821 <
822 ForwardRange2 const
823 >::type iterator_type2;
824
825 if (std::size_t(boost::size(forward_range1)) > min_elements
826 && std::size_t(boost::size(forward_range2)) > min_elements)
827 {
828 std::vector<iterator_type1> iterator_vector1;
829 std::vector<iterator_type2> iterator_vector2;
830 Box total;
831 assign_inverse(total);
832 expand_to_range<IncludePolicy1>(forward_range1, total,
833 iterator_vector1, expand_policy1);
834 expand_to_range<IncludePolicy2>(forward_range2, total,
835 iterator_vector2, expand_policy2);
836
837 return detail::partition::partition_two_ranges
838 <
839 0, Box
840 >::apply(total, iterator_vector1, iterator_vector2,
841 0, min_elements, visitor, expand_policy1,
842 overlaps_policy1, expand_policy2, overlaps_policy2,
843 box_visitor);
844 }
845 else
846 {
847 for(iterator_type1 it1 = boost::begin(forward_range1);
848 it1 != boost::end(forward_range1);
849 ++it1)
850 {
851 for(iterator_type2 it2 = boost::begin(forward_range2);
852 it2 != boost::end(forward_range2);
853 ++it2)
854 {
855 if (! visitor.apply(*it1, *it2))
856 {
857 return false; // interrupt
858 }
859 }
860 }
861 }
862
863 return true;
864 }
865 };
866
867
868 }} // namespace boost::geometry
869
870 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP