diff options
Diffstat (limited to 'ast/stc.c')
-rw-r--r-- | ast/stc.c | 3703 |
1 files changed, 3703 insertions, 0 deletions
diff --git a/ast/stc.c b/ast/stc.c new file mode 100644 index 0000000..08e4392 --- /dev/null +++ b/ast/stc.c @@ -0,0 +1,3703 @@ +/* +*class++ +* Name: +* Stc + +* Purpose: +* Represents an instance of the IVOA STC class. + +* Constructor Function: +c astStc +f AST_STC + +* Description: +* The Stc class is an implementation of the IVOA STC class which forms +* part of the IVOA Space-Time Coordinate Metadata system. See: +* +* http://hea-www.harvard.edu/~arots/nvometa/STC.html +* +* The Stc class does not have a constructor function of its own, as it +* is simply a container class for a family of specialised sub-classes +* including StcCatalogEntryLocation, StcResourceProfile, StcSearchLocation +* and StcObsDataLocation. + +* Inheritance: +* The Stc class inherits from the Region class. + +* Attributes: +* In addition to those attributes common to all Regions, every +* Stc also has the following attributes: +* +* - RegionClass: The class name of the encapsulated Region. + +* Functions: +c In addition to those functions applicable to all Regions, the +c following functions may also be applied to all Stc's: +f In addition to those routines applicable to all Regions, the +f following routines may also be applied to all Stc's: +* +c - astGetStcRegion: Get a pointer to the encapsulated Region +f - AST_GETSTCREGION: Get a pointer to the encapsulated Region +c - astGetStcCoord: Get information about an AstroCoords element +f - AST_GETSTCCOORD: Get information about an AstroCoords element +c - astGetStcNCoord: Returns the number of AstroCoords elements in an Stc +f - AST_GETSTCNCOORD: Returns the number of AstroCoords elements in an Stc + +* Copyright: +* Copyright (C) 1997-2006 Council for the Central Laboratory of the +* Research Councils +* Copyright (C) 2008 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: +* DSB: David S. Berry (Starlink) + +* History: +* 23-NOV-2004 (DSB): +* Original version. +* 14-FEB-2006 (DSB): +* Override astGetObjSize. +* 13-MAR-2009 (DSB): +* Over-ride astRegBasePick. +*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 Stc + +/* The number of components in an AstroCoords element which are described + using a Region within a KeyMap. */ +#define NREG 5 + +/* 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 "object.h" /* Base Object class */ +#include "unitmap.h" /* Unit Mappings */ +#include "region.h" /* Regions (parent class) */ +#include "channel.h" /* I/O channels */ +#include "stc.h" /* Interface definition for this class */ +#include "keymap.h" /* Lists of value/key pairs */ +#include "pointlist.h" /* Individual points in a Frame */ +#include "ellipse.h" /* Ellipses within a Frame */ +#include "interval.h" /* Axis intervals within a Frame */ +#include "prism.h" /* Extrusions into higher dimensions */ + +/* Error code definitions. */ +/* ----------------------- */ +#include "ast_err.h" /* AST error codes */ + +/* C header files. */ +/* --------------- */ +#include <stdarg.h> +#include <stddef.h> +#include <string.h> +#include <stdio.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 AstMapping *(* parent_simplify)( AstMapping *, int * ); +static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * ); +static AstRegion *(* parent_getdefunc)( AstRegion *, int * ); +static const char *(* parent_getattrib)( AstObject *, const char *, int * ); +static int (* parent_equal)( AstObject *, AstObject *, int * ); +static int (* parent_getobjsize)( AstObject *, int * ); +static int (* parent_getusedefs)( AstObject *, int * ); +static int (* parent_testattrib)( AstObject *, const char *, int * ); +static void (* parent_clearattrib)( AstObject *, const char *, int * ); +static void (* parent_setattrib)( AstObject *, const char *, int * ); +static void (* parent_setregfs)( AstRegion *, AstFrame *, int * ); +static void (*parent_regclearattrib)( AstRegion *, const char *, char **, int * ); +static void (*parent_regsetattrib)( AstRegion *, const char *, char **, int * ); + +static void (* parent_clearnegated)( AstRegion *, int * ); +static void (* parent_clearclosed)( AstRegion *, int * ); +static void (* parent_clearfillfactor)( AstRegion *, int * ); +static void (* parent_clearmeshsize)( AstRegion *, int * ); + +static void (* parent_setclosed)( AstRegion *, int, int * ); +static void (* parent_setfillfactor)( AstRegion *, double, int * ); +static void (* parent_setmeshsize)( AstRegion *, int, int * ); +static void (* parent_setnegated)( AstRegion *, int, int * ); + +#if defined(THREAD_SAFE) +static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * ); +#endif + +/* The keys associated with each component of an AstroCoords element + within KeyMap */ +static const char *regkey[ NREG ] = { AST__STCERROR, + AST__STCRES, + AST__STCSIZE, + AST__STCPIXSZ, + AST__STCVALUE }; + +/* The comments associated with each component of an AstroCoords element + within KeyMap */ +static const char *regcom[ NREG ] = { "AstroCoords error region", + "AstroCoords resolution region", + "AstroCoords size region", + "AstroCoords pixel size region", + "AstroCoords value region" }; + + +#ifdef THREAD_SAFE +/* Define how to initialise thread-specific globals. */ +#define GLOBAL_inits \ + globals->Class_Init = 0; + +/* Create the function that initialises global data for this module. */ +astMAKE_INITGLOBALS(Stc) + +/* Define macros for accessing each item of thread specific global data. */ +#define class_init astGLOBAL(Stc,Class_Init) +#define class_vtab astGLOBAL(Stc,Class_Vtab) + + +#include <pthread.h> + + +#else + + +/* Define the class virtual function table and its initialisation flag + as static variables. */ +static AstStcVtab class_vtab; /* Virtual function table */ +static int class_init = 0; /* Virtual function table initialised? */ + +#endif + +/* External Interface Function Prototypes. */ +/* ======================================= */ + +/* Prototypes for Private Member Functions. */ +/* ======================================== */ +static AstKeyMap *GetStcCoord( AstStc *, int, int * ); +static AstKeyMap *MakeAstroCoordsKeyMap( AstRegion *, AstKeyMap *, const char *, int * ); +static AstMapping *Simplify( AstMapping *, int * ); +static AstPointSet *RegBaseMesh( AstRegion *, int * ); +static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * ); +static AstRegion *GetDefUnc( AstRegion *, int * ); +static AstRegion *GetStcRegion( AstStc *, int * ); +static AstRegion *RegBasePick( AstRegion *this, int, const int *, int * ); +static const char *GetRegionClass( AstStc *, int * ); +static int Equal( AstObject *, AstObject *, int * ); +static int GetBounded( AstRegion *, int * ); +static int GetObjSize( AstObject *, int * ); +static int GetStcNCoord( AstStc *, int * ); +static int GetUseDefs( AstObject *, int * ); +static int Overlap( AstRegion *, AstRegion *, int * ); +static int OverlapX( AstRegion *, AstRegion *, int * ); +static int RegPins( AstRegion *, AstPointSet *, AstRegion *, int **, int * ); +static void Copy( const AstObject *, AstObject *, int * ); +static void Delete( AstObject *, int * ); +static void Dump( AstObject *, AstChannel *, int * ); +static void GetRegion( AstStc *, AstRegion **, int *, int * ); +static void RegBaseBox( AstRegion *, double *, double *, int * ); +static void RegClearAttrib( AstRegion *, const char *, char **, int * ); +static void RegSetAttrib( AstRegion *, const char *, char **, int * ); +static void SetRegFS( AstRegion *, AstFrame *, int * ); + +static void ClearAttrib( AstObject *, const char *, int * ); +static const char *GetAttrib( AstObject *, const char *, int * ); +static void SetAttrib( AstObject *, const char *, int * ); +static int TestAttrib( AstObject *, const char *, int * ); + +static void ClearClosed( AstRegion *, int * ); +static int GetClosed( AstRegion *, int * ); +static void SetClosed( AstRegion *, int, int * ); +static int TestClosed( AstRegion *, int * ); + +static void ClearMeshSize( AstRegion *, int * ); +static int GetMeshSize( AstRegion *, int * ); +static void SetMeshSize( AstRegion *, int, int * ); +static int TestMeshSize( AstRegion *, int * ); + +static void ClearFillFactor( AstRegion *, int * ); +static double GetFillFactor( AstRegion *, int * ); +static void SetFillFactor( AstRegion *, double, int * ); +static int TestFillFactor( AstRegion *, int * ); + +static void ClearNegated( AstRegion *, int * ); +static int GetNegated( AstRegion *, int * ); +static void SetNegated( AstRegion *, int, int * ); +static int TestNegated( AstRegion *, int * ); + +#if defined(THREAD_SAFE) +static int ManageLock( AstObject *, int, int, AstObject **, int * ); +#endif + +/* Member functions. */ +/* ================= */ +static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) { +/* +* Name: +* ClearAttrib + +* Purpose: +* Clear an attribute value for a Stc. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* void ClearAttrib( AstObject *this, const char *attrib, int *status ) + +* Class Membership: +* Stc member function (over-rides the astClearAttrib protected +* method inherited from the Region class). + +* Description: +* This function clears the value of a specified attribute for a +* Stc, so that the default value will subsequently be used. + +* Parameters: +* this +* Pointer to the Stc. +* 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. + +*/ + +/* Local Variables: */ + AstStc *this; /* Pointer to the Stc structure */ + int len; /* Length of attrib string */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Stc structure. */ + this = (AstStc *) this_object; + +/* Obtain the length of the "attrib" string. */ + len = strlen( attrib ); + +/* Check the attribute name and clear the appropriate attribute. */ + +/* (none as yet) */ +/* ------------- */ + +/* Read-only attributes. */ +/* --------------------- */ +/* Test if the attribute name matches any of the read-only attributes + of this class. If it does, then report an error. */ + if ( !strcmp( attrib, "regionclass" ) ) { + astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" " + "value for a %s.", status, attrib, astGetClass( this ) ); + astError( AST__NOWRT, "This is a read-only attribute." , status); + +/* Not recognised. */ +/* --------------- */ +/* If the attribute is still not recognised, pass it on to the parent + method for further interpretation. */ + } else { + (*parent_clearattrib)( this_object, attrib, status ); + } +} + +static int Equal( AstObject *this_object, AstObject *that_object, int *status ) { +/* +* Name: +* Equal + +* Purpose: +* Test if two Objects are equivalent. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* int Equal( AstObject *this_object, AstObject *that_object, int *status ) + +* Class Membership: +* Stc member function (over-rides the astEqual protected +* method inherited from the Region class). + +* Description: +* This function returns a boolean result (0 or 1) to indicate whether +* two Stcs are equivalent. + +* Parameters: +* this +* Pointer to the first Stc. +* that +* Pointer to the second Stc. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* One if the Stcs are equivalent, zero otherwise. + +* Notes: +* - The Stcs are equivalent if their encapsulated Region are +* equivalent, and if they have the same boolean operation, negation +* and closed flags. +* - 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: */ + AstStc *that; + AstStc *this; + int result; + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Invoke the Equal method inherited from the parent Region class. This checks + that the Objects are both of the same class, and have the same Negated + and Closed flags (amongst other things). */ + if( (*parent_equal)( this_object, that_object, status ) ) { + +/* Obtain pointers to the two Stc structures. */ + this = (AstStc *) this_object; + that = (AstStc *) that_object; + +/* Test their encapsulated Region for equality. */ + result = astEqual( this->region, that->region ); + } + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = 0; + +/* Return the result, */ + return result; +} + +/* +* Name: +* MAKE_SET + +* Purpose: +* Define a function to set an attribute value for a Stc. + +* Type: +* Private macro. + +* Synopsis: +* #include "stc.h" +* MAKE_SET(attribute,lattribute,type) + +* Class Membership: +* Defined by the Stc class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static void Set<Attribute>( AstRegion *this, <Type> value ) +* +* that sets the value of a specified Region attribute in the parent +* Region structure and also in the encapsulated Region. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +* lattribute +* Name of the attribute, all in lower case. +* type +* The C type of the attribute. +*/ + +/* Define the macro. */ +#define MAKE_SET(attribute,lattribute,type) \ +static void Set##attribute( AstRegion *this_region, type value, int *status ) { \ +\ +/* Local Variables: */ \ + AstStc *this; /* Pointer to the Stc structure */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return; \ +\ +/* Use the parent method to set the value in the parent Region structure. */ \ + (*parent_set##lattribute)( this_region, value, status ); \ +\ +/* Also set the value in the encapsulated Region. */ \ + this = (AstStc *) this_region; \ + astSet##attribute( this->region, value ); \ +} + +/* Use the above macro to create accessors for the MeshSize, Closed and + FillFactor attributes. */ +MAKE_SET(FillFactor,fillfactor,double) +MAKE_SET(MeshSize,meshsize,int) +MAKE_SET(Closed,closed,int) +MAKE_SET(Negated,negated,int) + +/* Undefine the macro. */ +#undef MAKE_SET + +/* +* Name: +* MAKE_CLEAR + +* Purpose: +* Define a function to clear an attribute value for a Stc. + +* Type: +* Private macro. + +* Synopsis: +* #include "stc.h" +* MAKE_CLEAR(attribute,lattribute) + +* Class Membership: +* Defined by the Stc class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static void Clear<Attribute>( AstRegion *this ) +* +* that sets the value of a specified Region attribute in the parent +* Region structure and also in the encapsulated Region. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +* lattribute +* Name of the attribute, all in lower case. +*/ + +/* Define the macro. */ +#define MAKE_CLEAR(attribute,lattribute) \ +static void Clear##attribute( AstRegion *this_region, int *status ) { \ +\ +/* Local Variables: */ \ + AstStc *this; /* Pointer to the Stc structure */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return; \ +\ +/* Use the parent method to clear the value in the parent Region structure. */ \ + (*parent_clear##lattribute)( this_region, status ); \ +\ +/* Also clear the value in the encapsulated Region. */ \ + this = (AstStc *) this_region; \ + astClear##attribute( this->region ); \ +} + +/* Use the above macro to create accessors for the MeshSize, Closed and + FillFactor attributes. */ +MAKE_CLEAR(FillFactor,fillfactor) +MAKE_CLEAR(MeshSize,meshsize) +MAKE_CLEAR(Closed,closed) +MAKE_CLEAR(Negated,negated) + +/* Undefine the macro. */ +#undef MAKE_CLEAR + + +/* +* Name: +* MAKE_GET + +* Purpose: +* Define a function to get an attribute value for a Stc. + +* Type: +* Private macro. + +* Synopsis: +* #include "stc.h" +* MAKE_GET(attribute,type,bad) + +* Class Membership: +* Defined by the Stc class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static <Type> Get<Attribute>( AstRegion *this ) +* +* that gets the value of a specified Region attribute from the encapsulated +* Region. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +* type +* The C type of the attribute. +* bad +* Value to return in caseof error. +*/ + +/* Define the macro. */ +#define MAKE_GET(attribute,type,bad) \ +static type Get##attribute( AstRegion *this_region, int *status ) { \ +\ +/* Local Variables: */ \ + AstStc *this; /* Pointer to the Stc structure */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return (bad); \ +\ +/* Get the value from the encapsulated Region. */ \ + this = (AstStc *) this_region; \ + return astGet##attribute( this->region ); \ +} + +/* Use the above macro to create accessors for the MeshSize, Closed and + FillFactor attributes. */ +MAKE_GET(FillFactor,double,AST__BAD) +MAKE_GET(MeshSize,int,100) +MAKE_GET(Closed,int,1) +MAKE_GET(Negated,int,0) + +/* Undefine the macro. */ +#undef MAKE_GET + +/* +* Name: +* MAKE_TEST + +* Purpose: +* Define a function to test an attribute value for a Stc. + +* Type: +* Private macro. + +* Synopsis: +* #include "stc.h" +* MAKE_TEST(attribute) + +* Class Membership: +* Defined by the Stc class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static int Test<Attribute>( AstRegion *this ) +* +* that test the value of a specified Region attribute from the encapsulated +* Region. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +* type +* The C type of the attribute. +*/ + +/* Define the macro. */ +#define MAKE_TEST(attribute) \ +static int Test##attribute( AstRegion *this_region, int *status ) { \ +\ +/* Local Variables: */ \ + AstStc *this; /* Pointer to the Stc structure */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return 0; \ +\ +/* Test the value from the encapsulated Region. */ \ + this = (AstStc *) this_region; \ + return astTest##attribute( this->region ); \ +} + +/* Use the above macro to create accessors for the MeshSize, Closed and + FillFactor attributes. */ +MAKE_TEST(FillFactor) +MAKE_TEST(MeshSize) +MAKE_TEST(Closed) +MAKE_TEST(Negated) + +/* Undefine the macro. */ +#undef MAKE_TEST + + + + +static int GetObjSize( AstObject *this_object, int *status ) { +/* +* Name: +* GetObjSize + +* Purpose: +* Return the in-memory size of an Object. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* int GetObjSize( AstObject *this, int *status ) + +* Class Membership: +* Stc member function (over-rides the astGetObjSize protected +* method inherited from the parent class). + +* Description: +* This function returns the in-memory size of the supplied Stc, +* in bytes. + +* Parameters: +* this +* Pointer to the Stc. +* 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: */ + AstStc *this; /* Pointer to Stc structure */ + int result; /* Result value to return */ + int i; /* AstroCoords index */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointers to the Stc structure. */ + this = (AstStc *) 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->region ); + + if( this->coord ) { + for( i = 0; i < this->ncoord; i++ ) { + result += astGetObjSize( this->coord[ i ] ); + } + result += astTSizeOf( this->coord ); + } + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = 0; + +/* 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 Stc. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* const char *GetAttrib( AstObject *this, const char *attrib, int *status ) + +* Class Membership: +* Stc member function (over-rides the protected astGetAttrib +* method inherited from the Region class). + +* Description: +* This function returns a pointer to the value of a specified +* attribute for a Stc, formatted as a character string. + +* Parameters: +* this +* Pointer to the Stc. +* 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: +* - The returned string pointer may point at memory allocated +* within the Stc, 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 Stc. 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: */ + AstStc *this; /* Pointer to the Stc structure */ + const char *result; /* Pointer value to return */ + int len; /* Length of attrib string */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the Stc structure. */ + this = (AstStc *) this_object; + +/* Obtain the length of the attrib string. */ + len = strlen( attrib ); + +/* Compare "attrib" with each recognised attribute name in turn, + obtaining the value of the required attribute. If necessary, write + the value into "buff" as a null-terminated string in an appropriate + format. Set "result" to point at the result string. */ + +/* RegionClass. */ +/* ------------ */ + if ( !strcmp( attrib, "regionclass" ) ) { + result = astGetClass( this->region ); + +/* Not recognised. */ +/* --------------- */ +/* If the attribute name was not recognised, pass it on to the parent + method for further interpretation. */ + } else { + result = (*parent_getattrib)( this_object, attrib, status ); + } + +/* Return the result. */ + return result; +} + +static int GetBounded( AstRegion *this_region, int *status ) { +/* +* Name: +* GetBounded + +* Purpose: +* Is the Region bounded? + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* int GetBounded( AstRegion *this, int *status ) + +* Class Membership: +* Stc method (over-rides the astGetBounded method inherited from +* the Region class). + +* Description: +* This function returns a flag indicating if the Region is bounded. +* The implementation provided by the base Region class is suitable +* for Region sub-classes representing the inside of a single closed +* curve (e.g. Circle, Ellipse, Box, etc). Other sub-classes (such as +* Stc, PointList, etc ) may need to provide their own implementations. + +* Parameters: +* this +* Pointer to the Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* Non-zero if the Region is bounded. Zero otherwise. + +*/ + +/* Local Variables: */ + AstStc *this; /* Pointer to Stc structure */ + AstRegion *reg; /* Pointer to the encapsulated Region */ + int neg; /* Negated flag to use */ + int neg_old; /* Original Negated flag */ + int result; /* Returned result */ + +/* Initialise */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Get a pointer to the Stc structure. */ + this = (AstStc *) this_region; + +/* Get the encapsulated Region, and the Negated value which should be used + with it. The returned values take account of whether the supplied Stc has + itself been Negated or not. The returned Region represent a region within + the base Frame of the FrameSet encapsulated by the parent Region + structure. */ + GetRegion( this, ®, &neg, status ); + +/* Temporarily set the Negated attribute to the required value.*/ + neg_old = astGetNegated( reg ); + astSetNegated( reg, neg ); + +/* See if the encapsulated Region is bounded. */ + result = astGetBounded( reg ); + +/* Re-instate the original value for the Negated attribute of the + encapsulated Region. */ + if( reg ) astSetNegated( reg, neg_old ); + +/* Free resources. */ + reg = astAnnul( reg ); + +/* Return zero if an error occurred. */ + if( !astOK ) result = 0; + +/* Return the required pointer. */ + return result; +} + +static AstRegion *GetDefUnc( AstRegion *this_region, int *status ) { +/* +* Name: +* GetDefUnc + +* Purpose: +* Obtain a pointer to the default uncertainty Region for a given Region. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* AstRegion *GetDefUnc( AstRegion *this ) + +* Class Membership: +* Stc method (over-rides the astGetDefUnc method inherited from +* the Region class). + +* This function returns a pointer to a Region which represents the +* default uncertainty associated with a position on the boundary of the +* given Region. The returned Region refers to the base Frame within the +* FrameSet encapsulated by the supplied Region. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* A pointer to the Region. This should be annulled (using astAnnul) +* when no longer needed. + +* 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: */ + AstStc *this; /* Pointer to the Stc structure */ + AstRegion *result; /* Returned pointer */ + +/* Initialise */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Get a pointer to the Stc structure. */ + this = (AstStc *) this_region; + +/* If the encapsulated region has non-default uncertainty, use it as + the default uncertainty for the Cmpregion. Note, the current Frame of + an uncertainty Region is assumed to be the same as the base Frame in the + Stc. */ + if( astTestUnc( this->region ) ) { + result = astGetUncFrm( this->region, AST__CURRENT ); + +/* Otherwise, use the parent method to determine the default uncertainty. */ + } else { + result = (* parent_getdefunc)( this_region, status ); + } + +/* Return NULL if an error occurred. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the required pointer. */ + return result; +} + +static void GetRegion( AstStc *this, AstRegion **reg, int *neg, int *status ) { +/* +* +* Name: +* GetRegion + +* Purpose: +* Get the encapsulated Region of a Stc. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void GetRegion( AstStc *this, AstRegion **reg, int *neg, int *status ) + +* Class Membership: +* Stc member function + +* Description: +* This function returns a pointer to a Region which is equivalent to +* the supplied Stc. If the Stc has been negated, then the returned +* "negated" flag will be set such that it represents the negated Stc. +* +* The current Frames in returned encapsulated Region will be equivalent +* to the base Frame in the FrameSet encapsulated by the parent Region +* structure. + +* Parameters: +* this +* Pointer to the Stc. +* reg +* Address of a location to receive a pointer to the encapsulated +* Region. The current Frame in this region will be equivalent to +* the base Frame in the FrameSet +* neg +* The value of the Negated attribute to be used with reg. +* status +* Pointer to the inherited status variable. + +* Notes: +* - Any changes made to the encapsulated Region using the returned +* pointer will be reflected in the supplied Stc. + +*/ + +/* Initialise */ + if( reg ) *reg = NULL; + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Return the component Region pointers. */ + if( reg ) *reg = astClone( this->region ); + +/* Initialise the other returned items. Note, the Stc initialiser stored a + deep copy of the supplied encapsulated Region, and so we do not + need to worry about attributes of the Region having been changed + after the creation of the Stc. This is different to the CmpMap + class which merely clones its supplied component pointers and so has + to save copies of the original Invert settings within the CmpMap + structure. */ + if( neg ) *neg = astGetNegated( this->region ); + +/* If the Stc has been inverted, we modify the boolean operator and + negation flags so that they reflect the inverted Stc. */ + if( astGetNegated( this ) && neg ) *neg = *neg ? 0 : 1; +} + +static const char *GetRegionClass( AstStc *this, int *status ){ +/* +*+ +* Name: +* astGetRegionClass + +* Purpose: +* Get the value of a RegionClass attribute for a Stc. + +* Type: +* Protected function. + +* Synopsis: +* #include "stc.h" +* const char *astGetRegionClass( AstStc *this ) + +* Class Membership: +* Stc virtual function + +* Description: +* This function returns a pointer to the value of the RegionClass +* attribute for a Stc. + +* Parameters: +* this +* Pointer to the Stc. + +* Returned Value: +* - Pointer to a null-terminated string containing the attribute +* value. + +* Notes: +* - The returned string pointer may point at memory allocated +* within the Stc, 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 Stc. 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. +*- +*/ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Obtain and return the class of the encapsulated Region. */ + return astGetClass( ((AstStc *) this)->region ); +} + + +static AstKeyMap *GetStcCoord( AstStc *this, int icoord, int *status ){ +/* +*++ +* Name: +c astGetStcCoord +f AST_GETSTCCOORD + +* Purpose: +* Return information about an AstroCoords element stored in an Stc. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "specframe.h" +c AstKeyMap *astGetStcCoord( AstStc *this, int icoord ) +f RESULT = AST_GETSTCCOORD( THIS, ICOORD, STATUS ) + +* Class Membership: +* Stc method. + +* Description: +* When any sub-class of Stc is created, the constructor function +* allows one or more AstroCoords elements to be stored within the Stc. +* This function allows any one of these AstroCoords elements to be +* retrieved. The format of the returned information is the same as +* that used to pass the original information to the Stc constructor. +* That is, the information is returned in a KeyMap structure +* containing elements with one or more of the keys given by symbolic +* constants AST__STCNAME, AST__STCVALUE, AST__STCERROR, AST__STCRES, +* AST__STCSIZE and AST__STCPIXSZ. +* +* If the coordinate system represented by the Stc has been changed +* since it was created (for instance, by changing its System +* attribute), then the sizes and positions in the returned KeyMap +* will reflect the change in coordinate system. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Stc. +c icoord +f ICOORD = INTEGER (Given) +* The index of the AstroCoords element required. The first has index +* one. The number of AstroCoords elements in the Stc can be found using +c function astGetStcNcoord. +f function AST_GETSTCNCOORD. +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Returned Value: +c astGetStcCoord() +f AST_GETSTCCOORD = INTEGER +* A pointer to a new KeyMap containing the required information. + +* 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. +*-- +*/ + +/* Local Variables: */ + AstFrame *frm; + AstKeyMap *result; + AstMapping *map; + AstMapping *smap; + AstObject *obj; + AstRegion *reg; + AstRegion *rereg; + AstRegion *srereg; + int ikey; + int nc; + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Validate the supplied index. */ + nc = astGetStcNCoord( this ); + if( icoord < 1 || icoord > nc ) { + astError( AST__STCIND, "astGetStcCoord(%s): Supplied AstroCoords " + "index (%d) is invalid.", status, astGetClass( this ), icoord ); + + if( icoord < 1 ) { + astError( AST__STCIND, "The index of the first AstroCoord " + "element is one, not zero." , status); + } else if( nc == 0 ) { + astError( AST__STCIND, "There are no AstroCoords elements in " + "the supplied %s.", status, astGetClass( this ) ); + } else if( nc == 1 ) { + astError( AST__STCIND, "There is 1 AstroCoords element in " + "the supplied %s.", status, astGetClass( this ) ); + } else { + astError( AST__STCIND, "There are %d AstroCoords elements in " + "the supplied %s.", status, nc, astGetClass( this ) ); + } + +/* If the index is OK, initialise the returned KeyMap to be a copy of the + KeyMap holding information about the required AstroCoords element.*/ + } else { + result = astCopy( this->coord[ icoord - 1 ] ); + +/* The Regions stored within this KeyMap describe regions within the base + Frame of the parent Region structure. If the Mapping from base to current + Frame in the parent Region structure is not a UnitMap, we need to + change these to represent regions within the current Frame of the + parent Region structure. */ + map = astGetMapping( ((AstRegion *)this)->frameset, + AST__BASE, AST__CURRENT ); + smap = astSimplify( map ); + frm = astGetFrame( ((AstRegion *)this)->frameset, AST__CURRENT ); + +/* If the Frame represented by the Region has changed, erase the Names + element since they may no longer be correct. */ + if( !astIsAUnitMap( smap ) ) astMapRemove( result, AST__STCNAME ); + +/* Loop round keys for which a Region may be stored in the KeyMap. */ + for( ikey = 0; ikey < NREG; ikey++ ) { + +/* If the KeyMap contains a Region for this key, get a pointer to it. */ + if( astMapGet0A( result, regkey[ ikey ], &obj ) ){ + reg = (AstRegion *) obj; + +/* Sets its RegionFS attribute so that the encapsulated FrameSet will be + included in any dump of the Region. This is needed since the returned + Region pointer will have no parent Region from which the FrameSet can + be determined. */ + astSetRegionFS( reg, 1 ); + +/* If necessary, remap the Region into the current Frame, and simplify. */ + if( !astIsAUnitMap( smap ) ) { + rereg = astMapRegion( reg, smap, frm ); + srereg = astSimplify( rereg ); + rereg = astAnnul( rereg ); + } else { + srereg = astClone( reg ); + } + +/* Replace the Region in the KeyMap with the remapped Region. */ + astMapPut0A( result, regkey[ ikey ], srereg, NULL ); + +/* Free resources */ + reg = astAnnul( reg ); + srereg = astAnnul( srereg ); + } + } + + frm = astAnnul( frm ); + map = astAnnul( map ); + smap = astAnnul( smap ); + +/* Annul the returned KeyMap if an error has occurred. */ + if( !astOK ) result = astAnnul( result ); + } + +/* Return the pointer */ + return result; + +} + +static int GetStcNCoord( AstStc *this, int *status ){ +/* +*++ +* Name: +c astGetStcNCoord +f AST_GETSTCNCOORD + +* Purpose: +* Return the number of AstroCoords elements stored in an Stc. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "stc.h" +c int astGetStcNCoord( AstStc *this ) +f RESULT = AST_GETSTCNCOORD( THIS, STATUS ) + +* Class Membership: +* Stc method. + +* Description: +* This function returns the number of AstroCoords elements stored in +* an Stc. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Stc. +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Returned Value: +c astGetStcNCoord() +f AST_GETSTCNCOORD = INTEGER +* The number of AstroCoords elements stored in the Stc. + +* Notes: +* - Zero 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. +*-- +*/ + +/* Return the required value. */ + return astOK ? this->ncoord : 0; + +} + +static AstRegion *GetStcRegion( AstStc *this, int *status ) { +/* +*++ +* Name: +c astGetStcRegion +f AST_GETSTCREGION + +* Purpose: +* Obtain a copy of the encapsulated Region within a Stc. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "stc.h" +c AstRegion *astGetStcRegion( AstStc *this ) +f RESULT = AST_GETSTCREGION( THIS, STATUS ) + +* Class Membership: +* Region method. + +* Description: +* This function returns a pointer to a deep copy of the Region +* supplied when the Stc was created. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Stc. +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Returned Value: +c astGetStcRegion() +f AST_GETSTCREGION = INTEGER +* A pointer to a deep copy of the Region encapsulated within the +* supplied Stc. + +* 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. +*-- +*/ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Return a pointer to a copy of the encapsulated Region. */ + return astCopy( this->region ); +} + +static int GetUseDefs( AstObject *this_object, int *status ) { +/* +* Name: +* GetUseDefs + +* Purpose: +* Get the value of the UseDefs attribute for a Stc. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* int GetUseDefs( AstObject *this_object, int *status ) { + +* Class Membership: +* Stc member function (over-rides the protected astGetUseDefs +* method inherited from the Region class). + +* Description: +* This function returns the value of the UseDefs attribute for a +* Stc, supplying a suitable default. + +* Parameters: +* this +* Pointer to the Stc. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* - The USeDefs value. +*/ + +/* Local Variables: */ + AstStc *this; /* Pointer to the Stc structure */ + int result; /* Value to return */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the Stc structure. */ + this = (AstStc *) this_object; + +/* If the UseDefs value for the Stc has been set explicitly, use the + Get method inherited from the parent Region class to get its value. */ + if( astTestUseDefs( this ) ) { + result = (*parent_getusedefs)( this_object, status ); + +/* Otherwise, supply a default value equal to the UseDefs value of the + encapsulated Region. */ + } else { + result = astGetUseDefs( this->region ); + } + +/* Return the result. */ + return result; +} + +void astInitStcVtab_( AstStcVtab *vtab, const char *name, int *status ) { +/* +*+ +* Name: +* astInitStcVtab + +* Purpose: +* Initialise a virtual function table for a Stc. + +* Type: +* Protected function. + +* Synopsis: +* #include "stc.h" +* void astInitStcVtab( AstStcVtab *vtab, const char *name ) + +* Class Membership: +* Stc vtab initialiser. + +* Description: +* This function initialises the component of a virtual function +* table which is used by the Stc 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 */ + AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */ + AstRegionVtab *region; /* Pointer to Region 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. */ + astInitRegionVtab( (AstRegionVtab *) vtab, name ); + +/* Store a unique "magic" value in the virtual function table. This + will be used (by astIsAStc) 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 = &(((AstRegionVtab *) vtab)->id); + +/* Initialise member function pointers. */ +/* ------------------------------------ */ +/* Store pointers to the member functions (implemented here) that + provide virtual methods for this class. */ + + vtab->GetRegionClass = GetRegionClass; + vtab->GetStcRegion = GetStcRegion; + vtab->GetStcCoord = GetStcCoord; + vtab->GetStcNCoord = GetStcNCoord; + +/* Save the inherited pointers to methods that will be extended, and + replace them with pointers to the new member functions. */ + object = (AstObjectVtab *) vtab; + mapping = (AstMappingVtab *) vtab; + region = (AstRegionVtab *) vtab; + + parent_getobjsize = object->GetObjSize; + object->GetObjSize = GetObjSize; + +#if defined(THREAD_SAFE) + parent_managelock = object->ManageLock; + object->ManageLock = ManageLock; +#endif + + 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_transform = mapping->Transform; + mapping->Transform = Transform; + + parent_simplify = mapping->Simplify; + mapping->Simplify = Simplify; + + parent_setregfs = region->SetRegFS; + region->SetRegFS = SetRegFS; + + parent_equal = object->Equal; + object->Equal = Equal; + + parent_clearclosed = region->ClearClosed; + region->ClearClosed = ClearClosed; + + parent_setclosed = region->SetClosed; + region->SetClosed = SetClosed; + + region->TestClosed = TestClosed; + region->GetClosed = GetClosed; + + parent_regsetattrib = region->RegSetAttrib; + region->RegSetAttrib = RegSetAttrib; + + parent_regclearattrib = region->RegClearAttrib; + region->RegClearAttrib = RegClearAttrib; + + parent_clearnegated = region->ClearNegated; + region->ClearNegated = ClearNegated; + + parent_setnegated = region->SetNegated; + region->SetNegated = SetNegated; + + region->TestNegated = TestNegated; + region->GetNegated = GetNegated; + + parent_setmeshsize = region->SetMeshSize; + region->SetMeshSize = SetMeshSize; + + parent_clearmeshsize = region->ClearMeshSize; + region->ClearMeshSize = ClearMeshSize; + + region->TestMeshSize = TestMeshSize; + region->GetMeshSize = GetMeshSize; + + parent_setfillfactor = region->SetFillFactor; + region->SetFillFactor = SetFillFactor; + + parent_clearfillfactor = region->ClearFillFactor; + region->ClearFillFactor = ClearFillFactor; + + region->TestFillFactor = TestFillFactor; + region->GetFillFactor = GetFillFactor; + + parent_getusedefs = object->GetUseDefs; + object->GetUseDefs = GetUseDefs; + + parent_getdefunc = region->GetDefUnc; + region->GetDefUnc = GetDefUnc; + +/* Store replacement pointers for methods which will be over-ridden by + new member functions implemented here. */ + region->Overlap = Overlap; + region->OverlapX = OverlapX; + region->RegBaseBox = RegBaseBox; + region->RegBaseMesh = RegBaseMesh; + region->RegBasePick = RegBasePick; + region->RegPins = RegPins; + region->GetBounded = GetBounded; + +/* Declare the copy constructor, destructor and class dump function. */ + astSetCopy( vtab, Copy ); + astSetDelete( vtab, Delete ); + astSetDump( vtab, Dump, "Stc", "An IVOA Space-Time-Coords object" ); + +/* 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 AstKeyMap *MakeAstroCoordsKeyMap( AstRegion *reg, AstKeyMap *coord, + const char *class, int *status ){ +/* +* Name: +* MakeAstroCoordsKeyMap + +* Purpose: +* Create a new KeyMap holding Regions describing a supplied +* AstroCoords element. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* AstKeyMap *MakeAstroCoordsKeyMap( AstRegion *reg, AstKeyMap *coord, +* const char *class, int *status ) + +* Class Membership: +* Stc member function + +* Description: +* This function returns a pointer to a new KeyMap containing elements +* which correspond to the components of an STC AstroCoords element. +* The element with key AST__STCNAME holds a vector of character +* strings containing the names associated with each of the axies. +* The other elements of the returned KeyMap such as AST__STCERROR, +* AST__STCRES, etc, hold pointers to Regions describing the error +* box, resolution, etc, in the Frame of the supplied Region "reg". + +* Parameters: +* reg +* Pointer to the Region in which the AstroCoords is defined. +* coordId +* An ID (not a pointer) to a KeyMap defining a single <AstroCoords> +* element, having elements with keys given by constants AST__STCNAME, +* AST__STCVALUE, AST__STCERROR, AST__STCRES, AST__STCSIZE, +* AST__STCPIXSZ. Any of these elements may be omitted, but no other +* elements should be included. If supplied, the AST__STCNAME element +* should be a vector of character string pointers holding the "Name" +* item for each axis. Any other supplied elements should be scalar +* elements, each holding a pointer to a Region describing the +* associated item of ancillary information (error, resolution, size, +* pixel size or value). These Regions should refer to the coordinate +* system represented by "region". +* class +* Pointer to a string holding the STC class name. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* - Pointer to the new KeyMap. + +* 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: */ + AstFrame *frm; /* Pointer to current Frame */ + AstFrameSet *fs; /* Pointer to conversion FrameSet */ + AstKeyMap *result; /* Pointer value to return */ + AstMapping *map; /* Pointer to conversion Mapping */ + AstObject *obj; /* Pointer to Object stored in supplied KeyMap */ + AstRegion *areg; /* Pointer to remapped Region */ + AstRegion *sareg; /* Pointer to simplified remapped Region */ + const char *key; /* Current key */ + int j; /* Index of key within KeyMap */ + int naxes; /* Number of axes in region */ + int nkey; /* Number of keys in supplied KeyMap */ + int nv; /* Number of values in KeyMap element */ + int type; /* Data type of entry */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if( !astOK ) return result; + +/* Confirm it is a genuine KeyMap pointer. */ + if( !astIsAKeyMap( coord ) && astOK ) { + astError( AST__STCKEY, "astInitStc(%s): Supplied pointer is for " + "a %s, not a KeyMap.", status, class, astGetClass( coord ) ); + } + +/* Initialise the new KeyMap to be a copy of the supplied KeyMap. */ + result = astCopy( coord ); + +/* Check the supplied KeyMap is usable. */ + naxes = astGetNaxes( reg ); + nkey = astMapSize( result ); + for( j = 0; j < nkey; j++ ) { + key = astMapKey( result, j ); + if( key ) { + nv = astMapLength( result, key ); + type = astMapType( result, key ); + +/* Check no unknown keys are present in the KeyMap. */ + if( strcmp( key, AST__STCNAME ) && + strcmp( key, AST__STCVALUE ) && + strcmp( key, AST__STCERROR ) && + strcmp( key, AST__STCRES ) && + strcmp( key, AST__STCSIZE ) && + strcmp( key, AST__STCPIXSZ ) ) { + astError( AST__STCKEY, "astInitStc(%s): Unknown key " + "\"%s\" supplied in an AstroCoords list.", status, + class, key ); + break; + +/* Check that the "Name" element is a vector of "naxes" strings. */ + } else if( !strcmp( key, AST__STCNAME ) ) { + if( nv != naxes ) { + astError( AST__STCKEY, "astInitStc(%s): %d \"%s\" " + "values supplied in an AstroCoords list, but " + "the Stc has %d axes. ", status, class, nv, key, + naxes ); + break; + + } else if( type != AST__STRINGTYPE ) { + astError( AST__STCKEY, "astInitStc(%s): The \"%s\" " + "values supplied in an AstroCoords list are " + "not character strings. ", status, class, key ); + break; + } + +/* Check that all other elements are scalar. */ + } else if( nv != 1 ) { + astError( AST__STCKEY, "astInitStc(%s): %d \"%s\" " + "values supplied in an AstroCoords list, but " + "only one is allowed. ", status, class, nv, key ); + break; + +/* Check that all other elements are AST Object pointers. */ + } else if( type != AST__OBJECTTYPE ) { + astError( AST__STCKEY, "astInitStc(%s): The \"%s\" " + "value supplied in an AstroCoords list is " + "not an AST Object pointer. ", status, class, key ); + break; + +/* Check that the Object pointers are not NULL. */ + } else { + astMapGet0A( result, key, &obj ); + if( astOK ) { + if( !obj ) { + astError( AST__STCKEY, "astInitStc(%s): The \"%s\" " + "value supplied in an AstroCoords list is " + "a NULL pointer. ", status, class, key ); + break; + +/* Check that the Object pointers are Region pointers. */ + } else if( !astIsARegion( obj ) ){ + astError( AST__STCKEY, "astInitStc(%s): The \"%s\" " + "value supplied in an AstroCoords list is " + "a %s, not a Region. ", status, class, key, + astGetClass(obj) ); + obj = astAnnul( obj ); + break; + +/* Check that the Region pointers can be converted to the coordinate + system represented by the supplied Region. */ + } else { + fs = astConvert( obj, reg, "" ); + if( !fs ) { + obj = astAnnul( obj ); + astError( AST__STCKEY, "astInitStc(%s): The \"%s\" " + "value supplied in an AstroCoords list " + "cannot be converted to the coordinate " + "system of its parent Stc object.", status, class, + key ); + break; + +/* If necessary, map the Region into the same frame as the supplied + Region, and replace the Region in the returned KeyMap with the + remapped Region. Also set the RegionFS attribute to indicate that the + FrameSet in the Region does not need to be dumped if it contains a + UnitMap. */ + } else { + map = astGetMapping( fs, AST__BASE, AST__CURRENT ); + if( !astIsAUnitMap( map ) ) { + frm = astGetFrame( fs, AST__CURRENT ); + areg = astMapRegion( (AstRegion *) obj, map, frm ); + sareg = astSimplify( areg ); + astSetRegionFS( sareg, 0 ); + astMapPut0A( result, key, sareg, NULL ); + areg = astAnnul( areg ); + sareg = astAnnul( sareg ); + frm = astAnnul( frm ); + } else { + astSetRegionFS( (AstRegion *) obj, 0 ); + } + map = astAnnul( map ); + fs = astAnnul( fs ); + + } + obj = astAnnul( obj ); + } + } + } + } + } + +/* Free the returned KeyMap if an error has occurred. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the result */ + return result; + +} + +#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: +* Stc 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: */ + AstStc *this; /* Pointer to STC structure */ + int i; /* Loop count */ + 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 STC structure. */ + this = (AstStc *) 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->region, mode, extra, fail ); + for( i = 0; i < this->ncoord; i++ ) { + if( !result ) result = astManageLock( this->coord[ i ], mode, + extra, fail ); + } + + return result; + +} +#endif + +static int Overlap( AstRegion *this, AstRegion *that, int *status ){ +/* +* Name: +* Overlap + +* Purpose: +* Test if two regions overlap each other. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* int Overlap( AstRegion *this, AstRegion *that, int *status ) + +* Class Membership: +* Stc member function (over-rides the astOverlap method inherited +* from the Region class). + +* Description: +* This function returns an integer value indicating if the two +* supplied Regions overlap. The two Regions are converted to a commnon +* coordinate system before performing the check. If this conversion is +* not possible (for instance because the two Regions represent areas in +* different domains), then the check cannot be performed and a zero value +* is returned to indicate this. + +* Parameters: +* this +* Pointer to the first Region. +* that +* Pointer to the second Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* astOverlap() +* A value indicating if there is any overlap between the two Regions. +* Possible values are: +* +* 0 - The check could not be performed because the second Region +* could not be mapped into the coordinate system of the first +* Region. +* +* 1 - There is no overlap between the two Regions. +* +* 2 - The first Region is completely inside the second Region. +* +* 3 - The second Region is completely inside the first Region. +* +* 4 - There is partial overlap between the two Regions. +* +* 5 - The Regions are identical. +* +* 6 - The second Region is the negation of the first Region. + +* Notes: +* - The returned values 5 and 6 do not check the value of the Closed +* attribute in the two Regions. +* - A value of zero will be returned if this function is invoked with the +* AST error status set, or if it should fail for any reason. + +*/ + +/* Check the inherited status. */ + if ( !astOK ) return 0; + +/* Invoke the "astOverlap" method on the encapsulated Region. */ + return astOverlap( ((AstStc *)this)->region, that ); +} + +static int OverlapX( AstRegion *that, AstRegion *this, int *status ){ +/* +* Name: +* OverlapX + +* Purpose: +* Test if two regions overlap each other. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* int OverlapX( AstRegion *that, AstRegion *this ) + +* Class Membership: +* Stc member function (over-rides the astOverlapX method inherited +* from the Region class). + +* Description: +* This function performs the processing for the public astOverlap +* method and has exactly the same interface except that the order +* of the two arguments is swapped. This is a trick to allow +* the astOverlap method to be over-ridden by derived classes on +* the basis of the class of either of its two arguments. +* +* See the astOverlap method for details of the interface. + +*/ + +/* Local Variables: */ + int result; + +/* Check the inherited status. */ + if ( !astOK ) return 0; + +/* Invoke the "astOverlapX" method on the encapsulated Region. */ + result = astOverlap( ((AstStc *)that)->region, this ); + +/* Swap the returned values 2 and 3 to take account of the swapping of + the regions.*/ + if( result == 2 ) { + result = 3; + } else if( result == 3 ) { + result = 2; + } + +/* Return the result. */ + return result; +} + +static void RegBaseBox( AstRegion *this, double *lbnd, double *ubnd, int *status ){ +/* +* Name: +* RegBaseBox + +* Purpose: +* Returns the bounding box of an un-negated Region in the base Frame of +* the encapsulated FrameSet. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* void RegBaseBox( AstRegion *this, double *lbnd, double *ubnd, int *status ) + +* Class Membership: +* Stc member function (over-rides the astRegBaseBox protected +* method inherited from the Region class). + +* Description: +* This function returns the upper and lower axis bounds of a Region in +* the base Frame of the encapsulated FrameSet, assuming the Region +* has not been negated. That is, the value of the Negated attribute +* is ignored. + +* Parameters: +* this +* Pointer to the Region. +* lbnd +* Pointer to an array in which to return the lower axis bounds +* covered by the Region in the base Frame of the encapsulated +* FrameSet. It should have at least as many elements as there are +* axes in the base Frame. +* ubnd +* Pointer to an array in which to return the upper axis bounds +* covered by the Region in the base Frame of the encapsulated +* FrameSet. It should have at least as many elements as there are +* axes in the base Frame. +* status +* Pointer to the inherited status variable. + +*/ + +/* Check the global error status. */ + if( !astOK ) return; + +/* Invoke the method on the encapsulated Region. */ + astRegBaseBox( ((AstStc *)this)->region, lbnd, ubnd ); +} + +static AstPointSet *RegBaseMesh( AstRegion *this, int *status ){ +/* +* Name: +* RegBaseMesh + +* Purpose: +* Create a new PointSet containing a mesh of points on the boundary of a +* Region in its base Frame. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* AstPointSet *astRegBaseMesh( AstRegion *this, int *status ) + +* Class Membership: +* Stc member function (over-rides the astRegBaseMesh protected +* method inherited from the Region class). + +* Description: +* This function creates a new PointSet containing a mesh of points on the +* boundary of the Region. The points refer to the base Frame of +* the encapsulated FrameSet. + +* Parameters: +* this +* Pointer to the Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* Pointer to the PointSet. Annul the pointer using astAnnul when it +* is no longer needed. + +* Notes: +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. + +*/ + +/* Check the global error status. */ + if( !astOK ) return NULL; + +/* Invoke the astRegMesh method on the encapsulated Region. This returns + a mesh in the current Frame of the encapsulated Region which is the same + as the base Frame of the Stc Region. */ + return astRegMesh( ((AstStc *)this)->region ); +} + +static AstRegion *RegBasePick( AstRegion *this_region, int naxes, + const int *axes, int *status ){ +/* +* Name: +* RegBasePick + +* Purpose: +* Return a Region formed by picking selected base Frame axes from the +* supplied Region. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* AstRegion *RegBasePick( AstRegion *this, int naxes, const int *axes, +* int *status ) + +* Class Membership: +* Stc member function (over-rides the astRegBasePick protected +* method inherited from the Region class). + +* Description: +* This function attempts to return a Region that is spanned by selected +* axes from the base Frame of the encapsulated FrameSet of the supplied +* Region. This may or may not be possible, depending on the class of +* Region. If it is not possible a NULL pointer is returned. + +* Parameters: +* this +* Pointer to the Region. +* naxes +* The number of base Frame axes to select. +* axes +* An array holding the zero-based indices of the base Frame axes +* that are to be selected. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* Pointer to the Region, or NULL if no region can be formed. + +* Notes: +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. +*/ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Invoke the astRegBaePick method on the encapsulated Region. */ + return astRegBasePick( ((AstStc *)this_region)->region, naxes, axes ); +} + +static void RegClearAttrib( AstRegion *this_region, const char *attrib, + char **base_attrib, int *status ) { +/* +* Name: +* RegClearAttrib + +* Purpose: +* Clear an attribute value for a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "stc.h" +* void RegClearAttrib( AstRegion *this, const char *attrib, +* char **base_attrib, int *status ) + +* Class Membership: +* Stc method (over-rides the astRegClearAttrib method inherited from +* the Region class). + +* Description: +* This function clears the value of an attribute in both the base and +* current Frame in the FrameSet encapsulated within a Region, without +* remapping either Frame. +* +* No error is reported if the attribute is not recognised by the base +* Frame. + +* Parameters: +* this +* Pointer to the Region. +* attrib +* Pointer to a null terminated string containing an attribute name. +* NOTE, IT SHOULD BE ENTIRELY LOWER CASE. +* base_attrib +* Address of a location at which to return a pointer to the null +* terminated string holding the name of the attribute which was +* cleared in the base Frame of the encapsulated FrameSet. This may +* differ from the supplied name if the supplied name contains an axis +* index and the current->base Mapping in the FrameSet produces an +* axis permutation. The returned pointer should be freed using +* astFree when no longer needed. A NULL pointer may be supplied in +* which case no pointer is returned. +* status +* Pointer to the inherited status variable. + +*/ + +/* Local Variables: */ + AstStc *this; + char *batt; + int rep; + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Get a pointer to the Stc structure. */ + this = (AstStc *) this_region; + +/* Use the RegClearAttrib method inherited from the parent class to clear + the attribute in the current and base Frames in the FrameSet encapsulated + by the parent Region structure. */ + (*parent_regclearattrib)( this_region, attrib, &batt, status ); + +/* Now clear the base Frame attribute in the encapsulated Region (the current + Frame within the encapsulated Region is equivalent to the base Frame in the + parent Region structure). Annul any "attribute unknown" error that results + from attempting to do this. */ + if( astOK ) { + rep = astReporting( 0 ); + astRegClearAttrib( this->region, batt, NULL ); + if( astStatus == AST__BADAT ) astClearStatus; + astReporting( rep ); + } + +/* If required, return the base Frame attribute name, otherwise free it. */ + if( base_attrib ) { + *base_attrib = batt; + } else { + batt = astFree( batt ); + } +} + +static int RegPins( AstRegion *this, AstPointSet *pset, AstRegion *unc, + int **mask, int *status ){ +/* +* Name: +* RegPins + +* Purpose: +* Check if a set of points fall on the boundary of a given Stc. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* int RegPins( AstRegion *this, AstPointSet *pset, AstRegion *unc, +* int **mask, int *status ) + +* Class Membership: +* Stc member function (over-rides the astRegPins protected +* method inherited from the Region class). + +* Description: +* This function returns a flag indicating if the supplied set of +* points all fall on the boundary of the given Stc. +* +* Some tolerance is allowed, as specified by the uncertainty Region +* stored in the supplied Stc "this", and the supplied uncertainty +* Region "unc" which describes the uncertainty of the supplied points. + +* Parameters: +* this +* Pointer to the Stc. +* pset +* Pointer to the PointSet. The points are assumed to refer to the +* base Frame of the FrameSet encapsulated by "this". +* unc +* Pointer to a Region representing the uncertainties in the points +* given by "pset". The Region is assumed to represent the base Frame +* of the FrameSet encapsulated by "this". Zero uncertainity is assumed +* if NULL is supplied. +* mask +* Pointer to location at which to return a pointer to a newly +* allocated dynamic array of ints. The number of elements in this +* array is equal to the value of the Npoint attribute of "pset". +* Each element in the returned array is set to 1 if the +* corresponding position in "pset" is on the boundary of the Region +* and is set to zero otherwise. A NULL value may be supplied +* in which case no array is created. If created, the array should +* be freed using astFree when no longer needed. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* Non-zero if the points all fall on the boundary of the given +* Region, to within the tolerance specified. Zero otherwise. + +*/ + +/* Check the global error status. */ + if( !astOK ) return 0; + +/* Invoke the method on the encapsulated Region. */ + return astRegPins( ((AstStc *)this)->region, pset, unc, mask ); +} + +static void RegSetAttrib( AstRegion *this_region, const char *setting, + char **base_setting, int *status ) { +/* +* Name: +* RegSetAttrib + +* Purpose: +* Set an attribute value for a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* void RegSetAttrib( AstRegion *this, const char *setting, +* char **base_setting, int *status ) + +* Class Membership: +* Stc method (over-rides the astRegSetAttrib method inherited from +* the Region class). + +* Description: +* This function assigns an attribute value to both the base and +* current Frame in the FrameSet encapsulated within a Region, without +* remapping either Frame. +* +* No error is reported if the attribute is not recognised by the base +* Frame. + +* Parameters: +* this +* Pointer to the Region. +* setting +* Pointer to a null terminated attribute setting string. NOTE, IT +* SHOULD BE ENTIRELY LOWER CASE. The supplied string will be +* interpreted using the public interpretation implemented by +* astSetAttrib. This can be different to the interpretation of the +* protected accessor functions. For instance, the public +* interpretation of an unqualified floating point value for the +* Epoch attribute is to interpet the value as a gregorian year, +* but the protected interpretation is to interpret the value as an +* MJD. +* base_setting +* Address of a location at which to return a pointer to the null +* terminated attribute setting string which was applied to the +* base Frame of the encapsulated FrameSet. This may differ from +* the supplied setting if the supplied setting contains an axis +* index and the current->base Mapping in the FrameSet produces an +* axis permutation. The returned pointer should be freed using +* astFree when no longer needed. A NULL pointer may be supplied in +* which case no pointer is returned. +* status +* Pointer to the inherited status variable. + +*/ + +/* Local Variables: */ + AstKeyMap *keymap; + AstObject *obj; + AstRegion *reg; + AstStc *this; + char *bset; + int i; + int ikey; + int rep; + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Get a pointer to the Stc structure. */ + this = (AstStc *) this_region; + +/* Use the RegSetAttrib method inherited from the parent class to apply the + setting to the current and base Frames in the FrameSet encapsulated by the + parent Region structure. */ + (*parent_regsetattrib)( this_region, setting, &bset, status ); + +/* Now apply the base Frame setting to the encapsulated Region (the current + Frame within the encapsulated Region is equivalent to the base Frame in the + parent Region structure). Annul any "attribute unknown" error that results + from attempting to do this. Also do any AstroCoords in the Stc. */ + if( astOK ) { + rep = astReporting( 0 ); + astRegSetAttrib( this->region, bset, NULL ); + if( astStatus == AST__BADAT ) astClearStatus; + +/* Loop round all AstroCoords elements. */ + for( i = 0; i < this->ncoord; i++ ) { + +/* Get a pointer to the KeyMap holding a description of the current + AstroCoords element. */ + keymap = this->coord[ i ]; + +/* Loop round all the elements of this KeyMap which may hold a Region + pointer. */ + for( ikey = 0; ikey < NREG; ikey++ ) { + +/* If the KeyMap contains a Region for this key, get a pointer to it. */ + if( astMapGet0A( keymap, regkey[ ikey ], &obj ) ){ + reg = (AstRegion *) obj; + +/* Modify it by applying the attribute setting. */ + astRegSetAttrib( reg, bset, NULL ); + if( astStatus == AST__BADAT ) astClearStatus; + +/* Annul the pointer. */ + reg = astAnnul( reg ); + } + } + } + + astReporting( rep ); + } + +/* If required, return the base Frame setting string, otherwise free it. */ + if( base_setting ) { + *base_setting = bset; + } else { + bset = astFree( bset ); + } +} + +static void SetAttrib( AstObject *this_object, const char *setting, int *status ) { +/* +* Name: +* SetAttrib + +* Purpose: +* Set an attribute value for a Stc. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* void SetAttrib( AstObject *this, const char *setting, int *status ) + +* Class Membership: +* Stc member function (over-rides the astSetAttrib method inherited +* from the Region class). + +* Description: +* This function assigns an attribute value for a Stc, 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 Stc. +* setting +* Pointer to a null terminated string specifying the new attribute +* value. +* 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 Vaiables: */ + AstStc *this; /* Pointer to the Stc structure */ + int len; /* Length of setting string */ + int nc; /* Number of characters read by astSscanf */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Stc structure. */ + this = (AstStc *) this_object; + +/* Obtain the length of the setting string. */ + len = strlen( setting ); + +/* Test for each recognised attribute in turn, using "astSscanf" to parse the + setting string and extract the attribute value (or an offset to it in the + case of string values). In each case, use the value set in "nc" to check + that the entire string was matched. Once a value has been obtained, use the + appropriate method to set it. */ + +/* (none as yet) */ + +/* Read-only attributes. */ +/* --------------------- */ +/* Define a macro to see if the setting string matches any of the + read-only attributes of this class. */ +#define MATCH(attrib) \ + ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \ + ( nc >= len ) ) + +/* Use this macro to report an error if a read-only attribute has been + specified. */ + if ( MATCH( "regionclass" ) ) { + astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status, + setting, astGetClass( this ) ); + astError( AST__NOWRT, "This is a read-only attribute." , status); + +/* Not recognised. */ +/* --------------- */ +/* If the attribute is still not recognised, pass it on to the parent + method for further interpretation. */ + } else { + (*parent_setattrib)( this_object, setting, status ); + } + +/* Undefine macros local to this function. */ +#undef MATCH +} + +static void SetRegFS( AstRegion *this_region, AstFrame *frm, int *status ) { +/* +* Name: +* SetRegFS + +* Purpose: +* Stores a new FrameSet in a Region + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* void SetRegFS( AstRegion *this_region, AstFrame *frm, int *status ) + +* Class Membership: +* Stc method (over-rides the astSetRegFS method inherited from +* the Region class). + +* Description: +* This function creates a new FrameSet and stores it in the supplied +* Region. The new FrameSet contains two copies of the supplied +* Frame, connected by a UnitMap. + +* Parameters: +* this +* Pointer to the Region. +* frm +* The Frame to use. +* status +* Pointer to the inherited status variable. + +*/ + +/* Local Variables: */ + AstRegion *creg; /* Pointer to encapsulated Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Invoke the parent method to store the FrameSet in the parent Region + structure. */ + (* parent_setregfs)( this_region, frm, status ); + +/* If the encapsulated Region has a dummy FrameSet use this method + recursively to give it the same FrameSet. */ + creg = ((AstStc *) this_region )->region; + if( creg && !astGetRegionFS( creg ) ) astSetRegFS( creg, frm ); + +} + +static AstMapping *Simplify( AstMapping *this_mapping, int *status ) { +/* +* Name: +* Simplify + +* Purpose: +* Simplify a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstMapping *Simplify( AstMapping *this, int *status ) + +* Class Membership: +* Stc method (over-rides the astSimplify method inherited from +* the Region class). + +* Description: +* This function simplifies a Stc to eliminate redundant +* computational steps, or to merge separate steps which can be +* performed more efficiently in a single operation. + +* Parameters: +* this +* Pointer to the original Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* A new pointer to the (possibly simplified) Region. + +* 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: */ + AstFrame *frm; /* Current Frame */ + AstKeyMap *keymap; /* KeyMap holding stroCoords element */ + AstMapping *map; /* Base->current Mapping */ + AstObject *obj; /* Pointer to object retrieved from keymap */ + AstRegion *newreg; /* New encapsulated Region */ + AstRegion *reg; /* AstroCoords Region pointer */ + AstRegion *treg; /* Temporary Region pointer */ + AstStc *stc; /* Returned Stc Structure. */ + AstStc *temp; /* Temporary Stc pointer */ + int i; /* Index of current AstroCoords element */ + int ikey; /* Index of key to be tested */ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Invoke the Simplify method of the parent Region class. This simplifies + the FrameSet and uncertainty Region in the parent Region structure. */ + stc = (AstStc *) (AstRegion *) (* parent_simplify)( this_mapping, status ); + +/* If the Stc is negated, we can perform a simplication by transferring + the negated state from the Stc itself to the encapsulated Region. */ + if( astGetNegated( stc ) ) { + +/* Ensure that modifying "stc" will not modify the supplied Stc, by + creating a copy of the supplied Stc, if this has not already been done. */ + if( stc == (AstStc *) this_mapping ) { + temp = (AstStc *) astCopy( stc ); + (void) astAnnul( stc ); + stc = temp; + } + +/* Modify "temp" by negating both the Stc structure and its encapsulated + Region. */ + astNegate( stc ); + astNegate( stc->region ); + + } + +/* Get the base->current Mapping from the parent Region structure, and + the current Frame. */ + map = astGetMapping( ((AstRegion *) stc)->frameset, AST__BASE, AST__CURRENT ); + frm = astGetFrame( ((AstRegion *) stc)->frameset, AST__CURRENT ); + +/* We may be able to perform some more simplication on the encapsulated + Region itself. If the above mapping is not a unit map, remap the + encapsulated Region into the current Frame of the parent Region structure + and simplify it. This transfers complication from the Mapping in the + parent Region structure to the encapsulated Region. */ + if( !astIsAUnitMap( map ) ) { + treg = astMapRegion( stc->region, map, frm ); + newreg = astSimplify( treg ); + treg = astAnnul( treg ); + +/* If the base->current Mapping in the parent Region structure is a unit + map, simplification of the whole Stc is possible if the encapsulated + Region (without any remapping) can be simplied. */ + } else { + newreg = astSimplify( stc->region ); + } + +/* If the encapsulated Region has been changed, store it in the returned + Stc. */ + if( newreg != stc->region ) { + +/* Ensure that modifying "stc" will not modify the supplied Stc, by + creating a copy of the supplied Stc, if this has not already been done. */ + if( stc == (AstStc *) this_mapping ) { + temp = (AstStc *) astCopy( stc ); + (void) astAnnul( stc ); + stc = temp; + } + +/* Store the new region in "stc", annulling the existing Region. */ + if( stc ) { + (void) astAnnul( stc->region ); + stc->region = astClone( newreg ); + } + +/* The encapsulated Region now represents an area in the current Frame + represented by the supplied Stc. Since the encapsulated Region is + defined as being in the base Frame of the FrameSet in the parent + Region structure, the parent FrameSet should just be a UnitMap. Modify + it appropriately (if it not already a UnitMap). */ + if( !astIsAUnitMap( map ) ) astSetRegFS( stc, frm ); + } + +/* Free resources */ + newreg = astAnnul( newreg ); + +/* Now we do a similar process on any Regions held within an AstroCoords + elements. Loop round all AstroCoords elements. */ + if( stc ) { + for( i = 0; i < stc->ncoord; i++ ) { + +/* Get a pointewr to the KeyMap holding a description of the current + AstroCoords element. */ + keymap = stc->coord[ i ]; + +/* Loop round all the elements of this KeyMap which may hold a Region + pointer. */ + for( ikey = 0; ikey < NREG; ikey++ ) { + +/* If the KeyMap contains a Region for this key, get a pointer to it. */ + if( astMapGet0A( keymap, regkey[ ikey ], &obj ) ){ + reg = (AstRegion *) obj; + +/* We have two tasks now, firstly to ensure that this AstroCoords Region + describes an area in the base Frame of the FrameSet in the parent + Region structure (which may have been changed by the earlier + simplications performed by this function), and secondly, to attempt to + simplify the Region. + + The Stc structure addressed by the "stc" pointer will have a current + Frame given by "frm". This will also be its base Frame, and the + base->current Mapping will consequently be a UnitMap. The Mapping from + the original base Frame to the new base Frame is given by "map". Unless + this is a UnitMap, we need to remap the Region.*/ + if( !astIsAUnitMap( map ) ) { + treg = astMapRegion( reg, map, frm ); + } else { + treg = astClone( reg ); + } + +/* Now attempt to simplify the Region.*/ + newreg = astSimplify( treg ); + +/* If the Region has been changed by either of these steps, we need to + store the modified Region back in the "stc" structure which is being + returned. But we need to be careful we do not modify the supplied Stc + structure. */ + if( newreg != reg ) { + + if( stc == (AstStc *) this_mapping ) { + temp = astCopy( stc ); + (void) astAnnul( stc ); + stc = temp; + keymap = temp->coord[ i ]; + } + + astMapPut0A( keymap, regkey[ ikey ], newreg, regcom[ ikey ] ); + + } + +/* Free resources */ + reg = astAnnul( reg ); + treg = astAnnul( treg ); + newreg = astAnnul( newreg ); + + } + } + } + } + +/* Free resources */ + map = astAnnul( map ); + frm = astAnnul( frm ); + +/* If an error occurred, annul the returned Mapping. */ + if ( !astOK ) stc = astAnnul( stc ); + +/* Return the result. */ + return (AstMapping *) stc; +} + +static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) { +/* +* Name: +* TestAttrib + +* Purpose: +* Test if a specified attribute value is set for a Stc. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* int TestAttrib( AstObject *this, const char *attrib, int *status ) + +* Class Membership: +* Stc member function (over-rides the astTestAttrib protected +* method inherited from the Region class). + +* Description: +* This function returns a boolean result (0 or 1) to indicate whether +* a value has been set for one of a Stc's attributes. + +* Parameters: +* this +* Pointer to the Stc. +* 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: */ + AstStc *this; /* Pointer to the Stc structure */ + int len; /* Length of attrib string */ + int result; /* Result value to return */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the Stc structure. */ + this = (AstStc *) this_object; + +/* Obtain the length of the attrib string. */ + len = strlen( attrib ); + +/* Check the attribute name and test the appropriate attribute. */ + +/* Read-only attributes. */ +/* --------------------- */ +/* Test if the attribute name matches any of the read-only attributes + of this class. If it does, then return zero. */ + if ( !strcmp( attrib, "regionclass" ) ) { + result = 0; + +/* Not recognised. */ +/* --------------- */ +/* If the attribute is still not recognised, pass it on to the parent + method for further interpretation. */ + } else { + result = (*parent_testattrib)( this_object, attrib, status ); + } + +/* Return the result, */ + return result; +} + +static AstPointSet *Transform( AstMapping *this_mapping, AstPointSet *in, + int forward, AstPointSet *out, int *status ) { +/* +* Name: +* Transform + +* Purpose: +* Apply a Stc to transform a set of points. + +* Type: +* Private function. + +* Synopsis: +* #include "stc.h" +* AstPointSet *Transform( AstMapping *this, AstPointSet *in, +* int forward, AstPointSet *out, int *status ) + +* Class Membership: +* Stc member function (over-rides the astTransform method inherited +* from the Region class). + +* Description: +* This function takes a Stc and a set of points encapsulated in a +* PointSet and transforms the points so as to apply the required Region. +* This implies applying each of the Stc's encapsulated Region in turn, +* either in series or in parallel. + +* Parameters: +* this +* Pointer to the Stc. +* in +* Pointer to the PointSet associated with the input coordinate values. +* 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: +* - 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. +* - The number of coordinate values per point in the input PointSet must +* match the number of coordinates for the Stc being applied. +* - If an output PointSet is supplied, it must have space for sufficient +* number of points and coordinate values per point to accommodate the +* result. Any excess space will be ignored. +*/ + +/* Local Variables: */ + AstPointSet *ps; /* Pointer to PointSet */ + AstPointSet *pset_tmp; /* Pointer to PointSet holding base Frame positions*/ + AstPointSet *result; /* Pointer to output PointSet */ + AstRegion *reg; /* Pointer to encapsulated Region */ + AstStc *this; /* Pointer to the Stc structure */ + double **ptr; /* Pointer to axis values */ + double **ptr_out; /* Pointer to output coordinate data */ + int coord; /* Zero-based index for coordinates */ + int good; /* Is the point inside the Stc? */ + int ncoord_out; /* No. of coordinates per output point */ + int ncoord_tmp; /* No. of coordinates per base Frame point */ + int neg; /* Negated value for encapsulated Region */ + int neg_old; /* Original Negated flag */ + int npoint; /* No. of points */ + int point; /* Loop counter for points */ + int rep; /* Original error reporting status */ + int status_value; /* AST status value */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Get a Pointer to the Stc structure */ + this = (AstStc *) this_mapping; + +/* Get the encapsulated Region, and the Negated value which should be used + with it. The returned values take account of whether the supplied Stc has + itself been Negated or not. The returned Region represent a region within + the base Frame of the FrameSet encapsulated by the parent Region + structure. */ + GetRegion( this, ®, &neg, status ); + +/* Temporarily set the Negated attribute to the required value.*/ + neg_old = astGetNegated( reg ); + astSetNegated( reg, neg ); + +/* Apply the parent mapping using the stored pointer to the Transform member + function inherited from the parent Region class. This function validates + all arguments and generates an output PointSet if necessary, containing + a copy of the input PointSet. */ + result = (*parent_transform)( this_mapping, in, forward, out, status ); + +/* We will now extend the parent astTransform method by performing the + calculations needed to generate the output coordinate values. */ + +/* First use the encapsulated FrameSet in the parent Region structure to + transform the supplied positions from the current Frame in the + encapsulated FrameSet (the Frame represented by the Stc), to the + base Frame (the Frame in which the encapsulated Region are defined). Note, + the returned pointer may be a clone of the "in" pointer, and so we + must be carefull not to modify the contents of the returned PointSet. */ + pset_tmp = astRegTransform( this, in, 0, NULL, NULL ); + +/* Now transform this PointSet using the encapsulated Region. */ + ps = astTransform( reg, pset_tmp, 0, NULL ); + +/* Determine the numbers of points and coordinates per point for these base + Frame PointSets and obtain pointers for accessing the base Frame and output + coordinate values. */ + npoint = astGetNpoint( pset_tmp ); + ncoord_tmp = astGetNcoord( pset_tmp ); + ptr = astGetPoints( ps ); + ncoord_out = astGetNcoord( result ); + ptr_out = astGetPoints( result ); + +/* Perform coordinate arithmetic. */ +/* ------------------------------ */ + if ( astOK ) { + + for ( point = 0; point < npoint; point++ ) { + good = 0; + + for ( coord = 0; coord < ncoord_tmp; coord++ ) { + if( ptr[ coord ][ point ] != AST__BAD ) { + good = 1; + break; + } + } + + if( !good ) { + for ( coord = 0; coord < ncoord_out; coord++ ) { + ptr_out[ coord ][ point ] = AST__BAD; + } + } + } + } + +/* Re-instate the original value for the Negated attribute of the + encapsulated Region. Do this even if an error has occurred. */ + status_value = astStatus; + astClearStatus; + rep = astReporting( 0 ); + if( reg ) astSetNegated( reg, neg_old ); + astReporting( rep ); + astSetStatus( status_value ); + +/* Free resources. */ + reg = astAnnul( reg ); + ps = astAnnul( ps ); + pset_tmp = astAnnul( pset_tmp ); + +/* If an error occurred, clean up by deleting the output PointSet (if + allocated by this function) and setting a NULL result pointer. */ + if ( !astOK ) { + if ( !out ) result = astDelete( result ); + result = NULL; + } + +/* Return a pointer to the output PointSet. */ + return result; +} + + +/* Stc Attributes: */ +/* =============== */ + +/* +*att++ +* Name: +* RegionClass + +* Purpose: +* The AST class name of the Region encapsulated within an Stc + +* Type: +* Public attribute. + +* Synopsis: +* String, read-only. + +* Description: +* This is a read-only attribute giving the AST class name of the +* Region encapsulated within an Stc (that is, the class of the Region +* which was supplied when the Stc was created). + +* Applicability: +* Stc +* All Stc objects this attribute. +*att-- +*/ + +/* Copy constructor. */ +/* ----------------- */ +static void Copy( const AstObject *objin, AstObject *objout, int *status ) { +/* +* Name: +* Copy + +* Purpose: +* Copy constructor for Stc objects. + +* Type: +* Private function. + +* Synopsis: +* void Copy( const AstObject *objin, AstObject *objout, int *status ) + +* Description: +* This function implements the copy constructor for Stc objects. + +* Parameters: +* objin +* Pointer to the object to be copied. +* objout +* Pointer to the object being constructed. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* void + +* Notes: +* - This constructor makes a deep copy, including a copy of the component +* Regions within the Stc. +*/ + +/* Local Variables: */ + AstStc *in; /* Pointer to input Stc */ + AstStc *out; /* Pointer to output Stc */ + int i; /* AstroCoords index */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain pointers to the input and output Stcs. */ + in = (AstStc *) objin; + out = (AstStc *) objout; + +/* For safety, start by clearing any references to the input component + Regions, etc, from the output Stc. */ + out->region = NULL; + out->coord = NULL; + out->ncoord = 0; + +/* Make a copy of the Region and store a pointer to it in the output Stc + structure. */ + out->region = astCopy( in->region ); + +/* Copy any memory holding AstroCoords values */ + if( in->coord && in->ncoord ) { + out->ncoord = in->ncoord; + out->coord = astMalloc( sizeof(AstKeyMap *) * (size_t)in->ncoord ); + if( out->coord ) { + for( i = 0; i < in->ncoord; i++ ) { + out->coord[ i ] = astCopy( in->coord[ i ] ); + } + } + } +} + +/* Destructor. */ +/* ----------- */ +static void Delete( AstObject *obj, int *status ) { +/* +* Name: +* Delete + +* Purpose: +* Destructor for Stc objects. + +* Type: +* Private function. + +* Synopsis: +* void Delete( AstObject *obj, int *status ) + +* Description: +* This function implements the destructor for Stc objects. + +* Parameters: +* obj +* Pointer to the object to be deleted. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* void + +* Notes: +* This function attempts to execute even if the global error status is +* set. +*/ + +/* Local Variables: */ + AstStc *this; /* Pointer to Stc */ + int i; /* AstroCoords index */ + +/* Obtain a pointer to the Stc structure. */ + this = (AstStc *) obj; + +/* Annul the pointer to the encapsulated Region. */ + this->region = astAnnul( this->region ); + +/* Free any memory holding AstroCoords values */ + if( this->coord ) { + for( i = 0; i < this->ncoord; i++ ) { + this->coord[ i ] = astAnnul( this->coord[ i ] ); + } + this->coord = astFree( this->coord ); + } +} + +/* Dump function. */ +/* -------------- */ +static void Dump( AstObject *this_object, AstChannel *channel, int *status ) { +/* +* Name: +* Dump + +* Purpose: +* Dump function for Stc 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 Stc class to an output Channel. + +* Parameters: +* this +* Pointer to the Stc 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: */ + AstStc *this; /* Pointer to the Stc structure */ + char comment[ COMMENT_LEN + 1 ]; /* Buffer for comment string */ + char key[ KEY_LEN + 1 ]; /* Buffer for keyword string */ + int ico; /* Loop counter for KeyMaps */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Stc structure. */ + this = (AstStc *) this_object; + +/* Write out values representing the instance variables for the Stc + 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. */ + +/* Encapsulated Region. */ +/* -------------------- */ + astWriteObject( channel, "Region", 1, 1, this->region, + "STC Region" ); + +/* AstroCoords info */ +/* ---------------- */ + astWriteInt( channel, "Ncoord", ( this->ncoord != 0 ), 0, this->ncoord, + "Number of AstroCoords elements" ); + + for ( ico = 1; ico <= this->ncoord; ico++ ) { + (void) sprintf( key, "Coord%d", ico ); + (void) sprintf( comment, "AstroCoords number %d", ico ); + astWriteObject( channel, key, 1, 1, this->coord[ ico - 1 ], + comment ); + } + +/* Undefine macros local to this function. */ +#undef COMMENT_LEN +#undef KEY_LEN +} + +/* Standard class functions. */ +/* ========================= */ +/* Implement the astIsAStc and astCheckStc functions using the + macros defined for this purpose in the "object.h" header file. */ +astMAKE_ISA(Stc,Region) +astMAKE_CHECK(Stc) + +AstStc *astInitStc_( void *mem, size_t size, int init, AstStcVtab *vtab, + const char *name, AstRegion *region, int ncoords, + AstKeyMap **coords, int *status ) { +/* +*+ +* Name: +* astInitStc + +* Purpose: +* Initialise a Stc. + +* Type: +* Protected function. + +* Synopsis: +* #include "stc.h" +* AstStc *astInitStc( void *mem, size_t size, int init, AstStcVtab *vtab, +* const char *name, AstRegion *region, int ncoords, +* AstKeyMap **coords ) + +* Class Membership: +* Stc initialiser. + +* Description: +* This function is provided for use by class implementations to initialise +* a new Stc object. It allocates memory (if necessary) to +* accommodate the Stc plus any additional data associated with the +* derived class. It then initialises a Stc 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 Stc at the start of +* the memory passed via the "vtab" parameter. + +* Parameters: +* mem +* A pointer to the memory in which the Stc is to be initialised. +* This must be of sufficient size to accommodate the Stc data +* (sizeof(Stc)) 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 Stc (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 +* Stc structure, so a valid value must be supplied even if not +* required for allocating memory. +* init +* A logical flag indicating if the Stc'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 Stc. +* 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). +* region +* Pointer to the Region represented by the Stc. +* ncoords +* Number of KeyMap pointers supplied in "coords". Can be zero. +* Ignored if "coords" is NULL. +* coords +* Pointer to an array of "ncoords" KeyMap pointers, or NULL if +* "ncoords" is zero. Each KeyMap defines defines a single <AstroCoords> +* element, and should have elements with keys given by constants +* AST__STCNAME, AST__STCVALUE, AST__STCERROR, AST__STCRES, AST__STCSIZE, +* AST__STCPIXSZ. Any of these elements may be omitted, but no other +* elements should be included. If supplied, the AST__STCNAME element +* should be a vector of character string pointers holding the "Name" +* item for each axis. Any other supplied elements should be scalar +* elements, each holding a pointer to a Region describing the +* associated item of ancillary information (error, resolution, size, +* pixel size or value). These Regions should describe a volume within +* the coordinate system represented by "region". + +* Returned Value: +* A pointer to the new Stc. + +* 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: */ + AstMapping *frm; /* Current Frame in supplied Stc */ + AstMapping *map; /* Base -> Current Mapping in supplied Stc */ + AstRegion *reg; /* Copy of supplied Region */ + AstStc *new; /* Pointer to new Stc */ + int i; /* AstroCoords index */ + +/* Check the global status. */ + if ( !astOK ) return NULL; + +/* If necessary, initialise the virtual function table. */ + if ( init ) astInitStcVtab( vtab, name ); + +/* Initialise. */ + new = NULL; + +/* If the supplied Region is an Stc, create a new Region by mapping the + encapsulated Region within the supplied Stc into the current Frame of the + Stc. */ + if( astIsAStc( region ) ) { + map = astGetMapping( region->frameset, AST__BASE, AST__CURRENT ); + frm = astGetFrame( region->frameset, AST__CURRENT ); + reg = astMapRegion( ((AstStc *) region)->region, map, frm ); + frm = astAnnul( frm ); + map = astAnnul( map ); + +/* Otherwise, just take a copy of the supplied Region. */ + } else { + reg = astCopy( region ); + } + +/* Initialise a Region structure (the parent class) as the first component + within the Stc structure, allocating memory if necessary. A NULL + PointSet is suppled as the encapsulated Region will perform the function + of defining the Region shape. The base Frame of the FrameSet in the + parent Region structure will be the same as the current Frames of the + FrameSets in the two encapsulated Region. */ + if ( astOK ) { + new = (AstStc *) astInitRegion( mem, size, 0, (AstRegionVtab *) vtab, + name, reg, NULL, NULL ); + +/* Initialise the Stc data. */ +/* --------------------------- */ +/* Store a pointer to the encapsulated Region. */ + new->region = astClone( reg ); + +/* No AstroCoords info as yet. */ + new->ncoord = 0; + new->coord = NULL; + +/* Transfer attributes from the encapsulated region to the parent region. */ + astRegOverlay( new, reg, 1 ); + if( astTestIdent( reg ) ) astSetIdent( new, astGetIdent( reg ) ); + +/* If the base->current Mapping in the FrameSet within the encapsulated Region + is a UnitMap, then the FrameSet does not need to be included in the + Dump of the new Stc. Set the RegionFS attribute of the encapsulated + Region to zero to flag this. Note, we do this after the previous class + to astRegOverlay because we do not want this zero value for RegionFS to + be copied into the new Stc object. */ + astSetRegionFS( reg, 0 ); + +/* For each supplied AstroCoords, create a new KeyMap holding Regions + representing the various elements of the AstroCoords, and store the + new KeyMap in the Stc structure. */ + if( coords && ncoords > 0 ) { + new->ncoord = ncoords; + new->coord = astMalloc( sizeof( AstKeyMap *)*(size_t) ncoords ); + if( new->coord ) { + for( i = 0; i < ncoords; i++ ) { + new->coord[ i ] = MakeAstroCoordsKeyMap( reg, coords[ i ], + name, status ); + } + } + } + +/* If an error occurred, clean up deleting the new object. */ + if ( !astOK ) new = astDelete( new ); + } + +/* Free resources */ + reg = astAnnul( reg ); + +/* Return a pointer to the new object. */ + return new; +} + +AstStc *astLoadStc_( void *mem, size_t size, AstStcVtab *vtab, + const char *name, AstChannel *channel, int *status ) { +/* +*+ +* Name: +* astLoadStc + +* Purpose: +* Load a Stc. + +* Type: +* Protected function. + +* Synopsis: +* #include "stc.h" +* AstStc *astLoadStc( void *mem, size_t size, AstStcVtab *vtab, +* const char *name, AstChannel *channel ) + +* Class Membership: +* Stc loader. + +* Description: +* This function is provided to load a new Stc 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 +* Stc structure in this memory, using data read from the input +* Channel. +* +* If the "init" flag is set, it also initialises the contents of a +* virtual function table for a Stc at the start of the memory +* passed via the "vtab" parameter. + +* Parameters: +* mem +* A pointer to the memory into which the Stc is to be +* loaded. This must be of sufficient size to accommodate the +* Stc data (sizeof(Stc)) 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 Stc (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 Stc 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(AstStc) is used instead. +* vtab +* Pointer to the start of the virtual function table to be +* associated with the new Stc. If this is NULL, a pointer to +* the (static) virtual function table for the Stc 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 "Stc" is used instead. + +* Returned Value: +* A pointer to the new Stc. + +* 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: */ + AstFrame *f1; /* Base Frame in parent Region */ + AstObject *obj; /* Pointer to Object retrieved from KeyMap */ + AstRegion *creg; /* Pointer to encapsulated Region */ + AstStc *new; /* Pointer to the new Stc */ + char key[ KEY_LEN + 1 ]; /* Buffer for keyword string */ + int ico; /* Loop counter for AstroCoords */ + int ikey; /* Index of KeyMap */ + +/* 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 Stc. In this case the + Stc belongs to this class, so supply appropriate values to be + passed to the parent class loader (and its parent, etc.). */ + if ( !vtab ) { + size = sizeof( AstStc ); + vtab = &class_vtab; + name = "Stc"; + +/* If required, initialise the virtual function table for this class. */ + if ( !class_init ) { + astInitStcVtab( 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 Stc. */ + new = astLoadRegion( mem, size, (AstRegionVtab *) 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, "Stc" ); + +/* 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. */ + +/* Encapsulated Region. */ +/* -------------------- */ + new->region = astReadObject( channel, "region", NULL ); + +/* Get a pointer to the base Frame in the FrameSet encapsulated by the + parent Region structure. */ + f1 = astGetFrame( ((AstRegion *) new)->frameset, AST__BASE ); + +/* If the encapsulated Region has a dummy FrameSet rather than the correct + FrameSet, the correct FrameSet will have copies of the base Frame of the + new Stc as both its current and base Frames, connected by a UnitMap (this + is equivalent to a FrameSet containing a single Frame). However if the new + Stc being loaded has itself got a dummy FrameSet, then we do not do this + since we do not yet know what the correct FrameSet is. In this case we + wait until the parent Region invokes the astSetRegFS method on the new + Stc. */ + if( !astRegDummyFS( new ) ) { + creg = new->region; + if( astRegDummyFS( creg ) ) astSetRegFS( creg, f1 ); + } + +/* AstroCoords info */ +/* ---------------- */ +/* The number of AstroCoords described in the new Stc. */ + new->ncoord = astReadInt( channel, "ncoord", 0 ); + if( new->ncoord < 0 ) new->ncoord = 0; + +/* Read back each KeyMap describing these AstroCoords. */ + new->coord = astMalloc( sizeof( AstKeyMap *) * (size_t) new->ncoord ); + for( ico = 1; ico <= new->ncoord; ico++ ) { + (void) sprintf( key, "coord%d", ico ); + new->coord[ ico - 1 ] = astReadObject( channel, key, NULL ); + +/* Ensure the Regions within the KeyMap do not have dummy FrameSets. */ + if( new->coord[ ico - 1 ] && !astRegDummyFS( new ) ) { + for( ikey = 0; ikey < NREG; ikey++ ) { + if( astMapGet0A( new->coord[ ico - 1 ], regkey[ ikey ], &obj ) ){ + creg = (AstRegion *) obj; + if( astRegDummyFS( creg ) ) { + astSetRegFS( creg, f1 ); + astMapPut0A( new->coord[ ico - 1 ], regkey[ ikey ], creg, + regcom[ ikey ] ); + } + creg = astAnnul( creg ); + } + } + } + } + +/* Free resources */ + f1 = astAnnul( f1 ); + +/* If an error occurred, clean up by deleting the new Stc. */ + if ( !astOK ) new = astDelete( new ); + } + +/* Return the new Stc 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. */ + +const char *astGetRegionClass_( AstStc *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Stc,GetRegionClass))( this, status ); +} + +AstRegion *astGetStcRegion_( AstStc *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Stc,GetStcRegion))( this, status ); +} + +AstKeyMap *astGetStcCoord_( AstStc *this, int icoord, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Stc,GetStcCoord))( this, icoord, status ); +} + +int astGetStcNCoord_( AstStc *this, int *status ){ + if ( !astOK ) return 0; + return (**astMEMBER(this,Stc,GetStcNCoord))( this, status ); +} + + + + + + + + + + + + + |