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
0041
0042
0043
0044
0045
0046
0047 #ifndef BOOST_GEOMETRY_PROJECTIONS_AITOFF_HPP
0048 #define BOOST_GEOMETRY_PROJECTIONS_AITOFF_HPP
0049
0050 #include <boost/core/ignore_unused.hpp>
0051
0052 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0053 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0054 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0055 #include <boost/geometry/srs/projections/impl/pj_param.hpp>
0056 #include <boost/geometry/srs/projections/impl/projects.hpp>
0057
0058 #include <boost/geometry/util/math.hpp>
0059
0060 namespace boost { namespace geometry
0061 {
0062
0063 namespace projections
0064 {
0065 #ifndef DOXYGEN_NO_DETAIL
0066 namespace detail { namespace aitoff
0067 {
0068 enum mode_type {
0069 mode_aitoff = 0,
0070 mode_winkel_tripel = 1
0071 };
0072
0073 template <typename T>
0074 struct par_aitoff
0075 {
0076 T cosphi1;
0077 mode_type mode;
0078 };
0079
0080 template <typename T, typename Parameters>
0081 struct base_aitoff_spheroid
0082 {
0083 par_aitoff<T> m_proj_parm;
0084
0085
0086
0087 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0088 {
0089 T c, d;
0090
0091 if((d = acos(cos(lp_lat) * cos(c = 0.5 * lp_lon)))) {
0092 xy_x = 2. * d * cos(lp_lat) * sin(c) * (xy_y = 1. / sin(d));
0093 xy_y *= d * sin(lp_lat);
0094 } else
0095 xy_x = xy_y = 0.;
0096 if (this->m_proj_parm.mode == mode_winkel_tripel) {
0097 xy_x = (xy_x + lp_lon * this->m_proj_parm.cosphi1) * 0.5;
0098 xy_y = (xy_y + lp_lat) * 0.5;
0099 }
0100 }
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0125 {
0126 static const T pi = detail::pi<T>();
0127 static const T two_pi = detail::two_pi<T>();
0128 static const T epsilon = 1e-12;
0129
0130 int iter, max_iter = 10, round = 0, max_round = 20;
0131 T D, C, f1, f2, f1p, f1l, f2p, f2l, dp, dl, sl, sp, cp, cl, x, y;
0132
0133 if ((fabs(xy_x) < epsilon) && (fabs(xy_y) < epsilon )) {
0134 lp_lat = 0.; lp_lon = 0.;
0135 return;
0136 }
0137
0138
0139 lp_lat = xy_y; lp_lon = xy_x;
0140 do {
0141 iter = 0;
0142 do {
0143 sl = sin(lp_lon * 0.5); cl = cos(lp_lon * 0.5);
0144 sp = sin(lp_lat); cp = cos(lp_lat);
0145 D = cp * cl;
0146 C = 1. - D * D;
0147 D = acos(D) / math::pow(C, T(1.5));
0148 f1 = 2. * D * C * cp * sl;
0149 f2 = D * C * sp;
0150 f1p = 2.* (sl * cl * sp * cp / C - D * sp * sl);
0151 f1l = cp * cp * sl * sl / C + D * cp * cl * sp * sp;
0152 f2p = sp * sp * cl / C + D * sl * sl * cp;
0153 f2l = 0.5 * (sp * cp * sl / C - D * sp * cp * cp * sl * cl);
0154 if (this->m_proj_parm.mode == mode_winkel_tripel) {
0155 f1 = 0.5 * (f1 + lp_lon * this->m_proj_parm.cosphi1);
0156 f2 = 0.5 * (f2 + lp_lat);
0157 f1p *= 0.5;
0158 f1l = 0.5 * (f1l + this->m_proj_parm.cosphi1);
0159 f2p = 0.5 * (f2p + 1.);
0160 f2l *= 0.5;
0161 }
0162 f1 -= xy_x; f2 -= xy_y;
0163 dl = (f2 * f1p - f1 * f2p) / (dp = f1p * f2l - f2p * f1l);
0164 dp = (f1 * f2l - f2 * f1l) / dp;
0165 dl = fmod(dl, pi);
0166 lp_lat -= dp; lp_lon -= dl;
0167 } while ((fabs(dp) > epsilon || fabs(dl) > epsilon) && (iter++ < max_iter));
0168 if (lp_lat > two_pi) lp_lat -= 2.*(lp_lat-two_pi);
0169 if (lp_lat < -two_pi) lp_lat -= 2.*(lp_lat+two_pi);
0170 if ((fabs(fabs(lp_lat) - two_pi) < epsilon) && (!this->m_proj_parm.mode)) lp_lon = 0.;
0171
0172
0173 if((D = acos(cos(lp_lat) * cos(C = 0.5 * lp_lon))) != 0.0) {
0174 x = 2. * D * cos(lp_lat) * sin(C) * (y = 1. / sin(D));
0175 y *= D * sin(lp_lat);
0176 } else
0177 x = y = 0.;
0178 if (this->m_proj_parm.mode == mode_winkel_tripel) {
0179 x = (x + lp_lon * this->m_proj_parm.cosphi1) * 0.5;
0180 y = (y + lp_lat) * 0.5;
0181 }
0182
0183 } while (((fabs(xy_x-x) > epsilon) || (fabs(xy_y-y) > epsilon)) && (round++ < max_round));
0184
0185 if (iter == max_iter && round == max_round)
0186 {
0187 BOOST_THROW_EXCEPTION( projection_exception(error_non_convergent) );
0188
0189 }
0190 }
0191
0192 static inline std::string get_name()
0193 {
0194 return "aitoff_spheroid";
0195 }
0196
0197 };
0198
0199 template <typename Parameters>
0200 inline void setup(Parameters& par)
0201 {
0202 par.es = 0.;
0203 }
0204
0205
0206
0207 template <typename Parameters, typename T>
0208 inline void setup_aitoff(Parameters& par, par_aitoff<T>& proj_parm)
0209 {
0210 proj_parm.mode = mode_aitoff;
0211 setup(par);
0212 }
0213
0214
0215 template <typename Params, typename Parameters, typename T>
0216 inline void setup_wintri(Params& params, Parameters& par, par_aitoff<T>& proj_parm)
0217 {
0218 static const T two_div_pi = detail::two_div_pi<T>();
0219
0220 T phi1;
0221
0222 proj_parm.mode = mode_winkel_tripel;
0223 if (pj_param_r<srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1, phi1)) {
0224 if ((proj_parm.cosphi1 = cos(phi1)) == 0.)
0225 BOOST_THROW_EXCEPTION( projection_exception(error_lat_larger_than_90) );
0226 } else
0227 proj_parm.cosphi1 = two_div_pi;
0228 setup(par);
0229 }
0230
0231 }}
0232 #endif
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246 template <typename T, typename Parameters>
0247 struct aitoff_spheroid : public detail::aitoff::base_aitoff_spheroid<T, Parameters>
0248 {
0249 template <typename Params>
0250 inline aitoff_spheroid(Params const& , Parameters & par)
0251 {
0252 detail::aitoff::setup_aitoff(par, this->m_proj_parm);
0253 }
0254 };
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 template <typename T, typename Parameters>
0271 struct wintri_spheroid : public detail::aitoff::base_aitoff_spheroid<T, Parameters>
0272 {
0273 template <typename Params>
0274 inline wintri_spheroid(Params const& params, Parameters & par)
0275 {
0276 detail::aitoff::setup_wintri(params, par, this->m_proj_parm);
0277 }
0278 };
0279
0280 #ifndef DOXYGEN_NO_DETAIL
0281 namespace detail
0282 {
0283
0284
0285 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_aitoff, aitoff_spheroid)
0286 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_wintri, wintri_spheroid)
0287
0288
0289 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(aitoff_entry, aitoff_spheroid)
0290 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(wintri_entry, wintri_spheroid)
0291
0292 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(aitoff_init)
0293 {
0294 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(aitoff, aitoff_entry)
0295 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(wintri, wintri_entry)
0296 }
0297
0298 }
0299 #endif
0300
0301 }
0302
0303 }}
0304
0305 #endif
0306