Starlink-AST

 view release on metacpan or  search on metacpan

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

#include "pointset.h"            /* Sets of points */
#include "object.h"              /* Base Object class */
#include "mapping.h"             /* Coordinate Mappings */
#include "unitmap.h"             /* Unit Mappings */
#include "permmap.h"             /* Coordinate permutation Mappings */
#include "cmpmap.h"              /* Compound Mappings */
#include "axis.h"                /* Coordinate axes */
#include "frame.h"               /* Parent Frame class */
#include "cmpframe.h"            /* Interface definition for this class */
#include "globals.h"             /* Thread-safe global data access */

/* Error code definitions. */
/* ----------------------- */
#include "ast_err.h"             /* AST error codes */

/* C header files. */
/* --------------- */
#include <limits.h>
#include <float.h>
#include <math.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* 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 extended by this class. */
static AstSystemType (* parent_getalignsystem)( AstFrame *, int * );
static AstSystemType (* parent_getsystem)( AstFrame *, int * );
static const char *(* parent_getattrib)( AstObject *, const char *, int * );
static const char *(* parent_getdomain)( AstFrame *, int * );
static const char *(* parent_gettitle)( AstFrame *, int * );
static double (* parent_angle)( AstFrame *, const double[], const double[], const double[], int * );
static double (* parent_getdtai)( AstFrame *, int * );
static double (* parent_getdut1)( AstFrame *, int * );
static double (* parent_getepoch)( AstFrame *, int * );
static double (* parent_getobsalt)( AstFrame *, int * );
static double (* parent_getobslat)( AstFrame *, int * );
static double (* parent_getobslon)( AstFrame *, int * );
static int (* parent_getactiveunit)( AstFrame *, int * );
static int (* parent_getmaxaxes)( AstFrame *, int * );
static int (* parent_getminaxes)( AstFrame *, int * );
static size_t (* parent_getobjsize)( AstObject *, int * );
static int (* parent_getusedefs)( AstObject *, int * );
static int (* parent_testattrib)( AstObject *, const char *, int * );
static void (* parent_clearalignsystem)( AstFrame *, int * );
static void (* parent_clearattrib)( AstObject *, const char *, int * );
static void (* parent_cleardtai)( AstFrame *, int * );
static void (* parent_cleardut1)( AstFrame *, int * );
static void (* parent_clearepoch)( AstFrame *, int * );
static void (* parent_clearobsalt)( AstFrame *, int * );
static void (* parent_clearobslat)( AstFrame *, int * );
static void (* parent_clearobslon)( AstFrame *, int * );
static void (* parent_overlay)( AstFrame *, const int *, AstFrame *, int * );
static void (* parent_setactiveunit)( AstFrame *, int, 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_setepoch)( AstFrame *, double, int * );
static void (* parent_setframeflags)( AstFrame *, int, int * );
static void (* parent_setobsalt)( AstFrame *, double, int * );
static void (* parent_setobslat)( AstFrame *, double, int * );
static void (* parent_setobslon)( AstFrame *, double, int * );

#if defined(THREAD_SAFE)
static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * );
#endif


/* 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->Label_Buff[ 0 ] = 0; \
   globals->Symbol_Buff[ 0 ] = 0; \
   globals->GetDomain_Buff[ 0 ] = 0; \
   globals->GetTitle_Buff[ 0 ] = 0;

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

/* Define macros for accessing each item of thread specific global data. */
#define class_init astGLOBAL(CmpFrame,Class_Init)
#define class_vtab astGLOBAL(CmpFrame,Class_Vtab)
#define getdomain_buff astGLOBAL(CmpFrame,GetDomain_Buff)
#define gettitle_buff astGLOBAL(CmpFrame,GetTitle_Buff)
#define label_buff astGLOBAL(CmpFrame,Label_Buff)
#define symbol_buff astGLOBAL(CmpFrame,Symbol_Buff)
#define qsort_axes astGLOBAL(CmpFrame,qsort_axes)



/* If thread safety is not needed, declare and initialise globals at static
   variables. */
#else

/* Pointer to axis index array accessed by "qsort". */
static int *qsort_axes;

/* Default Label string buffer */
static char label_buff[ 101 ];

/* Default Symbol buffer */
static char symbol_buff[ 51 ];

/* Buffer for returned domain name in GetDomain */
static char getdomain_buff[ 101 ];

