File indexing completed on 2025-01-18 09:35:45
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 #ifndef BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP
0042 #define BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP
0043
0044 #include <memory>
0045 #include <type_traits>
0046
0047 #include <boost/geometry/core/static_assert.hpp>
0048 #include <boost/geometry/srs/projections/impl/aasincos.hpp>
0049 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0050 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0051 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0052 #include <boost/geometry/srs/projections/impl/pj_ell_set.hpp>
0053 #include <boost/geometry/srs/projections/impl/projects.hpp>
0054 #include <boost/geometry/util/math.hpp>
0055
0056 namespace boost { namespace geometry
0057 {
0058
0059 namespace projections
0060 {
0061 #ifndef DOXYGEN_NO_DETAIL
0062 namespace detail {
0063
0064
0065 template <typename T>
0066 inline detail::dynamic_wrapper_b<T, projections::parameters<T> >*
0067 create_new(srs::detail::proj4_parameters const& params,
0068 projections::parameters<T> const& parameters);
0069
0070 template <typename T>
0071 inline detail::dynamic_wrapper_b<T, projections::parameters<T> >*
0072 create_new(srs::dpar::parameters<T> const& params,
0073 projections::parameters<T> const& parameters);
0074
0075 }
0076
0077 namespace detail { namespace ob_tran
0078 {
0079
0080 static const double tolerance = 1e-10;
0081
0082 template <typename Parameters>
0083 inline Parameters o_proj_parameters(srs::detail::proj4_parameters const& params,
0084 Parameters const& par)
0085 {
0086
0087 Parameters pj = par;
0088
0089
0090 pj.id = pj_get_param_s(params, "o_proj");
0091 if (pj.id.is_unknown())
0092 BOOST_THROW_EXCEPTION( projection_exception(error_no_rotation_proj) );
0093
0094
0095 if( pj.id.name == "ob_tran")
0096 BOOST_THROW_EXCEPTION( projection_exception(error_failed_to_find_proj) );
0097
0098
0099
0100
0101
0102
0103 return pj;
0104 }
0105
0106 template <typename T, typename Parameters>
0107 inline Parameters o_proj_parameters(srs::dpar::parameters<T> const& params,
0108 Parameters const& par)
0109 {
0110
0111 Parameters pj = par;
0112
0113
0114 typename srs::dpar::parameters<T>::const_iterator
0115 it = pj_param_find(params, srs::dpar::o_proj);
0116 if (it != params.end())
0117 pj.id = static_cast<srs::dpar::value_proj>(it->template get_value<int>());
0118 else
0119 BOOST_THROW_EXCEPTION( projection_exception(error_no_rotation_proj) );
0120
0121
0122 if( pj.id.id == srs::dpar::proj_ob_tran)
0123 BOOST_THROW_EXCEPTION( projection_exception(error_failed_to_find_proj) );
0124
0125
0126
0127
0128
0129
0130 return pj;
0131 }
0132
0133 template <typename ...Ps, typename Parameters>
0134 inline Parameters o_proj_parameters(srs::spar::parameters<Ps...> const& ,
0135 Parameters const& par)
0136 {
0137
0138 Parameters pj = par;
0139
0140
0141 typedef srs::spar::parameters<Ps...> params_type;
0142 typedef typename geometry::tuples::find_if
0143 <
0144 params_type,
0145 srs::spar::detail::is_param_t<srs::spar::o_proj>::pred
0146 >::type o_proj_type;
0147
0148 static const bool is_found = geometry::tuples::is_found<o_proj_type>::value;
0149 BOOST_GEOMETRY_STATIC_ASSERT((is_found),
0150 "Rotation projection not specified.",
0151 params_type);
0152
0153 typedef typename o_proj_type::type proj_type;
0154 static const bool is_specialized = srs::spar::detail::proj_traits<proj_type>::is_specialized;
0155 BOOST_GEOMETRY_STATIC_ASSERT((is_specialized),
0156 "Rotation projection not specified.",
0157 params_type);
0158
0159 pj.id = srs::spar::detail::proj_traits<proj_type>::id;
0160
0161
0162 static const bool is_non_resursive = ! std::is_same<proj_type, srs::spar::proj_ob_tran>::value;
0163 BOOST_GEOMETRY_STATIC_ASSERT((is_non_resursive),
0164 "o_proj parameter can not be set to ob_tran projection.",
0165 params_type);
0166
0167
0168
0169
0170
0171
0172 return pj;
0173 }
0174
0175
0176
0177
0178
0179
0180 template <typename T, typename Parameters>
0181 struct par_ob_tran
0182 {
0183 template <typename Params>
0184 par_ob_tran(Params const& params, Parameters const& par)
0185 : link(projections::detail::create_new(params, o_proj_parameters(params, par)))
0186 {
0187 if (! link.get())
0188 BOOST_THROW_EXCEPTION( projection_exception(error_unknown_projection_id) );
0189 }
0190
0191 inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0192 {
0193 link->fwd(link->params(), lp_lon, lp_lat, xy_x, xy_y);
0194 }
0195
0196 inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0197 {
0198 link->inv(link->params(), xy_x, xy_y, lp_lon, lp_lat);
0199 }
0200
0201 std::shared_ptr<dynamic_wrapper_b<T, Parameters> > link;
0202 T lamp;
0203 T cphip, sphip;
0204 };
0205
0206 template <typename StaticParameters, typename T, typename Parameters>
0207 struct par_ob_tran_static
0208 {
0209
0210 typedef typename srs::spar::detail::pick_o_proj_tag
0211 <
0212 StaticParameters
0213 >::type o_proj_tag;
0214
0215
0216 static const bool is_o_proj_not_ob_tran = ! std::is_same<o_proj_tag, srs::spar::proj_ob_tran>::value;
0217 BOOST_GEOMETRY_STATIC_ASSERT((is_o_proj_not_ob_tran),
0218 "o_proj parameter can not be set to ob_tran projection.",
0219 StaticParameters);
0220
0221 typedef typename projections::detail::static_projection_type
0222 <
0223 o_proj_tag,
0224
0225
0226 typename projections::detail::static_srs_tag<StaticParameters>::type,
0227 StaticParameters,
0228 T,
0229 Parameters
0230 >::type projection_type;
0231
0232 par_ob_tran_static(StaticParameters const& params, Parameters const& par)
0233 : link(params, o_proj_parameters(params, par))
0234 {}
0235
0236 inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0237 {
0238 link.fwd(link.params(), lp_lon, lp_lat, xy_x, xy_y);
0239 }
0240
0241 inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0242 {
0243 link.inv(link.params(), xy_x, xy_y, lp_lon, lp_lat);
0244 }
0245
0246 projection_type link;
0247 T lamp;
0248 T cphip, sphip;
0249 };
0250
0251 template <typename T, typename Par>
0252 inline void o_forward(T lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& proj_parm)
0253 {
0254 T coslam, sinphi, cosphi;
0255
0256 coslam = cos(lp_lon);
0257 sinphi = sin(lp_lat);
0258 cosphi = cos(lp_lat);
0259 lp_lon = adjlon(aatan2(cosphi * sin(lp_lon), proj_parm.sphip * cosphi * coslam +
0260 proj_parm.cphip * sinphi) + proj_parm.lamp);
0261 lp_lat = aasin(proj_parm.sphip * sinphi - proj_parm.cphip * cosphi * coslam);
0262
0263 proj_parm.fwd(lp_lon, lp_lat, xy_x, xy_y);
0264 }
0265
0266 template <typename T, typename Par>
0267 inline void o_inverse(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat, Par const& proj_parm)
0268 {
0269 T coslam, sinphi, cosphi;
0270
0271 proj_parm.inv(xy_x, xy_y, lp_lon, lp_lat);
0272 if (lp_lon != HUGE_VAL) {
0273 coslam = cos(lp_lon -= proj_parm.lamp);
0274 sinphi = sin(lp_lat);
0275 cosphi = cos(lp_lat);
0276 lp_lat = aasin(proj_parm.sphip * sinphi + proj_parm.cphip * cosphi * coslam);
0277 lp_lon = aatan2(cosphi * sin(lp_lon), proj_parm.sphip * cosphi * coslam -
0278 proj_parm.cphip * sinphi);
0279 }
0280 }
0281
0282 template <typename T, typename Par>
0283 inline void t_forward(T lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& proj_parm)
0284 {
0285 T cosphi, coslam;
0286
0287 cosphi = cos(lp_lat);
0288 coslam = cos(lp_lon);
0289 lp_lon = adjlon(aatan2(cosphi * sin(lp_lon), sin(lp_lat)) + proj_parm.lamp);
0290 lp_lat = aasin(- cosphi * coslam);
0291
0292 proj_parm.fwd(lp_lon, lp_lat, xy_x, xy_y);
0293 }
0294
0295 template <typename T, typename Par>
0296 inline void t_inverse(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat, Par const& proj_parm)
0297 {
0298 T cosphi, t;
0299
0300 proj_parm.inv(xy_x, xy_y, lp_lon, lp_lat);
0301 if (lp_lon != HUGE_VAL) {
0302 cosphi = cos(lp_lat);
0303 t = lp_lon - proj_parm.lamp;
0304 lp_lon = aatan2(cosphi * sin(t), - sin(lp_lat));
0305 lp_lat = aasin(cosphi * cos(t));
0306 }
0307 }
0308
0309
0310 template <typename T, typename Params, typename Parameters, typename ProjParameters>
0311 inline T setup_ob_tran(Params const& params, Parameters & , ProjParameters& proj_parm)
0312 {
0313 static const T half_pi = detail::half_pi<T>();
0314
0315 T phip, alpha;
0316
0317
0318
0319
0320
0321
0322 if (pj_param_r<srs::spar::o_alpha>(params, "o_alpha", srs::dpar::o_alpha, alpha)) {
0323 T lamc, phic;
0324
0325 lamc = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lon_c", srs::dpar::o_lon_c);
0326 phic = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lat_c", srs::dpar::o_lat_c);
0327
0328
0329 if (fabs(fabs(phic) - half_pi) <= tolerance)
0330 BOOST_THROW_EXCEPTION( projection_exception(error_lat_0_or_alpha_eq_90) );
0331
0332 proj_parm.lamp = lamc + aatan2(-cos(alpha), -sin(alpha) * sin(phic));
0333 phip = aasin(cos(phic) * sin(alpha));
0334 } else if (pj_param_r<srs::spar::o_lat_p>(params, "o_lat_p", srs::dpar::o_lat_p, phip)) {
0335 proj_parm.lamp = pj_get_param_r<T, srs::spar::o_lon_p>(params, "o_lon_p", srs::dpar::o_lon_p);
0336
0337 } else {
0338 T lam1, lam2, phi1, phi2, con;
0339
0340 lam1 = pj_get_param_r<T, srs::spar::o_lon_1>(params, "o_lon_1", srs::dpar::o_lon_1);
0341 phi1 = pj_get_param_r<T, srs::spar::o_lat_1>(params, "o_lat_1", srs::dpar::o_lat_1);
0342 lam2 = pj_get_param_r<T, srs::spar::o_lon_2>(params, "o_lon_2", srs::dpar::o_lon_2);
0343 phi2 = pj_get_param_r<T, srs::spar::o_lat_2>(params, "o_lat_2", srs::dpar::o_lat_2);
0344 if (fabs(phi1 - phi2) <= tolerance || (con = fabs(phi1)) <= tolerance ||
0345 fabs(con - half_pi) <= tolerance || fabs(fabs(phi2) - half_pi) <= tolerance)
0346 BOOST_THROW_EXCEPTION( projection_exception(error_lat_1_or_2_zero_or_90) );
0347
0348 proj_parm.lamp = atan2(cos(phi1) * sin(phi2) * cos(lam1) -
0349 sin(phi1) * cos(phi2) * cos(lam2),
0350 sin(phi1) * cos(phi2) * sin(lam2) -
0351 cos(phi1) * sin(phi2) * sin(lam1));
0352 phip = atan(-cos(proj_parm.lamp - lam1) / tan(phi1));
0353 }
0354
0355 if (fabs(phip) > tolerance) {
0356 proj_parm.cphip = cos(phip);
0357 proj_parm.sphip = sin(phip);
0358 } else {
0359 }
0360
0361
0362
0363
0364
0365
0366
0367
0368 return phip;
0369 }
0370
0371 template <typename T, typename Parameters>
0372 struct base_ob_tran_oblique
0373 {
0374 par_ob_tran<T, Parameters> m_proj_parm;
0375
0376 inline base_ob_tran_oblique(par_ob_tran<T, Parameters> const& proj_parm)
0377 : m_proj_parm(proj_parm)
0378 {}
0379
0380
0381
0382 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0383 {
0384
0385 o_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm);
0386 }
0387
0388
0389
0390 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0391 {
0392
0393 o_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm);
0394 }
0395
0396 static inline std::string get_name()
0397 {
0398 return "ob_tran_oblique";
0399 }
0400
0401 };
0402
0403 template <typename T, typename Parameters>
0404 struct base_ob_tran_transverse
0405 {
0406 par_ob_tran<T, Parameters> m_proj_parm;
0407
0408 inline base_ob_tran_transverse(par_ob_tran<T, Parameters> const& proj_parm)
0409 : m_proj_parm(proj_parm)
0410 {}
0411
0412
0413
0414 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0415 {
0416
0417 t_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm);
0418 }
0419
0420
0421
0422 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0423 {
0424
0425 t_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm);
0426 }
0427
0428 static inline std::string get_name()
0429 {
0430 return "ob_tran_transverse";
0431 }
0432
0433 };
0434
0435 template <typename StaticParameters, typename T, typename Parameters>
0436 struct base_ob_tran_static
0437 {
0438 par_ob_tran_static<StaticParameters, T, Parameters> m_proj_parm;
0439 bool m_is_oblique;
0440
0441 inline base_ob_tran_static(StaticParameters const& params, Parameters const& par)
0442 : m_proj_parm(params, par)
0443 {}
0444
0445
0446
0447 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0448 {
0449
0450 if (m_is_oblique) {
0451 o_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm);
0452 } else {
0453 t_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm);
0454 }
0455 }
0456
0457
0458
0459 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0460 {
0461
0462 if (m_is_oblique) {
0463 o_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm);
0464 } else {
0465 t_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm);
0466 }
0467 }
0468
0469 static inline std::string get_name()
0470 {
0471 return "ob_tran";
0472 }
0473
0474 };
0475
0476 }}
0477 #endif
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504 template <typename T, typename Parameters>
0505 struct ob_tran_oblique : public detail::ob_tran::base_ob_tran_oblique<T, Parameters>
0506 {
0507 template <typename Params>
0508 inline ob_tran_oblique(Params const& , Parameters const& ,
0509 detail::ob_tran::par_ob_tran<T, Parameters> const& proj_parm)
0510 : detail::ob_tran::base_ob_tran_oblique<T, Parameters>(proj_parm)
0511 {
0512
0513
0514 }
0515 };
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542 template <typename T, typename Parameters>
0543 struct ob_tran_transverse : public detail::ob_tran::base_ob_tran_transverse<T, Parameters>
0544 {
0545 template <typename Params>
0546 inline ob_tran_transverse(Params const& , Parameters const& ,
0547 detail::ob_tran::par_ob_tran<T, Parameters> const& proj_parm)
0548 : detail::ob_tran::base_ob_tran_transverse<T, Parameters>(proj_parm)
0549 {
0550
0551
0552 }
0553 };
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580 template <typename StaticParameters, typename T, typename Parameters>
0581 struct ob_tran_static : public detail::ob_tran::base_ob_tran_static<StaticParameters, T, Parameters>
0582 {
0583 inline ob_tran_static(StaticParameters const& params, Parameters const& par)
0584 : detail::ob_tran::base_ob_tran_static<StaticParameters, T, Parameters>(params, par)
0585 {
0586 T phip = detail::ob_tran::setup_ob_tran<T>(params, par, this->m_proj_parm);
0587 this->m_is_oblique = fabs(phip) > detail::ob_tran::tolerance;
0588 }
0589 };
0590
0591 #ifndef DOXYGEN_NO_DETAIL
0592 namespace detail
0593 {
0594
0595
0596 template <typename SP, typename CT, typename P>
0597 struct static_projection_type<srs::spar::proj_ob_tran, srs_sphere_tag, SP, CT, P>
0598 {
0599 typedef static_wrapper_fi<ob_tran_static<SP, CT, P>, P> type;
0600 };
0601 template <typename SP, typename CT, typename P>
0602 struct static_projection_type<srs::spar::proj_ob_tran, srs_spheroid_tag, SP, CT, P>
0603 {
0604 typedef static_wrapper_fi<ob_tran_static<SP, CT, P>, P> type;
0605 };
0606
0607
0608 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_BEGIN(ob_tran_entry)
0609 {
0610 Parameters parameters_copy = parameters;
0611 detail::ob_tran::par_ob_tran<T, Parameters> proj_parm(params, parameters_copy);
0612 T phip = detail::ob_tran::setup_ob_tran<T>(params, parameters_copy, proj_parm);
0613
0614 if (fabs(phip) > detail::ob_tran::tolerance)
0615 return new dynamic_wrapper_fi<ob_tran_oblique<T, Parameters>, T, Parameters>(params, parameters_copy, proj_parm);
0616 else
0617 return new dynamic_wrapper_fi<ob_tran_transverse<T, Parameters>, T, Parameters>(params, parameters_copy, proj_parm);
0618 }
0619 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END
0620
0621 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(ob_tran_init)
0622 {
0623 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(ob_tran, ob_tran_entry)
0624 }
0625
0626 }
0627 #endif
0628
0629 }
0630
0631 }}
0632
0633 #endif
0634