Beispiel #1
0
/* $Procedure      STLABX ( Stellar aberration, transmission case ) */
/* Subroutine */ int stlabx_(doublereal *pobj, doublereal *vobs, doublereal *
	corpos)
{
    extern /* Subroutine */ int chkin_(char *, ftnlen), stelab_(doublereal *, 
	    doublereal *, doublereal *);
    doublereal negvel[3];
    extern /* Subroutine */ int chkout_(char *, ftnlen);
    extern logical return_(void);
    extern /* Subroutine */ int vminus_(doublereal *, doublereal *);

/* $ Abstract */

/*     Correct the position of a target for the stellar aberration */
/*     effect on radiation transmitted from a specified observer to */
/*     the target. */

/* $ 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 */

/*     None. */

/* $ Keywords */

/*      EPHEMERIS */

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

/*      VARIABLE  I/O  DESCRIPTION */
/*      --------  ---  -------------------------------------------------- */
/*      POBJ       I   Position of an object with respect to the */
/*                     observer. */
/*      VOBS       I   Velocity of the observer with respect to the */
/*                     Solar System barycenter. */
/*      CORPOS     O   Corrected position of the object. */

/* $ Detailed_Input */

/*      POBJ        is the cartesian position vector of an object with */
/*                  respect to the observer, possibly corrected for */
/*                  light time.  Units are km. */

/*      VOBS        is the cartesian velocity vector of the observer */
/*                  with respect to the Solar System barycenter.  Units */
/*                  are km/s. */

/* $ Detailed_Output */

/*      CORPOS      is the  position of the object relative to the */
/*                  observer, corrected for the stellar aberration */
/*                  effect on radiation directed toward the target.  This */
/*                  correction is the inverse of the usual stellar */
/*                  aberration correction:  the corrected vector */
/*                  indicates the direction in which radiation must be */
/*                  emitted from the observer, as seen in an inertial */
/*                  reference frame having velocity equal to that of the */
/*                  observer, in order to reach the position indicated by */
/*                  the input vector POBJ. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1) If the velocity of the observer is greater than or equal */
/*        to the speed of light, the error is diagnosed by a routine */
/*        called by this routine.  The outputs are undefined. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     In order to transmit radiation from an observer to a specified */
/*     target, the emission direction must be corrected for one way */
/*     light time and for the motion of the observer relative to the */
/*     solar system barycenter.  The correction for the observer's */
/*     motion when transmitting to a target is the inverse of the */
/*     usual stellar aberration correction applied to the light-time */
/*     corrected position of the target as seen by the observer. */

/*     Below is the description of the stellar aberration correction */
/*     used in the SPICELIB routine STELAB (with the notation changed */
/*     slightly): */

/*        Let r be the vector from the observer to the object, and v be */
/*        the velocity of the observer with respect to the Solar System */
/*        barycenter. Let w be the angle between them. The aberration */
/*        angle phi is given by */

/*           sin(phi) = v sin(w) / c */

/*        Let h be the vector given by the cross product */

/*           h = r X v */

/*        Rotate r by phi radians about h to obtain the apparent position */
/*        of the object. */

/*     This routine applies the inverse correction, so here the rotation */
/*     about h is by -phi radians. */

/* $ Examples */

/*     In the following example, STLABX is used to correct the position */
/*     of a target body for the stellar aberration effect on radiation */
/*     transmitted to the target. */

/*          [Previous subroutine calls have loaded an SPK file and */
/*           the leapseconds kernel file.  The SPK file contains */
/*           sufficient data to enable computation of observer and */
/*           target states relative to the solar system barycenter.] */

/*      C */
/*      C     Get the geometric state of the observer OBS relative to */
/*      C     the solar system barycenter. */
/*      C */
/*            CALL SPKSSB ( OBS, ET, 'J2000', SOBS ) */

/*      C */
/*      C     Get the light-time corrected position TPOS of the target */
/*      C     body TARG as seen by the observer. Normally we would */
/*      C     call SPKPOS to obtain this vector, but we already have */
/*      C     the state of the observer relative to the solar system */
/*      C     barycenter, so we can avoid looking up that state twice */
/*      C     by calling SPKAPO. */
/*      C */
/*            CALL SPKAPO ( TARG, ET, 'J2000', SOBS, 'XLT', TPOS, LT ) */

/*      C */
/*      C     Apply the correction for stellar aberration to the */
/*      C     light-time corrected position of the target body. */
/*      C     The corrected position is returned in the argument */
/*      C     PCORR. */
/*      C */
/*            CALL STLABX ( TPOS, SOBS(4), PCORR ) */


/*      Note that this example is somewhat contrived. The sequence */
/*      of calls above could be replaced by a single call to SPKEZP, */
/*      using the aberration correction flag 'XLT+S'. */

/*      For more information on aberration-corrected states or */
/*      positions, see the headers of any of the routines */

/*         SPKEZR */
/*         SPKEZ */
/*         SPKPOS */
/*         SPKEZP */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     1) W.M. Owen, Jr., JPL IOM #314.8-524, "The Treatment of */
/*        Aberration in Optical Navigation", 8 February 1985. */

/* $ Author_and_Institution */

/*     N.J. Bachman    (JPL) */
/*     W.L. Taber      (JPL) */
/*     I.M. Underwood  (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.0.1, 8-JAN-2008 (NJB) */

/*        The header example was updated to remove references */
/*        to SPKAPP. */

/* -    SPICELIB Version 1.0.0, 02-JAN-2002 (IMU) (WLT) (NJB) */

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

/*     stellar aberration for transmission case */

/* -& */

/*     SPICELIB functions */


/*     Local variables */


/*     Standard SPICE error handling. */

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

/*     Obtain the negative of the observer's velocity.  This */
/*     velocity, combined with the target's position, will yield */
/*     the inverse of the usual stellar aberration correction, */
/*     which is exactly what we seek. */

    vminus_(vobs, negvel);
    stelab_(pobj, negvel, corpos);
    chkout_("STLABX", (ftnlen)6);
    return 0;
} /* stlabx_ */
Beispiel #2
0
/* $Procedure ILLUM ( Illumination angles ) */
/* Subroutine */ int illum_(char *target, doublereal *et, char *abcorr, char *
	obsrvr, doublereal *spoint, doublereal *phase, doublereal *solar, 
	doublereal *emissn, ftnlen target_len, ftnlen abcorr_len, ftnlen 
	obsrvr_len)
{
    /* Initialized data */

    static logical first = TRUE_;

    extern /* Subroutine */ int zzbods2c_(integer *, char *, integer *, 
	    logical *, char *, integer *, logical *, ftnlen, ftnlen);
    extern doublereal vsep_(doublereal *, doublereal *);
    extern /* Subroutine */ int vsub_(doublereal *, doublereal *, doublereal *
	    ), vequ_(doublereal *, doublereal *), zzctruin_(integer *);
    integer n;
    doublereal radii[3];
    extern /* Subroutine */ int chkin_(char *, ftnlen), errch_(char *, char *,
	     ftnlen, ftnlen);
    logical found;
    extern /* Subroutine */ int spkez_(integer *, doublereal *, char *, char *
	    , integer *, doublereal *, doublereal *, ftnlen, ftnlen);
    extern logical eqstr_(char *, char *, ftnlen, ftnlen);
    static logical svfnd1, svfnd2;
    static integer svctr1[2], svctr2[2];
    integer obscde;
    doublereal lt;
    extern /* Subroutine */ int bodvcd_(integer *, char *, integer *, integer 
	    *, doublereal *, ftnlen);
    integer frcode;
    extern /* Subroutine */ int cidfrm_(integer *, integer *, char *, logical 
	    *, ftnlen);
    char frname[80];
    integer trgcde;
    doublereal offobs[3], obsvec[3], tepoch, normal[3];
    static integer svtcde;
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, 
	    ftnlen);
    static integer svobsc;
    doublereal offsun[3];
    extern /* Subroutine */ int setmsg_(char *, ftnlen);
    doublereal sstate[6], sunvec[3], tstate[6];
    static char svtarg[36];
    extern /* Subroutine */ int surfnm_(doublereal *, doublereal *, 
	    doublereal *, doublereal *, doublereal *);
    extern logical return_(void);
    static char svobsr[36];
    extern /* Subroutine */ int vminus_(doublereal *, doublereal *);
    doublereal lts;

/* $ Abstract */

/*     Deprecated: This routine has been superseded by the SPICELIB */
/*     routine ILUMIN. This routine is supported for purposes of */
/*     backward compatibility only. */

/*     Find the illumination angles at a specified surface point of a */
/*     target body. */

/* $ 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 */

/*     KERNEL */
/*     NAIF_IDS */
/*     SPK */
/*     TIME */

/* $ Keywords */

/*     GEOMETRY */
/*     MOSPICE */

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

/*     This include file defines the dimension of the counter */
/*     array used by various SPICE subsystems to uniquely identify */
/*     changes in their states. */

/* $ 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. */

/* $ Parameters */

/*     CTRSIZ      is the dimension of the counter array used by */
/*                 various SPICE subsystems to uniquely identify */
/*                 changes in their states. */

/* $ Author_and_Institution */

/*     B.V. Semenov    (JPL) */

/* $ Literature_References */

/*     None. */

/* $ Version */

/* -    SPICELIB Version 1.0.0, 29-JUL-2013 (BVS) */

/* -& */

/*     End of include file. */

/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     TARGET     I   Name of target body. */
/*     ET         I   Epoch in ephemeris seconds past J2000. */
/*     ABCORR     I   Desired aberration correction. */
/*     OBSRVR     I   Name of observing body. */
/*     SPOINT     I   Body-fixed coordinates of a target surface point. */
/*     PHASE      O   Phase angle at the surface point. */
/*     SOLAR      O   Solar incidence angle at the surface point. */
/*     EMISSN     O   Emission angle at the surface point. */

/* $ Detailed_Input */

/*     TARGET         is the name of the target body.  TARGET is */
/*                    case-insensitive, and leading and trailing blanks */
/*                    in TARGET are not significant. Optionally, you may */
/*                    supply a string containing the integer ID code for */
/*                    the object.  For example both 'MOON' and '301' are */
/*                    legitimate strings that indicate the moon is the */
/*                    target body. */

/*     ET             is the epoch, specified in ephemeris seconds past */
/*                    J2000, at which the apparent illumination angles at */
/*                    the specified surface point on the target body, as */
/*                    seen from the observing body, are to be computed. */

/*     ABCORR         is the aberration correction to be used in */
/*                    computing the location and orientation of the */
/*                    target body and the location of the Sun.  Possible */
/*                    values are: */

/*                       'NONE'        No aberration correction. */

/*                       'LT'          Correct the position and */
/*                                     orientation of target body for */
/*                                     light time, and correct the */
/*                                     position of the Sun for light */
/*                                     time. */

/*                       'LT+S'        Correct the observer-target vector */
/*                                     for light time and stellar */
/*                                     aberration, correct the */
/*                                     orientation of the target body */
/*                                     for light time, and correct the */
/*                                     target-Sun vector for light time */
/*                                     and stellar aberration. */

/*                       'CN'          Converged Newtonian light time */
/*                                     correction. In solving the light */
/*                                     time equation, the 'CN' */
/*                                     correction iterates until the */
/*                                     solution converges (three */
/*                                     iterations on all supported */
/*                                     platforms). Whether the 'CN+S' */
/*                                     solution is substantially more */
/*                                     accurate than the 'LT' solution */
/*                                     depends on the geometry of the */
/*                                     participating objects and on the */
/*                                     accuracy of the input data. In */
/*                                     all cases this routine will */
/*                                     execute more slowly when a */
/*                                     converged solution is computed. */
/*                                     See the Particulars section of */
/*                                     SPKEZR for a discussion of */
/*                                     precision of light time */
/*                                     corrections. */