/* Buffer for returned title in GetTitle */
static char gettitle_buff[ 101 ];


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

   parent_clearepoch = frame->ClearEpoch;
   frame->ClearEpoch = ClearEpoch;

   parent_getdtai = frame->GetDtai;
   frame->GetDtai = GetDtai;

   parent_setdtai = frame->SetDtai;
   frame->SetDtai = SetDtai;

   parent_cleardtai = frame->ClearDtai;
   frame->ClearDtai = ClearDtai;

   parent_getdut1 = frame->GetDut1;
   frame->GetDut1 = GetDut1;

   parent_setdut1 = frame->SetDut1;
   frame->SetDut1 = SetDut1;

   parent_cleardut1 = frame->ClearDut1;
   frame->ClearDut1 = ClearDut1;

   parent_getobslon = frame->GetObsLon;
   frame->GetObsLon = GetObsLon;

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

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

   parent_getobslat = frame->GetObsLat;
   frame->GetObsLat = GetObsLat;

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

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

   parent_getobsalt = frame->GetObsAlt;
   frame->GetObsAlt = GetObsAlt;

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

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

   parent_angle = frame->Angle;
   frame->Angle = Angle;

   parent_getsystem = frame->GetSystem;
   frame->GetSystem = GetSystem;

   parent_getalignsystem = frame->GetAlignSystem;
   frame->GetAlignSystem = GetAlignSystem;

   parent_clearalignsystem = frame->ClearAlignSystem;
   frame->ClearAlignSystem = ClearAlignSystem;

   parent_overlay = frame->Overlay;
   frame->Overlay = Overlay;

   parent_setactiveunit = frame->SetActiveUnit;
   frame->SetActiveUnit = SetActiveUnit;

   parent_getactiveunit = frame->GetActiveUnit;
   frame->GetActiveUnit = GetActiveUnit;

   parent_setframeflags = frame->SetFrameFlags;
   frame->SetFrameFlags = SetFrameFlags;

   parent_getmaxaxes = frame->GetMaxAxes;
   frame->GetMaxAxes = GetMaxAxes;

   parent_getminaxes = frame->GetMinAxes;
   frame->GetMinAxes = GetMinAxes;

/* Store replacement pointers for methods which will be over-ridden by
   new member functions implemented here. */
   object->Cast = Cast;
   mapping->Decompose = Decompose;
   frame->Abbrev = Abbrev;
   frame->ClearDirection = ClearDirection;
   frame->ClearFormat = ClearFormat;
   frame->ClearLabel = ClearLabel;
   frame->ClearSymbol = ClearSymbol;
   frame->ClearUnit = ClearUnit;
   frame->Distance = Distance;
   frame->Fields = Fields;
   frame->Format = Format;
   frame->FrameGrid = FrameGrid;
   frame->Centre = Centre;
   frame->Gap = Gap;
   frame->GetAxis = GetAxis;
   frame->GetDirection = GetDirection;
   frame->GetFormat = GetFormat;
   frame->GetLabel = GetLabel;
   frame->GetNaxes = GetNaxes;
   frame->GetPerm = GetPerm;
   frame->GetSymbol = GetSymbol;
   frame->GetUnit = GetUnit;
   frame->IsUnitFrame = IsUnitFrame;
   frame->Match = Match;
   frame->Norm = Norm;
   frame->NormalPoints = NormalPoints;
   frame->NormBox = NormBox;
   frame->Offset = Offset;
   frame->PermAxes = PermAxes;
   frame->PrimaryFrame = PrimaryFrame;
   frame->Resolve = Resolve;
   frame->ResolvePoints = ResolvePoints;
   frame->SetAxis = SetAxis;
   frame->SetDirection = SetDirection;
   frame->SetFormat = SetFormat;
   frame->SetLabel = SetLabel;
   frame->SetSymbol = SetSymbol;
   frame->SetUnit = SetUnit;
   frame->SubFrame = SubFrame;
   frame->TestDirection = TestDirection;
   frame->TestFormat = TestFormat;

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

         offset2 = offset * dist2 / dist;
      }
   }

/* If OK, apply the separate offsets to each component Frame. */
   if ( astOK && !bad ) {
      astOffset( this->frame1, p1, p2, offset1, p3 );
      astOffset( this->frame2, p1 + naxes1, p2 + naxes1, offset2,
                 p3 + naxes1 );

/* Copy the resulting coordinates into the output array "point3",
   permuting them back into the required order. */
      if ( astOK ) {
         for ( axis = 0; axis < naxes; axis++ ) {
            point3[ axis ] = p3[ perm[ axis ] ];

/* If any of the result coordinates is bad, set the "bad" flag and
   quit copying. */
            if ( point3[ axis ] == AST__BAD ) {
               bad = 1;
               break;
            }
         }
      }
   }

