123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- #ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_HPP
- #define BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_HPP
- #include <boost/geometry/formulas/area_formulas.hpp>
- #include <boost/geometry/srs/sphere.hpp>
- #include <boost/geometry/strategy/area.hpp>
- #include <boost/geometry/strategies/spherical/get_radius.hpp>
- namespace boost { namespace geometry
- {
- namespace strategy { namespace area
- {
- template
- <
- typename RadiusTypeOrSphere = double,
- typename CalculationType = void
- >
- class spherical
- {
- typedef typename strategy_detail::get_radius
- <
- RadiusTypeOrSphere
- >::type radius_type;
-
- static const bool LongSegment = false;
- public:
- template <typename Geometry>
- struct result_type
- : strategy::area::detail::result_type
- <
- Geometry,
- CalculationType
- >
- {};
- template <typename Geometry>
- class state
- {
- friend class spherical;
- typedef typename result_type<Geometry>::type return_type;
- public:
- inline state()
- : m_sum(0)
- , m_crosses_prime_meridian(0)
- {}
- private:
- template <typename RadiusType>
- inline return_type area(RadiusType const& r) const
- {
- return_type result;
- return_type radius = r;
-
- if(m_crosses_prime_meridian % 2 == 1)
- {
- size_t times_crosses_prime_meridian
- = 1 + (m_crosses_prime_meridian / 2);
- result = return_type(2)
- * geometry::math::pi<return_type>()
- * times_crosses_prime_meridian
- - geometry::math::abs(m_sum);
- if(geometry::math::sign<return_type>(m_sum) == 1)
- {
- result = - result;
- }
- } else {
- result = m_sum;
- }
- result *= radius * radius;
- return result;
- }
- return_type m_sum;
-
- size_t m_crosses_prime_meridian;
- };
- public :
-
- inline spherical()
- : m_radius(1.0)
- {}
- template <typename RadiusOrSphere>
- explicit inline spherical(RadiusOrSphere const& radius_or_sphere)
- : m_radius(strategy_detail::get_radius
- <
- RadiusOrSphere
- >::apply(radius_or_sphere))
- {}
- template <typename PointOfSegment, typename Geometry>
- inline void apply(PointOfSegment const& p1,
- PointOfSegment const& p2,
- state<Geometry>& st) const
- {
- if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
- {
- typedef geometry::formula::area_formulas
- <
- typename result_type<Geometry>::type
- > area_formulas;
- st.m_sum += area_formulas::template spherical<LongSegment>(p1, p2);
-
- if (area_formulas::crosses_prime_meridian(p1, p2))
- {
- st.m_crosses_prime_meridian++;
- }
- }
- }
- template <typename Geometry>
- inline typename result_type<Geometry>::type
- result(state<Geometry> const& st) const
- {
- return st.area(m_radius);
- }
- srs::sphere<radius_type> model() const
- {
- return srs::sphere<radius_type>(m_radius);
- }
- private :
- radius_type m_radius;
- };
- #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
- namespace services
- {
- template <>
- struct default_strategy<spherical_equatorial_tag>
- {
- typedef strategy::area::spherical<> type;
- };
- template <>
- struct default_strategy<spherical_polar_tag>
- {
- typedef strategy::area::spherical<> type;
- };
- }
- #endif
- }}
- }}
- #endif
|