Geometric Event Finding Hands-On Lesson (C)





March 30, 2005

Updated to correct minor bugs in Fortran utilities: umbrella functions MODRIS and MODOCP, as well as entries in these functions SETRIS and SETOCP, now return the value .FALSE. Fortran callers of SETRIS and SETOCP were updated to use function call syntax.

June 1, 2004

Updated to include code to test routines written by student: srfazl and occpt.

May 7, 2004



Overview




This lesson illustrates how the CSPICE Toolkit can be used to find time intervals when specified geometric conditions are satisfied. The student is asked to construct a program that finds the times within a specified time range when a point target is visible from a specified surface point on an extended body. As a concrete example, the student is asked to find the complete set of times within the interval

   2004 MAY 1 TDB
   2004 MAY 5 TDB
when the Mars Express Orbiter is visible from the DSN station DSS-14. The program is to consider occultation of the spacecraft by Mars and by the earth. We'll consider the spacecraft occulted by the earth if its elevation is below six degrees when measured in the topocentric frame DSS-14_TOPO, which is centered at DSS-14.

Although we've identified a specific set of objects participating in our observation geometry problem, the solution program should be written in such a way that these selections could be changed simply by modifying a meta-kernel read by the program.

In this lesson, we use the terms ``event finding'' or ``root finding'' to designate the process of solving for the set of times when a specified geometric condition is met. Rather than ask the student to devise event finding algorithms, we provide the student with functions to perform this task. See the section titled ``Utility routines'' below for details.

The utility routines provided here are not part of the CSPICE Toolkit. NAIF plans to include event finding software in a future Toolkit release. The planned CSPICE Toolkit subsystem dealing with event finding is called the ``Geometry Finder.'' The Geometry Finder's function API will not closely resemble the event finding interface presented here. However, the event finding utilities comprise a small part of the overall set of routines the student will use in this lesson. Aside from these few utilities, the other functions presented in this lesson are in common use among CSPICE programmers.

One set of CSPICE functions that are particularly relevant to event finding are the CSPICE window manipulation functions. In addition to this lesson, the ``Other Stuff'' hands-on programming lesson contains an exercise dealing with CSPICE window functions. The student may wish to complete that exercise in addition to this lesson.

This lesson consists of a series of programming exercises. In each exercise, the student writes a portion of the program constituting the complete problem solution. The exercise topics are:

This document contains a chapter for each of the listed topics.



References




This section provides a list of SPICE documents that are referred to in this lesson.

Of these documents, the ``Tutorials'' contains the highest level descriptions with the fewest details while the ``Required Reading'' documents contain much more detailed specifications. The most complete specifications are provided in the ``Headers'' -- the comments in the top section of each CSPICE source file.



Tutorials



The following SPICE tutorials may be particularly useful as references for this lesson:

   Name                    Lesson steps/routines that it describes
   ---------------         -----------------------------------------
   Time                    Conversion between UTC and ET
   Intro to Kernel Files   Loading SPICE kernels
   SPK                     Computing positions and velocities
   Frames                  Computing transformations between frames
These tutorials are available in printed form and as MS Office or PDF files from the NAIF server at JPL:

   ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/Tutorials


Required Reading Documents



The Required Reading documents are provided with the Toolkit and are located under ``toolkit/doc'' or ``cspice/doc'' directory in the FORTRAN and C Toolkit installation trees.

   Name             Functions/routines that it describes
   ---------------  -----------------------------------------
   cells.req        The SPICE cell data type
   error.req        SPICE error handling
   frames.req       Using reference frames
   kernel.req       Loading SPICE kernels
   naif_ids.req     Body and reference frame names
   sets.req         The SPICE set data type
   spk.req          Computing positions and velocities
   time.req         UTC to ET time conversion
   windows.req      The SPICE window data type
Another very useful document, also distributed with the Toolkit, is the ``Permuted Index'', called ``cspice.idx''; the Permuted index is located under ``doc'' directory in the Toolkit installation tree.

This text document provides an easy way to find which SPICE routine(s) performs a particular function in which you are interested. It also provides the name of the source file that contains this function.



Source Code Header Comments



The most detailed specification of a given SPICE FORTRAN or C routine is contained in the header section of its source code. The source code is distributed with the Toolkit and is located under ``toolkit/src/spicelib'' in FORTRAN and under ``cspice/src/cspice'' in C Toolkits.

For example the source code of the STR2ET/str2et_c routine is

   toolkit/src/spicelib/str2et.for
in the FORTRAN Toolkit and in

   cspice/src/cspice/str2et_c.c
in the C Toolkit.

Since some of the FORTRAN routines are entry points they are usually part of a source file that has different name. The ``Permuted Index'' document mentioned above can be used to locate the name of their source file.



Kernels Used




The following kernels are used in examples provided in this lesson:

   File Name                       Type  Description
   -----------------------         ----  --------------------------
   de405s.bsp                      SPK   Planet Ephemeris SPK
   dsnstns.bsp                     SPK   DSN station SPK
   DSN_topo.frm                    FK    DSN station frame definitions
   earth_031228_231229_predict.bpc PCK   Binary predict PCK for earth
   ORMM__040501000000_00069.BSP    SPK   MEX Orbiter Trajectory SPK
   naif0007.tls                    LSK   Generic LSK
   pck00007.tpc                    PCK   Generic PCK
These SPICE kernels are available from the NAIF server at JPL:

   ftp://naif.jpl.nasa.gov/pub/naif/misc/lessons/events


CSPICE Routines Used




The following CSPICE routines are used in the solution programs to be written by the student, or in the supporting utility routines provided in this lesson:

   Name        Function that it performs
   ----------  ---------------------------------------------------
   appndd_c    Appends an item to a d.p. cell
   badkpv_c    Checks a kernel variable definition
   card_c      Return cardinality of d.p. cell
   chkin_c     SPICE call tree tracing check-in
   chkout_c    SPICE call tree tracing check-out
   cnmfrm_c    Map a body name to an associated frame
   rpd_c       Return number of degrees per radian
   errch_c     Substitute a character string into an error message
   errdp_c     Substitute a d.p. number into an error message
   furnsh_c    Loads kernels, individually or listed in meta-kernel
   gcpool_c    Fetch string values from the kernel pool
   gdpool_c    Fetch d.p. values from the kernel pool
   kdata_c     Return info on specified loaded kernel
   ktotal_c    Return the count of loaded kernels of a given type
   reclat_c    Transform from rectangular to latitudinal coordinates
   return_c    Test whether CSPICE routines should return on entry
   rpd_c       Return number of radians per degree
   setmsg_c    Set the SPICE long error message
   sigerr_c    Signal a SPICE error
   spkpos_c    Computes positions of ephemeris objects
   str2et_c    Converts a time string to ET seconds past J2000
   srfxpt_c    Find intersection of ray and ellipsoidal target body
   timout_c    Format a time string for output
   vnorm_c     Find the norm of a 3-vector
   wndifd_c    Find the difference of two d.p. windows
   wnfetd_c    Fetch a specified interval from a d.p. window
   wninsd_c    Insert an interval into a d.p. window
The most detailed documentation source for these routines is their headers.



Utility routines not included in CSPICE




The following utility routines are used in the solution programs to be written by the student, or in the supporting utility routines provided in this lesson:

   Name        Function that it performs
   ----------  ---------------------------------------------------
   fndevt      Find set of times of state transitions
   makwin      Convert state transition set to CSPICE window
   modocp      Umbrella file for occultation utilities
   modris      Umbrella file for rise-set utilities
   setocp      Set parameter values for occultation utilities
   setris      Set parameter values for rise-set utilities
   stocp       Indicate whether target is occulted
   stris       Indicate whether target elevation is above limit
The function fndevt is the key root-finding utility. Given a SpiceBoolean function of time f(t), and a time interval, fndevt finds the set of times within the interval at which the value returned by f(t) changes.

In this context, we call f(t) a ``state function'' and the epochs at which the value of f(t) changes ``epochs of state transitions'' or simply ``state transitions.''

fndevt stores the state transition epochs it finds in a CSPICE set, which is an output argument.

The utility makwin converts the set returned by fndevt into a CSPICE window whose intervals represent the time periods when the state returned by f(t) is SPICETRUE.

The purpose of the suite of routines contained in the module modris is to enable a user to define and use a ``state function'' that indicates when a target is above a specified elevation limit, as seen by an observer at a surface location on an extended body. The module contains an initialization function setris that allows a user to set parameters defining the geometry of interest and a state function stris that uses values established by setris to decide whether the target is above the elevation limit at a specified time. The function stris computes target elevation using the function srfazl, which is supplied by the student.

In the same vein, the purpose of the suite of routines contained in the module modocp is to enable a user to define and use a ``state function'' that indicates when a point target is occulted by a specified extended body, as seen by a specified observer. The module contains an initialization function setocp that allows a user to set parameters defining the geometry of interest and a state function stocp that uses values established by setocp to decide whether the target is occulted at a specified time. The function stocp tests for occultation using the function occpt, which is supplied by the student.



Input Data







Task Statement




Write a program that loads SPICE kernels and reads input values required to solve the point target visibility problem.

Create a SPICE text kernel (``meta-kernel'') containing information required to initialize the program. The program is to read both command inputs and SPICE kernel names from this SPICE text kernel. The following items are to be read from the kernel:

The program should perform error checking on the inputs obtained from the kernel file. Each item, other than the kernels to be loaded, should be verified to be present and to have the correct data type. To test the program, use the following inputs:

Finally, the program should write to standard output the kernel variable inputs read from the text kernel. Times should be displayed in both TDB and UTC calendar format. The items displayed should include the names and types of the loaded SPICE kernels.



Learning Goals




The student is introduced to flexible, robust techniques for introducing data into CSPICE based programs.

The student is exposed to the following SPICE components:



Approach






Solution steps



A possible solution would consist of the following steps:

Preparation:

Next, write a program that performs the following steps:

You may find it useful to consult the permuted index, the headers of various source modules, and the ``Time Required Reading'' and ``Kernel Required Reading'' documents.



Solution






Solution Meta-Kernel



The meta-kernel we created for the solution to this exercise is named 'geomevnt.mk'. Its contents follow:

 
 
      Example meta-kernel for geometric event finding hands-on
      coding lesson.
 
         Version 1.0.0 07-MAY-2004 (NJB)
 
 
      Identify names of kernels to load:
 
   \begindata
 
      KERNELS_TO_LOAD = (
 
              'kernels/spk/de405s.bsp'
              'kernels/spk/dsnstns.bsp'
              'kernels/fk/DSN_topo.frm'
              'kernels/pck/earth_031228_231229_predict.bpc'
              'kernels/lsk/naif0007.tls'
              'kernels/spk/ORMM__040501000000_00069.BSP'
              'kernels/pck/pck00007.tpc'
                        )
 
   \begintext
 
       Set values of other inputs:
 
           surface point
           target
           occulting body
           aberration correction
           search interval start time
           search interval stop time
           elevation limit
 
      The kernel variable names used here are examples; the
      programmer may choose other names.  The names must be no
      longer than 32 characters and are case-sensitive.  These
      names must be referenced in calls to the kernel pool fetch
      routines.
 
   \begindata
 
      SCVIEW_SRFPT  = 'DSS-14'
      SCVIEW_TARGET = 'MEX'
      SCVIEW_OCCBDY = 'MARS'
      SCVIEW_ABCORR = 'CN+S'
      SCVIEW_START  = '2004 MAY 1 TDB'
      SCVIEW_STOP   = '2004 MAY 5 TDB'
      SCVIEW_ELVLIM =  6.0
 
   \begintext


Solution Code



