00001
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
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 #include <PalmOS.h>
00088 #include <PalmCompatibility.h>
00089 #include "MathLib.h"
00090
00091
00092
00093 #include "tranmerc.h"
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 #define PI 3.14159265358979323e0
00107 #define PI_OVER (PI/2.0e0)
00108 #define MAX_LAT ((PI * 89.99)/180.0)
00109 #define MAX_DELTA_LONG ((PI * 90)/180.0)
00110 #define MIN_SCALE_FACTOR 0.3
00111 #define MAX_SCALE_FACTOR 3.0
00112
00113 #define SPHTMD(Latitude) ((double) (TranMerc_ap * Latitude \
00114 - TranMerc_bp * sin(2.e0 * Latitude) + TranMerc_cp * sin(4.e0 * Latitude) \
00115 - TranMerc_dp * sin(6.e0 * Latitude) + TranMerc_ep * sin(8.e0 * Latitude) ) )
00116
00117 #define SPHSN(Latitude) ((double) (TranMerc_a / sqrt( 1.e0 - TranMerc_es * \
00118 pow(sin(Latitude), 2))))
00119
00120 #define SPHSR(Latitude) ((double) (TranMerc_a * (1.e0 - TranMerc_es) / \
00121 pow(DENOM(Latitude), 3)))
00122
00123 #define DENOM(Latitude) ((double) (sqrt(1.e0 - TranMerc_es * pow(sin(Latitude),2))))
00124
00125
00126
00127
00128
00129
00130
00131
00132 static double TranMerc_a = 6378137.0;
00133 static double TranMerc_f = 1 / 298.257223563;
00134 static double TranMerc_es = 0.0066943799901413800;
00135 static double TranMerc_ebs = 0.0067394967565869;
00136
00137
00138 static double TranMerc_Origin_Lat = 0.0;
00139 static double TranMerc_Origin_Long = 0.0;
00140 static double TranMerc_False_Northing = 0.0;
00141 static double TranMerc_False_Easting = 0.0;
00142 static double TranMerc_Scale_Factor = 1.0;
00143
00144
00145 static double TranMerc_ap = 6367449.1458008;
00146 static double TranMerc_bp = 16038.508696861;
00147 static double TranMerc_cp = 16.832613334334;
00148 static double TranMerc_dp = 0.021984404273757;
00149 static double TranMerc_ep = 3.1148371319283e-005;
00150
00151
00152 static double TranMerc_Delta_Easting = 40000000.0;
00153 static double TranMerc_Delta_Northing = 40000000.0;
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 long Set_Transverse_Mercator_Parameters(double a,
00166 double f,
00167 double Origin_Latitude,
00168 double Central_Meridian,
00169 double False_Easting,
00170 double False_Northing,
00171 double Scale_Factor)
00172
00173 {
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 double tn;
00193 double tn2;
00194 double tn3;
00195 double tn4;
00196 double tn5;
00197 double dummy_northing;
00198 double TranMerc_b;
00199 double inv_f = 1 / f;
00200 long Error_Code = TRANMERC_NO_ERROR;
00201
00202 if (a <= 0.0)
00203 {
00204 Error_Code |= TRANMERC_A_ERROR;
00205 }
00206 if ((inv_f < 250) || (inv_f > 350))
00207 {
00208 Error_Code |= TRANMERC_INV_F_ERROR;
00209 }
00210 if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT))
00211 {
00212 Error_Code |= TRANMERC_ORIGIN_LAT_ERROR;
00213 }
00214 if ((Central_Meridian < -PI) || (Central_Meridian > (2*PI)))
00215 {
00216 Error_Code |= TRANMERC_CENT_MER_ERROR;
00217 }
00218 if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR))
00219 {
00220 Error_Code |= TRANMERC_SCALE_FACTOR_ERROR;
00221 }
00222 if (!Error_Code)
00223 {
00224 TranMerc_a = a;
00225 TranMerc_f = f;
00226 TranMerc_Origin_Lat = 0;
00227 TranMerc_Origin_Long = 0;
00228 TranMerc_False_Northing = 0;
00229 TranMerc_False_Easting = 0;
00230 TranMerc_Scale_Factor = 1;
00231
00232
00233 TranMerc_es = 2 * TranMerc_f - TranMerc_f * TranMerc_f;
00234
00235 TranMerc_ebs = (1 / (1 - TranMerc_es)) - 1;
00236
00237 TranMerc_b = TranMerc_a * (1 - TranMerc_f);
00238
00239 tn = (TranMerc_a - TranMerc_b) / (TranMerc_a + TranMerc_b);
00240 tn2 = tn * tn;
00241 tn3 = tn2 * tn;
00242 tn4 = tn3 * tn;
00243 tn5 = tn4 * tn;
00244
00245 TranMerc_ap = TranMerc_a * (1.e0 - tn + 5.e0 * (tn2 - tn3)/4.e0
00246 + 81.e0 * (tn4 - tn5)/64.e0 );
00247 TranMerc_bp = 3.e0 * TranMerc_a * (tn - tn2 + 7.e0 * (tn3 - tn4)
00248 /8.e0 + 55.e0 * tn5/64.e0 )/2.e0;
00249 TranMerc_cp = 15.e0 * TranMerc_a * (tn2 - tn3 + 3.e0 * (tn4 - tn5 )/4.e0) /16.0;
00250 TranMerc_dp = 35.e0 * TranMerc_a * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0;
00251 TranMerc_ep = 315.e0 * TranMerc_a * (tn4 - tn5) / 512.e0;
00252 Convert_Geodetic_To_Transverse_Mercator(MAX_LAT,
00253 MAX_DELTA_LONG,
00254 &TranMerc_Delta_Easting,
00255 &TranMerc_Delta_Northing);
00256 Convert_Geodetic_To_Transverse_Mercator(0,
00257 MAX_DELTA_LONG,
00258 &TranMerc_Delta_Easting,
00259 &dummy_northing);
00260 TranMerc_Origin_Lat = Origin_Latitude;
00261 if (Central_Meridian > PI)
00262 Central_Meridian -= (2*PI);
00263 TranMerc_Origin_Long = Central_Meridian;
00264 TranMerc_False_Northing = False_Northing;
00265 TranMerc_False_Easting = False_Easting;
00266 TranMerc_Scale_Factor = Scale_Factor;
00267 }
00268 return (Error_Code);
00269 }
00270
00271
00272 void Get_Transverse_Mercator_Parameters(double *a,
00273 double *f,
00274 double *Origin_Latitude,
00275 double *Central_Meridian,
00276 double *False_Easting,
00277 double *False_Northing,
00278 double *Scale_Factor)
00279
00280 {
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 *a = TranMerc_a;
00297 *f = TranMerc_f;
00298 *Origin_Latitude = TranMerc_Origin_Lat;
00299 *Central_Meridian = TranMerc_Origin_Long;
00300 *False_Easting = TranMerc_False_Easting;
00301 *False_Northing = TranMerc_False_Northing;
00302 *Scale_Factor = TranMerc_Scale_Factor;
00303 return;
00304 }
00305
00306
00307
00308 long Convert_Geodetic_To_Transverse_Mercator (double Latitude,
00309 double Longitude,
00310 double *Easting,
00311 double *Northing)
00312
00313 {
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 double c;
00330 double c2;
00331 double c3;
00332 double c5;
00333 double c7;
00334 double dlam;
00335 double eta;
00336 double eta2;
00337 double eta3;
00338 double eta4;
00339 double s;
00340 double sn;
00341 double t;
00342 double tan2;
00343 double tan3;
00344 double tan4;
00345 double tan5;
00346 double tan6;
00347 double t1;
00348 double t2;
00349 double t3;
00350 double t4;
00351 double t5;
00352 double t6;
00353 double t7;
00354 double t8;
00355 double t9;
00356 double tmd;
00357 double tmdo;
00358 long Error_Code = TRANMERC_NO_ERROR;
00359 double temp_Origin;
00360 double temp_Long;
00361
00362 if ((Latitude < -MAX_LAT) || (Latitude > MAX_LAT))
00363 {
00364 Error_Code|= TRANMERC_LAT_ERROR;
00365 }
00366 if (Longitude > PI)
00367 Longitude -= (2 * PI);
00368 if ((Longitude < (TranMerc_Origin_Long - MAX_DELTA_LONG))
00369 || (Longitude > (TranMerc_Origin_Long + MAX_DELTA_LONG)))
00370 {
00371 if (Longitude < 0)
00372 temp_Long = Longitude + 2 * PI;
00373 else
00374 temp_Long = Longitude;
00375 if (TranMerc_Origin_Long < 0)
00376 temp_Origin = TranMerc_Origin_Long + 2 * PI;
00377 else
00378 temp_Origin = TranMerc_Origin_Long;
00379 if ((temp_Long < (temp_Origin - MAX_DELTA_LONG))
00380 || (temp_Long > (temp_Origin + MAX_DELTA_LONG)))
00381 Error_Code|= TRANMERC_LON_ERROR;
00382 }
00383 if (!Error_Code)
00384 {
00385
00386
00387
00388
00389 dlam = Longitude - TranMerc_Origin_Long;
00390
00391 if (fabs(dlam) > (9.0 * PI / 180))
00392 {
00393 Error_Code |= TRANMERC_LON_WARNING;
00394 }
00395
00396 if (dlam > PI)
00397 dlam -= (2 * PI);
00398 if (dlam < -PI)
00399 dlam += (2 * PI);
00400 if (fabs(dlam) < 2.e-10)
00401 dlam = 0.0;
00402
00403 s = sin(Latitude);
00404 c = cos(Latitude);
00405 c2 = c * c;
00406 c3 = c2 * c;
00407 c5 = c3 * c2;
00408 c7 = c5 * c2;
00409 t = tan (Latitude);
00410 tan2 = t * t;
00411 tan3 = tan2 * t;
00412 tan4 = tan3 * t;
00413 tan5 = tan4 * t;
00414 tan6 = tan5 * t;
00415 eta = TranMerc_ebs * c2;
00416 eta2 = eta * eta;
00417 eta3 = eta2 * eta;
00418 eta4 = eta3 * eta;
00419
00420
00421 sn = SPHSN(Latitude);
00422
00423
00424 tmd = SPHTMD(Latitude);
00425
00426
00427 tmdo = SPHTMD (TranMerc_Origin_Lat);
00428
00429
00430 t1 = (tmd - tmdo) * TranMerc_Scale_Factor;
00431 t2 = sn * s * c * TranMerc_Scale_Factor/ 2.e0;
00432 t3 = sn * s * c3 * TranMerc_Scale_Factor * (5.e0 - tan2 + 9.e0 * eta
00433 + 4.e0 * eta2) /24.e0;
00434
00435 t4 = sn * s * c5 * TranMerc_Scale_Factor * (61.e0 - 58.e0 * tan2
00436 + tan4 + 270.e0 * eta - 330.e0 * tan2 * eta + 445.e0 * eta2
00437 + 324.e0 * eta3 -680.e0 * tan2 * eta2 + 88.e0 * eta4
00438 -600.e0 * tan2 * eta3 - 192.e0 * tan2 * eta4) / 720.e0;
00439
00440 t5 = sn * s * c7 * TranMerc_Scale_Factor * (1385.e0 - 3111.e0 *
00441 tan2 + 543.e0 * tan4 - tan6) / 40320.e0;
00442
00443 *Northing = TranMerc_False_Northing + t1 + pow(dlam,2.e0) * t2
00444 + pow(dlam,4.e0) * t3 + pow(dlam,6.e0) * t4
00445 + pow(dlam,8.e0) * t5;
00446
00447
00448 t6 = sn * c * TranMerc_Scale_Factor;
00449 t7 = sn * c3 * TranMerc_Scale_Factor * (1.e0 - tan2 + eta ) /6.e0;
00450 t8 = sn * c5 * TranMerc_Scale_Factor * (5.e0 - 18.e0 * tan2 + tan4
00451 + 14.e0 * eta - 58.e0 * tan2 * eta + 13.e0 * eta2 + 4.e0 * eta3
00452 - 64.e0 * tan2 * eta2 - 24.e0 * tan2 * eta3 )/ 120.e0;
00453 t9 = sn * c7 * TranMerc_Scale_Factor * ( 61.e0 - 479.e0 * tan2
00454 + 179.e0 * tan4 - tan6 ) /5040.e0;
00455
00456 *Easting = TranMerc_False_Easting + dlam * t6 + pow(dlam,3.e0) * t7
00457 + pow(dlam,5.e0) * t8 + pow(dlam,7.e0) * t9;
00458 }
00459 return (Error_Code);
00460 }
00461
00462
00463 long Convert_Transverse_Mercator_To_Geodetic (
00464 double Easting,
00465 double Northing,
00466 double *Latitude,
00467 double *Longitude)
00468 {
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 double c;
00485 double de;
00486 double dlam;
00487 double eta;
00488 double eta2;
00489 double eta3;
00490 double eta4;
00491 double ftphi;
00492 int i;
00493 double s;
00494 double sn;
00495 double sr;
00496 double t;
00497 double tan2;
00498 double tan4;
00499 double t10;
00500 double t11;
00501 double t12;
00502 double t13;
00503 double t14;
00504 double t15;
00505 double t16;
00506 double t17;
00507 double tmd;
00508 double tmdo;
00509 long Error_Code = TRANMERC_NO_ERROR;
00510
00511 if ((Easting < (TranMerc_False_Easting - TranMerc_Delta_Easting))
00512 ||(Easting > (TranMerc_False_Easting + TranMerc_Delta_Easting)))
00513 {
00514 Error_Code |= TRANMERC_EASTING_ERROR;
00515 }
00516 if ((Northing < (TranMerc_False_Northing - TranMerc_Delta_Northing))
00517 || (Northing > (TranMerc_False_Northing + TranMerc_Delta_Northing)))
00518 {
00519 Error_Code |= TRANMERC_NORTHING_ERROR;
00520 }
00521
00522 if (!Error_Code)
00523 {
00524
00525 tmdo = SPHTMD(TranMerc_Origin_Lat);
00526
00527
00528 tmd = tmdo + (Northing - TranMerc_False_Northing) / TranMerc_Scale_Factor;
00529
00530
00531 sr = SPHSR(0.e0);
00532 ftphi = tmd/sr;
00533
00534 for (i = 0; i < 5 ; i++)
00535 {
00536 t10 = SPHTMD (ftphi);
00537 sr = SPHSR(ftphi);
00538 ftphi = ftphi + (tmd - t10) / sr;
00539 }
00540
00541
00542 sr = SPHSR(ftphi);
00543
00544
00545 sn = SPHSN(ftphi);
00546
00547
00548 s = sin(ftphi);
00549 c = cos(ftphi);
00550
00551
00552 t = tan(ftphi);
00553 tan2 = t * t;
00554 tan4 = tan2 * tan2;
00555 eta = TranMerc_ebs * pow(c,2);
00556 eta2 = eta * eta;
00557 eta3 = eta2 * eta;
00558 eta4 = eta3 * eta;
00559 de = Easting - TranMerc_False_Easting;
00560 if (fabs(de) < 0.0001)
00561 de = 0.0;
00562
00563
00564 t10 = t / (2.e0 * sr * sn * pow(TranMerc_Scale_Factor, 2));
00565 t11 = t * (5.e0 + 3.e0 * tan2 + eta - 4.e0 * pow(eta,2)
00566 - 9.e0 * tan2 * eta) / (24.e0 * sr * pow(sn,3)
00567 * pow(TranMerc_Scale_Factor,4));
00568 t12 = t * (61.e0 + 90.e0 * tan2 + 46.e0 * eta + 45.E0 * tan4
00569 - 252.e0 * tan2 * eta - 3.e0 * eta2 + 100.e0
00570 * eta3 - 66.e0 * tan2 * eta2 - 90.e0 * tan4
00571 * eta + 88.e0 * eta4 + 225.e0 * tan4 * eta2
00572 + 84.e0 * tan2* eta3 - 192.e0 * tan2 * eta4)
00573 / ( 720.e0 * sr * pow(sn,5) * pow(TranMerc_Scale_Factor, 6) );
00574 t13 = t * ( 1385.e0 + 3633.e0 * tan2 + 4095.e0 * tan4 + 1575.e0
00575 * pow(t,6))/ (40320.e0 * sr * pow(sn,7) * pow(TranMerc_Scale_Factor,8));
00576 *Latitude = ftphi - pow(de,2) * t10 + pow(de,4) * t11 - pow(de,6) * t12
00577 + pow(de,8) * t13;
00578
00579 t14 = 1.e0 / (sn * c * TranMerc_Scale_Factor);
00580
00581 t15 = (1.e0 + 2.e0 * tan2 + eta) / (6.e0 * pow(sn,3) * c *
00582 pow(TranMerc_Scale_Factor,3));
00583
00584 t16 = (5.e0 + 6.e0 * eta + 28.e0 * tan2 - 3.e0 * eta2
00585 + 8.e0 * tan2 * eta + 24.e0 * tan4 - 4.e0
00586 * eta3 + 4.e0 * tan2 * eta2 + 24.e0
00587 * tan2 * eta3) / (120.e0 * pow(sn,5) * c
00588 * pow(TranMerc_Scale_Factor,5));
00589
00590 t17 = (61.e0 + 662.e0 * tan2 + 1320.e0 * tan4 + 720.e0
00591 * pow(t,6)) / (5040.e0 * pow(sn,7) * c
00592 * pow(TranMerc_Scale_Factor,7));
00593
00594
00595 dlam = de * t14 - pow(de,3) * t15 + pow(de,5) * t16 - pow(de,7) * t17;
00596
00597
00598 (*Longitude) = TranMerc_Origin_Long + dlam;
00599 while (*Latitude > (90.0 * PI / 180.0))
00600 {
00601 *Latitude = PI - *Latitude;
00602 *Longitude += PI;
00603 if (*Longitude > PI)
00604 *Longitude -= (2 * PI);
00605 }
00606
00607 while (*Latitude < (-90.0 * PI / 180.0))
00608 {
00609 *Latitude = - (*Latitude + PI);
00610 *Longitude += PI;
00611 if (*Longitude > PI)
00612 *Longitude -= (2 * PI);
00613 }
00614 if (*Longitude > (2*PI))
00615 *Longitude -= (2 * PI);
00616 if (*Longitude < -PI)
00617 *Longitude += (2 * PI);
00618
00619 if (fabs(dlam) > (9.0 * PI / 180))
00620 {
00621 Error_Code |= TRANMERC_LON_WARNING;
00622 }
00623 }
00624 return (Error_Code);
00625 }