partition.hpp 29 KB

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