The example program below shows one possible solution.

 
      #include <stdio.h>
      #include <math.h>
      #include "SpiceUsr.h"
 
 
      /*
      PROGRAM SCVIEW
 
      Find the view periods for a point target as seen from a
      specified surface location.  Exclude periods when target
      is occulted by extended bodies other than the one associated
      with the viewing location. Display the windows of visibility.
 
      The following items are loaded from a SPICE text kernel:
 
         - Observer (surface point) name
         - Target name
         - Occulting body name
         - Aberration correction specification
         - Start time string
         - Stop time #include <string.h>
         - Elevation limit (in degrees)
 
      This program assumes all necessary kernels and kernel
      variable definitions are specified in a SPICE  meta-kernel.
      The meta-kernel name is assumed to be 'geomevnt.mk'.
 
        07-MAY-2004 (NJB)
 
        31-OCT-2002 (NJB)
 
      */
 
   int main()
   {
 
      /*
      Local constants
      */
 
      /*
      The  meta-kernel:
      */
      #define META            "geomevnt.mk"
 
 
      /*
      Labels of kernel pool items:
      */
      #define CORLBL          "SCVIEW_ABCORR"
      #define ELVLBL          "SCVIEW_ELVLIM"
      #define OCCLBL          "SCVIEW_OCCBDY"
      #define SRFLBL          "SCVIEW_SRFPT"
      #define STPLBL          "SCVIEW_STOP"
      #define STRLBL          "SCVIEW_START"
      #define TRGLBL          "SCVIEW_TARGET"
 
 
      /*
      String lengths and other bounds:
      */
      #define CORLEN          11
      #define FILSIZ          256
      #define LNSIZE          201
      #define NAMLEN          33
      #define TIMLEN          51
      #define TYPLEN          51
 
      /*
      Local variables
      */
      SpiceBoolean            found;
 
      SpiceChar               abcorr  [ CORLEN ];
      SpiceChar               file    [ FILSIZ ];
      SpiceChar               filtyp  [ TYPLEN ];
      SpiceChar               occbdy  [ NAMLEN ];
      SpiceChar               source  [ FILSIZ ];
      SpiceChar               srfpt   [ NAMLEN ];
      SpiceChar               start   [ TIMLEN ];
      SpiceChar               stop    [ TIMLEN ];
      SpiceChar               target  [ NAMLEN ];
      SpiceChar               timstr  [ TIMLEN ];
 
      SpiceDouble             elvlim;
      SpiceDouble             etbeg;
      SpiceDouble             etend;
      SpiceDouble             revlim;
 
      SpiceInt                handle;
      SpiceInt                i;
      SpiceInt                n;
      SpiceInt                nker;
 
 
      /*
      Load the meta-kernel.
      */
      furnsh_c ( META );
 
      /*
      Look up observation location, target, name of the
      occulting body, aberration correction, start
      and stop times, and elevation limit.
 
      We simplify error checking by using badkpv_c.  badkpv_c
      tests whether a kernel variable having specified
      attributes is present in the kernel pool. The fourth
      argument of badkpv_c is the expected dimension; the
      last indicates the expected data type.  Read the
      header of badkpv_c for details.
      */
      badkpv_c ( "scview", SRFLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", OCCLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", TRGLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", CORLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STRLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STPLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", ELVLBL, "=",  1,      1, 'N' );
 
      /*
      Now we know the kernel variables of interest have been
      defined; look up the values.  We don't need to check
      the found flag because badkpv_c has ensured that each item
      will be found.
      */
      gcpool_c ( SRFLBL, 0, 1,      NAMLEN, &n,    srfpt,   &found );
      gcpool_c ( OCCLBL, 0, 1,      NAMLEN, &n,    occbdy,  &found );
      gcpool_c ( TRGLBL, 0, 1,      NAMLEN, &n,    target,  &found );
      gcpool_c ( CORLBL, 0, 1,      CORLEN, &n,    abcorr,  &found );
      gcpool_c ( STRLBL, 0, 1,      TIMLEN, &n,    start,   &found );
      gcpool_c ( STPLBL, 0, 1,      TIMLEN, &n,    stop,    &found );
      gdpool_c ( ELVLBL, 0, 1,              &n,    &elvlim, &found );
 
      revlim = rpd_c() * elvlim;
 
      /*
      Display to standard output a banner for the output report:
      */
      printf ( "\n%s\n\n",
               "Inputs for geometric event finding program" );
 
      printf ( "   Target                       = %s\n", target  );
      printf ( "   Observation surface location = %s\n", srfpt   );
      printf ( "   Occulting body               = %s\n", occbdy  );
      printf ( "   Aberration correction        = %s\n", abcorr  );
 
      /*
      Convert the start and stop times to ET.
      */
      str2et_c ( start, &etbeg );
      str2et_c ( stop,  &etend );
 
      /*
      Display the start time as both calendar ET and
      calendar UTC using the formats shown below.
 
         2004 MAY 06 20:15:00.000 (UTC)
         2004 MAY 06 20:15:00.000 (TDB)
      */
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      /*
      Display the elevation limit in degrees.
      */
      printf ( "   Elevation limit (degrees)    = %f\n", elvlim  );
 
 
      /*
      Display the names of the SPICE kernels we've loaded.
      */
      printf ( "\n"
               "Loaded SPICE Kernels:\n"  );
 
      ktotal_c ( "ALL", &nker );
 
      for ( i = 0;  i < nker;  i++  )
      {
         kdata_c ( i,     "ALL",   FILSIZ,  TYPLEN,   FILSIZ,
                   file,  filtyp,  source,  &handle,  &found );
 
         /*
         Due to the way we've constructed the loop, there's
         no need to check the 'found' flag.
         */
         printf ( "\n"
                  "   Kernel name:    %s\n"
                  "   Kernel type:    %s\n"
                  "   Kernel source:  %s\n",
                  file,
                  filtyp,
                  source                      );
      }
 
      return ( 0 );
   }


Solution Sample Output



Numerical results shown for this example may differ across platforms since the results depend on the SPICE kernels used as input and on the host platform's arithmetic implementation.

After compiling the program, execute it. The output is:

 
   Inputs for geometric event finding program
 
      Target                       = MEX
      Observation surface location = DSS-14
      Occulting body               = MARS
      Aberration correction        = CN+S
      Start time                   = 2004 APR 30 23:58:55.814 (UTC)
      Start time                   = 2004 MAY 01 00:00:00.000 (TDB)
      Stop time                    = 2004 MAY 04 23:58:55.814 (UTC)
      Stop time                    = 2004 MAY 05 00:00:00.000 (TDB)
      Elevation limit (degrees)    = 6.000000
 
   Loaded SPICE Kernels:
 
      Kernel name:    geomevnt.mk
      Kernel type:    META
      Kernel source:
 
      Kernel name:    de405s.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    dsnstns.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    DSN_topo.frm
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    earth_031228_231229_predict.bpc
      Kernel type:    PCK
      Kernel source:  geomevnt.mk
 
      Kernel name:    naif0007.tls
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    ORMM__040501000000_00069.BSP
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    pck00007.tpc
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk


Find Azimuth and Elevation of Target







Task Statement




Write a function to find the azimuth and elevation of a target as seen from a specified location on the surface of an extended body. Also return the range to the target.

The output angles are measured relative to a topocentric frame centered at the surface location. Angular units are radians.

In the topocentric frame, elevation is equivalent to latitude, and azimuth is the negative of longitude.

The function is to have the exact signature shown below:

   void srfazl ( ConstSpiceChar       * srfpt,
                 SpiceDouble            et,
                 ConstSpiceChar       * abcorr,
                 ConstSpiceChar       * targ,
                 SpiceDouble          * az,
                 SpiceDouble          * el,
                 SpiceDouble          * r      )
The meanings of the arguments are as follows:

   srfpt      Name of surface point, e.g. "DSS-14"
   et         Computation epoch, seconds past J2000 TDB.
   abcorr     Aberration correction flag: "NONE", "LT+S", etc.
   targ       Target name.
   az         Azimuth in radians.
   el         Elevation in radians.
   r          Range in kilometers.
This function will be used by the supplied event finding utilities to find times when the target is above the specified elevation limit.

Test the routine by calling it twice and displaying the outputs. The first call should use the input values:

   srfpt      "DSS-14"
   et         Double precision count of seconds past J2000 TDB
              corresponding to 2004 MAY 01 16:10:26.686 TDB
   abcorr     "CN+S"
   targ       "MEX"
The second call should use the same inputs as the first, except that the time should be the double precision count of seconds past J2000 TDB corresponding to 2004 MAY 01 16:10:26.688 TDB.

The two times are intended to bracket a spacecraft ``rise'' event: the target spacecraft should have elevation below the specified limit at the first time and above the limit at the second.



Learning Goals




This exercise introduces the student to elementary geometry computations using CSPICE. The student uses spkpos_c to look up position vectors and reclat_c to convert from rectangular to latitudinal coordinates.

When the CSPICE event finding software is delivered, computations of this type usually will not have to be performed by users in the course of solving event-finding problems: the CSPICE event finding software will do the job behind the scenes. However, this exercise is meant to provide the student with some insight into the geometry computations involved in an event finding system.



Approach






Solution steps



A possible solution would consist of the following steps:

Write the srfazl function:

Add test code to the main program:



Solution






srfazl Solution Code



The example program below shows one possible implementation of the function srfazl.

 
      #include "SpiceUsr.h"
 
 
      void srfazl ( ConstSpiceChar       * srfpt,
                    SpiceDouble            et,
                    ConstSpiceChar       * abcorr,
                    ConstSpiceChar       * targ,
                    SpiceDouble          * az,
                    SpiceDouble          * el,
                    SpiceDouble          * r      )
 
   /*
      Find the azimuth and elevation of a target as seen from
      a specified location on the surface of an extended body.
      Also return the range to the target and the one-way light
      time.
 
      The output angles are measured relative to a topocentric
      frame centered at the surface location.  Angular units are
      radians.
 
 
      Subroutine arguments:
 
 
         srfpt         is a string giving the name of the surface
                       point of interest.  A topocentric frame is
                       defined at this point.
 
         et            is the epoch at which the location of the
                       target is to be found.  et is given in
                       seconds past J2000 (TDB).
 
         abcorr        indicates the aberration correction.
                       Values and meanings are:
 
                          "NONE"   No correction.  Use geometric
                                   states.
 
                         The following are for the "reception"
                         case where radiation travels from the
                         target to the surface point and arrives
                         at et:
 
                          "LT"     Correct for one-way light time.
 
                          "LT+S"   Correct for one-way light time
                                   and stellar aberration.
 
                          "CN"     Converged Newtonian light time
                                   correction.
 
                          "CN+S"   Converged Newtonian light time
                                   and stellar aberration
                                   corrections.
 
 
                         The following are for the "transmission"
                         case where radiation travels from the
                         surface point to the target, departing the
                         surface location at et:
 
                          "XLT"    Correct for one-way light time.
 
                          "XLT+S"  Correct for one-way light time
                                   and stellar aberration.
 
                          "XCN"    Converged Newtonian light time
                                   correction.
 
                          "XCN+S"  Converged Newtonian light time
                                   and stellar aberration
                                   corrections.
 
 
         targ          is a string containing the target name.
 
         az,
         el            are the azimuth and elevation of the
                       target vector at et.  Azimuth and
                       elevation are
                       given with respect to a right-handed frame
                       with z-axis equal to the local surface
                       normal,
                       x-axis orthogonal to the z-axis and pointing
                       north, and the y-axis equal to z cross x.
 
                       Azimuth is the angle between the x-axis and
                       the projection of the target vector onto the
                       topocentric x-y plane.  Azimuth increases in
                       the clockwise direction.
 
                       Elevation is the angle between the target
                       vector and the x-y plane.
 
                       Both angles are given in radians.
 
         r             is the range to the target, in km.
 
    -Version
 
       Events Code Lesson 1.0.1 07-MAY-2004 (NJB)
 
          Description of erstwhile output argument `lt' was removed.
 
       Events Code Lesson 1.0.0 04-MAY-2004 (NJB)
 
          Modified to use cnmfrm_c.c.
 
       RS Code Lesson 1.0.0 31-OCT-2002 (NJB)
 
   */
 
   {
      /*
      Local constants
      */
      #define FRNMLN          33
 
      /*
      Local variables
      */
      SpiceBoolean            found;
 
      SpiceChar               frname [FRNMLN];
 
      SpiceDouble             lon;
      SpiceDouble             lt;
      SpiceDouble             trgpos[3];
 
      SpiceInt                frcode;
 
 
 
      if ( return_c() )
      {
         return;
      }
      chkin_c ( "srfazl" );
 
 
      /*
      Look up the topocentric reference frame associated with the
      surface point.  The definition of this frame is supplied in
      a frame kernel loaded by the calling program.
      */
      cnmfrm_c ( srfpt, FRNMLN, &frcode, frname, &found );
 
      if ( !found )
      {
         setmsg_c ( "No frame is associated with body #."
                    "This can be due to a required frame "
                    "kernel not having been loaded."       );
         errch_c  ( "#", srfpt                             );
         sigerr_c ( "SPICE(NOTDEFINED)"                    );
         chkout_c ( "srfazl"                               );
         return;
      }
 
 
      /*
      Find the position of the target as seen from the observer
      at 'et'.  Use the specified aberration corrections.  Ask for
      the position vector in the topocentric frame associated
      with the surface point.
      */
      spkpos_c ( targ, et, frname, abcorr, srfpt, trgpos, < );
 
 
      /*
      Elevation is the angular separation of the surface point-target
      vector from the x-y plane of the topocentric frame; this is
      simply latitude.  Azimuth is the negative of the longitude
      angle.
 
      Note lon is a local variable; r and el are pointer arguments
      of this function.
      */
      reclat_c ( trgpos, r, &lon, el );
 
      *az = -lon;
 
      chkout_c ( "srfazl" );
   }


Solution: Add Test Code to the Main Program