/*                                     Both the state and rotation of */
/*                                     the target body are corrected for */
/*                                     light time. */

/*                          'CN+S'     Converged Newtonian light time */
/*                                     correction and stellar aberration */
/*                                     correction. */

/*                                     Both the state and rotation of */
/*                                     the target body are corrected for */
/*                                     light time. */

/*     OBSRVR         is the name of the observing body, typically a */
/*                    spacecraft, the earth, or a surface point on the */
/*                    earth.  OBSRVR is case-insensitive, and leading */
/*                    and trailing blanks in OBSRVR are not significant. */
/*                    Optionally, you may supply a string containing the */
/*                    integer ID code for the object.  For example both */
/*                    'EARTH' and '399' are legitimate strings that */
/*                    indicate the earth is the observer. */

/*                    OBSRVR may be not be identical to TARGET. */

/*     SPOINT         is a surface point on the target body, expressed */
/*                    in rectangular body-fixed (body equator and prime */
/*                    meridian) coordinates.  SPOINT need not be visible */
/*                    from the observer's location at time ET. */

/* $ Detailed_Output */


/*     PHASE          is the phase angle at SPOINT, as seen from OBSRVR */
/*                    at time ET.  This is the angle between the */
/*                    SPOINT-OBSRVR vector and the SPOINT-Sun vector. */
/*                    Units are radians.  The range of  PHASE is [0, pi]. */
/*                    See Particulars below for a detailed discussion of */
/*                    the definition. */

/*     SOLAR          is the solar incidence angle at SPOINT, as seen */
/*                    from OBSRVR at time ET.  This is the angle */
/*                    between the surface normal vector at SPOINT and the */
/*                    SPOINT-Sun vector.  Units are radians.  The range */
/*                    of SOLAR is [0, pi]. See Particulars below for a */
/*                    detailed discussion of the definition. */

/*     EMISSN         is the emission angle at SPOINT, as seen from */
/*                    OBSRVR at time ET.  This is the angle between the */
/*                    surface normal vector at SPOINT and the */
/*                    SPOINT-observer vector.  Units are radians.  The */
/*                    range of EMISSN is [0, pi]. See Particulars below */
/*                    for a detailed discussion of the definition. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)  If TARGET and OBSRVR are not distinct, the error */
/*         SPICE(BODIESNOTDISTINCT) will be signaled. */

/*     2)  If no SPK (ephemeris) data are available for the observer, */
/*         target, and Sun at the time specified by ET, the error will */
/*         be diagnosed by routines called by this routine.  If light */
/*         time corrections are used, SPK data for the target body must */
/*         be available at the time ET - LT, where LT is the one-way */
/*         light time from the target to the observer at ET. */
/*         Additionally, SPK data must be available for the Sun at the */
/*         time ET - LT - LT2, where LT2 is the light time from the Sun */
/*         to the target body at time ET - LT. */

/*     3)  If PCK data defining the orientation or shape of the target */
/*         body are unavailable, the error will be diagnosed by routines */
/*         called by this routine. */

/*     4)  If no body-fixed frame is associated with the target body, */
/*         the error SPICE(NOFRAME) is signaled. */

/*     5) If name of target or observer cannot be translated to its */
/*        NAIF ID code, the error SPICE(IDCODENOTFOUND) is signaled. */

/* $ Files */

/*     No files are input to this routine.  However, ILLUM expects */
/*     that the appropriate SPK and PCK files have been loaded via */
/*     FURNSH. */

/* $ Particulars */


/*     The term "illumination angles" refers to following set of */
/*     angles: */


/*        solar incidence angle    Angle between the surface normal at */
/*                                 the specified surface point and the */
/*                                 vector from the surface point to the */
/*                                 Sun. */

/*        emission angle           Angle between the surface normal at */
/*                                 the specified surface point and the */
/*                                 vector from the surface point to the */
/*                                 observer. */

/*        phase angle              Angle between the vectors from the */
/*                                 surface point to the observing body's */
/*                                 location and from the surface point */
/*                                 to the Sun. */


/*     The diagram below illustrates the geometrical relationships */
/*     defining these angles.  The labels for the solar incidence, */
/*     emission, and phase angles are "s.i.", "e.", and "phase". */


/*                                                      * */
/*                                                     Sun */

/*                    surface normal vector */
/*                              ._                 _. */
/*                              |\                 /|  Sun vector */
/*                                \    phase      / */
/*                                 \   .    .    / */
/*                                 .            . */
/*                                   \   ___   / */
/*                              .     \/     \/ */
/*                                    _\ s.i./ */
/*                             .    /   \   / */
/*                             .   |  e. \ / */
/*         *             <--------------- *  surface point on */
/*      viewing            vector            target body */
/*      location           to viewing */
/*      (observer)         location */


/*     Note that if the target-observer vector, the target normal vector */
/*     at the surface point, and the target-sun vector are coplanar, */
/*     then phase is the sum of incidence and emission.  This is rarely */
/*     true; usually */

/*        phase angle  <  solar incidence angle + emission angle */

/*     All of the above angles can be computed using light time */
/*     corrections, light time and stellar aberration corrections, or */
/*     no aberration corrections.  The way aberration corrections */
/*     are used is described below. */

/*     Care must be used in computing light time corrections.  The */
/*     guiding principle used here is "describe what appears in */
/*     an image."  We ignore differential light time; the light times */
/*     from all points on the target to the observer are presumed to be */
/*     equal. */


/*        Observer-target body vector */
/*        --------------------------- */

/*        Let ET be the epoch at which an observation or remote */
/*        sensing measurement is made, and let ET - LT ("LT" stands */
/*        for "light time") be the epoch at which the photons received */
/*        at ET were emitted from the body (we use the term "emitted" */
/*        loosely here). */

/*        The correct observer-target vector points from the observer's */
/*        location at ET to the target body's location at ET - LT. */
/*        The target-observer vector points in the opposite direction. */

/*        Since light time corrections are not symmetric, the correct */
/*        target-observer vector CANNOT be found by computing the light */
/*        time corrected position of the observer as seen from the */
/*        target body. */


/*        Target body's orientation */
/*        ------------------------- */

/*        Using the definitions of ET and LT above, the target */
/*        body's orientation at ET - LT is used.  The surface */
/*        normal is dependent on the target body's orientation, so */
/*        the body's orientation model must be evaluated for the correct */
/*        epoch. */


/*        Target body -- Sun vector */
/*        ------------------------- */

/*        All surface features on the target body will appear in */
/*        a measurement made at ET as they were at ET-LT.  In */
/*        particular, lighting on the target body is dependent on */
/*        the apparent location of the Sun as seen from the target */
/*        body at ET-LT.  So, a second light time correction is used */
/*        in finding the apparent location of the Sun. */


/*     Stellar aberration corrections, when used, are applied as follows: */


/*        Observer-target body vector */
/*        --------------------------- */

/*        In addition to light time correction, stellar aberration is */
/*        used in computing the apparent target body position as seen */
/*        from the observer's location at time ET.  This apparent */
/*        position defines the observer-target body vector. */


/*        Target body-Sun vector */
/*        ---------------------- */

/*        The target body-Sun vector is the apparent position of the Sun, */
/*        corrected for light time and stellar aberration, as seen from */
/*        the target body at time ET-LT.  Note that the target body's */
/*        position is not affected by the stellar aberration correction */
/*        applied in finding its apparent position as seen by the */
/*        observer. */


/*     Once all of the vectors, as well as the target body's */
/*     orientation, have been computed with the proper aberration */
/*     corrections, the element of time is eliminated from the */
/*     computation.  The problem becomes a purely geometrical one, */
/*     and is described by the diagram above. */


/* $ Examples */

/*     The numerical results shown for this example may differ across */
/*     platforms.  The results depend on the SPICE kernels used as */
/*     input, the compiler and supporting libraries, and the machine */
/*     specific arithmetic implementation. */

/*     In the following example program, the file */

/*        spk_m_031103-040201_030502.bsp */

/*     is a binary SPK file containing data for Mars Global Surveyor, */
/*     Mars, and the Sun for a time interval bracketing the date */

/*         2004 JAN 1 12:00:00 UTC. */

/*     pck00007.tpc is a planetary constants kernel file containing */
/*     radii and rotation model constants.  naif0007.tls is a */
/*     leapseconds kernel. */

/*     Find the phase, solar incidence, and emission angles at the */
/*     sub-solar and sub-spacecraft points on Mars as seen from the */
/*     Mars Global Surveyor spacecraft at a specified UTC time. */
/*     Use light time and stellar aberration corrections. */

/*           PROGRAM ANGLES */
/*           IMPLICIT NONE */
/*     C */
/*     C     SPICELIB functions */
/*     C */
/*           DOUBLE PRECISION      DPR */

/*     C */
/*     C     Local parameters */
/*     C */
/*           INTEGER               NAMLEN */
/*           PARAMETER           ( NAMLEN = 32 ) */

/*           INTEGER               TIMLEN */
/*           PARAMETER           ( TIMLEN = 25 ) */

/*     C */
/*     C     Local variables */
/*     C */
/*           CHARACTER*(NAMLEN)    OBSRVR */
/*           CHARACTER*(NAMLEN)    TARGET */
/*           CHARACTER*(TIMLEN)    UTC */

/*           DOUBLE PRECISION      ALT */
/*           DOUBLE PRECISION      ET */
/*           DOUBLE PRECISION      SSCEMI */
/*           DOUBLE PRECISION      SSCPHS */
/*           DOUBLE PRECISION      SSCSOL */
/*           DOUBLE PRECISION      SSLEMI */
/*           DOUBLE PRECISION      SSLPHS */
/*           DOUBLE PRECISION      SSLSOL */
/*           DOUBLE PRECISION      SSOLPT ( 3 ) */
/*           DOUBLE PRECISION      SSCPT  ( 3 ) */

/*     C */
/*     C     Load kernel files. */
/*     C */
/*           CALL FURNSH ( 'naif0007.tls'                   ) */
/*           CALL FURNSH ( 'pck00007.tpc'                   ) */
/*           CALL FURNSH ( 'spk_m_031103-040201_030502.bsp' ) */


/*     C */
/*     C     Convert our UTC time to ephemeris seconds past J2000. */
/*     C */
/*           UTC = '2004 JAN 1 12:00:00' */

/*           CALL UTC2ET ( UTC, ET ) */

/*     C */
/*     C     Assign observer and target names.  The acronym MGS */
/*     C     indicates Mars Global Surveyor.  See NAIF_IDS for a */
/*     C     list of names recognized by SPICE. */
/*     C */
/*           TARGET = 'Mars' */
/*           OBSRVR = 'MGS' */

/*     C */
/*     C     Find the sub-solar point on the Earth as seen from */
/*     C     the MGS spacecraft at ET.  Use the "surface intercept" */
/*     C     style of sub-point definition. This makes it easy */
/*     C     to verify the solar incidence angle. */
/*     C */
/*           CALL SUBSOL ( 'Near point', TARGET,  ET, */
/*          .              'LT+S',       OBSRVR,  SSOLPT  ) */

/*     C */
/*     C     Now find the sub-spacecraft point.  Use the */
/*     C     "nearest point" definition of the sub-point */
/*     C     here---this makes it easy to verify the emission angle. */
/*     C */
/*           CALL SUBPT ( 'Near point',  TARGET,  ET, */
/*          .             'LT+S',        OBSRVR,  SSCPT,  ALT ) */

