Starlink-AST

 view release on metacpan or  search on metacpan

ast/src/skyframe.c  view on Meta::CPAN

*        in order to avoid expensive re-computations.
*     22-AUG-2006 (DSB):
*        Ensure the cached Local Apparent Siderial Time is initialised
*        when initialising or loading a SkyFrame.
*     22-SEP-2006 (DSB):
*        Report an error in SetSystem if it is not possible to convert
*        from old to new systems.
*     3-OCT-2006 (DSB):
*        Added Equation of Equinoxes to the SkyFrame structure.
*     6-OCT-2006 (DSB):
*        - Guard against annulling null pointers in subFrame.
*        - Add Dut1 attribute
*        - Use linear approximation for LAST over short periods (less
*          than 0.001 of a day)
*        - Remove Equation of Equinoxes from the SkyFrame structure.
*     10-OCT-2006 (DSB):
*        Use "AlOff" instead of "AlignOffset" as the external channel name
*        for the AlignOffset attribute. The longer form exceeded the
*        limit that can be used by the Channel class.
*     14-OCT-2006 (DSB):
*        - Move Dut1 attribute to the Frame class.
*        - Use the TimeFrame class to do the TDB->LAST conversions.
*     17-JAN-2007 (DSB):
*        - Use a UnitMap to align offset coordinate systems in two
*        SkyFrames, regardless of other attribute values.
*        - Only align in offset coordinates if both target and template
*        have a non-zero value for AlignOffset.
*     23-JAN-2007 (DSB):
*        Modified so that a SkyFrame can be used as a template to find a
*        SkyFrame contained within a CmpFrame. This involves changes in
*        Match and the removal of the local versions of SetMaxAxes and
*        SetMinAxes.
*     4-JUL-2007 (DSB):
*        Modified GetLast to use the correct solar to sidereal conversion
*        factor. As a consequence the largest acceptable epoch gap before
*        the LAST needs to be recalculated has been increased.
*     11-JUL-2007 (DSB):
*        Override astSetEpoch and astClearEpoch by implementations which
*        update the LAST value stored in the SkyFrame.
*     7-AUG-2007 (DSB):
*        - Set a value for the CentreZero attribute when extracting a
*        SkyAxis from a SkyFrame in function SubFrame.
*        - In SubFrame, clear extended attributes such as System after
*        all axis attributes have been "fixated.
*     30-AUG-2007 (DSB):
*        Override astSetDut1 and astClearDut1 by implementations which
*        update the LAST value stored in the SkyFrame.
*     31-AUG-2007 (DSB):
*        - Cache the magnitude of the diurnal aberration vector in the
*        SkyFrame structure for use when correcting for diurnal aberration.
*        - Modify the azel conversions to include correction for diurnal
*        aberration.
*        - Override astClearObsLat and astSetObsLat by implementations which
*        reset the magnitude of the diurnal aberration vector.
*     3-SEP-2007 (DSB):
*        In SubFrame, since AlignSystem is extended by the SkyFrame class
*        it needs to be cleared before invoking the parent SubFrame
*        method in cases where the result Frame is not a SkyFrame.
*     2-OCT-2007 (DSB):
*        In Overlay, clear AlignSystem as well as System before calling
*        the parent overlay method.
*     10-OCT-2007 (DSB):
*        In MakeSkyMapping, correct the usage of variables "system" and
*        "align_sys" when aligning in AZEL.
*     18-OCT-2007 (DSB):
*        Compare target and template AlignSystem values in Match, rather
*        than comparing target and result AlignSystem values in MakeSkyMapping
*        (since result is basically a copy of target).
*     27-NOV-2007 (DSB):
*        - Modify SetSystem to ensure that SkyRef and SkyRefP position are
*        always transformed as absolute values, rather than as offset
*        values.
*        - Modify SubMatch so that a value of zero is assumed for
*        AlignOffset when restoring thre integrity of a FrameSet.
*     15-DEC-2008 (DSB):
*        Improve calculation of approximate Local Apparent Sidereal time
*        by finding and using the ratio of solar to sidereal time
*        independently for each approximation period.
*     14-JAN-2009 (DSB):
*        Override the astIntersect method.
*     21-JAN-2009 (DSB):
*        Fix mis-use of results buffers for GetFormat and GetAttrib.
*     16-JUN-2009 (DSB):
*        All sky coordinate systems currently supported by SkyFrame are
*        left handed. So fix GetDirection method to return zero for all
*        longitude axes and 1 for all latitude axes.
*     18-JUN-2009 (DSB):
*        Incorporate the new ObsAlt attribute.
*     23-SEP-2009 (DSB):
*        Allow some rounding error when checking for changes in SetObsLon
*        and SetDut1. This reduces the number of times the expensive
*        calculation of LAST is performed.
*     24-SEP-2009 (DSB);
*        Create a static cache of LAST values stored in the class virtual
*        function table. These are used in preference to calculating a new
*        value from scratch.
*     25-SEP-2009 (DSB);
*        Do not calculate LAST until it is needed.
*     12-OCT-2009 (DSB);
*        - Handle 2.PI->0 discontinuity in cached LAST values.
*     12-OCT-2009 (BEC);
*        - Fix bug in caching LAST value.
*     31-OCT-2009 (DSB);
*        Correct SetCachedLAST to handle cases where the epoch to be
*        stored is smaller than any epoch already in the table.
*     24-NOV-2009 (DSB):
*        - In CalcLast, only use end values form the table of stored
*        LAST values if the corresponding epochs are within 0.001 of
*        a second of the required epoch (this tolerance used to be
*        0.1 seconds).
*        - Do not clear the cached LAST value in SetEpoch and ClearEpoch.
*     8-MAR-2010 (DSB):
*        Add astSkyOffsetMap method.
*     7-APR-2010 (DSB):
*        Add IsLatAxis and IsLonAxis attributes.
*     11-MAY-2010 (DSB):
*        In SetSystem, clear SkyRefP as well as SkyRef.
*     22-MAR-2011 (DSB):
*        Override astFrameGrid method.
*     29-APR-2011 (DSB):
*        Prevent astFindFrame from matching a subclass template against a