The example program below shows one possible solution.

 
      #include <stdio.h>
      #include <math.h>
      #include "SpiceUsr.h"
 
 
      /*
      PROGRAM SCVIEW
 
      Find the view periods for a point target as seen from a
      specified surface location.  Exclude periods when target
      is occulted by extended bodies other than the one associated
      with the viewing location. Display the windows of visibility.
 
      The following items are loaded from a SPICE text kernel:
 
         - Observer (surface point) name
         - Target name
         - Occulting body name
         - Aberration correction specification
         - Start time string
         - Stop time #include <string.h>
         - Elevation limit (in degrees)
 
      This program assumes all necessary kernels and kernel
      variable definitions are specified in a SPICE  meta-kernel.
      The meta-kernel name is assumed to be 'geomevnt.mk'.
 
        07-MAY-2004 (NJB)
 
        31-OCT-2002 (NJB)
 
      */
 
   int main()
   {
 
      /*
      Prototypes
      */
      void         srfazl ( ConstSpiceChar   * srfpt,
                            SpiceDouble        et,
                            ConstSpiceChar   * abcorr,
                            ConstSpiceChar   * targ,
                            SpiceDouble      * az,
                            SpiceDouble      * el,
                            SpiceDouble      * r      );
      /*
      Local constants
      */
 
      /*
      The  meta-kernel:
      */
      #define META            "geomevnt.mk"
 
 
      /*
      Labels of kernel pool items:
      */
      #define CORLBL          "SCVIEW_ABCORR"
      #define ELVLBL          "SCVIEW_ELVLIM"
      #define OCCLBL          "SCVIEW_OCCBDY"
      #define SRFLBL          "SCVIEW_SRFPT"
      #define STPLBL          "SCVIEW_STOP"
      #define STRLBL          "SCVIEW_START"
      #define TRGLBL          "SCVIEW_TARGET"
 
      /*
      String lengths and other bounds:
      */
      #define CORLEN          11
      #define FILSIZ          256
      #define LNSIZE          201
      #define NAMLEN          33
      #define TIMLEN          51
      #define TYPLEN          51
 
      /*
      Local variables
      */
      SpiceBoolean            found;
 
      SpiceChar               abcorr  [ CORLEN ];
      SpiceChar               file    [ FILSIZ ];
      SpiceChar               filtyp  [ TYPLEN ];
      SpiceChar               occbdy  [ NAMLEN ];
      SpiceChar               source  [ FILSIZ ];
      SpiceChar               srfpt   [ NAMLEN ];
      SpiceChar               start   [ TIMLEN ];
      SpiceChar               stop    [ TIMLEN ];
      SpiceChar               target  [ NAMLEN ];
      SpiceChar               timstr  [ TIMLEN ];
      SpiceChar             * tsttim  [2];
 
      SpiceDouble             az;
      SpiceDouble             el;
      SpiceDouble             elvlim;
      SpiceDouble             et;
      SpiceDouble             etbeg;
      SpiceDouble             etend;
      SpiceDouble             r;
      SpiceDouble             revlim;
 
      SpiceInt                handle;
      SpiceInt                i;
      SpiceInt                n;
      SpiceInt                nker;
 
 
      /*
      Load the meta-kernel.
      */
      furnsh_c ( META );
 
      /*
      Look up observation location, target, name of the
      occulting body, aberration correction, start
      and stop times, and elevation limit.
 
      We simplify error checking by using badkpv_c.  badkpv_c
      tests whether a kernel variable having specified
      attributes is present in the kernel pool. The fourth
      argument of badkpv_c is the expected dimension; the
      last indicates the expected data type.  Read the
      header of badkpv_c for details.
      */
      badkpv_c ( "scview", SRFLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", OCCLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", TRGLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", CORLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STRLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STPLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", ELVLBL, "=",  1,      1, 'N' );
 
      /*
      Now we know the kernel variables of interest have been
      defined; look up the values.  We don't need to check
      the found flag because badkpv_c has ensured that each item
      will be found.
      */
      gcpool_c ( SRFLBL, 0, 1,      NAMLEN, &n,    srfpt,   &found );
      gcpool_c ( OCCLBL, 0, 1,      NAMLEN, &n,    occbdy,  &found );
      gcpool_c ( TRGLBL, 0, 1,      NAMLEN, &n,    target,  &found );
      gcpool_c ( CORLBL, 0, 1,      CORLEN, &n,    abcorr,  &found );
      gcpool_c ( STRLBL, 0, 1,      TIMLEN, &n,    start,   &found );
      gcpool_c ( STPLBL, 0, 1,      TIMLEN, &n,    stop,    &found );
      gdpool_c ( ELVLBL, 0, 1,              &n,    &elvlim, &found );
 
      revlim = rpd_c() * elvlim;
 
      /*
      Display to standard output a banner for the output report:
      */
      printf ( "\n%s\n\n",
               "Inputs for geometric event finding program" );
 
      printf ( "   Target                       = %s\n", target  );
      printf ( "   Observation surface location = %s\n", srfpt   );
      printf ( "   Occulting body               = %s\n", occbdy  );
      printf ( "   Aberration correction        = %s\n", abcorr  );
 
      /*
      Convert the start and stop times to ET.
      */
      str2et_c ( start, &etbeg );
      str2et_c ( stop,  &etend );
 
      /*
      Display the start time as both calendar ET and
      calendar UTC using the formats shown below.
 
         2004 MAY 06 20:15:00.000 (UTC)
         2004 MAY 06 20:15:00.000 (TDB)
      */
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      /*
      Display the elevation limit in degrees.
      */
      printf ( "   Elevation limit (degrees)    = %f\n", elvlim  );
 
 
      /*
      Display the names of the SPICE kernels we've loaded.
      */
      printf ( "\n"
               "Loaded SPICE Kernels:\n"  );
 
      ktotal_c ( "ALL", &nker );
 
      for ( i = 0;  i < nker;  i++  )
      {
         kdata_c ( i,     "ALL",   FILSIZ,  TYPLEN,   FILSIZ,
                   file,  filtyp,  source,  &handle,  &found );
 
         /*
         Due to the way we've constructed the loop, there's
         no need to check the 'found' flag.
         */
         printf ( "\n"
                  "   Kernel name:    %s\n"
                  "   Kernel type:    %s\n"
                  "   Kernel source:  %s\n",
                  file,
                  filtyp,
                  source                      );
      }
 
      printf ( "\n"
               "srfazl test results:\n"
               "\n"                     );
 
      /*
      Test srfazl:  make two calls at times bracketing
      a spacecraft "rise" event.
      */
      tsttim[0] = "2004 MAY 01 16:10:26.686 TDB";
      tsttim[1] = "2004 MAY 01 16:10:26.688 TDB";
 
      for ( i = 0;  i < 2;  i++ )
      {
         /*
         Convert the TDB calendar time to seconds past J2000.
         Find the azimuth, elevation, and range at this time.
         */
         str2et_c ( tsttim[i], &et );
         srfazl   ( srfpt, et, abcorr, target, &az, &el, &r );
 
         /*
         Display the time and srfazl outputs.  Convert radians
         to degrees for output using the CSPICE function dpr_c().
         */
         printf ( "   ET = %s\n"
                  "      Elevation (degrees):  %21.16e\n"
                  "      Azimuth   (degrees):  %21.16e\n"
                  "      Range     (km):       %21.16e\n"
                  "\n",
                  tsttim[i],
                  el * dpr_c(),
                  az * dpr_c(),
                  r                                       );
      }
 
      return ( 0 );
   }


Solution Sample Output



Numerical results shown for this example may differ across platforms since the results depend on the SPICE kernels used as input and on the host platform's arithmetic implementation.

 
   Inputs for geometric event finding program
 
      Target                       = MEX
      Observation surface location = DSS-14
      Aberration correction        = CN+S
      Start time                   = 2004 APR 30 23:58:55.814 (UTC)
      Start time                   = 2004 MAY 01 00:00:00.000 (TDB)
      Stop time                    = 2004 MAY 04 23:58:55.814 (UTC)
      Stop time                    = 2004 MAY 05 00:00:00.000 (TDB)
      Elevation limit (degrees)    = 6.000000
 
   Loaded SPICE Kernels:
 
      Kernel name:    geomevnt.mk
      Kernel type:    META
      Kernel source:
 
      Kernel name:    de405s.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    dsnstns.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    DSN_topo.frm
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    earth_031228_231229_predict.bpc
      Kernel type:    PCK
      Kernel source:  geomevnt.mk
 
      Kernel name:    naif0007.tls
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    ORMM__040501000000_00069.BSP
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    pck00007.tpc
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
   srfazl test results:
 
      ET = 2004 MAY 01 16:10:26.686 TDB
         Elevation (degrees):  5.9999951213034e+00
         Azimuth   (degrees):  6.3942106540558e+01
         Range     (km):       3.2480333721584e+08
 
      ET = 2004 MAY 01 16:10:26.688 TDB
         Elevation (degrees):  6.0000012274140e+00
         Azimuth   (degrees):  6.3942111060397e+01
         Range     (km):       3.2480333724230e+08
 


Test for Occultation of Point Target







Task Statement




Write a SpiceBoolean function to test when a point target is occulted by a specified extended body, as seen from a specified observing body.

The function is to have the exact signature shown below:

   SpiceBoolean occpt ( ConstSpiceChar    * target,
                        ConstSpiceChar    * occbdy,
                        SpiceDouble         et,
                        ConstSpiceChar    * abcorr,
                        ConstSpiceChar    * obsrvr  );
The meanings of the arguments are as follows:

   target     Target name.
   occbdy     Occulting body name.
   et         Computation epoch, seconds past J2000 TDB.
   abcorr     Aberration correction flag: "none", "lt+s", etc.
   obsrvr     Observing body name.
   occpt      SpiceBoolean function value:  SPICETRUE if the target
              is occulted; SPICEFALSE otherwise.
This function will be used by the supplied event finding utilities to find times when the target is occulted by the specified occulting body.

Test the routine by calling it twice and displaying the outputs. The first call should use the input values:

   target     "MEX"
   occbdy     "MARS"
   et         Double precision count of seconds past J2000 TDB
              corresponding to 2004 MAY 01 13:38:36.740 TDB
   abcorr     "CN+S"
   obsrvr     "DSS-14"
The second call should use the same inputs as the first, except that the time should be the double precision count of seconds past J2000 TDB corresponding to 2004 MAY 01 13:38:36.742 TDB.

The two times are intended to bracket a spacecraft occultation ingress event: the aberration-corrected target spacecraft location should be visible at the first time and occulted at the second.



Learning Goals




This exercise introduces the student to further elementary geometry computations using CSPICE. The student uses spkpos_c to look up position vectors and srfxpt_c to test whether a specified ray intersects an extended body modeled as a triaxial ellipsoid.

This exercise is meant to provide the student with further understanding of the geometry computations involved in an event finding system.



Approach






Solution steps



A possible solution would consist of the following steps:

Write the occpt function:

Add test code to the main program:



Solution






Solution Code



The example program below shows one possible solution.

 
      #include "SpiceUsr.h"
 
      SpiceBoolean occpt ( ConstSpiceChar    * target,
                           ConstSpiceChar    * occbdy,
                           SpiceDouble         et,
                           ConstSpiceChar    * abcorr,
                           ConstSpiceChar    * obsrvr  )
 
      /*
      Determine whether a point target is occulted by extended
      body, as seen from a specified observation location.
 
 
      Subroutine arguments:
 
 
         target        is a string giving the name of the target
                       body of interest
 
         occbdy        is a string giving the name of a potentially
                       occulting extended body.
 
         et            is the epoch at which the visibility
                       computation is to be performed.  et is
                       given in seconds past J2000 (TDB).
 
         abcorr        indicates the aberration correction.
                       Values and meanings are:
 
                          "NONE"   No correction.  Use geometric
                                   states.
 
                         The following are for the "reception"
                         case where radiation travels from the
                         target body and arrives at the observer
                         at ET:
 
                          "LT"     Correct for one-way light time.
 
                          "LT+S"   Correct for one-way light time
                                   and stellar aberration.
 
                          "CN"     Converged Newtonian light time
                                   correction.
 
                          "CN+S"   Converged Newtonian light time
                                   and stellar aberration
                                   corrections.
 
 
                         The following are for the "transmission"
                         case where radiation travels from the
                         observer to the target body, departing the
                         observer's location at et:
 
                          "XLT"    Correct for one-way light time.
 
                          "XLT+S"  Correct for one-way light time
                                   and stellar aberration.
 
                          "XCN"    Converged Newtonian light time
                                   correction.
 
                          "XCN+S"  Converged Newtonian light time
                                   and stellar aberration
                                   corrections.
 
         obsrvr        is a string containing the observer's name.
 
 
      The function returns SPICETRUE if the target is occulted and
      SPICEFALSE otherwise.
 
         07-MAY-2004 (NJB)
 
            Updated to use srfxpt_c.
 
         31-OCT-2002 (NJB)
      */
   {
 
 
      /*
      Local constants
      */
      #define FRNMLN          33
 
      /*
      Local variables
      */
      SpiceBoolean            found;
 
      SpiceDouble             dist;
      SpiceDouble             obspos [3];
      SpiceDouble             trgepc;
      SpiceDouble             trglt;
      SpiceDouble             trgpos [3];
      SpiceDouble             xpt    [3];
 
      if ( return_c() )
      {
         return ( SPICEFALSE );
      }
      chkin_c ( "occpt" );
 
 
      /*
      Find the position of the target relative to the observer,
      using the specified aberration corrections.  Use the J2000
      reference frame.
      */
      spkpos_c ( target, et,    "J2000", abcorr,
                 obsrvr, trgpos, &trglt         );
 
      /*
      Determine the surface intercept (if any) with the
      occulting body of the ray emanating from the observer and
      pointing toward the target.
      */
      srfxpt_c ( "Ellipsoid",  occbdy,   et,      abcorr,
                 obsrvr,       "J2000",  trgpos,  xpt,
                 &dist,        &trgepc,  obspos,  &found );
 
      if ( !found )
      {
         /*
         If there's no intercept, the target is not occulted.
         We're done.
         */
         chkout_c ( "occpt" );
 
         return ( SPICEFALSE );
      }
 
      /*
      At this point, we know there's an intercept.  If the target
      lies between the observer and the intercept point, the target
      is still visible.  Otherwise, the target is occulted.
      */
      chkout_c ( "occpt" );
 
      return (  (  SpiceBoolean  )
                (  vnorm_c(trgpos)  >  dist  )   );
   }


