File indexing completed on 2025-11-03 09:23:36
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