File indexing completed on 2025-01-18 09:35:42
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 #ifndef BOOST_GEOMETRY_PROJECTIONS_IMW_P_HPP
0041 #define BOOST_GEOMETRY_PROJECTIONS_IMW_P_HPP
0042
0043 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0044 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0045 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0046 #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp>
0047 #include <boost/geometry/srs/projections/impl/pj_param.hpp>
0048 #include <boost/geometry/srs/projections/impl/projects.hpp>
0049
0050 #include <boost/geometry/util/math.hpp>
0051
0052 namespace boost { namespace geometry
0053 {
0054
0055 namespace projections
0056 {
0057 #ifndef DOXYGEN_NO_DETAIL
0058 namespace detail { namespace imw_p
0059 {
0060
0061 static const double tolerance = 1e-10;
0062 static const double epsilon = 1e-10;
0063
0064 template <typename T>
0065 struct point_xy { T x, y; };
0066
0067 enum mode_type {
0068 none_is_zero = 0,
0069 phi_1_is_zero = 1,
0070 phi_2_is_zero = -1
0071 };
0072
0073 template <typename T>
0074 struct par_imw_p
0075 {
0076 T P, Pp, Q, Qp, R_1, R_2, sphi_1, sphi_2, C2;
0077 T phi_1, phi_2, lam_1;
0078 detail::en<T> en;
0079 mode_type mode;
0080 };
0081
0082 template <typename Params, typename T>
0083 inline int phi12(Params const& params,
0084 par_imw_p<T> & proj_parm, T *del, T *sig)
0085 {
0086 int err = 0;
0087
0088 if (!pj_param_r<srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1, proj_parm.phi_1) ||
0089 !pj_param_r<srs::spar::lat_2>(params, "lat_2", srs::dpar::lat_2, proj_parm.phi_2)) {
0090 err = -41;
0091 } else {
0092
0093
0094 *del = 0.5 * (proj_parm.phi_2 - proj_parm.phi_1);
0095 *sig = 0.5 * (proj_parm.phi_2 + proj_parm.phi_1);
0096 err = (fabs(*del) < epsilon || fabs(*sig) < epsilon) ? -42 : 0;
0097 }
0098 return err;
0099 }
0100 template <typename Parameters, typename T>
0101 inline point_xy<T> loc_for(T const& lp_lam, T const& lp_phi,
0102 Parameters const& par,
0103 par_imw_p<T> const& proj_parm,
0104 T *yc)
0105 {
0106 point_xy<T> xy;
0107
0108 if (lp_phi == 0.0) {
0109 xy.x = lp_lam;
0110 xy.y = 0.;
0111 } else {
0112 T xa, ya, xb, yb, xc, D, B, m, sp, t, R, C;
0113
0114 sp = sin(lp_phi);
0115 m = pj_mlfn(lp_phi, sp, cos(lp_phi), proj_parm.en);
0116 xa = proj_parm.Pp + proj_parm.Qp * m;
0117 ya = proj_parm.P + proj_parm.Q * m;
0118 R = 1. / (tan(lp_phi) * sqrt(1. - par.es * sp * sp));
0119 C = sqrt(R * R - xa * xa);
0120 if (lp_phi < 0.) C = - C;
0121 C += ya - R;
0122 if (proj_parm.mode == phi_2_is_zero) {
0123 xb = lp_lam;
0124 yb = proj_parm.C2;
0125 } else {
0126 t = lp_lam * proj_parm.sphi_2;
0127 xb = proj_parm.R_2 * sin(t);
0128 yb = proj_parm.C2 + proj_parm.R_2 * (1. - cos(t));
0129 }
0130 if (proj_parm.mode == phi_1_is_zero) {
0131 xc = lp_lam;
0132 *yc = 0.;
0133 } else {
0134 t = lp_lam * proj_parm.sphi_1;
0135 xc = proj_parm.R_1 * sin(t);
0136 *yc = proj_parm.R_1 * (1. - cos(t));
0137 }
0138 D = (xb - xc)/(yb - *yc);
0139 B = xc + D * (C + R - *yc);
0140 xy.x = D * sqrt(R * R * (1 + D * D) - B * B);
0141 if (lp_phi > 0)
0142 xy.x = - xy.x;
0143 xy.x = (B + xy.x) / (1. + D * D);
0144 xy.y = sqrt(R * R - xy.x * xy.x);
0145 if (lp_phi > 0)
0146 xy.y = - xy.y;
0147 xy.y += C + R;
0148 }
0149 return (xy);
0150 }
0151 template <typename Parameters, typename T>
0152 inline void xy(Parameters const& par, par_imw_p<T> const& proj_parm,
0153 T const& phi,
0154 T *x, T *y, T *sp, T *R)
0155 {
0156 T F;
0157
0158 *sp = sin(phi);
0159 *R = 1./(tan(phi) * sqrt(1. - par.es * *sp * *sp ));
0160 F = proj_parm.lam_1 * *sp;
0161 *y = *R * (1 - cos(F));
0162 *x = *R * sin(F);
0163 }
0164
0165 template <typename T, typename Parameters>
0166 struct base_imw_p_ellipsoid
0167 {
0168 par_imw_p<T> m_proj_parm;
0169
0170
0171
0172 inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0173 {
0174 T yc = 0;
0175 point_xy<T> xy = loc_for(lp_lon, lp_lat, par, m_proj_parm, &yc);
0176 xy_x = xy.x; xy_y = xy.y;
0177 }
0178
0179
0180
0181 inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0182 {
0183 point_xy<T> t;
0184 T yc = 0.0;
0185 int i = 0;
0186 const int n_max_iter = 1000;
0187
0188 lp_lat = this->m_proj_parm.phi_2;
0189 lp_lon = xy_x / cos(lp_lat);
0190 do {
0191 t = loc_for(lp_lon, lp_lat, par, m_proj_parm, &yc);
0192 lp_lat = ((lp_lat - this->m_proj_parm.phi_1) * (xy_y - yc) / (t.y - yc)) + this->m_proj_parm.phi_1;
0193 lp_lon = lp_lon * xy_x / t.x;
0194 i++;
0195 } while (i < n_max_iter &&
0196 (fabs(t.x - xy_x) > tolerance || fabs(t.y - xy_y) > tolerance));
0197
0198 if( i == n_max_iter )
0199 {
0200 lp_lon = lp_lat = HUGE_VAL;
0201 }
0202 }
0203
0204 static inline std::string get_name()
0205 {
0206 return "imw_p_ellipsoid";
0207 }
0208
0209 };
0210
0211
0212 template <typename Params, typename Parameters, typename T>
0213 inline void setup_imw_p(Params const& params, Parameters const& par, par_imw_p<T>& proj_parm)
0214 {
0215 T del, sig, s, t, x1, x2, T2, y1, m1, m2, y2;
0216 int err;
0217
0218 proj_parm.en = pj_enfn<T>(par.es);
0219 if( (err = phi12(params, proj_parm, &del, &sig)) != 0)
0220 BOOST_THROW_EXCEPTION( projection_exception(err) );
0221 if (proj_parm.phi_2 < proj_parm.phi_1) {
0222 del = proj_parm.phi_1;
0223 proj_parm.phi_1 = proj_parm.phi_2;
0224 proj_parm.phi_2 = del;
0225 }
0226 if (pj_param_r<srs::spar::lon_1>(params, "lon_1", srs::dpar::lon_1, proj_parm.lam_1)) {
0227
0228 } else {
0229 sig = fabs(sig * geometry::math::r2d<T>());
0230 if (sig <= 60) sig = 2.;
0231 else if (sig <= 76) sig = 4.;
0232 else sig = 8.;
0233 proj_parm.lam_1 = sig * geometry::math::d2r<T>();
0234 }
0235 proj_parm.mode = none_is_zero;
0236 if (proj_parm.phi_1 != 0.0)
0237 xy(par, proj_parm, proj_parm.phi_1, &x1, &y1, &proj_parm.sphi_1, &proj_parm.R_1);
0238 else {
0239 proj_parm.mode = phi_1_is_zero;
0240 y1 = 0.;
0241 x1 = proj_parm.lam_1;
0242 }
0243 if (proj_parm.phi_2 != 0.0)
0244 xy(par, proj_parm, proj_parm.phi_2, &x2, &T2, &proj_parm.sphi_2, &proj_parm.R_2);
0245 else {
0246 proj_parm.mode = phi_2_is_zero;
0247 T2 = 0.;
0248 x2 = proj_parm.lam_1;
0249 }
0250 m1 = pj_mlfn(proj_parm.phi_1, proj_parm.sphi_1, cos(proj_parm.phi_1), proj_parm.en);
0251 m2 = pj_mlfn(proj_parm.phi_2, proj_parm.sphi_2, cos(proj_parm.phi_2), proj_parm.en);
0252 t = m2 - m1;
0253 s = x2 - x1;
0254 y2 = sqrt(t * t - s * s) + y1;
0255 proj_parm.C2 = y2 - T2;
0256 t = 1. / t;
0257 proj_parm.P = (m2 * y1 - m1 * y2) * t;
0258 proj_parm.Q = (y2 - y1) * t;
0259 proj_parm.Pp = (m2 * x1 - m1 * x2) * t;
0260 proj_parm.Qp = (x2 - x1) * t;
0261 }
0262
0263 }}
0264 #endif
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282 template <typename T, typename Parameters>
0283 struct imw_p_ellipsoid : public detail::imw_p::base_imw_p_ellipsoid<T, Parameters>
0284 {
0285 template <typename Params>
0286 inline imw_p_ellipsoid(Params const& params, Parameters const& par)
0287 {
0288 detail::imw_p::setup_imw_p(params, par, this->m_proj_parm);
0289 }
0290 };
0291
0292 #ifndef DOXYGEN_NO_DETAIL
0293 namespace detail
0294 {
0295
0296
0297 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_imw_p, imw_p_ellipsoid)
0298
0299
0300 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(imw_p_entry, imw_p_ellipsoid)
0301
0302 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(imw_p_init)
0303 {
0304 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(imw_p, imw_p_entry)
0305 }
0306
0307 }
0308 #endif
0309
0310 }
0311
0312 }}
0313
0314 #endif
0315