1 /* zzgetelm.f -- translated by f2c (version 19980913).
2 You must link the resulting object file with the libraries:
3 -lf2c -lm (in that order)
4 */
5
6 #include "f2c.h"
7
8 /* Table of constant values */
9
10 static integer c__3 = 3;
11 static integer c__2 = 2;
12 static integer c__4 = 4;
13
14 /* $Procedure ZZGETELM ( Get the components from two-line elements) */
zzgetelm_(integer * frstyr,char * lines,doublereal * epoch,doublereal * elems,logical * ok,char * error,ftnlen lines_len,ftnlen error_len)15 /* Subroutine */ int zzgetelm_(integer *frstyr, char *lines, doublereal *
16 epoch, doublereal *elems, logical *ok, char *error, ftnlen lines_len,
17 ftnlen error_len)
18 {
19 /* Initialized data */
20
21 static logical first = TRUE_;
22
23 /* System generated locals */
24 address a__1[3], a__2[2];
25 integer i__1, i__2, i__3[3], i__4[2];
26
27 /* Builtin functions */
28 /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen);
29 integer s_rnge(char *, integer, char *, integer), s_cmp(char *, char *,
30 ftnlen, ftnlen);
31 /* Subroutine */ int s_cat(char *, char **, integer *, integer *, ftnlen);
32
33 /* Local variables */
34 static doublereal ndd60;
35 static char cday[32];
36 static doublereal incl, ndt20;
37 static integer bexp, year;
38 static doublereal tvec[8];
39 static char term[160*13];
40 static integer nexp;
41 static doublereal node0;
42 static integer i__, k;
43 static char cndd60[32], cincl[32];
44 static doublereal omega;
45 static char cndt20[32];
46 extern /* Subroutine */ int chkin_(char *, ftnlen);
47 static char cyear[32];
48 extern /* Subroutine */ int repmc_(char *, char *, char *, char *, ftnlen,
49 ftnlen, ftnlen, ftnlen), repmd_(char *, char *, doublereal *,
50 integer *, char *, ftnlen, ftnlen, ftnlen);
51 static char ciexp[32];
52 static integer begyr;
53 static doublereal bstar;
54 extern /* Subroutine */ int repmi_(char *, char *, integer *, char *,
55 ftnlen, ftnlen, ftnlen);
56 static doublereal power[75];
57 extern doublereal twopi_(void);
58 static char cnode0[32], comega[32];
59 static doublereal mo, no;
60 static char cibexp[32];
61 static integer yr;
62 static char cbstar[32];
63 extern integer lastnb_(char *, ftnlen);
64 extern /* Subroutine */ int nparsd_(char *, doublereal *, char *, integer
65 *, ftnlen, ftnlen), nparsi_(char *, integer *, char *, integer *,
66 ftnlen, ftnlen), chkout_(char *, ftnlen);
67 static doublereal d2r, pi2;
68 extern /* Subroutine */ int ttrans_(char *, char *, doublereal *, ftnlen,
69 ftnlen);
70 static char errprs[160*13];
71 extern logical return_(void);
72 static doublereal ecc, day;
73 static char cmo[32], cno[32];
74 extern doublereal rpd_(void);
75 static integer ptr;
76 static char cecc[32];
77
78 /* $ Abstract */
79
80 /* Given a the "lines" of a two-line element set, parse the */
81 /* lines and return the elements in units suitable for use */
82 /* in SPICE software. */
83
84 /* $ Disclaimer */
85
86 /* THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
87 /* CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
88 /* GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
89 /* ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
90 /* PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
91 /* TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
92 /* WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
93 /* PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
94 /* SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
95 /* SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */
96
97 /* IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
98 /* BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
99 /* LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
100 /* INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
101 /* REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
102 /* REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */
103
104 /* RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
105 /* THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
106 /* CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
107 /* ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */
108
109 /* $ Required_Reading */
110
111 /* None. */
112
113 /* $ Keywords */
114
115 /* PARSING */
116
117 /* $ Declarations */
118 /* $ Brief_I/O */
119
120 /* VARIABLE I/O DESCRIPTION */
121 /* -------- --- -------------------------------------------------- */
122 /* FRSTYR I year of earliest representable two-line elements */
123 /* LINES I a pair of "lines" containing two-line elements */
124 /* EPOCH O The epoch of the elements in seconds past J2000 */
125 /* ELEMS O The elements converted to SPICE units. */
126 /* OK O Boolean indicating error state. */
127 /* ERROR O String describing error. */
128
129 /* $ Detailed_Input */
130
131 /* FRSTYR is the first year possible for two line elements. */
132 /* Since two line elements allow only two digits for */
133 /* the year, some conventions must be followed concerning */
134 /* which century the two digits refer to . FRSTYR */
135 /* is the year of the earliest representable elements. */
136 /* The two-digit year is mapped to the year in */
137 /* the interval from FRSTYR to FRSTYR + 99 that */
138 /* has the same last two digits as the two digit */
139 /* year in the element set. For example if FRSTYR */
140 /* is set to 1960 then the two digit years are mapped */
141 /* as shown in the table below: */
142
143 /* Two-line Maps to */
144 /* element year */
145 /* 00 2000 */
146 /* 01 2001 */
147 /* 02 2002 */
148 /* . . */
149 /* . . */
150 /* . . */
151 /* 58 2058 */
152 /* 59 2059 */
153 /* -------------------- */
154 /* 60 1960 */
155 /* 61 1961 */
156 /* 62 1962 */
157 /* . . */
158 /* . . */
159 /* . . */
160 /* 99 1999 */
161
162 /* Note that if Space Command should decide to represent */
163 /* years in 21st century as 100 + the last two digits */
164 /* of the year (for example: 2015 is represented as 115) */
165 /* instead of simply dropping the first two digits of */
166 /* the year, this routine will correctly map the year */
167 /* as long as you set FRSTYR to some value between 1900 */
168 /* and 1999. */
169
170 /* LINES is a pair of lines of text that comprise a Space */
171 /* command ``two-line element'' set. These text lines */
172 /* should be the same as they are presented in the */
173 /* two-line element files available from Space Command */
174 /* (formerly NORAD). Below is an example of a two-line */
175 /* set for TOPEX. */
176
177 /* TOPEX */
178 /* 1 22076U 92052A 97173.53461370 -.00000038 00000-0 10000-3 0 594 */
179 /* 2 22076 66.0378 163.4372 0008359 278.7732 81.2337 12.80930736227550 */
180
181
182 /* $ Detailed_Output */
183
184 /* EPOCH is the epoch of the two line elements supplied via */
185 /* the input array LINES. Epoch is returned in TDB */
186 /* seconds past J2000. */
187
188 /* ELEMS is an array containing the elements from the two line */
189 /* set supplied via the array LINES. The elements are */
190 /* in units suitable for use by the SPICE routine */
191 /* EV2LIN. */
192
193 /* Also note that the elements XNDD6O and BSTAR */
194 /* incorporate the exponential factor present in the */
195 /* input two line elements in LINES. (See particulars */
196 /* below. */
197
198 /* ELEMS ( 1 ) = XNDT2O in radians/minute**2 */
199 /* ELEMS ( 2 ) = XNDD6O in radians/minute**3 */
200 /* ELEMS ( 3 ) = BSTAR */
201 /* ELEMS ( 4 ) = XINCL in radians */
202 /* ELEMS ( 5 ) = XNODEO in radians */
203 /* ELEMS ( 6 ) = EO */
204 /* ELEMS ( 7 ) = OMEGAO in radians */
205 /* ELEMS ( 8 ) = XMO in radians */
206 /* ELEMS ( 9 ) = XNO in radians/minute */
207 /* ELEMS ( 10 ) = EPOCH of the elements in seconds */
208 /* past ephemeris epoch J2000. */
209
210 /* OK a boolean flag indicating whether an error occured */
211 /* while processing the TLE. Processing errors include */
212 /* incorrect format for TLEs, angular values beyond */
213 /* allowed range. */
214
215 /* ERROR a string containing a description of any TLE */
216 /* processing error. */
217
218 /* $ Parameters */
219
220 /* None. */
221
222 /* $ Files */
223
224 /* You must have loaded a SPICE leapseconds kernel into the */
225 /* kernel pool prior to caling this routine. */
226
227 /* $ Exceptions */
228
229 /* This routine does not signal errors, rather it returns an */
230 /* error flag and description to the calling program. Errors */
231 /* reported: */
232
233 /* 1) TLE line has incorrect format. */
234
235 /* 2) A TLE '2' line has a different vehicle tag than the */
236 /* corresponding '1' line. */
237
238 /* 3) TLE data length more than 69 characters, or less than 68 */
239 /* characters. */
240
241 /* 4) An NPARS* routine cannot parse a string to a numeric value. */
242
243 /* 5) The value of an angular measure, NODE0, OMEGA, MO, or INCL */
244 /* fails to lie within the expected numerical bounds. */
245
246 /* $ Particulars */
247
248 /* This routine parses a Space Command Two-line element set and */
249 /* returns the orbital elements properly scaled and in units */
250 /* suitable for use by other SPICE software. Input elements */
251 /* have the form: */
252
253 /* 1 22076U 92052A 97173.53461370 -.00000038 00000-0 10000-3 0 594 */
254 /* 2 22076 66.0378 163.4372 0008359 278.7732 81.2337 12.80930736227550 */
255 /* ^ */
256 /* 123456789012345678901234567890123456789012345678901234567890123456789 */
257 /* 1 2 3 4 5 6 */
258
259 /* The ``raw'' elements in the first and second lines are marked */
260 /* below. Note that in several instances exponents and decimal */
261 /* points are implied. Also note that */
262 /* input units are degrees, degrees/day**n and revolutions/day. */
263
264
265 /* DAY OF YEAR NDD60 BSTAR */
266 /* vvvvvvvvvvvv vvvvvv vvvvvv */
267 /* --------------------------------------------------------------------- */
268 /* 1 22076U 92052A 97173.53461370 -.00000038 00000-0 10000-3 0 594 */
269 /* --------------------------------------------------------------------- */
270 /* ^^ ^^^^^^^^^^ ^^ ^^ */
271 /* YEAR NDT20 IEXP IBEXP */
272
273
274
275 /* The ``raw'' elements in the second line are marked below */
276 /* NODE0 OMEGA N0 */
277 /* vvvvvvvv vvvvvvvv vvvvvvvvvvv */
278 /* --------------------------------------------------------------------- */
279 /* 2 22076 66.0378 163.4372 0008359 278.7732 81.2337 12.80930736227550 */
280 /* --------------------------------------------------------------------- */
281 /* ^^^^^^^^ ^^^^^^^ ^^^^^^^^ */
282 /* Inclination Eccentricity M0 */
283
284 /* This routine extracts these values ``inserts'' the implied */
285 /* decimal points and exponents and then converts the inputs */
286 /* to units of radians, radians/minute, radians/minute**2, and */
287 /* radians/minute**3 */
288
289 /* $ Examples */
290
291 /* Suppose you have a set of two-line elements and an array */
292 /* containing the related geophysical constants necessary */
293 /* to evaluate a state. The example below shows how you */
294 /* can use this routine together with the routine EV2LIN to */
295 /* propagate a state to an epoch of interest. */
296
297
298 /* The parameters below will make it easier to make assignments */
299 /* to the array GEOPHS required by EV2LIN. */
300
301 /* J2 --- location of J2 */
302 /* J3 --- location of J3 */
303 /* J4 --- location if J4 */
304 /* KE --- location of KE = sqrt(GM) in eart-radii**1.5/MIN */
305 /* QO --- location of upper bound of atmospheric model in KM */
306 /* SO --- location of lower bound of atmospheric model in KM */
307 /* ER --- location of earth equatorial radius in KM. */
308 /* AE --- location of distance units/earth radius */
309
310 /* PARAMETER ( J2 = 1 ) */
311 /* PARAMETER ( J3 = 2 ) */
312 /* PARAMETER ( J4 = 3 ) */
313 /* PARAMETER ( KE = 4 ) */
314 /* PARAMETER ( QO = 5 ) */
315 /* PARAMETER ( SO = 6 ) */
316 /* PARAMETER ( ER = 7 ) */
317 /* PARAMETER ( AE = 8 ) */
318
319
320 /* We set the lower bound for the years to be the beginning */
321 /* of the space age. */
322
323 /* FRSTYR = 1957 */
324
325 /* Read in the next two lines from the text file that contains */
326 /* the two-line elements. We assume that file has been opened */
327 /* properly and that we have set the ``file pointer'' to the */
328 /* correct location for reading the next set of elements. */
329
330 /* READ (UNIT,FMT='(A)' ) LINE(1) */
331 /* READ (UNIT,FMT='(A)' ) LINE(2) */
332
333 /* CALL ZZGETELM ( FRSTYR, LINE, EPOCH, ELEMS, OK, ERROR ) */
334
335 /* Set up the geophysical quantities. At last check these */
336 /* were the values used by Space Command. */
337
338 /* GEOPHS( J2 ) = 1.082616D-3 */
339 /* GEOPHS( J3 ) = -2.53881D-6 */
340 /* GEOPHS( J4 ) = -1.65597D-6 */
341 /* GEOPHS( KE ) = 7.43669161D-2 */
342 /* GEOPHS( QO ) = 120.0D0 */
343 /* GEOPHS( SO ) = 78.0D0 */
344 /* GEOPHS( ER ) = 6378.135D0 */
345 /* GEOPHS( AE ) = 1.0D0 */
346
347 /* Now propagate the state using EV2LIN to the epoch of */
348 /* interest. */
349
350 /* CALL EV2LIN ( ET, GEOPHS, ELEMS, STATE ) */
351
352
353 /* $ Restrictions */
354
355 /* The format of the two-line elements suffer from a "millenium" */
356 /* problem---only two digits are used for the year of the elements. */
357 /* It is not clear how Space Command will deal with this problem */
358 /* as the year 2000 comes and goes. We hope that by adjusting */
359 /* the input FRSTYR you should be able to use this */
360 /* routine well into the 21st century. However, since we can't */
361 /* predict how others will resolve the millenium problem we */
362 /* can't be sure that our approach will be addequate to deal with */
363 /* the problem. */
364
365 /* The approach taken to mapping the two-digit year to the */
366 /* full year is given by the code below. Here, YR is the */
367 /* integer obtained by parsing the two-digit year from the first */
368 /* line of the elements. */
369
370 /* BEGYR = (FRSTYR/100)*100 */
371 /* YEAR = BEGYR + YR */
372
373 /* IF ( YEAR .LT. FRSTYR ) THEN */
374 /* YEAR = YEAR + 100 */
375 /* END IF */
376
377 /* This mapping will be changed if future two-line element */
378 /* representations make this method of computing the full year */
379 /* inaccurate. */
380
381 /* $ Author_and_Institution */
382
383 /* W.L. Taber (JPL) */
384 /* E.D. Wright (JPL) */
385
386 /* $ Literature_References */
387
388 /* None. */
389
390 /* $ Version */
391
392
393 /* - SPICELIB Version 1.0.0, 26-APR-2004 (EDW) */
394
395 /* Modified routine GETELM to confirm */
396 /* acceptable range for angular measures and exponents. */
397 /* The routine does not signal errors,it returns an error */
398 /* flag and error string to the calling program. */
399
400 /* Routine named ZZGETELM from GETELM. */
401
402 /* -& */
403 /* $ Index_Entries */
404
405 /* Parse two-line elements */
406
407 /* -& */
408
409 /* Spicelib functions */
410
411
412 /* An enumeration of the various components of the */
413 /* elements array---ELEMS */
414
415 /* KNDT20 */
416 /* KNDD60 */
417 /* KBSTAR */
418 /* KINCL */
419 /* KNODE0 */
420 /* KECC */
421 /* KOMEGA */
422 /* KMO */
423 /* KNO */
424
425
426 /* Character string lengths */
427
428
429 /* Maximum exponent (base 10) */
430
431
432 /* Double precision constants. */
433
434
435 /* Minutes/day */
436
437
438 /* Local variables */
439
440
441 /* Standard SPICE error handling. */
442
443 if (return_()) {
444 return 0;
445 }
446 chkin_("ZZGETELM", (ftnlen)8);
447
448 /* Initialize the error indicators and the elements to zero. */
449
450 *ok = TRUE_;
451 s_copy(error, " ", error_len, (ftnlen)1);
452 elems[0] = 0.;
453 elems[1] = 0.;
454 elems[2] = 0.;
455 elems[3] = 0.;
456 elems[4] = 0.;
457 elems[5] = 0.;
458 elems[6] = 0.;
459 elems[7] = 0.;
460 elems[8] = 0.;
461 elems[9] = 0.;
462 *epoch = 0.;
463
464 /* First entry initialization. */
465
466 if (first) {
467
468 /* Define two constants. This initialization proves the most */
469 /* useful when processing thousands of TLE sets. */
470
471 d2r = rpd_();
472 pi2 = twopi_();
473 first = FALSE_;
474 power[37] = 1.;
475 for (i__ = 1; i__ <= 37; ++i__) {
476 power[(i__1 = i__ + 37) < 75 && 0 <= i__1 ? i__1 : s_rnge("power",
477 i__1, "zzgetelm_", (ftnlen)535)] = power[(i__2 = i__ +
478 36) < 75 && 0 <= i__2 ? i__2 : s_rnge("power", i__2,
479 "zzgetelm_", (ftnlen)535)] * 10.;
480 power[(i__1 = -i__ + 37) < 75 && 0 <= i__1 ? i__1 : s_rnge("power"
481 , i__1, "zzgetelm_", (ftnlen)536)] = 1. / power[(i__2 =
482 i__ + 37) < 75 && 0 <= i__2 ? i__2 : s_rnge("power", i__2,
483 "zzgetelm_", (ftnlen)536)];
484 }
485 s_copy(term, "\"YEAR\" (characters 19 to 20 of the first line of a t"
486 "wo-line element set)", (ftnlen)160, (ftnlen)72);
487 s_copy(term + 160, "\"DAY\" (characters 21 to 32 of the first line o"
488 "f a two-line element set)", (ftnlen)160, (ftnlen)71);
489 s_copy(term + 320, "\"NDT20\" (characters 34 to 43 of the first line"
490 " of a two-line element set)", (ftnlen)160, (ftnlen)73);
491 s_copy(term + 480, "\"NDD60\" (characters 45 to 45 of the first line"
492 " of a two-line element set)", (ftnlen)160, (ftnlen)73);
493 s_copy(term + 640, "\"IEXP\" (characters 51 to 52 of the first line "
494 "of a two-line element set)", (ftnlen)160, (ftnlen)72);
495 s_copy(term + 800, "\"BSTAR\" (characters 54 to 54 of the first line"
496 " of a two-line element set)", (ftnlen)160, (ftnlen)73);
497 s_copy(term + 960, "\"IBEXP\" (characters 60 to 61 of the first line"
498 " of a two-line element set)", (ftnlen)160, (ftnlen)73);
499 s_copy(term + 1120, "\"INCL\" (characters 9 to 16 of the second line"
500 " of a two-line element set)", (ftnlen)160, (ftnlen)72);
501 s_copy(term + 1280, "\"NODE0\" (characters 18 to 25 of the second li"
502 "ne of a two-line element set)", (ftnlen)160, (ftnlen)74);
503 s_copy(term + 1440, "\"ECC\" (characters 27 to 33 of the second line"
504 " of a two-line element set)", (ftnlen)160, (ftnlen)72);
505 s_copy(term + 1600, "\"OMEGA\" (characters 35 to 42 of the second li"
506 "ne of a two-line element set)", (ftnlen)160, (ftnlen)74);
507 s_copy(term + 1760, "\"MO\" (characters 44 to 51 of the second line "
508 "of a two-line element set)", (ftnlen)160, (ftnlen)71);
509 s_copy(term + 1920, "\"NO\" (characters 53 to 63 of the second line "
510 "of a two-line element set)", (ftnlen)160, (ftnlen)71);
511 }
512
513 /* Ensure the vehicle IDs match in each line. */
514
515 if (s_cmp(lines + 1, lines + (lines_len + 1), (ftnlen)6, (ftnlen)6) != 0)
516 {
517
518 /* Vehicle IDs do not match. Flag an error. */
519
520 s_copy(error, "Line 1 of the TLE pair tagged with vehicle ID #1, li"
521 "ne 2 of TLE pair tagged with vehicle ID #2", error_len, (
522 ftnlen)95);
523 repmc_(error, "#1", lines + 1, error, error_len, (ftnlen)2, (ftnlen)6,
524 error_len);
525 repmc_(error, "#2", lines + (lines_len + 1), error, error_len, (
526 ftnlen)2, (ftnlen)6, error_len);
527 *ok = FALSE_;
528 chkout_("ZZGETELM", (ftnlen)8);
529 return 0;
530 }
531
532 /* Check line format and length. */
533
534 for (k = 1; k <= 2; ++k) {
535 if (lastnb_(lines + ((i__1 = k - 1) < 2 && 0 <= i__1 ? i__1 : s_rnge(
536 "lines", i__1, "zzgetelm_", (ftnlen)604)) * lines_len,
537 lines_len) != 68 && lastnb_(lines + ((i__2 = k - 1) < 2 && 0
538 <= i__2 ? i__2 : s_rnge("lines", i__2, "zzgetelm_", (ftnlen)
539 604)) * lines_len, lines_len) != 69) {
540
541 /* The TLE data line was not 68 or 69 characters long (ignoring */
542 /* trailing whitespace). Flag an error. */
543
544 s_copy(error, "Line #1 of the TLE has incorrect data length. Exp"
545 "ected length 68 or 69 elements, actual length: #2. TLE l"
546 "ine value: #3", error_len, (ftnlen)118);
547 repmi_(error, "#1", &k, error, error_len, (ftnlen)2, error_len);
548 i__2 = lastnb_(lines + ((i__1 = k - 1) < 2 && 0 <= i__1 ? i__1 :
549 s_rnge("lines", i__1, "zzgetelm_", (ftnlen)615)) *
550 lines_len, lines_len);
551 repmi_(error, "#2", &i__2, error, error_len, (ftnlen)2, error_len)
552 ;
553 repmc_(error, "#3", lines + ((i__1 = k - 1) < 2 && 0 <= i__1 ?
554 i__1 : s_rnge("lines", i__1, "zzgetelm_", (ftnlen)616)) *
555 lines_len, error, error_len, (ftnlen)2, lines_len,
556 error_len);
557 *ok = FALSE_;
558 chkout_("ZZGETELM", (ftnlen)8);
559 return 0;
560 }
561 }
562
563 /* This isn't particularly pretty, but it is straight */
564 /* forward. According to the documentation on the two line */
565 /* element sets, (as well as what's indicated by the program */
566 /* driver that is documented in SPACETRACK REPORT NO.3 */
567 /* we can simply pick out the various components of the */
568 /* elements from the input lines 1 and 2. */
569
570 /* For the record we include the DECODE statement in DRIVER */
571 /* for fetching the data out of lines one and two (after a bit */
572 /* of pretty printing). Note that some of these formats have */
573 /* and implied decimal point. In particular f6.5 and f7.7 in */
574 /* all other cases the decimal points seem to be given explicitely. */
575
576 /* decode (abuf,702) epoch, xndt20, ... */
577 /* xndd60, iexp, bstar, ibexp, ... */
578 /* xincl, xnodeo, ... */
579 /* eo, omegao, xmo, xno */
580 /* format( 18x, d14.8, 1x, f10.8, */
581 /* 1x, f6.5, i2, 1x, f6.5, i2, /, */
582 /* 8x, f8.4, 1x, f8.4, */
583 /* 1x, f7.7, 1x, f8.4, 1x, f8.4 1x, f11.8 ) */
584
585 /* Note that in the two-line element sets, the epoch is read */
586 /* as a single number. However the documentation that describes */
587 /* this data (as well as the code in THETAG) show that it's a lot */
588 /* easier to capture the year and day of year separately. */
589
590 s_copy(cyear, lines + 18, (ftnlen)32, (ftnlen)2);
591 s_copy(cday, lines + 20, (ftnlen)32, (ftnlen)12);
592 s_copy(cndt20, lines + 33, (ftnlen)32, (ftnlen)10);
593 /* Writing concatenation */
594 i__3[0] = 1, a__1[0] = lines + 44;
595 i__3[1] = 1, a__1[1] = ".";
596 i__3[2] = 5, a__1[2] = lines + 45;
597 s_cat(cndd60, a__1, i__3, &c__3, (ftnlen)32);
598 s_copy(ciexp, lines + 50, (ftnlen)32, (ftnlen)2);
599 /* Writing concatenation */
600 i__3[0] = 1, a__1[0] = lines + 53;
601 i__3[1] = 1, a__1[1] = ".";
602 i__3[2] = 5, a__1[2] = lines + 54;
603 s_cat(cbstar, a__1, i__3, &c__3, (ftnlen)32);
604 s_copy(cibexp, lines + 59, (ftnlen)32, (ftnlen)2);
605 s_copy(cincl, lines + (lines_len + 8), (ftnlen)32, (ftnlen)8);
606 s_copy(cnode0, lines + (lines_len + 17), (ftnlen)32, (ftnlen)8);
607 /* Writing concatenation */
608 i__4[0] = 2, a__2[0] = "0.";
609 i__4[1] = 7, a__2[1] = lines + (lines_len + 26);
610 s_cat(cecc, a__2, i__4, &c__2, (ftnlen)32);
611 s_copy(comega, lines + (lines_len + 34), (ftnlen)32, (ftnlen)8);
612 s_copy(cmo, lines + (lines_len + 43), (ftnlen)32, (ftnlen)8);
613 s_copy(cno, lines + (lines_len + 52), (ftnlen)32, (ftnlen)11);
614
615 /* Parse the numerical values from the data string. */
616
617 nparsi_(cyear, &yr, errprs, &ptr, (ftnlen)32, (ftnlen)160);
618 nparsd_(cday, &day, errprs + 160, &ptr, (ftnlen)32, (ftnlen)160);
619 nparsd_(cndt20, &ndt20, errprs + 320, &ptr, (ftnlen)32, (ftnlen)160);
620 nparsd_(cndd60, &ndd60, errprs + 480, &ptr, (ftnlen)32, (ftnlen)160);
621 nparsi_(ciexp, &nexp, errprs + 640, &ptr, (ftnlen)32, (ftnlen)160);
622 nparsd_(cbstar, &bstar, errprs + 800, &ptr, (ftnlen)32, (ftnlen)160);
623 nparsi_(cibexp, &bexp, errprs + 960, &ptr, (ftnlen)32, (ftnlen)160);
624 nparsd_(cincl, &incl, errprs + 1120, &ptr, (ftnlen)32, (ftnlen)160);
625 nparsd_(cnode0, &node0, errprs + 1280, &ptr, (ftnlen)32, (ftnlen)160);
626 nparsd_(cecc, &ecc, errprs + 1440, &ptr, (ftnlen)32, (ftnlen)160);
627 nparsd_(comega, &omega, errprs + 1600, &ptr, (ftnlen)32, (ftnlen)160);
628 nparsd_(cmo, &mo, errprs + 1760, &ptr, (ftnlen)32, (ftnlen)160);
629 nparsd_(cno, &no, errprs + 1920, &ptr, (ftnlen)32, (ftnlen)160);
630
631 /* Check for parse errors. */
632
633 for (i__ = 1; i__ <= 13; ++i__) {
634 if (s_cmp(errprs + ((i__1 = i__ - 1) < 13 && 0 <= i__1 ? i__1 :
635 s_rnge("errprs", i__1, "zzgetelm_", (ftnlen)692)) * 160,
636 " ", (ftnlen)160, (ftnlen)1) != 0) {
637
638 /* Something could not parse. Set the error message then */
639 /* return. */
640
641 s_copy(error, "An error occurred while trying to parse the term "
642 "#. The diagnostic was: # ", error_len, (ftnlen)75);
643 repmc_(error, "#", term + ((i__1 = i__ - 1) < 13 && 0 <= i__1 ?
644 i__1 : s_rnge("term", i__1, "zzgetelm_", (ftnlen)700)) *
645 160, error, error_len, (ftnlen)1, (ftnlen)160, error_len);
646 repmc_(error, "#", errprs + ((i__1 = i__ - 1) < 13 && 0 <= i__1 ?
647 i__1 : s_rnge("errprs", i__1, "zzgetelm_", (ftnlen)701)) *
648 160, error, error_len, (ftnlen)1, (ftnlen)160, error_len)
649 ;
650 *ok = FALSE_;
651 chkout_("ZZGETELM", (ftnlen)8);
652 return 0;
653 }
654 }
655
656 /* Check for reasonable exponets; a single digit. These should */
657 /* probably be LE 0. */
658
659 if (abs(nexp) > 9) {
660 s_copy(error, "NEXP (exponent) not a single digit. Actual value #1",
661 error_len, (ftnlen)51);
662 repmi_(error, "#1", &nexp, error, error_len, (ftnlen)2, error_len);
663 *ok = FALSE_;
664 chkout_("ZZGETELM", (ftnlen)8);
665 return 0;
666 }
667 if (abs(bexp) > 9) {
668 s_copy(error, "BEXP (exponent) not a single digit. Actual value #1",
669 error_len, (ftnlen)51);
670 repmi_(error, "#1", &bexp, error, error_len, (ftnlen)2, error_len);
671 *ok = FALSE_;
672 chkout_("ZZGETELM", (ftnlen)8);
673 return 0;
674 }
675
676 /* Confirm correct bounds on angular values. */
677
678 /* NODE0 - right ascension of the ascending node, [0,360) */
679
680 if (node0 < 0. || node0 >= 360.) {
681 s_copy(error, "NODE0 (RA acend node) expected bounds [0,360). Actual"
682 " value #1", error_len, (ftnlen)62);
683 repmd_(error, "#1", &node0, &c__4, error, error_len, (ftnlen)2,
684 error_len);
685 *ok = FALSE_;
686 chkout_("ZZGETELM", (ftnlen)8);
687 return 0;
688 }
689
690 /* OMEAGA - argument of the periapsis, [0,360) */
691
692 if (omega < 0. || omega >= 360.) {
693 s_copy(error, "OMEGA (arg periap) expected bounds [0,360). Actual va"
694 "lue #1", error_len, (ftnlen)59);
695 repmd_(error, "#1", &omega, &c__4, error, error_len, (ftnlen)2,
696 error_len);
697 *ok = FALSE_;
698 chkout_("ZZGETELM", (ftnlen)8);
699 return 0;
700 }
701
702 /* MO - mean anomoly, [0,360) */
703
704 if (mo < 0. || mo >= 360.) {
705 s_copy(error, "MO (mean anomoly) expected bounds [0,360). Actual val"
706 "ue #1", error_len, (ftnlen)58);
707 repmd_(error, "#1", &mo, &c__4, error, error_len, (ftnlen)2,
708 error_len);
709 *ok = FALSE_;
710 chkout_("ZZGETELM", (ftnlen)8);
711 return 0;
712 }
713
714 /* INCL - inclination, [0,180] */
715
716 if (incl < 0. || incl > 180.) {
717 s_copy(error, "INCL (inclination) expected bounds [0,180). Actual va"
718 "lue #1", error_len, (ftnlen)59);
719 repmd_(error, "#1", &incl, &c__4, error, error_len, (ftnlen)2,
720 error_len);
721 *ok = FALSE_;
722 chkout_("ZZGETELM", (ftnlen)8);
723 return 0;
724 }
725
726 /* NO - mean motion (0,20) (Earth orbiter). */
727
728 if (no > 20. || no < 0.) {
729 s_copy(error, "NO (mean motion) expected bounds (0,20). Actual value"
730 " #1", error_len, (ftnlen)56);
731 repmd_(error, "#1", &no, &c__4, error, error_len, (ftnlen)2,
732 error_len);
733 *ok = FALSE_;
734 chkout_("ZZGETELM", (ftnlen)8);
735 return 0;
736 }
737
738 /* Finish up the computation of NDD60 and BSTAR */
739
740 ndd60 *= power[(i__1 = nexp + 37) < 75 && 0 <= i__1 ? i__1 : s_rnge("pow"
741 "er", i__1, "zzgetelm_", (ftnlen)827)];
742 bstar *= power[(i__1 = bexp + 37) < 75 && 0 <= i__1 ? i__1 : s_rnge("pow"
743 "er", i__1, "zzgetelm_", (ftnlen)828)];
744
745 /* Convert everything from degrees to radians ... */
746
747 node0 *= d2r;
748 omega *= d2r;
749 mo *= d2r;
750 incl *= d2r;
751
752 /* ... and from revolutions/day**n to radians/minutes**n */
753
754 no = no * pi2 / 1440.;
755 ndt20 = ndt20 * pi2 / 1440. / 1440.;
756 ndd60 = ndd60 * pi2 / 1440. / 1440. / 1440.;
757
758 /* Finally, we need to convert the input epoch to */
759 /* seconds past 2000. First let's adjust the year. */
760 /* Add to YR the largest multiple of 100 that is */
761 /* less than or equal to FRSTYR */
762
763 begyr = *frstyr / 100 * 100;
764 year = begyr + yr;
765 if (year < *frstyr) {
766 year += 100;
767 }
768
769 /* Compute the epoch of the year and date. */
770
771 tvec[0] = (doublereal) year;
772 tvec[1] = day;
773 ttrans_("YD.D", "TDB", tvec, (ftnlen)4, (ftnlen)3);
774 *epoch = tvec[0];
775
776 /* That's it. Load ELEMS with the elements and ship them */
777 /* back to the calling routine. */
778
779 elems[0] = ndt20;
780 elems[1] = ndd60;
781 elems[2] = bstar;
782 elems[3] = incl;
783 elems[4] = node0;
784 elems[5] = ecc;
785 elems[6] = omega;
786 elems[7] = mo;
787 elems[8] = no;
788 elems[9] = *epoch;
789 chkout_("ZZGETELM", (ftnlen)8);
790 return 0;
791 } /* zzgetelm_ */
792
793