ob_tran.hpp 22 KB

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