/* Free the workspace arrays. */
   p1 = astFree( p1 );
   p2 = astFree( p2 );
   p3 = astFree( p3 );

/* If no error has occurred, but bad coordinates must be returned,
   then set these in the output array. */
   if ( astOK && bad ) {
      for ( axis = 0; axis < naxes; axis++ ) point3[ axis ] = AST__BAD;
   }
}

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

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

*  Type:
*     Private function.

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

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

*  Description:
*     This function overlays attributes from a CmpFrame 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.

*  Parameters:
*     template
*        Pointer to the template CmpFrame, for whose current Frame
*        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 axis in the current Frame of
*        the template CmpFrame to which it corresponds. This array is
*        used to establish from which template Frame axis any
*        axis-dependent attributes should be obtained.
*
*        If any axis in the result Frame is not associated with a
*        template Frame 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.
*/

/* Local Variables: */
   AstCmpFrame *res;             /* Pointer to the result CmpFrame structure */
   AstCmpFrame *template;        /* Pointer to the template CmpFrame structure */
   AstFrame *sub1;               /* Template subframe for 1st result subframe */
   AstFrame *sub2;               /* Template subframe for 2nd result subframe */
   const int *perm;              /* Template axis permutation array */
   const int *rperm;             /* Result axis permutation array */
   int *axes1;                   /* Axis associations with template frame1 */
   int *axes2;                   /* Axis associations with template frame2 */
   int done;                     /* Have attributes been overlayed yet? */
   int i;                        /* Index of result axis */
   int icmp;                     /* Internal template axis number */
   int isfirst;                  /* Res. subframe -> 1st template subframe? */
   int issecond;                 /* Res. subframe -> 2nd template subframe? */
   int j;                        /* Index of template axis */
   int nc1;                      /* Number of axes in template frame1 */
   int nres1;                    /* Number of axes in first result subframe */
   int nres2;                    /* Number of axes in second result subframe */
   int nres;                     /* Number of axes in result Frame */

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

/* Obtain a pointer to the CmpFrame structure. */
   template = (AstCmpFrame *) template_frame;

/* Get the axis permutation array for the template CmpFrame. */
   perm = astGetPerm( template );

/* Get the number of axes in the first component Frame in the template
   CmpFrame. */
   nc1 = astGetNaxes( template->frame1 );

/* Indicate we have not yet overlayed any attributes. */
   done = 0;

/* If the result Frame is a CmpFrame... */
   if( astIsACmpFrame( result ) ) {

/* Get the number of axes in the two component Frames of the result CmpFrame. */
      res = (AstCmpFrame *) result;
      nres1 = astGetNaxes( res->frame1 );
      nres2 = astGetNaxes( res->frame2 );

/* Get the total number of axes in the result CmpFrame. */
      nres = nres1 + nres2;

/* Get the axis permutation array for the result CmpFrame. */
      rperm = astGetPerm( result );

/* Allocate memory for two new axes arrays, one for each result sub-frame. */
      axes1 = astMalloc( sizeof(int)*(size_t)nres1 );
      axes2 = astMalloc( sizeof(int)*(size_t)nres2 );
      if( astOK ) {

/* Assume that there is a 1-to-1 correspondence between axes in the
   subframes of the result and template CmpFrame. That is, all the axes
   in each result sub-frame are overlayed from the same template sub-frame. */
         done = 1;

/* Loop round each axis in the first result sub-frame. */
         isfirst = 0;
         issecond = 0;
         for( i = 0; i < nres1; i++ ) {

/* Find the external result CmpFrame axis index (j) for internal axis i. */
            for( j = 0; j < nres; j++ ) {
               if( rperm[ j ] == i ) break;
            }

/* Get the internal axis number within the template CmpFrame which
   provides attribute values for the current result axis. */
            icmp = perm[ template_axes ? template_axes[ j ] : j ];

/* If this template axis is in the first template subframe, store the
   corresponding internal frame axis index in "axes1" and set a flag
   indicating that the first result subframe corresponds to the first
   template subframe. If the correspondance has already been established,
   but is broken by this axis, then set "done" false and exit the axis
   loop. */
            if( icmp < nc1 ) {
               if( issecond ) {
                  done = 0;
                  break;
               } else {
                  isfirst = 1;
                  axes1[ i ] = icmp;
               }

            } else {
               if( isfirst ) {
                  done = 0;
                  break;
               } else {
                  issecond = 1;
                  axes1[ i ] = icmp - nc1;
               }
            }
         }

/* Save a pointer to the template subframe which is associated with the first
   result subframe.*/
         sub1 = isfirst ?  template->frame1 :template->frame2;

/* Now do the same for the axes in the second result sub-frame. */
         isfirst = 0;
         issecond = 0;
         for( i = 0; i < nres2; i++ ) {
            for( j = 0; j < nres; j++ ) {
               if( rperm[ j ] == i + nres1 ) break;
            }

            icmp = perm[ template_axes ? template_axes[ j ] : j ];

            if( icmp < nc1 ) {
               if( issecond ) {
                  done = 0;
                  break;
               } else {
                  isfirst = 1;
                  axes2[ i ] = icmp;
               }

            } else {
               if( isfirst ) {
                  done = 0;
                  break;
               } else {
                  issecond = 1;
                  axes2[ i ] = icmp - nc1;
               }
            }
         }

/* Save a pointer to the template subframe which is associated with the
   second result subframe.*/
         sub2 = isfirst ?  template->frame1 :template->frame2;

/* If the two used template subframes are the same, something has gone
   wrong. */
         if( sub1 == sub2 ) done = 0;

/* If all axes within each result subframe are associated with the same
   template subframe we continue to use the subframe astOverlay methods. */
         if( done ) {

/* Overlay the first result subframe. */
            astOverlay( sub1, axes1, res->frame1 );
            astOverlay( sub2, axes2, res->frame2 );
         }
      }

/* Free the axes arrays. */
      axes1 = astFree( axes1 );
      axes2 = astFree( axes2 );
   }