/*     C */
/*     C     Find the phase, solar incidence, and emission */
/*     C     angles at the sub-solar point on the Earth as seen */
/*     C     from Mars Observer at time ET. */
/*     C */
/*           CALL ILLUM ( TARGET, ET,     'LT+S', OBSRVR, */
/*          .             SSOLPT, SSLPHS, SSLSOL, SSLEMI ) */

/*     C */
/*     C     Do the same for the sub-spacecraft point. */
/*     C */
/*           CALL ILLUM ( TARGET, ET,     'LT+S', OBSRVR, */
/*          .             SSCPT,  SSCPHS, SSCSOL, SSCEMI ) */

/*     C */
/*     C     Convert the angles to degrees and write them out. */
/*     C */
/*           SSLPHS = DPR() * SSLPHS */
/*           SSLSOL = DPR() * SSLSOL */
/*           SSLEMI = DPR() * SSLEMI */

/*           SSCPHS = DPR() * SSCPHS */
/*           SSCSOL = DPR() * SSCSOL */
/*           SSCEMI = DPR() * SSCEMI */

/*           WRITE (*,*) ' ' */
/*           WRITE (*,*) 'UTC epoch is ', UTC */
/*           WRITE (*,*) ' ' */
/*           WRITE (*,*) 'Illumination angles at the sub-solar point:' */
/*           WRITE (*,*) ' ' */
/*           WRITE (*,*) 'Phase angle           (deg.): ', SSLPHS */
/*           WRITE (*,*) 'Solar incidence angle (deg.): ', SSLSOL */
/*           WRITE (*,*) 'Emission angle        (deg.): ', SSLEMI */
/*           WRITE (*,*) ' ' */
/*           WRITE (*,*) 'The solar incidence angle should be 0.' */
/*           WRITE (*,*) 'The emission and phase angles should be equal.' */

/*           WRITE (*,*) ' ' */
/*           WRITE (*,*) 'Illumination angles at the sub-s/c point:' */
/*           WRITE (*,*) ' ' */
/*           WRITE (*,*) 'Phase angle           (deg.): ', SSCPHS */
/*           WRITE (*,*) 'Solar incidence angle (deg.): ', SSCSOL */
/*           WRITE (*,*) 'Emission angle        (deg.): ', SSCEMI */
/*           WRITE (*,*) ' ' */
/*           WRITE (*,*) 'The emission angle should be 0.' */
/*           WRITE (*,*) 'The solar incidence and phase angles should '// */
/*          .            'be equal.' */

/*           END */


/*     When this program is executed, the output will be: */


/*        UTC epoch is 2004 JAN 1 12:00:00 */

/*        Illumination angles at the sub-solar point: */

/*        Phase angle           (deg.):   150.210714 */
/*        Solar incidence angle (deg.):   6.3735213E-15 */
/*        Emission angle        (deg.):   150.210714 */

/*        The solar incidence angle should be 0. */
/*        The emission and phase angles should be equal. */

/*        Illumination angles at the sub-s/c point: */

/*        Phase angle           (deg.):   123.398202 */
/*        Solar incidence angle (deg.):   123.398202 */
/*        Emission angle        (deg.):   6.36110936E-15 */

/*        The emission angle should be 0. */
/*        The solar incidence and phase angles should be equal. */


/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     C.H. Acton     (JPL) */
/*     B.V. Semenov   (JPL) */
/*     N.J. Bachman   (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.3.0, 04-JUL-2014 (NJB) (BVS) */

/*        Discussion of light time corrections was updated. Assertions */
/*        that converged light time corrections are unlikely to be */
/*        useful were removed. */

/*     Last update was 19-SEP-2013 (BVS) */

/*        Updated to save the input body names and ZZBODTRN state */
/*        counters and to do name-ID conversions only if the counters */
/*        have changed. */

/* -    SPICELIB Version 1.2.2, 18-MAY-2010 (BVS) */

/*        Index lines now state that this routine is deprecated. */

/* -    SPICELIB Version 1.2.1, 07-FEB-2008 (NJB) */

/*        Abstract now states that this routine is deprecated. */

/* -    SPICELIB Version 1.2.0, 23-OCT-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in VSUB calls.  Replaced call to BODVAR with call to BODVCD. */

/* -    SPICELIB Version 1.1.0, 22-JUL-2004 (NJB) */

/*        Updated to support representations of integers in the input */
/*        arguments TARGET and OBSRVR. */

/* -    SPICELIB Version 1.0.2, 27-JUL-2003 (NJB) (CHA) */

/*        Various header corrections were made.  The example program */
/*        was upgraded to use real kernels, and the program's output is */
/*        shown. */

/* -    SPICELIB Version 1.0.1, 10-JUL-2002 (NJB) */

/*        Updated Index_Entries header section. */

/* -    SPICELIB Version 1.0.0, 21-MAR-1999 (NJB) */

/*        Adapted from the MGSSPICE version dated 10-MAR-1992. */
/* -& */
/* $ Index_Entries */

/*     DEPRECATED illumination angles */
/*     DEPRECATED lighting angles */
/*     DEPRECATED phase angle */
/*     DEPRECATED solar incidence angle */
/*     DEPRECATED emission angle */

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

/* -    SPICELIB Version 1.2.0, 23-OCT-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in VSUB calls.  Replaced call to BODVAR with call to BODVCD. */

/* -    SPICELIB Version 1.1.0, 22-JUL-2004 (NJB) */

/*        Updated to support representations of integers in the */
/*        input arguments TARGET and OBSRVR:  calls to BODN2C */
/*        were replaced by calls to BODS2C. */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     Saved body name length. */


/*     Local variables */


/*     Saved name/ID item declarations. */


/*     Saved name/ID items. */


/*     Initial values. */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("ILLUM", (ftnlen)5);
    }

/*     Initialization. */

    if (first) {

/*        Initialize counters. */

	zzctruin_(svctr1);
	zzctruin_(svctr2);
	first = FALSE_;
    }

/*     Obtain integer codes for the target and observer. */

    zzbods2c_(svctr1, svtarg, &svtcde, &svfnd1, target, &trgcde, &found, (
	    ftnlen)36, target_len);
    if (! found) {
	setmsg_("The target, '#', is not a recognized name for an ephemeris "
		"object. The cause of this problem may be that you need an up"
		"dated version of the SPICE Toolkit. ", (ftnlen)155);
	errch_("#", target, (ftnlen)1, target_len);
	sigerr_("SPICE(IDCODENOTFOUND)", (ftnlen)21);
	chkout_("ILLUM", (ftnlen)5);
	return 0;
    }
    zzbods2c_(svctr2, svobsr, &svobsc, &svfnd2, obsrvr, &obscde, &found, (
	    ftnlen)36, obsrvr_len);
    if (! found) {
	setmsg_("The observer, '#', is not a recognized name for an ephemeri"
		"s object. The cause of this problem may be that you need an "
		"updated version of the SPICE Toolkit. ", (ftnlen)157);
	errch_("#", obsrvr, (ftnlen)1, obsrvr_len);
	sigerr_("SPICE(IDCODENOTFOUND)", (ftnlen)21);
	chkout_("ILLUM", (ftnlen)5);
	return 0;
    }

/*     The observer and target must be distinct. */

    if (trgcde == obscde) {
	setmsg_("Target is #; observer is #.", (ftnlen)27);
	errch_("#", target, (ftnlen)1, target_len);
	errch_("#", obsrvr, (ftnlen)1, obsrvr_len);
	sigerr_("SPICE(BODIESNOTDISTINCT)", (ftnlen)24);
	chkout_("ILLUM", (ftnlen)5);
	return 0;
    }

/*     Find the name of the body-fixed frame associated with the */
/*     target body.  We'll want the state of the target relative to */
/*     the observer in this body-fixed frame. */

    cidfrm_(&trgcde, &frcode, frname, &found, (ftnlen)80);
    if (! found) {
	setmsg_("No body-fixed frame is associated with target body #; a fra"
		"me kernel must be loaded to make this association.  Consult "
		"the FRAMES Required Reading for details.", (ftnlen)159);
	errch_("#", target, (ftnlen)1, target_len);
	sigerr_("SPICE(NOFRAME)", (ftnlen)14);
	chkout_("ILLUM", (ftnlen)5);
	return 0;
    }

/*     Find the body-fixed state of the target as seen from the observer */
/*     at ET.  The appropriate aberration corrections will be used in */
/*     evaluating this state. */

    spkez_(&trgcde, et, frname, abcorr, &obscde, tstate, &lt, (ftnlen)80, 
	    abcorr_len);

/*     Determine the epoch to be used in computing the target-Sun vector. */

    if (eqstr_(abcorr, "NONE", abcorr_len, (ftnlen)4)) {
	tepoch = *et;
    } else {
	tepoch = *et - lt;
    }

/*     Find the body-fixed state of the Sun as seen from the target at */
/*     TEPOCH. */

    spkez_(&c__10, &tepoch, frname, abcorr, &trgcde, sstate, &lts, (ftnlen)80,
	     abcorr_len);

/*     Grab the position portions of the states (the first three */
/*     elements of each state).  Negate the observer-target vector, */
/*     since the vector required for the illumination angle */
/*     computation is the target-observer vector.  The vectors we've */
/*     found point from the target body center to the observer and */
/*     Sun, and already take light time corrections into account. */

    vminus_(tstate, obsvec);
    vequ_(sstate, sunvec);

/*     Now we'll modify target-observer and target-Sun vectors to */
/*     take into account the offset between the target center and the */
/*     surface point of interest; we want the vectors to point from */
/*     the surface point to the observer and Sun respectively. */

    vsub_(obsvec, spoint, offobs);
    vsub_(sunvec, spoint, offsun);

/*     Find the surface normal at SPOINT.  We'll need the radii of the */
/*     target body. */

    bodvcd_(&trgcde, "RADII", &c__3, &n, radii, (ftnlen)5);
    surfnm_(radii, &radii[1], &radii[2], spoint, normal);

