Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:36:49

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