ast/src/skyframe.c  view on Meta::CPAN


/* Cached Line structure. */
/* ---------------------- */
/* This structure contains information describing a line segment within a
   SkyFrame. It differs from the AstLineDef defined in frame.h because
   positions are represented by 3D (x,y,z) cartesian coords rather than
   2D (long,lat) coords. */

typedef struct SkyLineDef {
   AstFrame *frame;            /* Pointer to Frame in which the line is defined */
   double length;              /* Line length */
   int infinite;               /* Disregard the start and end of the line? */
   double start[3];            /* Unit vector defining start of line */
   double end[3];              /* Unit vector defining end of line */
   double dir[3];              /* Unit vector defining line direction */
   double q[3];                /* Unit vector perpendicular to line */
   double start_2d[2];
   double end_2d[2];
} SkyLineDef;

/* Module Variables. */
/* ================= */

/* Address of this static variable is used as a unique identifier for
   member of this class. */
static int class_check;

/* Pointers to parent class methods which are used or extended by this
   class. */

static AstPointSet *(* parent_normalpoints)( AstFrame *, AstPointSet *, int, AstPointSet *, int * );
static AstSystemType (* parent_getalignsystem)( AstFrame *, int * );
static AstSystemType (* parent_getsystem)( AstFrame *, int * );
static const char *(* parent_format)( AstFrame *, int, double, int * );
static const char *(* parent_getattrib)( AstObject *, const char *, int * );
static const char *(* parent_getdomain)( AstFrame *, int * );
static const char *(* parent_getformat)( AstFrame *, int, int * );
static const char *(* parent_getlabel)( AstFrame *, int, int * );
static const char *(* parent_getsymbol)( AstFrame *, int, int * );
static const char *(* parent_gettitle)( AstFrame *, int * );
static const char *(* parent_getunit)( AstFrame *, int, int * );
static double (* parent_gap)( AstFrame *, int, double, int *, int * );
static double (* parent_getbottom)( AstFrame *, int, int * );
static double (* parent_getepoch)( AstFrame *, int * );
static double (* parent_gettop)( AstFrame *, int, int * );
static int (* parent_getdirection)( AstFrame *, int, int * );
static size_t (* parent_getobjsize)( AstObject *, int * );
static int (* parent_match)( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * );
static int (* parent_subframe)( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * );
static int (* parent_testattrib)( AstObject *, const char *, int * );
static int (* parent_testformat)( AstFrame *, int, int * );
static int (* parent_unformat)( AstFrame *, int, const char *, double *, int * );
static void (* parent_clearattrib)( AstObject *, const char *, int * );
static void (* parent_cleardtai)( AstFrame *, int * );
static void (* parent_cleardut1)( AstFrame *, int * );
static void (* parent_clearformat)( AstFrame *, int, int * );
static void (* parent_clearobsalt)( AstFrame *, int * );
static void (* parent_clearobslat)( AstFrame *, int * );
static void (* parent_clearobslon)( AstFrame *, int * );
static void (* parent_clearsystem)( AstFrame *, int * );
static void (* parent_overlay)( AstFrame *, const int *, AstFrame *, int * );
static void (* parent_setattrib)( AstObject *, const char *, int * );
static void (* parent_setdtai)( AstFrame *, double, int * );
static void (* parent_setdut1)( AstFrame *, double, int * );
static void (* parent_setformat)( AstFrame *, int, const char *, int * );
static void (* parent_setobsalt)( AstFrame *, double, int * );
static void (* parent_setobslat)( AstFrame *, double, int * );
static void (* parent_setobslon)( AstFrame *, double, int * );
static void (* parent_setsystem)( AstFrame *, AstSystemType, int * );

/* Factors for converting between hours, degrees and radians. */
static double hr2rad;
static double deg2rad;
static double pi;
static double piby2;

/* Table of cached Local Apparent Sidereal Time values and corresponding
   epochs. */
static int nlast_tables = 0;
static AstSkyLastTable **last_tables = NULL;


/* Define macros for accessing each item of thread specific global data. */
#ifdef THREAD_SAFE

/* Define how to initialise thread-specific globals. */
#define GLOBAL_inits \
   globals->Class_Init = 0; \
   globals->GetAttrib_Buff[ 0 ] = 0; \
   globals->GetFormat_Buff[ 0 ] = 0; \
   globals->GetLabel_Buff[ 0 ] = 0; \
   globals->GetSymbol_Buff[ 0 ] = 0; \
   globals->GetTitle_Buff[ 0 ] = 0; \
   globals->GetTitle_Buff2[ 0 ] = 0; \
   globals->TDBFrame = NULL; \
   globals->LASTFrame = NULL; \

/* Create the function that initialises global data for this module. */
astMAKE_INITGLOBALS(SkyFrame)

/* Define macros for accessing each item of thread specific global data. */
#define class_init astGLOBAL(SkyFrame,Class_Init)
#define class_vtab astGLOBAL(SkyFrame,Class_Vtab)
#define getattrib_buff astGLOBAL(SkyFrame,GetAttrib_Buff)
#define getformat_buff astGLOBAL(SkyFrame,GetFormat_Buff)
#define getlabel_buff astGLOBAL(SkyFrame,GetLabel_Buff)
#define getsymbol_buff astGLOBAL(SkyFrame,GetSymbol_Buff)
#define gettitle_buff astGLOBAL(SkyFrame,GetTitle_Buff)
#define gettitle_buff2 astGLOBAL(SkyFrame,GetTitle_Buff2)
#define tdbframe astGLOBAL(SkyFrame,TDBFrame)
#define lastframe astGLOBAL(SkyFrame,LASTFrame)



static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
#define LOCK_MUTEX2 pthread_mutex_lock( &mutex2 );
#define UNLOCK_MUTEX2 pthread_mutex_unlock( &mutex2 );