/*     Find the illumination angles.  VSEP will give us angular */
/*     separation in radians. */

    *phase = vsep_(offsun, offobs);
    *solar = vsep_(normal, offsun);
    *emissn = vsep_(normal, offobs);
    chkout_("ILLUM", (ftnlen)5);
    return 0;
} /* illum_ */
Beispiel #3
0
/* $Procedure      SUBPT ( Sub-observer point ) */
/* Subroutine */ int subpt_(char *method, char *target, doublereal *et, char *
	abcorr, char *obsrvr, doublereal *spoint, doublereal *alt, ftnlen 
	method_len, ftnlen target_len, ftnlen abcorr_len, ftnlen obsrvr_len)
{
    /* Initialized data */

    static doublereal origin[3] = { 0.,0.,0. };

    doublereal radii[3];
    extern /* Subroutine */ int chkin_(char *, ftnlen), errch_(char *, char *,
	     ftnlen, ftnlen);
    logical found;
    extern doublereal vdist_(doublereal *, doublereal *);
    extern /* Subroutine */ int spkez_(integer *, doublereal *, char *, char *
	    , integer *, doublereal *, doublereal *, ftnlen, ftnlen);
    extern logical eqstr_(char *, char *, ftnlen, ftnlen);
    extern /* Subroutine */ int bods2c_(char *, integer *, logical *, ftnlen);
    integer obscde;
    doublereal lt;
    extern /* Subroutine */ int bodvcd_(integer *, char *, integer *, integer 
	    *, doublereal *, ftnlen);
    integer frcode;
    extern /* Subroutine */ int cidfrm_(integer *, integer *, char *, logical 
	    *, ftnlen);
    integer nradii;
    char frname[80];
    integer trgcde;
    extern /* Subroutine */ int nearpt_(doublereal *, doublereal *, 
	    doublereal *, doublereal *, doublereal *, doublereal *), sigerr_(
	    char *, ftnlen), chkout_(char *, ftnlen), setmsg_(char *, ftnlen);
    doublereal tstate[6];
    extern logical return_(void);
    extern /* Subroutine */ int vminus_(doublereal *, doublereal *), surfpt_(
	    doublereal *, doublereal *, doublereal *, doublereal *, 
	    doublereal *, doublereal *, logical *);
    doublereal pos[3];

/* $ Abstract */

/*     Deprecated: This routine has been superseded by the SPICELIB */
/*     routine SUBPNT. This routine is supported for purposes of */
/*     backward compatibility only. */

/*     Compute the rectangular coordinates of the sub-observer point on */
/*     a target body at a particular epoch, optionally corrected for */
/*     planetary (light time) and stellar aberration.  Return these */
/*     coordinates expressed in the body-fixed frame associated with the */
/*     target body.  Also, return the observer's altitude above the */
/*     target body. */

/* $ 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 */

/*     FRAMES */
/*     PCK */
/*     SPK */
/*     TIME */

/* $ Keywords */

/*     GEOMETRY */

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

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     METHOD     I   Computation method. */
/*     TARGET     I   Name of target body. */
/*     ET         I   Epoch in ephemeris seconds past J2000 TDB. */
/*     ABCORR     I   Aberration correction. */
/*     OBSRVR     I   Name of observing body. */
/*     SPOINT     O   Sub-observer point on the target body. */
/*     ALT        O   Altitude of the observer above the target body. */

/* $ Detailed_Input */

/*     METHOD      is a short string specifying the computation method */
/*                 to be used.  The choices are: */

/*                    'Near point'       The sub-observer point is */
/*                                       defined as the nearest point on */
/*                                       the target relative to the */
/*                                       observer. */

/*                    'Intercept'        The sub-observer point is */
/*                                       defined as the target surface */
/*                                       intercept of the line */
/*                                       containing the observer and the */
/*                                       target's center. */

/*                 In both cases, the intercept computation treats the */
/*                 surface of the target body as a triaxial ellipsoid. */
/*                 The ellipsoid's radii must be available in the kernel */
/*                 pool. */

/*                 Neither case nor white space are significant in */
/*                 METHOD.  For example, the string ' NEARPOINT' is */
/*                 valid. */


/*     TARGET      is the name of a target body.  Optionally, you may */
/*                 supply the integer ID code for the object as */
/*                 an integer string.  For example both 'MOON' and */
/*                 '301' are legitimate strings that indicate the */
/*                 moon is the target body. This routine assumes */
/*                 that this body is modeled by a tri-axial ellipsoid, */
/*                 and that a PCK file containing its radii has been */
/*                 loaded into the kernel pool via FURNSH. */

/*     ET          is the epoch in ephemeris seconds past J2000 at which */
/*                 the sub-observer point on the target body is to be */
/*                 computed. */


/*     ABCORR      indicates the aberration corrections to be applied */
/*                 when computing the observer-target state.  ABCORR */
/*                 may be any of the following. */

/*                    'NONE'     Apply no correction. Return the */
/*                               geometric sub-observer point on the */
/*                               target body. */

/*                    'LT'       Correct for planetary (light time) */
/*                               aberration.  Both the state and rotation */
/*                               of the target body are corrected for */
/*                               light time. */

/*                    'LT+S'     Correct for planetary (light time) and */
/*                               stellar aberrations. Both the state and */
/*                               rotation of the target body are */
/*                               corrected for light time. */

/*                    'CN'       Converged Newtonian light time */
/*                               corrections.  This is the same as LT */
/*                               corrections but with further iterations */
/*                               to a converged Newtonian light time */
/*                               solution.  Given that relativistic */
/*                               effects may be as large as the higher */
/*                               accuracy achieved by this computation, */
/*                               this is correction is seldom worth the */
/*                               additional computations required unless */
/*                               the user incorporates additional */
/*                               relativistic corrections.  Both the */
/*                               state and rotation of the target body */
/*                               are corrected for light time. */

/*                    'CN+S'     Converged Newtonian light time */
/*                               corrections and stellar aberration. */
/*                               Both the state and rotation of the */
/*                               target body are corrected for light */
/*                               time. */

/*     OBSRVR      is the name of the observing body.  This is typically */
/*                 a spacecraft, the earth, or a surface point on the */
/*                 earth. Optionally, you  may supply the ID code of */
/*                 the object as an integer string. For example, both */
/*                 'EARTH' and '399' are legitimate strings to supply */
/*                 to indicate the observer is Earth. */

/* $ Detailed_Output */

/*     SPOINT      is the sub-observer point on the target body at ET */
/*                 expressed relative to the body-fixed frame of the */
/*                 target body. */

/*                 The sub-observer point is defined either as the point */
/*                 on the target body that is closest to the observer, */
/*                 or the target surface intercept of the line from the */
/*                 observer to the target's center; the input argument */
/*                 METHOD selects the definition to be used. */

/*                 The body-fixed frame, which is time-dependent, is */
/*                 evaluated at ET if ABCORR is 'NONE'; otherwise the */
/*                 frame is evaluated at ET-LT, where LT is the one-way */
/*                 light time from target to observer. */

/*                 The state of the target body is corrected for */
/*                 aberration as specified by ABCORR; the corrected */
/*                 state is used in the geometric computation.  As */
/*                 indicated above, the rotation of the target is */
/*                 retarded by one-way light time if ABCORR specifies */
/*                 that light time correction is to be done. */


/*     ALT         is the "altitude" of the observer above the target */
/*                 body.  When METHOD specifies a "near point" */
/*                 computation, ALT is truly altitude in the standard */
/*                 geometric sense:  the length of a segment dropped from */
/*                 the observer to the target's surface, such that the */
/*                 segment is perpendicular to the surface at the */
/*                 contact point SPOINT. */

/*                 When METHOD specifies an "intercept" computation, ALT */
/*                 is still the length of the segment from the observer */
/*                 to the surface point SPOINT, but this segment in */
/*                 general is not perpendicular to the surface. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     If any of the listed errors occur, the output arguments are */
/*     left unchanged. */


/*     1) If the input argument METHOD is not recognized, the error */
/*        SPICE(DUBIOUSMETHOD) is signaled. */

/*     2) If either of the input body names TARGET or OBSRVR cannot be */
/*        mapped to NAIF integer codes, the error SPICE(IDCODENOTFOUND) */
/*        is signaled. */

/*     3) If OBSRVR and TARGET map to the same NAIF integer ID codes, the */
/*        error SPICE(BODIESNOTDISTINCT) is signaled. */

/*     4) If frame definition data enabling the evaluation of the state */
/*        of the target relative to the observer in target body-fixed */
/*        coordinates have not been loaded prior to calling SUBPT, the */
/*        error will be diagnosed and signaled by a routine in the call */
/*        tree of this routine. */

/*     5) If the specified aberration correction is not recognized, the */
/*        error will be diagnosed and signaled by a routine in the call */
/*        tree of this routine. */

/*     6) If insufficient ephemeris data have been loaded prior to */
/*        calling SUBPT, the error will be diagnosed and signaled by a */
/*        routine in the call tree of this routine. */

/*     7) If the triaxial radii of the target body have not been loaded */
/*        into the kernel pool prior to calling SUBPT, the error will be */
/*        diagnosed and signaled by a routine in the call tree of this */
/*        routine. */

/*     8) The target must be an extended body:  if any of the radii of */
/*        the target body are non-positive, the error will be diagnosed */
/*        and signaled by routines in the call tree of this routine. */

/*     9) If PCK data supplying a rotation model for the target body */
/*        have not been loaded prior to calling SUBPT, the error will be */
/*        diagnosed and signaled by a routine in the call tree of this */
/*        routine. */

/* $ Files */

/*     Appropriate SPK, PCK, and frame kernels must be loaded */
/*     prior by the calling program before this routine is called. */

/*     The following data are required: */

/*        - SPK data:  ephemeris data for target and observer must be */
/*          loaded.  If aberration corrections are used, the states of */
/*          target and observer relative to the solar system barycenter */
/*          must be calculable from the available ephemeris data. */
/*          Typically ephemeris data are made available by loading one */
/*          or more SPK files via FURNSH. */

/*        - PCK data:  triaxial radii for the target body must be loaded */
/*          into the kernel pool.  Typically this is done by loading a */
/*          text PCK file via FURNSH. */

/*        - Further PCK data:  rotation data for the target body must */
/*          be loaded.  These may be provided in a text or binary PCK */
/*          file.  Either type of file may be loaded via FURNSH. */

/*        - Frame data:  if a frame definition is required to convert */
/*          the observer and target states to the body-fixed frame of */
/*          the target, that definition must be available in the kernel */
/*          pool.  Typically the definition is supplied by loading a */
/*          frame kernel via FURNSH. */

/*     In all cases, kernel data are normally loaded once per program */
/*     run, NOT every time this routine is called. */

/* $ Particulars */

/*     SUBPT computes the sub-observer point on a target body. */
/*     (The sub-observer point is commonly called the sub-spacecraft */
/*     point when the observer is a spacecraft.)  SUBPT also */
/*     determines the altitude of the observer above the target body. */

/*     There are two different popular ways to define the sub-observer */
/*     point:  "nearest point on target to observer" or "target surface */
/*     intercept of line containing observer and target."  These */
/*     coincide when the target is spherical and generally are distinct */
/*     otherwise. */

/*     When comparing sub-point computations with results from sources */
/*     other than SPICE, it's essential to make sure the same geometric */
/*     definitions are used. */

/* $ Examples */

/*     The numerical results shown for this example may differ across */
/*     platforms.  The results depend on the SPICE kernels used as */
/*     input, the compiler and supporting libraries, and the machine */
/*     specific arithmetic implementation. */

/*     In the following example program, the file */

/*        spk_m_031103-040201_030502.bsp */

/*     is a binary SPK file containing data for Mars Global Surveyor, */
/*     Mars, and the Sun for a time interval bracketing the date */

/*         2004 JAN 1 12:00:00 UTC. */

/*     pck00007.tpc is a planetary constants kernel file containing */
/*     radii and rotation model constants.  naif0007.tls is a */
/*     leapseconds kernel. */

/*     Find the sub-observer point of the Mars Global Surveyor (MGS) */
/*     spacecraft on Mars for a specified time.  Perform the computation */
/*     twice, using both the "intercept" and "near point" options. */


/*           IMPLICIT NONE */

/*           CHARACTER*25          METHOD ( 2 ) */

/*           INTEGER               I */

/*           DOUBLE PRECISION      ALT */
/*           DOUBLE PRECISION      DPR */
/*           DOUBLE PRECISION      ET */
/*           DOUBLE PRECISION      LAT */
/*           DOUBLE PRECISION      LON */
/*           DOUBLE PRECISION      RADIUS */
/*           DOUBLE PRECISION      SPOINT ( 3 ) */

/*           DATA                  METHOD / 'Intercept', 'Near point' / */

/*     C */
/*     C     Load kernel files. */
/*     C */
/*           CALL FURNSH ( 'naif0007.tls'                   ) */
/*           CALL FURNSH ( 'pck00007.tpc'                   ) */
/*           CALL FURNSH ( 'spk_m_031103-040201_030502.bsp' ) */

/*     C */
/*     C     Convert the UTC request time to ET (seconds past */
/*     C     J2000, TDB). */
/*     C */
/*           CALL STR2ET ( '2004 JAN 1 12:00:00', ET ) */

/*     C */
/*     C     Compute sub-spacecraft point using light time and stellar */
/*     C     aberration corrections.  Use the "target surface intercept" */
/*     C     definition of sub-spacecraft point on the first loop */
/*     C     iteration, and use the "near point" definition on the */
/*     C     second. */
/*     C */
/*           DO I = 1, 2 */

/*              CALL SUBPT ( METHOD(I), */
/*          .               'MARS',     ET,     'LT+S', */
/*          .               'MGS',      SPOINT,  ALT    ) */

/*     C */
/*     C        Convert rectangular coordinates to planetocentric */
/*     C        latitude and longitude.  Convert radians to degrees. */
/*     C */
/*              CALL RECLAT ( SPOINT, RADIUS, LON, LAT  ) */

/*              LON = LON * DPR () */
/*              LAT = LAT * DPR () */

/*     C */
/*     C        Write the results. */
/*     C */
/*              WRITE (*,*) ' ' */
/*              WRITE (*,*) 'Computation method: ', METHOD(I) */
/*              WRITE (*,*) ' ' */
/*              WRITE (*,*) '  Radius                   (km)  = ', RADIUS */
/*              WRITE (*,*) '  Planetocentric Latitude  (deg) = ', LAT */
/*              WRITE (*,*) '  Planetocentric Longitude (deg) = ', LON */
/*              WRITE (*,*) '  Altitude                 (km)  = ', ALT */
/*              WRITE (*,*) ' ' */

/*           END DO */

/*           END */


/*     When this program is executed, the output will be: */


/*        Computation method: Intercept */

/*          Radius                   (km)  =   3387.97077 */
/*          Planetocentric Latitude  (deg) =  -39.7022724 */
/*          Planetocentric Longitude (deg) =  -159.226663 */
/*          Altitude                 (km)  =   373.173506 */


/*        Computation method: Near point */

/*          Radius                   (km)  =   3387.9845 */
/*          Planetocentric Latitude  (deg) =  -39.6659329 */
/*          Planetocentric Longitude (deg) =  -159.226663 */
/*          Altitude                 (km)  =   373.166636 */


/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     C.H. Acton     (JPL) */
/*     N.J. Bachman   (JPL) */
/*     J.E. McLean    (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.2.3, 18-MAY-2010 (BVS) */

/*        Index line now states that this routine is deprecated. */

/* -    SPICELIB Version 1.2.2, 17-MAR-2009 (EDW) */

/*        Typo correction in Required_Reading, changed */
/*        FRAME to FRAMES. */

/* -    SPICELIB Version 1.2.1, 07-FEB-2008 (NJB) */

/*        Abstract now states that this routine is deprecated. */

/* -    SPICELIB Version 1.2.0, 24-OCT-2005 (NJB) */

/*        Replaced call to BODVAR with call to BODVCD. */

/* -    SPICELIB Version 1.1.0, 21-JUL-2004 (EDW) */

/*        Changed BODN2C call to BODS2C giving the routine */
/*        the capability to accept string representations of */
/*        interger IDs for TARGET and OBSRVR. */

/* -    SPICELIB Version 1.0.1, 27-JUL-2003 (NJB) (CHA) */

/*        Various header corrections were made.  The example program */
/*        was upgraded to use real kernels, and the program's output is */
/*        shown. */

/* -    SPICELIB Version 1.0.0, 03-SEP-1999 (NJB) (JEM) */

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

/*     DEPRECATED sub-observer point */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     Local variables */


/*     Saved variables */


/*     Initial values */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("SUBPT", (ftnlen)5);
    }

