1 /*
2 *class++
3 * Name:
4 * Axis
5
6 * Purpose:
7 * Store axis information.
8
9 * Constructor Function:
10 * None.
11
12 * Description:
13 * The Axis class is used to store information associated with a
14 * particular axis of a Frame. It is used internally by the AST
15 * library and has no constructor function. You should encounter it
16 c only within textual output (e.g. from astWrite).
17 f only within textual output (e.g. from AST_WRITE).
18
19 * Inheritance:
20 * The Axis class inherits from the Object class.
21
22 * Copyright:
23 * Copyright (C) 1997-2006 Council for the Central Laboratory of the
24 * Research Councils
25
26 * Licence:
27 * This program is free software: you can redistribute it and/or
28 * modify it under the terms of the GNU Lesser General Public
29 * License as published by the Free Software Foundation, either
30 * version 3 of the License, or (at your option) any later
31 * version.
32 *
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU Lesser General Public License for more details.
37 *
38 * You should have received a copy of the GNU Lesser General
39 * License along with this program. If not, see
40 * <http://www.gnu.org/licenses/>.
41
42 * Authors:
43 * RFWS: R.F. Warren-Smith (Starlink)
44 * DSB: B.S. Berry (Starlink)
45
46 * History:
47 * 1-MAR-1996 (RFWS):
48 * Original version.
49 * 10-SEP-1996 (RFWS):
50 * Added I/O facilities.
51 * 11-SEP-1996 (RFWS):
52 * Added astAxisGap (written by DSB).
53 * 25-FEB-1998 (RFWS):
54 * Added astAxisUnformat.
55 * 29-AUG-2001 (DSB):
56 * Added AxisDistance and AxisOffset.
57 * 20-OCT-2002 (DSB):
58 * Added Top and Bottom attributes.
59 * 8-JAN-2003 (DSB):
60 * - Changed private InitVtab method to protected astInitAxisVtab
61 * method.
62 * - Include descriptive label for units string within a Dump.
63 * 24-JAN-2004 (DSB):
64 * - Added astAxisFields.
65 * - Added argument "fmt" to definition of AxisAbbrev.
66 * 3-FEB-2004 (DSB):
67 * - Added "log" formatting using the "&" flag character in the
68 * Format string.
69 * 15-SEP-2004 (DSB):
70 * - If a format string is set which includes a wildcard precision
71 * value (".*"), then use the Digits value to determine the precision
72 * to be used.
73 * - If the conversion code is of integer type (e.g. "%d") cast value
74 * to integer before printing.
75 * 2-FEB-2005 (DSB):
76 * - Avoid using astStore to allocate more storage than is supplied
77 * in the "data" pointer. This can cause access violations since
78 * astStore will then read beyond the end of the "data" area.
79 * 15-MAR-2005 (DSB):
80 * - Avoid exponents in log format labels which are close to zero but
81 * not quite zero.
82 * 14-FEB-2006 (DSB):
83 * Override astGetObjSize.
84 * 30-JUN-2006 (DSB):
85 * Guard against a null "str1" value in AxisAbbrev.
86 *class--
87 */
88
89 /* Module Macros. */
90 /* ============== */
91 /* Set the name of the class we are implementing. This indicates to
92 the header files that define class interfaces that they should make
93 "protected" symbols available. */
94 #define astCLASS Axis
95
96
97 /* Header files. */
98 /* ============= */
99 #include "ast_err.h" /* Error code definitions */
100
101 /* Interface definitions. */
102 /* ---------------------- */
103
104 #include "globals.h" /* Thread-safe global data access */
105 #include "error.h" /* Error reporting facilities */
106 #include "memory.h" /* Memory allocation facilities */
107 #include "object.h" /* Object interface (parent class) */
108 #include "pointset.h" /* Sets of coordinates (for AST__BAD) */
109 #include "channel.h" /* I/O channels */
110 #include "axis.h" /* Interface definition for this class */
111 #include "unit.h" /* Definitions of physical units */
112 #include "globals.h" /* Thread-safe global data access */
113
114 /* C header files. */
115 /* --------------- */
116 #include <ctype.h>
117 #include <errno.h>
118 #include <float.h>
119 #include <limits.h>
120 #include <math.h>
121 #include <stdarg.h>
122 #include <stddef.h>
123 #include <stdio.h>
124 #include <stdlib.h>
125 #include <string.h>
126
127 /* Module Variables. */
128 /* ================= */
129
130 /* Address of this static variable is used as a unique identifier for
131 member of this class. */
132 static int class_check;
133
134 /* Pointers to parent class methods which are extended by this class. */
135 static int (* parent_getobjsize)( AstObject *, int * );
136 static const char *(* parent_getattrib)( AstObject *, const char *, int * );
137 static int (* parent_testattrib)( AstObject *, const char *, int * );
138 static void (* parent_clearattrib)( AstObject *, const char *, int * );
139 static void (* parent_setattrib)( AstObject *, const char *, int * );
140
141 /* Plain text equivalents. */
142 static const char *log_txt = "10^";
143
144 /* Define macros for accessing each item of thread specific global data. */
145 #ifdef THREAD_SAFE
146
147 /* Define how to initialise thread-specific globals. */
148 #define GLOBAL_inits \
149 globals->Class_Init = 0; \
150 globals->GetDefaultFormat_Buff[ 0 ] = 0; \
151 globals->AxisFormat_Buff[ 0 ] = 0; \
152 globals->GetAxisNormUnit_Buff[ 0 ] = 0; \
153 globals->GetAttrib_Buff[ 0 ] = 0;
154
155 /* Create the function that initialises global data for this module. */
156 astMAKE_INITGLOBALS(Axis)
157
158 /* Define macros for accessing each item of thread specific global data. */
159 #define class_init astGLOBAL(Axis,Class_Init)
160 #define class_vtab astGLOBAL(Axis,Class_Vtab)
161 #define getdefaultformat_buff astGLOBAL(Axis,GetDefaultFormat_Buff)
162 #define axisformat_buff astGLOBAL(Axis,AxisFormat_Buff)
163 #define getaxisnormunit_buff astGLOBAL(Axis,GetAxisNormUnit_Buff)
164 #define getattrib_buff astGLOBAL(Axis,GetAttrib_Buff)
165
166
167
168 /* If thread safety is not needed, declare and initialise globals at static
169 variables. */
170 #else
171
172 static char getdefaultformat_buff[ AST__AXIS_GETDEFAULTFORMAT_BUFF_LEN + 1 ];
173 static char axisformat_buff[ AST__AXIS_GETDEFAULTFORMAT_BUFF_LEN + 1 ];
174 static char getaxisnormunit_buff[ AST__AXIS_GETAXISNORMUNIT_BUFF_LEN + 1 ];
175 static char getattrib_buff[ AST__AXIS_GETATTRIB_BUFF_LEN + 1 ];
176
177
178 /* Define the class virtual function table and its initialisation flag
179 as static variables. */
180 static AstAxisVtab class_vtab; /* Virtual function table */
181 static int class_init = 0; /* Virtual function table initialised? */
182
183 #endif
184
185 /* External Interface Function Prototypes. */
186 /* ======================================= */
187 /* The following functions have public prototypes only (i.e. no
188 protected prototypes), so we must provide local prototypes for use
189 within this module. */
190 AstAxis *astAxisId_( const char *, ... );
191
192 /* Prototypes for Private Member Functions. */
193 /* ======================================== */
194 static const char *AxisAbbrev( AstAxis *, const char *, const char *, const char *, int * );
195 static const char *AxisFormat( AstAxis *, double, int * );
196 static int GetObjSize( AstObject *, int * );
197 static const char *GetAttrib( AstObject *, const char *, int * );
198 static const char *GetAxisFormat( AstAxis *, int * );
199 static const char *GetAxisLabel( AstAxis *, int * );
200 static const char *GetAxisSymbol( AstAxis *, int * );
201 static const char *GetAxisUnit( AstAxis *, int * );
202 static const char *GetAxisNormUnit( AstAxis *, int * );
203 static const char *GetDefaultFormat( AstAxis *, int * );
204 static char *ParseAxisFormat( const char *, int, int *, int *, int *, int *, int * );
205 static double AxisDistance( AstAxis *, double, double, int * );
206 static double AxisGap( AstAxis *, double, int *, int * );
207 static double AxisOffset( AstAxis *, double, double, int * );
208 static int AxisFields( AstAxis *, const char *, const char *, int, char **, int *, double *, int * );
209 static int AxisIn( AstAxis *, double, double, double, int, int * );
210 static int AxisUnformat( AstAxis *, const char *, double *, int * );
211 static int GetAxisDigits( AstAxis *, int * );
212 static int GetAxisDirection( AstAxis *, int * );
213 static int TestAttrib( AstObject *, const char *, int * );
214 static int TestAxisDigits( AstAxis *, int * );
215 static int TestAxisDirection( AstAxis *, int * );
216 static int TestAxisFormat( AstAxis *, int * );
217 static int TestAxisLabel( AstAxis *, int * );
218 static int TestAxisSymbol( AstAxis *, int * );
219 static int TestAxisUnit( AstAxis *, int * );
220 static int TestAxisNormUnit( AstAxis *, int * );
221 static void AxisNorm( AstAxis *, double *, int * );
222 static void AxisOverlay( AstAxis *, AstAxis *, int * );
223 static void ClearAttrib( AstObject *, const char *, int * );
224 static void ClearAxisDigits( AstAxis *, int * );
225 static void ClearAxisDirection( AstAxis *, int * );
226 static void ClearAxisFormat( AstAxis *, int * );
227 static void ClearAxisLabel( AstAxis *, int * );
228 static void ClearAxisSymbol( AstAxis *, int * );
229 static void ClearAxisUnit( AstAxis *, int * );
230 static void Copy( const AstObject *, AstObject *, int * );
231 static void Delete( AstObject *, int * );
232 static void Dump( AstObject *, AstChannel *, int * );
233 static void SetAttrib( AstObject *, const char *, int * );
234 static void SetAxisDigits( AstAxis *, int, int * );
235 static void SetAxisDirection( AstAxis *, int, int * );
236 static void SetAxisFormat( AstAxis *, const char *, int * );
237 static void SetAxisLabel( AstAxis *, const char *, int * );
238 static void SetAxisSymbol( AstAxis *, const char *, int * );
239 static void SetAxisUnit( AstAxis *, const char *, int * );
240
241 static double GetAxisTop( AstAxis *, int * );
242 static int TestAxisTop( AstAxis *, int * );
243 static void ClearAxisTop( AstAxis *, int * );
244 static void SetAxisTop( AstAxis *, double, int * );
245
246 static double GetAxisBottom( AstAxis *, int * );
247 static int TestAxisBottom( AstAxis *, int * );
248 static void ClearAxisBottom( AstAxis *, int * );
249 static void SetAxisBottom( AstAxis *, double, int * );
250
251
252 /* Member functions. */
253 /* ================= */
AxisAbbrev(AstAxis * this,const char * fmt,const char * str1,const char * str2,int * status)254 static const char *AxisAbbrev( AstAxis *this, const char *fmt,
255 const char *str1, const char *str2, int *status ) {
256 /*
257 *+
258 * Name:
259 * astAxisAbbrev
260
261 * Purpose:
262 * Abbreviate a formatted Axis value by skipping leading fields.
263
264 * Type:
265 * Protected virtual function.
266
267 * Synopsis:
268 * #include "axis.h"
269 * const char *astAxisAbbrev( AstAxis *this, const char *fmt,
270 * const char *str1, const char *str2 )
271
272 * Class Membership:
273 * Axis method.
274
275 * Description:
276 * This function compares two Axis values that have been formatted
277 * (using astAxisFormat) and determines if they have any redundant
278 * leading fields (i.e. leading fields in common which can be
279 * suppressed when tabulating the values or plotting them on the
280 * axis of a graph).
281
282 * Parameters:
283 * this
284 * Pointer to the Axis.
285 * fmt
286 * Pointer to a constant null-terminated string containing the
287 * format specifier used to format the two values.
288 * str1
289 * Pointer to a constant null-terminated string containing the
290 * first formatted value. If this is null, the returned pointer
291 * points to the start of the final field in str2.
292 * str2
293 * Pointer to a constant null-terminated string containing the
294 * second formatted value.
295
296 * Returned Value:
297 * A pointer into the "str2" string which locates the first
298 * character in the first field that differs between the two
299 * formatted values.
300 *
301 * If the two values have no leading fields in common, the returned
302 * value will point at the start of string "str2". If the two
303 * values are equal, it will point at the terminating null at the
304 * end of this string.
305
306 * Notes:
307 * - This function assumes that the format specification used was
308 * the same when both values were formatted.
309 * - A pointer to the start of "str2" will be returned if this
310 * function is invoked with the global error status set, or if it
311 * should fail for any reason.
312 *-
313 */
314
315 /* Local Variables: */
316 const char *result; /* Result pointer to return */
317
318 /* Initialise. */
319 result = str2;
320
321 /* Check the global error status. */
322 if ( !astOK ) return result;
323
324 /* In the Axis class, there is only one field in a formatted value.
325 We return the value of "str2", unless the two strings are
326 identical, in which case we return a pointer to the final null in
327 "str2". */
328 if( str1 && !strcmp( str1, str2 ) ) result += strlen( str2 );
329
330 /* Return the result. */
331 return result;
332 }
333
AxisDistance(AstAxis * this,double v1,double v2,int * status)334 static double AxisDistance( AstAxis *this, double v1, double v2, int *status ) {
335 /*
336 *+
337 * Name:
338 * astAxisDistance
339
340 * Purpose:
341 * Find the distance between two axis values.
342
343 * Type:
344 * Protected virtual function.
345
346 * Synopsis:
347 * #include "axis.h"
348 * AxisDistance( AstAxis *this, double v1, double v2 )
349
350 * Class Membership:
351 * Axis method.
352
353 * Description:
354 * This function returns a signed value representing the axis increment
355 * from axis value v1 to axis value v2.
356 *
357 * For a simple Axis, this is a trivial operation. But for other
358 * derived classes of Axis (such as a SkyAxis) this is not the case.
359
360 * Parameters:
361 * this
362 * Pointer to the Axis.
363 * v1
364 * The first axis value
365 * v2
366 * The second axis value
367
368 * Returned Value:
369 * The axis increment from v1 to v2.
370
371 * Notes:
372 * - A value of AST__BAD is returned if either axis value is AST__BAD.
373 * - A value of AST__BAD will be returned if this function is invoked
374 * with the global error status set, or if it should fail for any
375 * reason.
376 *-
377 */
378
379 /* Local Variables: */
380 double result; /* Returned gap size */
381
382 /* Initialise. */
383 result = AST__BAD;
384
385 /* Check the global error status. */
386 if ( !astOK ) return result;
387
388 /* Check both axis values are OK, and form the returned increment. */
389 if( v1 != AST__BAD && v2 != AST__BAD ) result = v2 - v1;
390
391 /* Return the result. */
392 return result;
393 }
394
AxisFields(AstAxis * this,const char * fmt0,const char * str,int maxfld,char ** fields,int * nc,double * val,int * status)395 static int AxisFields( AstAxis *this, const char *fmt0, const char *str,
396 int maxfld, char **fields, int *nc, double *val, int *status ) {
397 /*
398 *+
399 * Name:
400 * astAxisFields
401
402 * Purpose:
403 * Identify numerical fields within a formatted Axis value.
404
405 * Type:
406 * Protected virtual function.
407
408 * Synopsis:
409 * #include "axis.h"
410 * int astAxisFields( AstAxis *this, const char *fmt0, const char *str,
411 * int maxfld, char **fields, int *nc, double *val )
412
413 * Class Membership:
414 * Axis member function.
415
416 * Description:
417 * This function identifies the numerical fields within an Axis value
418 * that have been formatted using astAxisFormat. It assumes that the
419 * value was formatted using the supplied format string. It also
420 * returns the equivalent floating point value.
421
422 * Parameters:
423 * this
424 * Pointer to the Axis.
425 * fmt0
426 * Pointer to a constant null-terminated string containing the
427 * format used when creating "str".
428 * str
429 * Pointer to a constant null-terminated string containing the
430 * formatted value.
431 * maxfld
432 * The maximum number of fields to identify within "str".
433 * fields
434 * A pointer to an array of at least "maxfld" character pointers.
435 * Each element is returned holding a pointer to the start of the
436 * corresponding field in "str" (in the order in which they occur
437 * within "str"), or NULL if no corresponding field can be found.
438 * nc
439 * A pointer to an array of at least "maxfld" integers. Each
440 * element is returned holding the number of characters in the
441 * corresponding field, or zero if no corresponding field can be
442 * found.
443 * val
444 * Pointer to a location at which to store the value
445 * equivalent to the returned field values. If this is NULL,
446 * it is ignored.
447
448 * Returned Value:
449 * The number of fields succesfully identified and returned.
450
451 * Notes:
452 * - Leading and trailing spaces are ignored.
453 * - If the formatted value is not consistent with the supplied format
454 * string, then a value of zero will be returned, "fields" will be
455 * returned holding NULLs, "nc" will be returned holding zeros, and
456 * "val" is returned holding VAL__BAD.
457 * - Fields are counted from the start of the formatted string. If the
458 * string contains more than "maxfld" fields, then trailing fields are
459 * ignored.
460 * - If this function is invoked with the global error status set, or
461 * if it should fail for any reason, then a value of zero will be returned
462 * as the function value, and "fields", "nc" and "val" will be returned
463 * holding their supplied values
464 *-
465 */
466
467 /* Local Variables: */
468 char log_esc[ 50 ]; /* Buffer for graphical delimiter string */
469 const char *fmt; /* Pointer to parsed Format string */
470 const char *log_del; /* Pointer to delimiter string */
471 const char *p; /* Pointer to next character */
472 double value; /* Equivalent radians value */
473 int ifld; /* Field index */
474 int integ; /* Cast axis value to integer before printing? */
475 int len; /* Length of formatted string */
476 int log; /* Format as "10**x"? */
477 int n; /* Number of characters read */
478 int neg; /* Negate final value? */
479 int result; /* Result fields count to return */
480 int sign; /* Include leading sign in front of "10**x"? */
481 int space; /* Include leading space in front of "10**x"? */
482
483 /* Check the global error status. */
484 if ( !astOK ) return 0;
485
486 /* Initialise. */
487 result = 0;
488 for( ifld = 0; ifld < maxfld; ifld++ ) {
489 fields[ ifld ] = NULL;
490 nc[ ifld ] = 0;
491 }
492 if( val ) *val = AST__BAD;
493
494 /* Parse the Format string. This returns a collection of flags indicating
495 if any AST specific formatting features are specified in the Format
496 string. It also returns a pointer to a new Format string which is a
497 standard C printf format specifier. Currently the only flags are "log"
498 which indicates if the value should be formatted as "10**x" using
499 the graphical escape sequences defined within the Plot class to produce
500 "x" as a superscript of "10", "sign" which is used with log to indicate
501 if a sign should always be included infront of the "10", and "space"
502 which indicates if a leading space should be included infronyt of "10" if
503 no sign is included. */
504 fmt = ParseAxisFormat( fmt0, astGetAxisDigits( this ), &log, &sign,
505 &space, &integ, status );
506 fmt = astFree( (void *) fmt );
507
508 if( astOK ) {
509
510 /* Obtain the length of the formatted string. */
511 len = (int) strlen( str );
512
513 /* First deal with "log" format. */
514 if( log ) {
515
516 /* We need room for at least 2 fields. */
517 if( maxfld > 1 ) {
518
519 /* Return a pointer to the first non-blank character. */
520 p = str;
521 while( *p == ' ' ) p++;
522 fields[ 0 ] = (char *) p;
523
524 /* If the first non-blank character is a minus sign, note it and skip it. */
525 neg = 0;
526 if( *p == '-' ) {
527 neg = 1;
528 p++;
529
530 /* If the first non-blank character is a plus sign, and skip it. */
531 } else if( *p == '+' ) {
532 p++;
533 }
534
535 /* Select the delimter.*/
536 if( astEscapes( -1 ) ) {
537 astTuneC( "exdel", NULL, log_esc, sizeof( log_esc ) );
538 log_del = log_esc;
539 } else {
540 log_del = log_txt;
541 }
542
543 /* Check the remaining string starts with the correct delimiter. If
544 so, store the number of characters in the first field and skip over the
545 delimiter. */
546 n = 0;
547 if( strstr( p, log_del ) == p ) {
548 nc[ 0 ] = p + 2 - fields[ 0 ];
549 p += strlen( log_del );
550
551 /* Attempt to read a floating point value from the start of the remaining
552 string. */
553 if( 1 == sscanf( p, "%lg%n", &value, &n ) ) {
554
555 /* If succesfull, store the returned values. */
556 result = 2;
557 fields[ 1 ] = (char *) p;
558 nc[ 1 ] = n;
559 if( val ) {
560 *val = pow( 10.0, value );
561 if( neg ) *val = -(*val);
562 }
563
564 /* Otherwise, see if the string starts with <bad> */
565 } else if( strstr( p, "<bad>" ) == p ) {
566
567 /* If succesfull, store the returned values. */
568 result = 2;
569 fields[ 1 ] = (char *) p;
570 nc[ 1 ] = 5;
571 if( val ) *val = 0.0;
572 }
573
574 /* Zero is never formatted as an exponent. If the string starts with zero,
575 return a single zero field. */
576 } else if( 1 == sscanf( p, "%lg%n", &value, &n ) ) {
577 if( value == 0.0 ) {
578 result = 1;
579 nc[ 0 ] = p + n - fields[ 0 ];
580 if( val ) *val = 0.0;
581 }
582 }
583 }
584
585 /* Now deal with normal decimal format */
586 } else {
587
588 /* Attempt to read a floating point value from the formatted string. */
589 if ( n = 0,
590 ( 1 == sscanf( str, "%lg %n", &value, &n ) )
591 && ( n >= len ) && maxfld > 0 ) {
592
593 /* If succesful, return a pointer to the first non-blank character. */
594 p = str;
595 while( *p == ' ' ) p++;
596 fields[ 0 ] = (char *) p;
597
598 /* Find the last non-blank character. */
599 p += len;
600 while( p[ -1 ] == ' ' ) p--;
601
602 /* Return the number of characters in the field. */
603 nc[ 0 ] = p - fields[ 0 ];
604
605 /* Return the field value. */
606 if( val ) *val = value;
607
608 /* Indicate that we are returning one field. */
609 result = 1;
610 }
611 }
612 }
613
614 /* Return the result. */
615 return result;
616 }
617
AxisFormat(AstAxis * this,double value,int * status)618 static const char *AxisFormat( AstAxis *this, double value, int *status ) {
619 /*
620 *+
621 * Name:
622 * astAxisFormat
623
624 * Purpose:
625 * Format a coordinate value for an Axis.
626
627 * Type:
628 * Public virtual function.
629
630 * Synopsis:
631 * #include "axis.h"
632 * const char *astAxisFormat( AstAxis *this, double value )
633
634 * Class Membership:
635 * Axis method.
636
637 * Description:
638 * This function returns a pointer to a string containing the formatted
639 * (character) version of a coordinate value for an Axis. The formatting
640 * applied is that specified by a previous invocation of the
641 * astSetAxisFormat method. A suitable default format is applied if
642 * necessary.
643
644 * Parameters:
645 * this
646 * Pointer to the Axis.
647 * value
648 * The coordinate value to be formatted.
649
650 * Returned Value:
651 * A pointer to a null-terminated string containing the formatted value.
652
653 * Notes:
654 * - The returned string pointer may point at memory allocated within
655 * the Axis object, or at static memory. The contents of the string may be
656 * over-written or the pointer may become invalid following a further
657 * invocation of the same function or deletion of the Axis. A copy of the
658 * string should therefore be made if necessary.
659 * - A NULL pointer will be returned if this function is invoked with the
660 * global error status set, or if it should fail for any reason.
661 *-
662 */
663
664 /* Local Constants: */
665 #define ERRBUF_LEN 80
666
667 /* Local Variables: */
668 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
669 char *errstat; /* Pointer for system error message */
670 char errbuf[ ERRBUF_LEN ]; /* Buffer for system error message */
671 char log_esc[ 50 ]; /* Buffer for graphical delimiter string */
672 const char *fmt0; /* Pointer to original Format string */
673 const char *fmt; /* Pointer to parsed Format string */
674 const char *log_del; /* Pointer to delimiter string */
675 const char *result; /* Pointer to formatted value */
676 double x; /* The value to be formatted by sprintf */
677 int integ; /* Cast axis value to integer before printing? */
678 int log; /* Format as "10**x"? */
679 int nc; /* Total number of characters written */
680 int ncc; /* Number of characters written */
681 int sign; /* Include leading sign in front of "10**x"? */
682 int space; /* Include leading space in front of "10**x"? */
683 int stat; /* Value of errno after error */
684
685 /* Check the global error status. */
686 if ( !astOK ) return NULL;
687
688 /* Get a pointer to the thread specific global data structure. */
689 astGET_GLOBALS(this);
690
691 /* Initialise. */
692 result = NULL;
693 nc = 0;
694 x = value;
695
696 /* Check if a bad coordinate value was supplied and return a pointer to an
697 appropriate string if necessary. */
698 if ( value == AST__BAD ) {
699 result = "<bad>";
700
701 /* Otherwise, obtain a pointer to the Format string. Note a private member
702 function is used here in preference to an object method. This is because the
703 syntax of the Format string may be extended by derived classes and we do not
704 want to obtain a string that we cannot interpret here (where we are
705 restricted to C format specifiers capable of formatting double values).
706 Classes that extend the syntax should provide their own astAxisFormat method
707 and may need to store the string in a separate location. The original
708 location should not be re-used as the string it contains may be needed by
709 the Axis astOverlay method when overlaying attributes on to another Axis
710 object. */
711 } else {
712 fmt0 = GetAxisFormat( this, status );
713
714 /* Parse the Format string. This returns a collection of flags indicating
715 if any AST specific formatting features are specified in the Format
716 string. It also returns a pointer to a new Format string which is a
717 standard C printf format specifier. Currently the only flags are "log"
718 which indicates if the value should be formatted as "10**x" using
719 the graphical escape sequences defined within the Plot class to produce
720 "x" as a superscript of "10", "sign" which is used with log to indicate
721 if a sign should always be included infront of the "10", and "space"
722 which indicates if a leading space should be included infronyt of "10"
723 if no sign is included. It also modifies ".*" precision fields by
724 replacing the "*" by the current vale of the Digits attribute. */
725 fmt = ParseAxisFormat( fmt0, astGetAxisDigits( this ), &log, &sign,
726 &space, &integ, status );
727 if( astOK ) {
728
729 /* Format zero normally. */
730 if( value == 0.0 ) log = 0;
731
732 /* If log format is required, find the value of the exponent "x", and
733 initialise the returned string to hold the exponent and the graphical
734 escape sequence which produces a superscript. Otherwise just format the
735 supplied value. */
736 if( log ) {
737
738 if( sign ) {
739 axisformat_buff[ 0 ] ='+';
740 nc = 1;
741
742 } else if( space ) {
743 axisformat_buff[ 0 ] =' ';
744 nc = 1;
745 }
746
747 if( value > 0 ) {
748 x = log10( integ ? (int) value : value );
749
750 } else {
751 x = log10( integ ? (int) -value : -value );
752 axisformat_buff[ 0 ] ='-';
753 nc = 1;
754 }
755
756 if( astEscapes( -1 ) ) {
757 astTuneC( "exdel", NULL, log_esc, sizeof( log_esc ) );
758 log_del = log_esc;
759 } else {
760 log_del = log_txt;
761 }
762
763 nc += sprintf( axisformat_buff + nc, "%s", log_del );
764
765 /* Round small exponents to zero. */
766 if( fabs( x ) < 1.0E-10 ) x = 0.0;
767 }
768 }
769
770 /* Clear errno and attempt to format the value as if the Format string were
771 a standard "sprintf" format. */
772 if ( astOK ) {
773 errno = 0;
774 if( integ ) {
775 ncc = sprintf( axisformat_buff + nc, fmt, (int) x );
776 } else {
777 ncc = sprintf( axisformat_buff + nc, fmt, x );
778 }
779 nc += ncc;
780
781 /* If log format is being used, terminate the string with an escape
782 sequence which resets the graphical attributes to what they were at the
783 start of the string. */
784 if( log ) nc += sprintf( axisformat_buff + nc, "%%+" );
785
786 /* The possibilities for error detection are limited here, but check if an
787 error value was returned and report an error. Include information from
788 errno if it was set. */
789 if ( ncc < 0 ) {
790 stat = errno;
791 if( stat ) {
792 #if HAVE_STRERROR_R
793 strerror_r( stat, errbuf, ERRBUF_LEN );
794 errstat = errbuf;
795 #else
796 errstat = strerror( stat );
797 #endif
798 } else {
799 *errbuf = 0;
800 errstat = errbuf;
801 }
802 astError( AST__FMTER, "astAxisFormat(%s): Error formatting a "
803 "coordinate value of %1.*G%s%s.", status, astGetClass( this ),
804 DBL_DIG, value, stat? " - " : "", errstat );
805 astError( AST__FMTER, "The format string was \"%s\".", status, fmt );
806
807 /* Also check that the result buffer did not overflow. If it did, memory will
808 probably have been corrupted but this cannot be prevented with "sprintf".
809 Report the error and abort. */
810 } else if ( nc > AST__AXIS_AXISFORMAT_BUFF_LEN ) {
811 astError( AST__FMTER, "astAxisFormat(%s): Internal buffer "
812 "overflow while formatting a coordinate value of %1.*G "
813 "- result exceeds %d characters.", status, astGetClass( this ),
814 DBL_DIG, value, AST__AXIS_AXISFORMAT_BUFF_LEN );
815 astError( AST__FMTER, "The format string was \"%s\".", status, fmt );
816
817 /* If succesfull, return a pointer to the buffer. */
818 } else {
819 result = axisformat_buff;
820 }
821 }
822
823 /* Free resources. */
824 fmt = astFree( (void *) fmt );
825
826 }
827
828 /* Return the result. */
829 return result;
830
831 }
832 #undef ERRBUF_LEN
833
AxisGap(AstAxis * this,double gap,int * ntick,int * status)834 static double AxisGap( AstAxis *this, double gap, int *ntick, int *status ) {
835 /*
836 *+
837 * Name:
838 * astAxisGap
839
840 * Purpose:
841 * Find a "nice" gap for tabulating Axis values.
842
843 * Type:
844 * Protected virtual function.
845
846 * Synopsis:
847 * #include "axis.h"
848 * double astAxisGap( AstAxis *this, double gap, int *ntick )
849
850 * Class Membership:
851 * Axis method.
852
853 * Description:
854 * This function returns a gap size which produces a nicely spaced
855 * series of formatted Axis values, the returned gap size being as
856 * close as possible to the supplied target gap size. It also
857 * returns a convenient number of divisions into which the gap can
858 * be divided.
859
860 * Parameters:
861 * this
862 * Pointer to the Axis.
863 * gap
864 * The target gap size.
865 * ntick
866 * Address of an int in which to return a convenient number of
867 * divisions into which the gap can be divided.
868
869 * Returned Value:
870 * The nice gap size.
871
872 * Notes:
873 * - A value of zero is returned if the supplied gap size is zero.
874 * - A negative gap size is returned if the supplied gap size is negative.
875 * - A value of zero will be returned if this function is invoked
876 * with the global error status set, or if it should fail for any
877 * reason.
878 *-
879 */
880
881 /* Local Variables: */
882 double absgap; /* Absolute supplied gap size */
883 double b; /* Decimal step size */
884 double result; /* Returned gap size */
885 int index; /* Index into tables */
886 int positive; /* Value is positive (or zero)? */
887
888 /* Local Data: */
889 static double table1[ 10 ] = /* Table of nice decimal gaps */
890 { 1.0, 2.0, 2.0, 5.0, 5.0, 5.0, 5.0, 10.0, 10.0, 10.0 };
891 static int table2[ 10 ] = /* Table giving number of divisions */
892 { 5, 4, 4, 5, 5, 5, 5, 5, 5, 5 };
893
894 /* Initialise. */
895 result = 0.0;
896
897 /* Check the global error status. */
898 if ( !astOK ) return result;
899
900 /* Check that the supplied gap size is not zero. */
901 if ( gap != 0.0 ) {
902
903 /* Determine if the supplied gap size is positive and obtain its
904 absolute value. */
905 positive = ( gap >= 0.0 );
906 absgap = positive ? gap : -gap;
907
908 /* Obtain a value which has a 1 at the position of the most
909 significant decimal digit in the target gap size and zeros at all
910 other positions. */
911 b = pow( 10.0, floor( log10( absgap ) ) );
912
913 /* This value is the basic "step size". Find the nearest whole number
914 of steps in the supplied gap, and then use the look-up-table in
915 "table1" to find the closest acceptable gap size. Convert this gap
916 size back to an absolute value by multiplying by the step size. */
917 index = (int) ( absgap / b + 0.5 ) - 1;
918 result = b * table1[ index ];
919
920 /* If the target gap was negative, negate the result. */
921 if( !positive ) result = -result;
922
923 /* Store the number of divisions in the gap. */
924 if ( ntick ) *ntick = table2[ index ];
925 }
926
927 /* Return the result. */
928 return result;
929 }
930
AxisIn(AstAxis * this,double lo,double hi,double val,int closed,int * status)931 static int AxisIn( AstAxis *this, double lo, double hi, double val, int closed, int *status ){
932 /*
933 *+
934 * Name:
935 * astAxisIn
936
937 * Purpose:
938 * Test if an axis value lies within a given interval.
939
940 * Type:
941 * Protected virtual function.
942
943 * Synopsis:
944 * #include "axis.h"
945 * int AxisIn( AstAxis *this, double lo, double hi, double val, int closed )
946
947 * Class Membership:
948 * Axis member function.
949
950 * Description:
951 * This function returns non-zero if a given axis values lies within a
952 * given axis interval.
953
954 * Parameters:
955 * this
956 * Pointer to the Axis.
957 * lo
958 * The lower axis limit of the interval.
959 * hi
960 * The upper axis limit of the interval.
961 * val
962 * The axis value to be tested.
963 * closed
964 * If non-zero, then the lo and hi axis values are themselves
965 * considered to be within the interval. Otherwise they are outside.
966
967 * Returned Value:
968 * Non-zero if the test value is inside the interval.
969
970 * Class Applicability:
971 * Axis
972 * Uses simple Euclidean test
973 * SkyAxis
974 * All angles which are numerically between "lo" and "hi" are within
975 * the interval. Angle outside this range are also within the interval
976 * if they can be brought into the range by addition or subtraction
977 * of a multiple of 2.PI.
978 *-
979 */
980
981 /* For speed, omit the astOK check since no pointers are being used. */
982 if( closed ) {
983 return ( lo <= val && val <= hi );
984 } else {
985 return ( lo < val && val < hi );
986 }
987 }
988
AxisNorm(AstAxis * this,double * value,int * status)989 static void AxisNorm( AstAxis *this, double *value, int *status ) {
990 /*
991 *+
992 * Name:
993 * astAxisNorm
994
995 * Purpose:
996 * Normalise an Axis coordinate value.
997
998 * Type:
999 * Public virtual function.
1000
1001 * Synopsis:
1002 * #include "axis.h"
1003 * void astAxisNorm( AstAxis *this, double *value )
1004
1005 * Class Membership:
1006 * Axis method.
1007
1008 * Description:
1009 * This function converts an Axis coordinate value which might
1010 * potentially be unsuitable for display to a user (for instance,
1011 * may lie outside the expected range of values) into an acceptable
1012 * alternative value suitable for display.
1013 *
1014 * Typically, for axes that represent cyclic values such as angles,
1015 * this function wraps an arbitrary coordinate value so that it
1016 * lies within the first cycle (say zero to 2*pi). For an ordinary
1017 * linear Axis, without constraints, this function will typically
1018 * return the original value unchanged.
1019
1020 * Parameters:
1021 * this
1022 * Pointer to the Axis.
1023 * value
1024 * Pointer to the coordinate value to be normalised, which will
1025 * be modified in place.
1026 *-
1027 */
1028
1029 /* In the Axis class there are no constraints, so simply return
1030 without action. */
1031 return;
1032 }
1033
AxisOffset(AstAxis * this,double v1,double dist,int * status)1034 static double AxisOffset( AstAxis *this, double v1, double dist, int *status ) {
1035 /*
1036 *+
1037 * Name:
1038 * astAxisOffset
1039
1040 * Purpose:
1041 * Add an increment onto a supplied axis value.
1042
1043 * Type:
1044 * Protected virtual function.
1045
1046 * Synopsis:
1047 * #include "axis.h"
1048 * AxisOffset( AstAxis *this, double v1, double dist )
1049
1050 * Class Membership:
1051 * Axis method.
1052
1053 * Description:
1054 * This function returns an axis value formed by adding a signed axis
1055 * increment onto a supplied axis value.
1056 *
1057 * For a simple Axis, this is a trivial operation. But for other
1058 * derived classes of Axis (such as a SkyAxis) this is not the case.
1059
1060 * Parameters:
1061 * this
1062 * Pointer to the Axis.
1063 * v1
1064 * The supplied axis value
1065 * dist
1066 * The axis increment
1067
1068 * Returned Value:
1069 * The axis value which is the specified increment away from v1.
1070
1071 * Notes:
1072 * - A value of AST__BAD is returned if either axis value is AST__BAD.
1073 * - A value of AST__BAD will be returned if this function is invoked
1074 * with the global error status set, or if it should fail for any
1075 * reason.
1076 *-
1077 */
1078
1079 /* Local Variables: */
1080 double result; /* Returned gap size */
1081
1082 /* Initialise. */
1083 result = AST__BAD;
1084
1085 /* Check the global error status. */
1086 if ( !astOK ) return result;
1087
1088 /* Check both axis values are OK, and form the returned axis value. */
1089 if( v1 != AST__BAD && dist != AST__BAD ) result = v1 + dist;
1090
1091 /* Return the result. */
1092 return result;
1093 }
1094
AxisOverlay(AstAxis * template,AstAxis * result,int * status)1095 static void AxisOverlay( AstAxis *template, AstAxis *result, int *status ) {
1096 /*
1097 *+
1098 * Name:
1099 * astAxisOverlay
1100
1101 * Purpose:
1102 * Overlay the attributes of a template Axis on to another Axis.
1103
1104 * Type:
1105 * Protected virtual function.
1106
1107 * Synopsis:
1108 * #include "axis.h"
1109 * void astAxisOverlay( AstAxis *template, AstAxis *result )
1110
1111 * Class Membership:
1112 * Axis method.
1113
1114 * Description:
1115 * This function overlays attributes of one Axis (the "template") on to
1116 * another Axis, so as to over-ride selected attributes of that second
1117 * Axis. Normally only those attributes which have been specifically set
1118 * in the template will be transferred. This implements a form of
1119 * defaulting, in which an Axis acquires attributes from the template, but
1120 * retains its original attributes (as the default) if new values have not
1121 * previously been explicitly set in the template.
1122
1123 * Parameters:
1124 * template
1125 * Pointer to the template Axis, for which values should have been
1126 * explicitly set for any attribute which is to be transferred.
1127 * result
1128 * Pointer to the Axis which is to receive the new attribute values.
1129
1130 * Returned Value:
1131 * void
1132 *-
1133 */
1134
1135 /* Check the global error status. */
1136 if ( !astOK ) return;
1137
1138 /* Define a macro to overlay a single attribute. This tests if the attribute
1139 is set in the template Axis. If it is, its value is obtained and set in the
1140 result Axis also. */
1141 #define OVERLAY(par) \
1142 if ( astTestAxis##par( template ) ) { \
1143 astSetAxis##par( result, astGetAxis##par( template ) ); \
1144 }
1145 /* Overlay each Axis attribute in turn. */
1146 OVERLAY(Digits);
1147 OVERLAY(Direction);
1148 OVERLAY(Label);
1149 OVERLAY(Symbol);
1150 OVERLAY(Unit);
1151
1152 /* Handle the Format string slightly differently by using a private member
1153 function to obtain it. This is necessary in case derived classes have
1154 extended the string syntax (see the AxisFormat function for more
1155 details). */
1156 if ( TestAxisFormat( template, status ) ) {
1157 SetAxisFormat( result, GetAxisFormat( template, status ), status );
1158 }
1159
1160 /* Undefine macros local to this function. */
1161 #undef OVERLAY
1162 }
1163
AxisUnformat(AstAxis * this,const char * string,double * value,int * status)1164 static int AxisUnformat( AstAxis *this, const char *string, double *value, int *status ) {
1165 /*
1166 *+
1167 * Name:
1168 * astAxisUnformat
1169
1170 * Purpose:
1171 * Read a formatted coordinate value for an Axis.
1172
1173 * Type:
1174 * Public virtual function.
1175
1176 * Synopsis:
1177 * #include "axis.h"
1178 * int astAxisUnformat( AstAxis *this, const char *string, double *value )
1179
1180 * Class Membership:
1181 * Axis method.
1182
1183 * Description:
1184 * This function reads a formatted coordinate value for an Axis
1185 * (supplied as a string) and returns the equivalent numerical
1186 * value as a double. It also returns the number of characters read
1187 * from the string.
1188
1189 * Parameters:
1190 * this
1191 * Pointer to the Axis.
1192 * string
1193 * Pointer to a constant null-terminated string containing the
1194 * formatted coordinate value.
1195 * value
1196 * Pointer to a double in which the coordinate value read will be
1197 * returned.
1198
1199 * Returned Value:
1200 * The number of characters read from the string to obtain the
1201 * coordinate value.
1202
1203 * Notes:
1204 * - Any white space at the beginning of the string will be
1205 * skipped, as also will any trailing white space following the
1206 * coordinate value read. The function's return value will reflect
1207 * this.
1208 * - A function value of zero (and no coordinate value) will be
1209 * returned, without error, if the string supplied does not contain
1210 * a suitably formatted value.
1211 * - The string "<bad>" is recognised as a special case and will
1212 * generate the value AST__BAD, without error. The test for this
1213 * string is case-insensitive and permits embedded white space.
1214 * - A function result of zero will be returned and no coordinate
1215 * value will be returned via the "value" pointer if this function
1216 * is invoked with the global error status set, or if it should
1217 * fail for any reason.
1218 *-
1219 */
1220
1221 /* Local Variables: */
1222 double coord; /* Coordinate value read */
1223 int nc; /* Number of characters read */
1224
1225 /* Initialise. */
1226 nc = 0;
1227
1228 /* Check the global error status. */
1229 if ( !astOK ) return nc;
1230
1231 /* See if the string can be read as a floating point number. If so,
1232 return its value. Also obtain the number of characters read,
1233 including any leading and trailing white space. */
1234 if ( 1 == astSscanf( string, "%lf %n", &coord, &nc ) ) {
1235 *value = coord;
1236
1237 /* Otherwise, see if the string starts with "<bad>", allowing mixed
1238 case and leading, embedded and trailing white space. If so, return
1239 the value AST__BAD. */
1240 } else if ( nc = 0,
1241 ( 0 == astSscanf( string, " < %*1[Bb] %*1[Aa] %*1[Dd] > %n", &nc )
1242 && ( nc > 0 ) ) ) {
1243 *value = AST__BAD;
1244
1245 /* If the string cannot be read, return a function result of zero. */
1246 } else {
1247 nc = 0;
1248 }
1249
1250 /* Return the number of characters read. */
1251 return nc;
1252 }
1253
ClearAttrib(AstObject * this_object,const char * attrib,int * status)1254 static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) {
1255 /*
1256 * Name:
1257 * ClearAttrib
1258
1259 * Purpose:
1260 * Clear an attribute value for an Axis.
1261
1262 * Type:
1263 * Private function.
1264
1265 * Synopsis:
1266 * #include "axis.h"
1267 * void ClearAttrib( AstObject *this, const char *attrib, int *status )
1268
1269 * Class Membership:
1270 * Axis member function (over-rides the astClearAttrib protected
1271 * method inherited from the Object class).
1272
1273 * Description:
1274 * This function clears the value of a specified attribute for an
1275 * Axis, so that the default value will subsequently be used.
1276
1277 * Parameters:
1278 * this
1279 * Pointer to the Axis.
1280 * attrib
1281 * Pointer to a null-terminated string specifying the attribute
1282 * name. This should be in lower case with no surrounding white
1283 * space.
1284 * status
1285 * Pointer to the inherited status variable.
1286 */
1287
1288 /* Local Variables: */
1289 AstAxis *this; /* Pointer to the Axis structure */
1290
1291 /* Check the global error status. */
1292 if ( !astOK ) return;
1293
1294 /* Obtain a pointer to the Axis structure. */
1295 this = (AstAxis *) this_object;
1296
1297 /* Check the attribute name and clear the appropriate attribute. */
1298
1299 /* Digits. */
1300 /* ------- */
1301 if ( !strcmp( attrib, "digits" ) ) {
1302 astClearAxisDigits( this );
1303
1304 /* Direction. */
1305 /* ---------- */
1306 } else if ( !strcmp( attrib, "direction" ) ) {
1307 astClearAxisDirection( this );
1308
1309 /* Format. */
1310 /* ------- */
1311 } else if ( !strcmp( attrib, "format" ) ) {
1312 astClearAxisFormat( this );
1313
1314 /* Label. */
1315 /* ------ */
1316 } else if ( !strcmp( attrib, "label" ) ) {
1317 astClearAxisLabel( this );
1318
1319 /* Top. */
1320 /* ---- */
1321 } else if ( !strcmp( attrib, "top" ) ) {
1322 astClearAxisTop( this );
1323
1324 /* Bottom. */
1325 /* ------- */
1326 } else if ( !strcmp( attrib, "bottom" ) ) {
1327 astClearAxisBottom( this );
1328
1329 /* Symbol. */
1330 /* ------- */
1331 } else if ( !strcmp( attrib, "symbol" ) ) {
1332 astClearAxisSymbol( this );
1333
1334 /* Unit. */
1335 /* ----- */
1336 } else if ( !strcmp( attrib, "unit" ) ) {
1337 astClearAxisUnit( this );
1338
1339 /* Read-only attributes. */
1340 /* --------------------- */
1341 /* Test if the attribute name matches any of the read-only attributes
1342 of this class. If it does, then report an error. */
1343 } else if ( !strcmp( attrib, "normunit" ) ) {
1344 astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" "
1345 "value for a %s.", status, attrib, astGetClass( this ) );
1346 astError( AST__NOWRT, "This is a read-only attribute." , status);
1347
1348 /* If the attribute is still not recognised, pass it on to the parent
1349 method for further interpretation. */
1350 } else {
1351 (*parent_clearattrib)( this_object, attrib, status );
1352 }
1353 }
1354
GetAxisNormUnit(AstAxis * this,int * status)1355 static const char *GetAxisNormUnit( AstAxis *this, int *status ){
1356 /*
1357 *+
1358 * Name:
1359 * astGetAxisNormUnit
1360
1361 * Purpose:
1362 * Return the normalised Unit attribute for an Axis.
1363
1364 * Type:
1365 * Protected virtual function.
1366
1367 * Synopsis:
1368 * #include "axis.h"
1369 * const char *astGetAxisNormUnit( AstAxis *this ){
1370
1371 * Class Membership:
1372 * Axis method.
1373
1374 * Description:
1375 * This function normalised and returns the axis Unit attribute.
1376 * Normalisation refers to transformations such as "s*(m/s)" -> "m".
1377
1378 * Parameters:
1379 * this
1380 * Pointer to the Axis.
1381
1382 * Returned Value:
1383 * - Pointer to a null-terminated string containing the normalised
1384 * unit string.
1385
1386 * Notes:
1387 * - The returned pointer points to a static memory buffer. The
1388 * contents of this buffer will be over-written on each invocation of
1389 * this function. A copy of the returned string should therefore be
1390 * taken if it will be needed later.
1391 * - A NULL pointer will be returned if this function is invoked
1392 * with the global error status set, or if it should fail for any
1393 * reason.
1394 *-
1395 */
1396
1397 /* Local Variables: */
1398 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1399 const char *result; /* Pointer to dynamic memory holding returned text */
1400 int nc; /* Length of normalised Unit string */
1401
1402 /* Check the global error status. */
1403 if ( !astOK ) return NULL;
1404
1405 /* Get a pointer to the thread specific global data structure. */
1406 astGET_GLOBALS(this);
1407
1408 /* Get the Axis Unit attrribute and normalise it. */
1409 result = astUnitNormaliser( astGetAxisUnit( this ) );
1410
1411 /* If successful, check that the resulting string will fit in the buffer.
1412 If not, report an error. */
1413 if( result ) {
1414 nc = strlen( result );
1415 if( nc > AST__AXIS_GETAXISNORMUNIT_BUFF_LEN ) {
1416 astError( AST__FMTER, "astGetAxisNormUnit(%s): Internal buffer "
1417 "overflow while normalising the units string '%s' "
1418 "- result exceeds %d characters.", status, astGetClass( this ),
1419 result, AST__AXIS_GETAXISNORMUNIT_BUFF_LEN );
1420 result = astFree( (void *) result );
1421
1422 /* If so, copy it into the static buffer and free the dynamic memory returned
1423 by astUnitNormaliser. */
1424 } else {
1425 strcpy( getaxisnormunit_buff, result );
1426 }
1427 astFree( (void *) result );
1428
1429 result = getaxisnormunit_buff;
1430 }
1431
1432 /* Return the answer. */
1433 return result;
1434 }
1435
GetObjSize(AstObject * this_object,int * status)1436 static int GetObjSize( AstObject *this_object, int *status ) {
1437 /*
1438 * Name:
1439 * GetObjSize
1440
1441 * Purpose:
1442 * Return the in-memory size of an Object.
1443
1444 * Type:
1445 * Private function.
1446
1447 * Synopsis:
1448 * #include "axis.h"
1449 * int GetObjSize( AstObject *this, int *status )
1450
1451 * Class Membership:
1452 * Axis member function (over-rides the astGetObjSize protected
1453 * method inherited from the parent class).
1454
1455 * Description:
1456 * This function returns the in-memory size of the supplied Axis,
1457 * in bytes.
1458
1459 * Parameters:
1460 * this
1461 * Pointer to the Axis.
1462 * status
1463 * Pointer to the inherited status variable.
1464
1465 * Returned Value:
1466 * The Object size, in bytes.
1467
1468 * Notes:
1469 * - A value of zero will be returned if this function is invoked
1470 * with the global status set, or if it should fail for any reason.
1471 */
1472
1473 /* Local Variables: */
1474 AstAxis *this; /* Pointer to Axis structure */
1475 int result; /* Result value to return */
1476
1477 /* Initialise. */
1478 result = 0;
1479
1480 /* Check the global error status. */
1481 if ( !astOK ) return result;
1482
1483 /* Obtain a pointers to the Axis structure. */
1484 this = (AstAxis *) this_object;
1485
1486 /* Invoke the GetObjSize method inherited from the parent class, and then
1487 add on any components of the class structure defined by thsi class
1488 which are stored in dynamically allocated memory. */
1489 result = (*parent_getobjsize)( this_object, status );
1490
1491 result += astTSizeOf( this->label );
1492 result += astTSizeOf( this->format );
1493 result += astTSizeOf( this->symbol );
1494 result += astTSizeOf( this->unit );
1495
1496 /* If an error occurred, clear the result value. */
1497 if ( !astOK ) result = 0;
1498
1499 /* Return the result, */
1500 return result;
1501 }
1502
GetAttrib(AstObject * this_object,const char * attrib,int * status)1503 static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) {
1504 /*
1505 * Name:
1506 * GetAttrib
1507
1508 * Purpose:
1509 * Get the value of a specified attribute for an Axis.
1510
1511 * Type:
1512 * Private function.
1513
1514 * Synopsis:
1515 * #include "axis.h"
1516 * const char *GetAttrib( AstObject *this, const char *attrib, int *status )
1517
1518 * Class Membership:
1519 * Axis member function (over-rides the protected astGetAttrib
1520 * method inherited from the Object class).
1521
1522 * Description:
1523 * This function returns a pointer to the value of a specified
1524 * attribute for an Axis, formatted as a character string.
1525
1526 * Parameters:
1527 * this
1528 * Pointer to the Axis.
1529 * attrib
1530 * Pointer to a null-terminated string containing the name of
1531 * the attribute whose value is required. This name should be in
1532 * lower case, with all white space removed.
1533 * status
1534 * Pointer to the inherited status variable.
1535
1536 * Returned Value:
1537 * - Pointer to a null-terminated string containing the attribute
1538 * value.
1539
1540 * Notes:
1541 * - The returned string pointer may point at memory allocated
1542 * within the Axis, or at static memory. The contents of the string
1543 * may be over-written or the pointer may become invalid following
1544 * a further invocation of the same function or any modification of
1545 * the Axis. A copy of the string should therefore be made if
1546 * necessary.
1547 * - A NULL pointer will be returned if this function is invoked
1548 * with the global error status set, or if it should fail for any
1549 * reason.
1550 */
1551
1552 /* Local Variables: */
1553 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1554 AstAxis*this; /* Pointer to the Axis structure */
1555 const char *result; /* Pointer value to return */
1556 double dval; /* Double attribute value */
1557 int digits; /* Digits attribute value */
1558 int direction; /* Direction attribute value */
1559
1560 /* Initialise. */
1561 result = NULL;
1562
1563 /* Check the global error status. */
1564 if ( !astOK ) return result;
1565
1566 /* Get a pointer to the thread specific global data structure. */
1567 astGET_GLOBALS(this_object);
1568
1569 /* Obtain a pointer to the Axis structure. */
1570 this = (AstAxis *) this_object;
1571
1572 /* Compare "attrib" with each recognised attribute name in turn,
1573 obtaining the value of the required attribute. If necessary, write
1574 the value into "getattrib_buff" as a null-terminated string in an
1575 appropriate format. Set "result" to point at the result string. */
1576
1577 /* Digits. */
1578 /* ------- */
1579 if ( !strcmp( attrib, "digits" ) ) {
1580 digits = astGetAxisDigits( this );
1581 if ( astOK ) {
1582 (void) sprintf( getattrib_buff, "%d", digits );
1583 result = getattrib_buff;
1584 }
1585
1586 /* Direction. */
1587 /* ---------- */
1588 } else if ( !strcmp( attrib, "direction" ) ) {
1589 direction = astGetAxisDirection( this );
1590 if ( astOK ) {
1591 (void) sprintf( getattrib_buff, "%d", direction );
1592 result = getattrib_buff;
1593 }
1594
1595 /* Top. */
1596 /* ---- */
1597 } else if ( !strcmp( attrib, "top" ) ) {
1598 dval = astGetAxisTop( this );
1599 if ( astOK ) {
1600 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
1601 result = getattrib_buff;
1602 }
1603
1604 /* Bottom. */
1605 /* ------- */
1606 } else if ( !strcmp( attrib, "bottom" ) ) {
1607 dval = astGetAxisBottom( this );
1608 if ( astOK ) {
1609 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
1610 result = getattrib_buff;
1611 }
1612
1613 /* Format. */
1614 /* ------- */
1615 } else if ( !strcmp( attrib, "format" ) ) {
1616 result = astGetAxisFormat( this );
1617
1618 /* Label. */
1619 /* ------ */
1620 } else if ( !strcmp( attrib, "label" ) ) {
1621 result = astGetAxisLabel( this );
1622
1623 /* Symbol. */
1624 /* ------- */
1625 } else if ( !strcmp( attrib, "symbol" ) ) {
1626 result = astGetAxisSymbol( this );
1627
1628 /* Unit. */
1629 /* ----- */
1630 } else if ( !strcmp( attrib, "unit" ) ) {
1631 result = astGetAxisUnit( this );
1632
1633 /* NormUnit. */
1634 /* --------- */
1635 } else if ( !strcmp( attrib, "normunit" ) ) {
1636 result = astGetAxisNormUnit( this );
1637
1638 /* If the attribute name was not recognised, pass it on to the parent
1639 method for further interpretation. */
1640 } else {
1641 result = (*parent_getattrib)( this_object, attrib, status );
1642 }
1643
1644 /* Return the result. */
1645 return result;
1646
1647 }
1648
GetDefaultFormat(AstAxis * this,int * status)1649 static const char *GetDefaultFormat( AstAxis *this, int *status ){
1650 /*
1651 * Name:
1652 * GetDefaultFormat
1653
1654 * Purpose:
1655 * Return a pointer to a string holding the default Format value.
1656
1657 * Type:
1658 * Private function.
1659
1660 * Synopsis:
1661 * #include "axis.h"
1662 * const char *GetDefaultFormat( AstAxis *this, int *status )
1663
1664 * Class Membership:
1665 * Axis member function
1666
1667 * Description:
1668 * This function returns a pointer to a string holding the default
1669 * Format value, which is based on the current Digits value.
1670
1671 * Parameters:
1672 * this
1673 * A pointer to the Axis structure.
1674 * status
1675 * Pointer to the inherited status variable.
1676
1677 * Returned Value:
1678 * - Pointer to a static null-terminated character string containing
1679 * the default Format string.
1680
1681 * Notes:
1682 * - A null string will be returned if this function is invoked
1683 * with the global error status set, or if it should fail for any
1684 * reason.
1685 */
1686
1687 /* Local Variables: */
1688 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1689
1690 /* Check the global error status. */
1691 if ( !astOK ) return "";
1692
1693 /* Get a pointer to the thread specific global data structure. */
1694 astGET_GLOBALS(this);
1695
1696 /* Create the default format value and store it in the "format_buff"
1697 static variable. */
1698 (void) sprintf( getdefaultformat_buff, "%%1.%dG", astGetAxisDigits( this ) );
1699
1700 /* Return a pointer to the "format_buff" static variable. */
1701 return getdefaultformat_buff;
1702 }
1703
astInitAxisVtab_(AstAxisVtab * vtab,const char * name,int * status)1704 void astInitAxisVtab_( AstAxisVtab *vtab, const char *name, int *status ) {
1705 /*
1706 *+
1707 * Name:
1708 * astInitAxisVtab
1709
1710 * Purpose:
1711 * Initialise a virtual function table for an Axis.
1712
1713 * Type:
1714 * Protected function.
1715
1716 * Synopsis:
1717 * #include "axis.h"
1718 * void astInitAxisVtab( AstAxisVtab *vtab, const char *name )
1719
1720 * Class Membership:
1721 * Axis vtab initialiser.
1722
1723 * Description:
1724 * This function initialises the component of a virtual function
1725 * table which is used by the Axis class.
1726
1727 * Parameters:
1728 * vtab
1729 * Pointer to the virtual function table. The components used by
1730 * all ancestral classes will be initialised if they have not already
1731 * been initialised.
1732 * name
1733 * Pointer to a constant null-terminated character string which contains
1734 * the name of the class to which the virtual function table belongs (it
1735 * is this pointer value that will subsequently be returned by the Object
1736 * astClass function).
1737 *-
1738 */
1739
1740 /* Local Variables: */
1741 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1742 AstObjectVtab *object; /* Pointer to Object component of Vtab */
1743
1744 /* Check the local error status. */
1745 if ( !astOK ) return;
1746
1747 /* Get a pointer to the thread specific global data structure. */
1748 astGET_GLOBALS(NULL);
1749
1750 /* Initialize the component of the virtual function table used by the
1751 parent class. */
1752 astInitObjectVtab( (AstObjectVtab *) vtab, name );
1753
1754 /* Store a unique "magic" value in the virtual function table. This
1755 will be used (by astIsAAxis) to determine if an object belongs
1756 to this class. We can conveniently use the address of the (static)
1757 class_check variable to generate this unique value. */
1758 vtab->id.check = &class_check;
1759 vtab->id.parent = &(((AstObjectVtab *) vtab)->id);
1760
1761 /* Initialise member function pointers. */
1762 /* ------------------------------------ */
1763 /* Store pointers to the member functions (implemented here) that provide
1764 virtual methods for this class. */
1765 vtab->AxisAbbrev = AxisAbbrev;
1766 vtab->AxisFields = AxisFields;
1767 vtab->AxisFormat = AxisFormat;
1768 vtab->AxisDistance = AxisDistance;
1769 vtab->AxisOffset = AxisOffset;
1770 vtab->AxisGap = AxisGap;
1771 vtab->AxisIn = AxisIn;
1772 vtab->AxisNorm = AxisNorm;
1773 vtab->AxisOverlay = AxisOverlay;
1774 vtab->AxisUnformat = AxisUnformat;
1775 vtab->ClearAxisDigits = ClearAxisDigits;
1776 vtab->ClearAxisDirection = ClearAxisDirection;
1777 vtab->ClearAxisFormat = ClearAxisFormat;
1778 vtab->ClearAxisLabel = ClearAxisLabel;
1779 vtab->ClearAxisSymbol = ClearAxisSymbol;
1780 vtab->ClearAxisUnit = ClearAxisUnit;
1781 vtab->GetAxisDigits = GetAxisDigits;
1782 vtab->GetAxisDirection = GetAxisDirection;
1783 vtab->GetAxisFormat = GetAxisFormat;
1784 vtab->GetAxisLabel = GetAxisLabel;
1785 vtab->GetAxisSymbol = GetAxisSymbol;
1786 vtab->GetAxisUnit = GetAxisUnit;
1787 vtab->GetAxisNormUnit = GetAxisNormUnit;
1788 vtab->SetAxisDigits = SetAxisDigits;
1789 vtab->SetAxisDirection = SetAxisDirection;
1790 vtab->SetAxisFormat = SetAxisFormat;
1791 vtab->SetAxisLabel = SetAxisLabel;
1792 vtab->SetAxisSymbol = SetAxisSymbol;
1793 vtab->SetAxisUnit = SetAxisUnit;
1794 vtab->TestAxisDigits = TestAxisDigits;
1795 vtab->TestAxisDirection = TestAxisDirection;
1796 vtab->TestAxisFormat = TestAxisFormat;
1797 vtab->TestAxisLabel = TestAxisLabel;
1798 vtab->TestAxisSymbol = TestAxisSymbol;
1799 vtab->TestAxisUnit = TestAxisUnit;
1800 vtab->TestAxisNormUnit = TestAxisNormUnit;
1801
1802 vtab->ClearAxisTop = ClearAxisTop;
1803 vtab->GetAxisTop = GetAxisTop;
1804 vtab->SetAxisTop = SetAxisTop;
1805 vtab->TestAxisTop = TestAxisTop;
1806
1807 vtab->ClearAxisBottom = ClearAxisBottom;
1808 vtab->GetAxisBottom = GetAxisBottom;
1809 vtab->SetAxisBottom = SetAxisBottom;
1810 vtab->TestAxisBottom = TestAxisBottom;
1811
1812 /* Save the inherited pointers to methods that will be extended, and replace
1813 them with pointers to the new member functions. */
1814 object = (AstObjectVtab *) vtab;
1815
1816 parent_clearattrib = object->ClearAttrib;
1817 parent_getobjsize = object->GetObjSize;
1818 object->GetObjSize = GetObjSize;
1819 object->ClearAttrib = ClearAttrib;
1820 parent_getattrib = object->GetAttrib;
1821 object->GetAttrib = GetAttrib;
1822 parent_setattrib = object->SetAttrib;
1823 object->SetAttrib = SetAttrib;
1824 parent_testattrib = object->TestAttrib;
1825 object->TestAttrib = TestAttrib;
1826
1827 /* Declare the destructor, copy constructor and dump function. */
1828 astSetDelete( vtab, Delete );
1829 astSetCopy( vtab, Copy );
1830 astSetDump( vtab, Dump, "Axis", "Coordinate axis" );
1831
1832 /* If we have just initialised the vtab for the current class, indicate
1833 that the vtab is now initialised, and store a pointer to the class
1834 identifier in the base "object" level of the vtab. */
1835 if( vtab == &class_vtab ) {
1836 class_init = 1;
1837 astSetVtabClassIdentifier( vtab, &(vtab->id) );
1838 }
1839 }
1840
ParseAxisFormat(const char * fmt0,int digs,int * log,int * sign,int * lspace,int * integ,int * status)1841 static char *ParseAxisFormat( const char *fmt0, int digs, int *log, int *sign,
1842 int *lspace, int *integ, int *status ){
1843 /*
1844 * Name:
1845 * ParseAxisFormat
1846
1847 * Purpose:
1848 * Parse the Format string for an Axis.
1849
1850 * Type:
1851 * Private function.
1852
1853 * Synopsis:
1854 * #include "axis.h"
1855 * char *ParseAxisFormat( const char *fmt0, int digs, int *log, int *sign,
1856 * int *lspace, int *integ, int *status )
1857
1858 * Class Membership:
1859 * Axis member function
1860
1861 * Description:
1862 * This function returns a collection of flags indicating if any AST
1863 * specific formatting features are specified in the supplied Format
1864 * string. It also returns a pointer to a new Format string which is a
1865 * standard C printf format specifier.
1866
1867 * Parameters:
1868 * fmt0
1869 * The value of the Format attribute.
1870 * digs
1871 * The default number of digits of precision to use. This is used
1872 * if the given format specifier includes a wildcard precision (".*").
1873 * In this case, the returned format specifier will be modified to
1874 * include an explicit precision value equal to the supplied value
1875 * of "digs".
1876 * log
1877 * Pointer to an integer in which to store a flag indicating if the
1878 * if the axis value should be formatted as "10**x" using the graphical
1879 * escape sequences defined within the Plot class to produce "x" as a
1880 * superscript of "10". A non-zero value will be returned if the
1881 * supplied Format string has a '&' character in its printf <flags>
1882 * field (that is, between the leading '%' sign and the optional
1883 * printf field width).
1884 * sign
1885 * Pointer to an integer in which to store a flag indicating if a
1886 * sign character ('+' or '-') should always be included in front
1887 * of the "10" if "log" is returned non-zero. If "log" is returned
1888 * zero, then "sign" will also be zero. If "log" is non-zero, then
1889 * a non-zero value for "sign" will be returned if the supplied Format
1890 * string has a '+' character in its printf <flags> field (that is,
1891 * between the leading '%' sign and the optional printf field width).
1892 * lspace
1893 * Pointer to an integer in which to store a flag indicating if a
1894 * leading space should be included in front of the "10" if "log" is
1895 * returned non-zero and "sign" is returned zero. Otherwise, "lspace"
1896 * will also be zero. If "log" is non-zero, then a non-zero value for
1897 * "lspace" will be returned if the supplied Format string has a ' '
1898 * character in its printf <flags> field (that is, between the leading
1899 * '%' sign and the optional printf field width).
1900 * integ
1901 * Pointer to an integer in which to store a flag indicating if the
1902 * returned format specifier includes an integer conversion code
1903 * (e.g. %d) or floating point conversion code (e.g. "%.7G").
1904 * status
1905 * Pointer to the inherited status variable.
1906
1907 * Returned Value:
1908 * - Pointer to a dynamically allocated null-terminated string containing
1909 * the modified Format string. This will be a copy of the supplied
1910 * Format string, but with any '&' flag removed. Any '+' or ' ' flag will
1911 * also be removed if "log" is returned as non-zero. An explicit
1912 * precision field will be included if the supplied format includes a
1913 * ".*" precision field.
1914
1915 * Notes:
1916 * - A NULL pointer will be returned if this function is invoked
1917 * with the global error status set, or if it should fail for any
1918 * reason.
1919 */
1920
1921 /* Local Variables: */
1922 char *a; /* Pointer to next char read from original format */
1923 char *b; /* Pointer to next char to write to new format */
1924 char *c; /* Pointer to next char read from original format */
1925 char *new; /* Pointer to new returned string */
1926 char *perc; /* Pointer to percent sign */
1927 char *result; /* Pointer to the returned string */
1928 int hash; /* Was a '#' flag found? */
1929 int len; /* Used length of format string */
1930 int minus; /* Was a '-' flag found? */
1931 int plus; /* Was a '+' flag found? */
1932 int rlen; /* Length of result */
1933 int space; /* Was a ' ' flag found? */
1934
1935 /* Initialise. */
1936 result = NULL;
1937 *log = 0;
1938 *sign = 0;
1939 *lspace = 0;
1940 *integ = 0;
1941
1942 /* Check the global error status. */
1943 if ( !astOK ) return result;
1944
1945 /* Take a copy of the supplied string. Check the pointer can be used
1946 safely. */
1947 len = astChrLen( fmt0 );
1948 result = astStore( NULL, fmt0, len + 1 );
1949 if( astOK ) {
1950 result[ len ] = 0;
1951
1952 /* Find the first percent sign. Do nothing if none is found. */
1953 perc = strchr( result, '%' );
1954 if( perc ) {
1955
1956 /* Check each character following the percent sign until one is found
1957 which is not a legal printf flag, or a legal AST extension flag. Note
1958 which ones are present. */
1959 minus = 0;
1960 plus = 0;
1961 space = 0;
1962 hash = 0;
1963
1964 a = perc;
1965 while( ++a ){
1966 if( *a == '-' ){
1967 minus = 1;
1968 } else if( *a == '+' ){
1969 plus = 1;
1970 } else if( *a == ' ' ){
1971 space = 1;
1972 } else if( *a == '#' ){
1973 hash = 1;
1974 } else if( *a == '&' ){
1975 *log = 1;
1976 } else {
1977 break;
1978 }
1979 }
1980
1981 /* If no '&' flag was found just return the unaltered copy of the
1982 supplied Format string. Otherwise, remove any '+' or ' ' flag. */
1983 if( *log ) {
1984 if( plus ) *sign = 1;
1985 if( space ) *lspace = 1;
1986
1987 /* Append any remaining flag characters to the output string. */
1988 perc++;
1989 if( minus ) *(perc++) = '-';
1990 if( hash ) *(perc++) = '#';
1991
1992 /* Copy the remaining characters down to fill up the gap left by the
1993 removed flags. */
1994 while( *a ) *(perc++) = *(a++);
1995
1996 /* Terminate the returned string. */
1997 *perc = 0;
1998
1999 }
2000 }
2001 }
2002
2003 /* If the format specifier being returned does include a ".*" precision,
2004 replace the "*" with the value of the Digits attribute. */
2005 if( result ) {
2006
2007 /* Find the first percent sign. Do nothing if none is found. */
2008 a = strchr( result, '%' );
2009 if( a ) {
2010
2011 /* Check each character following the percent sign until one is found
2012 which is not a legal printf flag. */
2013 while( ++a ){
2014 if( *a != '-' && *a != '+' && *a != ' ' && *a != '#' ) break;
2015 }
2016
2017 /* Skip any field width (a decimal integer) following the flags. */
2018 a--;
2019 while( ++a ) {
2020 if( !isdigit( *a ) ) break;
2021 }
2022
2023 /* Get a pointer to the next alphabetic character. This will be the
2024 conversion code. If it an integer code, return *integ non-zero. */
2025 c = a - 1;
2026 while( ++c ) {
2027 if( isalpha( *c ) ) {
2028 if( *c == 'd' || *c == 'i' || *c == 'u' || *c == 'o' ||
2029 *c == 'x' || *c == 'X' || *c == 'c' ) *integ = 1;
2030 break;
2031 }
2032 }
2033
2034 /* Go back to the end of the field width. If the next two characters are
2035 "." and "*", change the asterisk to the supplied "digs" value. */
2036 if( a[ 0 ] == '.' && a[ 1 ] == '*' ) {
2037
2038 /* Allocate memory to hold the extended format string (allowing 20
2039 characters for formatting the digs value - just in case something like
2040 INT_MAX is supplied by mistake), and store the existing string in it. */
2041 rlen = strlen( result );
2042 new = astMalloc( rlen + 22 );
2043 if( new ) memcpy( new, result, rlen + 1 );
2044
2045 /* Put the precision into the new string, following the field width. */
2046 b = new + ( a - result );
2047 b += sprintf( b, ".%d", digs );
2048
2049 /* Copy the remainder of the original format string to the new format
2050 string. */
2051 if( a[ 2 ] != 0 ) strcpy( b, a + 2 );
2052
2053 /* Use the new format string in place of the old.*/
2054 astFree( result );
2055 result = new;
2056 }
2057 }
2058 }
2059
2060 /* Return the result. */
2061 return result;
2062
2063 }
2064
SetAttrib(AstObject * this_object,const char * setting,int * status)2065 static void SetAttrib( AstObject *this_object, const char *setting, int *status ) {
2066 /*
2067 * Name:
2068 * SetAttrib
2069
2070 * Purpose:
2071 * Set an attribute value for an Axis.
2072
2073 * Type:
2074 * Private function.
2075
2076 * Synopsis:
2077 * #include "axis.h"
2078 * void SetAttrib( AstObject *this, const char *setting, int *status )
2079
2080 * Class Membership:
2081 * Axis member function (over-rides the protected astSetAttrib
2082 * method inherited from the Object class).
2083
2084 * Description:
2085 * This function assigns an attribute value for an Axis, the
2086 * attribute and its value being specified by means of a string of
2087 * the form:
2088 *
2089 * "attribute= value "
2090 *
2091 * Here, "attribute" specifies the attribute name and should be in
2092 * lower case with no white space present. The value to the right
2093 * of the "=" should be a suitable textual representation of the
2094 * value to be assigned and this will be interpreted according to
2095 * the attribute's data type. White space surrounding the value is
2096 * only significant for string attributes.
2097
2098 * Parameters:
2099 * this
2100 * Pointer to the Axis.
2101 * setting
2102 * Pointer to a null terminated string specifying the new
2103 * attribute value.
2104 * status
2105 * Pointer to the inherited status variable.
2106 */
2107
2108 /* Local Variables: */
2109 AstAxis *this; /* Pointer to Axis structure */
2110 double dval; /* Double attribute value */
2111 int digits; /* Number of digits of precision */
2112 int direction; /* Plot axis in normal direction? */
2113 int format; /* Offset of Format string */
2114 int label; /* Offset of Label string */
2115 int len; /* Length of setting string */
2116 int nc; /* Number of characters read from setting */
2117 int symbol; /* Offset of Symbol string */
2118 int unit; /* Offset of Unit string */
2119
2120 /* Check the global error status. */
2121 if ( !astOK ) return;
2122
2123 /* Obtain a pointer to the Axis structure. */
2124 this = (AstAxis *) this_object;
2125
2126 /* Obtain the length of the setting string. */
2127 len = (int) strlen( setting );
2128
2129 /* Test for each recognised attribute in turn, using "astSscanf" to parse
2130 the setting string and extract the attribute value (or an offset to
2131 it in the case of string values). In each case, use the value set
2132 in "nc" to check that the entire string was matched. Once a value
2133 has been obtained, use the appropriate method to set it. */
2134
2135 /* Digits. */
2136 /* ------- */
2137 if ( nc = 0,
2138 ( 1 == astSscanf( setting, "digits= %d %n", &digits, &nc ) )
2139 && ( nc >= len ) ) {
2140 astSetAxisDigits( this, digits );
2141
2142 /* Direction. */
2143 /* ---------- */
2144 } else if ( nc = 0,
2145 ( 1 == astSscanf( setting, "direction= %d %n", &direction, &nc ) )
2146 && ( nc >= len ) ) {
2147 astSetAxisDirection( this, direction );
2148
2149 /* Top. */
2150 /* ---- */
2151 } else if ( nc = 0,
2152 ( 1 == astSscanf( setting, "top= %lg %n", &dval, &nc ) )
2153 && ( nc >= len ) ) {
2154 astSetAxisTop( this, dval );
2155
2156 /* Bottom. */
2157 /* ------- */
2158 } else if ( nc = 0,
2159 ( 1 == astSscanf( setting, "bottom= %lg %n", &dval, &nc ) )
2160 && ( nc >= len ) ) {
2161 astSetAxisBottom( this, dval );
2162
2163 /* Format. */
2164 /* ------- */
2165 } else if ( nc = 0,
2166 ( 0 == astSscanf( setting, "format=%n%*[^\n]%n", &format, &nc ) )
2167 && ( nc >= len ) ) {
2168 astSetAxisFormat( this, setting + format );
2169
2170 /* Label. */
2171 /* ------ */
2172 } else if ( nc = 0,
2173 ( 0 == astSscanf( setting, "label=%n%*[^\n]%n", &label, &nc ) )
2174 && ( nc >= len ) ) {
2175 astSetAxisLabel( this, setting + label );
2176
2177 /* Symbol. */
2178 /* ------- */
2179 } else if ( nc = 0,
2180 ( 0 == astSscanf( setting, "symbol=%n%*[^\n]%n", &symbol, &nc ) )
2181 && ( nc >= len ) ) {
2182 astSetAxisSymbol( this, setting + symbol );
2183
2184 /* Unit. */
2185 /* ----- */
2186 } else if ( nc = 0,
2187 ( 0 == astSscanf( setting, "unit=%n%*[^\n]%n", &unit, &nc ) )
2188 && ( nc >= len ) ) {
2189 astSetAxisUnit( this, setting + unit );
2190
2191 /* Read-only attributes. */
2192 /* --------------------- */
2193 /* Define a macro to see if the setting string matches any of the
2194 read-only attributes of this class. */
2195 #define MATCH(attrib) \
2196 ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \
2197 ( nc >= len ) )
2198
2199 /* Use this macro to report an error if a read-only attribute has been
2200 specified. */
2201 } else if ( MATCH( "normunit" ) ) {
2202 astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status,
2203 setting, astGetClass( this ) );
2204 astError( AST__NOWRT, "This is a read-only attribute." , status);
2205
2206 /* Pass any unrecognised attribute setting to the parent method for further
2207 interpretation. */
2208 } else {
2209 (*parent_setattrib)( this_object, setting, status );
2210 }
2211
2212 /* Undefine macros local to this function. */
2213 #undef MATCH
2214 }
2215
TestAttrib(AstObject * this_object,const char * attrib,int * status)2216 static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) {
2217 /*
2218 * Name:
2219 * TestAttrib
2220
2221 * Purpose:
2222 * Test if a specified attribute value is set for an Axis.
2223
2224 * Type:
2225 * Private function.
2226
2227 * Synopsis:
2228 * #include "axis.h"
2229 * int TestAttrib( AstObject *this, const char *attrib, int *status )
2230
2231 * Class Membership:
2232 * Axis member function (over-rides the astTestAttrib protected
2233 * method inherited from the Object class).
2234
2235 * Description:
2236 * This function returns a boolean result (0 or 1) to indicate
2237 * whether a value has been set for one of an Axis' attributes.
2238
2239 * Parameters:
2240 * this
2241 * Pointer to the Axis.
2242 * attrib
2243 * Pointer to a null-terminated string specifying the attribute
2244 * name. This should be in lower case with no surrounding white
2245 * space.
2246 * status
2247 * Pointer to the inherited status variable.
2248
2249 * Returned Value:
2250 * One if a value has been set, otherwise zero.
2251
2252 * Notes:
2253 * - A value of zero will be returned if this function is invoked
2254 * with the global status set, or if it should fail for any reason.
2255 */
2256
2257 /* Local Variables: */
2258 AstAxis *this; /* Pointer to the Axis structure */
2259 int result; /* Result value to return */
2260
2261 /* Initialise. */
2262 result = 0;
2263
2264 /* Check the global error status. */
2265 if ( !astOK ) return result;
2266
2267 /* Obtain a pointer to the Axis structure. */
2268 this = (AstAxis *) this_object;
2269
2270 /* Check the attribute name and test the appropriate attribute. */
2271
2272 /* Digits. */
2273 /* ------- */
2274 if ( !strcmp( attrib, "digits" ) ) {
2275 result = astTestAxisDigits( this );
2276
2277 /* Direction. */
2278 /* ---------- */
2279 } else if ( !strcmp( attrib, "direction" ) ) {
2280 result = astTestAxisDirection( this );
2281
2282 /* Top. */
2283 /* ---- */
2284 } else if ( !strcmp( attrib, "top" ) ) {
2285 result = astTestAxisTop( this );
2286
2287 /* Bottom. */
2288 /* ------- */
2289 } else if ( !strcmp( attrib, "bottom" ) ) {
2290 result = astTestAxisBottom( this );
2291
2292 /* Format. */
2293 /* ------- */
2294 } else if ( !strcmp( attrib, "format" ) ) {
2295 result = astTestAxisFormat( this );
2296
2297 /* Label. */
2298 /* ------ */
2299 } else if ( !strcmp( attrib, "label" ) ) {
2300 result = astTestAxisLabel( this );
2301
2302 /* Symbol. */
2303 /* ------- */
2304 } else if ( !strcmp( attrib, "symbol" ) ) {
2305 result = astTestAxisSymbol( this );
2306
2307 /* Unit. */
2308 /* ----- */
2309 } else if ( !strcmp( attrib, "unit" ) ) {
2310 result = astTestAxisUnit( this );
2311
2312 /* NormUnit. */
2313 /* --------- */
2314 } else if ( !strcmp( attrib, "normunit" ) ) {
2315 result = astTestAxisNormUnit( this );
2316
2317 /* If the attribute is still not recognised, pass it on to the parent
2318 method for further interpretation. */
2319 } else {
2320 result = (*parent_testattrib)( this_object, attrib, status );
2321 }
2322
2323 /* Return the result, */
2324 return result;
2325 }
2326
TestAxisNormUnit(AstAxis * this,int * status)2327 static int TestAxisNormUnit( AstAxis *this, int *status ){
2328 /*
2329 * Name:
2330 * TestAxisNormUnit
2331
2332 * Purpose:
2333 * Test if a NormUnit attribute value is set for an Axis.
2334
2335 * Type:
2336 * Private function.
2337
2338 * Synopsis:
2339 * #include "axis.h"
2340 * int TestAxisNormUnit( AstAxis *this, int *status )
2341
2342 * Class Membership:
2343 * Axis member function
2344
2345 * Description:
2346 * This function returns a boolean result (0 or 1) to indicate
2347 * whether a value has been set for the NormUnit string.
2348
2349 * Parameters:
2350 * this
2351 * Pointer to the Axis.
2352 * status
2353 * Pointer to the inherited status variable.
2354
2355 * Returned Value:
2356 * One if a value has been set, otherwise zero.
2357
2358 * Notes:
2359 * - A value of zero will be returned if this function is invoked
2360 * with the global status set, or if it should fail for any reason.
2361 */
2362
2363 return astTestAxisUnit( this );
2364 }
2365
2366
2367 /* Functions which access class attributes. */
2368 /* ---------------------------------------- */
2369 /* Implement member functions to access the attributes associated with this
2370 class using the macros defined for this purpose in the "object.h" file. For
2371 a description of each attribute, see the class interface (in the associated
2372 .h file). */
2373
2374 /* Digits. */
2375 /* ------- */
2376 /* Clear the Digits value by setting it to -INT_MAX. */
2377 astMAKE_CLEAR(Axis,AxisDigits,digits,-INT_MAX)
2378
2379 /* Supply a default of 7 digits if no value has been set. */
2380 astMAKE_GET(Axis,AxisDigits,int,0,( this->digits != -INT_MAX ?
2381 this->digits : 7 ))
2382
2383 /* Constrain the Digits value being set to be at least 1. */
2384 astMAKE_SET(Axis,AxisDigits,int,digits,( value > 1 ? value : 1 ))
2385
2386 /* The Digits value is set if it is not -INT_MAX. */
2387 astMAKE_TEST(Axis,AxisDigits,( this->digits != -INT_MAX ))
2388
2389 /* Direction. */
2390 /* ---------- */
2391 /* Clear the Direction value by setting it to -INT_MAX. */
2392 astMAKE_CLEAR(Axis,AxisDirection,direction,-INT_MAX)
2393
2394 /* Supply a default value of 1 if the Direction value is not set. */
2395 astMAKE_GET(Axis,AxisDirection,int,0,( this->direction != -INT_MAX ?
2396 this->direction : 1 ))
2397
2398 /* Set a Direction value of 1 if any non-zero value is supplied. */
2399 astMAKE_SET(Axis,AxisDirection,int,direction,( value != 0 ))
2400
2401 /* The Direction value is set if it is not -INT_MAX. */
2402 astMAKE_TEST(Axis,AxisDirection,( this->direction != -INT_MAX ))
2403
2404 /* Top. */
2405 /* -----*/
2406 /* Clear the Top Direction value by setting it to AST__BAD. */
astMAKE_CLEAR(Axis,AxisTop,top,AST__BAD)2407 astMAKE_CLEAR(Axis,AxisTop,top,AST__BAD)
2408
2409 /* Supply a default value of DBL_MAX if the Top value is not set.*/
2410 astMAKE_GET(Axis,AxisTop,double,0,( this->top != AST__BAD ? this->top : DBL_MAX))
2411
2412 /* Set the Top value. */
2413 astMAKE_SET(Axis,AxisTop,double,top,(value))
2414
2415 /* The Top value is set if it is not AST__BAD. */
2416 astMAKE_TEST(Axis,AxisTop,( this->top != AST__BAD ))
2417
2418 /* Bottom. */
2419 /* --------*/
2420 /* Clear the Bottom Direction value by setting it to AST__BAD. */
2421 astMAKE_CLEAR(Axis,AxisBottom,bottom,AST__BAD)
2422
2423 /* Supply a default value of -DBL_MAX if the Bottom value is not set.*/
2424 astMAKE_GET(Axis,AxisBottom,double,0.0,( this->bottom != AST__BAD ? this->bottom : -DBL_MAX))
2425
2426 /* Set the Bottom value. */
2427 astMAKE_SET(Axis,AxisBottom,double,bottom,(value))
2428
2429 /* The Bottom value is set if it is not AST__BAD. */
2430 astMAKE_TEST(Axis,AxisBottom,( this->bottom != AST__BAD ))
2431
2432 /* Format. */
2433 /* ------- */
2434 /* Clear the Format value by freeing the allocated memory and assigning a NULL
2435 pointer. */
2436 astMAKE_CLEAR(Axis,AxisFormat,format,astFree( this->format ))
2437
2438 /* If the Format value is not set, return a pointer to a default Format
2439 string. */
2440 astMAKE_GET(Axis,AxisFormat,const char *,NULL,( this->format ? this->format :
2441 GetDefaultFormat( this, status ) ) )
2442
2443 /* Set a Format value by freeing any previously allocated memory, allocating
2444 new memory, storing the string and saving the pointer to the copy. */
2445 astMAKE_SET(Axis,AxisFormat,const char *,format,astStore( this->format, value,
2446 strlen( value ) + (size_t) 1 ))
2447
2448 /* The Format value is set if the pointer to it is not NULL. */
2449 astMAKE_TEST(Axis,AxisFormat,( this->format != NULL ))
2450
2451 /* Label. */
2452 /* ------ */
2453 /* Clear the Label value by freeing the allocated memory and assigning a NULL
2454 pointer. */
2455 astMAKE_CLEAR(Axis,AxisLabel,label,astFree( this->label ))
2456
2457 /* If the Label value is not set, supply a default value by way of a pointer
2458 to the constant string "Coordinate Axis". */
2459 astMAKE_GET(Axis,AxisLabel,const char *,NULL,( this->label ? this->label :
2460 "Coordinate axis" ))
2461
2462 /* Set a Label value by freeing any previously allocated memory, allocating
2463 new memory, storing the string and saving the pointer to the copy. */
2464 astMAKE_SET(Axis,AxisLabel,const char *,label,astStore( this->label, value,
2465 strlen( value ) + (size_t) 1 ))
2466
2467 /* The Label value is set if the pointer to it is not NULL. */
2468 astMAKE_TEST(Axis,AxisLabel,( this->label != NULL ))
2469
2470 /* Symbol. */
2471 /* ------- */
2472 /* Clear the Symbol value by freeing the allocated memory and assigning a NULL
2473 pointer. */
2474 astMAKE_CLEAR(Axis,AxisSymbol,symbol,astFree( this->symbol ))
2475
2476 /* If the Symbol value is not set, supply a default value by way of a pointer
2477 to the constant string "x". */
2478 astMAKE_GET(Axis,AxisSymbol,const char *,NULL,( this->symbol ? this->symbol :
2479 "x" ))
2480
2481 /* Set a Symbol value by freeing any previously allocated memory, allocating
2482 new memory, storing the string and saving the pointer to the copy. */
2483 astMAKE_SET(Axis,AxisSymbol,const char *,symbol,astStore( this->symbol, value,
2484 strlen( value ) + (size_t) 1 ))
2485
2486 /* The Symbol value is set if the pointer to it is not NULL. */
2487 astMAKE_TEST(Axis,AxisSymbol,( this->symbol != NULL ))
2488
2489 /* Unit. */
2490 /* ----- */
2491 /* Clear the Unit value by freeing the allocated memory and assigning a NULL
2492 pointer. */
2493 astMAKE_CLEAR(Axis,AxisUnit,unit,astFree( this->unit ))
2494
2495 /* If the Unit value is not set, supply a default value by way of a pointer
2496 to the constant string "". */
2497 astMAKE_GET(Axis,AxisUnit,const char *,NULL,( this->unit ? this->unit : "" ))
2498
2499 /* Set a Unit value by freeing any previously allocated memory, allocating
2500 new memory, storing the string and saving the pointer to the copy. */
2501 astMAKE_SET(Axis,AxisUnit,const char *,unit,astStore( this->unit, value,
2502 strlen( value ) + (size_t) 1 ))
2503
2504 /* The Unit value is set if the pointer to it is not NULL. */
2505 astMAKE_TEST(Axis,AxisUnit,( this->unit != NULL ))
2506
2507 /* Copy constructor. */
2508 /* ----------------- */
2509 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
2510 /*
2511 * Name:
2512 * Copy
2513
2514 * Purpose:
2515 * Copy constructor for Axis objects.
2516
2517 * Type:
2518 * Private function.
2519
2520 * Synopsis:
2521 * void Copy( const AstObject *objin, AstObject *objout, int *status )
2522
2523 * Description:
2524 * This function implements the copy constructor for Axis objects.
2525
2526 * Parameters:
2527 * objin
2528 * Pointer to the object to be copied.
2529 * objout
2530 * Pointer to the object being constructed.
2531 * status
2532 * Pointer to the inherited status variable.
2533
2534 * Returned Value:
2535 * void
2536
2537 * Notes:
2538 * - This constructor makes a deep copy.
2539 */
2540
2541 /* Local Variables: */
2542 AstAxis *in; /* Pointer to input Axis */
2543 AstAxis *out; /* Pointer to output Axis */
2544
2545 /* Check the global error status. */
2546 if ( !astOK ) return;
2547
2548 /* Obtain pointers to the input and output Axis structures. */
2549 in = (AstAxis *) objin;
2550 out = (AstAxis *) objout;
2551
2552 /* For safety, first clear any references to the input memory from
2553 the output Axis. */
2554 out->format = NULL;
2555 out->label = NULL;
2556 out->symbol = NULL;
2557 out->unit = NULL;
2558
2559 /* Make copies of the allocated strings and Objects. */
2560 if ( in->label ) out->label = astStore( NULL, in->label,
2561 strlen( in->label ) + (size_t) 1 );
2562 if ( in->format ) out->format = astStore( NULL, in->format,
2563 strlen( in->format ) + (size_t) 1 );
2564 if ( in->symbol ) out->symbol = astStore( NULL, in->symbol,
2565 strlen( in->symbol ) + (size_t) 1 );
2566 if ( in->unit ) out->unit = astStore( NULL, in->unit,
2567 strlen( in->unit ) + (size_t) 1 );
2568
2569 /* If an error occurred, clean up by freeing all memory allocated above. */
2570 if ( !astOK ) {
2571 out->format = astFree( out->format );
2572 out->label = astFree( out->label );
2573 out->symbol = astFree( out->symbol );
2574 out->unit = astFree( out->unit );
2575 }
2576 }
2577
2578 /* Destructor. */
2579 /* ----------- */
Delete(AstObject * obj,int * status)2580 static void Delete( AstObject *obj, int *status ) {
2581 /*
2582 * Name:
2583 * Delete
2584
2585 * Purpose:
2586 * Destructor for Axis objects.
2587
2588 * Type:
2589 * Private function.
2590
2591 * Synopsis:
2592 * void Delete( AstObject *obj, int *status )
2593
2594 * Description:
2595 * This function implements the destructor for Axis objects.
2596
2597 * Parameters:
2598 * obj
2599 * Pointer to the object to be deleted.
2600 * status
2601 * Pointer to the inherited status variable.
2602
2603 * Returned Value:
2604 * void
2605
2606 * Notes:
2607 * This function attempts to execute even if the global error status is
2608 * set.
2609 */
2610
2611 /* Local Variables: */
2612 AstAxis *this; /* Pointer to Axis */
2613
2614 /* Obtain a pointer to the Axis structure. */
2615 this = (AstAxis *) obj;
2616
2617 /* Free all allocated memory. */
2618 this->format = astFree( this->format );
2619 this->label = astFree( this->label );
2620 this->symbol = astFree( this->symbol );
2621 this->unit = astFree( this->unit );
2622 }
2623
2624 /* Dump function. */
2625 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)2626 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
2627 /*
2628 * Name:
2629 * Dump
2630
2631 * Purpose:
2632 * Dump function for Axis objects.
2633
2634 * Type:
2635 * Private function.
2636
2637 * Synopsis:
2638 * void Dump( AstObject *this, AstChannel *channel, int *status )
2639
2640 * Description:
2641 * This function implements the Dump function which writes out data
2642 * for the Axis class to an output Channel.
2643
2644 * Parameters:
2645 * this
2646 * Pointer to the Axis whose data are being written.
2647 * channel
2648 * Pointer to the Channel to which the data are being written.
2649 * status
2650 * Pointer to the inherited status variable.
2651 */
2652
2653 /* Local Variables: */
2654 AstAxis *this; /* Pointer to the Axis structure */
2655 char comment[ 80 ]; /* Buffer for comment string */
2656 const char *sval; /* Pointer to string value */
2657 const char *lab; /* Pointer to unit label */
2658 double dval; /* Double value */
2659 int ival; /* Integer value */
2660 int set; /* Attribute value set? */
2661
2662 /* Check the global error status. */
2663 if ( !astOK ) return;
2664
2665 /* Obtain a pointer to the Axis structure. */
2666 this = (AstAxis *) this_object;
2667
2668 /* Write out values representing the instance variables for the
2669 Axis class. Accompany these with appropriate comment strings,
2670 possibly depending on the values being written.*/
2671
2672 /* In the case of attributes, we first use the appropriate (private)
2673 Test... member function to see if they are set. If so, we then use
2674 the (private) Get... function to obtain the value to be written
2675 out.
2676
2677 For attributes which are not set, we use the astGet... method to
2678 obtain the value instead. This will supply a default value
2679 (possibly provided by a derived class which over-rides this method)
2680 which is more useful to a human reader as it corresponds to the
2681 actual default attribute value. Since "set" will be zero, these
2682 values are for information only and will not be read back. */
2683
2684 /* Label. */
2685 /* ------ */
2686 set = TestAxisLabel( this, status );
2687 sval = set ? GetAxisLabel( this, status ) : astGetAxisLabel( this );
2688 astWriteString( channel, "Label", set, 1, sval, "Axis Label" );
2689
2690 /* Symbol. */
2691 /* ------- */
2692 set = TestAxisSymbol( this, status );
2693 sval = set ? GetAxisSymbol( this, status ) : astGetAxisSymbol( this );
2694 astWriteString( channel, "Symbol", set, 1, sval, "Axis symbol" );
2695
2696 /* Unit. */
2697 /* ----- */
2698 set = TestAxisUnit( this, status );
2699 sval = set ? GetAxisUnit( this, status ) : astGetAxisUnit( this );
2700
2701 /* Get any label associated with the unit string. */
2702 lab = astUnitLabel( sval );
2703
2704 /* Construct a comment including the above label (but only if it is not
2705 the same as the unit string) . */
2706 if( lab && strcmp( lab, sval ) ) {
2707 (void) sprintf( comment, "Axis units (%s)", lab );
2708 } else {
2709 (void) sprintf( comment, "Axis units" );
2710 }
2711
2712 /* Write out the Unit value. */
2713 astWriteString( channel, "Unit", set, 0, sval, comment );
2714
2715 /* Digits. */
2716 /* ------- */
2717 set = TestAxisDigits( this, status );
2718 ival = set ? GetAxisDigits( this, status ) : astGetAxisDigits( this );
2719 astWriteInt( channel, "Digits", set, 0, ival,
2720 "Default formatting precision" );
2721
2722 /* Format. */
2723 /* ------- */
2724 set = TestAxisFormat( this, status );
2725 sval = set ? GetAxisFormat( this, status ) : astGetAxisFormat( this );
2726 astWriteString( channel, "Format", set, 0, sval, "Format specifier" );
2727
2728 /* Direction. */
2729 /* ---------- */
2730 set = TestAxisDirection( this, status );
2731 ival = set ? GetAxisDirection( this, status ) : astGetAxisDirection( this );
2732 astWriteInt( channel, "Dirn", set, 0, ival,
2733 ival ? "Plot in conventional direction (hint)" :
2734 "Plot in reverse direction (hint)" );
2735 /* Top. */
2736 /* ---- */
2737 set = TestAxisTop( this, status );
2738 dval = set ? GetAxisTop( this, status ) : astGetAxisTop( this );
2739 astWriteDouble( channel, "Top", set, 0, dval, "Maximum legal axis value" );
2740
2741 /* Bottom. */
2742 /* ------- */
2743 set = TestAxisBottom( this, status );
2744 dval = set ? GetAxisBottom( this, status ) : astGetAxisBottom( this );
2745 astWriteDouble( channel, "Bottom", set, 0, dval, "Minimum legal axis value" );
2746 }
2747
2748 /* Standard class functions. */
2749 /* ========================= */
2750 /* Implement the astIsAAxis and astCheckAxis functions using the macros
2751 defined for this purpose in the "object.h" header file. */
astMAKE_ISA(Axis,Object)2752 astMAKE_ISA(Axis,Object)
2753 astMAKE_CHECK(Axis)
2754
2755 AstAxis *astAxis_( const char *options, int *status, ...) {
2756 /*
2757 *+
2758 * Name:
2759 * astAxis
2760
2761 * Purpose:
2762 * Create an Axis.
2763
2764 * Type:
2765 * Public function.
2766
2767 * Synopsis:
2768 * #include "axis.h"
2769 * AstAxis *astAxis( const char *options, int *status, ... )
2770
2771 * Class Membership:
2772 * Axis constructor.
2773
2774 * Description:
2775 * This function creates a new Axis and optionally initialises its
2776 * attributes.
2777
2778 * Parameters:
2779 * options
2780 * Pointer to a null terminated string containing an optional
2781 * comma-separated list of attribute assignments to be used for
2782 * initialising the new Axis. The syntax used is the same as for the
2783 * astSet method and may include "printf" format specifiers identified
2784 * by "%" symbols in the normal way.
2785 * status
2786 * Pointer to the inherited status variable.
2787 * ...
2788 * If the "options" string contains "%" format specifiers, then an
2789 * optional list of arguments may follow it in order to supply values to
2790 * be substituted for these specifiers. The rules for supplying these
2791 * are identical to those for the astSet method (and for the C "printf"
2792 * function).
2793
2794 * Returned Value:
2795 * A pointer to the new Axis.
2796
2797 * Notes:
2798 * - A NULL pointer will be returned if this function is invoked with the
2799 * global error status set, or if it should fail for any reason.
2800 *-
2801 */
2802
2803 /* Local Variables: */
2804 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
2805 AstAxis *new; /* Pointer to new Axis */
2806 va_list args; /* Variable argument list */
2807
2808 /* Get a pointer to the thread specific global data structure. */
2809 astGET_GLOBALS(NULL);
2810
2811 /* Check the global error status. */
2812 if ( !astOK ) return NULL;
2813
2814 /* Initialise the Axis, allocating memory and initialising the virtual
2815 function table as well if necessary. */
2816 new = astInitAxis( NULL, sizeof( AstAxis ), !class_init, &class_vtab,
2817 "Axis" );
2818
2819 /* If successful, note that the virtual function table has been
2820 initialised. */
2821 if ( astOK ) {
2822 class_init = 1;
2823
2824 /* Obtain the variable argument list and pass it along with the
2825 options string to the astVSet method to initialise the new Axis'
2826 attributes. */
2827 va_start( args, status );
2828 astVSet( new, options, NULL, args );
2829 va_end( args );
2830
2831 /* If an error occurred, clean up by deleting the new object. */
2832 if ( !astOK ) new = astDelete( new );
2833 }
2834
2835 /* Return a pointer to the new Axis. */
2836 return new;
2837 }
2838
astAxisId_(const char * options,...)2839 AstAxis *astAxisId_( const char *options, ... ) {
2840 /*
2841 * Name:
2842 * astAxisId_
2843
2844 * Purpose:
2845 * Create an Axis.
2846
2847 * Type:
2848 * Private function.
2849
2850 * Synopsis:
2851 * #include "axis.h"
2852 * AstAxis *astAxisId_( const char *options, ... );
2853
2854 * Class Membership:
2855 * Axis constructor.
2856
2857 * Description:
2858 * This function implements the external (public) interface to the
2859 * astAxis constructor function. It returns an ID value (instead of
2860 * a true C pointer) to external users, and must be provided
2861 * because astAxis_ has a variable argument list which cannot be
2862 * encapsulated in a macro (where this conversion would otherwise
2863 * occur).
2864 *
2865 * The variable argument list also prevents this function from
2866 * invoking astAxis_ directly, so it must be a re-implementation of
2867 * it in all respects, except for the final conversion of the
2868 * result to an ID value.
2869
2870 * Parameters:
2871 * As for astAxis_.
2872
2873 * Returned Value:
2874 * The ID value associated with the new Axis.
2875 */
2876
2877 /* Local Variables: */
2878 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
2879 AstAxis *new; /* Pointer to new Axis */
2880 va_list args; /* Variable argument list */
2881
2882 int *status; /* Pointer to inherited status value */
2883
2884 /* Get a pointer to the inherited status value. */
2885 status = astGetStatusPtr;
2886
2887 /* Get a pointer to the thread specific global data structure. */
2888 astGET_GLOBALS(NULL);
2889
2890 /* Check the global error status. */
2891 if ( !astOK ) return NULL;
2892
2893 /* Initialise the Axis, allocating memory and initialising the virtual
2894 function table as well if necessary. */
2895 new = astInitAxis( NULL, sizeof( AstAxis ), !class_init, &class_vtab,
2896 "Axis" );
2897
2898 /* If successful, note that the virtual function table has been
2899 initialised. */
2900 if ( astOK ) {
2901 class_init = 1;
2902
2903 /* Obtain the variable argument list and pass it along with the
2904 options string to the astVSet method to initialise the new Axis'
2905 attributes. */
2906 va_start( args, options );
2907 astVSet( new, options, NULL, args );
2908 va_end( args );
2909
2910 /* If an error occurred, clean up by deleting the new object. */
2911 if ( !astOK ) new = astDelete( new );
2912 }
2913
2914 /* Return an ID value for the new Axis. */
2915 return astMakeId( new );
2916 }
2917
astInitAxis_(void * mem,size_t size,int init,AstAxisVtab * vtab,const char * name,int * status)2918 AstAxis *astInitAxis_( void *mem, size_t size, int init,
2919 AstAxisVtab *vtab, const char *name, int *status ) {
2920 /*
2921 *+
2922 * Name:
2923 * astInitAxis
2924
2925 * Purpose:
2926 * Initialise an Axis.
2927
2928 * Type:
2929 * Protected function.
2930
2931 * Synopsis:
2932 * #include "axis.h"
2933 * AstAxis *astInitAxis( void *mem, size_t size, int init,
2934 * AstAxisVtab *vtab, const char *name )
2935
2936 * Class Membership:
2937 * Axis initialiser.
2938
2939 * Description:
2940 * This function is provided for use by class implementations to initialise
2941 * a new Axis object. It allocates memory (if necessary) to accommodate
2942 * the Axis plus any additional data associated with the derived class.
2943 * It then initialises an Axis structure at the start of this memory. If
2944 * the "init" flag is set, it also initialises the contents of a virtual
2945 * function table for an Axis at the start of the memory passed via the
2946 * "vtab" parameter.
2947
2948 * Parameters:
2949 * mem
2950 * A pointer to the memory in which the Axis is to be created. This
2951 * must be of sufficient size to accommodate the Axis data
2952 * (sizeof(Axis)) plus any data used by the derived class. If a value
2953 * of NULL is given, this function will allocate the memory itself using
2954 * the "size" parameter to determine its size.
2955 * size
2956 * The amount of memory used by the Axis (plus derived class data).
2957 * This will be used to allocate memory if a value of NULL is given for
2958 * the "mem" parameter. This value is also stored in the Axis
2959 * structure, so a valid value must be supplied even if not required for
2960 * allocating memory.
2961 * init
2962 * A logical flag indicating if the Axis's virtual function table is
2963 * to be initialised. If this value is non-zero, the virtual function
2964 * table will be initialised by this function.
2965 * vtab
2966 * Pointer to the start of the virtual function table to be associated
2967 * with the new Axis.
2968 * name
2969 * Pointer to a constant null-terminated character string which contains
2970 * the name of the class to which the new object belongs (it is this
2971 * pointer value that will subsequently be returned by the astClass
2972 * method).
2973
2974 * Returned Value:
2975 * A pointer to the new Axis.
2976
2977 * Notes:
2978 * - A NULL pointer will be returned if this function is invoked with the
2979 * global error status set, or if it should fail for any reason.
2980 *-
2981 */
2982
2983 /* Local Variables: */
2984 AstAxis *new; /* Pointer to new Axis */
2985
2986 /* Check the global status. */
2987 if ( !astOK ) return NULL;
2988
2989 /* If necessary, initialise the virtual function table. */
2990 if ( init ) astInitAxisVtab( vtab, name );
2991
2992 /* Initialise an Object structure (the parent class) as the first component
2993 within the Axis structure, allocating memory if necessary. */
2994 new = (AstAxis *) astInitObject( mem, size, 0, (AstObjectVtab *) vtab,
2995 name );
2996
2997 if ( astOK ) {
2998
2999 /* Initialise the Axis data. */
3000 /* ------------------------- */
3001 /* Initialise all attributes to their "undefined" values. */
3002 new->digits = -INT_MAX;
3003 new->direction = -INT_MAX;
3004 new->format = NULL;
3005 new->label = NULL;
3006 new->symbol = NULL;
3007 new->unit = NULL;
3008 new->top = AST__BAD;
3009 new->bottom = AST__BAD;
3010
3011 /* If an error occurred, clean up by deleting the new Axis. */
3012 if ( !astOK ) new = astDelete( new );
3013 }
3014
3015 /* Return a pointer to the new Axis. */
3016 return new;
3017 }
3018
astLoadAxis_(void * mem,size_t size,AstAxisVtab * vtab,const char * name,AstChannel * channel,int * status)3019 AstAxis *astLoadAxis_( void *mem, size_t size,
3020 AstAxisVtab *vtab, const char *name,
3021 AstChannel *channel, int *status ) {
3022 /*
3023 *+
3024 * Name:
3025 * astLoadAxis
3026
3027 * Purpose:
3028 * Load an Axis.
3029
3030 * Type:
3031 * Protected function.
3032
3033 * Synopsis:
3034 * #include "axis.h"
3035 * AstAxis *astLoadAxis( void *mem, size_t size,
3036 * AstAxisVtab *vtab, const char *name,
3037 * AstChannel *channel )
3038
3039 * Class Membership:
3040 * Axis loader.
3041
3042 * Description:
3043 * This function is provided to load a new Axis using data read
3044 * from a Channel. It first loads the data used by the parent class
3045 * (which allocates memory if necessary) and then initialises a
3046 * Axis structure in this memory, using data read from the input
3047 * Channel.
3048 *
3049 * If the "init" flag is set, it also initialises the contents of a
3050 * virtual function table for a Axis at the start of the memory
3051 * passed via the "vtab" parameter.
3052
3053
3054 * Parameters:
3055 * mem
3056 * A pointer to the memory into which the Axis is to be
3057 * loaded. This must be of sufficient size to accommodate the
3058 * Axis data (sizeof(Axis)) plus any data used by derived
3059 * classes. If a value of NULL is given, this function will
3060 * allocate the memory itself using the "size" parameter to
3061 * determine its size.
3062 * size
3063 * The amount of memory used by the Axis (plus derived class
3064 * data). This will be used to allocate memory if a value of
3065 * NULL is given for the "mem" parameter. This value is also
3066 * stored in the Axis structure, so a valid value must be
3067 * supplied even if not required for allocating memory.
3068 *
3069 * If the "vtab" parameter is NULL, the "size" value is ignored
3070 * and sizeof(AstAxis) is used instead.
3071 * vtab
3072 * Pointer to the start of the virtual function table to be
3073 * associated with the new Axis. If this is NULL, a pointer
3074 * to the (static) virtual function table for the Axis class
3075 * is used instead.
3076 * name
3077 * Pointer to a constant null-terminated character string which
3078 * contains the name of the class to which the new object
3079 * belongs (it is this pointer value that will subsequently be
3080 * returned by the astGetClass method).
3081 *
3082 * If the "vtab" parameter is NULL, the "name" value is ignored
3083 * and a pointer to the string "Axis" is used instead.
3084
3085 * Returned Value:
3086 * A pointer to the new Axis.
3087
3088 * Notes:
3089 * - A null pointer will be returned if this function is invoked
3090 * with the global error status set, or if it should fail for any
3091 * reason.
3092 *-
3093 */
3094
3095 /* Local Variables: */
3096 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
3097 AstAxis *new; /* Pointer to the new Axis */
3098
3099 /* Initialise. */
3100 new = NULL;
3101
3102 /* Check the global error status. */
3103 if ( !astOK ) return new;
3104
3105 /* Get a pointer to the thread specific global data structure. */
3106 astGET_GLOBALS(channel);
3107
3108 /* If a NULL virtual function table has been supplied, then this is
3109 the first loader to be invoked for this Axis. In this case the
3110 Axis belongs to this class, so supply appropriate values to be
3111 passed to the parent class loader (and its parent, etc.). */
3112 if ( !vtab ) {
3113 size = sizeof( AstAxis );
3114 vtab = &class_vtab;
3115 name = "Axis";
3116
3117 /* If required, initialise the virtual function table for this class. */
3118 if ( !class_init ) {
3119 astInitAxisVtab( vtab, name );
3120 class_init = 1;
3121 }
3122 }
3123
3124 /* Invoke the parent class loader to load data for all the ancestral
3125 classes of the current one, returning a pointer to the resulting
3126 partly-built Axis. */
3127 new = astLoadObject( mem, size, (AstObjectVtab *) vtab, name,
3128 channel );
3129
3130 if ( astOK ) {
3131
3132 /* Read input data. */
3133 /* ================ */
3134 /* Request the input Channel to read all the input data appropriate to
3135 this class into the internal "values list". */
3136 astReadClassData( channel, "Axis" );
3137
3138 /* Now read each individual data item from this list and use it to
3139 initialise the appropriate instance variable(s) for this class. */
3140
3141 /* In the case of attributes, we first read the "raw" input value,
3142 supplying the "unset" value as the default. If a "set" value is
3143 obtained, we then use the appropriate (private) Set... member
3144 function to validate and set the value properly. */
3145
3146 /* Label. */
3147 /* ------ */
3148 /* Note that string values do not require any additional processing. */
3149 new->label = astReadString( channel, "label", NULL );
3150
3151 /* Symbol. */
3152 /* ------- */
3153 new->symbol = astReadString( channel, "symbol", NULL );
3154
3155 /* Unit. */
3156 /* ----- */
3157 new->unit = astReadString( channel, "unit", NULL );
3158
3159 /* Digits. */
3160 /* ------- */
3161 new->digits = astReadInt( channel, "digits", -INT_MAX );
3162 if ( TestAxisDigits( new, status ) ) SetAxisDigits( new, new->digits, status );
3163
3164 /* Format. */
3165 /* ------- */
3166 new->format = astReadString( channel, "format", NULL );
3167
3168 /* Direction. */
3169 /* ---------- */
3170 new->direction = astReadInt( channel, "dirn", -INT_MAX );
3171 if ( TestAxisDirection( new, status ) ) SetAxisDirection( new, new->direction, status );
3172
3173 /* Top. */
3174 /* ---- */
3175 new->top = astReadDouble( channel, "top", AST__BAD );
3176 if ( TestAxisTop( new, status ) ) SetAxisTop( new, new->top, status );
3177
3178 /* Bottom. */
3179 /* ---- */
3180 new->bottom = astReadDouble( channel, "bottom", AST__BAD );
3181 if ( TestAxisBottom( new, status ) ) SetAxisBottom( new, new->bottom, status );
3182
3183 /* If an error occurred, clean up by deleting the new Axis. */
3184 if ( !astOK ) new = astDelete( new );
3185 }
3186
3187 /* Return the new Axis pointer. */
3188 return new;
3189 }
3190
3191 /* Virtual function interfaces. */
3192 /* ============================ */
3193 /* These provide the external interface to the virtual functions defined by
3194 this class. Each simply checks the global error status and then locates and
3195 executes the appropriate member function, using the function pointer stored
3196 in the object's virtual function table (this pointer is located using the
3197 astMEMBER macro defined in "object.h").
3198
3199 Note that the member function may not be the one defined here, as it may
3200 have been over-ridden by a derived class. However, it should still have the
3201 same interface. */
3202
3203 /* External interfaces for the attribute access functions are generated
3204 automatically by the macros that implement the access functions themselves.
3205 Hence, we need only provide external interfaces for a few additional
3206 functions here. */
astAxisAbbrev_(AstAxis * this,const char * fmt,const char * str1,const char * str2,int * status)3207 const char *astAxisAbbrev_( AstAxis *this, const char *fmt,
3208 const char *str1, const char *str2, int *status ) {
3209 if ( !astOK ) return str2;
3210 return (**astMEMBER(this,Axis,AxisAbbrev))( this, fmt, str1, str2, status );
3211 }
astAxisFormat_(AstAxis * this,double value,int * status)3212 const char *astAxisFormat_( AstAxis *this, double value, int *status ) {
3213 if ( !astOK ) return NULL;
3214 return (**astMEMBER(this,Axis,AxisFormat))( this, value, status );
3215 }
astAxisDistance_(AstAxis * this,double v1,double v2,int * status)3216 double astAxisDistance_( AstAxis *this, double v1, double v2, int *status ) {
3217 if ( !astOK ) return AST__BAD;
3218 return (**astMEMBER(this,Axis,AxisDistance))( this, v1, v2, status );
3219 }
astAxisOffset_(AstAxis * this,double v1,double dist,int * status)3220 double astAxisOffset_( AstAxis *this, double v1, double dist, int *status ) {
3221 if ( !astOK ) return AST__BAD;
3222 return (**astMEMBER(this,Axis,AxisOffset))( this, v1, dist, status );
3223 }
astAxisGap_(AstAxis * this,double gap,int * ntick,int * status)3224 double astAxisGap_( AstAxis *this, double gap, int *ntick, int *status ) {
3225 if ( !astOK ) return 0.0;
3226 return (**astMEMBER(this,Axis,AxisGap))( this, gap, ntick, status );
3227 }
astAxisNorm_(AstAxis * this,double * value,int * status)3228 void astAxisNorm_( AstAxis *this, double *value, int *status ) {
3229 if ( !astOK ) return;
3230 (**astMEMBER(this,Axis,AxisNorm))( this, value, status );
3231 }
astAxisOverlay_(AstAxis * template,AstAxis * result,int * status)3232 void astAxisOverlay_( AstAxis *template, AstAxis *result, int *status ) {
3233 if ( !astOK ) return;
3234 (**astMEMBER(template,Axis,AxisOverlay))( template, result, status );
3235 }
astAxisUnformat_(AstAxis * this,const char * string,double * value,int * status)3236 int astAxisUnformat_( AstAxis *this, const char *string, double *value, int *status ) {
3237 if ( !astOK ) return 0;
3238 return (**astMEMBER(this,Axis,AxisUnformat))( this, string, value, status );
3239 }
astAxisFields_(AstAxis * this,const char * fmt,const char * str,int maxfld,char ** fields,int * nc,double * val,int * status)3240 int astAxisFields_( AstAxis *this, const char *fmt, const char *str,
3241 int maxfld, char **fields, int *nc, double *val, int *status ) {
3242 if ( !astOK ) return 0;
3243 return (**astMEMBER(this,Axis,AxisFields))( this, fmt, str, maxfld, fields, nc, val, status );
3244 }
astAxisIn_(AstAxis * this,double lo,double hi,double val,int closed,int * status)3245 int astAxisIn_( AstAxis *this, double lo, double hi, double val, int closed, int *status ){
3246 if ( !astOK ) return 0;
3247 return (**astMEMBER(this,Axis,AxisIn))( this, lo, hi, val, closed, status );
3248 }
astGetAxisNormUnit_(AstAxis * this,int * status)3249 const char *astGetAxisNormUnit_( AstAxis *this, int *status ) {
3250 if ( !astOK ) return NULL;
3251 return (**astMEMBER(this,Axis,GetAxisNormUnit))( this, status );
3252 }
astTestAxisNormUnit_(AstAxis * this,int * status)3253 int astTestAxisNormUnit_( AstAxis *this, int *status ) {
3254 if ( !astOK ) return 0;
3255 return (**astMEMBER(this,Axis,TestAxisNormUnit))( this, status );
3256 }
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266