/* A read-write lock used to protect the table of cached LAST values so
   that multiple threads can read simultaneously so long as no threads are
   writing to the table. */

ast/src/skyframe.c  view on Meta::CPAN

   object->TestAttrib = TestAttrib;

   parent_gettop = frame->GetTop;
   frame->GetTop = GetTop;

   parent_normalpoints = frame->NormalPoints;
   frame->NormalPoints = NormalPoints;

   parent_setobsalt = frame->SetObsAlt;
   frame->SetObsAlt = SetObsAlt;

   parent_setobslat = frame->SetObsLat;
   frame->SetObsLat = SetObsLat;

   parent_setobslon = frame->SetObsLon;
   frame->SetObsLon = SetObsLon;

   parent_clearobslon = frame->ClearObsLon;
   frame->ClearObsLon = ClearObsLon;

   parent_clearobsalt = frame->ClearObsAlt;
   frame->ClearObsAlt = ClearObsAlt;

   parent_clearobslat = frame->ClearObsLat;
   frame->ClearObsLat = ClearObsLat;

   parent_getbottom = frame->GetBottom;
   frame->GetBottom = GetBottom;

   parent_getepoch = frame->GetEpoch;
   frame->GetEpoch = GetEpoch;

   parent_format = frame->Format;
   frame->Format = Format;
   parent_gap = frame->Gap;
   frame->Gap = Gap;
   parent_getdirection = frame->GetDirection;
   frame->GetDirection = GetDirection;
   parent_getdomain = frame->GetDomain;
   frame->GetDomain = GetDomain;
   parent_getsystem = frame->GetSystem;
   frame->GetSystem = GetSystem;
   parent_setsystem = frame->SetSystem;
   frame->SetSystem = SetSystem;
   parent_clearsystem = frame->ClearSystem;
   frame->ClearSystem = ClearSystem;
   parent_getalignsystem = frame->GetAlignSystem;
   frame->GetAlignSystem = GetAlignSystem;
   parent_getformat = frame->GetFormat;
   frame->GetFormat = GetFormat;
   parent_getlabel = frame->GetLabel;
   frame->GetLabel = GetLabel;
   parent_getsymbol = frame->GetSymbol;
   frame->GetSymbol = GetSymbol;
   parent_gettitle = frame->GetTitle;
   frame->GetTitle = GetTitle;
   parent_getunit = frame->GetUnit;
   frame->GetUnit = GetUnit;
   parent_match = frame->Match;
   frame->Match = Match;
   parent_overlay = frame->Overlay;
   frame->Overlay = Overlay;
   parent_subframe = frame->SubFrame;
   frame->SubFrame = SubFrame;
   parent_unformat = frame->Unformat;
   frame->Unformat = Unformat;

   parent_setdtai = frame->SetDtai;
   frame->SetDtai = SetDtai;
   parent_setdut1 = frame->SetDut1;
   frame->SetDut1 = SetDut1;

   parent_cleardtai = frame->ClearDtai;
   frame->ClearDtai = ClearDtai;
   parent_cleardut1 = frame->ClearDut1;
   frame->ClearDut1 = ClearDut1;

/* Store replacement pointers for methods which will be over-ridden by new
   member functions implemented here. */
   frame->Angle = Angle;
   frame->Distance = Distance;
   frame->FrameGrid = FrameGrid;
   frame->Intersect = Intersect;
   frame->Norm = Norm;
   frame->NormBox = NormBox;
   frame->Resolve = Resolve;
   frame->ResolvePoints = ResolvePoints;
   frame->Offset = Offset;
   frame->Offset2 = Offset2;
   frame->ValidateSystem = ValidateSystem;
   frame->SystemString = SystemString;
   frame->SystemCode = SystemCode;
   frame->LineDef = LineDef;
   frame->LineContains = LineContains;
   frame->LineCrossing = LineCrossing;
   frame->LineOffset = LineOffset;
   frame->GetActiveUnit = GetActiveUnit;
   frame->TestActiveUnit = TestActiveUnit;
   frame->MatchAxesX = MatchAxesX;

/* Store pointers to inherited methods that will be invoked explicitly
   by this class. */
   parent_clearformat = frame->ClearFormat;
   parent_setformat = frame->SetFormat;
   parent_testformat = frame->TestFormat;

/* Declare the copy constructor, destructor and class dump
   function. */
   astSetCopy( vtab, Copy );
   astSetDelete( vtab, Delete );
   astSetDump( vtab, Dump, "SkyFrame",
               "Description of celestial coordinate system" );

/* Initialize constants for converting between hours, degrees and
   radians, etc.. */
   LOCK_MUTEX2
   palDtf2r( 1, 0, 0.0, &hr2rad, &stat );
   palDaf2r( 1, 0, 0.0, &deg2rad, &stat );
   palDaf2r( 180, 0, 0.0, &pi, &stat );
   piby2 = 0.5*pi;
   UNLOCK_MUTEX2

ast/src/skyframe.c  view on Meta::CPAN

/* Annul the remaining Frame pointer used in the above tests. */
         frame0 = astAnnul( frame0 );
      }

/* If this test is passed, we can now test that the underlying axis indices
   are 0 and 1, in either order. This then ensures that we have a
   single SkyFrame (not a compound Frame) with both axes present. */
      if ( match && astOK ) {
         match = ( ( ( iaxis0 == 0 ) && ( iaxis1 == 1 ) ) ||
                   ( ( iaxis1 == 0 ) && ( iaxis0 == 1 ) ) );
      }

   }

/* If a possible match has been detected, we must now decide how the
   order of the axes in the result Frame relates to the order of axes
   in the target Frame. There are two factors involved. The first
   depends on whether the axis permutation array for the template
   SkyFrame (whose method we are executing) causes an axis
   reversal. Determine this by permuting axis index zero. */
   if ( astOK && match ) {
      swap1 = ( astValidateAxis( template, 0, 1, "astMatch" ) != 0 );

/* The second factor depends on whether the axes of the underlying
   primary SkyFrame are reversed when seen in the target Frame. */
      swap2 = ( iaxis0 != 0 );

/* Combine these to determine if an additional axis swap will be
   needed. */
      swap = ( swap1 != swap2 );

/* Now check to see if this additional swap is permitted by the
   template's Permute attribute. */
      match = ( !swap || astGetPermute( template ) );
   }