Solution: Add Test Code to the Main Program



The example program below shows one possible solution.

 
      #include <stdio.h>
      #include <math.h>
      #include "SpiceUsr.h"
 
 
      /*
      PROGRAM SCVIEW
 
      Find the view periods for a point target as seen from a
      specified surface location.  Exclude periods when target
      is occulted by extended bodies other than the one associated
      with the viewing location. Display the windows of visibility.
 
      The following items are loaded from a SPICE text kernel:
 
         - Observer (surface point) name
         - Target name
         - Occulting body name
         - Aberration correction specification
         - Start time string
         - Stop time #include <string.h>
         - Elevation limit (in degrees)
 
      This program assumes all necessary kernels and kernel
      variable definitions are specified in a SPICE  meta-kernel.
      The meta-kernel name is assumed to be 'geomevnt.mk'.
 
        07-MAY-2004 (NJB)
 
        31-OCT-2002 (NJB)
 
      */
 
   int main()
   {
 
      /*
      Prototypes
      */
      SpiceBoolean occpt  ( ConstSpiceChar   * target,
                            ConstSpiceChar   * occbdy,
                            SpiceDouble        et,
                            ConstSpiceChar   * abcorr,
                            ConstSpiceChar   * obsrvr  );
 
      void         srfazl ( ConstSpiceChar   * srfpt,
                            SpiceDouble        et,
                            ConstSpiceChar   * abcorr,
                            ConstSpiceChar   * targ,
                            SpiceDouble      * az,
                            SpiceDouble      * el,
                            SpiceDouble      * r      );
      /*
      Local constants
      */
 
      /*
      The  meta-kernel:
      */
      #define META            "geomevnt.mk"
 
 
      /*
      Labels of kernel pool items:
      */
      #define CORLBL          "SCVIEW_ABCORR"
      #define ELVLBL          "SCVIEW_ELVLIM"
      #define OCCLBL          "SCVIEW_OCCBDY"
      #define SRFLBL          "SCVIEW_SRFPT"
      #define STPLBL          "SCVIEW_STOP"
      #define STRLBL          "SCVIEW_START"
      #define TRGLBL          "SCVIEW_TARGET"
 
 
      /*
      STEPSZ is the step size, measured in seconds, used to search
      for times bracketing a state transition.
      */
      #define STEPSZ          (300.0)
 
      /*
      Maximum number of events we can handle in our event set:
      */
      #define MAXEVT          1000
 
      /*
      Maximum result window size:
      */
      #define MAXWIN          ( 2 * MAXEVT )
 
      /*
      String lengths and other bounds:
      */
      #define CORLEN          11
      #define FILSIZ          256
      #define LNSIZE          201
      #define NAMLEN          33
      #define TIMLEN          51
      #define TYPLEN          51
 
      /*
      Local variables
      */
      SpiceBoolean            found;
      SpiceBoolean            hidden;
 
      SpiceChar               abcorr  [ CORLEN ];
      SpiceChar               file    [ FILSIZ ];
      SpiceChar               filtyp  [ TYPLEN ];
      SpiceChar               occbdy  [ NAMLEN ];
      SpiceChar               source  [ FILSIZ ];
      SpiceChar               srfpt   [ NAMLEN ];
      SpiceChar               start   [ TIMLEN ];
      SpiceChar               stop    [ TIMLEN ];
      SpiceChar               target  [ NAMLEN ];
      SpiceChar               timstr  [ TIMLEN ];
      SpiceChar             * tsttim  [2];
 
      SpiceDouble             az;
      SpiceDouble             el;
      SpiceDouble             elvlim;
      SpiceDouble             et;
      SpiceDouble             etbeg;
      SpiceDouble             etend;
      SpiceDouble             r;
      SpiceDouble             revlim;
 
      SpiceInt                handle;
      SpiceInt                i;
      SpiceInt                n;
      SpiceInt                nker;
 
 
      /*
      Load the meta-kernel.
      */
      furnsh_c ( META );
 
      /*
      Look up observation location, target, name of the
      occulting body, aberration correction, start
      and stop times, and elevation limit.
 
      We simplify error checking by using badkpv_c.  badkpv_c
      tests whether a kernel variable having specified
      attributes is present in the kernel pool. The fourth
      argument of badkpv_c is the expected dimension; the
      last indicates the expected data type.  Read the
      header of badkpv_c for details.
      */
      badkpv_c ( "scview", SRFLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", OCCLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", TRGLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", CORLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STRLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STPLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", ELVLBL, "=",  1,      1, 'N' );
 
      /*
      Now we know the kernel variables of interest have been
      defined; look up the values.  We don't need to check
      the found flag because badkpv_c has ensured that each item
      will be found.
      */
      gcpool_c ( SRFLBL, 0, 1,      NAMLEN, &n,    srfpt,   &found );
      gcpool_c ( OCCLBL, 0, 1,      NAMLEN, &n,    occbdy,  &found );
      gcpool_c ( TRGLBL, 0, 1,      NAMLEN, &n,    target,  &found );
      gcpool_c ( CORLBL, 0, 1,      CORLEN, &n,    abcorr,  &found );
      gcpool_c ( STRLBL, 0, 1,      TIMLEN, &n,    start,   &found );
      gcpool_c ( STPLBL, 0, 1,      TIMLEN, &n,    stop,    &found );
      gdpool_c ( ELVLBL, 0, 1,              &n,    &elvlim, &found );
 
      revlim = rpd_c() * elvlim;
 
      /*
      Display to standard output a banner for the output report:
      */
      printf ( "\n%s\n\n",
               "Inputs for geometric event finding program" );
 
      printf ( "   Target                       = %s\n", target  );
      printf ( "   Observation surface location = %s\n", srfpt   );
      printf ( "   Occulting body               = %s\n", occbdy  );
      printf ( "   Aberration correction        = %s\n", abcorr  );
 
      /*
      Convert the start and stop times to ET.
      */
      str2et_c ( start, &etbeg );
      str2et_c ( stop,  &etend );
 
      /*
      Display the start time as both calendar ET and
      calendar UTC using the formats shown below.
 
         2004 MAY 06 20:15:00.000 (UTC)
         2004 MAY 06 20:15:00.000 (TDB)
      */
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      /*
      Display the elevation limit in degrees.
      */
      printf ( "   Elevation limit (degrees)    = %f\n", elvlim  );
 
 
      /*
      Display the names of the SPICE kernels we've loaded.
      */
      printf ( "\n"
               "Loaded SPICE Kernels:\n"  );
 
      ktotal_c ( "ALL", &nker );
 
      for ( i = 0;  i < nker;  i++  )
      {
         kdata_c ( i,     "ALL",   FILSIZ,  TYPLEN,   FILSIZ,
                   file,  filtyp,  source,  &handle,  &found );
 
         /*
         Due to the way we've constructed the loop, there's
         no need to check the 'found' flag.
         */
         printf ( "\n"
                  "   Kernel name:    %s\n"
                  "   Kernel type:    %s\n"
                  "   Kernel source:  %s\n",
                  file,
                  filtyp,
                  source                      );
      }
 
 
      /*
      Test srfazl:  make two calls at times bracketing
      a spacecraft "rise" event.
      */
      printf ( "\n"
               "srfazl test results:\n"
               "\n"                     );
 
      tsttim[0] = "2004 MAY 01 16:10:26.686 TDB";
      tsttim[1] = "2004 MAY 01 16:10:26.688 TDB";
 
      for ( i = 0;  i < 2;  i++ )
      {
         /*
         Convert the TDB calendar time to seconds past J2000.
         Find the azimuth, elevation, and range at this time.
         */
         str2et_c ( tsttim[i], &et );
         srfazl   ( srfpt, et, abcorr, target, &az, &el, &r );
 
         /*
         Display the time and outputs from srfazl.  Convert radians
         to degrees for output using the CSPICE function dpr_c().
         */
         printf ( "   ET = %s\n"
                  "      Elevation (degrees):  %21.16e\n"
                  "      Azimuth   (degrees):  %21.16e\n"
                  "      Range     (km):       %21.16e\n"
                  "\n",
                  tsttim[i],
                  el * dpr_c(),
                  az * dpr_c(),
                  r                                       );
      }
 
 
      /*
      Test occpt:  make two calls at times bracketing
      a spacecraft occultation ingress event.
      */
      printf ( "occpt test results:\n"
               "\n"                     );
 
      tsttim[0] = "2004 MAY 01 13:38:36.740 TDB";
      tsttim[1] = "2004 MAY 01 13:38:36.742 TDB";
 
      for ( i = 0;  i < 2;  i++ )
      {
         /*
         Convert the TDB calendar time to seconds past J2000.
         */
         str2et_c ( tsttim[i], &et );
         hidden = occpt ( target, occbdy, et, abcorr, srfpt );
 
         /*
         Display the time and occultation state.
         */
         if ( hidden )
         {
             printf ( "   ET = %s.  Occulted.\n",     tsttim[i] );
         }
         else
         {
             printf ( "   ET = %s.  Not occulted.\n",  tsttim[i] );
         }
      }
 
      printf ( "\n" );
 
      return ( 0 );
   }


Solution Sample Output



Numerical results shown for this example may differ across platforms since the results depend on the SPICE kernels used as input and on the host platform's arithmetic implementation.

 
   Inputs for geometric event finding program
 
      Target                       = MEX
      Observation surface location = DSS-14
      Aberration correction        = CN+S
      Start time                   = 2004 APR 30 23:58:55.814 (UTC)
      Start time                   = 2004 MAY 01 00:00:00.000 (TDB)
      Stop time                    = 2004 MAY 04 23:58:55.814 (UTC)
      Stop time                    = 2004 MAY 05 00:00:00.000 (TDB)
      Elevation limit (degrees)    = 6.000000
 
   Loaded SPICE Kernels:
 
      Kernel name:    geomevnt.mk
      Kernel type:    META
      Kernel source:
 
      Kernel name:    de405s.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    dsnstns.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    DSN_topo.frm
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    earth_031228_231229_predict.bpc
      Kernel type:    PCK
      Kernel source:  geomevnt.mk
 
      Kernel name:    naif0007.tls
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    ORMM__040501000000_00069.BSP
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    pck00007.tpc
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
   srfazl test results:
 
      ET = 2004 MAY 01 16:10:26.686 TDB
         Elevation (degrees):  5.9999951213034e+00
         Azimuth   (degrees):  6.3942106540558e+01
         Range     (km):       3.2480333721584e+08
 
      ET = 2004 MAY 01 16:10:26.688 TDB
         Elevation (degrees):  6.0000012274140e+00
         Azimuth   (degrees):  6.3942111060397e+01
         Range     (km):       3.2480333724230e+08
 
   occpt test results:
 
      ET = 2004 MAY 01 13:38:36.740 TDB.  Not occulted.
      ET = 2004 MAY 01 13:38:36.742 TDB.  Occulted.
 


Find Times when Target is Above the Elevation Limit







Task Statement




Extend the program of the previous chapter to find times when the target object is above the 6 degree elevation limit in the topocentric frame associated with the specified surface point.

Store the set of time intervals when the target is visible in a CSPICE window. We'll call this the ``result window.''

Display each of the intervals in the result window as a pair of start and stop times. Express each time as a TDB calendar date using the same format as in the previous program.



Learning Goals




The student is introduced to topocentric frames and the CSPICE calls required to compute azimuth and elevation of a vector expressed in a topocentric frame.

The student is introduced to a few of the most used CSPICE cell, set and window functions.

The student is introduced to some elementary root-finding techniques. Some aspects of root-finding are widely applicable, such as selecting a search step size or a root-finding convergence tolerance. In addition, manipulation of CSPICE cells, sets, and windows is quite useful for solving more complex root-finding problems, such as finding times when Boolean combinations of geometric criteria are satisfied.

The non-CSPICE utility routines presented here are not emphasized, in part because these utilities unofficial, and more importantly because the planned CSPICE geometric event finding software will replace the utilities presented here.



Approach






Solution steps



A possible solution would consist of the following steps:

            fndevt ( etbeg, etend, stepsz, &stris, &evtset );
            makwin ( etbeg, etend, &stris, &evtset, &riswin );


Solution






Solution Code



