source: Sophya/trunk/SophyaExt/XephemAstroLib/dbfmt.c@ 4017

Last change on this file since 4017 was 4017, checked in by cmv, 14 years ago

fichiers de Xephem 3.7.5 update, cmv 21/09/2011

File size: 25.5 KB
Line 
1/* code to convert between .edb format and an Obj */
2
3#include <stdio.h>
4#include <ctype.h>
5#include <math.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "astro.h"
10#include "preferences.h"
11
12
13int get_fields (char *s, int delim, char *fields[]);
14
15#define MAXDBLINE 512 /* longest allowed db line */
16
17#define FLDSEP ',' /* major field separator */
18#define SUBFLD '|' /* subfield separator */
19#define MAXFLDS 20 /* must be more than on any expected line */
20#define MAXESGOOD 100 /* max earth satellite good, days */
21
22static char *enm (char *flds[MAXFLDS]);
23static int crack_f (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
24static int crack_e (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
25static int crack_h (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
26static int crack_p (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
27static int crack_E (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
28static int crack_P (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
29static int crack_B (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
30static int crack_name (Obj *op, char *flds[MAXFLDS], int nf,
31 char nm[][MAXNM], int nnm);
32static void crack_year (char *bp, double *p);
33static void crack_okdates (char *fld, float *startok, float *endok);
34static int get_okdates (char *lp, float *sp, float *ep);
35static int tle_sum (char *l);
36static double tle_fld (char *l, int from, int thru);
37static double tle_expfld (char *l, int start);
38static void write_f (Obj *op, char lp[]);
39static void write_e (Obj *op, char lp[]);
40static void write_h (Obj *op, char lp[]);
41static void write_p (Obj *op, char lp[]);
42static void write_E (Obj *op, char lp[]);
43static void write_P (Obj *op, char lp[]);
44static void write_B (Obj *op, char lp[]);
45
46/* crack the given .edb database line into op.
47 * if ok
48 * return number of names in nm[], or 1 if nm == NULL
49 * else
50 * if whynot
51 * if not even a candidate
52 * set whynot[0] = '\0'
53 * else
54 * fill whynot with reason message.
55 * return -1
56 * only the first name is stored in op, all names (up to nnm) are in nm[], or
57 * ignored if nm == NULL.
58 */
59int
60db_crack_line (char s[], Obj *op, char nm[][MAXNM], int nnm, char whynot[])
61{
62 char copy[MAXDBLINE]; /* work copy; leave s untouched */
63 char *flds[MAXFLDS]; /* point to each field for easy reference */
64 int nf;
65 int i;
66
67 /* init no response */
68 if (whynot)
69 whynot[0] = '\0';
70
71 /* basic initial check */
72 if (dbline_candidate (s) < 0)
73 return (-1);
74
75 /* do all the parsing on a copy */
76 (void) strncpy (copy, s, MAXDBLINE-1);
77 copy[MAXDBLINE-1] = '\0';
78 i = strlen(copy);
79 if (copy[i-1] == '\n')
80 copy[i-1] = '\0';
81
82 /* parse into main fields */
83 nf = get_fields (copy, FLDSEP, flds);
84
85 /* need at least 2: name and type */
86 if (nf < 2) {
87 if (whynot)
88 sprintf (whynot, "Bogus: %s", s);
89 return (-1);
90 }
91
92 /* switch out on type of object - the second field */
93 switch (flds[1][0]) {
94
95 case 'f':
96 if (crack_f (op, flds, nf, whynot) < 0)
97 return (-1);
98 break;
99
100 case 'e':
101 if (crack_e (op, flds, nf, whynot) < 0)
102 return (-1);
103 break;
104
105 case 'h':
106 if (crack_h (op, flds, nf, whynot) < 0)
107 return (-1);
108 break;
109
110 case 'p':
111 if (crack_p (op, flds, nf, whynot) < 0)
112 return (-1);
113 break;
114
115 case 'B':
116 if (crack_B (op, flds, nf, whynot) < 0)
117 return (-1);
118 break;
119
120 case 'E':
121 if (crack_E (op, flds, nf, whynot) < 0)
122 return (-1);
123 break;
124
125 case 'P':
126 if (crack_P (op, flds, nf, whynot) < 0)
127 return (-1);
128 break;
129
130 default:
131 if (whynot)
132 sprintf (whynot, "%s: Unknown type %c for %s", enm(flds),
133 flds[1][0], flds[0]);
134 return (-1);
135 }
136
137 return (crack_name (op, flds, nf, nm, nnm));
138}
139
140/* write the given Obj in .edb format to lp[].
141 * we do _not_ include a trailing '\n'.
142 */
143void
144db_write_line (Obj *op, char lp[])
145{
146 switch (op->o_type) {
147 case FIXED:
148 write_f (op, lp);
149 break;
150
151 case BINARYSTAR:
152 write_B (op, lp);
153 break;
154
155 case ELLIPTICAL:
156 write_e (op, lp);
157 break;
158
159 case HYPERBOLIC:
160 write_h (op, lp);
161 break;
162
163 case PARABOLIC:
164 write_p (op, lp);
165 break;
166
167 case EARTHSAT:
168 write_E (op, lp);
169 break;
170
171 case PLANET:
172 write_P (op, lp);
173 break;
174
175 default:
176 printf ("Unknown type for %s: %d\n", op->o_name, op->o_type);
177 abort();
178 }
179}
180
181/* given 3 lines, first of which is name and next 2 are TLE, fill op.
182 * we skip leading whitespace on all lines.
183 * we do /not/ assume the 2 TLE lines are 0 terminated, but we do reach out into
184 * each as far as 69 chars.
185 * we detect nonconformance as efficiently as possible.
186 * name ends at first '\0', '\r' or '\n'.
187 * set startok/endok.
188 * if ok return 0 else return -1
189 */
190int
191db_tle (char *name, char *l1, char *l2, Obj *op)
192{
193 double ep;
194 int i;
195
196 /* check for correct line numbers, macthing satellite numbers and
197 * correct checksums.
198 */
199 while (isspace(*l1))
200 l1++;
201 if (*l1 != '1')
202 return (-1);
203 while (isspace(*l2))
204 l2++;
205 if (*l2 != '2')
206 return (-1);
207 if (strncmp (l1+2, l2+2, 5))
208 return (-1);
209 if (tle_sum (l1) < 0)
210 return (-1);
211 if (tle_sum (l2) < 0)
212 return (-1);
213
214 /* assume it's ok from here out */
215
216 /* fresh */
217 zero_mem ((void *)op, sizeof(ObjES));
218 op->o_type = EARTHSAT;
219
220 /* name, sans leading and trailing whitespace */
221 while (isspace(*name))
222 name++;
223 i = strcspn (name, "\r\n");
224 while (i > 0 && name[i-1] == ' ')
225 --i;
226 if (i == 0)
227 return (-1);
228 if (i > MAXNM-1)
229 i = MAXNM-1;
230 sprintf (op->o_name, "%.*s", i, name);
231
232 /* goodies from "line 1" */
233 op->es_drag = (float) tle_expfld (l1, 54);
234 op->es_decay = (float) tle_fld (l1, 34, 43);
235 i = (int) tle_fld (l1, 19, 20);
236 if (i < 57)
237 i += 100;
238 cal_mjd (1, tle_fld(l1, 21, 32), i+1900, &ep);
239 op->es_epoch = ep;
240
241 /* goodies from "line 2" */
242 op->es_n = tle_fld (l2, 53, 63);
243 op->es_inc = (float)tle_fld (l2, 9, 16);
244 op->es_raan = (float)tle_fld (l2, 18, 25);
245 op->es_e = (float)(tle_fld (l2, 27, 33) * 1e-7);
246 op->es_ap = (float)tle_fld (l2, 35, 42);
247 op->es_M = (float)tle_fld (l2, 44, 51);
248 op->es_orbit = (int)tle_fld (l2, 64, 68);
249
250 /* limit date range to decay period that changes period by 1% but
251 * never more than MAXESGOOD.
252 * es_n is rev/day, es_decay is (rev/day)/day
253 */
254 if (fabs(op->es_decay) > 0) {
255 double dt = 0.01*op->es_n/fabs(op->es_decay);
256 if (dt > MAXESGOOD)
257 dt = MAXESGOOD;
258 op->es_startok = op->es_epoch - dt;
259 op->es_endok = op->es_epoch + dt;
260 }
261
262 /* yes! */
263 return (0);
264}
265
266/* return 0 if op has no date range information or what it does have brackets
267 * now, else -1
268 */
269int
270dateRangeOK (Now *np, Obj *op)
271{
272 float *sp, *ep;
273
274 switch (op->o_type) {
275 case ELLIPTICAL:
276 sp = &op->e_startok;
277 ep = &op->e_endok;
278 break;
279 case HYPERBOLIC:
280 sp = &op->h_startok;
281 ep = &op->h_endok;
282 break;
283 case PARABOLIC:
284 sp = &op->p_startok;
285 ep = &op->p_endok;
286 break;
287 case EARTHSAT:
288 sp = &op->es_startok;
289 ep = &op->es_endok;
290 break;
291 default:
292 return (0);
293 }
294
295 if (*sp <= mjd && (!*ep || mjd <= *ep))
296 return (0);
297 return (-1);
298}
299
300/* given a null-terminated string, fill in fields[] with the starting addresses
301 * of each field delimited by delim or '\0'.
302 * N.B. each character matching delim is REPLACED BY '\0' IN PLACE.
303 * N.B. 0-length fields count, so even if *s=='\0' we return 1.
304 * return the number of fields.
305 */
306int
307get_fields (char *s, int delim, char *fields[])
308{
309 int n;
310 char c;
311
312 *fields = s;
313 n = 0;
314 do {
315 c = *s++;
316 if (c == delim || c == '\0') {
317 s[-1] = '\0';
318 *++fields = s;
319 n++;
320 }
321 } while (c);
322
323 return (n);
324}
325
326/* return 0 if buf qualifies as a database line worthy of a cracking
327 * attempt, else -1.
328 */
329int
330dbline_candidate (char *buf)
331{
332 char c = buf[0];
333
334 return (c == '#' || c == '!' || isspace(c) ? -1 : 0);
335}
336
337/* return 0 if TLE checksum is ok, else -1 */
338static int
339tle_sum (char *l)
340{
341 char *lastl = l + 68;
342 int sum;
343
344 for (sum = 0; l < lastl; ) {
345 char c = *l++;
346 if (c == '\0')
347 return (-1);
348 if (isdigit(c))
349 sum += c - '0';
350 else if (c == '-')
351 sum++;
352 }
353
354 return (*l - '0' == (sum%10) ? 0 : -1);
355}
356
357/* extract the given columns and return value.
358 * N.B. from and to are 1-based within l
359 */
360static double
361tle_fld (char *l, int from, int thru)
362{
363 char buf[32];
364
365 sprintf (buf, "%.*s", thru-from+1, l+from-1);
366 return (atod (buf));
367}
368
369/* extract the exponential value starting at the given column.
370 * N.B. start is 1-based within l
371 */
372static double
373tle_expfld (char *l, int start)
374{
375 char buf[32];
376 double v;
377
378 sprintf (buf, ".%.*s", 5, l+start);
379 v = atod (buf) * pow (10.0, tle_fld(l, start+6, start+7));
380 if (l[start-1] == '-')
381 v = -v;
382 return (v);
383}
384
385static int
386crack_f (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
387{
388 char *sflds[MAXFLDS];
389 double tmp;
390 int nsf;
391
392 if (nf < 5 || nf > 7) {
393 if (whynot)
394 sprintf (whynot, "%s: type f needs 5-7 fields, not %d",
395 enm(flds),nf);
396 return (-1);
397 }
398
399 zero_mem ((void *)op, sizeof(ObjF));
400 op->o_type = FIXED;
401
402 nsf = get_fields(flds[1], SUBFLD, sflds);
403 if (nsf > 1) {
404 switch (sflds[1][0]) {
405 case 'A': case 'B': case 'C': case 'D': case 'F': case 'G':
406 case 'H': case 'K': case 'J': case 'L': case 'M': case 'N':
407 case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
408 case 'U': case 'V': case 'Y':
409 op->f_class = sflds[1][0];
410 if (op->f_class == 'B')
411 op->f_class = 'D'; /* merge B and D since BINARYSTAR */
412 break;
413 default:
414 if (whynot)
415 sprintf (whynot, "%s: Bad f class: %c", enm(flds),
416 sflds[1][0]);
417 return (-1);
418 }
419 } else
420 op->f_class = 'T'; /* default to star-like */
421 if (nsf > 2) {
422 /* fill f_spect all the way */
423 char buf[sizeof(op->f_spect)+1];
424 memset (buf, 0, sizeof(buf));
425 sprintf (buf, "%.*s", (int)sizeof(op->f_spect), sflds[2]);
426 memcpy (op->f_spect, buf, (int)sizeof(op->f_spect));
427 }
428
429 nsf = get_fields(flds[2], SUBFLD, sflds);
430 f_scansexa (sflds[0], &tmp);
431 op->f_RA = (float) hrrad(tmp);
432 if (nsf > 1)
433 op->f_pmRA = (float) 1.327e-11*atod(sflds[1]);/*mas/yr->rad/dy*/
434
435 nsf = get_fields(flds[3], SUBFLD, sflds);
436 f_scansexa (sflds[0], &tmp);
437 op->f_dec = (float) degrad(tmp);
438 if (nsf > 1)
439 op->f_pmdec = (float)1.327e-11*atod(sflds[1]);/*mas/yr->rad/dy*/
440 if (fabs(op->f_dec) < PI/2)
441 op->f_pmRA /= cos (op->f_dec);
442
443 set_fmag (op, atod(flds[4]));
444
445 if (nf > 5 && flds[5][0]) {
446 tmp = op->f_epoch;
447 crack_year (flds[5], &tmp);
448 op->f_epoch = (float) tmp;
449 } else
450 op->f_epoch = J2000; /* default */
451
452 if (nf > 6) {
453 op->f_size = (float) atod(flds[6]);
454
455 /* optional minor axis and position angle subfields */
456 nsf = get_fields(flds[6], SUBFLD, sflds);
457 if (nsf == 3) {
458 set_ratio(op, op->s_size, atod(sflds[1]));
459 set_pa(op,degrad(atod(sflds[2])));
460 } else {
461 set_ratio(op,1,1); /* round */
462 set_pa(op,0.0);
463 }
464 }
465
466 return (0);
467}
468
469static int
470crack_e (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
471{
472 if (nf != 13 && nf != 14) {
473 if (whynot)
474 sprintf (whynot, "%s: type e needs 13 or 14 fields, not %d",
475 enm(flds), nf);
476 return (-1);
477 }
478
479 zero_mem ((void *)op, sizeof(ObjE));
480 op->o_type = ELLIPTICAL;
481
482 op->e_inc = (float) atod (flds[2]);
483 op->e_Om = (float) atod (flds[3]);
484 op->e_om = (float) atod (flds[4]);
485 op->e_a = (float) atod (flds[5]);
486 /* retired op->e_n = (float) atod (flds[6]); */
487 op->e_e = atod (flds[7]);
488 op->e_M = (float) atod (flds[8]);
489 crack_year (flds[9], &op->e_cepoch);
490 crack_okdates (flds[9], &op->e_startok, &op->e_endok);
491 crack_year (flds[10], &op->e_epoch);
492
493 /* magnitude model gk or HG(default). allow prefixes in either field */
494 op->e_mag.whichm = flds[11][0] == 'g' ? MAG_gk : MAG_HG;
495 if (isdigit(flds[11][0]))
496 op->e_mag.m1 = (float) atod(&flds[11][0]);
497 else
498 op->e_mag.m1 = (float) atod(&flds[11][1]);
499 if (isdigit(flds[12][0]))
500 op->e_mag.m2 = (float) atod(&flds[12][0]);
501 else
502 op->e_mag.m2 = (float) atod(&flds[12][1]);
503
504 if (nf == 14)
505 op->e_size = (float) atod (flds[13]);
506
507 return (0);
508}
509
510static int
511crack_h (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
512{
513 if (nf != 11 && nf != 12) {
514 if (whynot)
515 sprintf (whynot, "%s: type h needs 11 or 12 fields, not %d",
516 enm(flds), nf);
517 return (-1);
518 }
519
520 zero_mem ((void *)op, sizeof(ObjH));
521 op->o_type = HYPERBOLIC;
522
523 crack_year (flds[2], &op->h_ep);
524 crack_okdates (flds[2], &op->h_startok, &op->h_endok);
525 op->h_inc = (float) atod (flds[3]);
526 op->h_Om = (float) atod (flds[4]);
527 op->h_om = (float) atod (flds[5]);
528 op->h_e = (float) atod (flds[6]);
529 op->h_qp = (float) atod (flds[7]);
530 crack_year (flds[8], &op->h_epoch);
531 op->h_g = (float) atod (flds[9]);
532 op->h_k = (float) atod (flds[10]);
533
534 if (nf == 12)
535 op->h_size = (float) atod (flds[11]);
536
537 return (0);
538}
539
540static int
541crack_p (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
542{
543 if (nf != 10 && nf != 11) {
544 if (whynot)
545 sprintf (whynot, "%s: type p needs 10 or 11 fields, not %d",
546 enm(flds), nf);
547 return (-1);
548 }
549
550 zero_mem ((void *)op, sizeof(ObjP));
551 op->o_type = PARABOLIC;
552
553 crack_year (flds[2], &op->p_ep);
554 crack_okdates (flds[2], &op->p_startok, &op->p_endok);
555 op->p_inc = (float) atod (flds[3]);
556 op->p_om = (float) atod (flds[4]);
557 op->p_qp = (float) atod (flds[5]);
558 op->p_Om = (float) atod (flds[6]);
559 crack_year (flds[7], &op->p_epoch);
560 op->p_g = (float) atod (flds[8]);
561 op->p_k = (float) atod (flds[9]);
562
563 if (nf == 11)
564 op->p_size = (float) atod (flds[10]);
565
566 return (0);
567}
568
569static int
570crack_E (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
571{
572 if (nf != 11 && nf != 12) {
573 if (whynot)
574 sprintf (whynot, "%s: type E needs 11 or 12 fields, not %d",
575 enm(flds), nf);
576 return (-1);
577 }
578
579 zero_mem ((void *)op, sizeof(ObjES));
580 op->o_type = EARTHSAT;
581 crack_year (flds[2], &op->es_epoch);
582 crack_okdates (flds[2], &op->es_startok, &op->es_endok);
583 op->es_inc = (float) atod (flds[3]);
584 op->es_raan = (float) atod (flds[4]);
585 op->es_e = (float) atod (flds[5]);
586 op->es_ap = (float) atod (flds[6]);
587 op->es_M = (float) atod (flds[7]);
588 op->es_n = atod (flds[8]);
589 op->es_decay = (float) atod (flds[9]);
590 op->es_orbit = atoi (flds[10]);
591 if (nf == 12)
592 op->es_drag = (float) atod (flds[11]);
593
594 /* if not already specified, limit date range to decay period that
595 * changes period by 1% but never longer than MAXESGOOD.
596 * es_n is rev/day, es_decay is (rev/day)/day
597 */
598 if (op->es_startok == 0 && op->es_endok == 0 && fabs(op->es_decay) > 0){
599 double dt = 0.01*op->es_n/fabs(op->es_decay);
600 if (dt > MAXESGOOD)
601 dt = MAXESGOOD;
602 op->es_startok = op->es_epoch - dt;
603 op->es_endok = op->es_epoch + dt;
604 }
605
606 return (0);
607}
608
609static int
610crack_P (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
611{
612 Obj *bi;
613 int nbi;
614 int i;
615
616 nbi = getBuiltInObjs (&bi);
617
618 for (i = 0; i < nbi; i++) {
619 Obj *bop = bi + i;
620 if (is_type(bop,PLANETM) && !strcmp (flds[0], bop->o_name)) {
621 memcpy ((void *)op, bop, sizeof(ObjPl));
622 return (0);
623 }
624 }
625
626 if (whynot)
627 sprintf (whynot, "%s: Unknown planet or moon", enm(flds));
628 return (-1);
629}
630
631static int
632crack_B (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
633{
634 char *sflds[MAXFLDS];
635 double tmp;
636 int nsf;
637
638 if (nf != 7) {
639 if (whynot)
640 sprintf (whynot, "%s: B need 7 fields, not %d", enm(flds), nf);
641 return (-1);
642 }
643
644 zero_mem ((void *)op, sizeof(ObjB));
645 op->o_type = BINARYSTAR;
646
647 nsf = get_fields(flds[1], SUBFLD, sflds);
648 if (nsf > 1) {
649 switch (sflds[1][0]) {
650 case 'a': case 'c': case 'e': case 'x': case 'y': case 'o':
651 case 's': case 't': case 'u': case 'v': case 'b': case 'd':
652 case 'q': case 'r': case 'p': case 'U': case 'V': case 'Y':
653 op->f_class = sflds[1][0];
654 break;
655 default:
656 if (whynot)
657 sprintf (whynot, "%s: Bad B class: %c", enm(flds),
658 sflds[1][0]);
659 return (-1);
660 }
661 }
662 if (nsf > 2) {
663 /* fill f_spect all the way */
664 char buf[sizeof(op->f_spect)+1];
665 memset (buf, 0, sizeof(buf));
666 sprintf (buf, "%.*s", (int)sizeof(op->f_spect), sflds[2]);
667 memcpy (op->f_spect, buf, (int)sizeof(op->f_spect));
668 }
669 if (nsf > 3) {
670 /* fill b_2spect all the way */
671 char buf[sizeof(op->b_2spect)+1];
672 memset (buf, 0, sizeof(buf));
673 sprintf (buf, "%.*s", (int)sizeof(op->b_2spect), sflds[3]);
674 memcpy (op->b_2spect, buf, (int)sizeof(op->b_2spect));
675 }
676
677 nsf = get_fields(flds[2], SUBFLD, sflds);
678 f_scansexa (sflds[0], &tmp);
679 op->f_RA = (float) hrrad(tmp);
680 if (nsf > 1)
681 op->f_pmRA = (float) 1.327e-11*atod(sflds[1]);/*mas/yr->rad/dy*/
682
683 nsf = get_fields(flds[3], SUBFLD, sflds);
684 f_scansexa (sflds[0], &tmp);
685 op->f_dec = (float) degrad(tmp);
686 if (nsf > 1)
687 op->f_pmdec = (float)1.327e-11*atod(sflds[1]);/*mas/yr->rad/dy*/
688 if (fabs(op->f_dec) < PI/2)
689 op->f_pmRA /= cos (op->f_dec);
690
691 nsf = get_fields(flds[4], SUBFLD, sflds);
692 if (nsf > 0)
693 set_fmag (op, atod(sflds[0]));
694 if (nsf > 1)
695 op->b_2mag = (short)floor((atod(sflds[1]))*MAGSCALE + 0.5);
696
697 if (flds[5][0]) {
698 tmp = op->f_epoch;
699 crack_year (flds[5], &tmp);
700 op->f_epoch = (float) tmp;
701 } else
702 op->f_epoch = J2000; /* default */
703
704 nsf = get_fields(flds[6], SUBFLD, sflds);
705 if (nsf == 7) {
706 int l;
707 char c;
708
709 op->b_bo.bo_a = atod(sflds[0]);
710 op->b_bo.bo_i = atod(sflds[1]);
711 op->b_bo.bo_O = atod(sflds[2]);
712 op->b_bo.bo_e = atod(sflds[3]);
713 op->b_bo.bo_T = atod(sflds[4]);
714 op->b_bo.bo_o = atod(sflds[5]);
715 op->b_bo.bo_P = atod(sflds[6]);
716
717 /* reject some weird entries actually seen in real lists */
718 if (op->b_bo.bo_a <= 0) {
719 if (whynot)
720 sprintf (whynot, "%s: Bogus B semi major axis: %g",
721 enm(flds), op->b_bo.bo_a);
722 return (-1);
723 }
724 if (op->b_bo.bo_P <= 0) {
725 if (whynot)
726 sprintf (whynot, "%s: Bogus B period: %g", enm(flds),
727 op->b_bo.bo_P);
728 return (-1);
729 }
730
731 /* scale period */
732 l = strlen (sflds[6]);
733 c = sflds[6][l-1];
734 switch (c) {
735 case 'y': case 'Y':
736 break;
737 case 'h': case 'H':
738 op->b_bo.bo_P /= (24.0*365.25);
739 break;
740 case 'd': case 'D':
741 op->b_bo.bo_P /= 365.25;
742 break;
743 default:
744 if (c != ' ' && !isdigit(c)) {
745 if (whynot)
746 sprintf (whynot,"%s: B period suffix not Y, D or H: %c",
747 enm(flds), c);
748 return (-1);
749 }
750 }
751
752 } else if (nsf==3 || nsf==6 || nsf==9) {
753 double yr;
754 int i;
755
756 op->b_nbp = nsf/3;
757 for (i = 0; i < nsf; i += 3) {
758 tmp = 0;
759 crack_year (sflds[i+0], &tmp);
760 mjd_year (tmp, &yr);
761 op->b_bp[i/3].bp_ep = (float)yr;
762 op->b_bp[i/3].bp_sep = atod(sflds[i+1]);
763 op->b_bp[i/3].bp_pa = degrad(atod(sflds[i+2]));
764 }
765 } else {
766 if (whynot)
767 sprintf (whynot,
768 "%s: type B needs 3,6 or 7 subfields in field 7, not %d",
769 enm(flds), nsf);
770 return (-1);
771 }
772
773 return (0);
774}
775
776/* put all names in nm but load only the first into o_name */
777static int
778crack_name (Obj *op, char *flds[MAXFLDS], int nf, char nm[][MAXNM], int nnm)
779{
780 char *sflds[MAXFLDS];
781 int nsf;
782 int i;
783
784 nsf = get_fields (flds[0], SUBFLD, sflds);
785 for (i = 0; nm && i < nsf && i < nnm; i++) {
786 strncpy (nm[i], sflds[i], MAXNM);
787 nm[i][MAXNM-1] = '\0';
788 }
789 strncpy (op->o_name, sflds[0], MAXNM-1);
790 return (nsf);
791}
792
793/* simple name cracker just for error messages */
794static char *
795enm (char *flds[MAXFLDS])
796{
797 char *sflds[MAXFLDS];
798 int nsf = get_fields (flds[0], SUBFLD, sflds);
799 return (nsf > 0 ? sflds[0] : "Unknown");
800}
801
802/* given either a decimal year (xxxx[.xxx]) or a calendar (x/x/x) date
803 * convert it to an mjd and store it at *p.
804 */
805static void
806crack_year (char *bp, double *p)
807{
808 int m, y;
809 double d;
810
811 mjd_cal (*p, &m, &d, &y); /* init with current */
812 f_sscandate (bp, PREF_MDY, &m, &d, &y);
813 cal_mjd (m, d, y, p);
814}
815
816/* crack the startok and endok date fields found in several Obj types.
817 * set to 0 if blank or any problems.
818 */
819static void
820crack_okdates (char *fld, float *startok, float *endok)
821{
822 char *sflds[MAXFLDS];
823 double tmp;
824 int m, y;
825 double d;
826 int nsf;
827
828 *startok = *endok = 0;
829 nsf = get_fields(fld, SUBFLD, sflds);
830 if (nsf > 1) {
831 d = m = y = 0;
832 f_sscandate (sflds[1], PREF_MDY, &m, &d, &y);
833 cal_mjd (m, d, y, &tmp);
834 *startok = (float)tmp;
835 if (nsf > 2) {
836 d = m = y = 0;
837 f_sscandate (sflds[2], PREF_MDY, &m, &d, &y);
838 cal_mjd (m, d, y, &tmp);
839 *endok = (float)tmp;
840 }
841 }
842}
843
844/* add startok and endok to string at lp if non-zero.
845 * return number of characters added.
846 */
847static int
848get_okdates (char *lp, float *sp, float *ep)
849{
850 char *lp0 = lp;
851
852 if (*sp || *ep) {
853 *lp++ = '|';
854 if (*sp)
855 lp += fs_date (lp, PREF_MDY, *sp);
856 if (*ep) {
857 *lp++ = '|';
858 lp += fs_date (lp, PREF_MDY, *ep);
859 }
860 }
861
862 return (lp - lp0);
863}
864
865static void
866write_f (Obj *op, char lp[])
867{
868 double tmp;
869
870 lp += sprintf (lp, "%s,f", op->o_name);
871 if (op->f_class)
872 lp += sprintf (lp, "|%c", op->f_class);
873 if (op->f_spect[0])
874 lp += sprintf (lp, "|%.*s", (int)sizeof(op->f_spect), op->f_spect);
875 *lp++ = ',';
876 lp += fs_sexa (lp, radhr(op->f_RA), 2, 36000);
877 if (op->f_pmRA)
878 lp += sprintf (lp, "|%.6g",cos(op->f_dec)*op->f_pmRA/1.327e-11);
879 *lp++ = ',';
880 lp += fs_sexa (lp, raddeg(op->f_dec), 3, 3600);
881 if (op->f_pmdec)
882 lp += sprintf (lp, "|%.6g", op->f_pmdec/1.327e-11);
883 lp += sprintf (lp, ",%.2f", get_mag(op));
884 mjd_year (op->f_epoch, &tmp);
885 lp += sprintf (lp, ",%.6g", tmp); /* %.7g gives 2000.001 */
886 lp += sprintf (lp, ",%.7g", op->f_size);
887 if (op->f_size && (op->f_ratio || op->f_pa))
888 lp += sprintf (lp,"|%g|%g", op->f_size*get_ratio(op),
889 raddeg(get_pa(op)));
890}
891
892static void
893write_e (Obj *op, char lp[])
894{
895 lp += sprintf (lp, "%s,e", op->o_name);
896 lp += sprintf (lp, ",%.7g", op->e_inc);
897 lp += sprintf (lp, ",%.7g", op->e_Om);
898 lp += sprintf (lp, ",%.7g", op->e_om);
899 lp += sprintf (lp, ",%.7g", op->e_a);
900 lp += sprintf (lp, ",%.7g", 0.0); /* retired op->e_n */
901 lp += sprintf (lp, ",%.7g", op->e_e);
902 lp += sprintf (lp, ",%.7g", op->e_M);
903 *lp++ = ',';
904 lp += fs_date (lp, PREF_MDY, op->e_cepoch);
905 lp += get_okdates (lp, &op->e_startok, &op->e_endok);
906 *lp++ = ',';
907 lp += fs_date (lp, PREF_MDY, op->e_epoch);
908 if (op->e_mag.whichm == MAG_gk)
909 lp += sprintf (lp, ",g%.7g", op->e_mag.m1);
910 else if (op->e_mag.whichm == MAG_HG)
911 lp += sprintf (lp, ",H%.7g", op->e_mag.m1);
912 else
913 lp += sprintf (lp, ",%.7g", op->e_mag.m1);
914 lp += sprintf (lp, ",%.7g", op->e_mag.m2);
915 lp += sprintf (lp, ",%.7g", op->e_size);
916}
917
918static void
919write_h (Obj *op, char lp[])
920{
921 lp += sprintf (lp, "%s,h", op->o_name);
922 *lp++ = ',';
923 lp += fs_date (lp, PREF_MDY, op->h_ep);
924 lp += get_okdates (lp, &op->h_startok, &op->h_endok);
925 lp += sprintf (lp, ",%.7g", op->h_inc);
926 lp += sprintf (lp, ",%.7g", op->h_Om);
927 lp += sprintf (lp, ",%.7g", op->h_om);
928 lp += sprintf (lp, ",%.7g", op->h_e);
929 lp += sprintf (lp, ",%.7g", op->h_qp);
930 *lp++ = ',';
931 lp += fs_date (lp, PREF_MDY, op->h_epoch);
932 lp += sprintf (lp, ",%.7g", op->h_g);
933 lp += sprintf (lp, ",%.7g", op->h_k);
934 lp += sprintf (lp, ",%.7g", op->h_size);
935}
936
937static void
938write_p (Obj *op, char lp[])
939{
940 lp += sprintf (lp, "%s,p", op->o_name);
941 *lp++ = ',';
942 lp += fs_date (lp, PREF_MDY, op->p_ep);
943 lp += get_okdates (lp, &op->p_startok, &op->p_endok);
944 lp += sprintf (lp, ",%.7g", op->p_inc);
945 lp += sprintf (lp, ",%.7g", op->p_om);
946 lp += sprintf (lp, ",%.7g", op->p_qp);
947 lp += sprintf (lp, ",%.7g", op->p_Om);
948 *lp++ = ',';
949 lp += fs_date (lp, PREF_MDY, op->p_epoch);
950 lp += sprintf (lp, ",%.7g", op->p_g);
951 lp += sprintf (lp, ",%.7g", op->p_k);
952 lp += sprintf (lp, ",%.7g", op->p_size);
953}
954
955static void
956write_E (Obj *op, char lp[])
957{
958 double d;
959 int m, y;
960
961 lp += sprintf (lp, "%s,E", op->o_name);
962 *lp++ = ',';
963 mjd_cal (op->es_epoch, &m, &d, &y); /* need more day prec than fs_date*/
964 lp += sprintf (lp, "%d/%.12g/%d", m, d, y);
965 lp += get_okdates (lp, &op->es_startok, &op->es_endok);
966 lp += sprintf (lp, ",%.8g", op->es_inc);
967 lp += sprintf (lp, ",%.8g", op->es_raan);
968 lp += sprintf (lp, ",%.8g", op->es_e);
969 lp += sprintf (lp, ",%.8g", op->es_ap);
970 lp += sprintf (lp, ",%.8g", op->es_M);
971 lp += sprintf (lp, ",%.12g", op->es_n); /* double */
972 lp += sprintf (lp, ",%.8g", op->es_decay);
973 lp += sprintf (lp, ",%d", op->es_orbit);
974 lp += sprintf (lp, ",%.8g", op->es_drag);
975}
976
977static void
978write_B (Obj *op, char lp[])
979{
980 double tmp;
981
982 lp += sprintf (lp, "%s,B", op->o_name);
983 if (op->f_class)
984 lp += sprintf (lp, "|%c", op->f_class);
985 if (op->f_spect[0])
986 lp += sprintf (lp, "|%.*s", (int)sizeof(op->f_spect), op->f_spect);
987 if (op->b_2spect[0])
988 lp += sprintf (lp, "|%.*s", (int)sizeof(op->b_2spect),op->b_2spect);
989 *lp++ = ',';
990 lp += fs_sexa (lp, radhr(op->f_RA), 2, 36000);
991 if (op->f_pmRA)
992 lp += sprintf (lp, "|%.6g",cos(op->f_dec)*op->f_pmRA/1.327e-11);
993 *lp++ = ',';
994 lp += fs_sexa (lp, raddeg(op->f_dec), 3, 3600);
995 if (op->f_pmdec)
996 lp += sprintf (lp, "|%.6g", op->f_pmdec/1.327e-11);
997 lp += sprintf (lp, ",%.2f", get_mag(op));
998 lp += sprintf (lp, "|%.2f", op->b_2mag/MAGSCALE);
999 mjd_year (op->f_epoch, &tmp);
1000 lp += sprintf (lp, ",%.6g", tmp); /* %.7g gives 2000.001 */
1001 if (op->b_nbp == 0) {
1002 lp += sprintf (lp, ",%.6g", op->b_bo.bo_a);
1003 lp += sprintf (lp, "|%.6g", op->b_bo.bo_i);
1004 lp += sprintf (lp, "|%.6g", op->b_bo.bo_O);
1005 lp += sprintf (lp, "|%.6g", op->b_bo.bo_e);
1006 lp += sprintf (lp, "|%.6g", op->b_bo.bo_T);
1007 lp += sprintf (lp, "|%.6g", op->b_bo.bo_o);
1008 lp += sprintf (lp, "|%.6gy", op->b_bo.bo_P);
1009 } else {
1010 int i;
1011
1012 for (i = 0; i < op->b_nbp; i++) {
1013 BinPos *bp = &op->b_bp[i];
1014 lp += sprintf (lp, "%c%.6g", i==0?',':'|', bp->bp_ep);
1015 lp += sprintf (lp, "|%.6g", bp->bp_sep);
1016 lp += sprintf (lp, "|%.6g", raddeg(bp->bp_pa));
1017 }
1018 }
1019}
1020
1021static void
1022write_P (Obj *op, char lp[])
1023{
1024
1025 lp += sprintf (lp, "%s,P", op->o_name);
1026}
1027
1028/* For RCS Only -- Do Not Edit */
1029static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: dbfmt.c,v $ $Date: 2011-09-21 16:17:48 $ $Revision: 1.10 $ $Name: not supported by cvs2svn $"};
Note: See TracBrowser for help on using the repository browser.