/* If the Frames still match, we next set up the axis association
   arrays. */
   if ( astOK && match ) {

/* If the target axis order is to be preserved, then the target axis
   association involves no permutation but the template axis
   association may involve an axis swap. */
      if ( astGetPreserveAxes( template ) ) {
         (*template_axes)[ 0 ] = swap;
         (*template_axes)[ 1 ] = !swap;
         (*target_axes)[ 0 ] = target_axis0;
         (*target_axes)[ 1 ] = target_axis1;

/* Otherwise, any swap applies to the target axis association
   instead. */
      } else {
         (*template_axes)[ 0 ] = 0;
         (*template_axes)[ 1 ] = 1;
         (*target_axes)[ 0 ] = swap ? target_axis1 : target_axis0;
         (*target_axes)[ 1 ] = swap ? target_axis0 : target_axis1;
      }

/* Use the target's "astSubFrame" method to create a new Frame (the
   result Frame) with copies of the target axes in the required
   order. This process also overlays the template attributes on to the
   target Frame and returns a Mapping between the target and result
   Frames which effects the required coordinate conversion. */
      match = astSubFrame( target, template, 2, *target_axes, *template_axes,
                           map, result );
   }

/* If an error occurred, or conversion to the result Frame's
   coordinate system was not possible, then free all memory, annul the
   returned objects, and reset the returned value. */
   if ( !astOK || !match ) {
      *template_axes = astFree( *template_axes );
      *target_axes = astFree( *target_axes );
      if( *map ) *map = astAnnul( *map );
      if( *result ) *result = astAnnul( *result );
      match = 0;
   }

/* Return the result. */
   return match;
}

static void MatchAxesX( AstFrame *frm2_frame, AstFrame *frm1, int *axes,
                        int *status ) {
/*
*  Name:
*     MatchAxesX

*  Purpose:
*     Find any corresponding axes in two Frames.

*  Type:
*     Private function.

*  Synopsis:
*     #include "skyframe.h"
*     void MatchAxesX( AstFrame *frm2, AstFrame *frm1, int *axes )
*                      int *status )

*  Class Membership:
*     SkyFrame member function (over-rides the protected astMatchAxesX
*     method inherited from the Frame class).

*     This function looks for corresponding axes within two supplied
*     Frames. An array of integers is returned that contains an element
*     for each axis in the second supplied Frame. An element in this array
*     will be set to zero if the associated axis within the second Frame
*     has no corresponding axis within the first Frame. Otherwise, it
*     will be set to the index (a non-zero positive integer) of the
*     corresponding axis within the first supplied Frame.

*  Parameters:
*     frm2
*        Pointer to the second Frame.
*     frm1
*        Pointer to the first Frame.
*     axes
*        Pointer to an integer array in which to return the indices of
*        the axes (within the first Frame) that correspond to each axis
*        within the second Frame. Axis indices start at 1. A value of zero
*        will be stored in the returned array for each axis in the second

ast/src/skyframe.c  view on Meta::CPAN

/* Create the vector Q2 representing the point on the equator (i.e. a
   latitude of zero), which has a longitude 90 degrees to the west of
   the required point. */
         q2[ 0 ] = -sina1;
         q2[ 1 ] =  cosa1;
         q2[ 2 ] =  0.0;

/* Create the vector Q3 representing the point which is 90 degrees away
   from the required point, along the required great circle. */
         cosoff = cos( offset );
         sinoff = sin( offset );

         q3[ 0 ] = -sinoff*r0[ 0 ] + cosoff*r3[ 0 ];
         q3[ 1 ] = -sinoff*r0[ 1 ] + cosoff*r3[ 1 ];
         q3[ 2 ] = -sinoff*r0[ 2 ] + cosoff*r3[ 2 ];

/* Calculate the position angle of the great circle at the required
   point. */
         pa = atan2( palDvdv( q3, q2 ), palDvdv( q3, q1 ) );

/* Convert this from a pa into the required angle. */
         result = ( perm[ 0 ] == 0 )? pa: piby2 - pa;

/* Ensure that the end angle is in the range 0 to 2*pi. */
         result = palDranrm( result );

/* Permute the result coordinates to undo the effect of the SkyFrame
   axis permutation array. */
         point2[ 0 ] = p2[ perm[ 0 ] ];
         point2[ 1 ] = p2[ perm[ 1 ] ];
      }
   }

/* Return the result. */
   return result;

}

