Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 08:14:00

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2018-2021 Oracle and/or its affiliates.
0004 // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
0005 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0006 
0007 // Use, modification and distribution is subject to the Boost Software License,
0008 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0009 // http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
0012 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP
0013 
0014 #include <type_traits>
0015 
0016 #include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
0017 #include <boost/geometry/algorithms/envelope.hpp>
0018 
0019 #include <boost/geometry/strategies/distance.hpp>
0020 #include <boost/geometry/strategies/normalize.hpp>
0021 #include <boost/geometry/strategies/spherical/disjoint_box_box.hpp>
0022 #include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
0023 #include <boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp>
0024 #include <boost/geometry/strategies/spherical/point_in_point.hpp>
0025 #include <boost/geometry/strategies/cartesian/point_in_box.hpp> // spherical
0026 #include <boost/geometry/strategies/spherical/ssf.hpp>
0027 
0028 #include <boost/geometry/util/numeric_cast.hpp>
0029 
0030 
0031 namespace boost { namespace geometry
0032 {
0033 
0034 
0035 namespace strategy { namespace distance
0036 {
0037 
0038 struct generic_segment_box
0039 {
0040     template
0041     <
0042             typename LessEqual,
0043             typename ReturnType,
0044             typename SegmentPoint,
0045             typename BoxPoint,
0046             typename Strategies
0047     >
0048     static inline ReturnType segment_below_of_box(
0049             SegmentPoint const& p0,
0050             SegmentPoint const& p1,
0051             BoxPoint const&,
0052             BoxPoint const& top_right,
0053             BoxPoint const& bottom_left,
0054             BoxPoint const& bottom_right,
0055             Strategies const& strategies)
0056     {
0057         ReturnType result;
0058         typename LessEqual::other less_equal;
0059         typedef geometry::model::segment<SegmentPoint> segment_type;
0060         // if cs_tag is spherical_tag check segment's cs_tag with spherical_equatorial_tag as default
0061         typedef std::conditional_t
0062             <
0063                 std::is_same<typename Strategies::cs_tag, spherical_tag>::value,
0064                 std::conditional_t
0065                     <
0066                         std::is_same
0067                             <
0068                                 typename geometry::cs_tag<segment_type>::type,
0069                                 spherical_polar_tag
0070                             >::value,
0071                         spherical_polar_tag, spherical_equatorial_tag
0072                     >,
0073                 typename Strategies::cs_tag
0074             > cs_tag;
0075         typedef geometry::detail::disjoint::
0076                 disjoint_segment_box_sphere_or_spheroid<cs_tag>
0077                 disjoint_sb;
0078         typedef typename disjoint_sb::disjoint_info disjoint_info_type;
0079 
0080         segment_type seg(p0, p1);
0081 
0082         geometry::model::box<BoxPoint> input_box;
0083         geometry::set_from_radian<geometry::min_corner, 0>
0084                 (input_box, geometry::get_as_radian<0>(bottom_left));
0085         geometry::set_from_radian<geometry::min_corner, 1>
0086                 (input_box, geometry::get_as_radian<1>(bottom_left));
0087         geometry::set_from_radian<geometry::max_corner, 0>
0088                 (input_box, geometry::get_as_radian<0>(top_right));
0089         geometry::set_from_radian<geometry::max_corner, 1>
0090                 (input_box, geometry::get_as_radian<1>(top_right));
0091 
0092         SegmentPoint p_max;
0093 
0094         // TODO: Think about rewriting this and simply passing strategies
0095         //       The problem is that this algorithm is called by disjoint(S/B) strategies.
0096         disjoint_info_type disjoint_result = disjoint_sb::
0097                 apply(seg, input_box, p_max,
0098                       strategies.azimuth(),
0099                       strategies.normalize(p0),
0100                       strategies.covered_by(p0, input_box), // disjoint
0101                       strategies.disjoint(input_box, input_box));
0102 
0103         if (disjoint_result == disjoint_info_type::intersect) //intersect
0104         {
0105             return 0;
0106         }
0107         // disjoint but vertex not computed
0108         if (disjoint_result == disjoint_info_type::disjoint_no_vertex)
0109         {
0110             typedef typename coordinate_type<SegmentPoint>::type CT;
0111 
0112             geometry::model::box<SegmentPoint> mbr;
0113             geometry::envelope(seg, mbr, strategies);
0114 
0115             CT lon1 = geometry::get_as_radian<0>(p0);
0116             CT lat1 = geometry::get_as_radian<1>(p0);
0117             CT lon2 = geometry::get_as_radian<0>(p1);
0118             CT lat2 = geometry::get_as_radian<1>(p1);
0119 
0120             if (lon1 > lon2)
0121             {
0122                 std::swap(lon1, lon2);
0123                 std::swap(lat1, lat2);
0124             }
0125 
0126             CT vertex_lat;
0127             CT lat_sum = lat1 + lat2;
0128             if (lat_sum > CT(0))
0129             {
0130                 vertex_lat = geometry::get_as_radian<geometry::max_corner, 1>(mbr);
0131             } else {
0132                 vertex_lat = geometry::get_as_radian<geometry::min_corner, 1>(mbr);
0133             }
0134 
0135             CT alp1;
0136             strategies.azimuth().apply(lon1, lat1, lon2, lat2, alp1);
0137 
0138             // TODO: formula should not call strategy!
0139             CT vertex_lon = geometry::formula::vertex_longitude
0140                     <
0141                         CT,
0142                         cs_tag
0143                     >::apply(lon1, lat1, lon2, lat2,
0144                              vertex_lat, alp1, strategies.azimuth());
0145 
0146             geometry::set_from_radian<0>(p_max, vertex_lon);
0147             geometry::set_from_radian<1>(p_max, vertex_lat);
0148         }
0149         //otherwise disjoint and vertex computed inside disjoint
0150 
0151         if (less_equal(geometry::get_as_radian<0>(bottom_left),
0152                        geometry::get_as_radian<0>(p_max)))
0153         {
0154             result = util::numeric_cast<ReturnType>(
0155                 strategies.distance(bottom_left, seg).apply(bottom_left, p0, p1));
0156         }
0157         else
0158         {
0159             // TODO: The strategy should not call the algorithm like that
0160             result = geometry::detail::distance::segment_to_box_2D
0161                         <
0162                             ReturnType,
0163                             SegmentPoint,
0164                             BoxPoint,
0165                             Strategies
0166                         >::template call_above_of_box
0167                             <
0168                                 typename LessEqual::other
0169                             >(p1, p0, p_max, bottom_right, strategies);
0170         }
0171         return result;
0172     }
0173 
0174     template <typename SPoint, typename BPoint>
0175     static void mirror(SPoint& p0,
0176                        SPoint& p1,
0177                        BPoint& bottom_left,
0178                        BPoint& bottom_right,
0179                        BPoint& top_left,
0180                        BPoint& top_right)
0181     {
0182         //if segment's vertex is the southest point then mirror geometries
0183         if (geometry::get<1>(p0) + geometry::get<1>(p1) < 0)
0184         {
0185             BPoint bl = bottom_left;
0186             BPoint br = bottom_right;
0187             geometry::set<1>(p0, geometry::get<1>(p0) * -1);
0188             geometry::set<1>(p1, geometry::get<1>(p1) * -1);
0189             geometry::set<1>(bottom_left, geometry::get<1>(top_left) * -1);
0190             geometry::set<1>(top_left, geometry::get<1>(bl) * -1);
0191             geometry::set<1>(bottom_right, geometry::get<1>(top_right) * -1);
0192             geometry::set<1>(top_right, geometry::get<1>(br) * -1);
0193         }
0194     }
0195 };
0196 
0197 //===========================================================================
0198 
0199 template
0200 <
0201     typename CalculationType = void,
0202     typename Strategy = haversine<double, CalculationType>
0203 >
0204 struct spherical_segment_box
0205 {
0206     template <typename PointOfSegment, typename PointOfBox>
0207     struct calculation_type
0208         : promote_floating_point
0209           <
0210               typename strategy::distance::services::return_type
0211                   <
0212                       Strategy,
0213                       PointOfSegment,
0214                       PointOfBox
0215                   >::type
0216           >
0217     {};
0218 
0219     typedef spherical_tag cs_tag;
0220 
0221     // constructors
0222 
0223     inline spherical_segment_box()
0224     {}
0225 
0226     explicit inline spherical_segment_box(typename Strategy::radius_type const& r)
0227         : m_strategy(r)
0228     {}
0229 
0230     inline spherical_segment_box(Strategy const& s)
0231         : m_strategy(s)
0232     {}
0233 
0234     typename Strategy::radius_type radius() const
0235     {
0236         return m_strategy.radius();
0237     }
0238 
0239     // methods
0240 
0241     template
0242     <
0243         typename LessEqual, typename ReturnType,
0244         typename SegmentPoint, typename BoxPoint,
0245         typename Strategies
0246     >
0247     inline ReturnType segment_below_of_box(SegmentPoint const& p0,
0248                                            SegmentPoint const& p1,
0249                                            BoxPoint const& top_left,
0250                                            BoxPoint const& top_right,
0251                                            BoxPoint const& bottom_left,
0252                                            BoxPoint const& bottom_right,
0253                                            Strategies const& strategies) const
0254     {
0255         return generic_segment_box::segment_below_of_box
0256                <
0257                     LessEqual,
0258                     ReturnType
0259                >(p0,p1,top_left,top_right,bottom_left,bottom_right,
0260                  strategies);
0261     }
0262 
0263     template <typename SPoint, typename BPoint>
0264     static void mirror(SPoint& p0,
0265                        SPoint& p1,
0266                        BPoint& bottom_left,
0267                        BPoint& bottom_right,
0268                        BPoint& top_left,
0269                        BPoint& top_right)
0270     {
0271 
0272        generic_segment_box::mirror(p0, p1,
0273                                    bottom_left, bottom_right,
0274                                    top_left, top_right);
0275     }
0276 
0277 private:
0278     Strategy m_strategy;
0279 };
0280 
0281 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0282 namespace services
0283 {
0284 
0285 template <typename CalculationType, typename Strategy>
0286 struct tag<spherical_segment_box<CalculationType, Strategy> >
0287 {
0288     typedef strategy_tag_distance_segment_box type;
0289 };
0290 
0291 template <typename CalculationType, typename Strategy, typename PS, typename PB>
0292 struct return_type<spherical_segment_box<CalculationType, Strategy>, PS, PB>
0293     : spherical_segment_box<CalculationType, Strategy>::template calculation_type<PS, PB>
0294 {};
0295 
0296 template <typename CalculationType, typename Strategy>
0297 struct comparable_type<spherical_segment_box<CalculationType, Strategy> >
0298 {
0299     // Define a cartesian_segment_box strategy with its underlying point-segment
0300     // strategy being comparable
0301     typedef spherical_segment_box
0302         <
0303             CalculationType,
0304             typename comparable_type<Strategy>::type
0305         > type;
0306 };
0307 
0308 
0309 template <typename CalculationType, typename Strategy>
0310 struct get_comparable<spherical_segment_box<CalculationType, Strategy> >
0311 {
0312     typedef typename comparable_type
0313         <
0314             spherical_segment_box<CalculationType, Strategy>
0315         >::type comparable_type;
0316 public :
0317     static inline comparable_type apply(spherical_segment_box<CalculationType, Strategy> const& )
0318     {
0319         return comparable_type();
0320     }
0321 };
0322 
0323 template <typename CalculationType, typename Strategy, typename PS, typename PB>
0324 struct result_from_distance<spherical_segment_box<CalculationType, Strategy>, PS, PB>
0325 {
0326 private :
0327     typedef typename return_type<
0328                                     spherical_segment_box
0329                                     <
0330                                         CalculationType,
0331                                         Strategy
0332                                     >,
0333                                     PS,
0334                                     PB
0335                                  >::type return_type;
0336 public :
0337     template <typename T>
0338     static inline return_type apply(spherical_segment_box<CalculationType,
0339                                                           Strategy> const& ,
0340                                     T const& value)
0341     {
0342         Strategy s;
0343         return result_from_distance<Strategy, PS, PB>::apply(s, value);
0344     }
0345 };
0346 
0347 template <typename Segment, typename Box>
0348 struct default_strategy
0349     <
0350         segment_tag, box_tag, Segment, Box,
0351         spherical_equatorial_tag, spherical_equatorial_tag
0352     >
0353 {
0354     typedef spherical_segment_box<> type;
0355 };
0356 
0357 template <typename Box, typename Segment>
0358 struct default_strategy
0359     <
0360         box_tag, segment_tag, Box, Segment,
0361         spherical_equatorial_tag, spherical_equatorial_tag
0362     >
0363 {
0364     typedef typename default_strategy
0365         <
0366             segment_tag, box_tag, Segment, Box,
0367             spherical_equatorial_tag, spherical_equatorial_tag
0368         >::type type;
0369 };
0370 
0371 }
0372 #endif
0373 
0374 }} // namespace strategy::distance
0375 
0376 }} // namespace boost::geometry
0377 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_SEGMENT_BOX_HPP