/* If we have not yet overlayed any attributes... */
   if( !done ) {

/* Get the number of axes in the result Frame. */
      nres = astGetNaxes( result );

/* Allocate memory for two new template_axes arrays. */
      axes1 = astMalloc( sizeof(int)*(size_t)nres );
      axes2 = astMalloc( sizeof(int)*(size_t)nres );
      if( astOK ) {

/* Set elements to -1 in "axes1" if they do not refer to the first component
   Frame in the template CmpFrame. Likewise, set elements to -1 in "axes2" if
   they do not refer to the second component Frame in the template CmpFrame. */
         for( i = 0; i < nres; i++ ) {

/* Get the internal axis number within the template CmpFrame which
   provides attribute values for the current results axis. */
            icmp = perm[ template_axes ? template_axes[ i ] : i ];

/* If this template axis is in the first component Frame, store the
   corresponding internal frame axis index in "axes1" and set "axis2" to
   -1. */
            if( icmp < nc1 ) {
               axes1[ i ] = icmp;
               axes2[ i ] = -1;

/* If this template axis is in the second component Frame, store the
   corresponding internal frame axis index in "axes2" and set "axis1" to
   -1. */
            } else {
               axes1[ i ] = -1;
               axes2[ i ] = icmp - nc1;
            }
         }

/* Now use the astOverlay methods of the two component Frames to overlay
   attributes onto the appropriate axes of the results Frame. */
         astOverlay( template->frame1, axes1, result );
         astOverlay( template->frame2, axes2, result );
      }

/* Free the axes arrays. */
      axes1 = astFree( axes1 );
      axes2 = astFree( axes2 );
   }
}

