Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/geometry/srs/projections/proj/ob_tran.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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