Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:10:51

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