partition.hpp 29 KB

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