predicates.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. // Boost.Geometry Index
  2. //
  3. // Spatial query predicates definition and checks.
  4. //
  5. // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
  6. //
  7. // This file was modified by Oracle on 2019-2021.
  8. // Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
  9. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  10. //
  11. // Use, modification and distribution is subject to the Boost Software License,
  12. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  13. // http://www.boost.org/LICENSE_1_0.txt)
  14. #ifndef BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
  15. #define BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
  16. #include <tuple>
  17. #include <type_traits>
  18. //#include <utility>
  19. #include <boost/geometry/core/static_assert.hpp>
  20. #include <boost/geometry/core/tag.hpp>
  21. #include <boost/geometry/core/tags.hpp>
  22. #include <boost/geometry/index/detail/tags.hpp>
  23. #include <boost/geometry/strategies/default_strategy.hpp>
  24. namespace boost { namespace geometry { namespace index { namespace detail {
  25. namespace predicates {
  26. // ------------------------------------------------------------------ //
  27. // predicates
  28. // ------------------------------------------------------------------ //
  29. template <typename Fun, bool IsFunction = std::is_function<Fun>::value>
  30. struct satisfies_impl
  31. {
  32. satisfies_impl() : fun(nullptr) {}
  33. satisfies_impl(Fun f) : fun(f) {}
  34. Fun * fun;
  35. };
  36. template <typename Fun>
  37. struct satisfies_impl<Fun, false>
  38. {
  39. satisfies_impl() = default;
  40. satisfies_impl(Fun const& f) : fun(f) {}
  41. Fun fun;
  42. };
  43. template <typename Fun, bool Negated>
  44. struct satisfies : satisfies_impl<Fun>
  45. {
  46. using base_t = satisfies_impl<Fun>;
  47. satisfies() = default;
  48. satisfies(Fun const& f) : base_t(f) {}
  49. satisfies(base_t const& b) : base_t(b) {}
  50. };
  51. // ------------------------------------------------------------------ //
  52. struct contains_tag {};
  53. struct covered_by_tag {};
  54. struct covers_tag {};
  55. struct disjoint_tag {};
  56. struct intersects_tag {};
  57. struct overlaps_tag {};
  58. struct touches_tag {};
  59. struct within_tag {};
  60. template <typename Geometry, typename Tag, bool Negated>
  61. struct spatial_predicate
  62. {
  63. spatial_predicate() {}
  64. spatial_predicate(Geometry const& g) : geometry(g) {}
  65. Geometry geometry;
  66. };
  67. // ------------------------------------------------------------------ //
  68. // CONSIDER: separated nearest<> and path<> may be replaced by
  69. // nearest_predicate<Geometry, Tag>
  70. // where Tag = point_tag | path_tag
  71. // IMPROVEMENT: user-defined nearest predicate allowing to define
  72. // all or only geometrical aspects of the search
  73. template <typename PointOrRelation>
  74. struct nearest
  75. {
  76. nearest()
  77. // : count(0)
  78. {}
  79. nearest(PointOrRelation const& por, std::size_t k)
  80. : point_or_relation(por)
  81. , count(k)
  82. {}
  83. PointOrRelation point_or_relation;
  84. std::size_t count;
  85. };
  86. template <typename SegmentOrLinestring>
  87. struct path
  88. {
  89. path()
  90. // : count(0)
  91. {}
  92. path(SegmentOrLinestring const& g, std::size_t k)
  93. : geometry(g)
  94. , count(k)
  95. {}
  96. SegmentOrLinestring geometry;
  97. std::size_t count;
  98. };
  99. } // namespace predicates
  100. // ------------------------------------------------------------------ //
  101. // predicate_check
  102. // ------------------------------------------------------------------ //
  103. template <typename Predicate, typename Tag>
  104. struct predicate_check
  105. {
  106. BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
  107. "Not implemented for this Predicate or Tag.",
  108. Predicate, Tag);
  109. };
  110. // ------------------------------------------------------------------ //
  111. template <typename Fun>
  112. struct predicate_check<predicates::satisfies<Fun, false>, value_tag>
  113. {
  114. template <typename Value, typename Indexable, typename Strategy>
  115. static inline bool apply(predicates::satisfies<Fun, false> const& p, Value const& v, Indexable const& , Strategy const&)
  116. {
  117. return p.fun(v);
  118. }
  119. };
  120. template <typename Fun>
  121. struct predicate_check<predicates::satisfies<Fun, true>, value_tag>
  122. {
  123. template <typename Value, typename Indexable, typename Strategy>
  124. static inline bool apply(predicates::satisfies<Fun, true> const& p, Value const& v, Indexable const& , Strategy const&)
  125. {
  126. return !p.fun(v);
  127. }
  128. };
  129. // ------------------------------------------------------------------ //
  130. template <typename Tag>
  131. struct spatial_predicate_call
  132. {
  133. BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
  134. "Not implemented for this Tag.",
  135. Tag);
  136. };
  137. template <>
  138. struct spatial_predicate_call<predicates::contains_tag>
  139. {
  140. template <typename G1, typename G2, typename S>
  141. static inline bool apply(G1 const& g1, G2 const& g2, S const&)
  142. {
  143. return geometry::within(g2, g1);
  144. }
  145. };
  146. template <>
  147. struct spatial_predicate_call<predicates::covered_by_tag>
  148. {
  149. template <typename G1, typename G2, typename S>
  150. static inline bool apply(G1 const& g1, G2 const& g2, S const&)
  151. {
  152. return geometry::covered_by(g1, g2);
  153. }
  154. };
  155. template <>
  156. struct spatial_predicate_call<predicates::covers_tag>
  157. {
  158. template <typename G1, typename G2, typename S>
  159. static inline bool apply(G1 const& g1, G2 const& g2, S const&)
  160. {
  161. return geometry::covered_by(g2, g1);
  162. }
  163. };
  164. template <>
  165. struct spatial_predicate_call<predicates::disjoint_tag>
  166. {
  167. template <typename G1, typename G2, typename S>
  168. static inline bool apply(G1 const& g1, G2 const& g2, S const&)
  169. {
  170. return geometry::disjoint(g1, g2);
  171. }
  172. };
  173. // TEMP: used to implement CS-specific intersects predicate for certain
  174. // combinations of geometries until umbrella strategies are implemented
  175. template
  176. <
  177. typename G1, typename G2,
  178. typename Tag1 = typename tag<G1>::type,
  179. typename Tag2 = typename tag<G2>::type
  180. >
  181. struct spatial_predicate_intersects
  182. {
  183. template <typename S>
  184. static inline bool apply(G1 const& g1, G2 const& g2, S const&)
  185. {
  186. return geometry::intersects(g1, g2);
  187. }
  188. };
  189. // TEMP: used in within and relate
  190. template <typename G1, typename G2>
  191. struct spatial_predicate_intersects<G1, G2, box_tag, point_tag>
  192. {
  193. static inline bool apply(G1 const& g1, G2 const& g2, default_strategy const&)
  194. {
  195. return geometry::intersects(g1, g2);
  196. }
  197. template <typename S>
  198. static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
  199. {
  200. return geometry::intersects(g1, g2, s);
  201. }
  202. };
  203. template <>
  204. struct spatial_predicate_call<predicates::intersects_tag>
  205. {
  206. template <typename G1, typename G2, typename S>
  207. static inline bool apply(G1 const& g1, G2 const& g2, S const& s)
  208. {
  209. return spatial_predicate_intersects<G1, G2>::apply(g1, g2, s);
  210. }
  211. };
  212. template <>
  213. struct spatial_predicate_call<predicates::overlaps_tag>
  214. {
  215. template <typename G1, typename G2, typename S>
  216. static inline bool apply(G1 const& g1, G2 const& g2, S const&)
  217. {
  218. return geometry::overlaps(g1, g2);
  219. }
  220. };
  221. template <>
  222. struct spatial_predicate_call<predicates::touches_tag>
  223. {
  224. template <typename G1, typename G2, typename S>
  225. static inline bool apply(G1 const& g1, G2 const& g2, S const&)
  226. {
  227. return geometry::touches(g1, g2);
  228. }
  229. };
  230. template <>
  231. struct spatial_predicate_call<predicates::within_tag>
  232. {
  233. template <typename G1, typename G2, typename S>
  234. static inline bool apply(G1 const& g1, G2 const& g2, S const&)
  235. {
  236. return geometry::within(g1, g2);
  237. }
  238. };
  239. // ------------------------------------------------------------------ //
  240. // spatial predicate
  241. template <typename Geometry, typename Tag>
  242. struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, value_tag>
  243. {
  244. typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
  245. template <typename Value, typename Indexable, typename Strategy>
  246. static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
  247. {
  248. return spatial_predicate_call<Tag>::apply(i, p.geometry, s);
  249. }
  250. };
  251. // negated spatial predicate
  252. template <typename Geometry, typename Tag>
  253. struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, value_tag>
  254. {
  255. typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
  256. template <typename Value, typename Indexable, typename Strategy>
  257. static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
  258. {
  259. return !spatial_predicate_call<Tag>::apply(i, p.geometry, s);
  260. }
  261. };
  262. // ------------------------------------------------------------------ //
  263. template <typename DistancePredicates>
  264. struct predicate_check<predicates::nearest<DistancePredicates>, value_tag>
  265. {
  266. template <typename Value, typename Box, typename Strategy>
  267. static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&, Strategy const&)
  268. {
  269. return true;
  270. }
  271. };
  272. template <typename Linestring>
  273. struct predicate_check<predicates::path<Linestring>, value_tag>
  274. {
  275. template <typename Value, typename Box, typename Strategy>
  276. static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&, Strategy const&)
  277. {
  278. return true;
  279. }
  280. };
  281. // ------------------------------------------------------------------ //
  282. // predicates_check for bounds
  283. // ------------------------------------------------------------------ //
  284. template <typename Fun, bool Negated>
  285. struct predicate_check<predicates::satisfies<Fun, Negated>, bounds_tag>
  286. {
  287. template <typename Value, typename Box, typename Strategy>
  288. static bool apply(predicates::satisfies<Fun, Negated> const&, Value const&, Box const&, Strategy const&)
  289. {
  290. return true;
  291. }
  292. };
  293. // ------------------------------------------------------------------ //
  294. // NOT NEGATED
  295. // value_tag bounds_tag
  296. // ---------------------------
  297. // contains(I,G) covers(I,G)
  298. // covered_by(I,G) intersects(I,G)
  299. // covers(I,G) covers(I,G)
  300. // disjoint(I,G) !covered_by(I,G)
  301. // intersects(I,G) intersects(I,G)
  302. // overlaps(I,G) intersects(I,G) - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
  303. // touches(I,G) intersects(I,G)
  304. // within(I,G) intersects(I,G) - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
  305. // spatial predicate - default
  306. template <typename Geometry, typename Tag>
  307. struct predicate_check<predicates::spatial_predicate<Geometry, Tag, false>, bounds_tag>
  308. {
  309. typedef predicates::spatial_predicate<Geometry, Tag, false> Pred;
  310. template <typename Value, typename Indexable, typename Strategy>
  311. static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
  312. {
  313. return spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry, s);
  314. }
  315. };
  316. // spatial predicate - contains
  317. template <typename Geometry>
  318. struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, false>, bounds_tag>
  319. {
  320. typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, false> Pred;
  321. template <typename Value, typename Indexable, typename Strategy>
  322. static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
  323. {
  324. return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry, s);
  325. }
  326. };
  327. // spatial predicate - covers
  328. template <typename Geometry>
  329. struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, false>, bounds_tag>
  330. {
  331. typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, false> Pred;
  332. template <typename Value, typename Indexable, typename Strategy>
  333. static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
  334. {
  335. return spatial_predicate_call<predicates::covers_tag>::apply(i, p.geometry, s);
  336. }
  337. };
  338. // spatial predicate - disjoint
  339. template <typename Geometry>
  340. struct predicate_check<predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false>, bounds_tag>
  341. {
  342. typedef predicates::spatial_predicate<Geometry, predicates::disjoint_tag, false> Pred;
  343. template <typename Value, typename Indexable, typename Strategy>
  344. static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
  345. {
  346. return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry, s);
  347. }
  348. };
  349. // NEGATED
  350. // value_tag bounds_tag
  351. // ---------------------------
  352. // !contains(I,G) TRUE
  353. // !covered_by(I,G) !covered_by(I,G)
  354. // !covers(I,G) TRUE
  355. // !disjoint(I,G) !disjoint(I,G)
  356. // !intersects(I,G) !covered_by(I,G)
  357. // !overlaps(I,G) TRUE
  358. // !touches(I,G) !intersects(I,G)
  359. // !within(I,G) !within(I,G)
  360. // negated spatial predicate - default
  361. template <typename Geometry, typename Tag>
  362. struct predicate_check<predicates::spatial_predicate<Geometry, Tag, true>, bounds_tag>
  363. {
  364. typedef predicates::spatial_predicate<Geometry, Tag, true> Pred;
  365. template <typename Value, typename Indexable, typename Strategy>
  366. static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
  367. {
  368. return !spatial_predicate_call<Tag>::apply(i, p.geometry, s);
  369. }
  370. };
  371. // negated spatial predicate - contains
  372. template <typename Geometry>
  373. struct predicate_check<predicates::spatial_predicate<Geometry, predicates::contains_tag, true>, bounds_tag>
  374. {
  375. typedef predicates::spatial_predicate<Geometry, predicates::contains_tag, true> Pred;
  376. template <typename Value, typename Indexable, typename Strategy>
  377. static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
  378. {
  379. return true;
  380. }
  381. };
  382. // negated spatial predicate - covers
  383. template <typename Geometry>
  384. struct predicate_check<predicates::spatial_predicate<Geometry, predicates::covers_tag, true>, bounds_tag>
  385. {
  386. typedef predicates::spatial_predicate<Geometry, predicates::covers_tag, true> Pred;
  387. template <typename Value, typename Indexable, typename Strategy>
  388. static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
  389. {
  390. return true;
  391. }
  392. };
  393. // negated spatial predicate - intersects
  394. template <typename Geometry>
  395. struct predicate_check<predicates::spatial_predicate<Geometry, predicates::intersects_tag, true>, bounds_tag>
  396. {
  397. typedef predicates::spatial_predicate<Geometry, predicates::intersects_tag, true> Pred;
  398. template <typename Value, typename Indexable, typename Strategy>
  399. static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const& s)
  400. {
  401. return !spatial_predicate_call<predicates::covered_by_tag>::apply(i, p.geometry, s);
  402. }
  403. };
  404. // negated spatial predicate - overlaps
  405. template <typename Geometry>
  406. struct predicate_check<predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true>, bounds_tag>
  407. {
  408. typedef predicates::spatial_predicate<Geometry, predicates::overlaps_tag, true> Pred;
  409. template <typename Value, typename Indexable, typename Strategy>
  410. static inline bool apply(Pred const& , Value const&, Indexable const&, Strategy const&)
  411. {
  412. return true;
  413. }
  414. };
  415. // negated spatial predicate - touches
  416. template <typename Geometry>
  417. struct predicate_check<predicates::spatial_predicate<Geometry, predicates::touches_tag, true>, bounds_tag>
  418. {
  419. typedef predicates::spatial_predicate<Geometry, predicates::touches_tag, true> Pred;
  420. template <typename Value, typename Indexable, typename Strategy>
  421. static inline bool apply(Pred const& p, Value const&, Indexable const& i, Strategy const&)
  422. {
  423. return !spatial_predicate_call<predicates::intersects_tag>::apply(i, p.geometry);
  424. }
  425. };
  426. // ------------------------------------------------------------------ //
  427. template <typename DistancePredicates>
  428. struct predicate_check<predicates::nearest<DistancePredicates>, bounds_tag>
  429. {
  430. template <typename Value, typename Box, typename Strategy>
  431. static inline bool apply(predicates::nearest<DistancePredicates> const&, Value const&, Box const&, Strategy const&)
  432. {
  433. return true;
  434. }
  435. };
  436. template <typename Linestring>
  437. struct predicate_check<predicates::path<Linestring>, bounds_tag>
  438. {
  439. template <typename Value, typename Box, typename Strategy>
  440. static inline bool apply(predicates::path<Linestring> const&, Value const&, Box const&, Strategy const&)
  441. {
  442. return true;
  443. }
  444. };
  445. // ------------------------------------------------------------------ //
  446. // predicates_length
  447. // ------------------------------------------------------------------ //
  448. template <typename T>
  449. struct predicates_length
  450. {
  451. static const std::size_t value = 1;
  452. };
  453. template <typename ...Ts>
  454. struct predicates_length<std::tuple<Ts...>>
  455. {
  456. static const std::size_t value = std::tuple_size<std::tuple<Ts...>>::value;
  457. };
  458. // ------------------------------------------------------------------ //
  459. // predicates_element
  460. // ------------------------------------------------------------------ //
  461. template <std::size_t I, typename T>
  462. struct predicates_element
  463. {
  464. BOOST_GEOMETRY_STATIC_ASSERT((I < 1),
  465. "Invalid I index.",
  466. std::integral_constant<std::size_t, I>);
  467. typedef T type;
  468. static type const& get(T const& p) { return p; }
  469. };
  470. template <std::size_t I, typename ...Ts>
  471. struct predicates_element<I, std::tuple<Ts...>>
  472. {
  473. typedef std::tuple<Ts...> predicate_type;
  474. typedef typename std::tuple_element<I, predicate_type>::type type;
  475. static type const& get(predicate_type const& p) { return std::get<I>(p); }
  476. };
  477. // ------------------------------------------------------------------ //
  478. // predicates_check
  479. // ------------------------------------------------------------------ //
  480. template <typename TuplePredicates, typename Tag, std::size_t First, std::size_t Last>
  481. struct predicates_check_tuple
  482. {
  483. template <typename Value, typename Indexable, typename Strategy>
  484. static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i, Strategy const& s)
  485. {
  486. return predicate_check
  487. <
  488. typename std::tuple_element<First, TuplePredicates>::type,
  489. Tag
  490. >::apply(std::get<First>(p), v, i, s)
  491. && predicates_check_tuple<TuplePredicates, Tag, First+1, Last>::apply(p, v, i, s);
  492. }
  493. };
  494. template <typename TuplePredicates, typename Tag, std::size_t First>
  495. struct predicates_check_tuple<TuplePredicates, Tag, First, First>
  496. {
  497. template <typename Value, typename Indexable, typename Strategy>
  498. static inline bool apply(TuplePredicates const& , Value const& , Indexable const& , Strategy const& )
  499. {
  500. return true;
  501. }
  502. };
  503. template <typename Predicate, typename Tag, std::size_t First, std::size_t Last>
  504. struct predicates_check_impl
  505. {
  506. static const bool check = First < 1 && Last <= 1 && First <= Last;
  507. BOOST_GEOMETRY_STATIC_ASSERT((check),
  508. "Invalid First or Last index.",
  509. std::integer_sequence<std::size_t, First, Last>);
  510. template <typename Value, typename Indexable, typename Strategy>
  511. static inline bool apply(Predicate const& p, Value const& v, Indexable const& i, Strategy const& s)
  512. {
  513. return predicate_check<Predicate, Tag>::apply(p, v, i, s);
  514. }
  515. };
  516. template <typename ...Ts, typename Tag, std::size_t First, std::size_t Last>
  517. struct predicates_check_impl<std::tuple<Ts...>, Tag, First, Last>
  518. {
  519. typedef std::tuple<Ts...> predicates_type;
  520. static const std::size_t pred_len = std::tuple_size<predicates_type>::value;
  521. static const bool check = First < pred_len && Last <= pred_len && First <= Last;
  522. BOOST_GEOMETRY_STATIC_ASSERT((check),
  523. "Invalid First or Last index.",
  524. std::integer_sequence<std::size_t, First, Last>);
  525. template <typename Value, typename Indexable, typename Strategy>
  526. static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i, Strategy const& s)
  527. {
  528. return predicates_check_tuple
  529. <
  530. predicates_type,
  531. Tag, First, Last
  532. >::apply(p, v, i, s);
  533. }
  534. };
  535. template <typename Tag, typename Predicates, typename Value, typename Indexable, typename Strategy>
  536. inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i, Strategy const& s)
  537. {
  538. return detail::predicates_check_impl
  539. <
  540. Predicates, Tag, 0, predicates_length<Predicates>::value
  541. >::apply(p, v, i, s);
  542. }
  543. // ------------------------------------------------------------------ //
  544. // nearest predicate helpers
  545. // ------------------------------------------------------------------ //
  546. // predicates_is_nearest
  547. template <typename P>
  548. struct predicates_is_distance
  549. {
  550. static const std::size_t value = 0;
  551. };
  552. template <typename DistancePredicates>
  553. struct predicates_is_distance< predicates::nearest<DistancePredicates> >
  554. {
  555. static const std::size_t value = 1;
  556. };
  557. template <typename Linestring>
  558. struct predicates_is_distance< predicates::path<Linestring> >
  559. {
  560. static const std::size_t value = 1;
  561. };
  562. // predicates_count_nearest
  563. template <typename T>
  564. struct predicates_count_distance
  565. {
  566. static const std::size_t value = predicates_is_distance<T>::value;
  567. };
  568. template <typename Tuple, std::size_t N>
  569. struct predicates_count_distance_tuple
  570. {
  571. static const std::size_t value =
  572. predicates_is_distance<typename std::tuple_element<N-1, Tuple>::type>::value
  573. + predicates_count_distance_tuple<Tuple, N-1>::value;
  574. };
  575. template <typename Tuple>
  576. struct predicates_count_distance_tuple<Tuple, 1>
  577. {
  578. static const std::size_t value =
  579. predicates_is_distance<typename std::tuple_element<0, Tuple>::type>::value;
  580. };
  581. template <typename ...Ts>
  582. struct predicates_count_distance<std::tuple<Ts...>>
  583. {
  584. static const std::size_t value = predicates_count_distance_tuple<
  585. std::tuple<Ts...>,
  586. std::tuple_size<std::tuple<Ts...>>::value
  587. >::value;
  588. };
  589. // predicates_find_nearest
  590. template <typename T>
  591. struct predicates_find_distance
  592. {
  593. static const std::size_t value = predicates_is_distance<T>::value ? 0 : 1;
  594. };
  595. template <typename Tuple, std::size_t N>
  596. struct predicates_find_distance_tuple
  597. {
  598. static const bool is_found = predicates_find_distance_tuple<Tuple, N-1>::is_found
  599. || predicates_is_distance<typename std::tuple_element<N-1, Tuple>::type>::value;
  600. static const std::size_t value = predicates_find_distance_tuple<Tuple, N-1>::is_found ?
  601. predicates_find_distance_tuple<Tuple, N-1>::value :
  602. (predicates_is_distance<typename std::tuple_element<N-1, Tuple>::type>::value ?
  603. N-1 : std::tuple_size<Tuple>::value);
  604. };
  605. template <typename Tuple>
  606. struct predicates_find_distance_tuple<Tuple, 1>
  607. {
  608. static const bool is_found = predicates_is_distance<typename std::tuple_element<0, Tuple>::type>::value;
  609. static const std::size_t value = is_found ? 0 : std::tuple_size<Tuple>::value;
  610. };
  611. template <typename ...Ts>
  612. struct predicates_find_distance<std::tuple<Ts...>>
  613. {
  614. static const std::size_t value = predicates_find_distance_tuple<
  615. std::tuple<Ts...>,
  616. std::tuple_size<std::tuple<Ts...>>::value
  617. >::value;
  618. };
  619. }}}} // namespace boost::geometry::index::detail
  620. #endif // BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP