Пример #1
0
/* $Procedure PCKW02 ( Write PCK segment, type 2 ) */
/* Subroutine */ int pckw02_(integer *handle, integer *body, char *frame, 
	doublereal *first, doublereal *last, char *segid, doublereal *intlen, 
	integer *n, integer *polydg, doublereal *cdata, doublereal *btime, 
	ftnlen frame_len, ftnlen segid_len)
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    integer i__, k;
    extern /* Subroutine */ int etcal_(doublereal *, char *, ftnlen), chkin_(
	    char *, ftnlen), dafps_(integer *, integer *, doublereal *, 
	    integer *, doublereal *);
    doublereal descr[5];
    extern /* Subroutine */ int errch_(char *, char *, ftnlen, ftnlen);
    doublereal ltime;
    extern /* Subroutine */ int errdp_(char *, doublereal *, ftnlen);
    doublereal rsize;
    char etstr[40];
    extern /* Subroutine */ int dafada_(doublereal *, integer *), dafbna_(
	    integer *, doublereal *, char *, ftnlen), dafena_(void);
    extern logical failed_(void);
    extern /* Subroutine */ int chckid_(char *, integer *, char *, ftnlen, 
	    ftnlen);
    integer refcod, ninrec;
    doublereal radius, numrec;
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, 
	    ftnlen), irfnum_(char *, integer *, ftnlen), setmsg_(char *, 
	    ftnlen), errint_(char *, integer *, ftnlen);
    extern logical return_(void);
    char netstr[40];
    doublereal dcd[2];
    integer icd[5];
    doublereal mid;

/* $ Abstract */

/*    Write a type 2 segment to a PCK binary file given */
/*    the file handle, body, frame, time range covered by the */
/*    segment, and the Chebyshev polynomial coefficeients. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     NAIF_IDS */
/*     SPC */
/*     PCK */

/* $ Keywords */

/*     PCK */

/* $ Declarations */
/* $ Brief_I/O */

/*   Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     HANDLE     I   Handle of binary PCK file open for writing. */
/*     BODY       I   NAIF code for ephemeris object. */
/*     FRAME      I   Reference frame name. */
/*     FIRST      I   Start time of interval covered by segment. */
/*     LAST       I   End time of interval covered by segment. */
/*     SEGID      I   Segment identifier. */
/*     INTLEN     I   Length of time covered by logical record. */
/*     N          I   Number of logical records in segment. */
/*     POLYDG     I   Chebyshev polynomial degree. */
/*     CDATA      I   Array of Chebyshev coefficients. */
/*     BTIME      I   Begin time of first logical record. */

/* $ Detailed_Input */

/*     HANDLE         is the DAF handle of an PCK file to which a type 2 */
/*                    segment is to be added.  The PCK file must be open */
/*                    for writing. */

/*     BODY           is the NAIF integer code for an ephemeris object */
/*                    whose orientation is described by the segment to */
/*                    be created. */

/*     FRAME          is the NAIF name for a reference frame relative to */
/*                    which the orientation information for BODY is */
/*                    specified. */

/*     FIRST, */
/*     LAST           are, respectively, the start and stop times of */
/*                    the time interval over which the segment defines */
/*                    the orientation of body. */

/*     SEGID          is the segment identifier.  A PCK segment */
/*                    identifier may contain up to 40 characters. */

/*     INTLEN         Length of time, in seconds, covered by each set of */
/*                    Chebyshev polynomial coefficients (each logical */
/*                    record).  Each set of Chebyshev coefficents must */
/*                    cover this fixed time interval, INTLEN. */

/*     N              is the number of sets of Chebyshev polynomial */
/*                    coefficents (number of logical records) */
/*                    to be stored in the segment.  There is one set */
/*                    of Chebyshev coefficients for each time period. */

/*     POLYDG         Degree of each set of Chebyshev polynomials. */

/*     CDATA          Array containing all the sets of Chebyshev */
/*                    polynomial coefficients to be contained in the */
/*                    segment of the PCK file.  The coefficients are */
/*                    stored in CDATA in order as follows: */

/*                       the (degree + 1) coefficients for the first */
/*                       Euler angle of the first logical record */

/*                       the coefficients for the second Euler angle */

/*                       the coefficients for the third Euler angle */

/*                       the coefficients for the first Euler angle for */
/*                       the second logical record, ... */

/*                       and so on. */

/*     BTIME          Begin time (seconds past J2000 TDB) of first set */
/*                    of Chebyshev polynomial coefficients (first */
/*                    logical record). */

/* $ Detailed_Output */

/*      None. */

/* $ Parameters */

/*      None. */

/* $ Exceptions */

/*     1) If the number of sets of coefficients is not positive */
/*        'SPICE(NUMCOEFFSNOTPOS)' is signalled. */

/*     2) If the interval length is not positive, 'SPICE(INTLENNOTPOS)' */
/*        is signalled. */