/*     Obtain integer codes for the target and observer. */

/*     Target... */

    bods2c_(target, &trgcde, &found, target_len);
    if (! found) {
	setmsg_("The target, '#', is not a recognized name for an ephemeris "
		"object. The cause of this problem may be that you need an up"
		"dated version of the SPICE Toolkit. ", (ftnlen)155);
	errch_("#", target, (ftnlen)1, target_len);
	sigerr_("SPICE(IDCODENOTFOUND)", (ftnlen)21);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }

/*     ...observer. */

    bods2c_(obsrvr, &obscde, &found, obsrvr_len);
    if (! found) {
	setmsg_("The observer, '#', is not a recognized name for an ephemeri"
		"s object. The cause of this problem may be that you need an "
		"updated version of the SPICE Toolkit. ", (ftnlen)157);
	errch_("#", obsrvr, (ftnlen)1, obsrvr_len);
	sigerr_("SPICE(IDCODENOTFOUND)", (ftnlen)21);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }

/*     Check the input body codes.  If they are equal, signal */
/*     an error. */

    if (obscde == trgcde) {
	setmsg_("In computing the sub-observer point, the observing body and"
		" target body are the same. Both are #.", (ftnlen)97);
	errch_("#", obsrvr, (ftnlen)1, obsrvr_len);
	sigerr_("SPICE(BODIESNOTDISTINCT)", (ftnlen)24);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }

/*     Get the radii of the target body from the kernel pool. */

    bodvcd_(&trgcde, "RADII", &c__3, &nradii, radii, (ftnlen)5);

/*     Find the name of the body-fixed frame associated with the */
/*     target body.  We'll want the state of the target relative to */
/*     the observer in this body-fixed frame. */

    cidfrm_(&trgcde, &frcode, frname, &found, (ftnlen)80);
    if (! found) {
	setmsg_("No body-fixed frame is associated with target body #; a fra"
		"me kernel must be loaded to make this association.  Consult "
		"the FRAMES Required Reading for details.", (ftnlen)159);
	errch_("#", target, (ftnlen)1, target_len);
	sigerr_("SPICE(NOFRAME)", (ftnlen)14);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }

/*     Determine the position of the observer in target */
/*     body-fixed coordinates. */

/*         -  Call SPKEZR to compute the position of the target */
/*            body as seen from the observing body and the light time */
/*            (LT) between them.  SPKEZR returns a state which is */
/*            the position and velocity, but we'll only use the position */
/*            which is the first three elements.  We request that the */
/*            coordinates of POS be returned relative to the body fixed */
/*            reference frame associated with the target body, using */
/*            aberration corrections specified by the input argument */
/*            ABCORR. */

/*         -  Call VMINUS to negate the direction of the vector (POS) */
/*            so it will be the position of the observer as seen from */
/*            the target body in target body fixed coordinates. */

/*            Note that this result is not the same as the result of */
/*            calling SPKEZR with the target and observer switched.  We */
/*            computed the vector FROM the observer TO the target in */
/*            order to get the proper light time and stellar aberration */
/*            corrections (if requested).  Now we need the inverse of */
/*            that corrected vector in order to compute the sub-point. */

    spkez_(&trgcde, et, frname, abcorr, &obscde, tstate, &lt, (ftnlen)80, 
	    abcorr_len);

/*     Negate the target's state to obtain the position of the observer */
/*     relative to the target. */

    vminus_(tstate, pos);