static void Overlay( AstFrame *template, const int *template_axes,
                     AstFrame *result, int *status ) {
/*
*  Name:
*     Overlay

*  Purpose:
*     Overlay the attributes of a template SkyFrame on to another Frame.

*  Type:
*     Private function.

*  Synopsis:
*     #include "skyframe.h"
*     void Overlay( AstFrame *template, const int *template_axes,
*                   AstFrame *result, int *status )

*  Class Membership:
*     SkyFrame member function (over-rides the protected astOverlay method
*     inherited from the Frame class).

*  Description:
*     This function overlays attributes of a SkyFrame (the "template") on to
*     another Frame, so as to over-ride selected attributes of that second
*     Frame. Normally only those attributes which have been specifically set
*     in the template will be transferred. This implements a form of
*     defaulting, in which a Frame acquires attributes from the template, but
*     retains its original attributes (as the default) if new values have not
*     previously been explicitly set in the template.
*
*     Note that if the result Frame is a SkyFrame and a change of sky
*     coordinate system occurs as a result of overlaying its System
*     attribute, then some of its original attribute values may no
*     longer be appropriate (e.g. the Title, or attributes describing
*     its axes). In this case, these will be cleared before overlaying
*     any new values.

*  Parameters:
*     template
*        Pointer to the template SkyFrame, for which values should have been
*        explicitly set for any attribute which is to be transferred.
*     template_axes
*        Pointer to an array of int, with one element for each axis of the
*        "result" Frame (see below). For each axis in the result frame, the
*        corresponding element of this array should contain the (zero-based)
*        index of the template axis to which it corresponds. This array is used
*        to establish from which template axis any axis-dependent attributes
*        should be obtained.
*
*        If any axis in the result Frame is not associated with a template
*        axis, the corresponding element of this array should be set to -1.
*
*        If a NULL pointer is supplied, the template and result axis
*        indices are assumed to be identical.
*     result
*        Pointer to the Frame which is to receive the new attribute values.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     void

*  Notes:
*     -  In general, if the result Frame is not from the same class as the
*     template SkyFrame, or from a class derived from it, then attributes may
*     exist in the template SkyFrame which do not exist in the result Frame. In
*     this case, these attributes will not be transferred.
*/


/* Local Variables: */
   AstSystemType new_alignsystem;/* Code identifying new alignment coords */
   AstSystemType new_system;     /* Code identifying new sky cordinates */
   AstSystemType old_system;     /* Code identifying old sky coordinates */
   int axis;                     /* Loop counter for result SkyFrame axes */
   int skyref_changed;           /* Has the SkyRef attribute changed? */
   int reset_system;             /* Was the template System value cleared? */
   int skyframe;                 /* Result Frame is a SkyFrame? */
   int tax0;                     /* Template axis for result axis 0 */
   int tax1;                     /* Template axis for result axis 1 */

/* Check the global error status. */
   if ( !astOK ) return;

/* Indicate that we do not need to reset the System attribute of the
   template. */
   reset_system = 0;
   new_system = AST__UNKNOWN;

/* If the result Frame is a SkyFrame, we must test to see if overlaying its
   System attribute will change the type of sky coordinate system it
   describes. Determine the value of this attribute for the result and template
   SkyFrames. We also need to do this if either SkyRef attribute would
   change. */
   skyframe = astIsASkyFrame( result );
   if ( skyframe ) {
      old_system = astGetSystem( result );
      new_system = astGetSystem( template );
      skyref_changed = ( astGetSkyRef( result, 0 ) !=
                         astGetSkyRef( template, 0 ) ) ||
                       ( astGetSkyRef( result, 1 ) !=
                         astGetSkyRef( template, 1 ) );

/* If the coordinate system will change, any value already set for the result
   SkyFrame's Title will no longer be appropriate, so clear it. Note, the
   system value will only be changed in the result if it has been set in the
   template. */
      if ( ( (new_system != old_system) && astTestSystem( template ) )
           || skyref_changed ) {
         astClearTitle( result );

/* Test if the old and new sky coordinate systems are similar enough to make
   use of the same axis attribute values (e.g. if they are both equatorial
   systems, then they can both use the same axis labels, etc.,so long as
   the SKyRefIs value has not changed). */
         if ( IsEquatorial( new_system, status ) != IsEquatorial( old_system, status ) ||
              skyref_changed ) {

/* If necessary, clear inappropriate values for all those axis attributes
   whose access functions are over-ridden by this class (these access functions
   will then provide suitable defaults appropriate to the new coordinate system
   instead). */
            for ( axis = 0; axis < 2; axis++ ) {
               astClearAsTime( result, axis );
               astClearDirection( result, axis );
               astClearFormat( result, axis );
               astClearLabel( result, axis );
               astClearSymbol( result, axis );
               astClearUnit( result, axis );
            }
         }
      }

/* If the result Frame is not a SkyFrame, we must temporarily clear the
   System and AlignSystem values since the values used by this class are only
   appropriate to this class. */
   } else {
      if( astTestSystem( template ) ) {
         new_system = astGetSystem( template );
         astClearSystem( template );
         new_alignsystem = astGetAlignSystem( template );
         astClearAlignSystem( template );
         reset_system = 1;
      }
   }

/* Invoke the parent class astOverlay method to transfer attributes inherited
   from the parent class. */
   (*parent_overlay)( template, template_axes, result, status );

/* Reset the System and AlignSystem values if necessary */
   if( reset_system ) {
      astSetSystem( template, new_system );
      astSetAlignSystem( template, new_alignsystem );
   }

/* Check if the result Frame is a SkyFrame or from a class derived from
   SkyFrame. If not, we cannot transfer SkyFrame attributes to it as it is
   insufficiently specialised. In this case simply omit these attributes. */
   if ( skyframe && astOK ) {

/* Define a macro that tests whether an attribute is set in the template and,
   if so, transfers its value to the result. */
#define OVERLAY(attr) \
   if ( astTest##attr( template ) ) { \
      astSet##attr( result, astGet##attr( template ) ); \
   }

/* Store template axis indices */
   if( template_axes ) {
      tax0 = template_axes[ 0 ];
      tax1 = template_axes[ 1 ];
   } else {
      tax0 = 0;
      tax1 = 1;
   }

/* Define a similar macro that does the same for SkyFrame specific axis
   attributes. */
#define OVERLAY2(attr) \
   if( astTest##attr( template, tax0 ) ) { \
      astSet##attr( result, 0, astGet##attr( template, tax0 ) ); \
   } \
   if( astTest##attr( template, tax1 ) ) { \
      astSet##attr( result, 1, astGet##attr( template, tax1 ) ); \
   }

/* Use the macro to transfer each SkyFrame attribute in turn. */
      OVERLAY(Equinox);
      OVERLAY(Projection);
      OVERLAY(NegLon);
      OVERLAY(SkyTol);
      OVERLAY(AlignOffset);
      OVERLAY(SkyRefIs);
      OVERLAY2(SkyRef);
      OVERLAY2(SkyRefP);
   }

/* Undefine macros local to this function. */
#undef OVERLAY
#undef OVERLAY2
}

static void Resolve( AstFrame *this_frame, const double point1[],
                     const double point2[], const double point3[],
                     double point4[], double *d1, double *d2, int *status ){
/*
*  Name:
*     Resolve

ast/src/skyframe.c  view on Meta::CPAN

   if( !astOK ) result = astAnnul( result );

/* Return a pointer to the output PointSet. */
   return result;
}