/*     3) If the integer code for the reference frame is not recognized, */
/*        'SPICE(INVALIDREFFRAME)' is signalled. */

/*     4) If segment stop time is not greater then the begin time, */
/*         'SPICE(BADDESCRTIMES)' is signalled. */

/*     5) If the time of the first record is not greater than */
/*        or equal to the descriptor begin time, 'SPICE(BADDESCRTIMES)' */
/*        is signalled. */

/*     6) If the end time of the last record is not greater than */
/*        or equal to the descriptor end time, 'SPICE(BADDESCRTIMES)' is */
/*        signalled. */

/* $ Files */

/*     A new type 2 PCK segment is written to the PCK file attached */
/*     to HANDLE. */

/* $ Particulars */

/*     This routine writes an PCK type 2 data segment to the designated */
/*     PCK file, according to the format described in the PCK Required */
/*     Reading. */

/*     Each segment can contain data for only one body and reference */
/*     frame.  The Chebyshev polynomial degree and length of time covered */
/*     by each logical record are also fixed.  However, an arbitrary */
/*     number of logical records of Chebyshev polynomial coefficients can */
/*     be written in each segment.  Minimizing the number of segments in */
/*     a PCK file will help optimize how the SPICE system accesses the */
/*     file. */


/* $ Examples */


/*     Suppose that you have sets of Chebyshev polynomial coefficients */
/*     in an array CDATA pertaining to the position of the moon (NAIF ID */
/*     = 301) in the J2000 reference frame, and want to put these into a */
/*     type 2 segment in an existing PCK file.  The following code could */
/*     be used to add one new type 2 segment.  To add multiple segments, */
/*     put the call to PCKW02 in a loop. */

/*     C */
/*     C      First open the PCK file and get a handle for it. */
/*     C */
/*            CALL DAFOPW ( PCKNAM, HANDLE ) */

/*     C */
/*     C      Create a segment identifier. */
/*     C */
/*            SEGID = 'MY_SAMPLE_PCK_TYPE_2_SEGMENT' */

/*     C */
/*     C      Write the segment. */

/*            CALL PCKW02 (  HANDLE, 301,    'J2000', */
/*     .                     FIRST,  LAST,   SEGID,   INTLEN, */
/*     .                     N,      POLYDG, CDATA,   BTIME) */

/*     C */
/*     C      Close the file. */
/*     C */
/*            CALL DAFCLS ( HANDLE ) */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     K.S. Zukor (JPL) */

/* $ Version */

/* -    SPICELIB Version 2.0.0, 1-AUG-1995 (KSZ) */

/*        The calling sequence was corrected so that REF is */
/*        a character string and BTIME contains only the start */
/*        time of the first record.  Comments updated, and new */
/*        routine CHCKID is called to check segment identifier. */

/* -    SPICELIB Version 1.0.0, 11-MAR-1994 (KSZ) */

/* -& */
/* $ Index_Entries */

/*     write pck type_2 data segment */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 2.0.0, 1-AUG-1995 (KSZ) */

/*        The calling sequence was corrected so that REF is */
/*        a character string and BTIME contains only the start */
/*        time of the first record.  Comments updated, and new */
/*        routine CHCKID is called to check segment identifier. */

/* -& */

/*     SPICELIB functions */


/*     Local Parameters */

/*     DTYPE is the PCK data type. */


/*     NS is the size of a packed PCK segment descriptor. */


/*     ND is the number of double precision components in an PCK */
/*     segment descriptor. PCK uses ND = 2. */


/*     NI is the number of integer components in an PCK segment */
/*     descriptor. PCK uses NI = 5. */


/*     SIDLEN is the maximum number of characters allowed in an */
/*     PCK segment identifier. */


/*     Local variables */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("PCKW02", (ftnlen)6);
    }

/*     The number of sets of coefficients must be positive. */

    if (*n <= 0) {
	setmsg_("The number of sets of Euler anglecoefficients is not positi"
		"ve. N = #", (ftnlen)68);
	errint_("#", n, (ftnlen)1);
	sigerr_("SPICE(NUMCOEFFSNOTPOS)", (ftnlen)22);
	chkout_("PCKW02", (ftnlen)6);
	return 0;
    }

/*     The interval length must be positive. */

    if (*intlen <= 0.) {
	setmsg_("The interval length is not positive.N = #", (ftnlen)41);
	errdp_("#", intlen, (ftnlen)1);
	sigerr_("SPICE(INTLENNOTPOS)", (ftnlen)19);
	chkout_("PCKW02", (ftnlen)6);
	return 0;
    }

/*     Get the NAIF integer code for the reference frame. */

    irfnum_(frame, &refcod, frame_len);
    if (refcod == 0) {
	setmsg_("The reference frame # is not supported.", (ftnlen)39);
	errch_("#", frame, (ftnlen)1, frame_len);
	sigerr_("SPICE(INVALIDREFFRAME)", (ftnlen)22);
	chkout_("PCKW02", (ftnlen)6);
	return 0;
    }

/*     The segment stop time must be greater than the begin time. */

    if (*first > *last) {
	setmsg_("The segment start time: # is greater than the segment end t"
		"ime: #", (ftnlen)65);
	etcal_(first, etstr, (ftnlen)40);
	errch_("#", etstr, (ftnlen)1, (ftnlen)40);
	etcal_(last, netstr, (ftnlen)40);
	errch_("#", netstr, (ftnlen)1, (ftnlen)40);
	sigerr_("SPICE(BADDESCRTIMES)", (ftnlen)20);
	chkout_("PCKW02", (ftnlen)6);
	return 0;
    }

/*     The begin time of the first record must be less than or equal */
/*     to the begin time of the segment. */

    if (*first < *btime) {
	setmsg_("The segment descriptor start time: # is less than the begin"
		"ning time of the segment data: #", (ftnlen)91);
	etcal_(first, etstr, (ftnlen)40);
	errch_("#", etstr, (ftnlen)1, (ftnlen)40);
	etcal_(btime, etstr, (ftnlen)40);
	errch_("#", etstr, (ftnlen)1, (ftnlen)40);
	sigerr_("SPICE(BADDESCRTIMES)", (ftnlen)20);
	chkout_("PCKW02", (ftnlen)6);
	return 0;
    }

/*     The end time of the final record must be greater than or */
/*     equal to the end time of the segment. */

    ltime = *btime + *n * *intlen;
    if (*last > ltime) {
	setmsg_("The segment descriptor end time: # is greater than the end "
		"time of the segment data: #", (ftnlen)86);
	etcal_(last, etstr, (ftnlen)40);
	errch_("#", etstr, (ftnlen)1, (ftnlen)40);
	etcal_(&ltime, etstr, (ftnlen)40);
	errch_("#", etstr, (ftnlen)1, (ftnlen)40);
	sigerr_("SPICE(BADDESCRTIMES)", (ftnlen)20);
	chkout_("PCKW02", (ftnlen)6);
	return 0;
    }

/*     Now check the validity of the segment identifier. */

    chckid_("PCK segment identifier", &c__40, segid, (ftnlen)22, segid_len);
    if (failed_()) {
	chkout_("PCKW02", (ftnlen)6);
	return 0;
    }

/*     Store the start and end times to be associated */
/*     with this segment. */

    dcd[0] = *first;
    dcd[1] = *last;

/*     Create the integer portion of the descriptor. */

    icd[0] = *body;
    icd[1] = refcod;
    icd[2] = 2;

/*     Pack the segment descriptor. */

    dafps_(&c__2, &c__5, dcd, icd, descr);

/*     Begin a new segment of PCK type 2 form: */

/*        Record 1 */
/*        Record 2 */
/*        ... */
/*        Record N */
/*        INIT       ( initial epoch of first record ) */
/*        INTLEN     ( length of interval covered by each record ) */
/*        RSIZE      ( number of data elements in each record ) */
/*        N          ( number of records in segment ) */

/*     Each record will have the form: */

/*        MID        ( midpoint of time interval ) */
/*        RADIUS     ( radius of time interval ) */
/*        X coefficients, Y coefficients, Z coefficients */

    dafbna_(handle, descr, segid, segid_len);

/*     Calculate the number of entries in a record. */

    ninrec = (*polydg + 1) * 3;

/*     Fill segment with N records of data. */

    i__1 = *n;
    for (i__ = 1; i__ <= i__1; ++i__) {

/*        Calculate the midpoint and radius of the time of each */
/*        record, and put that at the beginning of each record. */

	radius = *intlen / 2;
	mid = *btime + radius + (i__ - 1) * *intlen;
	dafada_(&mid, &c__1);
	dafada_(&radius, &c__1);

/*        Put one set of coefficients into the segment. */

	k = (i__ - 1) * ninrec + 1;
	dafada_(&cdata[k - 1], &ninrec);
    }

/*     Store the initial epoch of the first record. */

    dafada_(btime, &c__1);

/*     Store the length of interval covered by each record. */

    dafada_(intlen, &c__1);

/*     Store the size of each record (total number of array elements). */

    rsize = (doublereal) (ninrec + 2);
    dafada_(&rsize, &c__1);

/*     Store the number of records contained in the segment. */

    numrec = (doublereal) (*n);
    dafada_(&numrec, &c__1);

/*     End this segment. */

    dafena_();
    chkout_("PCKW02", (ftnlen)6);
    return 0;
} /* pckw02_ */
Пример #2
0
/* $Procedure SPKW20 ( SPK, write segment, type 20 ) */
/* Subroutine */ int spkw20_(integer *handle, integer *body, integer *center,
                             char *frame, doublereal *first, doublereal *last, char *segid,
                             doublereal *intlen, integer *n, integer *polydg, doublereal *cdata,
                             doublereal *dscale, doublereal *tscale, doublereal *initjd,
                             doublereal *initfr, ftnlen frame_len, ftnlen segid_len)
{
    /* System generated locals */
    integer i__1;
    doublereal d__1, d__2;

    /* Local variables */
    extern /* Subroutine */ int etcal_(doublereal *, char *, ftnlen), chkin_(
        char *, ftnlen), dafps_(integer *, integer *, doublereal *,
                                integer *, doublereal *);
    doublereal btime, descr[5];
    extern /* Subroutine */ int errch_(char *, char *, ftnlen, ftnlen);
    doublereal ltime;
    extern /* Subroutine */ int errdp_(char *, doublereal *, ftnlen);
    char etstr[40];
    extern /* Subroutine */ int dafada_(doublereal *, integer *), dafbna_(
        integer *, doublereal *, char *, ftnlen), dafena_(void);
    extern logical failed_(void);
    extern /* Subroutine */ int chckid_(char *, integer *, char *, ftnlen,
                                        ftnlen);
    integer refcod, ninrec;
    extern /* Subroutine */ int namfrm_(char *, integer *, ftnlen);
    doublereal numrec;
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *,
            ftnlen), setmsg_(char *, ftnlen), errint_(char *, integer *,
                    ftnlen);
    extern logical return_(void);
    char netstr[40];
    doublereal dcd[2];
    extern doublereal j2000_(void);
    integer icd[6];
    extern doublereal spd_(void);
    doublereal tol;

    /* $ Abstract */

    /*     Write a type 20 segment to an SPK file. */

    /* $ Disclaimer */

    /*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
    /*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
    /*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
    /*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
    /*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
    /*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
    /*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
    /*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
    /*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
    /*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

    /*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
    /*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
    /*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
    /*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
    /*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
    /*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

    /*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
    /*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
    /*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
    /*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

    /* $ Required_Reading */

    /*     DAF */
    /*     NAIF_IDS */
    /*     TIME */
    /*     SPK */

    /* $ Keywords */

    /*     EPHEMERIS */

    /* $ Declarations */
    /* $ Abstract */

    /*     Declare parameters specific to SPK type 20. */

    /* $ Disclaimer */

    /*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
    /*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
    /*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
    /*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
    /*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
    /*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
    /*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
    /*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
    /*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
    /*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

    /*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
    /*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
    /*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
    /*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
    /*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
    /*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

    /*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
    /*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
    /*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
    /*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

    /* $ Required_Reading */

    /*     SPK */

    /* $ Keywords */

    /*     SPK */

    /* $ Restrictions */

    /*     None. */

    /* $ Author_and_Institution */

    /*     N.J. Bachman      (JPL) */

    /* $ Literature_References */

    /*     None. */

    /* $ Version */

    /* -    SPICELIB Version 1.0.0, 30-DEC-2013 (NJB) */

    /* -& */
    /*     MAXDEG         is the maximum allowed degree of the input */
    /*                    Chebyshev expansions. If the value of MAXDEG is */
    /*                    increased, the SPICELIB routine SPKPVN must be */
    /*                    changed accordingly. In particular, the size of */
    /*                    the record passed to SPKRnn and SPKEnn must be */
    /*                    increased, and comments describing the record size */
    /*                    must be changed. */

    /*                    The record size requirement is */

    /*                       MAXREC = 3 * ( MAXDEG + 3 ) */



    /*     TOLSCL         is a tolerance scale factor (also called a */
    /*                    "relative tolerance") used for time coverage */
    /*                    bound checking. TOLSCL is unitless. TOLSCL */
    /*                    produces a tolerance value via the formula */

    /*                       TOL = TOLSCL * MAX( ABS(FIRST), ABS(LAST) ) */

    /*                    where FIRST and LAST are the coverage time bounds */
    /*                    of a type 20 segment, expressed as seconds past */
    /*                    J2000 TDB. */

    /*                    The resulting parameter TOL is used as a tolerance */
    /*                    for comparing the input segment descriptor time */
    /*                    bounds to the first and last epoch covered by the */
    /*                    sequence of time intervals defined by the inputs */
    /*                    to SPKW20: */

    /*                       INITJD */
    /*                       INITFR */
    /*                       INTLEN */
    /*                       N */

    /*     Tolerance scale for coverage gap at the endpoints */
    /*     of the segment coverage interval: */


    /*     End of include file spk20.inc. */

    /* $ Brief_I/O */

    /*   Variable  I/O  Description */
    /*     --------  ---  -------------------------------------------------- */
    /*     HANDLE     I   Handle of SPK file open for writing. */
    /*     BODY       I   NAIF code for ephemeris object. */
    /*     CENTER     I   NAIF code for the center of motion of the body. */
    /*     FRAME      I   Reference frame name. */
    /*     FIRST      I   Start time of interval covered by segment. */
    /*     LAST       I   End time of interval covered by segment. */
    /*     SEGID      I   Segment identifier. */
    /*     INTLEN     I   Length of time covered by logical record (days). */
    /*     N          I   Number of logical records in segment. */
    /*     POLYDG     I   Chebyshev polynomial degree. */
    /*     CDATA      I   Array of Chebyshev coefficients and positions. */
    /*     DSCALE     I   Distance scale of data. */
    /*     TSCALE     I   Time scale of data. */
    /*     INITJD     I   Integer part of begin time (TDB Julian date) of */
    /*                    first record. */
    /*     INITFR     I   Fractional part of begin time (TDB Julian date) of */
    /*                    first record. */
    /*     MAXDEG     P   Maximum allowed degree of Chebyshev expansions. */
    /*     TOLSCL     P   Tolerance scale for coverage bound checking. */

    /* $ Detailed_Input */

    /*     HANDLE         is the DAF handle of an SPK file to which a type 20 */
    /*                    segment is to be added.  The SPK file must be open */
    /*                    for writing. */

    /*     BODY           is the NAIF integer code for an ephemeris object */
    /*                    whose state relative to another body is described */
    /*                    by the segment to be created. */

    /*     CENTER         is the NAIF integer code for the center of motion */
    /*                    of the object identified by BODY. */

    /*     FRAME          is the NAIF name for a reference frame relative to */
    /*                    which the state information for BODY is specified. */

    /*     FIRST, */
    /*     LAST           are the start and stop times of the time interval */
    /*                    over which the segment defines the state of the */
    /*                    object identified by BODY. */

    /*     SEGID          is a segment identifier. An SPK segment identifier */
    /*                    may contain up to 40 characters. */

    /*     INTLEN         is the length of time, in TDB Julian days, covered */
    /*                    by each set of Chebyshev polynomial coefficients */
    /*                    (each logical record). */

    /*     N              is the number of logical records to be stored in */
    /*                    the segment. There is one logical record for each */
    /*                    time period. Each logical record contains three */
    /*                    sets of Chebyshev coefficients---one for each */
    /*                    coordinate---and three position vector components. */

    /*     POLYDG         is the degree of each set of Chebyshev */
    /*                    polynomials, i.e. the number of Chebyshev */
    /*                    coefficients per coordinate minus one. POLYDG must */
    /*                    be less than or equal to the parameter MAXDEG. */

    /*     CDATA          is an array containing all the sets of Chebyshev */
    /*                    polynomial coefficients and position components to */
    /*                    be placed in the new segment of the SPK file. */
    /*                    There are three sets of coefficients and position */
    /*                    components for each time interval covered by the */
    /*                    segment. */

    /*                    The coefficients and position components are */
    /*                    stored in CDATA in order as follows: */

    /*                       the (POLYDG + 1) coefficients for the first */
    /*                       coordinate of the first logical record, */
    /*                       followed by the X component of position at the */
    /*                       first interval midpoint. The first coefficient */
    /*                       is that of the constant term of the expansion. */

    /*                       the coefficients for the second coordinate, */
    /*                       followed by the Y component of position at the */
    /*                       first interval midpoint. */

    /*                       the coefficients for the third coordinate, */
    /*                       followed by the Z component of position at the */
    /*                       first interval midpoint. */

    /*                       the coefficients for the first coordinate for */
    /*                       the second logical record, followed by the X */
    /*                       component of position at the second interval */
    /*                       midpoint. */

    /*                       and so on. */

    /*                    The logical data records are stored contiguously: */

    /*                       +----------+ */
    /*                       | Record 1 | */
    /*                       +----------+ */
    /*                       | Record 2 | */
    /*                       +----------+ */
    /*                           ... */
    /*                       +----------+ */
    /*                       | Record N | */
    /*                       +----------+ */

    /*                    The contents of an individual record are: */

    /*                       +--------------------------------------+ */
    /*                       | Coeff set for X velocity component   | */
    /*                       +--------------------------------------+ */
    /*                       | X position component                 | */
    /*                       +--------------------------------------+ */
    /*                       | Coeff set for Y velocity component   | */
    /*                       +--------------------------------------+ */
    /*                       | Y position component                 | */
    /*                       +--------------------------------------+ */
    /*                       | Coeff set for Z velocity component   | */
    /*                       +--------------------------------------+ */
    /*                       | Z position component                 | */
    /*                       +--------------------------------------+ */

    /*                   Each coefficient set has the structure: */

    /*                       +--------------------------------------+ */
    /*                       | Coefficient of T_0                   | */
    /*                       +--------------------------------------+ */
    /*                       | Coefficient of T_1                   | */
    /*                       +--------------------------------------+ */
    /*                                         ... */
    /*                       +--------------------------------------+ */
    /*                       | Coefficient of T_POLYDG              | */
    /*                       +--------------------------------------+ */

    /*                    Where T_n represents the Chebyshev polynomial */
    /*                    of the first kind of degree n. */


    /*     DSCALE, */
    /*     TSCALE         are, respectively, the distance scale of the input */
    /*                    position and velocity data in km, and the time */
    /*                    scale of the input velocity data in TDB seconds. */

    /*                    For example, if the input distance data have units */
    /*                    of astronomical units (AU), DSCALE should be set */
    /*                    to the number of km in one AU. If the input */
    /*                    velocity data have time units of Julian days, then */
    /*                    TSCALE should be set to the number of seconds per */
    /*                    Julian day (86400). */


    /*     INITJD         is the integer part of the Julian ephemeris date */
    /*                    of initial epoch of the first record. INITJD may */
    /*                    be less than, equal to, or greater than the */
    /*                    initial epoch. */

    /*     INITFR         is the fractional part of the Julian ephemeris date */
    /*                    of initial epoch of the first record. INITFR has */
    /*                    units of Julian days. INITFR has magnitude */
    /*                    strictly less than 1 day. The sum */

    /*                       INITJD + INITFR */

    /*                    equals the Julian ephemeris date of the initial */
    /*                    epoch of the first record. */


    /* $ Detailed_Output */

    /*     None. This routine writes data to an SPK file. */

    /* $ Parameters */

    /*     The parameters described in this section are declared in the */
    /*     Fortran INCLUDE file spk20.inc */


    /*     MAXDEG         is the maximum allowed degree of the input */
    /*                    Chebyshev expansions. */


    /*     TOLSCL         is a tolerance scale factor (also called a */
    /*                    "relative tolerance") used for time coverage */
    /*                    bound checking. TOLSCL is unitless. TOLSCL */
    /*                    produces a tolerance value via the formula */

    /*                       TOL = TOLSCL * MAX( ABS(FIRST), ABS(LAST) ) */

    /*                    where FIRST and LAST are the coverage time bounds */
    /*                    of a type 20 segment, expressed as seconds past */
    /*                    J2000 TDB. */

    /*                    The resulting parameter TOL is used as a tolerance */
    /*                    for comparing the input segment descriptor time */
    /*                    bounds to the first and last epoch covered by the */
    /*                    sequence of time intervals defined by the inputs */

    /*                       INITJD */
    /*                       INITFR */
    /*                       INTLEN */
    /*                       N */

    /*                    See the Exceptions section below for a description */
    /*                    of the error check using this tolerance. */

    /* $ Exceptions */

    /*     1)  If the number of sets of coefficients is not positive */
    /*         SPICE(INVALIDCOUNT) is signaled. */

    /*     2)  If the interval length is not positive, SPICE(INTLENNOTPOS) */
    /*         is signaled. */

    /*     3)  If the name of the reference frame is not recognized, */
    /*         SPICE(INVALIDREFFRAME) is signaled. */

    /*     4)  If segment stop time is not greater than or equal to */
    /*         the begin time, SPICE(BADDESCRTIMES) is signaled. */

    /*     5)  If the start time of the first record exceeds the descriptor */
    /*         begin time by more than a computed tolerance, or if the end */
    /*         time of the last record precedes the descriptor end time by */
    /*         more than a computed tolerance, the error SPICE(COVERAGEGAP) */
    /*         is signaled. See the Parameters section above for a */
    /*         description of the tolerance. */

    /*     6)  If the input degree POLYDG is less than 0 or greater than */
    /*         MAXDEG, the error SPICE(INVALIDDEGREE) is signaled. */

    /*     7)  If the last non-blank character of SEGID occurs past index */
    /*         40, or if SEGID contains any nonprintable characters, the */
    /*         error will be diagnosed by a routine in the call tree of this */
    /*         routine. */

    /*     8)  If either the distance or time scale is non-positive, the */
    /*         error SPICE(NONPOSITIVESCALE) will be signaled. */

    /* $ Files */

    /*     A new type 20 SPK segment is written to the SPK file attached */
    /*     to HANDLE. */

    /* $ Particulars */

    /*     This routine writes an SPK type 20 data segment to the designated */
    /*     SPK file, according to the format described in the SPK Required */
    /*     Reading. */

    /*     Each segment can contain data for only one target, central body, */
    /*     and reference frame. The Chebyshev polynomial degree and length */
    /*     of time covered by each logical record are also fixed. However, */
    /*     an arbitrary number of logical records of Chebyshev polynomial */
    /*     coefficients can be written in each segment.  Minimizing the */
    /*     number of segments in an SPK file will help optimize how the */
    /*     SPICE system accesses the file. */

    /* $ Examples */

    /*     Suppose that you have in an array CDATA sets of Chebyshev */
    /*     polynomial coefficients and position vectors representing the */
    /*     state of the moon (NAIF ID = 301), relative to the Earth-moon */
    /*     barycenter (NAIF ID = 3), in the J2000 reference frame, and you */
    /*     want to put these into a type 20 segment in an existing SPK file. */
    /*     The following code could be used to add one new type 20 segment. */
    /*     To add multiple segments, put the call to SPKW20 in a loop. */

    /*     C */
    /*     C      First open the SPK file and get a handle for it. */
    /*     C */
    /*            CALL DAFOPW ( SPKNAM, HANDLE ) */

    /*     C */
    /*     C      Create a segment identifier. */
    /*     C */
    /*            SEGID = 'MY_SAMPLE_SPK_TYPE_20_SEGMENT' */

    /*     C */
    /*     C      Note that the interval length INTLEN has units */
    /*     C      of Julian days. The start time of the first record */
    /*     C      is expressed using two inputs: integer and fractional */
    /*     C      portions of the Julian ephemeris date of the start */
    /*     C      time. */
    /*     C */
    /*     C      Write the segment. */
    /*     C */
    /*            CALL SPKW20 ( HANDLE, 301,    3,      'J2000', */
    /*          .               FIRST,  LAST,   SEGID,  INTLEN, */
    /*          .               N,      POLYDG, CDATA,  DSCALE, */
    /*          .               TSCALE, INITJD, INITFR           ) */

    /*     C */
    /*     C      Close the file. */
    /*     C */
    /*            CALL DAFCLS ( HANDLE ) */

    /* $ Restrictions */

    /*     None. */

    /* $ Literature_References */

    /*     None. */

    /* $ Author_and_Institution */

    /*     N.J. Bachman (JPL) */
    /*     K.S. Zukor   (JPL) */

    /* $ Version */

    /* -    SPICELIB Version 1.0.0, 17-JAN-2017 (NJB) (KSZ) */

    /* -& */
    /* $ Index_Entries */

    /*     write spk type_20 data segment */

    /* -& */

    /*     SPICELIB functions */


    /*     Local Parameters */


    /*     DTYPE is the SPK data type. */


    /*     ND is the number of double precision components in an SPK */
    /*     segment descriptor. SPK uses ND = 2. */


    /*     NI is the number of integer components in an SPK segment */
    /*     descriptor. SPK uses NI = 6. */


    /*     NS is the size of a packed SPK segment descriptor. */


    /*     SIDLEN is the maximum number of characters allowed in an */
    /*     SPK segment identifier. */


    /*     Local variables */



    /*     Standard SPICE error handling. */

    if (return_()) {
        return 0;
    }
    chkin_("SPKW20", (ftnlen)6);

    /*     The number of sets of coefficients must be positive. */

    if (*n <= 0) {
        setmsg_("The number of sets of coordinate coefficients is not positi"
                "ve. N = # ", (ftnlen)69);
        errint_("#", n, (ftnlen)1);
        sigerr_("SPICE(INVALIDCOUNT)", (ftnlen)19);
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }

    /*     Make sure that the degree of the interpolating polynomials is */
    /*     in range. */

    if (*polydg < 0 || *polydg > 50) {
        setmsg_("The interpolating polynomials have degree #; the valid degr"
                "ee range is [0, #].", (ftnlen)78);
        errint_("#", polydg, (ftnlen)1);
        errint_("#", &c__50, (ftnlen)1);
        sigerr_("SPICE(INVALIDDEGREE)", (ftnlen)20);
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }

    /*     The interval length must be positive. */

    if (*intlen <= 0.) {
        setmsg_("The interval length is not positive.N = #", (ftnlen)41);
        errdp_("#", intlen, (ftnlen)1);
        sigerr_("SPICE(INTLENNOTPOS)", (ftnlen)19);
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }

    /*     Get the NAIF integer code for the reference frame. */

    namfrm_(frame, &refcod, frame_len);
    if (refcod == 0) {
        setmsg_("The reference frame # is not supported.", (ftnlen)39);
        errch_("#", frame, (ftnlen)1, frame_len);
        sigerr_("SPICE(INVALIDREFFRAME)", (ftnlen)22);
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }

    /*     The segment stop time must be greater than or equal to the begin */
    /*     time. */

    if (*first > *last) {
        setmsg_("The segment start time: # (# TDB) is greater than the segme"
                "nt end time: (# TDB).", (ftnlen)80);
        etcal_(first, etstr, (ftnlen)40);
        errch_("#", etstr, (ftnlen)1, (ftnlen)40);
        errdp_("#", first, (ftnlen)1);
        etcal_(last, netstr, (ftnlen)40);
        errch_("#", netstr, (ftnlen)1, (ftnlen)40);
        errdp_("#", last, (ftnlen)1);
        sigerr_("SPICE(BADDESCRTIMES)", (ftnlen)20);
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }

    /*     The distance and time scales must be positive. */

    if (*dscale <= 0.) {
        setmsg_("The distance scale is not positive.DSCALE = #", (ftnlen)45);
        errdp_("#", dscale, (ftnlen)1);
        sigerr_("SPICE(NONPOSITIVESCALE)", (ftnlen)23);
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }
    if (*tscale <= 0.) {
        setmsg_("The time scale is not positive.TSCALE = #", (ftnlen)41);
        errdp_("#", tscale, (ftnlen)1);
        sigerr_("SPICE(NONPOSITIVESCALE)", (ftnlen)23);
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }

    /*     The begin time of the first record must be less than or equal */
    /*     to the begin time of the segment. Convert the two-part input */
    /*     epoch to seconds past J2000 for the purpose of this check. */

    btime = spd_() * (*initjd - j2000_() + *initfr);
    ltime = btime + *n * *intlen * spd_();

    /*     Compute the tolerance to use for descriptor time bound checks. */

    /* Computing MAX */
    d__1 = abs(btime), d__2 = abs(ltime);
    tol = max(d__1,d__2) * 1e-13;
    if (*first < btime - tol) {
        setmsg_("The segment descriptor start time # is too much less than t"
                "he beginning time of the segment data # (in seconds past J20"
                "00: #). The difference is # seconds; the tolerance is # seco"
                "nds.", (ftnlen)183);
        etcal_(first, etstr, (ftnlen)40);
        errch_("#", etstr, (ftnlen)1, (ftnlen)40);
        etcal_(&btime, etstr, (ftnlen)40);
        errch_("#", etstr, (ftnlen)1, (ftnlen)40);
        errdp_("#", first, (ftnlen)1);
        d__1 = btime - *first;
        errdp_("#", &d__1, (ftnlen)1);
        errdp_("#", &tol, (ftnlen)1);
        sigerr_("SPICE(COVERAGEGAP)", (ftnlen)18);
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }

    /*     The end time of the final record must be greater than or */
    /*     equal to the end time of the segment. */

    if (*last > ltime + tol) {
        setmsg_("The segment descriptor end time # is too much greater than "
                "the end time of the segment data # (in seconds past J2000: #"
                "). The difference is # seconds; the tolerance is # seconds.",
                (ftnlen)178);
        etcal_(last, etstr, (ftnlen)40);
        errch_("#", etstr, (ftnlen)1, (ftnlen)40);
        etcal_(&ltime, etstr, (ftnlen)40);
        errch_("#", etstr, (ftnlen)1, (ftnlen)40);
        errdp_("#", last, (ftnlen)1);
        d__1 = *last - ltime;
        errdp_("#", &d__1, (ftnlen)1);
        errdp_("#", &tol, (ftnlen)1);
        sigerr_("SPICE(COVERAGEGAP)", (ftnlen)18);
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }

    /*     Now check the validity of the segment identifier. */

    chckid_("SPK segment identifier", &c__40, segid, (ftnlen)22, segid_len);
    if (failed_()) {
        chkout_("SPKW20", (ftnlen)6);
        return 0;
    }

    /*     Store the start and end times to be associated */
    /*     with this segment. */

    dcd[0] = *first;
    dcd[1] = *last;

    /*     Create the integer portion of the descriptor. */

    icd[0] = *body;
    icd[1] = *center;
    icd[2] = refcod;
    icd[3] = 20;

    /*     Pack the segment descriptor. */

    dafps_(&c__2, &c__6, dcd, icd, descr);

    /*     Begin a new segment of SPK type 20 form: */

    /*        Record 1 */
    /*        Record 2 */
    /*        ... */
    /*        Record N */
    /*        DSCALE     ( distance scale in km ) */
    /*        TSCALE     ( time scale in seconds ) */
    /*        INITJD     ( integer part of initial epoch of first record, */
    /*                     expressed as a TDB Julian date ) */
    /*        INITFR     ( fractional part of initial epoch, in units of */
    /*                     TDB Julian days ) */
    /*        INTLEN     ( length of interval covered by each record, in */
    /*                     units of TDB Julian days ) */
    /*        RSIZE      ( number of data elements in each record ) */
    /*        N          ( number of records in segment ) */

    /*     Each record will have the form: */

    /*        X coefficients */
    /*        X position component at interval midpoint */
    /*        Y coefficients */
    /*        Y position component at interval midpoint */
    /*        Z coefficients */
    /*        Z position component at interval midpoint */


    dafbna_(handle, descr, segid, segid_len);

    /*     Calculate the number of entries in a record. */

    ninrec = (*polydg + 2) * 3;

    /*     Fill segment with N records of data. */

    i__1 = *n * ninrec;
    dafada_(cdata, &i__1);

    /*     Store the distance and time scales. */

    dafada_(dscale, &c__1);
    dafada_(tscale, &c__1);

    /*     Store the integer and fractional parts of the initial epoch of */
    /*     the first record. */

    dafada_(initjd, &c__1);
    dafada_(initfr, &c__1);

    /*     Store the length of interval covered by each record. */

    dafada_(intlen, &c__1);

    /*     Store the size of each record (total number of array elements). */
    /*     Note that this size is smaller by 2 than the size of a type 2 */
    /*     record of the same degree, since the record coverage midpoint */
    /*     and radius are not stored. */

    d__1 = (doublereal) ninrec;
    dafada_(&d__1, &c__1);

    /*     Store the number of records contained in the segment. */

    numrec = (doublereal) (*n);
    dafada_(&numrec, &c__1);

    /*     End this segment. */

    dafena_();
    chkout_("SPKW20", (ftnlen)6);
    return 0;
} /* spkw20_ */