File indexing completed on 2025-01-18 09:36:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
0032
0033
0034
0035
0036
0037
0038
0039
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
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
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
0115 size_t m_crosses_prime_meridian;
0116 };
0117
0118 public :
0119
0120
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
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
0184 template <>
0185 struct default_strategy<spherical_polar_tag>
0186 {
0187 typedef strategy::area::spherical<> type;
0188 };
0189
0190 }
0191
0192 #endif
0193
0194
0195 }}
0196
0197
0198
0199
0200 }}
0201
0202 #endif