predicates.hpp 23 KB

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