The example program below shows one possible solution.

 
      #include <stdio.h>
      #include <math.h>
      #include "SpiceUsr.h"
 
 
      /*
      PROGRAM SCVIEW
 
      Find the view periods for a point target as seen from a
      specified surface location.  Exclude periods when target
      is occulted by extended bodies other than the one associated
      with the viewing location. Display the windows of visibility.
 
      The following items are loaded from a SPICE text kernel:
 
         - Observer (surface point) name
         - Target name
         - Occulting body name
         - Aberration correction specification
         - Start time string
         - Stop time #include <string.h>
         - Elevation limit (in degrees)
 
      This program assumes all necessary kernels and kernel
      variable definitions are specified in a SPICE  meta-kernel.
      The meta-kernel name is assumed to be 'geomevnt.mk'.
 
      Find and display the window of times when the target is
      above the elevation limit in the observer's topocentric
      reference frame.
 
 
 
        07-MAY-2004 (NJB)
 
        31-OCT-2002 (NJB)
 
      */
 
   int main()
   {
 
      /*
      Prototypes
      */
      void         fndevt ( SpiceDouble        etbeg,
                            SpiceDouble        etend,
                            SpiceDouble        step,
                            SpiceBoolean    (* statef)(SpiceDouble),
                            SpiceCell        * xset                 );
 
      void         makwin ( SpiceDouble        etbeg,
                            SpiceDouble        etend,
                            SpiceBoolean    (* fstate)(SpiceDouble),
                            SpiceCell        * evtset,
                            SpiceCell        * evtwin               );
 
      SpiceBoolean occpt ( ConstSpiceChar    * target,
                           ConstSpiceChar    * occbdy,
                           SpiceDouble         et,
                           ConstSpiceChar    * abcorr,
                           ConstSpiceChar    * obsrvr  );
 
 
      void         setris ( ConstSpiceChar   * srfpt,
                            ConstSpiceChar   * abcorr,
                            ConstSpiceChar   * target,
                            SpiceDouble        revlim );
 
      void         srfazl ( ConstSpiceChar   * srfpt,
                            SpiceDouble        et,
                            ConstSpiceChar   * abcorr,
                            ConstSpiceChar   * targ,
                            SpiceDouble      * az,
                            SpiceDouble      * el,
                            SpiceDouble      * r      );
 
      SpiceBoolean stris  ( SpiceDouble        et );
 
 
      /*
      Local constants
      */
 
      /*
      The  meta-kernel:
      */
      #define META            "geomevnt.mk"
 
 
      /*
      Labels of kernel pool items:
      */
      #define CORLBL          "SCVIEW_ABCORR"
      #define ELVLBL          "SCVIEW_ELVLIM"
      #define OCCLBL          "SCVIEW_OCCBDY"
      #define SRFLBL          "SCVIEW_SRFPT"
      #define STPLBL          "SCVIEW_STOP"
      #define STRLBL          "SCVIEW_START"
      #define TRGLBL          "SCVIEW_TARGET"
 
 
      /*
      STEPSZ is the step size, measured in seconds, used to search
      for times bracketing a state transition.
      */
      #define STEPSZ          (300.0)
 
      /*
      Maximum number of events we can handle in our event set:
      */
      #define MAXEVT          1000
 
      /*
      Maximum result window size:
      */
      #define MAXWIN          ( 2 * MAXEVT )
 
      /*
      String lengths and other bounds:
      */
      #define CORLEN          11
      #define FILSIZ          256
      #define LNSIZE          201
      #define NAMLEN          33
      #define TIMLEN          51
      #define TYPLEN          51
 
      /*
      Local variables
      */
      SpiceBoolean            found;
      SpiceBoolean            hidden;
 
      SpiceChar               abcorr  [ CORLEN ];
      SpiceChar               file    [ FILSIZ ];
      SpiceChar               filtyp  [ TYPLEN ];
      SpiceChar               occbdy  [ NAMLEN ];
      SpiceChar               source  [ FILSIZ ];
      SpiceChar               srfpt   [ NAMLEN ];
      SpiceChar               start   [ TIMLEN ];
      SpiceChar               stop    [ TIMLEN ];
      SpiceChar               target  [ NAMLEN ];
      SpiceChar               timstr  [ TIMLEN ];
      SpiceChar             * tsttim  [2];
 
      /*
      The event set.
      */
      SPICEDOUBLE_CELL        ( evtset, MAXEVT );
 
      /*
      Windows to hold sets of times when
 
         - target is occulted
         - target is above the elevation limit
         - target is visible
      */
      SPICEDOUBLE_CELL        ( riswin, MAXWIN );
 
      SpiceDouble             az;
      SpiceDouble             el;
      SpiceDouble             elvlim;
      SpiceDouble             et;
      SpiceDouble             etbeg;
      SpiceDouble             etend;
      SpiceDouble             intbeg;
      SpiceDouble             intend;
      SpiceDouble             r;
      SpiceDouble             revlim;
 
      SpiceInt                handle;
      SpiceInt                i;
      SpiceInt                n;
      SpiceInt                nker;
      SpiceInt                winsiz;
 
 
      /*
      Load the meta-kernel.
      */
      furnsh_c ( META );
 
      /*
      Look up observation location, target, name of the
      occulting body, aberration correction, start
      and stop times, and elevation limit.
 
      We simplify error checking by using badkpv_c.  badkpv_c
      tests whether a kernel variable having specified
      attributes is present in the kernel pool. The fourth
      argument of badkpv_c is the expected dimension; the
      last indicates the expected data type.  Read the
      header of badkpv_c for details.
     */
      badkpv_c ( "scview", SRFLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", TRGLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", OCCLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", CORLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STRLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STPLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", ELVLBL, "=",  1,      1, 'N' );
 
      /*
      Now we know the kernel variables of interest have been
      defined; look up the values.  We don't need to check
      the found flag because badkpv_c has ensured the item
      will be found.
      */
      gcpool_c ( SRFLBL, 0, 1,      NAMLEN, &n,    srfpt,   &found );
      gcpool_c ( TRGLBL, 0, 1,      NAMLEN, &n,    target,  &found );
      gcpool_c ( OCCLBL, 0, 1,      NAMLEN, &n,    occbdy,  &found );
      gcpool_c ( CORLBL, 0, 1,      CORLEN, &n,    abcorr,  &found );
      gcpool_c ( STRLBL, 0, 1,      TIMLEN, &n,    start,   &found );
      gcpool_c ( STPLBL, 0, 1,      TIMLEN, &n,    stop,    &found );
      gdpool_c ( ELVLBL, 0, 1,              &n,    &elvlim, &found );
 
      revlim = rpd_c() * elvlim;
 
      /*
      Display to standard output a banner for the output report:
      */
      printf ( "\n%s\n\n",
               "Inputs for geometric event finding program" );
 
      printf ( "   Target                       = %s\n", target  );
      printf ( "   Observation surface location = %s\n", srfpt   );
      printf ( "   Occulting body               = %s\n", occbdy  );
      printf ( "   Aberration correction        = %s\n", abcorr  );
 
      /*
      Convert the start and stop times to ET.
      */
      str2et_c ( start, &etbeg );
      str2et_c ( stop,  &etend );
 
      /*
      Display the start time as both calendar ET and
      calendar UTC using the formats shown below.
 
         2004 MAY 06 20:15:00.000 (UTC)
         2004 MAY 06 20:15:00.000 (TDB)
      */
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      /*
      Display the elevation limit in degrees.
      */
      printf ( "   Elevation limit (degrees)    = %f\n", elvlim  );
 
 
      /*
      Display the names of the SPICE kernels we've loaded.
      */
      printf ( "\n"
               "Loaded SPICE Kernels:\n"  );
 
      ktotal_c ( "ALL", &nker );
 
      for ( i = 0;  i < nker;  i++  )
      {
         kdata_c ( i,     "ALL",   FILSIZ,  TYPLEN,   FILSIZ,
                   file,  filtyp,  source,  &handle,  &found );
 
         /*
         Due to the way we've constructed the loop, there's
         no need to check the 'found' flag.
         */
         printf ( "\n"
                  "   Kernel name:    %s\n"
                  "   Kernel type:    %s\n"
                  "   Kernel source:  %s\n",
                  file,
                  filtyp,
                  source                      );
      }
 
 
      /*
      Test srfazl:  make two calls at times bracketing
      a spacecraft "rise" event.
      */
      printf ( "\n"
               "srfazl test results:\n"
               "\n"                     );
 
      tsttim[0] = "2004 MAY 01 16:10:26.686 TDB";
      tsttim[1] = "2004 MAY 01 16:10:26.688 TDB";
 
      for ( i = 0;  i < 2;  i++ )
      {
         /*
         Convert the TDB calendar time to seconds past J2000.
         Find the azimuth, elevation, and range at this time.
         */
         str2et_c ( tsttim[i], &et );
         srfazl   ( srfpt, et, abcorr, target, &az, &el, &r );
 
         /*
         Display the time and outputs from srfazl.  Convert radians
         to degrees for output using the CSPICE function dpr_c().
         */
         printf ( "   ET = %s\n"
                  "      Elevation (degrees):  %21.16e\n"
                  "      Azimuth   (degrees):  %21.16e\n"
                  "      Range     (km):       %21.16e\n"
                  "\n",
                  tsttim[i],
                  el * dpr_c(),
                  az * dpr_c(),
                  r                                       );
      }
 
 
      /*
      Test occpt:  make two calls at times bracketing
      a spacecraft occultation ingress event.
      */
      printf ( "occpt test results:\n"
               "\n"                     );
 
      tsttim[0] = "2004 MAY 01 13:38:36.740 TDB";
      tsttim[1] = "2004 MAY 01 13:38:36.742 TDB";
 
      for ( i = 0;  i < 2;  i++ )
      {
         /*
         Convert the TDB calendar time to seconds past J2000.
         */
         str2et_c ( tsttim[i], &et );
         hidden = occpt ( target, occbdy, et, abcorr, srfpt );
 
         /*
         Display the time and occultation state.
         */
         if ( hidden )
         {
             printf ( "   ET = %s.  Occulted.\n",     tsttim[i] );
         }
         else
         {
             printf ( "   ET = %s.  Not occulted.\n",  tsttim[i] );
         }
      }
 
      printf ( "\n" );
 
 
      /*
      Set the parameters required by the rise/set state routine.
      */
      setris ( srfpt, abcorr, target, revlim );
 
      /*
      Locate the epochs where the target passes through elevation
      zero.  The SpiceBoolean function stris determines the "state"
      of the target:  SPICETRUE when the target's elevation is
      positive, SPICEFALSE otherwise.
      */
      fndevt ( etbeg, etend, STEPSZ, &stris, &evtset );
 
      /*
      Use the transition set to create a window of time intervals
      when the target is above the elevation limit at the
      surface point.
      */
      makwin ( etbeg, etend, &stris, &evtset, &riswin );
 
      /*
      Display the rise and set times.
      */
      printf ( "Rise and set times of %s as seen from %s:"
               "\n\n",
               target, srfpt                               );
 
 
      winsiz = card_c ( &riswin ) / 2;
 
      for (  i = 0;   i < winsiz;   i++  )
      {
         /*
         Fetch the Ith interval from the window.
         */
         wnfetd_c ( &riswin, i, &intbeg, &intend );
 
         /*
         Convert the transition time to a TDB calendar string.
         */
         timout_c ( intbeg,
                    "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                    TIMLEN,
                    timstr                                 );
 
         /*
         Write the string to standard output.
         */
         if ( i == 0 )
         {
            printf ( "Target rise time (or window start):  %s\n",
                      timstr                                      );
         }
         else
         {
            printf ( "Target rise time:                    %s\n",
                      timstr                                      );
         }
 
         timout_c ( intend,
                    "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                    TIMLEN,
                    timstr                                  );
 
         /*
         Write the string to standard output.
         */
         if ( i == winsiz-1 )
         {
            printf ( "Target set time (or window end):     %s\n",
                      timstr                                      );
         }
         else
         {
            printf ( "Target set time:                     %s\n",
                      timstr                                      );
         }
 
         printf ( "\n" );
      }
 
 
      return ( 0 );
   }


Solution Sample Output



Numerical results shown for this example may differ across platforms since the results depend on the SPICE kernels used as input and on the host platform's arithmetic implementation.

