File indexing completed on 2025-01-18 09:36:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_AREA_BOX_HPP
0011 #define BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_AREA_BOX_HPP
0012
0013
0014 #include <boost/geometry/core/radian_access.hpp>
0015 #include <boost/geometry/srs/spheroid.hpp>
0016 #include <boost/geometry/strategies/spherical/get_radius.hpp>
0017 #include <boost/geometry/strategy/area.hpp>
0018 #include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp>
0019
0020
0021 namespace boost { namespace geometry
0022 {
0023
0024 namespace strategy { namespace area
0025 {
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 template
0059 <
0060 typename Spheroid = srs::spheroid<double>,
0061 typename CalculationType = void
0062 >
0063 class geographic_box
0064 {
0065 public:
0066 template <typename Box>
0067 struct result_type
0068 : strategy::area::detail::result_type
0069 <
0070 Box,
0071 CalculationType
0072 >
0073 {};
0074
0075 geographic_box() = default;
0076
0077 explicit geographic_box(Spheroid const& spheroid)
0078 : m_spheroid(spheroid)
0079 {}
0080
0081 template <typename Box>
0082 inline auto apply(Box const& box) const
0083 {
0084 typedef typename result_type<Box>::type return_type;
0085
0086 return_type const c0 = 0;
0087
0088 return_type x_min = get_as_radian<min_corner, 0>(box);
0089 return_type y_min = get_as_radian<min_corner, 1>(box);
0090 return_type x_max = get_as_radian<max_corner, 0>(box);
0091 return_type y_max = get_as_radian<max_corner, 1>(box);
0092
0093 math::normalize_spheroidal_box_coordinates<radian>(x_min, y_min, x_max, y_max);
0094
0095 if (x_min == x_max || y_max == y_min)
0096 {
0097 return c0;
0098 }
0099
0100 return_type const e2 = formula::eccentricity_sqr<return_type>(m_spheroid);
0101
0102 return_type const x_diff = x_max - x_min;
0103 return_type const sin_y_min = sin(y_min);
0104 return_type const sin_y_max = sin(y_max);
0105
0106 if (math::equals(e2, c0))
0107 {
0108
0109 return_type const a = get_radius<0>(m_spheroid);
0110 return x_diff * (sin_y_max - sin_y_min) * a * a;
0111 }
0112
0113 return_type const c1 = 1;
0114 return_type const c2 = 2;
0115 return_type const b = get_radius<2>(m_spheroid);
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 return_type const comp0_min = c1 / (c1 - e2 * sin_y_min * sin_y_min);
0146 return_type const comp0_max = c1 / (c1 - e2 * sin_y_max * sin_y_max);
0147
0148
0149 return_type comp1_min = 0, comp1_max = 0;
0150 if (e2 > c0)
0151 {
0152 return_type const e = math::sqrt(e2);
0153 return_type const e_sin_y_min = e * sin_y_min;
0154 return_type const e_sin_y_max = e * sin_y_max;
0155
0156 comp1_min = e_sin_y_min == c0 ? c1 : atanh(e_sin_y_min) / e_sin_y_min;
0157 comp1_max = e_sin_y_max == c0 ? c1 : atanh(e_sin_y_max) / e_sin_y_max;
0158 }
0159 else
0160 {
0161 return_type const ea = math::sqrt(-e2);
0162 return_type const ea_sin_y_min = ea * sin_y_min;
0163 return_type const ea_sin_y_max = ea * sin_y_max;
0164
0165 comp1_min = ea_sin_y_min == c0 ? c1 : atan(ea_sin_y_min) / ea_sin_y_min;
0166 comp1_max = ea_sin_y_max == c0 ? c1 : atan(ea_sin_y_max) / ea_sin_y_max;
0167 }
0168
0169 return_type const comp01_min = sin_y_min * (comp0_min + comp1_min);
0170 return_type const comp01_max = sin_y_max * (comp0_max + comp1_max);
0171
0172 return b * b * x_diff * (comp01_max - comp01_min) / c2;
0173 }
0174
0175 Spheroid model() const
0176 {
0177 return m_spheroid;
0178 }
0179
0180 private:
0181 Spheroid m_spheroid;
0182 };
0183
0184
0185 }}
0186
0187
0188 }}
0189
0190
0191 #endif