Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-13 08:34:54

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2023-2024 Adam Wulkiewicz, Lodz, Poland.
0004 
0005 // Copyright (c) 2014-2023 Oracle and/or its affiliates.
0006 
0007 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0008 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0009 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0010 
0011 // Licensed under the Boost Software License version 1.0.
0012 // http://www.boost.org/users/license.html
0013 
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
0016 
0017 #include <cstddef>
0018 #include <functional>
0019 #include <type_traits>
0020 #include <vector>
0021 
0022 #include <boost/core/ignore_unused.hpp>
0023 
0024 #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
0025 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
0026 #include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
0027 #include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
0028 #include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
0029 #include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
0030 #include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
0031 #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
0032 #include <boost/geometry/algorithms/dispatch/distance.hpp>
0033 #include <boost/geometry/algorithms/not_implemented.hpp>
0034 
0035 #include <boost/geometry/core/access.hpp>
0036 #include <boost/geometry/core/assert.hpp>
0037 #include <boost/geometry/core/closure.hpp>
0038 #include <boost/geometry/core/coordinate_dimension.hpp>
0039 #include <boost/geometry/core/point_type.hpp>
0040 #include <boost/geometry/core/tags.hpp>
0041 
0042 #include <boost/geometry/policies/compare.hpp>
0043 
0044 #include <boost/geometry/util/calculation_type.hpp>
0045 #include <boost/geometry/util/constexpr.hpp>
0046 #include <boost/geometry/util/has_nan_coordinate.hpp>
0047 #include <boost/geometry/util/math.hpp>
0048 #include <boost/geometry/util/numeric_cast.hpp>
0049 
0050 #include <boost/geometry/strategies/disjoint.hpp>
0051 #include <boost/geometry/strategies/distance.hpp>
0052 #include <boost/geometry/strategies/tags.hpp>
0053 
0054 namespace boost { namespace geometry
0055 {
0056 
0057 
0058 #ifndef DOXYGEN_NO_DETAIL
0059 namespace detail { namespace distance
0060 {
0061 
0062 
0063 template <typename Segment, typename Box, typename Strategy>
0064 inline bool intersects_segment_box(Segment const& segment, Box const& box,
0065                                    Strategy const& strategy)
0066 {
0067     return ! detail::disjoint::disjoint_segment_box::apply(segment, box, strategy);
0068 }
0069 
0070 // TODO: segment_to_box_2D_generic is not used anymore. Remove?
0071 
0072 // TODO: Furthermore this utility can potentially use different strategy than
0073 //       the one that was passed into bg::distance() but it seems this is by design.
0074 
0075 template
0076 <
0077     typename Segment,
0078     typename Box,
0079     typename Strategies,
0080     bool UsePointBoxStrategy = false // use only PointSegment strategy
0081 >
0082 class segment_to_box_2D_generic
0083 {
0084 private:
0085     using segment_point = point_type_t<Segment>;
0086     using box_point = point_type_t<Box>;
0087     using ps_strategy_type = distance::strategy_t<box_point, Segment, Strategies>;
0088 
0089     using point_to_point_range = detail::closest_feature::point_to_point_range
0090         <
0091             segment_point,
0092             std::vector<box_point>,
0093             open
0094         >;
0095 
0096 public:
0097     // TODO: Or should the return type be defined by sb_strategy_type?
0098     typedef distance::return_t<box_point, Segment, Strategies> return_type;
0099 
0100     static inline return_type apply(Segment const& segment,
0101                                     Box const& box,
0102                                     Strategies const& strategies,
0103                                     bool check_intersection = true)
0104     {
0105         if (check_intersection && intersects_segment_box(segment, box, strategies))
0106         {
0107             return return_type(0);
0108         }
0109 
0110         // get segment points
0111         segment_point p[2];
0112         detail::assign_point_from_index<0>(segment, p[0]);
0113         detail::assign_point_from_index<1>(segment, p[1]);
0114 
0115         // get box points
0116         std::vector<box_point> box_points(4);
0117         detail::assign_box_corners_oriented<true>(box, box_points);
0118 
0119         ps_strategy_type const strategy = strategies.distance(dummy_point(), dummy_segment());
0120 
0121         auto const cstrategy = strategy::distance::services::get_comparable
0122                                 <
0123                                     ps_strategy_type
0124                                 >::apply(strategy);
0125 
0126         distance::creturn_t<box_point, Segment, Strategies> cd[6];
0127         for (unsigned int i = 0; i < 4; ++i)
0128         {
0129             cd[i] = cstrategy.apply(box_points[i], p[0], p[1]);
0130         }
0131 
0132         std::pair
0133             <
0134                 typename std::vector<box_point>::const_iterator,
0135                 typename std::vector<box_point>::const_iterator
0136             > bit_min[2];
0137 
0138         bit_min[0] = point_to_point_range::apply(p[0],
0139                                                  box_points.begin(),
0140                                                  box_points.end(),
0141                                                  cstrategy,
0142                                                  cd[4]);
0143         bit_min[1] = point_to_point_range::apply(p[1],
0144                                                  box_points.begin(),
0145                                                  box_points.end(),
0146                                                  cstrategy,
0147                                                  cd[5]);
0148 
0149         unsigned int imin = 0;
0150         for (unsigned int i = 1; i < 6; ++i)
0151         {
0152             if (cd[i] < cd[imin])
0153             {
0154                 imin = i;
0155             }
0156         }
0157 
0158         if BOOST_GEOMETRY_CONSTEXPR (is_comparable<ps_strategy_type>::value)
0159         {
0160             return cd[imin];
0161         }
0162         else // else prevents unreachable code warning
0163         {
0164             if (imin < 4)
0165             {
0166                 return strategy.apply(box_points[imin], p[0], p[1]);
0167             }
0168             else
0169             {
0170                 unsigned int bimin = imin - 4;
0171                 return strategy.apply(p[bimin],
0172                                       *bit_min[bimin].first,
0173                                       *bit_min[bimin].second);
0174             }
0175         }
0176     }
0177 };
0178 
0179 
0180 template
0181 <
0182     typename Segment,
0183     typename Box,
0184     typename Strategies
0185 >
0186 class segment_to_box_2D_generic<Segment, Box, Strategies, true> // Use both PointSegment and PointBox strategies
0187 {
0188 private:
0189     using segment_point = point_type_t<Segment>;
0190     using box_point = point_type_t<Box>;
0191 
0192     using ps_strategy_type = distance::strategy_t<box_point, Segment, Strategies>;
0193     using pb_strategy_type = distance::strategy_t<segment_point, Box, Strategies>;
0194 
0195 public:
0196     // TODO: Or should the return type be defined by sb_strategy_type?
0197     using return_type = distance::return_t<box_point, Segment, Strategies>;
0198 
0199     static inline return_type apply(Segment const& segment,
0200                                     Box const& box,
0201                                     Strategies const& strategies,
0202                                     bool check_intersection = true)
0203     {
0204         if (check_intersection && intersects_segment_box(segment, box, strategies))
0205         {
0206             return return_type(0);
0207         }
0208 
0209         // get segment points
0210         segment_point p[2];
0211         detail::assign_point_from_index<0>(segment, p[0]);
0212         detail::assign_point_from_index<1>(segment, p[1]);
0213 
0214         // get box points
0215         std::vector<box_point> box_points(4);
0216         detail::assign_box_corners_oriented<true>(box, box_points);
0217 
0218         distance::creturn_t<box_point, Segment, Strategies> cd[6];
0219 
0220         ps_strategy_type ps_strategy = strategies.distance(dummy_point(), dummy_segment());
0221         auto const ps_cstrategy = strategy::distance::services::get_comparable
0222                                     <
0223                                         ps_strategy_type
0224                                     >::apply(ps_strategy);
0225         boost::ignore_unused(ps_strategy, ps_cstrategy);
0226 
0227         for (unsigned int i = 0; i < 4; ++i)
0228         {
0229             cd[i] = ps_cstrategy.apply(box_points[i], p[0], p[1]);
0230         }
0231 
0232         pb_strategy_type const pb_strategy = strategies.distance(dummy_point(), dummy_box());
0233         auto const pb_cstrategy = strategy::distance::services::get_comparable
0234                                     <
0235                                         pb_strategy_type
0236                                     >::apply(pb_strategy);
0237         boost::ignore_unused(pb_strategy, pb_cstrategy);
0238 
0239         cd[4] = pb_cstrategy.apply(p[0], box);
0240         cd[5] = pb_cstrategy.apply(p[1], box);
0241 
0242         unsigned int imin = 0;
0243         for (unsigned int i = 1; i < 6; ++i)
0244         {
0245             if (cd[i] < cd[imin])
0246             {
0247                 imin = i;
0248             }
0249         }
0250 
0251         if (imin < 4)
0252         {
0253             if (is_comparable<ps_strategy_type>::value)
0254             {
0255                 return cd[imin];
0256             }
0257 
0258             return ps_strategy.apply(box_points[imin], p[0], p[1]);
0259         }
0260         else
0261         {
0262             if (is_comparable<pb_strategy_type>::value)
0263             {
0264                 return cd[imin];
0265             }
0266 
0267             return pb_strategy.apply(p[imin - 4], box);
0268         }
0269     }
0270 };
0271 
0272 
0273 
0274 
0275 template
0276 <
0277     typename ReturnType,
0278     typename SegmentPoint,
0279     typename BoxPoint,
0280     typename Strategies
0281 >
0282 class segment_to_box_2D
0283 {
0284 private:
0285     template <typename Result>
0286     struct cast_to_result
0287     {
0288         template <typename T>
0289         static inline Result apply(T const& t)
0290         {
0291             return util::numeric_cast<Result>(t);
0292         }
0293     };
0294 
0295 
0296     template <typename T, bool IsLess /* true */>
0297     struct compare_less_equal
0298     {
0299         typedef compare_less_equal<T, !IsLess> other;
0300 
0301         template <typename T1, typename T2>
0302         inline bool operator()(T1 const& t1, T2 const& t2) const
0303         {
0304             return std::less_equal<T>()(cast_to_result<T>::apply(t1),
0305                                         cast_to_result<T>::apply(t2));
0306         }
0307     };
0308 
0309     template <typename T>
0310     struct compare_less_equal<T, false>
0311     {
0312         typedef compare_less_equal<T, true> other;
0313 
0314         template <typename T1, typename T2>
0315         inline bool operator()(T1 const& t1, T2 const& t2) const
0316         {
0317             return std::greater_equal<T>()(cast_to_result<T>::apply(t1),
0318                                            cast_to_result<T>::apply(t2));
0319         }
0320     };
0321 
0322 
0323     template <typename LessEqual>
0324     struct other_compare
0325     {
0326         typedef typename LessEqual::other type;
0327     };
0328 
0329 
0330     // it is assumed here that p0 lies to the right of the box (so the
0331     // entire segment lies to the right of the box)
0332     template <typename LessEqual>
0333     struct right_of_box
0334     {
0335         static inline ReturnType apply(SegmentPoint const& p0,
0336                                        SegmentPoint const& p1,
0337                                        BoxPoint const& bottom_right,
0338                                        BoxPoint const& top_right,
0339                                        Strategies const& strategies)
0340         {
0341             // the implementation below is written for non-negative slope
0342             // segments
0343             //
0344             // for negative slope segments swap the roles of bottom_right
0345             // and top_right and use greater_equal instead of less_equal.
0346 
0347             typedef cast_to_result<ReturnType> cast;
0348 
0349             LessEqual less_equal;
0350 
0351             auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
0352 
0353             if (less_equal(geometry::get<1>(bottom_right), geometry::get<1>(p0)))
0354             {
0355                 //if p0 is in box's band
0356                 if (less_equal(geometry::get<1>(p0), geometry::get<1>(top_right)))
0357                 {
0358                     // segment & crosses band (TODO:merge with box-box dist)
0359                     if (math::equals(geometry::get<0>(p0), geometry::get<0>(p1)))
0360                     {
0361                         SegmentPoint high = geometry::get<1>(p1) > geometry::get<1>(p0) ? p1 : p0;
0362                         if (less_equal(geometry::get<1>(high), geometry::get<1>(top_right)))
0363                         {
0364                             return cast::apply(ps_strategy.apply(high, bottom_right, top_right));
0365                         }
0366                         return cast::apply(ps_strategy.apply(top_right, p0, p1));
0367                     }
0368                     return cast::apply(ps_strategy.apply(p0, bottom_right, top_right));
0369                 }
0370                 // distance is realized between the top-right
0371                 // corner of the box and the segment
0372                 return cast::apply(ps_strategy.apply(top_right, p0, p1));
0373             }
0374             else
0375             {
0376                 // distance is realized between the bottom-right
0377                 // corner of the box and the segment
0378                 return cast::apply(ps_strategy.apply(bottom_right, p0, p1));
0379             }
0380         }
0381     };
0382 
0383     // it is assumed here that p0 lies above the box (so the
0384     // entire segment lies above the box)
0385 
0386     template <typename LessEqual>
0387     struct above_of_box
0388     {
0389 
0390         static inline ReturnType apply(SegmentPoint const& p0,
0391                                        SegmentPoint const& p1,
0392                                        BoxPoint const& top_left,
0393                                        Strategies const& strategies)
0394         {
0395             return apply(p0, p1, p0, top_left, strategies);
0396         }
0397 
0398         static inline ReturnType apply(SegmentPoint const& p0,
0399                                        SegmentPoint const& p1,
0400                                        SegmentPoint const& p_max,
0401                                        BoxPoint const& top_left,
0402                                        Strategies const& strategies)
0403         {
0404             auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
0405 
0406             typedef cast_to_result<ReturnType> cast;
0407             LessEqual less_equal;
0408 
0409             // p0 is above the upper segment of the box (and inside its band)
0410             // then compute the vertical (i.e. meridian for spherical) distance
0411             if (less_equal(geometry::get<0>(top_left), geometry::get<0>(p_max)))
0412             {
0413                 ReturnType diff = ps_strategy.vertical_or_meridian(
0414                                     geometry::get_as_radian<1>(p_max),
0415                                     geometry::get_as_radian<1>(top_left));
0416 
0417                 return strategy::distance::services::result_from_distance
0418                     <
0419                         std::remove_const_t<decltype(ps_strategy)>,
0420                         SegmentPoint, BoxPoint
0421                     >::apply(ps_strategy, math::abs(diff));
0422             }
0423 
0424             // p0 is to the left of the box, but p1 is above the box
0425             // in this case the distance is realized between the
0426             // top-left corner of the box and the segment
0427             return cast::apply(ps_strategy.apply(top_left, p0, p1));
0428         }
0429     };
0430 
0431     template <typename LessEqual>
0432     struct check_right_left_of_box
0433     {
0434         static inline bool apply(SegmentPoint const& p0,
0435                                  SegmentPoint const& p1,
0436                                  BoxPoint const& top_left,
0437                                  BoxPoint const& top_right,
0438                                  BoxPoint const& bottom_left,
0439                                  BoxPoint const& bottom_right,
0440                                  Strategies const& strategies,
0441                                  ReturnType& result)
0442         {
0443             // p0 lies to the right of the box
0444             if (geometry::get<0>(p0) >= geometry::get<0>(top_right))
0445             {
0446                 result = right_of_box
0447                     <
0448                         LessEqual
0449                     >::apply(p0, p1, bottom_right, top_right,
0450                              strategies);
0451                 return true;
0452             }
0453 
0454             // p1 lies to the left of the box
0455             if (geometry::get<0>(p1) <= geometry::get<0>(bottom_left))
0456             {
0457                 result = right_of_box
0458                     <
0459                         typename other_compare<LessEqual>::type
0460                     >::apply(p1, p0, top_left, bottom_left,
0461                              strategies);
0462                 return true;
0463             }
0464 
0465             return false;
0466         }
0467     };
0468 
0469     template <typename LessEqual>
0470     struct check_above_below_of_box
0471     {
0472         static inline bool apply(SegmentPoint const& p0,
0473                                  SegmentPoint const& p1,
0474                                  BoxPoint const& top_left,
0475                                  BoxPoint const& top_right,
0476                                  BoxPoint const& bottom_left,
0477                                  BoxPoint const& bottom_right,
0478                                  Strategies const& strategies,
0479                                  ReturnType& result)
0480         {
0481             typedef compare_less_equal<ReturnType, false> GreaterEqual;
0482 
0483             // the segment lies below the box
0484             if (geometry::get<1>(p1) < geometry::get<1>(bottom_left))
0485             {
0486                 auto const sb_strategy = strategies.distance(dummy_segment(), dummy_box());
0487 
0488                 // TODO: this strategy calls this algorithm's again, specifically:
0489                 //       geometry::detail::distance::segment_to_box_2D<>::call_above_of_box
0490                 //       If possible rewrite them to avoid this.
0491                 //       For now just pass umbrella strategy.
0492                 result = sb_strategy.template segment_below_of_box
0493                         <
0494                             LessEqual,
0495                             ReturnType
0496                         >(p0, p1,
0497                           top_left, top_right,
0498                           bottom_left, bottom_right,
0499                           strategies);
0500                 return true;
0501             }
0502 
0503             // the segment lies above the box
0504             if (geometry::get<1>(p0) > geometry::get<1>(top_right))
0505             {
0506                 result = (std::min)(above_of_box
0507                                     <
0508                                         LessEqual
0509                                     >::apply(p0, p1, top_left, strategies),
0510                                     above_of_box
0511                                     <
0512                                         GreaterEqual
0513                                     >::apply(p1, p0, top_right, strategies));
0514                 return true;
0515             }
0516             return false;
0517         }
0518     };
0519 
0520     struct check_generic_position
0521     {
0522         static inline bool apply(SegmentPoint const& p0,
0523                                  SegmentPoint const& p1,
0524                                  BoxPoint const& corner1,
0525                                  BoxPoint const& corner2,
0526                                  Strategies const& strategies,
0527                                  ReturnType& result)
0528         {
0529             auto const side_strategy = strategies.side();
0530             auto const ps_strategy = strategies.distance(dummy_point(), dummy_segment());
0531 
0532             typedef cast_to_result<ReturnType> cast;
0533             ReturnType diff1 = cast::apply(geometry::get<1>(p1))
0534                                - cast::apply(geometry::get<1>(p0));
0535 
0536             int sign = diff1 < 0 ? -1 : 1;
0537             if (side_strategy.apply(p0, p1, corner1) * sign < 0)
0538             {
0539                 result = cast::apply(ps_strategy.apply(corner1, p0, p1));
0540                 return true;
0541             }
0542             if (side_strategy.apply(p0, p1, corner2) * sign > 0)
0543             {
0544                 result = cast::apply(ps_strategy.apply(corner2, p0, p1));
0545                 return true;
0546             }
0547             return false;
0548         }
0549     };
0550 
0551     static inline ReturnType
0552     non_negative_slope_segment(SegmentPoint const& p0,
0553                                SegmentPoint const& p1,
0554                                BoxPoint const& top_left,
0555                                BoxPoint const& top_right,
0556                                BoxPoint const& bottom_left,
0557                                BoxPoint const& bottom_right,
0558                                Strategies const& strategies)
0559     {
0560         typedef compare_less_equal<ReturnType, true> less_equal;
0561 
0562         // assert that the segment has non-negative slope
0563         BOOST_GEOMETRY_ASSERT( ( math::equals(geometry::get<0>(p0), geometry::get<0>(p1))
0564                               && geometry::get<1>(p0) < geometry::get<1>(p1))
0565                             ||
0566                                ( geometry::get<0>(p0) < geometry::get<0>(p1)
0567                               && geometry::get<1>(p0) <= geometry::get<1>(p1) )
0568                             || geometry::has_nan_coordinate(p0)
0569                             || geometry::has_nan_coordinate(p1));
0570 
0571         ReturnType result(0);
0572 
0573         if (check_right_left_of_box
0574                 <
0575                     less_equal
0576                 >::apply(p0, p1,
0577                          top_left, top_right, bottom_left, bottom_right,
0578                          strategies, result))
0579         {
0580             return result;
0581         }
0582 
0583         if (check_above_below_of_box
0584                 <
0585                     less_equal
0586                 >::apply(p0, p1,
0587                          top_left, top_right, bottom_left, bottom_right,
0588                          strategies, result))
0589         {
0590             return result;
0591         }
0592 
0593         if (check_generic_position::apply(p0, p1,
0594                                           top_left, bottom_right,
0595                                           strategies, result))
0596         {
0597             return result;
0598         }
0599 
0600         // in all other cases the box and segment intersect, so return 0
0601         return result;
0602     }
0603 
0604 
0605     static inline ReturnType
0606     negative_slope_segment(SegmentPoint const& p0,
0607                            SegmentPoint const& p1,
0608                            BoxPoint const& top_left,
0609                            BoxPoint const& top_right,
0610                            BoxPoint const& bottom_left,
0611                            BoxPoint const& bottom_right,
0612                            Strategies const& strategies)
0613     {
0614         typedef compare_less_equal<ReturnType, false> greater_equal;
0615 
0616         // assert that the segment has negative slope
0617         BOOST_GEOMETRY_ASSERT( ( geometry::get<0>(p0) < geometry::get<0>(p1)
0618                               && geometry::get<1>(p0) > geometry::get<1>(p1) )
0619                             || geometry::has_nan_coordinate(p0)
0620                             || geometry::has_nan_coordinate(p1) );
0621 
0622         ReturnType result(0);
0623 
0624         if (check_right_left_of_box
0625                 <
0626                     greater_equal
0627                 >::apply(p0, p1,
0628                          bottom_left, bottom_right, top_left, top_right,
0629                          strategies, result))
0630         {
0631             return result;
0632         }
0633 
0634         if (check_above_below_of_box
0635                 <
0636                     greater_equal
0637                 >::apply(p1, p0,
0638                          top_right, top_left, bottom_right, bottom_left,
0639                          strategies, result))
0640         {
0641             return result;
0642         }
0643 
0644         if (check_generic_position::apply(p0, p1,
0645                                           bottom_left, top_right,
0646                                           strategies, result))
0647         {
0648             return result;
0649         }
0650 
0651         // in all other cases the box and segment intersect, so return 0
0652         return result;
0653     }
0654 
0655 public:
0656     static inline ReturnType apply(SegmentPoint const& p0,
0657                                    SegmentPoint const& p1,
0658                                    BoxPoint const& top_left,
0659                                    BoxPoint const& top_right,
0660                                    BoxPoint const& bottom_left,
0661                                    BoxPoint const& bottom_right,
0662                                    Strategies const& strategies)
0663     {
0664         BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, Strategies>()(p0, p1))
0665                             || geometry::has_nan_coordinate(p0)
0666                             || geometry::has_nan_coordinate(p1) );
0667 
0668         if (geometry::get<0>(p0) < geometry::get<0>(p1)
0669             && geometry::get<1>(p0) > geometry::get<1>(p1))
0670         {
0671             return negative_slope_segment(p0, p1,
0672                                           top_left, top_right,
0673                                           bottom_left, bottom_right,
0674                                           strategies);
0675         }
0676 
0677         return non_negative_slope_segment(p0, p1,
0678                                           top_left, top_right,
0679                                           bottom_left, bottom_right,
0680                                           strategies);
0681     }
0682 
0683     template <typename LessEqual>
0684     static inline ReturnType call_above_of_box(SegmentPoint const& p0,
0685                                                SegmentPoint const& p1,
0686                                                SegmentPoint const& p_max,
0687                                                BoxPoint const& top_left,
0688                                                Strategies const& strategies)
0689     {
0690         return above_of_box<LessEqual>::apply(p0, p1, p_max, top_left, strategies);
0691     }
0692 
0693     template <typename LessEqual>
0694     static inline ReturnType call_above_of_box(SegmentPoint const& p0,
0695                                                SegmentPoint const& p1,
0696                                                BoxPoint const& top_left,
0697                                                Strategies const& strategies)
0698     {
0699         return above_of_box<LessEqual>::apply(p0, p1, top_left, strategies);
0700     }
0701 };
0702 
0703 //=========================================================================
0704 
0705 template
0706 <
0707     typename Segment,
0708     typename Box,
0709     typename std::size_t Dimension,
0710     typename Strategies
0711 >
0712 class segment_to_box
0713     : not_implemented<Segment, Box>
0714 {};
0715 
0716 
0717 template
0718 <
0719     typename Segment,
0720     typename Box,
0721     typename Strategies
0722 >
0723 class segment_to_box<Segment, Box, 2, Strategies>
0724 {
0725     typedef distance::strategy_t<Segment, Box, Strategies> strategy_type;
0726 
0727 public:
0728     typedef distance::return_t<Segment, Box, Strategies> return_type;
0729 
0730     static inline return_type apply(Segment const& segment,
0731                                     Box const& box,
0732                                     Strategies const& strategies)
0733     {
0734         using segment_point = point_type_t<Segment>;
0735         using box_point = point_type_t<Box>;
0736 
0737         segment_point p[2];
0738         detail::assign_point_from_index<0>(segment, p[0]);
0739         detail::assign_point_from_index<1>(segment, p[1]);
0740 
0741         if (detail::equals::equals_point_point(p[0], p[1], strategies))
0742         {
0743             return dispatch::distance
0744                 <
0745                     segment_point,
0746                     Box,
0747                     Strategies
0748                 >::apply(p[0], box, strategies);
0749         }
0750 
0751         box_point top_left, top_right, bottom_left, bottom_right;
0752         detail::assign_box_corners(box, bottom_left, bottom_right,
0753                                    top_left, top_right);
0754 
0755         strategy_type::mirror(p[0], p[1],
0756                               bottom_left, bottom_right,
0757                               top_left, top_right);
0758 
0759         typedef geometry::less<segment_point, -1, Strategies> less_type;
0760         if (less_type()(p[0], p[1]))
0761         {
0762             return segment_to_box_2D
0763                 <
0764                     return_type,
0765                     segment_point,
0766                     box_point,
0767                     Strategies
0768                 >::apply(p[0], p[1],
0769                          top_left, top_right, bottom_left, bottom_right,
0770                          strategies);
0771         }
0772         else
0773         {
0774             return segment_to_box_2D
0775                 <
0776                     return_type,
0777                     segment_point,
0778                     box_point,
0779                     Strategies
0780                 >::apply(p[1], p[0],
0781                          top_left, top_right, bottom_left, bottom_right,
0782                          strategies);
0783         }
0784     }
0785 };
0786 
0787 
0788 }} // namespace detail::distance
0789 #endif // DOXYGEN_NO_DETAIL
0790 
0791 
0792 #ifndef DOXYGEN_NO_DISPATCH
0793 namespace dispatch
0794 {
0795 
0796 
0797 template <typename Segment, typename Box, typename Strategies>
0798 struct distance
0799     <
0800         Segment, Box, Strategies, segment_tag, box_tag,
0801         strategy_tag_distance_segment_box, false
0802     >
0803 {
0804     static inline auto apply(Segment const& segment, Box const& box,
0805                              Strategies const& strategies)
0806     {
0807         assert_dimension_equal<Segment, Box>();
0808 
0809         return detail::distance::segment_to_box
0810             <
0811                 Segment,
0812                 Box,
0813                 dimension<Segment>::value,
0814                 Strategies
0815             >::apply(segment, box, strategies);
0816     }
0817 };
0818 
0819 
0820 
0821 } // namespace dispatch
0822 #endif // DOXYGEN_NO_DISPATCH
0823 
0824 
0825 }} // namespace boost::geometry
0826 
0827 
0828 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP