Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Boost.Geometry - gis-projections (based on PROJ4)
0002 
0003 // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
0005 
0006 // This file was modified by Oracle on 2017-2020.
0007 // Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
0008 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle.
0009 
0010 // Use, modification and distribution is subject to the Boost Software License,
0011 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0012 // http://www.boost.org/LICENSE_1_0.txt)
0013 
0014 // This file is converted from PROJ4, http://trac.osgeo.org/proj
0015 // PROJ4 is originally written by Gerald Evenden (then of the USGS)
0016 // PROJ4 is maintained by Frank Warmerdam
0017 // PROJ4 is converted to Boost.Geometry by Barend Gehrels
0018 
0019 // Last updated version of proj: 5.0.0
0020 
0021 // Original copyright notice:
0022 
0023 // Permission is hereby granted, free of charge, to any person obtaining a
0024 // copy of this software and associated documentation files (the "Software"),
0025 // to deal in the Software without restriction, including without limitation
0026 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
0027 // and/or sell copies of the Software, and to permit persons to whom the
0028 // Software is furnished to do so, subject to the following conditions:
0029 
0030 // The above copyright notice and this permission notice shall be included
0031 // in all copies or substantial portions of the Software.
0032 
0033 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0034 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0035 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
0036 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0037 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0038 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
0039 // DEALINGS IN THE SOFTWARE.
0040 
0041 #ifndef BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP
0042 #define BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP
0043 
0044 #include <memory>
0045 #include <type_traits>
0046 
0047 #include <boost/geometry/core/static_assert.hpp>
0048 #include <boost/geometry/srs/projections/impl/aasincos.hpp>
0049 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0050 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0051 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0052 #include <boost/geometry/srs/projections/impl/pj_ell_set.hpp>
0053 #include <boost/geometry/srs/projections/impl/projects.hpp>
0054 #include <boost/geometry/util/math.hpp>
0055 
0056 namespace boost { namespace geometry
0057 {
0058 
0059 namespace projections
0060 {
0061     #ifndef DOXYGEN_NO_DETAIL
0062     namespace detail {
0063 
0064         // fwd declaration needed below
0065         template <typename T>
0066         inline detail::dynamic_wrapper_b<T, projections::parameters<T> >*
0067             create_new(srs::detail::proj4_parameters const& params,
0068                        projections::parameters<T> const& parameters);
0069 
0070         template <typename T>
0071         inline detail::dynamic_wrapper_b<T, projections::parameters<T> >*
0072             create_new(srs::dpar::parameters<T> const& params,
0073                        projections::parameters<T> const& parameters);
0074 
0075     } // namespace detail
0076 
0077     namespace detail { namespace ob_tran
0078     {
0079 
0080             static const double tolerance = 1e-10;
0081 
0082             template <typename Parameters>
0083             inline Parameters o_proj_parameters(srs::detail::proj4_parameters const& params,
0084                                                 Parameters const& par)
0085             {
0086                 /* copy existing header into new */
0087                 Parameters pj = par;
0088 
0089                 /* get name of projection to be translated */
0090                 pj.id = pj_get_param_s(params, "o_proj");
0091                 if (pj.id.is_unknown())
0092                     BOOST_THROW_EXCEPTION( projection_exception(error_no_rotation_proj) );
0093 
0094                 /* avoid endless recursion */
0095                 if( pj.id.name == "ob_tran")
0096                     BOOST_THROW_EXCEPTION( projection_exception(error_failed_to_find_proj) );
0097 
0098                 // Commented out for consistency with Proj4 >= 5.0.0
0099                 /* force spherical earth */
0100                 //pj.one_es = pj.rone_es = 1.;
0101                 //pj.es = pj.e = 0.;
0102 
0103                 return pj;
0104             }
0105 
0106             template <typename T, typename Parameters>
0107             inline Parameters o_proj_parameters(srs::dpar::parameters<T> const& params,
0108                                                 Parameters const& par)
0109             {
0110                 /* copy existing header into new */
0111                 Parameters pj = par;
0112 
0113                 /* get name of projection to be translated */
0114                 typename srs::dpar::parameters<T>::const_iterator
0115                     it = pj_param_find(params, srs::dpar::o_proj);
0116                 if (it != params.end())
0117                     pj.id = static_cast<srs::dpar::value_proj>(it->template get_value<int>());
0118                 else
0119                     BOOST_THROW_EXCEPTION( projection_exception(error_no_rotation_proj) );
0120 
0121                 /* avoid endless recursion */
0122                 if( pj.id.id == srs::dpar::proj_ob_tran)
0123                     BOOST_THROW_EXCEPTION( projection_exception(error_failed_to_find_proj) );
0124 
0125                 // Commented out for consistency with Proj4 >= 5.0.0
0126                 /* force spherical earth */
0127                 //pj.one_es = pj.rone_es = 1.;
0128                 //pj.es = pj.e = 0.;
0129 
0130                 return pj;
0131             }
0132 
0133             template <typename ...Ps, typename Parameters>
0134             inline Parameters o_proj_parameters(srs::spar::parameters<Ps...> const& /*params*/,
0135                                                 Parameters const& par)
0136             {
0137                 /* copy existing header into new */
0138                 Parameters pj = par;
0139 
0140                 /* get name of projection to be translated */
0141                 typedef srs::spar::parameters<Ps...> params_type;
0142                 typedef typename geometry::tuples::find_if
0143                     <
0144                         params_type,
0145                         srs::spar::detail::is_param_t<srs::spar::o_proj>::pred
0146                     >::type o_proj_type;
0147 
0148                 static const bool is_found = geometry::tuples::is_found<o_proj_type>::value;
0149                 BOOST_GEOMETRY_STATIC_ASSERT((is_found),
0150                     "Rotation projection not specified.",
0151                     params_type);
0152 
0153                 typedef typename o_proj_type::type proj_type;
0154                 static const bool is_specialized = srs::spar::detail::proj_traits<proj_type>::is_specialized;
0155                 BOOST_GEOMETRY_STATIC_ASSERT((is_specialized),
0156                     "Rotation projection not specified.",
0157                     params_type);
0158 
0159                 pj.id = srs::spar::detail::proj_traits<proj_type>::id;
0160 
0161                 /* avoid endless recursion */
0162                 static const bool is_non_resursive = ! std::is_same<proj_type, srs::spar::proj_ob_tran>::value;
0163                 BOOST_GEOMETRY_STATIC_ASSERT((is_non_resursive),
0164                     "o_proj parameter can not be set to ob_tran projection.",
0165                     params_type);
0166 
0167                 // Commented out for consistency with Proj4 >= 5.0.0
0168                 /* force spherical earth */
0169                 //pj.one_es = pj.rone_es = 1.;
0170                 //pj.es = pj.e = 0.;
0171 
0172                 return pj;
0173             }
0174 
0175             // TODO: It's possible that the original Parameters could be used
0176             // instead of a copy in link.
0177             // But it's not possible with the current implementation of
0178             // dynamic_wrapper_b always storing params
0179 
0180             template <typename T, typename Parameters>
0181             struct par_ob_tran
0182             {
0183                 template <typename Params>
0184                 par_ob_tran(Params const& params, Parameters const& par)
0185                     : link(projections::detail::create_new(params, o_proj_parameters(params, par)))
0186                 {
0187                     if (! link.get())
0188                         BOOST_THROW_EXCEPTION( projection_exception(error_unknown_projection_id) );
0189                 }
0190 
0191                 inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0192                 {
0193                     link->fwd(link->params(), lp_lon, lp_lat, xy_x, xy_y);
0194                 }
0195 
0196                 inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0197                 {
0198                     link->inv(link->params(), xy_x, xy_y, lp_lon, lp_lat);
0199                 }
0200 
0201                 std::shared_ptr<dynamic_wrapper_b<T, Parameters> > link;
0202                 T lamp;
0203                 T cphip, sphip;
0204             };
0205 
0206             template <typename StaticParameters, typename T, typename Parameters>
0207             struct par_ob_tran_static
0208             {
0209                 // this metafunction handles static error handling
0210                 typedef typename srs::spar::detail::pick_o_proj_tag
0211                     <
0212                         StaticParameters
0213                     >::type o_proj_tag;
0214 
0215                 /* avoid endless recursion */
0216                 static const bool is_o_proj_not_ob_tran = ! std::is_same<o_proj_tag, srs::spar::proj_ob_tran>::value;
0217                 BOOST_GEOMETRY_STATIC_ASSERT((is_o_proj_not_ob_tran),
0218                     "o_proj parameter can not be set to ob_tran projection.",
0219                     StaticParameters);
0220 
0221                 typedef typename projections::detail::static_projection_type
0222                     <
0223                         o_proj_tag,
0224                         // Commented out for consistency with Proj4 >= 5.0.0
0225                         //srs_sphere_tag, // force spherical
0226                         typename projections::detail::static_srs_tag<StaticParameters>::type,
0227                         StaticParameters,
0228                         T,
0229                         Parameters
0230                     >::type projection_type;
0231 
0232                 par_ob_tran_static(StaticParameters const& params, Parameters const& par)
0233                     : link(params, o_proj_parameters(params, par))
0234                 {}
0235 
0236                 inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0237                 {
0238                     link.fwd(link.params(), lp_lon, lp_lat, xy_x, xy_y);
0239                 }
0240 
0241                 inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0242                 {
0243                     link.inv(link.params(), xy_x, xy_y, lp_lon, lp_lat);
0244                 }
0245 
0246                 projection_type link;
0247                 T lamp;
0248                 T cphip, sphip;
0249             };
0250 
0251             template <typename T, typename Par>
0252             inline void o_forward(T lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& proj_parm)
0253             {
0254                 T coslam, sinphi, cosphi;
0255 
0256                 coslam = cos(lp_lon);
0257                 sinphi = sin(lp_lat);
0258                 cosphi = cos(lp_lat);
0259                 lp_lon = adjlon(aatan2(cosphi * sin(lp_lon), proj_parm.sphip * cosphi * coslam +
0260                     proj_parm.cphip * sinphi) + proj_parm.lamp);
0261                 lp_lat = aasin(proj_parm.sphip * sinphi - proj_parm.cphip * cosphi * coslam);
0262 
0263                 proj_parm.fwd(lp_lon, lp_lat, xy_x, xy_y);
0264             }
0265 
0266             template <typename T, typename Par>
0267             inline void o_inverse(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat, Par const& proj_parm)
0268             {
0269                 T coslam, sinphi, cosphi;
0270 
0271                 proj_parm.inv(xy_x, xy_y, lp_lon, lp_lat);
0272                 if (lp_lon != HUGE_VAL) {
0273                     coslam = cos(lp_lon -= proj_parm.lamp);
0274                     sinphi = sin(lp_lat);
0275                     cosphi = cos(lp_lat);
0276                     lp_lat = aasin(proj_parm.sphip * sinphi + proj_parm.cphip * cosphi * coslam);
0277                     lp_lon = aatan2(cosphi * sin(lp_lon), proj_parm.sphip * cosphi * coslam -
0278                         proj_parm.cphip * sinphi);
0279                 }
0280             }
0281 
0282             template <typename T, typename Par>
0283             inline void t_forward(T lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& proj_parm)
0284             {
0285                 T cosphi, coslam;
0286 
0287                 cosphi = cos(lp_lat);
0288                 coslam = cos(lp_lon);
0289                 lp_lon = adjlon(aatan2(cosphi * sin(lp_lon), sin(lp_lat)) + proj_parm.lamp);
0290                 lp_lat = aasin(- cosphi * coslam);
0291 
0292                 proj_parm.fwd(lp_lon, lp_lat, xy_x, xy_y);
0293             }
0294 
0295             template <typename T, typename Par>
0296             inline void t_inverse(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat, Par const& proj_parm)
0297             {
0298                 T cosphi, t;
0299 
0300                 proj_parm.inv(xy_x, xy_y, lp_lon, lp_lat);
0301                 if (lp_lon != HUGE_VAL) {
0302                     cosphi = cos(lp_lat);
0303                     t = lp_lon - proj_parm.lamp;
0304                     lp_lon = aatan2(cosphi * sin(t), - sin(lp_lat));
0305                     lp_lat = aasin(cosphi * cos(t));
0306                 }
0307             }
0308 
0309             // General Oblique Transformation
0310             template <typename T, typename Params, typename Parameters, typename ProjParameters>
0311             inline T setup_ob_tran(Params const& params, Parameters & /*par*/, ProjParameters& proj_parm)
0312             {
0313                 static const T half_pi = detail::half_pi<T>();
0314 
0315                 T phip, alpha;
0316 
0317                 // Commented out for consistency with Proj4 >= 5.0.0
0318                 //par.es = 0.; /* force to spherical */
0319 
0320                 // proj_parm.link should be created at this point
0321 
0322                 if (pj_param_r<srs::spar::o_alpha>(params, "o_alpha", srs::dpar::o_alpha, alpha)) {
0323                     T lamc, phic;
0324 
0325                     lamc    = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lon_c", srs::dpar::o_lon_c);
0326                     phic    = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lat_c", srs::dpar::o_lat_c);
0327                     //alpha   = pj_get_param_r(par.params, "o_alpha");
0328 
0329                     if (fabs(fabs(phic) - half_pi) <= tolerance)
0330                         BOOST_THROW_EXCEPTION( projection_exception(error_lat_0_or_alpha_eq_90) );
0331 
0332                     proj_parm.lamp = lamc + aatan2(-cos(alpha), -sin(alpha) * sin(phic));
0333                     phip = aasin(cos(phic) * sin(alpha));
0334                 } else if (pj_param_r<srs::spar::o_lat_p>(params, "o_lat_p", srs::dpar::o_lat_p, phip)) { /* specified new pole */
0335                     proj_parm.lamp = pj_get_param_r<T, srs::spar::o_lon_p>(params, "o_lon_p", srs::dpar::o_lon_p);
0336                     //phip = pj_param_r(par.params, "o_lat_p");
0337                 } else { /* specified new "equator" points */
0338                     T lam1, lam2, phi1, phi2, con;
0339 
0340                     lam1 = pj_get_param_r<T, srs::spar::o_lon_1>(params, "o_lon_1", srs::dpar::o_lon_1);
0341                     phi1 = pj_get_param_r<T, srs::spar::o_lat_1>(params, "o_lat_1", srs::dpar::o_lat_1);
0342                     lam2 = pj_get_param_r<T, srs::spar::o_lon_2>(params, "o_lon_2", srs::dpar::o_lon_2);
0343                     phi2 = pj_get_param_r<T, srs::spar::o_lat_2>(params, "o_lat_2", srs::dpar::o_lat_2);
0344                     if (fabs(phi1 - phi2) <= tolerance || (con = fabs(phi1)) <= tolerance ||
0345                         fabs(con - half_pi) <= tolerance || fabs(fabs(phi2) - half_pi) <= tolerance)
0346                         BOOST_THROW_EXCEPTION( projection_exception(error_lat_1_or_2_zero_or_90) );
0347 
0348                     proj_parm.lamp = atan2(cos(phi1) * sin(phi2) * cos(lam1) -
0349                         sin(phi1) * cos(phi2) * cos(lam2),
0350                         sin(phi1) * cos(phi2) * sin(lam2) -
0351                         cos(phi1) * sin(phi2) * sin(lam1));
0352                     phip = atan(-cos(proj_parm.lamp - lam1) / tan(phi1));
0353                 }
0354 
0355                 if (fabs(phip) > tolerance) { /* oblique */
0356                     proj_parm.cphip = cos(phip);
0357                     proj_parm.sphip = sin(phip);
0358                 } else { /* transverse */
0359                 }
0360 
0361                 // TODO:
0362                 /* Support some rather speculative test cases, where the rotated projection */
0363                 /* is actually latlong. We do not want scaling in that case... */
0364                 //if (proj_parm.link...mutable_parameters().right==PJ_IO_UNITS_ANGULAR)
0365                 //    par.right = PJ_IO_UNITS_PROJECTED;
0366 
0367                 // return phip to choose model
0368                 return phip;
0369             }
0370 
0371             template <typename T, typename Parameters>
0372             struct base_ob_tran_oblique
0373             {
0374                 par_ob_tran<T, Parameters> m_proj_parm;
0375 
0376                 inline base_ob_tran_oblique(par_ob_tran<T, Parameters> const& proj_parm)
0377                     : m_proj_parm(proj_parm)
0378                 {}
0379 
0380                 // FORWARD(o_forward)  spheroid
0381                 // Project coordinates from geographic (lon, lat) to cartesian (x, y)
0382                 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0383                 {
0384                     // NOTE: Parameters ignored, m_proj_parm.link has a copy
0385                     o_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm);
0386                 }
0387 
0388                 // INVERSE(o_inverse)  spheroid
0389                 // Project coordinates from cartesian (x, y) to geographic (lon, lat)
0390                 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0391                 {
0392                     // NOTE: Parameters ignored, m_proj_parm.link has a copy
0393                     o_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm);
0394                 }
0395 
0396                 static inline std::string get_name()
0397                 {
0398                     return "ob_tran_oblique";
0399                 }
0400 
0401             };
0402 
0403             template <typename T, typename Parameters>
0404             struct base_ob_tran_transverse
0405             {
0406                 par_ob_tran<T, Parameters> m_proj_parm;
0407 
0408                 inline base_ob_tran_transverse(par_ob_tran<T, Parameters> const& proj_parm)
0409                     : m_proj_parm(proj_parm)
0410                 {}
0411 
0412                 // FORWARD(t_forward)  spheroid
0413                 // Project coordinates from geographic (lon, lat) to cartesian (x, y)
0414                 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0415                 {
0416                     // NOTE: Parameters ignored, m_proj_parm.link has a copy
0417                     t_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm);
0418                 }
0419 
0420                 // INVERSE(t_inverse)  spheroid
0421                 // Project coordinates from cartesian (x, y) to geographic (lon, lat)
0422                 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0423                 {
0424                     // NOTE: Parameters ignored, m_proj_parm.link has a copy
0425                     t_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm);
0426                 }
0427 
0428                 static inline std::string get_name()
0429                 {
0430                     return "ob_tran_transverse";
0431                 }
0432 
0433             };
0434 
0435             template <typename StaticParameters, typename T, typename Parameters>
0436             struct base_ob_tran_static
0437             {
0438                 par_ob_tran_static<StaticParameters, T, Parameters> m_proj_parm;
0439                 bool m_is_oblique;
0440 
0441                 inline base_ob_tran_static(StaticParameters const& params, Parameters const& par)
0442                     : m_proj_parm(params, par)
0443                 {}
0444 
0445                 // FORWARD(o_forward)  spheroid
0446                 // Project coordinates from geographic (lon, lat) to cartesian (x, y)
0447                 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0448                 {
0449                     // NOTE: Parameters ignored, m_proj_parm.link has a copy
0450                     if (m_is_oblique) {
0451                         o_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm);
0452                     } else {
0453                         t_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm);
0454                     }
0455                 }
0456 
0457                 // INVERSE(o_inverse)  spheroid
0458                 // Project coordinates from cartesian (x, y) to geographic (lon, lat)
0459                 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0460                 {
0461                     // NOTE: Parameters ignored, m_proj_parm.link has a copy
0462                     if (m_is_oblique) {
0463                         o_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm);
0464                     } else {
0465                         t_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm);
0466                     }
0467                 }
0468 
0469                 static inline std::string get_name()
0470                 {
0471                     return "ob_tran";
0472                 }
0473 
0474             };
0475 
0476     }} // namespace detail::ob_tran
0477     #endif // doxygen
0478 
0479     /*!
0480         \brief General Oblique Transformation projection
0481         \ingroup projections
0482         \tparam Geographic latlong point type
0483         \tparam Cartesian xy point type
0484         \tparam Parameters parameter type
0485         \par Projection characteristics
0486          - Miscellaneous
0487          - Spheroid
0488         \par Projection parameters
0489          - o_proj (string)
0490          - Plus projection parameters
0491          - o_lat_p (degrees)
0492          - o_lon_p (degrees)
0493          - New pole
0494          - o_alpha: Alpha (degrees)
0495          - o_lon_c (degrees)
0496          - o_lat_c (degrees)
0497          - o_lon_1 (degrees)
0498          - o_lat_1: Latitude of first standard parallel (degrees)
0499          - o_lon_2 (degrees)
0500          - o_lat_2: Latitude of second standard parallel (degrees)
0501         \par Example
0502         \image html ex_ob_tran.gif
0503     */
0504     template <typename T, typename Parameters>
0505     struct ob_tran_oblique : public detail::ob_tran::base_ob_tran_oblique<T, Parameters>
0506     {
0507         template <typename Params>
0508         inline ob_tran_oblique(Params const& , Parameters const& ,
0509                                detail::ob_tran::par_ob_tran<T, Parameters> const& proj_parm)
0510             : detail::ob_tran::base_ob_tran_oblique<T, Parameters>(proj_parm)
0511         {
0512             // already done
0513             //detail::ob_tran::setup_ob_tran(this->m_par, this->m_proj_parm);
0514         }
0515     };
0516 
0517     /*!
0518         \brief General Oblique Transformation projection
0519         \ingroup projections
0520         \tparam Geographic latlong point type
0521         \tparam Cartesian xy point type
0522         \tparam Parameters parameter type
0523         \par Projection characteristics
0524          - Miscellaneous
0525          - Spheroid
0526         \par Projection parameters
0527          - o_proj (string)
0528          - Plus projection parameters
0529          - o_lat_p (degrees)
0530          - o_lon_p (degrees)
0531          - New pole
0532          - o_alpha: Alpha (degrees)
0533          - o_lon_c (degrees)
0534          - o_lat_c (degrees)
0535          - o_lon_1 (degrees)
0536          - o_lat_1: Latitude of first standard parallel (degrees)
0537          - o_lon_2 (degrees)
0538          - o_lat_2: Latitude of second standard parallel (degrees)
0539         \par Example
0540         \image html ex_ob_tran.gif
0541     */
0542     template <typename T, typename Parameters>
0543     struct ob_tran_transverse : public detail::ob_tran::base_ob_tran_transverse<T, Parameters>
0544     {
0545         template <typename Params>
0546         inline ob_tran_transverse(Params const& , Parameters const& ,
0547                                   detail::ob_tran::par_ob_tran<T, Parameters> const& proj_parm)
0548             : detail::ob_tran::base_ob_tran_transverse<T, Parameters>(proj_parm)
0549         {
0550             // already done
0551             //detail::ob_tran::setup_ob_tran(this->m_par, this->m_proj_parm);
0552         }
0553     };
0554 
0555     /*!
0556         \brief General Oblique Transformation projection
0557         \ingroup projections
0558         \tparam Geographic latlong point type
0559         \tparam Cartesian xy point type
0560         \tparam Parameters parameter type
0561         \par Projection characteristics
0562          - Miscellaneous
0563          - Spheroid
0564         \par Projection parameters
0565          - o_proj (string)
0566          - Plus projection parameters
0567          - o_lat_p (degrees)
0568          - o_lon_p (degrees)
0569          - New pole
0570          - o_alpha: Alpha (degrees)
0571          - o_lon_c (degrees)
0572          - o_lat_c (degrees)
0573          - o_lon_1 (degrees)
0574          - o_lat_1: Latitude of first standard parallel (degrees)
0575          - o_lon_2 (degrees)
0576          - o_lat_2: Latitude of second standard parallel (degrees)
0577         \par Example
0578         \image html ex_ob_tran.gif
0579     */
0580     template <typename StaticParameters, typename T, typename Parameters>
0581     struct ob_tran_static : public detail::ob_tran::base_ob_tran_static<StaticParameters, T, Parameters>
0582     {
0583         inline ob_tran_static(StaticParameters const& params, Parameters const& par)
0584             : detail::ob_tran::base_ob_tran_static<StaticParameters, T, Parameters>(params, par)
0585         {
0586             T phip = detail::ob_tran::setup_ob_tran<T>(params, par, this->m_proj_parm);
0587             this->m_is_oblique = fabs(phip) > detail::ob_tran::tolerance;
0588         }
0589     };
0590 
0591     #ifndef DOXYGEN_NO_DETAIL
0592     namespace detail
0593     {
0594 
0595         // Static projection
0596         template <typename SP, typename CT, typename P>
0597         struct static_projection_type<srs::spar::proj_ob_tran, srs_sphere_tag, SP, CT, P>
0598         {
0599             typedef static_wrapper_fi<ob_tran_static<SP, CT, P>, P> type;
0600         };
0601         template <typename SP, typename CT, typename P>
0602         struct static_projection_type<srs::spar::proj_ob_tran, srs_spheroid_tag, SP, CT, P>
0603         {
0604             typedef static_wrapper_fi<ob_tran_static<SP, CT, P>, P> type;
0605         };
0606 
0607         // Factory entry(s)
0608         BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_BEGIN(ob_tran_entry)
0609         {
0610             Parameters parameters_copy = parameters;
0611             detail::ob_tran::par_ob_tran<T, Parameters> proj_parm(params, parameters_copy);
0612             T phip = detail::ob_tran::setup_ob_tran<T>(params, parameters_copy, proj_parm);
0613 
0614             if (fabs(phip) > detail::ob_tran::tolerance)
0615                 return new dynamic_wrapper_fi<ob_tran_oblique<T, Parameters>, T, Parameters>(params, parameters_copy, proj_parm);
0616             else
0617                 return new dynamic_wrapper_fi<ob_tran_transverse<T, Parameters>, T, Parameters>(params, parameters_copy, proj_parm);
0618         }
0619         BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END
0620 
0621         BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(ob_tran_init)
0622         {
0623             BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(ob_tran, ob_tran_entry)
0624         }
0625 
0626     } // namespace detail
0627     #endif // doxygen
0628 
0629 } // namespace projections
0630 
0631 }} // namespace boost::geometry
0632 
0633 #endif // BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP
0634