After compiling the program, execute it. The output is:

 
   Inputs for geometric event finding program
 
      Target                       = MEX
      Observation surface location = DSS-14
      Occulting body               = MARS
      Aberration correction        = CN+S
      Start time                   = 2004 APR 30 23:58:55.814 (UTC)
      Start time                   = 2004 MAY 01 00:00:00.000 (TDB)
      Stop time                    = 2004 MAY 04 23:58:55.814 (UTC)
      Stop time                    = 2004 MAY 05 00:00:00.000 (TDB)
      Elevation limit (degrees)    = 6.000000
 
   Loaded SPICE Kernels:
 
      Kernel name:    geomevnt.mk
      Kernel type:    META
      Kernel source:
 
      Kernel name:    de405s.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    dsnstns.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    DSN_topo.frm
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    earth_031228_231229_predict.bpc
      Kernel type:    PCK
      Kernel source:  geomevnt.mk
 
      Kernel name:    naif0007.tls
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    ORMM__040501000000_00069.BSP
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    pck00007.tpc
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
   srfazl test results:
 
      ET = 2004 MAY 01 16:10:26.686 TDB
         Elevation (degrees):  5.9999951213034e+00
         Azimuth   (degrees):  6.3942106540558e+01
         Range     (km):       3.2480333721584e+08
 
      ET = 2004 MAY 01 16:10:26.688 TDB
         Elevation (degrees):  6.0000012274140e+00
         Azimuth   (degrees):  6.3942111060397e+01
         Range     (km):       3.2480333724230e+08
 
   occpt test results:
 
      ET = 2004 MAY 01 13:38:36.740 TDB.  Not occulted.
      ET = 2004 MAY 01 13:38:36.742 TDB.  Occulted.
 
   Rise and set times of MEX as seen from DSS-14:
 
   Target rise time (or window start):  2004 MAY 01 00:00:00.000 (TDB)
   Target set time:                     2004 MAY 01 05:36:08.338 (TDB)
 
   Target rise time:                    2004 MAY 01 16:10:26.687 (TDB)
   Target set time:                     2004 MAY 02 05:35:03.020 (TDB)
 
   Target rise time:                    2004 MAY 02 16:09:14.024 (TDB)
   Target set time:                     2004 MAY 03 05:33:57.180 (TDB)
 
   Target rise time:                    2004 MAY 03 16:08:02.224 (TDB)
   Target set time:                     2004 MAY 04 05:32:50.686 (TDB)
 
   Target rise time:                    2004 MAY 04 16:06:51.203 (TDB)
   Target set time (or window end):     2004 MAY 05 00:00:00.000 (TDB)
 


Find Times when Target is Visible







Task Statement




Extend the program of the previous chapter to find times when the target object is:

Store the set of time intervals when the target is visible in a CSPICE window. We'll call this the ``result window.''

Display each of the intervals in the result window as a pair of start and stop times. Express each time as a TDB calendar date using the same format as in the previous program.



Learning Goals




The student gains further experience with the CSPICE cell, set and window functions, and with root finding techniques.



Approach






Solution steps



A possible solution would consist of the following steps:

            fndevt ( etbeg, etend, stepsz, &stocp, &evtset );
            makwin ( etbeg, etend, &stocp, &evtset, &occwin );
This completes the assignment.



Solution






Solution Code



 
      #include <stdio.h>
      #include <math.h>
      #include "SpiceUsr.h"
 
 
      /*
      PROGRAM SCVIEW
 
      Find the view periods for a point target as seen from a
      specified surface location.  Exclude periods when target
      is occulted by extended bodies other than the one associated
      with the viewing location. Display the windows of visibility.
 
      The following items are loaded from a SPICE text kernel:
 
         - Observer (surface point) name
         - Target name
         - Occulting body name
         - Aberration correction specification
         - Start time string
         - Stop time #include <string.h>
         - Elevation limit (in degrees)
 
      This program assumes all necessary kernels and kernel
      variable definitions are specified in a SPICE  meta-kernel.
      The meta-kernel name is assumed to be 'geomevnt.mk'.
 
      Find and display the window of times when the target is
      occulted as seen from the observer's location.
 
      Find and display the window of times when the target is
      above the elevation limit and not occulted.
 
 
        07-MAY-2004 (NJB)
 
        31-OCT-2002 (NJB)
 
      */
 
   int main()
   {
 
      /*
      Prototypes
      */
      void         fndevt ( SpiceDouble        etbeg,
                            SpiceDouble        etend,
                            SpiceDouble        step,
                            SpiceBoolean    (* statef)(SpiceDouble),
                            SpiceCell        * xset                 );
 
      void         makwin ( SpiceDouble        etbeg,
                            SpiceDouble        etend,
                            SpiceBoolean    (* fstate)(SpiceDouble),
                            SpiceCell        * evtset,
                            SpiceCell        * evtwin               );
 
      SpiceBoolean occpt ( ConstSpiceChar    * target,
                           ConstSpiceChar    * occbdy,
                           SpiceDouble         et,
                           ConstSpiceChar    * abcorr,
                           ConstSpiceChar    * obsrvr  );
 
      void         setocp ( ConstSpiceChar   * target,
                            ConstSpiceChar   * occbdy,
                            ConstSpiceChar   * abcorr,
                            ConstSpiceChar   * obsrvr );
 
      void         setris ( ConstSpiceChar   * srfpt,
                            ConstSpiceChar   * abcorr,
                            ConstSpiceChar   * target,
                            SpiceDouble        revlim );
 
      void         srfazl ( ConstSpiceChar   * srfpt,
                            SpiceDouble        et,
                            ConstSpiceChar   * abcorr,
                            ConstSpiceChar   * targ,
                            SpiceDouble      * az,
                            SpiceDouble      * el,
                            SpiceDouble      * r      );
 
      SpiceBoolean stocp  ( SpiceDouble        et );
 
      SpiceBoolean stris  ( SpiceDouble        et );
 
 
      /*
      Local constants
      */
 
      /*
      The  meta-kernel:
      */
      #define META            "geomevnt.mk"
 
 
      /*
      Labels of kernel pool items:
      */
      #define CORLBL          "SCVIEW_ABCORR"
      #define ELVLBL          "SCVIEW_ELVLIM"
      #define OCCLBL          "SCVIEW_OCCBDY"
      #define SRFLBL          "SCVIEW_SRFPT"
      #define STPLBL          "SCVIEW_STOP"
      #define STRLBL          "SCVIEW_START"
      #define TRGLBL          "SCVIEW_TARGET"
 
 
      /*
      STEPSZ is the step size, measured in seconds, used to search
      for times bracketing a state transition.
      */
      #define STEPSZ          (300.0)
 
      /*
      Maximum number of events we can handle in our event set:
      */
      #define MAXEVT          1000
 
      /*
      Maximum result window size:
      */
      #define MAXWIN          ( 2 * MAXEVT )
 
      /*
      String lengths and other bounds:
      */
      #define CORLEN          11
      #define FILSIZ          256
      #define LNSIZE          201
      #define NAMLEN          33
      #define TIMLEN          51
      #define TYPLEN          51
 
      /*
      Local variables
      */
      SpiceBoolean            found;
      SpiceBoolean            hidden;
 
      SpiceChar               abcorr  [ CORLEN ];
      SpiceChar               file    [ FILSIZ ];
      SpiceChar               filtyp  [ TYPLEN ];
      SpiceChar               occbdy  [ NAMLEN ];
      SpiceChar               source  [ FILSIZ ];
      SpiceChar               srfpt   [ NAMLEN ];
      SpiceChar               start   [ TIMLEN ];
      SpiceChar               stop    [ TIMLEN ];
      SpiceChar               target  [ NAMLEN ];
      SpiceChar               timstr  [ TIMLEN ];
      SpiceChar             * tsttim  [2];
 
      /*
      The event set.
      */
      SPICEDOUBLE_CELL        ( evtset, MAXEVT );
 
      /*
      Windows to hold sets of times when
 
         - target is occulted
         - target is above the elevation limit
         - target is visible
      */
      SPICEDOUBLE_CELL        ( occwin, MAXWIN );
      SPICEDOUBLE_CELL        ( riswin, MAXWIN );
      SPICEDOUBLE_CELL        ( viswin, MAXWIN );
 
      SpiceDouble             az;
      SpiceDouble             el;
      SpiceDouble             elvlim;
      SpiceDouble             et;
      SpiceDouble             etbeg;
      SpiceDouble             etend;
      SpiceDouble             intbeg;
      SpiceDouble             intend;
      SpiceDouble             r;
      SpiceDouble             revlim;
 
      SpiceInt                handle;
      SpiceInt                i;
      SpiceInt                n;
      SpiceInt                nker;
      SpiceInt                winsiz;
 
 
      /*
      Load the meta-kernel.
      */
      furnsh_c ( META );
 
      /*
      Look up observation location, target,  name of the
      occulting body, aberration correction, start
      and stop times, and elevation limit.
 
      We simplify error checking by using badkpv_c.  badkpv_c
      tests whether a kernel variable having specified
      attributes is present in the kernel pool. The fourth
      argument of badkpv_c is the expected dimension; the
      last indicates the expected data type.  Read the
      header of badkpv_c for details.
     */
      badkpv_c ( "scview", SRFLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", TRGLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", OCCLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", CORLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STRLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", STPLBL, "=",  1,      1, 'C' );
      badkpv_c ( "scview", ELVLBL, "=",  1,      1, 'N' );
 
      /*
      Now we know the kernel variables of interest have been
      defined; look up the values.  We don't need to check
      the found flag because badkpv_c has ensured the item
      will be found.
      */
      gcpool_c ( SRFLBL, 0, 1,      NAMLEN, &n,    srfpt,   &found );
      gcpool_c ( TRGLBL, 0, 1,      NAMLEN, &n,    target,  &found );
      gcpool_c ( OCCLBL, 0, 1,      NAMLEN, &n,    occbdy,  &found );
      gcpool_c ( CORLBL, 0, 1,      CORLEN, &n,    abcorr,  &found );
      gcpool_c ( STRLBL, 0, 1,      TIMLEN, &n,    start,   &found );
      gcpool_c ( STPLBL, 0, 1,      TIMLEN, &n,    stop,    &found );
      gdpool_c ( ELVLBL, 0, 1,              &n,    &elvlim, &found );
 
      revlim = rpd_c() * elvlim;
 
      /*
      Display to standard output a banner for the output report:
      */
      printf ( "\n%s\n\n",
               "Inputs for geometric event finding program" );
 
      printf ( "   Target                       = %s\n", target  );
      printf ( "   Observation surface location = %s\n", srfpt   );
      printf ( "   Occulting body               = %s\n", occbdy  );
      printf ( "   Aberration correction        = %s\n", abcorr  );
 
      /*
      Convert the start and stop times to ET.
      */
      str2et_c ( start, &etbeg );
      str2et_c ( stop,  &etend );
 
      /*
      Display the start time as both calendar ET and
      calendar UTC using the formats shown below.
 
         2004 MAY 06 20:15:00.000 (UTC)
         2004 MAY 06 20:15:00.000 (TDB)
      */
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etbeg,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Start time                   = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (UTC)",
                 TIMLEN,
                 timstr                            );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      timout_c ( etend,
                 "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                 TIMLEN,
                 timstr                                     );
 
      printf ( "   Stop time                    = %s\n", timstr  );
 
 
      /*
      Display the elevation limit in degrees.
      */
      printf ( "   Elevation limit (degrees)    = %f\n", elvlim  );
 
 
      /*
      Display the names of the SPICE kernels we've loaded.
      */
      printf ( "\n"
               "Loaded SPICE Kernels:\n"  );
 
      ktotal_c ( "ALL", &nker );
 
      for ( i = 0;  i < nker;  i++  )
      {
         kdata_c ( i,     "ALL",   FILSIZ,  TYPLEN,   FILSIZ,
                   file,  filtyp,  source,  &handle,  &found );
 
         /*
         Due to the way we've constructed the loop, there's
         no need to check the 'found' flag.
         */
         printf ( "\n"
                  "   Kernel name:    %s\n"
                  "   Kernel type:    %s\n"
                  "   Kernel source:  %s\n",
                  file,
                  filtyp,
                  source                      );
      }
 
 
      /*
      Test srfazl:  make two calls at times bracketing
      a spacecraft "rise" event.
      */
      printf ( "\n"
               "srfazl test results:\n"
               "\n"                     );
 
      tsttim[0] = "2004 MAY 01 16:10:26.686 TDB";
      tsttim[1] = "2004 MAY 01 16:10:26.688 TDB";
 
      for ( i = 0;  i < 2;  i++ )
      {
         /*
         Convert the TDB calendar time to seconds past J2000.
         Find the azimuth, elevation, and range at this time.
         */
         str2et_c ( tsttim[i], &et );
         srfazl   ( srfpt, et, abcorr, target, &az, &el, &r );
 
         /*
         Display the time and outputs from srfazl.  Convert radians
         to degrees for output using the CSPICE function dpr_c().
         */
         printf ( "   ET = %s\n"
                  "      Elevation (degrees):  %21.16e\n"
                  "      Azimuth   (degrees):  %21.16e\n"
                  "      Range     (km):       %21.16e\n"
                  "\n",
                  tsttim[i],
                  el * dpr_c(),
                  az * dpr_c(),
                  r                                       );
      }
 
 
      /*
      Test occpt:  make two calls at times bracketing
      a spacecraft occultation ingress event.
      */
      printf ( "occpt test results:\n"
               "\n"                     );
 
      tsttim[0] = "2004 MAY 01 13:38:36.740 TDB";
      tsttim[1] = "2004 MAY 01 13:38:36.742 TDB";
 
      for ( i = 0;  i < 2;  i++ )
      {
         /*
         Convert the TDB calendar time to seconds past J2000.
         */
         str2et_c ( tsttim[i], &et );
         hidden = occpt ( target, occbdy, et, abcorr, srfpt );
 
         /*
         Display the time and occultation state.
         */
         if ( hidden )
         {
             printf ( "   ET = %s.  Occulted.\n",     tsttim[i] );
         }
         else
         {
             printf ( "   ET = %s.  Not occulted.\n",  tsttim[i] );
         }
      }
 
      printf ( "\n" );
 
 
      /*
      Set the parameters required by the rise/set state routine.
      */
      setris ( srfpt, abcorr, target, revlim );
 
      /*
      Locate the epochs where the target passes through elevation
      zero.  The SpiceBoolean function stris determines the "state"
      of the target:  SPICETRUE when the target's elevation is
      positive, SPICEFALSE otherwise.
      */
      fndevt ( etbeg, etend, STEPSZ, &stris, &evtset );
 
      /*
      Use the transition set to create a window of time intervals
      when the target is above the elevation limit at the
      surface point.
      */
      makwin ( etbeg, etend, &stris, &evtset, &riswin );
 
      /*
      Display the rise and set times.
      */
      printf ( "\n\n"
               "Rise and set times of %s as seen from %s:"
               "\n\n",
               target, srfpt                               );
 
 
      winsiz = card_c ( &riswin ) / 2;
 
      for (  i = 0;   i < winsiz;   i++  )
      {
         /*
         Fetch the Ith interval from the window.
         */
         wnfetd_c ( &riswin, i, &intbeg, &intend );
 
         /*
         Convert the transition time to a TDB calendar string.
         */
         timout_c ( intbeg,
                    "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                    TIMLEN,
                    timstr                                 );
 
         /*
         Write the string to standard output.
         */
         if ( i == 0 )
         {
            printf ( "Target rise time (or window start):  %s\n",
                      timstr                                      );
         }
         else
         {
            printf ( "Target rise time:                    %s\n",
                      timstr                                      );
         }
 
         timout_c ( intend,
                    "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                    TIMLEN,
                    timstr                                  );
 
         /*
         Write the string to standard output.
         */
         if ( i == winsiz-1 )
         {
            printf ( "Target set time (or window end):     %s\n",
                      timstr                                      );
         }
         else
         {
            printf ( "Target set time:                     %s\n",
                      timstr                                      );
         }
 
         printf ( "\n" );
      }
 
 
      /*
      Now find the window of times when the target is occulted
      by the designated blocking body.
 
      Initialize the occultation finding utilities.
      */
      setocp ( target, occbdy, abcorr, srfpt );
 
      /*
      Locate the epochs where the target passes into or out
      of occultation by the occulting body.  These epochs
      will be returned as a CSPICE set.
      */
      fndevt ( etbeg, etend, STEPSZ, &stocp, &evtset );
 
      /*
      Make the set into a window of times when the target
      is occulted.
      */
      makwin ( etbeg, etend, &stocp, &evtset, &occwin );
 
      /*
      Display the set of times when the target is occulted.
      */
      printf ( "\n\n"
               "%s occultation of %s ---\n"
               "Ingress and egress times as seen from %s:\n\n",
               occbdy,
               target,
               srfpt                                          );
 
      winsiz = card_c ( &occwin ) / 2;
 
      for ( i = 0;  i < winsiz;  i++ )
      {
         wnfetd_c ( &occwin, i, &intbeg, &intend );
 
         /*
         Convert the transition times to TDB calendar strings.
         */
         timout_c ( intbeg,
                    "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                    TIMLEN,
                    timstr                                     );
 
         /*
         Write the string to standard output.
         */
         if ( i == 0 )
         {
            printf ( "Occ. ingress time (or window start): %s\n",
                      timstr                                      );
         }
         else
         {
            printf ( "Occultation ingress time:            %s\n",
                      timstr                                      );
         }
 
 
         timout_c ( intend,
                    "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                    TIMLEN,
                    timstr                                     );
 
         /*
         Write the string to standard output.
         */
         if ( i == winsiz-1 )
         {
            printf ( "Occ. egress time (or window end):    %s\n",
                      timstr                                      );
         }
         else
         {
            printf ( "Occultation egress time:             %s\n",
                      timstr                                      );
         }
 
         printf ( "\n" );
      }
 
 
      /*
      Find the visibility window by subtracting the occultation
      window from the rise-set window.  Display the result.
      */
      wndifd_c ( &riswin, &occwin, &viswin );
 
      /*
      Display the set of times when the target is visible.
      */
      printf ( "\n\n"
               "%s visibility start and stop times "
               "as seen from %s:\n\n",
               target,
               srfpt                                   );
 
 
      winsiz = card_c ( &viswin ) / 2;
 
      for ( i = 0;  i < winsiz;  i++ )
      {
         wnfetd_c ( &viswin, i, &intbeg, &intend );
 
         /*
         Convert the transition times to TDB calendar strings.
         */
         timout_c ( intbeg,
                    "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                    TIMLEN,
                    timstr                                     );
 
         /*
         Write the string to standard output.
         */
         if ( i == 0 )
         {
            printf ( "Vis. start time (or window start):   %s\n",
                      timstr                                      );
         }
         else
         {
            printf ( "Visibility start time:               %s\n",
                      timstr                                      );
         }
 
 
         timout_c ( intend,
                    "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                    TIMLEN,
                    timstr                                     );
 
         /*
         Write the string to standard output.
         */
         if ( i == winsiz-1 )
 
         {
            printf ( "Vis. end time (or window end):       %s\n",
                      timstr                                      );
         }
         else
         {
            printf ( "Visibility end time:                 %s\n",
                      timstr                                      );
         }
 
         timout_c ( intend,
                    "YYYY MON DD HR:MN:SC.### (TDB) ::TDB",
                    TIMLEN,
                    timstr                                     );
 
         printf ( "\n" );
      }
 
      return ( 0 );
   }


