• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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