/*     Find the sub-point and "altitude" (distance from observer to */
/*     sub-point) using the specified geometric definition. */

    if (eqstr_(method, "Near point", method_len, (ftnlen)10)) {

/*        Locate the nearest point to the observer on the target. */

	nearpt_(pos, radii, &radii[1], &radii[2], spoint, alt);
    } else if (eqstr_(method, "Intercept", method_len, (ftnlen)9)) {
	surfpt_(origin, pos, radii, &radii[1], &radii[2], spoint, &found);

/*        Since the line in question passes through the center of the */
/*        target, there will always be a surface intercept.  So we should */
/*        never have FOUND = .FALSE. */

	if (! found) {
	    setmsg_("Call to SURFPT returned FOUND=FALSE even though vertex "
		    "of ray is at target center. This indicates a bug. Please"
		    " contact NAIF.", (ftnlen)125);
	    sigerr_("SPICE(BUG)", (ftnlen)10);
	    chkout_("SUBPT", (ftnlen)5);
	    return 0;
	}

/*        SURFPT doesn't compute altitude, so do it here. */

	*alt = vdist_(pos, spoint);
    } else {
	setmsg_("The computation method # was not recognized. Allowed values"
		" are \"Near point\" and \"Intercept.\"", (ftnlen)93);
	errch_("#", method, (ftnlen)1, method_len);
	sigerr_("SPICE(DUBIOUSMETHOD)", (ftnlen)20);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }
    chkout_("SUBPT", (ftnlen)5);
    return 0;
} /* subpt_ */
Beispiel #4
0
/* $Procedure ZZEDTERM ( Ellipsoid terminator ) */
/* Subroutine */ int zzedterm_(char *type__, doublereal *a, doublereal *b, 
	doublereal *c__, doublereal *srcrad, doublereal *srcpos, integer *
	npts, doublereal *trmpts, ftnlen type_len)
{
    /* System generated locals */
    integer trmpts_dim2, i__1, i__2;
    doublereal d__1, d__2, d__3;

    /* Builtin functions */
    integer s_cmp(char *, char *, ftnlen, ftnlen);
    double asin(doublereal);
    integer s_rnge(char *, integer, char *, integer);
    double d_sign(doublereal *, doublereal *);

    /* Local variables */
    extern /* Subroutine */ int vadd_(doublereal *, doublereal *, doublereal *
	    );
    doublereal rmin, rmax;
    extern /* Subroutine */ int vscl_(doublereal *, doublereal *, doublereal *
	    );
    extern doublereal vdot_(doublereal *, doublereal *), vsep_(doublereal *, 
	    doublereal *);
    integer nitr;
    extern /* Subroutine */ int vsub_(doublereal *, doublereal *, doublereal *
	    ), vequ_(doublereal *, doublereal *);
    doublereal d__, e[3];
    integer i__;
    doublereal s, angle, v[3], x[3], delta, y[3], z__[3], inang;
    extern /* Subroutine */ int chkin_(char *, ftnlen), frame_(doublereal *, 
	    doublereal *, doublereal *);
    doublereal plane[4];
    extern /* Subroutine */ int ucase_(char *, char *, ftnlen, ftnlen), 
	    errch_(char *, char *, ftnlen, ftnlen), vpack_(doublereal *, 
	    doublereal *, doublereal *, doublereal *);
    doublereal theta;
    extern /* Subroutine */ int errdp_(char *, doublereal *, ftnlen);
    doublereal trans[9]	/* was [3][3] */, srcpt[3], vtemp[3];
    extern doublereal vnorm_(doublereal *), twopi_(void);
    extern /* Subroutine */ int ljust_(char *, char *, ftnlen, ftnlen), 
	    pl2nvc_(doublereal *, doublereal *, doublereal *);
    doublereal lambda;
    extern /* Subroutine */ int nvp2pl_(doublereal *, doublereal *, 
	    doublereal *);
    extern doublereal halfpi_(void);
    doublereal minang, minrad, maxang, maxrad;
    extern /* Subroutine */ int latrec_(doublereal *, doublereal *, 
	    doublereal *, doublereal *);
    doublereal angerr;
    logical umbral;
    extern doublereal touchd_(doublereal *);
    doublereal offset[3], prvdif;
    extern /* Subroutine */ int sigerr_(char *, ftnlen);
    doublereal outang, plcons, prvang;
    extern /* Subroutine */ int chkout_(char *, ftnlen), setmsg_(char *, 
	    ftnlen), errint_(char *, integer *, ftnlen);
    char loctyp[50];
    extern logical return_(void);
    extern /* Subroutine */ int vminus_(doublereal *, doublereal *);
    doublereal dir[3];
    extern /* Subroutine */ int mxv_(doublereal *, doublereal *, doublereal *)
	    ;
    doublereal vtx[3];

/* $ Abstract */

/*     SPICE Private routine intended solely for the support of SPICE */
/*     routines.  Users should not call this routine directly due */
/*     to the volatile nature of this routine. */

/*     Compute a set of points on the umbral or penumbral terminator of */
/*     a specified ellipsoid, given a spherical light source. */

/* $ 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 */

/*     ELLIPSES */

/* $ Keywords */

/*     BODY */
/*     GEOMETRY */
/*     MATH */

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

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     TYPE       I   Terminator type. */
/*     A          I   Length of ellipsoid semi-axis lying on the x-axis. */
/*     B          I   Length of ellipsoid semi-axis lying on the y-axis. */
/*     C          I   Length of ellipsoid semi-axis lying on the z-axis. */
/*     SRCRAD     I   Radius of light source. */
/*     SRCPOS     I   Position of center of light source. */
/*     NPTS       I   Number of points in terminator point set. */
/*     TRMPTS     O   Terminator point set. */

/* $ Detailed_Input */

/*     TYPE           is a string indicating the type of terminator to */
/*                    compute:  umbral or penumbral.  The umbral */
/*                    terminator is the boundary of the portion of the */
/*                    ellipsoid surface in total shadow.  The penumbral */
/*                    terminator is the boundary of the portion of the */
/*                    surface that is completely illuminated.  Possible */
/*                    values of TYPE are */

/*                       'UMBRAL' */
/*                       'PENUMBRAL' */

/*                    Case and leading or trailing blanks in TYPE are */
/*                    not significant. */

/*     A, */
/*     B, */
/*     C              are the lengths of the semi-axes of a triaxial */
/*                    ellipsoid.  The ellipsoid is centered at the */
/*                    origin and oriented so that its axes lie on the */
/*                    x, y and z axes.  A, B, and C are the lengths of */
/*                    the semi-axes that point in the x, y, and z */
/*                    directions respectively. */

/*                    Length units associated with A, B, and C must */
/*                    match those associated with SRCRAD, SRCPOS, */
/*                    and the output TRMPTS. */

/*     SRCRAD         is the radius of the spherical light source. */

/*     SRCPOS         is the position of the center of the light source */
/*                    relative to the center of the ellipsoid. */

/*     NPTS           is the number of terminator points to compute. */


/* $ Detailed_Output */

/*     TRMPTS         is an array of points on the umbral or penumbral */
/*                    terminator of the ellipsoid, as specified by the */
/*                    input argument TYPE.  The Ith point is contained */
/*                    in the array elements */

/*                        TRMPTS(J,I),  J = 1, 2, 3 */

/*                    The terminator points are expressed in the */
/*                    body-fixed reference frame associated with the */
/*                    ellipsoid.  Units are those associated with */
/*                    the input axis lengths. */

/*                    Each terminator point is the point of tangency of */
/*                    a plane that is also tangent to the light source. */
/*                    These associated points of tangency on the light */
/*                    source have uniform distribution in longitude when */
/*                    expressed in a cylindrical coordinate system whose */
/*                    Z-axis is SRCPOS.  The magnitude of the separation */
/*                    in longitude between these tangency points on the */
/*                    light source is */

/*                       2*Pi / NPTS */

/*                    If the target is spherical, the terminator points */
/*                    also are uniformly distributed in longitude in the */
/*                    cylindrical system described above.  If the target */
/*                    is non-spherical, the longitude distribution of */
/*                    the points generally is not uniform. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)  If the terminator type is not recognized, the error */
/*         SPICE(NOTSUPPORTED) is signaled. */

/*     2)  If the set size NPTS is not at least 1, the error */
/*         SPICE(INVALIDSIZE) is signaled. */

/*     3)  If any of the ellipsoid's semi-axis lengths is non-positive, */
/*         the error SPICE(INVALIDAXISLENGTH) is signaled. */

/*     4)  If the light source has non-positive radius, the error */
/*         SPICE(INVALIDRADIUS) is signaled. */

/*     5)  If the light source intersects the smallest sphere */
/*         centered at the origin and containing the ellipsoid, the */
/*         error SPICE(OBJECTSTOOCLOSE) is signaled. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     This routine models the boundaries of shadow regions on an */
/*     ellipsoid "illuminated" by a spherical light source.  Light rays */
/*     are assumed to travel along straight lines; refraction is not */
/*     modeled. */

/*     Points on the ellipsoid at which the entire cap of the light */
/*     source is visible are considered to be completely illuminated. */
/*     Points on the ellipsoid at which some portion (or all) of the cap */
/*     of the light source are blocked are considered to be in partial */
/*     (or total) shadow. */

/*     In this routine, we use the term "umbral terminator" to denote */
/*     the curve ususally called the "terminator":  this curve is the */
/*     boundary of the portion of the surface that lies in total shadow. */
/*     We use the term "penumbral terminator" to denote the boundary of */
/*     the completely illuminated portion of the surface. */

/*     In general, the terminator on an ellipsoid is a more complicated */
/*     curve than the limb (which is always an ellipse).  Aside from */
/*     various special cases, the terminator does not lie in a plane. */

/*     However, the condition for a point X on the ellipsoid to lie on */
/*     the terminator is simple:  a plane tangent to the ellipsoid at X */
/*     must also be tangent to the light source.  If this tangent plane */
/*     does not intersect the vector from the center of the ellipsoid to */
/*     the center of the light source, then X lies on the umbral */
/*     terminator; otherwise X lies on the penumbral terminator. */

/* $ Examples */

/*     See the SPICELIB routine EDTERM. */

/* $ Restrictions */

/*     This is a private SPICELIB routine.  User applications should not */
/*     call this routine. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

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

/* $ Version */

/* -    SPICELIB Version 1.0.0, 03-FEB-2007 (NJB) */

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

/*     find terminator on ellipsoid */
/*     find umbral terminator on ellipsoid */
/*     find penumbral terminator on ellipsoid */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     Local variables */


/*     Standard SPICELIB error handling. */

    /* Parameter adjustments */
    trmpts_dim2 = *npts;

    /* Function Body */
    if (return_()) {
	return 0;
    }
    chkin_("ZZEDTERM", (ftnlen)8);

/*     Check the terminator type. */

    ljust_(type__, loctyp, type_len, (ftnlen)50);
    ucase_(loctyp, loctyp, (ftnlen)50, (ftnlen)50);
    if (s_cmp(loctyp, "UMBRAL", (ftnlen)50, (ftnlen)6) == 0) {
	umbral = TRUE_;
    } else if (s_cmp(loctyp, "PENUMBRAL", (ftnlen)50, (ftnlen)9) == 0) {
	umbral = FALSE_;
    } else {
	setmsg_("Terminator type must be UMBRAL or PENUMBRAL but was actuall"
		"y #.", (ftnlen)63);
	errch_("#", type__, (ftnlen)1, type_len);
	sigerr_("SPICE(NOTSUPPORTED)", (ftnlen)19);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     Check the terminator set dimension. */

    if (*npts < 1) {
	setmsg_("Set must contain at least one point; NPTS  = #.", (ftnlen)47)
		;
	errint_("#", npts, (ftnlen)1);
	sigerr_("SPICE(INVALIDSIZE)", (ftnlen)18);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     The ellipsoid semi-axes must have positive length. */

    if (*a <= 0. || *b <= 0. || *c__ <= 0.) {
	setmsg_("Semi-axis lengths:  A = #, B = #, C = #. ", (ftnlen)41);
	errdp_("#", a, (ftnlen)1);
	errdp_("#", b, (ftnlen)1);
	errdp_("#", c__, (ftnlen)1);
	sigerr_("SPICE(INVALIDAXISLENGTH)", (ftnlen)24);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     Check the input light source radius. */

    if (*srcrad <= 0.) {
	setmsg_("Light source must have positive radius; actual radius was #."
		, (ftnlen)60);
	errdp_("#", srcrad, (ftnlen)1);
	sigerr_("SPICE(INVALIDRADIUS)", (ftnlen)20);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     The light source must not intersect the outer bounding */
/*     sphere of the ellipsoid. */

    d__ = vnorm_(srcpos);
/* Computing MAX */
    d__1 = max(*a,*b);
    rmax = max(d__1,*c__);
/* Computing MIN */
    d__1 = min(*a,*b);
    rmin = min(d__1,*c__);
    if (*srcrad + rmax >= d__) {

/*        The light source is too close. */

	setmsg_("Light source intersects outer bounding sphere of the ellips"
		"oid.  Light source radius = #; ellipsoid's longest axis = #;"
		" sum = #; distance between centers = #.", (ftnlen)158);
	errdp_("#", srcrad, (ftnlen)1);
	errdp_("#", &rmax, (ftnlen)1);
	d__1 = *srcrad + rmax;
	errdp_("#", &d__1, (ftnlen)1);
	errdp_("#", &d__, (ftnlen)1);
	sigerr_("SPICE(OBJECTSTOOCLOSE)", (ftnlen)22);
	chkout_("ZZEDTERM", (ftnlen)8);
	return 0;
    }

/*     Find bounds on the angular size of the target as seen */
/*     from the source. */

/* Computing MIN */
    d__1 = rmax / d__;
    minang = asin((min(d__1,1.)));
/* Computing MIN */
    d__1 = rmin / d__;
    maxang = asin((min(d__1,1.)));

/*     Let the inverse of the ellipsoid-light source vector be the */
/*     Z-axis of a frame we'll use to generate the terminator set. */

    vminus_(srcpos, z__);
    frame_(z__, x, y);

/*     Create the rotation matrix required to convert vectors */
/*     from the source-centered frame back to the target body-fixed */
/*     frame. */

    vequ_(x, trans);
    vequ_(y, &trans[3]);
    vequ_(z__, &trans[6]);

/*     Find the maximum and minimum target radii. */

/* Computing MAX */
    d__1 = max(*a,*b);
    maxrad = max(d__1,*c__);
/* Computing MIN */
    d__1 = min(*a,*b);
    minrad = min(d__1,*c__);
    if (umbral) {

/*        Compute the angular offsets from the axis of rays tangent to */
/*        both the source and the bounding spheres of the target, where */
/*        the tangency points lie in a half-plane bounded by the line */
/*        containing the origin and SRCPOS.  (We'll call this line */
/*        the "axis.") */

/*        OUTANG corresponds to the target's outer bounding sphere; */
/*        INANG to the inner bounding sphere. */

	outang = asin((*srcrad - maxrad) / d__);
	inang = asin((*srcrad - minrad) / d__);
    } else {

/*        Compute the angular offsets from the axis of rays tangent to */
/*        both the source and the bounding spheres of the target, where */
/*        the tangency points lie in opposite half-planes bounded by the */
/*        axis (compare the case above). */

/*        OUTANG corresponds to the target's outer bounding sphere; */
/*        INANG to the inner bounding sphere. */

	outang = asin((*srcrad + maxrad) / d__);
	inang = asin((*srcrad + minrad) / d__);
    }

/*     Compute the angular delta we'll use for generating */
/*     terminator points. */

    delta = twopi_() / *npts;

/*     Generate the terminator points. */

    i__1 = *npts;
    for (i__ = 1; i__ <= i__1; ++i__) {
	theta = (i__ - 1) * delta;

/*        Let SRCPT be the surface point on the source lying in */
/*        the X-Y plane of the frame produced by FRAME */
/*        and corresponding to the angle THETA. */

	latrec_(srcrad, &theta, &c_b30, srcpt);

/*        Now solve for the angle by which SRCPT must be rotated (toward */
/*        +Z in the umbral case, away from +Z in the penumbral case) */
/*        so that a plane tangent to the source at SRCPT is also tangent */
/*        to the target. The rotation is bracketed by OUTANG on the low */
/*        side and INANG on the high side in the umbral case; the */
/*        bracketing values are reversed in the penumbral case. */

	if (umbral) {
	    angle = outang;
	} else {
	    angle = inang;
	}
	prvdif = twopi_();
	prvang = angle + halfpi_();
	nitr = 0;
	for(;;) { /* while(complicated condition) */
	    d__2 = (d__1 = angle - prvang, abs(d__1));
	    if (!(nitr <= 10 && touchd_(&d__2) < prvdif))
	    	break;
	    ++nitr;
	    d__2 = (d__1 = angle - prvang, abs(d__1));
	    prvdif = touchd_(&d__2);
	    prvang = angle;

/*           Find the closest point on the ellipsoid to the plane */
/*           corresponding to "ANGLE". */

/*           The tangent point on the source is obtained by rotating */
/*           SRCPT by ANGLE towards +Z.  The plane's normal vector is */
/*           parallel to VTX in the source-centered frame. */

	    latrec_(srcrad, &theta, &angle, vtx);
	    vequ_(vtx, dir);

/*           VTX and DIR are expressed in the source-centered frame.  We */
/*           must translate VTX to the target frame and rotate both */
/*           vectors into that frame. */

	    mxv_(trans, vtx, vtemp);
	    vadd_(srcpos, vtemp, vtx);
	    mxv_(trans, dir, vtemp);
	    vequ_(vtemp, dir);

/*           Create the plane defined by VTX and DIR. */

	    nvp2pl_(dir, vtx, plane);

/*           Find the closest point on the ellipsoid to the plane. At */
/*           the point we seek, the outward normal on the ellipsoid is */
/*           parallel to the choice of plane normal that points away */
/*           from the origin.  We can always obtain this choice from */
/*           PL2NVC. */

	    pl2nvc_(plane, dir, &plcons);

/*           At the point */

/*               E = (x, y, z) */

/*           on the ellipsoid's surface, an outward normal */
/*           is */

/*               N = ( x/A**2, y/B**2, z/C**2 ) */

/*           which is also */

/*               lambda * ( DIR(1), DIR(2), DIR(3) ) */

/*           Equating components in the normal vectors yields */

/*               E = lambda * ( DIR(1)*A**2, DIR(2)*B**2, DIR(3)*C**2 ) */

/*           Taking the inner product with the point E itself and */
/*           applying the ellipsoid equation, we find */

/*               lambda * <DIR, E>  =  < N, E >  =  1 */

/*           The first term above is */

/*               lambda**2 * || ( A*DIR(1), B*DIR(2), C*DIR(3) ) ||**2 */

/*           So the positive root lambda is */

/*               1 / || ( A*DIR(1), B*DIR(2), C*DIR(3) ) || */

/*           Having lambda we can compute E. */

	    d__1 = *a * dir[0];
	    d__2 = *b * dir[1];
	    d__3 = *c__ * dir[2];
	    vpack_(&d__1, &d__2, &d__3, v);
	    lambda = 1. / vnorm_(v);
	    d__1 = *a * v[0];
	    d__2 = *b * v[1];
	    d__3 = *c__ * v[2];
	    vpack_(&d__1, &d__2, &d__3, e);
	    vscl_(&lambda, e, &trmpts[(i__2 = i__ * 3 - 3) < trmpts_dim2 * 3 
		    && 0 <= i__2 ? i__2 : s_rnge("trmpts", i__2, "zzedterm_", 
		    (ftnlen)586)]);

/*           Make a new estimate of the plane rotation required to touch */
/*           the target. */

	    vsub_(&trmpts[(i__2 = i__ * 3 - 3) < trmpts_dim2 * 3 && 0 <= i__2 
		    ? i__2 : s_rnge("trmpts", i__2, "zzedterm_", (ftnlen)592)]
		    , vtx, offset);

/*           Let ANGERR be an estimate of the magnitude of angular error */
/*           between the plane and the terminator. */

	    angerr = vsep_(dir, offset) - halfpi_();

/*           Let S indicate the sign of the altitude error:  where */
/*           S is positive, the plane is above E. */

	    d__1 = vdot_(e, dir);
	    s = d_sign(&c_b35, &d__1);
	    if (umbral) {

/*              If the plane is above the target, increase the */
/*              rotation angle; otherwise decrease the angle. */

		angle += s * angerr;
	    } else {

/*              This is the penumbral case; decreasing the angle */
/*              "lowers" the plane toward the target. */

		angle -= s * angerr;
	    }
	}
    }
    chkout_("ZZEDTERM", (ftnlen)8);
    return 0;
} /* zzedterm_ */
Beispiel #5
0
/* $Procedure ZZSTELAB ( Private --- stellar aberration correction ) */
/* Subroutine */ int zzstelab_(logical *xmit, doublereal *accobs, doublereal *
	vobs, doublereal *starg, doublereal *scorr, doublereal *dscorr)
{
    /* System generated locals */
    integer i__1;
    doublereal d__1, d__2;

    /* Builtin functions */
    double sqrt(doublereal);
    integer s_rnge(char *, integer, char *, integer);

    /* Local variables */
    extern /* Subroutine */ int vadd_(doublereal *, doublereal *, doublereal *
	    );
    doublereal dphi, rhat[3];
    extern /* Subroutine */ int vhat_(doublereal *, doublereal *);
    extern doublereal vdot_(doublereal *, doublereal *);
    extern /* Subroutine */ int vequ_(doublereal *, doublereal *);
    doublereal term1[3], term2[3], term3[3], c__, lcacc[3];
    integer i__;
    doublereal s;
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    doublereal saoff[6]	/* was [3][2] */, drhat[3];
    extern /* Subroutine */ int dvhat_(doublereal *, doublereal *);
    doublereal ptarg[3], evobs[3], srhat[6], vphat[3], vtarg[3];
    extern /* Subroutine */ int vlcom_(doublereal *, doublereal *, doublereal 
	    *, doublereal *, doublereal *), vperp_(doublereal *, doublereal *,
	     doublereal *);
    extern doublereal vnorm_(doublereal *);
    extern logical vzero_(doublereal *);
    extern /* Subroutine */ int vlcom3_(doublereal *, doublereal *, 
	    doublereal *, doublereal *, doublereal *, doublereal *, 
	    doublereal *), cleard_(integer *, doublereal *);
    doublereal vp[3];
    extern doublereal clight_(void);
    doublereal dptmag, ptgmag, eptarg[3], dvphat[3], lcvobs[3];
    extern /* Subroutine */ int qderiv_(integer *, doublereal *, doublereal *,
	     doublereal *, doublereal *), sigerr_(char *, ftnlen), chkout_(
	    char *, ftnlen), setmsg_(char *, ftnlen);
    doublereal svphat[6];
    extern logical return_(void);
    extern /* Subroutine */ int vminus_(doublereal *, doublereal *);
    doublereal sgn, dvp[3], svp[6];

/* $ Abstract */

/*     SPICE Private routine intended solely for the support of SPICE */
/*     routines.  Users should not call this routine directly due */
/*     to the volatile nature of this routine. */

/*     Return the state (position and velocity) of a target body */
/*     relative to an observing body, optionally corrected for light */
/*     time (planetary aberration) and stellar aberration. */

/* $ 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 */

/*     EPHEMERIS */

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

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     XMIT       I   Reception/transmission flag. */
/*     ACCOBS     I   Observer acceleration relative to SSB. */
/*     VOBS       I   Observer velocity relative to to SSB. */
/*     STARG      I   State of target relative to observer. */
/*     SCORR      O   Stellar aberration correction for position. */
/*     DSCORR     O   Stellar aberration correction for velocity. */

/* $ Detailed_Input */

/*     XMIT        is a logical flag which is set to .TRUE. for the */
/*                 "transmission" case in which photons *depart* from */
/*                 the observer's location at an observation epoch ET */
/*                 and arrive at the target's location at the light-time */
/*                 corrected epoch ET+LT, where LT is the one-way light */
/*                 time between observer and target; XMIT is set to */
/*                 .FALSE. for "reception" case in which photons depart */
/*                 from the target's location at the light-time */
/*                 corrected epoch ET-LT and *arrive* at the observer's */
/*                 location at ET. */

/*                 Note that the observation epoch is not used in this */
/*                 routine. */

/*                 XMIT must be consistent with any light time */
/*                 corrections used for the input state STARG: if that */
/*                 state has been corrected for "reception" light time; */
/*                 XMIT must be .FALSE.; otherwise XMIT must be .TRUE. */

/*     ACCOBS      is the geometric acceleration of the observer */
/*                 relative to the solar system barycenter. Units are */
/*                 km/sec**2. ACCOBS must be expressed relative to */
/*                 an inertial reference frame. */

/*     VOBS        is the geometric velocity of the observer relative to */
/*                 the solar system barycenter. VOBS must be expressed */
/*                 relative to the same inertial reference frame as */
/*                 ACCOBS. Units are km/sec. */

/*     STARG       is the Cartesian state of the target relative to the */
/*                 observer. Normally STARG has been corrected for */
/*                 one-way light time, but this is not required. STARG */
/*                 must be expressed relative to the same inertial */
/*                 reference frame as ACCOBS. Components are */
/*                 (x, y, z, dx, dy, dz). Units are km and km/sec. */

/* $ Detailed_Output */

/*     SCORR       is the stellar aberration correction for the position */
/*                 component of STARG. Adding SCORR to this position */
/*                 vector produces the input observer-target position, */
/*                 corrected for stellar aberration. */

/*                 The reference frame of SCORR is the common frame */
/*                 relative to which the inputs ACCOBS, VOBS, and STARG */
/*                 are expressed. Units are km. */

/*     DSCORR      is the stellar aberration correction for the velocity */
/*                 component of STARG. Adding DSCORR to this velocity */
/*                 vector produces the input observer-target velocity, */
/*                 corrected for stellar aberration. */

/*                 The reference frame of DSCORR is the common frame */
/*                 relative to which the inputs ACCOBS, VOBS, and STARG */
/*                 are expressed. Units are km/s. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1) If attempt to divide by zero occurs, the error */
/*        SPICE(DIVIDEBYZERO) will be signaled. This case may occur */
/*        due to uninitialized inputs. */

/*     2) Loss of precision will occur for geometric cases in which */
/*        VOBS is nearly parallel to the position component of STARG. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     This routine computes a Newtonian estimate of the stellar */
/*     aberration correction of an input state. Normally the input state */
/*     has already been corrected for one-way light time. */

/*     Since stellar aberration corrections are typically "small" */
/*     relative to the magnitude of the input observer-target position */
/*     and velocity, this routine avoids loss of precision by returning */
/*     the corrections themselves rather than the corrected state */
/*     vector. This allows the caller to manipulate (for example, */
/*     interpolate) the corrections with greater accuracy. */

/* $ Examples */

/*     See SPICELIB routine SPKACS. */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     SPK Required Reading. */

/* $ Author_and_Institution */

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

/* $ Version */

/* -    SPICELIB Version 2.0.0, 15-APR-2014 (NJB) */

/*        Added RETURN test and discovery check-in. */
/*        Check for division by zero was added. This */
/*        case might occur due to uninitialized inputs. */

/* -    SPICELIB Version 1.0.1, 12-FEB-2009 (NJB) */

/*        Minor updates were made to the inline documentation. */

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

/* -& */

/*     Note for the maintenance programmer */
/*     =================================== */

/*     The source code of the test utility T_ZZSTLABN must be */
/*     kept in sync with the source code of this routine. That */
/*     routine uses a value of SEPLIM that forces the numeric */
/*     branch of the velocity computation to be taken in all */
/*     cases. See the documentation of that routine for details. */


/*     SPICELIB functions */


/*     Local parameters */


/*     Let PHI be the (non-negative) rotation angle of the stellar */
/*     aberration correction; then SEPLIM is a limit on how close PHI */
/*     may be to zero radians while stellar aberration velocity is */
/*     computed analytically. When sin(PHI) is less than SEPLIM, the */
/*     velocity must be computed numerically. */


/*     Let TDELTA be the time interval, measured in seconds, */
/*     used for numerical differentiation of the stellar */
/*     aberration correction, when this is necessary. */


/*     Local variables */


/*     Use discovery check-in. */

    if (return_()) {
	return 0;
    }

/*     In the discussion below, the dot product of vectors X and Y */
/*     is denoted by */

/*        <X,Y> */

/*     The speed of light is denoted by the lower case letter "c." BTW, */
/*     variable names used here are case-sensitive: upper case "C" */
/*     represents a different quantity which is unrelated to the speed */
/*     of light. */

/*     Variable names ending in "HAT" denote unit vectors. Variable */
/*     names starting with "D" denote derivatives with respect to time. */

/*     We'll compute the correction SCORR and its derivative with */
/*     respect to time DSCORR for the reception case. In the */
/*     transmission case, we perform the same computation with the */
/*     negatives of the observer velocity and acceleration. */

/*     In the code below, we'll store the position and velocity portions */
/*     of the input observer-target state STARG in the variables PTARG */
/*     and VTARG, respectively. */

/*     Let VP be the component of VOBS orthogonal to PTARG. VP */
/*     is defined as */

/*         VOBS - < VOBS, RHAT > RHAT                                 (1) */

/*     where RHAT is the unit vector */

/*         PTARG/||PTARG|| */

/*     Then */

/*        ||VP||/c                                                    (2) */

/*     is the magnitude of */

/*        s = sin( phi )                                              (3) */

/*     where phi is the stellar aberration correction angle. We'll */
/*     need the derivative with respect to time of (2). */

/*     Differentiating (1) with respect to time yields the */
/*     velocity DVP, where, letting */

/*        DRHAT  =  d(RHAT) / dt */
/*        VPHAT  =  VP      / ||VP|| */
/*        DVPMAG =  d( ||VP|| ) / dt */

/*     we have */

/*        DVP = d(VP)/dt */

/*            = ACCOBS - (  ( <VOBS,DRHAT> + <ACCOBS, RHAT> )*RHAT */
/*                        +   <VOBS,RHAT>  * DRHAT                 )  (4) */

/*     and */

/*        DVPMAG = < DVP, VPHAT >                                     (5) */

/*     Now we can find the derivative with respect to time of */
/*     the stellar aberration angle phi: */

/*        ds/dt = d(sin(phi))/dt = d(phi)/dt * cos(phi)               (6) */

/*     Using (2) and (5), we have for positive phi, */

/*        ds/dt = (1/c)*DVPMAG = (1/c)*<DVP, VPHAT>                   (7) */

/*     Then for positive phi */

/*        d(phi)/dt = (1/cos(phi)) * (1/c) * <DVP, VPHAT>             (8) */

/*     Equation (8) is well-defined as along as VP is non-zero: */
/*     if VP is the zero vector, VPHAT is undefined. We'll treat */
/*     the singular and near-singular cases separately. */

/*     The aberration correction itself is a rotation by angle phi */
/*     from RHAT towards VP, so the corrected vector is */

/*        ( sin(phi)*VPHAT + cos(phi)*RHAT ) * ||PTARG|| */

/*     and  we can express the offset of the corrected vector from */
/*     PTARG, which is the output SCORR, as */

/*        SCORR = */

/*        ( sin(phi)*VPHAT + (cos(phi)-1)*RHAT ) * ||PTARG||          (9) */

/*     Let DPTMAG be defined as */

/*        DPTMAG  =  d ( ||PTARG|| ) / dt                            (10) */

/*     Then the derivative with respect to time of SCORR is */

/*        DSCORR = */

/*             (      sin(phi)*DVPHAT */

/*                +   cos(phi)*d(phi)/dt * VPHAT */

/*                +  (cos(phi) - 1) * DRHAT */

/*                +  ( -sin(phi)*d(phi)/dt ) * RHAT   ) * ||PTARG|| */

/*           + ( sin(phi)*VPHAT + (cos(phi)-1)*RHAT ) * DPTMAG       (11) */


/*     Computations begin here: */

/*     Split STARG into position and velocity components. Compute */

/*        RHAT */
/*        DRHAT */
/*        VP */
/*        DPTMAG */

    if (*xmit) {
	vminus_(vobs, lcvobs);
	vminus_(accobs, lcacc);
    } else {
	vequ_(vobs, lcvobs);
	vequ_(accobs, lcacc);
    }
    vequ_(starg, ptarg);
    vequ_(&starg[3], vtarg);
    dvhat_(starg, srhat);
    vequ_(srhat, rhat);
    vequ_(&srhat[3], drhat);
    vperp_(lcvobs, rhat, vp);
    dptmag = vdot_(vtarg, rhat);

/*     Compute sin(phi) and cos(phi), which we'll call S and C */
/*     respectively. Note that phi is always close to zero for */
/*     realistic inputs (for which ||VOBS|| << CLIGHT), so the */
/*     cosine term is positive. */

    s = vnorm_(vp) / clight_();
/* Computing MAX */
    d__1 = 0., d__2 = 1 - s * s;
    c__ = sqrt((max(d__1,d__2)));
    if (c__ == 0.) {

/*        C will be used as a divisor later (in the computation */
/*        of DPHI), so we'll put a stop to the problem here. */

	chkin_("ZZSTELAB", (ftnlen)8);
	setmsg_("Cosine of the aberration angle is 0; this cannot occur for "
		"realistic observer velocities. This case can arise due to un"
		"initialized inputs. This cosine value is used as a divisor i"
		"n a later computation, so it must not be equal to zero.", (
		ftnlen)234);
	sigerr_("SPICE(DIVIDEBYZERO)", (ftnlen)19);
	chkout_("ZZSTELAB", (ftnlen)8);
	return 0;
    }

/*     Compute the unit vector VPHAT and the stellar */
/*     aberration correction. We avoid relying on */
/*     VHAT's exception handling for the zero vector. */

    if (vzero_(vp)) {
	cleard_(&c__3, vphat);
    } else {
	vhat_(vp, vphat);
    }

/*     Now we can use equation (9) to obtain the stellar */
/*     aberration correction SCORR: */

/*        SCORR = */

/*           ( sin(phi)*VPHAT + (cos(phi)-1)*RHAT ) * ||PTARG|| */


    ptgmag = vnorm_(ptarg);
    d__1 = ptgmag * s;
    d__2 = ptgmag * (c__ - 1.);
    vlcom_(&d__1, vphat, &d__2, rhat, scorr);

/*     Now we use S as an estimate of PHI to decide if we're */
/*     going to differentiate the stellar aberration correction */
/*     analytically or numerically. */

/*     Note that S is non-negative by construction, so we don't */
/*     need to use the absolute value of S here. */

    if (s >= 1e-6) {

/*        This is the analytic case. */

/*        Compute DVP---the derivative of VP with respect to time. */
/*        Recall equation (4): */

/*        DVP = d(VP)/dt */

/*            = ACCOBS - (  ( <VOBS,DRHAT> + <ACCOBS, RHAT> )*RHAT */
/*                        +   <VOBS,RHAT>  * DRHAT                 ) */

	d__1 = -vdot_(lcvobs, drhat) - vdot_(lcacc, rhat);
	d__2 = -vdot_(lcvobs, rhat);
	vlcom3_(&c_b7, lcacc, &d__1, rhat, &d__2, drhat, dvp);
	vhat_(vp, vphat);

/*        Now we can compute DVPHAT, the derivative of VPHAT: */

	vequ_(vp, svp);
	vequ_(dvp, &svp[3]);
	dvhat_(svp, svphat);
	vequ_(&svphat[3], dvphat);

/*        Compute the DPHI, the time derivative of PHI, using equation 8: */

/*           d(phi)/dt = (1/cos(phi)) * (1/c) * <DVP, VPHAT> */


	dphi = 1. / (c__ * clight_()) * vdot_(dvp, vphat);

/*        At long last we've assembled all of the "ingredients" required */
/*        to compute DSCORR: */

/*           DSCORR = */

/*             (     sin(phi)*DVPHAT */

/*                +  cos(phi)*d(phi)/dt * VPHAT */

/*                +  (cos(phi) - 1) * DRHAT */

/*                +  ( -sin(phi)*d(phi)/dt ) * RHAT   ) * ||PTARG|| */

/*                +  ( sin(phi)*VPHAT + (cos(phi)-1)*RHAT ) * DPTMAG */


	d__1 = c__ * dphi;
	vlcom_(&s, dvphat, &d__1, vphat, term1);
	d__1 = c__ - 1.;
	d__2 = -s * dphi;
	vlcom_(&d__1, drhat, &d__2, rhat, term2);
	vadd_(term1, term2, term3);
	d__1 = dptmag * s;
	d__2 = dptmag * (c__ - 1.);
	vlcom3_(&ptgmag, term3, &d__1, vphat, &d__2, rhat, dscorr);
    } else {

/*        This is the numeric case. We're going to differentiate */
/*        the stellar aberration correction offset vector using */
/*        a quadratic estimate. */

	for (i__ = 1; i__ <= 2; ++i__) {

/*           Set the sign of the time offset. */

	    if (i__ == 1) {
		sgn = -1.;
	    } else {
		sgn = 1.;
	    }

/*           Estimate the observer's velocity relative to the */
/*           solar system barycenter at the current epoch. We use */
/*           the local copies of the input velocity and acceleration */
/*           to make a linear estimate. */

	    d__1 = sgn * 1.;
	    vlcom_(&c_b7, lcvobs, &d__1, lcacc, evobs);

/*           Estimate the observer-target vector. We use the */
/*           observer-target state velocity to make a linear estimate. */

	    d__1 = sgn * 1.;
	    vlcom_(&c_b7, starg, &d__1, &starg[3], eptarg);

/*           Let RHAT be the unit observer-target position. */
/*           Compute the component of the observer's velocity */
/*           that is perpendicular to the target position; call */
/*           this vector VP. Also compute the unit vector in */
/*           the direction of VP. */

	    vhat_(eptarg, rhat);
	    vperp_(evobs, rhat, vp);
	    if (vzero_(vp)) {
		cleard_(&c__3, vphat);
	    } else {
		vhat_(vp, vphat);
	    }

/*           Compute the sine and cosine of the correction */
/*           angle. */

	    s = vnorm_(vp) / clight_();
/* Computing MAX */
	    d__1 = 0., d__2 = 1 - s * s;
	    c__ = sqrt((max(d__1,d__2)));

/*           Compute the vector offset of the correction. */

	    ptgmag = vnorm_(eptarg);
	    d__1 = ptgmag * s;
	    d__2 = ptgmag * (c__ - 1.);
	    vlcom_(&d__1, vphat, &d__2, rhat, &saoff[(i__1 = i__ * 3 - 3) < 6 
		    && 0 <= i__1 ? i__1 : s_rnge("saoff", i__1, "zzstelab_", (
		    ftnlen)597)]);
	}

/*        Now compute the derivative. */

	qderiv_(&c__3, saoff, &saoff[3], &c_b7, dscorr);
    }

/*     At this point the correction offset SCORR and its derivative */
/*     with respect to time DSCORR are both set. */

    return 0;
} /* zzstelab_ */