Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:35:04

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