Solution Sample Output



Numerical results shown for this example may differ across platforms since the results depend on the SPICE kernels used as input and on the host platform's arithmetic implementation.

After compiling the program, execute it. The output is:

   Inputs for geometric event finding program
 
      Target                       = MEX
      Observation surface location = DSS-14
      Occulting body               = MARS
      Aberration correction        = CN+S
      Start time                   = 2004 APR 30 23:58:55.814 (UTC)
      Start time                   = 2004 MAY 01 00:00:00.000 (TDB)
      Stop time                    = 2004 MAY 04 23:58:55.814 (UTC)
      Stop time                    = 2004 MAY 05 00:00:00.000 (TDB)
      Elevation limit (degrees)    = 6.000000
 
   Loaded SPICE Kernels:
 
      Kernel name:    geomevnt.mk
      Kernel type:    META
      Kernel source:
 
      Kernel name:    de405s.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    dsnstns.bsp
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    DSN_topo.frm
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    earth_031228_231229_predict.bpc
      Kernel type:    PCK
      Kernel source:  geomevnt.mk
 
      Kernel name:    naif0007.tls
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
      Kernel name:    ORMM__040501000000_00069.BSP
      Kernel type:    SPK
      Kernel source:  geomevnt.mk
 
      Kernel name:    pck00007.tpc
      Kernel type:    TEXT
      Kernel source:  geomevnt.mk
 
   srfazl test results:
 
      ET = 2004 MAY 01 16:10:26.686 TDB
         Elevation (degrees):  5.9999951213034e+00
         Azimuth   (degrees):  6.3942106540558e+01
         Range     (km):       3.2480333721584e+08
 
      ET = 2004 MAY 01 16:10:26.688 TDB
         Elevation (degrees):  6.0000012274140e+00
         Azimuth   (degrees):  6.3942111060397e+01
         Range     (km):       3.2480333724230e+08
 
   occpt test results:
 
      ET = 2004 MAY 01 13:38:36.740 TDB.  Not occulted.
      ET = 2004 MAY 01 13:38:36.742 TDB.  Occulted.
 
   Rise and set times of MEX as seen from DSS-14:
 
   Target rise time (or window start):  2004 MAY 01 00:00:00.000 (TDB)
   Target set time:                     2004 MAY 01 05:36:08.338 (TDB)
 
   Target rise time:                    2004 MAY 01 16:10:26.687 (TDB)
   Target set time:                     2004 MAY 02 05:35:03.020 (TDB)
 
   Target rise time:                    2004 MAY 02 16:09:14.024 (TDB)
   Target set time:                     2004 MAY 03 05:33:57.180 (TDB)
 
   Target rise time:                    2004 MAY 03 16:08:02.224 (TDB)
   Target set time:                     2004 MAY 04 05:32:50.686 (TDB)
 
   Target rise time:                    2004 MAY 04 16:06:51.203 (TDB)
   Target set time (or window end):     2004 MAY 05 00:00:00.000 (TDB)
 
 
 
   MARS occultation of MEX ---
   Ingress and egress times as seen from DSS-14:
 
   Occ. ingress time (or window start): 2004 MAY 01 06:03:15.313 (TDB)
   Occultation egress time:             2004 MAY 01 07:05:45.105 (TDB)
 
   Occultation ingress time:            2004 MAY 01 13:38:36.741 (TDB)
   Occultation egress time:             2004 MAY 01 14:40:51.279 (TDB)
 
   Occultation ingress time:            2004 MAY 01 21:14:05.206 (TDB)
   Occultation egress time:             2004 MAY 01 22:16:04.347 (TDB)
 
   Occultation ingress time:            2004 MAY 02 04:49:26.607 (TDB)
   Occultation egress time:             2004 MAY 02 05:51:12.175 (TDB)
 
   Occultation ingress time:            2004 MAY 02 12:24:51.007 (TDB)
   Occultation egress time:             2004 MAY 02 13:26:20.244 (TDB)
 
   Occultation ingress time:            2004 MAY 02 20:00:17.624 (TDB)
   Occultation egress time:             2004 MAY 02 21:01:31.988 (TDB)
 
   Occultation ingress time:            2004 MAY 03 03:35:37.097 (TDB)
   Occultation egress time:             2004 MAY 03 04:36:36.001 (TDB)
 
   Occultation ingress time:            2004 MAY 03 11:11:00.963 (TDB)
   Occultation egress time:             2004 MAY 03 12:11:43.066 (TDB)
 
   Occultation ingress time:            2004 MAY 03 18:46:20.320 (TDB)
   Occultation egress time:             2004 MAY 03 19:46:47.607 (TDB)
 
   Occultation ingress time:            2004 MAY 04 02:21:38.679 (TDB)
   Occultation egress time:             2004 MAY 04 03:21:49.169 (TDB)
 
   Occultation ingress time:            2004 MAY 04 09:57:02.737 (TDB)
   Occultation egress time:             2004 MAY 04 10:56:56.827 (TDB)
 
   Occultation ingress time:            2004 MAY 04 17:32:19.374 (TDB)
   Occ. egress time (or window end):    2004 MAY 04 18:31:58.252 (TDB)
 
 
 
   MEX visibility start and stop times as seen from DSS-14:
 
   Vis. start time (or window start):   2004 MAY 01 00:00:00.000 (TDB)
   Visibility end time:                 2004 MAY 01 05:36:08.338 (TDB)
 
   Visibility start time:               2004 MAY 01 16:10:26.687 (TDB)
   Visibility end time:                 2004 MAY 01 21:14:05.206 (TDB)
 
   Visibility start time:               2004 MAY 01 22:16:04.347 (TDB)
   Visibility end time:                 2004 MAY 02 04:49:26.607 (TDB)
 
   Visibility start time:               2004 MAY 02 16:09:14.024 (TDB)
   Visibility end time:                 2004 MAY 02 20:00:17.624 (TDB)
 
   Visibility start time:               2004 MAY 02 21:01:31.988 (TDB)
   Visibility end time:                 2004 MAY 03 03:35:37.097 (TDB)
 
   Visibility start time:               2004 MAY 03 04:36:36.001 (TDB)
   Visibility end time:                 2004 MAY 03 05:33:57.180 (TDB)
 
   Visibility start time:               2004 MAY 03 16:08:02.224 (TDB)
   Visibility end time:                 2004 MAY 03 18:46:20.320 (TDB)
 
   Visibility start time:               2004 MAY 03 19:46:47.607 (TDB)
   Visibility end time:                 2004 MAY 04 02:21:38.679 (TDB)
 
   Visibility start time:               2004 MAY 04 03:21:49.169 (TDB)
   Visibility end time:                 2004 MAY 04 05:32:50.686 (TDB)
 
   Visibility start time:               2004 MAY 04 16:06:51.203 (TDB)
   Visibility end time:                 2004 MAY 04 17:32:19.374 (TDB)
 
   Visibility start time:               2004 MAY 04 18:31:58.252 (TDB)
   Vis. end time (or window end):       2004 MAY 05 00:00:00.000 (TDB)
 


Utilities