static void PartitionSelection( int nselect, const int select[],
                                const int perm[], int naxes1, int naxes2,
                                int iframe[], int following, int *status ) {
/*
*  Name:
*     PartitionSelection

*  Purpose:
*     Partition a CmpFrame axis selection into two component Frame selections.

*  Type:
*     Private function.

*  Synopsis:
*     #include "cmpframe.h"
*     void PartitionSelection( int nselect, const int select[],
*                              const int perm[], int naxes1, int naxes2,
*                              int iframe[], int following, int *status )

*  Class Membership:
*     CmpFrame member function.

*  Description:
*     This function accepts an array containing the indices of axes
*     which are to be selected from a CmpFrame, and partitions these
*     indices to indicate which must be selected from each of the
*     CmpFrame's two component Frames.
*
*     This operation is trivial if all the axis indices supplied refer
*     to valid CmpFrame axes. However, if some of them do not (these
*     should generally be set to -1), this function assigns these
*     "extra" axes to one or other of the component Frames by
*     associating them with the axes selected immediately before (or
*     after). Allowance is made for the possibility that several
*     consecutive selected axes may be "extra" ones, or even that they
*     may all be. The CmpFrame's axis permutation array is also taken
*     into account.

*  Parameters:
*     nselect
*        The number of axes to be selected.
*     select
*        An array containing the (zero-based) indices of the CmpFrame
*        axes to be selected, or -1 where "extra" axes are required.
*     perm
*        The CmpFrame's axis permutation array.
*     naxes1
*        The number of axes in the CmpFrame's first component Frame.
*     naxes2

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

   AstMapping *permmap;          /* Pointer to PermMap */
   AstMapping *tmp_map;          /* Temporary Mapping pointer */
   const int *perm;              /* Template axis permutation array pointer */
   int *inperm;                  /* Pointer to temporary permutation array */
   int *invperm;                 /* Inverse axis permutation array pointer */
   int *outperm;                 /* Pointer to temporary permutation array */
   int *pick;                    /* Pointer to array of axis selections */
   int *result_order;            /* Relative result axis order array pointer */
   int *result_perm;             /* Result axis permutation array pointer */
   int *target_assoc;            /* Target axis association array pointer */
   int *target_axes1;            /* Target axis associations from 1st match */
   int *target_axes2;            /* Target axis associations from 2nd match */
   int *template_assoc;          /* Template axis association array pointer */
   int *template_axes1;          /* Template axis associations, 1st match */
   int *template_axes2;          /* Template axis associations, 2nd match */
   int first;                    /* Axis in 1st component? */
   int full_axis;                /* Result Frame axis index, before sub-set */
   int match1;                   /* First match successful? */
   int match2;                   /* Second match successful? */
   int match;                    /* Both matches successful? (result) */
   int match_end1;               /* MatchEnd attribute for component 1 */
   int match_end2;               /* MatchEnd attribute for component 2 */
   int match_end;                /* MatchEnd attribute for template */
   int match_end_set;            /* Component MatchEnd attribute set? */
   int output_axis;              /* Output axis index */
   int part_result_axis;         /* Result Frame component axis index */
   int part_target_axis;         /* Target Frame component axis index */
   int part_template_axis;       /* Template CmpFrame component axis index */
   int permute_set;              /* Component Permute attribute set? */
   int permute_value;            /* Component Permute attribute value */
   int preserve_axes;            /* Template PreserveAxes attribute value */
   int preserve_axes_set;        /* Component PreserveAxes attribute set? */
   int ref_naxes;                /* Number of reference Frame axes */
   int result_axis;              /* Result Frame axis index */
   int result_naxes1;            /* Number of result Frame axes, component 1 */
   int result_naxes2;            /* Number of result Frame axes, component 2 */
   int result_naxes;             /* Total number of result Frame axes */
   int target_axis;              /* Target Frame axis index */
   int target_naxes;             /* Number of target Frame axes */
   int template_axis;            /* Template CmpFrame axis index */
   int template_naxes1;          /* Number of template axes, component 1 */
   int template_naxes;           /* Total number of template axes */

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

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

/* Initialise other variables to avoid compiler errors. */
   ref_naxes = 0;

/* Select the required sub-Frames from the target. */
/* ----------------------------------------------- */
/* We first create two sub-Frames (that can be matched against the two
   template component Frames) by selecting the two specified sets of
   axes from the target. This is done without overlaying any template
   attributes. Annul the Mappings produced by this process, as these
   are not needed. */

   frame1 = NULL;
   junk_map = NULL;
   (void) astSubFrame( target, NULL, naxes1, axes1, NULL, &junk_map, &frame1 );
   if( junk_map ) junk_map = astAnnul( junk_map );

   frame2 = NULL;
   junk_map = NULL;
   (void) astSubFrame( target, NULL, naxes2, axes2, NULL, &junk_map, &frame2 );
   if( junk_map ) junk_map = astAnnul( junk_map );

/* Match the sub-Frames with the template component Frames. */
/* -------------------------------------------------------- */
/* We now have two sub-Frames obtained from the target, and will
   attempt to match these with the component Frames contained within
   the template CmpFrame. */

/* Before using each template component Frame, see whether any of its
   attributes that control matching is "un-set". If so, over-ride it
   with the attribute value of the template CmpFrame as a whole. */
   match_end_set = astTestMatchEnd( template->frame1 );
   if ( !match_end_set ) {
      astSetMatchEnd( template->frame1, astGetMatchEnd( template ) );
   }
   preserve_axes_set = astTestPreserveAxes( template->frame1 );
   if ( !preserve_axes_set ) {
      astSetPreserveAxes( template->frame1, astGetPreserveAxes( template ) );
   }

/* We must also temporarily set the Permute attribute to 1 (this is
   normally the default, but might have been set otherwise). This is
   needed so that permutations of the target axes will be considered.
   Without this, the order in which the axes are presented is
   significant and we would have to test all the permutations. If the
   Permute attribute of the template CmpFrame as a whole is zero, then
   the resulting match may still have to be rejected, but this must be
   done at a higher level. */
   permute_set = astTestPermute( template->frame1 );
   permute_value = ( permute_set ) ? astGetPermute( template->frame1 ) : 0;
   astSetPermute( template->frame1, 1 );

/* Test for a match with the first template component Frame. */
   match1 = astMatch( template->frame1, frame1, matchsub,
                      &template_axes1, &target_axes1, &map1, &result1 );

/* Clear the attribute values again afterwards if necessary. */
   if ( !match_end_set ) astClearMatchEnd( template->frame1 );
   if ( !preserve_axes_set ) astClearPreserveAxes( template->frame1 );

/* Also restore the original Permute attribute setting. */
   if ( permute_set ) {
      astSetPermute( template->frame1, permute_value );
   } else {
      astClearPermute( template->frame1 );
   }

/* Repeat the whole process for the second component Frame. */
   match_end_set = astTestMatchEnd( template->frame2 );

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

*  Notes:
*     - A NULL pointer value is returned if the coordinate system
*     code was not recognised. This does not produce an error.
*     - A NULL pointer value is also returned if this function is
*     invoked with the global error status set or if it should fail
*     for any reason.
*/

/* Local Variables: */
   const char *result;           /* Pointer value to return */

/* Initialise. */
   result = NULL;

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

/* Match the "system" value against each possibility and convert to a
   string pointer. (Where possible, return the same string as would be
   used in the FITS WCS representation of the coordinate system). A
   CmpFrame only allows a single System value, "Compound". */
   switch ( system ) {
   case AST__COMP:
      result = "Compound";
      break;
   }

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

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 CmpFrame and convert to the new coordinate system.

*  Type:
*     Private function.

*  Synopsis:
*     #include "cmpframe.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:
*     CmpFrame 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" CmpFrame 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 CmpFrame, 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 CmpFrame. 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 CmpFrame 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 Deficiencies:
*     - It is not clear that the method of handling "extra" axes is
*     the best one, nor is the method of setting the "following" flag
*     necessarily correct.  However, it is also not obvious that this
*     feature will ever be needed, so improvements have been left
*     until the requirement is clearer.
*/

/* Local Variables: */
   AstCmpFrame *target;          /* Pointer to target CmpFrame structure */
   AstFrame *sub_result1;        /* Pointer to result Frame for frame1 */
   AstFrame *sub_result2;        /* Pointer to result Frame for frame2 */
   AstMapping *permmap_pref;     /* Pointer to PermMap used as a prefix */
   AstMapping *permmap_suff;     /* Pointer to PermMap used as a suffix */
   AstMapping *sub_map1;         /* Pointer to Mapping from frame1 */
   AstMapping *sub_map2;         /* Pointer to Mapping from frame2 */
   AstMapping *sub_map;          /* Pointer to combined component Mappings */
   AstMapping *tmp_map;          /* Temporary Mapping pointer */
   const int *perm;              /* Pointer to axis permutation array */
   int *frame_choice;            /* Pointer to flag array for partitioning */
   int *inperm_pref;             /* Pointer to prefix permutation array */
   int *inperm_suff;             /* Pointer to suffix permutation array */
   int *outperm_pref;            /* Pointer to prefix permutation array */
   int *outperm_suff;            /* Pointer to suffix permutation array */
   int *target_axes1;            /* Pointer to frame1 axis selection array */
   int *target_axes2;            /* Pointer to frame2 axis selection array */
   int *template_axes1;          /* Pointer to frame1 template axis array */
   int *template_axes2;          /* Pointer to frame2 template axis array */
   int axis_p;                   /* Permuted axis index */

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


/* Allocate two arrays to hold the axis indices that refer to each of
   the component Frames. The maximum number of indices is given by
   "result_naxes" (if all the selected axes come from one component
   Frame alone). */
   target_axes1 = astMalloc( sizeof( int ) * (size_t) result_naxes );
   target_axes2 = astMalloc( sizeof( int ) * (size_t) result_naxes );

/* If a template Frame has been provided, allocate similar arrays to
   hold the indices of the two groups of template axes. */
   if ( template ) {
      template_axes1 = astMalloc( sizeof( int ) * (size_t) result_naxes );
      template_axes2 = astMalloc( sizeof( int ) * (size_t) result_naxes );
   }

/* Initialise the count of axes selected from each component Frame. */
   if ( astOK ) {
      n1 = n2 = 0;

/* Loop through each axis index to be selected from the CmpFrame. */
      for ( result_axis = 0; result_axis < result_naxes; result_axis++ ) {
         target_axis = target_axes[ result_axis ];

/* Determine if the index refers to a valid CmpFrame axis. If it does,
   then permute the index, otherwise set it to -1. */
         if ( ( target_axis >= 0 ) && ( target_axis < naxes ) ) {
            axis_p = perm[ target_axis ];
         } else {
            axis_p = -1;
         }

/* If the axis is to be selected from the first component Frame, store
   the index of the axis to be selected. Also store the associated
   template axis index (if any). */
         if ( frame_choice[ result_axis ] == 1 ) {
            target_axes1[ n1 ] = axis_p;
            if ( template ) {
               template_axes1[ n1 ] = template_axes[ result_axis ];
            }

/* Count the axes selected from the first component Frame. */
            n1++;

/* If the axis is to be selected from the second component Frame,
   store the index of the index to be selected (adjusting for the
   offset in axis numbering). Also store the associated template axis
   index (if any) and count the axes selected. */
         } else {
            target_axes2[ n2 ] = ( axis_p == -1 ) ? -1 : axis_p - naxes1;
            if ( template ) {
               template_axes2[ n2 ] = template_axes[ result_axis ];
            }
            n2++;
         }
      }
   }

/* Select from first component Frame only. */
/* --------------------------------------- */
/* If all the selected axes come from the first component Frame, use
   that Frame's astSubFrame method to select them (and overlay the
   template attributes if required). */
   if ( astOK ) {
      if ( n1 && !n2 ) {
         sub_map1 = NULL;
         match = astSubFrame( target->frame1, template, n1, target_axes1,
                              template_axes1, &sub_map1, result );

/* If this is successful, the "result" Frame will be ready to return
   and "sub_map1" will point at a Mapping that converts from the first
   component Frame to the "result" Frame. We must now modify this
   mapping to account for the CmpFrame's axis permutation array
   (i.e. make it refer back to the CmpFrame's original axis order). */
         if ( astOK && match ) {

/* To do this we must prefix the Mapping with a PermMap which converts
   between the target CmpFrame axes and those of the first component
   Frame. Allocate space for the permutation arrays required. */
            inperm_pref = astMalloc( sizeof( int ) * (size_t) naxes );
            outperm_pref = astMalloc( sizeof( int ) * (size_t) naxes1 );
            if ( astOK ) {

/* Permute each target axis index. */
               for ( target_axis = 0; target_axis < naxes; target_axis++ ) {
                  axis_p = perm[ target_axis ];

/* Set up arrays that describe this permutation and its inverse. */
                  if ( axis_p < naxes1 ) {
                     inperm_pref[ target_axis ] = axis_p;
                     outperm_pref[ axis_p ] = target_axis;

/* Note which target axes do not correspond with axes in the first
   component Frame and assign -1 (so the PermMap will assign "bad"
   coordinate values to these axes). */
                  } else {
                     inperm_pref[ target_axis ] = -1;
                  }
               }

/* Use these permutation arrays to construct the PermMap. Prefix this
   to the Mapping obtained earlier to give the final Mapping to be
   returned. */
               permmap_pref =
                  (AstMapping *) astPermMap( naxes, inperm_pref,
                                             naxes1, outperm_pref, NULL, "", status );
               *map = (AstMapping *) astCmpMap( permmap_pref, sub_map1, 1, "", status );

/* Annul the PermMap pointer. */
               permmap_pref = astAnnul( permmap_pref );
            }

/* Free the permutation arrays and annul the original Mapping pointer. */
            inperm_pref = astFree( inperm_pref );
            outperm_pref = astFree( outperm_pref );
            sub_map1 = astAnnul( sub_map1 );
         }

/* Select from second component Frame only. */
/* ---------------------------------------- */
/* If all the selected axes come from the second component Frame, use
   that Frame's astSubFrame method to select them (and overlay the
   template attributes if required). */
      } else if ( n2 && !n1 ) {
         sub_map2 = NULL;
         match = astSubFrame( target->frame2, template, n2, target_axes2,
                              template_axes2, &sub_map2, result );

/* If this is successful, the "result" Frame will be ready to return
   and "sub_map2" will point at a Mapping that converts from the second
   component Frame to the "result" Frame. We must now modify this
   mapping to account for the CmpFrame's axis permutation array
   (i.e. make it refer back to the CmpFrame's original axis order). */
         if ( astOK && match ) {

/* To do this we must prefix the Mapping with a PermMap which converts
   between the target CmpFrame axes and those of the second component
   Frame. Allocate space for the permutation arrays required. */
            inperm_pref = astMalloc( sizeof( int ) * (size_t) naxes );
            outperm_pref = astMalloc( sizeof( int ) * (size_t) naxes2 );
            if ( astOK ) {

/* Permute each target axis index. */
               for ( target_axis = 0; target_axis < naxes; target_axis++ ) {
                  axis_p = perm[ target_axis ];

/* Set up arrays that describe this permutation and its inverse,
   allowing for the shift in axis numbering for the second component
   Frame. */
                  if ( axis_p >= naxes1 ) {
                     inperm_pref[ target_axis ] = axis_p - naxes1;
                     outperm_pref[ axis_p - naxes1 ] = target_axis;

/* Note which target axes do not correspond with axes in the second
   component Frame and assign -1 (so the PermMap will assign "bad"
   coordinate values to these axes). */
                  } else {
                     inperm_pref[ target_axis ] = -1;
                  }
               }

/* Use these permutation arrays to construct the PermMap. Prefix this
   to the Mapping obtained earlier to give the final Mapping to be
   returned. */
               permmap_pref =
                  (AstMapping *) astPermMap( naxes, inperm_pref,
                                             naxes2, outperm_pref, NULL, "", status );

               *map = (AstMapping *) astCmpMap( permmap_pref, sub_map2, 1, "", status );

/* Annul the PermMap pointer. */
               permmap_pref = astAnnul( permmap_pref );
            }

/* Free the permutation arrays and annul the original Mapping pointer. */
            inperm_pref = astFree( inperm_pref );
            outperm_pref = astFree( outperm_pref );
            sub_map2 = astAnnul( sub_map2 );
         }

/* Select from both component Frames. */
/* ---------------------------------- */
/* If the selected axes come from both component Frames, then use both
   Frames' astSubFrame methods to select the required axes from each
   of them (and overlay the template attributes if required). */
      } else {
         sub_map1 = NULL;
         sub_map2 = NULL;
         sub_result1 = NULL;
         sub_result2 = NULL;
         match = astSubFrame( target->frame1, template, n1, target_axes1,
                              template_axes1, &sub_map1, &sub_result1 );
         if ( match ) {
            match = astSubFrame( target->frame2, template, n2, target_axes2,
                                 template_axes2, &sub_map2, &sub_result2 );
         }

/* If this is successful, the two "result" Frames will need to be
   combined together (in a CmpFrame) in order to produce the required
   result, and the two accompanying Mappings will also need to be
   applied in parallel (in a CmpMap). However, the axis order
   resulting from this will still not match that required.

   On the target side, this is because of the target's axis
   permutation array.  On the result side, it is because the result
   axes cannot be inter-mingled (as may be required) simply by joining
   the Frames and Mappings in parallel. The resulting CmpFrame axes
   will therefore need permuting into the required final order. */
         if ( astOK && match ) {

/* In addition, the Mappings will need to be both prefixed and
   suffixed with suitable PermMaps which re-order the axes. Allocate
   space for the permutation arrays required. */
            inperm_pref = astMalloc( sizeof( int ) * (size_t) naxes );
            outperm_pref = astMalloc( sizeof( int ) * (size_t) naxes );
            inperm_suff = astMalloc( sizeof( int ) * (size_t) result_naxes );
            outperm_suff = astMalloc( sizeof( int ) * (size_t) result_naxes );
            if ( astOK ) {

/* Set up permutation arrays to construct the prefix PermMap. This
   simply represents the target CmpFrame's axis permutation array and
   its inverse. */
               for ( target_axis = 0; target_axis < naxes; target_axis++ ) {
                  axis_p = perm[ target_axis ];
                  inperm_pref[ target_axis ] = axis_p;
                  outperm_pref[ axis_p ] = target_axis;
               }

/* Set up permutation arrays to construct the suffix PermMap. This
   represents the way the original axis selections were partitioned
   between the two component frames. */
               i1 = i2 = 0;
               for ( result_axis = 0; result_axis < result_naxes;
                                      result_axis++ ) {

/* For each result axis derived from the first component Frame, set up
   permutation array elements to link the output axis with the next
   component Frame axis. Count the number of component Frame axes
   used. */
                  if ( frame_choice[ result_axis ] == 1 ) {
                     inperm_suff[ i1 ] = result_axis;
                     outperm_suff[ result_axis ] = i1;
                     i1++;

/* Similarly link the axes derived from the second component Frame



( run in 1.299 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )