diff options
Diffstat (limited to 'ast/cmpframe.c')
-rw-r--r-- | ast/cmpframe.c | 10654 |
1 files changed, 0 insertions, 10654 deletions
diff --git a/ast/cmpframe.c b/ast/cmpframe.c deleted file mode 100644 index 09b5f73..0000000 --- a/ast/cmpframe.c +++ /dev/null @@ -1,10654 +0,0 @@ -/* -*class++ -* Name: -* CmpFrame - -* Purpose: -* Compound Frame. - -* Constructor Function: -c astCmpFrame -f AST_CMPFRAME - -* Description: -* A CmpFrame is a compound Frame which allows two component Frames -* (of any class) to be merged together to form a more complex -* Frame. The axes of the two component Frames then appear together -* in the resulting CmpFrame (those of the first Frame, followed by -* those of the second Frame). -* -* Since a CmpFrame is itself a Frame, it can be used as a -* component in forming further CmpFrames. Frames of arbitrary -* complexity may be built from simple individual Frames in this -* way. -* -* Also since a Frame is a Mapping, a CmpFrame can also be used as a -* Mapping. Normally, a CmpFrame is simply equivalent to a UnitMap, -* but if either of the component Frames within a CmpFrame is a Region -* (a sub-class of Frame), then the CmpFrame will use the Region as a -* Mapping when transforming values for axes described by the Region. -* Thus input axis values corresponding to positions which are outside the -* Region will result in bad output axis values. - -* Inheritance: -* The CmpFrame class inherits from the Frame class. - -* Attributes: -* The CmpFrame class does not define any new attributes beyond -* those which are applicable to all Frames. However, the attributes -* of the component Frames can be accessed as if they were attributes -* of the CmpFrame. For instance, if a CmpFrame contains a SpecFrame -* and a SkyFrame, then the CmpFrame will recognise the "Equinox" -* attribute and forward access requests to the component SkyFrame. -* Likewise, it will recognise the "RestFreq" attribute and forward -* access requests to the component SpecFrame. An axis index can -* optionally be appended to the end of any attribute name, in which -* case the request to access the attribute will be forwarded to the -* primary Frame defining the specified axis. - -* Functions: -c The CmpFrame class does not define any new functions beyond those -f The CmpFrame class does not define any new routines beyond those -* which are applicable to all Frames. - -* Copyright: -* Copyright (C) 1997-2006 Council for the Central Laboratory of the -* Research Councils -* Copyright (C) 2009 Science & Technology Facilities Council. -* All Rights Reserved. - -* Licence: -* This program is free software: you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation, either -* version 3 of the License, or (at your option) any later -* version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General -* License along with this program. If not, see -* <http://www.gnu.org/licenses/>. - -* Authors: -* RFWS: R.F. Warren-Smith (Starlink) -* DSB: David S. Berry (Starlink) - -* History: -* 4-MAR-1996 (RFWS): -* Original version. -* 27-FEB-1997 (RFWS): -* Improved public prologues. -* 25-FEB-1998 (RFWS): -* Over-ride the astUnformat method. -* 6-APR-1998 (RFWS): -* Fixed bug in returned value of GenAxisSelection. -* 22-SEP-1998 (RFWS): -* Fixed bug in Match function - was not checking Domain values -* for equality. -* 11-JUN-1999 (RFWS): -* Fixed bug in GenAxisSelection- some selections were being omitted. -* 5-FEB-2001 (DSB): -* Ensure that Title and Domain values appropriate to a CmpFrame -* are preserved if a CmpFrame result is generated by SubFrame. -* 27-FEB-2001 (DSB): -* Modified Match so that all the frames have some axes in order to -* match. Otherwise, null pointers are created (for zero axes), -* resulting in a seg vio. -* 21-JUN-2001 (DSB): -* Added astAngle. -* 7-SEP-2001 (DSB): -* Added astResolve. -* 26-SEP-2001 (DSB): -* Over-ride the astDecompose method. -* 20-DEC-2002 (DSB): -* Allows any attribute of a component frame to be accessed as though -* it were an attribute of the CmpFrame by including an axis index in -* the attribute name (e.g. "System(3)"). -* 8-JAN-2003 (DSB): -* - Changed private InitVtab method to protected astInitCmpFrameVtab -* method. -* - Override astGetAttrib, astClearAttrib, astTestAttrib, -* astSetAttrib to allow attributes to be set for individual -* axes. -* - Override astGetEpoch astGetSystem, astGetAlignSystem. -* astValidateSystem, astSystemString, astSystemCode. -* 27-FEB-2003 (DSB): -* - Modify the default Domain name for a CmpFrame to be the -* domains of the two subFrames separated by a "-". -* 24-JAN-2004 (DSB): -* o Override the astFields method. -* o Added argument "fmt" to Abbrev. -* 24-MAR-2004 (DSB): -* Over-ride the astSimplify and astTransform methods. -* 8-SEP-2004 (DSB): -* Over-ride astResolvePoints method. -* 21-JAN-2005 (DSB): -* Over-ride the astGetActiveUnit and astSetActiveUnit methods. -* 23-FEB-2005 (DSB): -* Modify GetDomain to avoid over-writing the static "buff" array -* if called recursively. -* 29-MAR-2005 (DSB): -* Override astSetEpoch and astClearEpoch by implementations which -* propagate the changed epoch value to the component Frames. -* 5-APR-2005 (DSB): -* Correct error checking in Clear/Get/Set/TestAttrib. -* 12-MAY-2005 (DSB): -* Override astNormBox method. -* 12-AUG-2005 (DSB): -* Override astSetObsLat/Lon and astClearObslat/Lon by implementations -* which propagate the changed value to the component Frames. -* 14-FEB-2006 (DSB): -* Override astGetObjSize. -* 3-APR-2006 (DSB): -* Modify Match so that an attempt is made to align the target with -* each of the two component Frames if the target cannot be matched -* with the CmpFrame as a whole. -* 3-MAY-2006 (DSB): -* Fix bug in Match that could cause segvio when matching a target -* against the second component of a CmpFrame. -* 31-OCT-2006 (DSB): -* Over-ride the SetFrameFlags method. -* 1-NOV-2005 (DSB): -* Override astSetDut1, astGetDut1 and astClearDut1. -* 15-MAR-2007 (DSB): -* Override astClearAlignSystem by an implementation that clears -* AlignSystem in the component Frames. -* 7-FEB-2008 (DSB): -* Allow the MaxAxes and MinAxes attributes to be specified for a -* CmpFrame (rather than just being the sum of the attribute values -* in the component frames). This enables, for instance, a (detector -* index,mjd) frame to match with a ((velocity,detector index),mjd) -* frame. -* 5-MAY-2009 (DSB): -* In GetAttrib, if an index is included in the attribute name, attempt -* to use the GetAttrib method of the primary frame before using the -* parent GetAttrib method. This is because the Frame getattrib -* method will dissociate axes from their parent class. Thus, a -* SkyAxis attribute such as AsTime will come out wrong since its -* value is managed by the SkyFrame class rather than the SkyAxis -* class. -* 18-JUN-2009 (DSB): -* Override astSetObsAlt and astClearObsAlt. -* 29-SEP-2009 (DSB): -* Ensure the astMatch method provided by this class honours the -* PreserveAxes, MaxAxes and MinAxes attribute settings. -* 22-MAR-2011 (DSB): -* Override astFrameGrid method. -* 29-APR-2011 (DSB): -* Prevent astFindFrame from matching a subclass template against a -* superclass target. -* 10-FEB-2015 (DSB): -* When checking attribute settings for attribute names that end with -* an axis index, stop looking for the axis index when the first equals -* sign is encountered. -* 26-MAR-2015 (DSB): -* Increase size of "buf2" buffer in SetAttrib, and trap buffer overflow. -*class-- -*/ - -/* Module Macros. */ -/* ============== */ -/* Set the name of the class we are implementing. This indicates to - the header files that define class interfaces that they should make - "protected" symbols available. */ -#define astCLASS CmpFrame - -/* Define the first and last acceptable System values. */ -#define FIRST_SYSTEM AST__COMP -#define LAST_SYSTEM AST__COMP - -/* Define macros to implement member functions for accessing axis - attributes. */ -/* -* Name: -* MAKE_CLEAR - -* Purpose: -* Implement a function to clear an attribute value for a CmpFrame axis. - -* Type: -* Private macro. - -* Synopsis: -* #include "cmpframe.h" -* MAKE_CLEAR(attribute) - -* Class Membership: -* Defined by the CmpFrame class. - -* Description: -* This macro expands to an implementation of a private member -* function of the form: -* -* static void Clear<Attribute>( AstFrame *this, int axis ) -* -* which clears an attribute value for a specified axis of a CmpFrame. - -* Parameters: -* attribute -* The name of the attribute to be cleared, as it appears in the -* function name (e.g. Label in "ClearLabel"). - -* Notes: -* - This macro assumes the existence of a method of the form: -* -* void astClear<Attribute>( AstFrame *this, int axis ) -* -* which clears the required attribute for a Frame object. -* - To avoid problems with some compilers, you should not leave -* any white space around the macro arguments. -*/ - -/* Define the macro. */ -#define MAKE_CLEAR(attribute) \ -static void Clear##attribute( AstFrame *this_frame, int axis, int *status ) { \ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ \ - int naxes1; /* Number of axes in frame1 */ \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Obtain a pointer to the CmpFrame structure. */ \ - this = (AstCmpFrame *) this_frame; \ -\ -/* Validate and alidateAxispermute the axis index supplied. */ \ - axis = astValidateAxis( this, axis, 1, "astSet" #attribute ); \ -\ -/* Determine the number of axes in the first component Frame. */ \ - naxes1 = astGetNaxes( this->frame1 ); \ - if ( astOK ) { \ -\ -/* Decide which Frame contains the axis and invoke its astClear... method to \ - clear the attribute value. */ \ - if ( axis < naxes1 ) { \ - astClear##attribute( this->frame1, axis ); \ - } else { \ - astClear##attribute( this->frame2, axis - naxes1 ); \ - } \ - } \ -} - -/* -* Name: -* MAKE_GET - -* Purpose: -* Implement a function to get an attribute value for a CmpFrame axis. - -* Type: -* Private macro. - -* Synopsis: -# #include "cmpframe.h" -* MAKE_GET(attribute,type,bad_value,default,assign_default) - -* Class Membership: -* Defined by the CmpFrame class. - -* Description: -* This macro expands to an implementation of a private member -* function of the form: -* -* static <Type> Get<Attribute>( AstFrame *this, int axis ) -* -* which gets an attribute value for a specified axis of a -* CmpFrame. - -* Parameters: -* attribute -* The name of the attribute whose value is to be obtained, as -* it appears in the function name (e.g. Label in "GetLabel"). -* type -* The C type of the attribute. -* bad_value -* A constant value to return if the global error status is set, -* or if the function fails. -* default -* A boolean (int) value that indicates whether a new default -* value should be returned if the requested attribute has not -* been set for the appropriate axis of the appropriate -* component Frame. If this value is zero, the component Frame's -* default (for the appropriate axis) will be used instead. -* assign_default -* An expression that evaluates to the new default value to be -* assigned. This value is ignored if "default" is zero, but a -* valid (e.g. constant) value should nevertheless be supplied. - -* Notes: -* - This macro assumes the existence of a method of the form: -* -* <Type> astGet<Attribute>( AstFrame *this, int axis ) -* -* which gets the required attribute for a Frame object. -* - To avoid problems with some compilers, you should not leave -* any white space around the macro arguments. -*/ - -/* Define the macro. */ -#define MAKE_GET(attribute,type,bad_value,default,assign_default) \ -static type Get##attribute( AstFrame *this_frame, int axis, int *status ) { \ - astDECLARE_GLOBALS /* Declare the thread specific global data */ \ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ \ - AstFrame *frame; /* Pointer to Frame containing axis */\ - int axis_p; /* Permuted axis index */ \ - int naxes1; /* Number of axes in frame1 */ \ - int set; /* Digits attribute set? */ \ - type result; /* Result value to return */ \ - \ -/* Initialise. */ \ - result = (bad_value); \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Get a pointer to the structure holding thread-specific global data. */ \ - astGET_GLOBALS(this_frame); \ -\ -/* Obtain a pointer to the CmpFrame structure. */ \ - this = (AstCmpFrame *) this_frame; \ -\ -/* Validate and permute the axis index supplied. */ \ - axis_p = astValidateAxis( this, axis, 1, "astGet" #attribute ); \ -\ -/* Determine the number of axes in the first component Frame. */ \ - naxes1 = astGetNaxes( this->frame1 ); \ - if ( astOK ) { \ -\ -/* Decide which Frame contains the axis and adjust the axis index if \ - necessary. */ \ - frame = ( axis_p < naxes1 ) ? this->frame1 : this->frame2; \ - axis_p = ( axis_p < naxes1 ) ? axis_p : axis_p - naxes1; \ -\ -/* Since the component Frame is "managed" by the enclosing CmpFrame, we next \ - test if any Frame attributes which may affect the result are undefined \ - (i.e. have not been explicitly set). If so, we over-ride them, giving \ - them temporary values dictated by the CmpFrame. Only the Digits attribute \ - is relevant here. */ \ - set = astTestDigits( frame ); \ - if ( !set ) astSetDigits( frame, astGetDigits( this ) ); \ -\ -/* If the default value is to be over-ridden, test if the Frame's axis \ - attribute has been set. Then, if required, obtain the attribute value from \ - the Frame. */ \ - if ( !(default) || astTest##attribute( frame, axis_p ) ) { \ - result = astGet##attribute( frame, axis_p ); \ -\ -/* If required, assign the new default value. */ \ - } else { \ - result = (assign_default); \ - } \ -\ -/* Clear Frame attributes which were temporarily over-ridden. */ \ - if ( !set ) astClearDigits( frame ); \ - } \ -\ -/* If an error occurred, clear the result value. */ \ - if ( !astOK ) result = (bad_value); \ -\ -/* Return the result. */ \ - return result; \ -} - -/* -* Name: -* MAKE_SET - -* Purpose: -* Implement a function to set an attribute value for a CmpFrame axis. - -* Type: -* Private macro. - -* Synopsis: -* #include "cmpframe.h" -* MAKE_SET(attribute,type) - -* Class Membership: -* Defined by the CmpFrame class. - -* Description: -* This macro expands to an implementation of a private member -* function of the form: -* -* static void Set<Attribute>( AstFrame *this, int axis, <Type> value ) -* -* which sets an attribute value for a specified axis of a CmpFrame. - -* Parameters: -* attribute -* The name of the attribute to be set, as it appears in the -* function name (e.g. Label in "SetLabel"). -* type -* The C type of the attribute. - -* Notes: -* - This macro assumes the existence of a method of the form: -* -* void astSet<Attribute>( AstFrame *this, int axis, <Type> value ) -* -* which sets the required attribute for a Frame object. -* - To avoid problems with some compilers, you should not leave -* any white space around the macro arguments. -*/ - -/* Define the macro. */ -#define MAKE_SET(attribute,type) \ -static void Set##attribute( AstFrame *this_frame, int axis, type value, int *status ) { \ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ \ - int naxes1; /* Number of axes in frame1 */ \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Obtain a pointer to the CmpFrame structure. */ \ - this = (AstCmpFrame *) this_frame; \ -\ -/* Validate and permute the axis index supplied. */ \ - axis = astValidateAxis( this, axis, 1, "astSet" #attribute ); \ -\ -/* Determine the number of axes in the first component Frame. */ \ - naxes1 = astGetNaxes( this->frame1 ); \ - if ( astOK ) { \ -\ -/* Decide which Frame contains the axis and invoke its astSet... method to \ - set the attribute value. */ \ - if ( axis < naxes1 ) { \ - astSet##attribute( this->frame1, axis, value ); \ - } else { \ - astSet##attribute( this->frame2, axis - naxes1, value ); \ - } \ - } \ -} - -/* -* Name: -* MAKE_TEST - -* Purpose: -* Implement a function to test if an attribute is set for a CmpFrame axis. - -* Type: -* Private macro. - -* Synopsis: -* #include "cmpframe.h" -* MAKE_TEST(attribute) - -* Class Membership: -* Defined by the CmpFrame class. - -* Description: -* This macro expands to an implementation of a private member -* function of the form: -* -* static int Test<Attribute>( AstFrame *this, int axis ) -* -* which tests whether an attribute value is set for a specified -* axis of a CmpFrame. - -* Parameters: -* attribute -* The name of the attribute to be tested, as it appears in the -* function name (e.g. Label in "TestLabel"). - -* Notes: -* - This macro assumes the existence of a method of the form: -* -* int astTest<Attribute>( AstFrame *this, int axis ) -* -* which tests the required attribute for a Frame object. -* - To avoid problems with some compilers, you should not leave -* any white space around the macro arguments. -*/ - -/* Define the macro. */ -#define MAKE_TEST(attribute) \ -static int Test##attribute( AstFrame *this_frame, int axis, int *status ) { \ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ \ - int naxes1; /* Number of axes in frame1 */ \ - int result; /* Result value to return */ \ -\ -/* Initialise. */ \ - result = 0; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Obtain a pointer to the CmpFrame structure. */ \ - this = (AstCmpFrame *) this_frame; \ -\ -/* Validate and permute the axis index supplied. */ \ - axis = astValidateAxis( this, axis, 1, "astSet" #attribute ); \ -\ -/* Determine the number of axes in the first component Frame. */ \ - naxes1 = astGetNaxes( this->frame1 ); \ - if ( astOK ) { \ -\ -/* Decide which Frame contains the axis and invoke its astTest... method to \ - test the attribute. */ \ - if ( axis < naxes1 ) { \ - result = astTest##attribute( this->frame1, axis ); \ - } else { \ - result = astTest##attribute( this->frame2, axis - naxes1 ); \ - } \ - } \ -\ -/* Return the result. */ \ - return result; \ -} - -/* Include files. */ -/* ============== */ -/* Interface definitions. */ -/* ---------------------- */ - -#include "globals.h" /* Thread-safe global data access */ -#include "error.h" /* Error reporting facilities */ -#include "memory.h" /* Memory allocation facilities */ -#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_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 int (* 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_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_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 ]; - - -/* Define the class virtual function table and its initialisation flag - as static variables. */ -static AstCmpFrameVtab class_vtab; /* Virtual function table */ -static int class_init = 0; /* Virtual function table initialised? */ - -#endif - - -/* External Interface Function Prototypes. */ -/* ======================================= */ -/* The following functions have public prototypes only (i.e. no - protected prototypes), so we must provide local prototypes for use - within this module. */ -AstCmpFrame *astCmpFrameId_( void *, void *, const char *, ... ); - -/* Prototypes for Private Member Functions. */ -/* ======================================== */ -static AstAxis *GetAxis( AstFrame *, int, int * ); -static AstMapping *RemoveRegions( AstMapping *, int * ); -static AstMapping *Simplify( AstMapping *, int * ); -static AstObject *Cast( AstObject *, AstObject *, int * ); -static AstPointSet *FrameGrid( AstFrame *, int, const double *, const double *, int * ); -static AstPointSet *ResolvePoints( AstFrame *, const double [], const double [], AstPointSet *, AstPointSet *, int * ); -static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * ); -static AstSystemType GetAlignSystem( AstFrame *, int * ); -static AstSystemType GetSystem( AstFrame *, int * ); -static AstSystemType SystemCode( AstFrame *, const char *, int * ); -static AstSystemType ValidateSystem( AstFrame *, AstSystemType, const char *, int * ); -static const char *Abbrev( AstFrame *, int, const char *, const char *, const char *, int * ); -static const char *Format( AstFrame *, int, double, int * ); -static const char *GetDomain( AstFrame *, int * ); -static const char *GetFormat( AstFrame *, int, int * ); -static const char *GetLabel( AstFrame *, int, int * ); -static const char *GetSymbol( AstFrame *, int, int * ); -static const char *GetTitle( AstFrame *, int * ); -static const char *GetUnit( AstFrame *, int, int * ); -static const char *SystemString( AstFrame *, AstSystemType, int * ); -static const int *GetPerm( AstFrame *, int * ); -static double Angle( AstFrame *, const double[], const double[], const double[], int * ); -static double Distance( AstFrame *, const double[], const double[], int * ); -static double Centre( AstFrame *, int, double, double, int * ); -static double Gap( AstFrame *, int, double, int *, int * ); -static int ComponentMatch( AstCmpFrame *, AstFrame *, int, int, int **, int **, AstMapping **, AstFrame **, int * ); -static int Fields( AstFrame *, int, const char *, const char *, int, char **, int *, double *, int * ); -static int GenAxisSelection( int, int, int [], int * ); -static int GetActiveUnit( AstFrame *, int * ); -static int GetDirection( AstFrame *, int, int * ); -static int GetMaxAxes( AstFrame *, int * ); -static int GetMinAxes( AstFrame *, int * ); -static int GetNaxes( AstFrame *, int * ); -static int GetObjSize( AstObject *, int * ); -static int GetUseDefs( AstObject *, int * ); -static int GoodPerm( int, const int [], int, const int [], int * ); -static int IsUnitFrame( AstFrame *, int * ); -static int Match( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * ); -static int PartMatch( AstCmpFrame *, AstFrame *, int, int, const int [], int, const int [], int **, int **, AstMapping **, AstFrame **, int * ); -static int QsortCmpAxes( const void *, const void * ); -static int SubFrame( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * ); -static int TestDirection( AstFrame *, int, int * ); -static int TestFormat( AstFrame *, int, int * ); -static int TestLabel( AstFrame *, int, int * ); -static int TestSymbol( AstFrame *, int, int * ); -static int TestUnit( AstFrame *, int, int * ); -static int Unformat( AstFrame *, int, const char *, double *, int * ); -static void AddExtraAxes( int, int [], int, int, int, int * ); -static void ClearDirection( AstFrame *, int, int * ); -static void ClearFormat( AstFrame *, int, int * ); -static void ClearLabel( AstFrame *, int, int * ); -static void ClearSymbol( AstFrame *, int, int * ); -static void ClearUnit( AstFrame *, int, int * ); -static void Copy( const AstObject *, AstObject *, int * ); -static void Decompose( AstMapping *, AstMapping **, AstMapping **, int *, int *, int *, int * ); -static void Delete( AstObject *, int * ); -static void Dump( AstObject *, AstChannel *, int * ); -static void MatchAxesX( AstFrame *, AstFrame *, int *, int * ); -static void Norm( AstFrame *, double [], int * ); -static void NormBox( AstFrame *, double[], double[], AstMapping *, int * ); -static void Offset( AstFrame *, const double [], const double [], double, double [], int * ); -static void Overlay( AstFrame *, const int *, AstFrame *, int * ); -static void PartitionSelection( int, const int [], const int [], int, int, int [], int, int * ); -static void PermAxes( AstFrame *, const int[], int * ); -static void PrimaryFrame( AstFrame *, int, AstFrame **, int *, int * ); -static void RenumberAxes( int, int [], int * ); -static void Resolve( AstFrame *, const double [], const double [], const double [], double [], double *, double *, int * ); -static void SetActiveUnit( AstFrame *, int, int * ); -static void SetAxis( AstFrame *, int, AstAxis *, int * ); -static void SetDirection( AstFrame *, int, int, int * ); -static void SetFormat( AstFrame *, int, const char *, int * ); -static void SetFrameFlags( AstFrame *, int, int * ); -static void SetLabel( AstFrame *, int, const char *, int * ); -static void SetSymbol( AstFrame *, int, const char *, int * ); -static void SetUnit( AstFrame *, int, const char *, int * ); - -static const char *GetAttrib( AstObject *, const char *, int * ); -static int TestAttrib( AstObject *, const char *, int * ); -static void ClearAttrib( AstObject *, const char *, int * ); -static void SetAttrib( AstObject *, const char *, int * ); - -static double GetEpoch( AstFrame *, int * ); -static void ClearEpoch( AstFrame *, int * ); -static void SetEpoch( AstFrame *, double, int * ); - -static double GetDut1( AstFrame *, int * ); -static void ClearDut1( AstFrame *, int * ); -static void SetDut1( AstFrame *, double, int * ); - -static double GetObsLon( AstFrame *, int * ); -static void ClearObsLon( AstFrame *, int * ); -static void SetObsLon( AstFrame *, double, int * ); - -static double GetObsLat( AstFrame *, int * ); -static void ClearObsLat( AstFrame *, int * ); -static void SetObsLat( AstFrame *, double, int * ); - -static double GetObsAlt( AstFrame *, int * ); -static void ClearObsAlt( AstFrame *, int * ); -static void SetObsAlt( AstFrame *, double, int * ); - -static void ClearAlignSystem( AstFrame *, int * ); - -#if defined(THREAD_SAFE) -static int ManageLock( AstObject *, int, int, AstObject **, int * ); -#endif - -/* Member functions. */ -/* ================= */ -static const char *Abbrev( AstFrame *this_frame, int axis, const char *fmt, - const char *str1, const char *str2, int *status ) { -/* -* Name: -* Abbrev - -* Purpose: -* Abbreviate a formatted CmpFrame axis value by skipping leading fields. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* const char *Abbrev( AstFrame *this, int axis, const char *fmt, -* const char *str1, const char *str2, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astAbbrev -* method inherited from the Frame class). - -* Description: -* This function compares two CmpFrame axis values that have been -* formatted (using astFormat) and determines if they have any -* redundant leading fields (i.e. leading fields in common which -* can be suppressed when tabulating the values or plotting them on -* the axis of a graph). - -* Parameters: -* this -* Pointer to the CmpFrame. -* axis -* The number of the CmpFrame axis for which the values have -* been formatted (axis numbering starts at zero for the first -* axis). -* fmt -* Pointer to a constant null-terminated string containing the -* format specification used to format the two values. -* str1 -* Pointer to a constant null-terminated string containing the -* first formatted value. If this is null, the returned pointer -* points to the start of the final field in str2. -* str2 -* Pointer to a constant null-terminated string containing the -* second formatted value. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer into the "str2" string which locates the first -* character in the first field that differs between the two -* formatted values. -* -* If the two values have no leading fields in common, the returned -* value will point at the start of string "str2". If the two -* values are equal, it will point at the terminating null at the -* end of this string. - -* Notes: -* - This function assumes that the format specification used was -* the same when both values were formatted and that they both -* apply to the same CmpFrame axis. -* - A pointer to the start of "str2" will be returned if this -* function is invoked with the global error status set, or if it -* should fail for any reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - AstFrame *frame; /* Pointer to Frame containing axis */ - const char *result; /* Pointer value to return */ - int naxes1; /* Number of axes in frame1 */ - int set; /* Digits attribute set? */ - -/* Initialise. */ - result = str2; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate and permute the axis index supplied. */ - axis = astValidateAxis( this, axis, 1, "astAbbrev" ); - -/* Determine the number of axes in the first component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - if ( astOK ) { - -/* Decide which component Frame contains the axis and adjust the axis - index if necessary. */ - frame = ( axis < naxes1 ) ? this->frame1 : this->frame2; - axis = ( axis < naxes1 ) ? axis : axis - naxes1; - -/* Since the component Frame is "managed" by the enclosing CmpFrame, - we next test if any Frame attributes which may affect the result - are undefined (i.e. have not been explicitly set). If so, we - over-ride them, giving them temporary values dictated by the - CmpFrame. Only the Digits attribute is relevant here. */ - set = astTestDigits( frame ); - if ( !set ) astSetDigits( frame, astGetDigits( this ) ); - -/* Invoke the Frame's astAbbrev method to perform the processing. */ - result = astAbbrev( frame, axis, fmt, str1, str2 ); - -/* Clear Frame attributes which were temporarily over-ridden. */ - if ( !set ) astClearDigits( frame ); - } - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = str2; - -/* Return the result. */ - return result; -} - -static void AddExtraAxes( int naxes, int axes[], int i1, int i2, - int following, int *status ) { -/* -* Name: -* AddExtraAxes - -* Purpose: -* Add extra axis indices in place of missing ones. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void AddExtraAxes( int naxes, int axes[], int i1, int i2, -* int following, int *status ) - -* Class Membership: -* CmpFrame member function. - -* Description: -* This function takes an array of axis indices that refer to the -* axes of a Frame, and which may have values missing (denoted by -* an index of -1). It replaces each occurrence of -1 by a new axis -* index (and re-numbers the others to avoid duplication) in such a -* way that the new indices introduced are "associated" with -* certain of the pre-existing indices, by virtue of being numbered -* consecutively with them. -* -* The purpose of this operation is to establish the relative -* location of new axes in relation to the pre-existing ones. -* -* Normally, each new axis will be associated with (i.e. numbered -* one more than) the pre-existing index which precedes -* it. However, if the "following" parameter is non-zero, it will -* instead be associated with (numbered one less than) the one -* which follows it. If there is no preceding (or following) -* pre-existing index, the following (or preceding) one is used -* instead. If several adjacent occurrences of -1 must be replaced, -* they are numbered consecutively in their order of occurrence. - -* Parameters: -* naxes -* The number of axis indices in the array. -* axes -* The array containing the axis indices. -* i1 -* Index of the first element of the array to be processed. -* i2 -* Index of the last element of the array to be processed. -* following -* Boolean flag to determine if new indices are associated with -* the preceding index (if zero) or the following index (if -* non-zero). -* status -* Pointer to the inherited status variable. - -* Notes: -* - The values of "i1" and "i2" dictate the range of array -* elements where values of -1 will be replaced, but all array -* elements are candidates for renumbering in order to avoid -* duplicate axis indices. -* - This function aims to establish the location of new axes only -* by means of the relative numerical value of the indices assigned -* to them. It does not constrain the actual indices assigned in -* any further way. -* - Because axis indices are always incremented (never -* decremented) in order to avoid duplicates, where a number of new -* indices have been introduced, the maximum index present in the -* result array may exceed the original maximum. -* - Some axis indices may remain unused (i.e. not present) in the -* result array. -*/ - -/* Local Variables: */ - int end; /* Loop termination value */ - int extra; /* Index to apply to next "extra" axis */ - int found; /* Default value found? */ - int i; /* Main loop counter */ - int inc; /* Loop increment value */ - int j; /* Loop counter for eliminating duplicates */ - int start; /* Loop starting value */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Initialise the default index of the next extra axis to add. This - will apply only if there are no valid axis indices from which to - obtain a better default. */ - extra = 0; - -/* Initialise loop parameters so as to scan the axis indices provided - in either the forward or reverse direction, according to the value - of "following". Start with the section of the array being processed, - but continue looking for a default right up to the end of the array - (this prevents the current section being numbered inconsistently - with respect to adjacent ones that may already have been - processed). */ - start = following ? i2 : i1; - end = following ? -1 : naxes; - inc = following ? -1 : 1; - -/* Search for the first (in whichever direction this is) valid axis - index and use it to set a new default index for the next extra axis - to add. If scanning forward, use the valid axis index (causing any - preceding extra axis to displace it upwards). If scanning - backwards, use one more than the valid axis index (causing any - following extra axis to tag on the end). */ - found = 0; - for ( i = start; i != end; i += inc ) { - if ( axes[ i ] != -1 ) { - found = 1; - extra = axes[ i ] + ( following ? 1 : 0 ); - break; - } - } - -/* If no default has yet been found, repeat the above process by - scanning in the opposite direction (by inverting the "following" - value used). Again, this prevents inconsistency with neighbouring - regions. This time a default must be found unless the entire array - is filled with -1's (in which case a default of zero is used). */ - if ( !found ) { - start = !following ? i2 : i1; - end = !following ? -1 : naxes; - inc = !following ? -1 : 1; - for ( i = start; i != end; i += inc ) { - if ( axes[ i ] != -1 ) { - extra = axes[ i ] + ( !following ? 1 : 0 ); - break; - } - } - } - -/* Reset the loop parameters to scan just the region of interest in - the original (correct) direction. */ - start = following ? i2 : i1; - end = following ? i1 - 1 : i2 + 1; - inc = following ? -1 : 1; - -/* Identify those indices which are not valid. */ - for ( i = start; i != end; i += inc ) { - if ( axes[ i ] == -1 ) { - -/* We wish to assign the value "extra" in place of this invalid axis - index. However, this may duplicate an index already present, so - increment by one all valid indices which are not less than the new - index. This eliminates any possibility duplication, although it may - leave an axis index value unused (if no duplication would actually - have occurred). */ - for ( j = 0; j < naxes; j++ ) { - if ( axes[ j ] != -1 ) { - if ( axes[ j ] >= extra ) axes[ j ]++; - } - } - -/* We can now assign the new axis index. */ - axes[ i ] = extra; - -/* Assign the value to be used for the next extra axis index. If - scanning forward, this will be one more than the last one used (so - it will follow it). If scanning backwards, it is equal to the last - one (so that it will displace the last one upwards). */ - extra += ( following ? 0 : 1 ); - -/* When a valid axis index is encountered, reset the value to be used - for the next extra axis index. If scanning forward, this is one - more than the last valid index (so the extra axis will follow - it). If scanning backwards, it is equal to the last valid index (so - it will displace the valid index upwards). */ - } else { - extra = axes[ i ] + ( following ? 0 : 1 ); - } - } -} - -static double Angle( AstFrame *this_frame, const double a[], - const double b[], const double c[], int *status ) { -/* -* Name: -* Angle - -* Purpose: -* Calculate the angle subtended by two points at a third point. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* double Angle( AstFrame *this_frame, const double a[], -* const double b[], const double c[], int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astAngle method -* inherited from the Frame class). - -* Description: -* This function finds the angle at point B between the line joining -* points A and B, and the line joining points C and B, in the context -* of a CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* a -* An array of double, with one element for each CmpFrame axis, -* containing the coordinates of the first point. -* b -* An array of double, with one element for each CmpFrame axis, -* containing the coordinates of the second point. -* c -* An array of double, with one element for each CmpFrame axis, -* containing the coordinates of the third point. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The required angle, or AST__BAD if the angle is undefined. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - AstFrame *pframe; /* Pointer to the primary Frame for an axis */ - const int *perm; /* Pointer to axis permutation array */ - double *pa; /* Permuted coordinates for point a */ - double *pb; /* Permuted coordinates for point b */ - double *pc; /* Permuted coordinates for point c */ - double ang1; /* Angle between input points in frame1 */ - double ang2; /* Angle between input points in frame2 */ - double result; /* Required angle */ - int axis; /* Loop counter for axes */ - int iscart; /* Is the CmpFrame a Cartesian system? */ - int naxes1; /* Number of axes in frame1 */ - int naxes; /* Total number of axes in CmpFrame */ - int paxis; /* Axis index within primary Frame */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Obtain the number of axes in the CmpFrame. */ - naxes = astGetNaxes( this ); - -/* See if all axes within the CmpFrame belong to a simple Frame, in which - case we assume that the CmpFrame describes a Cartesian coordinate system. */ - iscart = 1; - for( axis = 0; axis < naxes; axis++ ){ - PrimaryFrame( this_frame, axis, &pframe, &paxis, status ); - if( strcmp( astGetClass( pframe ), "Frame" ) ) { - iscart = 0; - pframe = astAnnul( pframe ); - break; - } - pframe = astAnnul( pframe ); - } - -/* If the CmpFrame describes a Cartesian coordinate system, we can use the - Angle method from the parent Frame class. */ - if( iscart ) { - result = (*parent_angle)( this_frame, a, b, c, status ); - -/* If the CmpFrame is not Cartesian... */ - } else { - -/* Obtain a pointer to the CmpFrame's axis permutation array. */ - perm = astGetPerm( this ); - -/* Get workspace. */ - pa = (double *) astMalloc( sizeof(double)*naxes ); - pb = (double *) astMalloc( sizeof(double)*naxes ); - pc = (double *) astMalloc( sizeof(double)*naxes ); - -/* If OK, apply the axis permutation array to obtain the coordinates in the - required order. */ - if( astOK ) { - for( axis = 0; axis < naxes; axis++ ) { - pa[ perm[ axis ] ] = a[ axis ]; - pb[ perm[ axis ] ] = b[ axis ]; - pc[ perm[ axis ] ] = c[ axis ]; - } - -/* Obtain the number of axes in the first component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - -/* Project the two input points into the two component Frames and - determine the angle between the points in each Frame. */ - ang1 = astAngle( this->frame1, pa, pb, pc ); - ang2 = astAngle( this->frame2, pa + naxes1, pb + naxes1, - pc + naxes1 ); - -/* The required angle is defined if one and only one of the two component - frames gives a defined angle between the two points. */ - if( ang1 == AST__BAD ) { - result = ang2; - } else if( ang2 == AST__BAD ) { - result = ang1; - } - } - -/* Free the workspace */ - pa = (double *) astFree( (void *) pa ); - pb = (double *) astFree( (void *) pb ); - pc = (double *) astFree( (void *) pc ); - } - -/* Return the result. */ - return result; -} - -static AstObject *Cast( AstObject *this_object, AstObject *obj, int *status ) { -/* -* Name: -* Cast - -* Purpose: -* Cast an Object into an instance of a sub-class. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstObject *Cast( AstObject *this, AstObject *obj, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astCast -* method inherited from the Frame class). - -* Description: -* This function returns a deep copy of an ancestral component of the -* supplied object. The required class of the ancestral component is -* specified by another object. Specifically, if "this" and "new" are -* of the same class, a copy of "this" is returned. If "this" is an -* instance of a subclass of "obj", then a copy of the component -* of "this" that matches the class of "obj" is returned. Otherwise, -* a NULL pointer is returned without error. - -* Parameters: -* this -* Pointer to the Object to be cast. -* obj -* Pointer to an Object that defines the class of the returned Object. -* The returned Object will be of the same class as "obj". - -* Returned Value: -* A pointer to the new Object. NULL if "this" is not a sub-class of -* "obj", or if an error occurs. - -* Notes: -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables; */ - AstAxis *newaxis; - AstFrame *cfrm; - AstFrame *this; - AstObject *new; - astDECLARE_GLOBALS - int generation_gap; - int i; - int naxes; - -/* Initialise */ - new = NULL; - -/* Check inherited status */ - if( !astOK ) return new; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* See how many steps up the class inheritance ladder it is from "obj" - to this class (CmpFrame). A positive value is returned if CmpFrame - is a sub-class of "obj". A negative value is returned if "obj" is - a sub-class of CmpFrame. Zero is returned if "obj" is a CmpFrame. - AST__COUSIN is returned if "obj" is not on the same line of descent - as CmpFrame. */ - generation_gap = astClassCompare( (AstObjectVtab *) &class_vtab, - astVTAB( obj ) ); - -/* If "obj" is a CmpFrame or a sub-class of CmpFrame, we can cast by - truncating the vtab for "this" so that it matches the vtab of "obJ", - and then taking a deep copy of "this". */ - if( generation_gap <= 0 && generation_gap != AST__COUSIN ) { - new = astCastCopy( this_object, obj ); - -/* If "obj" is not a CmpFrame or a sub-class of CmpFrame (e.g. it's a - Frame), we create a basic Frame containing the same axes and attributes - as the CmpFrame, and then attempt to cast this Frame into the class - indicated by "obj". */ - } else { - this = (AstFrame *) this_object; - -/* Create a basic Frame with the right number of axes. */ - naxes = astGetNaxes( this ); - cfrm = astFrame( naxes, " ", status ); - -/* Replace the Axis structures in the basic Frame with those in the - CmpFrame. */ - for( i = 0; i < naxes; i++ ) { - newaxis = astGetAxis( this, i ); - astSetAxis( cfrm, i, newaxis ); - newaxis = astAnnul( newaxis ); - } - -/* Overlay the properties of the CmpFrame onto the basic Frame. */ - astOverlay( this, NULL, cfrm ); - -/* Try to cast the basic Frame to the class of "obj". */ - new = astCast( cfrm, obj ); - -/* Annull the basic Frame. */ - cfrm = astAnnul( cfrm ); - } - -/* Return the new pointer. */ - return new; -} - -static double Centre( AstFrame *this_frame, int axis, double value, double gap, int *status ) { -/* -* Name: -* Centre - -* Purpose: -* Find a "nice" central value for tabulating CmpFrame axis values. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* double Centre( AstFrame *this_frame, int axis, double value, -* double gap, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astCentre method -* inherited from the Frame class). - -* Description: -* This function returns an axis value which produces a nice formatted -* value suitable for a major tick mark on a plot axis, close to the -* supplied axis value. - -* Parameters: -* this -* Pointer to the Frame. -* axis -* The number of the axis (zero-based) for which a central value -* is to be found. -* value -* An arbitrary axis value in the section that is being plotted. -* gap -* The gap size. - -* Returned Value: -* The nice central axis value. - -* Notes: -* - A value of zero is returned if the supplied gap size is zero. -* - 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. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - AstFrame *frame; /* Pointer to Frame containing axis */ - double result; /* Result value to return */ - int naxes1; /* Number of axes in frame1 */ - int set1; /* Digits attribute set? */ - int set2; /* Format attribute set? */ - -/* Initialise. */ - result = 0.0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate and permute the axis index supplied. */ - axis = astValidateAxis( this, axis, 1, "astCentre" ); - -/* Determine the number of axes in the first component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - if ( astOK ) { - -/* Decide which component Frame contains the axis and adjust the axis - index if necessary. */ - frame = ( axis < naxes1 ) ? this->frame1 : this->frame2; - axis = ( axis < naxes1 ) ? axis : axis - naxes1; - -/* Since the component Frame is "managed" by the enclosing CmpFrame, - we next test if any Frame attributes which may affect the result - are undefined (i.e. have not been explicitly set). If so, we - over-ride them, giving them temporary values dictated by the - CmpFrame. Only the Digits and Format attributes are relevant here. */ - set1 = astTestDigits( frame ); - if ( !set1 ) astSetDigits( frame, astGetDigits( this ) ); - - set2 = astTestFormat( frame, axis ); - if ( !set2 ) astSetFormat( frame, axis, astGetFormat( this, axis ) ); - -/* Invoke the Frame's astCentre method to find the central value. */ - result = astCentre( frame, axis, value, gap ); - -/* Clear Frame attributes which were temporarily over-ridden. */ - if ( !set1 ) astClearDigits( frame ); - if ( !set2 ) astClearFormat( frame, axis ); - } - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = 0.0; - -/* Return the result. */ - return result; -} - -static void ClearAlignSystem( AstFrame *this_frame, int *status ) { -/* -* Name: -* ClearAlignSystem - -* Purpose: -* Clear the value of the AlignSystem attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void ClearAlignSystem( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astClearAlignSystem method -* inherited from the Frame class). - -* Description: -* This function clears the AlignSystem value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to clear the CmpFrame AlignSystem value. */ - (*parent_clearalignsystem)( this_frame, status ); - -/* Now clear the AlignSystem attribute in the two component Frames. */ - astClearAlignSystem( this->frame1 ); - astClearAlignSystem( this->frame2 ); -} - -static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* ClearAttrib - -* Purpose: -* Clear an attribute value for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void ClearAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astClearAttrib protected -* method inherited from the Frame class). - -* Description: -* This function clears the value of a specified attribute for a -* CmpFrame, so that the default value will subsequently be used. - -* Parameters: -* this -* Pointer to the CmpFrame. -* attrib -* Pointer to a null terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function uses one-based axis numbering so that it is -* suitable for external (public) use. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - AstFrame *pfrm; /* Pointer to primary Frame containing axis */ - char buf1[80]; /* For for un-indexed attribute name */ - char buf2[80]; /* For for indexed attribute name */ - int axis; /* Sipplied (1-based) axis index */ - int len; /* Length of attrib string */ - int nc; /* Number of characters used so dar */ - int oldrep; /* Original error reporting state */ - int paxis; /* Index of primary Frame axis */ - int ok; /* Has the attribute been accessed succesfully? */ - - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_object; - -/* Obtain the length of the "attrib" string. */ - len = strlen( attrib ); - -/* Indicate we have not yet acessed the attribute succesfully. */ - ok = 0; - -/* First check the supplied attribute name against each of the attribute - names defined by this class. In fact there is nothing to do here - since the CmpFrame class currently defines no extra attributes, but - this may change in the future. */ - if( 0 ) { - - - -/* If the attribute is not a CmpFrame specific attribute... */ - } else if( astOK ) { - -/* We want to allow easy access to the attributes of the component Frames. - That is, we do not want it to be necessary to extract a Frame from - its parent CmpFrame in order to access its attributes. For this reason - we first temporarily switch off error reporting so that if an attempt - to access the attribute fails, we can try a different approach. */ - oldrep = astReporting( 0 ); - -/* Our first attempt is to see if the attribute is recognised by the parent - class (Frame). */ - (*parent_clearattrib)( this_object, attrib, status ); - -/* Indicate success. */ - if( astOK ) { - ok = 1; - -/* Otherwise, clear the error condition so that we can try a different - approach. */ - } else { - astClearStatus; - -/* If the attribute is qualified by an axis index, try accessing it as an - attribute of the primary Frame containing the specified index. */ - if ( nc = 0, - ( 2 == astSscanf( attrib, "%[^(](%d)%n", buf1, &axis, &nc ) ) - && ( nc >= len ) ) { - -/* Find the primary Frame containing the specified axis. */ - astPrimaryFrame( this, axis - 1, &pfrm, &paxis ); - if( astOK ) { - -/* astPrimaryFrame returns the original - unpermuted - axis index within - the primary Frame. So we need to take into account any axis permutation - which has been applied to the primary Frame when forming the attribute name - to use below. Find the permuted (external) axis index which corresponds to - the internal (unpermuted) axis index "paxis". */ - paxis = astValidateAxis( pfrm, paxis, 0, "astClear" ); - -/* Create a new attribute with the same name but with the axis index - appropriate to the primary Frame. */ - sprintf( buf2, "%s(%d)", buf1, paxis + 1 ); - -/* Attempt to access the attribute. */ - astClearAttrib( pfrm, buf2 ); - -/* Indicate success. */ - if( astOK ) { - ok = 1; - -/* Otherwise clear the status value, and try again without any axis index. */ - } else { - astClearStatus; - astClearAttrib( pfrm, buf1 ); - -/* Indicate success, or clear the status value. */ - if( astOK ) { - ok = 1; - } else { - astClearStatus; - } - } - -/* Free the primary frame pointer. */ - pfrm = astAnnul( pfrm ); - } - -/* If the attribute is not qualified by an axis index, try accessing it - using the primary Frame of each axis in turn. */ - } else { - -/* Loop round all axes attribute. */ - for( axis = 0; axis < astGetNaxes( this ); axis++ ) { - -/* Get the primary Frame containing this axis. */ - astPrimaryFrame( this, axis, &pfrm, &paxis ); - -/* Attempt to access the attribute as an attribute of the primary Frame. */ - astClearAttrib( pfrm, attrib ); - -/* Free the primary Frame pointer. */ - pfrm = astAnnul( pfrm ); - -/* Indicate success, or clear the status value. */ - if( astOK ) { - ok = 1; - } else { - astClearStatus; - } - } - } - } - -/* Re-instate the original error reporting state. */ - astReporting( oldrep ); - - } - -/* Report an error if the attribute could not be accessed. */ - if( !ok && astOK ) { - astError( AST__BADAT, "astClear: The %s given does not have an attribute " - "called \"%s\".", status, astGetClass( this ), attrib ); - } - -} - -static void ClearDut1( AstFrame *this_frame, int *status ) { -/* -* Name: -* ClearDut1 - -* Purpose: -* Clear the value of the Dut1 attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void ClearDut1( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astClearDut1 method -* inherited from the Frame class). - -* Description: -* This function clears the Dut1 value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to clear the CmpFrame Dut1 value. */ - (*parent_cleardut1)( this_frame, status ); - -/* Now clear the Dut1 attribute in the two component Frames. */ - astClearDut1( this->frame1 ); - astClearDut1( this->frame2 ); -} - -static void ClearEpoch( AstFrame *this_frame, int *status ) { -/* -* Name: -* ClearEpoch - -* Purpose: -* Clear the value of the Epoch attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void ClearEpoch( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astClearEpoch method -* inherited from the Frame class). - -* Description: -* This function clears the Epoch value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to clear the CmpFrame epoch. */ - (*parent_clearepoch)( this_frame, status ); - -/* Now clear the Epoch attribute in the two component Frames. */ - astClearEpoch( this->frame1 ); - astClearEpoch( this->frame2 ); -} - -static void ClearObsAlt( AstFrame *this_frame, int *status ) { -/* -* Name: -* ClearObsAlt - -* Purpose: -* Clear the value of the ObsAlt attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void ClearObsAlt( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astClearObsAlt method -* inherited from the Frame class). - -* Description: -* This function clears the ObsAlt value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to clear the CmpFrame ObsAlt. */ - (*parent_clearobsalt)( this_frame, status ); - -/* Now clear the ObsAlt attribute in the two component Frames. */ - astClearObsAlt( this->frame1 ); - astClearObsAlt( this->frame2 ); -} - -static void ClearObsLat( AstFrame *this_frame, int *status ) { -/* -* Name: -* ClearObsLat - -* Purpose: -* Clear the value of the ObsLat attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void ClearObsLat( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astClearObsLat method -* inherited from the Frame class). - -* Description: -* This function clears the ObsLat value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to clear the CmpFrame ObsLat. */ - (*parent_clearobslat)( this_frame, status ); - -/* Now clear the ObsLat attribute in the two component Frames. */ - astClearObsLat( this->frame1 ); - astClearObsLat( this->frame2 ); -} - -static void ClearObsLon( AstFrame *this_frame, int *status ) { -/* -* Name: -* ClearObsLon - -* Purpose: -* Clear the value of the ObsLon attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void ClearObsLon( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astClearObsLon method -* inherited from the Frame class). - -* Description: -* This function clears the ObsLon value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to clear the CmpFrame ObsLon. */ - (*parent_clearobslon)( this_frame, status ); - -/* Now clear the ObsLon attribute in the two component Frames. */ - astClearObsLon( this->frame1 ); - astClearObsLon( this->frame2 ); -} - -static int ComponentMatch( AstCmpFrame *template, AstFrame *target, int matchsub, - int icomp, int **template_axes, int **target_axes, - AstMapping **map, AstFrame **result, int *status ) { -/* -* Name: -* ComponentMatch - -* Purpose: -* Determine if conversion is possible between a component Frame in a -* template CmpFrame and another target Frame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int ComponentMatch( AstCmpFrame *template, AstFrame *target, int matchsub, -* int icomp, int **template_axes, int **target_axes, -* AstMapping **map, AstFrame **result, int *status ) - -* Class Membership: -* CmpFrame member function - -* Description: -* This function is like astMatch, but it compares the supplied target -* Frame with a specified component Frame of the supplied template -* CmpFrame, rather than with the entire template CmpFrame. If a match -* is found, the returned Mapping, Frame and axis lists are adjusted so -* that they refer to the entire template CmpFrame. - -* Parameters: -* template -* Pointer to the template CmpFrame. This describes the -* coordinate system (or set of possible coordinate systems) -* into which we wish to convert our coordinates. -* target -* Pointer to the target Frame. This describes the coordinate -* system in which we already have coordinates. -* matchsub -* If zero then a match only occurs if the template is of the same -* class as the target, or of a more specialised class. If non-zero -* then a match can occur even if this is not the case (i.e. if the -* target is of a more specialised class than the template). In -* this latter case, the target is cast down to the class of the -* template. -* icomp -* The index of the component Frame to use within the template -* CmpFrame; 0 or 1. -* template_axes -* Address of a location where a pointer to int will be returned -* if the requested coordinate conversion is possible. This -* pointer will point at a dynamically allocated array of -* integers with one element for each axis of the "result" Frame -* (see below). It must be freed by the caller (using astFree) -* when no longer required. -* -* For each axis in the result Frame, the corresponding element -* of this array will return the (zero-based) index of the -* template CmpFrame axis from which it is derived. If it is not -* derived from any template axis, a value of -1 will be -* returned instead. -* target_axes -* Address of a location where a pointer to int will be returned -* if the requested coordinate conversion is possible. This -* pointer will point at a dynamically allocated array of -* integers with one element for each axis of the "result" Frame -* (see below). It must be freed by the caller (using astFree) -* when no longer required. -* -* For each axis in the result Frame, the corresponding element -* of this array will return the (zero-based) index of the -* target Frame axis from which it is derived. If it is not -* derived from any target axis, a value of -1 will be returned -* instead. -* map -* Address of a location where a pointer to a new Mapping will -* be returned if the requested coordinate conversion is -* possible. If returned, the forward transformation of this -* Mapping may be used to convert coordinates between the -* "target" Frame and the "result" Frame (see below) and the -* inverse transformation will convert in the opposite -* direction. -* result -* Address of a location where a pointer to a new Frame will be -* returned if the requested coordinate conversion is -* possible. If returned, this Frame describes the coordinate -* system that results from applying the returned Mapping -* (above) to the "target" coordinate system. In general, this -* Frame will combine attributes from (and will therefore be -* more specific than) both the target Frame and the template -* CmpFrame. In particular, when the template allows the -* possibility of transformaing to any one of a set of -* alternative coordinate systems, the "result" Frame will -* indicate which of the alternatives was used. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if the requested coordinate -* conversion is possible. Otherwise zero is returned (this will -* not in itself result in an error condition). - -* Notes: -* - By default, the "result" Frame will have its number of axes -* and axis order determined by the "template" CmpFrame. However, -* if the PreserveAxes attribute of the template CmpFrame is -* non-zero, then the axis count and axis order of the "target" -* Frame will be used instead. -* - 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. -*/ - -/* Local Variables: */ - AstFrame *ctemplate; - AstFrame *fother; - AstFrame *fresult; - AstMapping *fmap; - AstPermMap *pm; - const int *perm; - int *ftarget_axes; - int *ftemplate_axes; - int *inperm; - int *operm; - int *outperm; - int axis; - int match; - int nax1; - int nax2; - int naxr; - int prax; - int praxo; - int result_naxes; - int template_naxes; - -/* 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; - -/* Get a pointer to the requested component Frame of the template CmpFrame. */ - ctemplate = icomp ? template->frame2 :template->frame1; - -/* Temporarily set the component Frame PreserveAxes value to that of the - template CmpFrame. PreserveAxes determines whether astMatch returns a - result Frame that looks like the template or the target. */ - if( astTestPreserveAxes( ctemplate ) ) { - praxo = astGetPreserveAxes( ctemplate ) ? 1 : 0; - } else { - praxo = -1; - } - prax = astGetPreserveAxes( template ); - astSetPreserveAxes( ctemplate, prax ); - -/* Attempt to find a match between the axes of the supplied target Frame - and the axes of the selected component Frame in the template. */ - match = astMatch( ctemplate, target, matchsub, &ftemplate_axes, &ftarget_axes, - &fmap, &fresult ); - -/* Restore the original PreserveAxes value in the component template - Frame. */ - if( praxo == -1 ) { - astClearPreserveAxes( ctemplate ); - } else { - astSetPreserveAxes( ctemplate, praxo ); - } - -/* If a match was found, we need to adjust the Mapping, Frame and axis - lists returned by the above call to astMatch so that they refer to the - full template CmpFrame or target (depending on PreserveAxes). */ - if( match ) { - -/* Get the number of axes in each component Frame and the total number of - axes in the template CmpFrame. */ - nax1 = astGetNaxes( template->frame1 ); - nax2 = astGetNaxes( template->frame2 ); - template_naxes = nax1 + nax2; - -/* Get the axis permutation array from the template and get its inverse. - The "perm" array holds the internal axis index at each external axis - index. The "operm" array holds the external axis index at each - internal axis index. */ - perm = astGetPerm( template ); - operm = astMalloc( sizeof( int )*(size_t)template_naxes ); - if( astOK) { - for( axis = 0; axis < template_naxes; axis++ ) { - operm[ perm[ axis ] ] = axis; - } - -/* The PreserveAxes attribute is used by astMatch to decide whether the - result Frame should inherit its axes from the target frame or the - template frame. First deal with cases where the order and count of axes - in the result frame is the same as the target. */ - if( prax ) { - -/* Return the result Frame and Mapping unchanged since they already refer - to the full target Frame used in the above call to astMatch. */ - *result = astClone( fresult ); - *map = astClone( fmap ); - -/* Also return the lists of target axes unchanged. */ - *target_axes = ftarget_axes; - -/* The values in the template axes list refer to the component template - Frame, but we want to return values that refer to the full template - CmpFrame. This involve sup to two setps 1) for the second component - Frame only, increase the axis numbers by the number of axes in the - first component Frame, and 2) take account of any axis permutation in - the template. First allocate memory for the returned list (which, - because PreserveAxes is zero, will have an entry for each template axis). */ - *template_axes = astMalloc( sizeof( int )*template_naxes ); - -/* Now, if the second component of the template has been selected, increment - the template axes so that they give the internal axis indices of the - second component Frame within the CmpFrame. The first component axes - will be unchanged. */ - result_naxes = astGetNaxes( fresult ); - if( icomp ) { - for( axis = 0; axis < result_naxes; axis++ ) { - ftemplate_axes[ axis ] += nax1; - } - } - -/* Now copy the internal axis value into the returned array, modifying them - in the process from internal to external axis ordering. */ - for( axis = 0; axis < result_naxes; axis++ ) { - (*template_axes)[ axis ] = operm[ ftemplate_axes[ axis ] ]; - } - -/* If the order and count of axes in the result frame is the same as the - template CmpFrame... */ - } else { - -/* We need to adjust the Mapping, Frame and axis lists returned by the - above call to astMatch so that they refer to the supplied template - CmpFrame rather than to the selected component Frame. Get the number - of axes in the result Frame returned by astMatch (naxr) and the number - in the result Frame returned by this function (result-naxes). */ - naxr = astGetNaxes( fresult ); - result_naxes = ( icomp ? nax1 : nax2 ) + naxr; - -/* Create the full result Frame by combining the partial result Frame - returned by astMatch above with the other component Frame from the - template. */ - if( icomp ) { - fother = astCopy( template->frame1 ); - *result = (AstFrame *) astCmpFrame( fother, fresult, "", status ); - } else { - fother = astCopy( template->frame2 ); - *result = (AstFrame *) astCmpFrame( fresult, fother, "", status ); - } - fother = astAnnul( fother ); - -/* Modify the Mapping returned by the above call to astMatch so that it - produces positions within the full result Frame created above. */ - if( icomp ) { - inperm = astMalloc( sizeof( int )*(size_t) naxr ); - outperm = astMalloc( sizeof( int )*(size_t) result_naxes ); - if( astOK ) { - for( axis = 0; axis < nax1; axis++ ) outperm[ axis ] = -1; - for( axis = 0; axis < naxr; axis++ ) { - outperm[ axis + nax1 ] = axis; - inperm[ axis ] = axis + nax1; - } - } - - } else { - inperm = NULL; - outperm = NULL; - } - - pm = astPermMap( naxr, inperm, result_naxes, outperm, NULL, "", status ); - *map = (AstMapping *) astCmpMap( fmap, pm, 1, "", status ); - -/* Free resources. */ - pm = astAnnul( pm ); - if( inperm ) inperm = astFree( inperm ); - if( outperm ) outperm = astFree( outperm ); - -/* Allocate memory for the returned list of axes. */ - *template_axes = astMalloc( sizeof( int )*(size_t)result_naxes ); - *target_axes = astMalloc( sizeof( int )*(size_t)result_naxes ); - -/* The axis indices returned by astMatch above will refer to the selected - component Frame rather than the permuted (i.e. external) axis indices for - the template CmpFrame. Change the template axes list so that they describe - the axes in the full result Frame in terms of the external template axis - numbering. This involves shifting the indices for the second component - Frame to leave room for the axes of the first component Frame, and - also permuting the axis indices from internal to external order. */ - if( icomp ) { - for( axis = 0; axis < nax1; axis++ ) { - (*template_axes)[ axis ] = operm[ axis ]; - } - - for( ; axis < result_naxes; axis++ ) { - (*template_axes)[ axis ] = operm[ nax1 + ftemplate_axes[ axis - nax1 ] ]; - } - - } else { - for( axis = 0; axis < nax1; axis++ ) { - (*template_axes)[ axis ] = operm[ ftemplate_axes[ axis ] ]; - } - - for( ; axis < result_naxes; axis++ ) { - (*template_axes)[ axis ] = operm[ axis ]; - } - } - -/* Change the target axes list so that they describe the axes in the - full result Frame (this just means padding with -1 to indicate that - the extra axes do not correspond to any axis in the target). */ - for( axis = 0; axis < naxr; axis++ ) { - (*target_axes)[ axis ] = ftarget_axes[ axis ]; - } - - for( ; axis < result_naxes; axis++ ) { - (*target_axes)[ axis ] = -1; - } - -/* Free resources */ - ftarget_axes = astFree( ftarget_axes ); - } - } - - operm = astFree( operm ); - ftemplate_axes = astFree( ftemplate_axes ); - fmap = astAnnul( fmap ); - fresult = astAnnul( fresult ); - - } - -/* If an error occurred, free all allocated memory, annul the result - Object pointers and clear all returned values. */ - if ( !astOK ) { - *template_axes = astFree( *template_axes ); - *target_axes = astFree( *target_axes ); - *map = astAnnul( *map ); - *result = astAnnul( *result ); - match = 0; - } - -/* Return the result. */ - return match; -} - -static void Decompose( AstMapping *this_cmpframe, AstMapping **map1, - AstMapping **map2, int *series, int *invert1, - int *invert2, int *status ) { -/* -* -* Name: -* Decompose - -* Purpose: -* Decompose a CmpFrame into two component CmpFrames. - -* Type: -* Private function. - -* Synopsis: -* #include "mapping.h" -* void Decompose( AstMapping *this, AstMapping **map1, -* AstMapping **map2, int *series, -* int *invert1, int *invert2, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astDecompose -* method inherited from the Mapping class). - -* Description: -* This function returns pointers to two Mappings which, when applied -* either in series or parallel, are equivalent to the supplied Mapping. -* -* Since the Frame class inherits from the Mapping class, Frames can -* be considered as special types of Mappings and so this method can -* be used to decompose either CmpMaps or CmpFrames. - -* Parameters: -* this -* Pointer to the Mapping. -* map1 -* Address of a location to receive a pointer to first component -* Mapping. -* map2 -* Address of a location to receive a pointer to second component -* Mapping. -* series -* Address of a location to receive a value indicating if the -* component Mappings are applied in series or parallel. A non-zero -* value means that the supplied Mapping is equivalent to applying map1 -* followed by map2 in series. A zero value means that the supplied -* Mapping is equivalent to applying map1 to the lower numbered axes -* and map2 to the higher numbered axes, in parallel. -* invert1 -* The value of the Invert attribute to be used with map1. -* invert2 -* The value of the Invert attribute to be used with map2. -* status -* Pointer to the inherited status variable. - -* Notes: -* - Any changes made to the component rames using the returned -* pointers will be reflected in the supplied CmpFrame. - -*- -*/ - - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpMap structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpMap structure. */ - this = (AstCmpFrame *) this_cmpframe; - -/* The components Frames of a CmpFrame are considered to be parallel - Mappings. */ - if( series ) *series = 0; - -/* The Frames are returned in their original order whether or not the - CmpFrame has been inverted. */ - if( map1 ) *map1 = astClone( this->frame1 ); - if( map2 ) *map2 = astClone( this->frame2 ); - -/* If the CmpFrame has been inverted, return inverted Invert flags. */ - if( astGetInvert( this ) ) { - if( invert1 ) *invert1 = astGetInvert( this->frame1 ) ? 0 : 1; - if( invert2 ) *invert2 = astGetInvert( this->frame2 ) ? 0 : 1; - -/* If the CmpFrame has not been inverted, return the current Invert flags. */ - } else { - if( invert1 ) *invert1 = astGetInvert( this->frame1 ); - if( invert2 ) *invert2 = astGetInvert( this->frame2 ); - } -} - -static double Distance( AstFrame *this_frame, - const double point1[], const double point2[], int *status ) { -/* -* Name: -* Distance - -* Purpose: -* Calculate the distance between two points. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* double Distance( AstFrame *this, -* const double point1[], const double point2[], int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astDistance method -* inherited from the Frame class). - -* Description: -* This function finds the distance between two points whose -* CmpFrame coordinates are given. The distance calculated is that -* along the geodesic curve that joins the two points. This is -* computed as the Cartesian sum of the distances between the -* points when their coordinates are projected into each of the -* CmpFrame's component Frames. - -* Parameters: -* this -* Pointer to the CmpFrame. -* point1 -* An array of double, with one element for each CmpFrame axis, -* containing the coordinates of the first point. -* point2 -* An array of double, with one element for each CmpFrame axis, -* containing the coordinates of the second point. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The distance between the two points. - -* Notes: -* - This function will return a "bad" result value (AST__BAD) if -* any of the input coordinates has this value. -* - A "bad" value will also be returned if this function is -* invoked with the AST error status set or if it should fail for -* any reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - const int *perm; /* Axis permutation array */ - double *p1; /* Pointer to permuted point1 coordinates */ - double *p2; /* Pointer to permuted point2 coordinates */ - double dist1; /* Distance in frame1 */ - double dist2; /* Distance in frame2 */ - double result; /* Value to return */ - int axis; /* Loop counter for axes */ - int naxes1; /* Number of axes in frame1 */ - int naxes; /* Number of axes in CmpFrame */ - int ok; /* No "bad" coordinates found? */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Obtain a pointer to the CmpFrame's axis permutation array. */ - perm = astGetPerm( this ); - -/* Obtain the number of axes in the CmpFrame and in the first - component Frame. */ - naxes = astGetNaxes( this ); - naxes1 = astGetNaxes( this->frame1 ); - -/* Allocate memory to hold the permuted coordinates of each point. */ - p1 = astMalloc( sizeof( double ) * (size_t) naxes ); - p2 = astMalloc( sizeof( double ) * (size_t) naxes ); - if ( astOK ) { - -/* Examine the coordinates of both points and note if any coordinate - value is "bad". */ - ok = 1; - for ( axis = 0; axis < naxes; axis++ ) { - if ( ( point1[ axis ] == AST__BAD ) || - ( point2[ axis ] == AST__BAD ) ) { - ok = 0; - break; - -/* Permute good coordinates using the CmpFrame's axis permutation - array to put them into the order required internally (i.e. by the - two component Frames). */ - } else { - p1[ perm[ axis ] ] = point1[ axis ]; - p2[ perm[ axis ] ] = point2[ axis ]; - } - } - -/* If no "bad" coordinates were found, obtain the distance between the - two points when their coordinates are projected into each component - Frame. */ - if ( ok ) { - dist1 = astDistance( this->frame1, p1, p2 ); - dist2 = astDistance( this->frame2, p1 + naxes1, p2 + naxes1 ); - -/* If the distances found were OK, compute the distance between the - two points as the Cartesian sum of the two component distances. */ - if ( astOK && ( dist1 != AST__BAD ) && ( dist2 != AST__BAD ) ) { - result = sqrt( ( dist1 * dist1 ) + ( dist2 * dist2 ) ); - } - } - } - -/* Free the memory used for the permuted coordinates. */ - p1 = astFree( p1 ); - p2 = astFree( p2 ); - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = AST__BAD; - -/* Return the result. */ - return result; -} - -static int Fields( AstFrame *this_frame, int axis, const char *fmt, - const char *str, int maxfld, char **fields, - int *nc, double *val, int *status ) { -/* -*+ -* Name: -* astFields - -* Purpose: -* Identify numerical fields within a formatted CmpFrame axis value. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "cmpframe.h" -* int astFields( AstFrame *this, int axis, const char *fmt, -* const char *str, int maxfld, char **fields, -* int *nc, double *val ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astFields -* method inherited from the Frame class). - -* Description: -* This function identifies the numerical fields within a CmpFrame axis -* value that has been formatted using astAxisFormat. It assumes that -* the value was formatted using the supplied format string. It also -* returns the equivalent floating point value. - -* Parameters: -* this -* Pointer to the CmpFrame. -* axis -* The number of the CmpFrame axis for which the values have been -* formatted (axis numbering starts at zero for the first axis). -* fmt -* Pointer to a constant null-terminated string containing the -* format used when creating "str". -* str -* Pointer to a constant null-terminated string containing the -* formatted value. -* maxfld -* The maximum number of fields to identify within "str". -* fields -* A pointer to an array of at least "maxfld" character pointers. -* Each element is returned holding a pointer to the start of the -* corresponding field in "str" (in the order in which they occur -* within "str"), or NULL if no corresponding field can be found. -* nc -* A pointer to an array of at least "maxfld" integers. Each -* element is returned holding the number of characters in the -* corresponding field, or zero if no corresponding field can be -* found. -* val -* Pointer to a location at which to store the value -* equivalent to the returned field values. If this is NULL, -* it is ignored. - -* Returned Value: -* The number of fields succesfully identified and returned. - -* Notes: -* - Leading and trailing spaces are ignored. -* - If the formatted value is not consistent with the supplied format -* string, then a value of zero will be returned, "fields" will be -* returned holding NULLs, "nc" will be returned holding zeros, and -* "val" is returned holding VAL__BAD. -* - Fields are counted from the start of the formatted string. If the -* string contains more than "maxfld" fields, then trailing fields are -* ignored. -* - If this function is invoked with the global error status set, or -* if it should fail for any reason, then a value of zero will be returned -* as the function value, and "fields", "nc" and "val" will be returned -* holding their supplied values -*- -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - AstFrame *frame; /* Pointer to Frame containing axis */ - int naxes1; /* Number of axes in frame1 */ - int result; /* Result field count to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate and permute the axis index supplied. */ - axis = astValidateAxis( this, axis, 1, "astFields" ); - -/* Determine the number of axes in the first component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - if ( astOK ) { - -/* Decide which component Frame contains the axis and adjust the axis - index if necessary. */ - frame = ( axis < naxes1 ) ? this->frame1 : this->frame2; - axis = ( axis < naxes1 ) ? axis : axis - naxes1; - -/* Invoke the Frame's astFields method to perform the processing. */ - result = astFields( frame, axis, fmt, str, maxfld, fields, - nc, val ); - } - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = 0; - -/* Return the result. */ - return result; -} - -static const char *Format( AstFrame *this_frame, int axis, double value, int *status ) { -/* -* Name: -* Format - -* Purpose: -* Format a coordinate value for a CmpFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* const char *Format( AstFrame *this, int axis, double value, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astFormat method -* inherited from the Frame class). - -* Description: -* This function returns a pointer to a string containing the -* formatted (character) version of a coordinate value for a -* CmpFrame axis. The formatting applied is that specified by a -* previous invocation of the astSetFormat method (or a default -* format appropriate to the axis in question). - -* Parameters: -* this -* Pointer to the CmpFrame. -* axis -* The number of the axis (zero-based) for which formatting is -* to be performed. -* value -* The coordinate value to be formatted. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to a null-terminated string containing the formatted -* value. - -* Notes: -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - AstFrame *frame; /* Pointer to Frame containing axis */ - const char *result; /* Pointer value to return */ - int naxes1; /* Number of axes in frame1 */ - int set; /* Digits attribute set? */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate and permute the axis index supplied. */ - axis = astValidateAxis( this, axis, 1, "astFormat" ); - -/* Determine the number of axes in the first component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - if ( astOK ) { - -/* Decide which component Frame contains the axis and adjust the axis - index if necessary. */ - frame = ( axis < naxes1 ) ? this->frame1 : this->frame2; - axis = ( axis < naxes1 ) ? axis : axis - naxes1; - -/* Since the component Frame is "managed" by the enclosing CmpFrame, - we next test if any Frame attributes which may affect the result - are undefined (i.e. have not been explicitly set). If so, we - over-ride them, giving them temporary values dictated by the - CmpFrame. Only the Digits attribute is relevant here. */ - set = astTestDigits( frame ); - if ( !set ) astSetDigits( frame, astGetDigits( this ) ); - -/* Invoke the Frame's astFormat method to format the value. */ - result = astFormat( frame, axis, value ); - -/* Clear Frame attributes which were temporarily over-ridden. */ - if ( !set ) astClearDigits( frame ); - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = NULL; - -/* Return the result. */ - return result; -} - -static AstPointSet *FrameGrid( AstFrame *this_object, int size, const double *lbnd, - const double *ubnd, int *status ){ -/* -* Name: -* FrameGrid - -* Purpose: -* Return a grid of points covering a rectangular area of a Frame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstPointSet *FrameGrid( AstFrame *this_frame, int size, -* const double *lbnd, const double *ubnd, -* int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astFrameGrid -* method inherited from the Frame class). - -* Description: -* This function returns a PointSet containing positions spread -* approximately evenly throughtout a specified rectangular area of -* the Frame. - -* Parameters: -* this -* Pointer to the Frame. -* size -* The preferred number of points in the returned PointSet. The -* actual number of points in the returned PointSet may be -* different, but an attempt is made to stick reasonably closely to -* the supplied value. -* lbnd -* Pointer to an array holding the lower bound of the rectangular -* area on each Frame axis. The array should have one element for -* each Frame axis. -* ubnd -* Pointer to an array holding the upper bound of the rectangular -* area on each Frame axis. The array should have one element for -* each Frame axis. - -* Returned Value: -* A pointer to a new PointSet holding the grid of points. - -* Notes: -* - A NULL pointer is returned if an error occurs. -*/ - -/* Local Variables: */ - AstCmpFrame *this; - AstPointSet *ps1; - AstPointSet *ps2; - AstPointSet *result; - const int *perm; - double **ptr1; - double **ptr2; - double **ptr; - double *lbnd1; - double *lbnd2; - double *p; - double *ubnd1; - double *ubnd2; - double v; - int axis; - int iax1; - int iax2; - int iaxis; - int ip1; - int ip2; - int nax1; - int nax2; - int naxes; - int npoint1; - int npoint2; - int npoint; - int size1; - int size2; - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_object; - -/* Get the number of axes in each component Frame, and the total number - of axes. */ - nax1 = astGetNaxes( this->frame1 ); - nax2 = astGetNaxes( this->frame2 ); - naxes = nax1 + nax2; - -/* Allocate memory to hold bounds for each component Frame */ - lbnd1 = astMalloc( nax1*sizeof( double ) ); - ubnd1 = astMalloc( nax1*sizeof( double ) ); - lbnd2 = astMalloc( nax2*sizeof( double ) ); - ubnd2 = astMalloc( nax2*sizeof( double ) ); - -/* Obtain a pointer to the CmpFrame's axis permutation array. This array - holds the original axis index for each current Frame axis index. */ - perm = astGetPerm( this ); - -/* Check pointers can be used safely, and check the supplied size value - is good. */ - if( astOK && size > 0 ) { - -/* Copy the supplied bounds into the work arrays, permuting them in the - process so that they use the internal axis numbering of the two - component Frames. */ - for( axis = 0; axis < naxes; axis++ ) { - iaxis = perm[ axis ]; - if( iaxis < nax1 ) { - lbnd1[ iaxis ] = lbnd[ axis ]; - ubnd1[ iaxis ] = ubnd[ axis ]; - } else { - iaxis -= nax1; - lbnd2[ iaxis ] = lbnd[ axis ]; - ubnd2[ iaxis ] = ubnd[ axis ]; - } - } - -/* Get the target number of points to be used in the grid that covers the - first Frame. */ - size1 = (int)( pow( size, (double)nax1/(double)naxes ) + 0.5 ); - -/* Get the target number of points to be used in the grid that covers the - second Frame. */ - size2 = (int)( (double)size/(double)size1 + 0.5 ); - -/* Get the grids covering the two component Frames, and get the actual sizes - of the resulting PointSets. */ - ps1 = astFrameGrid( this->frame1, size1, lbnd1, ubnd1 ); - ptr1 = astGetPoints( ps1 ); - npoint1 = astGetNpoint( ps1 ); - - ps2 = astFrameGrid( this->frame2, size2, lbnd2, ubnd2 ); - ptr2 = astGetPoints( ps2 ); - npoint2 = astGetNpoint( ps2 ); - -/* Get the number of points in the returned FrameSet, and then create a - PointSet large enough to hold them. */ - npoint = npoint1*npoint2; - result = astPointSet( npoint, naxes, " ", status ); - ptr = astGetPoints( result ); - if( astOK ) { - -/* For every point in the first Frame's PointSet, duplicate the second - Frame's entire PointSet, using the first Frame's axis values. */ - for( ip1 = 0; ip1 < npoint1; ip1++ ) { - for( iax1 = 0; iax1 < nax1; iax1++ ) { - p = ptr[ iax1 ]; - v = ptr1[ iax1 ][ ip1 ]; - for( ip2 = 0; ip2 < npoint2; ip2++ ) { - *(p++) = v; - } - ptr[ iax1 ] = p; - } - for( iax2 = 0; iax2 < nax2; iax2++ ) { - memcpy( ptr[ iax2 + nax1 ], ptr2[ iax2 ], npoint2*sizeof( double ) ); - ptr[ iax2 + nax1 ] += npoint2*sizeof( double ); - } - } - -/* Permute the returned PointSet so that it uses external axis numbering. */ - astPermPoints( result, 1, perm ); - } - -/* Free resources. */ - ps1 = astAnnul( ps1 ); - ps2 = astAnnul( ps2 ); - -/* Report error if supplied values were bad. */ - } else if( astOK ) { - astError( AST__ATTIN, "astFrameGrid(%s): The supplied grid " - "size (%d) is invalid (programming error).", - status, astGetClass( this ), size ); - } - -/* Free resources. */ - lbnd1 = astFree( lbnd1 ); - ubnd1 = astFree( ubnd1 ); - lbnd2 = astFree( lbnd2 ); - ubnd2 = astFree( ubnd2 ); - -/* Annul the returned PointSet if an error has occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return the PointSet holding the grid. */ - return result; -} - -static double Gap( AstFrame *this_frame, int axis, double gap, int *ntick, int *status ) { -/* -* Name: -* Gap - -* Purpose: -* Find a "nice" gap for tabulating CmpFrame axis values. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* double Gap( AstFrame *this, int axis, double gap, int *ntick, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astGap method -* inherited from the Frame class). - -* Description: -* This function returns a gap size which produces a nicely spaced -* series of formatted values for a CmpFrame axis, the returned gap -* size being as close as possible to the supplied target gap -* size. It also returns a convenient number of divisions into -* which the gap can be divided. - -* Parameters: -* this -* Pointer to the CmpFrame. -* axis -* The number of the axis (zero-based) for which a gap is to be found. -* gap -* The target gap size. -* ntick -* Address of an int in which to return a convenient number of -* divisions into which the gap can be divided. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The nice gap size. - -* Notes: -* - A value of zero is returned if the target gap size is zero. -* - A negative gap size is returned if the supplied gap size is negative. -* - 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. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - AstFrame *frame; /* Pointer to Frame containing axis */ - double result; /* Result value to return */ - int naxes1; /* Number of axes in frame1 */ - int set; /* Digits attribute set? */ - -/* Initialise. */ - result = 0.0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate and permute the axis index supplied. */ - axis = astValidateAxis( this, axis, 1, "astGap" ); - -/* Determine the number of axes in the first component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - if ( astOK ) { - -/* Decide which component Frame contains the axis and adjust the axis - index if necessary. */ - frame = ( axis < naxes1 ) ? this->frame1 : this->frame2; - axis = ( axis < naxes1 ) ? axis : axis - naxes1; - -/* Since the component Frame is "managed" by the enclosing CmpFrame, - we next test if any Frame attributes which may affect the result - are undefined (i.e. have not been explicitly set). If so, we - over-ride them, giving them temporary values dictated by the - CmpFrame. Only the Digits attribute is relevant here. */ - set = astTestDigits( frame ); - if ( !set ) astSetDigits( frame, astGetDigits( this ) ); - -/* Invoke the Frame's astGap method to find the gap size. */ - result = astGap( frame, axis, gap, ntick ); - -/* Clear Frame attributes which were temporarily over-ridden. */ - if ( !set ) astClearDigits( frame ); - } - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = 0.0; - -/* Return the result. */ - return result; -} - -static int GetObjSize( AstObject *this_object, int *status ) { -/* -* Name: -* GetObjSize - -* Purpose: -* Return the in-memory size of an Object. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int GetObjSize( AstObject *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetObjSize protected -* method inherited from the parent class). - -* Description: -* This function returns the in-memory size of the supplied CmpFrame, -* in bytes. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The Object size, in bytes. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointers to the CmpFrame structure. */ - this = (AstCmpFrame *) this_object; - -/* Invoke the GetObjSize method inherited from the parent class, and then - add on any components of the class structure defined by thsi class - which are stored in dynamically allocated memory. */ - result = (*parent_getobjsize)( this_object, status ); - - result += astGetObjSize( this->frame1 ); - result += astGetObjSize( this->frame2 ); - result += astTSizeOf( this->perm ); - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = 0; - -/* Return the result, */ - return result; -} - -static AstSystemType GetAlignSystem( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetAlignSystem - -* Purpose: -* Obtain the AlignSystem attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstSystemType GetAlignSystem( AstFrame *this_frame, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetAlignSystem protected -* method inherited from the Frame class). - -* Description: -* This function returns the AlignSystem attribute for a CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The AlignSystem value. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - AstSystemType result; /* Value to return */ - -/* Initialise. */ - result = AST__BADSYSTEM; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If a AlignSystem attribute has been set, invoke the parent method to obtain - it. */ - if ( astTestAlignSystem( this ) ) { - result = (*parent_getalignsystem)( this_frame, status ); - -/* Otherwise, provide a suitable default. */ - } else { - result = AST__COMP; - } - -/* Return the result. */ - return result; -} - -static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* GetAttrib - -* Purpose: -* Get the value of a specified attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "CmpFrame.h" -* const char *GetAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astGetAttrib -* method inherited from the Frame class). - -* Description: -* This function returns a pointer to the value of a specified -* attribute for a CmpFrame, formatted as a character string. - -* Parameters: -* this -* Pointer to the CmpFrame. -* attrib -* Pointer to a null-terminated string containing the name of -* the attribute whose value is required. This name should be in -* lower case, with all white space removed. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* - Pointer to a null-terminated string containing the attribute -* value. - -* Notes: -* - This function uses one-based axis numbering so that it is -* suitable for external (public) use. -* - The returned string pointer may point at memory allocated -* within the CmpFrame, or at static memory. The contents of the -* string may be over-written or the pointer may become invalid -* following a further invocation of the same function or any -* modification of the CmpFrame. A copy of the string should -* therefore be made if necessary. -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - AstFrame *pfrm; /* Pointer to primary Frame containing axis */ - char buf1[80]; /* For for un-indexed attribute name */ - char buf2[80]; /* For for indexed attribute name */ - const char *result; /* Pointer value to return */ - int axis; /* Supplied (1-base) axis index */ - int len; /* Length of attrib string */ - int nc; /* Length of string used so far */ - int ok; /* Has the attribute been accessed succesfully? */ - int oldrep; /* Original error reporting state */ - int paxis; /* Index of primary Frame axis */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_object; - -/* Obtain the length of the attrib string. */ - len = strlen( attrib ); - -/* Indicate we have not yet acessed the attribute succesfully. */ - ok = 0; - -/* First check the supplied attribute name against each of the attribute - names defined by this class. In fact there is nothing to do here - since the CmpFrame class currently defines no extra attributes, but - this may change in the future. */ - if( 0 ) { - -/* If the attribute is not a CmpFrame specific attribute... */ - } else if( astOK ) { - -/* We want to allow easy access to the attributes of the component Frames. - That is, we do not want it to be necessary to extract a Frame from - its parent CmpFrame in order to access its attributes. For this reason - we first temporarily switch off error reporting so that if an attempt - to access the attribute fails, we can try a different approach. */ - oldrep = astReporting( 0 ); - -/* If the attribute is qualified by an axis index, try accessing it as an - attribute of the primary Frame containing the specified index. */ - if ( nc = 0, - ( 2 == astSscanf( attrib, "%[^(](%d)%n", buf1, &axis, &nc ) ) - && ( nc >= len ) ) { - -/* Find the primary Frame containing the specified axis. */ - astPrimaryFrame( this, axis - 1, &pfrm, &paxis ); - if( astOK ) { - -/* astPrimaryFrame returns the original - unpermuted - axis index within - the primary Frame. So we need to take into account any axis permutation - which has been applied to the primary Frame when forming the attribute name - to use below. Find the permuted (external) axis index which corresponds to - the internal (unpermuted) axis index "paxis". */ - paxis = astValidateAxis( pfrm, paxis, 0, "astGet" ); - -/* Create a new attribute with the same name but with the axis index - appropriate to the primary Frame. */ - sprintf( buf2, "%s(%d)", buf1, paxis + 1 ); - -/* Attempt to access the attribute. */ - result = astGetAttrib( pfrm, buf2 ); - -/* Indicate success. */ - if( astOK ) { - ok = 1; - -/* Otherwise clear the status value, and try again without any axis index. */ - } else { - astClearStatus; - result = astGetAttrib( pfrm, buf1 ); - -/* Indicate success, or clear the status value. */ - if( astOK ) { - ok = 1; - } else { - astClearStatus; - } - } - -/* Free the primary frame pointer. */ - pfrm = astAnnul( pfrm ); - } - -/* If the attribute is not qualified by an axis index, try accessing it - using the parent Frame method. */ - } else if( astOK ){ - result = (*parent_getattrib)( this_object, attrib, status ); - -/* Indicate success. */ - if( astOK ) { - ok = 1; - -/* Otherwise, clear the error condition so that we can try a different - approach. */ - } else { - astClearStatus; - -/* Next try accessing it using the primary Frame of each axis in turn. - Loop round all axes, until one is found which defines the specified - attribute. */ - for( axis = 0; axis < astGetNaxes( this ) && !ok; axis++ ) { - -/* Get the primary Frame containing this axis. */ - astPrimaryFrame( this, axis, &pfrm, &paxis ); - -/* Attempt to access the attribute as an attribute of the primary Frame. */ - result = astGetAttrib( pfrm, attrib ); - -/* Indicate success, or clear the status value. */ - if( astOK ) { - ok = 1; - } else { - astClearStatus; - } - -/* Free the primary Frame pointer. */ - pfrm = astAnnul( pfrm ); - - } - } - } - -/* Re-instate the original error reporting state. */ - astReporting( oldrep ); - - } - -/* Report an error if the attribute could not be accessed. */ - if( !ok && astOK ) { - astError( AST__BADAT, "astGet: The %s given does not have an attribute " - "called \"%s\".", status, astGetClass( this ), attrib ); - } - -/* Return the result. */ - return result; - -} - -static int GenAxisSelection( int naxes, int nselect, int axes[], int *status ) { -/* -* Name: -* GenAxisSelection - -* Purpose: -* Generate a sequence of axis selections. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int GenAxisSelection( int naxes, int nselect, int axes[], int *status ) - -* Class Membership: -* CmpFrame member function. - -* Description: -* This function generates a sequence of axis selections covering -* all possible ways of selecting a specified number of axes from a -* Frame. - -* Parameters: -* naxes -* The number of axes in the Frame. -* nselect -* The number of axes to be selected (between zero and "naxes"). -* axes -* An array with "nselect" elements. On entry it should contain -* the (zero-based) indices of the initial set of distinct axes -* to be selected, in increasing order (initiallly this should -* just be the sequence [0,1,...nselect-1]). On exit, these -* indices will be updated to identify the next possible axis -* selection. -* -* By invoking the function repeatedly, and passing this array -* each time, all possible selections will be covered. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if a new axis selection has been returned. Zero if all -* possible selections have already been returned (in which case -* the selection returned this time is not valid and should not be -* used). - -* 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. -*/ - -/* Local Variables: */ - int i; /* Loop counter for axes */ - int iselect; /* Selection index */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Start with the first axis index and loop until the selection has - been updated. */ - iselect = 0; - while ( 1 ) { - -/* Increment the current axis index if it is the final one or it can - be incremented without equalling the one which follows (this ensures - the indices remain in increasing order). */ - if ( ( iselect == ( nselect - 1 ) ) || - ( axes[ iselect + 1 ] > ( axes[ iselect ] + 1 ) ) ) { - axes[ iselect ]++; - -/* After incrementing an index, reset all previous indices to their - starting values. */ - for ( i = 0; i < iselect; i++ ) axes[ i ] = i; - break; - -/* If this axis index can't be incremented, consider the next one. - Quit if we go beyond the end of the selection array. */ - } else if ( ++iselect >= nselect ) { - break; - } - } - -/* Return a result to indicate if we've reached the final selection - (when the final axis index goes out of range). */ - return ( nselect > 0 ) && ( axes[ nselect - 1 ] < naxes ); -} - -static AstAxis *GetAxis( AstFrame *this_frame, int axis, int *status ) { -/* -* Name: -* GetAxis - -* Purpose: -* Obtain a pointer to a specified Axis from a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstAxis *GetAxis( AstFrame *this, int axis, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetAxis method -* inherited from the Frame class). - -* Description: -* This function returns a pointer to the Axis object associated -* with one of the axes of a CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* axis -* The number of the axis (zero-based) for which an Axis pointer -* is required. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the requested Axis object. - -* Notes: -* - The reference count of the requested Axis object will be -* incremented by one to reflect the additional pointer returned by -* this function. -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Vaiables: */ - AstAxis *result; /* Pointer value to return */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - int naxes1; /* Number of axes for frame1 */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate and permute the axis index supplied. */ - axis = astValidateAxis( this, axis, 1, "astGetAxis" ); - -/* Obtain the number of axes for frame1. */ - naxes1 = astGetNaxes( this->frame1 ); - -/* Decide which Frame the axis belongs to and obtain the required - Axis pointer. */ - if ( axis < naxes1 ) { - result = astGetAxis( this->frame1, axis ); - } else { - result = astGetAxis( this->frame2, axis - naxes1 ); - } - -/* Return the result. */ - return result; -} - -static const char *GetDomain( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetDomain - -* Purpose: -* Obtain a pointer to the Domain attribute string for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* const char *GetDomain( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetDomain protected -* method inherited from the Frame class). - -* Description: -* This function returns a pointer to the Domain attribute string -* for a CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to a constant null-terminated string containing the -* Domain value. - -* Notes: -* - The returned pointer or the string it refers to may become -* invalid following further invocation of this function or -* modification of the CmpFrame. -* - A NULL pointer is returned if this function is invoked with -* the global error status set or if it should fail for any reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - char *dom1; /* Pointer to first sub domain */ - char *dom2; /* Pointer to second sub domain */ - const char *result; /* Pointer value to return */ - const char *t; /* Temporary pointer */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this_frame); - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If a Domain attribute string has been set, invoke the parent method - to obtain a pointer to it. */ - if ( astTestDomain( this ) ) { - result = (*parent_getdomain)( this_frame, status ); - -/* Otherwise, provide a pointer to a suitable default string. */ - } else { - -/* Get the Domain value for the two component Frames and store new - copies of them. This is necessary because the component Frames may - themselves be CmpFrames, resulting in this function being called - recursively and so causing the static "getdomain_buff" array to be used in - multiple contexts. */ - t = astGetDomain( this->frame1 ); - dom1 = t ? astStore( NULL, t, strlen(t) + 1 ) : NULL; - t = astGetDomain( this->frame2 ); - dom2 = t ? astStore( NULL, t, strlen(t) + 1 ) : NULL; - - if( dom2 ) { - if( strlen( dom1 ) > 0 || strlen( dom2 ) > 0 ) { - sprintf( (char *) getdomain_buff, "%s-%s", dom1, dom2 ); - result = getdomain_buff; - } else { - result = "CMP"; - } - } - - dom1 = astFree( dom1 ); - dom2 = astFree( dom2 ); - } - -/* Return the result. */ - return result; -} - -static int GetMaxAxes( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetMaxAxes - -* Purpose: -* Get a value for the MaxAxes attribute of a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int GetMaxAxes( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetMaxAxes method -* inherited from the Frame class). - -* Description: -* This function returns a value for the MaxAxes attribute of a -* CmpFrame. A large default value is supplied that is much larger -* than the maximum likely number of axes in a Frame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The MaxAxes attribute value. - -* 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. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If a value has been set explicitly for the CmpFrame, return it. - Otherwise returned a large default value. */ - if( astTestMaxAxes( this ) ) { - result = (*parent_getmaxaxes)( this_frame, status ); - } else { - result = 1000000; - } - -/* Return the result. */ - return result; -} - -static int GetMinAxes( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetMinAxes - -* Purpose: -* Get a value for the MinAxes attribute of a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int GetMinAxes( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetMinAxes method -* inherited from the Frame class). - -* Description: -* This function returns a value for the MinAxes attribute of a -* CmpFrame. A default value of zero is used. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The MinAxes attribute value. - -* 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. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If a value has been set explicitly for the CmpFrame, return it. - Otherwise returned a default value of zero. */ - if( astTestMinAxes( this ) ) { - result = (*parent_getminaxes)( this_frame, status ); - } else { - result = 0; - } - -/* Return the result. */ - return result; -} - -static double GetDut1( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetDut1 - -* Purpose: -* Get a value for the Dut1 attribute of a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* double GetDut1( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetDut1 method -* inherited from the Frame class). - -* Description: -* This function returns a value for the Dut1 attribute of a -* CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The Dut1 attribute value. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - double result; /* Result value to return */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If an Dut1 attribute value has been set, invoke the parent method - to obtain it. */ - if ( astTestDut1( this ) ) { - result = (*parent_getdut1)( this_frame, status ); - -/* Otherwise, if the Dut1 value is set in the first component Frame, - return it. */ - } else if( astTestDut1( this->frame1 ) ){ - result = astGetDut1( this->frame1 ); - -/* Otherwise, if the Dut1 value is set in the second component Frame, - return it. */ - } else if( astTestDut1( this->frame2 ) ){ - result = astGetDut1( this->frame2 ); - -/* Otherwise, return the default Dut1 value from the first component - Frame. */ - } else { - result = astGetDut1( this->frame1 ); - } - -/* Return the result. */ - return result; -} - -static double GetEpoch( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetEpoch - -* Purpose: -* Get a value for the Epoch attribute of a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* double GetEpoch( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetEpoch method -* inherited from the Frame class). - -* Description: -* This function returns a value for the Epoch attribute of a -* CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The Epoch attribute value. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - double result; /* Result value to return */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If an Epoch attribute value has been set, invoke the parent method - to obtain it. */ - if ( astTestEpoch( this ) ) { - result = (*parent_getepoch)( this_frame, status ); - -/* Otherwise, if the Epoch value is set in the first component Frame, - return it. */ - } else if( astTestEpoch( this->frame1 ) ){ - result = astGetEpoch( this->frame1 ); - -/* Otherwise, if the Epoch value is set in the second component Frame, - return it. */ - } else if( astTestEpoch( this->frame2 ) ){ - result = astGetEpoch( this->frame2 ); - -/* Otherwise, return the default Epoch value from the first component - Frame. */ - } else { - result = astGetEpoch( this->frame1 ); - } - -/* Return the result. */ - return result; -} - -static double GetObsAlt( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetObsAlt - -* Purpose: -* Get a value for the ObsAlt attribute of a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* double GetObsAlt( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetObsAlt method -* inherited from the Frame class). - -* Description: -* This function returns a value for the ObsAlt attribute of a -* CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The ObsAlt attribute value. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - double result; /* Result value to return */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If an ObsAlt attribute value has been set, invoke the parent method - to obtain it. */ - if ( astTestObsAlt( this ) ) { - result = (*parent_getobsalt)( this_frame, status ); - -/* Otherwise, if the ObsAlt value is set in the first component Frame, - return it. */ - } else if( astTestObsAlt( this->frame1 ) ){ - result = astGetObsAlt( this->frame1 ); - -/* Otherwise, if the ObsAlt value is set in the second component Frame, - return it. */ - } else if( astTestObsAlt( this->frame2 ) ){ - result = astGetObsAlt( this->frame2 ); - -/* Otherwise, return the default ObsAlt value from the first component - Frame. */ - } else { - result = astGetObsAlt( this->frame1 ); - } - -/* Return the result. */ - return result; -} - -static double GetObsLat( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetObsLat - -* Purpose: -* Get a value for the ObsLat attribute of a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* double GetObsLat( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetObsLat method -* inherited from the Frame class). - -* Description: -* This function returns a value for the ObsLat attribute of a -* CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The ObsLat attribute value. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - double result; /* Result value to return */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If an ObsLat attribute value has been set, invoke the parent method - to obtain it. */ - if ( astTestObsLat( this ) ) { - result = (*parent_getobslat)( this_frame, status ); - -/* Otherwise, if the ObsLat value is set in the first component Frame, - return it. */ - } else if( astTestObsLat( this->frame1 ) ){ - result = astGetObsLat( this->frame1 ); - -/* Otherwise, if the ObsLat value is set in the second component Frame, - return it. */ - } else if( astTestObsLat( this->frame2 ) ){ - result = astGetObsLat( this->frame2 ); - -/* Otherwise, return the default ObsLat value from the first component - Frame. */ - } else { - result = astGetObsLat( this->frame1 ); - } - -/* Return the result. */ - return result; -} - -static double GetObsLon( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetObsLon - -* Purpose: -* Get a value for the ObsLon attribute of a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* double GetObsLon( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetObsLon method -* inherited from the Frame class). - -* Description: -* This function returns a value for the ObsLon attribute of a -* CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The ObsLon attribute value. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - double result; /* Result value to return */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If an ObsLon attribute value has been set, invoke the parent method - to obtain it. */ - if ( astTestObsLon( this ) ) { - result = (*parent_getobslon)( this_frame, status ); - -/* Otherwise, if the ObsLon value is set in the first component Frame, - return it. */ - } else if( astTestObsLon( this->frame1 ) ){ - result = astGetObsLon( this->frame1 ); - -/* Otherwise, if the ObsLon value is set in the second component Frame, - return it. */ - } else if( astTestObsLon( this->frame2 ) ){ - result = astGetObsLon( this->frame2 ); - -/* Otherwise, return the default ObsLon value from the first component - Frame. */ - } else { - result = astGetObsLon( this->frame1 ); - } - -/* Return the result. */ - return result; -} - -static int GetNaxes( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetNaxes - -* Purpose: -* Determine how many axes a CmpFrame has. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int GetNaxes( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetNaxes method -* inherited from the Frame class). - -* Description: -* This function returns the number of axes for a CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The number of CmpFrame axes. - -* 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. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - int naxes1; /* Number of axes for frame1 */ - int naxes2; /* Number of axes for frame2 */ - int result; /* Number of CmpFrame axes */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Obtain the number of axes for each component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - naxes2 = astGetNaxes( this->frame2 ); - -/* If OK, calculate the total number of axes. */ - if ( astOK ) result = naxes1 + naxes2; - -/* Return the result. */ - return result; -} - -static const int *GetPerm( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetPerm - -* Purpose: -* Access the axis permutation array for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* const int *astGetPerm( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astGetPerm -* method inherited from the Frame class). - -* Description: -* This function returns a pointer to the axis permutation array -* for a CmpFrame. This array constitutes a lookup-table that -* converts between an axis number supplied externally and the -* corresponding index in the CmpFrame's internal data. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to the CmpFrame's axis permutation array (a constant -* array of int). Each element of this contains the (zero-based) -* internal axis index to be used in place of the external index -* which is used to address the permutation array. If the CmpFrame -* has zero axes, this pointer will be NULL. - -* Notes: -* - This protected method is provided to assist class -* implementations which need to implement axis-dependent -* extensions to CmpFrame methods, and which therefore need to know -* how a CmpFrames's external axis index is converted for internal -* use. -* - The pointer returned by this function gives direct access to -* data internal to the CmpFrame object. It remains valid only so -* long as the CmpFrame exists. The permutation array contents may -* be modified by other functions which operate on the CmpFrame and -* this may render the returned pointer invalid. -* - A NULL pointer 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 function performs essentially the same operation as the -* Frame member function which it over-rides. However, it returns a -* pointer to the "perm" array held in the CmpFrame structure -* (rather than the one in the parent Frame structure). This -* duplication of the array is necessary because the one in the -* Frame structure is of zero length, the number of axes in the -* Frame structure having been set to zero to prevent unnecessary -* allocation of Axis objects which are not needed by the CmpFrame. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Return a pointer to the axis permutation array. */ - return this->perm; -} - -static AstSystemType GetSystem( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetSystem - -* Purpose: -* Obtain the System attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstSystemType GetSystem( AstFrame *this_frame, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetSystem protected -* method inherited from the Frame class). - -* Description: -* This function returns the System attribute for a CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The System value. - -* Notes: -* - AST__BADSYSTEM is returned if this function is invoked with -* the global error status set or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - AstSystemType result; /* Value to return */ - -/* Initialise. */ - result = AST__BADSYSTEM; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If a System attribute has been set, invoke the parent method to obtain - it. */ - if ( astTestSystem( this ) ) { - result = (*parent_getsystem)( this_frame, status ); - -/* Otherwise, provide a suitable default. */ - } else { - result = AST__COMP; - } - -/* Return the result. */ - return result; -} - -static const char *GetTitle( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetTitle - -* Purpose: -* Obtain a pointer to the Title attribute string for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* const char *GetTitle( AstFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetTitle protected -* method inherited from the Frame class). - -* Description: -* This function returns a pointer to the Title attribute string for -* a CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to a constant null-terminated string containing the -* Title value. - -* Notes: -* - The returned pointer or the string it refers to may become -* invalid following further invocation of this function or -* modification of the CmpFrame. -* - A NULL pointer is returned if this function is invoked with -* the global error status set or if it should fail for any reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - const char *result; /* Pointer value to return */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this_frame); - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* If a Title attribute string has been set, invoke the parent method - to obtain a pointer to it. */ - if ( astTestTitle( this ) ) { - result = (*parent_gettitle)( this_frame, status ); - -/* Otherwise, create a suitable default string and return a pointer to - this. */ - } else { - (void) sprintf( gettitle_buff, "%d-d compound coordinate system", - astGetNaxes( this ) ); - if ( astOK ) result = gettitle_buff; - } - -/* Return the result. */ - return result; - -} - -static int GetUseDefs( AstObject *this_object, int *status ) { -/* -* Name: -* GetUseDefs - -* Purpose: -* Get a value for the UseDefs attribute of a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int GetUseDefs( AstCmpFrame *this, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetUseDefs method -* inherited from the Frame class). - -* Description: -* This function returns a value for the UseDefs attribute of a -* CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The UseDefs attribute value. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 1; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_object; - -/* If an UseDefs attribute value has been set, invoke the parent method - to obtain it. */ - if ( astTestUseDefs( this ) ) { - result = (*parent_getusedefs)( this_object, status ); - -/* Otherwise, use the UseDefs value in the first component Frame as the - default. */ - } else { - result = (*parent_getusedefs)( (AstObject *) this->frame1, status ); - } - -/* Return the result. */ - return result; -} - -static int GoodPerm( int ncoord_in, const int inperm[], - int ncoord_out, const int outperm[], int *status ) { -/* -* Name: -* GoodPerm - -* Purpose: -* Test if a PermMap will be non-null. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int GoodPerm( int ncoord_in, const int inperm[], -* int ncoord_out, const int outperm[], int *status ) - -* Class Membership: -* CmpFrame member function. - -* Description: -* This function tests if a pair of permutation arrays will, when -* used to create a PermMap, result in a PermMap which has a -* non-null effect (i.e. one which is not simply equivalent to a -* unit Mapping). - -* Parameters: -* ncoord_in -* The number of input coordinates for the PermMap. -* inperm -* The input permutation array for the PermMap (with "ncoord_in" -* elements). -* ncoord_out -* The number of output coordinates for the PermMap. -* outperm -* The output permutation array for the PermMap (with -* "ncoord_out" elements). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Zero if the PermMap would be equivalent to a unit Mapping, -* otherwise one. - -* 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. -*/ - -/* Local Variables: */ - int axis; /* Loop counter for axes */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* First test if the number of input and output coordinates are - different. */ - result = ( ncoord_in != ncoord_out ); - -/* If they are not, examine the contents of the "inperm" array. */ - if ( !result ) { - for ( axis = 0; axis < ncoord_in; axis++ ) { - -/* We have a non-null Mapping if any element of this array selects an - output axis with a different index to the input axis (or selects an - invalid axis or a constant). */ - if ( inperm[ axis ] != axis ) { - result = 1; - break; - } - } - } - -/* If the Mapping still appears to be null, also examine the "outperm" - array in the same way. */ - if ( !result ) { - for ( axis = 0; axis < ncoord_out; axis++ ) { - if ( outperm[ axis ] != axis ) { - result = 1; - break; - } - } - } - -/* Return the result. */ - return result; -} - -void astInitCmpFrameVtab_( AstCmpFrameVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitCmpFrameVtab - -* Purpose: -* Initialise a virtual function table for a CmpFrame. - -* Type: -* Protected function. - -* Synopsis: -* #include "cmpframe.h" -* void astInitCmpFrameVtab( AstCmpFrameVtab *vtab, const char *name ) - -* Class Membership: -* CmpFrame vtab initialiser. - -* Description: -* This function initialises the component of a virtual function -* table which is used by the CmpFrame class. - -* Parameters: -* vtab -* Pointer to the virtual function table. The components used by -* all ancestral classes will be initialised if they have not already -* been initialised. -* name -* Pointer to a constant null-terminated character string which contains -* the name of the class to which the virtual function table belongs (it -* is this pointer value that will subsequently be returned by the Object -* astClass function). -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstObjectVtab *object; /* Pointer to Object component of Vtab */ - AstFrameVtab *frame; /* Pointer to Frame component of Vtab */ - AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */ - -/* Check the local error status. */ - if ( !astOK ) return; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Initialize the component of the virtual function table used by the - parent class. */ - astInitFrameVtab( (AstFrameVtab *) vtab, name ); - -/* Store a unique "magic" value in the virtual function table. This - will be used (by astIsACmpFrame) to determine if an object belongs - to this class. We can conveniently use the address of the (static) - class_check variable to generate this unique value. */ - vtab->id.check = &class_check; - vtab->id.parent = &(((AstFrameVtab *) vtab)->id); - -/* Initialise member function pointers. */ -/* ------------------------------------ */ -/* Store pointers to the member functions (implemented here) that - provide virtual methods for this class. */ - -/* Save the inherited pointers to methods that will be extended, and - replace them with pointers to the new member functions. */ - object = (AstObjectVtab *) vtab; - frame = (AstFrameVtab *) vtab; - parent_getobjsize = object->GetObjSize; - object->GetObjSize = GetObjSize; - mapping = (AstMappingVtab *) vtab; - - parent_clearattrib = object->ClearAttrib; - object->ClearAttrib = ClearAttrib; - parent_getattrib = object->GetAttrib; - object->GetAttrib = GetAttrib; - parent_setattrib = object->SetAttrib; - object->SetAttrib = SetAttrib; - parent_testattrib = object->TestAttrib; - object->TestAttrib = TestAttrib; - - parent_getusedefs = object->GetUseDefs; - object->GetUseDefs = GetUseDefs; - -#if defined(THREAD_SAFE) - parent_managelock = object->ManageLock; - object->ManageLock = ManageLock; -#endif - - mapping->RemoveRegions = RemoveRegions; - mapping->Simplify = Simplify; - mapping->Transform = Transform; - - parent_getdomain = frame->GetDomain; - frame->GetDomain = GetDomain; - - parent_gettitle = frame->GetTitle; - frame->GetTitle = GetTitle; - - parent_getepoch = frame->GetEpoch; - frame->GetEpoch = GetEpoch; - - parent_setepoch = frame->SetEpoch; - frame->SetEpoch = SetEpoch; - - parent_clearepoch = frame->ClearEpoch; - frame->ClearEpoch = ClearEpoch; - - 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->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; - frame->TestLabel = TestLabel; - frame->TestSymbol = TestSymbol; - frame->TestUnit = TestUnit; - frame->Unformat = Unformat; - frame->ValidateSystem = ValidateSystem; - frame->SystemString = SystemString; - frame->SystemCode = SystemCode; - frame->MatchAxesX = MatchAxesX; - -/* Declare the copy constructor, destructor and class dump - function. */ - astSetCopy( vtab, Copy ); - astSetDelete( vtab, Delete ); - astSetDump( vtab, Dump, "CmpFrame", - "Compound coordinate system description" ); - -/* If we have just initialised the vtab for the current class, indicate - that the vtab is now initialised, and store a pointer to the class - identifier in the base "object" level of the vtab. */ - if( vtab == &class_vtab ) { - class_init = 1; - astSetVtabClassIdentifier( vtab, &(vtab->id) ); - } -} - -static int IsUnitFrame( AstFrame *this_frame, int *status ){ -/* -* Name: -* IsUnitFrame - -* Purpose: -* Is this Frame equivalent to a UnitMap? - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int IsUnitFrame( AstFrame *this, int *status ) - -* Class Membership: -* Region member function (over-rides the protected astIsUnitFrame -* method inherited from the Frame class). - -* Description: -* This function returns a flag indicating if the supplied Frame is -* equivalent to a UnitMap when treated as a Mapping (note, the Frame -* class inherits from Mapping and therefore every Frame is also a Mapping). - -* Parameters: -* this -* Pointer to the Frame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if the supplied Frame is equivalent to -* a UnitMap when treated as a Mapping. - -*- -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Return the result. */ - return astIsUnitFrame( this->frame1 ) && astIsUnitFrame( this->frame2 ); -} - -#if defined(THREAD_SAFE) -static int ManageLock( AstObject *this_object, int mode, int extra, - AstObject **fail, int *status ) { -/* -* Name: -* ManageLock - -* Purpose: -* Manage the thread lock on an Object. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* AstObject *ManageLock( AstObject *this, int mode, int extra, -* AstObject **fail, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astManageLock protected -* method inherited from the parent class). - -* Description: -* This function manages the thread lock on the supplied Object. The -* lock can be locked, unlocked or checked by this function as -* deteremined by parameter "mode". See astLock for details of the way -* these locks are used. - -* Parameters: -* this -* Pointer to the Object. -* mode -* An integer flag indicating what the function should do: -* -* AST__LOCK: Lock the Object for exclusive use by the calling -* thread. The "extra" value indicates what should be done if the -* Object is already locked (wait or report an error - see astLock). -* -* AST__UNLOCK: Unlock the Object for use by other threads. -* -* AST__CHECKLOCK: Check that the object is locked for use by the -* calling thread (report an error if not). -* extra -* Extra mode-specific information. -* fail -* If a non-zero function value is returned, a pointer to the -* Object that caused the failure is returned at "*fail". This may -* be "this" or it may be an Object contained within "this". Note, -* the Object's reference count is not incremented, and so the -* returned pointer should not be annulled. A NULL pointer is -* returned if this function returns a value of zero. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A local status value: -* 0 - Success -* 1 - Could not lock or unlock the object because it was already -* locked by another thread. -* 2 - Failed to lock a POSIX mutex -* 3 - Failed to unlock a POSIX mutex -* 4 - Bad "mode" value supplied. - -* Notes: -* - This function attempts to execute even if an error has already -* occurred. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - int result; /* Returned status value */ - -/* Initialise */ - result = 0; - -/* Check the supplied pointer is not NULL. */ - if( !this_object ) return result; - -/* Obtain a pointers to the CmpFrame structure. */ - this = (AstCmpFrame *) this_object; - -/* Invoke the ManageLock method inherited from the parent class. */ - if( !result ) result = (*parent_managelock)( this_object, mode, extra, - fail, status ); - -/* Invoke the astManageLock method on any Objects contained within - the supplied Object. */ - if( !result ) result = astManageLock( this->frame1, mode, extra, fail ); - if( !result ) result = astManageLock( this->frame2, mode, extra, fail ); - - return result; - -} -#endif - -static int Match( AstFrame *template_frame, AstFrame *target, int matchsub, - int **template_axes, int **target_axes, - AstMapping **map, AstFrame **result, int *status ) { -/* -* Name: -* Match - -* Purpose: -* Determine if conversion is possible between two coordinate systems. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int Match( AstFrame *template, AstFrame *target, int matchsub, -* int **template_axes, int **target_axes, -* AstMapping **map, AstFrame **result, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astMatch -* method inherited from the Frame class). - -* Description: -* This function matches a "template" CmpFrame to a "target" Frame -* and determines whether it is possible to convert coordinates -* between them. If it is, a Mapping that performs the -* transformation is returned along with a new Frame that describes -* the coordinate system that results when this Mapping is applied -* to the "target" coordinate system. In addition, information is -* returned to allow the axes in this "result" Frame to be -* associated with the corresponding axes in the "target" Frame and -* "template" CmpFrame from which they are derived. - -* Parameters: -* template -* Pointer to the template CmpFrame. This describes the -* coordinate system (or set of possible coordinate systems) -* into which we wish to convert our coordinates. -* target -* Pointer to the target Frame. This describes the coordinate -* system in which we already have coordinates. -* matchsub -* If zero then a match only occurs if the template is of the same -* class as the target, or of a more specialised class. If non-zero -* then a match can occur even if this is not the case (i.e. if the -* target is of a more specialised class than the template). In -* this latter case, the target is cast down to the class of the -* template. NOTE, this argument is handled by the global method -* wrapper function "astMatch_", rather than by the class-specific -* implementations of this method. -* template_axes -* Address of a location where a pointer to int will be returned -* if the requested coordinate conversion is possible. This -* pointer will point at a dynamically allocated array of -* integers with one element for each axis of the "result" Frame -* (see below). It must be freed by the caller (using astFree) -* when no longer required. -* -* For each axis in the result Frame, the corresponding element -* of this array will return the (zero-based) index of the -* template CmpFrame axis from which it is derived. If it is not -* derived from any template axis, a value of -1 will be -* returned instead. -* target_axes -* Address of a location where a pointer to int will be returned -* if the requested coordinate conversion is possible. This -* pointer will point at a dynamically allocated array of -* integers with one element for each axis of the "result" Frame -* (see below). It must be freed by the caller (using astFree) -* when no longer required. -* -* For each axis in the result Frame, the corresponding element -* of this array will return the (zero-based) index of the -* target Frame axis from which it is derived. If it is not -* derived from any target axis, a value of -1 will be returned -* instead. -* map -* Address of a location where a pointer to a new Mapping will -* be returned if the requested coordinate conversion is -* possible. If returned, the forward transformation of this -* Mapping may be used to convert coordinates between the -* "target" Frame and the "result" Frame (see below) and the -* inverse transformation will convert in the opposite -* direction. -* result -* Address of a location where a pointer to a new Frame will be -* returned if the requested coordinate conversion is -* possible. If returned, this Frame describes the coordinate -* system that results from applying the returned Mapping -* (above) to the "target" coordinate system. In general, this -* Frame will combine attributes from (and will therefore be -* more specific than) both the target Frame and the template -* CmpFrame. In particular, when the template allows the -* possibility of transformaing to any one of a set of -* alternative coordinate systems, the "result" Frame will -* indicate which of the alternatives was used. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if the requested coordinate -* conversion is possible. Otherwise zero is returned (this will -* not in itself result in an error condition). - -* Notes: -* - By default, the "result" Frame will have its number of axes -* and axis order determined by the "template" CmpFrame. However, -* if the PreserveAxes attribute of the template CmpFrame is -* non-zero, then the axis count and axis order of the "target" -* Frame will be used instead. -* - 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. -*/ - -/* Local Variables: */ - AstCmpFrame *template; /* Pointer to template CmpFrame structure */ - char *template_domain; /* Pointer to copy of template domain */ - const char *ptr; /* Pointer to domain string */ - const char *target_domain; /* Pointer to target domain string */ - int *axes1; /* Pointer to axis selection 1 */ - int *axes2; /* Pointer to axis selection 2 */ - int *used; /* Pointer to flags array */ - int axis2; /* Index for axis selection 2 */ - int axis; /* Index for axis arrays */ - int last_target; /* Last target axis association */ - int last_template; /* Last template axis associateion */ - int match; /* Match obtained (returned result)? */ - int maxax1; /* MaxAxes attribute for component 1 */ - int maxax2; /* MaxAxes attribute for component 2 */ - int maxax; /* Max axes that can be matched by template */ - int minax1; /* MinAxes attribute for component 1 */ - int minax2; /* MinAxes attribute for component 2 */ - int minax; /* Min axes that can be matched by template */ - int naxes1; /* Number of axes assigned to component 1 */ - int naxes2; /* Number of axes assigned to component 2 */ - int naxes; /* Total number of target axes */ - int naxes_max1; /* First estimate of naxes_max */ - int naxes_max2; /* Second estimate of naxes_max */ - int naxes_max; /* Max number of axes to match component 1 */ - int naxes_min1; /* First estimate of naxes_min */ - int naxes_min2; /* Second estimate of naxes_min */ - int naxes_min; /* Min number of axes to match component 1 */ - int permute; /* Permute attribute for template */ - int result_naxes; /* Number of result Frame 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; - -/* Obtain a pointer to the template CmpFrame structure. */ - template = (AstCmpFrame *) template_frame; - -/* Further initialisation to avoid compiler warnings. */ - naxes_min = 0; - naxes_max = 0; - -/* Obtain the maximum number of axes that the template CmpFrame, and each - component Frame of the template CmpFrame, can match. If the MaxAxes - attribute is set for the template, use it and assume that each - component Frame can match any number of axes. */ - if( astTestMaxAxes( template ) ) { - maxax = astGetMaxAxes( template ); - maxax1 = 100000; - maxax2 = 100000; - } else { - maxax1 = astGetMaxAxes( template->frame1 ); - maxax2 = astGetMaxAxes( template->frame2 ); - maxax = maxax1 + maxax2; - } - -/* Do the same for the minimum number of axes that can be matched by the - template CmpFrame. */ - if( astTestMinAxes( template ) ) { - minax = astGetMinAxes( template ); - minax1 = 1; - minax2 = 1; - } else { - minax1 = astGetMinAxes( template->frame1 ); - minax2 = astGetMinAxes( template->frame2 ); - minax = minax1 + minax2; - } - -/* Obtain the number of axes in the target Frame and test to see if it - is possible for the template to match it on the basis of axis - counts. */ - naxes = astGetNaxes( target ); - match = ( naxes >= minax && naxes <= maxax ); - -/* The next requirement is that all the frames have some axes. */ - if( naxes == 0 || maxax1 == 0 || maxax2 == 0 ) match = 0; - -/* The next requirement is that if the template CmpFrame has its - Domain attribute defined, then the target Frame must also have the - same Domain (although it need not be set - the default will - do). First check if the template has a domain. */ - if ( astOK && match ) { - if ( astTestDomain( template ) ) { - -/* Obtain a pointer to the template domain. Then allocate memory and - make a copy of it (this is necessary as we will next inquire the - domain of the target and may over-write the buffer holding the - template's domain). */ - ptr = astGetDomain( template ); - if ( astOK ) { - template_domain = astStore( NULL, ptr, - strlen( ptr ) + (size_t) 1 ); - -/* Obtain a pointer to the target domain. */ - target_domain = astGetDomain( target ); - -/* Compare the domain strings for equality. Then free the memory - allocated above. */ - match = astOK && !strcmp( template_domain, target_domain ); - template_domain = astFree( template_domain ); - } - } - } - -/* If a match still appears possible, determine the minimum number of - target axes that will have to match the first component Frame of - the template CmpFrame. */ - if ( astOK && match ) { - naxes_min1 = minax1; - naxes_min2 = naxes - maxax2; - naxes_min = ( naxes_min1 > naxes_min2 ) ? naxes_min1 : naxes_min2; - -/* Also determine the maximum number of target axes that may match - this component of the template. */ - naxes_max1 = maxax1; - naxes_max2 = naxes - minax2; - naxes_max = ( naxes_max1 < naxes_max2 ) ? naxes_max1 : naxes_max2; - -/* No match possible if the number of axes are inconsistent. */ - if( naxes_min > naxes_max ) match = 0; - } - -/* If a match is still possible, allocate workspace. */ - if( match ) { - axes1 = astMalloc( sizeof( int ) * (size_t) naxes ); - axes2 = astMalloc( sizeof( int ) * (size_t) naxes ); - used = astMalloc( sizeof( int ) * (size_t) naxes ); - -/* Obtain the value of the template's Permute attribute. */ - permute = astGetPermute( template ); - if ( astOK ) { - -/* Loop to consider all possible choices of the number of template - axes that might match the first component Frame of the template, - and derive the corresponding number of axes that must match the - second component at the same time. */ - for ( naxes1 = naxes_max; naxes1 >= naxes_min; naxes1-- ) { - naxes2 = naxes - naxes1; - -/* Initialise the selection of target axes that we will attempt to - match against the first template component (to [0,1,2,...]). */ - for ( axis = 0; axis < naxes1; axis++ ) axes1[ axis ] = axis; - -/* Loop to consider all possible selections with this number of axes, - until a match is found. */ - while ( 1 ) { - -/* Initialise an array of flags to zero for each target axis. Then set - the flag to 1 for each axis which is in the first selection.*/ - for ( axis = 0; axis < naxes; axis++ ) used[ axis ] = 0; - for( axis = 0; axis < naxes1; axis++ ) { - used[ axes1[ axis ] ] = 1; - } - -/* Generate the second selection by including all target axes that are - not in the first selection. */ - axis2 = 0; - for ( axis = 0; axis < naxes; axis++ ) { - if ( !used[ axis ] ) axes2[ axis2++ ] = axis; - } - -/* Attempt to match the target axes partitioned in this way to the two - template components. */ - match = PartMatch( template, target, matchsub, - naxes1, axes1, naxes2, axes2, - template_axes, target_axes, map, result, status ); - -/* If a match was obtained but the template's Permute attribute is zero, - then we must check to see if the match involves permuting the target - axes. */ - if ( astOK && match && !permute ) { - -/* Obtain the number of result Frame axes. */ - result_naxes = astGetNaxes( *result ); - -/* Loop to check the target and template axis associations for all the - result Frame axes. The match will only be accepted if both of these - are monotonically increasing (indicating no axis permutation) after - allowing for any absent associations . */ - last_template = -1; - last_target = -1; - for ( axis = 0; axis < result_naxes; axis++ ) { - -/* Check the template axis association against the previous value, - omitting any axes witout valid associations. */ - if ( ( *template_axes )[ axis ] != -1 ) { - if ( ( *template_axes )[ axis ] <= last_template ) { - match = 0; - break; - -/* Update the previous association value. */ - } else { - last_template = ( *template_axes )[ axis ]; - } - } - -/* Repeat this process for the target axis associations. */ - if ( ( *target_axes )[ axis ] != -1 ) { - if ( ( *target_axes )[ axis ] <= last_target ) { - match = 0; - break; - } else { - last_target = ( *target_axes )[ axis ]; - } - } - } - -/* If the match was rejected because it involves an axis permutation, - then free the allocated memory and annul the Object pointers - associated with the match. */ - if ( !match ) { - *template_axes = astFree( *template_axes ); - *target_axes = astFree( *target_axes ); - *map = astAnnul( *map ); - *result = astAnnul( *result ); - } - } - -/* If an error occurred or a match was found, quit searching, - otherwise generate the next axis selection and try that - instead. Quit if there are no more selections to try. */ - if ( !astOK || match || - !GenAxisSelection( naxes, naxes1, axes1, status ) ) break; - } - -/* Quit the outer loop if an error occurs or a match is found. */ - if ( !astOK || match ) break; - } - } - -/* Free the workspace arrays. */ - axes1 = astFree( axes1 ); - axes2 = astFree( axes2 ); - used = astFree( used ); - } - -/* If the target did not match the supplied template CmpFrame, see if it - will match either of the component Frames. First try matching it against - the first component Frame. */ - if( !match ) match = ComponentMatch( template, target, matchsub, 0, - template_axes, target_axes, map, result, - status ); - -/* If we still dont have a mcth, try matching it against the second - component Frame. */ - if( !match ) match = ComponentMatch( template, target, matchsub, 1, - template_axes, target_axes, map, - result, status ); - -/* If an error occurred, free all allocated memory, annul the result - Object pointers and clear all returned values. */ - if ( !astOK ) { - *template_axes = astFree( *template_axes ); - *target_axes = astFree( *target_axes ); - *map = astAnnul( *map ); - *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 "cmpframe.h" -* void MatchAxesX( AstFrame *frm2, AstFrame *frm1, int *axes ) -* int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected astMatchAxesX -* method inherited from the Frame class). - -* Description: -* 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 -* Frame that has no corresponding axis in the first Frame. -* -* The number of elements in this array must be greater than or -* equal to the number of axes in the second Frame. -* status -* Pointer to inherited status value. - -* Notes: -* - Corresponding axes are identified by the fact that a Mapping -* can be found between them using astFindFrame or astConvert. Thus, -* "corresponding axes" are not necessarily identical. For instance, -* SkyFrame axes in two Frames will match even if they describe -* different celestial coordinate systems -*/ - -/* Local Variables: */ - AstCmpFrame *frm2; - const int *perm; - int *work; - int i; - int nax2; - int nax1; - int nax; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to the CmpFrame. */ - frm2 = (AstCmpFrame *) frm2_frame; - -/* Get the number of axes in the two component Frames, and the total - number of axes in the CmpFrame. */ - nax2 = astGetNaxes( frm2->frame1 ); - nax1 = astGetNaxes( frm2->frame2 ); - nax = nax2 + nax1; - -/* Allocate a work array to hold the unpermuted axis indices */ - work = astMalloc( sizeof( int )*nax ); - if( astOK ) { - -/* Use the astMatchAxes method to match axes in the first component Frame - within CmpFrame "frm2". Write the associated axis indices into the first - part of the work array. */ - astMatchAxes( frm1, frm2->frame1, work ); - -/* Use the MatchAxes method to match axes in the second component - Frame. Write the associated axis indices into the work array - following the end of the values already in there. */ - astMatchAxes( frm1, frm2->frame2, work + nax2 ); - -/* Obtain a pointer to the CmpFrame's axis permutation array. The index - into "perm" represents the external axis index, and the value held in - each element of "perm" represents the corresponding internal axis index. */ - perm = astGetPerm( frm2 ); - if( astOK ) { - -/* Copy the frm2 axis indices from the work array into the returned "axes" - array, permuting their order into the external axis order of the - CmpFrame. */ - for( i = 0; i < nax; i++ ) axes[ i ] = work[ perm[ i ] ]; - } - -/* Free resources */ - work = astFree( work ); - } -} - -static void Norm( AstFrame *this_frame, double value[], int *status ) { -/* -* Name: -* Norm - -* Purpose: -* Normalise a set of CmpFrame coordinates. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void Norm( AstAxis *this, double value[], int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astNorm method -* inherited from the Frame class). - -* Description: -* This function converts a set of CmpFrame coordinate values, -* which might potentially be unsuitable for display to a user (for -* instance, may lie outside the expected range of values) into a -* set of acceptable alternative values suitable for display. - -* Parameters: -* this -* Pointer to the CmpFrame. -* value -* An array of double, with one element for each CmpFrame axis. -* This should contain the initial set of coordinate values, -* which will be modified in place. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - const int *perm; /* Axis permutation array */ - double *v; /* Pointer to permuted coordinates */ - int axis; /* Loop counter for axes */ - int naxes1; /* Number of axes in frame1 */ - int naxes; /* Number of axes in CmpFrame */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Obtain a pointer to the CmpFrame's axis permutation array. */ - perm = astGetPerm( this ); - -/* Obtain the number of axes in the CmpFrame and in the first - component Frame. */ - naxes = astGetNaxes( this ); - naxes1 = astGetNaxes( this->frame1 ); - -/* Allocate memory to hold the permuted coordinates. */ - v = astMalloc( sizeof( double ) * (size_t) naxes ); - if ( astOK ) { - -/* Permute the coordinates using the CmpFrame's axis permutation array - to put them into the order required internally (i.e. by the two - component Frames). */ - for ( axis = 0; axis < naxes; axis++ ) v[ perm[ axis ] ] = value[ axis ]; - -/* Invoke the astNorm method of both component Frames, passing the - relevant (permuted) coordinate values for normalisation. */ - astNorm( this->frame1, v ); - astNorm( this->frame2, v + naxes1 ); - -/* Copy the normalised values back into the original coordinate array, - un-permuting them in the process. */ - for ( axis = 0; axis < naxes; axis++ ) value[ axis ] = v[ perm[ axis ] ]; - } - -/* Free the memory used for the permuted coordinates. */ - v = astFree( v ); -} - -static void NormBox( AstFrame *this_frame, double lbnd[], double ubnd[], - AstMapping *reg, int *status ) { -/* -* Name: -* NormBox - -* Purpose: -* Extend a box to include effect of any singularities in the Frame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void astNormBox( AstFrame *this, double lbnd[], double ubnd[], -* AstMapping *reg, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astNormBox method inherited -* from the Frame class). - -* Description: -* This function modifies a supplied box to include the effect of any -* singularities in the co-ordinate system represented by the Frame. -* For a normal Cartesian coordinate system, the box will be returned -* unchanged. Other classes of Frame may do other things. For instance, -* a SkyFrame will check to see if the box contains either the north -* or south pole and extend the box appropriately. - -* Parameters: -* this -* Pointer to the Frame. -* lbnd -* An array of double, with one element for each Frame axis -* (Naxes attribute). Initially, this should contain a set of -* lower axis bounds for the box. They will be modified on exit -* to include the effect of any singularities within the box. -* ubnd -* An array of double, with one element for each Frame axis -* (Naxes attribute). Initially, this should contain a set of -* upper axis bounds for the box. They will be modified on exit -* to include the effect of any singularities within the box. -* reg -* A Mapping which should be used to test if any singular points are -* inside or outside the box. The Mapping should leave an input -* position unchanged if the point is inside the box, and should -* set all bad if the point is outside the box. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstCmpFrame *this; - AstCmpMap *m1; - AstCmpMap *m2; - AstCmpMap *m3; - AstCmpMap *m4; - AstCmpMap *m5; - AstCmpMap *m6; - AstPermMap *pm1; - AstPermMap *pm2; - AstPermMap *pm3; - const int *perm; - double *vl; - double *vu; - int *inperm; - int axis; - int naxes1; - int naxes; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Obtain a pointer to the CmpFrame's axis permutation array. */ - perm = astGetPerm( this ); - -/* Obtain the number of axes in the CmpFrame and in the first - component Frame. */ - naxes = astGetNaxes( this ); - naxes1 = astGetNaxes( this->frame1 ); - -/* Allocate memory to hold the permuted coordinates. */ - vl = astMalloc( sizeof( double ) * (size_t) naxes ); - vu = astMalloc( sizeof( double ) * (size_t) naxes ); - inperm = astMalloc( sizeof( int ) * (size_t) naxes ); - if( inperm ) { - -/* Permute the coordinates using the CmpFrame's axis permutation array - to put them into the order required internally (i.e. by the two - component Frames). */ - for ( axis = 0; axis < naxes; axis++ ) { - vl[ perm[ axis ] ] = lbnd[ axis ]; - vu[ perm[ axis ] ] = ubnd[ axis ]; - } - -/* Create a PermMap with a forward transformation which reorders a position - which uses internal axis ordering into a position which uses external axis - ordering. */ - pm1 = astPermMap( naxes, NULL, naxes, perm, NULL, "", status ); - -/* Put it in front of the supplied Mapping. The combination transforms an - input internal position into an output external position. */ - m1 = astCmpMap( pm1, reg, 1, "", status ); - -/* Invert it and add it to the end. This combination now transforms an - input internal position into an output internal position. */ - astInvert( pm1 ); - m2 = astCmpMap( m1, pm1, 1, "", status ); - -/* Create a PermMap with a forward transformation which copies the lower - naxes1 inputs to the same outputs, and supplies AST__BAD for the other - outputs. */ - for( axis = 0; axis < naxes1; axis++ ) inperm[ axis ] = axis; - pm2 = astPermMap( naxes1, inperm, naxes, NULL, NULL, "", status ); - -/* Put it in front of the Mapping created above, then invert it and add - it at the end. */ - m3 = astCmpMap( pm2, m2, 1, "", status ); - astInvert( pm2 ); - m4 = astCmpMap( m3, pm2, 1, "", status ); - -/* Invoke the astNormBox method of the first component Frame, passing the - relevant (permuted) coordinate values for normalisation. */ - astNormBox( this->frame1, vl, vu, m4 ); - -/* Create a PermMap with a forward transformation which copies the upper - inputs to the same outputs, and supplied AST__BAD for the other - outputs. */ - for( axis = 0; axis < naxes - naxes1; axis++ ) inperm[ axis ] = naxes1 + axis; - pm3 = astPermMap( naxes1, inperm, naxes, NULL, NULL, "", status ); - -/* Put it in front of the Mapping created above, then invert it and add - it at the end. */ - m5 = astCmpMap( pm3, m2, 1, "", status ); - astInvert( pm3 ); - m6 = astCmpMap( m5, pm3, 1, "", status ); - -/* Invoke the astNormBox method of the seond component Frame, passing the - relevant (permuted) coordinate values for normalisation. */ - astNormBox( this->frame2, vl + naxes1, vu + naxes1, m6 ); - -/* Copy the normalised values back into the original coordinate array, - un-permuting them in the process. */ - for ( axis = 0; axis < naxes; axis++ ) { - lbnd[ axis ] = vl[ perm[ axis ] ]; - ubnd[ axis ] = vu[ perm[ axis ] ]; - } - -/* Free resources. */ - pm1 = astAnnul( pm1 ); - pm2 = astAnnul( pm2 ); - pm3 = astAnnul( pm3 ); - m1 = astAnnul( m1 ); - m2 = astAnnul( m2 ); - m3 = astAnnul( m3 ); - m4 = astAnnul( m4 ); - m5 = astAnnul( m5 ); - m6 = astAnnul( m6 ); - } - inperm = astFree( inperm ); - vl = astFree( vl ); - vu = astFree( vu ); -} - -static void Offset( AstFrame *this_frame, const double point1[], - const double point2[], double offset, double point3[], int *status ) { -/* -* Name: -* Offset - -* Purpose: -* Calculate an offset along a geodesic curve. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void Offset( AstFrame *this, -* const double point1[], const double point2[], -* double offset, double point3[], int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astOffset method -* inherited from the Frame class). - -* Description: -* This function finds the CmpFrame coordinate values of a point -* which is offset a specified distance along the geodesic curve -* between two other points. - -* Parameters: -* this -* Pointer to the CmpFrame. -* point1 -* An array of double, with one element for each CmpFrame axis. -* This should contain the coordinates of the point marking the -* start of the geodesic curve. -* point2 -* An array of double, with one element for each CmpFrame axis. -* This should contain the coordinates of the point marking the -* end of the geodesic curve. -* offset -* The required offset from the first point along the geodesic -* curve. If this is positive, it will be towards the second -* point. If it is negative, it will be in the opposite -* direction. This offset need not imply a position lying -* between the two points given, as the curve will be -* extrapolated if necessary. -* point3 -* An array of double, with one element for each CmpFrame axis -* in which the coordinates of the required point will be -* returned. -* status -* Pointer to the inherited status variable. - -* Notes: -* - The geodesic curve used by this function is the path of -* shortest distance between two points, as defined by the -* astDistance function. -* - This function will return "bad" coordinate values (AST__BAD) -* if any of the input coordinates has this value. -* - "Bad" coordinate values will also be returned if the two -* points supplied are coincident (or otherwise fail to uniquely -* specify a geodesic curve) but the requested offset is non-zero. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - const int *perm; /* Pointer to axis permutation array */ - double *p1; /* Permuted coordinates for point1 */ - double *p2; /* Permuted coordinates for point2 */ - double *p3; /* Permuted coordinates for point3 */ - double dist1; /* Distance between input points in frame1 */ - double dist2; /* Distance between input points in frame2 */ - double dist; /* Total distance between input points */ - double offset1; /* Offset distance required in frame1 */ - double offset2; /* Offset distance required in frame2 */ - int axis; /* Loop counter for axes */ - int bad; /* Set bad output coordinates? */ - int naxes1; /* Number of axes in frame1 */ - int naxes; /* Total number of axes in CmpFrame */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Obtain the number of axes in the CmpFrame. */ - naxes = astGetNaxes( this ); - -/* Obtain a pointer to the CmpFrame's axis permutation array. */ - perm = astGetPerm( this ); - -/* Allocate workspace. */ - p1 = astMalloc( sizeof( double ) * (size_t) naxes ); - p2 = astMalloc( sizeof( double ) * (size_t) naxes ); - p3 = astMalloc( sizeof( double ) * (size_t) naxes ); - -/* Initialise variables to avoid compiler warnings. */ - dist1 = 0.0; - dist2 = 0.0; - offset1 = 0.0; - offset2 = 0.0; - naxes1 = 0; - -/* Initialise a flag to indicate whether "bad" coordinates should be - returned. */ - bad = 0; - -/* Check that all the coordinates of both input points are OK. If not, - set the "bad" flag and quit checking. */ - if ( astOK ) { - for ( axis = 0; axis < naxes; axis++ ) { - if ( ( point1[ axis ] == AST__BAD ) || - ( point2[ axis ] == AST__BAD ) ) { - bad = 1; - break; - -/* If the coordinates are OK, apply the axis permutation array to - obtain them in the required order. */ - } else { - p1[ perm[ axis ] ] = point1[ axis ]; - p2[ perm[ axis ] ] = point2[ axis ]; - } - } - } - -/* If OK, obtain the number of axes in the first component Frame. */ - if ( astOK && !bad ) { - naxes1 = astGetNaxes( this->frame1 ); - -/* Project the two input points into the two component Frames and - determine the distance between the points in each Frame. */ - dist1 = astDistance( this->frame1, p1, p2 ); - dist2 = astDistance( this->frame2, p1 + naxes1, p2 + naxes1 ); - -/* Check that the returned distances are not bad. */ - if ( astOK ) bad = ( ( dist1 == AST__BAD ) || ( dist2 == AST__BAD ) ); - } - -/* If OK, calculate the total distance between the two points. */ - if ( astOK && !bad ) { - dist = sqrt( dist1 * dist1 + dist2 * dist2 ); - -/* If the points are co-incident, but "offset" is non-zero, then set - the "bad" flag. */ - if ( dist == 0.0 ) { - if ( offset != 0.0 ) { - bad = 1; - -/* Otherwise, set the offset distance required in each Frame to - zero. */ - } else { - offset1 = 0.0; - offset2 = 0.0; - } - -/* If the points are not co-incident, divide the total offset required - between each component Frame in such a way that the path being - followed will pass through the second point. */ - } else { - offset1 = offset * dist1 / dist; - 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 -* The number of axes in the CmpFrame's second component Frame. -* iframe -* An array with "nselect" elements in which to return a number -* (either 1 or 2) to indicate to which component Frame (frame1 -* or frame2) each selected axis belongs. -* following -* If this is zero, "extra" axes will be associated with the -* preceding normal selected axis which appears in the "select" -* array (if any), otherwise they will be associated with the -* following normal selected axis. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - int end; /* Loop termination value */ - int ifr; /* Choice of Frame for next "extra" axis */ - int inc; /* Loop increment value */ - int iselect; /* Loop counter for axis selections */ - int naxes; /* Total number of CmpFrame axes */ - int start; /* Loop starting value */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain the total number of CmpFrame axes. */ - naxes = naxes1 + naxes2; - -/* Loop through each axis selection and identify those which refer to - valid CmpFrame axes. */ - for ( iselect = 0; iselect < nselect; iselect++ ) { - if ( ( select[ iselect ] >= 0 ) && ( select[ iselect ] < naxes ) ) { - -/* For these selections (only), enter a flag into the "iframe" array - which indicates which component Frame the selected axis resides - in. Permute each axis index before deciding this. */ - iframe[ iselect ] = 1 + ( perm[ select[ iselect ] ] >= naxes1 ); - } - } - -/* Set up a start, end, and increment value for looping through the - array of axis selections forward (if "following" is 0) or backwards - (otherwise). */ - start = following ? nselect - 1 : 0; - end = following ? -1 : nselect; - inc = following ? -1 : 1; - -/* Set the default choice of component Frame. This will be used if - there are no normal axis selections to guide the choice at all. */ - ifr = following ? 2 : 1; - -/* Search for the first normal axis selection so that we can replace - this default, if possible. (Here, "first" actually means "last" if - "following" is set, because we will then be scanning the array of - selections in reverse.) */ - for ( iselect = start; iselect != end; iselect += inc ) { - -/* Identify normal axis selections and obtain the choice of component - Frame for the first one found. The resulting value "ifr" will be - used for initial (or final, if "following" is set) "extra" - selections for which no earlier normal selection exists - see - below. */ - if ( ( select[ iselect ] >= 0 ) && ( select[ iselect ] < naxes ) ) { - ifr = iframe[ iselect ]; - break; - } - } - -/* Loop through the selections again to allocate a choice of Frame to - the "extra" selected axes. */ - for ( iselect = start; iselect != end; iselect += inc ) { - -/* Remember the component Frame used by the most recently encountered - normal axis selection. */ - if ( ( select[ iselect ] >= 0 ) && ( select[ iselect ] < naxes ) ) { - ifr = iframe[ iselect ]; - -/* For "extra" axes, allocate the most recent Frame choice. The - default choice (found above) will apply if no "most recent" choice - has been encountered. */ - } else { - iframe[ iselect ] = ifr; - } - } -} - -static int PartMatch( AstCmpFrame *template, AstFrame *target, - int matchsub, int naxes1, const int axes1[], - int naxes2, const int axes2[], - int **template_axes, int **target_axes, - AstMapping **map, AstFrame **result, int *status ) { -/* -* Name: -* PartMatch - -* Purpose: -* Match a CmpFrame template to partitioned target axes. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int PartMatch( AstCmpFrame *template, AstFrame *target, -* int matchsub, int naxes1, const int axes1[], -* int naxes2, const int axes2[], -* int **template_axes, int **target_axes, -* AstMapping **map, AstFrame **result, int *status ) - -* Class Membership: -* CmpFrame member function. - -* Description: -* This function matches a "template" CmpFrame to a "target" Frame -* and determines whether it is possible to convert coordinates -* between them. If it is, a Mapping that performs the -* transformation is returned along with a new Frame that describes -* the coordinate system that results when this Mapping is applied -* to the "target" coordinate system. In addition, information is -* returned to allow the axes in this "result" Frame to be -* associated with the corresponding axes in the "target" Frame and -* "template" CmpFrame from which they are derived. -* -* To simplify the matching process for a CmpFrame template, this -* function requires the caller to specify how the axes of the -* target Frame should be partitioned between the two component -* Frames of the template. The function attempts to find a match -* using this axis partitioning only. In general, the way in which -* the target axes must be partitioned is not known in advance, so -* this function must be invoked several times with alternative -* partitioning before a match will be found. - -* Parameters: -* template -* Pointer to the template CmpFrame. This describes the -* coordinate system (or set of possible coordinate systems) -* into which we wish to convert our coordinates. -* target -* Pointer to the target Frame. This describes the coordinate -* system in which we already have coordinates. -* matchsub -* If zero then a match only occurs if the template is of the same -* class as the target, or of a more specialised class. If non-zero -* then a match can occur even if this is not the case (i.e. if the -* target is of a more specialised class than the template). In -* this latter case, the target is cast down to the class of the -* template. -* naxes1 -* The number of target axes to be matched against the first -* component Frame of the template CmpFrame. -* axes1 -* An array with "naxes1" elements containing the (zero-based) -* indices of the target axes to be matched against the first -* component Frame. Order is not significant. -* naxes2 -* The number of target axes to be matched against the second -* component Frame of the template CmpFrame. -* axes2 -* An array with "naxes2" elements containing the (zero-based) -* indices of the target axes to be matched against the second -* component Frame. Order is not significant. -* template_axes -* Address of a location where a pointer to int will be returned -* if the requested coordinate conversion is possible. This -* pointer will point at a dynamically allocated array of -* integers with one element for each axis of the "result" Frame -* (see below). It must be freed by the caller (using astFree) -* when no longer required. -* -* For each axis in the result Frame, the corresponding element -* of this array will return the (zero-based) index of the -* template CmpFrame axis from which it is derived. If it is not -* derived from any template axis, a value of -1 will be -* returned instead. -* target_axes -* Address of a location where a pointer to int will be returned -* if the requested coordinate conversion is possible. This -* pointer will point at a dynamically allocated array of -* integers with one element for each axis of the "result" Frame -* (see below). It must be freed by the caller (using astFree) -* when no longer required. -* -* For each axis in the result Frame, the corresponding element -* of this array will return the (zero-based) index of the -* target Frame axis from which it is derived. If it is not -* derived from any target Frame axis, a value of -1 will be -* returned instead. -* map -* Address of a location where a pointer to a new Mapping will -* be returned if the requested coordinate conversion is -* possible. If returned, the forward transformation of this -* Mapping may be used to convert coordinates between the -* "target" Frame and the "result" Frame (see below) and the -* inverse transformation will convert in the opposite -* direction. -* result -* Address of a location where a pointer to a new Frame will be -* returned if the requested coordinate conversion is -* possible. If returned, this Frame describes the coordinate -* system that results from applying the returned Mapping -* (above) to the "target" coordinate system. In general, this -* Frame will combine attributes from (and will therefore be -* more specific than) both the target Frame and the template -* CmpFrame. In particular, when the template allows the -* possibility of transformaing to any one of a set of -* alternative coordinate systems, the "result" Frame will -* indicate which of the alternatives was used. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if the requested coordinate -* conversion is possible. Otherwise zero is returned (this will -* not in itself result in an error condition). - -* Notes: -* - The "axes1" and "axes2" arrays should not contain any axis -* indices in common and should, taken together, list all the axes -* of the target Frame. -* - By default, the "result" Frame will have its number of axes -* and axis order determined by the "template" CmpFrame. However, -* if the PreserveAxes attribute of the template is non-zero, then -* the axis count and axis order of the "target" Frame will be used -* instead. -* - 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. -*/ - -/* Local Variables: */ - AstFrame *frame1; /* Pointer to first sub-Frame from target */ - AstFrame *frame2; /* Pointer to second sub-Frame from target */ - AstFrame *result1; /* Result Frame pointer from first match */ - AstFrame *result2; /* Result Frame pointer from second match */ - AstFrame *tmp_frame; /* Temporary Frame pointer */ - AstMapping *junk_map; /* Mapping pointer returned by astSubFrame */ - AstMapping *map1; /* Mapping pointer from first match */ - AstMapping *map2; /* Mapping pointer from second match */ - 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 ); - if ( !match_end_set ) { - astSetMatchEnd( template->frame2, astGetMatchEnd( template ) ); - } - preserve_axes_set = astTestPreserveAxes( template->frame2 ); - if ( !preserve_axes_set ) { - astSetPreserveAxes( template->frame2, astGetPreserveAxes( template ) ); - } - permute_set = astTestPermute( template->frame2 ); - if ( permute_set ) permute_value = astGetPermute( template->frame2 ); - astSetPermute( template->frame2, 1 ); - - match2 = astMatch( template->frame2, frame2, matchsub, - &template_axes2, &target_axes2, &map2, &result2 ); - - if ( !match_end_set ) astClearMatchEnd( template->frame2 ); - if ( !preserve_axes_set ) astClearPreserveAxes( template->frame2 ); - if ( permute_set ) { - astSetPermute( template->frame2, permute_value ); - } else { - astClearPermute( template->frame2 ); - } - -/* See if both matches were successful. */ - if ( astOK && match1 && match2 ) { - match = 1; - -/* Obtain the number of target axes. */ - target_naxes = astGetNaxes( target ); - -/* Obtain the number of axes in each of the result Frames produced by - the matching operation. */ - result_naxes1 = astGetNaxes( result1 ); - result_naxes2 = astGetNaxes( result2 ); - -/* Obtain the number of axes in the first template component Frame and - in the template CmpFrame as a whole. */ - template_naxes1 = astGetNaxes( template->frame1 ); - template_naxes = astGetNaxes( template ); - -/* Obtain the value of the MatchEnd attribute for each of the - template's component Frames and for the template CmpFrame as a - whole. */ - match_end1 = astGetMatchEnd( template->frame1 ); - match_end2 = astGetMatchEnd( template->frame2 ); - match_end = astGetMatchEnd( template ); - -/* Obtain a pointer to the template CmpFrame's axis permutation - array. Allocate space for a further array and fill it with the - inverse of this axis permutation. */ - perm = astGetPerm( template ); - invperm = astMalloc( sizeof( int ) * (size_t) template_naxes ); - if ( astOK ) { - for ( template_axis = 0; template_axis < template_naxes; - template_axis++ ) { - invperm[ perm[ template_axis ] ] = template_axis; - } - } - -/* Generate template and target axis associations. */ -/* ----------------------------------------------- */ -/* We now construct two arrays which identify the axis associations - between the result axes (in the order obtained from the matching - process above) and the axes of the template and target. This - involves tracing back through several steps. */ - -/* First calculate the total number of result axes and allocate memory - for the association arrays. */ - result_naxes = result_naxes1 + result_naxes2; - template_assoc = astMalloc( sizeof( int ) * (size_t) result_naxes ); - target_assoc = astMalloc( sizeof( int ) * (size_t) result_naxes ); - if ( astOK ) { - -/* Produce associations for each result axis in turn. */ - for ( result_axis = 0; result_axis < result_naxes; result_axis++ ) { - -/* Decide whether this result axis is contained in the first (or - second) individual result Frame. */ - first = ( result_axis < result_naxes1 ); - -/* Obtain the index of the axis within the individual result Frame. - This involves adjusting for the axis numbering offset of the second - result Frame if necessary. */ - part_result_axis = first ? result_axis : - result_axis - result_naxes1; - -/* Find the template and target axis associations for this axis by - looking them up in the association arrays returned from the - matching process. This gives axis indices that apply to the - individual template/target Frames supplied as input to the matching - process. */ - part_template_axis = first ? template_axes1[ part_result_axis ] : - template_axes2[ part_result_axis ]; - part_target_axis = first ? target_axes1[ part_result_axis ] : - target_axes2[ part_result_axis ]; - -/* Check that the resulting template association identifies a valid - template axis. */ - if ( part_template_axis != -1 ) { - -/* If so, obtain the template axis index. This involves adjusting for - the axis numbering offset of the second template component Frame - (if necessary) and then applying the inverse template axis - permutation to convert to the external template axis - numbering. Store the result in the template association array. */ - template_assoc[ result_axis ] = - invperm[ first ? part_template_axis : - part_template_axis + template_naxes1 ]; - -/* Indicate if there is no template axis association by storing an - index of -1. */ - } else { - template_assoc[ result_axis ] = -1; - } - -/* Similarly, check that the target association identifies a valid - target axis. */ - if ( part_target_axis != -1 ) { - -/* If so, obtain the target axis index. This simply involves using the - axis selection arrays provided by the caller to look up which - target axes were involved in the matching process. */ - target_assoc[ result_axis ] = - first ? axes1[ part_target_axis ] : - axes2[ part_target_axis ]; - -/* Indicate if there is no target axis association by storing an index - of -1. */ - } else { - target_assoc[ result_axis ] = -1; - } - } - } - -/* Free the inverse axis permutation array. */ - invperm = astFree( invperm ); - -/* Create the output Frame. */ -/* ------------------------ */ -/* Initialise. */ - result_order = NULL; - result_perm = NULL; - -/* Construct the basis of the final result Frame by combining the two - individual result Frames (from the matching process) using a - CmpFrame. */ - if ( astOK ) { - *result = (AstFrame *) astCmpFrame( result1, result2, "", status ); - -/* The next step is to permute the result Frame's axis order so that - it corresponds with the axis order of the "reference Frame". The - reference Frame is either the template or the target, depending on - whether the template's PreserveAxes attribute is non-zero. Obtain - the value of this attribute. */ - preserve_axes = astGetPreserveAxes( template ); - -/* Decide how many axes the reference Frame contains. */ - ref_naxes = preserve_axes ? target_naxes : template_naxes; - -/* Make a copy of the axis association array that refers to the - reference Frame. */ - result_order = astStore( NULL, - preserve_axes ? target_assoc : - template_assoc, - sizeof( int ) * (size_t) result_naxes ); - -/* The intention is to use this axis association array to permute the - result axes into the same order as the reference Frame's axes. It - is not that simple, however, because some of the axis associations - may be null (i.e. result axes may exist that are not associated - with reference axes) and they may also be incomplete (i.e. not - every reference axis may be associated with a result axis). - - This prevents us from permuting the result axis order using this - array directly, essentially because we haven't yet defined where - any "extra" result axes (those with no association) should appear - in the final axis order. */ - -/* To overcome this, we replace all the null (-1) entries in the - "result_order" array with new values which define their position - relative to the other entries. This also involves re-numbering - other entries to avoid clashes. The new numbers assigned depend on - the MatchEnd attribute for each of the template component Frames, - so we handle the associations for each of these components - separately. */ - AddExtraAxes( result_naxes, result_order, - 0, result_naxes1 - 1, match_end1, status ); - AddExtraAxes( result_naxes, result_order, - result_naxes1, result_naxes - 1, match_end2, status ); - -/* There may now be some reference Frame axes which are not referenced - in this array, so we renumber the entries starting at zero (but - preserving their relative order) so that there are no missing - values due to these. */ - RenumberAxes( result_naxes, result_order, status ); - -/* The resulting "result_order" array no longer describes the original - reference Frame axis associations, but is now suitable for - permuting the result axes into the required order. However, we - require the inverse of this permutation, so allocate an array and - fill it with the inverse. */ - result_perm = astMalloc( sizeof( int ) * (size_t) result_naxes ); - if ( astOK ) { - for ( result_axis = 0; result_axis < result_naxes; - result_axis++ ) { - result_perm[ result_order[ result_axis ] ] = result_axis; - } - } - -/* Apply the inverse permutation to the result CmpFrame to put its - axes into the required order. */ - astPermAxes( *result, result_perm ); - -/* Check if the number of result Frame axes differs from the number of - reference axes. This can arise if the PreserveAxes attribute of - either template component Frame is set to a value that differs from - that of the template CmpFrame as a whole. If this is the case, we - must select a sub-set (or super-set) of the result axes, so that we - end up with the same number of axes as the reference Frame. */ - if ( ref_naxes != result_naxes ) { - -/* Allocate an array to hold the indices of the axes required. */ - pick = astMalloc( sizeof( int ) * (size_t) ref_naxes ); - if ( astOK ) { - -/* Generate the axis indices, using the template CmpFrame's MatchEnd - attribute to decide which ones to use. */ - for ( output_axis = 0; output_axis < ref_naxes; - output_axis++ ) { - full_axis = - match_end ? output_axis + ( result_naxes - ref_naxes ) : - output_axis; - -/* If the index is valid (i.e. the required axis is available), store - it. Otherwise, use an index of -1, which requests that new - (default) axes be supplied where needed. */ - if ( ( full_axis >= 0 ) && ( full_axis < result_naxes ) ) { - pick[ output_axis ] = full_axis; - } else { - pick[ output_axis ] = -1; - } - } - } - -/* Pick the required axes from the result Frame and replace it with - the new one. */ - tmp_frame = astPickAxes( *result, ref_naxes, pick, NULL ); - *result = astAnnul( *result ); - *result = tmp_frame; - -/* Free the array of axis indices. */ - pick = astFree( pick ); - } - } - -/* Create output axis association arrays. */ -/* -------------------------------------- */ -/* We now construct the two arrays that are returned to identify which - template and target axes (if any) are associated with each final - result Frame axis. Allocate memory for these arrays. */ - if ( astOK ) { - *target_axes = astMalloc( sizeof( int ) * (size_t) ref_naxes ); - *template_axes = astMalloc( sizeof( int ) * (size_t) ref_naxes ); - if ( astOK ) { - -/* For each output axis, obtain the original result axis index (before - any sub-set or super-set of the output axes was selected). */ - for ( output_axis = 0; output_axis < ref_naxes; output_axis++ ) { - full_axis = - match_end ? output_axis + ( result_naxes - ref_naxes ) : - output_axis; - -/* Derive the result axis index before the axes were permuted into - their final order. */ - if ( ( full_axis >= 0 ) && ( full_axis < result_naxes ) ) { - result_axis = result_perm[ full_axis ]; - -/* Use this axis index and the axis association arrays generated - earlier to obtain the required associations, and store these in the - output arrays. */ - ( *template_axes )[ output_axis ] = - template_assoc[ result_axis ]; - ( *target_axes )[ output_axis ] = - target_assoc[ result_axis ]; - -/* Store a value of -1 if there is no association. */ - } else { - ( *template_axes )[ output_axis ] = -1; - ( *target_axes )[ output_axis ] = -1; - } - } - } - } - -/* Free the original (un-permuted) axis association arrays. */ - template_assoc = astFree( template_assoc ); - target_assoc = astFree( target_assoc ); - -/* Create the output Mapping. */ -/* -------------------------- */ -/* Construct the basis of the final output Mapping by combining the - Mappings produced by the individual matching processes in parallel, - using a CmpMap. */ - *map = (AstMapping *) astCmpMap( map1, map2, 0, "", status ); - -/* It is now necessary to prefix and suffix this CmpMap with two - PermMaps, which correct the input and output axis order to - correspond with the target and result Frame axes. - - At the target end, this reflects the partitioning of the target - axes into two groups, as specified by the caller. At the result - end, it reflects the axis permutation applied (above) to put the - final result Frame axes into the required order, together with the - selection of any sub-set or super-set of these axes. */ - -/* Allocate memory for permutation arrays to describe the prefix - PermMap. */ - inperm = astMalloc( sizeof( int ) * (size_t) target_naxes ); - outperm = astMalloc( sizeof( int ) * (size_t) target_naxes ); - if ( astOK ) { - -/* Consider the target axes in the order that they were supplied to - the matching processes (i.e. the order that corresponds with the - input coordinates of the CmpMap produced above). */ - for ( target_axis = 0; target_axis < target_naxes; target_axis++ ) { - -/* Decide whether each axis belongs to the first (or second) selected - group of target axes. */ - first = ( target_axis < naxes1 ); - -/* Obtain the index of the target axis within the group. This involves - allowing for the numbering offset of the second group if - necessary. */ - part_target_axis = first ? target_axis : - target_axis - naxes1; - -/* Obtain the original target axis index by looking up the axis in the - appropriate axis selection array provided by the caller. */ - outperm[ target_axis ] = first ? axes1[ part_target_axis ] : - axes2[ part_target_axis ]; - -/* Fill the "inperm" array with the inverse of this permutation. */ - inperm[ outperm[ target_axis ] ] = target_axis; - } - } - -/* If the permutation is not null, use these permutation arrays to - construct the required prefix PermMap. */ - if ( GoodPerm( target_naxes, inperm, target_naxes, outperm, status ) ) { - permmap = (AstMapping *) astPermMap( target_naxes, inperm, - target_naxes, outperm, - NULL, "", status ); - -/* Add the PermMap as a prefix to the result Mapping and then annul - the original Mapping pointers. */ - tmp_map = (AstMapping *) astCmpMap( permmap, *map, 1, "", status ); - (void) astAnnul( *map ); - *map = tmp_map; - permmap = astAnnul( permmap ); - } - -/* Free the permutation arrays. */ - inperm = astFree( inperm ); - outperm = astFree( outperm ); - -/* Allocate memory for permutation arrays to describe the suffix - PermMap. */ - inperm = astMalloc( sizeof( int ) * (size_t) result_naxes ); - outperm = astMalloc( sizeof( int ) * (size_t) ref_naxes ); - if ( astOK ) { - -/* Initialise the "inperm" array. */ - for ( result_axis = 0; result_axis < result_naxes; result_axis++ ) { - inperm[ result_axis ] = -1; - } - -/* For each output axis, obtain the index of the corresponding result - axis before any sub-set or super-set was selected. */ - for ( output_axis = 0; output_axis < ref_naxes; output_axis++ ) { - full_axis = - match_end ? output_axis + ( result_naxes - ref_naxes ) : - output_axis; - -/* Store the axis index before the result axes were permuted, and also - construct the inverse permutation. */ - if ( ( full_axis >= 0 ) && ( full_axis < result_naxes ) ) { - outperm[ output_axis ] = result_perm[ full_axis ]; - inperm[ outperm[ output_axis ] ] = output_axis; - -/* Note which output axes do not exist in the result Frame - (e.g. because a super-set was selected). */ - } else { - outperm[ output_axis ] = -1; - } - } - } - -/* If the permutation is not null, use these permutation arrays to - construct the required suffix PermMap. */ - if ( GoodPerm( target_naxes, inperm, target_naxes, outperm, status ) ) { - permmap = (AstMapping *) astPermMap( result_naxes, inperm, - ref_naxes, outperm, - NULL, "", status ); - -/* Add the PermMap as a suffix to the result Mapping and then annul - the original Mapping pointers. */ - tmp_map = (AstMapping *) astCmpMap( *map, permmap, 1, "", status ); - (void) astAnnul( *map ); - *map = tmp_map; - permmap = astAnnul( permmap ); - } - -/* Free the permutation arrays. */ - inperm = astFree( inperm ); - outperm = astFree( outperm ); - -/* Free the result axis permutation arrays. */ - result_order = astFree( result_order ); - result_perm = astFree( result_perm ); - } - -/* If necessary, free the results of the first matching process. */ - if ( match1 ) { - template_axes1 = astFree( template_axes1 ); - target_axes1 = astFree( target_axes1 ); - map1 = astAnnul( map1 ); - result1 = astAnnul( result1 ); - } - -/* If necessary, free the results of the second matching process. */ - if ( match2 ) { - template_axes2 = astFree( template_axes2 ); - target_axes2 = astFree( target_axes2 ); - map2 = astAnnul( map2 ); - result2 = astAnnul( result2 ); - } - -/* Annul the pointers to the sub-Frames selected from the target. */ - frame1 = astAnnul( frame1 ); - frame2 = astAnnul( frame2 ); - -/* If an error occurred, free all allocated memory, annul the result - Object pointers and clear all returned values. */ - if ( !astOK ) { - *template_axes = astFree( *template_axes ); - *target_axes = astFree( *target_axes ); - *map = astAnnul( *map );; - *result = astAnnul( *result ); - match = 0; - } - -/* Return the result. */ - return match; -} - -static void PermAxes( AstFrame *this_frame, const int perm[], int *status ) { -/* -* Name: -* PermAxes - -* Purpose: -* Permute the order of a CmpFrame's axes. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void astPermAxes( AstFrame *this, const int perm[], int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astPermAxes method -* inherited from the Frame class). - -* Description: -* This function permutes the order in which a CmpFrame's axes occur. - -* Parameters: -* this -* Pointer to the CmpFrame. -* perm -* An array of int (with one element for each axis of the -* CmpFrame) which lists the axes in their new order. Each -* element of this array should be a (zero-based) axis index -* identifying the axes according to their old (un-permuted) -* order. -* status -* Pointer to the inherited status variable. - -* Notes: -* - Only genuine permutations of the axis order are permitted, so -* each axis must be referenced exactly once in the "perm" array. -* - If more than one axis permutation is applied to a CmpFrame, -* the effects are cumulative. - -* Implementation Notes: -* - This function performs essentially the same operation as the -* Frame member function which it over-rides. However, it operates -* on a "perm" array held in the CmpFrame structure (rather than -* the one in the parent Frame structure). This duplication of the -* array is necessary because the one in the Frame structure is of -* zero length, the number of axes in the Frame structure having -* been set to zero to prevent unnecessary allocation of Axis -* objects which are not needed by the CmpFrame. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - int *old; /* Pointer to copy of old permutation array */ - int axis; /* Loop counter for CmpFrame axes */ - int naxes; /* Number of CmpFrame axes */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate the permutation array, to check that it describes a - genuine permutation. */ - astCheckPerm( this, perm, "astPermAxes" ); - -/* Obtain the number of CmpFrame axes. */ - naxes = astGetNaxes( this ); - -/* Allocate memory and use it to store a copy of the old permutation - array for the CmpFrame. */ - old = astStore( NULL, this->perm, sizeof( int ) * (size_t) naxes ); - -/* Apply the new axis permutation cumulatively to the old one and - store the result in the CmpFrame. */ - if ( astOK ) { - for ( axis = 0; axis < naxes; axis++ ) { - this->perm[ axis ] = old[ perm[ axis ] ]; - } - } - -/* Free the temporary copy of the old array. */ - old = astFree( old ); -} - -static void PrimaryFrame( AstFrame *this_frame, int axis1, - AstFrame **frame, int *axis2, int *status ) { -/* -* Name: -* PrimaryFrame - -* Purpose: -* Uniquely identify a primary Frame and one of its axes. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void astPrimaryFrame( AstFrame *this, int axis1, AstFrame **frame, -* int *axis2, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the protected -* astPrimaryFrame method inherited from the Frame class). - -* Description: -* This function returns information about the underlying (primary) -* Frame corresponding to a specified CmpFrame axis. - -* Parameters: -* this -* Pointer to the CmpFrame. -* axis1 -* An axis index (zero-based) identifying the CmpFrame axis for -* which information is required. -* frame -* Address of a location to receive a pointer to the underlying -* (primary) Frame to which the requested axis belongs -* (i.e. this will not be a compound Frame). -* axis2 -* Pointer to an int which is to receive the (zero-based) axis -* index within "frame" which identifies the axis being referred -* to, using the axis order that applied when the primary Frame -* was originally constructed (i.e. this function undoes all -* subsequent axis pemutations and the effects of combining -* Frames, in order to reveal the original underlying axis -* order). -* status -* Pointer to the inherited status variable. - -* Notes: -* - This protected method is provided so that class -* implementations can distinguish the axes of Frames from one -* another (e.g. can distinguish a longitude axis as being -* different from a latitide axis) even after their order has been -* permuted and they have been combined with axes from other -* Frames. -* - The reference count of the primary Frame will be incremented -* by one to reflect the new pointer returned. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - int naxes1; /* Number of axes in frame1 */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate and permute the axis index supplied. */ - axis1 = astValidateAxis( this, axis1, 1, "astPrimaryFrame" ); - -/* Obtain the number of axes in the first component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - if ( astOK ) { - -/* Decide which Frame contains the axis and invoke its astPrimaryFrame - method to obtain the required information. */ - if ( axis1 < naxes1 ) { - astPrimaryFrame( this->frame1, axis1, frame, axis2 ); - } else { - astPrimaryFrame( this->frame2, axis1 - naxes1, frame, axis2 ); - } - } -} - -static int QsortCmpAxes( const void *a, const void *b ) { -/* -* Name: -* QsortCmpAxes - -* Purpose: -* Compare two axis indices for "qsort". - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int QsortCmpAxes( const void *a, const void *b ) - -* Class Membership: -* CmpFrame member function. - -* Description: -* This is a service function for the C RTL routine "qsort". It -* takes the two values supplied and interprets them as integer -* indices into the static "qsort_axes" array. It compares the -* values of these two array elements and returns the result -* required by "qsort". -* -* This function is used when sorting an array of indices so that -* they access the "qsort_axes" array in ascending order. - -* Parameters: -* As required by "qsort". - -* Returned Value: -* As required by "qsort". -*/ - -/* Local Variables. */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - int result; /* Result value to return */ - int val_a; /* First axis index */ - int val_b; /* Second axis index */ - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Convert the values passed by "qsort" into integer array indices and - use these to access the "qsort_axes" array (this pointer to the - array being assigned by the caller of "qsort"). Extract the two - values being compared. */ - val_a = qsort_axes[ *( (const int *) a ) ]; - val_b = qsort_axes[ *( (const int *) b ) ]; - -/* Compare the two values as required by "qsort". */ - if ( val_a < val_b ) { - result = -1; - } else if ( val_a == val_b ) { - result = 0; - } else { - result = 1; - } - -/* Return the result. */ - return result; -} - -static AstMapping *RemoveRegions( AstMapping *this_mapping, int *status ) { -/* -* Name: -* RemoveRegions - -* Purpose: -* Remove any Regions from a Mapping. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstMapping *RemoveRegions( AstMapping *this, int *status ) - -* Class Membership: -* CmpFrame method (over-rides the astRemoveRegions method inherited -* from the Frame class). - -* Description: -* This function searches the supplied Mapping (which may be a -* compound Mapping such as a CmpMap) for any component Mappings -* that are instances of the AST Region class. It then creates a new -* Mapping from which all Regions have been removed. If a Region -* cannot simply be removed (for instance, if it is a component of a -* parallel CmpMap), then it is replaced with an equivalent UnitMap -* in the returned Mapping. -* -* The implementation provided by the CmpFrame class invokes the -* astRemoveRegions method on the two component Frames, and joins -* the results together into a new CmpFrame. This replaces any Regions -* with their equivalent Frames. - -* Parameters: -* this -* Pointer to the original Region. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the modified mapping. - -* Notes: -* - A NULL pointer value will be returned if this function is -* invoked with the AST error status set, or if it should fail for -* any reason. -*/ - -/* Local Variables: */ - AstCmpFrame *new; /* Pointer to new CmpFrame */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - AstFrame *newfrm1; /* New first component Frame */ - AstFrame *newfrm2; /* New second component Frame */ - AstMapping *result; /* Result pointer to return */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the CmpFrame. */ - this = (AstCmpFrame *) this_mapping; - -/* Invoke the astRemoveRegions method on the two component Frames. */ - newfrm1 = astRemoveRegions( this->frame1 ); - newfrm2 = astRemoveRegions( this->frame2 ); - -/* If neither component was modified, just return a clone of the supplied - pointer. */ - if( this->frame1 == newfrm1 && this->frame2 == newfrm2 ) { - result = astClone( this ); - -/* Annul new new Frame pointers. */ - newfrm1 = astAnnul( newfrm1 ); - newfrm2 = astAnnul( newfrm2 ); - -/* Otherwise, we need to create a new CmpFrame to return. */ - } else { - -/* Make a copy of the supplied CmpFrame so that the new CmpFrame retains - any attribute settings of the supplied CmpFrame. */ - new = astCopy( this ); - result = (AstMapping *) new; - -/* Replace the two component Frames with the simplified Frames. */ - (void) astAnnul( new->frame1 ); - (void) astAnnul( new->frame2 ); - new->frame1 = (AstFrame *) newfrm1; - new->frame2 = (AstFrame *) newfrm2; - } - -/* Annul the returned Mapping if an error has occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return the result. */ - return result; -} - -static void RenumberAxes( int naxes, int axes[], int *status ) { -/* -* Name: -* RenumberAxes - -* Purpose: -* Renumber axis indices to eliminate missing ones. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void RenumberAxes( int naxes, int axes[], int *status ) - -* Class Membership: -* CmpFrame member function. - -* Description: -* This function takes an array containing a list of (zero-based) -* axis indices referring to the axes of a Frame, some of whose -* axes may not be referenced. It renumbers the axis indices, to -* eliminate any which are missing (i.e. not referenced), while -* preserving the original order. It does this by replacing each -* axis index by its rank (starting at zero) when the indices are -* sorted into ascending order. - -* Parameters: -* naxes -* The number of axis indices present. -* axes -* An array, with "naxes" elements, containing the indices. This -* is modified by this function to contain the new indices. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - int *work; /* Pointer to workspace array */ - int i; /* Loop counter */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Allocate workspace. */ - work = astMalloc( sizeof( int ) * (size_t) naxes ); - if ( astOK ) { - -/* Fill the workspace with indices which address the axis index values - in their natural order. */ - for ( i = 0; i < naxes; i++ ) work[ i ] = i; - -/* Make the "axes" values available to the C RTL function "qsort" via - the static "qsort_axes" pointer. Then use "qsort" to permute the - contents of "work" so that it addresses the axis indices in - ascending order. */ - qsort_axes = axes; - qsort( work, (size_t) naxes, sizeof( int ), QsortCmpAxes ); - -/* Use the result to replace each axis index by its rank when sorted - into ascending order (starting with zero). */ - for ( i = 0; i < naxes; i++ ) axes[ work[ i ] ] = i; - } - -/* Free the workspace array. */ - work = astFree( work ); -} - -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 - -* Purpose: -* Resolve a vector into two orthogonal components - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void Resolve( AstFrame *this, const double point1[], -* const double point2[], const double point3[], -* double point4[], double *d1, double *d2, int *status ); - -* Class Membership: -* CmpFrame member function (over-rides the astOffset method -* inherited from the Frame class). - -* Description: -* This function resolves a vector into two perpendicular components. -* The vector from point 1 to point 2 is used as the basis vector. -* The vector from point 1 to point 3 is resolved into components -* parallel and perpendicular to this basis vector. The lengths of the -* two components are returned, together with the position of closest -* aproach of the basis vector to point 3. - -* Parameters: -* this -* Pointer to the Frame. -* point1 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the start of the basis vector, -* and of the vector to be resolved. -* point2 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the end of the basis vector. -* point3 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the end of the vector to be -* resolved. -* point4 -* An array of double, with one element for each Frame axis -* in which the coordinates of the point of closest approach of the -* basis vector to point 3 will be returned. -* d1 -* The address of a location at which to return the distance from -* point 1 to point 4 (that is, the length of the component parallel -* to the basis vector). Positive values are in the same sense as -* movement from point 1 to point 2. -* d2 -* The address of a location at which to return the distance from -* point 4 to point 3 (that is, the length of the component -* perpendicular to the basis vector). The returned value is always -* positive. -* status -* Pointer to the inherited status variable. - -* Notes: -* - Each vector used in this function is the path of -* shortest distance between two points, as defined by the -* astDistance function. -* - This function will return "bad" coordinate values (AST__BAD) -* if any of the input coordinates has this value, or if the required -* output values are undefined. -*-- -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - const int *perm; /* Pointer to axis permutation array */ - double *p1; /* Permuted coordinates for point1 */ - double *p2; /* Permuted coordinates for point2 */ - double *p3; /* Permuted coordinates for point3 */ - double *p4; /* Permuted coordinates for point4 */ - double d1a; /* Parallel distance in frame1 */ - double d1b; /* Parallel distance in frame2 */ - double d2a; /* Perpendicular distance in frame1 */ - double d2b; /* Perpendicular distance in frame2 */ - double d; /* Total length of basis vector */ - double da; /* Length of basis vector in frame1 */ - double db; /* Length of basis vector in frame2 */ - int axis; /* Loop counter for axes */ - int bad; /* Set bad output coordinates? */ - int naxes1; /* Number of axes in frame1 */ - int naxes; /* Total number of axes in CmpFrame */ - -/* Check the global error status. */ - *d1 = AST__BAD; - *d2 = AST__BAD; - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Obtain the number of axes in the CmpFrame. */ - naxes = astGetNaxes( this ); - -/* Obtain a pointer to the CmpFrame's axis permutation array. */ - perm = astGetPerm( this ); - -/* Allocate workspace. */ - p1 = astMalloc( sizeof( double ) * (size_t) naxes ); - p2 = astMalloc( sizeof( double ) * (size_t) naxes ); - p3 = astMalloc( sizeof( double ) * (size_t) naxes ); - p4 = astMalloc( sizeof( double ) * (size_t) naxes ); - -/* Initialise a flag to indicate whether "bad" coordinates should be - returned. */ - bad = 0; - -/* Initialise ther variables to avoid compiler warnings. */ - da = 0.0; - db = 0.0; - -/* Check that all the coordinates of both input points are OK. If not, - set the "bad" flag and quit checking. */ - if ( astOK ) { - for ( axis = 0; axis < naxes; axis++ ) { - if ( ( point1[ axis ] == AST__BAD ) || - ( point2[ axis ] == AST__BAD ) || - ( point3[ axis ] == AST__BAD ) ) { - bad = 1; - break; - -/* If the coordinates are OK, apply the axis permutation array to - obtain them in the required order. */ - } else { - p1[ perm[ axis ] ] = point1[ axis ]; - p2[ perm[ axis ] ] = point2[ axis ]; - p3[ perm[ axis ] ] = point3[ axis ]; - } - } - } - -/* If OK, obtain the number of axes in the first component Frame. */ - if ( astOK && !bad ) { - naxes1 = astGetNaxes( this->frame1 ); - -/* Find the projection of the required parallel distance into each of the - two Frames. */ - astResolve( this->frame1, p1, p2, p3, p4, &d1a, &d2a ); - astResolve( this->frame2, p1 + naxes1, p2 + naxes1, p3 + naxes1, - p4 + naxes1, &d1b, &d2b ); - -/* Project the first two input points into the two component Frames and - determine the length of the basis vector in each Frame. */ - da = astDistance( this->frame1, p1, p2 ); - db = astDistance( this->frame2, p1 + naxes1, p2 + naxes1 ); - -/* Check that the returned distances are not bad. */ - if ( astOK ) bad = ( bad || ( da == AST__BAD ) || ( db == AST__BAD ) ); - -/* We can tolerate a bad parallel distance within a sub-Frame if the - basis vector has zero length in the sub-Frame, because the bad - parallel distance will have zero weight in the calculation. Set such - bad parallel distanced arbitrarily to zero. */ - if( d1a == AST__BAD && da == 0.0 ) d1a = 0.0; - if( d1b == AST__BAD && db == 0.0 ) d1b = 0.0; - -/* Check that the final parallel distances are not bad. */ - if ( astOK ) bad = ( bad || ( d1a == AST__BAD ) || ( d1b == AST__BAD ) ); - - } - -/* If OK, calculate the total distance between the two points. */ - if ( astOK && !bad ) { - d = sqrt( da * da + db * db ); - -/* If the points are co-incident, then set the "bad" flag. */ - if ( d == 0.0 ) { - bad = 1; - -/* If the points are not co-incident, combine the parallel distances for - the individual Frames into a single parallel distance for the entire - CmpFrame. */ - } else { - *d1 = ( da*d1a + db*d1b )/d; - -/* Offset this distance away from point 1 towards point 2 to get point 4. */ - astOffset( this, point1, point2, *d1, point4 ); - -/* Now find the perpendicular distance (the distance between point4 and - point3). */ - *d2 = astDistance( this, point4, point3 ); - - } - } - -/* Free the workspace arrays. */ - p1 = astFree( p1 ); - p2 = astFree( p2 ); - p3 = astFree( p3 ); - p4 = astFree( p4 ); - -/* If no error has occurred, but bad coordinates must be returned, - then set these in the output array. */ - if ( astOK && bad ) { - *d1 = AST__BAD; - *d2 = AST__BAD; - for ( axis = 0; axis < naxes; axis++ ) point4[ axis ] = AST__BAD; - } - -} - -static AstPointSet *ResolvePoints( AstFrame *this_frame, const double point1[], - const double point2[], AstPointSet *in, - AstPointSet *out, int *status ) { -/* -* Name: -* ResolvePoints - -* Purpose: -* Resolve a set of vectors into orthogonal components - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstPointSet *ResolvePoints( AstFrame *this, const double point1[], -* const double point2[], AstPointSet *in, -* AstPointSet *out ) - -* Class Membership: -* CmpFrame member function (over-rides the astResolvePoints method -* inherited from the Frame class). - -* Description: -* This function takes a CmpFrame and a set of vectors encapsulated -* in a PointSet, and resolves each one into two orthogonal components, -* returning these two components in another PointSet. -* -* This is exactly the same as the public astResolve method, except -* that this method allows many vectors to be processed in a single call, -* thus reducing the computational cost of overheads of many -* individual calls to astResolve. - -* Parameters: -* this -* Pointer to the CmpFrame. -* point1 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the start of the basis vector, -* and of the vectors to be resolved. -* point2 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the end of the basis vector. -* in -* Pointer to the PointSet holding the ends of the vectors to be -* resolved. -* out -* Pointer to a PointSet which will hold the length of the two -* resolved components. A NULL value may also be given, in which -* case a new PointSet will be created by this function. - -* Returned Value: -* Pointer to the output (possibly new) PointSet. The first axis will -* hold the lengths of the vector components parallel to the basis vector. -* These values will be signed (positive values are in the same sense as -* movement from point 1 to point 2. The second axis will hold the lengths -* of the vector components perpendicular to the basis vector. These -* values will always be positive. - -* Notes: -* - The number of coordinate values per point in the input -* PointSet must match the number of axes in the supplied Frame. -* - If an output PointSet is supplied, it must have space for -* sufficient number of points and 2 coordinate values per point. -* - A null pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - AstPointSet *in1; /* Pointer to input PointSet for frame1 */ - AstPointSet *in2; /* Pointer to input PointSet for frame2 */ - AstPointSet *out1; /* Pointer to output PointSet for frame1 */ - AstPointSet *out2; /* Pointer to output PointSet for frame2 */ - AstPointSet *result; /* Pointer to output PointSet */ - const int *perm; /* Pointer to axis permutation array */ - double **ptr_in; /* Pointers to input axis values */ - double **ptr_out1; /* Pointers to frame1 component lengths */ - double **ptr_out2; /* Pointers to frame2 component lengths */ - double **ptr_out; /* Pointers to returned component lengths */ - double *d1; /* Pointer to next parallel component value */ - double *d1_1; /* arallel distance in frame1 */ - double *d1_2; /* Parallel distance in frame2 */ - double *d2; /* Pointer to next perpendicular component value */ - double *d2_1; /* Perpendicular distance in frame1 */ - double *d2_2; /* Perpendicular distance in frame2 */ - double *p1; /* Permuted coordinates for point1 */ - double *p2; /* Permuted coordinates for point2 */ - double *p3; /* Supplied vector */ - double *p4; /* Closest approach to supplied vector */ - double b1; /* Length of basis vector in frame1 */ - double b2; /* Length of basis vector in frame2 */ - double b; /* Length of basis vector */ - int axis; /* Loop counter for axes */ - int ipoint; /* Index of next point */ - int nax; /* Number of Frame axes */ - int naxes1; /* Number of axes in frame1 */ - int naxes2; /* Number of axes in frame2 */ - int ncoord_in; /* Number of input PointSet coordinates */ - int ncoord_out; /* Number of coordinates in output PointSet */ - int npoint; /* Number of points to transform */ - int npoint_out; /* Number of points in output PointSet */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Further initialise to prevent compiler "uninitialised use" messages. */ - d1 = NULL; - d2 = NULL; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Obtain the number of axes in the two component Frames */ - naxes1 = astGetNaxes( this->frame1 ); - naxes2 = astGetNaxes( this->frame2 ); - -/* For the total number of axes. */ - nax = naxes1 + naxes2; - -/* Obtain the number of input vectors to resolve and the number of coordinate - values per vector. */ - npoint = astGetNpoint( in ); - ncoord_in = astGetNcoord( in ); - -/* If OK, check that the number of input coordinates matches the number - required by the Frame. Report an error if these numbers do not match. */ - if ( astOK && ( ncoord_in != nax ) ) { - astError( AST__NCPIN, "astResolvePoints(%s): Bad number of coordinate " - "values (%d) in input %s.", status, astGetClass( this ), ncoord_in, - astGetClass( in ) ); - astError( AST__NCPIN, "The %s given requires %d coordinate value(s) for " - "each input point.", status, astGetClass( this ), nax ); - } - -/* If still OK, and a non-NULL pointer has been given for the output PointSet, - then obtain the number of points and number of coordinates per point for - this PointSet. */ - if ( astOK && out ) { - npoint_out = astGetNpoint( out ); - ncoord_out = astGetNcoord( out ); - -/* Check that the dimensions of this PointSet are adequate to accommodate the - output coordinate values and report an error if they are not. */ - if ( astOK ) { - if ( npoint_out < npoint ) { - astError( AST__NOPTS, "astResolvePoints(%s): Too few points (%d) in " - "output %s.", status, astGetClass( this ), npoint_out, - astGetClass( out ) ); - astError( AST__NOPTS, "The %s needs space to hold %d transformed " - "point(s).", status, astGetClass( this ), npoint ); - } else if ( ncoord_out < 2 ) { - astError( AST__NOCTS, "astResolvePoints(%s): Too few coordinate " - "values per point (%d) in output %s.", status, - astGetClass( this ), ncoord_out, astGetClass( out ) ); - astError( AST__NOCTS, "The %s supplied needs space to store 2 " - "coordinate value(s) per transformed point.", status, - astGetClass( this ) ); - } - } - } - -/* If all the validation stages are passed successfully, and a NULL output - pointer was given, then create a new PointSet to encapsulate the output - coordinate data. */ - if ( astOK ) { - if ( !out ) { - result = astPointSet( npoint, 2, "", status ); - -/* Otherwise, use the PointSet supplied. */ - } else { - result = out; - } - } - -/* Store points to the first two axis arrays in the returned PointSet. */ - ptr_out = astGetPoints( result ); - if( astOK ) { - d1 = ptr_out[ 0 ]; - d2 = ptr_out[ 1 ]; - } - -/* Obtain a pointer to the CmpFrame's axis permutation array. This array - holds the original axis index for each current Frame axis index. */ - perm = astGetPerm( this ); - -/* Temporarily permute the coordinates within the supplied PointSet back - in to the axis order which existed when the CmpFrame was created. */ - astPermPoints( in, 0, perm ); - -/* Extract the axis values relevant to each of the two sub-Frames from the - point1 and point2 arrays, at the same time undoing any axis permutation - applied to the CmpFrame as a whole. */ - p1 = astMalloc( sizeof( double )*( size_t )nax ); - p2 = astMalloc( sizeof( double )*( size_t )nax ); - if( astOK ) { - for( axis = 0; axis < nax; axis++ ) { - p1[ perm[ axis ] ] = point1[ axis ]; - p2[ perm[ axis ] ] = point2[ axis ]; - } - } - -/* Project the first two input points into the two component Frames and - determine the length of the basis vector in each Frame. */ - b1 = astDistance( this->frame1, p1, p2 ); - b2 = astDistance( this->frame2, p1 + naxes1, p2 + naxes1 ); - -/* If either of these distances is bad or if both are zero, then fill the - returned PointSet with bad values. */ - if( b1 == AST__BAD || b2 == AST__BAD || ( b1 == 0.0 && b2 == 0.0 ) ) { - for( ipoint = 0; ipoint < npoint; ipoint++, d1++, d2++ ) { - *d1 = AST__BAD; - *d2 = AST__BAD; - } - -/* Otherwise we continue to calculate the resolved components */ - } else if( astOK ){ - -/* Calculate the total distance between the two points. */ - b = sqrt( b1*b1 + b2*b2 ); - -/* Create PointSets holding the input values which refer to each of the - two component Frames. */ - in1 = astPointSet( npoint, naxes1, "", status ); - in2 = astPointSet( npoint, naxes2, "", status ); - -/* Associated the appropriate subset of the data in the supplied input - PointSet with each of these two PointSets. */ - astSetSubPoints( in, 0, 0, in1 ); - astSetSubPoints( in, 0, naxes1, in2 ); - -/* Invoke the astResolvePoints method on each of the sub-Frames. These - invocations create two new PointSets containing the output values. */ - out1 = astResolvePoints( this->frame1, p1, p2, in1, NULL ); - out2 = astResolvePoints( this->frame2, p1 + naxes1, p2 + naxes1, in2, NULL ); - -/* Get pointers to the axis values in these pointsets. */ - ptr_out1 = astGetPoints( out1 ); - ptr_out2 = astGetPoints( out2 ); - -/* More work space */ - p3 = astMalloc( sizeof( double )*( size_t )nax ); - p4 = astMalloc( sizeof( double )*( size_t )nax ); - -/* Get pointers to the input axis values (these are still permuted to - undo any axis permutation applied to the CmpFrame). */ - ptr_in = astGetPoints( in ); - -/* Check pointers can be used safely. */ - if( astOK ) { - -/* Get pointers to the parallel (d1) and perpendiclar (d2) components - within the two sub-Frames (_1 and _2). */ - d1_1 = ptr_out1[ 0 ]; - d2_1 = ptr_out1[ 1 ]; - d1_2 = ptr_out2[ 0 ]; - d2_2 = ptr_out2[ 1 ]; - -/* Loop round each supplied vector. */ - for( ipoint = 0; ipoint < npoint; ipoint++, d1++, d2++, - d1_1++, d2_1++, - d1_2++, d2_2++ ) { - -/* We can tolerate a bad parallel distance within a sub-Frame if the - basis vector has zero length in the sub-Frame, because the bad - parallel distance will have zero weight in the calculation. Set such - bad parallel distanced arbitrarily to zero. */ - if( *d1_1 == AST__BAD && b1 == 0.0 ) *d1_1 = 0.0; - if( *d1_2 == AST__BAD && b2 == 0.0 ) *d1_2 = 0.0; - -/* Combine the parallel distances for the individual Frames into a single - parallel distance for the entire CmpFrame. */ - if( *d1_1 != AST__BAD && *d1_2 != AST__BAD ) { - *d1 = ( b1*(*d1_1) + b2*(*d1_2) )/b; - -/* Offset this distance away from point 1 towards point 2 to get point 4. */ - astOffset( this, p1, p2, *d1, p4 ); - -/* Now find the perpendicular distance (the distance between point4 and - point3). */ - for( axis = 0; axis < nax; axis++ ) p3[ axis ] = ptr_in[ axis ][ ipoint ]; - *d2 = astDistance( this, p4, p3 ); - - } else { - *d1 = AST__BAD; - *d2 = AST__BAD; - } - } - } - -/* Free resources */ - in1 = astAnnul( in1 ); - in2 = astAnnul( in2 ); - out1 = astAnnul( out1 ); - out2 = astAnnul( out2 ); - p3 = astFree( p3 ); - p4 = astFree( p4 ); - } - -/* Free resources */ - p1 = astFree( p1 ); - p2 = astFree( p2 ); - -/* Re-instate the original ordering of the coordinates within the - supplied PointSet. */ - astPermPoints( in, 1, perm ); - -/* Annul the returned PointSet if an error occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return a pointer to the output PointSet. */ - return result; -} - -static void SetActiveUnit( AstFrame *this_frame, int value, int *status ){ -/* -* Name: -* SetActiveUnit - -* Purpose: -* Specify how the Unit attribute should be used. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void SetActiveUnit( AstFrame *this, int value, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astSetActiveUnit method -* inherited from the Frame class). - -* Description: -* This function sets the current value of the ActiveUnit flag for a -* CmpFrame, which controls how the Frame behaves when it is used (by -* astFindFrame) as a template to match another (target) Frame, or is -* used as the "to" Frame by astConvert. It determines if the Mapping -* between the template and target Frames should take differences in -* axis units into account. - -* Parameters: -* this -* Pointer to the CmpFrame. -* value -* The new value to use. -* status -* Pointer to the inherited status variable. -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Invoke the parent method to set the ActiveUnitFlag for the CmpFrame, - then set the same value for the component Frames. */ - (*parent_setactiveunit)( this_frame, value, status ); - astSetActiveUnit( ((AstCmpFrame *)this_frame)->frame1, value ); - astSetActiveUnit( ((AstCmpFrame *)this_frame)->frame2, value ); -} - -static void SetFrameFlags( AstFrame *this_frame, int value, int *status ){ -/* -* Name: -* SetFrameFlags - -* Purpose: -* Set flags that control current Frame behaviour. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void SetFrameFlags( AstFrame *this, int value, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astSetFrameFlags method -* inherited from the Frame class). - -* Description: -* This function sets values for the bit mask of flags that control -* how the CmpFrame behaves. It ensures that both component Frames use -* the the same bitmask as the parent CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* value -* The new value to use. -* status -* Pointer to the inherited status variable. -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Invoke the parent method to set the FrameFlags for the CmpFrame, - then set the same value for the component Frames. */ - (*parent_setframeflags)( this_frame, value, status ); - astSetFrameFlags( ((AstCmpFrame *)this_frame)->frame1, value ); - astSetFrameFlags( ((AstCmpFrame *)this_frame)->frame2, value ); -} - -static int GetActiveUnit( AstFrame *this_frame, int *status ){ -/* -* Name: -* GetActiveUnit - -* Purpose: -* Determines how the Unit attribute will be used. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int GetActiveUnit( AstFrame *this_frame, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astGetActiveUnit method -* inherited from the Frame class). - -* Description: -* This function returns the current value of the ActiveUnit flag for a -* CmpFrame. See the description of the astSetActiveUnit function -* for a description of the ActiveUnit flag. - -* Parameters: -* this -* Pointer to the CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The current value of the ActiveUnit flag. - -*/ - -/* Local Variables; */ - int result; /* The ActiveUnit flag for the CmpFrame */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* If the ActiveUnit value has been set for the CmpFrame use the parent - implementation to get its value. */ - if( astTestActiveUnit( this_frame ) ) { - result = (*parent_getactiveunit)( this_frame, status ); - -/* Otherwise, the default is determined by the component Frames. If both - components have active units, the default for the CmpFrame is "on" */ - } else { - result = astGetActiveUnit( ((AstCmpFrame *)this_frame)->frame1 ) || - astGetActiveUnit( ((AstCmpFrame *)this_frame)->frame2 ); - } - -/* Return the result */ - return result; -} - -static void SetAttrib( AstObject *this_object, const char *setting, int *status ) { -/* -* Name: -* SetAttrib - -* Purpose: -* Set an attribute value for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void SetAttrib( AstObject *this, const char *setting, int *status ) - -* Class Membership: -* CmpFrame member function (extends the astSetAttrib method inherited from -* the Mapping class). - -* Description: -* This function assigns an attribute value for a CmpFrame, 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 CmpFrame. -* setting -* Pointer to a null terminated string specifying the new attribute -* value. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* void - -* Notes: -* This protected method is intended to be invoked by the Object astSet -* method and makes additional attributes accessible to it. -*/ - -#define BUF_LEN 1024 - -/* Local Vaiables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - AstFrame *pfrm; /* Pointer to primary Frame containing axis */ - char buf1[BUF_LEN]; /* For for un-indexed attribute name */ - char buf2[BUF_LEN]; /* For for indexed attribute name */ - int axis; /* Supplied (1-base) axis index */ - int len; /* Length of setting string */ - int nc; /* Number of characters read by astSscanf */ - int oldrep; /* Original error reporting state */ - int paxis; /* Index of primary Frame axis */ - int ok; /* Have we accessed the attribute succesfully? */ - int value; /* Offset to start fo value string */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_object; - -/* Obtain the length of the setting string. */ - len = strlen( setting ); - -/* Indicate we have not yet acessed the attribute succesfully. */ - ok = 0; - -/* First check the supplied attribute name against each of the attribute - names defined by this class. In fact there is nothing to do here - since the CmpFrame class currently defines no extra attributes, but - this may change in the future. */ - if( 0 ) { - - - -/* If the attribute is not a CmpFrame specific attribute... */ - } else if( astOK ) { - -/* We want to allow easy access to the attributes of the component Frames. - That is, we do not want it to be necessary to extract a Frame from - its parent CmpFrame in order to access its attributes. For this reason - we first temporarily switch off error reporting so that if an attempt - to access the attribute fails, we can try a different approach. */ - oldrep = astReporting( 0 ); - -/* Our first attempt is to see if the attribute is recognised by the parent - class (Frame). */ - (*parent_setattrib)( this_object, setting, status ); - -/* Indicate success. */ - if( astOK ) { - ok = 1; - -/* Otherwise, clear the error condition so that we can try a different - approach. */ - } else { - astClearStatus; - -/* If the attribute is qualified by an axis index, try accessing it as an - attribute of the primary Frame containing the specified index. */ - if ( nc = 0, - ( 2 == astSscanf( setting, "%[^(=](%d)= %n%*s %n", buf1, &axis, - &value, &nc ) ) && ( nc >= len ) ) { - -/* Find the primary Frame containing the specified axis. */ - astPrimaryFrame( this, axis - 1, &pfrm, &paxis ); - if( astOK ) { - -/* astPrimaryFrame returns the original - unpermuted - axis index within - the primary Frame. So we need to take into account any axis permutation - which has been applied to the primary Frame when forming the attribute name - to use below. Find the permuted (external) axis index which corresponds to - the internal (unpermuted) axis index "paxis". */ - paxis = astValidateAxis( pfrm, paxis, 0, "astSet" ); - -/* Create a new setting with the same name but with the axis index - appropriate to the primary Frame. */ - nc = sprintf( buf2, "%s(%d)=%s", buf1, paxis + 1, - setting+value ); - if( nc < BUF_LEN ) { - -/* Attempt to access the attribute. */ - astSetAttrib( pfrm, buf2 ); - -/* Indicate success. */ - if( astOK ) { - ok = 1; - -/* Otherwise clear the status value, and try again without any axis index. */ - } else { - astClearStatus; - sprintf( buf2, "%s=%s", buf1, setting+value ); - astSetAttrib( pfrm, buf2 ); - -/* Indicate success, or clear the status value. */ - if( astOK ) { - ok = 1; - } else { - astClearStatus; - } - } - -/* Buffer overflow */ - } else if( astOK ) { - astError( AST__INTER, "SetAttrib(CmpFrame): Buffer " - "over-flow (internal AST programming error).", - status ); - } - -/* Free the primary frame pointer. */ - pfrm = astAnnul( pfrm ); - } - -/* If the attribute is not qualified by an axis index, try accessing it - using the primary Frame of each axis in turn. */ - } else { - -/* Loop round all axes attribute. */ - for( axis = 0; axis < astGetNaxes( this ); axis++ ) { - -/* Get the primary Frame containing this axis. */ - astPrimaryFrame( this, axis, &pfrm, &paxis ); - -/* Attempt to access the attribute as an attribute of the primary Frame. */ - astSetAttrib( pfrm, setting ); - -/* Free the primary Frame pointer. */ - pfrm = astAnnul( pfrm ); - -/* Indicate success, or clear the status value. */ - if( astOK ) { - ok = 1; - } else { - astClearStatus; - } - } - } - } - -/* Re-instate the original error reporting state. */ - astReporting( oldrep ); - - } - -/* Report an error if the attribute could not be accessed. */ - if( !ok && astOK ) { - astError( AST__BADAT, "astSet: The attribute setting \"%s\" is invalid " - "for the given %s.", status, setting, astGetClass( this ) ); - } - -#undef BUF_LEN -} - -static void SetAxis( AstFrame *this_frame, int axis, AstAxis *newaxis, int *status ) { -/* -* Name: -* SetAxis - -* Purpose: -* Set a new Axis for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void astSetAxis( AstFrame *this, int axis, AstAxis *newaxis, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astSetAxis method -* inherited from the Frame class). - -* Description: -* This function allows a new Axis object to be associated with one -* of the axes of a CmpFrame, replacing the previous one. Each Axis -* object contains a description of the quantity represented along -* one of the CmpFrame's axes, so this function allows this -* description to be exchanged for another one. - -* Parameters: -* this -* Pointer to the CmpFrame. -* axis -* The index (zero-based) of the CmpFrame axis whose associated -* Axis object is to be replaced. -* newaxis -* Pointer to the new Axis object. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - int naxes1; /* Number of axes in frame1 */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate and permute the axis index supplied. */ - axis = astValidateAxis( this, axis, 1, "astSetAxis" ); - -/* Determine the number of axes in the first component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - if ( astOK ) { - -/* Decide which Frame contains the axis and invoke its astSetAxis - method to set the new Axis. */ - if ( axis < naxes1 ) { - astSetAxis( this->frame1, axis, newaxis ); - } else { - astSetAxis( this->frame2, axis - naxes1, newaxis ); - } - } -} - -static void SetDut1( AstFrame *this_frame, double val, int *status ) { -/* -* Name: -* SetDut1 - -* Purpose: -* Set the value of the Dut1 attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void SetDut1( AstFrame *this, double val, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astSetDut1 method -* inherited from the Frame class). - -* Description: -* This function sets the Dut1 value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* val -* New Dut1 value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to set the CmpFrame Dut1 value. */ - (*parent_setdut1)( this_frame, val, status ); - -/* Now set the Dut1 attribute in the two component Frames. */ - astSetDut1( this->frame1, val ); - astSetDut1( this->frame2, val ); -} - -static void SetEpoch( AstFrame *this_frame, double val, int *status ) { -/* -* Name: -* SetEpoch - -* Purpose: -* Set the value of the Epoch attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void SetEpoch( AstFrame *this, double val, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astSetEpoch method -* inherited from the Frame class). - -* Description: -* This function sets the Epoch value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* val -* New Epoch value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to set the CmpFrame epoch. */ - (*parent_setepoch)( this_frame, val, status ); - -/* Now set the Epoch attribute in the two component Frames. */ - astSetEpoch( this->frame1, val ); - astSetEpoch( this->frame2, val ); -} - -static void SetObsAlt( AstFrame *this_frame, double val, int *status ) { -/* -* Name: -* SetObsAlt - -* Purpose: -* Set the value of the ObsAlt attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void SetObsAlt( AstFrame *this, double val, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astSetObsAlt method -* inherited from the Frame class). - -* Description: -* This function sets the ObsAlt value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* val -* New ObsAlt value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to set the CmpFrame ObsAlt. */ - (*parent_setobsalt)( this_frame, val, status ); - -/* Now set the ObsAlt attribute in the two component Frames. */ - astSetObsAlt( this->frame1, val ); - astSetObsAlt( this->frame2, val ); -} - -static void SetObsLat( AstFrame *this_frame, double val, int *status ) { -/* -* Name: -* SetObsLat - -* Purpose: -* Set the value of the ObsLat attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void SetObsLat( AstFrame *this, double val, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astSetObsLat method -* inherited from the Frame class). - -* Description: -* This function sets the ObsLat value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* val -* New ObsLat value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to set the CmpFrame ObsLat. */ - (*parent_setobslat)( this_frame, val, status ); - -/* Now set the ObsLat attribute in the two component Frames. */ - astSetObsLat( this->frame1, val ); - astSetObsLat( this->frame2, val ); -} - -static void SetObsLon( AstFrame *this_frame, double val, int *status ) { -/* -* Name: -* SetObsLon - -* Purpose: -* Set the value of the ObsLon attribute for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* void SetObsLon( AstFrame *this, double val, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astSetObsLon method -* inherited from the Frame class). - -* Description: -* This function sets the ObsLon value in the component Frames as -* well as this CmpFrame. - -* Parameters: -* this -* Pointer to the CmpFrame. -* val -* New ObsLon value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Invoke the parent method to set the CmpFrame ObsLon. */ - (*parent_setobslon)( this_frame, val, status ); - -/* Now set the ObsLon attribute in the two component Frames. */ - astSetObsLon( this->frame1, val ); - astSetObsLon( this->frame2, val ); -} - -static AstMapping *Simplify( AstMapping *this_mapping, int *status ) { -/* -* Name: -* Simplify - -* Purpose: -* Simplify the Mapping represented by a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstMapping *Simplify( AstMapping *this, int *status ) - -* Class Membership: -* CmpFrame method (over-rides the astSimplify method inherited -* from the Frame class). - -* Description: -* This function simplifies the Mapping represented by a CmpFrame, -* by using the astSimplify method on each of the component Frames and -* combining the resulting Mappings together. - -* Parameters: -* this -* Pointer to the original CmpFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A new pointer to the simplified CmpFrame. - -* Notes: -* - A NULL pointer value will be returned if this function is -* invoked with the AST error status set, or if it should fail for -* any reason. -*/ - -/* Local Variables: */ - AstCmpFrame *new; /* Pointer to new CmpFrame structure */ - AstCmpFrame *this; /* Pointer to original CmpFrame structure */ - AstMapping *map1; /* Intermediate Mapping */ - AstMapping *map2; /* Intermediate Mapping */ - AstMapping *result; /* Result pointer to return */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_mapping; - -/* Simplify each of the component Frames. */ - map1 = astSimplify( this->frame1 ); - map2 = astSimplify( this->frame2 ); - -/* Did any usable simplification occur? */ - if( astIsAFrame( map1 ) && astIsAFrame( map2 ) && - ( map1 != (AstMapping *) this->frame1 || - map2 != (AstMapping *) this->frame2 ) ) { - -/* Make a copy of the supplied CmpFrame. */ - new = astCopy( this ); - result = (AstMapping *) new; - -/* Replace the two component Frames with the simplified Frames. */ - (void) astAnnul( new->frame1 ); - (void) astAnnul( new->frame2 ); - new->frame1 = (AstFrame *) map1; - new->frame2 = (AstFrame *) map2; - -/* If no simplication took place, annul the Mapping pointers and return a - clone of the supplied pointer. */ - } else { - map1 = astAnnul( map1 ); - map2 = astAnnul( map2 ); - result= astClone( this ); - } - -/* If an error occurred, annul the returned pointer. */ - if ( !astOK ) result = astAnnul( result ); - -/* Return the result. */ - return result; -} - -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 "cmpframe.h" -* AstSystemType SystemCode( AstFrame *this, const char *system, int *status ) - -* Class Membership: -* CmpFrame 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 coordinate system into a CmpFrame -* 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 coordinate system. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The System type code. - -* Notes: -* - A value of AST__BADSYSTEM is returned if the coordinate -* system description was not recognised. This does not produce an -* error. -* - A value of AST__BADSYSTEM is also returned if this function -* is invoked with the global error status set or if it should fail -* for any reason. -*/ - -/* Local Variables: */ - AstSystemType result; /* Result value to return */ - -/* Initialise. */ - result = AST__BADSYSTEM; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Match the "system" string against each possibility and assign the - result. The CmpFrame class only supports a single system "Compound". */ - if ( astChrMatch( "Compound", system ) ) { - result = AST__COMP; - } - -/* Return the result. */ - return result; -} - -static const char *SystemString( AstFrame *this, AstSystemType system, int *status ) { -/* -* Name: -* SystemString - -* Purpose: -* Convert a coordinate system type code into a string. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* const char *SystemString( AstFrame *this, AstSystemType system, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astSystemString method -* inherited from the Frame class). - -* Description: -* This function converts a CmpFrame coordinate system type code -* (System attribute value) into a string suitable for use as an -* external representation of the coordinate system type. - -* Parameters: -* this -* The Frame. -* system -* The coordinate system type code. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to a constant null-terminated string containing the -* textual equivalent of the type code supplied. - -* 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 */ - int following; /* Associate extra axis and following axis? */ - int i1; /* Count of axes obtained from frame1 */ - int i2; /* Count of axes obtained from frame2 */ - int match; /* Result value to return */ - int n1; /* Number of axes obtained from frame1 */ - int n2; /* Number of axes obtained from frame2 */ - int naxes1; /* Number of axes in frame1 */ - int naxes2; /* Number of axes in frame2 */ - int naxes; /* Number of axes in target */ - int result_axis; /* Result axis index */ - int target_axis; /* Target axis index */ - -/* 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 CmpFrame structure. */ - target = (AstCmpFrame *) target_frame; - -/* Obtain the number of axes in the target CmpFrame and in each of its - component Frames. */ - naxes = astGetNaxes( target ); - naxes1 = astGetNaxes( target->frame1 ); - naxes2 = astGetNaxes( target->frame2 ); - -/* Iinitialise variables to avoid compiler warnings. */ - template_axes1 = NULL; - template_axes2 = NULL; - n1 = 0; - n2 = 0; - -/* Obtain the axis permutation array for the target CmpFrame. */ - perm = astGetPerm( target ); - -/* Determine how any "extra" axes should be associated with existing - axes (i.e. whether to associate with the preceding or following - axis). */ - following = astGetMatchEnd( target ); - -/* Split selected axes into two groups. */ -/* ------------------------------------ */ -/* Allocate a workspace array to hold the choice of component Frame - for each selected target axis. */ - frame_choice = astMalloc( sizeof( int ) * (size_t) result_naxes ); - -/* Obtain an array of flags indicating whether each selected target - axis should be obtained from the first or second component - Frame. */ - PartitionSelection( result_naxes, target_axes, perm, naxes1, naxes2, - frame_choice, following, status ); - -/* 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 - with the appropriate axes of that Frame. */ - } else { - inperm_suff[ n1 + i2 ] = result_axis; - outperm_suff[ result_axis ] = n1 + i2; - i2++; - } - } - -/* Combine the Mappings supplied by the two component Frames in - parallel. */ - sub_map = (AstMapping *) astCmpMap( sub_map1, sub_map2, 0, "", status ); - -/* Create the PermMaps which are to be used as a prefix and a suffix. */ - permmap_pref = - (AstMapping *) astPermMap( naxes, inperm_pref, - naxes, outperm_pref, NULL, "", status ); - permmap_suff = - (AstMapping *) astPermMap( result_naxes, inperm_suff, - result_naxes, outperm_suff, - NULL, "", status ); - -/* Add the prefix and suffix PermMaps. */ - tmp_map = (AstMapping *) astCmpMap( permmap_pref, sub_map, - 1, "", status ); - *map = (AstMapping *) astCmpMap( tmp_map, permmap_suff, 1, "", status ); - -/* Annul the Mapping pointers that are no longer required. */ - sub_map = astAnnul( sub_map ); - permmap_pref = astAnnul( permmap_pref ); - permmap_suff = astAnnul( permmap_suff ); - tmp_map = astAnnul( tmp_map ); - -/* Create the result CmpFrame by combining the two component result - Frames and permuting the resulting axes into the required order. */ - *result = (AstFrame *) astCmpFrame( sub_result1, sub_result2, - "", status ); - astPermAxes( *result, outperm_suff ); - -/* ADDED BY DSB (5-FEB-2001). Without this, properties of the target frame - (most importantly, Domain) are not transferred to the result frame. - This results in Frames not matching which should match. - =================================================================== */ - -/* If the result CmpFrame includes all the axes of the target CmpFrame, - then it should inherit any Domain and Title attributes set in the target - CmpFrame. */ - if( result_naxes == naxes ) { - - if( astTestDomain( target ) ) { - astSetDomain( *result, astGetDomain( target ) ); - } - - if( astTestTitle( target ) ) { - astSetTitle( *result, astGetTitle( target ) ); - } - } - -/* End of DSB insertion (5/2/01). - =================================================================== */ - } - -/* Free the temporary permutation arrays. */ - inperm_pref = astFree( inperm_pref ); - inperm_suff = astFree( inperm_suff ); - outperm_pref = astFree( outperm_pref ); - outperm_suff = astFree( outperm_suff ); - } - -/* Annul the Mapping and Frame pointers obtained from each component - Frame. */ - if( sub_map1 ) sub_map1 = astAnnul( sub_map1 ); - if( sub_map2 ) sub_map2 = astAnnul( sub_map2 ); - if( sub_result1 ) sub_result1 = astAnnul( sub_result1 ); - if( sub_result2 ) sub_result2 = astAnnul( sub_result2 ); - } - } - -/* Free the workspace used to store the choice of component Frame and the - axis indices for each component Frame. */ - frame_choice = astFree( frame_choice ); - target_axes1 = astFree( target_axes1 ); - target_axes2 = astFree( target_axes2 ); - -/* If necessary, also free the memory used for the template axis - indices. */ - if ( template ) { - template_axes1 = astFree( template_axes1 ); - template_axes2 = astFree( template_axes2 ); - } - -/* If an error occurred, clean up by annulling the result pointers and - returning appropriate null values. */ - if ( !astOK ) { - *map = astAnnul( *map ); - *result = astAnnul( *result ); - match = 0; - } - -/* Return the result. */ - return match; -} - -static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* TestAttrib - -* Purpose: -* Test if a specified attribute value is set for a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int TestAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astTestAttrib protected -* method inherited from the Frame class). - -* Description: -* This function returns a boolean result (0 or 1) to indicate whether -* a value has been set for one of a CmpFrame's attributes. - -* Parameters: -* this -* Pointer to the CmpFrame. -* attrib -* Pointer to a null terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if a value has been set, otherwise zero. - -* Notes: -* - This function uses one-based axis numbering so that it is -* suitable for external (public) use. -* - A value of zero will be returned if this function is invoked -* with the global status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - AstFrame *pfrm; /* Pointer to primary Frame containing axis */ - char buf1[80]; /* For for un-indexed attribute name */ - char buf2[80]; /* For for indexed attribute name */ - int axis; /* Supplied (1-base) axis index */ - int len; /* Length of attrib string */ - int nc; /* Length of string used so far */ - int oldrep; /* Original error reporting state */ - int paxis; /* Index of primary Frame axis */ - int result; /* Result value to return */ - int ok; /* Has the attribute been accessed succesfully? */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_object; - -/* Obtain the length of the attrib string. */ - len = strlen( attrib ); - -/* Indicate we have not yet acessed the attribute succesfully. */ - ok = 0; - -/* First check the supplied attribute name against each of the attribute - names defined by this class. In fact there is nothing to do here - since the CmpFrame class currently defines no extra attributes, but - this may change in the future. */ - if( 0 ) { - - - -/* If the attribute is not a CmpFrame specific attribute... */ - } else if( astOK ) { - -/* We want to allow easy access to the attributes of the component Frames. - That is, we do not want it to be necessary to extract a Frame from - its parent CmpFrame in order to access its attributes. For this reason - we first temporarily switch off error reporting so that if an attempt - to access the attribute fails, we can try a different approach. */ - oldrep = astReporting( 0 ); - -/* Our first attempt is to see if the attribute is recognised by the parent - class (Frame). */ - result = (*parent_testattrib)( this_object, attrib, status ); - -/* Indicate success. */ - if( astOK ) { - ok = 1; - -/* Otherwise, clear the error condition so that we can try a different - approach. */ - } else { - astClearStatus; - -/* If the attribute is qualified by an axis index, try accessing it as an - attribute of the primary Frame containing the specified index. */ - if ( nc = 0, - ( 2 == astSscanf( attrib, "%[^(](%d)%n", buf1, &axis, &nc ) ) - && ( nc >= len ) ) { - -/* Find the primary Frame containing the specified axis. */ - astPrimaryFrame( this, axis - 1, &pfrm, &paxis ); - if( astOK ) { - -/* astPrimaryFrame returns the original - unpermuted - axis index within - the primary Frame. So we need to take into account any axis permutation - which has been applied to the primary Frame when forming the attribute name - to use below. Find the permuted (external) axis index which corresponds to - the internal (unpermuted) axis index "paxis". */ - paxis = astValidateAxis( pfrm, paxis, 0, "astTest" ); - -/* Create a new attribute with the same name but with the axis index - appropriate to the primary Frame. */ - sprintf( buf2, "%s(%d)", buf1, paxis + 1 ); - -/* Attempt to access the attribute. */ - result = astTestAttrib( pfrm, buf2 ); - -/* Indicate success. */ - if( astOK ) { - ok = 1; - -/* Otherwise clear the status value, and try again without any axis index. */ - } else { - astClearStatus; - result = astTestAttrib( pfrm, buf1 ); - -/* Indicate success, or clear the status value. */ - if( astOK ) { - ok = 1; - } else { - astClearStatus; - } - } - -/* Free the primary frame pointer. */ - pfrm = astAnnul( pfrm ); - } - -/* If the attribute is not qualified by an axis index, try accessing it - using the primary Frame of each axis in turn. */ - } else { - -/* Loop round all axes, until one is found which defines the specified - attribute. */ - for( axis = 0; axis < astGetNaxes( this ) && !ok; axis++ ) { - -/* Get the primary Frame containing this axis. */ - astPrimaryFrame( this, axis, &pfrm, &paxis ); - -/* Attempt to access the attribute as an attribute of the primary Frame. */ - result = astTestAttrib( pfrm, attrib ); - -/* Indicate success, or clear the status value. */ - if( astOK ) { - ok = 1; - } else { - astClearStatus; - } - -/* Free the primary Frame pointer. */ - pfrm = astAnnul( pfrm ); - - } - } - } - -/* Re-instate the original error reporting state. */ - astReporting( oldrep ); - - } - -/* Report an error if the attribute could not be accessed. */ - if( !ok && astOK ) { - astError( AST__BADAT, "astTest: The %s given does not have an attribute " - "called \"%s\".", status, astGetClass( this ), attrib ); - } - -/* Return the result. */ - return result; - -} - -static AstPointSet *Transform( AstMapping *this_mapping, AstPointSet *in, - int forward, AstPointSet *out, int *status ) { -/* -* Name: -* Transform - -* Purpose: -* Transform a set of points. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstPointSet *Transform( AstMapping *this, AstPointSet *in, -* int forward, AstPointSet *out, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astTransform method -* inherited from the Frame class). - -* Description: -* This function takes a CmpFrame and a set of points encapsulated -* in a PointSet, and applies the coordinate transformation equivalent -* to the CmpFrame (this will normally be a UnitMap but may not be if -* the CmpFrame contains any Regions). - -* Parameters: -* this -* Pointer to the CmpFrame. -* in -* Pointer to the PointSet holding the input coordinate data. -* forward -* A non-zero value indicates that the forward coordinate transformation -* should be applied, while a zero value requests the inverse -* transformation. -* out -* Pointer to a PointSet which will hold the transformed (output) -* coordinate values. A NULL value may also be given, in which case a -* new PointSet will be created by this function. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to the output (possibly new) PointSet. - -* Notes: -* - The number of coordinate values per point in the input -* PointSet must match the number of axes in the CmpFrame. -* - If an output PointSet is supplied, it must have space for -* sufficient number of points and coordinate values per point to -* accommodate the result (e.g. the number of CmpFrame axes). Any -* excess space will be ignored. -* - A null pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to original CmpFrame structure */ - AstCmpMap *map2; /* Intermediate Mapping */ - AstCmpMap *map; /* Equivalent Mapping */ - AstPermMap *pmap; /* Intermediate PermMap */ - AstPointSet *result; /* Pointer value to return */ - const int *inperm; /* Pointer to axis permutation array */ - int *outperm; /* Pointer to inverse axis permutation array */ - int i; /* External axis index */ - int naxes; /* Number of axes in CmpFrame */ - int perm; /* Is there an axis permutation to undo? */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_mapping; - -/* Form a parallel CmpMap from the two component Frames. */ - map = astCmpMap( this->frame1, this->frame2, 0, "", status ); - -/* The above CmpMap does not take into account any axis permutation - which has been applied to the CmpFrame as a whole (as opposed to axis - permutations applied to the individual component Frames, which are taken - care of by the Transform methods of the individual Frames). Therefore - we need to modify the Mapping by adding a PermMap at the start which - converts from external axis numbering to internal axis numbering, and a - corresponding PermMap at the end which converts from internal to external - axis numbering. Obtain the number of axes in the CmpFrame */ - naxes = astGetNaxes( this ); - -/* Obtain a pointer to the CmpFrame's axis permutation array. This - contains internal axis numbers and is indexed by external axis number. */ - inperm = astGetPerm( this ); - -/* Check if there is any axis permutation to be performed. */ - perm = 0; - for( i = 0; i < naxes; i++ ) { - if( inperm[ i ] != i ) { - perm = 1; - break; - } - } - -/* If so, create an array holding the inverse permutation - one which - contains external axis numbers and is indexed by internal axis number. */ - if( perm ) { - outperm = astMalloc( sizeof( int )*(size_t) naxes ); - if( astOK ) for( i = 0; i < naxes; i++ ) outperm[ inperm[ i ] ] = i; - -/* Create a PermMap from these permutation arrays. The forward - transformation maps from external axis indices to internal axis - indices. */ - pmap = astPermMap( naxes, inperm, naxes, outperm, NULL, "", status ); - outperm = astFree( outperm ); - -/* Combine this PermMap with the CmpMap created above, adding it in the - forward direction at the start and in the inverse direction at the end. */ - map2 = astCmpMap( pmap, map, 1, "", status ); - map = astAnnul( map ); - astInvert( pmap ); - map = astCmpMap( map2, pmap, 1, "", status ); - map2 = astAnnul( map2 ); - pmap = astAnnul( pmap ); - - } - -/* Apply the Mapping to the input PointSet. */ - result = astTransform( map, in, forward, out ); - -/* Annul the Mapping pointer. */ - map = astAnnul( map ); - -/* If an error has occurred and a new PointSet may have been created, then - clean up by annulling it. In any case, ensure that a NULL result is - returned.*/ - if ( !astOK ) { - if ( !out ) result = astAnnul( result ); - result = NULL; - } - -/* Return a pointer to the output PointSet. */ - return result; -} - -static int Unformat( AstFrame *this_frame, int axis, const char *string, - double *value, int *status ) { -/* -* Name: -* Unformat - -* Purpose: -* Read a formatted coordinate value for a CmpFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* int Unformat( AstFrame *this, int axis, const char *string, -* double *value, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the public astUnformat -* method inherited from the Frame class). - -* Description: -* This function reads a formatted coordinate value for a CmpFrame -* axis (supplied as a string) and returns the equivalent numerical -* value as a double. It also returns the number of characters read -* from the string. - -* Parameters: -* this -* Pointer to the CmpFrame. -* axis -* The number of the CmpFrame axis for which the coordinate -* value is to be read (axis numbering starts at zero for the -* first axis). -* string -* Pointer to a constant null-terminated string containing the -* formatted coordinate value. -* value -* Pointer to a double in which the coordinate value read will be -* returned. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The number of characters read from the string to obtain the -* coordinate value. - -* Notes: -* - Any white space at the beginning of the string will be -* skipped, as also will any trailing white space following the -* coordinate value read. The function's return value will reflect -* this. -* - A function value of zero (and no coordinate value) will be -* returned, without error, if the string supplied does not contain -* a suitably formatted value. -* - The string "<bad>" is recognised as a special case and will -* generate the value AST__BAD, without error. The test for this -* string is case-insensitive and permits embedded white space. -* - A function result of zero will be returned and no coordinate -* value will be returned via the "value" pointer if this function -* is invoked with the global error status set, or if it should -* fail for any reason. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - AstFrame *frame; /* Pointer to Frame containing axis */ - double coord; /* Coordinate value read */ - int naxes1; /* Number of axes in frame1 */ - int nc; /* Number of characters read */ - int set; /* Digits attribute set? */ - -/* Initialise. */ - nc = 0; - -/* Check the global error status. */ - if ( !astOK ) return nc; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_frame; - -/* Validate and permute the axis index supplied. */ - axis = astValidateAxis( this, axis, 1, "astUnformat" ); - -/* Determine the number of axes in the first component Frame. */ - naxes1 = astGetNaxes( this->frame1 ); - if ( astOK ) { - -/* Decide which component Frame contains the axis and adjust the axis - index if necessary. */ - frame = ( axis < naxes1 ) ? this->frame1 : this->frame2; - axis = ( axis < naxes1 ) ? axis : axis - naxes1; - -/* Since the component Frame is "managed" by the enclosing CmpFrame, - we next test if any Frame attributes which may affect the result - are undefined (i.e. have not been explicitly set). If so, we - over-ride them, giving them temporary values dictated by the - CmpFrame. Only the Digits attribute is potentially relevant - here. */ - set = astTestDigits( frame ); - if ( !set ) astSetDigits( frame, astGetDigits( this ) ); - -/* Invoke the Frame's astUnformat method to read the coordinate value. */ - nc = astUnformat( frame, axis, string, &coord ); - -/* Clear Frame attributes which were temporarily over-ridden. */ - if ( !set ) astClearDigits( frame ); - } - -/* If an error occurred, clear the number of characters read. */ - if ( !astOK ) { - nc = 0; - -/* Otherwise, if characters were read, return the coordinate value. */ - } else if ( nc ) { - *value = coord; - } - -/* Return the number of chracters read. */ - return nc; -} - -static int ValidateSystem( AstFrame *this, AstSystemType system, const char *method, int *status ) { -/* -* -* Name: -* ValidateSystem - -* Purpose: -* Validate a value for a CmpFrame's System attribute. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "cmpframe.h" -* int ValidateSystem( AstFrame *this, AstSystemType system, -* const char *method, int *status ) - -* Class Membership: -* CmpFrame member function (over-rides the astValidateSystem method -* inherited from the Frame class). - -* Description: -* This function checks the validity of the supplied system value. -* If the value is valid, it is returned unchanged. Otherwise, an -* error is reported and a value of AST__BADSYSTEM is returned. - -* Parameters: -* this -* Pointer to the Frame. -* system -* The system value to be checked. -* method -* Pointer to a constant null-terminated character string -* containing the name of the method that invoked this function -* to validate an axis index. This method name is used solely -* for constructing error messages. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The validated system value. - -* Notes: -* - A value of AST__BADSYSTEM will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstSystemType result; /* Validated system value */ - -/* Initialise. */ - result = AST__BADSYSTEM; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* If the value is out of bounds, report an error. */ - if ( system < FIRST_SYSTEM || system > LAST_SYSTEM ) { - astError( AST__AXIIN, "%s(%s): Bad value (%d) given for the System " - "or AlignSystem attribute of a %s.", status, method, - astGetClass( this ), (int) system, astGetClass( this ) ); - -/* Otherwise, return the supplied value. */ - } else { - result = system; - } - -/* Return the result. */ - return result; -} - -/* Functions which access class attributes. */ -/* ---------------------------------------- */ -/* Implement member functions to access the attributes associated with - the axes of a CmpFrame using the private macros defined for this - purpose at the start of this file. */ - -/* Direction(axis). */ -/* ---------------- */ -MAKE_CLEAR(Direction) -MAKE_GET(Direction,int,0,0,0) -MAKE_SET(Direction,int) -MAKE_TEST(Direction) - -/* Format(axis). */ -/* ------------- */ -MAKE_CLEAR(Format) -MAKE_GET(Format,const char *,NULL,0,NULL) -MAKE_SET(Format,const char *) -MAKE_TEST(Format) - -/* Label(axis). */ -/* ------------ */ -MAKE_CLEAR(Label) - -/* Over-ride the default axis labels produced by Frame class objects - and substitute the axis numbering of the enclosing CmpFrame - instead. */ -static const char *label_class; -MAKE_GET(Label,const char *,NULL,( label_class = astGetClass( frame ), - ( astOK && !strcmp( label_class, - "Frame" ) ) ), - ( (void) sprintf( label_buff, "Axis %d", axis + 1 ), label_buff )) -MAKE_SET(Label,const char *) -MAKE_TEST(Label) - -/* Symbol(axis). */ -/* ------------- */ -MAKE_CLEAR(Symbol) - -/* Over-ride the default axis symbols produced by Frame class objects - and substitute the axis numbering of the enclosing CmpFrame - instead. */ -static const char *symbol_class; -MAKE_GET(Symbol,const char *,NULL,( symbol_class = astGetClass( frame ), - ( astOK && !strcmp( symbol_class, - "Frame" ) ) ), - ( (void) sprintf( symbol_buff, "x%d", axis + 1 ), symbol_buff )) -MAKE_SET(Symbol,const char *) -MAKE_TEST(Symbol) - -/* Unit(axis). */ -/* ----------- */ -MAKE_CLEAR(Unit) -MAKE_GET(Unit,const char *,NULL,0,NULL) -MAKE_SET(Unit,const char *) -MAKE_TEST(Unit) - -/* Copy constructor. */ -/* ----------------- */ -static void Copy( const AstObject *objin, AstObject *objout, int *status ) { -/* -* Name: -* Copy - -* Purpose: -* Copy constructor for CmpFrame objects. - -* Type: -* Private function. - -* Synopsis: -* void Copy( const AstObject *objin, AstObject *objout, int *status ) - -* Description: -* This function implements the copy constructor for CmpFrame objects. - -* Parameters: -* objin -* Pointer to the object to be copied. -* objout -* Pointer to the object being constructed. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This constructor makes a deep copy. -*/ - -/* Local Variables: */ - AstCmpFrame *in; /* Pointer to input CmpFrame */ - AstCmpFrame *out; /* Pointer to output CmpFrame */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain pointers to the input and output CmpFrames. */ - in = (AstCmpFrame *) objin; - out = (AstCmpFrame *) objout; - -/* Copy the two component Frames. */ - out->frame1 = astCopy( in->frame1 ); - out->frame2 = astCopy( in->frame2 ); - -/* Determine the number of axes and copy the axis permutation - array. */ - out->perm = astStore( NULL, in->perm, sizeof( int ) * - (size_t) GetNaxes( (AstFrame *) in, status ) ); -} - -/* Destructor. */ -/* ----------- */ -static void Delete( AstObject *obj, int *status ) { -/* -* Name: -* Delete - -* Purpose: -* Destructor for CmpFrame objects. - -* Type: -* Private function. - -* Synopsis: -* void Delete( AstObject *obj, int *status ) - -* Description: -* This function implements the destructor for CmpFrame objects. - -* Parameters: -* obj -* Pointer to the object to be deleted. -* status -* Pointer to the inherited status variable. - -* Notes: -* This function attempts to execute even if the global error -* status is set. -*/ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to CmpFrame structure */ - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) obj; - -/* Annul the two component Frame pointers. */ - if ( this->frame1 ) this->frame1 = astAnnul( this->frame1 ); - if ( this->frame2 ) this->frame2 = astAnnul( this->frame2 ); - -/* Free the axis permutation array. */ - if ( this->perm ) this->perm = astFree( this->perm ); -} - -/* Dump function. */ -/* -------------- */ -static void Dump( AstObject *this_object, AstChannel *channel, int *status ) { -/* -* Name: -* Dump - -* Purpose: -* Dump function for CmpFrame objects. - -* Type: -* Private function. - -* Synopsis: -* void Dump( AstObject *this, AstChannel *channel, int *status ) - -* Description: -* This function implements the Dump function which writes out data -* for the CmpFrame class to an output Channel. - -* Parameters: -* this -* Pointer to the CmpFrame whose data are being written. -* channel -* Pointer to the Channel to which the data are being written. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Constants: */ -#define COMMENT_LEN 150 /* Maximum length of a comment string */ -#define KEY_LEN 50 /* Maximum length of a keyword */ - -/* Local Variables: */ - AstCmpFrame *this; /* Pointer to the CmpFrame structure */ - char comment[ COMMENT_LEN + 1 ]; /* Buffer for comment strings */ - char key[ KEY_LEN + 1 ]; /* Buffer for keywords */ - int axis; /* Loop counter for CmpFrame axes */ - int full; /* Full attribute value */ - int full_set; /* Full attribute set? */ - int ival; /* Integer value */ - int naxes; /* Number of CmpFrame axes */ - int set; /* Attribute value set? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the CmpFrame structure. */ - this = (AstCmpFrame *) this_object; - -/* Write out values representing the instance variables for the - CmpFrame class. Accompany these with appropriate comment strings, - possibly depending on the values being written.*/ - -/* In the case of attributes, we first use the appropriate (private) - Test... member function to see if they are set. If so, we then use - the (private) Get... function to obtain the value to be written - out. - - For attributes which are not set, we use the astGet... method to - obtain the value instead. This will supply a default value - (possibly provided by a derived class which over-rides this method) - which is more useful to a human reader as it corresponds to the - actual default attribute value. Since "set" will be zero, these - values are for information only and will not be read back. */ - -/* Axis permutation array. */ -/* ----------------------- */ -/* Obtain the number of CmpFrame axes. */ - naxes = GetNaxes( (AstFrame *) this, status ); - -/* Write out the CmpFrame axis permutation array value for each axis, - converting to 1-based axis numbering. */ - for ( axis = 0; axis < naxes; axis++ ) { - set = ( this->perm[ axis ] != axis ); - ival = this->perm[ axis ] + 1; - -/* Create a keyword and comment appropriate to the axis. */ - (void) sprintf( key, "Axp%d", axis + 1 ); - if ( set ) { - (void) sprintf( comment, - "Axis %d permuted to use internal axis %d", - axis + 1, ival ); - } else { - (void) sprintf( comment, "Axis %d not permuted", axis + 1 ); - } - astWriteInt( channel, key, set, 0, ival, comment ); - } - -/* Component Frames. */ -/* ----------------- */ -/* Temporarily set the Channel's Full attribute to -1 (unless it is +1 - to start with), remembering the original setting. This prevents any - unnecessary "un-set" Frame values being output that would otherwise - simply duplicate the CmpFrame's attributes which have already been - written. "Set" Frame values are still written, however (and all - values are written if Full is set to 1). */ - full_set = astTestFull( channel ); - full = astGetFull( channel ); - if ( full <= 0 ) astSetFull( channel, -1 ); - -/* Write out Object descriptions for the two component Frames. */ - astWriteObject( channel, "FrameA", 1, 1, this->frame1, - "First component Frame" ); - astWriteObject( channel, "FrameB", 1, 1, this->frame2, - "Second component Frame" ); - -/* Restore the Channel's original Full attribute setting. */ - if ( full_set ) { - astSetFull( channel, full ); - } else { - astClearFull( channel ); - } - -/* Undefine macros local to this function. */ -#undef COMMENT_LEN -#undef KEY_LEN -} - -/* Standard class functions. */ -/* ========================= */ -/* Implement the astIsACmpFrame and astCheckCmpFrame functions using the macros - defined for this purpose in the "object.h" header file. */ -astMAKE_ISA(CmpFrame,Frame) -astMAKE_CHECK(CmpFrame) - -AstCmpFrame *astCmpFrame_( void *frame1_void, void *frame2_void, - const char *options, int *status, ...) { -/* -*++ -* Name: -c astCmpFrame -f AST_CMPFRAME - -* Purpose: -* Create a CmpFrame. - -* Type: -* Public function. - -* Synopsis: -c #include "cmpframe.h" -c AstCmpFrame *astCmpFrame( AstFrame *frame1, AstFrame *frame2, -c const char *options, ... ) -f RESULT = AST_CMPFRAME( FRAME1, FRAME2, OPTIONS, STATUS ) - -* Class Membership: -* CmpFrame constructor. - -* Description: -* This function creates a new CmpFrame and optionally initialises -* its attributes. -* -* A CmpFrame is a compound Frame which allows two component Frames -* (of any class) to be merged together to form a more complex -* Frame. The axes of the two component Frames then appear together -* in the resulting CmpFrame (those of the first Frame, followed by -* those of the second Frame). -* -* Since a CmpFrame is itself a Frame, it can be used as a -* component in forming further CmpFrames. Frames of arbitrary -* complexity may be built from simple individual Frames in this -* way. -* -* Also since a Frame is a Mapping, a CmpFrame can also be used as a -* Mapping. Normally, a CmpFrame is simply equivalent to a UnitMap, -* but if either of the component Frames within a CmpFrame is a Region -* (a sub-class of Frame), then the CmpFrame will use the Region as a -* Mapping when transforming values for axes described by the Region. -* Thus input axis values corresponding to positions which are outside the -* Region will result in bad output axis values. - -* Parameters: -c frame1 -f FRAME1 = INTEGER (Given) -* Pointer to the first component Frame. -c frame2 -f FRAME2 = INTEGER (Given) -* Pointer to the second component Frame. -c options -f OPTIONS = CHARACTER * ( * ) (Given) -c Pointer to a null-terminated string containing an optional -c comma-separated list of attribute assignments to be used for -c initialising the new CmpFrame. The syntax used is identical to -c that for the astSet function and may include "printf" format -c specifiers identified by "%" symbols in the normal way. -f A character string containing an optional comma-separated -f list of attribute assignments to be used for initialising the -f new CmpFrame. The syntax used is identical to that for the -f AST_SET routine. -c ... -c If the "options" string contains "%" format specifiers, then -c an optional list of additional arguments may follow it in -c order to supply values to be substituted for these -c specifiers. The rules for supplying these are identical to -c those for the astSet function (and for the C "printf" -c function). -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astCmpFrame() -f AST_CMPFRAME = INTEGER -* A pointer to the new CmpFrame. - -* Notes: -* - A null Object pointer (AST__NULL) will be returned if this -c function is invoked with the AST error status set, or if it -f function is invoked with STATUS set to an error value, or if it -* should fail for any reason. - -* Status Handling: -* The protected interface to this function includes an extra -* parameter at the end of the parameter list descirbed above. This -* parameter is a pointer to the integer inherited status -* variable: "int *status". - -*-- - -* Implementation Notes: -* - This function implements the basic CmpFrame constructor which -* is available via the protected interface to the CmpFrame class. -* A public interface is provided by the astCmpFrameId_ function. -* - Because this function has a variable argument list, it is -* invoked by a macro that evaluates to a function pointer (not a -* function invocation) and no checking or casting of arguments is -* performed before the function is invoked. Because of this, the -* "frame1" and "frame2" parameters are of type (void *) and are -* converted and validated within the function itself. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstCmpFrame *new; /* Pointer to new CmpFrame */ - AstFrame *frame1; /* Pointer to first Frame structure */ - AstFrame *frame2; /* Pointer to second Frame structure */ - va_list args; /* Variable argument list */ - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Check the global status. */ - new = NULL; - if ( !astOK ) return new; - -/* Obtain and validate pointers to the Frame structures provided. */ - frame1 = astCheckFrame( frame1_void ); - frame2 = astCheckFrame( frame2_void ); - if ( astOK ) { - -/* Initialise the CmpFrame, allocating memory and initialising the - virtual function table as well if necessary. */ - new = astInitCmpFrame( NULL, sizeof( AstCmpFrame ), !class_init, - &class_vtab, "CmpFrame", frame1, frame2 ); - -/* If successful, note that the virtual function table has been - initialised. */ - if ( astOK ) { - class_init = 1; - -/* Obtain the variable argument list and pass it along with the - options string to the astVSet method to initialise the new - CmpFrame's attributes. */ - va_start( args, status ); - astVSet( new, options, NULL, args ); - va_end( args ); - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - } - -/* Return a pointer to the new CmpFrame. */ - return new; -} - -AstCmpFrame *astCmpFrameId_( void *frame1_void, void *frame2_void, - const char *options, ... ) { -/* -* Name: -* astCmpFrameId_ - -* Purpose: -* Create a CmpFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "cmpframe.h" -* AstCmpFrame *astCmpFrameId_( void *frame1_void, void *frame2_void, -* const char *options, ... ) - -* Class Membership: -* CmpFrame constructor. - -* Description: -* This function implements the external (public) interface to the -* astCmpFrame constructor function. It returns an ID value -* (instead of a true C pointer) to external users, and must be -* provided because astCmpFrame_ has a variable argument list which -* cannot be encapsulated in a macro (where this conversion would -* otherwise occur). For the same reason, the "frame1" and "frame2" -* parameters are of type (void *) and are converted and validated -* within the function itself. -* -* The variable argument list also prevents this function from -* invoking astCmpFrame_ directly, so it must be a -* re-implementation of it in all respects, except for the final -* conversion of the result to an ID value. - -* Parameters: -* As for astCmpFrame_. - -* Returned Value: -* The ID value associated with the new CmpFrame. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstCmpFrame *new; /* Pointer to new CmpFrame */ - AstFrame *frame1; /* Pointer to first Frame structure */ - AstFrame *frame2; /* Pointer to second Frame structure */ - va_list args; /* Variable argument list */ - - int *status; /* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Pointer to inherited status value */ - -/* Get a pointer to the inherited status value. */ - status = astGetStatusPtr; - -/* Check the global status. */ - new = NULL; - if ( !astOK ) return new; - -/* Obtain the Frame pointers from the ID's supplied and validate the - pointers to ensure they identify valid Frames. */ - frame1 = astVerifyFrame( astMakePointer( frame1_void ) ); - frame2 = astVerifyFrame( astMakePointer( frame2_void ) ); - if ( astOK ) { - -/* Initialise the CmpFrame, allocating memory and initialising the - virtual function table as well if necessary. */ - new = astInitCmpFrame( NULL, sizeof( AstCmpFrame ), !class_init, - &class_vtab, "CmpFrame", frame1, frame2 ); - -/* If successful, note that the virtual function table has been - initialised. */ - if ( astOK ) { - class_init = 1; - -/* Obtain the variable argument list and pass it along with the - options string to the astVSet method to initialise the new - CmpFrame's attributes. */ - va_start( args, options ); - astVSet( new, options, NULL, args ); - va_end( args ); - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - } - -/* Return an ID value for the new CmpFrame. */ - return astMakeId( new ); -} - -AstCmpFrame *astInitCmpFrame_( void *mem, size_t size, int init, - AstCmpFrameVtab *vtab, const char *name, - AstFrame *frame1, AstFrame *frame2, int *status ) { -/* -*+ -* Name: -* astInitCmpFrame - -* Purpose: -* Initialise a CmpFrame. - -* Type: -* Protected function. - -* Synopsis: -* #include "cmpframe.h" -* AstCmpFrame *astInitCmpFrame( void *mem, size_t size, int init, -* AstCmpFrameVtab *vtab, const char *name, -* AstFrame *frame1, AstFrame *frame2 ) - -* Class Membership: -* CmpFrame initialiser. - -* Description: -* This function is provided for use by class implementations to -* initialise a new CmpFrame object. It allocates memory (if -* necessary) to accommodate the CmpFrame plus any additional data -* associated with the derived class. It then initialises a -* CmpFrame structure at the start of this memory. If the "init" -* flag is set, it also initialises the contents of a virtual -* function table for a CmpFrame at the start of the memory passed -* via the "vtab" parameter. - -* Parameters: -* mem -* A pointer to the memory in which the CmpFrame is to be -* created. This must be of sufficient size to accommodate the -* CmpFrame data (sizeof(CmpFrame)) plus any data used by the -* derived class. If a value of NULL is given, this function -* will allocate the memory itself using the "size" parameter to -* determine its size. -* size -* The amount of memory used by the CmpFrame (plus derived class -* data). This will be used to allocate memory if a value of -* NULL is given for the "mem" parameter. This value is also -* stored in the CmpFrame structure, so a valid value must be -* supplied even if not required for allocating memory. -* init -* A logical flag indicating if the CmpFrame's virtual function -* table is to be initialised. If this value is non-zero, the -* virtual function table will be initialised by this function. -* vtab -* Pointer to the start of the virtual function table to be -* associated with the new CmpFrame. -* name -* Pointer to a constant null-terminated character string which -* contains the name of the class to which the new object -* belongs (it is this pointer value that will subsequently be -* returned by the Object astClass function). -* frame1 -* Pointer to the first Frame to be included in the new CmpFrame. -* frame2 -* Pointer to the second Frame to be included in the new CmpFrame. - -* Returned Value: -* A pointer to the new CmpFrame. - -* Notes: -* - A null pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - AstCmpFrame *new; /* Pointer to new CmpFrame */ - int axis; /* Loop counter for axes */ - int naxes; /* Number of CmpFrame axes */ - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* If necessary, initialise the virtual function table. */ - if ( init ) astInitCmpFrameVtab( vtab, name ); - -/* Initialise a Frame structure (the parent class) as the first - component within the CmpFrame structure, allocating memory if - necessary. Set the number of Frame axes to zero, since all axis - information is stored within the component Frames. */ - new = (AstCmpFrame *) astInitFrame( mem, size, 0, (AstFrameVtab *) vtab, - name, 0 ); - - if ( astOK ) { - -/* Initialise the CmpFrame data. */ -/* ----------------------------- */ -/* Clone the component Frame pointers. */ - new->frame1 = astClone( frame1 ); - new->frame2 = astClone( frame2 ); - -/* Determine the number of CmpFrame axes. */ - naxes = astGetNaxes( frame1 ) + astGetNaxes( frame2 ); - -/* Allocate memory to hold the axis permutation array and initialise - this array. */ - new->perm = astMalloc( sizeof( int ) * (size_t) naxes ); - if ( astOK ) { - for ( axis = 0; axis < naxes; axis++ ) new->perm[ axis ] = axis; - } - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return a pointer to the new object. */ - return new; -} - -AstCmpFrame *astLoadCmpFrame_( void *mem, size_t size, - AstCmpFrameVtab *vtab, const char *name, - AstChannel *channel, int *status ) { -/* -*+ -* Name: -* astLoadCmpFrame - -* Purpose: -* Load a CmpFrame. - -* Type: -* Protected function. - -* Synopsis: -* #include "cmpframe.h" -* AstCmpFrame *astLoadCmpFrame( void *mem, size_t size, -* AstCmpFrameVtab *vtab, const char *name, -* AstChannel *channel ) - -* Class Membership: -* CmpFrame loader. - -* Description: -* This function is provided to load a new CmpFrame using data read -* from a Channel. It first loads the data used by the parent class -* (which allocates memory if necessary) and then initialises a -* CmpFrame structure in this memory, using data read from the -* input Channel. - -* Parameters: -* mem -* A pointer to the memory into which the CmpFrame is to be -* loaded. This must be of sufficient size to accommodate the -* CmpFrame data (sizeof(CmpFrame)) plus any data used by -* derived classes. If a value of NULL is given, this function -* will allocate the memory itself using the "size" parameter to -* determine its size. -* size -* The amount of memory used by the CmpFrame (plus derived class -* data). This will be used to allocate memory if a value of -* NULL is given for the "mem" parameter. This value is also -* stored in the CmpFrame structure, so a valid value must be -* supplied even if not required for allocating memory. -* -* If the "vtab" parameter is NULL, the "size" value is ignored -* and sizeof(AstCmpFrame) is used instead. -* vtab -* Pointer to the start of the virtual function table to be -* associated with the new CmpFrame. If this is NULL, a pointer -* to the (static) virtual function table for the CmpFrame class -* is used instead. -* name -* Pointer to a constant null-terminated character string which -* contains the name of the class to which the new object -* belongs (it is this pointer value that will subsequently be -* returned by the astGetClass method). -* -* If the "vtab" parameter is NULL, the "name" value is ignored -* and a pointer to the string "CmpFrame" is used instead. - -* Returned Value: -* A pointer to the new CmpFrame. - -* Notes: -* - A null pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Constants: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ -#define KEY_LEN 50 /* Maximum length of a keyword */ - -/* Local Variables: */ - AstCmpFrame *new; /* Pointer to the new CmpFrame */ - char key[ KEY_LEN + 1 ]; /* Buffer for keywords */ - int axis; /* Loop counter for axes */ - int naxes; /* Number of CmpFrame axes */ - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(channel); - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* If a NULL virtual function table has been supplied, then this is - the first loader to be invoked for this CmpFrame. In this case the - CmpFrame belongs to this class, so supply appropriate values to be - passed to the parent class loader (and its parent, etc.). */ - if ( !vtab ) { - size = sizeof( AstCmpFrame ); - vtab = &class_vtab; - name = "CmpFrame"; - -/* If required, initialise the virtual function table for this class. */ - if ( !class_init ) { - astInitCmpFrameVtab( vtab, name ); - class_init = 1; - } - } - -/* Invoke the parent class loader to load data for all the ancestral - classes of the current one, returning a pointer to the resulting - partly-built CmpFrame. */ - new = astLoadFrame( mem, size, (AstFrameVtab *) vtab, name, - channel ); - - if ( astOK ) { - -/* Read input data. */ -/* ================ */ -/* Request the input Channel to read all the input data appropriate to - this class into the internal "values list". */ - astReadClassData( channel, "CmpFrame" ); - -/* Now read each individual data item from this list and use it to - initialise the appropriate instance variable(s) for this class. */ - -/* In the case of attributes, we first read the "raw" input value, - supplying the "unset" value as the default. If a "set" value is - obtained, we then use the appropriate (private) Set... member - function to validate and set the value properly. */ - -/* Component Frames. */ -/* ----------------- */ -/* Read both component Frames, supplying a default 1-dimensional Frame - if necessary. */ - new->frame1 = astReadObject( channel, "framea", NULL ); - if ( !new->frame1 ) new->frame1 = astFrame( 1, "", status ); - - new->frame2 = astReadObject( channel, "frameb", NULL ); - if ( !new->frame2 ) new->frame2 = astFrame( 1, "", status ); - -/* Axis permutation array. */ -/* ----------------------- */ -/* Obtain the number of CmpFrame axes and allocate memory to hold the - axis permutation array. */ - naxes = GetNaxes( (AstFrame *) new, status ); - new->perm = astMalloc( sizeof( int ) * (size_t) naxes ); - -/* If OK, loop to read the array value for each axis. */ - if ( astOK ) { - for ( axis = 0; axis < naxes; axis++ ) { - -/* Convert from 1-based to zero-based axis numbering at this - point. The default is the "un-permuted" value. */ - sprintf( key, "axp%d", axis + 1 ); - new->perm[ axis ] = astReadInt( channel, key, axis + 1 ) - 1; - -/* Quit looping if an error occurs. */ - if ( !astOK ) break; - } - } - -/* If an error occurred, clean up by deleting the new CmpFrame. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return the new CmpFrame pointer. */ - return new; - -/* Undefine macros local to this function. */ -#undef KEY_LEN -} - -/* Virtual function interfaces. */ -/* ============================ */ -/* These provide the external interface to the virtual functions defined by - this class. Each simply checks the global error status and then locates and - executes the appropriate member function, using the function pointer stored - in the object's virtual function table (this pointer is located using the - astMEMBER macro defined in "object.h"). - - Note that the member function may not be the one defined here, as it may - have been over-ridden by a derived class. However, it should still have the - same interface. */ - - - - - |