diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2018-01-09 19:28:07 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2018-01-09 19:28:07 (GMT) |
commit | 3bfbbb90d4d6ebd44cc5eac38af24d1f78318a58 (patch) | |
tree | f278119398ae5d67a6a338705a76db420f6b8f7e /ast/axis.c | |
parent | 1332d38f2805d986ea130e43218c0d2e870b4dc1 (diff) | |
download | blt-3bfbbb90d4d6ebd44cc5eac38af24d1f78318a58.zip blt-3bfbbb90d4d6ebd44cc5eac38af24d1f78318a58.tar.gz blt-3bfbbb90d4d6ebd44cc5eac38af24d1f78318a58.tar.bz2 |
update ast 8.6.2
Diffstat (limited to 'ast/axis.c')
-rw-r--r-- | ast/axis.c | 3500 |
1 files changed, 3500 insertions, 0 deletions
diff --git a/ast/axis.c b/ast/axis.c new file mode 100644 index 0000000..6f58b14 --- /dev/null +++ b/ast/axis.c @@ -0,0 +1,3500 @@ +/* +*class++ +* Name: +* Axis + +* Purpose: +* Store axis information. + +* Constructor Function: +* None. + +* Description: +* The Axis class is used to store information associated with a +* particular axis of a Frame. 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 Axis class inherits from the Object class. + +* Copyright: +* Copyright (C) 1997-2006 Council for the Central Laboratory of the +* Research Councils + +* 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. +* 10-SEP-1996 (RFWS): +* Added I/O facilities. +* 11-SEP-1996 (RFWS): +* Added astAxisGap (written by DSB). +* 25-FEB-1998 (RFWS): +* Added astAxisUnformat. +* 29-AUG-2001 (DSB): +* Added AxisDistance and AxisOffset. +* 20-OCT-2002 (DSB): +* Added Top and Bottom attributes. +* 8-JAN-2003 (DSB): +* - Changed private InitVtab method to protected astInitAxisVtab +* method. +* - Include descriptive label for units string within a Dump. +* 24-JAN-2004 (DSB): +* - Added astAxisFields. +* - Added argument "fmt" to definition of AxisAbbrev. +* 3-FEB-2004 (DSB): +* - Added "log" formatting using the "&" flag character in the +* Format string. +* 15-SEP-2004 (DSB): +* - If a format string is set which includes a wildcard precision +* value (".*"), then use the Digits value to determine the precision +* to be used. +* - If the conversion code is of integer type (e.g. "%d") cast value +* to integer before printing. +* 2-FEB-2005 (DSB): +* - Avoid using astStore to allocate more storage than is supplied +* in the "data" pointer. This can cause access violations since +* astStore will then read beyond the end of the "data" area. +* 15-MAR-2005 (DSB): +* - Avoid exponents in log format labels which are close to zero but +* not quite zero. +* 14-FEB-2006 (DSB): +* Override astGetObjSize. +* 30-JUN-2006 (DSB): +* Guard against a null "str1" value in AxisAbbrev. +* 17-APR-2015 (DSB): +* Added astAxisCentre. +* 26-OCT-2016 (DSB): +* Added astAxisNormValues. +*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 Axis + + +/* Header files. */ +/* ============= */ +#include "ast_err.h" /* Error code definitions */ + +/* Interface definitions. */ +/* ---------------------- */ + +#include "globals.h" /* Thread-safe global data access */ +#include "error.h" /* Error reporting facilities */ +#include "memory.h" /* Memory allocation facilities */ +#include "object.h" /* Object interface (parent class) */ +#include "pointset.h" /* Sets of coordinates (for AST__BAD) */ +#include "channel.h" /* I/O channels */ +#include "axis.h" /* Interface definition for this class */ +#include "unit.h" /* Definitions of physical units */ +#include "globals.h" /* Thread-safe global data access */ + +/* C header files. */ +/* --------------- */ +#include <ctype.h> +#include <errno.h> +#include <float.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 int (* parent_testattrib)( AstObject *, const char *, int * ); +static void (* parent_clearattrib)( AstObject *, const char *, int * ); +static void (* parent_setattrib)( AstObject *, const char *, int * ); + +/* Plain text equivalents. */ +static const char *log_txt = "10^"; + +/* 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->GetDefaultFormat_Buff[ 0 ] = 0; \ + globals->AxisFormat_Buff[ 0 ] = 0; \ + globals->GetAxisNormUnit_Buff[ 0 ] = 0; \ + globals->GetAttrib_Buff[ 0 ] = 0; + +/* Create the function that initialises global data for this module. */ +astMAKE_INITGLOBALS(Axis) + +/* Define macros for accessing each item of thread specific global data. */ +#define class_init astGLOBAL(Axis,Class_Init) +#define class_vtab astGLOBAL(Axis,Class_Vtab) +#define getdefaultformat_buff astGLOBAL(Axis,GetDefaultFormat_Buff) +#define axisformat_buff astGLOBAL(Axis,AxisFormat_Buff) +#define getaxisnormunit_buff astGLOBAL(Axis,GetAxisNormUnit_Buff) +#define getattrib_buff astGLOBAL(Axis,GetAttrib_Buff) + + + +/* If thread safety is not needed, declare and initialise globals at static + variables. */ +#else + +static char getdefaultformat_buff[ AST__AXIS_GETDEFAULTFORMAT_BUFF_LEN + 1 ]; +static char axisformat_buff[ AST__AXIS_GETDEFAULTFORMAT_BUFF_LEN + 1 ]; +static char getaxisnormunit_buff[ AST__AXIS_GETAXISNORMUNIT_BUFF_LEN + 1 ]; +static char getattrib_buff[ AST__AXIS_GETATTRIB_BUFF_LEN + 1 ]; + + +/* Define the class virtual function table and its initialisation flag + as static variables. */ +static AstAxisVtab class_vtab; /* Virtual function table */ +static int class_init = 0; /* Virtual function table initialised? */ + +#endif + +/* External Interface Function Prototypes. */ +/* ======================================= */ +/* The following functions have public prototypes only (i.e. no + protected prototypes), so we must provide local prototypes for use + within this module. */ +AstAxis *astAxisId_( 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 *GetAxisLabel( AstAxis *, int * ); +static const char *GetAxisSymbol( AstAxis *, int * ); +static const char *GetAxisUnit( AstAxis *, int * ); +static const char *GetAxisInternalUnit( AstAxis *, int * ); +static const char *GetAxisNormUnit( AstAxis *, int * ); +static const char *GetDefaultFormat( AstAxis *, int * ); +static char *ParseAxisFormat( const char *, int, int *, int *, int *, int *, int * ); +static double AxisDistance( AstAxis *, double, double, int * ); +static double AxisCentre( AstAxis *, double, double, int * ); +static double AxisGap( AstAxis *, double, int *, int * ); +static double AxisOffset( AstAxis *, double, double, int * ); +static int AxisFields( AstAxis *, const char *, const char *, int, char **, int *, double *, int * ); +static int AxisIn( AstAxis *, double, double, double, int, int * ); +static int AxisUnformat( AstAxis *, const char *, double *, int * ); +static int GetAxisDigits( AstAxis *, int * ); +static int GetAxisDirection( AstAxis *, int * ); +static int TestAttrib( AstObject *, const char *, int * ); +static int TestAxisDigits( AstAxis *, int * ); +static int TestAxisDirection( AstAxis *, int * ); +static int TestAxisFormat( AstAxis *, int * ); +static int TestAxisLabel( AstAxis *, int * ); +static int TestAxisSymbol( AstAxis *, int * ); +static int TestAxisUnit( AstAxis *, int * ); +static int TestAxisInternalUnit( AstAxis *, int * ); +static int TestAxisNormUnit( AstAxis *, 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 ClearAxisDigits( AstAxis *, int * ); +static void ClearAxisDirection( AstAxis *, int * ); +static void ClearAxisFormat( AstAxis *, int * ); +static void ClearAxisLabel( AstAxis *, int * ); +static void ClearAxisSymbol( AstAxis *, int * ); +static void ClearAxisUnit( AstAxis *, int * ); +static void Copy( const AstObject *, AstObject *, int * ); +static void Delete( AstObject *, int * ); +static void Dump( AstObject *, AstChannel *, int * ); +static void SetAttrib( AstObject *, const char *, int * ); +static void SetAxisDigits( AstAxis *, int, int * ); +static void SetAxisDirection( AstAxis *, int, int * ); +static void SetAxisFormat( AstAxis *, const char *, int * ); +static void SetAxisLabel( AstAxis *, const char *, int * ); +static void SetAxisSymbol( AstAxis *, const char *, int * ); +static void SetAxisUnit( AstAxis *, const char *, int * ); + +static double GetAxisTop( AstAxis *, int * ); +static int TestAxisTop( AstAxis *, int * ); +static void ClearAxisTop( AstAxis *, int * ); +static void SetAxisTop( AstAxis *, double, int * ); + +static double GetAxisBottom( AstAxis *, int * ); +static int TestAxisBottom( AstAxis *, int * ); +static void ClearAxisBottom( AstAxis *, int * ); +static void SetAxisBottom( AstAxis *, double, int * ); + + +/* Member functions. */ +/* ================= */ +static const char *AxisAbbrev( AstAxis *this, const char *fmt, + const char *str1, const char *str2, int *status ) { +/* +*+ +* Name: +* astAxisAbbrev + +* Purpose: +* Abbreviate a formatted Axis value by skipping leading fields. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* const char *astAxisAbbrev( AstAxis *this, const char *fmt, +* const char *str1, const char *str2 ) + +* Class Membership: +* Axis method. + +* Description: +* This function compares two Axis values that have been formatted +* (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 Axis. +* 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: +* - This function assumes that the format specification used was +* the same when both values were formatted. +* - 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: */ + const char *result; /* Result pointer to return */ + +/* Initialise. */ + result = str2; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* In the Axis class, there is only one field in a formatted value. + We return the value of "str2", unless the two strings are + identical, in which case we return a pointer to the final null in + "str2". */ + if( str1 && !strcmp( str1, str2 ) ) result += strlen( str2 ); + +/* Return the result. */ + return result; +} + +static double AxisDistance( AstAxis *this, double v1, double v2, int *status ) { +/* +*+ +* Name: +* astAxisDistance + +* Purpose: +* Find the distance between two axis values. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* AxisDistance( AstAxis *this, double v1, double v2 ) + +* Class Membership: +* Axis method. + +* Description: +* This function returns a signed value representing the axis increment +* from axis value v1 to axis value v2. +* +* For a simple Axis, this is a trivial operation. But for other +* derived classes of Axis (such as a SkyAxis) this is not the case. + +* Parameters: +* this +* Pointer to the Axis. +* 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. */ + if( v1 != AST__BAD && v2 != AST__BAD ) result = v2 - v1; + +/* Return the result. */ + return result; +} + +static int AxisFields( AstAxis *this, const char *fmt0, const char *str, + int maxfld, char **fields, int *nc, double *val, int *status ) { +/* +*+ +* Name: +* astAxisFields + +* Purpose: +* Identify numerical fields within a formatted Axis value. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* int astAxisFields( AstAxis *this, const char *fmt0, const char *str, +* int maxfld, char **fields, int *nc, double *val ) + +* Class Membership: +* Axis member function. + +* Description: +* This function identifies the numerical fields within an Axis 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. + +* Parameters: +* this +* Pointer to the Axis. +* fmt0 +* Pointer to a constant null-terminated string containing the +* format used when creating "str". +* str +* Pointer to a constant null-terminated string containing the +* formatted value. +* maxfld +* The maximum number of fields to identify within "str". +* fields +* A pointer to an array of at least "maxfld" character pointers. +* Each element is returned holding a pointer to the start of the +* corresponding field in "str" (in the order in which they occur +* within "str"), or NULL if no corresponding field can be found. +* nc +* A pointer to an array of at least "maxfld" integers. Each +* element is returned holding the number of characters in the +* corresponding field, or zero if no corresponding field can be +* found. +* val +* Pointer to a location at which to store the value +* equivalent to the returned field values. If this is NULL, +* it is ignored. + +* Returned Value: +* The number of fields succesfully identified and returned. + +* Notes: +* - Leading and trailing spaces are ignored. +* - If the formatted value is not consistent with the supplied format +* string, then a value of zero will be returned, "fields" will be +* returned holding NULLs, "nc" will be returned holding zeros, and +* "val" is returned holding VAL__BAD. +* - Fields are counted from the start of the formatted string. If the +* string contains more than "maxfld" fields, then trailing fields are +* ignored. +* - If this function is invoked with the global error status set, or +* if it should fail for any reason, then a value of zero will be returned +* as the function value, and "fields", "nc" and "val" will be returned +* holding their supplied values +*- +*/ + +/* Local Variables: */ + char log_esc[ 50 ]; /* Buffer for graphical delimiter string */ + const char *fmt; /* Pointer to parsed Format string */ + const char *log_del; /* Pointer to delimiter string */ + const char *p; /* Pointer to next character */ + double value; /* Equivalent radians value */ + int ifld; /* Field index */ + int integ; /* Cast axis value to integer before printing? */ + int len; /* Length of formatted string */ + int log; /* Format as "10**x"? */ + int n; /* Number of characters read */ + int neg; /* Negate final value? */ + int result; /* Result fields count to return */ + int sign; /* Include leading sign in front of "10**x"? */ + int space; /* Include leading space in front of "10**x"? */ + +/* Check the global error status. */ + if ( !astOK ) return 0; + +/* Initialise. */ + result = 0; + for( ifld = 0; ifld < maxfld; ifld++ ) { + fields[ ifld ] = NULL; + nc[ ifld ] = 0; + } + if( val ) *val = AST__BAD; + +/* Parse the Format string. This returns a collection of flags indicating + if any AST specific formatting features are specified in the Format + string. It also returns a pointer to a new Format string which is a + standard C printf format specifier. Currently the only flags are "log" + which indicates if the value should be formatted as "10**x" using + the graphical escape sequences defined within the Plot class to produce + "x" as a superscript of "10", "sign" which is used with log to indicate + if a sign should always be included infront of the "10", and "space" + which indicates if a leading space should be included infronyt of "10" if + no sign is included. */ + fmt = ParseAxisFormat( fmt0, astGetAxisDigits( this ), &log, &sign, + &space, &integ, status ); + fmt = astFree( (void *) fmt ); + + if( astOK ) { + +/* Obtain the length of the formatted string. */ + len = (int) strlen( str ); + +/* First deal with "log" format. */ + if( log ) { + +/* We need room for at least 2 fields. */ + if( maxfld > 1 ) { + +/* Return a pointer to the first non-blank character. */ + p = str; + while( *p == ' ' ) p++; + fields[ 0 ] = (char *) p; + +/* If the first non-blank character is a minus sign, note it and skip it. */ + neg = 0; + if( *p == '-' ) { + neg = 1; + p++; + +/* If the first non-blank character is a plus sign, and skip it. */ + } else if( *p == '+' ) { + p++; + } + +/* Select the delimter.*/ + if( astEscapes( -1 ) ) { + astTuneC( "exdel", NULL, log_esc, sizeof( log_esc ) ); + log_del = log_esc; + } else { + log_del = log_txt; + } + +/* Check the remaining string starts with the correct delimiter. If + so, store the number of characters in the first field and skip over the + delimiter. */ + n = 0; + if( strstr( p, log_del ) == p ) { + nc[ 0 ] = p + 2 - fields[ 0 ]; + p += strlen( log_del ); + +/* Attempt to read a floating point value from the start of the remaining + string. */ + if( 1 == sscanf( p, "%lg%n", &value, &n ) ) { + +/* If succesfull, store the returned values. */ + result = 2; + fields[ 1 ] = (char *) p; + nc[ 1 ] = n; + if( val ) { + *val = pow( 10.0, value ); + if( neg ) *val = -(*val); + } + +/* Otherwise, see if the string starts with <bad> */ + } else if( strstr( p, "<bad>" ) == p ) { + +/* If succesfull, store the returned values. */ + result = 2; + fields[ 1 ] = (char *) p; + nc[ 1 ] = 5; + if( val ) *val = 0.0; + } + +/* Zero is never formatted as an exponent. If the string starts with zero, + return a single zero field. */ + } else if( 1 == sscanf( p, "%lg%n", &value, &n ) ) { + if( value == 0.0 ) { + result = 1; + nc[ 0 ] = p + n - fields[ 0 ]; + if( val ) *val = 0.0; + } + } + } + +/* Now deal with normal decimal format */ + } else { + +/* Attempt to read a floating point value from the formatted string. */ + if ( n = 0, + ( 1 == sscanf( str, "%lg %n", &value, &n ) ) + && ( n >= len ) && maxfld > 0 ) { + +/* If succesful, return a pointer to the first non-blank character. */ + p = str; + while( *p == ' ' ) p++; + fields[ 0 ] = (char *) p; + +/* Find the last non-blank character. */ + p += len; + while( p[ -1 ] == ' ' ) p--; + +/* Return the number of characters in the field. */ + nc[ 0 ] = p - fields[ 0 ]; + +/* Return the field value. */ + if( val ) *val = value; + +/* Indicate that we are returning one field. */ + result = 1; + } + } + } + +/* Return the result. */ + return result; +} + +static const char *AxisFormat( AstAxis *this, double value, int *status ) { +/* +*+ +* Name: +* astAxisFormat + +* Purpose: +* Format a coordinate value for an Axis. + +* Type: +* Public virtual function. + +* Synopsis: +* #include "axis.h" +* const char *astAxisFormat( AstAxis *this, double value ) + +* Class Membership: +* Axis method. + +* Description: +* This function returns a pointer to a string containing the formatted +* (character) version of a coordinate value for an Axis. 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 Axis. +* value +* The coordinate value to be formatted. + +* 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 Axis 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 Axis. 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 Constants: */ +#define ERRBUF_LEN 80 + +/* Local Variables: */ + astDECLARE_GLOBALS /* Pointer to thread-specific global data */ + char *errstat; /* Pointer for system error message */ + char errbuf[ ERRBUF_LEN ]; /* Buffer for system error message */ + char log_esc[ 50 ]; /* Buffer for graphical delimiter string */ + const char *fmt0; /* Pointer to original Format string */ + const char *fmt; /* Pointer to parsed Format string */ + const char *log_del; /* Pointer to delimiter string */ + const char *result; /* Pointer to formatted value */ + double x; /* The value to be formatted by sprintf */ + int integ; /* Cast axis value to integer before printing? */ + int log; /* Format as "10**x"? */ + int nc; /* Total number of characters written */ + int ncc; /* Number of characters written */ + int sign; /* Include leading sign in front of "10**x"? */ + int space; /* Include leading space in front of "10**x"? */ + int stat; /* Value of errno after error */ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Get a pointer to the thread specific global data structure. */ + astGET_GLOBALS(this); + +/* Initialise. */ + result = NULL; + nc = 0; + x = value; + +/* Check if a bad coordinate value was supplied and return a pointer to an + appropriate string if necessary. */ + if ( value == AST__BAD ) { + result = "<bad>"; + +/* Otherwise, obtain a pointer to the Format string. Note a private member + function is used here in preference to an object method. This is because the + syntax of the Format string may be extended by derived classes and we do not + want to obtain a string that we cannot interpret here (where we are + restricted to C format specifiers capable of formatting double values). + Classes that extend the syntax should provide their own astAxisFormat method + and may need to store the string in a separate location. The original + location should not be re-used as the string it contains may be needed by + the Axis astOverlay method when overlaying attributes on to another Axis + object. */ + } else { + fmt0 = GetAxisFormat( this, status ); + +/* Parse the Format string. This returns a collection of flags indicating + if any AST specific formatting features are specified in the Format + string. It also returns a pointer to a new Format string which is a + standard C printf format specifier. Currently the only flags are "log" + which indicates if the value should be formatted as "10**x" using + the graphical escape sequences defined within the Plot class to produce + "x" as a superscript of "10", "sign" which is used with log to indicate + if a sign should always be included infront of the "10", and "space" + which indicates if a leading space should be included infronyt of "10" + if no sign is included. It also modifies ".*" precision fields by + replacing the "*" by the current vale of the Digits attribute. */ + fmt = ParseAxisFormat( fmt0, astGetAxisDigits( this ), &log, &sign, + &space, &integ, status ); + if( astOK ) { + +/* Format zero normally. */ + if( value == 0.0 ) log = 0; + +/* If log format is required, find the value of the exponent "x", and + initialise the returned string to hold the exponent and the graphical + escape sequence which produces a superscript. Otherwise just format the + supplied value. */ + if( log ) { + + if( sign ) { + axisformat_buff[ 0 ] ='+'; + nc = 1; + + } else if( space ) { + axisformat_buff[ 0 ] =' '; + nc = 1; + } + + if( value > 0 ) { + x = log10( integ ? (int) value : value ); + + } else { + x = log10( integ ? (int) -value : -value ); + axisformat_buff[ 0 ] ='-'; + nc = 1; + } + + if( astEscapes( -1 ) ) { + astTuneC( "exdel", NULL, log_esc, sizeof( log_esc ) ); + log_del = log_esc; + } else { + log_del = log_txt; + } + + nc += sprintf( axisformat_buff + nc, "%s", log_del ); + +/* Round small exponents to zero. */ + if( fabs( x ) < 1.0E-10 ) x = 0.0; + } + } + +/* Clear errno and attempt to format the value as if the Format string were + a standard "sprintf" format. */ + if ( astOK ) { + errno = 0; + if( integ ) { + ncc = sprintf( axisformat_buff + nc, fmt, (int) x ); + } else { + ncc = sprintf( axisformat_buff + nc, fmt, x ); + } + nc += ncc; + +/* If log format is being used, terminate the string with an escape + sequence which resets the graphical attributes to what they were at the + start of the string. */ + if( log ) nc += sprintf( axisformat_buff + nc, "%%+" ); + +/* The possibilities for error detection are limited here, but check if an + error value was returned and report an error. Include information from + errno if it was set. */ + if ( ncc < 0 ) { + stat = errno; + if( stat ) { +#if HAVE_STRERROR_R + strerror_r( stat, errbuf, ERRBUF_LEN ); + errstat = errbuf; +#else + errstat = strerror( stat ); +#endif + } else { + *errbuf = 0; + errstat = errbuf; + } + astError( AST__FMTER, "astAxisFormat(%s): Error formatting a " + "coordinate value of %1.*G%s%s.", status, astGetClass( this ), + AST__DBL_DIG, value, stat? " - " : "", errstat ); + astError( AST__FMTER, "The format string was \"%s\".", status, fmt ); + +/* Also check that the result buffer did not overflow. If it did, memory will + probably have been corrupted but this cannot be prevented with "sprintf". + Report the error and abort. */ + } else if ( nc > AST__AXIS_AXISFORMAT_BUFF_LEN ) { + astError( AST__FMTER, "astAxisFormat(%s): Internal buffer " + "overflow while formatting a coordinate value of %1.*G " + "- result exceeds %d characters.", status, astGetClass( this ), + AST__DBL_DIG, value, AST__AXIS_AXISFORMAT_BUFF_LEN ); + astError( AST__FMTER, "The format string was \"%s\".", status, fmt ); + +/* If succesfull, return a pointer to the buffer. */ + } else { + result = axisformat_buff; + } + } + +/* Free resources. */ + fmt = astFree( (void *) fmt ); + + } + +/* Return the result. */ + return result; + +} +#undef ERRBUF_LEN + +static double AxisCentre( AstAxis *this, double value, double gap, int *status ) { +/* +*+ +* Name: +* astAxisCentre + +* Purpose: +* Find a "nice" central value for tabulating Axis values. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* double astAxisCentre( AstAxis *this, double value, double gap ) + +* Class Membership: +* Axis method. + +* Description: +* This function returns an axis value which produces a nice formatted +* value suitable for a major tick mark on a plot axis. + +* Parameters: +* this +* Pointer to the Axis. +* value +* An arbitrary axis value in the section that is being plotted. +* gap +* The gap size. + +* Returned Value: +* The nice central axis value. + +* Notes: +* - A value of zero is returned if the supplied gap size is zero. +* - A value of zero will be returned if this function is invoked +* with the global error status set, or if it should fail for any +* reason. +*- +*/ + +/* Local Variables: */ + double result; /* Returned central axis value */ + +/* Initialise. */ + result = 0.0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* The returned central value is an integral number of gaps away from the + origin and is close to the supplied axis value. This would result in + the origin being at a major tick mark. */ + if( gap != 0.0 && gap != AST__BAD && value != AST__BAD ) { + result = gap*floor( 0.5 + value/gap ); + } + +/* Return the result. */ + return result; +} + +static double AxisGap( AstAxis *this, double gap, int *ntick, int *status ) { +/* +*+ +* Name: +* astAxisGap + +* Purpose: +* Find a "nice" gap for tabulating Axis values. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* double astAxisGap( AstAxis *this, double gap, int *ntick ) + +* Class Membership: +* Axis method. + +* Description: +* This function returns a gap size which produces a nicely spaced +* series of formatted Axis 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 Axis. +* 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. + +* Returned Value: +* The nice gap size. + +* Notes: +* - 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: */ + double absgap; /* Absolute supplied gap size */ + double b; /* Decimal step size */ + double result; /* Returned gap size */ + int index; /* Index into tables */ + int positive; /* Value is positive (or zero)? */ + +/* Local Data: */ + static double table1[ 10 ] = /* Table of nice decimal gaps */ + { 1.0, 2.0, 2.0, 5.0, 5.0, 5.0, 5.0, 10.0, 10.0, 10.0 }; + static int table2[ 10 ] = /* Table giving number of divisions */ + { 5, 4, 4, 5, 5, 5, 5, 5, 5, 5 }; + +/* Initialise. */ + result = 0.0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Check that the supplied gap size is not zero. */ + if ( gap != 0.0 ) { + +/* Determine if the supplied gap size is positive and obtain its + absolute value. */ + positive = ( gap >= 0.0 ); + absgap = positive ? gap : -gap; + +/* Obtain a value which has a 1 at the position of the most + significant decimal digit in the target gap size and zeros at all + other positions. */ + b = pow( 10.0, floor( log10( absgap ) ) ); + +/* This value is the basic "step size". Find the nearest whole number + of steps in the supplied gap, and then use the look-up-table in + "table1" to find the closest acceptable gap size. Convert this gap + size back to an absolute value by multiplying by the step size. */ + index = (int) ( absgap / b + 0.5 ) - 1; + result = b * table1[ index ]; + +/* If the target gap was negative, negate the result. */ + if( !positive ) result = -result; + +/* Store the number of divisions in the gap. */ + if ( ntick ) *ntick = table2[ index ]; + } + +/* Return the result. */ + return result; +} + +static int AxisIn( AstAxis *this, double lo, double hi, double val, int closed, int *status ){ +/* +*+ +* Name: +* astAxisIn + +* Purpose: +* Test if an axis value lies within a given interval. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* int AxisIn( AstAxis *this, double lo, double hi, double val, int closed ) + +* Class Membership: +* Axis member function. + +* Description: +* This function returns non-zero if a given axis values lies within a +* given axis interval. + +* 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. + +* Returned Value: +* Non-zero if the test value is inside the interval. + +* Class Applicability: +* Axis +* Uses simple Euclidean test +* SkyAxis +* All angles which are numerically between "lo" and "hi" are within +* the interval. Angle outside this range are also within the interval +* if they can be brought into the range by addition or subtraction +* of a multiple of 2.PI. +*- +*/ + +/* For speed, omit the astOK check since no pointers are being used. */ + if( closed ) { + return ( lo <= val && val <= hi ); + } else { + return ( lo < val && val < hi ); + } +} + +static void AxisNorm( AstAxis *this, double *value, int *status ) { +/* +*+ +* Name: +* astAxisNorm + +* Purpose: +* Normalise an Axis coordinate value. + +* Type: +* Public virtual function. + +* Synopsis: +* #include "axis.h" +* void astAxisNorm( AstAxis *this, double *value ) + +* Class Membership: +* Axis method. + +* Description: +* This function converts an Axis 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. +* +* Typically, for axes that represent cyclic values such as angles, +* this function wraps an arbitrary coordinate value so that it +* lies within the first cycle (say zero to 2*pi). For an ordinary +* linear Axis, without constraints, this function will typically +* return the original value unchanged. + +* Parameters: +* this +* Pointer to the Axis. +* value +* Pointer to the coordinate value to be normalised, which will +* be modified in place. +*- +*/ + +/* In the Axis class there are no constraints, so simply return + without action. */ + return; +} + +static void AxisNormValues( AstAxis *this, int oper, int nval, + double *values, int *status ){ +/* +*+ +* Name: +* astAxisNormValues + +* Purpose: +* Normalise an array of axis coordinate values. + +* Type: +* Public virtual function. + +* Synopsis: +* #include "axis.h" +* void astAxisNormValues( AstAxis *this, int oper, int nval, +* double *values ) + +* Class Membership: +* Axis method. + +* Description: +* This function modifies a supplied array of axis values so that +* they are normalised in the manner indicated by parameter "oper". +* +* For a simple axis, the supplied values are always returned +* unchanged regardless of the value of "oper". + +* 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. +*- +*/ + +/* In the Axis class there are no constraints, so simply return + without action. */ + return; +} + +static double AxisOffset( AstAxis *this, double v1, double dist, int *status ) { +/* +*+ +* Name: +* astAxisOffset + +* Purpose: +* Add an increment onto a supplied axis value. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* AxisOffset( AstAxis *this, double v1, double dist ) + +* Class Membership: +* Axis method. + +* Description: +* This function returns an axis value formed by adding a signed axis +* increment onto a supplied axis value. +* +* For a simple Axis, this is a trivial operation. But for other +* derived classes of Axis (such as a SkyAxis) this is not the case. + +* Parameters: +* this +* Pointer to the Axis. +* 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; + +/* Return the result. */ + return result; +} + +static void AxisOverlay( AstAxis *template, AstAxis *result, int *status ) { +/* +*+ +* Name: +* astAxisOverlay + +* Purpose: +* Overlay the attributes of a template Axis on to another Axis. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* void astAxisOverlay( AstAxis *template, AstAxis *result ) + +* Class Membership: +* Axis method. + +* Description: +* This function overlays attributes of one Axis (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 Axis, 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. + +* Returned Value: +* void +*- +*/ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Define a macro to overlay a single attribute. This tests if the attribute + is set in the template Axis. If it is, its value is obtained and set in the + result Axis also. */ +#define OVERLAY(par) \ + if ( astTestAxis##par( template ) ) { \ + astSetAxis##par( result, astGetAxis##par( template ) ); \ + } +/* Overlay each Axis attribute in turn. */ + OVERLAY(Digits); + OVERLAY(Direction); + OVERLAY(Label); + OVERLAY(Symbol); + OVERLAY(Unit); + +/* Handle the Format string slightly differently by using a private member + function to obtain it. This is necessary in case derived classes have + extended the string syntax (see the AxisFormat function for more + details). */ + if ( TestAxisFormat( template, status ) ) { + SetAxisFormat( result, GetAxisFormat( template, status ), status ); + } + +/* Undefine macros local to this function. */ +#undef OVERLAY +} + +static int AxisUnformat( AstAxis *this, const char *string, double *value, int *status ) { +/* +*+ +* Name: +* astAxisUnformat + +* Purpose: +* Read a formatted coordinate value for an Axis. + +* Type: +* Public virtual function. + +* Synopsis: +* #include "axis.h" +* int astAxisUnformat( AstAxis *this, const char *string, double *value ) + +* Class Membership: +* Axis method. + +* Description: +* This function reads a formatted coordinate value for an Axis +* (supplied as a string) and returns the equivalent numerical +* value as a double. It also returns the number of characters read +* from the string. + +* Parameters: +* this +* Pointer to the Axis. +* string +* Pointer to a constant null-terminated string containing the +* formatted coordinate value. +* value +* Pointer to a double in which the coordinate value read will be +* returned. + +* Returned Value: +* The number of characters read from the string to obtain the +* coordinate value. + +* Notes: +* - Any white space at the beginning of the string will be +* skipped, as also will any trailing white space following the +* coordinate value read. The function's return value will reflect +* this. +* - A function value of zero (and no coordinate value) will be +* returned, without error, if the string supplied does not contain +* a suitably formatted value. +* - The string "<bad>" is recognised as a special case and will +* generate the value AST__BAD, without error. The test for this +* string is case-insensitive and permits embedded white space. +* - A function result of zero will be returned and no coordinate +* value will be returned via the "value" pointer if this function +* is invoked with the global error status set, or if it should +* fail for any reason. +*- +*/ + +/* Local Variables: */ + double coord; /* Coordinate value read */ + int nc; /* Number of characters read */ + +/* Initialise. */ + nc = 0; + +/* Check the global error status. */ + if ( !astOK ) return nc; + +/* See if the string can be read as a floating point number. If so, + return its value. Also obtain the number of characters read, + including any leading and trailing white space. */ + if ( 1 == astSscanf( string, "%lf %n", &coord, &nc ) ) { + *value = coord; + +/* Otherwise, see if the string starts with "<bad>", allowing mixed + case and leading, embedded and trailing white space. If so, return + the value AST__BAD. */ + } else if ( nc = 0, + ( 0 == astSscanf( string, " < %*1[Bb] %*1[Aa] %*1[Dd] > %n", &nc ) + && ( nc > 0 ) ) ) { + *value = AST__BAD; + +/* If the string cannot be read, return a function result of zero. */ + } else { + nc = 0; + } + +/* Return the number of characters read. */ + return nc; +} + +static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) { +/* +* Name: +* ClearAttrib + +* Purpose: +* Clear an attribute value for an Axis. + +* Type: +* Private function. + +* Synopsis: +* #include "axis.h" +* void ClearAttrib( AstObject *this, const char *attrib, int *status ) + +* Class Membership: +* Axis member function (over-rides the astClearAttrib protected +* method inherited from the Object class). + +* Description: +* This function clears the value of a specified attribute for an +* Axis, so that the default value will subsequently be used. + +* Parameters: +* this +* Pointer to the Axis. +* 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: */ + AstAxis *this; /* Pointer to the Axis structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Axis structure. */ + this = (AstAxis *) this_object; + +/* Check the attribute name and clear the appropriate attribute. */ + +/* Digits. */ +/* ------- */ + if ( !strcmp( attrib, "digits" ) ) { + astClearAxisDigits( this ); + +/* Direction. */ +/* ---------- */ + } else if ( !strcmp( attrib, "direction" ) ) { + astClearAxisDirection( this ); + +/* Format. */ +/* ------- */ + } else if ( !strcmp( attrib, "format" ) ) { + astClearAxisFormat( this ); + +/* Label. */ +/* ------ */ + } else if ( !strcmp( attrib, "label" ) ) { + astClearAxisLabel( this ); + +/* Top. */ +/* ---- */ + } else if ( !strcmp( attrib, "top" ) ) { + astClearAxisTop( this ); + +/* Bottom. */ +/* ------- */ + } else if ( !strcmp( attrib, "bottom" ) ) { + astClearAxisBottom( this ); + +/* Symbol. */ +/* ------- */ + } else if ( !strcmp( attrib, "symbol" ) ) { + astClearAxisSymbol( this ); + +/* Unit. */ +/* ----- */ + } else if ( !strcmp( attrib, "unit" ) ) { + astClearAxisUnit( this ); + +/* Read-only attributes. */ +/* --------------------- */ +/* Test if the attribute name matches any of the read-only attributes + of this class. If it does, then report an error. */ + } else if ( !strcmp( attrib, "normunit" ) || + !strcmp( attrib, "internalunit" ) ) { + astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" " + "value for a %s.", status, attrib, astGetClass( this ) ); + astError( AST__NOWRT, "This is a read-only attribute." , status); + +/* 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 const char *GetAxisInternalUnit( AstAxis *this, int *status ){ +/* +*+ +* Name: +* astGetAxisInternalUnit + +* Purpose: +* Return the unit string for unformatted Axis values + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* const char *astGetAxisInternalUnit( AstAxis *this ){ + +* Class Membership: +* Axis method. + +* Description: +* This function returns the axis InternalUnit attribute. For basic +* axes, the InternalUnit and Unit attributes are the same. + +* 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 astGetAxisUnit( this ); +} + +static const char *GetAxisNormUnit( AstAxis *this, int *status ){ +/* +*+ +* Name: +* astGetAxisNormUnit + +* Purpose: +* Return the normalised Unit attribute for an Axis. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "axis.h" +* const char *astGetAxisNormUnit( AstAxis *this ){ + +* Class Membership: +* Axis method. + +* Description: +* This function normalised and returns the axis Unit attribute. +* Normalisation refers to transformations such as "s*(m/s)" -> "m". + +* Parameters: +* this +* Pointer to the Axis. + +* Returned Value: +* - Pointer to a null-terminated string containing the normalised +* 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. +*- +*/ + +/* Local Variables: */ + astDECLARE_GLOBALS /* Pointer to thread-specific global data */ + const char *result; /* Pointer to dynamic memory holding returned text */ + int nc; /* Length of normalised Unit string */ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Get a pointer to the thread specific global data structure. */ + astGET_GLOBALS(this); + +/* Get the Axis Unit attrribute and normalise it. */ + result = astUnitNormaliser( astGetAxisUnit( this ) ); + +/* If successful, check that the resulting string will fit in the buffer. + If not, report an error. */ + if( result ) { + nc = strlen( result ); + if( nc > AST__AXIS_GETAXISNORMUNIT_BUFF_LEN ) { + astError( AST__FMTER, "astGetAxisNormUnit(%s): Internal buffer " + "overflow while normalising the units string '%s' " + "- result exceeds %d characters.", status, astGetClass( this ), + result, AST__AXIS_GETAXISNORMUNIT_BUFF_LEN ); + result = astFree( (void *) result ); + +/* If so, copy it into the static buffer and free the dynamic memory returned + by astUnitNormaliser. */ + } else { + strcpy( getaxisnormunit_buff, result ); + } + astFree( (void *) result ); + + result = getaxisnormunit_buff; + } + +/* Return the answer. */ + 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 "axis.h" +* int GetObjSize( AstObject *this, int *status ) + +* Class Membership: +* Axis member function (over-rides the astGetObjSize protected +* method inherited from the parent class). + +* Description: +* This function returns the in-memory size of the supplied Axis, +* in bytes. + +* Parameters: +* this +* Pointer to the Axis. +* 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: */ + AstAxis *this; /* Pointer to Axis structure */ + int result; /* Result value to return */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointers to the Axis structure. */ + this = (AstAxis *) 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->label ); + result += astTSizeOf( this->format ); + result += astTSizeOf( this->symbol ); + result += astTSizeOf( this->unit ); + +/* 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 an Axis. + +* Type: +* Private function. + +* Synopsis: +* #include "axis.h" +* const char *GetAttrib( AstObject *this, const char *attrib, int *status ) + +* Class Membership: +* Axis member function (over-rides the protected astGetAttrib +* method inherited from the Object class). + +* Description: +* This function returns a pointer to the value of a specified +* attribute for an Axis, formatted as a character string. + +* Parameters: +* this +* Pointer to the Axis. +* 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 Axis, 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 Axis. 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 */ + AstAxis*this; /* Pointer to the Axis structure */ + const char *result; /* Pointer value to return */ + double dval; /* Double attribute value */ + int digits; /* Digits attribute value */ + int direction; /* Direction 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 Axis structure. */ + this = (AstAxis *) 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. */ + +/* Digits. */ +/* ------- */ + if ( !strcmp( attrib, "digits" ) ) { + digits = astGetAxisDigits( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", digits ); + result = getattrib_buff; + } + +/* Direction. */ +/* ---------- */ + } else if ( !strcmp( attrib, "direction" ) ) { + direction = astGetAxisDirection( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", direction ); + result = getattrib_buff; + } + +/* Top. */ +/* ---- */ + } else if ( !strcmp( attrib, "top" ) ) { + dval = astGetAxisTop( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); + result = getattrib_buff; + } + +/* Bottom. */ +/* ------- */ + } else if ( !strcmp( attrib, "bottom" ) ) { + dval = astGetAxisBottom( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); + result = getattrib_buff; + } + +/* Format. */ +/* ------- */ + } else if ( !strcmp( attrib, "format" ) ) { + result = astGetAxisFormat( this ); + +/* Label. */ +/* ------ */ + } else if ( !strcmp( attrib, "label" ) ) { + result = astGetAxisLabel( this ); + +/* Symbol. */ +/* ------- */ + } else if ( !strcmp( attrib, "symbol" ) ) { + result = astGetAxisSymbol( this ); + +/* Unit. */ +/* ----- */ + } else if ( !strcmp( attrib, "unit" ) ) { + result = astGetAxisUnit( this ); + +/* NormUnit. */ +/* --------- */ + } else if ( !strcmp( attrib, "normunit" ) ) { + result = astGetAxisNormUnit( this ); + +/* InternalUnit. */ +/* ------------- */ + } else if ( !strcmp( attrib, "internalunit" ) ) { + result = astGetAxisInternalUnit( this ); + +/* 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 const char *GetDefaultFormat( AstAxis *this, int *status ){ +/* +* Name: +* GetDefaultFormat + +* Purpose: +* Return a pointer to a string holding the default Format value. + +* Type: +* Private function. + +* Synopsis: +* #include "axis.h" +* const char *GetDefaultFormat( AstAxis *this, int *status ) + +* Class Membership: +* Axis member function + +* Description: +* This function returns a pointer to a string holding the default +* Format value, which is based on the current Digits value. + +* Parameters: +* this +* A pointer to the Axis structure. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* - Pointer to a static null-terminated character string containing +* the default Format string. + +* Notes: +* - A null string 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 */ + +/* Check the global error status. */ + if ( !astOK ) return ""; + +/* Get a pointer to the thread specific global data structure. */ + astGET_GLOBALS(this); + +/* Create the default format value and store it in the "format_buff" + static variable. */ + (void) sprintf( getdefaultformat_buff, "%%1.%dG", astGetAxisDigits( this ) ); + +/* Return a pointer to the "format_buff" static variable. */ + return getdefaultformat_buff; +} + +void astInitAxisVtab_( AstAxisVtab *vtab, const char *name, int *status ) { +/* +*+ +* Name: +* astInitAxisVtab + +* Purpose: +* Initialise a virtual function table for an Axis. + +* Type: +* Protected function. + +* Synopsis: +* #include "axis.h" +* void astInitAxisVtab( AstAxisVtab *vtab, const char *name ) + +* Class Membership: +* Axis vtab initialiser. + +* Description: +* This function initialises the component of a virtual function +* table which is used by the Axis class. + +* Parameters: +* vtab +* Pointer to the virtual function table. The components used by +* all ancestral classes will be initialised if they have not already +* been initialised. +* name +* Pointer to a constant null-terminated character string which contains +* the name of the class to which the virtual function table belongs (it +* is this pointer value that will subsequently be returned by the Object +* astClass function). +*- +*/ + +/* Local Variables: */ + astDECLARE_GLOBALS /* Pointer to thread-specific global data */ + AstObjectVtab *object; /* Pointer to Object component of Vtab */ + +/* 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. */ + astInitObjectVtab( (AstObjectVtab *) vtab, name ); + +/* Store a unique "magic" value in the virtual function table. This + will be used (by astIsAAxis) 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 = &(((AstObjectVtab *) vtab)->id); + +/* Initialise member function pointers. */ +/* ------------------------------------ */ +/* Store pointers to the member functions (implemented here) that provide + virtual methods for this class. */ + vtab->AxisAbbrev = AxisAbbrev; + vtab->AxisFields = AxisFields; + vtab->AxisFormat = AxisFormat; + vtab->AxisDistance = AxisDistance; + vtab->AxisOffset = AxisOffset; + vtab->AxisCentre = AxisCentre; + vtab->AxisGap = AxisGap; + vtab->AxisIn = AxisIn; + vtab->AxisNorm = AxisNorm; + vtab->AxisNormValues = AxisNormValues; + vtab->AxisOverlay = AxisOverlay; + vtab->AxisUnformat = AxisUnformat; + vtab->ClearAxisDigits = ClearAxisDigits; + vtab->ClearAxisDirection = ClearAxisDirection; + vtab->ClearAxisFormat = ClearAxisFormat; + vtab->ClearAxisLabel = ClearAxisLabel; + vtab->ClearAxisSymbol = ClearAxisSymbol; + vtab->ClearAxisUnit = ClearAxisUnit; + vtab->GetAxisDigits = GetAxisDigits; + vtab->GetAxisDirection = GetAxisDirection; + vtab->GetAxisFormat = GetAxisFormat; + vtab->GetAxisLabel = GetAxisLabel; + vtab->GetAxisSymbol = GetAxisSymbol; + vtab->GetAxisUnit = GetAxisUnit; + vtab->GetAxisInternalUnit = GetAxisInternalUnit; + vtab->GetAxisNormUnit = GetAxisNormUnit; + vtab->SetAxisDigits = SetAxisDigits; + vtab->SetAxisDirection = SetAxisDirection; + vtab->SetAxisFormat = SetAxisFormat; + vtab->SetAxisLabel = SetAxisLabel; + vtab->SetAxisSymbol = SetAxisSymbol; + vtab->SetAxisUnit = SetAxisUnit; + vtab->TestAxisDigits = TestAxisDigits; + vtab->TestAxisDirection = TestAxisDirection; + vtab->TestAxisFormat = TestAxisFormat; + vtab->TestAxisLabel = TestAxisLabel; + vtab->TestAxisSymbol = TestAxisSymbol; + vtab->TestAxisUnit = TestAxisUnit; + vtab->TestAxisInternalUnit = TestAxisInternalUnit; + vtab->TestAxisNormUnit = TestAxisNormUnit; + + vtab->ClearAxisTop = ClearAxisTop; + vtab->GetAxisTop = GetAxisTop; + vtab->SetAxisTop = SetAxisTop; + vtab->TestAxisTop = TestAxisTop; + + vtab->ClearAxisBottom = ClearAxisBottom; + vtab->GetAxisBottom = GetAxisBottom; + vtab->SetAxisBottom = SetAxisBottom; + vtab->TestAxisBottom = TestAxisBottom; + +/* Save the inherited pointers to methods that will be extended, and replace + them with pointers to the new member functions. */ + object = (AstObjectVtab *) vtab; + + parent_clearattrib = object->ClearAttrib; + parent_getobjsize = object->GetObjSize; + object->GetObjSize = GetObjSize; + object->ClearAttrib = ClearAttrib; + parent_getattrib = object->GetAttrib; + object->GetAttrib = GetAttrib; + parent_setattrib = object->SetAttrib; + object->SetAttrib = SetAttrib; + parent_testattrib = object->TestAttrib; + object->TestAttrib = TestAttrib; + +/* Declare the destructor, copy constructor and dump function. */ + astSetDelete( vtab, Delete ); + astSetCopy( vtab, Copy ); + astSetDump( vtab, Dump, "Axis", "Coordinate axis" ); + +/* 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 char *ParseAxisFormat( const char *fmt0, int digs, int *log, int *sign, + int *lspace, int *integ, int *status ){ +/* +* Name: +* ParseAxisFormat + +* Purpose: +* Parse the Format string for an Axis. + +* Type: +* Private function. + +* Synopsis: +* #include "axis.h" +* char *ParseAxisFormat( const char *fmt0, int digs, int *log, int *sign, +* int *lspace, int *integ, int *status ) + +* Class Membership: +* Axis member function + +* Description: +* This function returns a collection of flags indicating if any AST +* specific formatting features are specified in the supplied Format +* string. It also returns a pointer to a new Format string which is a +* standard C printf format specifier. + +* Parameters: +* fmt0 +* The value of the Format attribute. +* digs +* The default number of digits of precision to use. This is used +* if the given format specifier includes a wildcard precision (".*"). +* In this case, the returned format specifier will be modified to +* include an explicit precision value equal to the supplied value +* of "digs". +* log +* Pointer to an integer in which to store a flag indicating if the +* if the axis value should be formatted as "10**x" using the graphical +* escape sequences defined within the Plot class to produce "x" as a +* superscript of "10". A non-zero value will be returned if the +* supplied Format string has a '&' character in its printf <flags> +* field (that is, between the leading '%' sign and the optional +* printf field width). +* sign +* Pointer to an integer in which to store a flag indicating if a +* sign character ('+' or '-') should always be included in front +* of the "10" if "log" is returned non-zero. If "log" is returned +* zero, then "sign" will also be zero. If "log" is non-zero, then +* a non-zero value for "sign" will be returned if the supplied Format +* string has a '+' character in its printf <flags> field (that is, +* between the leading '%' sign and the optional printf field width). +* lspace +* Pointer to an integer in which to store a flag indicating if a +* leading space should be included in front of the "10" if "log" is +* returned non-zero and "sign" is returned zero. Otherwise, "lspace" +* will also be zero. If "log" is non-zero, then a non-zero value for +* "lspace" will be returned if the supplied Format string has a ' ' +* character in its printf <flags> field (that is, between the leading +* '%' sign and the optional printf field width). +* integ +* Pointer to an integer in which to store a flag indicating if the +* returned format specifier includes an integer conversion code +* (e.g. %d) or floating point conversion code (e.g. "%.7G"). +* status +* Pointer to the inherited status variable. + +* Returned Value: +* - Pointer to a dynamically allocated null-terminated string containing +* the modified Format string. This will be a copy of the supplied +* Format string, but with any '&' flag removed. Any '+' or ' ' flag will +* also be removed if "log" is returned as non-zero. An explicit +* precision field will be included if the supplied format includes a +* ".*" precision field. + +* 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: */ + char *a; /* Pointer to next char read from original format */ + char *b; /* Pointer to next char to write to new format */ + char *c; /* Pointer to next char read from original format */ + char *new; /* Pointer to new returned string */ + char *perc; /* Pointer to percent sign */ + char *result; /* Pointer to the returned string */ + int hash; /* Was a '#' flag found? */ + int len; /* Used length of format string */ + int minus; /* Was a '-' flag found? */ + int plus; /* Was a '+' flag found? */ + int rlen; /* Length of result */ + int space; /* Was a ' ' flag found? */ + +/* Initialise. */ + result = NULL; + *log = 0; + *sign = 0; + *lspace = 0; + *integ = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Take a copy of the supplied string. Check the pointer can be used + safely. */ + len = astChrLen( fmt0 ); + result = astStore( NULL, fmt0, len + 1 ); + if( astOK ) { + result[ len ] = 0; + +/* Find the first percent sign. Do nothing if none is found. */ + perc = strchr( result, '%' ); + if( perc ) { + +/* Check each character following the percent sign until one is found + which is not a legal printf flag, or a legal AST extension flag. Note + which ones are present. */ + minus = 0; + plus = 0; + space = 0; + hash = 0; + + a = perc; + while( ++a ){ + if( *a == '-' ){ + minus = 1; + } else if( *a == '+' ){ + plus = 1; + } else if( *a == ' ' ){ + space = 1; + } else if( *a == '#' ){ + hash = 1; + } else if( *a == '&' ){ + *log = 1; + } else { + break; + } + } + +/* If no '&' flag was found just return the unaltered copy of the + supplied Format string. Otherwise, remove any '+' or ' ' flag. */ + if( *log ) { + if( plus ) *sign = 1; + if( space ) *lspace = 1; + +/* Append any remaining flag characters to the output string. */ + perc++; + if( minus ) *(perc++) = '-'; + if( hash ) *(perc++) = '#'; + +/* Copy the remaining characters down to fill up the gap left by the + removed flags. */ + while( *a ) *(perc++) = *(a++); + +/* Terminate the returned string. */ + *perc = 0; + + } + } + } + +/* If the format specifier being returned does include a ".*" precision, + replace the "*" with the value of the Digits attribute. */ + if( result ) { + +/* Find the first percent sign. Do nothing if none is found. */ + a = strchr( result, '%' ); + if( a ) { + +/* Check each character following the percent sign until one is found + which is not a legal printf flag. */ + while( ++a ){ + if( *a != '-' && *a != '+' && *a != ' ' && *a != '#' ) break; + } + +/* Skip any field width (a decimal integer) following the flags. */ + a--; + while( ++a ) { + if( !isdigit( *a ) ) break; + } + +/* Get a pointer to the next alphabetic character. This will be the + conversion code. If it an integer code, return *integ non-zero. */ + c = a - 1; + while( ++c ) { + if( isalpha( *c ) ) { + if( *c == 'd' || *c == 'i' || *c == 'u' || *c == 'o' || + *c == 'x' || *c == 'X' || *c == 'c' ) *integ = 1; + break; + } + } + +/* Go back to the end of the field width. If the next two characters are + "." and "*", change the asterisk to the supplied "digs" value. */ + if( a[ 0 ] == '.' && a[ 1 ] == '*' ) { + +/* Allocate memory to hold the extended format string (allowing 20 + characters for formatting the digs value - just in case something like + INT_MAX is supplied by mistake), and store the existing string in it. */ + rlen = strlen( result ); + new = astMalloc( rlen + 22 ); + if( new ) memcpy( new, result, rlen + 1 ); + +/* Put the precision into the new string, following the field width. */ + b = new + ( a - result ); + b += sprintf( b, ".%d", digs ); + +/* Copy the remainder of the original format string to the new format + string. */ + if( a[ 2 ] != 0 ) strcpy( b, a + 2 ); + +/* Use the new format string in place of the old.*/ + astFree( result ); + result = new; + } + } + } + +/* Return the result. */ + return result; + +} + +static void SetAttrib( AstObject *this_object, const char *setting, int *status ) { +/* +* Name: +* SetAttrib + +* Purpose: +* Set an attribute value for an Axis. + +* Type: +* Private function. + +* Synopsis: +* #include "axis.h" +* void SetAttrib( AstObject *this, const char *setting, int *status ) + +* Class Membership: +* Axis member function (over-rides the protected astSetAttrib +* method inherited from the Object class). + +* Description: +* This function assigns an attribute value for an Axis, 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 Axis. +* setting +* Pointer to a null terminated string specifying the new +* attribute value. +* status +* Pointer to the inherited status variable. +*/ + +/* Local Variables: */ + AstAxis *this; /* Pointer to Axis structure */ + double dval; /* Double attribute value */ + int digits; /* Number of digits of precision */ + int direction; /* Plot axis in normal direction? */ + int format; /* Offset of Format string */ + int label; /* Offset of Label string */ + int len; /* Length of setting string */ + int nc; /* Number of characters read from setting */ + int symbol; /* Offset of Symbol string */ + int unit; /* Offset of Unit string */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Axis structure. */ + this = (AstAxis *) 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. */ + +/* Digits. */ +/* ------- */ + if ( nc = 0, + ( 1 == astSscanf( setting, "digits= %d %n", &digits, &nc ) ) + && ( nc >= len ) ) { + astSetAxisDigits( this, digits ); + +/* Direction. */ +/* ---------- */ + } else if ( nc = 0, + ( 1 == astSscanf( setting, "direction= %d %n", &direction, &nc ) ) + && ( nc >= len ) ) { + astSetAxisDirection( this, direction ); + +/* Top. */ +/* ---- */ + } else if ( nc = 0, + ( 1 == astSscanf( setting, "top= %lg %n", &dval, &nc ) ) + && ( nc >= len ) ) { + astSetAxisTop( this, dval ); + +/* Bottom. */ +/* ------- */ + } else if ( nc = 0, + ( 1 == astSscanf( setting, "bottom= %lg %n", &dval, &nc ) ) + && ( nc >= len ) ) { + astSetAxisBottom( this, dval ); + +/* Format. */ +/* ------- */ + } else if ( nc = 0, + ( 0 == astSscanf( setting, "format=%n%*[^\n]%n", &format, &nc ) ) + && ( nc >= len ) ) { + astSetAxisFormat( this, setting + format ); + +/* Label. */ +/* ------ */ + } else if ( nc = 0, + ( 0 == astSscanf( setting, "label=%n%*[^\n]%n", &label, &nc ) ) + && ( nc >= len ) ) { + astSetAxisLabel( this, setting + label ); + +/* Symbol. */ +/* ------- */ + } else if ( nc = 0, + ( 0 == astSscanf( setting, "symbol=%n%*[^\n]%n", &symbol, &nc ) ) + && ( nc >= len ) ) { + astSetAxisSymbol( this, setting + symbol ); + +/* Unit. */ +/* ----- */ + } else if ( nc = 0, + ( 0 == astSscanf( setting, "unit=%n%*[^\n]%n", &unit, &nc ) ) + && ( nc >= len ) ) { + astSetAxisUnit( this, setting + unit ); + +/* Read-only attributes. */ +/* --------------------- */ +/* Define a macro to see if the setting string matches any of the + read-only attributes of this class. */ +#define MATCH(attrib) \ + ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \ + ( nc >= len ) ) + +/* Use this macro to report an error if a read-only attribute has been + specified. */ + } else if ( MATCH( "normunit" ) || + MATCH( "internalunit" ) ) { + astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status, + setting, astGetClass( this ) ); + astError( AST__NOWRT, "This is a read-only attribute." , status); + +/* Pass any unrecognised attribute setting to the parent method for further + interpretation. */ + } else { + (*parent_setattrib)( this_object, setting, status ); + } + +/* Undefine macros local to this function. */ +#undef MATCH +} + +static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) { +/* +* Name: +* TestAttrib + +* Purpose: +* Test if a specified attribute value is set for an Axis. + +* Type: +* Private function. + +* Synopsis: +* #include "axis.h" +* int TestAttrib( AstObject *this, const char *attrib, int *status ) + +* Class Membership: +* Axis member function (over-rides the astTestAttrib protected +* method inherited from the Object class). + +* Description: +* This function returns a boolean result (0 or 1) to indicate +* whether a value has been set for one of an Axis' attributes. + +* Parameters: +* this +* Pointer to the Axis. +* 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: */ + AstAxis *this; /* Pointer to the Axis structure */ + int result; /* Result value to return */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the Axis structure. */ + this = (AstAxis *) this_object; + +/* Check the attribute name and test the appropriate attribute. */ + +/* Digits. */ +/* ------- */ + if ( !strcmp( attrib, "digits" ) ) { + result = astTestAxisDigits( this ); + +/* Direction. */ +/* ---------- */ + } else if ( !strcmp( attrib, "direction" ) ) { + result = astTestAxisDirection( this ); + +/* Top. */ +/* ---- */ + } else if ( !strcmp( attrib, "top" ) ) { + result = astTestAxisTop( this ); + +/* Bottom. */ +/* ------- */ + } else if ( !strcmp( attrib, "bottom" ) ) { + result = astTestAxisBottom( this ); + +/* Format. */ +/* ------- */ + } else if ( !strcmp( attrib, "format" ) ) { + result = astTestAxisFormat( this ); + +/* Label. */ +/* ------ */ + } else if ( !strcmp( attrib, "label" ) ) { + result = astTestAxisLabel( this ); + +/* Symbol. */ +/* ------- */ + } else if ( !strcmp( attrib, "symbol" ) ) { + result = astTestAxisSymbol( this ); + +/* Unit. */ +/* ----- */ + } else if ( !strcmp( attrib, "unit" ) ) { + result = astTestAxisUnit( this ); + +/* InternalUnit. */ +/* --------- */ + } else if ( !strcmp( attrib, "internalunit" ) ) { + result = astTestAxisInternalUnit( this ); + +/* NormUnit. */ +/* --------- */ + } else if ( !strcmp( attrib, "normunit" ) ) { + result = astTestAxisNormUnit( 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 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: +* Axis member function + +* 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 if and + only if a value has been set for Unit. */ + return astTestAxisUnit( this ); +} + +static int TestAxisNormUnit( AstAxis *this, int *status ){ +/* +* Name: +* TestAxisNormUnit + +* Purpose: +* Test if a NormUnit attribute value is set for an Axis. + +* Type: +* Private function. + +* Synopsis: +* #include "axis.h" +* int TestAxisNormUnit( AstAxis *this, int *status ) + +* Class Membership: +* Axis member function + +* Description: +* This function returns a boolean result (0 or 1) to indicate +* whether a value has been set for the NormUnit 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. +*/ + + return astTestAxisUnit( this ); +} + + +/* Functions which access class attributes. */ +/* ---------------------------------------- */ +/* Implement member functions to access the attributes associated with this + 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). */ + +/* Digits. */ +/* ------- */ +/* Clear the Digits value by setting it to -INT_MAX. */ +astMAKE_CLEAR(Axis,AxisDigits,digits,-INT_MAX) + +/* Supply a default of 7 digits if no value has been set. */ +astMAKE_GET(Axis,AxisDigits,int,0,( this->digits != -INT_MAX ? + this->digits : 7 )) + +/* Constrain the Digits value being set to be at least 1. */ +astMAKE_SET(Axis,AxisDigits,int,digits,( value > 1 ? value : 1 )) + +/* The Digits value is set if it is not -INT_MAX. */ +astMAKE_TEST(Axis,AxisDigits,( this->digits != -INT_MAX )) + +/* Direction. */ +/* ---------- */ +/* Clear the Direction value by setting it to -INT_MAX. */ +astMAKE_CLEAR(Axis,AxisDirection,direction,-INT_MAX) + +/* Supply a default value of 1 if the Direction value is not set. */ +astMAKE_GET(Axis,AxisDirection,int,0,( this->direction != -INT_MAX ? + this->direction : 1 )) + +/* Set a Direction value of 1 if any non-zero value is supplied. */ +astMAKE_SET(Axis,AxisDirection,int,direction,( value != 0 )) + +/* The Direction value is set if it is not -INT_MAX. */ +astMAKE_TEST(Axis,AxisDirection,( this->direction != -INT_MAX )) + +/* Top. */ +/* -----*/ +/* Clear the Top Direction value by setting it to AST__BAD. */ +astMAKE_CLEAR(Axis,AxisTop,top,AST__BAD) + +/* Supply a default value of DBL_MAX if the Top value is not set.*/ +astMAKE_GET(Axis,AxisTop,double,0,( this->top != AST__BAD ? this->top : DBL_MAX)) + +/* Set the Top value. */ +astMAKE_SET(Axis,AxisTop,double,top,(value)) + +/* The Top value is set if it is not AST__BAD. */ +astMAKE_TEST(Axis,AxisTop,( this->top != AST__BAD )) + +/* Bottom. */ +/* --------*/ +/* Clear the Bottom Direction value by setting it to AST__BAD. */ +astMAKE_CLEAR(Axis,AxisBottom,bottom,AST__BAD) + +/* Supply a default value of -DBL_MAX if the Bottom value is not set.*/ +astMAKE_GET(Axis,AxisBottom,double,0.0,( this->bottom != AST__BAD ? this->bottom : -DBL_MAX)) + +/* Set the Bottom value. */ +astMAKE_SET(Axis,AxisBottom,double,bottom,(value)) + +/* The Bottom value is set if it is not AST__BAD. */ +astMAKE_TEST(Axis,AxisBottom,( this->bottom != AST__BAD )) + +/* Format. */ +/* ------- */ +/* Clear the Format value by freeing the allocated memory and assigning a NULL + pointer. */ +astMAKE_CLEAR(Axis,AxisFormat,format,astFree( this->format )) + +/* If the Format value is not set, return a pointer to a default Format + string. */ +astMAKE_GET(Axis,AxisFormat,const char *,NULL,( this->format ? this->format : + GetDefaultFormat( this, status ) ) ) + +/* Set a Format value by freeing any previously allocated memory, allocating + new memory, storing the string and saving the pointer to the copy. */ +astMAKE_SET(Axis,AxisFormat,const char *,format,astStore( this->format, value, + strlen( value ) + (size_t) 1 )) + +/* The Format value is set if the pointer to it is not NULL. */ +astMAKE_TEST(Axis,AxisFormat,( this->format != NULL )) + +/* Label. */ +/* ------ */ +/* Clear the Label value by freeing the allocated memory and assigning a NULL + pointer. */ +astMAKE_CLEAR(Axis,AxisLabel,label,astFree( this->label )) + +/* If the Label value is not set, supply a default value by way of a pointer + to the constant string "Coordinate Axis". */ +astMAKE_GET(Axis,AxisLabel,const char *,NULL,( this->label ? this->label : + "Coordinate axis" )) + +/* Set a Label value by freeing any previously allocated memory, allocating + new memory, storing the string and saving the pointer to the copy. */ +astMAKE_SET(Axis,AxisLabel,const char *,label,astStore( this->label, value, + strlen( value ) + (size_t) 1 )) + +/* The Label value is set if the pointer to it is not NULL. */ +astMAKE_TEST(Axis,AxisLabel,( this->label != NULL )) + +/* Symbol. */ +/* ------- */ +/* Clear the Symbol value by freeing the allocated memory and assigning a NULL + pointer. */ +astMAKE_CLEAR(Axis,AxisSymbol,symbol,astFree( this->symbol )) + +/* If the Symbol value is not set, supply a default value by way of a pointer + to the constant string "x". */ +astMAKE_GET(Axis,AxisSymbol,const char *,NULL,( this->symbol ? this->symbol : + "x" )) + +/* Set a Symbol value by freeing any previously allocated memory, allocating + new memory, storing the string and saving the pointer to the copy. */ +astMAKE_SET(Axis,AxisSymbol,const char *,symbol,astStore( this->symbol, value, + strlen( value ) + (size_t) 1 )) + +/* The Symbol value is set if the pointer to it is not NULL. */ +astMAKE_TEST(Axis,AxisSymbol,( this->symbol != NULL )) + +/* Unit. */ +/* ----- */ +/* Clear the Unit value by freeing the allocated memory and assigning a NULL + pointer. */ +astMAKE_CLEAR(Axis,AxisUnit,unit,astFree( this->unit )) + +/* If the Unit value is not set, supply a default value by way of a pointer + to the constant string "". */ +astMAKE_GET(Axis,AxisUnit,const char *,NULL,( this->unit ? this->unit : "" )) + +/* Set a Unit value by freeing any previously allocated memory, allocating + new memory, storing the string and saving the pointer to the copy. */ +astMAKE_SET(Axis,AxisUnit,const char *,unit,astStore( this->unit, value, + strlen( value ) + (size_t) 1 )) + +/* The Unit value is set if the pointer to it is not NULL. */ +astMAKE_TEST(Axis,AxisUnit,( this->unit != NULL )) + +/* Copy constructor. */ +/* ----------------- */ +static void Copy( const AstObject *objin, AstObject *objout, int *status ) { +/* +* Name: +* Copy + +* Purpose: +* Copy constructor for Axis objects. + +* Type: +* Private function. + +* Synopsis: +* void Copy( const AstObject *objin, AstObject *objout, int *status ) + +* Description: +* This function implements the copy constructor for Axis 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: */ + AstAxis *in; /* Pointer to input Axis */ + AstAxis *out; /* Pointer to output Axis */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain pointers to the input and output Axis structures. */ + in = (AstAxis *) objin; + out = (AstAxis *) objout; + +/* For safety, first clear any references to the input memory from + the output Axis. */ + out->format = NULL; + out->label = NULL; + out->symbol = NULL; + out->unit = NULL; + +/* Make copies of the allocated strings and Objects. */ + if ( in->label ) out->label = astStore( NULL, in->label, + strlen( in->label ) + (size_t) 1 ); + if ( in->format ) out->format = astStore( NULL, in->format, + strlen( in->format ) + (size_t) 1 ); + if ( in->symbol ) out->symbol = astStore( NULL, in->symbol, + strlen( in->symbol ) + (size_t) 1 ); + if ( in->unit ) out->unit = astStore( NULL, in->unit, + strlen( in->unit ) + (size_t) 1 ); + +/* If an error occurred, clean up by freeing all memory allocated above. */ + if ( !astOK ) { + out->format = astFree( out->format ); + out->label = astFree( out->label ); + out->symbol = astFree( out->symbol ); + out->unit = astFree( out->unit ); + } +} + +/* Destructor. */ +/* ----------- */ +static void Delete( AstObject *obj, int *status ) { +/* +* Name: +* Delete + +* Purpose: +* Destructor for Axis objects. + +* Type: +* Private function. + +* Synopsis: +* void Delete( AstObject *obj, int *status ) + +* Description: +* This function implements the destructor for Axis 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: */ + AstAxis *this; /* Pointer to Axis */ + +/* Obtain a pointer to the Axis structure. */ + this = (AstAxis *) obj; + +/* Free all allocated memory. */ + this->format = astFree( this->format ); + this->label = astFree( this->label ); + this->symbol = astFree( this->symbol ); + this->unit = astFree( this->unit ); +} + +/* Dump function. */ +/* -------------- */ +static void Dump( AstObject *this_object, AstChannel *channel, int *status ) { +/* +* Name: +* Dump + +* Purpose: +* Dump function for Axis 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 Axis class to an output Channel. + +* Parameters: +* this +* Pointer to the Axis 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; /* Pointer to the Axis structure */ + char comment[ 80 ]; /* Buffer for comment string */ + const char *sval; /* Pointer to string value */ + const char *lab; /* Pointer to unit label */ + double dval; /* Double value */ + int ival; /* Integer value */ + int set; /* Attribute value set? */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Axis structure. */ + this = (AstAxis *) this_object; + +/* Write out values representing the instance variables for the + Axis 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. */ + +/* Label. */ +/* ------ */ + set = TestAxisLabel( this, status ); + sval = set ? GetAxisLabel( this, status ) : astGetAxisLabel( this ); + astWriteString( channel, "Label", set, 1, sval, "Axis Label" ); + +/* Symbol. */ +/* ------- */ + set = TestAxisSymbol( this, status ); + sval = set ? GetAxisSymbol( this, status ) : astGetAxisSymbol( this ); + astWriteString( channel, "Symbol", set, 1, sval, "Axis symbol" ); + +/* Unit. */ +/* ----- */ + set = TestAxisUnit( this, status ); + sval = set ? GetAxisUnit( this, status ) : astGetAxisUnit( this ); + +/* Get any label associated with the unit string. */ + lab = astUnitLabel( sval ); + +/* Construct a comment including the above label (but only if it is not + the same as the unit string) . */ + if( lab && strcmp( lab, sval ) ) { + (void) sprintf( comment, "Axis units (%s)", lab ); + } else { + (void) sprintf( comment, "Axis units" ); + } + +/* Write out the Unit value. */ + astWriteString( channel, "Unit", set, 0, sval, comment ); + +/* Digits. */ +/* ------- */ + set = TestAxisDigits( this, status ); + ival = set ? GetAxisDigits( this, status ) : astGetAxisDigits( this ); + astWriteInt( channel, "Digits", set, 0, ival, + "Default formatting precision" ); + +/* Format. */ +/* ------- */ + set = TestAxisFormat( this, status ); + sval = set ? GetAxisFormat( this, status ) : astGetAxisFormat( this ); + astWriteString( channel, "Format", set, 0, sval, "Format specifier" ); + +/* Direction. */ +/* ---------- */ + set = TestAxisDirection( this, status ); + ival = set ? GetAxisDirection( this, status ) : astGetAxisDirection( this ); + astWriteInt( channel, "Dirn", set, 0, ival, + ival ? "Plot in conventional direction (hint)" : + "Plot in reverse direction (hint)" ); +/* Top. */ +/* ---- */ + set = TestAxisTop( this, status ); + dval = set ? GetAxisTop( this, status ) : astGetAxisTop( this ); + astWriteDouble( channel, "Top", set, 0, dval, "Maximum legal axis value" ); + +/* Bottom. */ +/* ------- */ + set = TestAxisBottom( this, status ); + dval = set ? GetAxisBottom( this, status ) : astGetAxisBottom( this ); + astWriteDouble( channel, "Bottom", set, 0, dval, "Minimum legal axis value" ); +} + +/* Standard class functions. */ +/* ========================= */ +/* Implement the astIsAAxis and astCheckAxis functions using the macros + defined for this purpose in the "object.h" header file. */ +astMAKE_ISA(Axis,Object) +astMAKE_CHECK(Axis) + +AstAxis *astAxis_( const char *options, int *status, ...) { +/* +*+ +* Name: +* astAxis + +* Purpose: +* Create an Axis. + +* Type: +* Public function. + +* Synopsis: +* #include "axis.h" +* AstAxis *astAxis( const char *options, int *status, ... ) + +* Class Membership: +* Axis constructor. + +* Description: +* This function creates a new Axis 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 Axis. 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 Axis. + +* 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 */ + AstAxis *new; /* Pointer to new Axis */ + 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 Axis, allocating memory and initialising the virtual + function table as well if necessary. */ + new = astInitAxis( NULL, sizeof( AstAxis ), !class_init, &class_vtab, + "Axis" ); + +/* 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 Axis' + 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 Axis. */ + return new; +} + +AstAxis *astAxisId_( const char *options, ... ) { +/* +* Name: +* astAxisId_ + +* Purpose: +* Create an Axis. + +* Type: +* Private function. + +* Synopsis: +* #include "axis.h" +* AstAxis *astAxisId_( const char *options, ... ); + +* Class Membership: +* Axis constructor. + +* Description: +* This function implements the external (public) interface to the +* astAxis constructor function. It returns an ID value (instead of +* a true C pointer) to external users, and must be provided +* because astAxis_ 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 astAxis_ 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 astAxis_. + +* Returned Value: +* The ID value associated with the new Axis. +*/ + +/* Local Variables: */ + astDECLARE_GLOBALS /* Pointer to thread-specific global data */ + AstAxis *new; /* Pointer to new Axis */ + 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 Axis, allocating memory and initialising the virtual + function table as well if necessary. */ + new = astInitAxis( NULL, sizeof( AstAxis ), !class_init, &class_vtab, + "Axis" ); + +/* 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 Axis' + 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 Axis. */ + return astMakeId( new ); +} + +AstAxis *astInitAxis_( void *mem, size_t size, int init, + AstAxisVtab *vtab, const char *name, int *status ) { +/* +*+ +* Name: +* astInitAxis + +* Purpose: +* Initialise an Axis. + +* Type: +* Protected function. + +* Synopsis: +* #include "axis.h" +* AstAxis *astInitAxis( void *mem, size_t size, int init, +* AstAxisVtab *vtab, const char *name ) + +* Class Membership: +* Axis initialiser. + +* Description: +* This function is provided for use by class implementations to initialise +* a new Axis object. It allocates memory (if necessary) to accommodate +* the Axis plus any additional data associated with the derived class. +* It then initialises an Axis structure at the start of this memory. If +* the "init" flag is set, it also initialises the contents of a virtual +* function table for an Axis at the start of the memory passed via the +* "vtab" parameter. + +* Parameters: +* mem +* A pointer to the memory in which the Axis is to be created. This +* must be of sufficient size to accommodate the Axis data +* (sizeof(Axis)) 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 Axis (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 Axis +* structure, so a valid value must be supplied even if not required for +* allocating memory. +* init +* A logical flag indicating if the Axis'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 Axis. +* 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 Axis. + +* Notes: +* - A NULL pointer will be returned if this function is invoked with the +* global error status set, or if it should fail for any reason. +*- +*/ + +/* Local Variables: */ + AstAxis *new; /* Pointer to new Axis */ + +/* Check the global status. */ + if ( !astOK ) return NULL; + +/* If necessary, initialise the virtual function table. */ + if ( init ) astInitAxisVtab( vtab, name ); + +/* Initialise an Object structure (the parent class) as the first component + within the Axis structure, allocating memory if necessary. */ + new = (AstAxis *) astInitObject( mem, size, 0, (AstObjectVtab *) vtab, + name ); + + if ( astOK ) { + +/* Initialise the Axis data. */ +/* ------------------------- */ +/* Initialise all attributes to their "undefined" values. */ + new->digits = -INT_MAX; + new->direction = -INT_MAX; + new->format = NULL; + new->label = NULL; + new->symbol = NULL; + new->unit = NULL; + new->top = AST__BAD; + new->bottom = AST__BAD; + +/* If an error occurred, clean up by deleting the new Axis. */ + if ( !astOK ) new = astDelete( new ); + } + +/* Return a pointer to the new Axis. */ + return new; +} + +AstAxis *astLoadAxis_( void *mem, size_t size, + AstAxisVtab *vtab, const char *name, + AstChannel *channel, int *status ) { +/* +*+ +* Name: +* astLoadAxis + +* Purpose: +* Load an Axis. + +* Type: +* Protected function. + +* Synopsis: +* #include "axis.h" +* AstAxis *astLoadAxis( void *mem, size_t size, +* AstAxisVtab *vtab, const char *name, +* AstChannel *channel ) + +* Class Membership: +* Axis loader. + +* Description: +* This function is provided to load a new Axis 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 +* Axis 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 Axis at the start of the memory +* passed via the "vtab" parameter. + + +* Parameters: +* mem +* A pointer to the memory into which the Axis is to be +* loaded. This must be of sufficient size to accommodate the +* Axis data (sizeof(Axis)) 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 Axis (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 Axis 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(AstAxis) is used instead. +* vtab +* Pointer to the start of the virtual function table to be +* associated with the new Axis. If this is NULL, a pointer +* to the (static) virtual function table for the Axis 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 "Axis" is used instead. + +* Returned Value: +* A pointer to the new Axis. + +* 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 */ + AstAxis *new; /* Pointer to the new Axis */ + +/* 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 Axis. In this case the + Axis belongs to this class, so supply appropriate values to be + passed to the parent class loader (and its parent, etc.). */ + if ( !vtab ) { + size = sizeof( AstAxis ); + vtab = &class_vtab; + name = "Axis"; + +/* If required, initialise the virtual function table for this class. */ + if ( !class_init ) { + astInitAxisVtab( 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 Axis. */ + new = astLoadObject( mem, size, (AstObjectVtab *) 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, "Axis" ); + +/* 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. */ + +/* Label. */ +/* ------ */ +/* Note that string values do not require any additional processing. */ + new->label = astReadString( channel, "label", NULL ); + +/* Symbol. */ +/* ------- */ + new->symbol = astReadString( channel, "symbol", NULL ); + +/* Unit. */ +/* ----- */ + new->unit = astReadString( channel, "unit", NULL ); + +/* Digits. */ +/* ------- */ + new->digits = astReadInt( channel, "digits", -INT_MAX ); + if ( TestAxisDigits( new, status ) ) SetAxisDigits( new, new->digits, status ); + +/* Format. */ +/* ------- */ + new->format = astReadString( channel, "format", NULL ); + +/* Direction. */ +/* ---------- */ + new->direction = astReadInt( channel, "dirn", -INT_MAX ); + if ( TestAxisDirection( new, status ) ) SetAxisDirection( new, new->direction, status ); + +/* Top. */ +/* ---- */ + new->top = astReadDouble( channel, "top", AST__BAD ); + if ( TestAxisTop( new, status ) ) SetAxisTop( new, new->top, status ); + +/* Bottom. */ +/* ---- */ + new->bottom = astReadDouble( channel, "bottom", AST__BAD ); + if ( TestAxisBottom( new, status ) ) SetAxisBottom( new, new->bottom, status ); + +/* If an error occurred, clean up by deleting the new Axis. */ + if ( !astOK ) new = astDelete( new ); + } + +/* Return the new Axis 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. */ + +/* External interfaces for the attribute access functions are generated + automatically by the macros that implement the access functions themselves. + Hence, we need only provide external interfaces for a few additional + functions here. */ +const char *astAxisAbbrev_( AstAxis *this, const char *fmt, + const char *str1, const char *str2, int *status ) { + if ( !astOK ) return str2; + return (**astMEMBER(this,Axis,AxisAbbrev))( this, fmt, str1, str2, status ); +} +const char *astAxisFormat_( AstAxis *this, double value, int *status ) { + if ( !astOK ) return NULL; + return (**astMEMBER(this,Axis,AxisFormat))( this, value, status ); +} +double astAxisDistance_( AstAxis *this, double v1, double v2, int *status ) { + if ( !astOK ) return AST__BAD; + return (**astMEMBER(this,Axis,AxisDistance))( this, v1, v2, status ); +} +double astAxisOffset_( AstAxis *this, double v1, double dist, int *status ) { + if ( !astOK ) return AST__BAD; + return (**astMEMBER(this,Axis,AxisOffset))( this, v1, dist, status ); +} +double astAxisCentre_( AstAxis *this, double value, double gap, int *status ) { + if ( !astOK ) return 0.0; + return (**astMEMBER(this,Axis,AxisCentre))( this, value, gap, status ); +} +double astAxisGap_( AstAxis *this, double gap, int *ntick, int *status ) { + if ( !astOK ) return 0.0; + return (**astMEMBER(this,Axis,AxisGap))( this, gap, ntick, status ); +} +void astAxisNorm_( AstAxis *this, double *value, int *status ) { + if ( !astOK ) return; + (**astMEMBER(this,Axis,AxisNorm))( this, value, status ); +} +void astAxisOverlay_( AstAxis *template, AstAxis *result, int *status ) { + if ( !astOK ) return; + (**astMEMBER(template,Axis,AxisOverlay))( template, result, status ); +} +int astAxisUnformat_( AstAxis *this, const char *string, double *value, int *status ) { + if ( !astOK ) return 0; + return (**astMEMBER(this,Axis,AxisUnformat))( this, string, value, status ); +} +int astAxisFields_( AstAxis *this, const char *fmt, const char *str, + int maxfld, char **fields, int *nc, double *val, int *status ) { + if ( !astOK ) return 0; + return (**astMEMBER(this,Axis,AxisFields))( this, fmt, str, maxfld, fields, nc, val, status ); +} +int astAxisIn_( AstAxis *this, double lo, double hi, double val, int closed, int *status ){ + if ( !astOK ) return 0; + return (**astMEMBER(this,Axis,AxisIn))( this, lo, hi, val, closed, status ); +} +const char *astGetAxisNormUnit_( AstAxis *this, int *status ) { + if ( !astOK ) return NULL; + return (**astMEMBER(this,Axis,GetAxisNormUnit))( this, status ); +} +int astTestAxisNormUnit_( AstAxis *this, int *status ) { + if ( !astOK ) return 0; + return (**astMEMBER(this,Axis,TestAxisNormUnit))( this, status ); +} +const char *astGetAxisInternalUnit_( AstAxis *this, int *status ) { + if ( !astOK ) return NULL; + return (**astMEMBER(this,Axis,GetAxisInternalUnit))( this, status ); +} +int astTestAxisInternalUnit_( AstAxis *this, int *status ) { + if ( !astOK ) return 0; + return (**astMEMBER(this,Axis,TestAxisInternalUnit))( this, status ); +} +void astAxisNormValues_( AstAxis *this, int oper, int nval, double *values, + int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Axis,AxisNormValues))( this, oper, nval, values, status ); +} + + + + + + |