diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 19:01:49 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 19:01:49 (GMT) |
commit | beb90b7d3f526440250bba67e5ab07bb7eb7bbc3 (patch) | |
tree | 8d0d428ac62291f834ea8927bfa82c115ff1689d /ast/skyaxis.c | |
parent | a213dadabce2b2e02eca8376765fa425f01792f5 (diff) | |
download | blt-beb90b7d3f526440250bba67e5ab07bb7eb7bbc3.zip blt-beb90b7d3f526440250bba67e5ab07bb7eb7bbc3.tar.gz blt-beb90b7d3f526440250bba67e5ab07bb7eb7bbc3.tar.bz2 |
upgrade ast 8.7.1
Diffstat (limited to 'ast/skyaxis.c')
-rw-r--r-- | ast/skyaxis.c | 5150 |
1 files changed, 0 insertions, 5150 deletions
diff --git a/ast/skyaxis.c b/ast/skyaxis.c deleted file mode 100644 index fd6d6f6..0000000 --- a/ast/skyaxis.c +++ /dev/null @@ -1,5150 +0,0 @@ -/* -*class++ -* Name: -* SkyAxis - -* Purpose: -* Store celestial axis information. - -* Constructor Function: -* None. - -* Description: -* The SkyAxis class is used to store information associated with a -* particular axis of a SkyFrame. It is used internally by the AST -* library and has no constructor function. You should encounter it -c only within textual output (e.g. from astWrite). -f only within textual output (e.g. from AST_WRITE). - -* Inheritance: -* The SkyAxis class inherits from the Axis class. - -* 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: -* RFWS: R.F. Warren-Smith (Starlink) -* DSB: B.S. Berry (Starlink) - -* History: -* 1-MAR-1996 (RFWS): -* Original version. -* 19-APR-1996 (RFWS): -* Tidied up, etc. -* 8-MAY-1996 (RFWS): -* Remove leading minus sign from formatted HMS string if all -* fields are zero. -* 9-MAY-1996 (RFWS): -* Fixed bug in rounding of fractional parts of HMS strings and -* improved algorithm to cope gracefully with requests for -* excessive numbers of decimal places. -* 13-MAY-1996 (RFWS): -* Over-ride the astGetAxisDirection method so that a SkyAxis -* with the AsTime attribute set is displayed in reverse by -* default. -* 17-MAY-1996 (RFWS): -* Change AxisNorm to return a bad coordinate value if a bad -* value is given. -* 11-SEP-1996 (RFWS): -* Added AxisGap and DHmsGap (written by DSB). -* 26-FEB-1998 (RFWS): -* Over-ride the astAxisUnformat method. -* 6-MAR-1998 (RFWS): -* Add formatting options to omit degrees/hours field and change -* all affected functions. -* 10-AUG-2000 (DSB): -* Fixed bug in DHmsFormat which could cause (for instance) a formatted -* galactic longitude value of zero to be formated as "-0.-0". -* 29-AUG-2001 (DSB): -* Added AxisDistance and AxisOffset. -* 10-OCT-2002 (DSB): -* Over-ride the astGetAxisTop and astGetAxisBottom methods so that a -* SkyAxis with the IsLatitude attribute set is legal between plus -* and minus 90 degrees. -* 8-JAN-2003 (DSB): -* - Changed private InitVtab method to protected astInitSkyAxisVtab -* method. -* - Modify DHmsGap to avoid decimal gap "4" which produces things -* like "0.0 0.4 0.8 1.2 1.6 2.0" ("4" replaced by "5"). -* 24-JAN-2004 (DSB): -* o Added AxisFields. -* o Added 'g' format character which produces graphical separators. -* o Modified AxisAbbrev to use AxisFields so that delimiters which -* include digits can be recognised. -* 13-SEP-20904 (DSB): -* Modify AxisFields to correct usage of the "p" pointer in the -* case that the first and only field begins with a minus sign. -* 15-SEP-2004 (DSB): -* Modified ParseDHmsFormat so that the number of decimal places -* is specified by Digits if the given format string include a ".*" -* precision (e.g. "dms.*"). -* 18-MAR-2005 (DSB): -* Invoke methods inherited from parent Axis class if the format -* string starts with a '%' character. -* 14-FEB-2006 (DSB): -* Override astGetObjSize. -* 30-JUN-2006 (DSB): -* Guard against a null "str1" value in AxisAbbrev. -* 7-AUG-2007 (DSB): -* Added CentreZero attribute. -* 1-FEB-2008 (DSB): -* Modified AxisUnformat to allow the final numerical field to include -* an exponent. -* 13-OCT-2011 (DSB): -* Use tuning parameters to store graphical delimiters. -* 27-APR-2015 (DSB): -* Added InternalUNit attribute.. -* 26-OCT-2016 (DSB): -* Override astAxisNormValues. -* 7-NOV-2016 (DSB): -* Ensure astAxisNormValues ignores bad axis values. -*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 SkyAxis - -/* Header files. */ -/* ============= */ -#include "ast_err.h" /* Error code definitions */ - -/* Interface definitions. */ -/* ---------------------- */ -#include "pal.h" /* SLALIB interface */ - -#include "globals.h" /* Thread-safe global data access */ -#include "error.h" /* Error reporting facilities */ -#include "memory.h" /* Memory allocation facilities */ -#include "pointset.h" /* Sets of points (for AST__BAD) */ -#include "axis.h" /* Axis (parent) class interface */ -#include "skyaxis.h" /* Interface definition for this class */ -#include "globals.h" /* Thread-safe global data access */ -#include "wcsmap.h" /* For constants */ - -/* C header files. */ -/* --------------- */ -#include <ctype.h> -#include <limits.h> -#include <math.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* Module Variables. */ -/* ================= */ - -/* Address of this static variable is used as a unique identifier for - member of this class. */ -static int class_check; - -/* Pointers to parent class methods which are extended by this class. */ -static int (* parent_getobjsize)( AstObject *, int * ); -static const char *(* parent_getattrib)( AstObject *, const char *, int * ); -static const char *(* parent_getaxislabel)( AstAxis *, int * ); -static const char *(* parent_getaxissymbol)( AstAxis *, int * ); -static const char *(* parent_getaxisunit)( AstAxis *, int * ); -static int (* parent_testattrib)( AstObject *, const char *, int * ); -static int (*parent_getaxisdirection)( AstAxis *this, int * ); -static void (* parent_axisoverlay)( AstAxis *, AstAxis *, int * ); -static void (* parent_clearattrib)( AstObject *, const char *, int * ); -static void (* parent_setattrib)( AstObject *, const char *, int * ); -static double (*parent_getaxisbottom)( AstAxis *this, int * ); -static double (*parent_getaxistop)( AstAxis *this, int * ); -static const char *(* parent_axisformat)( AstAxis *, double, int * ); -static double (*parent_axisgap)( AstAxis *, double, int *, int * ); -static int (*parent_axisunformat)( AstAxis *, const char *, double *, int * ); -static int (*parent_axisfields)( AstAxis *, const char *, const char *, int, char **, int *, double *, int * ); - -/* Factors for converting between hours, degrees and radians. */ -static double hr2rad; -static double deg2rad; -static double pi; -static double piby2; - -/* Define macros for accessing each item of thread specific global data. */ -#ifdef THREAD_SAFE - -/* Define how to initialise thread-specific globals. */ -#define GLOBAL_inits \ - globals->Class_Init = 0; \ - globals->DHmsFormat_Buff[ 0 ] = 0; \ - globals->DHmsUnit_Buff[ 0 ] = 0; \ - globals->GetAttrib_Buff[ 0 ] = 0; \ - globals->GetAxisFormat_Buff[ 0 ] = 0; - -/* Create the function that initialises global data for this module. */ -astMAKE_INITGLOBALS(SkyAxis) - -/* Define macros for accessing each item of thread specific global data. */ -#define class_init astGLOBAL(SkyAxis,Class_Init) -#define class_vtab astGLOBAL(SkyAxis,Class_Vtab) -#define dhmsformat_buff astGLOBAL(SkyAxis,DHmsFormat_Buff) -#define dhmsunit_buff astGLOBAL(SkyAxis,DHmsUnit_Buff) -#define getattrib_buff astGLOBAL(SkyAxis,GetAttrib_Buff) -#define getaxisformat_buff astGLOBAL(SkyAxis,GetAxisFormat_Buff) - -static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_MUTEX2 pthread_mutex_lock( &mutex2 ); -#define UNLOCK_MUTEX2 pthread_mutex_unlock( &mutex2 ); - -/* If thread safety is not needed, declare and initialise globals at static - variables. */ -#else - -static char dhmsformat_buff[ AST__SKYAXIS_DHMSFORMAT_BUFF_LEN + 1 ]; -static char dhmsunit_buff[ AST__SKYAXIS_DHMSUNIT_BUFF_LEN + 1 ]; -static char getattrib_buff[ AST__SKYAXIS_GETATTRIB_BUFF_LEN + 1 ]; -static char getaxisformat_buff[ AST__SKYAXIS_GETAXISFORMAT_BUFF_LEN + 1 ]; - -/* Define the class virtual function table and its initialisation flag - as static variables. */ -static AstSkyAxisVtab class_vtab; /* Virtual function table */ -static int class_init = 0; /* Virtual function table initialised? */ - -#define LOCK_MUTEX2 -#define UNLOCK_MUTEX2 - -#endif - - -/* External Interface Function Prototypes. */ -/* ======================================= */ -/* The following functions have public prototypes only (i.e. no - protected prototypes), so we must provide local prototypes for use - within this module. */ -AstSkyAxis *astSkyAxisId_( const char *, ... ); - -/* Prototypes for Private Member Functions. */ -/* ======================================== */ -static const char *AxisAbbrev( AstAxis *, const char *, const char *, const char *, int * ); -static const char *AxisFormat( AstAxis *, double, int * ); -static int GetObjSize( AstObject *, int * ); -static const char *GetAttrib( AstObject *, const char *, int * ); -static const char *GetAxisFormat( AstAxis *, int * ); -static const char *GetAxisInternalUnit( AstAxis *, int * ); -static const char *GetAxisLabel( AstAxis *, int * ); -static const char *GetAxisSymbol( AstAxis *, int * ); -static const char *GetAxisUnit( AstAxis *, int * ); -static const char *DHmsFormat( const char *, int, double, int * ); -static const char *DHmsUnit( const char *, int, int, int * ); -static double AxisGap( AstAxis *, double, int *, int * ); -static double AxisDistance( AstAxis *, double, double, int * ); -static double AxisOffset( AstAxis *, double, double, int * ); -static double DHmsGap( const char *, int, double, int *, int * ); -static double GetAxisTop( AstAxis *, int * ); -static double GetAxisBottom( AstAxis *, int * ); -static int AxisIn( AstAxis *, double, double, double, int, int * ); -static int AxisFields( AstAxis *, const char *, const char *, int, char **, int *, double *, int * ); -static int AxisUnformat( AstAxis *, const char *, double *, int * ); -static int GetAxisAsTime( AstSkyAxis *, int * ); -static int GetAxisDirection( AstAxis *, int * ); -static int GetAxisIsLatitude( AstSkyAxis *, int * ); -static int GetAxisCentreZero( AstSkyAxis *, int * ); -static int TestAttrib( AstObject *, const char *, int * ); -static int TestAxisAsTime( AstSkyAxis *, int * ); -static int TestAxisFormat( AstAxis *, int * ); -static int TestAxisInternalUnit( AstAxis *, int * ); -static int TestAxisIsLatitude( AstSkyAxis *, int * ); -static int TestAxisCentreZero( AstSkyAxis *, int * ); -static void AxisNorm( AstAxis *, double *, int * ); -static void AxisNormValues( AstAxis *, int, int, double *, int * ); -static void AxisOverlay( AstAxis *, AstAxis *, int * ); -static void ClearAttrib( AstObject *, const char *, int * ); -static void ClearAxisAsTime( AstSkyAxis *, int * ); -static void ClearAxisFormat( AstAxis *, int * ); -static void ClearAxisIsLatitude( AstSkyAxis *, int * ); -static void ClearAxisCentreZero( AstSkyAxis *, int * ); -static void Copy( const AstObject *, AstObject *, int * ); -static void Delete( AstObject *, int * ); -static void Dump( AstObject *, AstChannel *, int * ); -static void ParseDHmsFormat( const char *, int, char *, int *, int *, int *, int *, int *, int *, int *, int * ); -static void SetAttrib( AstObject *, const char *, int * ); -static void SetAxisAsTime( AstSkyAxis *, int, int * ); -static void SetAxisFormat( AstAxis *, const char *, int * ); -static void SetAxisIsLatitude( AstSkyAxis *, int, int * ); -static void SetAxisCentreZero( AstSkyAxis *, int, int * ); - -/* Member functions. */ -/* ================= */ -static const char *AxisAbbrev( AstAxis *this_axis, const char *fmt, - const char *str1, const char *str2, int *status ) { -/* -* Name: -* AxisAbbrev - -* Purpose: -* Abbreviate a formatted SkyAxis value by skipping leading fields. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* const char *AxisAbbrev( AstAxis *this, const char *fmt, -* const char *str1, const char *str2 ) - -* Class Membership: -* SkyAxis member function (over-rides the protected astAxisAbbrev -* method inherited from the Axis class). - -* Description: -* This function compares two SkyAxis values that have been -* formatted with the supplied format specifier (using astAxisFormat) -* and determines if they have any redundant leading fields (i.e. -* leading fields in common which can be suppressed when tabulating -* the values or plotting them on the axis of a graph). - -* Parameters: -* this -* Pointer to the SkyAxis. -* fmt -* Pointer to a constant null-terminated string containing the -* format specifier used to format the two values. -* str1 -* Pointer to a constant null-terminated string containing the -* first formatted value. If this is null, the returned pointer -* points to the start of the final field in str2. -* str2 -* Pointer to a constant null-terminated string containing the -* second formatted value. - -* Returned Value: -* A pointer into the "str2" string which locates the first -* character in the first field that differs between the two -* formatted values. -* -* If the two values have no leading fields in common, the returned -* value will point at the start of string "str2". If the two -* values are equal, it will point at the terminating null at the -* end of this string. - -* Notes: -* - A pointer to the start of "str2" will be returned if this -* function is invoked with the global error status set, or if it -* should fail for any reason. -*/ - -/* Local Variables: */ - char *fld1[ 3 ]; /* Pointers to start of each field in str1 */ - char *fld2[ 3 ]; /* Pointers to start of each field in str2 */ - const char *result; /* Result pointer to return */ - int i; /* Loop counter for string fields */ - int nf1; /* Number of fields found in str1 */ - int nf2; /* Number of fields found in str2 */ - int nc1[ 3 ]; /* Length of each field in str1 */ - int nc2[ 3 ]; /* Length of each field in str2 */ - -/* Initialise. */ - result = str2; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Find the fields within the "str2" string. */ - nf2 = astAxisFields( this_axis, fmt, str2, 3, fld2, nc2, NULL ); - -/* If "str1" was not supplied, return a pointer to the final field in - "str2". */ - if( !str1 ) { - result = fld2[ nf2 - 1 ]; - -/* Otherwise, find the fields within the "str1" string. */ - } else { - nf1 = astAxisFields( this_axis, fmt, str1, 3, fld1, nc1, NULL ); - -/* Loop to inspect corresponding fields from each string. */ - for ( i = 0; i < nf1 && i < nf2; i++ ) { - -/* If the fields are different, break out of the loop. */ - if ( nc1[ i ] != nc2[ i ] || - strncmp( fld1[ i ], fld2[ i ], nc1[ i ] ) ) { - break; - -/* Otherwise, move the returned poitner on to point to the start of the - next field in str2. If we are already at the last field in str2, - return a pointer to the terminating null. */ - } else { - if ( i + 1 < nf2 ) { - result = fld2[ i + 1 ]; - } else { - result = strchr( str2, '\0' ); - } - } - } - } - -/* Return the result. */ - return result; -} - -static double AxisDistance( AstAxis *this_axis, double v1, double v2, int *status ) { -/* -* Name: -* AxisDistance - -* Purpose: -* Find the distance between two axis values. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* AxisDistance( AstAxis *this, double v1, double v2 ) - -* Class Membership: -* SkyAxis member function (over-rides the protected astAxisDistance -* method inherited from the Axis class). - -* Description: -* This function returns a signed value representing the axis increment -* from axis value v1 to axis value v2. -* -* For a SkyAxis, the angular difference between the two supplied axis -* values is normalized into the range +PI to -PI. - -* Parameters: -* this -* Pointer to the SkyAxis. -* v1 -* The first axis value -* v2 -* The second axis value - -* Returned Value: -* The axis increment from v1 to v2. - -* Notes: -* - A value of AST__BAD is returned if either axis value is AST__BAD. -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - double result; /* Returned gap size */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Check both axis values are OK, and form the returned increment, - normalizing it into the range +PI to -PI. */ - if( v1 != AST__BAD && v2 != AST__BAD ) result = palDrange( v2 - v1 ); - -/* Return the result. */ - return result; -} - -static int AxisFields( AstAxis *this_axis, const char *fmt, const char *str, - int maxfld, char **fields, int *nc, double *val, int *status ) { -/* -* Name: -* AxisFields - -* Purpose: -* Identify numerical fields within a formatted SkyAxis value. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* int AxisFields( AstAxis *this_axis, const char *fmt, const char *str, -* int maxfld, char **fields, int *nc, double *val ) - -* Class Membership: -* SkyAxis member function (over-rides the protected astAxisFields -* method inherited from the Axis class). - -* Description: -* This function identifies the numerical fields within a SkyAxis value -* that have been formatted using astAxisFormat. It assumes that the -* value was formatted using the supplied format string. It also -* returns the equivalent floating point value in radians. - -* Parameters: -* this -* Pointer to the SkyAxis. -* fmt -* Pointer to a constant null-terminated string containing the -* format used when creating "str". -* str -* Pointer to a constant null-terminated string containing the -* formatted value. -* maxfld -* The maximum number of fields to identify within "str". -* fields -* A pointer to an array of at least "maxfld" character pointers. -* Each element is returned holding a pointer to the start of the -* corresponding field in "str" (in the order in which they occur -* within "str"), or NULL if no corresponding field can be found. -* nc -* A pointer to an array of at least "maxfld" integers. Each -* element is returned holding the number of characters in the -* corresponding field, or zero if no corresponding field can be -* found. -* val -* Pointer to a location at which to store the radians value -* equivalent to the returned field values. If this is NULL, -* it is ignored. - -* Returned Value: -* The number of fields succesfully identified and returned. - -* Notes: -* - Leading and trailing spaces are ignored. -* - If the formatted value is not consistent with the supplied format -* string, then a value of zero will be returned, "fields" will be -* returned holding NULLs, "nc" will be returned holding zeros, and -* "val" is returned holding VAL__BAD. -* - Fields are counted from the start of the formatted string. If the -* string contains more than "maxfld" fields, then trailing fields are -* ignored. -* - If this function is invoked with the global error status set, or -* if it should fail for any reason, then a value of zero will be returned -* as the function value, and "fields", "nc" and "val" will be returned -* holding their supplied values - -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - char sep; /* Field separator character */ - char tbuf[50]; /* Buffer for terminator string */ - char *p; /* Pointer to next character */ - char *t; /* Pointer to start of terminator string */ - char *term; /* Pointer to terminator string */ - double dval; /* Value read from string */ - double value; /* Equivalent radians value */ - int as_time; /* Format the value as a time? */ - int dh; /* Hours field required? */ - int ifld; /* Field index */ - int lead_zero; /* Add leading zeros? */ - int min; /* Minutes field required? */ - int ndp; /* Number of decimal places */ - int ok; /* Value and format consistent? */ - int plus; /* Add leading plus sign? */ - int result; /* Result fields count to return */ - int sec; /* Seconds field required? */ - int sign; /* The sign of the radians value */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(this_axis); - -/* If the format string starts with a "%" call the method inherited from - the parent Axis class. */ - if( fmt[ 0 ] == '%' ) { - return (*parent_axisfields)( this_axis, fmt, str, maxfld, fields, nc, - val, status ); - } - -/* Initialise. */ - result = 0; - for( ifld = 0; ifld < maxfld; ifld++ ) { - fields[ ifld ] = NULL; - nc[ ifld ] = 0; - } - if( val ) *val = AST__BAD; - -/* Parse the format specifier. */ - ParseDHmsFormat( fmt, astGetAxisDigits( this_axis ), &sep, &plus, &lead_zero, - &as_time, &dh, &min, &sec, &ndp, status ); - -/* Only proceed if the format was parsed succesfully, and the supplied arrays - are not of zero size. */ - if( astOK && maxfld > 0 ) { - -/* Indicate that we have not yet found any inconsistency between the - formatted value and the forat string. */ - ok = 1; - -/* Variable "p" points to the next character to be read from the - formatted string. Initialise it to point to the first non-space - character. */ - p = (char *) str; - while( *p == ' ' ) p++; - -/* Note the start of the first field. */ - fields[ 0 ] = p; - -/* If the first non-blank character is a + or - sign, skip it and note - the sign of the final value. */ - sign = 1; - if( *p == '-' ) { - sign = -1; - p++; - } else if( *p == '+' ) { - p++; - } - -/* Initialise the equivalent radian value. */ - value = 0.0; - -/* If the format string specifies a degrees or hours field, it should be - the first field. */ - if( dh ) { - -/* If the format indicates that fields are separated by characters, or if - there is a minutes or seconds field, then the first field should end with - the appropriate separator. In these cases locate the terminator,and - store the length of the first field. */ - if( sep == 'l' || sep == 'g' || min || sec ) { - - if( sep == 'l' ) { - term = as_time ? "h" : "d"; - - } else if( sep == 'g' ) { - astTuneC( as_time ? "hrdel":"dgdel", NULL, tbuf, - sizeof( tbuf ) ); - term = tbuf; - - } else { - tbuf[ 0 ] = sep; - tbuf[ 1 ] = '\0'; - term = tbuf; - } - - t = strstr( p, term ); - if( t ) { - nc[ 0 ] = t - fields[ 0 ]; - } else { - ok = 0; - } - -/* Move on to the first character following the terminator. */ - p = t + strlen( term ); - -/* In all other cases, the first field is the only field and is not - terminated. Note its length (ignoring trailing spaces). Move the - pointer on by the length of the field, remembering that any leading - minus sign has already been skipped. */ - } else { - nc[ 0 ] = astChrLen( fields[ 0 ] ); - p += nc[ result ]; - if( sign == -1 ) p--; - } - -/* Read a numerical value from the first field. */ - if( astSscanf( fields[ 0 ], "%lg", &dval ) ) { - value = fabs( dval ); - } else { - ok = 0; - } - -/* Increment then number of returned fields if OK */ - if( ok ) result++; - - } - -/* If the format string specifies a minutes field, it should be the next - field. */ - if( min && ok ) { - -/* Note the start of the next field. */ - fields[ result ] = p; - -/* If the format indicates that fields are separated by characters, or if - there is a seconds field, then this field should end with the appropriate - separator. In these cases locate the terminator,and store the length of - this field. */ - if( sep == 'l' || sep == 'g' || sec ) { - if( sep == 'l' ) { - term = "m"; - - } else if( sep == 'g' ) { - astTuneC( as_time ? "mndel":"amdel", NULL, tbuf, - sizeof( tbuf ) ); - term = tbuf; - - } else { - tbuf[ 0 ] = sep; - tbuf[ 1 ] = '\0'; - term = tbuf; - } - - t = strstr( p, term ); - if( t ) { - nc[ result ] = t - fields[ result ]; - } else { - ok = 0; - } - -/* Move on to the first character following the terminator. */ - p = t + strlen( term ); - -/* In all other cases, this field is not terminated. Note its length - (ignoring trailing spaces). */ - } else { - nc[ result ] = astChrLen( fields[ result ] ); - p += nc[ result ]; - } - -/* Read a numerical value from this field. */ - if( astSscanf( fields[ result ], "%lg", &dval ) ) { - value += dval/60.0; - } else { - ok = 0; - } - -/* Increment then number of returned fields if OK */ - if( ok ) result++; - - } - -/* If the format string specifies a seconds field, it should be the next - field. */ - if( sec && ok ) { - -/* Note the start of the next field. */ - fields[ result ] = p; - -/* If the format indicates that fields are separated by characters, then this - field should end with the appropriate separator. In this case locate the - terminator,and store the length of this field. */ - if( sep == 'l' || sep == 'g' ) { - if( sep == 'l' ) { - term = "s"; - } else { - astTuneC( as_time ? "scdel":"asdel", NULL, tbuf, - sizeof( tbuf ) ); - term = tbuf; - } - - t = strstr( p, term ); - if( t ) { - nc[ result ] = t - fields[ result ]; - } else { - ok = 0; - } - -/* Move on to the first character following the terminator. */ - p = t + strlen( term ); - -/* In all other cases, this field is not terminated. Note its length - (ignoring trailing spaces). */ - } else { - nc[ result ] = astChrLen( fields[ result ] ); - p += nc[ result ]; - } - -/* Read a numerical value from this field. */ - if( astSscanf( fields[ result ], "%lg", &dval ) ) { - value += dval/3600.0; - } else { - ok = 0; - } - -/* Increment then number of returned fields if OK */ - if( ok ) result++; - - } - -/* Check that nothing is left.*/ - if( astChrLen( p ) > 0 ) ok = 0; - -/* If OK, convert the axis value to radians. */ - if( ok ) { - if( val ) { - *val = sign*value*( as_time ? hr2rad : deg2rad ); - } - -/* Otherwise, return zero. */ - } else { - result = 0; - for( ifld = 0; ifld < maxfld; ifld++ ) { - fields[ ifld ] = NULL; - nc[ ifld ] = 0; - } - } - } - -/* Return the result. */ - return result; -} - -static const char *AxisFormat( AstAxis *this_axis, double value, int *status ) { -/* -* Name: -* AxisFormat - -* Purpose: -* Format a coordinate value for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* const char *AxisFormat( AstAxis *this, double value, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astAxisFormat method inherited -* from the Axis class). - -* Description: -* This function returns a pointer to a string containing the formatted -* (character) version of a coordinate value for a SkyAxis. The formatting -* applied is that specified by a previous invocation of the -* astSetAxisFormat method. A suitable default format is applied if -* necessary. - -* Parameters: -* this -* Pointer to the SkyAxis. -* value -* The coordinate value to be formatted (in radians). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to a null-terminated string containing the formatted value. - -* Notes: -* - The returned string pointer may point at memory allocated within -* the SkyAxis object, 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 deletion of the SkyAxis. 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: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - const char *fmt; /* Pointer to format specifier */ - const char *result; /* Pointer to result string */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Initialise. */ - result = NULL; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Obtain a pointer to the format specifier to be used. Note we use a private - member function to obtain this (not a method) in case derived classes have - extended the syntax of this string. */ - fmt = GetAxisFormat( this_axis, status ); - -/* If the format string starts with a percent, use the AxisFormat method - inherited from the parent Axis class. Otherwise, format using the - syntax of this class. */ - if ( astOK ) { - if( fmt[ 0 ] == '%' ) { - result = (*parent_axisformat)( this_axis, value, status ); - } else { - result = DHmsFormat( fmt, astGetAxisDigits( this ), value, status ); - } - } - -/* Return the result. */ - return result; -} - -static double AxisGap( AstAxis *this_axis, double gap, int *ntick, int *status ) { -/* -* Name: -* AxisGap - -* Purpose: -* Find a "nice" gap for tabulating SkyAxis values. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* double AxisGap( AstAxis *this, double gap, int *ntick, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the protected astAxisGap -* method inherited from the Axis class). - -* Description: -* This function returns a gap size in radians which produces a -* nicely spaced series of formatted SkyAxis values, the returned -* gap size being as close as possible to the supplied target gap -* size. It also returns a convenient number of divisions into -* which the gap can be divided. - -* Parameters: -* this -* Pointer to the SkyAxis. -* gap -* The target gap size. -* ntick -* Address of an int in which to return a convenient number of -* divisions into which the gap can be divided. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The nice gap size. - -* Notes: -* - The returned gap size is influenced by the format string -* specified for the SkyAxis by a previous invocation of the -* astSetAxisFormat method. A suitable default format is used if -* necessary. -* - A value of zero is returned if the supplied gap size is zero. -* - A negative gap size is returned if the supplied gap size is negative. -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - const char *fmt; /* Pointer to Format string */ - double result; /* Returned gap size */ - -/* Initialise. */ - result = 0.0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Obtain a pointer to the format string to be used. Note we use a - private member function to obtain this (not a method) in case - derived classes have extended the syntax of this string. */ - fmt = GetAxisFormat( this_axis, status ); - -/* Obtain the closest "nice" gap size. */ - if ( astOK ) result = DHmsGap( fmt, astGetAxisDigits( this ), gap, ntick, status ); - -/* If the format string starts with a percent, use the AxisGap method - inherited from the parent Axis class. Otherwise, use the method - provided by this class. */ - if ( astOK ) { - if( fmt[ 0 ] == '%' ) { - result = (*parent_axisgap)( this_axis, gap, ntick, status ); - } else { - result = DHmsGap( fmt, astGetAxisDigits( this ), gap, ntick, status ); - } - } - -/* Return the result. */ - return result; -} - -static int AxisIn( AstAxis *this, double lo, double hi, double val, int closed, int *status ){ -/* -* Name: -* AxisIn - -* Purpose: -* Test if an axis value lies within a given interval. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "skyaxis.h" -* int AxisIn( AstAxis *this, double lo, double hi, double val, int closed, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astAxisIn method inherited -* from the Axis class). - -* Description: -* This function returns non-zero if a given axis values lies within a -* given axis interval. -* -* The SkyAxis implementation of this method treats the supplied -* numerical values as non-cyclic (e.g. lo=10, hi = 350 implies that -* val = 180 is inside and zero is outside: lo = 10, hi = 400 would imply -* that all angles are inside: lo = -10, hi = 10 would imply that 180 is -* outside and zero is inside). But when testing a supplied value, adding -* or subtracting multiples of 2.PI from the supplied value will make no -* difference to whether the point is inside or outside). - -* Parameters: -* this -* Pointer to the Axis. -* lo -* The lower axis limit of the interval. -* hi -* The upper axis limit of the interval. -* val -* The axis value to be tested. -* closed -* If non-zero, then the lo and hi axis values are themselves -* considered to be within the interval. Otherwise they are outside. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Non-zero if the test value is inside the interval. - -*/ - -/* For speed, omit the astOK check since no pointers are being used. */ - -/* Deal with closed intervals. */ - if( closed ) { - -/* If the supplied value is greater than the upper limit, subtract 2.PI until - it is not. */ - while( val > hi ) val -= 2*pi; - -/* If the value is now less than the lower limit, add 2.PI until it is not. */ - while( val < lo ) val += 2*pi; - -/* The axis value is in the range if its numerical value is less than or - equal to the end value. */ - return ( val <= hi ); - -/* Now deal with open intervals. */ - } else { - -/* If the supplied value is greater than or equal to the upper limit, subtract - 2.PI until it is not. */ - while( val >= hi ) val -= 2*pi; - -/* If the value is now less than or equal to the lower limit, add 2.PI until - it is not. */ - while( val <= lo ) val += 2*pi; - -/* The axis value is in the range if its numerical value is less than the - end value. */ - return ( val < hi ); - } -} - -static void AxisNorm( AstAxis *this_axis, double *value, int *status ) { -/* -* Name: -* AxisNorm - -* Purpose: -* Normalise a SkyAxis coordinate value. - -* Type: -* Public virtual function. - -* Synopsis: -* #include "skyaxis.h" -* void AxisNorm( AstAxis *this, double *value, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astAxisNorm method inherited -* from the Axis class). - -* Description: -* This function converts a SkyAxis coordinate value which might -* potentially be unsuitable for display to a user (for instance, -* may lie outside the expected range of values) into an acceptable -* alternative value suitable for display. -* -* For a SkyAxis that is a longitude axis, values are wrapped into -* the range zero to 2*pi, while for a latitude axis, they are -* wrapped into the range -pi to +pi. The astAxisCentreZero method -* is used to determine which algorithm to apply. - -* Parameters: -* this -* Pointer to the SkyAxis. -* value -* Pointer to the coordinate value to be normalised, which will -* be modified in place. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - int centrezero; /* SkyAxis range centred on zero? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* If the coordinate value is bad, then return it unchanged. Otherwise, - determine if the SkyAxis range is centred on zero or PI. */ - if ( *value != AST__BAD ) { - centrezero = astGetAxisCentreZero( this ); - -/* Wrap the value into the appropriate range. */ - if ( astOK ) *value = centrezero ? palDrange( *value ) : - palDranrm( *value ); - } -} - -static void AxisNormValues( AstAxis *this_axis, int oper, int nval, - double *values, int *status ){ -/* -* Name: -* astAxisNormValues - -* Purpose: -* Normalise an array of axis coordinate values. - -* Type: -* Public virtual function. - -* Synopsis: -* #include "skyaxis.h" -* void astAxisNormValues( AstAxis *this, int oper, int nval, -* double *values ) - -* Class Membership: -* SkyAxis member function (over-rides the astAxisNormValues method -* inherited from the Axis class). - -* Description: -* This function modifies a supplied array of axis values so that -* they are normalised in the manner indicated by parameter "oper". -* -* For a SkyAxis, if "oper" is 0, longitude values are returned in -* the range [0,2*PI]. If "oper" is 1, longitude values are returned -* in either the range [0,2*PI] or [-PI,PI]. The choice is made so -* that the resulting list has the smallest range. Latitude values -* are always returned in the range [-PI,PI]. - -* Parameters: -* this -* Pointer to the Axis. -* oper -* Indicates the type of normalisation to be applied. If zero is -* supplied, the normalisation will be the same as that performed by -* function astAxisNorm. If 1 is supplied, the normalisation will be -* chosen automatically so that the resulting list has the smallest -* range. -* nval -* The number of points in the values array. -* values -* On entry, the axis values to be normalised. Modified on exit to -* hold the normalised values. - -* Notes: -* - Bad axis values, and axis values outside the range -1E6 to +1E6 -* radians (such as DBL_MAX and DBL_MIN) are returned unchanged. - -*/ - -/* Local macros */ -#define VAL_OK(v) ((v)!=AST__BAD&&fabs(v)<1.0E6) - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - double *pv; /* Pointer to next axis value */ - double hi; /* Max axis value after normalisation */ - double lo; /* Min axis value after normalisation */ - double mn1; /* Min value in range [-pi,0] */ - double mn2; /* Min value in range [0,pi] */ - double mn3; /* Min value in range [pi,2pi] */ - double mx1; /* Max value in range [-pi,0] */ - double mx2; /* Max value in range [0,pi] */ - double mx3; /* Max value in range [pi,2pi] */ - double range1; /* Range after normalising to [0,2*pi] */ - double range2; /* Range after normalising to [-pi,pi] */ - double twopi; /* Two PI */ - int centrezero; /* SkyAxis range centred on zero? */ - int i; /* Index of next axis value */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Oper 0 - always normalise according to the value of the CentreZero - attribute (i.e. mimic AxisNorm). */ - if( oper == 0 ) { - -/* Determine if the SkyAxis range is centred on zero or PI. */ - centrezero = astGetAxisCentreZero( this ); - -/* Loop over axis values. */ - pv = values; - for( i = 0; i < nval; i++,pv++ ) { - -/* If the coordinate value is bad, or unusually large, then return it - unchanged. Otherwise, wrap the value into the appropriate range. */ - if( VAL_OK(*pv) ) *pv = centrezero ? palDrange( *pv ) : - palDranrm( *pv ); - } - -/* Oper 1 - choose a range that leaves most values unchanged. */ - } else if( oper == 1 ) { - -/* Normalise latitude axes into [-PI,+PI]. */ - if( astGetAxisIsLatitude( this ) ) { - pv = values; - for( i = 0; i < nval; i++,pv++ ) { - if( VAL_OK(*pv) ) *pv = palDrange( *pv ); - } - -/* Now deal with longitude axes. */ - } else { - -/* First ensure all values are in the range [-PI,2*PI] and find the max - and min value in each of the three ranges [-PI,0], [0,PI], [PI, 2PI]. */ - twopi = 2*AST__DPI; - mx1 = -DBL_MAX; - mn1 = DBL_MAX; - mx2 = -DBL_MAX; - mn2 = DBL_MAX; - mx3 = -DBL_MAX; - mn3 = DBL_MAX; - - pv = values; - for( i = 0; i < nval; i++,pv++ ) { - if( VAL_OK(*pv) ) { - while( *pv > twopi ) *pv -= twopi; - while( *pv < -AST__DPIBY2 ) *pv += twopi; - - if( *pv > AST__DPI ) { - mx3 = astMAX( mx3, *pv ); - mn3 = astMIN( mn3, *pv ); - } else if( *pv > 0 ) { - mx2 = astMAX( mx2, *pv ); - mn2 = astMIN( mn2, *pv ); - } else { - mx1 = astMAX( mx1, *pv ); - mn1 = astMIN( mn1, *pv ); - } - } - } - -/* What would the range be if we normalised into [0,2.PI] ? */ - if( mx1 != -DBL_MAX ) { - hi = astMAX( mx2, astMAX( mx1 + twopi, mx3) ); - lo = astMIN( mn2, astMIN( mn1 + twopi, mn3) ); - } else { - hi = astMAX( mx2, mx3 ); - lo = astMIN( mn2, mn3 ); - } - range1 = hi - lo; - -/* What would the range be if we normalised into [-PI,PI] ? */ - if( mn3 != -DBL_MAX ) { - hi = astMAX( mx2, astMAX( mx3 - twopi, mx1) ); - lo = astMIN( mn2, astMIN( mn3 - twopi, mn1) ); - } else { - hi = astMAX( mx2, mx1 ); - lo = astMIN( mn2, mn1 ); - } - range2 = hi - lo; - -/* If [-PI,PI] produces the smaller range, normalise into [-PI,PI]. */ - if( range2 < range1 ) { - pv = values; - for( i = 0; i < nval; i++,pv++ ) { - if( VAL_OK(*pv) ) *pv = palDrange( *pv ); - } - -/* Otherwise, normalise all into the range [0,2PI]. */ - } else { - pv = values; - for( i = 0; i < nval; i++,pv++ ) { - if( VAL_OK(*pv) ) *pv = palDranrm( *pv ); - } - } - } - -/* Report an error if the supplied operation is invalid. */ - } else if( astOK ) { - astError( AST__INTER, "astAxisNormValues: Invalid oper value %d " - "supplied (internal AST programming error).", status, oper ); - } - -#undef VAL_OK -} - -static double AxisOffset( AstAxis *this_axis, double v1, double dist, int *status ) { -/* -* -* Name: -* AxisOffset - -* Purpose: -* Add an increment onto a supplied axis value. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* AxisOffset( AstSkyAxis *this, double v1, double dist ) - -* Class Membership: -* SkyAxis member function (over-rides the protected astAxisOffset -* method inherited from the Axis class). - -* Description: -* This function returns an axis value formed by adding a signed axis -* increment onto a supplied axis value. -* -* For a SkyFrame, the result is normalized into the correct angular -* range (+PI to -PI for latitude axes, and 0 to 2*PI for longitude axes). - -* Parameters: -* this -* Pointer to the SkyAxis. -* v1 -* The supplied axis value -* dist -* The axis increment - -* Returned Value: -* The axis value which is the specified increment away from v1. - -* Notes: -* - A value of AST__BAD is returned if either axis value is AST__BAD. -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - double result; /* Returned gap size */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Check both axis values are OK, and form the returned axis value. */ - if( v1 != AST__BAD && dist != AST__BAD ) { - result = v1 + dist; - AxisNorm( this_axis, &result, status ); - } - -/* Return the result. */ - return result; -} - -static void AxisOverlay( AstAxis *template_axis, AstAxis *result, int *status ) { -/* -* Name: -* AxisOverlay - -* Purpose: -* Overlay the attributes of a template SkyAxis on to another Axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* void AxisOverlay( AstAxis *template, AstAxis *result, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astAxisOverlay method inherited -* from the Axis class). - -* Description: -* This function overlays attributes of a SkyAxis (the "template") on to -* another Axis, so as to over-ride selected attributes of that second -* Axis. Normally only those attributes which have been specifically set -* in the template will be transferred. This implements a form of -* defaulting, in which an Axis acquires attributes from the template, but -* retains its original attributes (as the default) if new values have not -* previously been explicitly set in the template. - -* Parameters: -* template -* Pointer to the template SkyAxis, for which values should have been -* explicitly set for any attribute which is to be transferred. -* result -* Pointer to the Axis which is to receive the new attribute values. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* void -*/ - -/* Local Variables: */ - AstSkyAxis *template; /* Pointer to the SkyAxis structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the template SkyAxis structure. */ - template = (AstSkyAxis *) template_axis; - -/* Invoke the parent astAstOverlay method to overlay inherited attributes. */ - (*parent_axisoverlay)( template_axis, result, status ); - -/* Test if the "result" Axis is a SkyAxis (if not, it cannot acquire any - further attributes, so there is nothing more to do). */ - if ( astIsASkyAxis( result ) && astOK ) { - -/* Overlay the Format attribute if it is set in the template. Note that we - use private member functions (not methods) to access the Format value, since - derived classes may extend the syntax of this string and we should not - overlay a string whose syntax cannot be interpreted by the result Axis. */ - if ( TestAxisFormat( template_axis, status ) ) { - SetAxisFormat( result, GetAxisFormat( template_axis, status ), status ); - } - -/* Overlay the AsTime attribute in the same way, but this time using methods - to access it. */ - if ( astTestAxisAsTime( template ) ) { - astSetAxisAsTime( result, astGetAxisAsTime( template ) ); - } - -/* Also overlay the IsLatitude attribute. */ - if ( astTestAxisIsLatitude( template ) ) { - astSetAxisIsLatitude( result, astGetAxisIsLatitude( template ) ); - } - -/* Also overlay the CentreZero attribute. */ - if ( astTestAxisCentreZero( template ) ) { - astSetAxisCentreZero( result, astGetAxisCentreZero( template ) ); - } - } -} - -static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* ClearAttrib - -* Purpose: -* Clear an attribute value for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* void ClearAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astClearAttrib protected -* method inherited from the Axis class). - -* Description: -* This function clears the value of a specified attribute for a -* SkyAxis, so that the default value will subsequently be used. - -* Parameters: -* this -* Pointer to the SkyAxis. -* 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: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_object; - -/* Check the attribute name and clear the appropriate attribute. */ - -/* AsTime. */ -/* ------- */ - if ( !strcmp( attrib, "astime" ) ) { - astClearAxisAsTime( this ); - -/* IsLatitude. */ -/* ----------- */ - } else if ( !strcmp( attrib, "islatitude" ) ) { - astClearAxisIsLatitude( this ); - -/* CentreZero. */ -/* ----------- */ - } else if ( !strcmp( attrib, "centrezero" ) ) { - astClearAxisCentreZero( this ); - -/* 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 void ClearAxisFormat( AstAxis *this_axis, int *status ) { -/* -* Name: -* ClearAxisFormat - -* Purpose: -* Clear the Format attribute for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* void ClearAxisFormat( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astClearAxisFormat method -* inherited from the Axis class). - -* Description: -* This function clears the Format attribute of a SkyAxis, as if no value -* had ever been set for it. - -* Parameters: -* this -* Pointer to the SkyAxis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* void -*/ - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Free any memory allocated to hold the Format string and reset the string - pointer to NULL. */ - this->skyformat = astFree( this->skyformat ); -} - -static const char *DHmsFormat( const char *fmt, int digs, double value, int *status ) { -/* -* Name: -* DHmsFormat - -* Purpose: -* Format a value representing degrees/hours, minutes and seconds. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* const char *DHmsFormat( const char *fmt, int digs, double value, int *status ) - -* Class Membership: -* SkyAxis member function. - -* Description: -* This function formats a value representing an angle in radians -* into a text string giving degrees/hours, minutes and seconds -* according to a format specifier supplied. See the "Format -* Specifier" section for details of the formats available. - -* Parameters: -* fmt -* Pointer to a null terminated string containing the format -* specifier. -* digs -* The default number of digits of precision to use. This is used -* if the given format specifier indicates the number of decimal -* places to use with the string ".*". In this case, the number of -* decimal places produced will be chosen so that the total number -* of digits of precision is equal to "digs". -* double -* The value to be formatted (in radians). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to a null terminated character string containing the -* formatted value. - -* Format Specifier: -* The format specifier supplied via the "fmt" parameter should -* contain zero or more of the following characters to specify the -* format required. These characters may occur in any order, but -* the following is recommended for clarity: -* -* '+' -* Indicates that a plus sign should be prefixed to positive -* values. By default, no plus sign is used. -* 'z' -* Indicates that leading zeros should be prefixed to the value -* so that the first field is always of constant width, as would -* be required in a fixed-width table. (Leading zeros are always -* prefixed to any fields that follow.) By default, no leading -* zeros are added. -* 'i' -* Use the standard ISO field separator (a colon) between -* fields. This is the default behaviour. -* 'b' -* Use a blank to separate fields. -* 'l' -* Use a letter ('d'/'h', 'm' or 's' as appropriate) to separate -* and identify fields. -* 'g' -* As 'l', but escape sequences are included in the returned -* character string which cause the separators ('h', 'd', 'm', etc) -* to be drawn as small super-scripts when plotted by the astText -* or astGrid. -* 'd' -* Express the value as an angle and include a degrees -* field. Expressing the value as an angle is also the default -* behaviour if neither 'h' nor 't' is given, and expressing it -* in degrees is the default if neither 'm' nor 's' is given. -* 'h' -* Express the value as a time instead of an angle (where 24 -* hours correspond to 360 degrees) and include an hours -* field. Expressing times in hours is the default if 't' is -* given without either 'm' or 's'. -* 'm' -* Include a minutes field. By default this is not included. -* 's' -* Include a seconds field. By default this is not -* included. This request is ignored if 'd' or 'h' is given, -* unless a minutes field is also included. -* 't' -* Express the value as a time instead of an angle (where 24 -* hours correspond to 360 degrees). This option is ignored if -* either 'd' or 'h' is given and is intended for use in cases -* where the value is to be expressed purely in minutes and/or -* seconds of time (no hours field). If 't' is given without -* 'd', 'h', 'm' or 's' being present, then it is equivalent to -* 'h'. -* '.' -* Indicates that decimal places are to be given for the final -* field in the formatted string (whichever field this is). The -* '.' should be followed immediately by a zero or positive integer -* which gives the number of decimal places required. The '.' may -* also be followed by asterisk (i.e. '.*') which causes the number -* of decimal places to be chosen so that the total number of digits -* is equal to the value of Digits. -* -* Format specifiers are not case sensitive. If several characters -* make conflicting requests (e.g. if both 'i' and 'l' appear in a -* format specifier), then the character occurring last takes -* precedence, except that 'd' and 'h' always override 't'. - -* Notes: -* - The result string may be stored in static memory. Its contents -* may be over-written or the returned pointer may become invalid -* following a further invocation of this function. 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. - -* Acknowledgements: -* - This function is a close approximation to a Fortran 77 routine -* written by Clive Davenhall which implements the system of format -* specifiers for angles described in his document on the CAT -* catalogue access library (Starlink User Note 181). Some minor -* improvements have been made to ensure better behaviour when -* results are rounded to a specified number of decimal places. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - char *term; /* Pointer to terminator string */ - char sep; /* Field separator character */ - char tbuf[50]; /* Buffer for terminator string */ - const char *result; /* Pointer to result string */ - double absvalue; /* Absolute value in radians */ - double fract; /* Fractional part of final field */ - double idh; /* Integer number of degrees/hours */ - double ifract; /* Fractional part expressed as an integer */ - double imin; /* Integer number of minutes */ - double isec; /* Integer number of seconds */ - double shift; /* Factor for rounding fractional part */ - double test; /* Test value to determine rounding */ - int as_time; /* Format the value as a time? */ - int dh; /* Degrees/hours field required? */ - int lead_zero; /* Add leading zeros? */ - int min; /* Minutes field required? */ - int ndp; /* Number of decimal places */ - int plus; /* Add leading plus sign? */ - int pos; /* Position to add next character */ - int positive; /* Value is positive (or zero)? */ - int sec; /* Seconds field required? */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Initialise. */ - result = NULL; - -/* Check if a bad coordinate value has been given and return an - appropriate string. */ - if ( value == AST__BAD ) { - result = "<bad>"; - -/* Otherwise... */ - } else { - -/* Parse the format specifier. */ - ParseDHmsFormat( fmt, digs, &sep, &plus, &lead_zero, - &as_time, &dh, &min, &sec, &ndp, status ); - -/* Break the value into fields. */ -/* ---------------------------- */ -/* Restrict the number of decimal places requested, if necessary, so - that under the worst case the buffer for the result string is not - likely to overflow. */ - if ( astOK ) { - if ( ( ndp + 11 ) > AST__SKYAXIS_DHMSFORMAT_BUFF_LEN ) ndp = AST__SKYAXIS_DHMSFORMAT_BUFF_LEN - 11; - -/* Some operating systems have a "minus zero" value (for instance - "-1.2*0" would give "-0"). This value is numerically equivalent to - zero, but is formated as "-0" instead of "0". The leading minus sign - confuses the following code, and so ensure now that all zero values - are the usual "+0". */ - if ( value == 0.0 ) value = 0.0; - -/* Determine if the value to be formatted is positive and obtain its - absolute value in radians. */ - positive = ( value >= 0.0 ); - absvalue = positive ? value : -value; - -/* Convert this to an absolute number of degrees or hours, as - required. */ - fract = absvalue / ( as_time ? hr2rad : deg2rad ); - -/* If a degrees/hours field is required, extract the whole number of - degrees/hours and the remaining fractional part of a - degree/hour. */ - idh = 0.0; - if ( dh ) fract = modf( fract, &idh ); - -/* If a minutes field is required, convert the value remaining to - minutes and extract the whole number of minutes and the remaining - fractional part of a minute. */ - imin = 0.0; - if ( min ) fract = modf( fract * 60.0, &imin ); - -/* If a seconds field is required, convert the value remaining to - seconds (allowing for the absence of a minutes field if necessary) - and extract the whole number of seconds and the remaining - fractional part of a second. */ - isec = 0.0; - if ( sec ) { - if ( !min ) fract *= 60.0; - fract = modf( fract * 60.0, &isec ); - } - -/* Round to the required number of decimal places. */ -/* ----------------------------------------------- */ -/* We must now round the fractional part (of whichever field) to the - required number of decimal places. Calculate the power of 10 that - brings the least significant digit into the units column. Scale the - fractional part by this factor and truncate to an integer (but - stored as a double to prevent possible integer overflow if the - number of decimal places is excessive). */ - shift = pow( 10.0, (double) ndp ); - ifract = floor( fract * shift ); - -/* Next we must determine if truncation was adequate, or whether we - should round upwards instead. This process is more subtle than it - seems because if a value with a 5 as the final digit is converted - to radians and then back again, it may no longer end in 5 (because - it cannot be represented exactly in radians) and so may round - either up or down. If we want to recover the original (textual) - value, we must compare the value we are formatting not with a test - value whose last digit is 5, but with the closest number to this - that can be represented exactly in radians. - - To do this, we add 0.5 to our truncated value, divide by the scale - factor (to get the truncated fractional part, but now with a - trailing digit 5 appended) and then combine this fractional part - with the value of all the other fields. Finally, we convert this - test value back into radians. */ - test = ( 0.5 + ifract ) / shift; - if ( sec ) test = ( isec + test ) / 60.0; - if ( min ) { - test = ( imin + test ) / 60.0; - } else if ( sec ) { - test /= 60.0; - } - if ( dh ) test += idh; - test *= ( as_time ? hr2rad : deg2rad ); - -/* We now compare the absolute value we are formatting with this test - value. If it is not smaller than it, we should have rounded up - instead of truncating the final digit of the fractional part, so - increment the integer representation of the truncated fractional - part by 1.0 to compensate. */ - if ( absvalue >= test ) ifract += 1.0; - -/* Divide by the scale factor to obtain the correctly rounded - fractional part. Then check if this fractional part is 1.0. If so, - rounding has caused it to overflow into the units column of the - final field, so clear the fractional part. */ - fract = ( ifract / shift ); - if ( fract >= 1.0 ) { - ifract = 0.0; - -/* If a seconds field is present, propagate the overflow up through - each field in turn, but omitting fields which are not required. Be - careful about possible rounding errors when comparing integer - values stored as double. */ - if ( sec ) { - isec += 1.0; - if ( ( floor( isec + 0.5 ) > 59.5 ) && min ) { - isec = 0.0; - imin += 1.0; - if ( ( floor( imin + 0.5 ) > 59.5 ) && dh ) { - imin = 0.0; - idh += 1.0; - } - } - -/* Omit the seconds field if it is not present. */ - } else if ( min ) { - imin += 1.0; - if ( ( floor( imin + 0.5 ) > 59.5 ) && dh ) { - imin = 0.0; - idh += 1.0; - } - -/* If only the degree/hour field is present, simply increment it. */ - } else { - idh += 1.0; - } - } - -/* Construct the result string. */ -/* ---------------------------- */ -/* We now have the value of each field and the information about how - they are to be formatted, so we can combine them into the required - string. */ - -/* If each field is either not required or equal to zero, disregard - any sign. */ - if ( !positive && ( !dh || floor( idh + 0.5 ) < 0.5 ) && - ( !min || floor( imin + 0.5 ) < 0.5 ) && - ( !sec || floor( isec + 0.5 ) < 0.5 ) && - ( floor( ifract + 0.5 ) < 0.5 ) ) { - positive = 1; - } - -/* Use "pos" to identify where the next character should be - added. Insert a leading '+' or '-' sign if required. */ - pos = 0; - if ( !positive ) { - dhmsformat_buff[ pos++ ] = '-'; - } else if ( plus ) { - dhmsformat_buff[ pos++ ] = '+'; - } - -/* Use "sprintf" to format the degrees/hours field, if required. Set - the minimum field width according to whether padding with leading - zeros is required and whether the value represents hours (2 digits) - or degrees (3 digits). */ - if ( dh ) { - pos += sprintf( dhmsformat_buff + pos, "%0*.0f", - lead_zero ? ( as_time ? 2 : 3 ) : 1, idh ); - -/* If letters are being used as field separators, and there are more - fields to follow, append "d" or "h" as necessary. */ - if ( min || sec ) { - if ( sep == 'l' ) { - dhmsformat_buff[ pos++ ] = ( as_time ? 'h' : 'd' ); - } else if( sep == 'g' ) { - astTuneC( as_time ? "hrdel":"dgdel", NULL, tbuf, - sizeof( tbuf ) ); - term = tbuf; - pos += sprintf( dhmsformat_buff + pos, "%s", term ); - } - } - } - -/* If a minutes field is required, first add an appropriate non-letter - field separator if needed. */ - if ( min ) { - if ( ( sep != 'l' && sep != 'g' ) && dh ) dhmsformat_buff[ pos++ ] = sep; - -/* Then format the minutes field with a leading zero to make it two - digits if necessary. */ - pos += sprintf( dhmsformat_buff + pos, "%0*.0f", ( dh || lead_zero ) ? 2 : 1, - imin ); - -/* If letters are being used as field separators, and there is another - field to follow, append the separator. */ - if ( sec ) { - if ( sep == 'l' ) { - dhmsformat_buff[ pos++ ] = 'm'; - } else if( sep == 'g' ) { - astTuneC( as_time ? "mndel":"amdel", NULL, tbuf, - sizeof( tbuf ) ); - term = tbuf; - pos += sprintf( dhmsformat_buff + pos, "%s", term ); - } - } - } - -/* Similarly, if a seconds field is required, first add an appropriate - non-letter field separator if needed. */ - if ( sec ) { - if ( ( sep != 'l' && sep != 'g' ) && ( dh || min ) ) dhmsformat_buff[ pos++ ] = sep; - -/* Then format the seconds field with a leading zero to make it two - digits if necessary. */ - pos += sprintf( dhmsformat_buff + pos, "%0*.0f", - ( dh || min || lead_zero ) ? 2 : 1, isec ); - } - -/* If decimal places are needed, add a decimal point followed by the - integer representation of the correctly rounded fractional part, - padded with leading zeros if necessary. */ - if ( ndp > 0 ) { - dhmsformat_buff[ pos++ ] = '.'; - pos += sprintf( dhmsformat_buff + pos, "%0*.0f", ndp, ifract ); - } - -/* If letters are being used as separators, append the appropriate one - to the final field. */ - if ( sep == 'l' ) { - dhmsformat_buff[ pos++ ] = ( sec ? 's' : ( min ? 'm' : - ( as_time ? 'h' : 'd' ) ) ); - } else if ( sep == 'g' ) { - astTuneC( as_time ? ( sec ? "scdel" : ( min ? "mndel" : "hrdel" ) ) : - ( sec ? "asdel" : ( min ? "amdel" : "dgdel" ) ), - NULL, tbuf, sizeof( tbuf ) ); - term = tbuf; - pos += sprintf( dhmsformat_buff + pos, "%s", term ); - } - -/* Terminate the result string and return a pointer to it. */ - dhmsformat_buff[ pos ] = '\0'; - result = dhmsformat_buff; - } - } - -/* Return the result. */ - return result; -} - -static double DHmsGap( const char *fmt, int digs, double gap, int *ntick, int *status ) { -/* -* Name: -* DHmsGap - -* Purpose: -* Find a "nice" gap for formatted SkyAxis values. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* double DHmsGap( const char *fmt, int digs, double gap, int *ntick, int *status ) - -* Class Membership: -* SkyAxis member function. - -* Description: -* This function returns a gap size in radians which produces a -* nicely spaced series of formatted SkyAxis values, the returned -* gap size being as close as possible to the supplied target gap -* size. It also returns a convenient number of divisions into -* which the gap can be divided. - -* Parameters: -* fmt -* Pointer to a constant null-terminated string containing the -* format specifier which will be used to format the SkyAxis -* values. -* digs -* The default number of digits of precision to use. This is used -* if the given format specifier indicates the number of decimal -* places to use with the string ".*". In this case, the number of -* decimal places produced will be chosen so that the total number -* of digits of precision is equal to "digs". -* gap -* The target gap size. -* ntick -* Address of an int in which to return a convenient number of -* divisions into which the gap can be divided. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The nice gap size. - -* Notes: -* - A value of zero is returned if the target gap size is zero. -* - A negative gap size is returned if the supplied gap size is -* negative. -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Constants: */ -#define BUFF_LEN 50 /* Length of character buffer */ - -/* Local Variables: */ - char buff[ BUFF_LEN + 1 ]; /* Buffer for formatted scaled "nice" value */ - char sep; /* Field separator character */ - const double *table; /* Pointer to nice gap table */ - const int *nticks; /* Pointer to number of subdivisions table */ - double field_value[ 3 ]; /* Formatted field values in radians */ - double scale; /* Power of ten scaling factor */ - double scaled_table_value; /* Scaled "nice" value to test against */ - int as_time; /* Format the value as a time? */ - int decimal; /* Use nice decimal gap value? */ - int dh; /* Degrees/hours field required? */ - int field; /* ID of most significant formatted field */ - int i; /* Look-up-table index */ - int iter; /* Iteration count */ - int lead_zero; /* Add leading zeros? */ - int min; /* Minutes field required? */ - int ndp; /* Number of decimal places */ - int plus; /* Add leading plus sign? */ - int positive; /* Value is positive (or zero)? */ - int sec; /* Seconds field required? */ - -/* Local Data: */ -/* ----------- */ -/* Table of nice decimal gaps. */ - const double dec_table[] = { 1.0, 2.0, 5.0, 5.0, 10.0, -1.0 }; - const int dec_nticks[] = { 5, 4, 5, 5, 5 }; - -/* Table of nice degrees gaps. */ - const double deg_table[] = - { 1.0, 2.0, 5.0, 10.0, 30.0, 45.0, 60.0, 90.0, 180.0, 360.0, -1.0 }; - const int deg_nticks[] = - { 4, 4, 5, 5, 6, 3, 6, 3, 3, 4 }; - -/* Table of nice hours gaps. */ - const double hr_table[] = { 1.0, 2.0, 3.0, 6.0, 12.0, 24.0, -1.0 }; - const int hr_nticks[] = { 4, 4, 6, 6, 4, 4 }; - -/* Table of nice minutes or seconds gaps. */ - const double minsec_table[] = { 1.0, 2.0, 5.0, 10.0, 30.0, 60.0, -1.0 }; - const int minsec_nticks[] = { 4, 4, 5, 5, 6, 4 }; - -/* Check the global error status. */ - if ( !astOK ) return 0.0; - -/* Check that the supplied gap size is not zero. */ - if ( gap != 0.0 ) { - -/* Parse the format specifier. */ - ParseDHmsFormat( fmt, digs, &sep, &plus, &lead_zero, &as_time, &dh, &min, - &sec, &ndp, status ); - -/* If OK, calculate the value of each formatted field in radians. */ - if ( astOK ) { - field_value[ 0 ] = ( as_time ? hr2rad : deg2rad ); - field_value[ 1 ] = field_value[ 0 ] / 60.0; - field_value[ 2 ] = field_value[ 0 ] / 3600.0; - -/* Determine if the suggested gap size is positive and obtain its - absolute value. */ - positive = ( gap >= 0.0 ); - if ( !positive ) gap = -gap; - -/* Perform two iterations to determine the optimum gap value. This is - because the method of choosing the gap value depends on the initial - value. If a nice decimal gap is chosen on the first iteration, - this may round the suggested gap value downwards, making it - preferable to choose the gap value using a different method on the - second iteration. */ - for ( iter = 0; iter < 2; iter++ ) { - -/* Decide which is the most significant field that the suggested gap - value will occupy when formatted. Also decide whether to use a - special "nice" gap value specific to that field, or simply to use a - generic nice decimal gap value. Perform all tests on the gap size - in radians, so as to avoid any rounding problems from conversion - into degrees/hours, minutes or seconds. */ - decimal = 0; - -/* Suggested values exceeding one degree/hour. */ -/* ------------------------------------------- */ - if ( gap > field_value[ 0 ] ) { - -/* If a degree/hour field is present, use a special gap value, unless - the suggested value exceeds the normal range of this field (in - which case use a decimal gap). */ - if ( dh ) { - field = 1; - decimal = ( gap > ( field_value[ 0 ] * - ( as_time ? 24.0 : 360.0 ) ) ); - -/* If the most significant field is not degrees/hours, then its normal - range will be exceeded, so use a decimal gap. */ - } else if ( min ) { - field = 2; - decimal = 1; - } else { - field = 3; - decimal = 1; - } - -/* Suggested values exceeding one minute. */ -/* -------------------------------------- */ - } else if ( gap > field_value[ 1 ] ) { - -/* If a minutes field is present, the suggested value will lie within - its normal range, so use a special gap value. */ - if ( min ) { - field = 2; - -/* Otherwise, if the most significant field is seconds, its normal - range will be exceeded, so use a decimal gap value. */ - } else if ( sec ) { - field = 3; - decimal = 1; - -/* If only a degrees/hours field is present, then only digits after - the decimal point can be affected, so use a decimal gap value. */ - } else { - field = 1; - decimal = 1; - } - -/* Suggested values exceeding one second. */ -/* -------------------------------------- */ - } else if ( gap > field_value[ 2 ] ) { - -/* If a seconds field is present, the suggested value will lie within - its normal range, so use a special gap value. */ - if ( sec ) { - field = 3; - -/* If the least significant field is degrees/hours or minutes, then - only digits after the decimal point can be affected, so use a - decimal gap value. */ - } else if ( min ) { - field = 2; - decimal = 1; - } else { - field = 1; - decimal = 1; - } - -/* Suggested values less than one second. */ -/* -------------------------------------- */ - } else { - -/* Only digits after the decimal point can be affected, so decide - which is the least significant field present and use a decimal - gap. */ - if ( sec ) { - field = 3; - } else if ( min ) { - field = 2; - } else { - field = 1; - } - decimal = 1; - } - -/* If a decimal gap value is required, select the appropriate table of - gap values and numbers of subdivisions. */ - if ( decimal ) { - table = dec_table; - nticks = dec_nticks; - -/* Find a power of ten divisor which scales the suggested value (when - formatted) into the range 1.0 to 10.0. */ - scale = pow( 10.0, - floor( log10( gap / field_value[ field - 1 ] ) ) ); - -/* Look the scaled value up in the table, comparing values in radians - to avoid rounding problems due to conversion to/from - degrees/radians, etc. */ - for ( i = 0; table[ i + 1 ] > 0.0; i++ ) { - -/* We must be careful about rounding errors here. If, for example, we - read in a value of 0.15 as the suggested gap value, the scaled - "nice" value we would be comparing it with would be 0.1 times the - values in the nice values table. The relevant value in this table - is 1.5 (i.e. 0.5 * ( 1.0 + 2.0 ) ), so we would compute 0.1 * 1.5 - as the test value. However, this is probably not equal (to machine - precision) to the number that results when a formatted value of - 0.15 is read, because 0.1 isn't exactly representable. Since it is - the formatted appearance of the numbers which matters, we want a - new scaled nice table containing the numbers that result from - reading the formatted values 0.1, 0.2, etc. To achieve this effect, - we format the scaled table value using the default floating point - precision (which rounds to a relatively small number of decimal - digits) and then read the value back again. */ - (void ) sprintf( buff, "%g", scale * - 0.5 * ( table[ i ] + table[ i + 1 ] ) ); - (void) astSscanf( buff, "%lf", &scaled_table_value ); - -/* Now test the suggested gap value against the scaled table value. */ - if ( gap < ( field_value[ field - 1 ] * - scaled_table_value ) ) break; - } - -/* Return the nice gap value and the number of subdivisions. */ - gap = scale * field_value[ field - 1 ] * table[ i ]; - if ( ntick ) *ntick = nticks[ i ]; - -/* If a special gap value appropriate to the field is required, then - select the table of gap values and numbers of subdivisions - according to which field we are considering and whether it contains - degrees or hours. */ - } else { - if ( field == 1 ) { - if ( as_time ) { - table = hr_table; - nticks = hr_nticks; - } else { - table = deg_table; - nticks = deg_nticks; - } - } else { - table = minsec_table; - nticks = minsec_nticks; - } - -/* Search the table for a suitable gap. We do not need to format and - unformat the test value here (as we did above) because the table - values are being used literally and not being scaled. */ - for ( i = 0; table[ i + 1 ] > 0.0; i++ ) { - if ( gap < ( field_value[ field - 1 ] * - 0.5 * ( table[ i ] + table[ i + 1 ] ) ) ) break; - } - -/* Return the nice gap value and the number of subdivisions. */ - gap = field_value[ field - 1 ] * table[ i ]; - if ( ntick ) *ntick = nticks[ i ]; - } - } - -/* After iterations are complete, restore the original sign. */ - if ( !positive ) gap = -gap; - } - } - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) gap = 0.0; - -/* Return the result. */ - return gap; - -/* Undefine macros local to this function */ -#undef BUFF_LEN -} - -static const char *DHmsUnit( const char *fmt, int digs, int output, int *status ) { -/* -* Name: -* DHmsUnit - -* Purpose: -* Generate a unit string to describe a formatted angle or time. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* const char *DHmsUnit( const char *fmt, int digs, int output, int *status ) - -* Class Membership: -* SkyAxis member function. - -* Description: -* This function generates a string that may be used to describe -* either (a) the units of an angle or time that has been formatted -* for output using the DHmsFormat function, or (b) a suitable -* format to be used for an angle or time that is to be supplied as -* an input coordinate value. - -* Parameters: -* fmt -* Pointer to a null terminated string containing the format -* specifier used to format coordinate values. For details of -* the syntax of this string, see the DHmsFormat function. -* digs -* The default number of digits of precision to use. This is used -* if the given format specifier indicates the number of decimal -* places to use with the string ".*". In this case, the number of -* decimal places produced will be chosen so that the total number -* of digits of precision is equal to "digs". -* output -* If non-zero, the returned string will be in a form suitable -* for describing the units/format of output produced using -* DHmsFormat. -* -* If zero, the returned string will be in a form suitable for -* describing a suggested input format, which will subsequently -* be read using AxisUnformat. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to a null terminated string containing the unit description. - -* Notes: -* - The result string may be stored in static memory. Its contents -* may be over-written or the returned pointer may become invalid -* following a further invocation of this function. 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: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - char dpchar; /* Character to indicate decimal places */ - char sep; /* Field separator character */ - const char *result; /* Pointer to result string */ - const int maxdp = 6; /* Maximum number of decimal places to show */ - int as_time; /* Value formatted as a time? */ - int dh; /* Degrees/hours field required? */ - int dp; /* Loop counter for decimal places */ - int lead_zero; /* Add leading zeros? */ - int min; /* Minutes field required? */ - int ndp; /* Number of decimal places */ - int plus; /* Leading plus sign required? */ - int pos; /* Position to add next character */ - int sec; /* Seconds field required? */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Parse the format specifier. */ - ParseDHmsFormat( fmt, digs, &sep, &plus, &lead_zero, &as_time, &dh, &min, - &sec, &ndp, status ); - -/* If the units string is required to describe formatted output and - the field separators are letters (e.g. giving "01h23m45s" or - "012d34m56s"), then the units will already be clear so return a - pointer to an empty units string. */ - if ( astOK ) { - if ( output && ( sep == 'l' || sep == 'g' ) ) { - result = ""; - -/* Otherwise, if the units string is required to describe formatted - output and there is only one field present, then select an - appropriate string. */ - } else if ( output && dh && !min && !sec ) { - result = as_time ? "hours" : "degrees"; - - } else if ( output && !dh && min && !sec ) { - result = as_time ? "minutes of time" : "arcminutes"; - - } else if ( output && !dh && !min && sec ) { - result = as_time ? "seconds of time" : "arcseconds"; - -/* If there is more than one field present, or we want to describe how - to supply formatted input, then we will generate a units string of - the general form "ddd:mm:ss.sss" or "hh:mm:ss.s" or - similar. Initialise the output character count and the character to - be used to represent decimal places. */ - } else { - pos = 0; - dpchar = 'd'; - -/* Decide which field separator to use (use a space if letters were - requested since it is easier to input). */ - if ( sep == 'l' || sep == 'g' ) sep = ' '; - -/* Start with the "ddd" or "hh" field, if required, and update the - decimal places character appropriately. */ - if ( dh ) { - pos += sprintf( dhmsunit_buff, "%s", as_time ? "hh" : "ddd" ); - dpchar = as_time ? 'h' : 'd'; - } - -/* If a minutes field is present, add a separator if necessary and - "mm" and update the decimal places character. */ - if ( min ) { - if ( dh ) dhmsunit_buff[ pos++ ] = sep; - dhmsunit_buff[ pos++ ] = 'm'; - dhmsunit_buff[ pos++ ] = 'm'; - dpchar = 'm'; - } - -/* Repeat this process for the seconds field, if present. */ - if ( sec ) { - if ( dh || min ) dhmsunit_buff[ pos++ ] = sep; - dhmsunit_buff[ pos++ ] = 's'; - dhmsunit_buff[ pos++ ] = 's'; - dpchar = 's'; - } - -/* If decimal places are present, add a decimal point and then loop to - add further instances of the decimal places character to represent - the digits that follow. */ - if ( ndp > 0 ) { - dhmsunit_buff[ pos++ ] = '.'; - for ( dp = 0; dp < ndp; dp++ ) { - if ( dp < maxdp ) { - dhmsunit_buff[ pos++ ] = dpchar; - -/* After showing the maximum number of decimal places, simply add an - ellipsis and quit (otherwise the result gets boring to look at). */ - } else { - dhmsunit_buff[ pos - 1 ] = '.'; - dhmsunit_buff[ pos - 2 ] = '.'; - dhmsunit_buff[ pos - 3 ] = '.'; - break; - } - } - } - -/* Terminate the result string and return a pointer to it. */ - dhmsunit_buff[ pos ] = '\0'; - result = dhmsunit_buff; - } - } - -/* Return the result. */ - return result; -} - -static int GetObjSize( AstObject *this_object, int *status ) { -/* -* Name: -* GetObjSize - -* Purpose: -* Return the in-memory size of an Object. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* int GetObjSize( AstObject *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astGetObjSize protected -* method inherited from the parent class). - -* Description: -* This function returns the in-memory size of the supplied SkyAxis, -* in bytes. - -* Parameters: -* this -* Pointer to the SkyAxis. -* 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: */ - AstSkyAxis *this; /* Pointer to SkyAxis structure */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointers to the SkyAxis structure. */ - this = (AstSkyAxis *) 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 += astTSizeOf( this->skyformat ); - -/* 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 SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* const char *GetAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the protected astGetAttrib -* method inherited from the Axis class). - -* Description: -* This function returns a pointer to the value of a specified -* attribute for a SkyAxis, formatted as a character string. - -* Parameters: -* this -* Pointer to the SkyAxis. -* 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 SkyAxis, 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 SkyAxis. 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: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - const char *result; /* Pointer value to return */ - int as_time; /* AsTime attribute value */ - int centrezero; /* CentreZero attribute value */ - int is_latitude; /* IsLatitude attribute value */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(this_object); - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_object; - -/* Compare "attrib" with each recognised attribute name in turn, - obtaining the value of the required attribute. If necessary, write - the value into "getattrib_buff" as a null-terminated string in an appropriate - format. Set "result" to point at the result string. */ - -/* AsTime. */ -/* ------- */ - if ( !strcmp( attrib, "astime" ) ) { - as_time = astGetAxisAsTime( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", as_time ); - result = getattrib_buff; - } - -/* IsLatitude. */ -/* ----------- */ - } else if ( !strcmp( attrib, "islatitude" ) ) { - is_latitude = astGetAxisIsLatitude( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", is_latitude ); - result = getattrib_buff; - } - -/* CentreZero. */ -/* ----------- */ - } else if ( !strcmp( attrib, "centrezero" ) ) { - centrezero= astGetAxisCentreZero( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", centrezero ); - result = getattrib_buff; - } - -/* 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 double GetAxisBottom( AstAxis *this_axis, int *status ) { -/* -* Name: -* GetAxisBottom - -* Purpose: -* Obtain the value of the Bottom attribute for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* double GetAxisBottom( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astGetAxisBottom method -* inherited from the Axis class). - -* Description: -* This function returns a value for the Bottom attribute of a SkyAxis. -* This attribute indicates the lowest legal value for the axis. - -* Parameters: -* this -* Pointer to the SkyAxis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The atribute value. A suitable default value is supplied if necessary. - -* Notes: -* - A value of -DBL_MAX will be returned if this function is invoked -* with the global error status set, or if it should fail for any reason. -*/ - -/* Local Variables. */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - double result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return -DBL_MAX; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Check if a value has been set for the Bottom attribute. If so, obtain - this value. */ - if ( astTestAxisBottom( this ) ) { - result = (*parent_getaxisbottom)( this_axis, status ); - -/* Otherwise, supply a default of -pi/2 for latitude axes, and -DBL_MAX - for longitude axes. */ - } else { - result = astGetAxisIsLatitude( this ) ? -piby2 : -DBL_MAX; - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = -DBL_MAX; - -/* Return the result. */ - return result; -} - -static const char *GetAxisInternalUnit( AstAxis *this, int *status ){ -/* -* Name: -* GetAxisInternalUnit - -* Purpose: -* Return the unit string for unformatted Axis values - -* Type: -* Private function. - -* Synopsis: -* #include "axis.h" -* const char *GetAxisInternalUnit( AstAxis *this ) - -* Class Membership: -* SkyAxis member function (over-rides the astGetAxisInternalUnit method -* inherited from the Axis class). - -* Description: -* This function returns the axis InternalUnit attribute. For sky -* axes, the InternalUnit is always "rad" (radians). - -* Parameters: -* this -* Pointer to the Axis. - -* Returned Value: -* - Pointer to a null-terminated string containing the internal -* unit string. - -* Notes: -* - The returned pointer points to a static memory buffer. The -* contents of this buffer will be over-written on each invocation of -* this function. A copy of the returned string should therefore be -* taken if it will be needed later. -* - 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. -*/ - return "rad"; -} - -static double GetAxisTop( AstAxis *this_axis, int *status ) { -/* -* Name: -* GetAxisTop - -* Purpose: -* Obtain the value of the Top attribute for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* double GetAxisTop( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astGetAxisTop method -* inherited from the Axis class). - -* Description: -* This function returns a value for the Top attribute of a SkyAxis. -* This attribute indicates the highest legal value for the axis. - -* Parameters: -* this -* Pointer to the SkyAxis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The atribute value. A suitable default value is supplied if necessary. - -* Notes: -* - A value of DBL_MAX will be returned if this function is invoked -* with the global error status set, or if it should fail for any reason. -*/ - -/* Local Variables. */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - double result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return DBL_MAX; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Check if a value has been set for the Top attribute. If so, obtain - this value. */ - if ( astTestAxisTop( this ) ) { - result = (*parent_getaxistop)( this_axis, status ); - -/* Otherwise, supply a default of pi/2 for latitude axes, and DBL_MAX - for longitude axes. */ - } else { - result = astGetAxisIsLatitude( this ) ? piby2 : DBL_MAX; - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = DBL_MAX; - -/* Return the result. */ - return result; -} - -static int GetAxisDirection( AstAxis *this_axis, int *status ) { -/* -* Name: -* GetAxisDirection - -* Purpose: -* Obtain the value of the Direction attribute for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* int GetAxisDirection( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astGetAxisDirection method -* inherited from the Axis class). - -* Description: -* This function returns a value for the Direction attribute of a SkyAxis. -* This attribute indicates in which direction the SkyAxis's values should -* increase when represented on a graph (1 for the conventional direction, -* 0 for reverse direction). - -* Parameters: -* this -* Pointer to the SkyAxis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Zero or one, according to the attribute setting. A suitable default -* value is supplied if necessary. - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables. */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - int result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Check if a value has been set for the Direction attribute. If so, obtain - this value. */ - if ( astTestAxisDirection( this ) ) { - result = (*parent_getaxisdirection)( this_axis, status ); - -/* Otherwise, supply a default of 1 unless the SkyAxis values are being - formatted as times (instead of angles) by default. */ - } else { - result = !astGetAxisAsTime( this ); - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = 0; - -/* Return the result. */ - return result; -} - -static const char *GetAxisFormat( AstAxis *this_axis, int *status ) { -/* -* Name: -* GetAxisFormat - -* Purpose: -* Obtain a pointer to the Format attribute for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* const char *GetAxisFormat( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astGetAxisFormat method inherited -* from the Axis class). - -* Description: -* This function returns a pointer to the Format attribute associated with -* a SkyAxis and provides a suitable default if necessary. This string -* attribute contains the format specifier that will be interpreted by the -* astAxisFormat method when formatting a value for the SkyAxis. The default -* Format may depend on other attribute settings, in particular on the -* Digits and AsTime attributes. - -* Parameters: -* this -* Pointer to the SkyAxis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to the Format string (null terminated). - -* Notes: -* - The pointer returned may point at memory allocated within the SkyAxis -* object, 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, deletion of the SkyAxis, or assignment -* of a new Format value. A copy of the string should therefore be made if -* necessary. -* - This function will return a NULL pointer if it is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - const char *result; /* Pointer to result string */ - int as_time; /* Format SkyAxis values as times? */ - int digits; /* Number of digits of precision */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(this_axis); - -/* Initialise. */ - result = NULL; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Obtain a pointer to the Format string stored in the SkyAxis structure. Note - we do not use a method to obtain this, because we want a string with a - syntax appropriate to this class, and derived classes may have extended the - syntax. */ - result = this->skyformat; - -/* If no Format string has been set, we must generate a default one. Determine - how many digits of precision are to be used by default and whether the - SkyAxis values are to be formatted as times (instead of angles). */ - if ( !result ) { - digits = astGetAxisDigits( this ); - as_time = astGetAxisAsTime( this ); - if ( astOK ) { - -/* If formatting values as times, use the number of digits to select an - appropriate Format string and obtain a pointer to it. */ - if ( as_time ) { - if ( digits <= 2 ) { - result = "h"; - } else if ( digits == 3 ) { - result = "hm"; - } else if ( digits == 4 ) { - result = "hm"; - } else if ( digits == 5 ) { - result = "hms"; - } else if ( digits == 6 ) { - result = "hms"; - -/* Construct the Format string in a buffer if necessary. */ - } else { - (void) sprintf( getaxisformat_buff, "hms.%d", digits - 6 ); - result = getaxisformat_buff; - } - -/* Similarly, select a Format for expressing an angle if necessary. */ - } else { - if ( digits <= 3 ) { - result = "d"; - } else if ( digits == 4 ) { - result = "dm"; - } else if ( digits == 5 ) { - result = "dm"; - } else if ( digits == 6 ) { - result = "dms"; - } else if ( digits == 7 ) { - result = "dms"; - } else { - (void) sprintf( getaxisformat_buff, "dms.%d", digits - 7 ); - result = getaxisformat_buff; - } - } - } - } - -/* Return the result. */ - return result; -} - -static const char *GetAxisLabel( AstAxis *this_axis, int *status ) { -/* -* Name: -* GetAxisLabel - -* Purpose: -* Obtain a pointer to the Label attribute for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* const char *GetAxisLabel( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astGetAxisLabel method inherited -* from the Axis class). - -* Description: -* This function returns a pointer to the Label attribute associated with -* a SkyAxis and provides a suitable default if necessary. This string -* attribute specifies the label to be attached to the SkyAxis when it is -* represented in (e.g.) a graph. It is intended purely for interpretation -* by human readers and not by software. - -* Parameters: -* this -* Pointer to the SkyAxis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to the Label string (null terminated). - -* Notes: -* - The pointer returned may point at memory allocated within the SkyAxis -* object, 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, deletion of the SkyAxis, or assignment -* of a new Label value. A copy of the string should therefore be made if -* necessary. -* - This function will return a NULL pointer if it is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - const char *result; /* Pointer value to be returned */ - int as_time; /* SkyAxis values formatted as times? */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Initialise. */ - result = NULL; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Test if the Label attribute is set. If so, use the parent astGetAxisLabel - method to get a pointer to it. */ - if ( astTestAxisLabel( this ) ) { - result = (*parent_getaxislabel)( this_axis, status ); - -/* Otherwise, return a pointer to a suitable default string, using the result - of the astGetAxisAsTime method to determine whether a string describing - time or angle is more appropriate. */ - } else { - as_time = astGetAxisAsTime( this ); - if ( !astTestAxisIsLatitude( this ) ) { - result = as_time ? "Angle on sky expressed as time" : - "Angle on sky"; - } else if ( astGetAxisIsLatitude( this ) ) { - result = as_time ? "Sky latitude expressed as time" : - "Sky latitude"; - } else { - result = as_time ? "Sky longitude expressed as time" : - "Sky longitude"; - } - } - -/* If an error occurred, clear the result pointer. */ - if ( !astOK ) result = NULL; - -/* Return the result. */ - return result; -} - -static const char *GetAxisSymbol( AstAxis *this_axis, int *status ) { -/* -* Name: -* GetAxisSymbol - -* Purpose: -* Obtain a pointer to the Symbol attribute for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* const char *GetAxisSymbol( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astGetAxisSymbol method inherited -* from the Axis class). - -* Description: -* This function returns a pointer to the Symbol attribute associated with -* a SkyAxis and provides a suitable default if necessary. This string -* attribute specifies the symbol to be used to represent coordinate values -* for the SkyAxis in "short form", such as in algebraic expressions where a -* full description would be inappropriate. - -* Parameters: -* this -* Pointer to the SkyAxis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to the Symbol string (null terminated). - -* Notes: -* - The pointer returned may point at memory allocated within the SkyAxis -* object, 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, deletion of the SkyAxis, or assignment -* of a new Symbol value. A copy of the string should therefore be made if -* necessary. -* - This function will return a NULL pointer if it is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - const char *result; /* Pointer value to return */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Initialise. */ - result = NULL; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Test if the Symbol attribute is set. If so, use the parent astGetAxisSymbol - method to get a pointer to it. */ - if ( astTestAxisSymbol( this ) ) { - result = (*parent_getaxissymbol)( this_axis, status ); - -/* If a value has been set for the IsLatitude attribute, use it to decide - whether to use "delta" (for latitude) or "alpha" (for longitude). */ - } else if ( astTestAxisIsLatitude( this ) ) { - result = astGetAxisIsLatitude( this ) ? "delta" : "alpha"; - -/* Otherwise, use the AsTime attribute to decide whether the SkyAxis is - likely to be a longitude or latitude axis (the former usually having values - formatted as times). */ - } else { - result = astGetAxisAsTime( this ) ? "alpha" : "delta"; - } - -/* If an error occurred, clear the result pointer. */ - if ( !astOK ) result = NULL; - -/* Return the result. */ - return result; -} - -static const char *GetAxisUnit( AstAxis *this_axis, int *status ) { -/* -* Name: -* GetAxisUnit - -* Purpose: -* Obtain a pointer to the Unit attribute for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* const char *GetAxisUnit( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astGetAxisUnit method inherited -* from the Axis class). - -* Description: -* This function returns a pointer to the Unit attribute associated with -* a SkyAxis and provides a suitable default if necessary. This string -* attribute describes the unit used to represent formatted coordinate -* values on the SkyAxis. - -* Parameters: -* this -* Pointer to the SkyAxis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to the Unit string (null terminated). - -* Notes: -* - The pointer returned may point at memory allocated within the SkyAxis -* object, 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, deletion of the SkyAxis, or assignment -* of a new Unit value. A copy of the string should therefore be made if -* necessary. -* - This function will return a NULL pointer if it is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - const char *fmt; /* Pointer to format specifier */ - const char *result; /* Pointer to result string */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Initialise */ - result = NULL; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Test if the Unit attribute is set. If so, invoke the parent astGetAxisUnit - method to obtain a pointer to it. */ - if ( astTestAxisUnit( this ) ) { - result = (*parent_getaxisunit)( this_axis, status ); - -/* If we must provide a default, obtain a pointer to the format specifier used - to format SkyAxis values. Use a private member function (not a method) to - access this, in case derived classes have extended the syntax of this - string. */ - } else { - fmt = GetAxisFormat( this_axis, status ); - -/* If the format string starts with a percent, use "rad" as the default units - string. Otherwise, use the format specifier to generate a matching - default Unit string and obtain a pointer to it. */ - if ( astOK ) { - if( fmt[ 0 ] == '%' ) { - result = "rad"; - } else { - result = DHmsUnit( fmt, astGetAxisDigits( this_axis ), 1, status ); - } - } - } - -/* Return the result. */ - return result; -} - -void astInitSkyAxisVtab_( AstSkyAxisVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitSkyAxisVtab - -* Purpose: -* Initialise a virtual function table for a SkyAxis. - -* Type: -* Protected function. - -* Synopsis: -* #include "skyaxis.h" -* void astInitSkyAxisVtab( AstSkyAxisVtab *vtab, const char *name ) - -* Class Membership: -* SkyAxis vtab initialiser. - -* Description: -* This function initialises the component of a virtual function -* table which is used by the SkyAxis 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 */ - AstAxisVtab *axis; /* Pointer to Axis component of Vtab */ - AstObjectVtab *object; /* Pointer to Object component of Vtab */ - int stat; /* SLALIB status */ - -/* 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. */ - astInitAxisVtab( (AstAxisVtab *) vtab, name ); - -/* Store a unique "magic" value in the virtual function table. This - will be used (by astIsASkyAxis) 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 = &(((AstAxisVtab *) vtab)->id); - -/* Initialise member function pointers. */ -/* ------------------------------------ */ -/* Store pointers to the member functions (implemented here) that provide - virtual methods for this class. */ - vtab->ClearAxisAsTime = ClearAxisAsTime; - vtab->ClearAxisIsLatitude = ClearAxisIsLatitude; - vtab->ClearAxisCentreZero = ClearAxisCentreZero; - vtab->GetAxisAsTime = GetAxisAsTime; - vtab->GetAxisIsLatitude = GetAxisIsLatitude; - vtab->GetAxisCentreZero = GetAxisCentreZero; - vtab->SetAxisAsTime = SetAxisAsTime; - vtab->SetAxisIsLatitude = SetAxisIsLatitude; - vtab->SetAxisCentreZero = SetAxisCentreZero; - vtab->TestAxisAsTime = TestAxisAsTime; - vtab->TestAxisIsLatitude = TestAxisIsLatitude; - vtab->TestAxisCentreZero = TestAxisCentreZero; - -/* Save the inherited pointers to methods that will be extended, and - replace them with pointers to the new member functions. */ - object = (AstObjectVtab *) vtab; - axis = (AstAxisVtab *) vtab; - parent_getobjsize = object->GetObjSize; - object->GetObjSize = GetObjSize; - - 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_axisoverlay = axis->AxisOverlay; - axis->AxisOverlay = AxisOverlay; - parent_getaxisdirection = axis->GetAxisDirection; - axis->GetAxisDirection = GetAxisDirection; - parent_getaxislabel = axis->GetAxisLabel; - axis->GetAxisLabel = GetAxisLabel; - parent_getaxissymbol = axis->GetAxisSymbol; - axis->GetAxisSymbol = GetAxisSymbol; - parent_getaxisunit = axis->GetAxisUnit; - axis->GetAxisUnit = GetAxisUnit; - - parent_getaxistop = axis->GetAxisTop; - axis->GetAxisTop = GetAxisTop; - - parent_getaxisbottom = axis->GetAxisBottom; - axis->GetAxisBottom = GetAxisBottom; - - parent_axisformat = axis->AxisFormat; - axis->AxisFormat = AxisFormat; - - parent_axisunformat = axis->AxisUnformat; - axis->AxisUnformat = AxisUnformat; - - parent_axisgap = axis->AxisGap; - axis->AxisGap = AxisGap; - - parent_axisfields = axis->AxisFields; - axis->AxisFields = AxisFields; - -/* Store replacement pointers for methods which will be over-ridden by - new member functions implemented here. */ - axis->AxisAbbrev = AxisAbbrev; - axis->AxisIn = AxisIn; - axis->AxisDistance = AxisDistance; - axis->AxisOffset = AxisOffset; - axis->AxisNorm = AxisNorm; - axis->AxisNormValues = AxisNormValues; - axis->ClearAxisFormat = ClearAxisFormat; - axis->GetAxisFormat = GetAxisFormat; - axis->SetAxisFormat = SetAxisFormat; - axis->TestAxisFormat = TestAxisFormat; - axis->GetAxisInternalUnit = GetAxisInternalUnit; - axis->TestAxisInternalUnit = TestAxisInternalUnit; - -/* Declare the destructor, copy constructor and dump function. */ - astSetDelete( vtab, Delete ); - astSetCopy( vtab, Copy ); - astSetDump( vtab, Dump, "SkyAxis", "Celestial coordinate axis" ); - -/* Initialize constants for converting between hours, degrees and radians. */ - LOCK_MUTEX2 - palDtf2r( 1, 0, 0.0, &hr2rad, &stat ); - palDaf2r( 1, 0, 0.0, °2rad, &stat ); - palDaf2r( 180, 0, 0.0, &pi, &stat ); - piby2 = 0.5*pi; - UNLOCK_MUTEX2 - -/* 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 void ParseDHmsFormat( const char *fmt, int digs, char *sep, int *plus, - int *lead_zero, int *as_time, int *dh, int *min, - int *sec, int *ndp, int *status ) { -/* -* Name: -* ParseDHmsFormat - -* Purpose: -* Parse a format specifier for degrees/hours, minutes and seconds. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* void ParseDHmsFormat( const char *fmt, int digs, char *sep, int *plus, -* int *lead_zero, int *as_time, int *dh, int *min, -* int *sec, int *ndp, int *status ) - -* Class Membership: -* SkyAxis member function. - -* Description: -* This function parses a SkyAxis format specifier which describes -* how to convert an angle in radians into a text string with -* separate fields for degrees/hours, minutes and seconds. - -* Parameters: -* fmt -* Pointer to a null terminated string containing the format -* specifier. For details of the syntax of this string, see the -* DHmsFormat function. -* digs -* The default number of digits of precision to use. This is used -* if the given format specifier indicates the number of decimal -* places to use with the string ".*". In this case, the returned -* value for "ndp" will be set to produce the number of digits of -* precision given by "digs". -* sep -* Pointer to a location in which a single character will be -* returned to indicate which separator should be used to -* separate the fields. The returned value will be one of ' ' -* (use a blank as the separator), ':' (use a colon as the -* separator) or 'l' (use one of the letters "hdms" as -* appropriate) or 'g' (use one of the letters "hdms" but -* include suitable escape sequences to allow the Plot class to draw -* the letter as a small super-script). -* plus -* Pointer to an int in which a boolean value will be returned -* to indicate if a plus sign should be prefixed to positive -* values. -* lead_zero -* Pointer to an int in which a boolean value will be returned -* to indicate if leading zeros should be prefixed to the value -* so that the first field is always of constant (maximum) -* width, as would be required in a fixed-width table. Leading -* zeros are always prefixed to any fields that follow. -* as_time -* Pointer to an int in which a boolean value will be returned -* to indicate whether the value is to be formatted as a time -* (e.g. in hours) rather than as an angle (in degrees). -* dh -* Pointer to an int in which a boolean value will be returned -* to indicate whether a degrees or hours field is required. -* min -* Pointer to an int in which a boolean value will be returned -* to indicate whether a minutes field is required. -* sec -* Pointer to an int in which a boolean value will be returned -* to indicate whether a seconds field is required. -* ndp -* Pointer to an int in which to return the number of digits -* required following the decimal point in the final field. A -* value of zero indicates that the decimal point should be -* omitted. See parameter "digs". -* status -* Pointer to the inherited status variable. - -* Returned Value: -* void - -* Acknowledgements: -* - This function is a close approximation to a Fortran 77 routine -* written by Clive Davenhall which implements the system of format -* specifiers for angles described in his document on the CAT -* catalogue access library (Starlink User Note 181). It supports -* the same format specifiers. -*/ - -/* Local Variables: */ - int decpos; /* Offset of decimal point */ - int i; /* Loop counter for format characters */ - int ndpval; /* Number of decimal places required */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Initialise. */ - *as_time = -1; - *lead_zero = 0; - *dh = 0; - *min = 0; - *ndp = 0; - *plus = 0; - *sec = 0; - *sep = ':'; - decpos = -1; - -/* Loop to inspect and classify each character. */ - for ( i = 0; fmt[ i ]; i++ ) { - switch ( fmt[ i ] ) { - -/* Note if a '+' sign is needed. */ - case '+': - *plus = 1; - break; - -/* Note if leading zeros are needed. */ - case 'Z': case 'z': - *lead_zero = 1; - break; - -/* Set the required separator. Note we only use graphical separators if - astEscapes indicates that escape sequences are currently being used. */ - case 'I': case 'i': - *sep = ':'; - break; - case 'B': case 'b': - *sep = ' '; - break; - case 'L': case 'l': - *sep = 'l'; - break; - case 'G': case 'g': - *sep = astEscapes( -1 ) ? 'g' : 'l'; - break; - -/* Note if the value is to be formatted as a time (but not if a - degrees or hours field has already been specified). */ - case 'T': case 't': - if ( *as_time == -1 ) *as_time = 1; - break; - -/* Note if a degrees or hours field is required (and hence whether the - value is to be formatted as a time or an angle). */ - case 'H': case 'h': - *dh = 1; - *as_time = 1; - break; - case 'D': case 'd': - *dh = 1; - *as_time = 0; - break; - -/* Note if a minutes field is required. */ - case 'M': case 'm': - *min = 1; - break; - -/* Note if a seconds field is required. */ - case 'S': case 's': - *sec = 1; - break; - -/* Note if decimal places are required. */ - case '.': - decpos = i; - } - } - -/* Format the value as an angle by default. */ - if ( *as_time == -1 ) *as_time = 0; - -/* Use degrees (or hours) as the default field. */ - if ( !*min && !*sec ) *dh = 1; - -/* Omit the seconds field if the degrees/hours field is present but - the minutes field is not. */ - if ( *dh && !*min ) *sec = 0; - -/* Determine the default number of decimal places following the final field. - This is the number which will be used if the format specifier does not - indicate how many decimal places should be produced. It is shosen to - produce the requested total number of digits of precision. */ - -/* If decimal places are required, attempt to read the integer value - following the decimal point which specifies how many. If successful, - and a valid (positive or zero) result was obtained, note its value. If - an asterisk follows the decimal point, use a value determined by the - supplied "digs" value. */ - if ( ( decpos >= 0 ) && ( decpos < ( i - 1 ) ) ) { - - if ( astSscanf( fmt + decpos + 1, "%d", &ndpval ) == 1 ) { - if ( ndpval >= 0 ) *ndp = ndpval; - - } else if ( fmt[ decpos + 1 ] == '*' ) { - *ndp = digs; - if( *as_time ) { - *ndp = ( digs > 2 ) ? digs : 2; - if( *dh ) *ndp -= 2; - } else { - *ndp = ( digs > 3 ) ? digs : 3; - if( *dh ) *ndp -= 3; - } - if( *min ) *ndp -= 2; - if( *sec ) *ndp -= 2; - if( *ndp < 0 ) *ndp = 0; - } - } -} - -static void SetAttrib( AstObject *this_object, const char *setting, int *status ) { -/* -* Name: -* SetAttrib - -* Purpose: -* Set an attribute value for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* void SetAttrib( AstObject *this, const char *setting, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astSetAttrib method -* inherited from the Axis class). - -* Description: -* This function assigns an attribute value for a SkyAxis, 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 SkyAxis. -* setting -* Pointer to a null terminated string specifying the new -* attribute value. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - int as_time; /* Format values as times? */ - int centrezero; /* SkyAxis range centred on zero? */ - int is_latitude; /* SkyAxis is a latitude axis? */ - 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 SkyAxis structure. */ - this = (AstSkyAxis *) this_object; - -/* Obtain the length of the setting string. */ - len = (int) 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. */ - -/* AsTime. */ -/* ------- */ - if ( nc = 0, - ( 1 == astSscanf( setting, "astime= %d %n", &as_time, &nc ) ) - && ( nc >= len ) ) { - astSetAxisAsTime( this, as_time ); - -/* IsLatitude. */ -/* ----------- */ - } else if ( nc = 0, - ( 1 == astSscanf( setting, "islatitude= %d %n", &is_latitude, &nc ) ) - && ( nc >= len ) ) { - astSetAxisIsLatitude( this, is_latitude ); - -/* CentreZero. */ -/* ----------- */ - } else if ( nc = 0, - ( 1 == astSscanf( setting, "centrezero= %d %n", ¢rezero, &nc ) ) - && ( nc >= len ) ) { - astSetAxisCentreZero( this, centrezero ); - -/* Pass any unrecognised attribute setting to the parent method for further - interpretation. */ - } else { - (*parent_setattrib)( this_object, setting, status ); - } -} - -static void SetAxisFormat( AstAxis *this_axis, const char *format, int *status ) { -/* -* Name: -* SetAxisFormat - -* Purpose: -* Set a value for the Format attribute of a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* void SetAxisFormat( AstAxis *this, const char *format ) - -* Class Membership: -* SkyAxis member function (over-rides the astSetAxisFormat method inherited -* from the Axis class). - -* Description: -* This function sets a new value for the Format attribute of a SkyAxis. - -* Parameters: -* this -* Pointer to the SkyAxis. -* format -* Pointer to a null terminated string containing the new Format value. - -* Returned Value: -* void - -* Notes: -* - For details of the syntax of the Format string, see the DHmsFormat -* function. -*/ - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* Store a pointer to a copy of the Format string in the SkyAxis structure. */ - this->skyformat = astStore( this->skyformat, format, - strlen( format ) + (size_t) 1 ); -} - -static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* TestAttrib - -* Purpose: -* Test if a specified attribute value is set for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* int TestAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astTestAttrib protected -* method inherited from the Axis class). - -* Description: -* This function returns a boolean result (0 or 1) to indicate -* whether a value has been set for one of a SkyAxis' attributes. - -* Parameters: -* this -* Pointer to the SkyAxis. -* 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: -* - 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: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_object; - -/* Check the attribute name and test the appropriate attribute. */ - -/* AsTime. */ -/* ------- */ - if ( !strcmp( attrib, "astime" ) ) { - result = astTestAxisAsTime( this ); - -/* IsLatitude. */ -/* ----------- */ - } else if ( !strcmp( attrib, "islatitude" ) ) { - result = astTestAxisIsLatitude( this ); - -/* CentreZero. */ -/* ----------- */ - } else if ( !strcmp( attrib, "centrezero" ) ) { - result = astTestAxisCentreZero( this ); - -/* 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 int TestAxisFormat( AstAxis *this_axis, int *status ) { -/* -* Name: -* TestAxisFormat - -* Purpose: -* Test if a value has been set for the Format attribute of a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* int TestAxisFormat( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astTestAxisFormat method -* inherited from the Axis class). - -* Description: -* This function returns 0 or 1 to indicate whether a value has been set -* for the Format attribute of a SkyAxis. - -* Parameters: -* this -* Pointer to the SkyAxis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Zero if no Format value has been set, otherwise one. - -* Notes: -* - This function will return a value of zero if it is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - int result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_axis; - -/* The Format string has been set if the pointer to it is not NULL. */ - result = ( this->skyformat != NULL ); - -/* Return the result. */ - return result; -} - -static int TestAxisInternalUnit( AstAxis *this, int *status ){ -/* -* Name: -* TestAxisInternalUnit - -* Purpose: -* Test if a InternalUnit attribute value is set for an Axis. - -* Type: -* Private function. - -* Synopsis: -* #include "axis.h" -* int TestAxisInternalUnit( AstAxis *this, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astTestAxisInternalUnit -* protected method inherited from the Axis class). - -* Description: -* This function returns a boolean result (0 or 1) to indicate -* whether a value has been set for the InternalUnit string. - -* Parameters: -* this -* Pointer to the Axis. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if a value has been set, otherwise zero. - -* 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. -*/ - -/* Tell the world that we know what value to use for InternalUnit (i.e. - "rad"). */ - return 1; -} - -static int AxisUnformat( AstAxis *this_axis, const char *string, - double *value, int *status ) { -/* -* Name: -* AxisUnformat - -* Purpose: -* Read a formatted coordinate value for a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* int AxisUnformat( AstAxis *axis, const char *string, double *value, int *status ) - -* Class Membership: -* SkyAxis member function (over-rides the astAxisUnformat method -* inherited from the Axis class). - -* Description: -* This function reads a formatted coordinate value for a SkyAxis -* (supplied as a string) and returns the equivalent numerical -* value as a double. It also returns the number of characters read -* from the string. - -* Parameters: -* this -* Pointer to the SkyAxis. -* string -* Pointer to a constant null-terminated string containing the -* formatted coordinate value. -* value -* Pointer to a double in which the coordinate value read will be -* returned (in radians). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The number of characters read from the string to obtain the -* coordinate value. - -* Notes: -* - Any white space at the beginning of the string will be -* skipped, as also will any trailing white space following the -* coordinate value read. The function's return value will reflect -* this. -* - A function value of zero (and no coordinate value) will be -* returned, without error, if the string supplied does not contain -* a suitably formatted value. -* - The string "<bad>" is recognised as a special case and will -* generate the value AST__BAD, without error. The test for this -* string is case-insensitive and permits embedded white space. -* - A function result of zero will be returned and no coordinate -* value will be returned via the "value" pointer if this function -* is invoked with the global error status set, or if it should -* fail for any reason. -*- -*/ - -/* Local Constants: */ -#define FMT_LEN 50 /* Length of format buffer */ - -/* Local Variables: */ - char fmtbuf[ FMT_LEN + 1 ]; /* Buffer for C format specification */ - char fmtsep; /* Format field separator character */ - char last_sep; /* Previous separator character */ - char sep; /* Separator character */ - char sep_used; /* Separator character being used */ - char sign[ 2 ]; /* Sign character as string */ - const char *field_start[ 3 ]; /* Pointer to start of each field */ - const char *fmt; /* Pointer to SkyAxis Format string */ - const char *s; /* Pointer to current reading position */ - const char *string_start; /* Pointer to first significant character */ - double field[ 3 ]; /* Field values */ - double testval; /* Value to test for invalid fields */ - int angle_or_time; /* Value known to be angle or time? */ - int as_time; /* Value is a time (else an angle)? */ - int decimal; /* Decimal point in field? */ - int dh; /* Hours field required? */ - int digs; /* Default no. of digits of precision */ - int exponent; /* Exponent at end of field? */ - int field_id[ 3 ]; /* Field identification (0 = don't know) */ - int final; /* Final field read? */ - int good_sep; /* Separator character valid? */ - int i; /* Loop counter for characters */ - int ifield; /* Loop counter for fields */ - int lead_zero; /* Add leading zeros? */ - int len; /* Significant length of string */ - int m; /* Number of characters read by astSscanf */ - int match; /* Character pattern matches? */ - int min; /* Minutes field required? */ - int n; /* Number of characters read by astSscanf */ - int nc; /* Total no. characters read */ - int nchar; /* Number of characters in erroneous value */ - int ndp; /* Number of decimal places */ - int next_id; /* Next field ID to use (0 = don't know) */ - int nfield; /* Number of fields read */ - int nread; /* No. characters read for current field */ - int plus; /* Add leading plus sign? */ - int positive; /* Value is positive? */ - int sec; /* Seconds field required? */ - int sep_angle_or_time; /* Separator indicates angle or time? */ - int sep_field_id; /* Field ID from separator (0 = don't know) */ - int sep_index; /* Index of separator character in table */ - int sep_len; /* Length of separator plus trailing space */ - int suffix_sep; /* Field has a suffix separator? */ - -/* Local Data: */ - const char *sep_list = /* List of separator characters recognised */ - " :hHdDmM'sS\""; - - const int angle_or_time_list[] = /* Whether separator indicates angle or - time (1 or 2). Zero => don't know. */ - { 0, 0, 2, 2, 1, 1, 0, 0, 1, 0, 0, 1 }; - - const int field_id_list[] = /* Whether separator identifies previous field - (1, 2, or 3). Zero => doesn't identify. */ - { 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3 }; - - const double fieldvalue[ 3 ] = /* Nominal field values (degrees/hours) */ - { 1.0, 1.0 / 60.0, 1.0 / 3600.0 }; - -/* Initialise. */ - nc = 0; - -/* Check the global error status. */ - if ( !astOK ) return nc; - -/* Obtain the SkyAxis Format string. If its starts with a "%" sign, use - the parent AxisUnformat method inherited from the Axis class. Use - a private method to obtain the Format string, in case the syntax has been - over-ridden by a derived class. */ - fmt = GetAxisFormat( this_axis, status ); - if( fmt && fmt[0] == '%' ) { - nc = (*parent_axisunformat)( this_axis, string, value, status ); - -/* Otherwise, parse it to determine the default choice of input format. */ - } else if( astOK ){ - digs = astGetAxisDigits( this_axis ); - ParseDHmsFormat( fmt, digs, &fmtsep, &plus, &lead_zero, &as_time, &dh, - &min, &sec, &ndp, status ); - -/* Initialise a pointer into the string and advance it to the first - non-white space character. Save a copy of this pointer. */ - s = string; - while ( isspace( (int) *s ) ) s++; - string_start = s; - -/* Read sign information. */ -/* ---------------------- */ -/* Attempt to read an optional sign character ("+" or "-"), possibly - surrounded by white space. Set a flag to indicate if the returned - value should be positive or not. Increment the string pointer to - the next significant character. */ - positive = 1; - n = 0; - if ( 1 == astSscanf( s, " %1[+-] %n", sign, &n ) ) { - positive = ( *sign == '+' ); - s += n; - } - -/* Loop to read field information. */ -/* ------------------------------- */ -/* Initialise, then loop to read the values of up to three fields and - to identify the separators that accompany them. */ - angle_or_time = 0; - last_sep = '\0'; - next_id = 0; - nfield = 0; - sep_used = '\0'; - suffix_sep = 0; - sep_len = 0; - for ( ifield = 0; ifield < 3; ifield++ ) { - -/* Set the default field value. */ - field[ ifield ] = 0.0; - -/* If a prefix separator was identified for the second and subsequent - fields (when the previous field was being read), then step over the - prefix, including any following white space. */ - if ( ifield && !suffix_sep ) s += sep_len; - -/* Note where in the input string the field's numerical value - starts. */ - field_start[ ifield ] = s; - -/* Each field must consist of a string of digits, possibly surrounded - by white space, except that an optional decimal point may also be - present (in which case it indicates the final field). Since we want - to exclude signs, etc. from these fields, we must first identify a - valid sequence of digits, before attempting to read them as a number. - Start by assuming that we will find a decimal point but not an - exponent. */ - decimal = 1; - exponent = 0; - -/* Match a field and obtain its value. */ -/* ----------------------------------- */ -/* Look for a character sequence like "12.345", or similar, setting a - flag to identify a match. */ - n = 0; - match = ( 0 == astSscanf( s, "%*[0123456789].%*[0123456789]%n", &n ) ) - && n; - -/* If that failed, then look for a sequence like "12.", or similar. */ - if ( !match ) { - n = 0; - match = ( 0 == astSscanf( s, "%*[0123456789].%n", &n ) ) && n; - } - -/* If that also failed, then look for a sequence like ".12", or similar. */ - if ( !match ) { - n = 0; - match = ( 0 == astSscanf( s, ".%*[0123456789]%n", &n ) ) && n; - } - -/* If that also failed, then look for a sequence containing digits only. */ - if ( !match ) { - n = 0; - match = ( 0 == astSscanf( s, "%*[0123456789]%n", &n ) ) && n; - -/* Note we have not found a decimal point. */ - decimal = 0; - } - -/* Now look for numbers that end with an exponent. First check that the - string starts with a sequence of digits with or without a decimal point. */ - if( match ) { - -/* See if the numbers are followed by an exponent with an explicit sign - character. If so, increment the number of characters in the numerical - string prefix. */ - m = 0; - if( ( 0 == astSscanf( s + n, "%*1[Ee]%*1[+-]%*[0123456789]%n", &m ) ) - && m ) { - n += m; - exponent = 1; - -/* If the above check failed, see if the numbers are followed by an exponent - without an explicit sign character. If so, increment the number of - characters in the numerical string prefix. */ - } else { - m = 0; - if( ( 0 == astSscanf( s + n, "%*1[Ee]%*[0123456789]%n", &m ) ) - && m ) { - n += m; - exponent = 1; - } - } - } - -/* If we identified a suitable sequence of characters above, we will - now read them as a number. To prevent any subsequent characters - being included as part of this number, the field width must be - restricted to the length of the sequence we found. Write a format - specification to read a double with this field width, followed by - optional white space, and to return the total number of characters - read. */ - nread = 0; - if ( match ) { - (void) sprintf( fmtbuf, "%%%dlf %%n", n ); - -/* Use this format specification to read the field value. If - successful, increment the string pointer to the next significant - character. */ - if ( 1 == astSscanf( s, fmtbuf, field + ifield, &nread ) ) s += nread; - } - -/* Note the total number of characters read up to the end of the - numerical value in this field (including any following white - space). */ - nc = s - string; - -/* Identify the following separator. */ -/* --------------------------------- */ -/* We will now attempt to identify the field separator (if any) which - follows the field we have just read. By default, we behave as if - the separator is a space. Note we have actually found a space (at - least) if extra white space characters were read as part of the - field value above. */ - sep = ' '; - good_sep = ( nread > n ); - -/* Look for one of the recognised separator characters. If one is - found, save a copy of it and note we appear (so far) to have a - valid separator. */ - sep_len = 0; - if ( *s && strchr( sep_list, *s ) ) { - sep = *s; - good_sep = 1; - -/* Set "sep_len" to the number of characters associated with the - separator. This includes any following white space. */ - while ( isspace( (int) s[ ++sep_len ] ) ); - } - -/* Identify the separator character by looking it up in the separator - list (this just uses a space if no valid separator has been - found). */ - sep_index = strchr( sep_list, sep ) - sep_list; - -/* Determine if the separator can be used to identify the field which - preceded it and if it allows us to determine whether an angle or a - time is being read. Both of these properties are specified in data - tables (with zero indicating that the separator didn't supply any - information). */ - sep_field_id = field_id_list[ sep_index ]; - sep_angle_or_time = angle_or_time_list[ sep_index ]; - -/* Validate the separator. */ -/* ----------------------- */ -/* Now perform further checks that the separator is valid - (i.e. conforms to the required syntax). If it appears to identify - the previous field (i.e. is a "suffix" separator like "m" or "s"), - then it is valid only if its field ID is no less than the ID value - that would be used next, based on previous fields (if any), and no - less than the current field number. This ensures that fields occur - in the correct order without duplication. */ - if ( good_sep ) { - if ( sep_field_id ) { - good_sep = ( sep_field_id >= next_id ) && - ( sep_field_id > ifield ); - -/* Otherwise (i.e. we appear to have a "prefix" separator like ":" or - " "), it is valid if it is the first one used, or if it matches the - previous one used. Keep a note of the first such separator used for - checking subsequent ones. */ - } else { - good_sep = !sep_used || ( sep == sep_used ); - if ( !sep_used ) sep_used = sep; - } - } - -/* If the separator seems OK and we don't yet know whether we are reading - an angle or a time, then use whatever information the separator - provides about this. */ - if ( good_sep ) { - if ( !angle_or_time ) { - angle_or_time = sep_angle_or_time; - -/* If we already know whether we are reading an angle or a time and - the current separator also contains information about this, then - check that these sources of information are compatible. This - prevents inconsistent use of angle/time field separators. */ - } else { - good_sep = !sep_angle_or_time || - ( sep_angle_or_time == angle_or_time ); - } - } - -/* Update the count of characters read for this field and note if we - have identified a valid suffix separator. */ - if ( good_sep ) nread += sep_len; - suffix_sep = good_sep && sep_field_id; - -/* Identify which field was read. */ -/* ------------------------------ */ -/* If we have a valid suffix separator, store the field ID. Also make - a note of the ID to use for the next field. */ - if ( suffix_sep ) { - field_id[ ifield ] = sep_field_id; - next_id = sep_field_id + 1; - -/* Step over the separator (plus any following white space) and update - the total number of characters read (prefix separators are not - accounted for until we start to read the next field). */ - s += sep_len; - nc = s - string;; - -/* If the separator does not identify the current field, then assign a - field ID based on the previous field (if any). Update the ID to use - for the next field, if known. */ - } else { - field_id[ ifield ] = next_id; - if ( next_id ) next_id++; - } - -/* Count fields and exit when done. */ -/* -------------------------------- */ -/* If no characters have been read for the current field, then - disregard the field if: (a) it is the first one (i.e. there is - nothing to read), or (b) it follows a white space separator - (because trailing space does not delimit an extra field). In either - case, we have now read all the fields. Otherwise, increment the - count of fields read. */ - final = 0; - if ( !nread && ( !ifield || isspace( (int) last_sep ) ) ) { - final = 1; - } else { - nfield++; - } - -/* We have also read all the fields if: (a) the last one contained a - decimal point, or (b) the last one ended with an exponent, or (c) - the next character is not a valid field separator, or (d) we have - read the seconds field so the next field ID would exceed 3. */ - final = final || decimal || exponent || !good_sep || ( next_id > 3 ); - -/* Quit reading if we have read the final field. Otherwise, save the - separator character and attempt to read the next field. */ - if ( final ) break; - last_sep = sep; - } - -/* Complete the identification of fields. */ -/* -------------------------------------- */ -/* Although we have propagated field IDs from earlier ones to later - ones in the loop above, we have still not done the reverse. This - means there there may still be some leading fields which have not - been positively identified (i.e. still have a field ID of zero). In - fact, all the fields we have read might still be unidentified at - this point. */ - -/* Calculate the field ID that would apply to the final field we have - read in the absence of any other information. This depends on the - number of leading fields that are expected to be missing. */ - next_id = nfield + ( dh ? 0 : ( min ? 1 : 2 ) ); - if ( next_id > 3 ) next_id = 3; - -/* Loop through the fields in reverse order, propagating any positive - identifications backwards towards the first field. If no fields - have been positively identified, then they are simply numbered - consecutively based on the value calculated above. */ - for ( ifield = nfield - 1; ifield >= 0; ifield-- ) { - if ( field_id[ ifield ] ) { - next_id = field_id[ ifield ] - 1; - } else { - field_id[ ifield ] = next_id--; - } - } - -/* Handle inability to read any value. */ -/* ----------------------------------- */ -/* If no fields were read, then check to see if we are trying to read - the string "<bad>" (or similar) possibly surrounded by, or - containing, white space. If so, return the coordinate value - AST__BAD. */ - if ( !nfield ) { - if ( n = 0, - ( 0 == astSscanf( string, " < %*1[Bb] %*1[Aa] %*1[Dd] > %n", &n ) - && n ) ) { - *value = AST__BAD; - nc = n; - -/* If the string still cannot be read, then return a function value of - zero. */ - } else { - nc = 0; - } - -/* Finally determine angle or time. */ -/* -------------------------------- */ -/* If one or more fields have been read, check if we know whether to - interpret the value as an angle or a time (if not, we continue to - use the default choice obtained from the SkyAxis Format string). */ - } else { - if ( angle_or_time ) as_time = ( angle_or_time == 2 ); - -/* Validate field values. */ -/* ---------------------- */ -/* If OK, check all fields except the first one for a valid value (we - allow the first field to be unconstrained, so that angles and times - outside the conventional ranges can be represented). We only need - to test for values over 60.0, since negative values can't be - read. */ - if ( astOK ) { - for ( ifield = 1; ifield < nfield; ifield++ ) { - if ( field[ ifield ] >= 60.0 ) { - -/* If a suspect field is found, we must now re-read it. This is - because values like "59.9999..." are valid, even if they round up - to 60, whereas "60" isn't. To distinguish these cases, we read the - digits that occur before the decimal point (if any). Determine how - many such digits there are. */ - n = 0; - if ( ( 0 == astSscanf( field_start[ ifield ], - "%*[0123456789]%n", &n ) ) && n ) { - -/* If there are none (this shouldn't happen), the field is - valid. Otherwise, construct a format specification to read these - digits as a floating point number. */ - (void) sprintf( fmtbuf, "%%%dlf", n ); - -/* Read the digits and compare the result with 60.0. Report an error - and quit if necessary, limiting the string length in the error - message to include just the significant characters in the value - read. */ - if ( ( 1 == astSscanf( field_start[ ifield ], fmtbuf, - &testval ) ) - && ( testval >= 60.0 ) ) { - nchar = nc - ( string_start - string ); - for ( i = len = 0; i < nchar; i++ ) { - if ( !isspace( (int) string_start[ i ] ) ) { - len = i + 1; - } - } - astError( AST__UNFER, "Invalid %s%s value in sky " - "coordinate \"%.*s\".", status, as_time ? "" : "arc", - ( field_id[ ifield ] == 2 ) ? "minutes" : - "seconds", - len, string_start ); - break; - } - } - } - } - } - -/* Calculate final result. */ -/* ----------------------- */ -/* If OK, calculate the result by summing the field values and converting - to radians. */ - if ( astOK ) { - *value = 0.0; - for ( ifield = 0; ifield < nfield; ifield++ ) { - *value += field[ ifield ] * - fieldvalue[ field_id[ ifield ] - 1 ] * - ( as_time ? hr2rad : deg2rad ); - } - -/* Change sign if necessary. */ - if ( !positive ) *value = - *value; - } - } - } - -/* If an error occurred, set the number of characters read to zero. */ - if ( !astOK ) nc = 0; - -/* Return the number of characters read. */ - return nc; - -/* Undefine macros local to this function. */ -#undef FMT_LEN -} - -/* Functions which access class attributes. */ -/* ---------------------------------------- */ -/* Implement member functions to access the attributes associated with the - SkyAxis class using the macros defined for this purpose in the "object.h" - file. For a description of each attribute, see the class interface (in the - associated .h file). */ - -/* AsTime. */ -/* ------- */ -/* The value is constrained to be -INT_MAX, 0 or 1, with -INT_MAX for - "undefined". The default value is 0 unless the "IsLatitude" - attribute has been explicitly set to 0, in which case "AsTime" - defaults to 1. */ -astMAKE_CLEAR(SkyAxis,AxisAsTime,as_time,-INT_MAX) -astMAKE_GET(SkyAxis,AxisAsTime,int,0,( ( this->as_time != -INT_MAX ) ? - this->as_time : - ( astTestAxisIsLatitude( this ) && - !astGetAxisIsLatitude( this ) ) )) -astMAKE_SET(SkyAxis,AxisAsTime,int,as_time,( value != 0 )) -astMAKE_TEST(SkyAxis,AxisAsTime,( this->as_time != -INT_MAX )) - -/* IsLatitude. */ -/* ----------- */ -/* The value is constrained to be -INT_MAX, 0 or 1, with -INT_MAX for - "undefined". The default value is 0. */ -astMAKE_CLEAR(SkyAxis,AxisIsLatitude,is_latitude,-INT_MAX) -astMAKE_GET(SkyAxis,AxisIsLatitude,int,0,( this->is_latitude != -INT_MAX ? - this->is_latitude : 0 )) -astMAKE_SET(SkyAxis,AxisIsLatitude,int,is_latitude,( value != 0 )) -astMAKE_TEST(SkyAxis,AxisIsLatitude,( this->is_latitude != -INT_MAX )) - -/* CentreZero. */ -/* ----------- */ -/* The value is constrained to be -INT_MAX, 0 or 1, with -INT_MAX for - "undefined". The default value is equal to the value of IsLatitude. */ -astMAKE_CLEAR(SkyAxis,AxisCentreZero,centrezero,-INT_MAX) -astMAKE_GET(SkyAxis,AxisCentreZero,int,0,( this->centrezero != -INT_MAX ? - this->centrezero : astGetAxisIsLatitude( this ) )) -astMAKE_SET(SkyAxis,AxisCentreZero,int,centrezero,( value != 0 )) -astMAKE_TEST(SkyAxis,AxisCentreZero,( this->centrezero != -INT_MAX )) - -/* Copy constructor. */ -/* ----------------- */ -static void Copy( const AstObject *objin, AstObject *objout, int *status ) { -/* -* Name: -* Copy - -* Purpose: -* Copy constructor for SkyAxis objects. - -* Type: -* Private function. - -* Synopsis: -* void Copy( const AstObject *objin, AstObject *objout, int *status ) - -* Description: -* This function implements the copy constructor for SkyAxis 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. -*/ - -/* Local Variables: */ - AstSkyAxis *in; /* Pointer to input SkyAxis */ - AstSkyAxis *out; /* Pointer to output SkyAxis */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain pointers to the input and output SkyAxis structures. */ - in = (AstSkyAxis *) objin; - out = (AstSkyAxis *) objout; - -/* For safety, first clear any references to the input memory from - the output SkyAxis. */ - out->skyformat = NULL; - -/* Make copies of the allocated strings. */ - if ( in->skyformat ) out->skyformat = astStore( NULL, in->skyformat, - strlen( in->skyformat ) + (size_t) 1 ); - -/* If an error occurred, clean up by freeing all memory allocated above. */ - if ( !astOK ) { - out->skyformat = astFree( out->skyformat ); - } -} - -/* Destructor. */ -/* ----------- */ -static void Delete( AstObject *obj, int *status ) { -/* -* Name: -* Delete - -* Purpose: -* Destructor for SkyAxis objects. - -* Type: -* Private function. - -* Synopsis: -* void Delete( AstObject *obj, int *status ) - -* Description: -* This function implements the destructor for SkyAxis 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: */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) obj; - -/* Free all allocated memory. */ - this->skyformat = astFree( this->skyformat ); -} - -/* Dump function. */ -/* -------------- */ -static void Dump( AstObject *this_object, AstChannel *channel, int *status ) { -/* -* Name: -* Dump - -* Purpose: -* Dump function for SkyAxis 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 SkyAxis class to an output Channel. - -* Parameters: -* this -* Pointer to the SkyAxis 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 Variables: */ - AstAxis *this_axis; /* Pointer to Axis structure */ - AstSkyAxis *this; /* Pointer to the SkyAxis structure */ - const char *sval; /* Pointer to string value */ - int ival; /* Integer value */ - int set; /* Attribute value set? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyAxis structure. */ - this = (AstSkyAxis *) this_object; - -/* Write out values representing the instance variables for the - SkyAxis 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. */ - -/* Format. */ -/* ------- */ -/* We must write out the Format value stored locally as it over-rides - that provided by the Axis class. */ - this_axis = (AstAxis *) this; - set = TestAxisFormat( this_axis, status ); - sval = set ? GetAxisFormat( this_axis, status ) : astGetAxisFormat( this ); - astWriteString( channel, "Format", set, 0, sval, "Format specifier" ); - -/* IsLatitude. */ -/* ----------- */ - set = TestAxisIsLatitude( this, status ); - ival = set ? GetAxisIsLatitude( this, status ) : astGetAxisIsLatitude( this ); - astWriteInt( channel, "IsLat", set, 0, ival, - ival ? "Latitude axis (not longitude)" : - "Longitude axis (not latitude)" ); - -/* CentreZero. */ -/* ----------- */ - set = TestAxisCentreZero( this, status ); - ival = set ? GetAxisCentreZero( this, status ) : astGetAxisCentreZero( this ); - astWriteInt( channel, "CnZer", set, 0, ival, - ival ? "Display axis values in range -PI -> +PI" : - "Display axis values in range 0 -> 2.PI" ); - -/* AsTime. */ -/* ------- */ - set = TestAxisAsTime( this, status ); - ival = set ? GetAxisAsTime( this, status ) : astGetAxisAsTime( this ); - astWriteInt( channel, "AsTime", set, 0, ival, - ival ? "Display values as times (not angles)" : - "Display values as angles (not times)" ); -} - -/* Standard class functions. */ -/* ========================= */ -/* Implement the astIsASkyAxis and astCheckSkyAxis functions using the macros - defined for this purpose in the "object.h" header file. */ -astMAKE_ISA(SkyAxis,Axis) -astMAKE_CHECK(SkyAxis) - -AstSkyAxis *astSkyAxis_( const char *options, int *status, ...) { -/* -*+ -* Name: -* astSkyAxis - -* Purpose: -* Create a SkyAxis. - -* Type: -* Public function. - -* Synopsis: -* #include "skyaxis.h" -* AstSkyAxis *astSkyAxis( const char *options, int *status, ... ) - -* Class Membership: -* SkyAxis constructor. - -* Description: -* This function creates a new SkyAxis and optionally initialises its -* attributes. - -* Parameters: -* options -* Pointer to a null terminated string containing an optional -* comma-separated list of attribute assignments to be used for -* initialising the new SkyAxis. The syntax used is the same as for the -* astSet method and may include "printf" format specifiers identified -* by "%" symbols in the normal way. -* status -* Pointer to the inherited status variable. -* ... -* If the "options" string contains "%" format specifiers, then an -* optional list of arguments may follow it in order to supply values to -* be substituted for these specifiers. The rules for supplying these -* are identical to those for the astSet method (and for the C "printf" -* function). - -* Returned Value: -* A pointer to the new SkyAxis. - -* 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: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstSkyAxis *new; /* Pointer to new SkyAxis */ - va_list args; /* Variable argument list */ - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Initialise the SkyAxis, allocating memory and initialising the - virtual function table as well if necessary. */ - new = astInitSkyAxis( NULL, sizeof( AstSkyAxis ), !class_init, &class_vtab, - "SkyAxis" ); - -/* If successful, note that the virtual function table has been - initialised. */ - if ( astOK ) { - class_init = 1; - -/* Obtain the variable argument list and pass it along with the - options string to the astVSet method to initialise the new SkyAxis' - attributes. */ - va_start( args, status ); - astVSet( new, options, NULL, args ); - va_end( args ); - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return a pointer to the new SkyAxis. */ - return new; -} - -AstSkyAxis *astSkyAxisId_( const char *options, ... ) { -/* -* Name: -* astSkyAxisId_ - -* Purpose: -* Create a SkyAxis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyaxis.h" -* AstSkyAxis *astSkyAxisId_( const char *options, ... ) - -* Class Membership: -* SkyAxis constructor. - -* Description: -* This function implements the external (public) interface to the -* astSkyAxis constructor function. It returns an ID value (instead -* of a true C pointer) to external users, and must be provided -* because astSkyAxis_ has a variable argument list which cannot be -* encapsulated in a macro (where this conversion would otherwise -* occur). -* -* The variable argument list also prevents this function from -* invoking astSkyAxis_ directly, so it must be a re-implementation -* of it in all respects, except for the final conversion of the -* result to an ID value. - -* Parameters: -* As for astSkyAxis_. - -* Returned Value: -* The ID value associated with the new SkyAxis. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstSkyAxis *new; /* Pointer to new SkyAxis */ - va_list args; /* Variable argument list */ - - int *status; /* Pointer to inherited status value */ - -/* Get a pointer to the inherited status value. */ - status = astGetStatusPtr; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Initialise the SkyAxis, allocating memory and initialising the - virtual function table as well if necessary. */ - new = astInitSkyAxis( NULL, sizeof( AstSkyAxis ), !class_init, &class_vtab, - "SkyAxis" ); - -/* If successful, note that the virtual function table has been - initialised. */ - if ( astOK ) { - class_init = 1; - -/* Obtain the variable argument list and pass it along with the - options string to the astVSet method to initialise the new SkyAxis' - attributes. */ - va_start( args, options ); - astVSet( new, options, NULL, args ); - va_end( args ); - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return an ID value for the new SkyAxis. */ - return astMakeId( new ); -} - -AstSkyAxis *astInitSkyAxis_( void *mem, size_t size, int init, - AstSkyAxisVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitSkyAxis - -* Purpose: -* Initialise a SkyAxis. - -* Type: -* Protected function. - -* Synopsis: -* #include "skyaxis.h" -* AstSkyAxis *astInitSkyAxis( void *mem, size_t size, int init, -* AstSkyAxisVtab *vtab, const char *name ) - -* Class Membership: -* SkyAxis initialiser. - -* Description: -* This function is provided for use by class implementations to initialise -* a new SkyAxis object. It allocates memory (if necessary) to accommodate -* the SkyAxis plus any additional data associated with the derived class. -* It then initialises a SkyAxis 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 SkyAxis at the start of the memory passed via the -* "vtab" parameter. - -* Parameters: -* mem -* A pointer to the memory in which the SkyAxis is to be created. This -* must be of sufficient size to accommodate the SkyAxis data -* (sizeof(SkyAxis)) 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 SkyAxis (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 SkyAxis -* structure, so a valid value must be supplied even if not required for -* allocating memory. -* init -* A logical flag indicating if the SkyAxis'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 SkyAxis. -* 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 astClass -* method). - -* Returned Value: -* A pointer to the new SkyAxis. - -* 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: */ - AstSkyAxis *new; /* Pointer to the new SkyAxis */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* If necessary, initialise the virtual function table. */ - if ( init ) astInitSkyAxisVtab( vtab, name ); - -/* Initialise an Axis structure (the parent class) as the first component - within the SkyAxis structure, allocating memory if necessary. */ - new = (AstSkyAxis *) astInitAxis( mem, size, 0, (AstAxisVtab *) vtab, - name ); - - if ( astOK ) { - -/* Initialise the SkyAxis data. */ -/* ---------------------------- */ -/* Initialise all attributes to their "undefined" values. */ - new->as_time = -INT_MAX; - new->is_latitude = -INT_MAX; - new->centrezero = -INT_MAX; - new->skyformat = NULL; - -/* If an error occurred, clean up by deleting the new SkyAxis. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return a pointer to the new SkyAxis. */ - return new; -} - -AstSkyAxis *astLoadSkyAxis_( void *mem, size_t size, - AstSkyAxisVtab *vtab, const char *name, - AstChannel *channel, int *status ) { -/* -*+ -* Name: -* astLoadSkyAxis - -* Purpose: -* Load a SkyAxis. - -* Type: -* Protected function. - -* Synopsis: -* #include "skyaxis.h" -* AstSkyAxis *astLoadSkyAxis( void *mem, size_t size, -* AstSkyAxisVtab *vtab, const char *name, -* AstChannel *channel ) - -* Class Membership: -* SkyAxis loader. - -* Description: -* This function is provided to load a new SkyAxis 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 -* SkyAxis 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 SkyAxis at the start of the memory -* passed via the "vtab" parameter. - - -* Parameters: -* mem -* A pointer to the memory into which the SkyAxis is to be -* loaded. This must be of sufficient size to accommodate the -* SkyAxis data (sizeof(SkyAxis)) 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 SkyAxis (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 SkyAxis 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(AstSkyAxis) is used instead. -* vtab -* Pointer to the start of the virtual function table to be -* associated with the new SkyAxis. If this is NULL, a pointer -* to the (static) virtual function table for the SkyAxis 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 "SkyAxis" is used instead. - -* Returned Value: -* A pointer to the new SkyAxis. - -* 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: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstSkyAxis *new; /* Pointer to the new SkyAxis */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(channel); - -/* If a NULL virtual function table has been supplied, then this is - the first loader to be invoked for this SkyAxis. In this case the - SkyAxis belongs to this class, so supply appropriate values to be - passed to the parent class loader (and its parent, etc.). */ - if ( !vtab ) { - size = sizeof( AstSkyAxis ); - vtab = &class_vtab; - name = "SkyAxis"; - -/* If required, initialise the virtual function table for this class. */ - if ( !class_init ) { - astInitSkyAxisVtab( 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 SkyAxis. */ - new = astLoadAxis( mem, size, (AstAxisVtab *) 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, "SkyAxis" ); - -/* 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. */ - -/* Format. */ -/* ------- */ -/* Note that string values do not require any additional processing. */ - new->skyformat = astReadString( channel, "format", NULL ); - -/* IsLatitude. */ -/* ----------- */ - new->is_latitude = astReadInt( channel, "islat", -INT_MAX ); - if ( TestAxisIsLatitude( new, status ) ) { - SetAxisIsLatitude( new, new->is_latitude, status ); - } - -/* CentreZero. */ -/* ----------- */ - new->centrezero = astReadInt( channel, "cnzer", -INT_MAX ); - if ( TestAxisCentreZero( new, status ) ) { - SetAxisCentreZero( new, new->centrezero, status ); - } - -/* AsTime. */ -/* ------- */ - new->as_time = astReadInt( channel, "astime", -INT_MAX ); - if ( TestAxisAsTime( new, status ) ) SetAxisAsTime( new, new->as_time, status ); - -/* If an error occurred, clean up by deleting the new SkyAxis. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return the new SkyAxis pointer. */ - return new; -} - -/* 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. */ - -/* (No more to define at present.) */ - - - - - |