Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:35:40

0001 // Boost.Geometry - gis-projections (based on PROJ4)
0002 
0003 // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
0004 
0005 // This file was modified by Oracle on 2017, 2018, 2019.
0006 // Modifications copyright (c) 2017-2019, Oracle and/or its affiliates.
0007 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle.
0008 
0009 // Use, modification and distribution is subject to the Boost Software License,
0010 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0011 // http://www.boost.org/LICENSE_1_0.txt)
0012 
0013 // This file is converted from PROJ4, http://trac.osgeo.org/proj
0014 // PROJ4 is originally written by Gerald Evenden (then of the USGS)
0015 // PROJ4 is maintained by Frank Warmerdam
0016 // PROJ4 is converted to Boost.Geometry by Barend Gehrels
0017 
0018 // Last updated version of proj: 5.0.0
0019 
0020 // Original copyright notice:
0021 
0022 // Purpose:  Implementation of the aitoff (Aitoff) and wintri (Winkel Tripel)
0023 //           projections.
0024 // Author:   Gerald Evenden (1995)
0025 //           Drazen Tutic, Lovro Gradiser (2015) - add inverse
0026 //           Thomas Knudsen (2016) - revise/add regression tests
0027 // Copyright (c) 1995, Gerald Evenden
0028 
0029 // Permission is hereby granted, free of charge, to any person obtaining a
0030 // copy of this software and associated documentation files (the "Software"),
0031 // to deal in the Software without restriction, including without limitation
0032 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
0033 // and/or sell copies of the Software, and to permit persons to whom the
0034 // Software is furnished to do so, subject to the following conditions:
0035 
0036 // The above copyright notice and this permission notice shall be included
0037 // in all copies or substantial portions of the Software.
0038 
0039 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0040 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0041 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
0042 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0043 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0044 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
0045 // DEALINGS IN THE SOFTWARE.
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                 // FORWARD(s_forward)  spheroid
0086                 // Project coordinates from geographic (lon, lat) to cartesian (x, y)
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)))) {/* basic Aitoff */
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) { /* 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                 * Inverse functions added by Drazen Tutic and Lovro Gradiser based on paper:
0104                 *
0105                 * I.Özbug Biklirici and Cengizhan Ipbüker. A General Algorithm for the Inverse
0106                 * Transformation of Map Projections Using Jacobian Matrices. In Proceedings of the
0107                 * Third International Symposium Mathematical & Computational Applications,
0108                 * pages 175{182, Turkey, September 2002.
0109                 *
0110                 * Expected accuracy is defined by epsilon = 1e-12. Should be appropriate for
0111                 * most applications of Aitoff and Winkel Tripel projections.
0112                 *
0113                 * Longitudes of 180W and 180E can be mixed in solution obtained.
0114                 *
0115                 * Inverse for Aitoff projection in poles is undefined, longitude value of 0 is assumed.
0116                 *
0117                 * Contact : dtutic@geof.hr
0118                 * Date: 2015-02-16
0119                 *
0120                 ************************************************************************************/
0121 
0122                 // INVERSE(s_inverse)  sphere
0123                 // Project coordinates from cartesian (x, y) to geographic (lon, lat)
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                     /* intial values for Newton-Raphson method */
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) { /* 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); /* set to interval [-M_PI, M_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); /* correct if symmetrical solution for Aitoff */
0169                         if (lp_lat < -two_pi) lp_lat -= 2.*(lp_lat+two_pi); /* correct if symmetrical solution for Aitoff */
0170                         if ((fabs(fabs(lp_lat) - two_pi) < epsilon) && (!this->m_proj_parm.mode)) lp_lon = 0.; /* if pole in Aitoff, return longitude of 0 */
0171 
0172                         /* calculate x,y coordinates with solution obtained */
0173                         if((D = acos(cos(lp_lat) * cos(C = 0.5 * lp_lon))) != 0.0) {/* Aitoff */
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) { /* Winkel Tripel */
0179                             x = (x + lp_lon * this->m_proj_parm.cosphi1) * 0.5;
0180                             y = (y + lp_lat) * 0.5;
0181                         }
0182                     /* if too far from given values of x,y, repeat with better approximation of phi,lam */
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                         //fprintf(stderr, "Warning: Accuracy of 1e-12 not reached. Last increments: dlat=%e and dlon=%e\n", dp, dl);
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             // Aitoff
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             // Winkel Tripel
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 /* 50d28' or phi1=acos(2/pi) */
0227                     proj_parm.cosphi1 = two_div_pi;
0228                 setup(par);
0229             }
0230 
0231     }} // namespace detail::aitoff
0232     #endif // doxygen
0233 
0234     /*!
0235         \brief Aitoff projection
0236         \ingroup projections
0237         \tparam Geographic latlong point type
0238         \tparam Cartesian xy point type
0239         \tparam Parameters parameter type
0240         \par Projection characteristics
0241          - Miscellaneous
0242          - Spheroid
0243         \par Example
0244         \image html ex_aitoff.gif
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         \brief Winkel Tripel projection
0258         \ingroup projections
0259         \tparam Geographic latlong point type
0260         \tparam Cartesian xy point type
0261         \tparam Parameters parameter type
0262         \par Projection characteristics
0263          - Miscellaneous
0264          - Spheroid
0265         \par Projection parameters
0266          - lat_1: Latitude of first standard parallel (degrees)
0267         \par Example
0268         \image html ex_wintri.gif
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         // Static projection
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         // Factory entry(s)
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     } // namespace detail
0299     #endif // doxygen
0300 
0301 } // namespace projections
0302 
0303 }} // namespace boost::geometry
0304 
0305 #endif // BOOST_GEOMETRY_PROJECTIONS_AITOFF_HPP
0306