home *** CD-ROM | disk | FTP | other *** search
/ PC World 2002 March / PCWorld_2002-03_cd.bin / Software / Vyzkuste / homeplanet / TOOLS / COMETEL.C < prev   
C/C++ Source or Header  |  1997-04-04  |  12KB  |  359 lines

  1. /*
  2.  
  3.     Convert comet elements in the formats used by the Minor Planet
  4.     Center (and in the Minor Planet Electronic Circulars) to Home
  5.     Planet CSV format.  Multiple comet announcements can be extracted
  6.     from a file containing other irrelevant information.  This allows
  7.     you, for example, to process an entire Unix mail folder and extract
  8.     elements from all archived circulars within.
  9.     
  10.     Designed and implemented by John Walker in November of 1994.
  11.     Revision 1 by John Walker in April 1997 to use presence of
  12.     eccentricity to flag periodic comet format.
  13.  
  14.                      Elliptical Orbital Elements
  15.                      ---------------------------
  16.     
  17. PERIODIC COMET SHOEMAKER 4 (1994k)
  18.  
  19.             . . .
  20.  
  21.      T = 1994 Oct. 31.231 TT          Peri. = 196.521
  22.      e = 0.52851                      Node  =  92.603   2000.0
  23.      q = 2.92503 AU                   Incl. =  25.345
  24.        a =  6.20375 AU     n = 0.063786     P =  15.45 years
  25.           1         2         3         4         5         6         7
  26. 01234567890123456789012345678901234567890123456789012345678901234567890
  27.  
  28.     Some time after the original version of this program was released,
  29.     IAUCs dropped the "PERIODIC " designation, relying on the presence
  30.     or absence of eccentricity to distinguish elliptical and parabolic
  31.     elements.  The form for periodic elements as of this revision
  32.     (April 1997) is as follows:
  33.  
  34. COMET P/1997 B1 (KOBAYASHI)
  35.  
  36.             . . .
  37.  
  38.      T = 1997 Mar.  4.295 TT          Peri. = 184.202
  39.      e = 0.76831                      Node  = 329.032   2000.0
  40.      q = 2.06219 AU                   Incl. =  12.490
  41.        a =  8.90047 AU     n = 0.037118     P =  26.55 years
  42.           1         2         3         4         5         6         7
  43. 01234567890123456789012345678901234567890123456789012345678901234567890
  44.  
  45.                       Parabolic Orbital Elements
  46.                       --------------------------
  47.  
  48. COMET MUELLER (1994c)
  49.                                                                            
  50.                 . . .
  51.                                                                                              
  52.      T = 1993 Dec.  3.990 TT          Peri. = 102.512
  53.                                       Node  =   4.933   2000.0
  54.      q = 1.81118 AU                   Incl. = 145.454
  55.           1         2         3         4         5         6         7
  56. 01234567890123456789012345678901234567890123456789012345678901234567890
  57.  
  58.                             Output Format
  59.                             -------------
  60.     
  61. Name,Perihelion time,Perihelion AU,Eccentricity,Long. perihelion,Long. node,Inclination,Semimajor axis,Period
  62. P/1996 P1 (IRAS),1996-10-29.9968,1.702690,0.696589,356.8876,357.7007,45.9617,5.611833 AU,13.294 years
  63. C/1996 Q1 (TABUR),1996-11-3.562,0.84202,1,57.234,31.516,73.234,,Parabolic
  64. C/1996 P2 (RUSSELL-WATSON),1996-2-29.518,2.01067,1,188.661,101.556,29.134,,Parabolic
  65. P/1996 N2 (ELST-PIZARRO),1996-4-16.0159,2.617717,0.170415,132.4528,160.3483,1.3754,3.155453 AU,5.605 years
  66. C/1996 R1 (HERGENROTHER-SPAHR),1996-8-28.566,1.90096,1,139.250,149.648,145.876,,Parabolic
  67. P/1996 R2 (LAGERKVIST),1997-1-30.55,2.4783,0.3685,339.83,40.72,2.55,3.9245 AU,7.77 years
  68. P/1996 S2 (SHOEMAKER-HOLT 1),1997-11-20.2541,3.047026,0.321273,210.2130,214.5275,4.3617,4.489325 AU,9.512 years
  69. P/1996 U1 (SHOEMAKER-LEVY 3),1998-3-4.9475,2.817332,0.247914,181.3886,303.7122,5.0086,3.746025 AU,7.250 years
  70.     
  71. */
  72.  
  73. #include <stdio.h>
  74. #include <ctype.h>
  75. #include <string.h>
  76. #include <math.h>
  77.  
  78. #ifdef unix
  79. #define _strnicmp strncasecmp
  80. #define READMODE "r"
  81. #else
  82. /*  On DOS-like systems we read the input file in binary mode
  83.     so that a ^Z embedded in a Unix mail folder (they get there
  84.     when a DOS user embeds a file in a mail message) doesn't
  85.     truncate the input.  */
  86. #define READMODE "rb"
  87. #endif
  88.  
  89. /*  Define ECHO to embed the source lines from which each line of
  90.     CSV was generated.  This is handy for debugging when the format
  91.     changes.  */
  92.  
  93. #ifdef ECHO
  94. #define ECHOLINE(x) strcpy(s[x], s[0])
  95. #else
  96. #define ECHOLINE(x)
  97. #endif
  98.  
  99. static char s[8][132];                  /* Buffer to hold complete entry */
  100.  
  101. static int rs(char *s, FILE *fp)
  102. {
  103.     if (fgets(s, 132, fp) == NULL) {
  104.         return 0;
  105.     }
  106.     while (strlen(s) > 0 && s[strlen(s) - 1] < ' ') {
  107.         s[strlen(s) - 1] = 0;
  108.     }
  109.     return 1;
  110. }
  111.  
  112. static void sc(char *b, int line, int start, int end)
  113. {
  114.     char *c = s[line];
  115.     int i, n;
  116.     
  117.     for (i = 0, n = start; n <= end; n++) {
  118.         if (c[n] == 0) {
  119.             break;
  120.         }
  121.         if (!isspace(c[n])) {
  122.             b[i++] = c[n];
  123.         }
  124.     }
  125.     b[i] = 0;
  126. }
  127.  
  128.  
  129. static void sct(char *b, int line, int start, int end)
  130. {
  131.     char *c = s[line], sb[132];
  132.  
  133.     memcpy(sb, c + start, (end - start) + 1);
  134.     sb[(end - start) + 1] = 0;
  135.     while (strlen(sb) > 0 && isspace(sb[strlen(sb) - 1])) {
  136.         sb[strlen(sb) - 1] = 0;
  137.     }
  138.     c = sb;
  139.     while (*c && isspace(*c)) {
  140.         c++;
  141.     }
  142.     strcpy(b, c);
  143. }
  144.  
  145.  
  146. int main(int argc, char *argv[])
  147. {
  148.     int i, running = 1, written = 0;
  149.     FILE *fi = stdin, *fo = stdout;         /* Input and output file names */
  150.     static char cname[80], epoch[80], periau[80], perilong[80],
  151.                 eccen[80], longnode[80], inclin[80], semimaj[80], period[80];
  152.     
  153.     if (argc > 1) {
  154.         fi = fopen(argv[1], READMODE);      /* Input file */
  155.         if (fi == NULL) {
  156.             fprintf(stderr, "Cannot open input file %s\n", argv[1]);
  157.             return 2;
  158.         }
  159.         if (argc > 2) {
  160.             fo = fopen(argv[2], "w");       /* Output file */
  161.             if (fo == NULL) {
  162.                 fprintf(stderr, "Cannot open output file %s\n", argv[2]);
  163.                 return 2;
  164.             }
  165.         }
  166.     }
  167.  
  168.     fprintf(fo, "Name,Perihelion time,Perihelion AU,Eccentricity,Long. perihelion,\
  169. Long. node,Inclination,Semimajor axis,Period\n");
  170.     
  171.     while (running) {
  172.         int periodic = -1;
  173.         char *u, *v;
  174.         
  175.         while (1) {
  176.             if (!rs(s[0], fi)) {
  177.                 running = 0;
  178.                 break;
  179.             }
  180.             if (strncmp(s[0], "COMET ", 6) == 0) {
  181.                 sct(cname, 0, 6, 80);
  182.                 periodic = 0;
  183.                 break;  
  184.             } else if (strncmp(s[0], "PERIODIC COMET ", 15) == 0) {
  185.                 sct(cname, 0, 15, 80);
  186.                 periodic = 1;
  187.                 break;
  188.             } 
  189.         }
  190.         
  191.         if (!running) {
  192.             break;
  193.         }
  194.  
  195.         ECHOLINE(1);
  196.         
  197.         /* Scan until we either find a line which begins with the "T ="
  198.            specification or run into another comet header (indicating
  199.            this circular didn't contain elements. */
  200.            
  201.         while (1) {
  202.             char t[132];
  203.         
  204.             if (!rs(s[0], fi)) {
  205.                 running = 0;
  206.                 break;
  207.             }
  208.             if (strncmp(s[0], "COMET ", 6) == 0) {
  209.                 sct(cname, 0, 6, 80);
  210.                 periodic = 0;
  211.                 ECHOLINE(1);
  212.                 continue;  
  213.             } else if (strncmp(s[0], "PERIODIC COMET ", 15) == 0) {
  214.                 sct(cname, 0, 15, 80);
  215.                 periodic = 1;
  216.                 ECHOLINE(1);
  217.                 continue;
  218.             }
  219.             ECHOLINE(2);
  220.             sc(t, 0, 0, 80);
  221.             if (strncmp(t, "T=", 2) == 0 && isdigit(t[2])) {
  222.                 char y[20], m[20], daf[20];
  223.                 static char mname[] = "janfebmaraprmayjunjulaugsepoctnovdec";
  224.                 
  225.                 sscanf(u = strchr(s[0], '=') + 1, "%s %s", y, m);
  226.                 for (i = 0; i < 12; i++) {
  227.                     if (_strnicmp(m, mname + i * 3, 3) == 0) {
  228.                         sprintf(m, "%d", i + 1);
  229.                         break;
  230.                     }
  231.                 }
  232.                 
  233.                 /* Tiptoe up to the start of the year, since in the
  234.                    case of "Sept.199x" the month runs into the first
  235.                    digit of the year.  This code is resiliant in case
  236.                    a space is added later. */
  237.                 
  238.                 while (*u && isspace(*u)) {
  239.                     u++;
  240.                 }
  241.                 while (*u && !isspace(*u)) {
  242.                     u++;
  243.                 }
  244.                 while (*u && isspace(*u)) {
  245.                     u++;
  246.                 }
  247.                 while (*u && !isdigit(*u)) {
  248.                     u++;
  249.                 }
  250.                 sscanf(u, "%s", daf);
  251.                 sprintf(epoch, "%s-%s-%s", y, m, daf);
  252.                 v = strchr(u, '=');
  253.                 if (v != NULL) {
  254.                     sc(perilong, 0, (v + 1) - s[0], 80);
  255.                 } else {
  256.                     continue;
  257.                 }
  258.                 
  259.                 /* Process second line. */
  260.                 
  261.                 if (!rs(s[0], fi)) {
  262.                     running = 0;
  263.                     break;
  264.                 }
  265.                 ECHOLINE(3);
  266.                 sc(t, 0, 0, 80);
  267.                 if (strncmp(t, "e=", 2) == 0) {
  268.                     sscanf(u = strchr(s[0], '=') + 1, "%s", eccen);
  269.                     v = strchr(u, '='); 
  270.                     periodic = 1;
  271.                 } else {
  272.                     strcpy(eccen, "1");         /* Parabolic */
  273.                     v = strchr(s[0], '=');
  274.                 }
  275.                 if (v != NULL) {
  276.                     sscanf(v + 1, "%s", longnode);
  277.                 } else {
  278.                     continue;
  279.                 }
  280.                 
  281.                 /* Process third line. */
  282.                 
  283.                 if (!rs(s[0], fi)) {
  284.                     running = 0;
  285.                     break;
  286.                 }
  287.                 ECHOLINE(4);
  288.                 u = strchr(s[0], '=');
  289.                 if (u != NULL) {
  290.                     v = strchr(u + 1, '=');
  291.                 }
  292.                 if (u != NULL && v != NULL) {
  293.                     sscanf(u + 1, "%s", periau);
  294.                     sscanf(v + 1, "%s", inclin);
  295.                 } else {
  296.                     continue;
  297.                 }
  298.                 
  299.                 /* Process fourth line if comet is periodic. */
  300.                 
  301.                 strcpy(semimaj, "");
  302.                 strcpy(period, "Parabolic");
  303.                 if (periodic) {
  304.                     if (!rs(s[0], fi)) {
  305.                         running = 0;
  306.                         break;
  307.                     }
  308.                     ECHOLINE(5);
  309.                     u = strchr(s[0], '=');
  310.                     if (u != NULL) {
  311.                         v = strchr(u + 1, '=');
  312.                         if (v != NULL) {
  313.                             v = strchr(v + 1, '=');
  314.                         }
  315.                     }
  316.                     if (u != NULL && v != NULL) {
  317.                         char t1[30], t2[30];
  318.                         
  319.                         sscanf(u + 1, "%s %s", t1, t2);
  320.                         sprintf(semimaj, "%s %s", t1, t2);
  321.                         sscanf(v + 1, "%s %s", t1, t2);
  322.                         sprintf(period, "%s %s", t1, t2);
  323.                     } else {
  324.                         continue;
  325.                     }
  326.                 }
  327.                  
  328.                 break;
  329.             } 
  330.         }
  331.         
  332.         if (!running) {
  333.             break;
  334.         }
  335.  
  336. #ifdef ECHO
  337.         fprintf(fo, "\n\
  338.           1         2         3         4         5         6         7\n\
  339. 01234567890123456789012345678901234567890123456789012345678901234567890\n");
  340.         for (i = 1; i <= (periodic ? 5 : 4); i++) {
  341.             fprintf(fo, "%s\n", s[i]);
  342.         }
  343. #endif
  344.         
  345.         /* Output information in CSV format. */
  346.  
  347.         fprintf(fo, "%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
  348.                     cname, epoch, periau, eccen, perilong, longnode, inclin,
  349.                     semimaj, period);
  350.         written++;                  
  351.     }
  352.     
  353.     fclose(fi);
  354.     fclose(fo);
  355.     fprintf(stderr, "%d record%s written.\n", written, written == 1 ? "" : "s");        
  356.     
  357.     return 0;
  358. }
  359.