area_box.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Boost.Geometry
  2. // Copyright (c) 2021, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  4. // Licensed under the Boost Software License version 1.0.
  5. // http://www.boost.org/users/license.html
  6. #ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_BOX_HPP
  7. #define BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_BOX_HPP
  8. #include <boost/geometry/core/coordinate_type.hpp>
  9. #include <boost/geometry/core/coordinate_dimension.hpp>
  10. #include <boost/geometry/core/radian_access.hpp>
  11. #include <boost/geometry/srs/sphere.hpp>
  12. #include <boost/geometry/strategies/spherical/get_radius.hpp>
  13. #include <boost/geometry/strategy/area.hpp>
  14. #include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp>
  15. namespace boost { namespace geometry
  16. {
  17. namespace strategy { namespace area
  18. {
  19. // https://math.stackexchange.com/questions/131735/surface-element-in-spherical-coordinates
  20. // http://www.cs.cmu.edu/afs/cs/academic/class/16823-s16/www/pdfs/appearance-modeling-3.pdf
  21. // https://www.astronomyclub.xyz/celestial-sphere-2/solid-angle-on-the-celestial-sphere.html
  22. // https://mathworld.wolfram.com/SolidAngle.html
  23. // https://en.wikipedia.org/wiki/Spherical_coordinate_system
  24. // Note that the equations used in the above articles are spherical polar coordinates.
  25. // We use spherical equatorial, so the equation is different:
  26. // assume(y_max > y_min);
  27. // assume(x_max > x_min);
  28. // /* because of polar to equatorial conversion */
  29. // sin(%pi / 2 - y);
  30. // O: r ^ 2 * cos(y);
  31. // S: integrate(integrate(O, y, y_min, y_max), x, x_min, x_max);
  32. template
  33. <
  34. typename RadiusTypeOrSphere = double,
  35. typename CalculationType = void
  36. >
  37. class spherical_box
  38. {
  39. typedef typename strategy_detail::get_radius
  40. <
  41. RadiusTypeOrSphere
  42. >::type radius_type;
  43. public:
  44. template <typename Box>
  45. struct result_type
  46. : strategy::area::detail::result_type
  47. <
  48. Box,
  49. CalculationType
  50. >
  51. {};
  52. // For consistency with other strategies the radius is set to 1
  53. inline spherical_box()
  54. : m_radius(1.0)
  55. {}
  56. template <typename RadiusOrSphere>
  57. explicit inline spherical_box(RadiusOrSphere const& radius_or_sphere)
  58. : m_radius(strategy_detail::get_radius
  59. <
  60. RadiusOrSphere
  61. >::apply(radius_or_sphere))
  62. {}
  63. template <typename Box>
  64. inline auto apply(Box const& box) const
  65. {
  66. typedef typename result_type<Box>::type return_type;
  67. return_type x_min = get_as_radian<min_corner, 0>(box); // lon
  68. return_type y_min = get_as_radian<min_corner, 1>(box); // lat
  69. return_type x_max = get_as_radian<max_corner, 0>(box);
  70. return_type y_max = get_as_radian<max_corner, 1>(box);
  71. if (x_min == x_max || y_max == y_min)
  72. {
  73. return return_type(0);
  74. }
  75. math::normalize_spheroidal_box_coordinates<radian>(x_min, y_min, x_max, y_max);
  76. return (x_max - x_min)
  77. * (sin(y_max) - sin(y_min))
  78. * return_type(m_radius * m_radius);
  79. }
  80. srs::sphere<radius_type> model() const
  81. {
  82. return srs::sphere<radius_type>(m_radius);
  83. }
  84. private:
  85. radius_type m_radius;
  86. };
  87. }} // namespace strategy::area
  88. }} // namespace boost::geometry
  89. #endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_BOX_HPP