00001 #include "vpgl_datum_conversion.h"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <vcl_cmath.h>
00028 #include <vnl/vnl_math.h>
00029
00030 #define degree_to_rad (vnl_math::pi_over_180) // Degree to rad conv.
00031 #define dcos(x) vcl_cos((x)*vnl_math::pi_over_180)
00032 #define dsin(x) vcl_sin((x)*vnl_math::pi_over_180)
00033 #define EPSILON 1.0e-12
00034
00035
00036 double ipow(double x, int i)
00037 {
00038 double y = 1.0;
00039 if (i<0) { i *= -1; x = y/x; }
00040 while (i) { if (i%2) y*=x; i/=2; x*=x; }
00041 return y;
00042 }
00043
00044
00045
00046
00047
00048
00049
00050
00051 void wgs72_to_wgs84_deltas
00052 (double phi,
00053 double *delta_phi,
00054 double *delta_lamda,
00055 double *delta_hgt)
00056 {
00057
00058
00059
00060 double delta_f, a, delta_a, delta_r;
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 delta_f = .3121057e-7;
00074 a = 6378135;
00075 delta_a = 2.000;
00076 delta_r = 1.400;
00077
00078
00079
00080 *delta_phi = (4.5 * dcos(phi))/(a * dsin(1/3600.0)) +
00081 (delta_f * dsin(2.0 * phi)) / (dsin(1/3600.0));
00082
00083 *delta_lamda = .554;
00084
00085 *delta_hgt = 4.5 * dsin(phi) + a * delta_f * (dsin(phi) * dsin(phi))
00086 - delta_a + delta_r;
00087
00088
00089 *delta_phi /= 3600.0;
00090 *delta_lamda /= 3600.0;
00091 }
00092
00093
00094
00095
00096
00097 void wgs72_to_wgs84
00098 (
00099 double phi,
00100 double lamda,
00101 double height,
00102 double *wgs84_phi,
00103 double *wgs84_lamda,
00104 double *wgs84_hgt)
00105 {
00106 double delta_phi, delta_lamda, delta_hgt;
00107
00108 wgs72_to_wgs84_deltas(phi, &delta_phi, &delta_lamda, &delta_hgt);
00109
00110 *wgs84_phi = phi + delta_phi;
00111 *wgs84_lamda = lamda + delta_lamda;
00112 *wgs84_hgt = height + delta_hgt;
00113 }
00114
00115
00116
00117
00118
00119 void wgs84_to_wgs72
00120 (
00121 double phi,
00122 double lamda,
00123 double height,
00124 double *wgs72_phi,
00125 double *wgs72_lamda,
00126 double *wgs72_hgt)
00127 {
00128 double delta_phi, delta_lamda, delta_hgt;
00129
00130 wgs72_to_wgs84_deltas(phi, &delta_phi, &delta_lamda, &delta_hgt);
00131
00132 *wgs72_phi = phi - delta_phi;
00133 *wgs72_lamda = lamda - delta_lamda;
00134 *wgs72_hgt = height - delta_hgt;
00135 }
00136
00137
00138
00139
00140
00141
00142 void nad27m_to_wgs84_deltas
00143 (double phi,
00144 double lamda,
00145 double ,
00146 double *delta_phi,
00147 double *delta_lamda,
00148 double *delta_hgt)
00149 {
00150
00151
00152
00153
00154 double U,V, K;
00155
00156 K = .05235988;
00157
00158
00159 if (lamda < 0)
00160 lamda += 360.0;
00161
00162
00163
00164 U = K * (phi - 20);
00165 V = K * (lamda -290);
00166
00167 *delta_phi = .67775 + 10.02259*U - 18.72391*V + 12.66341*ipow(U,2) - 32.47686*ipow(V,2) - 52.70768*ipow(U,3) - 13.86527*U*ipow(V,2)
00168 - 16.82734*ipow(V,3) - 59.54646*V*ipow(U,3) + 120.64887*ipow(U,5) + 7.23362*ipow(U,2)*ipow(V,3) + 95.89131*ipow(U,5)*V -2.89651*U*ipow(V,5)
00169 - 1.23778*ipow(V,6) + 70.19213*ipow(U,8) + .84596*ipow(U,2)*ipow(V,6) + .14848*ipow(V,8) - 3.83786*ipow(U,3)*ipow(V,6) + .10405*U*ipow(V,9)
00170 + 30.09795*ipow(U,8)*ipow(V,3) + 12.93585*ipow(U,6)*ipow(V,6) - .58747*ipow(U,3)*ipow(V,9) + .7485*ipow(U,4)*ipow(V,9) +
00171 6.32462*ipow(U,8)*ipow(V,7) - .12736*ipow(U,6)*ipow(V,9) - .59993*ipow(U,9)*ipow(V,9);
00172
00173 *delta_lamda = -.33643 - 3.11777*V -5.16881*ipow(U,2) - 3.17318*ipow(V,2) - 34.59331*ipow(U,3) + .97215*U*ipow(V,2) - .5818*ipow(V,3) +
00174 223.78114*ipow(U,5) + 358.07266*ipow(U,6) + 270.68064*ipow(U,7) - 87.99549*ipow(U,6)*V - .09789*U*ipow(V,6) + 636.41982*ipow(U,7)*V -
00175 729.91514*ipow(U,6)*ipow(V,2) - .60122*ipow(U,3)*ipow(V,5) - 375.38863*ipow(U,6)*ipow(V,3) - 6.97538*ipow(U,4)*ipow(V,5) -
00176 .00138*ipow(V,9) - 363.45977*ipow(U,9)*V + 50.19955*ipow(U,8)*ipow(V,2) - 12.01575*ipow(U,5)*ipow(V,6) - .4314*ipow(U,6)*ipow(V,9) +
00177 .43907*ipow(U,9)*ipow(V,9);
00178
00179 *delta_hgt = -20.013 + 12.815*U - 8.084*V +74.122*ipow(U,2)*V +39.523*ipow(U,2)*ipow(V,2) - 23.158*ipow(U,4)*V + 194.444*ipow(U,6) +
00180 36.797*ipow(U,5)*V + .181*U*ipow(V,5) - 292.155*ipow(U,8) + 3.749*ipow(U,5)*ipow(V,5) +2.537*ipow(U,8)*ipow(V,6);
00181
00182
00183 *delta_phi /= 3600.0;
00184 *delta_lamda /= 3600.0;
00185 }
00186
00187
00188
00189
00190
00191
00192 void nad27m_to_wgs84
00193 (double phi,
00194 double lamda,
00195 double height,
00196 double *wgs84_phi,
00197 double *wgs84_lamda,
00198 double *wgs84_hgt)
00199 {
00200 double delta_phi, delta_lamda, delta_hgt;
00201
00202 nad27m_to_wgs84_deltas(phi, lamda, height,
00203 &delta_phi, &delta_lamda, &delta_hgt);
00204
00205 *wgs84_phi = phi + delta_phi;
00206 *wgs84_lamda = lamda + delta_lamda;
00207 *wgs84_hgt = height + delta_hgt;
00208 }
00209
00210
00211
00212
00213
00214
00215 void wgs84_to_nad27m
00216 (double phi,
00217 double lamda,
00218 double height,
00219 double *nad27m_phi,
00220 double *nad27m_lamda,
00221 double *nad27m_hgt)
00222 {
00223 double delta_phi, delta_lamda, delta_hgt;
00224
00225 nad27m_to_wgs84_deltas(phi, lamda, height,
00226 &delta_phi, &delta_lamda, &delta_hgt);
00227
00228 *nad27m_phi = phi - delta_phi;
00229 *nad27m_lamda = lamda - delta_lamda;
00230 *nad27m_hgt = height - delta_hgt;
00231 }
00232
00233
00234
00235
00236
00237
00238 void nad27n_to_wgs84_deltas
00239 (double phi,
00240 double lamda,
00241 double ,
00242 double *delta_phi,
00243 double *delta_lamda,
00244 double *delta_hgt)
00245 {
00246
00247
00248
00249 double U,V, K;
00250
00251 K = .05235988;
00252
00253
00254 if (lamda < 0)
00255 lamda += 360.0;
00256
00257 U = K * (phi - 37.0);
00258 V = K * (lamda -265.0);
00259
00260
00261
00262 *delta_phi = .16984 - .76173*U + .09585*V +1.09919*ipow(U,2) - 4.57801*ipow(U,3) - 1.13239*ipow(U,2)*V + .49831*ipow(V,3)
00263 - .98399*ipow(U,3)*V + .12415*U*ipow(V,3) + .1145*ipow(V,4) +27.05396*ipow(U,5) + 2.03449*ipow(U,4)*V +.73357*ipow(U,2)*ipow(V,3)
00264 - .37548*ipow(V,5) - .14197*ipow(V,6) -59.96555*ipow(U,7) + .07439*ipow(V,7) -4.76082*ipow(U,8) + .03385*ipow(V,8) +
00265 49.0432*ipow(U,9) - 1.30575*ipow(U,6)*ipow(V,3) - .07653*ipow(U,3)*ipow(V,9) + .08646*ipow(U,4)*ipow(V,9);
00266
00267 *delta_lamda = -.88437 + 2.05061*V + .26361*ipow(U,2) - .76804*U*V + .13374*ipow(V,2) - 1.31974*ipow(U,3) - .52162*ipow(U,2)*V -
00268 1.05853*U*ipow(V,2) -.49211*ipow(U,2)*ipow(V,2) + 2.17204*U*ipow(V,3) -.06004*ipow(V,4) +.30139*ipow(U,4)*V + 1.88585*U*ipow(V,4)
00269 - .81162*U*ipow(V,5) -.05183*ipow(V,6) -.96723*U*ipow(V,6) -.12948*ipow(U,3)*ipow(V,5) + 3.41827*ipow(U,9) -.44507*ipow(U,8)*V
00270 +.18882*U*ipow(V,8) -.01444*ipow(V,9) +.04794*U*ipow(V,9) -.59013*ipow(U,9)*ipow(V,3);
00271
00272 *delta_hgt = -36.526 +3.9*U -4.723*V -21.553*ipow(U,2) +7.294*U*V +8.886*ipow(V,2) -8.44*ipow(U,2)*V -2.93*U*ipow(V,2) +
00273 56.937*ipow(U,4) -58.756*ipow(U,3)*V -4.061*ipow(V,4) +4.447*ipow(U,4)*V +4.903*ipow(U,2)*ipow(V,3) -55.873*ipow(U,6)
00274 +212.005*ipow(U,5)*V + 3.081*ipow(V,6) -254.511*ipow(U,7)*V -.756*ipow(V,8) +30.654*ipow(U,8)*V -.122*U*ipow(V,9);
00275
00276
00277 *delta_phi /= 3600.0;
00278 *delta_lamda /= 3600.0;
00279 }
00280
00281
00282
00283
00284
00285
00286 void nad27n_to_wgs84
00287 (double phi,
00288 double lamda,
00289 double height,
00290 double *wgs84_phi,
00291 double *wgs84_lamda,
00292 double *wgs84_hgt)
00293 {
00294 double delta_phi, delta_lamda, delta_hgt;
00295
00296 nad27n_to_wgs84_deltas(phi, lamda, height,
00297 &delta_phi, &delta_lamda, &delta_hgt);
00298
00299 *wgs84_phi = phi + delta_phi;
00300 *wgs84_lamda = lamda + delta_lamda;
00301 *wgs84_hgt = height + delta_hgt;
00302 }
00303
00304
00305
00306
00307
00308 void wgs84_to_nad27n
00309 (double phi,
00310 double lamda,
00311 double height,
00312 double *nad27n_phi,
00313 double *nad27n_lamda,
00314 double *nad27n_hgt)
00315 {
00316 double delta_phi, delta_lamda, delta_hgt;
00317
00318 nad27n_to_wgs84_deltas(phi, lamda, height,
00319 &delta_phi, &delta_lamda, &delta_hgt);
00320
00321 *nad27n_phi = phi - delta_phi;
00322 *nad27n_lamda = lamda - delta_lamda;
00323 *nad27n_hgt = height - delta_hgt;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 void nad27n_to_wgs84_alternate
00344 (double nad27_lat, double nad27_lon, double nad27_el,
00345 double *wgs84_lat, double *wgs84_lon, double *wgs84_el)
00346 {
00347 double u,v,k;
00348
00349 double a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14;
00350 double a15,a16,a17,a18,a19,a20,a21,a22,a23;
00351
00352 double b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14;
00353 double b15,b16,b17,b18,b19,b20,b21,b22,b23;
00354
00355 double c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14;
00356 double c15,c16,c17,c18,c19,c20;
00357
00358 double delta_lat;
00359 double delta_lon;
00360 double delta_H;
00361 #ifdef DEBUG_DATUM
00362 double N_height;
00363 #endif
00364
00365 double delta_lat_p;
00366 double delta_lon_p;
00367
00368 #ifdef DEBUG_DATUM
00369 double prin_lat_rad;
00370 double ft_lat;
00371 double ft_lon;
00372 double c_error;
00373 #endif
00374
00375 #if 0
00376 int lon_int;
00377 double lon_int_fl;
00378 double lon_frac;
00379 #endif
00380
00381 #ifdef DEBUG_DATUM
00382 double new_lat;
00383 double new_lon;
00384 #endif
00385
00386 double prin_lat;
00387 double prin_lon;
00388
00389 #ifdef DEBUG_DATUM
00390
00391
00392 vcl_cout << "\n NAD27 to WGS84 Conversion routine\n\n"
00393 << " Enter latitude and longitude : ";
00394 vcl_cin >> nad27_lat >> nad27_lon;
00395
00396 #endif
00397
00398 prin_lat = (double) nad27_lat;
00399 prin_lon = (double) nad27_lon;
00400
00401 #ifdef DEBUG_DATUM
00402 prin_lat_rad = prin_lat * degree_to_rad;
00403 #endif
00404
00405
00406
00407
00408
00409 if (prin_lon < 0)
00410 prin_lon = 360.0 + prin_lon;
00411
00412
00413 k = .05235988;
00414 u = k*(prin_lat - 37);
00415 v = k*(prin_lon - 265);
00416
00417
00418
00419 a1 = 0.16984;
00420 a2 = -0.76173;
00421 a3 = 0.09585;
00422 a4 = 1.09919;
00423 a5 = -4.57801;
00424 a6 = -1.13239;
00425 a7 = 0.49831;
00426 a8 = -.98399;
00427 a9 = 0.12415;
00428 a10 = 0.11450;
00429 a11 = 27.05396;
00430 a12 = 2.03449;
00431 a13 = 0.73357;
00432 a14 = -0.37548;
00433 a15 = -0.14197;
00434 a16 = -59.96555;
00435 a17 = 0.07439;
00436 a18 = -4.76082;
00437 a19 = 0.03385;
00438 a20 = 49.04320;
00439 a21 = -1.30575;
00440 a22 = -0.07653;
00441 a23 = 0.08646;
00442
00443 delta_lat = a1 + a2*u + a3*v + a4*u*u + a5*u*u*u + a6*u*u*v
00444 + a7*v*v*v + a8*u*u*u*v + a9*u*v*v*v + a10*v*v*v*v
00445 + a11*u*u*u*u*u + a12*u*u*u*u*v + a13*u*u*v*v*v
00446 + a14*v*v*v*v*v + a15*v*v*v*v*v*v + a16*u*u*u*u*u*u*u
00447 + a17*v*v*v*v*v*v*v + a18*u*u*u*u*u*u*u*u
00448 + a19*v*v*v*v*v*v*v*v + a20*u*u*u*u*u*u*u*u*u
00449 + a21*u*u*u*u*u*u*v*v*v + a22*u*u*u*v*v*v*v*v*v*v*v*v
00450 + a23*u*u*u*u*v*v*v*v*v*v*v*v*v;
00451
00452
00453
00454 b1 = -0.88437;
00455 b2 = 2.05061;
00456 b3 = 0.26361;
00457 b4 = -0.76804;
00458 b5 = 0.13374;
00459 b6 = -1.31974;
00460 b7 = -0.52162;
00461 b8 = -1.05853;
00462 b9 = -0.49211;
00463 b10 = 2.17204;
00464 b11 = -0.06004;
00465 b12 = 0.30139;
00466 b13 = 1.88585;
00467 b14 = -0.81162;
00468 b15 = -0.05183;
00469 b16 = -0.96723;
00470 b17 = -.12948;
00471 b18 = 3.41827;
00472 b19 = -0.44507;
00473 b20 = 0.18882;
00474 b21 = -0.01444;
00475 b22 = 0.04794;
00476 b23 = -0.59013;
00477
00478 delta_lon = b1 + b2*v + b3*u*u + b4*u*v + b5*v*v + b6*u*u*u
00479 + b7*u*u*v + b8*u*v*v + b9*u*u*v*v + b10*u*v*v*v
00480 + b11*v*v*v*v + b12*u*u*u*u*v + b13*u*v*v*v*v
00481 + b14*u*v*v*v*v*v + b15*v*v*v*v*v*v
00482 + b16*u*v*v*v*v*v*v + b17*u*u*u*v*v*v*v*v
00483 + b18*u*u*u*u*u*u*u*u*u + b19*u*u*u*u*u*u*u*u*v
00484 + b20*u*v*v*v*v*v*v*v*v + b21*v*v*v*v*v*v*v*v*v
00485 + b22*u*v*v*v*v*v*v*v*v*v + b23*u*u*u*u*u*u*u*u*u*v*v*v;
00486
00487
00488 c1 = -36.526;
00489 c2 = 3.900;
00490 c3 = -4.723;
00491 c4 = -21.553;
00492 c5 = 7.294;
00493 c6 = 8.886;
00494 c7 = -8.440;
00495 c8 = -2.930;
00496 c9 = 56.937;
00497 c10 = -58.756;
00498 c11 = -4.061;
00499 c12 = 4.447;
00500 c13 = 4.903;
00501 c14 = -55.873;
00502 c15 = 212.005;
00503 c16 = 3.081;
00504 c17 = -254.511;
00505 c18 = -0.756;
00506 c19 = 30.654;
00507 c20 = -0.122;
00508
00509 delta_H = c1 + c2*u + c3*v + c4*u*u + c5*u*v + c6*v*v + c7*u*u*v
00510 + c8*u*v*v + c9*u*u*u*u + c10*u*u*u*v + c11*v*v*v*v
00511 + c12*u*u*u*u*v + c13*u*u*v*v*v + c14*u*u*u*u*u*u
00512 + c15*u*u*u*u*u*v + c16*v*v*v*v*v*v + c17*u*u*u*u*u*u*u*v
00513 + c18*v*v*v*v*v*v*v*v + c19*u*u*u*u*u*u*u*u*v
00514 + c20*v*v*v*v*v*v*v*v*v;
00515
00516
00517 #ifdef DEBUG_DATUM
00518 double d1 = 5.068;
00519 double d2 = -11.570;
00520 double d3 = -8.574;
00521 double d4 = 27.839;
00522 double d5 = -51.911;
00523 double d6 = 29.496;
00524 double d7 = 28.343;
00525 double d8 = 24.481;
00526 double d9 = 11.424;
00527 double d10 = 132.550;
00528 double d11 = -110.232;
00529 double d12 = 41.018;
00530 double d13 = -64.953;
00531 double d14 = -128.293;
00532 double d15 = 51.241;
00533 double d16 = -4.326;
00534 double d17 = 104.097;
00535 double d18 = -128.031;
00536 double d19 = 110.694;
00537 double d20 = 36.330;
00538 double d21 = 243.149;
00539 double d22 = -15.790;
00540 double d23 = -38.043;
00541 double d24 = -40.277;
00542 double d25 = 2.746;
00543 double d26 = -7.321;
00544 double d27 = -394.404;
00545 double d28 = -927.540;
00546 double d29 = 63.390;
00547 double d30 = 10.626;
00548 double d31 = -0.520;
00549 double d32 = -117.207;
00550 double d33 = 16.352;
00551
00552 N_height = d1 + d2*u + d3*v + d4*u*u + d5*u*v + d6*v*v + d7*u*u*u
00553 + d8*u*v*v + d9*v*v*v + d10*u*u*u*v + d11*u*u*v*v
00554 + d12*u*v*v*v + d13*v*v*v*v + d14*u*u*u*v*v + d15*u*v*v*v*v
00555 + d16*v*v*v*v*v + d17*u*u*u*u*v*v + d18*u*u*u*v*v*v
00556 + d19*u*u*v*v*v*v + d20*v*v*v*v*v*v + d21*u*u*u*u*u*u*v
00557 + d22*u*u*v*v*v*v*v + d23*u*v*v*v*v*v*v + d24*u*u*v*v*v*v*v*v
00558 + d25*u*v*v*v*v*v*v*v + d26*v*v*v*v*v*v*v*v
00559 + d27*u*u*u*u*u*u*u*u*u + d28*u*u*u*u*u*u*u*u*v
00560 + d29*u*u*u*u*v*v*v*v*v + d30*u*v*v*v*v*v*v*v*v
00561 + d31*u*v*v*v*v*v*v*v*v*v + d32*u*u*u*u*u*u*u*u*v*v*v*v
00562 + d33*u*u*u*u*u*v*v*v*v*v*v*v*v;
00563 #endif
00564
00565 delta_lat_p = (double)delta_lat;
00566 delta_lon_p = (double)delta_lon;
00567
00568 #ifdef DEBUG_DATUM
00569 ft_lat = 101.0 * delta_lat_p;
00570 ft_lon = 101.0 * vcl_cos(prin_lat_rad) * delta_lon_p;
00571
00572 c_error = (double)vcl_sqrt(ft_lat*ft_lat + ft_lon*ft_lon);
00573 #endif
00574
00575 *wgs84_lat = nad27_lat + (delta_lat_p/3600.0);
00576 *wgs84_lon = nad27_lon + (delta_lon_p/3600.0);
00577 *wgs84_el = nad27_el + delta_H;
00578
00579 #ifdef DEBUG_DATUM
00580 new_lat = *wgs84_lat;
00581 new_lon = *wgs84_lon;
00582 vcl_cout << "\n d_lat = " << delta_lat
00583 << "\n d_lon = " << delta_lon
00584 << "\n d_H = " << delta_H
00585 << "\n N = " << N_height
00586 << "\n circular error = " << c_error
00587 << "\n New Lat = " << new_lat << ", New Lon =\n" << new_lon
00588 << '\n';
00589 #endif
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599 void wgs84_to_nad27n_alternate
00600 (double wgs84_lat, double wgs84_lon, double wgs84_el,
00601 double *nad27n_lat, double *nad27n_lon, double *nad27n_el)
00602 {
00603 double u,v,k;
00604
00605 double a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14;
00606 double a15,a16,a17,a18,a19,a20,a21,a22,a23;
00607
00608 double b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14;
00609 double b15,b16,b17,b18,b19,b20,b21,b22,b23;
00610
00611 double c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14;
00612 double c15,c16,c17,c18,c19,c20;
00613
00614 double delta_lat;
00615 double delta_lon;
00616 double delta_H;
00617 #ifdef DEBUG_DATUM
00618 double N_height;
00619 #endif
00620
00621 double delta_lat_p;
00622 double delta_lon_p;
00623
00624 #ifdef DEBUG_DATUM
00625 double prin_lat_rad;
00626 double ft_lat;
00627 double ft_lon;
00628 double c_error;
00629 #endif
00630
00631 #if 0
00632 int lon_int;
00633 double lon_int_fl;
00634 double lon_frac;
00635 #endif
00636
00637 #ifdef DEBUG_DATUM
00638 double new_lat;
00639 double new_lon;
00640 #endif
00641
00642 double prin_lat;
00643 double prin_lon;
00644
00645 #ifdef DEBUG_DATUM
00646
00647
00648 vcl_cout << "\n wgs84 to NAD27N Conversion routine\n\n";
00649 " Enter latitude, longitude ";
00650 vcl_cin >> wgs84_lat >> wgs84_lon;
00651
00652 #endif
00653
00654 prin_lat = (double) wgs84_lat;
00655 prin_lon = (double) wgs84_lon;
00656
00657 #ifdef DEBUG_DATUM
00658 prin_lat_rad = prin_lat * degree_to_rad;
00659 #endif
00660
00661
00662
00663
00664
00665 if (prin_lon < 0)
00666 prin_lon = 360.0 + prin_lon;
00667
00668
00669 k = .05235988;
00670 u = k*(prin_lat - 37);
00671 v = k*(prin_lon - 265);
00672
00673
00674
00675 a1 = 0.16984;
00676 a2 = -0.76173;
00677 a3 = 0.09585;
00678 a4 = 1.09919;
00679 a5 = -4.57801;
00680 a6 = -1.13239;
00681 a7 = 0.49831;
00682 a8 = -.98399;
00683 a9 = 0.12415;
00684 a10 = 0.11450;
00685 a11 = 27.05396;
00686 a12 = 2.03449;
00687 a13 = 0.73357;
00688 a14 = -0.37548;
00689 a15 = -0.14197;
00690 a16 = -59.96555;
00691 a17 = 0.07439;
00692 a18 = -4.76082;
00693 a19 = 0.03385;
00694 a20 = 49.04320;
00695 a21 = -1.30575;
00696 a22 = -0.07653;
00697 a23 = 0.08646;
00698
00699 delta_lat = a1 + a2*u + a3*v + a4*u*u + a5*u*u*u + a6*u*u*v
00700 + a7*v*v*v + a8*u*u*u*v + a9*u*v*v*v + a10*v*v*v*v
00701 + a11*u*u*u*u*u + a12*u*u*u*u*v + a13*u*u*v*v*v
00702 + a14*v*v*v*v*v + a15*v*v*v*v*v*v + a16*u*u*u*u*u*u*u
00703 + a17*v*v*v*v*v*v*v + a18*u*u*u*u*u*u*u*u
00704 + a19*v*v*v*v*v*v*v*v + a20*u*u*u*u*u*u*u*u*u
00705 + a21*u*u*u*u*u*u*v*v*v + a22*u*u*u*v*v*v*v*v*v*v*v*v
00706 + a23*u*u*u*u*v*v*v*v*v*v*v*v*v;
00707
00708
00709
00710 b1 = -0.88437;
00711 b2 = 2.05061;
00712 b3 = 0.26361;
00713 b4 = -0.76804;
00714 b5 = 0.13374;
00715 b6 = -1.31974;
00716 b7 = -0.52162;
00717 b8 = -1.05853;
00718 b9 = -0.49211;
00719 b10 = 2.17204;
00720 b11 = -0.06004;
00721 b12 = 0.30139;
00722 b13 = 1.88585;
00723 b14 = -0.81162;
00724 b15 = -0.05183;
00725 b16 = -0.96723;
00726 b17 = -.12948;
00727 b18 = 3.41827;
00728 b19 = -0.44507;
00729 b20 = 0.18882;
00730 b21 = -0.01444;
00731 b22 = 0.04794;
00732 b23 = -0.59013;
00733
00734 delta_lon = b1 + b2*v + b3*u*u + b4*u*v + b5*v*v + b6*u*u*u
00735 + b7*u*u*v + b8*u*v*v + b9*u*u*v*v + b10*u*v*v*v
00736 + b11*v*v*v*v + b12*u*u*u*u*v + b13*u*v*v*v*v
00737 + b14*u*v*v*v*v*v + b15*v*v*v*v*v*v
00738 + b16*u*v*v*v*v*v*v + b17*u*u*u*v*v*v*v*v
00739 + b18*u*u*u*u*u*u*u*u*u + b19*u*u*u*u*u*u*u*u*v
00740 + b20*u*v*v*v*v*v*v*v*v + b21*v*v*v*v*v*v*v*v*v
00741 + b22*u*v*v*v*v*v*v*v*v*v + b23*u*u*u*u*u*u*u*u*u*v*v*v;
00742
00743
00744 c1 = -36.526;
00745 c2 = 3.900;
00746 c3 = -4.723;
00747 c4 = -21.553;
00748 c5 = 7.294;
00749 c6 = 8.886;
00750 c7 = -8.440;
00751 c8 = -2.930;
00752 c9 = 56.937;
00753 c10 = -58.756;
00754 c11 = -4.061;
00755 c12 = 4.447;
00756 c13 = 4.903;
00757 c14 = -55.873;
00758 c15 = 212.005;
00759 c16 = 3.081;
00760 c17 = -254.511;
00761 c18 = -0.756;
00762 c19 = 30.654;
00763 c20 = -0.122;
00764
00765 delta_H = c1 + c2*u + c3*v + c4*u*u + c5*u*v + c6*v*v + c7*u*u*v
00766 + c8*u*v*v + c9*u*u*u*u + c10*u*u*u*v + c11*v*v*v*v
00767 + c12*u*u*u*u*v + c13*u*u*v*v*v + c14*u*u*u*u*u*u
00768 + c15*u*u*u*u*u*v + c16*v*v*v*v*v*v + c17*u*u*u*u*u*u*u*v
00769 + c18*v*v*v*v*v*v*v*v + c19*u*u*u*u*u*u*u*u*v
00770 + c20*v*v*v*v*v*v*v*v*v;
00771
00772 #ifdef DEBUG_DATUM
00773 d1 = 5.068;
00774 d2 = -11.570;
00775 d3 = -8.574;
00776 d4 = 27.839;
00777 d5 = -51.911;
00778 d6 = 29.496;
00779 d7 = 28.343;
00780 d8 = 24.481;
00781 d9 = 11.424;
00782 d10 = 132.550;
00783 d11 = -110.232;
00784 d12 = 41.018;
00785 d13 = -64.953;
00786 d14 = -128.293;
00787 d15 = 51.241;
00788 d16 = -4.326;
00789 d17 = 104.097;
00790 d18 = -128.031;
00791 d19 = 110.694;
00792 d20 = 36.330;
00793 d21 = 243.149;
00794 d22 = -15.790;
00795 d23 = -38.043;
00796 d24 = -40.277;
00797 d25 = 2.746;
00798 d26 = -7.321;
00799 d27 = -394.404;
00800 d28 = -927.540;
00801 d29 = 63.390;
00802 d30 = 10.626;
00803 d31 = -0.520;
00804 d32 = -117.207;
00805 d33 = 16.352;
00806
00807 N_height = d1 + d2*u + d3*v + d4*u*u + d5*u*v + d6*v*v + d7*u*u*u
00808 + d8*u*v*v + d9*v*v*v + d10*u*u*u*v + d11*u*u*v*v
00809 + d12*u*v*v*v + d13*v*v*v*v + d14*u*u*u*v*v + d15*u*v*v*v*v
00810 + d16*v*v*v*v*v + d17*u*u*u*u*v*v + d18*u*u*u*v*v*v
00811 + d19*u*u*v*v*v*v + d20*v*v*v*v*v*v + d21*u*u*u*u*u*u*v
00812 + d22*u*u*v*v*v*v*v + d23*u*v*v*v*v*v*v + d24*u*u*v*v*v*v*v*v
00813 + d25*u*v*v*v*v*v*v*v + d26*v*v*v*v*v*v*v*v
00814 + d27*u*u*u*u*u*u*u*u*u + d28*u*u*u*u*u*u*u*u*v
00815 + d29*u*u*u*u*v*v*v*v*v + d30*u*v*v*v*v*v*v*v*v
00816 + d31*u*v*v*v*v*v*v*v*v*v + d32*u*u*u*u*u*u*u*u*v*v*v*v
00817 + d33*u*u*u*u*u*v*v*v*v*v*v*v*v;
00818 #endif
00819
00820 delta_lat_p = (double)delta_lat;
00821 delta_lon_p = (double)delta_lon;
00822
00823 #ifdef DEBUG_DATUM
00824 ft_lat = 101.0 * delta_lat_p;
00825 ft_lon = 101.0 * vcl_cos(prin_lat_rad) * delta_lon_p;
00826
00827 c_error = (double)vcl_sqrt(ft_lat*ft_lat + ft_lon*ft_lon);
00828 #endif
00829
00830
00831 *nad27n_lat = wgs84_lat - (delta_lat_p/3600.0);
00832 *nad27n_lon = wgs84_lon - (delta_lon_p/3600.0);
00833 *nad27n_el = wgs84_el - delta_H;
00834
00835 #ifdef DEBUG_DATUM
00836 new_lat = *nad27n_lat;
00837 new_lon = *nad27n_lon;
00838 vcl_cout << "\n d_lat = " << delta_lat
00839 << "\n d_lon = " << delta_lon
00840 << "\n d_H = " << delta_H
00841 << "\n N = " << N_height
00842 << "\n circular error = " << c_error
00843 << "\n New Lat = " << new_lat << ", New Lon =\n" << new_lon
00844 << '\n';
00845 #endif
00846 }
00847
00848
00849
00850
00851
00852 double geo_detic2centric
00853 (double geodetic_lat,
00854 double A,
00855 double B)
00856 {
00857 return(vcl_atan((B/A)*(B/A) * vcl_tan(geodetic_lat)));
00858 }
00859
00860
00861
00862
00863 double geo_centric2detic
00864 (double geocentric_lat,
00865 double A,
00866 double B)
00867 {
00868 return(vcl_atan((A/B)*(A/B) * vcl_tan(geocentric_lat)));
00869 }
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 void GRS_to_latlong
00891 (double x, double y, double z,
00892 double *geodetic_lat,
00893 double *lon,
00894 double *el,
00895 double A,
00896 double B)
00897 {
00898 double new_lat;
00899 double N;
00900 double xy_dist;
00901 double ee;
00902
00903 xy_dist = vcl_sqrt(x*x + y*y);
00904 ee = 1 - (B/A)*(B/A);
00905
00906
00907
00908
00909
00910 *lon = vcl_acos(x/xy_dist);
00911 if (y < 0)
00912 *lon = - *lon;
00913
00914
00915 new_lat = vcl_atan2(z, xy_dist);
00916
00917 do
00918 {
00919 *geodetic_lat = new_lat;
00920
00921
00922
00923
00924 N = A / vcl_sqrt(1 - ee * vcl_sin(*geodetic_lat) * vcl_sin(*geodetic_lat));
00925
00926
00927 new_lat = vcl_atan2( (z + N * ee * vcl_sin(*geodetic_lat)), xy_dist );
00928 }
00929 while (vcl_fabs(new_lat - *geodetic_lat) > EPSILON);
00930
00931 *geodetic_lat = new_lat;
00932 *el = xy_dist/vcl_cos(new_lat) - N;
00933 }
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955 void latlong_to_GRS
00956 (double geodetic_lat,
00957 double lon,
00958 double el,
00959 double *x,
00960 double *y,
00961 double *z,
00962 double A,
00963 double B)
00964 {
00965 double geocentric_lat;
00966 double local_radius;
00967 double c, s;
00968
00969 geocentric_lat = geo_detic2centric(geodetic_lat, A, B);
00970
00971
00972 s = vcl_sin(geocentric_lat);
00973 c = vcl_cos(geocentric_lat);
00974
00975
00976
00977 local_radius = (A*B) / vcl_sqrt(B*B*c*c + A*A*s*s);
00978
00979 *x = (local_radius*c + el*vcl_cos(geodetic_lat))*vcl_cos(lon);
00980 *y = (local_radius*c + el*vcl_cos(geodetic_lat))*vcl_sin(lon);
00981 *z = (local_radius*s + el*vcl_sin(geodetic_lat));
00982
00983 #ifdef DEBUG_DATUM
00984 double tlat, tlon, tel;
00985 GRS_to_latlong(*x, *y, *z, &tlat, &tlon, &tel, A, B);
00986 vcl_cout << "Error in computation: (" << (tlat-geodetic_lat) << ", " << (tlon-lon) << ", " << (tel-el) << ")\n";
00987 #endif
00988 }
00989
00990
00991
00992
00993
00994 void nad27n_to_wgs72
00995 (
00996 double phi,
00997 double lamda,
00998 double height,
00999 double *wgs72_phi,
01000 double *wgs72_lamda,
01001 double *wgs72_hgt)
01002 {
01003 double wgs84_phi, wgs84_lamda, wgs84_hgt;
01004
01005 nad27n_to_wgs84(phi, lamda, height,
01006 &wgs84_phi, &wgs84_lamda, &wgs84_hgt);
01007
01008 wgs84_to_wgs72(wgs84_phi, wgs84_lamda, wgs84_hgt,
01009 wgs72_phi, wgs72_lamda, wgs72_hgt);
01010 }
01011
01012
01013
01014
01015
01016
01017 void wgs72_to_nad27n
01018 (
01019 double phi,
01020 double lamda,
01021 double height,
01022 double *nad27n_phi,
01023 double *nad27n_lamda,
01024 double *nad27n_hgt)
01025 {
01026 double wgs84_phi, wgs84_lamda, wgs84_hgt;
01027
01028 wgs72_to_wgs84(phi, lamda, height,
01029 &wgs84_phi, &wgs84_lamda, &wgs84_hgt);
01030
01031 wgs84_to_nad27n(wgs84_phi, wgs84_lamda, wgs84_hgt,
01032 nad27n_phi, nad27n_lamda, nad27n_hgt);
01033 }
01034