/* $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_ */
/* $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, <, (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, <s, (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_ */
/* $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, <, (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_ */
/* $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_ */
/* $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_ */