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 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <ctype.h>
00029
00030
00031
00032
00033
00034 #include <math.h>
00035
00036 #include "GeomagnetismHeader.h"
00037 #include "EGM9615.h"
00038
00039
00040
00041 #define NaN log(-1.0)
00042
00043 #define RECL 81
00044
00045 #define MAXINBUFF RECL+14
00046
00049 #define MAXREAD MAXINBUFF-2
00050
00053 #define PATH MAXREAD
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
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 int main(int argv, char**argc)
00098 {
00099 #ifdef MAC
00100 ccommand(argv, argc);
00101 #endif
00102
00103
00104 MAGtype_MagneticModel *TimedMagneticModel, *MagneticModels[1];
00105 MAGtype_Ellipsoid Ellip;
00106 MAGtype_CoordSpherical CoordSpherical;
00107 MAGtype_CoordGeodetic CoordGeodetic;
00108 MAGtype_Date UserDate;
00109 MAGtype_GeoMagneticElements GeoMagneticElements;
00110 MAGtype_Geoid Geoid;
00111 char ans[20];
00112 char filename[] = "WMM.COF";
00113 int NumTerms, epochs = 1, epoch = 0, i, nMax = 0;
00114 char VersionDate_Large[] = "$Date: 2012-04-12 13:30:38 -0600 (Thu, 12 Apr 2012) $";
00115 char VersionDate[12];
00116
00117
00118 int again = 1;
00119 int decyears = 3;
00120 int units = 4;
00121 int decdeg = 3;
00122 int range = -1;
00123 int igdgc = 3;
00124 int isyear = -1;
00125 int ismonth = -1;
00126 int isday = -1;
00127 int ieyear = -1;
00128 int iemonth = -1;
00129 int ieday = -1;
00130 int ilat_deg = 200;
00131 int ilat_min = 200;
00132 int ilat_sec = 200;
00133 int ilon_deg = 200;
00134 int ilon_min = 200;
00135 int ilon_sec = 200;
00136
00137
00138 int coords_from_file = 0;
00139 int arg_err = 0;
00140
00141 char inbuff[MAXINBUFF];
00142
00143 char *begin;
00144 char *rest;
00145 char args[7][MAXREAD];
00146 int iarg;
00147
00148 char coord_fname[PATH];
00149 char out_fname[PATH];
00150 FILE *coordfile, *outfile;
00151 int iline = 0;
00152 int read_flag;
00153
00154 float minyr;
00155 float maxyr;
00156 float minalt;
00157 float maxalt;
00158 float alt = -999999;
00159 float sdate = -1;
00160 float step = -1;
00161 float edate = -1;
00162 float latitude = 200;
00163 float longitude = 200;
00164
00165
00166
00167
00168
00169 void print_result_file(FILE *outf, double d, double i, double h, double x, double y, double z, double f,
00170 double ddot, double idot, double hdot, double xdot, double ydot, double zdot, double fdot);
00171 float degrees_to_decimal();
00172 float julday();
00173 int safegets(char *buffer, int n);
00174 int getshc();
00175
00176
00177
00178
00179 inbuff[MAXREAD + 1] = '\0';
00180 inbuff[MAXINBUFF - 1] = '\0';
00181
00182
00183
00184
00185 strncpy(VersionDate, VersionDate_Large + 39, 11);
00186 VersionDate[11] = '\0';
00187 MAG_robustReadMagModels(filename, &MagneticModels, epochs);
00188 for(i = 0; i < epochs; i++) if(MagneticModels[i]->nMax > nMax) nMax = MagneticModels[i]->nMax;
00189 NumTerms = ((nMax + 1) * (nMax + 2) / 2);
00190
00191 TimedMagneticModel = MAG_AllocateModelMemory(NumTerms);
00192
00193 for(i = 0; i < epochs; i++) if(MagneticModels[i] == NULL || TimedMagneticModel == NULL)
00194 {
00195 MAG_Error(2);
00196 }
00197
00198 MAG_SetDefaults(&Ellip, &Geoid);
00199
00200
00201
00202
00203 Geoid.GeoidHeightBuffer = GeoidHeightBuffer;
00204 Geoid.Geoid_Initialized = 1;
00205
00206 maxyr = MagneticModels[0]->CoefficientFileEndDate;
00207 minyr = MagneticModels[0]->epoch;
00208
00209 for(iarg = 0; iarg < argv; iarg++)
00210 if(argc[iarg] != NULL)
00211 strncpy(args[iarg], argc[iarg], MAXREAD);
00212
00213
00214 printf("\n\n-----------------------------------------------\n");
00215 printf(" WMM File processing program %s", VersionDate);
00216 printf("\n-----------------------------------------------\n");
00217
00218 if(argv == 1 || ((argv == 2) && (*(args[1]) == 'h')))
00219 {
00220 printf("\nWelcome to the World Magnetic Model (WMM) C-Program\nof the US National Geophysical Data Center\n --- File Processing Program ----\n --- Model Release Date: 15 Dec 2009 ---\n --- Software Release Date: %s ---\nUSAGE:\n", VersionDate);
00221 printf("For example: MAG_file f input_file output_file\n");
00222 printf("This screen: MAG_file h \n");
00223 printf("\n");
00224 printf("The input file may have any number of entries but they must follow\n");
00225 printf("the following format\n");
00226 printf("Date and location Formats: \n");
00227 printf(" Date: xxxx.xxx for decimal (2013.7)\n");
00228 printf(" Altitude: M - Above mean sea level: E above WGS84 Ellipsoid \n");
00229 printf(" Altitude: Kxxxxxx.xxx for kilometers (K1000.13)\n");
00230 printf(" Mxxxxxx.xxx for meters (m1389.24)\n");
00231 printf(" Fxxxxxx.xxx for feet (F192133.73)\n");
00232 printf(" Lat/Lon: xxx.xxx in decimal (-76.53)\n");
00233 printf(" (Lat and Lon must be specified in the same format.)\n");
00234 printf(" Date and altitude must fit model.\n");
00235 printf(" Lat: -90 to 90 (Use - to denote Southern latitude.)\n");
00236 printf(" Lon: -180 to 180 (Use - to denote Western longitude.)\n");
00237 printf(" Date: 2010.0 to 2015.0\n");
00238 printf(" An example of an entry in input file\n");
00239 printf(" 2013.7 E F30000 -70.3 -30.8 \n");
00240 printf("\n Press enter to exit.");
00241 printf("\n >");
00242 fgets(ans, 20, stdin);
00243
00244 for(i = 0; i < epochs; i++) MAG_FreeMagneticModelMemory(MagneticModels[i]);
00245 MAG_FreeMagneticModelMemory(TimedMagneticModel);
00246
00247 exit(2);
00248 }
00249
00250 if((argv == 4) && (*(args[1]) == 'f'))
00251 {
00252 printf("\n\n 'f' switch: converting file with multiple locations.\n");
00253 printf(" The first five output columns repeat the input coordinates.\n");
00254 printf(" Then follows D, I, H, X, Y, Z, and F.\n");
00255 printf(" Finally the SV: dD, dI, dH, dX, dY, dZ, and dF\n");
00256
00257 coords_from_file = 1;
00258 strncpy(coord_fname, args[2], MAXREAD);
00259 coordfile = fopen(coord_fname, "rt");
00260 strncpy(out_fname, args[3], MAXREAD);
00261 outfile = fopen(out_fname, "w");
00262 fprintf(outfile, "Date Coord-System Altitude Latitude Longitude D_deg D_min I_deg I_min H_nT X_nT Y_nT Z_nT F_nT dD_min dI_min dH_nT dX_nT dY_nT dZ_nT dF_nT\n");
00263 }
00264
00265 if(argv >= 2 && argv != 4)
00266 {
00267 printf("\n\nERROR in 'f' switch option: wrong number of arguments\n");
00268 exit(2);
00269 }
00270
00271 if(argv == 1)
00272 {
00273 printf("\n\nERROR in switch option: wrong number of arguments\n");
00274 exit(2);
00275 }
00276
00277
00278
00279 while(again == 1)
00280 {
00281 if(coords_from_file)
00282 {
00283 argv = 6;
00284 read_flag = fscanf(coordfile, "%s%s%s%s%s%*[^\n]", args[1], args[2], args[3], args[4], args[5]);
00285 if(read_flag == EOF) goto reached_EOF;
00286 fprintf(outfile, "%s %s %s %s %s ", args[1], args[2], args[3], args[4], args[5]);
00287 fflush(outfile);
00288 iline++;
00289 }
00290
00291
00292
00293 switch(argv) {
00294 case 6: strncpy(inbuff, args[5], MAXREAD);
00295 if((rest = strchr(inbuff, ',')))
00296 {
00297 decdeg = 2;
00298 begin = inbuff;
00299 rest[0] = '\0';
00300 rest++;
00301 ilon_deg = atoi(begin);
00302 begin = rest;
00303 if((rest = strchr(begin, ',')))
00304 {
00305 rest[0] = '\0';
00306 rest++;
00307 ilon_min = atoi(begin);
00308 ilon_sec = atoi(rest);
00309 } else
00310 {
00311 ilon_min = 0;
00312 ilon_sec = 0;
00313 }
00314 } else
00315 {
00316 decdeg = 1;
00317 longitude = atof(args[5]);
00318 }
00319
00320 case 5: strncpy(inbuff, args[4], MAXREAD);
00321 if((rest = strchr(inbuff, ',')))
00322 {
00323 decdeg = 2;
00324 begin = inbuff;
00325 rest[0] = '\0';
00326 rest++;
00327 ilat_deg = atoi(begin);
00328 begin = rest;
00329 if((rest = strchr(begin, ',')))
00330 {
00331 rest[0] = '\0';
00332 rest++;
00333 ilat_min = atoi(begin);
00334 ilat_sec = atoi(rest);
00335 } else
00336 {
00337 ilat_min = 0;
00338 ilat_sec = 0;
00339 }
00340 } else
00341 {
00342 decdeg = 1;
00343 latitude = atof(args[4]);
00344 }
00345
00346 case 4: strncpy(inbuff, args[3], MAXREAD);
00347 inbuff[0] = toupper(inbuff[0]);
00348 if(inbuff[0] == 'K') units = 1;
00349 else if(inbuff[0] == 'M') units = 2;
00350 else if(inbuff[0] == 'F') units = 3;
00351 if(strlen(inbuff) > 1)
00352 {
00353 inbuff[0] = '\0';
00354 begin = inbuff + 1;
00355 alt = atof(begin);
00356 }
00357
00358 case 3: strncpy(inbuff, args[2], MAXREAD);
00359 inbuff[0] = toupper(inbuff[0]);
00360 if(inbuff[0] == 'M') igdgc = 1;
00361 else if(inbuff[0] == 'E') igdgc = 2;
00362
00363
00364 case 2: strncpy(inbuff, args[1], MAXREAD);
00365 if((rest = strchr(inbuff, '-')))
00366 {
00367 range = 2;
00368 rest[0] = '\0';
00369 rest++;
00370 begin = rest;
00371 if((rest = strchr(begin, '-')))
00372 {
00373 rest[0] = '\0';
00374 rest++;
00375 step = atof(rest);
00376 }
00377 if((rest = strchr(begin, ',')))
00378 {
00379 decyears = 2;
00380 rest[0] = '\0';
00381 rest++;
00382 ieyear = atoi(begin);
00383 begin = rest;
00384 if((rest = strchr(begin, ',')))
00385 {
00386 rest[0] = '\0';
00387 rest++;
00388 iemonth = atoi(begin);
00389 ieday = atoi(rest);
00390 } else
00391 {
00392 iemonth = 0;
00393 ieday = 0;
00394 }
00395 if((rest = strchr(inbuff, ',')))
00396 {
00397 begin = inbuff;
00398 rest[0] = '\0';
00399 rest++;
00400 isyear = atoi(begin);
00401 begin = rest;
00402 if((rest = strchr(begin, ',')))
00403 {
00404 rest[0] = '\0';
00405 rest++;
00406 ismonth = atoi(begin);
00407 isday = atoi(rest);
00408 } else
00409 {
00410 ismonth = 0;
00411 isday = 0;
00412 }
00413 } else
00414 {
00415 sdate = atof(inbuff);
00416 }
00417 } else
00418 {
00419 decyears = 1;
00420 sdate = atof(inbuff);
00421 edate = atof(begin);
00422 }
00423 } else
00424 {
00425 range = 1;
00426 if((rest = strchr(inbuff, ',')))
00427 {
00428 decyears = 2;
00429 begin = inbuff;
00430 rest[0] = '\0';
00431 rest++;
00432 isyear = atoi(begin);
00433 begin = rest;
00434 if((rest = strchr(begin, ',')))
00435 {
00436 rest[0] = '\0';
00437 rest++;
00438 ismonth = atoi(begin);
00439 isday = atoi(rest);
00440 } else
00441 {
00442 ismonth = 0;
00443 isday = 0;
00444 }
00445 } else
00446 {
00447 decyears = 1;
00448 sdate = atof(args[1]);
00449 }
00450 }
00451 if(sdate == 0)
00452 {
00453 decyears = -1;
00454 range = -1;
00455 }
00456 break;
00457
00458 }
00459
00460 if(range == 2 && coords_from_file)
00461 {
00462 printf("Error in line %1d, date = %s: date ranges not allowed for file option\n\n", iline, args[1]);
00463 exit(2);
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 if(coords_from_file && !arg_err && (decyears != 1 && decyears != 2))
00475 {
00476 printf("\nError: unrecognized date %s in coordinate file line %1d\n\n", args[1], iline);
00477 arg_err = 1;
00478 }
00479
00480 if(coords_from_file && !arg_err && range != 1)
00481 {
00482 printf("\nError: unrecognized date %s in coordinate file line %1d\n\n", args[1], iline);
00483 arg_err = 1;
00484 }
00485
00486 if(coords_from_file && !arg_err && (sdate < minyr || sdate > maxyr))
00487 {
00488 printf("\nWarning: date out of range in coordinate file line %1d\n\n", iline);
00489 printf("\nExpected range = %6.1lf - %6.1lf, entered %6.1lf\n", minyr, maxyr, sdate);
00490 }
00491
00492
00493
00494 minalt = -10;
00495 maxalt = 1000;
00496
00497
00498
00499 if(coords_from_file && !arg_err && (igdgc != 1 && igdgc != 2))
00500 {
00501 printf("\nError: Unrecognized height reference %s in coordinate file line %1d\n\n", args[1], iline);
00502 arg_err = 1;
00503 }
00504
00505
00506 if(igdgc == 2)
00507 {
00508 Geoid.UseGeoid = 0;
00509 } else if(igdgc == 1)
00510 {
00511 Geoid.UseGeoid = 1;
00512 }
00513
00514
00515
00516 if(units == 2)
00517 {
00518 minalt *= 1000.0;
00519 maxalt *= 1000.0;
00520 } else if(units == 3)
00521 {
00522 minalt *= 3280.0839895;
00523 maxalt *= 3280.0839895;
00524 }
00525
00526
00527
00528 if(coords_from_file && !arg_err && (alt < minalt || alt > maxalt))
00529 {
00530 printf("\nError: unrecognized altitude %s in coordinate file line %1d\n\n", args[3], iline);
00531 arg_err = 1;
00532 }
00533
00534
00535 if(units == 2)
00536 {
00537 alt *= 0.001;
00538 } else if(units == 3)
00539 {
00540 alt /= 3280.0839895;
00541 }
00542
00543
00544
00545
00546
00547 if(coords_from_file && !arg_err && decdeg != 1)
00548 {
00549 printf("\nError: unrecognized lat %s or lon %s in coordinate file line %1d\n\n", args[4], args[5], iline);
00550 arg_err = 1;
00551 }
00552
00553
00554
00555
00556
00557
00560 CoordGeodetic.lambda = longitude;
00561 CoordGeodetic.phi = latitude;
00562 CoordGeodetic.HeightAboveGeoid = alt;
00563 UserDate.DecimalYear = sdate;
00564
00565
00566 MAG_ConvertGeoidToEllipsoidHeight(&CoordGeodetic, &Geoid);
00567 MAG_GeodeticToSpherical(Ellip, CoordGeodetic, &CoordSpherical);
00568 epoch = ((int) UserDate.DecimalYear - 1900) / 5;
00569 if(epoch >= epochs)
00570 epoch = epochs - 1;
00571 if(epoch < 0)
00572 epoch = 0;
00573 MAG_TimelyModifyMagneticModel(UserDate, MagneticModels[epoch], TimedMagneticModel);
00574 MAG_Geomag(Ellip, CoordSpherical, CoordGeodetic, TimedMagneticModel, &GeoMagneticElements);
00575 MAG_CalculateGridVariation(CoordGeodetic, &GeoMagneticElements);
00576
00577
00578
00579
00583
00584
00585
00586 if(coords_from_file)
00587 {
00588 print_result_file(outfile,
00589 GeoMagneticElements.Decl,
00590 GeoMagneticElements.Incl,
00591 GeoMagneticElements.H,
00592 GeoMagneticElements.X,
00593 GeoMagneticElements.Y,
00594 GeoMagneticElements.Z,
00595 GeoMagneticElements.F,
00596 60 * GeoMagneticElements.Decldot,
00597 60 * GeoMagneticElements.Incldot,
00598 GeoMagneticElements.Hdot,
00599 GeoMagneticElements.Xdot,
00600 GeoMagneticElements.Ydot,
00601 GeoMagneticElements.Zdot,
00602 GeoMagneticElements.Fdot);
00603 }
00604
00605 if(coords_from_file)
00606 again = !feof(coordfile) && !arg_err;
00607
00608 if(again == 1)
00609 {
00610
00611 igdgc = decyears = units = decdeg = -1;
00612 ismonth = isday = isyear = sdate = edate = range = step = -1;
00613 latitude = ilat_deg = ilat_min = ilat_sec = 200;
00614 longitude = ilon_deg = ilon_min = ilon_sec = 200;
00615 alt = -9999999;
00616 argv = 1;
00617 }
00618 }
00619
00620 reached_EOF:
00621
00622 if(coords_from_file) printf("\n Processed %1d lines\n\n", iline);
00623
00624 if(coords_from_file && !feof(coordfile) && arg_err) printf("Terminated prematurely due to argument error in coordinate file\n\n");
00625
00626
00627 fclose(coordfile);
00628 fclose(outfile);
00629
00630 for(i = 0; i < epochs; i++) MAG_FreeMagneticModelMemory(MagneticModels[i]);
00631 MAG_FreeMagneticModelMemory(TimedMagneticModel);
00632
00633
00634
00635 return 0;
00636 }
00637
00638 void print_result_file(FILE *outf, double d, double i, double h, double x, double y, double z, double f,
00639 double ddot, double idot, double hdot, double xdot, double ydot, double zdot, double fdot)
00640 {
00641 int ddeg, ideg;
00642 float dmin, imin;
00643
00644
00645
00646 ddeg = (int) d;
00647 dmin = (d - (float) ddeg)*60;
00648 if(ddeg != 0) dmin = fabs(dmin);
00649 ideg = (int) i;
00650 imin = (i - (float) ideg)*60;
00651 if(ideg != 0) imin = fabs(imin);
00652
00653 if(MAG_isNaN(d))
00654 {
00655 if(MAG_isNaN(x))
00656 fprintf(outf, " NaN %4dd %2.0fm %8.1f NaN NaN %8.1f %8.1f", ideg, imin, h, z, f);
00657 else
00658 fprintf(outf, " NaN %4dd %2.0fm %8.1f %8.1f %8.1f %8.1f %8.1f", ideg, imin, h, x, y, z, f);
00659 } else
00660 fprintf(outf, " %4dd %2.0fm %4dd %2.0fm %8.1f %8.1f %8.1f %8.1f %8.1f", ddeg, dmin, ideg, imin, h, x, y, z, f);
00661
00662 if(MAG_isNaN(ddot))
00663 {
00664 if(MAG_isNaN(xdot))
00665 fprintf(outf, " NaN %7.1f %8.1f NaN NaN %8.1f %8.1f\n", idot, hdot, zdot, fdot);
00666 else
00667 fprintf(outf, " NaN %7.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n", idot, hdot, xdot, ydot, zdot, fdot);
00668 } else
00669 fprintf(outf, " %7.1f %7.1f %8.1f %8.1f %8.1f %8.1f %8.1f\n", ddot, idot, hdot, xdot, ydot, zdot, fdot);
00670 return;
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 int safegets(char *buffer, int n)
00696 {
00697 char *ptr;
00699 fgets(buffer, n, stdin);
00700 buffer[n + 1] = '\0';
00701 ptr = strchr(buffer, '\n');
00702 if(ptr != NULL)
00703 {
00704 ptr[0] = '\0';
00705 }
00706
00707 return strlen(buffer);
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 float degrees_to_decimal(int degrees, int minutes, int seconds)
00736 {
00737 float deg;
00738 float min;
00739 float sec;
00740 float decimal;
00741
00742 deg = degrees;
00743 min = minutes / 60.0;
00744 sec = seconds / 3600.0;
00745
00746 decimal = fabs(sec) + fabs(min) + fabs(deg);
00747
00748 if(deg < 0)
00749 {
00750 decimal = -decimal;
00751 } else if(deg == 0)
00752 {
00753 if(min < 0)
00754 {
00755 decimal = -decimal;
00756 } else if(min == 0)
00757 {
00758 if(sec < 0)
00759 {
00760 decimal = -decimal;
00761 }
00762 }
00763 }
00764
00765 return (decimal);
00766 }
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 float julday(i_month, i_day, i_year)
00801 int i_month;
00802 int i_day;
00803 int i_year;
00804 {
00805 int aggregate_first_day_of_month[13];
00806 int leap_year = 0;
00807 int truncated_dividend;
00808 float year;
00809 float day;
00810 float decimal_date;
00811 float remainder = 0.0;
00812 float divisor = 4.0;
00813 float dividend;
00814 float left_over;
00815
00816 aggregate_first_day_of_month[1] = 1;
00817 aggregate_first_day_of_month[2] = 32;
00818 aggregate_first_day_of_month[3] = 60;
00819 aggregate_first_day_of_month[4] = 91;
00820 aggregate_first_day_of_month[5] = 121;
00821 aggregate_first_day_of_month[6] = 152;
00822 aggregate_first_day_of_month[7] = 182;
00823 aggregate_first_day_of_month[8] = 213;
00824 aggregate_first_day_of_month[9] = 244;
00825 aggregate_first_day_of_month[10] = 274;
00826 aggregate_first_day_of_month[11] = 305;
00827 aggregate_first_day_of_month[12] = 335;
00828
00829
00830
00831 year = i_year;
00832 if((i_year != 1900) && (i_year != 2100))
00833 {
00834 dividend = year / divisor;
00835 truncated_dividend = dividend;
00836 left_over = dividend - truncated_dividend;
00837 remainder = left_over*divisor;
00838 if((remainder > 0.0) && (i_month > 2))
00839 {
00840 leap_year = 1;
00841 } else
00842 {
00843 leap_year = 0;
00844 }
00845 }
00846 day = aggregate_first_day_of_month[i_month] + i_day - 1 + leap_year;
00847 if(leap_year)
00848 {
00849 decimal_date = year + (day / 366.0);
00850 } else
00851 {
00852 decimal_date = year + (day / 365.0);
00853 }
00854 return (decimal_date);
00855 }
00856