static void SetAsTime( AstSkyFrame *this, int axis, int value, int *status ) {
/*
*  Name:
*     SetAsTime

*  Purpose:
*     Set a value for the AsTime attribute for a SkyFrame's axis.

*  Type:
*     Private function.

*  Synopsis:
*     #include "skyframe.h"
*     void SetAsTime( AstSkyFrame *this, int axis, int value, int *status )

*  Class Membership:
*     SkyFrame member function.

*  Description:
*     This function sets the boolean value of the AsTime attribute for a
*     specified axis of a SkyFrame. This value indicates whether axis values
*     should be formatted as times (as opposed to angles) by default.

*  Parameters:
*     this
*        Pointer to the SkyFrame.
*     axis
*        Index of the axis for which a value is to be set (zero based).
*     value
*        The boolean value to be set.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     void.
*/

/* Local Variables: */
   AstAxis *ax;                  /* Pointer to Axis object */
   AstSkyAxis *new_ax;           /* Pointer to new SkyAxis object */

/* Check the global error status. */
   if ( !astOK ) return;

/* Validate the axis index. */
   (void) astValidateAxis( this, axis, 1, "astSetAsTime" );

/* Obtain a pointer to the Axis object. */
   ax = astGetAxis( this, axis );

/* Check if the Axis object is a SkyAxis. If not, we will replace it with
   one. */
   if ( !astIsASkyAxis( ax ) ) {

/* Create a new SkyAxis and overlay the attributes of the original Axis. */
      new_ax = astSkyAxis( "", status );
      astAxisOverlay( ax, new_ax );

/* Modify the SkyFrame to use the new Skyaxis and annul the original Axis
   pointer. Retain a pointer to the new SkyAxis. */
      astSetAxis( this, axis, new_ax );
      ax = astAnnul( ax );
      ax = (AstAxis *) new_ax;
   }

/* Set a value for the Axis AsTime attribute. */
   astSetAxisAsTime( ax, value );

/* Annul the Axis pointer. */
   ax = astAnnul( ax );
}

static void SetAttrib( AstObject *this_object, const char *setting, int *status ) {
/*
*  Name:
*     SetAttrib

*  Purpose:
*     Set an attribute value for a SkyFrame.

*  Type:
*     Private function.

*  Synopsis:
*     #include "skyframe.h"
*     void SetAttrib( AstObject *this, const char *setting, int *status )

*  Class Membership:
*     SkyFrame member function (extends the astSetAttrib method inherited from
*     the Mapping class).

*  Description:
*     This function assigns an attribute value for a SkyFrame, the attribute
*     and its value being specified by means of a string of the form:
*
*        "attribute= value "
*
*     Here, "attribute" specifies the attribute name and should be in lower
*     case with no white space present. The value to the right of the "="
*     should be a suitable textual representation of the value to be assigned
*     and this will be interpreted according to the attribute's data type.
*     White space surrounding the value is only significant for string
*     attributes.

*  Parameters:
*     this
*        Pointer to the SkyFrame.
*     setting
*        Pointer to a null terminated string specifying the new attribute
*        value.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     void

ast/src/skyframe.c  view on Meta::CPAN


/* Create the vector R0 representing the given point. The XY plane
   defines zero latitude, Z is in the direction of increasing latitude,
   X is towards zero longitude, and Y is towards longitude 90 degrees. */
   r0[ 0 ] =  cosb0*cosa0;
   r0[ 1 ] =  cosb0*sina0;
   r0[ 2 ] =  sinb0;

/* Create the vector R1 representing the point in the meridian of the
   given point which has latitude 90 degrees greater than the
   given point. */
   r1[ 0 ] = -sinb0*cosa0;
   r1[ 1 ] = -sinb0*sina0;
   r1[ 2 ] =  cosb0;

/* Create the vector R2 representing the point on the equator (i.e. a
   latitude of zero), which has a longitude 90 degrees to the west of
   the given point. */
   r2[ 0 ] = -sina0;
   r2[ 1 ] =  cosa0;
   r2[ 2 ] =  0.0;

/* Create the vector R3 representing the point which is 90 degrees away
   from the given point, along the required great circle. */
   r3[ 0 ] =  cospa*r1[ 0 ] + sinpa*r2[ 0 ];
   r3[ 1 ] =  cospa*r1[ 1 ] + sinpa*r2[ 1 ];
   r3[ 2 ] =  cospa*r1[ 2 ] + sinpa*r2[ 2 ];

/* Return */
   return;
}

