14 # include <vcl_msvc_warnings.h> 17 #define DBLLONG 4.61168601e18 19 #define D2R 1.745329251994328e-2 51 static double scale_factor2;
52 static double es2, esp2;
54 static double false_easting2;
55 static double false_northing2 ;
57 static double e02,e12,e22,e32;
61 static inline int sign(
double x) {
return (x < 0.0) ? -1 : 1;}
63 static inline double sqr(
double x) {
return x*x; }
67 static double adjust_lon2(
double x)
69 for (
long count = 0; count <=
MAX_VAL; ++count)
74 x -= (sign(x) * vnl_math::twopi);
75 else if (
long(
vnl_math::abs(x / (vnl_math::twopi))) < std::numeric_limits<long>::max())
76 x -=
long((x/vnl_math::twopi)*vnl_math::twopi);
77 else if (((
long)
vnl_math::abs(x / (std::numeric_limits<long>::max() * vnl_math::twopi))) < std::numeric_limits<long>::max())
78 x -= (((
long)(x / (std::numeric_limits<long>::max() * vnl_math::twopi))) * (vnl_math::twopi * std::numeric_limits<long>::max()));
79 else if (((
long)
vnl_math::abs(x / (
DBLLONG * vnl_math::twopi))) < std::numeric_limits<long>::max())
80 x -= (((
long)(x / (
DBLLONG * vnl_math::twopi))) * (vnl_math::twopi *
DBLLONG));
82 x -= (sign(x) * vnl_math::twopi);
88 static double adjust_lat2(
double x)
90 for (
long count = 0; count <=
MAX_VAL; ++count)
95 x -= (sign(x) * vnl_math::pi);
96 else if (((
long)
vnl_math::abs(x / vnl_math::pi)) < std::numeric_limits<long>::max())
97 x -= ((
long)(x / vnl_math::pi))*vnl_math::pi;
98 else if (((
long)
vnl_math::abs(x / (std::numeric_limits<long>::max() * vnl_math::pi))) < std::numeric_limits<long>::max())
99 x -= (((
long)(x / (std::numeric_limits<long>::max() * vnl_math::pi))) * (vnl_math::pi * std::numeric_limits<long>::max()));
100 else if (((
long)
vnl_math::abs(x / (
DBLLONG * vnl_math::pi))) < std::numeric_limits<long>::max())
101 x -= (((
long)(x / (
DBLLONG * vnl_math::pi))) * (vnl_math::pi *
DBLLONG));
103 x -= (sign(x) *vnl_math::pi);
112 static inline double mlfn2(
double e0,
double e1,
double e2,
double e3,
double phi)
114 return e0*phi-e1*std::sin(2.0*phi)+e2*std::sin(4.0*phi)-e3*std::sin(6.0*phi);
119 static void UTM_init2(
double lat_center2,
double r_major,
double e,
int south_flag)
121 scale_factor2 = 0.9996;
123 es2 = e * (double) e;
124 e02 = 1.0-0.25*es2*(1.0+es2/16.0*(3.0+1.25*es2));
125 e12 = 0.375*es2*(1.0+0.25*es2*(1.0+0.46875*es2));
126 e22 = 0.05859375*es2*es2*(1.0+0.75*es2);
127 e32 = es2*es2*es2*(35.0/3072.0);
128 esp2 = es2/(1.0 - es2);
129 ml02 = r_major * mlfn2(e02, e12, e22, e32, lat_center2);
130 false_easting2 = 500000.0;
132 false_northing2 = (south_flag) ? 10000000.0 : 0.0;
147 : a_(6378137), b_(6356752.3142)
156 double& lat,
double& lon ,
double& elev,
158 double utm_central_meridian)
164 utm_central_meridian = (6 * utm_zone) - 183;
166 double lon_center2 = adjust_lon2(utm_central_meridian *
D2R);
167 double lat_center2 = 0.0;
171 UTM_init2(lat_center2,
a_, e, south_flag);
176 double sin_phi, cos_phi, tan_phi;
177 double c, cs, t, ts, n, r, d, ds;
178 double f, h, g, temp;
183 f = std::exp(x/(
a_ * scale_factor2));
185 temp = lat_center2 + y/(
a_ * scale_factor2);
187 con = std::sqrt((1.0 - h * h)/(1.0 + g * g));
191 phi = std::asin(1.0);
193 phi = std::asin(-1.0);
196 phi = std::asin(con);
200 if ((g == 0) && (h == 0))
202 lambda = lon_center2;
206 lambda = adjust_lon2(std::atan2(g,h) + lon_center2);
212 y -= false_northing2;
214 con = (ml02 + y / scale_factor2) /
a_;
219 ((con + e12 * std::sin(2.0*temp_phi) - e22 * std::sin(4.0*temp_phi) + e32 *
220 std::sin(6.0*temp_phi)) / e02) - temp_phi;
222 delta_phi = ((con + e12 * std::sin(2.0*phi) - e22 * std::sin(4.0*phi)) / e02) - phi;
224 temp_phi += delta_phi;
229 std::cout <<
"Transform failed to converge" << std::endl;
234 sin_phi = std::sin(temp_phi);
235 cos_phi = std::cos(temp_phi);
236 tan_phi = std::tan(temp_phi);
237 c = esp2 *
sqr(cos_phi);
241 con = 1.0 - es2 *
sqr(sin_phi);
242 n =
a_ / std::sqrt(con);
243 r = n * (1.0 - es2) / con;
244 d = x / (n * scale_factor2);
247 temp_phi - (n * tan_phi * ds / r) *
248 (0.5 - ds / 24.0 * (5.0 + 3.0 * t + 10.0 * c - 4.0 * cs - 9.0 *
249 esp2 - ds / 30.0 * (61.0 + 90.0 * t + 298.0 *
250 c + 45.0 * ts - 252.0 *
253 adjust_lon2(lon_center2 +
254 (d * (1.0 - ds / 6.0 * (1.0 + 2.0 * t + c - ds / 20.0
255 * (5.0 - 2.0 * c + 28.0 * t -
256 3.0 * cs + 8.0 * esp2 +
257 24.0 * ts))) / cos_phi));
261 phi = vnl_math::pi_over_2 * sign(y);
262 lambda = lon_center2;
266 lat = phi/
D2R; lon = lambda/
D2R, elev = z;
270 double& lat,
double& lon,
272 double utm_central_meridian)
277 south_flag, utm_central_meridian);
282 double& x,
double& y,
int& utm_zone)
285 utm_zone = int((lon+180)/6.0) + 1;
286 double e = std::sqrt(1.0 -
b_*
b_/(
a_*
a_));
290 double utm_central_meridian = 0;
292 utm_central_meridian = (6 * utm_zone) - 183;
296 double lon_center = adjust_lon2(utm_central_meridian *
D2R);
297 double lat_center = 0.0;
299 double phi = adjust_lat2(lat*
D2R);
300 double lambda = adjust_lon2(lon*
D2R);
302 UTM_init2(lat_center,
a_, e, south_flag);
306 double delta_lon = adjust_lon2(lambda - lon_center);
308 double sin_phi = std::sin(phi);
309 double cos_phi = std::cos(phi);
311 double al = cos_phi * delta_lon;
312 double als =
sqr(al);
313 double c = esp2 *
sqr(cos_phi);
314 double tq = std::tan(phi);
316 double con = 1.0 - es2 *
sqr(sin_phi);
317 double n =
a_ / std::sqrt(con);
318 double ml =
a_ * mlfn2(e02, e12, e22, e32, phi);
320 x = scale_factor2 * n * al * (1.0 + (als / 6.0) *
321 (1.0 - t + c + (als / 20.0) *
322 (5.0 - (18.0 * t) +
sqr(t) + (72.0 * c)
326 y = scale_factor2 * (ml - ml02 + n * tq * (als * (0.5 + (als / 24.0) *
A rip-off of the IUE utm_geodedic and geodetic_utm transform classes which allows the GeoPt to suppor...
vnl_bignum abs(vnl_bignum const &x)
vnl_bignum sqr(vnl_bignum const &x)
void transform(int utm_zone, double x, double y, double z, double &lat, double &lon, double &elev, bool south_flag=false, double utm_central_meridian=0)