Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
0004 
0005 // Copyright (c) 2016-2020 Oracle and/or its affiliates.
0006 // Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
0007 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0008 
0009 // Use, modification and distribution is subject to the Boost Software License,
0010 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0011 // http://www.boost.org/LICENSE_1_0.txt)
0012 
0013 #ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_HPP
0014 #define BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_HPP
0015 
0016 
0017 #include <boost/geometry/formulas/area_formulas.hpp>
0018 #include <boost/geometry/srs/sphere.hpp>
0019 #include <boost/geometry/strategy/area.hpp>
0020 #include <boost/geometry/strategies/spherical/get_radius.hpp>
0021 
0022 
0023 namespace boost { namespace geometry
0024 {
0025 
0026 namespace strategy { namespace area
0027 {
0028 
0029 
0030 /*!
0031 \brief Spherical area calculation
0032 \ingroup strategies
0033 \details Calculates area on the surface of a sphere using the trapezoidal rule
0034 \tparam RadiusTypeOrSphere \tparam_radius_or_sphere
0035 \tparam CalculationType \tparam_calculation
0036 
0037 \qbk{
0038 [heading See also]
0039 [link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
0040 }
0041 */
0042 template
0043 <
0044     typename RadiusTypeOrSphere = double,
0045     typename CalculationType = void
0046 >
0047 class spherical
0048 {
0049     typedef typename strategy_detail::get_radius
0050         <
0051             RadiusTypeOrSphere
0052         >::type radius_type;
0053 
0054     // Enables special handling of long segments
0055     static const bool LongSegment = false;
0056 
0057 public:
0058     template <typename Geometry>
0059     struct result_type
0060         : strategy::area::detail::result_type
0061             <
0062                 Geometry,
0063                 CalculationType
0064             >
0065     {};
0066 
0067     template <typename Geometry>
0068     class state
0069     {
0070         friend class spherical;
0071 
0072         typedef typename result_type<Geometry>::type return_type;
0073 
0074     public:
0075         inline state()
0076             : m_sum(0)
0077             , m_crosses_prime_meridian(0)
0078         {}
0079 
0080     private:
0081         template <typename RadiusType>
0082         inline return_type area(RadiusType const& r) const
0083         {
0084             return_type result;
0085             return_type radius = r;
0086 
0087             // Encircles pole
0088             if(m_crosses_prime_meridian % 2 == 1)
0089             {
0090                 size_t times_crosses_prime_meridian
0091                         = 1 + (m_crosses_prime_meridian / 2);
0092 
0093                 result = return_type(2)
0094                          * geometry::math::pi<return_type>()
0095                          * times_crosses_prime_meridian
0096                          - geometry::math::abs(m_sum);
0097 
0098                 if(geometry::math::sign<return_type>(m_sum) == 1)
0099                 {
0100                     result = - result;
0101                 }
0102 
0103             } else {
0104                 result =  m_sum;
0105             }
0106 
0107             result *= radius * radius;
0108 
0109             return result;
0110         }
0111 
0112         return_type m_sum;
0113 
0114         // Keep track if encircles some pole
0115         size_t m_crosses_prime_meridian;
0116     };
0117 
0118 public :
0119 
0120     // For backward compatibility reasons the radius is set to 1
0121     inline spherical()
0122         : m_radius(1.0)
0123     {}
0124 
0125     template <typename RadiusOrSphere>
0126     explicit inline spherical(RadiusOrSphere const& radius_or_sphere)
0127         : m_radius(strategy_detail::get_radius
0128                     <
0129                         RadiusOrSphere
0130                     >::apply(radius_or_sphere))
0131     {}
0132 
0133     template <typename PointOfSegment, typename Geometry>
0134     inline void apply(PointOfSegment const& p1,
0135                       PointOfSegment const& p2,
0136                       state<Geometry>& st) const
0137     {
0138         if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
0139         {
0140             typedef geometry::formula::area_formulas
0141                 <
0142                     typename result_type<Geometry>::type
0143                 > area_formulas;
0144 
0145             st.m_sum += area_formulas::template spherical<LongSegment>(p1, p2);
0146 
0147             // Keep track whenever a segment crosses the prime meridian
0148             if (area_formulas::crosses_prime_meridian(p1, p2))
0149             {
0150                 st.m_crosses_prime_meridian++;
0151             }
0152         }
0153     }
0154 
0155     template <typename Geometry>
0156     inline typename result_type<Geometry>::type
0157         result(state<Geometry> const& st) const
0158     {
0159         return st.area(m_radius);
0160     }
0161 
0162     srs::sphere<radius_type> model() const
0163     {
0164         return srs::sphere<radius_type>(m_radius);
0165     }
0166 
0167 private :
0168     radius_type m_radius;
0169 };
0170 
0171 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0172 
0173 namespace services
0174 {
0175 
0176 
0177 template <>
0178 struct default_strategy<spherical_equatorial_tag>
0179 {
0180     typedef strategy::area::spherical<> type;
0181 };
0182 
0183 // Note: spherical polar coordinate system requires "get_as_radian_equatorial"
0184 template <>
0185 struct default_strategy<spherical_polar_tag>
0186 {
0187     typedef strategy::area::spherical<> type;
0188 };
0189 
0190 } // namespace services
0191 
0192 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
0193 
0194 
0195 }} // namespace strategy::area
0196 
0197 
0198 
0199 
0200 }} // namespace boost::geometry
0201 
0202 #endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_HPP