static int SubFrame( AstFrame *target_frame, AstFrame *template,
                     int result_naxes, const int *target_axes,
                     const int *template_axes, AstMapping **map,
                     AstFrame **result, int *status ) {
/*
*  Name:
*     SubFrame

*  Purpose:
*     Select axes from a SkyFrame and convert to the new coordinate system.

*  Type:
*     Private function.

*  Synopsis:
*     #include "skyframe.h"
*     int SubFrame( AstFrame *target, AstFrame *template,
*                   int result_naxes, const int *target_axes,
*                   const int *template_axes, AstMapping **map,
*                   AstFrame **result, int *status )

*  Class Membership:
*     SkyFrame member function (over-rides the protected astSubFrame method
*     inherited from the Frame class).

*  Description:
*     This function selects a requested sub-set (or super-set) of the axes from
*     a "target" SkyFrame and creates a new Frame with copies of the selected
*     axes assembled in the requested order. It then optionally overlays the
*     attributes of a "template" Frame on to the result. It returns both the
*     resulting Frame and a Mapping that describes how to convert between the
*     coordinate systems described by the target and result Frames. If
*     necessary, this Mapping takes account of any differences in the Frames'
*     attributes due to the influence of the template.

*  Parameters:
*     target
*        Pointer to the target SkyFrame, from which axes are to be selected.
*     template
*        Pointer to the template Frame, from which new attributes for the
*        result Frame are to be obtained. Optionally, this may be NULL, in
*        which case no overlaying of template attributes will be performed.
*     result_naxes
*        Number of axes to be selected from the target Frame. This number may
*        be greater than or less than the number of axes in this Frame (or
*        equal).
*     target_axes
*        Pointer to an array of int with result_naxes elements, giving a list
*        of the (zero-based) axis indices of the axes to be selected from the
*        target SkyFrame. The order in which these are given determines the
*        order in which the axes appear in the result Frame. If any of the
*        values in this array is set to -1, the corresponding result axis will
*        not be derived from the target Frame, but will be assigned default
*        attributes instead.
*     template_axes
*        Pointer to an array of int with result_naxes elements. This should
*        contain a list of the template axes (given as zero-based axis indices)
*        with which the axes of the result Frame are to be associated. This
*        array determines which axes are used when overlaying axis-dependent
*        attributes of the template on to the result. If any element of this
*        array is set to -1, the corresponding result axis will not receive any
*        template attributes.
*
*        If the template argument is given as NULL, this array is not used and
*        a NULL pointer may also be supplied here.
*     map
*        Address of a location to receive a pointer to the returned Mapping.
*        The forward transformation of this Mapping will describe how to
*        convert coordinates from the coordinate system described by the target
*        SkyFrame to that described by the result Frame. The inverse
*        transformation will convert in the opposite direction.
*     result
*        Address of a location to receive a pointer to the result Frame.
*     status
*        Pointer to the inherited status variable.

*  Returned Value:
*     A non-zero value is returned if coordinate conversion is possible
*     between the target and the result Frame. Otherwise zero is returned and
*     *map and *result are returned as NULL (but this will not in itself
*     result in an error condition). In general, coordinate conversion should
*     always be possible if no template Frame is supplied but may not always
*     be possible otherwise.

*  Notes:
*     -  A value of zero will be returned if this function is invoked with the
*     global error status set, or if it should fail for any reason.

*  Implementation Notes:
*     -  This implementation addresses the selection of axes from a SkyFrame
*     object. This results in another object of the same class only if both
*     axes of the SkyFrame are selected, once each. Otherwise, the result is a
*     Frame class object which inherits the SkyFrame's axis information (if
*     appropriate) but none of the other properties of a SkyFrame.
*     -  In the event that a SkyFrame results, the returned Mapping will take
*     proper account of the relationship between the target and result sky
*     coordinate systems.
*     -  In the event that a Frame class object results, the returned Mapping
*     will only represent a selection/permutation of axes.

*  Implementation Deficiencies:
*     -  Any axis selection is currently permitted. Probably this should be
*     restricted so that each axis can only be selected once. The
*     astValidateAxisSelection method will do this but currently there are bugs
*     in the CmpFrame class that cause axis selections which will not pass this
*     test. Install the validation when these are fixed.
*/

/* Local Variables: */
   AstAxis *ax;                  /* Pointer to result Frame Axis object */
   AstMapping *tmpmap;           /* Temporary Mapping pointer */
   AstPermMap *permmap;          /* Pointer to PermMap */
   AstSkyFrame *target;          /* Pointer to the SkyFrame structure */
   AstSkyFrame *temp;            /* Pointer to copy of target SkyFrame */
   AstSystemType align_sys;      /* System in which to align the SkyFrames */
   int match;                    /* Coordinate conversion is possible? */
   int perm[ 2 ];                /* Permutation array for axis swap */
   int result_swap;              /* Swap result SkyFrame coordinates? */
   int set_usedefs;              /* Set the returned UseDefs attribute zero?*/
   int target_axis;              /* Target SkyFrame axis index */
   int target_swap;              /* Swap target SkyFrame coordinates? */

/* Initialise the returned values. */
   *map = NULL;
   *result = NULL;
   match = 0;

/* Check the global error status. */
   if ( !astOK ) return match;

/* Obtain a pointer to the target SkyFrame structure. */
   target = (AstSkyFrame *) target_frame;

/* Result is a SkyFrame. */
/* --------------------- */
/* Check if the result Frame is to have two axes obtained by selecting
   both of the target SkyFrame axes, in either order. If so, the
   result will also be a SkyFrame. */
   if ( ( result_naxes == 2 ) &&
        ( ( ( target_axes[ 0 ] == 0 ) && ( target_axes[ 1 ] == 1 ) ) ||
          ( ( target_axes[ 0 ] == 1 ) && ( target_axes[ 1 ] == 0 ) ) ) ) {

/* If a template has not been supplied, or is the same object as the
   target, we are simply extracting axes from the supplied SkyFrame. In
   this case we temporarily force the UseDefs attribute to 1 so that (for
   instance) the astPickAxes method can function correctly. E.g. if you
   have a SkyFrame with no set Epoch and UseDefs set zero,  and you try to
   swap the axes, the attempt would fail because MakeSkyMapping would be
   unable to determine the Mapping from original to swapped SkyFrame,
   because of the lack of an Epoch value. */
      set_usedefs = 0;
      if( !template || template == target_frame ) {
         if( !astGetUseDefs( target ) ) {
            astClearUseDefs( target );
            set_usedefs = 1;
         }
      }

/* Form the result from a copy of the target and then permute its axes
   into the order required. */
      *result = astCopy( target );
      astPermAxes( *result, target_axes );

/* If required, overlay the template attributes on to the result SkyFrame.
   Also get the system in which to align the two SkyFrames. This is the
   value of the AlignSystem attribute from the template (if there is a
   template). */
      if ( template ) {
         astOverlay( template, template_axes, *result );
         align_sys = astGetAlignSystem( template );

      } else {
         align_sys = astGetAlignSystem( target );
      }

/* See whether alignment occurs in offset coordinates or absolute
   coordinates. If the current call to this function is part of the
   process of restoring a FrameSet's integrity following changes to
   the FrameSet's current Frame, then we ignore the setting of the
   AlignOffset attributes and use 0. This ensures that when the System
   attribute (for instance) is changed via a FrameSet pointer, the
   Mappings within the FrameSet are modified to produce offsets in the
   new System. If we are not currently restoring a FrameSet's integrity,
   then we align in offsets if the template is a SkyFrame and both template
   and target want alignment to occur in the offset coordinate system. In
   this case we use a UnitMap to connect them. */
      if( ( astGetFrameFlags( target_frame ) & AST__INTFLAG ) == 0 ) {
         if( astGetAlignOffset( target ) &&
             astGetSkyRefIs( target ) != AST__IGNORED_REF &&
             template && astIsASkyFrame( template ) ){
            if( astGetAlignOffset( (AstSkyFrame *) template ) &&
                astGetSkyRefIs( (AstSkyFrame *) template ) != AST__IGNORED_REF ) {
               match = 1;
               *map = (AstMapping *) astUnitMap( 2, "", status );
            }
         }
      }

/* Otherwise, generate a Mapping that takes account of changes in the sky
   coordinate system (equinox, epoch, etc.) between the target SkyFrame and
   the result SkyFrame. If this Mapping can be generated, set "match" to
   indicate that coordinate conversion is possible. */
      if( ! *map ) {
         match = ( MakeSkyMapping( target, (AstSkyFrame *) *result,
                                   align_sys, map, status ) != 0 );
      }

/* If required, re-instate the original zero value of UseDefs. */
      if( set_usedefs ) {
         astSetUseDefs( target, 0 );
         astSetUseDefs( *result, 0 );
      }

/* If a Mapping has been obtained, it will expect coordinate values to be
   supplied in (longitude,latitude) pairs. Test whether we need to swap the
   order of the target SkyFrame coordinates to conform with this. */
      if ( astOK && match ) {
         target_swap = ( astValidateAxis( target, 0, 1, "astSubFrame" ) != 0 );

/* Coordinates will also be delivered in (longitude,latitude) pairs, so check
   to see whether the result SkyFrame coordinate order should be swapped. */
         result_swap = ( target_swap != ( target_axes[ 0 ] != 0 ) );

/* If either set of coordinates needs swapping, create a PermMap that

ast/src/skyframe.c  view on Meta::CPAN

      temp = astCopy( target );

/* Define a macro to test if an attribute is set. If not, set it
   explicitly to its default value. */
#define SET(attribute) \
   if ( !astTest##attribute( temp ) ) { \
      astSet##attribute( temp, astGet##attribute( temp ) ); \
   }

/* Set attribute values which apply to the Frame as a whole and which
   we want to retain, but whose defaults are over-ridden by the
   SkyFrame class. */
      SET(Domain)
      SET(Title)

/* Now loop to set explicit attribute values for each axis. */
      for ( target_axis = 0; target_axis < 2; target_axis++ ) {

/* Define a macro to test if an axis attribute is set. If not, set it
   explicitly to its default value. */
#define SET_AXIS(attribute) \
   if ( !astTest##attribute( temp, target_axis ) ) { \
      astSet##attribute( temp, target_axis, \
                         astGet##attribute( temp, target_axis ) ); \
   }

/* Use this macro to set explicit values for all the axis attributes
   for which the SkyFrame class over-rides the default value. */
         SET_AXIS(AsTime)
         SET_AXIS(Format)
         SET_AXIS(Label)
         SET_AXIS(Symbol)
         SET_AXIS(Unit)

/* Now handle axis attributes for which there are no SkyFrame access
   methods.  For these we require a pointer to the temporary
   SkyFrame's Axis object. */
         ax = astGetAxis( temp, target_axis );

/* Set an explicit value for the IsLatitude and CentreZero attributes. */
         if( astValidateAxis( temp, target_axis, 1, "astSubFrame" ) == 1 ) {
            astSetAxisIsLatitude( ax, 1 );
            astSetAxisCentreZero( ax, 1 );

         } else {
            astSetAxisIsLatitude( ax, 0 );
            astSetAxisCentreZero( ax, astGetNegLon( temp ) );
         }

/* Annul the Axis object pointer. */
         ax = astAnnul( ax );
      }

/* Clear attributes which have an extended range of values allowed by
   this class. */
      astClearSystem( temp );
      astClearAlignSystem( temp );

/* Invoke the astSubFrame method inherited from the Frame class to
   produce the result Frame by selecting the required set of axes and
   overlaying the template Frame's attributes. */
      match = (*parent_subframe)( (AstFrame *) temp, template,
                                  result_naxes, target_axes, template_axes,
                                  map, result, status );

/* Delete the temporary copy of the target SkyFrame. */
      temp = astDelete( temp );
   }

/* Ensure the returned Frame does not have active units. */
   astSetActiveUnit( *result, 0 );

/* If an error occurred or no match was found, annul the returned
   objects and reset the returned result. */
   if ( !astOK || !match ) {
      if( *map ) *map = astAnnul( *map );
      if( *result ) *result = astAnnul( *result );
      match = 0;
   }

/* Return the result. */
   return match;

/* Undefine macros local to this function. */
#undef SET
#undef SET_AXIS
}

static AstSystemType SystemCode( AstFrame *this, const char *system, int *status ) {
/*
*  Name:
*     SystemCode

*  Purpose:
*     Convert a string into a coordinate system type code.

*  Type:
*     Private function.

*  Synopsis:
*     #include "skyframe.h"
*     AstSystemType SystemCode( AstFrame *this, const char *system, int *status )

*  Class Membership:
*     SkyFrame member function (over-rides the astSystemCode method
*     inherited from the Frame class).

*  Description:
*     This function converts a string used for the external
*     description of a sky coordinate system into a SkyFrame
*     coordinate system type code (System attribute value). It is the
*     inverse of the astSystemString function.

*  Parameters:
*     this
*        The Frame.
*     system
*        Pointer to a constant null-terminated string containing the
*        external description of the sky coordinate system.
*     status
*        Pointer to the inherited status variable.



( run in 1.138 second using v1.01-cache-2.11-cpan-7fcb06a456a )