Rise/Set State Function Module modris




      #include "SpiceUsr.h"
      #include "SpiceZmc.h"
 
      /*
      Routines for rise-set state function computation.
      */
 
      /*
      Constants
      */
      #define NAMLEN          33
      #define CORLEN          11
 
      /*
      File scope variables:
      */
      static SpiceChar         svcorr [CORLEN];
      static SpiceChar         svsfpt [NAMLEN];
      static SpiceChar         svtarg [NAMLEN];
 
      static SpiceDouble       svlim;
 
 
 
      /*
      Save function arguments to be used while searching.
      */
      void setris ( ConstSpiceChar   * srfpt,
                    ConstSpiceChar   * abcorr,
                    ConstSpiceChar   * target,
                    SpiceDouble        revlim  )
   {
      strncpy ( svcorr, abcorr, CORLEN );
      strncpy ( svsfpt, srfpt,  NAMLEN );
      strncpy ( svtarg, target, NAMLEN );
 
      /*
      Insert null terminators for safety.
      */
      svcorr[CORLEN-1] = NULLCHAR;
      svsfpt[NAMLEN-1] = NULLCHAR;
      svtarg[NAMLEN-1] = NULLCHAR;
 
      svlim = revlim;
   }
 
 
 
 
 
      /*
      Logical function to indicate "state" of target:  the state
      is SPICETRUE when the target has a positive elevation
      in the topocentric frame at the saved surface point;
      otherwise the state is SPICEFALSE.
      */
      SpiceBoolean stris ( SpiceDouble  et )
   {
      /*
      Prototypes
      */
      void srfazl ( ConstSpiceChar       * srfpt,
                    SpiceDouble            et,
                    ConstSpiceChar       * abcorr,
                    ConstSpiceChar       * targ,
                    SpiceDouble          * az,
                    SpiceDouble          * el,
                    SpiceDouble          * r      );
 
      /*
      Local variables
      */
      SpiceDouble             az;
      SpiceDouble             el;
      SpiceDouble             r;
 
 
      /*
      Find the azimuth and elevation of the saved target at et;
      indicate whether the elevation is above the elevation limit.
      */
      srfazl ( svsfpt, et, svcorr, svtarg, &az, &el, &r );
 
      return (  (SpiceBoolean)( el > svlim )  );
   }


Point Target Occultation State Function Module modocp




      #include "SpiceUsr.h"
      #include "SpiceZmc.h"
 
      /*
      Routines for point target occultation state function computation.
      */
 
      /*
      Constants
      */
      #define NAMLEN          33
      #define CORLEN          11
 
      /*
      File scope variables:
      */
      static SpiceChar         svcorr [CORLEN];
      static SpiceChar         svobsv [NAMLEN];
      static SpiceChar         svocbd [NAMLEN];
      static SpiceChar         svtarg [NAMLEN];
 
 
 
 
 
      /*
      Save function arguments to be used while searching.
      */
      void setocp ( ConstSpiceChar   * target,
                    ConstSpiceChar   * occbdy,
                    ConstSpiceChar   * abcorr,
                    ConstSpiceChar   * obsrvr )
   {
      strncpy ( svcorr, abcorr, CORLEN );
      strncpy ( svocbd, occbdy, NAMLEN );
      strncpy ( svtarg, target, NAMLEN );
      strncpy ( svobsv, obsrvr, NAMLEN );
 
      svcorr[CORLEN-1] = NULLCHAR;
      svocbd[NAMLEN-1] = NULLCHAR;
      svtarg[NAMLEN-1] = NULLCHAR;
      svobsv[NAMLEN-1] = NULLCHAR;
   }
 
 
 
 
 
      /*
      Logical function to indicate "state" of target:  the state
      is SPICETRUE when the target has a positive elevation
      in the topocentric frame at the saved surface point;
      otherwise the state is SPICEFALSE.
      */
      SpiceBoolean stocp ( SpiceDouble  et )
   {
 
      /*
      Prototypes
      */
      SpiceBoolean occpt ( ConstSpiceChar    * target,
                           ConstSpiceChar    * occbdy,
                           SpiceDouble         et,
                           ConstSpiceChar    * abcorr,
                           ConstSpiceChar    * obsrvr  );
 
 
      return (  occpt( svtarg, svocbd, et, svcorr, svobsv )  );
   }
 
 


Event finder fndevt




 
      #include "SpiceUsr.h"
 
      void fndevt ( SpiceDouble       etbeg,
                    SpiceDouble       etend,
                    SpiceDouble       step,
                    SpiceBoolean   (* statef) ( SpiceDouble ),
                    SpiceCell       * xset                     )
 
      /*
      Find locations of state changes for a boolean function.
 
        31-OCT-2002 (NJB)
      */
 
   {
      /*
      Local constants
      */
      #define CNVLIM           (1.0e-6)
      #define MAXITR           100
 
      /*
      Local variables
      */
      SpiceBoolean            lstate;
      SpiceBoolean            mstate;
      SpiceBoolean            ustate;
 
      SpiceDouble             delta;
      SpiceDouble             lower;
      SpiceDouble             lpt;
      SpiceDouble             midpt;
      SpiceDouble             upper;
      SpiceDouble             upt;
 
      SpiceInt                nitr;
 
 
 
      if ( return_c() )
      {
         return;
      }
      chkin_c ( "fndevt" );
 
      /*
      Set the cardinality of the input cell to zero.
      */
      scard_c ( 0, xset );
 
      /*
      If the input interval is empty, we're done.
      */
      if ( etend <= etbeg )
      {
         chkout_c ( "fndevt" );
         return;
      }
 
      /*
      The step size must be at least as large as the convergence
      limit.
      */
      if ( step <= CNVLIM )
      {
         setmsg_c ( "STEP must be > the convergence limit #; "
                    "actual value was #."                      );
         errdp_c  ( "#", CNVLIM                                );
         errdp_c  ( "#", step                                  );
         sigerr_c ( "SPICE(INVALIDVALUE)"                      );
         chkout_c ( "fndevt"                                   );
         return;
      }
 
      /*
      Obtain the initial state; save this as the "lower" state.
      */
      lstate = (*statef) ( etbeg );
 
      /*
      Step along the input interval, looking for state changes.
      */
      lpt  =  etbeg;
      upt  =  brcktd_c ( etbeg + step,  etbeg,  etend );
 
      while ( lpt < etend )
      {
         /*
         Find the state at the epoch upt.  First, check that upt
         is actually greater than lpt.
         */
         if ( upt <= lpt )
         {
            /*
            We're not getting anywhere; the step is too small.
            */
            setmsg_c ( "Upper bracketing epoch UPT = #; "
                       "lower epoch LPT = #. This condition "
                       "arises when the step size is too small." );
            errdp_c  ( "#", lpt                                  );
            errdp_c  ( "#", upt                                  );
            sigerr_c ( "SPICE(STEPTOOSMALL)"                     );
            chkout_c ( "fndevt"                                  );
            return;
         }
 
         /*
         Find the state at the upper bound of our step interval.
         */
         ustate  =  (*statef)( upt );
 
         if ( ustate != lstate )
         {
            /*
            There's a state change between the right endpoint upt and
            the left endpoint lpt.  Do a binary search to locate the
            epoch at which the state changes.  Note: uniqueness of
            the root is not guaranteed; it's up to the caller to
            choose step small enough to ensure that only one root can
            occur in a time interval of length step.
            */
            lower  =  brcktd_c ( lpt, etbeg, etend );
            upper  =  brcktd_c ( upt, etbeg, etend );
            midpt  =  ( lower + upper ) / 2;
            mstate =  (*statef) ( midpt );
 
            nitr   =  0;
            delta  =  upper - lower;
 
            while (  ( delta > CNVLIM ) && ( nitr <= MAXITR )  )
            {
               /*
               Adjust our search interval so the length is reduced
               by a factor of two and so that the location of the
               state change remains between lower and upper.
               */
               if ( mstate == ustate )
               {
                  /*
                  The state is the same at the midpoint and the
                  upper bound, so a state change must occur
                  between the lower bound and the midpoint.
                  Make the midpoint the new upper bound.
                  */
                  upper = midpt;
               }
               else
               {
                  /*
                  There is a state change between the midpoint
                  and the upper bound; the state at the midpoint
                  matches the state at the lower bound.  Make
                  the midpoint the new lower bound.
                  */
                  lower = midpt;
               }
 
               midpt  = ( lower + upper ) / 2;
               mstate = (*statef) ( midpt );
 
               delta  =   upper - lower;
               nitr++;
 
               /*
               At this point, the state at lower matches the state
               at lpt (lstate), and the state at upper matches
               the state at upt (ustate).
               */
            }
 
            /*
            If we dropped out of the loop because we hit the
            iteration limit, we have a problem.
            */
            if ( delta > CNVLIM )
            {
               setmsg_c ( "Binary search failed to converge. "
                          "ETBEG = #, LOWER = #, MIDPT = #, "
                          "UPPER = #, ETEND = #"               );
               errdp_c  ( "#", etbeg                           );
               errdp_c  ( "#", lower                           );
               errdp_c  ( "#", midpt                           );
               errdp_c  ( "#", upper                           );
               errdp_c  ( "#", etend                           );
               sigerr_c ( "SPICE(NOCONVERGENCE)"               );
               chkout_c ( "fndevt"                             );
               return;
            }
 
            /*
            The epoch of the state transition has been determined
            to within CNVLIM.  We'll use upper as the epoch of
            the transition.  This ensures that the state at the
            transition epoch is ustate.
            */
            appndd_c ( upper, xset );
 
            /*
            upper becomes the left endpoint of the next interval.
            The state at the right interval endpoint upt becomes
            the state at the left endpoint of the next interval.
            Calculate upt at the next step.  We look up
            ustate at the top of the loop.
            */
            lpt     =  upper;
            lstate  =  ustate;
            upt     =  brcktd_c ( lpt + step,  etbeg,  etend );
         }
 
         else
         {
            /*
            No state change was found on this step.  upt becomes
            the lower bound of the next search interval.  lstate
            remains unchanged.  We look up ustate at the top of
            the loop.
            */
            lpt     =  upt;
            upt     =  brcktd_c ( lpt + step,  etbeg,  etend );
         }
      }
 
      /*
      The left endpoint equals the right endpoint of our search
      interval, so there are no more state changes to be found.
      */
      chkout_c ( "fndevt" );
   }


Set to Window Mapping Utility makwin




      #include "SpiceUsr.h"
 
 
      void makwin ( SpiceDouble          etbeg,
                    SpiceDouble          etend,
                    SpiceBoolean      (* fstate)( SpiceDouble ),
                    SpiceCell          * evtset,
                    SpiceCell          * evtwin                  )
 
      /*
      Utility program for creating a window representing
      time intervals when a specified binary state function
      returns SPICETRUE.
 
         Subroutine arguments:
 
            etbeg         is the start time of a time interval on
                          which the binary state function
                          fstate is defined.
 
            etend         is the end time corresponding to etbeg.
 
            fstate        is a binary state function of ET that
                          returns a value of type SpiceBoolean.
 
            evtset        is a CSPICE set containing epochs of state
                          transitions.  The members of evtset must
                          lie in the interval
 
                             [etbeg, etend]
 
            evtwin        is a CSPICE window constructed by this
                          routine.  evtwin contains subintervals
                          of the interval
 
                             [etbeg, etend]
 
                          on which fstate(et) is SPICETRUE.  evtwin
                          must be intialized by the caller of this
                          routine.
      */
 
   {
      /*
      Local variables
      */
      SpiceInt                card;
      SpiceInt                i;
 
 
      chkin_c ( "makwin" );
 
      /*
      Empty the output window.
      */
      scard_c ( 0, evtwin );
 
      /*
      Get a local copy of the cardinality of the event set.
      */
      card = card_c ( evtset );
 
      /*
      If fstate is SPICETRUE at etbeg, then the first state
      transition is at the right endpoint of the first window
      interval, and every subsequent even-numbered transition
      marks the start of a window interval. Otherwise,
      every odd-numbered transition marks the start of a window
      interval.
      */
 
      if ( (*fstate)(etbeg) )
      {
         /*
         The first window interval starts at etbeg.
         */
         if ( card == 0 )
         {
 
            /*
            The function is SPICETRUE the whole time.  The
            window consists of the single interval
 
               [etbeg, etend]
            */
            wninsd_c ( etbeg, etend, evtwin );
         }
         else
         {
            /*
            Insert the first interval into the window.
            */
            wninsd_c( etbeg, SPICE_CELL_ELEM_D(evtset,0), evtwin );
 
            /*
            Insert into our window any remaining intervals bounded
            by transitions.
            */
            i = 1;
 
            while ( i+1 < card )
            {
               wninsd_c ( SPICE_CELL_ELEM_D( evtset, i   ),
                          SPICE_CELL_ELEM_D( evtset, i+1 ),
                          evtwin                            );
 
               i += 2;
            }
 
            if ( i == card-1 )
            {
               /*
               The last interval begins at the [card-1] element
               of evtset and ends at etend.
               */
               wninsd_c ( SPICE_CELL_ELEM_D(evtset, card-1),
                          etend,
                          evtwin                          );
            }
         }
 
 
         /*
         We've handled the case where fstate is SPICETRUE at etbeg.
         */
      }
 
      else
      {
         /*
         The first interval starts at element [0] of evtset.
         */
         i = 0;
 
         while ( i+1 < card )
         {
            wninsd_c ( SPICE_CELL_ELEM_D( evtset, i   ),
                       SPICE_CELL_ELEM_D( evtset, i+1 ),
                       evtwin                            );
 
            i += 2;
         }
 
         if ( i == card-1 )
         {
            /*
            The last interval begins at the [card-1] element of evtset
            and ends at etend.
            */
            wninsd_c ( SPICE_CELL_ELEM_D(evtset, card-1),
                       etend,
                       evtwin                           );
         }
 
         /*
         We've handled the case where fstate is SPICEFALSE at etbeg.
         */
      }
 
      /*
      evtwin is ready for use.
      */
      chkout_c ( "makwin" );
   }