ob_tran.hpp 26 KB

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