]>
Commit | Line | Data |
---|---|---|
92f5a8d4 | 1 | // Boost.Geometry - gis-projections (based on PROJ4) |
11fdf7f2 TL |
2 | |
3 | // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | ||
20effc67 TL |
5 | // This file was modified by Oracle on 2017-2020. |
6 | // Modifications copyright (c) 2017-2020, Oracle and/or its affiliates. | |
11fdf7f2 TL |
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 | ||
92f5a8d4 | 18 | // Last updated version of proj: 5.0.0 |
11fdf7f2 TL |
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 | ||
92f5a8d4 TL |
40 | #ifndef BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP |
41 | #define BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP | |
42 | ||
20effc67 TL |
43 | #include <type_traits> |
44 | ||
11fdf7f2 TL |
45 | #include <boost/geometry/util/math.hpp> |
46 | #include <boost/shared_ptr.hpp> | |
47 | ||
20effc67 TL |
48 | #include <boost/geometry/core/static_assert.hpp> |
49 | ||
92f5a8d4 | 50 | #include <boost/geometry/srs/projections/impl/aasincos.hpp> |
11fdf7f2 TL |
51 | #include <boost/geometry/srs/projections/impl/base_static.hpp> |
52 | #include <boost/geometry/srs/projections/impl/base_dynamic.hpp> | |
11fdf7f2 | 53 | #include <boost/geometry/srs/projections/impl/factory_entry.hpp> |
92f5a8d4 TL |
54 | #include <boost/geometry/srs/projections/impl/pj_ell_set.hpp> |
55 | #include <boost/geometry/srs/projections/impl/projects.hpp> | |
11fdf7f2 TL |
56 | |
57 | namespace boost { namespace geometry | |
58 | { | |
59 | ||
11fdf7f2 TL |
60 | namespace projections |
61 | { | |
62 | #ifndef DOXYGEN_NO_DETAIL | |
63 | namespace detail { | |
64 | ||
65 | // fwd declaration needed below | |
92f5a8d4 TL |
66 | template <typename T> |
67 | inline detail::dynamic_wrapper_b<T, projections::parameters<T> >* | |
68 | create_new(srs::detail::proj4_parameters const& params, | |
69 | projections::parameters<T> const& parameters); | |
70 | ||
71 | template <typename T> | |
72 | inline detail::dynamic_wrapper_b<T, projections::parameters<T> >* | |
73 | create_new(srs::dpar::parameters<T> const& params, | |
74 | projections::parameters<T> const& parameters); | |
11fdf7f2 TL |
75 | |
76 | } // namespace detail | |
77 | ||
78 | namespace detail { namespace ob_tran | |
79 | { | |
80 | ||
92f5a8d4 | 81 | static const double tolerance = 1e-10; |
11fdf7f2 TL |
82 | |
83 | template <typename Parameters> | |
92f5a8d4 TL |
84 | inline Parameters o_proj_parameters(srs::detail::proj4_parameters const& params, |
85 | Parameters const& par) | |
11fdf7f2 | 86 | { |
92f5a8d4 TL |
87 | /* copy existing header into new */ |
88 | Parameters pj = par; | |
11fdf7f2 TL |
89 | |
90 | /* get name of projection to be translated */ | |
92f5a8d4 TL |
91 | pj.id = pj_get_param_s(params, "o_proj"); |
92 | if (pj.id.is_unknown()) | |
93 | BOOST_THROW_EXCEPTION( projection_exception(error_no_rotation_proj) ); | |
94 | ||
95 | /* avoid endless recursion */ | |
96 | if( pj.id.name == "ob_tran") | |
97 | BOOST_THROW_EXCEPTION( projection_exception(error_failed_to_find_proj) ); | |
98 | ||
99 | // Commented out for consistency with Proj4 >= 5.0.0 | |
100 | /* force spherical earth */ | |
101 | //pj.one_es = pj.rone_es = 1.; | |
102 | //pj.es = pj.e = 0.; | |
103 | ||
104 | return pj; | |
105 | } | |
106 | ||
107 | template <typename T, typename Parameters> | |
108 | inline Parameters o_proj_parameters(srs::dpar::parameters<T> const& params, | |
109 | Parameters const& par) | |
110 | { | |
11fdf7f2 | 111 | /* copy existing header into new */ |
92f5a8d4 TL |
112 | Parameters pj = par; |
113 | ||
114 | /* get name of projection to be translated */ | |
115 | typename srs::dpar::parameters<T>::const_iterator | |
116 | it = pj_param_find(params, srs::dpar::o_proj); | |
117 | if (it != params.end()) | |
118 | pj.id = static_cast<srs::dpar::value_proj>(it->template get_value<int>()); | |
119 | else | |
120 | BOOST_THROW_EXCEPTION( projection_exception(error_no_rotation_proj) ); | |
121 | ||
122 | /* avoid endless recursion */ | |
123 | if( pj.id.id == srs::dpar::proj_ob_tran) | |
124 | BOOST_THROW_EXCEPTION( projection_exception(error_failed_to_find_proj) ); | |
125 | ||
126 | // Commented out for consistency with Proj4 >= 5.0.0 | |
11fdf7f2 | 127 | /* force spherical earth */ |
92f5a8d4 TL |
128 | //pj.one_es = pj.rone_es = 1.; |
129 | //pj.es = pj.e = 0.; | |
11fdf7f2 TL |
130 | |
131 | return pj; | |
132 | } | |
133 | ||
20effc67 TL |
134 | template <typename ...Ps, typename Parameters> |
135 | inline Parameters o_proj_parameters(srs::spar::parameters<Ps...> const& /*params*/, | |
92f5a8d4 TL |
136 | Parameters const& par) |
137 | { | |
138 | /* copy existing header into new */ | |
139 | Parameters pj = par; | |
140 | ||
141 | /* get name of projection to be translated */ | |
20effc67 | 142 | typedef srs::spar::parameters<Ps...> params_type; |
f67539c2 | 143 | typedef typename geometry::tuples::find_if |
92f5a8d4 TL |
144 | < |
145 | params_type, | |
146 | srs::spar::detail::is_param_t<srs::spar::o_proj>::pred | |
147 | >::type o_proj_type; | |
148 | ||
f67539c2 | 149 | static const bool is_found = geometry::tuples::is_found<o_proj_type>::value; |
20effc67 TL |
150 | BOOST_GEOMETRY_STATIC_ASSERT((is_found), |
151 | "Rotation projection not specified.", | |
152 | params_type); | |
92f5a8d4 TL |
153 | |
154 | typedef typename o_proj_type::type proj_type; | |
155 | static const bool is_specialized = srs::spar::detail::proj_traits<proj_type>::is_specialized; | |
20effc67 TL |
156 | BOOST_GEOMETRY_STATIC_ASSERT((is_specialized), |
157 | "Rotation projection not specified.", | |
158 | params_type); | |
92f5a8d4 TL |
159 | |
160 | pj.id = srs::spar::detail::proj_traits<proj_type>::id; | |
161 | ||
162 | /* avoid endless recursion */ | |
20effc67 TL |
163 | static const bool is_non_resursive = ! std::is_same<proj_type, srs::spar::proj_ob_tran>::value; |
164 | BOOST_GEOMETRY_STATIC_ASSERT((is_non_resursive), | |
165 | "o_proj parameter can not be set to ob_tran projection.", | |
166 | params_type); | |
92f5a8d4 TL |
167 | |
168 | // Commented out for consistency with Proj4 >= 5.0.0 | |
169 | /* force spherical earth */ | |
170 | //pj.one_es = pj.rone_es = 1.; | |
171 | //pj.es = pj.e = 0.; | |
172 | ||
173 | return pj; | |
174 | } | |
175 | ||
176 | // TODO: It's possible that the original Parameters could be used | |
177 | // instead of a copy in link. | |
178 | // But it's not possible with the current implementation of | |
179 | // dynamic_wrapper_b always storing params | |
180 | ||
181 | template <typename T, typename Parameters> | |
11fdf7f2 TL |
182 | struct par_ob_tran |
183 | { | |
92f5a8d4 TL |
184 | template <typename Params> |
185 | par_ob_tran(Params const& params, Parameters const& par) | |
186 | : link(projections::detail::create_new(params, o_proj_parameters(params, par))) | |
11fdf7f2 TL |
187 | { |
188 | if (! link.get()) | |
92f5a8d4 | 189 | BOOST_THROW_EXCEPTION( projection_exception(error_unknown_projection_id) ); |
11fdf7f2 TL |
190 | } |
191 | ||
92f5a8d4 | 192 | inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const |
11fdf7f2 | 193 | { |
92f5a8d4 | 194 | link->fwd(link->params(), lp_lon, lp_lat, xy_x, xy_y); |
11fdf7f2 TL |
195 | } |
196 | ||
92f5a8d4 | 197 | inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const |
11fdf7f2 | 198 | { |
92f5a8d4 | 199 | link->inv(link->params(), xy_x, xy_y, lp_lon, lp_lat); |
11fdf7f2 TL |
200 | } |
201 | ||
92f5a8d4 TL |
202 | boost::shared_ptr<dynamic_wrapper_b<T, Parameters> > link; |
203 | T lamp; | |
204 | T cphip, sphip; | |
11fdf7f2 TL |
205 | }; |
206 | ||
92f5a8d4 | 207 | template <typename StaticParameters, typename T, typename Parameters> |
11fdf7f2 TL |
208 | struct par_ob_tran_static |
209 | { | |
92f5a8d4 TL |
210 | // this metafunction handles static error handling |
211 | typedef typename srs::spar::detail::pick_o_proj_tag | |
11fdf7f2 TL |
212 | < |
213 | StaticParameters | |
214 | >::type o_proj_tag; | |
215 | ||
92f5a8d4 | 216 | /* avoid endless recursion */ |
20effc67 TL |
217 | static const bool is_o_proj_not_ob_tran = ! std::is_same<o_proj_tag, srs::spar::proj_ob_tran>::value; |
218 | BOOST_GEOMETRY_STATIC_ASSERT((is_o_proj_not_ob_tran), | |
219 | "o_proj parameter can not be set to ob_tran projection.", | |
220 | StaticParameters); | |
92f5a8d4 | 221 | |
11fdf7f2 TL |
222 | typedef typename projections::detail::static_projection_type |
223 | < | |
224 | o_proj_tag, | |
92f5a8d4 TL |
225 | // Commented out for consistency with Proj4 >= 5.0.0 |
226 | //srs_sphere_tag, // force spherical | |
227 | typename projections::detail::static_srs_tag<StaticParameters>::type, | |
11fdf7f2 | 228 | StaticParameters, |
92f5a8d4 | 229 | T, |
11fdf7f2 TL |
230 | Parameters |
231 | >::type projection_type; | |
232 | ||
92f5a8d4 TL |
233 | par_ob_tran_static(StaticParameters const& params, Parameters const& par) |
234 | : link(params, o_proj_parameters(params, par)) | |
11fdf7f2 TL |
235 | {} |
236 | ||
92f5a8d4 | 237 | inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const |
11fdf7f2 | 238 | { |
92f5a8d4 | 239 | link.fwd(link.params(), lp_lon, lp_lat, xy_x, xy_y); |
11fdf7f2 TL |
240 | } |
241 | ||
92f5a8d4 | 242 | inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const |
11fdf7f2 | 243 | { |
92f5a8d4 | 244 | link.inv(link.params(), xy_x, xy_y, lp_lon, lp_lat); |
11fdf7f2 TL |
245 | } |
246 | ||
247 | projection_type link; | |
92f5a8d4 TL |
248 | T lamp; |
249 | T cphip, sphip; | |
11fdf7f2 TL |
250 | }; |
251 | ||
252 | template <typename T, typename Par> | |
92f5a8d4 | 253 | inline void o_forward(T lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& proj_parm) |
11fdf7f2 TL |
254 | { |
255 | T coslam, sinphi, cosphi; | |
256 | ||
257 | coslam = cos(lp_lon); | |
258 | sinphi = sin(lp_lat); | |
259 | cosphi = cos(lp_lat); | |
260 | lp_lon = adjlon(aatan2(cosphi * sin(lp_lon), proj_parm.sphip * cosphi * coslam + | |
261 | proj_parm.cphip * sinphi) + proj_parm.lamp); | |
262 | lp_lat = aasin(proj_parm.sphip * sinphi - proj_parm.cphip * cosphi * coslam); | |
263 | ||
264 | proj_parm.fwd(lp_lon, lp_lat, xy_x, xy_y); | |
265 | } | |
266 | ||
267 | template <typename T, typename Par> | |
92f5a8d4 | 268 | inline void o_inverse(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat, Par const& proj_parm) |
11fdf7f2 TL |
269 | { |
270 | T coslam, sinphi, cosphi; | |
271 | ||
272 | proj_parm.inv(xy_x, xy_y, lp_lon, lp_lat); | |
273 | if (lp_lon != HUGE_VAL) { | |
274 | coslam = cos(lp_lon -= proj_parm.lamp); | |
275 | sinphi = sin(lp_lat); | |
276 | cosphi = cos(lp_lat); | |
277 | lp_lat = aasin(proj_parm.sphip * sinphi + proj_parm.cphip * cosphi * coslam); | |
278 | lp_lon = aatan2(cosphi * sin(lp_lon), proj_parm.sphip * cosphi * coslam - | |
279 | proj_parm.cphip * sinphi); | |
280 | } | |
281 | } | |
282 | ||
283 | template <typename T, typename Par> | |
92f5a8d4 | 284 | inline void t_forward(T lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& proj_parm) |
11fdf7f2 TL |
285 | { |
286 | T cosphi, coslam; | |
287 | ||
288 | cosphi = cos(lp_lat); | |
289 | coslam = cos(lp_lon); | |
290 | lp_lon = adjlon(aatan2(cosphi * sin(lp_lon), sin(lp_lat)) + proj_parm.lamp); | |
291 | lp_lat = aasin(- cosphi * coslam); | |
92f5a8d4 | 292 | |
11fdf7f2 TL |
293 | proj_parm.fwd(lp_lon, lp_lat, xy_x, xy_y); |
294 | } | |
295 | ||
296 | template <typename T, typename Par> | |
92f5a8d4 | 297 | inline void t_inverse(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat, Par const& proj_parm) |
11fdf7f2 TL |
298 | { |
299 | T cosphi, t; | |
300 | ||
301 | proj_parm.inv(xy_x, xy_y, lp_lon, lp_lat); | |
302 | if (lp_lon != HUGE_VAL) { | |
303 | cosphi = cos(lp_lat); | |
304 | t = lp_lon - proj_parm.lamp; | |
305 | lp_lon = aatan2(cosphi * sin(t), - sin(lp_lat)); | |
306 | lp_lat = aasin(cosphi * cos(t)); | |
307 | } | |
308 | } | |
309 | ||
310 | // General Oblique Transformation | |
92f5a8d4 TL |
311 | template <typename T, typename Params, typename Parameters, typename ProjParameters> |
312 | inline T setup_ob_tran(Params const& params, Parameters & /*par*/, ProjParameters& proj_parm) | |
11fdf7f2 | 313 | { |
92f5a8d4 | 314 | static const T half_pi = detail::half_pi<T>(); |
11fdf7f2 | 315 | |
92f5a8d4 | 316 | T phip, alpha; |
11fdf7f2 | 317 | |
92f5a8d4 TL |
318 | // Commented out for consistency with Proj4 >= 5.0.0 |
319 | //par.es = 0.; /* force to spherical */ | |
11fdf7f2 TL |
320 | |
321 | // proj_parm.link should be created at this point | |
322 | ||
92f5a8d4 TL |
323 | if (pj_param_r<srs::spar::o_alpha>(params, "o_alpha", srs::dpar::o_alpha, alpha)) { |
324 | T lamc, phic; | |
325 | ||
326 | lamc = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lon_c", srs::dpar::o_lon_c); | |
327 | phic = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lat_c", srs::dpar::o_lat_c); | |
328 | //alpha = pj_get_param_r(par.params, "o_alpha"); | |
329 | ||
330 | if (fabs(fabs(phic) - half_pi) <= tolerance) | |
331 | BOOST_THROW_EXCEPTION( projection_exception(error_lat_0_or_alpha_eq_90) ); | |
332 | ||
11fdf7f2 TL |
333 | proj_parm.lamp = lamc + aatan2(-cos(alpha), -sin(alpha) * sin(phic)); |
334 | phip = aasin(cos(phic) * sin(alpha)); | |
92f5a8d4 TL |
335 | } else if (pj_param_r<srs::spar::o_lat_p>(params, "o_lat_p", srs::dpar::o_lat_p, phip)) { /* specified new pole */ |
336 | proj_parm.lamp = pj_get_param_r<T, srs::spar::o_lon_p>(params, "o_lon_p", srs::dpar::o_lon_p); | |
337 | //phip = pj_param_r(par.params, "o_lat_p"); | |
11fdf7f2 | 338 | } else { /* specified new "equator" points */ |
92f5a8d4 TL |
339 | T lam1, lam2, phi1, phi2, con; |
340 | ||
341 | lam1 = pj_get_param_r<T, srs::spar::o_lon_1>(params, "o_lon_1", srs::dpar::o_lon_1); | |
342 | phi1 = pj_get_param_r<T, srs::spar::o_lat_1>(params, "o_lat_1", srs::dpar::o_lat_1); | |
343 | lam2 = pj_get_param_r<T, srs::spar::o_lon_2>(params, "o_lon_2", srs::dpar::o_lon_2); | |
344 | phi2 = pj_get_param_r<T, srs::spar::o_lat_2>(params, "o_lat_2", srs::dpar::o_lat_2); | |
345 | if (fabs(phi1 - phi2) <= tolerance || (con = fabs(phi1)) <= tolerance || | |
346 | fabs(con - half_pi) <= tolerance || fabs(fabs(phi2) - half_pi) <= tolerance) | |
347 | BOOST_THROW_EXCEPTION( projection_exception(error_lat_1_or_2_zero_or_90) ); | |
348 | ||
11fdf7f2 TL |
349 | proj_parm.lamp = atan2(cos(phi1) * sin(phi2) * cos(lam1) - |
350 | sin(phi1) * cos(phi2) * cos(lam2), | |
351 | sin(phi1) * cos(phi2) * sin(lam2) - | |
352 | cos(phi1) * sin(phi2) * sin(lam1)); | |
353 | phip = atan(-cos(proj_parm.lamp - lam1) / tan(phi1)); | |
354 | } | |
92f5a8d4 TL |
355 | |
356 | if (fabs(phip) > tolerance) { /* oblique */ | |
11fdf7f2 TL |
357 | proj_parm.cphip = cos(phip); |
358 | proj_parm.sphip = sin(phip); | |
359 | } else { /* transverse */ | |
360 | } | |
92f5a8d4 TL |
361 | |
362 | // TODO: | |
363 | /* Support some rather speculative test cases, where the rotated projection */ | |
364 | /* is actually latlong. We do not want scaling in that case... */ | |
365 | //if (proj_parm.link...mutable_parameters().right==PJ_IO_UNITS_ANGULAR) | |
366 | // par.right = PJ_IO_UNITS_PROJECTED; | |
367 | ||
11fdf7f2 TL |
368 | // return phip to choose model |
369 | return phip; | |
370 | } | |
371 | ||
92f5a8d4 TL |
372 | template <typename T, typename Parameters> |
373 | struct base_ob_tran_oblique | |
11fdf7f2 | 374 | { |
92f5a8d4 | 375 | par_ob_tran<T, Parameters> m_proj_parm; |
11fdf7f2 | 376 | |
92f5a8d4 TL |
377 | inline base_ob_tran_oblique(par_ob_tran<T, Parameters> const& proj_parm) |
378 | : m_proj_parm(proj_parm) | |
11fdf7f2 TL |
379 | {} |
380 | ||
381 | // FORWARD(o_forward) spheroid | |
382 | // Project coordinates from geographic (lon, lat) to cartesian (x, y) | |
92f5a8d4 | 383 | inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const |
11fdf7f2 | 384 | { |
92f5a8d4 | 385 | // NOTE: Parameters ignored, m_proj_parm.link has a copy |
11fdf7f2 TL |
386 | o_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm); |
387 | } | |
388 | ||
389 | // INVERSE(o_inverse) spheroid | |
390 | // Project coordinates from cartesian (x, y) to geographic (lon, lat) | |
92f5a8d4 | 391 | inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const |
11fdf7f2 | 392 | { |
92f5a8d4 | 393 | // NOTE: Parameters ignored, m_proj_parm.link has a copy |
11fdf7f2 TL |
394 | o_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm); |
395 | } | |
396 | ||
397 | static inline std::string get_name() | |
398 | { | |
399 | return "ob_tran_oblique"; | |
400 | } | |
401 | ||
402 | }; | |
403 | ||
92f5a8d4 TL |
404 | template <typename T, typename Parameters> |
405 | struct base_ob_tran_transverse | |
11fdf7f2 | 406 | { |
92f5a8d4 | 407 | par_ob_tran<T, Parameters> m_proj_parm; |
11fdf7f2 | 408 | |
92f5a8d4 TL |
409 | inline base_ob_tran_transverse(par_ob_tran<T, Parameters> const& proj_parm) |
410 | : m_proj_parm(proj_parm) | |
11fdf7f2 TL |
411 | {} |
412 | ||
413 | // FORWARD(t_forward) spheroid | |
414 | // Project coordinates from geographic (lon, lat) to cartesian (x, y) | |
92f5a8d4 | 415 | inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const |
11fdf7f2 | 416 | { |
92f5a8d4 | 417 | // NOTE: Parameters ignored, m_proj_parm.link has a copy |
11fdf7f2 TL |
418 | t_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm); |
419 | } | |
420 | ||
421 | // INVERSE(t_inverse) spheroid | |
422 | // Project coordinates from cartesian (x, y) to geographic (lon, lat) | |
92f5a8d4 | 423 | inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const |
11fdf7f2 | 424 | { |
92f5a8d4 | 425 | // NOTE: Parameters ignored, m_proj_parm.link has a copy |
11fdf7f2 TL |
426 | t_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm); |
427 | } | |
428 | ||
429 | static inline std::string get_name() | |
430 | { | |
431 | return "ob_tran_transverse"; | |
432 | } | |
433 | ||
434 | }; | |
435 | ||
92f5a8d4 TL |
436 | template <typename StaticParameters, typename T, typename Parameters> |
437 | struct base_ob_tran_static | |
11fdf7f2 | 438 | { |
92f5a8d4 | 439 | par_ob_tran_static<StaticParameters, T, Parameters> m_proj_parm; |
11fdf7f2 TL |
440 | bool m_is_oblique; |
441 | ||
92f5a8d4 TL |
442 | inline base_ob_tran_static(StaticParameters const& params, Parameters const& par) |
443 | : m_proj_parm(params, par) | |
11fdf7f2 TL |
444 | {} |
445 | ||
446 | // FORWARD(o_forward) spheroid | |
447 | // Project coordinates from geographic (lon, lat) to cartesian (x, y) | |
92f5a8d4 | 448 | inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const |
11fdf7f2 | 449 | { |
92f5a8d4 | 450 | // NOTE: Parameters ignored, m_proj_parm.link has a copy |
11fdf7f2 TL |
451 | if (m_is_oblique) { |
452 | o_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm); | |
453 | } else { | |
454 | t_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm); | |
455 | } | |
456 | } | |
457 | ||
458 | // INVERSE(o_inverse) spheroid | |
459 | // Project coordinates from cartesian (x, y) to geographic (lon, lat) | |
92f5a8d4 | 460 | inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const |
11fdf7f2 | 461 | { |
92f5a8d4 | 462 | // NOTE: Parameters ignored, m_proj_parm.link has a copy |
11fdf7f2 TL |
463 | if (m_is_oblique) { |
464 | o_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm); | |
465 | } else { | |
466 | t_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm); | |
467 | } | |
468 | } | |
469 | ||
470 | static inline std::string get_name() | |
471 | { | |
472 | return "ob_tran"; | |
473 | } | |
474 | ||
475 | }; | |
476 | ||
477 | }} // namespace detail::ob_tran | |
478 | #endif // doxygen | |
479 | ||
480 | /*! | |
481 | \brief General Oblique Transformation projection | |
482 | \ingroup projections | |
483 | \tparam Geographic latlong point type | |
484 | \tparam Cartesian xy point type | |
485 | \tparam Parameters parameter type | |
486 | \par Projection characteristics | |
487 | - Miscellaneous | |
488 | - Spheroid | |
489 | \par Projection parameters | |
490 | - o_proj (string) | |
491 | - Plus projection parameters | |
492 | - o_lat_p (degrees) | |
493 | - o_lon_p (degrees) | |
494 | - New pole | |
495 | - o_alpha: Alpha (degrees) | |
496 | - o_lon_c (degrees) | |
497 | - o_lat_c (degrees) | |
498 | - o_lon_1 (degrees) | |
499 | - o_lat_1: Latitude of first standard parallel (degrees) | |
500 | - o_lon_2 (degrees) | |
501 | - o_lat_2: Latitude of second standard parallel (degrees) | |
502 | \par Example | |
503 | \image html ex_ob_tran.gif | |
504 | */ | |
92f5a8d4 TL |
505 | template <typename T, typename Parameters> |
506 | struct ob_tran_oblique : public detail::ob_tran::base_ob_tran_oblique<T, Parameters> | |
11fdf7f2 | 507 | { |
92f5a8d4 TL |
508 | template <typename Params> |
509 | inline ob_tran_oblique(Params const& , Parameters const& , | |
510 | detail::ob_tran::par_ob_tran<T, Parameters> const& proj_parm) | |
511 | : detail::ob_tran::base_ob_tran_oblique<T, Parameters>(proj_parm) | |
11fdf7f2 TL |
512 | { |
513 | // already done | |
514 | //detail::ob_tran::setup_ob_tran(this->m_par, this->m_proj_parm); | |
515 | } | |
516 | }; | |
517 | ||
518 | /*! | |
519 | \brief General Oblique Transformation projection | |
520 | \ingroup projections | |
521 | \tparam Geographic latlong point type | |
522 | \tparam Cartesian xy point type | |
523 | \tparam Parameters parameter type | |
524 | \par Projection characteristics | |
525 | - Miscellaneous | |
526 | - Spheroid | |
527 | \par Projection parameters | |
528 | - o_proj (string) | |
529 | - Plus projection parameters | |
530 | - o_lat_p (degrees) | |
531 | - o_lon_p (degrees) | |
532 | - New pole | |
533 | - o_alpha: Alpha (degrees) | |
534 | - o_lon_c (degrees) | |
535 | - o_lat_c (degrees) | |
536 | - o_lon_1 (degrees) | |
537 | - o_lat_1: Latitude of first standard parallel (degrees) | |
538 | - o_lon_2 (degrees) | |
539 | - o_lat_2: Latitude of second standard parallel (degrees) | |
540 | \par Example | |
541 | \image html ex_ob_tran.gif | |
542 | */ | |
92f5a8d4 TL |
543 | template <typename T, typename Parameters> |
544 | struct ob_tran_transverse : public detail::ob_tran::base_ob_tran_transverse<T, Parameters> | |
545 | { | |
546 | template <typename Params> | |
547 | inline ob_tran_transverse(Params const& , Parameters const& , | |
548 | detail::ob_tran::par_ob_tran<T, Parameters> const& proj_parm) | |
549 | : detail::ob_tran::base_ob_tran_transverse<T, Parameters>(proj_parm) | |
11fdf7f2 TL |
550 | { |
551 | // already done | |
552 | //detail::ob_tran::setup_ob_tran(this->m_par, this->m_proj_parm); | |
553 | } | |
554 | }; | |
555 | ||
556 | /*! | |
557 | \brief General Oblique Transformation projection | |
558 | \ingroup projections | |
559 | \tparam Geographic latlong point type | |
560 | \tparam Cartesian xy point type | |
561 | \tparam Parameters parameter type | |
562 | \par Projection characteristics | |
563 | - Miscellaneous | |
564 | - Spheroid | |
565 | \par Projection parameters | |
566 | - o_proj (string) | |
567 | - Plus projection parameters | |
568 | - o_lat_p (degrees) | |
569 | - o_lon_p (degrees) | |
570 | - New pole | |
571 | - o_alpha: Alpha (degrees) | |
572 | - o_lon_c (degrees) | |
573 | - o_lat_c (degrees) | |
574 | - o_lon_1 (degrees) | |
575 | - o_lat_1: Latitude of first standard parallel (degrees) | |
576 | - o_lon_2 (degrees) | |
577 | - o_lat_2: Latitude of second standard parallel (degrees) | |
578 | \par Example | |
579 | \image html ex_ob_tran.gif | |
580 | */ | |
92f5a8d4 TL |
581 | template <typename StaticParameters, typename T, typename Parameters> |
582 | struct ob_tran_static : public detail::ob_tran::base_ob_tran_static<StaticParameters, T, Parameters> | |
11fdf7f2 | 583 | { |
92f5a8d4 TL |
584 | inline ob_tran_static(StaticParameters const& params, Parameters const& par) |
585 | : detail::ob_tran::base_ob_tran_static<StaticParameters, T, Parameters>(params, par) | |
11fdf7f2 | 586 | { |
92f5a8d4 TL |
587 | T phip = detail::ob_tran::setup_ob_tran<T>(params, par, this->m_proj_parm); |
588 | this->m_is_oblique = fabs(phip) > detail::ob_tran::tolerance; | |
11fdf7f2 TL |
589 | } |
590 | }; | |
591 | ||
592 | #ifndef DOXYGEN_NO_DETAIL | |
593 | namespace detail | |
594 | { | |
595 | ||
596 | // Static projection | |
92f5a8d4 TL |
597 | template <typename SP, typename CT, typename P> |
598 | struct static_projection_type<srs::spar::proj_ob_tran, srs_sphere_tag, SP, CT, P> | |
11fdf7f2 | 599 | { |
92f5a8d4 | 600 | typedef static_wrapper_fi<ob_tran_static<SP, CT, P>, P> type; |
11fdf7f2 | 601 | }; |
92f5a8d4 TL |
602 | template <typename SP, typename CT, typename P> |
603 | struct static_projection_type<srs::spar::proj_ob_tran, srs_spheroid_tag, SP, CT, P> | |
11fdf7f2 | 604 | { |
92f5a8d4 | 605 | typedef static_wrapper_fi<ob_tran_static<SP, CT, P>, P> type; |
11fdf7f2 TL |
606 | }; |
607 | ||
608 | // Factory entry(s) | |
92f5a8d4 | 609 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_BEGIN(ob_tran_entry) |
11fdf7f2 | 610 | { |
92f5a8d4 TL |
611 | Parameters parameters_copy = parameters; |
612 | detail::ob_tran::par_ob_tran<T, Parameters> proj_parm(params, parameters_copy); | |
613 | T phip = detail::ob_tran::setup_ob_tran<T>(params, parameters_copy, proj_parm); | |
614 | ||
615 | if (fabs(phip) > detail::ob_tran::tolerance) | |
616 | return new dynamic_wrapper_fi<ob_tran_oblique<T, Parameters>, T, Parameters>(params, parameters_copy, proj_parm); | |
617 | else | |
618 | return new dynamic_wrapper_fi<ob_tran_transverse<T, Parameters>, T, Parameters>(params, parameters_copy, proj_parm); | |
619 | } | |
620 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END | |
11fdf7f2 | 621 | |
92f5a8d4 | 622 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(ob_tran_init) |
11fdf7f2 | 623 | { |
92f5a8d4 | 624 | BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(ob_tran, ob_tran_entry) |
11fdf7f2 TL |
625 | } |
626 | ||
627 | } // namespace detail | |
628 | #endif // doxygen | |
629 | ||
630 | } // namespace projections | |
631 | ||
632 | }} // namespace boost::geometry | |
633 | ||
634 | #endif // BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP | |
635 |