home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2002 March
/
PCWorld_2002-03_cd.bin
/
Software
/
Vyzkuste
/
homeplanet
/
TOOLS
/
COMETEL.C
< prev
Wrap
C/C++ Source or Header
|
1997-04-04
|
12KB
|
359 lines
/*
Convert comet elements in the formats used by the Minor Planet
Center (and in the Minor Planet Electronic Circulars) to Home
Planet CSV format. Multiple comet announcements can be extracted
from a file containing other irrelevant information. This allows
you, for example, to process an entire Unix mail folder and extract
elements from all archived circulars within.
Designed and implemented by John Walker in November of 1994.
Revision 1 by John Walker in April 1997 to use presence of
eccentricity to flag periodic comet format.
Elliptical Orbital Elements
---------------------------
PERIODIC COMET SHOEMAKER 4 (1994k)
. . .
T = 1994 Oct. 31.231 TT Peri. = 196.521
e = 0.52851 Node = 92.603 2000.0
q = 2.92503 AU Incl. = 25.345
a = 6.20375 AU n = 0.063786 P = 15.45 years
1 2 3 4 5 6 7
01234567890123456789012345678901234567890123456789012345678901234567890
Some time after the original version of this program was released,
IAUCs dropped the "PERIODIC " designation, relying on the presence
or absence of eccentricity to distinguish elliptical and parabolic
elements. The form for periodic elements as of this revision
(April 1997) is as follows:
COMET P/1997 B1 (KOBAYASHI)
. . .
T = 1997 Mar. 4.295 TT Peri. = 184.202
e = 0.76831 Node = 329.032 2000.0
q = 2.06219 AU Incl. = 12.490
a = 8.90047 AU n = 0.037118 P = 26.55 years
1 2 3 4 5 6 7
01234567890123456789012345678901234567890123456789012345678901234567890
Parabolic Orbital Elements
--------------------------
COMET MUELLER (1994c)
. . .
T = 1993 Dec. 3.990 TT Peri. = 102.512
Node = 4.933 2000.0
q = 1.81118 AU Incl. = 145.454
1 2 3 4 5 6 7
01234567890123456789012345678901234567890123456789012345678901234567890
Output Format
-------------
Name,Perihelion time,Perihelion AU,Eccentricity,Long. perihelion,Long. node,Inclination,Semimajor axis,Period
P/1996 P1 (IRAS),1996-10-29.9968,1.702690,0.696589,356.8876,357.7007,45.9617,5.611833 AU,13.294 years
C/1996 Q1 (TABUR),1996-11-3.562,0.84202,1,57.234,31.516,73.234,,Parabolic
C/1996 P2 (RUSSELL-WATSON),1996-2-29.518,2.01067,1,188.661,101.556,29.134,,Parabolic
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
C/1996 R1 (HERGENROTHER-SPAHR),1996-8-28.566,1.90096,1,139.250,149.648,145.876,,Parabolic
P/1996 R2 (LAGERKVIST),1997-1-30.55,2.4783,0.3685,339.83,40.72,2.55,3.9245 AU,7.77 years
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
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
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#ifdef unix
#define _strnicmp strncasecmp
#define READMODE "r"
#else
/* On DOS-like systems we read the input file in binary mode
so that a ^Z embedded in a Unix mail folder (they get there
when a DOS user embeds a file in a mail message) doesn't
truncate the input. */
#define READMODE "rb"
#endif
/* Define ECHO to embed the source lines from which each line of
CSV was generated. This is handy for debugging when the format
changes. */
#ifdef ECHO
#define ECHOLINE(x) strcpy(s[x], s[0])
#else
#define ECHOLINE(x)
#endif
static char s[8][132]; /* Buffer to hold complete entry */
static int rs(char *s, FILE *fp)
{
if (fgets(s, 132, fp) == NULL) {
return 0;
}
while (strlen(s) > 0 && s[strlen(s) - 1] < ' ') {
s[strlen(s) - 1] = 0;
}
return 1;
}
static void sc(char *b, int line, int start, int end)
{
char *c = s[line];
int i, n;
for (i = 0, n = start; n <= end; n++) {
if (c[n] == 0) {
break;
}
if (!isspace(c[n])) {
b[i++] = c[n];
}
}
b[i] = 0;
}
static void sct(char *b, int line, int start, int end)
{
char *c = s[line], sb[132];
memcpy(sb, c + start, (end - start) + 1);
sb[(end - start) + 1] = 0;
while (strlen(sb) > 0 && isspace(sb[strlen(sb) - 1])) {
sb[strlen(sb) - 1] = 0;
}
c = sb;
while (*c && isspace(*c)) {
c++;
}
strcpy(b, c);
}
int main(int argc, char *argv[])
{
int i, running = 1, written = 0;
FILE *fi = stdin, *fo = stdout; /* Input and output file names */
static char cname[80], epoch[80], periau[80], perilong[80],
eccen[80], longnode[80], inclin[80], semimaj[80], period[80];
if (argc > 1) {
fi = fopen(argv[1], READMODE); /* Input file */
if (fi == NULL) {
fprintf(stderr, "Cannot open input file %s\n", argv[1]);
return 2;
}
if (argc > 2) {
fo = fopen(argv[2], "w"); /* Output file */
if (fo == NULL) {
fprintf(stderr, "Cannot open output file %s\n", argv[2]);
return 2;
}
}
}
fprintf(fo, "Name,Perihelion time,Perihelion AU,Eccentricity,Long. perihelion,\
Long. node,Inclination,Semimajor axis,Period\n");
while (running) {
int periodic = -1;
char *u, *v;
while (1) {
if (!rs(s[0], fi)) {
running = 0;
break;
}
if (strncmp(s[0], "COMET ", 6) == 0) {
sct(cname, 0, 6, 80);
periodic = 0;
break;
} else if (strncmp(s[0], "PERIODIC COMET ", 15) == 0) {
sct(cname, 0, 15, 80);
periodic = 1;
break;
}
}
if (!running) {
break;
}
ECHOLINE(1);
/* Scan until we either find a line which begins with the "T ="
specification or run into another comet header (indicating
this circular didn't contain elements. */
while (1) {
char t[132];
if (!rs(s[0], fi)) {
running = 0;
break;
}
if (strncmp(s[0], "COMET ", 6) == 0) {
sct(cname, 0, 6, 80);
periodic = 0;
ECHOLINE(1);
continue;
} else if (strncmp(s[0], "PERIODIC COMET ", 15) == 0) {
sct(cname, 0, 15, 80);
periodic = 1;
ECHOLINE(1);
continue;
}
ECHOLINE(2);
sc(t, 0, 0, 80);
if (strncmp(t, "T=", 2) == 0 && isdigit(t[2])) {
char y[20], m[20], daf[20];
static char mname[] = "janfebmaraprmayjunjulaugsepoctnovdec";
sscanf(u = strchr(s[0], '=') + 1, "%s %s", y, m);
for (i = 0; i < 12; i++) {
if (_strnicmp(m, mname + i * 3, 3) == 0) {
sprintf(m, "%d", i + 1);
break;
}
}
/* Tiptoe up to the start of the year, since in the
case of "Sept.199x" the month runs into the first
digit of the year. This code is resiliant in case
a space is added later. */
while (*u && isspace(*u)) {
u++;
}
while (*u && !isspace(*u)) {
u++;
}
while (*u && isspace(*u)) {
u++;
}
while (*u && !isdigit(*u)) {
u++;
}
sscanf(u, "%s", daf);
sprintf(epoch, "%s-%s-%s", y, m, daf);
v = strchr(u, '=');
if (v != NULL) {
sc(perilong, 0, (v + 1) - s[0], 80);
} else {
continue;
}
/* Process second line. */
if (!rs(s[0], fi)) {
running = 0;
break;
}
ECHOLINE(3);
sc(t, 0, 0, 80);
if (strncmp(t, "e=", 2) == 0) {
sscanf(u = strchr(s[0], '=') + 1, "%s", eccen);
v = strchr(u, '=');
periodic = 1;
} else {
strcpy(eccen, "1"); /* Parabolic */
v = strchr(s[0], '=');
}
if (v != NULL) {
sscanf(v + 1, "%s", longnode);
} else {
continue;
}
/* Process third line. */
if (!rs(s[0], fi)) {
running = 0;
break;
}
ECHOLINE(4);
u = strchr(s[0], '=');
if (u != NULL) {
v = strchr(u + 1, '=');
}
if (u != NULL && v != NULL) {
sscanf(u + 1, "%s", periau);
sscanf(v + 1, "%s", inclin);
} else {
continue;
}
/* Process fourth line if comet is periodic. */
strcpy(semimaj, "");
strcpy(period, "Parabolic");
if (periodic) {
if (!rs(s[0], fi)) {
running = 0;
break;
}
ECHOLINE(5);
u = strchr(s[0], '=');
if (u != NULL) {
v = strchr(u + 1, '=');
if (v != NULL) {
v = strchr(v + 1, '=');
}
}
if (u != NULL && v != NULL) {
char t1[30], t2[30];
sscanf(u + 1, "%s %s", t1, t2);
sprintf(semimaj, "%s %s", t1, t2);
sscanf(v + 1, "%s %s", t1, t2);
sprintf(period, "%s %s", t1, t2);
} else {
continue;
}
}
break;
}
}
if (!running) {
break;
}
#ifdef ECHO
fprintf(fo, "\n\
1 2 3 4 5 6 7\n\
01234567890123456789012345678901234567890123456789012345678901234567890\n");
for (i = 1; i <= (periodic ? 5 : 4); i++) {
fprintf(fo, "%s\n", s[i]);
}
#endif
/* Output information in CSV format. */
fprintf(fo, "%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
cname, epoch, periau, eccen, perilong, longnode, inclin,
semimaj, period);
written++;
}
fclose(fi);
fclose(fo);
fprintf(stderr, "%d record%s written.\n", written, written == 1 ? "" : "s");
return 0;
}