1 // Boost.Geometry - gis-projections (based on PROJ4) 2 3 // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. 4 5 // This file was modified by Oracle on 2017, 2018, 2019. 6 // Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. 7 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. 8 9 // Use, modification and distribution is subject to the Boost Software License, 10 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 11 // http://www.boost.org/LICENSE_1_0.txt) 12 13 // This file is converted from PROJ4, http://trac.osgeo.org/proj 14 // PROJ4 is originally written by Gerald Evenden (then of the USGS) 15 // PROJ4 is maintained by Frank Warmerdam 16 // PROJ4 is converted to Boost.Geometry by Barend Gehrels 17 18 // Last updated version of proj: 5.0.0 19 20 // Original copyright notice: 21 22 // Permission is hereby granted, free of charge, to any person obtaining a 23 // copy of this software and associated documentation files (the "Software"), 24 // to deal in the Software without restriction, including without limitation 25 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 26 // and/or sell copies of the Software, and to permit persons to whom the 27 // Software is furnished to do so, subject to the following conditions: 28 29 // The above copyright notice and this permission notice shall be included 30 // in all copies or substantial portions of the Software. 31 32 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 33 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 35 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 37 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 38 // DEALINGS IN THE SOFTWARE. 39 40 #ifndef BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP 41 #define BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP 42 43 #include <boost/geometry/util/math.hpp> 44 #include <boost/shared_ptr.hpp> 45 46 #include <boost/geometry/srs/projections/impl/aasincos.hpp> 47 #include <boost/geometry/srs/projections/impl/base_static.hpp> 48 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> 49 #include <boost/geometry/srs/projections/impl/factory_entry.hpp> 50 #include <boost/geometry/srs/projections/impl/pj_ell_set.hpp> 51 #include <boost/geometry/srs/projections/impl/projects.hpp> 52 53 namespace boost { namespace geometry 54 { 55 56 namespace projections 57 { 58 #ifndef DOXYGEN_NO_DETAIL 59 namespace detail { 60 61 // fwd declaration needed below 62 template <typename T> 63 inline detail::dynamic_wrapper_b<T, projections::parameters<T> >* 64 create_new(srs::detail::proj4_parameters const& params, 65 projections::parameters<T> const& parameters); 66 67 template <typename T> 68 inline detail::dynamic_wrapper_b<T, projections::parameters<T> >* 69 create_new(srs::dpar::parameters<T> const& params, 70 projections::parameters<T> const& parameters); 71 72 } // namespace detail 73 74 namespace detail { namespace ob_tran 75 { 76 77 static const double tolerance = 1e-10; 78 79 template <typename Parameters> o_proj_parameters(srs::detail::proj4_parameters const & params,Parameters const & par)80 inline Parameters o_proj_parameters(srs::detail::proj4_parameters const& params, 81 Parameters const& par) 82 { 83 /* copy existing header into new */ 84 Parameters pj = par; 85 86 /* get name of projection to be translated */ 87 pj.id = pj_get_param_s(params, "o_proj"); 88 if (pj.id.is_unknown()) 89 BOOST_THROW_EXCEPTION( projection_exception(error_no_rotation_proj) ); 90 91 /* avoid endless recursion */ 92 if( pj.id.name == "ob_tran") 93 BOOST_THROW_EXCEPTION( projection_exception(error_failed_to_find_proj) ); 94 95 // Commented out for consistency with Proj4 >= 5.0.0 96 /* force spherical earth */ 97 //pj.one_es = pj.rone_es = 1.; 98 //pj.es = pj.e = 0.; 99 100 return pj; 101 } 102 103 template <typename T, typename Parameters> o_proj_parameters(srs::dpar::parameters<T> const & params,Parameters const & par)104 inline Parameters o_proj_parameters(srs::dpar::parameters<T> const& params, 105 Parameters const& par) 106 { 107 /* copy existing header into new */ 108 Parameters pj = par; 109 110 /* get name of projection to be translated */ 111 typename srs::dpar::parameters<T>::const_iterator 112 it = pj_param_find(params, srs::dpar::o_proj); 113 if (it != params.end()) 114 pj.id = static_cast<srs::dpar::value_proj>(it->template get_value<int>()); 115 else 116 BOOST_THROW_EXCEPTION( projection_exception(error_no_rotation_proj) ); 117 118 /* avoid endless recursion */ 119 if( pj.id.id == srs::dpar::proj_ob_tran) 120 BOOST_THROW_EXCEPTION( projection_exception(error_failed_to_find_proj) ); 121 122 // Commented out for consistency with Proj4 >= 5.0.0 123 /* force spherical earth */ 124 //pj.one_es = pj.rone_es = 1.; 125 //pj.es = pj.e = 0.; 126 127 return pj; 128 } 129 130 template <BOOST_GEOMETRY_PROJECTIONS_DETAIL_TYPENAME_PX, typename Parameters> o_proj_parameters(srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> const &,Parameters const & par)131 inline Parameters o_proj_parameters(srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> const& /*params*/, 132 Parameters const& par) 133 { 134 /* copy existing header into new */ 135 Parameters pj = par; 136 137 /* get name of projection to be translated */ 138 typedef srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> params_type; 139 typedef typename geometry::tuples::find_if 140 < 141 params_type, 142 srs::spar::detail::is_param_t<srs::spar::o_proj>::pred 143 >::type o_proj_type; 144 145 static const bool is_found = geometry::tuples::is_found<o_proj_type>::value; 146 BOOST_MPL_ASSERT_MSG((is_found), NO_ROTATION_PROJ, (params_type)); 147 148 typedef typename o_proj_type::type proj_type; 149 static const bool is_specialized = srs::spar::detail::proj_traits<proj_type>::is_specialized; 150 BOOST_MPL_ASSERT_MSG((is_specialized), NO_ROTATION_PROJ, (params_type)); 151 152 pj.id = srs::spar::detail::proj_traits<proj_type>::id; 153 154 /* avoid endless recursion */ 155 static const bool is_non_resursive = ! boost::is_same<proj_type, srs::spar::proj_ob_tran>::value; 156 BOOST_MPL_ASSERT_MSG((is_non_resursive), INVALID_O_PROJ_PARAMETER, (params_type)); 157 158 // Commented out for consistency with Proj4 >= 5.0.0 159 /* force spherical earth */ 160 //pj.one_es = pj.rone_es = 1.; 161 //pj.es = pj.e = 0.; 162 163 return pj; 164 } 165 166 // TODO: It's possible that the original Parameters could be used 167 // instead of a copy in link. 168 // But it's not possible with the current implementation of 169 // dynamic_wrapper_b always storing params 170 171 template <typename T, typename Parameters> 172 struct par_ob_tran 173 { 174 template <typename Params> par_ob_tranboost::geometry::projections::detail::ob_tran::par_ob_tran175 par_ob_tran(Params const& params, Parameters const& par) 176 : link(projections::detail::create_new(params, o_proj_parameters(params, par))) 177 { 178 if (! link.get()) 179 BOOST_THROW_EXCEPTION( projection_exception(error_unknown_projection_id) ); 180 } 181 fwdboost::geometry::projections::detail::ob_tran::par_ob_tran182 inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const 183 { 184 link->fwd(link->params(), lp_lon, lp_lat, xy_x, xy_y); 185 } 186 invboost::geometry::projections::detail::ob_tran::par_ob_tran187 inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const 188 { 189 link->inv(link->params(), xy_x, xy_y, lp_lon, lp_lat); 190 } 191 192 boost::shared_ptr<dynamic_wrapper_b<T, Parameters> > link; 193 T lamp; 194 T cphip, sphip; 195 }; 196 197 template <typename StaticParameters, typename T, typename Parameters> 198 struct par_ob_tran_static 199 { 200 // this metafunction handles static error handling 201 typedef typename srs::spar::detail::pick_o_proj_tag 202 < 203 StaticParameters 204 >::type o_proj_tag; 205 206 /* avoid endless recursion */ 207 static const bool is_o_proj_not_ob_tran = ! boost::is_same<o_proj_tag, srs::spar::proj_ob_tran>::value; 208 BOOST_MPL_ASSERT_MSG((is_o_proj_not_ob_tran), INVALID_O_PROJ_PARAMETER, (StaticParameters)); 209 210 typedef typename projections::detail::static_projection_type 211 < 212 o_proj_tag, 213 // Commented out for consistency with Proj4 >= 5.0.0 214 //srs_sphere_tag, // force spherical 215 typename projections::detail::static_srs_tag<StaticParameters>::type, 216 StaticParameters, 217 T, 218 Parameters 219 >::type projection_type; 220 par_ob_tran_staticboost::geometry::projections::detail::ob_tran::par_ob_tran_static221 par_ob_tran_static(StaticParameters const& params, Parameters const& par) 222 : link(params, o_proj_parameters(params, par)) 223 {} 224 fwdboost::geometry::projections::detail::ob_tran::par_ob_tran_static225 inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const 226 { 227 link.fwd(link.params(), lp_lon, lp_lat, xy_x, xy_y); 228 } 229 invboost::geometry::projections::detail::ob_tran::par_ob_tran_static230 inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const 231 { 232 link.inv(link.params(), xy_x, xy_y, lp_lon, lp_lat); 233 } 234 235 projection_type link; 236 T lamp; 237 T cphip, sphip; 238 }; 239 240 template <typename T, typename Par> o_forward(T lp_lon,T lp_lat,T & xy_x,T & xy_y,Par const & proj_parm)241 inline void o_forward(T lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& proj_parm) 242 { 243 T coslam, sinphi, cosphi; 244 245 coslam = cos(lp_lon); 246 sinphi = sin(lp_lat); 247 cosphi = cos(lp_lat); 248 lp_lon = adjlon(aatan2(cosphi * sin(lp_lon), proj_parm.sphip * cosphi * coslam + 249 proj_parm.cphip * sinphi) + proj_parm.lamp); 250 lp_lat = aasin(proj_parm.sphip * sinphi - proj_parm.cphip * cosphi * coslam); 251 252 proj_parm.fwd(lp_lon, lp_lat, xy_x, xy_y); 253 } 254 255 template <typename T, typename Par> o_inverse(T const & xy_x,T const & xy_y,T & lp_lon,T & lp_lat,Par const & proj_parm)256 inline void o_inverse(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat, Par const& proj_parm) 257 { 258 T coslam, sinphi, cosphi; 259 260 proj_parm.inv(xy_x, xy_y, lp_lon, lp_lat); 261 if (lp_lon != HUGE_VAL) { 262 coslam = cos(lp_lon -= proj_parm.lamp); 263 sinphi = sin(lp_lat); 264 cosphi = cos(lp_lat); 265 lp_lat = aasin(proj_parm.sphip * sinphi + proj_parm.cphip * cosphi * coslam); 266 lp_lon = aatan2(cosphi * sin(lp_lon), proj_parm.sphip * cosphi * coslam - 267 proj_parm.cphip * sinphi); 268 } 269 } 270 271 template <typename T, typename Par> t_forward(T lp_lon,T lp_lat,T & xy_x,T & xy_y,Par const & proj_parm)272 inline void t_forward(T lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& proj_parm) 273 { 274 T cosphi, coslam; 275 276 cosphi = cos(lp_lat); 277 coslam = cos(lp_lon); 278 lp_lon = adjlon(aatan2(cosphi * sin(lp_lon), sin(lp_lat)) + proj_parm.lamp); 279 lp_lat = aasin(- cosphi * coslam); 280 281 proj_parm.fwd(lp_lon, lp_lat, xy_x, xy_y); 282 } 283 284 template <typename T, typename Par> t_inverse(T const & xy_x,T const & xy_y,T & lp_lon,T & lp_lat,Par const & proj_parm)285 inline void t_inverse(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat, Par const& proj_parm) 286 { 287 T cosphi, t; 288 289 proj_parm.inv(xy_x, xy_y, lp_lon, lp_lat); 290 if (lp_lon != HUGE_VAL) { 291 cosphi = cos(lp_lat); 292 t = lp_lon - proj_parm.lamp; 293 lp_lon = aatan2(cosphi * sin(t), - sin(lp_lat)); 294 lp_lat = aasin(cosphi * cos(t)); 295 } 296 } 297 298 // General Oblique Transformation 299 template <typename T, typename Params, typename Parameters, typename ProjParameters> setup_ob_tran(Params const & params,Parameters &,ProjParameters & proj_parm)300 inline T setup_ob_tran(Params const& params, Parameters & /*par*/, ProjParameters& proj_parm) 301 { 302 static const T half_pi = detail::half_pi<T>(); 303 304 T phip, alpha; 305 306 // Commented out for consistency with Proj4 >= 5.0.0 307 //par.es = 0.; /* force to spherical */ 308 309 // proj_parm.link should be created at this point 310 311 if (pj_param_r<srs::spar::o_alpha>(params, "o_alpha", srs::dpar::o_alpha, alpha)) { 312 T lamc, phic; 313 314 lamc = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lon_c", srs::dpar::o_lon_c); 315 phic = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lat_c", srs::dpar::o_lat_c); 316 //alpha = pj_get_param_r(par.params, "o_alpha"); 317 318 if (fabs(fabs(phic) - half_pi) <= tolerance) 319 BOOST_THROW_EXCEPTION( projection_exception(error_lat_0_or_alpha_eq_90) ); 320 321 proj_parm.lamp = lamc + aatan2(-cos(alpha), -sin(alpha) * sin(phic)); 322 phip = aasin(cos(phic) * sin(alpha)); 323 } else if (pj_param_r<srs::spar::o_lat_p>(params, "o_lat_p", srs::dpar::o_lat_p, phip)) { /* specified new pole */ 324 proj_parm.lamp = pj_get_param_r<T, srs::spar::o_lon_p>(params, "o_lon_p", srs::dpar::o_lon_p); 325 //phip = pj_param_r(par.params, "o_lat_p"); 326 } else { /* specified new "equator" points */ 327 T lam1, lam2, phi1, phi2, con; 328 329 lam1 = pj_get_param_r<T, srs::spar::o_lon_1>(params, "o_lon_1", srs::dpar::o_lon_1); 330 phi1 = pj_get_param_r<T, srs::spar::o_lat_1>(params, "o_lat_1", srs::dpar::o_lat_1); 331 lam2 = pj_get_param_r<T, srs::spar::o_lon_2>(params, "o_lon_2", srs::dpar::o_lon_2); 332 phi2 = pj_get_param_r<T, srs::spar::o_lat_2>(params, "o_lat_2", srs::dpar::o_lat_2); 333 if (fabs(phi1 - phi2) <= tolerance || (con = fabs(phi1)) <= tolerance || 334 fabs(con - half_pi) <= tolerance || fabs(fabs(phi2) - half_pi) <= tolerance) 335 BOOST_THROW_EXCEPTION( projection_exception(error_lat_1_or_2_zero_or_90) ); 336 337 proj_parm.lamp = atan2(cos(phi1) * sin(phi2) * cos(lam1) - 338 sin(phi1) * cos(phi2) * cos(lam2), 339 sin(phi1) * cos(phi2) * sin(lam2) - 340 cos(phi1) * sin(phi2) * sin(lam1)); 341 phip = atan(-cos(proj_parm.lamp - lam1) / tan(phi1)); 342 } 343 344 if (fabs(phip) > tolerance) { /* oblique */ 345 proj_parm.cphip = cos(phip); 346 proj_parm.sphip = sin(phip); 347 } else { /* transverse */ 348 } 349 350 // TODO: 351 /* Support some rather speculative test cases, where the rotated projection */ 352 /* is actually latlong. We do not want scaling in that case... */ 353 //if (proj_parm.link...mutable_parameters().right==PJ_IO_UNITS_ANGULAR) 354 // par.right = PJ_IO_UNITS_PROJECTED; 355 356 // return phip to choose model 357 return phip; 358 } 359 360 template <typename T, typename Parameters> 361 struct base_ob_tran_oblique 362 { 363 par_ob_tran<T, Parameters> m_proj_parm; 364 base_ob_tran_obliqueboost::geometry::projections::detail::ob_tran::base_ob_tran_oblique365 inline base_ob_tran_oblique(par_ob_tran<T, Parameters> const& proj_parm) 366 : m_proj_parm(proj_parm) 367 {} 368 369 // FORWARD(o_forward) spheroid 370 // Project coordinates from geographic (lon, lat) to cartesian (x, y) fwdboost::geometry::projections::detail::ob_tran::base_ob_tran_oblique371 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const 372 { 373 // NOTE: Parameters ignored, m_proj_parm.link has a copy 374 o_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm); 375 } 376 377 // INVERSE(o_inverse) spheroid 378 // Project coordinates from cartesian (x, y) to geographic (lon, lat) invboost::geometry::projections::detail::ob_tran::base_ob_tran_oblique379 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const 380 { 381 // NOTE: Parameters ignored, m_proj_parm.link has a copy 382 o_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm); 383 } 384 get_nameboost::geometry::projections::detail::ob_tran::base_ob_tran_oblique385 static inline std::string get_name() 386 { 387 return "ob_tran_oblique"; 388 } 389 390 }; 391 392 template <typename T, typename Parameters> 393 struct base_ob_tran_transverse 394 { 395 par_ob_tran<T, Parameters> m_proj_parm; 396 base_ob_tran_transverseboost::geometry::projections::detail::ob_tran::base_ob_tran_transverse397 inline base_ob_tran_transverse(par_ob_tran<T, Parameters> const& proj_parm) 398 : m_proj_parm(proj_parm) 399 {} 400 401 // FORWARD(t_forward) spheroid 402 // Project coordinates from geographic (lon, lat) to cartesian (x, y) fwdboost::geometry::projections::detail::ob_tran::base_ob_tran_transverse403 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const 404 { 405 // NOTE: Parameters ignored, m_proj_parm.link has a copy 406 t_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm); 407 } 408 409 // INVERSE(t_inverse) spheroid 410 // Project coordinates from cartesian (x, y) to geographic (lon, lat) invboost::geometry::projections::detail::ob_tran::base_ob_tran_transverse411 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const 412 { 413 // NOTE: Parameters ignored, m_proj_parm.link has a copy 414 t_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm); 415 } 416 get_nameboost::geometry::projections::detail::ob_tran::base_ob_tran_transverse417 static inline std::string get_name() 418 { 419 return "ob_tran_transverse"; 420 } 421 422 }; 423 424 template <typename StaticParameters, typename T, typename Parameters> 425 struct base_ob_tran_static 426 { 427 par_ob_tran_static<StaticParameters, T, Parameters> m_proj_parm; 428 bool m_is_oblique; 429 base_ob_tran_staticboost::geometry::projections::detail::ob_tran::base_ob_tran_static430 inline base_ob_tran_static(StaticParameters const& params, Parameters const& par) 431 : m_proj_parm(params, par) 432 {} 433 434 // FORWARD(o_forward) spheroid 435 // Project coordinates from geographic (lon, lat) to cartesian (x, y) fwdboost::geometry::projections::detail::ob_tran::base_ob_tran_static436 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const 437 { 438 // NOTE: Parameters ignored, m_proj_parm.link has a copy 439 if (m_is_oblique) { 440 o_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm); 441 } else { 442 t_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm); 443 } 444 } 445 446 // INVERSE(o_inverse) spheroid 447 // Project coordinates from cartesian (x, y) to geographic (lon, lat) invboost::geometry::projections::detail::ob_tran::base_ob_tran_static448 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const 449 { 450 // NOTE: Parameters ignored, m_proj_parm.link has a copy 451 if (m_is_oblique) { 452 o_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm); 453 } else { 454 t_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm); 455 } 456 } 457 get_nameboost::geometry::projections::detail::ob_tran::base_ob_tran_static458 static inline std::string get_name() 459 { 460 return "ob_tran"; 461 } 462 463 }; 464 465 }} // namespace detail::ob_tran 466 #endif // doxygen 467 468 /*! 469 \brief General Oblique Transformation projection 470 \ingroup projections 471 \tparam Geographic latlong point type 472 \tparam Cartesian xy point type 473 \tparam Parameters parameter type 474 \par Projection characteristics 475 - Miscellaneous 476 - Spheroid 477 \par Projection parameters 478 - o_proj (string) 479 - Plus projection parameters 480 - o_lat_p (degrees) 481 - o_lon_p (degrees) 482 - New pole 483 - o_alpha: Alpha (degrees) 484 - o_lon_c (degrees) 485 - o_lat_c (degrees) 486 - o_lon_1 (degrees) 487 - o_lat_1: Latitude of first standard parallel (degrees) 488 - o_lon_2 (degrees) 489 - o_lat_2: Latitude of second standard parallel (degrees) 490 \par Example 491 \image html ex_ob_tran.gif 492 */ 493 template <typename T, typename Parameters> 494 struct ob_tran_oblique : public detail::ob_tran::base_ob_tran_oblique<T, Parameters> 495 { 496 template <typename Params> ob_tran_obliqueboost::geometry::projections::ob_tran_oblique497 inline ob_tran_oblique(Params const& , Parameters const& , 498 detail::ob_tran::par_ob_tran<T, Parameters> const& proj_parm) 499 : detail::ob_tran::base_ob_tran_oblique<T, Parameters>(proj_parm) 500 { 501 // already done 502 //detail::ob_tran::setup_ob_tran(this->m_par, this->m_proj_parm); 503 } 504 }; 505 506 /*! 507 \brief General Oblique Transformation projection 508 \ingroup projections 509 \tparam Geographic latlong point type 510 \tparam Cartesian xy point type 511 \tparam Parameters parameter type 512 \par Projection characteristics 513 - Miscellaneous 514 - Spheroid 515 \par Projection parameters 516 - o_proj (string) 517 - Plus projection parameters 518 - o_lat_p (degrees) 519 - o_lon_p (degrees) 520 - New pole 521 - o_alpha: Alpha (degrees) 522 - o_lon_c (degrees) 523 - o_lat_c (degrees) 524 - o_lon_1 (degrees) 525 - o_lat_1: Latitude of first standard parallel (degrees) 526 - o_lon_2 (degrees) 527 - o_lat_2: Latitude of second standard parallel (degrees) 528 \par Example 529 \image html ex_ob_tran.gif 530 */ 531 template <typename T, typename Parameters> 532 struct ob_tran_transverse : public detail::ob_tran::base_ob_tran_transverse<T, Parameters> 533 { 534 template <typename Params> ob_tran_transverseboost::geometry::projections::ob_tran_transverse535 inline ob_tran_transverse(Params const& , Parameters const& , 536 detail::ob_tran::par_ob_tran<T, Parameters> const& proj_parm) 537 : detail::ob_tran::base_ob_tran_transverse<T, Parameters>(proj_parm) 538 { 539 // already done 540 //detail::ob_tran::setup_ob_tran(this->m_par, this->m_proj_parm); 541 } 542 }; 543 544 /*! 545 \brief General Oblique Transformation projection 546 \ingroup projections 547 \tparam Geographic latlong point type 548 \tparam Cartesian xy point type 549 \tparam Parameters parameter type 550 \par Projection characteristics 551 - Miscellaneous 552 - Spheroid 553 \par Projection parameters 554 - o_proj (string) 555 - Plus projection parameters 556 - o_lat_p (degrees) 557 - o_lon_p (degrees) 558 - New pole 559 - o_alpha: Alpha (degrees) 560 - o_lon_c (degrees) 561 - o_lat_c (degrees) 562 - o_lon_1 (degrees) 563 - o_lat_1: Latitude of first standard parallel (degrees) 564 - o_lon_2 (degrees) 565 - o_lat_2: Latitude of second standard parallel (degrees) 566 \par Example 567 \image html ex_ob_tran.gif 568 */ 569 template <typename StaticParameters, typename T, typename Parameters> 570 struct ob_tran_static : public detail::ob_tran::base_ob_tran_static<StaticParameters, T, Parameters> 571 { ob_tran_staticboost::geometry::projections::ob_tran_static572 inline ob_tran_static(StaticParameters const& params, Parameters const& par) 573 : detail::ob_tran::base_ob_tran_static<StaticParameters, T, Parameters>(params, par) 574 { 575 T phip = detail::ob_tran::setup_ob_tran<T>(params, par, this->m_proj_parm); 576 this->m_is_oblique = fabs(phip) > detail::ob_tran::tolerance; 577 } 578 }; 579 580 #ifndef DOXYGEN_NO_DETAIL 581 namespace detail 582 { 583 584 // Static projection 585 template <typename SP, typename CT, typename P> 586 struct static_projection_type<srs::spar::proj_ob_tran, srs_sphere_tag, SP, CT, P> 587 { 588 typedef static_wrapper_fi<ob_tran_static<SP, CT, P>, P> type; 589 }; 590 template <typename SP, typename CT, typename P> 591 struct static_projection_type<srs::spar::proj_ob_tran, srs_spheroid_tag, SP, CT, P> 592 { 593 typedef static_wrapper_fi<ob_tran_static<SP, CT, P>, P> type; 594 }; 595 596 // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_BEGIN(ob_tran_entry)597 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_BEGIN(ob_tran_entry) 598 { 599 Parameters parameters_copy = parameters; 600 detail::ob_tran::par_ob_tran<T, Parameters> proj_parm(params, parameters_copy); 601 T phip = detail::ob_tran::setup_ob_tran<T>(params, parameters_copy, proj_parm); 602 603 if (fabs(phip) > detail::ob_tran::tolerance) 604 return new dynamic_wrapper_fi<ob_tran_oblique<T, Parameters>, T, Parameters>(params, parameters_copy, proj_parm); 605 else 606 return new dynamic_wrapper_fi<ob_tran_transverse<T, Parameters>, T, Parameters>(params, parameters_copy, proj_parm); 607 } 608 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END 609 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(ob_tran_init)610 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(ob_tran_init) 611 { 612 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(ob_tran, ob_tran_entry) 613 } 614 615 } // namespace detail 616 #endif // doxygen 617 618 } // namespace projections 619 620 }} // namespace boost::geometry 621 622 #endif // BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP 623 624