Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:36:33

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 geometry::coordinate_type_t<P>
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 geometry::coordinate_type_t<P>
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     using coordinate1_type = geometry::coordinate_type_t<Point1>;
0072     using units1_type = typename geometry::detail::cs_angular_units<Point1>::type;
0073     using coordinate2_type = geometry::coordinate_type_t<Point2>;
0074     using units2_type = typename geometry::detail::cs_angular_units<Point2>::type;
0075     using same_units_type = std::is_same<units1_type, units2_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     using coordinate1_type = geometry::coordinate_type_t<Point1>;
0140     using units1_type = typename geometry::detail::cs_angular_units<Point1>::type;
0141     using coordinate2_type = geometry::coordinate_type_t<Point2>;
0142     using units2_type = typename geometry::detail::cs_angular_units<Point2>::type;
0143     using same_units_type = std::is_same<units1_type, units2_type>;
0144     using units_type = std::conditional_t<same_units_type::value, units1_type, geometry::radian>;
0145 
0146     static const bool is_equatorial = 
0147         ! std::is_same<geometry::cs_tag_t<Point1>, geometry::spherical_polar_tag>::value;
0148 
0149     static inline bool are_both_at_antimeridian(coordinate1_type const& l0,
0150                                                 coordinate2_type const& r0,
0151                                                 bool & is_left_at,
0152                                                 bool & is_right_at)
0153     {
0154         is_left_at = math::is_longitude_antimeridian<units_type>(l0);
0155         is_right_at = math::is_longitude_antimeridian<units_type>(r0);
0156         return is_left_at && is_right_at;
0157     }
0158 
0159     static inline bool apply(Point1 const& left, Point2 const& right)
0160     {
0161         // if units are different the coordinates are in radians
0162         coordinate1_type const& l0 = compare::detail::get<0>(left, same_units_type());
0163         coordinate2_type const& r0 = compare::detail::get<0>(right, same_units_type());
0164         coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
0165         coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
0166 
0167         bool is_left_at_antimeridian = false;
0168         bool is_right_at_antimeridian = false;
0169 
0170             // longitudes equal
0171         if (EqualsPolicy::apply(l0, r0)
0172                // both at antimeridian
0173             || are_both_at_antimeridian(l0, r0, is_left_at_antimeridian, is_right_at_antimeridian)
0174                // both at pole
0175             || (EqualsPolicy::apply(l1, r1)
0176                 && math::is_latitude_pole<units_type, is_equatorial>(l1)))
0177         {
0178             return spherical_latitude
0179                 <
0180                     ComparePolicy, EqualsPolicy, Point1, Point2, DimensionCount
0181                 >::apply(left, right, l1, r1);
0182         }
0183         // if left is at antimeridian and right is not at antimeridian
0184         // then left is greater than right
0185         else if (is_left_at_antimeridian)
0186         {
0187             // less/equal_to -> false, greater -> true
0188             return ComparePolicy::apply(1, 0);
0189         }
0190         // if right is at antimeridian and left is not at antimeridian
0191         // then left is lesser than right
0192         else if (is_right_at_antimeridian)
0193         {
0194             // less -> true, equal_to/greater -> false
0195             return ComparePolicy::apply(0, 1);
0196         }
0197         else
0198         {
0199             return ComparePolicy::apply(l0, r0);
0200         }
0201     }
0202 };
0203 
0204 
0205 } // namespace detail
0206 #endif // DOXYGEN_NO_DETAIL
0207 
0208 
0209 /*!
0210 \brief Compare strategy for spherical coordinates
0211 \ingroup strategies
0212 \tparam Point point-type
0213 \tparam Dimension dimension
0214 */
0215 template
0216 <
0217     typename ComparePolicy,
0218     typename EqualsPolicy,
0219     int Dimension = -1
0220 >
0221 struct spherical
0222     : cartesian<ComparePolicy, EqualsPolicy, Dimension>
0223 {};
0224 
0225 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0226 // all dimensions starting from longitude
0227 template <typename ComparePolicy, typename EqualsPolicy>
0228 struct spherical<ComparePolicy, EqualsPolicy, -1>
0229 {
0230     template <typename Point1, typename Point2>
0231     static inline bool apply(Point1 const& left, Point2 const& right)
0232     {
0233         return compare::detail::spherical_longitude
0234             <
0235                 ComparePolicy,
0236                 EqualsPolicy,
0237                 Point1,
0238                 Point2,
0239                 std::conditional_t
0240                     <
0241                         (dimension<Point1>::value < dimension<Point2>::value),
0242                         std::integral_constant<std::size_t, dimension<Point1>::value>,
0243                         std::integral_constant<std::size_t, dimension<Point2>::value>
0244                     >::value
0245             >::apply(left, right);
0246     }
0247 };
0248 
0249 // only longitudes (and latitudes to check poles)
0250 template <typename ComparePolicy, typename EqualsPolicy>
0251 struct spherical<ComparePolicy, EqualsPolicy, 0>
0252 {
0253     template <typename Point1, typename Point2>
0254     static inline bool apply(Point1 const& left, Point2 const& right)
0255     {
0256         return compare::detail::spherical_longitude
0257             <
0258                 ComparePolicy, EqualsPolicy, Point1, Point2, 1
0259             >::apply(left, right);
0260     }
0261 };
0262 
0263 // only latitudes
0264 template <typename ComparePolicy, typename EqualsPolicy>
0265 struct spherical<ComparePolicy, EqualsPolicy, 1>
0266 {
0267     template <typename Point1, typename Point2>
0268     static inline bool apply(Point1 const& left, Point2 const& right)
0269     {
0270         return compare::detail::spherical_latitude
0271             <
0272                 ComparePolicy, EqualsPolicy, Point1, Point2, 2
0273             >::apply(left, right);
0274     }
0275 };
0276 
0277 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0278 
0279 
0280 namespace services
0281 {
0282 
0283 
0284 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0285 struct default_strategy
0286     <
0287         ComparePolicy, EqualsPolicy,
0288         Point1, Point2, Dimension,
0289         spherical_tag, spherical_tag
0290     >
0291 {
0292     typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0293 };
0294 
0295 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0296 struct default_strategy
0297     <
0298         ComparePolicy, EqualsPolicy,
0299         Point1, Point2, Dimension,
0300         spherical_polar_tag, spherical_polar_tag
0301     >
0302 {
0303     typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0304 };
0305 
0306 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0307 struct default_strategy
0308     <
0309         ComparePolicy, EqualsPolicy,
0310         Point1, Point2, Dimension,
0311         spherical_equatorial_tag, spherical_equatorial_tag
0312     >
0313 {
0314     typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0315 };
0316 
0317 template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
0318 struct default_strategy
0319     <
0320         ComparePolicy, EqualsPolicy,
0321         Point1, Point2, Dimension,
0322         geographic_tag, geographic_tag
0323     >
0324 {
0325     typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
0326 };
0327 
0328 
0329 } // namespace services
0330 
0331 
0332 }} // namespace strategy::compare
0333 
0334 
0335 }} // namespace boost::geometry
0336 
0337 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP