partition.hpp 29 KB

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