segment_to_box.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014-2019 Oracle and/or its affiliates.
  3. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  4. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  5. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  6. // Licensed under the Boost Software License version 1.0.
  7. // http://www.boost.org/users/license.html
  8. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
  9. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
  10. #include <cstddef>
  11. #include <functional>
  12. #include <vector>
  13. #include <boost/core/ignore_unused.hpp>
  14. #include <boost/mpl/if.hpp>
  15. #include <boost/numeric/conversion/cast.hpp>
  16. #include <boost/type_traits/is_same.hpp>
  17. #include <boost/geometry/core/access.hpp>
  18. #include <boost/geometry/core/assert.hpp>
  19. #include <boost/geometry/core/closure.hpp>
  20. #include <boost/geometry/core/coordinate_dimension.hpp>
  21. #include <boost/geometry/core/point_type.hpp>
  22. #include <boost/geometry/core/tags.hpp>
  23. #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
  24. #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
  25. #include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
  26. #include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
  27. #include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
  28. #include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
  29. #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
  30. #include <boost/geometry/algorithms/dispatch/distance.hpp>
  31. #include <boost/geometry/algorithms/not_implemented.hpp>
  32. #include <boost/geometry/policies/compare.hpp>
  33. #include <boost/geometry/util/calculation_type.hpp>
  34. #include <boost/geometry/util/condition.hpp>
  35. #include <boost/geometry/util/has_nan_coordinate.hpp>
  36. #include <boost/geometry/util/math.hpp>
  37. #include <boost/geometry/strategies/disjoint.hpp>
  38. #include <boost/geometry/strategies/distance.hpp>
  39. #include <boost/geometry/strategies/tags.hpp>
  40. namespace boost { namespace geometry
  41. {
  42. #ifndef DOXYGEN_NO_DETAIL
  43. namespace detail { namespace distance
  44. {
  45. // TODO: Take strategy
  46. template <typename Segment, typename Box>
  47. inline bool intersects_segment_box(Segment const& segment, Box const& box)
  48. {
  49. typedef typename strategy::disjoint::services::default_strategy
  50. <
  51. Segment, Box
  52. >::type strategy_type;
  53. return ! detail::disjoint::disjoint_segment_box::apply(segment, box,
  54. strategy_type());
  55. }
  56. template
  57. <
  58. typename Segment,
  59. typename Box,
  60. typename Strategy,
  61. bool UsePointBoxStrategy = false
  62. >
  63. class segment_to_box_2D_generic
  64. {
  65. private:
  66. typedef typename point_type<Segment>::type segment_point;
  67. typedef typename point_type<Box>::type box_point;
  68. typedef typename strategy::distance::services::comparable_type
  69. <
  70. typename Strategy::distance_ps_strategy::type
  71. >::type comparable_strategy;
  72. typedef detail::closest_feature::point_to_point_range
  73. <
  74. segment_point,
  75. std::vector<box_point>,
  76. open,
  77. comparable_strategy
  78. > point_to_point_range;
  79. typedef typename strategy::distance::services::return_type
  80. <
  81. comparable_strategy, segment_point, box_point
  82. >::type comparable_return_type;
  83. public:
  84. typedef typename strategy::distance::services::return_type
  85. <
  86. Strategy, segment_point, box_point
  87. >::type return_type;
  88. static inline return_type apply(Segment const& segment,
  89. Box const& box,
  90. Strategy const& strategy,
  91. bool check_intersection = true)
  92. {
  93. if (check_intersection && intersects_segment_box(segment, box))
  94. {
  95. return 0;
  96. }
  97. comparable_strategy cstrategy =
  98. strategy::distance::services::get_comparable
  99. <
  100. typename Strategy::distance_ps_strategy::type
  101. >::apply(strategy.get_distance_ps_strategy());
  102. // get segment points
  103. segment_point p[2];
  104. detail::assign_point_from_index<0>(segment, p[0]);
  105. detail::assign_point_from_index<1>(segment, p[1]);
  106. // get box points
  107. std::vector<box_point> box_points(4);
  108. detail::assign_box_corners_oriented<true>(box, box_points);
  109. comparable_return_type cd[6];
  110. for (unsigned int i = 0; i < 4; ++i)
  111. {
  112. cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
  113. }
  114. std::pair
  115. <
  116. typename std::vector<box_point>::const_iterator,
  117. typename std::vector<box_point>::const_iterator
  118. > bit_min[2];
  119. bit_min[0] = point_to_point_range::apply(p[0],
  120. box_points.begin(),
  121. box_points.end(),
  122. cstrategy,
  123. cd[4]);
  124. bit_min[1] = point_to_point_range::apply(p[1],
  125. box_points.begin(),
  126. box_points.end(),
  127. cstrategy,
  128. cd[5]);
  129. unsigned int imin = 0;
  130. for (unsigned int i = 1; i < 6; ++i)
  131. {
  132. if (cd[i] < cd[imin])
  133. {
  134. imin = i;
  135. }
  136. }
  137. if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
  138. {
  139. return cd[imin];
  140. }
  141. if (imin < 4)
  142. {
  143. return strategy.get_distance_ps_strategy().apply(box_points[imin], p[0], p[1]);
  144. }
  145. else
  146. {
  147. unsigned int bimin = imin - 4;
  148. return strategy.get_distance_ps_strategy().apply(p[bimin],
  149. *bit_min[bimin].first,
  150. *bit_min[bimin].second);
  151. }
  152. }
  153. };
  154. template
  155. <
  156. typename Segment,
  157. typename Box,
  158. typename Strategy
  159. >
  160. class segment_to_box_2D_generic<Segment, Box, Strategy, true>
  161. {
  162. private:
  163. typedef typename point_type<Segment>::type segment_point;
  164. typedef typename point_type<Box>::type box_point;
  165. typedef typename strategy::distance::services::comparable_type
  166. <
  167. Strategy
  168. >::type comparable_strategy;
  169. typedef typename strategy::distance::services::return_type
  170. <
  171. comparable_strategy, segment_point, box_point
  172. >::type comparable_return_type;
  173. typedef typename detail::distance::default_strategy
  174. <
  175. segment_point, Box
  176. >::type point_box_strategy;
  177. typedef typename strategy::distance::services::comparable_type
  178. <
  179. point_box_strategy
  180. >::type point_box_comparable_strategy;
  181. public:
  182. typedef typename strategy::distance::services::return_type
  183. <
  184. Strategy, segment_point, box_point
  185. >::type return_type;
  186. static inline return_type apply(Segment const& segment,
  187. Box const& box,
  188. Strategy const& strategy,
  189. bool check_intersection = true)
  190. {
  191. if (check_intersection && intersects_segment_box(segment, box))
  192. {
  193. return 0;
  194. }
  195. comparable_strategy cstrategy =
  196. strategy::distance::services::get_comparable
  197. <
  198. Strategy
  199. >::apply(strategy);
  200. boost::ignore_unused(cstrategy);
  201. // get segment points
  202. segment_point p[2];
  203. detail::assign_point_from_index<0>(segment, p[0]);
  204. detail::assign_point_from_index<1>(segment, p[1]);
  205. // get box points
  206. std::vector<box_point> box_points(4);
  207. detail::assign_box_corners_oriented<true>(box, box_points);
  208. comparable_return_type cd[6];
  209. for (unsigned int i = 0; i < 4; ++i)
  210. {
  211. cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
  212. }
  213. point_box_comparable_strategy pb_cstrategy;
  214. boost::ignore_unused(pb_cstrategy);
  215. cd[4] = pb_cstrategy.apply(p[0], box);
  216. cd[5] = pb_cstrategy.apply(p[1], box);
  217. unsigned int imin = 0;
  218. for (unsigned int i = 1; i < 6; ++i)
  219. {
  220. if (cd[i] < cd[imin])
  221. {
  222. imin = i;
  223. }
  224. }
  225. if (is_comparable<Strategy>::value)
  226. {
  227. return cd[imin];
  228. }
  229. if (imin < 4)
  230. {
  231. strategy.apply(box_points[imin], p[0], p[1]);
  232. }
  233. else
  234. {
  235. return point_box_strategy().apply(p[imin - 4], box);
  236. }
  237. }
  238. };
  239. template
  240. <
  241. typename ReturnType,
  242. typename SegmentPoint,
  243. typename BoxPoint,
  244. typename SBStrategy
  245. >
  246. class segment_to_box_2D
  247. {
  248. private:
  249. template <typename Result>
  250. struct cast_to_result
  251. {
  252. template <typename T>
  253. static inline Result apply(T const& t)
  254. {
  255. return boost::numeric_cast<Result>(t);
  256. }
  257. };
  258. template <typename T, bool IsLess /* true */>
  259. struct compare_less_equal
  260. {
  261. typedef compare_less_equal<T, !IsLess> other;
  262. template <typename T1, typename T2>
  263. inline bool operator()(T1 const& t1, T2 const& t2) const
  264. {
  265. return std::less_equal<T>()(cast_to_result<T>::apply(t1),
  266. cast_to_result<T>::apply(t2));
  267. }
  268. };
  269. template <typename T>
  270. struct compare_less_equal<T, false>
  271. {
  272. typedef compare_less_equal<T, true> other;
  273. template <typename T1, typename T2>
  274. inline bool operator()(T1 const& t1, T2 const& t2) const
  275. {
  276. return std::greater_equal<T>()(cast_to_result<T>::apply(t1),
  277. cast_to_result<T>::apply(t2));
  278. }
  279. };
  280. template <typename LessEqual>
  281. struct other_compare
  282. {
  283. typedef typename LessEqual::other type;
  284. };
  285. // it is assumed here that p0 lies to the right of the box (so the
  286. // entire segment lies to the right of the box)
  287. template <typename LessEqual>
  288. struct right_of_box
  289. {
  290. static inline ReturnType apply(SegmentPoint const& p0,
  291. SegmentPoint const& p1,
  292. BoxPoint const& bottom_right,
  293. BoxPoint const& top_right,
  294. SBStrategy const& sb_strategy)
  295. {
  296. boost::ignore_unused(sb_strategy);
  297. // the implementation below is written for non-negative slope
  298. // segments
  299. //
  300. // for negative slope segments swap the roles of bottom_right
  301. // and top_right and use greater_equal instead of less_equal.
  302. typedef cast_to_result<ReturnType> cast;
  303. LessEqual less_equal;
  304. typename SBStrategy::distance_ps_strategy::type ps_strategy =
  305. sb_strategy.get_distance_ps_strategy();
  306. if (less_equal(geometry::get<1>(bottom_right), geometry::get<1>(p0)))
  307. {
  308. //if p0 is in box's band
  309. if (less_equal(geometry::get<1>(p0), geometry::get<1>(top_right)))
  310. {
  311. // segment & crosses band (TODO:merge with box-box dist)
  312. if (math::equals(geometry::get<0>(p0), geometry::get<0>(p1)))
  313. {
  314. SegmentPoint high = geometry::get<1>(p1) > geometry::get<1>(p0) ? p1 : p0;
  315. if (less_equal(geometry::get<1>(high), geometry::get<1>(top_right)))
  316. {
  317. return cast::apply(ps_strategy.apply(high, bottom_right, top_right));
  318. }
  319. return cast::apply(ps_strategy.apply(top_right, p0, p1));
  320. }
  321. return cast::apply(ps_strategy.apply(p0, bottom_right, top_right));
  322. }
  323. // distance is realized between the top-right
  324. // corner of the box and the segment
  325. return cast::apply(ps_strategy.apply(top_right, p0, p1));
  326. }
  327. else
  328. {
  329. // distance is realized between the bottom-right
  330. // corner of the box and the segment
  331. return cast::apply(ps_strategy.apply(bottom_right, p0, p1));
  332. }
  333. }
  334. };
  335. // it is assumed here that p0 lies above the box (so the
  336. // entire segment lies above the box)
  337. template <typename LessEqual>
  338. struct above_of_box
  339. {
  340. static inline ReturnType apply(SegmentPoint const& p0,
  341. SegmentPoint const& p1,
  342. BoxPoint const& top_left,
  343. SBStrategy const& sb_strategy)
  344. {
  345. boost::ignore_unused(sb_strategy);
  346. return apply(p0, p1, p0, top_left, sb_strategy);
  347. }
  348. static inline ReturnType apply(SegmentPoint const& p0,
  349. SegmentPoint const& p1,
  350. SegmentPoint const& p_max,
  351. BoxPoint const& top_left,
  352. SBStrategy const& sb_strategy)
  353. {
  354. boost::ignore_unused(sb_strategy);
  355. typedef cast_to_result<ReturnType> cast;
  356. LessEqual less_equal;
  357. // p0 is above the upper segment of the box (and inside its band)
  358. // then compute the vertical (i.e. meridian for spherical) distance
  359. if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p_max)))
  360. {
  361. ReturnType diff =
  362. sb_strategy.get_distance_ps_strategy().vertical_or_meridian(
  363. geometry::get_as_radian<1>(p_max),
  364. geometry::get_as_radian<1>(top_left));
  365. return strategy::distance::services::result_from_distance
  366. <
  367. SBStrategy, SegmentPoint, BoxPoint
  368. >::apply(sb_strategy, math::abs(diff));
  369. }
  370. // p0 is to the left of the box, but p1 is above the box
  371. // in this case the distance is realized between the
  372. // top-left corner of the box and the segment
  373. return cast::apply(sb_strategy.get_distance_ps_strategy().
  374. apply(top_left, p0, p1));
  375. }
  376. };
  377. template <typename LessEqual>
  378. struct check_right_left_of_box
  379. {
  380. static inline bool apply(SegmentPoint const& p0,
  381. SegmentPoint const& p1,
  382. BoxPoint const& top_left,
  383. BoxPoint const& top_right,
  384. BoxPoint const& bottom_left,
  385. BoxPoint const& bottom_right,
  386. SBStrategy const& sb_strategy,
  387. ReturnType& result)
  388. {
  389. // p0 lies to the right of the box
  390. if (geometry::get<0>(p0) >= geometry::get<0>(top_right))
  391. {
  392. result = right_of_box
  393. <
  394. LessEqual
  395. >::apply(p0, p1, bottom_right, top_right,
  396. sb_strategy);
  397. return true;
  398. }
  399. // p1 lies to the left of the box
  400. if (geometry::get<0>(p1) <= geometry::get<0>(bottom_left))
  401. {
  402. result = right_of_box
  403. <
  404. typename other_compare<LessEqual>::type
  405. >::apply(p1, p0, top_left, bottom_left,
  406. sb_strategy);
  407. return true;
  408. }
  409. return false;
  410. }
  411. };
  412. template <typename LessEqual>
  413. struct check_above_below_of_box
  414. {
  415. static inline bool apply(SegmentPoint const& p0,
  416. SegmentPoint const& p1,
  417. BoxPoint const& top_left,
  418. BoxPoint const& top_right,
  419. BoxPoint const& bottom_left,
  420. BoxPoint const& bottom_right,
  421. SBStrategy const& sb_strategy,
  422. ReturnType& result)
  423. {
  424. typedef compare_less_equal<ReturnType, false> GreaterEqual;
  425. // the segment lies below the box
  426. if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))
  427. {
  428. result = sb_strategy.template segment_below_of_box
  429. <
  430. LessEqual,
  431. ReturnType
  432. >(p0, p1,
  433. top_left, top_right,
  434. bottom_left, bottom_right);
  435. return true;
  436. }
  437. // the segment lies above the box
  438. if (geometry::get<1>(p0) > geometry::get<1>(top_right))
  439. {
  440. result = (std::min)(above_of_box
  441. <
  442. LessEqual
  443. >::apply(p0, p1, top_left, sb_strategy),
  444. above_of_box
  445. <
  446. GreaterEqual
  447. >::apply(p1, p0, top_right, sb_strategy));
  448. return true;
  449. }
  450. return false;
  451. }
  452. };
  453. struct check_generic_position
  454. {
  455. static inline bool apply(SegmentPoint const& p0,
  456. SegmentPoint const& p1,
  457. BoxPoint const& corner1,
  458. BoxPoint const& corner2,
  459. SBStrategy const& sb_strategy,
  460. ReturnType& result)
  461. {
  462. typename SBStrategy::side_strategy_type
  463. side_strategy = sb_strategy.get_side_strategy();
  464. typedef cast_to_result<ReturnType> cast;
  465. ReturnType diff1 = cast::apply(geometry::get<1>(p1))
  466. - cast::apply(geometry::get<1>(p0));
  467. typename SBStrategy::distance_ps_strategy::type ps_strategy =
  468. sb_strategy.get_distance_ps_strategy();
  469. int sign = diff1 < 0 ? -1 : 1;
  470. if (side_strategy.apply(p0, p1, corner1) * sign < 0)
  471. {
  472. result = cast::apply(ps_strategy.apply(corner1, p0, p1));
  473. return true;
  474. }
  475. if (side_strategy.apply(p0, p1, corner2) * sign > 0)
  476. {
  477. result = cast::apply(ps_strategy.apply(corner2, p0, p1));
  478. return true;
  479. }
  480. return false;
  481. }
  482. };
  483. static inline ReturnType
  484. non_negative_slope_segment(SegmentPoint const& p0,
  485. SegmentPoint const& p1,
  486. BoxPoint const& top_left,
  487. BoxPoint const& top_right,
  488. BoxPoint const& bottom_left,
  489. BoxPoint const& bottom_right,
  490. SBStrategy const& sb_strategy)
  491. {
  492. typedef compare_less_equal<ReturnType, true> less_equal;
  493. // assert that the segment has non-negative slope
  494. BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1))
  495. && geometry::get<1>(p0) < geometry::get<1>(p1))
  496. ||
  497. ( geometry::get<0>(p0) < geometry::get<0>(p1)
  498. && geometry::get<1>(p0) <= geometry::get<1>(p1) )
  499. || geometry::has_nan_coordinate(p0)
  500. || geometry::has_nan_coordinate(p1));
  501. ReturnType result(0);
  502. if (check_right_left_of_box
  503. <
  504. less_equal
  505. >::apply(p0, p1,
  506. top_left, top_right, bottom_left, bottom_right,
  507. sb_strategy, result))
  508. {
  509. return result;
  510. }
  511. if (check_above_below_of_box
  512. <
  513. less_equal
  514. >::apply(p0, p1,
  515. top_left, top_right, bottom_left, bottom_right,
  516. sb_strategy, result))
  517. {
  518. return result;
  519. }
  520. if (check_generic_position::apply(p0, p1,
  521. top_left, bottom_right,
  522. sb_strategy, result))
  523. {
  524. return result;
  525. }
  526. // in all other cases the box and segment intersect, so return 0
  527. return result;
  528. }
  529. static inline ReturnType
  530. negative_slope_segment(SegmentPoint const& p0,
  531. SegmentPoint const& p1,
  532. BoxPoint const& top_left,
  533. BoxPoint const& top_right,
  534. BoxPoint const& bottom_left,
  535. BoxPoint const& bottom_right,
  536. SBStrategy const& sb_strategy)
  537. {
  538. typedef compare_less_equal<ReturnType, false> greater_equal;
  539. // assert that the segment has negative slope
  540. BOOST_GEOMETRY_ASSERT( ( geometry::get<0>(p0) < geometry::get<0>(p1)
  541. && geometry::get<1>(p0) > geometry::get<1>(p1) )
  542. || geometry::has_nan_coordinate(p0)
  543. || geometry::has_nan_coordinate(p1) );
  544. ReturnType result(0);
  545. if (check_right_left_of_box
  546. <
  547. greater_equal
  548. >::apply(p0, p1,
  549. bottom_left, bottom_right, top_left, top_right,
  550. sb_strategy, result))
  551. {
  552. return result;
  553. }
  554. if (check_above_below_of_box
  555. <
  556. greater_equal
  557. >::apply(p1, p0,
  558. top_right, top_left, bottom_right, bottom_left,
  559. sb_strategy, result))
  560. {
  561. return result;
  562. }
  563. if (check_generic_position::apply(p0, p1,
  564. bottom_left, top_right,
  565. sb_strategy, result))
  566. {
  567. return result;
  568. }
  569. // in all other cases the box and segment intersect, so return 0
  570. return result;
  571. }
  572. public:
  573. static inline ReturnType apply(SegmentPoint const& p0,
  574. SegmentPoint const& p1,
  575. BoxPoint const& top_left,
  576. BoxPoint const& top_right,
  577. BoxPoint const& bottom_left,
  578. BoxPoint const& bottom_right,
  579. SBStrategy const& sb_strategy)
  580. {
  581. BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, typename SBStrategy::cs_tag>()(p0, p1))
  582. || geometry::has_nan_coordinate(p0)
  583. || geometry::has_nan_coordinate(p1) );
  584. if (geometry::get<0>(p0) < geometry::get<0>(p1)
  585. && geometry::get<1>(p0) > geometry::get<1>(p1))
  586. {
  587. return negative_slope_segment(p0, p1,
  588. top_left, top_right,
  589. bottom_left, bottom_right,
  590. sb_strategy);
  591. }
  592. return non_negative_slope_segment(p0, p1,
  593. top_left, top_right,
  594. bottom_left, bottom_right,
  595. sb_strategy);
  596. }
  597. template <typename LessEqual>
  598. static inline ReturnType call_above_of_box(SegmentPoint const& p0,
  599. SegmentPoint const& p1,
  600. SegmentPoint const& p_max,
  601. BoxPoint const& top_left,
  602. SBStrategy const& sb_strategy)
  603. {
  604. return above_of_box<LessEqual>::apply(p0, p1, p_max, top_left, sb_strategy);
  605. }
  606. template <typename LessEqual>
  607. static inline ReturnType call_above_of_box(SegmentPoint const& p0,
  608. SegmentPoint const& p1,
  609. BoxPoint const& top_left,
  610. SBStrategy const& sb_strategy)
  611. {
  612. return above_of_box<LessEqual>::apply(p0, p1, top_left, sb_strategy);
  613. }
  614. };
  615. //=========================================================================
  616. template
  617. <
  618. typename Segment,
  619. typename Box,
  620. typename std::size_t Dimension,
  621. typename SBStrategy
  622. >
  623. class segment_to_box
  624. : not_implemented<Segment, Box>
  625. {};
  626. template
  627. <
  628. typename Segment,
  629. typename Box,
  630. typename SBStrategy
  631. >
  632. class segment_to_box<Segment, Box, 2, SBStrategy>
  633. {
  634. private:
  635. typedef typename point_type<Segment>::type segment_point;
  636. typedef typename point_type<Box>::type box_point;
  637. typedef typename strategy::distance::services::comparable_type
  638. <
  639. SBStrategy
  640. >::type ps_comparable_strategy;
  641. typedef typename strategy::distance::services::return_type
  642. <
  643. ps_comparable_strategy, segment_point, box_point
  644. >::type comparable_return_type;
  645. public:
  646. typedef typename strategy::distance::services::return_type
  647. <
  648. SBStrategy, segment_point, box_point
  649. >::type return_type;
  650. static inline return_type apply(Segment const& segment,
  651. Box const& box,
  652. SBStrategy const& sb_strategy)
  653. {
  654. segment_point p[2];
  655. detail::assign_point_from_index<0>(segment, p[0]);
  656. detail::assign_point_from_index<1>(segment, p[1]);
  657. if (detail::equals::equals_point_point(p[0], p[1],
  658. sb_strategy.get_equals_point_point_strategy()))
  659. {
  660. typedef typename boost::mpl::if_
  661. <
  662. boost::is_same
  663. <
  664. ps_comparable_strategy,
  665. SBStrategy
  666. >,
  667. typename strategy::distance::services::comparable_type
  668. <
  669. typename SBStrategy::distance_pb_strategy::type
  670. >::type,
  671. typename SBStrategy::distance_pb_strategy::type
  672. >::type point_box_strategy_type;
  673. return dispatch::distance
  674. <
  675. segment_point,
  676. Box,
  677. point_box_strategy_type
  678. >::apply(p[0], box, point_box_strategy_type());
  679. }
  680. box_point top_left, top_right, bottom_left, bottom_right;
  681. detail::assign_box_corners(box, bottom_left, bottom_right,
  682. top_left, top_right);
  683. SBStrategy::mirror(p[0], p[1],
  684. bottom_left, bottom_right,
  685. top_left, top_right);
  686. typedef geometry::less<segment_point, -1, typename SBStrategy::cs_tag> less_type;
  687. if (less_type()(p[0], p[1]))
  688. {
  689. return segment_to_box_2D
  690. <
  691. return_type,
  692. segment_point,
  693. box_point,
  694. SBStrategy
  695. >::apply(p[0], p[1],
  696. top_left, top_right, bottom_left, bottom_right,
  697. sb_strategy);
  698. }
  699. else
  700. {
  701. return segment_to_box_2D
  702. <
  703. return_type,
  704. segment_point,
  705. box_point,
  706. SBStrategy
  707. >::apply(p[1], p[0],
  708. top_left, top_right, bottom_left, bottom_right,
  709. sb_strategy);
  710. }
  711. }
  712. };
  713. }} // namespace detail::distance
  714. #endif // DOXYGEN_NO_DETAIL
  715. #ifndef DOXYGEN_NO_DISPATCH
  716. namespace dispatch
  717. {
  718. template <typename Segment, typename Box, typename Strategy>
  719. struct distance
  720. <
  721. Segment, Box, Strategy, segment_tag, box_tag,
  722. strategy_tag_distance_segment_box, false
  723. >
  724. {
  725. typedef typename strategy::distance::services::return_type
  726. <
  727. Strategy,
  728. typename point_type<Segment>::type,
  729. typename point_type<Box>::type
  730. >::type return_type;
  731. static inline return_type apply(Segment const& segment,
  732. Box const& box,
  733. Strategy const& strategy)
  734. {
  735. assert_dimension_equal<Segment, Box>();
  736. return detail::distance::segment_to_box
  737. <
  738. Segment,
  739. Box,
  740. dimension<Segment>::value,
  741. Strategy
  742. >::apply(segment, box, strategy);
  743. }
  744. };
  745. } // namespace dispatch
  746. #endif // DOXYGEN_NO_DISPATCH
  747. }} // namespace boost::geometry
  748. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP