File indexing completed on 2025-01-18 09:35:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #ifndef BOOST_GEOMETRY_PROJECTIONS_BONNE_HPP
0041 #define BOOST_GEOMETRY_PROJECTIONS_BONNE_HPP
0042
0043 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0044 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0045 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0046 #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp>
0047 #include <boost/geometry/srs/projections/impl/pj_param.hpp>
0048 #include <boost/geometry/srs/projections/impl/projects.hpp>
0049
0050 #include <boost/geometry/util/math.hpp>
0051
0052 #include <boost/math/special_functions/hypot.hpp>
0053
0054 namespace boost { namespace geometry
0055 {
0056
0057 namespace projections
0058 {
0059 #ifndef DOXYGEN_NO_DETAIL
0060 namespace detail { namespace bonne
0061 {
0062
0063 static const double epsilon10 = 1e-10;
0064
0065 template <typename T>
0066 struct par_bonne
0067 {
0068 T phi1;
0069 T cphi1;
0070 T am1;
0071 T m1;
0072 detail::en<T> en;
0073 };
0074
0075 template <typename T, typename Parameters>
0076 struct base_bonne_ellipsoid
0077 {
0078 par_bonne<T> m_proj_parm;
0079
0080
0081
0082 inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0083 {
0084 T rh, E, c;
0085
0086 rh = this->m_proj_parm.am1 + this->m_proj_parm.m1 - pj_mlfn(lp_lat, E = sin(lp_lat), c = cos(lp_lat), this->m_proj_parm.en);
0087 E = c * lp_lon / (rh * sqrt(1. - par.es * E * E));
0088 xy_x = rh * sin(E);
0089 xy_y = this->m_proj_parm.am1 - rh * cos(E);
0090 }
0091
0092
0093
0094 inline void inv(Parameters const& par, T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const
0095 {
0096 static const T half_pi = detail::half_pi<T>();
0097
0098 T s, rh;
0099
0100 rh = boost::math::hypot(xy_x, xy_y = this->m_proj_parm.am1 - xy_y);
0101 lp_lat = pj_inv_mlfn(this->m_proj_parm.am1 + this->m_proj_parm.m1 - rh, par.es, this->m_proj_parm.en);
0102 if ((s = fabs(lp_lat)) < half_pi) {
0103 s = sin(lp_lat);
0104 lp_lon = rh * atan2(xy_x, xy_y) *
0105 sqrt(1. - par.es * s * s) / cos(lp_lat);
0106 } else if (fabs(s - half_pi) <= epsilon10)
0107 lp_lon = 0.;
0108 else
0109 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0110 }
0111
0112 static inline std::string get_name()
0113 {
0114 return "bonne_ellipsoid";
0115 }
0116
0117 };
0118
0119 template <typename T, typename Parameters>
0120 struct base_bonne_spheroid
0121 {
0122 par_bonne<T> m_proj_parm;
0123
0124
0125
0126 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0127 {
0128 T E, rh;
0129
0130 rh = this->m_proj_parm.cphi1 + this->m_proj_parm.phi1 - lp_lat;
0131 if (fabs(rh) > epsilon10) {
0132 xy_x = rh * sin(E = lp_lon * cos(lp_lat) / rh);
0133 xy_y = this->m_proj_parm.cphi1 - rh * cos(E);
0134 } else
0135 xy_x = xy_y = 0.;
0136 }
0137
0138
0139
0140 inline void inv(Parameters const& , T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const
0141 {
0142 static const T half_pi = detail::half_pi<T>();
0143
0144 T rh;
0145
0146 rh = boost::math::hypot(xy_x, xy_y = this->m_proj_parm.cphi1 - xy_y);
0147 lp_lat = this->m_proj_parm.cphi1 + this->m_proj_parm.phi1 - rh;
0148 if (fabs(lp_lat) > half_pi) {
0149 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0150 }
0151 if (fabs(fabs(lp_lat) - half_pi) <= epsilon10)
0152 lp_lon = 0.;
0153 else
0154 lp_lon = rh * atan2(xy_x, xy_y) / cos(lp_lat);
0155 }
0156
0157 static inline std::string get_name()
0158 {
0159 return "bonne_spheroid";
0160 }
0161
0162 };
0163
0164
0165 template <typename Params, typename Parameters, typename T>
0166 inline void setup_bonne(Params const& params, Parameters const& par, par_bonne<T>& proj_parm)
0167 {
0168 static const T half_pi = detail::half_pi<T>();
0169
0170 T c;
0171
0172 proj_parm.phi1 = pj_get_param_r<T, srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1);
0173 if (fabs(proj_parm.phi1) < epsilon10)
0174 BOOST_THROW_EXCEPTION( projection_exception(error_lat1_is_zero) );
0175
0176 if (par.es != 0.0) {
0177 proj_parm.en = pj_enfn<T>(par.es);
0178 proj_parm.m1 = pj_mlfn(proj_parm.phi1, proj_parm.am1 = sin(proj_parm.phi1),
0179 c = cos(proj_parm.phi1), proj_parm.en);
0180 proj_parm.am1 = c / (sqrt(1. - par.es * proj_parm.am1 * proj_parm.am1) * proj_parm.am1);
0181 } else {
0182 if (fabs(proj_parm.phi1) + epsilon10 >= half_pi)
0183 proj_parm.cphi1 = 0.;
0184 else
0185 proj_parm.cphi1 = 1. / tan(proj_parm.phi1);
0186 }
0187 }
0188
0189 }}
0190 #endif
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207 template <typename T, typename Parameters>
0208 struct bonne_ellipsoid : public detail::bonne::base_bonne_ellipsoid<T, Parameters>
0209 {
0210 template <typename Params>
0211 inline bonne_ellipsoid(Params const& params, Parameters const& par)
0212 {
0213 detail::bonne::setup_bonne(params, par, this->m_proj_parm);
0214 }
0215 };
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 template <typename T, typename Parameters>
0233 struct bonne_spheroid : public detail::bonne::base_bonne_spheroid<T, Parameters>
0234 {
0235 template <typename Params>
0236 inline bonne_spheroid(Params const& params, Parameters const& par)
0237 {
0238 detail::bonne::setup_bonne(params, par, this->m_proj_parm);
0239 }
0240 };
0241
0242 #ifndef DOXYGEN_NO_DETAIL
0243 namespace detail
0244 {
0245
0246
0247 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_bonne, bonne_spheroid, bonne_ellipsoid)
0248
0249
0250 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(bonne_entry, bonne_spheroid, bonne_ellipsoid)
0251
0252 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(bonne_init)
0253 {
0254 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(bonne, bonne_entry);
0255 }
0256
0257 }
0258 #endif
0259
0260 }
0261
0262 }}
0263
0264 #endif
0265