File indexing completed on 2025-01-18 09:35:39
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
0042
0043
0044
0045
0046
0047 #ifndef BOOST_GEOMETRY_PROJECTIONS_AEA_HPP
0048 #define BOOST_GEOMETRY_PROJECTIONS_AEA_HPP
0049
0050 #include <boost/core/ignore_unused.hpp>
0051 #include <boost/geometry/util/math.hpp>
0052 #include <boost/math/special_functions/hypot.hpp>
0053
0054 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0055 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0056 #include <boost/geometry/srs/projections/impl/projects.hpp>
0057 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0058 #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp>
0059 #include <boost/geometry/srs/projections/impl/pj_msfn.hpp>
0060 #include <boost/geometry/srs/projections/impl/pj_param.hpp>
0061 #include <boost/geometry/srs/projections/impl/pj_qsfn.hpp>
0062
0063
0064 namespace boost { namespace geometry
0065 {
0066
0067 namespace projections
0068 {
0069 #ifndef DOXYGEN_NO_DETAIL
0070 namespace detail { namespace aea
0071 {
0072
0073 static const double epsilon10 = 1.e-10;
0074 static const double tolerance7 = 1.e-7;
0075 static const double epsilon = 1.0e-7;
0076 static const double tolerance = 1.0e-10;
0077 static const int n_iter = 15;
0078
0079 template <typename T>
0080 struct par_aea
0081 {
0082 T ec;
0083 T n;
0084 T c;
0085 T dd;
0086 T n2;
0087 T rho0;
0088 T phi1;
0089 T phi2;
0090 detail::en<T> en;
0091 bool ellips;
0092 };
0093
0094
0095 template <typename T>
0096 inline T phi1_(T const& qs, T const& Te, T const& Tone_es)
0097 {
0098 int i;
0099 T Phi, sinpi, cospi, con, com, dphi;
0100
0101 Phi = asin (.5 * qs);
0102 if (Te < epsilon)
0103 return( Phi );
0104 i = n_iter;
0105 do {
0106 sinpi = sin (Phi);
0107 cospi = cos (Phi);
0108 con = Te * sinpi;
0109 com = 1. - con * con;
0110 dphi = .5 * com * com / cospi * (qs / Tone_es -
0111 sinpi / com + .5 / Te * log ((1. - con) /
0112 (1. + con)));
0113 Phi += dphi;
0114 } while (fabs(dphi) > tolerance && --i);
0115 return( i ? Phi : HUGE_VAL );
0116 }
0117
0118 template <typename T, typename Parameters>
0119 struct base_aea_ellipsoid
0120 {
0121 par_aea<T> m_proj_parm;
0122
0123
0124
0125 inline void fwd(Parameters const& par, T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0126 {
0127 T rho = this->m_proj_parm.c - (this->m_proj_parm.ellips
0128 ? this->m_proj_parm.n * pj_qsfn(sin(lp_lat), par.e, par.one_es)
0129 : this->m_proj_parm.n2 * sin(lp_lat));
0130 if (rho < 0.)
0131 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0132 rho = this->m_proj_parm.dd * sqrt(rho);
0133 xy_x = rho * sin( lp_lon *= this->m_proj_parm.n );
0134 xy_y = this->m_proj_parm.rho0 - rho * cos(lp_lon);
0135 }
0136
0137
0138
0139 inline void inv(Parameters const& par, T xy_x, T xy_y, T& lp_lon, T& lp_lat) const
0140 {
0141 static const T half_pi = detail::half_pi<T>();
0142
0143 T rho = 0.0;
0144 if( (rho = boost::math::hypot(xy_x, xy_y = this->m_proj_parm.rho0 - xy_y)) != 0.0 ) {
0145 if (this->m_proj_parm.n < 0.) {
0146 rho = -rho;
0147 xy_x = -xy_x;
0148 xy_y = -xy_y;
0149 }
0150 lp_lat = rho / this->m_proj_parm.dd;
0151 if (this->m_proj_parm.ellips) {
0152 lp_lat = (this->m_proj_parm.c - lp_lat * lp_lat) / this->m_proj_parm.n;
0153 if (fabs(this->m_proj_parm.ec - fabs(lp_lat)) > tolerance7) {
0154 if ((lp_lat = phi1_(lp_lat, par.e, par.one_es)) == HUGE_VAL)
0155 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0156 } else
0157 lp_lat = lp_lat < 0. ? -half_pi : half_pi;
0158 } else if (fabs(lp_lat = (this->m_proj_parm.c - lp_lat * lp_lat) / this->m_proj_parm.n2) <= 1.)
0159 lp_lat = asin(lp_lat);
0160 else
0161 lp_lat = lp_lat < 0. ? -half_pi : half_pi;
0162 lp_lon = atan2(xy_x, xy_y) / this->m_proj_parm.n;
0163 } else {
0164 lp_lon = 0.;
0165 lp_lat = this->m_proj_parm.n > 0. ? half_pi : - half_pi;
0166 }
0167 }
0168
0169 static inline std::string get_name()
0170 {
0171 return "aea_ellipsoid";
0172 }
0173
0174 };
0175
0176 template <typename Parameters, typename T>
0177 inline void setup(Parameters const& par, par_aea<T>& proj_parm)
0178 {
0179 T cosphi, sinphi;
0180 int secant;
0181
0182 if (fabs(proj_parm.phi1 + proj_parm.phi2) < epsilon10)
0183 BOOST_THROW_EXCEPTION( projection_exception(error_conic_lat_equal) );
0184 proj_parm.n = sinphi = sin(proj_parm.phi1);
0185 cosphi = cos(proj_parm.phi1);
0186 secant = fabs(proj_parm.phi1 - proj_parm.phi2) >= epsilon10;
0187 if( (proj_parm.ellips = (par.es > 0.))) {
0188 T ml1, m1;
0189
0190 proj_parm.en = pj_enfn<T>(par.es);
0191 m1 = pj_msfn(sinphi, cosphi, par.es);
0192 ml1 = pj_qsfn(sinphi, par.e, par.one_es);
0193 if (secant) {
0194 T ml2, m2;
0195
0196 sinphi = sin(proj_parm.phi2);
0197 cosphi = cos(proj_parm.phi2);
0198 m2 = pj_msfn(sinphi, cosphi, par.es);
0199 ml2 = pj_qsfn(sinphi, par.e, par.one_es);
0200 if (ml2 == ml1)
0201 BOOST_THROW_EXCEPTION( projection_exception(0) );
0202
0203 proj_parm.n = (m1 * m1 - m2 * m2) / (ml2 - ml1);
0204 }
0205 proj_parm.ec = 1. - .5 * par.one_es * log((1. - par.e) /
0206 (1. + par.e)) / par.e;
0207 proj_parm.c = m1 * m1 + proj_parm.n * ml1;
0208 proj_parm.dd = 1. / proj_parm.n;
0209 proj_parm.rho0 = proj_parm.dd * sqrt(proj_parm.c - proj_parm.n * pj_qsfn(sin(par.phi0),
0210 par.e, par.one_es));
0211 } else {
0212 if (secant) proj_parm.n = .5 * (proj_parm.n + sin(proj_parm.phi2));
0213 proj_parm.n2 = proj_parm.n + proj_parm.n;
0214 proj_parm.c = cosphi * cosphi + proj_parm.n2 * sinphi;
0215 proj_parm.dd = 1. / proj_parm.n;
0216 proj_parm.rho0 = proj_parm.dd * sqrt(proj_parm.c - proj_parm.n2 * sin(par.phi0));
0217 }
0218 }
0219
0220
0221
0222 template <typename Params, typename Parameters, typename T>
0223 inline void setup_aea(Params const& params, Parameters const& par, par_aea<T>& proj_parm)
0224 {
0225 proj_parm.phi1 = 0.0;
0226 proj_parm.phi2 = 0.0;
0227 bool is_phi1_set = pj_param_r<srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1, proj_parm.phi1);
0228 bool is_phi2_set = pj_param_r<srs::spar::lat_2>(params, "lat_2", srs::dpar::lat_2, proj_parm.phi2);
0229
0230
0231 if (! is_phi1_set || ! is_phi2_set) {
0232 bool const use_defaults = ! pj_get_param_b<srs::spar::no_defs>(params, "no_defs", srs::dpar::no_defs);
0233 if (use_defaults) {
0234 if (!is_phi1_set)
0235 proj_parm.phi1 = 29.5;
0236 if (!is_phi2_set)
0237 proj_parm.phi2 = 45.5;
0238 }
0239 }
0240
0241 setup(par, proj_parm);
0242 }
0243
0244
0245 template <typename Params, typename Parameters, typename T>
0246 inline void setup_leac(Params const& params, Parameters const& par, par_aea<T>& proj_parm)
0247 {
0248 static const T half_pi = detail::half_pi<T>();
0249
0250 proj_parm.phi2 = pj_get_param_r<T, srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1);
0251 proj_parm.phi1 = pj_get_param_b<srs::spar::south>(params, "south", srs::dpar::south) ? -half_pi : half_pi;
0252 setup(par, proj_parm);
0253 }
0254
0255 }}
0256 #endif
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 template <typename T, typename Parameters>
0275 struct aea_ellipsoid : public detail::aea::base_aea_ellipsoid<T, Parameters>
0276 {
0277 template <typename Params>
0278 inline aea_ellipsoid(Params const& params, Parameters const& par)
0279 {
0280 detail::aea::setup_aea(params, par, this->m_proj_parm);
0281 }
0282 };
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300 template <typename T, typename Parameters>
0301 struct leac_ellipsoid : public detail::aea::base_aea_ellipsoid<T, Parameters>
0302 {
0303 template <typename Params>
0304 inline leac_ellipsoid(Params const& params, Parameters const& par)
0305 {
0306 detail::aea::setup_leac(params, par, this->m_proj_parm);
0307 }
0308 };
0309
0310 #ifndef DOXYGEN_NO_DETAIL
0311 namespace detail
0312 {
0313
0314
0315 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_aea, aea_ellipsoid)
0316 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_leac, leac_ellipsoid)
0317
0318
0319 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(aea_entry, aea_ellipsoid)
0320 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(leac_entry, leac_ellipsoid)
0321
0322 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(aea_init)
0323 {
0324 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(aea, aea_entry)
0325 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(leac, leac_entry)
0326 }
0327
0328 }
0329 #endif
0330
0331 }
0332
0333 }}
0334
0335 #endif
0336