File indexing completed on 2025-01-18 09:35:46
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_ROBIN_HPP
0041 #define BOOST_GEOMETRY_PROJECTIONS_ROBIN_HPP
0042
0043 #include <boost/geometry/util/math.hpp>
0044
0045 #include <boost/geometry/srs/projections/impl/base_static.hpp>
0046 #include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
0047 #include <boost/geometry/srs/projections/impl/projects.hpp>
0048 #include <boost/geometry/srs/projections/impl/factory_entry.hpp>
0049 #include <boost/geometry/srs/projections/impl/function_overloads.hpp>
0050
0051 namespace boost { namespace geometry
0052 {
0053
0054 namespace projections
0055 {
0056 #ifndef DOXYGEN_NO_DETAIL
0057 namespace detail { namespace robin
0058 {
0059
0060 static const double FXC = 0.8487;
0061 static const double FYC = 1.3523;
0062 static const double C1 = 11.45915590261646417544;
0063 static const double RC1 = 0.08726646259971647884;
0064 static const int n_nodes = 18;
0065 static const double one_plus_eps = 1.000001;
0066 static const double epsilon = 1e-8;
0067
0068 static const int max_iter = 100;
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 template <typename T>
0080 struct coefs {
0081 T c0, c1, c2, c3;
0082 };
0083
0084 template <typename T>
0085 inline const coefs<T> * coefs_x()
0086 {
0087 static const coefs<T> result[] = {
0088 {1.0, 2.2199e-17, -7.15515e-05, 3.1103e-06},
0089 {0.9986, -0.000482243, -2.4897e-05, -1.3309e-06},
0090 {0.9954, -0.00083103, -4.48605e-05, -9.86701e-07},
0091 {0.99, -0.00135364, -5.9661e-05, 3.6777e-06},
0092 {0.9822, -0.00167442, -4.49547e-06, -5.72411e-06},
0093 {0.973, -0.00214868, -9.03571e-05, 1.8736e-08},
0094 {0.96, -0.00305085, -9.00761e-05, 1.64917e-06},
0095 {0.9427, -0.00382792, -6.53386e-05, -2.6154e-06},
0096 {0.9216, -0.00467746, -0.00010457, 4.81243e-06},
0097 {0.8962, -0.00536223, -3.23831e-05, -5.43432e-06},
0098 {0.8679, -0.00609363, -0.000113898, 3.32484e-06},
0099 {0.835, -0.00698325, -6.40253e-05, 9.34959e-07},
0100 {0.7986, -0.00755338, -5.00009e-05, 9.35324e-07},
0101 {0.7597, -0.00798324, -3.5971e-05, -2.27626e-06},
0102 {0.7186, -0.00851367, -7.01149e-05, -8.6303e-06},
0103 {0.6732, -0.00986209, -0.000199569, 1.91974e-05},
0104 {0.6213, -0.010418, 8.83923e-05, 6.24051e-06},
0105 {0.5722, -0.00906601, 0.000182, 6.24051e-06},
0106 {0.5322, -0.00677797, 0.000275608, 6.24051e-06}
0107 };
0108 return result;
0109 }
0110
0111 template <typename T>
0112 inline const coefs<T> * coefs_y()
0113 {
0114 static const coefs<T> result[] = {
0115 {-5.20417e-18, 0.0124, 1.21431e-18, -8.45284e-11},
0116 {0.062, 0.0124, -1.26793e-09, 4.22642e-10},
0117 {0.124, 0.0124, 5.07171e-09, -1.60604e-09},
0118 {0.186, 0.0123999, -1.90189e-08, 6.00152e-09},
0119 {0.248, 0.0124002, 7.10039e-08, -2.24e-08},
0120 {0.31, 0.0123992, -2.64997e-07, 8.35986e-08},
0121 {0.372, 0.0124029, 9.88983e-07, -3.11994e-07},
0122 {0.434, 0.0123893, -3.69093e-06, -4.35621e-07},
0123 {0.4958, 0.0123198, -1.02252e-05, -3.45523e-07},
0124 {0.5571, 0.0121916, -1.54081e-05, -5.82288e-07},
0125 {0.6176, 0.0119938, -2.41424e-05, -5.25327e-07},
0126 {0.6769, 0.011713, -3.20223e-05, -5.16405e-07},
0127 {0.7346, 0.0113541, -3.97684e-05, -6.09052e-07},
0128 {0.7903, 0.0109107, -4.89042e-05, -1.04739e-06},
0129 {0.8435, 0.0103431, -6.4615e-05, -1.40374e-09},
0130 {0.8936, 0.00969686, -6.4636e-05, -8.547e-06},
0131 {0.9394, 0.00840947, -0.000192841, -4.2106e-06},
0132 {0.9761, 0.00616527, -0.000256, -4.2106e-06},
0133 {1.0, 0.00328947, -0.000319159, -4.2106e-06}
0134 };
0135 return result;
0136 }
0137
0138 template <typename T, typename Parameters>
0139 struct base_robin_spheroid
0140 {
0141 inline T v(coefs<T> const& c, T const& z) const
0142 { return (c.c0 + z * (c.c1 + z * (c.c2 + z * c.c3))); }
0143 inline T dv(coefs<T> const& c, T const& z) const
0144 { return (c.c1 + z * (c.c2 + c.c2 + z * 3. * c.c3)); }
0145
0146
0147
0148 inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
0149 {
0150 int i;
0151 T dphi;
0152
0153 i = int_floor((dphi = fabs(lp_lat)) * C1);
0154 if (i < 0) {
0155 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0156 }
0157 if (i >= n_nodes) i = n_nodes - 1;
0158 dphi = geometry::math::r2d<T>() * (dphi - RC1 * i);
0159 xy_x = v(coefs_x<T>()[i], dphi) * FXC * lp_lon;
0160 xy_y = v(coefs_y<T>()[i], dphi) * FYC;
0161 if (lp_lat < 0.) xy_y = -xy_y;
0162 }
0163
0164
0165
0166 inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
0167 {
0168 static const T half_pi = detail::half_pi<T>();
0169 const coefs<T> * coefs_x = robin::coefs_x<T>();
0170 const coefs<T> * coefs_y = robin::coefs_y<T>();
0171
0172 int i;
0173 T t, t1;
0174 coefs<T> coefs_t;
0175 int iters;
0176
0177 lp_lon = xy_x / FXC;
0178 lp_lat = fabs(xy_y / FYC);
0179 if (lp_lat >= 1.) {
0180 if (lp_lat > one_plus_eps) {
0181 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0182 } else {
0183 lp_lat = xy_y < 0. ? -half_pi : half_pi;
0184 lp_lon /= coefs_x[n_nodes].c0;
0185 }
0186 } else {
0187
0188 i = int_floor(lp_lat * n_nodes);
0189 if( i < 0 || i >= n_nodes ) {
0190 BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
0191 }
0192 for (;;) {
0193 if (coefs_y[i].c0 > lp_lat) --i;
0194 else if (coefs_y[i+1].c0 <= lp_lat) ++i;
0195 else break;
0196 }
0197 coefs_t = coefs_y[i];
0198
0199 t = 5. * (lp_lat - coefs_t.c0)/(coefs_y[i+1].c0 - coefs_t.c0);
0200
0201 coefs_t.c0 = (T)(coefs_t.c0 - lp_lat);
0202 for (iters = max_iter; iters ; --iters) {
0203 t -= t1 = v(coefs_t,t) / dv(coefs_t,t);
0204 if (fabs(t1) < epsilon)
0205 break;
0206 }
0207 if( iters == 0 )
0208 BOOST_THROW_EXCEPTION( projection_exception(error_non_convergent) );
0209 lp_lat = (5 * i + t) * geometry::math::d2r<T>();
0210 if (xy_y < 0.) lp_lat = -lp_lat;
0211 lp_lon /= v(coefs_x[i], t);
0212 }
0213 }
0214
0215 static inline std::string get_name()
0216 {
0217 return "robin_spheroid";
0218 }
0219
0220 };
0221
0222
0223 template <typename Parameters>
0224 inline void setup_robin(Parameters& par)
0225 {
0226 par.es = 0.;
0227 }
0228
0229 }}
0230 #endif
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 template <typename T, typename Parameters>
0245 struct robin_spheroid : public detail::robin::base_robin_spheroid<T, Parameters>
0246 {
0247 template <typename Params>
0248 inline robin_spheroid(Params const& , Parameters & par)
0249 {
0250 detail::robin::setup_robin(par);
0251 }
0252 };
0253
0254 #ifndef DOXYGEN_NO_DETAIL
0255 namespace detail
0256 {
0257
0258
0259 BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_robin, robin_spheroid)
0260
0261
0262 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(robin_entry, robin_spheroid)
0263
0264 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(robin_init)
0265 {
0266 BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(robin, robin_entry)
0267 }
0268
0269 }
0270 #endif
0271
0272 }
0273
0274 }}
0275
0276 #endif
0277