Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-16 09:14:54

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
0004 
0005 // This file was modified by Oracle on 2017-2023.
0006 // Modifications copyright (c) 2017-2023, Oracle and/or its affiliates.
0007 
0008 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0009 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0010 
0011 // Use, modification and distribution is subject to the Boost Software License,
0012 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0013 // http://www.boost.org/LICENSE_1_0.txt)
0014 
0015 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP
0016 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP
0017 
0018 
0019 #include <type_traits>
0020 
0021 #include <boost/geometry/core/access.hpp>
0022 #include <boost/geometry/core/coordinate_dimension.hpp>
0023 #include <boost/geometry/core/coordinate_system.hpp>
0024 #include <boost/geometry/core/coordinate_type.hpp>
0025 #include <boost/geometry/core/cs.hpp>
0026 #include <boost/geometry/core/radian_access.hpp>
0027 #include <boost/geometry/core/tags.hpp>
0028 
0029 #include <boost/geometry/strategies/compare.hpp>
0030 
0031 #include <boost/geometry/util/math.hpp>
0032 #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
0033 
0034 
0035 namespace boost { namespace geometry
0036 {
0037 
0038 
0039 namespace strategy { namespace compare
0040 {
0041 
0042 
0043 #ifndef DOXYGEN_NO_DETAIL
0044 namespace detail
0045 {
0046 
0047 template <std::size_t I, typename P>
0048 static inline typename geometry::coordinate_type<P>::type
0049 get(P const& p, std::true_type /*same units*/)
0050 {
0051     return geometry::get<I>(p);
0052 }
0053 
0054 template <std::size_t I, typename P>
0055 static inline typename geometry::coordinate_type<P>::type
0056 get(P const& p, std::false_type /*different units*/)
0057 {
0058     return geometry::get_as_radian<I>(p);
0059 }
0060 
0061 template
0062 <
0063     typename ComparePolicy,
0064     typename EqualsPolicy,
0065     typename Point1,
0066     typename Point2,
0067     std::size_t DimensionCount
0068 >
0069 struct spherical_latitude
0070 {
0071     typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
0072     typedef typename geometry::detail::cs_angular_units<Point1>::type units1_type;
0073     typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
0074     typedef typename geometry::detail::cs_angular_units<Point2>::type units2_type;
0075     typedef std::is_same<units1_type, units2_type> same_units_type;
0076 
0077     template <typename T1, typename T2>
0078     static inline bool apply(Point1 const& left, Point2 const& right,
0079                              T1 const& l1, T2 const& r1)
0080     {
0081         // latitudes equal
0082         if (EqualsPolicy::apply(l1, r1))
0083         {
0084             return compare::detail::compare_loop
0085                 <
0086                     ComparePolicy, EqualsPolicy, 2, DimensionCount
0087                 >::apply(left, right);
0088         }
0089         else
0090         {
0091             return ComparePolicy::apply(l1, r1);
0092         }
0093     }
0094 
0095     static inline bool apply(Point1 const& left, Point2 const& right)
0096     {
0097         coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
0098         coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
0099 
0100         return apply(left, right, l1, r1);
0101     }
0102 };
0103 
0104 template
0105 <
0106     typename ComparePolicy,
0107     typename EqualsPolicy,
0108     typename Point1,
0109     typename Point2
0110 >
0111 struct spherical_latitude<ComparePolicy, EqualsPolicy, Point1, Point2, 1>
0112 {
0113     template <typename T1, typename T2>
0114     static inline bool apply(Point1 const& left, Point2 const& right,
0115                              T1 const& , T2 const& )
0116     {
0117         return apply(left, right);
0118     }
0119 
0120     static inline bool apply(Point1 const& left, Point2 const& right)
0121     {
0122         return compare::detail::compare_loop
0123             <
0124                 ComparePolicy, EqualsPolicy, 1, 1
0125             >::apply(left, right);
0126     }
0127 };
0128 
0129 template
0130 <
0131     typename ComparePolicy,
0132     typename EqualsPolicy,
0133     typename Point1,
0134     typename Point2,
0135     std::size_t DimensionCount
0136 >
0137 struct spherical_longitude
0138 {
0139     typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
0140     typedef typename geometry::detail::cs_angular_units<Point1>::type units1_type;
0141     typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
0142     typedef typename geometry::detail::cs_angular_units<Point2>::type units2_type;
0143     typedef std::is_same<units1_type, units2_type> same_units_type;
0144     typedef std::conditional_t<same_units_type::value, units1_type, geometry::radian> units_type;
0145 
0146     static const bool is_equatorial = ! std::is_same
0147                                         <
0148                                             typename geometry::cs_tag<Point1>::type,
0149                                             geometry::spherical_polar_tag
0150                                         >::value;
0151 
0152     static inline bool are_both_at_antimeridian(coordinate1_type const& l0,
0153                                                 coordinate2_type const& r0,
0154                                                 bool & is_left_at,
0155                                                 bool & is_right_at)
0156     {
0157         is_left_at = math::is_longitude_antimeridian<units_type>(l0);
0158         is_right_at = math::is_longitude_antimeridian<units_type>(r0);
0159         return is_left_at && is_right_at;
0160     }
0161 
0162     static inline bool apply(Point1 const& left, Point2 const& right)
0163     {
0164         // if units are different the coordinates are in radians
0165         coordinate1_type const& l0 = compare::detail::get<0>(left, same_units_type());
0166         coordinate2_type const& r0 = compare::detail::get<0>(right, same_units_type());
0167         coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
0168         coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
0169 
0170         bool is_left_at_antimeridian = false;
0171         bool is_right_at_antimeridian = false;
0172 
0173             // longitudes equal
0174         if (EqualsPolicy::apply(l0, r0)
0175                // both at antimeridian
0176             || are_both_at_antimeridian(l0, r0, is_left_at_antimeridian, is_right_at_antimeridian)
0177                // both at pole
0178             || (EqualsPolicy::apply(l1, r1)
0179                 && math::is_latitude_pole<units_type, is_equatorial>(l1)))
0180         {
0181             return spherical_latitude
0182                 <
0183                     ComparePolicy, EqualsPolicy, Point1, Point2, DimensionCount
0184                 >::apply(left, right, l1, r1);
0185         }
0186         // if left is at antimeridian and right is not at antimeridian
0187         // then left is greater than right
0188         else if (is_left_at_antimeridian)
0189         {
0190             // less/equal_to -> false, greater -> true
0191             return ComparePolicy::apply(1, 0);
0192         }
0193         // if right is at antimeridian and left is not at antimeridian
0194         // then left is lesser than right
0195         else if (is_right_at_antimeridian)
0196         {
0197             // less -> true, equal_to/greater -> false
0198             return ComparePolicy::apply(0, 1);
0199         }
0200         else
0201         {
0202             return ComparePolicy::apply(l0, r0);
0203         }
0204     }
0205 };
0206 
0207 
0208 } // namespace detail
0209 #endif // DOXYGEN_NO_DETAIL
0210 
0211 
0212 /*!
0213 \brief Compare strategy for spherical coordinates
0214 \ingroup strategies
0215 \tparam Point point-type
0216 \tparam Dimension dimension
0217 */
0218 template
0219 <
0220     typename ComparePolicy,
0221     typename EqualsPolicy,
0222     int Dimension = -1
0223 >
0224 struct spherical
0225     : cartesian<ComparePolicy, EqualsPolicy, Dimension>
0226 {};
0227 
0228 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0229 // all dimensions starting from longitude
0230 template <typename ComparePolicy, typename EqualsPolicy>
0231 struct spherical<ComparePolicy, EqualsPolicy, -1>
0232 {
0233     template <typename Point1, typename Point2>
0234     static inline bool apply(Point1 const& left, Point2 const& right)
0235     {
0236         return compare::detail::spherical_longitude
0237             <
0238                 ComparePolicy,
0239                 EqualsPolicy,
0240                 Point1,
0241                 Point2,
0242                 std::conditional_t
0243                     <
0244                         (dimension<Point1>::value < dimension<Point2>::value),
0245                         std::integral_constant<std::size_t, dimension<Point1>::value>,
0246                         std::integral_constant<std::size_t, dimension<Point2>::value>
0247                     >::value
0248             >::apply(left, right);
0249     }
0250 };
0251 
0252 // only longitudes (and latitudes to check poles)
0253 template <typename ComparePolicy, typename EqualsPolicy>
0254 struct spherical<ComparePolicy, EqualsPolicy, 0>
0255 {
0256     template <typename Point1, typename Point2>
0257     static inline bool apply(Point1 const& left, Point2 const& right)
0258     {
0259         return compare::detail::spherical_longitude
0260             <
0261                 ComparePolicy, EqualsPolicy, Point1, Point2, 1
0262             >::apply(left, right);
0263     }
0264 };
0265 
0266 // only latitudes
0267 template <typename ComparePolicy, typename EqualsPolicy>
0268 struct spherical<ComparePolicy, EqualsPolicy, 1>
0269 {
0270     template <typename Point1, typename Point2>
0271     static inline bool apply(Point1 const& left, Point2 const& right)
0272     {
0273         return compare::detail::spherical_latitude
0274             <
0275                 ComparePolicy, EqualsPolicy, Point1, Point2, 2
0276             >::apply(left, right);
0277     }
0278 };
0279 
0280 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0281 
0282 
0283 namespace services
0284 {
0285 
0286 
0287 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0288 struct default_strategy
0289     <
0290         ComparePolicy, EqualsPolicy,
0291         Point1, Point2, Dimension,
0292         spherical_tag, spherical_tag
0293     >
0294 {
0295     typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0296 };
0297 
0298 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0299 struct default_strategy
0300     <
0301         ComparePolicy, EqualsPolicy,
0302         Point1, Point2, Dimension,
0303         spherical_polar_tag, spherical_polar_tag
0304     >
0305 {
0306     typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0307 };
0308 
0309 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0310 struct default_strategy
0311     <
0312         ComparePolicy, EqualsPolicy,
0313         Point1, Point2, Dimension,
0314         spherical_equatorial_tag, spherical_equatorial_tag
0315     >
0316 {
0317     typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0318 };
0319 
0320 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0321 struct default_strategy
0322     <
0323         ComparePolicy, EqualsPolicy,
0324         Point1, Point2, Dimension,
0325         geographic_tag, geographic_tag
0326     >
0327 {
0328     typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0329 };
0330 
0331 
0332 } // namespace services
0333 
0334 
0335 }} // namespace strategy::compare
0336 
0337 
0338 }} // namespace boost::geometry
0339 
0340 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP