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