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 #ifndef BOOST_GEOMETRY_PROJECTIONS_POLY_HPP
0041 #define BOOST_GEOMETRY_PROJECTIONS_POLY_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/projects.hpp>
0046 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0047 #include <boost/geometry/srs/projections/impl/pj_mlfn.hpp>
0048 #include <boost/geometry/srs/projections/impl/pj_msfn.hpp>
0049
0050 namespace boost { namespace geometry
0051 {
0052
0053 namespace projections
0054 {
0055 #ifndef DOXYGEN_NO_DETAIL
0056 namespace detail { namespace poly
0057 {
0058
0059 static const double tolerance = 1e-10;
0060 static const double conv_tolerance = 1e-10;
0061 static const int n_iter = 10;
0062 static const int i_iter = 20;
0063 static const double i_tolerance = 1.e-12;
0064
0065 template <typename T>
0066 struct par_poly
0067 {
0068 T ml0;
0069 detail::en<T> en;
0070 };
0071
0072 template <typename T, typename Parameters>
0073 struct base_poly_ellipsoid
0074 {
0075 par_poly<T> m_proj_parm;
0076
0077
0078
0079 inline void fwd(Parameters const& par, T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0080 {
0081 T ms, sp, cp;
0082
0083 if (fabs(lp_lat) <= tolerance) {
0084 xy_x = lp_lon;
0085 xy_y = -this->m_proj_parm.ml0;
0086 } else {
0087 sp = sin(lp_lat);
0088 ms = fabs(cp = cos(lp_lat)) > tolerance ? pj_msfn(sp, cp, par.es) / sp : 0.;
0089 xy_x = ms * sin(lp_lon *= sp);
0090 xy_y = (pj_mlfn(lp_lat, sp, cp, this->m_proj_parm.en) - this->m_proj_parm.ml0) + ms * (1. - cos(lp_lon));
0091 }
0092 }
0093
0094
0095
0096 inline void inv(Parameters const& par, T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const
0097 {
0098 xy_y += this->m_proj_parm.ml0;
0099 if (fabs(xy_y) <= tolerance) {
0100 lp_lon = xy_x;
0101 lp_lat = 0.;
0102 } else {
0103 T r, c, sp, cp, s2ph, ml, mlb, mlp, dPhi;
0104 int i;
0105
0106 r = xy_y * xy_y + xy_x * xy_x;
0107 for (lp_lat = xy_y, i = i_iter; i ; --i) {
0108 sp = sin(lp_lat);
0109 s2ph = sp * ( cp = cos(lp_lat));
0110 if (fabs(cp) < i_tolerance) {
0111 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0112 }
0113 c = sp * (mlp = sqrt(1. - par.es * sp * sp)) / cp;
0114 ml = pj_mlfn(lp_lat, sp, cp, this->m_proj_parm.en);
0115 mlb = ml * ml + r;
0116 mlp = par.one_es / (mlp * mlp * mlp);
0117 lp_lat += ( dPhi =
0118 ( ml + ml + c * mlb - 2. * xy_y * (c * ml + 1.) ) / (
0119 par.es * s2ph * (mlb - 2. * xy_y * ml) / c +
0120 2.* (xy_y - ml) * (c * mlp - 1. / s2ph) - mlp - mlp ));
0121 if (fabs(dPhi) <= i_tolerance)
0122 break;
0123 }
0124 if (!i) {
0125 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0126 }
0127 c = sin(lp_lat);
0128 lp_lon = asin(xy_x * tan(lp_lat) * sqrt(1. - par.es * c * c)) / sin(lp_lat);
0129 }
0130 }
0131
0132 static inline std::string get_name()
0133 {
0134 return "poly_ellipsoid";
0135 }
0136
0137 };
0138
0139 template <typename T, typename Parameters>
0140 struct base_poly_spheroid
0141 {
0142 par_poly<T> m_proj_parm;
0143
0144
0145
0146 inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0147 {
0148 T cot, E;
0149
0150 if (fabs(lp_lat) <= tolerance) {
0151 xy_x = lp_lon;
0152 xy_y = this->m_proj_parm.ml0;
0153 } else {
0154 cot = 1. / tan(lp_lat);
0155 xy_x = sin(E = lp_lon * sin(lp_lat)) * cot;
0156 xy_y = lp_lat - par.phi0 + cot * (1. - cos(E));
0157 }
0158 }
0159
0160
0161
0162 inline void inv(Parameters const& par, T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const
0163 {
0164 T B, dphi, tp;
0165 int i;
0166
0167 if (fabs(xy_y = par.phi0 + xy_y) <= tolerance) {
0168 lp_lon = xy_x;
0169 lp_lat = 0.;
0170 } else {
0171 lp_lat = xy_y;
0172 B = xy_x * xy_x + xy_y * xy_y;
0173 i = n_iter;
0174 do {
0175 tp = tan(lp_lat);
0176 lp_lat -= (dphi = (xy_y * (lp_lat * tp + 1.) - lp_lat -
0177 .5 * ( lp_lat * lp_lat + B) * tp) /
0178 ((lp_lat - xy_y) / tp - 1.));
0179 } while (fabs(dphi) > conv_tolerance && --i);
0180 if (! i) {
0181 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0182 }
0183 lp_lon = asin(xy_x * tan(lp_lat)) / sin(lp_lat);
0184 }
0185 }
0186
0187 static inline std::string get_name()
0188 {
0189 return "poly_spheroid";
0190 }
0191
0192 };
0193
0194
0195 template <typename Parameters, typename T>
0196 inline void setup_poly(Parameters const& par, par_poly<T>& proj_parm)
0197 {
0198 if (par.es != 0.0) {
0199 proj_parm.en = pj_enfn<T>(par.es);
0200 proj_parm.ml0 = pj_mlfn(par.phi0, sin(par.phi0), cos(par.phi0), proj_parm.en);
0201 } else {
0202 proj_parm.ml0 = -par.phi0;
0203 }
0204 }
0205
0206 }}
0207 #endif
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222 template <typename T, typename Parameters>
0223 struct poly_ellipsoid : public detail::poly::base_poly_ellipsoid<T, Parameters>
0224 {
0225 template <typename Params>
0226 inline poly_ellipsoid(Params const& , Parameters const& par)
0227 {
0228 detail::poly::setup_poly(par, this->m_proj_parm);
0229 }
0230 };
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245 template <typename T, typename Parameters>
0246 struct poly_spheroid : public detail::poly::base_poly_spheroid<T, Parameters>
0247 {
0248 template <typename Params>
0249 inline poly_spheroid(Params const& , Parameters const& par)
0250 {
0251 detail::poly::setup_poly(par, this->m_proj_parm);
0252 }
0253 };
0254
0255 #ifndef DOXYGEN_NO_DETAIL
0256 namespace detail
0257 {
0258
0259
0260 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_poly, poly_spheroid, poly_ellipsoid)
0261
0262
0263 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(poly_entry, poly_spheroid, poly_ellipsoid)
0264
0265 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(poly_init)
0266 {
0267 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(poly, poly_entry)
0268 }
0269
0270 }
0271 #endif
0272
0273 }
0274
0275 }}
0276
0277 #endif
0278