summaryrefslogtreecommitdiffstats
path: root/ast/stcschan.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2017-12-08 18:57:06 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2017-12-08 18:57:06 (GMT)
commit90a861b642f765d5657ab827aedabe3920ff9333 (patch)
tree88b93d468ca1feed91ef2958f46f3f74f1418aac /ast/stcschan.c
parentfba23129f50db253ed3fbbaa23d6e342bf86068e (diff)
downloadblt-90a861b642f765d5657ab827aedabe3920ff9333.zip
blt-90a861b642f765d5657ab827aedabe3920ff9333.tar.gz
blt-90a861b642f765d5657ab827aedabe3920ff9333.tar.bz2
upgrade AST
Diffstat (limited to 'ast/stcschan.c')
-rw-r--r--ast/stcschan.c8732
1 files changed, 0 insertions, 8732 deletions
diff --git a/ast/stcschan.c b/ast/stcschan.c
deleted file mode 100644
index 4b43524..0000000
--- a/ast/stcschan.c
+++ /dev/null
@@ -1,8732 +0,0 @@
-/*
-*class++
-* Name:
-* StcsChan
-
-* Purpose:
-* I/O Channel using STC-S to represent Objects.
-
-* Constructor Function:
-c astStcsChan
-f AST_STCSCHAN
-
-* Description:
-* A StcsChan is a specialised form of Channel which supports STC-S
-* I/O operations. Writing an Object to an StcsChan (using
-c astWrite) will, if the Object is suitable, generate an
-f AST_WRITE) will, if the Object is suitable, generate an
-* STC-S description of that Object, and reading from an StcsChan will
-* create a new Object from its STC-S description.
-*
-* When an STC-S description is read using
-c astRead,
-f AST_READ,
-* the returned AST Object may be 1) a PointList describing the STC
-* AstroCoords (i.e. a single point of interest within the coordinate frame
-* described by the STC-S description), or 2) a Region describing the STC
-* AstrCoordsArea (i.e. an area or volume of interest within the coordinate
-* frame described by the STC-S description), or 3) a KeyMap
-* containing the uninterpreted property values read form the STC-S
-* description, or 4) a KeyMap containing any combination of the first
-* 3 options. The attributes StcsArea, StcsCoords and StcsProps
-* control which of the above is returned by
-c astRead.
-f AST_READ.
-*
-* When an STC-S description is created from an AST Object using
-c astWrite,
-f AST_WRITE,
-* the AST Object must be either a Region or a KeyMap. If it is a
-* Region, it is assumed to define the AstroCoordsArea or (if the
-* Region is a single point) the AstroCoords to write to the STC-S
-* description. If the Object is a KeyMap, it may contain an entry
-* with the key "AREA", holding a Region to be used to define the
-* AstroCoordsArea. It may also contain an entry with the key "COORDS",
-* holding a Region (a PointList) to be used to create the
-* AstroCoords. It may also contain an entry with key "PROPS", holding
-* a KeyMap that contains uninterpreted property values to be used as
-* defaults for any STC-S properties that are not determined by the
-* other supplied Regions. In addition, a KeyMap supplied to
-c astWrite
-f AST_WRITE
-* may itself hold the default STC-S properties (rather than defaults
-* being held in a secondary KeyMap, stored as the "PROPS" entry in the
-* supplied KeyMap).
-*
-* The
-c astRead and astWrite
-f AST_READ and AST_WRITE
-* functions work together so that any Object returned by
-c astRead can immediately be re-written using astWrite.
-f AST_READ can immediately be re-written using AST_WRITE.
-*
-* Normally, when you use an StcsChan, you should provide "source"
-c and "sink" functions which connect it to an external data store
-c by reading and writing the resulting text. These functions
-f and "sink" routines which connect it to an external data store
-f by reading and writing the resulting text. These routines
-* should perform any conversions needed between external character
-c encodings and the internal ASCII encoding. If no such functions
-f encodings and the internal ASCII encoding. If no such routines
-* are supplied, a Channel will read from standard input and write
-* to standard output.
-*
-* Alternatively, an XmlChan can be told to read or write from
-* specific text files using the SinkFile and SourceFile attributes,
-* in which case no sink or source function need be supplied.
-*
-* Support for STC-S is currently based on the IVOA document "STC-S:
-* Space-Time Coordinate (STC) Metadata Linear String Implementation",
-* version 1.30 (dated 5th December 2007), available at
-* http://www.ivoa.net/Documents/latest/STC-S.html. Note, this
-* document is a recommednation only and does not constitute an accepted
-* IVOA standard.
-*
-* The full text of version 1.30 is supported by the StcsChan class,
-* with the following exceptions and provisos:
-*
-* - When reading an STC-S phrase, case is ignored except when reading
-* units strings.
-* - There is no support for multiple intervals specified within a
-* TimeInterval, PositionInterval, SpectralInterval or RedshiftInterval.
-* - If the ET timescale is specified, TT is used instead.
-* - If the TEB timescale is specified, TDB is used instead.
-* - The LOCAL timescale is not supported.
-* - The AST TimeFrame and SkyFrame classes do not currently allow a
-* reference position to be specified. Consequently, any <refpos>
-* specified within the Time or Space sub-phrase of an STC-S document
-* is ignored.
-* - The Convex identifier for the space sub-phrase is not supported.
-* - The GEO_C and GEO_D space frames are not supported.
-* - The UNITSPHERE and SPHER3 space flavours are not supported.
-* - If any Error values are supplied in a space sub-phrase, then the
-* number of values supplied should equal the number of spatial axes,
-* and the values are assumed to specify an error box (i.e. error
-* circles, ellipses, etc, are not supported).
-* - The spectral and redshift sub-phrases do not support the
-* following <refpos> values: LOCAL_GROUP_CENTER, UNKNOWNRefPos,
-* EMBARYCENTER, MOON, MERCURY, VENUS, MARS, JUPITER, SATURN, URANUS,
-* NEPTUNE, PLUTO.
-* - Error values are supported but error ranges are not.
-* - Resolution, PixSize and Size values are ignored.
-* - Space velocity sub-phrases are ignored.
-
-* Inheritance:
-* The StcsChan class inherits from the Channel class.
-
-* Attributes:
-* In addition to those attributes common to all Channels, every
-* StcsChan also has the following attributes:
-*
-* - StcsArea: Return the CoordinateArea component after reading an STC-S?
-* - StcsCoords: Return the Coordinates component after reading an STC-S?
-* - StcsLength: Controls output buffer length
-* - StcsProps: Return the STC-S properties after reading an STC-S?
-
-* Functions:
-c The StcsChan class does not define any new functions beyond those
-f The StcsChan class does not define any new routines beyond those
-* which are applicable to all Channels.
-
-* Copyright:
-* Copyright (C) 2009 Science & Technology Facilities Council.
-* All Rights Reserved.
-
-* Licence:
-* This program is free software: you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License as published by the Free Software Foundation, either
-* version 3 of the License, or (at your option) any later
-* version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General
-* License along with this program. If not, see
-* <http://www.gnu.org/licenses/>.
-
-* Authors:
-* DSB: David Berry (Starlink)
-
-* History:
-* 18-DEC-2008 (DSB):
-* Original version.
-* 22-MAY-2008 (DSB):
-* Retain default Equinox values in SkyFrame when reading an STC-S.
-* 30-OCT-2009 (DSB):
-* Make case insensitive (except for units strings).
-* 21-FEB-2014 (DSB):
-* Split long properties up into words when writing out an STC-S
-* description.
-* 26-MAR-2015 (DSB):
-* Guard against seg faults if an error has already occured.
-*class--
-*/
-
-/* Module Macros. */
-/* ============== */
-/* Set the name of the class we are implementing. This indicates to
- the header files that define class interfaces that they should make
- "protected" symbols available. */
-#define astCLASS StcsChan
-
-/* Values identifying particular forms of CoordArea */
-#define NULL_ID 1
-#define TIME_INTERVAL_ID 2
-#define START_TIME_ID 3
-#define STOP_TIME_ID 4
-#define POSITION_INTERVAL_ID 5
-#define ALLSKY_ID 6
-#define CIRCLE_ID 7
-#define ELLIPSE_ID 8
-#define BOX_ID 9
-#define POLYGON_ID 10
-#define CONVEX_ID 11
-#define POSITION_ID 12
-#define TIME_ID 13
-#define SPECTRAL_INTERVAL_ID 14
-#define SPECTRAL_ID 15
-#define REDSHIFT_INTERVAL_ID 16
-#define REDSHIFT_ID 17
-#define VELOCITY_INTERVAL_ID 18
-#define UNION_ID 19
-#define INTERSECTION_ID 20
-#define DIFFERENCE_ID 21
-#define NOT_ID 22
-#define VELOCITY_ID 23
-
-/* The number of words used to form an extract from an STC-S description
- for use in an error message. */
-#define NEWORD 10
-
-/* Max length of string returned by GetAttrib */
-#define GETATTRIB_BUFF_LEN 50
-
-/* Include files. */
-/* ============== */
-/* Interface definitions. */
-/* ---------------------- */
-
-#include "frame.h" /* Generic cartesian coordinate systems */
-#include "globals.h" /* Thread-safe global data access */
-#include "error.h" /* Error reporting facilities */
-#include "memory.h" /* Memory allocation facilities */
-#include "object.h" /* Base Object class */
-#include "channel.h" /* Interface for parent class */
-#include "stcschan.h" /* Interface definition for this class */
-#include "loader.h" /* Interface to the global loader */
-#include "skyframe.h" /* Celestial coordinate systems */
-#include "timeframe.h" /* Time coordinate systems */
-#include "specframe.h" /* Spectral coordinate systems */
-#include "wcsmap.h" /* PI-related constants */
-#include "region.h" /* Abstract regions */
-#include "interval.h" /* Axis intervals */
-#include "unitmap.h" /* Unit mappings */
-#include "nullregion.h" /* Boundless regions */
-#include "cmpregion.h" /* Compound regions */
-#include "box.h" /* Box regions */
-#include "prism.h" /* Prism regions */
-#include "circle.h" /* Circle regions */
-#include "ellipse.h" /* Ellipse regions */
-#include "polygon.h" /* Polygon regions */
-#include "pointlist.h" /* Lists of points */
-#include "keymap.h" /* KeyMap interface */
-
-
-/* Error code definitions. */
-/* ----------------------- */
-#include "ast_err.h" /* AST error codes */
-
-/* C header files. */
-/* --------------- */
-#include <ctype.h>
-#include <float.h>
-#include <limits.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* Module Types. */
-/* ============= */
-typedef struct WordContext {
- char *line;
- char *wnext;
- char *e;
- char f;
- int done;
- char *words[ NEWORD ];
- int next;
- int close;
- int open;
-} WordContext;
-
-/* Module Variables. */
-/* ================= */
-
-/* Pointers to parent class methods which are extended by this class. */
-static const char *(* parent_getattrib)( AstObject *, const char *, int * );
-static int (* parent_testattrib)( AstObject *, const char *, int * );
-static void (* parent_clearattrib)( AstObject *, const char *, int * );
-static void (* parent_setattrib)( AstObject *, const char *, int * );
-static int (* parent_getindent)( AstChannel *, int * );
-
-/* Address of this static variable is used as a unique identifier for
- member of this class. */
-static int class_check;
-
-/* Define macros for accessing each item of thread specific global data. */
-#ifdef THREAD_SAFE
-
-/* Define how to initialise thread-specific globals. */
-#define GLOBAL_inits \
- globals->GetAttrib_Buff[ 0 ] = 0; \
- globals->Class_Init = 0;
-
-/* Create the function that initialises global data for this module. */
-astMAKE_INITGLOBALS(StcsChan)
-
-/* Define macros for accessing each item of thread specific global data. */
-#define getattrib_buff astGLOBAL(StcsChan,GetAttrib_Buff)
-#define class_init astGLOBAL(StcsChan,Class_Init)
-#define class_vtab astGLOBAL(StcsChan,Class_Vtab)
-
-
-/* If thread safety is not needed, declare and initialise globals at static
- variables. */
-#else
-
-/* Define the class virtual function table and its initialisation flag
- as static variables. */
-static AstStcsChanVtab class_vtab; /* Virtual function table */
-static int class_init = 0; /* Virtual function table initialised? */
-
-/* Buffer returned by GetAttrib. */
-static char getattrib_buff[ GETATTRIB_BUFF_LEN + 1 ];
-
-#endif
-
-
-/* External Interface Function Prototypes. */
-/* ======================================= */
-/* The following functions have public prototypes only (i.e. no
- protected prototypes), so we must provide local prototypes for use
- within this module. */
-AstStcsChan *astStcsChanForId_( const char *(*)( void ),
- char *(*)( const char *(*)( void ), int * ),
- void (*)( const char * ),
- void (*)( void (*)( const char * ), const char *, int * ),
- const char *, ... );
-AstStcsChan *astStcsChanId_( const char *(* source)( void ),
- void (* sink)( const char * ),
- const char *options, ... );
-
-/* Prototypes for Private Member Functions. */
-/* ======================================== */
-static AstKeyMap *ReadProps( AstStcsChan *, int * );
-static AstObject *Read( AstChannel *, int * );
-static AstPointList *SinglePointList( AstFrame *, double *, AstRegion *, int *);
-static AstRegion *MakeSpaceRegion( AstKeyMap *, AstFrame *, double, int * );
-static char *AddItem( AstStcsChan *, AstKeyMap *, const char *, const char *, char *, int *, int *, int, int * );
-static char *ContextFragment( WordContext *, char **, int * );
-static char *PutRegionProps( AstStcsChan *, AstKeyMap *, const char *, int, char *, int *, int *, int, int * );
-static char *SourceWrap( const char *(*)( void ), int * );
-static const char *GetNextWord( AstStcsChan *, WordContext *, int * );
-static const char *ReadSpaceArgs( AstStcsChan *, const char *, int, int, WordContext *, AstKeyMap *, int * );
-static double *BoxCorners( AstFrame *, const double[2], const double[2], int * );
-static int GetIndent( AstChannel *, int * );
-static int GetRegionProps( AstStcsChan *, AstRegion *, AstKeyMap *, int, int, double, int, int * );
-static int SpaceId( const char *, int * );
-static int Write( AstChannel *, AstObject *, int * );
-static int WriteRegion( AstStcsChan *, AstRegion *, AstKeyMap *, int * );
-static void Dump( AstObject *, AstChannel *, int * );
-static void FreeContext( WordContext *, int * );
-static void GetFmt( const char *, AstKeyMap *, int, int, char *, int * );
-static void MapPut0C( AstKeyMap *, const char *, const char *, const char *, int, int * );
-static void MapPut0D( AstKeyMap *, const char *, double, double, int, int * );
-static void SetUnc( AstRegion *, AstRegion *, AstFrame *, int, double, double *, int, int * );
-static void SinkWrap( void (*)( const char * ), const char *, int * );
-static void WriteProps( AstStcsChan *, AstKeyMap *, int * );
-
-static int GetStcsArea( AstStcsChan *, int * );
-static int TestStcsArea( AstStcsChan *, int * );
-static void ClearStcsArea( AstStcsChan *, int * );
-static void SetStcsArea( AstStcsChan *, int, int * );
-
-static int GetStcsCoords( AstStcsChan *, int * );
-static int TestStcsCoords( AstStcsChan *, int * );
-static void ClearStcsCoords( AstStcsChan *, int * );
-static void SetStcsCoords( AstStcsChan *, int, int * );
-
-static int GetStcsProps( AstStcsChan *, int * );
-static int TestStcsProps( AstStcsChan *, int * );
-static void ClearStcsProps( AstStcsChan *, int * );
-static void SetStcsProps( AstStcsChan *, int, int * );
-
-static void ClearAttrib( AstObject *, const char *, int * );
-static const char *GetAttrib( AstObject *, const char *, int * );
-static void SetAttrib( AstObject *, const char *, int * );
-static int TestAttrib( AstObject *, const char *, int * );
-
-static int TestStcsLength( AstStcsChan *, int * );
-static void ClearStcsLength( AstStcsChan *, int * );
-static void SetStcsLength( AstStcsChan *, int, int * );
-static int GetStcsLength( AstStcsChan *, int * );
-
-/* Member functions. */
-/* ================= */
-
-static char *AddItem( AstStcsChan *this, AstKeyMap *km, const char *key,
- const char *prefix, char *line, int *nc, int *crem,
- int linelen, int *status ){
-/*
-* Name:
-* AddItem
-
-* Purpose:
-* Add an STC-S property item to a buffer.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* char *AddItem( AstStcsChan *this, AstKeyMap *km, const char *key,
-* const char *prefix, char *line, int *nc, int *crem,
-* int linelen, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function appends text describing a singlke STC-S property to
-* a supplied text buffer, handling the splitting of text into lines.
-
-* Parameters:
-* this
-* The StcsChan.
-* km
-* Pointer to a KeyMap containing the STC-S properties.
-* key
-* The key name associated with the property to be checked.
-* prefix
-* if not NULL, this is a string that is to be written out before
-* the property value. It should usually include a trailing space.
-* line
-* Pointer to the buffer to recieve the prefix and property value.
-* nc
-* Pointer to an int in which to store the number of characters in
-* the buffer. Updated on exit.
-* crem
-* Pointer to an int in which to store the maximum number of
-* characters before a new line. Ignored if linelen is zero. Updated
-* on exit.
-* linelen
-* The maximum number of character per line, or zero if all text is
-* to be included in a single line.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* A pointer to the buffer. This will usually be "line", but may be
-* different to "line" if it was necessary to expand the memory to make
-* room for the new property.
-
-*/
-
-/* Local Variables: */
- char *result; /* Returned pointer */
- char **words; /* All words */
- const char *text; /* Property value */
- const char *word; /* Single word */
- int iw; /* Word index */
- int len; /* Length of new text */
- int nw; /* Number of words in property */
-
-/* Initialise */
- result = line;
- len = 0;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* If the KeyMap contains the required property... */
- if( astMapGet0C( km, key, &text ) ) {
-
-/* Add any supplied prefix to the returned buffer. */
- if( prefix ) {
- len = strlen( prefix );
- if( len > *crem && len < linelen ) {
- astPutNextText( this, result );
- *nc = 0;
- result = astAppendString( result, nc, " " );
- *crem = linelen - 3;
- }
- result = astAppendString( result, nc, prefix );
- *crem -= len;
- }
-
-/* Split the property into words. */
- words = astChrSplit( text, &nw );
-
-/* Append each word to the buffer. */
- for( iw = 0; iw < nw; iw++ ) {
- word = words[ iw ];
-
-/* If required, get the number of characters to be added to the buffer. */
- if( linelen ) {
- len = strlen( word );
-
-/* If there is insufficient room left, write out the text through the
- Channel sink function, and start a new line with three spaces. Then
- reset the number of character remaining in the line. */
- if( len > *crem && len < linelen ) {
- astPutNextText( this, result );
- *nc = 0;
- result = astAppendString( result, nc, " " );
- *crem = linelen - 3;
- }
-
-/* Reduce crem to account for the text that is about to be added to the
- line. */
- *crem -= len;
- }
-
-/* Add the property value to the returned buffer. */
- result = astAppendString( result, nc, word );
-
-/* Add a traling space to the returned buffer, if there is room. */
- if( !linelen || *crem > 0 ) {
- result = astAppendString( result, nc, " " );
- (*crem)--;
- }
- }
-
-/* Free the words buffer. */
- if( words ) {
- for( iw = 0; iw < nw; iw++ ) words[ iw ] = astFree( words[ iw ] );
- words = astFree( words );
- }
- }
-
-/* Return the buffer pointer. */
- return result;
-}
-
-static double *BoxCorners( AstFrame *frm, const double centre[2],
- const double bsize[2], int *status ) {
-/*
-* Name:
-* BoxCorners
-
-* Purpose:
-* Determine the positions of the corners of an STC Box.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* double *BoxCorners( AstFrame *frm, const double centre[2],
-* const double bsize[2], int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function returns a pointer to a dynamically allocated array
-* holding the positions of the corners of the STC Box defined by the
-* supplied "centre" and "bsize" arrays.
-
-* Parameters:
-* frm
-* Pointer to the Frame in which the Box is defined. Must be 2-D.
-* centre
-* Two element array holding the Frame co-ordinates at the centre
-* of the Box.
-* bsize
-* Two element array holding the full width and height of the Box.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* A pointer to a dynamically allocated array holding the axis values
-* at the four corners, in a form suitable for passing to the
-* astPolygon constructor function. NULL is returned if an error has
-* already occurred, of if this function fails for any reason.
-*/
-
-/* Local Variables: */
- double *result; /* Returned pointer. */
- double bh1[ 2 ]; /* A first point on the bottom horizontal edge */
- double bh2[ 2 ]; /* A second point on the bottom horizontal edge */
- double blc[ 2 ]; /* Position of bottom left corner */
- double brc[ 2 ]; /* Position of bottom right corner */
- double lv1[ 2 ]; /* A first point on the left vertical edge */
- double lv2[ 2 ]; /* A second point on the left vertical edge */
- double pa; /* Position angle of great circle/straight line */
- double rv1[ 2 ]; /* A first point on the right vertical edge */
- double rv2[ 2 ]; /* A second point on the right vertical edge */
- double th1[ 2 ]; /* A first point on the top horizontal edge */
- double th2[ 2 ]; /* A second point on the top horizontal edge */
- double tlc[ 2 ]; /* Position of top left corner */
- double trc[ 2 ]; /* Position of top right corner */
-
-/* Initialise. */
- result = NULL;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Check the Frame is 2-dimensional. */
- if( astGetNaxes( frm ) != 2 ) {
- astError( AST__BADIN, "astRead(StcsChan): Supplied space frame has "
- "%d axes.", status, astGetNaxes( frm ) );
- astError( AST__BADIN, "astRead(StcsChan): Can only use STC Box regions "
- "with 2-dimensional space frames.", status );
- }
-
-/* Offset away from the centre by half the Box width along a great circle
- initially parallel to the positive first frame axis (i.e. position
- angle +pi/2). The end position goes in "rv1" and the position angle of
- the great circle (or straight line) at that point is returned as the
- function value. NOTE, the use of the words "left" and "right" below is
- vague because it depends on whether we are using a SkyFrame (which has
- a reversed first axis) or a basic Frame. In general, the choice of "left"
- and "right" below is appropriate for a basic Frame. */
- pa = astOffset2( frm, centre, AST__DPIBY2, bsize[ 0 ]/2, rv1 );
-
-/* Turn by 90 degrees and offset away by half the box height. This is done
- so that we have a second point (rv2) to define the great circle (or
- straight line) that forms the first vertical edge of the Box (i.e. the
- great circle or straight line through rv1 and rv2). Note, for spherical
- Frames (i.e. SkyFrames) "rv2" is not necessarily a corner of the box. */
- (void) astOffset2( frm, rv1, pa + AST__DPIBY2, bsize[ 1 ]/2, rv2 );
-
-/* In the same way, get two points on the second vertical Box edge. */
- pa = astOffset2( frm, centre, -AST__DPIBY2, bsize[ 0 ]/2, lv1 );
- (void) astOffset2( frm, lv1, pa + AST__DPIBY2, bsize[ 1 ]/2, lv2 );
-
-/* In the same way, get two points on the top horizontal Box edge. */
- pa = astOffset2( frm, centre, 0.0, bsize[ 1 ]/2, th1 );
- (void) astOffset2( frm, th1, pa + AST__DPIBY2, bsize[ 0 ]/2, th2 );
-
-/* In the same way, get two points on the bottom horizontal Box edge. */
- pa = astOffset2( frm, centre, AST__DPI, bsize[ 1 ]/2, bh1 );
- (void) astOffset2( frm, bh1, pa + AST__DPIBY2, bsize[ 0 ]/2, bh2 );
-
-/* The first corner of the Box is at the intersection of the first
- vertical and top horizontal edges. */
- astIntersect( frm, lv1, lv2, th1, th2, tlc );
-
-/* The top right corner of the Box is at the intersection of the right
- vertical and top horizontal edges. */
- astIntersect( frm, rv1, rv2, th1, th2, trc );
-
-/* The bottom left corner of the Box is at the intersection of the left
- vertical and bottom horizontal edges. */
- astIntersect( frm, lv1, lv2, bh1, bh2, blc );
-
-/* The bottom right corner of the Box is at the intersection of the right
- vertical and bottom horizontal edges. */
- astIntersect( frm, rv1, rv2, bh1, bh2, brc );
-
-/* Gather the corners together into an array suitable for use with
- astPolygon. Make sure the vertices are traversed in an ant-clockwise
- sense whether in a SkyFrame or a basic Frame. */
- result = astMalloc( 8*sizeof( *result ) );
- if( result ) {
- if( astIsASkyFrame( frm ) ) {
- result[ 0 ] = tlc[ 0 ];
- result[ 1 ] = trc[ 0 ];
- result[ 2 ] = brc[ 0 ];
- result[ 3 ] = blc[ 0 ];
- result[ 4 ] = tlc[ 1 ];
- result[ 5 ] = trc[ 1 ];
- result[ 6 ] = brc[ 1 ];
- result[ 7 ] = blc[ 1 ];
- } else {
- result[ 3 ] = tlc[ 0 ];
- result[ 2 ] = trc[ 0 ];
- result[ 1 ] = brc[ 0 ];
- result[ 0 ] = blc[ 0 ];
- result[ 7 ] = tlc[ 1 ];
- result[ 6 ] = trc[ 1 ];
- result[ 5 ] = brc[ 1 ];
- result[ 4 ] = blc[ 1 ];
- }
-
- }
-
-/* Return the pointer. */
- return result;
-}
-
-static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) {
-/*
-* Name:
-* ClearAttrib
-
-* Purpose:
-* Clear an attribute value for a StcsChan.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void ClearAttrib( AstObject *this, const char *attrib, int *status )
-
-* Class Membership:
-* StcsChan member function (over-rides the astClearAttrib protected
-* method inherited from the Channel class).
-
-* Description:
-* This function clears the value of a specified attribute for a
-* StcsChan, so that the default value will subsequently be used.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* attrib
-* Pointer to a null terminated string specifying the attribute
-* name. This should be in lower case with no surrounding white
-* space.
-* status
-* Pointer to the inherited status variable.
-*/
-
-/* Local Variables: */
- AstStcsChan *this; /* Pointer to the StcsChan structure */
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* Obtain a pointer to the StcsChan structure. */
- this = (AstStcsChan *) this_object;
-
-/* Check the attribute name and clear the appropriate attribute. */
-
- if ( !strcmp( attrib, "stcsarea" ) ) {
- astClearStcsArea( this );
-
- } else if ( !strcmp( attrib, "stcscoords" ) ) {
- astClearStcsCoords( this );
-
- } else if ( !strcmp( attrib, "stcsprop" ) ) {
- astClearStcsProps( this );
-
- } else if ( !strcmp( attrib, "stcslength" ) ) {
- astClearStcsLength( this );
-
-/* If the attribute is still not recognised, pass it on to the parent
- method for further interpretation. */
- } else {
- (*parent_clearattrib)( this_object, attrib, status );
- }
-}
-
-static char *ContextFragment( WordContext *con, char **buf, int *status ){
-/*
-* Name:
-* ContextFragment
-
-* Purpose:
-* Returns a string holding a fragment of the document being read.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* char *ContextFragment( WordContext *con, char **buf, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function returns a pointer to a string that holds a fragment
-* of the STC-S document currently being read. The fragment ends at
-* the last word read by function GetNextWord, and starts a certain
-* number of words earlier in the document, as specified by the NEWORD
-* macro.
-
-* Parameters:
-* con
-* Pointer to the context structure, managed by GetNextWord.
-* buf
-* Address of a pointer to a dynamically allocated buffer. This
-* pointer should be NULL on the first call to this function, and
-* will be updated by this function. The pointer should be freed
-* using astFree when no longer needed.
-* status
-* Address of the inherited status value.
-
-* Returned Value:
-* A pointer to the buffer.
-*/
-
-/* Local Variables: */
- int i; /* Word count */
- int j; /* Word index */
- int nc; /* Text length */
-
-/* Initialise the number of characters written to the buffer. */
- nc = 0;
-
-/* Get the index of the first word to add to the buffer. The "next"
- component of the context structure holds the index at which the word
- returned by the next call to GetNextWord will be stored. So at the
- moment, this is the index of the oldest word in the cyclic list. */
- j = con->next;
-
-/* Loop round all non-NULL words in the cyclic list. */
- for( i = 0; i < NEWORD; i++ ) {
- if( con->words[ j ] ) {
-
-/* Append this word to the buffer, extending the buffer size as
- necessary. */
- *buf = astAppendString( *buf, &nc, con->words[ j ] );
-
-/* Append a trailingh space. */
- *buf = astAppendString( *buf, &nc, " " );
- }
-
-/* Increment the index of the next word to use in the cyclic list. Wrap
- back to zerp when the end of the list is reached. */
- if( ++j == NEWORD ) j = 0;
- }
-
-/* Remove the final trailing space. */
- if( nc ) (*buf)[ nc - 1 ] = 0;
-
-/* Return a pointer to the supplied buffer. */
- return *buf;
-}
-
-static void FreeContext( WordContext *con, int *status ){
-/*
-* Name:
-* FreeContext
-
-* Purpose:
-* Free the resources used by a word-reading context structure.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* voidFreeContext( WordContext *con, int *status );
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function frees the resources used by the supplied WordContext
-* structure. This structure is used by GetNextWord to keep track of
-* which word to return next.
-*
-* This function frees the dynamic memory pointers stored within the
-* WordContext structure, but does not free the memory holding the
-* WordContext structure itself.
-
-* Parameters:
-* con
-* Pointer to a structure holding the context.
-* status
-* Pointer to the inherited status variable.
-
-*/
-
-/* Local Variables: */
- int i; /* Word index */
-
-/* Check the supplied pointer. */
- if ( !con ) return;
-
-/* Free the resources. */
- con->line = astFree( con->line );
-
- for( i = 0; i < NEWORD; i++ ) {
- con->words[ i ] = astFree( con->words[ i ] );
- }
-
-}
-
-static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) {
-/*
-* Name:
-* GetAttrib
-
-* Purpose:
-* Get the value of a specified attribute for a StcsChan.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* const char *GetAttrib( AstObject *this, const char *attrib, int *status )
-
-* Class Membership:
-* StcsChan member function (over-rides the protected astGetAttrib
-* method inherited from the Channel class).
-
-* Description:
-* This function returns a pointer to the value of a specified
-* attribute for a StcsChan, formatted as a character string.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* attrib
-* Pointer to a null terminated string containing the name of
-* the attribute whose value is required. This name should be in
-* lower case, with all white space removed.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* - Pointer to a null terminated string containing the attribute
-* value.
-
-* Notes:
-* - The returned string pointer may point at memory allocated
-* within the StcsChan, or at static memory. The contents of the
-* string may be over-written or the pointer may become invalid
-* following a further invocation of the same function or any
-* modification of the StcsChan. A copy of the string should
-* therefore be made if necessary.
-* - A NULL pointer will be returned if this function is invoked
-* with the global error status set, or if it should fail for any
-* reason.
-*/
-
-/* Local Variables: */
- astDECLARE_GLOBALS /* Declare the thread specific global data */
- AstStcsChan *this; /* Pointer to the StcsChan structure */
- const char *result; /* Pointer value to return */
- int ival; /* Integer attribute value */
-
-/* Initialise. */
- result = NULL;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Get a pointer to the structure holding thread-specific global data. */
- astGET_GLOBALS(this_object);
-
-/* Obtain a pointer to the StcsChan structure. */
- this = (AstStcsChan *) this_object;
-
-/* Compare "attrib" with each recognised attribute name in turn,
- obtaining the value of the required attribute. If necessary, write
- the value into "getattrib_buff" as a null terminated string in an appropriate
- format. Set "result" to point at the result string. */
-
-/* StcsArea. */
-/* --------- */
- if ( !strcmp( attrib, "stcsarea" ) ) {
- ival = astGetStcsArea( this );
- if ( astOK ) {
- (void) sprintf( getattrib_buff, "%d", ival );
- result = getattrib_buff;
- }
-
-/* StcsCoords. */
-/* ----------- */
- } else if ( !strcmp( attrib, "stcscoords" ) ) {
- ival = astGetStcsCoords( this );
- if ( astOK ) {
- (void) sprintf( getattrib_buff, "%d", ival );
- result = getattrib_buff;
- }
-
-
-/* StcsProps. */
-/* ---------- */
- } else if ( !strcmp( attrib, "stcsprops" ) ) {
- ival = astGetStcsProps( this );
- if ( astOK ) {
- (void) sprintf( getattrib_buff, "%d", ival );
- result = getattrib_buff;
- }
-
-/* StcsLength */
-/* --------- */
- } else if ( !strcmp( attrib, "stcslength" ) ) {
- ival = astGetStcsLength( this );
- if ( astOK ) {
- (void) sprintf( getattrib_buff, "%d", ival );
- result = getattrib_buff;
- }
-
-/* If the attribute name was not recognised, pass it on to the parent
- method for further interpretation. */
- } else {
- result = (*parent_getattrib)( this_object, attrib, status );
- }
-
-/* Return the result. */
- return result;
-
-}
-
-static void GetFmt( const char *key, AstKeyMap *props, int i, int defdigs,
- char *fmt, int *status ){
-/*
-* Name:
-* GetFmt
-
-* Purpose:
-* Decide how many digits to use when formatting a numerical STC-S
-* property value.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void GetFmt( const char *key, AstKeyMap *props, int i,
-* int defdigs, char *fmt, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function locates the named property in the supplied KeyMap. If
-* it is found, a printf format specifier is generated that matches
-* the value is determined and returned. Otherwise, a default format
-* specified based on the supplied default number of digits is returned.
-
-* Parameters:
-* key
-* The key name associated with the property.
-* km
-* Pointer to a KeyMap containing the STC-S properties.
-* i
-* For vector values, this is the index of the vector element to be
-* checked. Should be zero for scalar values. If "i" is greater
-* than the number of values in the vector, then the number of digits
-* in the first element is found and returned.
-* defdigs
-* The value to return if the KeyMap does not contain an entry with
-* the supplied key.
-* fmt
-* Pointer to a string in which to return the format specifier.
-* status
-* Pointer to the inherited status variable.
-
-*/
-
-/* Local Variables: */
- const char *dot; /* Pointer to decimal point */
- const char *p; /* Pointer to next character */
- const char *word; /* Property value */
- int after0; /* Digits after the decimal point in first word */
- int after; /* Digits after the decimal point in current word */
- int before0; /* Digits before the decimal point in first word */
- int before; /* Digits before the decimal point in current word */
- int exp0; /* Was an exponent found in first word? */
- int exp; /* Was an exponent found in current word? */
- int j; /* Index of current word */
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* Initialise. */
- exp = 1;
- before = defdigs;
- after = 0;
- exp0 = 0;
- before0 = 0;
- after0 = 0;
-
-/* If the KeyMap contains the required property... */
- if( astMapGet0C( props, key, &word ) ) {
-
-/* Skip over the words in the string. */
- p = word;
- for( j = 0; j <= i; j++ ) {
-
-/* Find the next space or terminating null at the end of the current word.
- Also count the number of digits before and after the decimal point and
- see if the word includes an exponent. */
- exp = 0;
- before = 0;
- after = 0;
- dot = NULL;
-
- while( *p != 0 && *p != ' ' ) {
- if( ! exp ) {
- if( isdigit( *p ) ) {
- if( dot ) {
- after++;
- } else {
- before++;
- }
-
- } else if( *p == '.' ) {
- dot = p;
-
- } else if( *p == 'e' || *p == 'E' ) {
- exp = 1;
- }
- }
- p++;
- }
-
-/* Note the values for the first word. */
- if( j == 0 ) {
- exp0 = exp;
- before0 = before;
- after0 = after;
- }
-
-/* Find the following non-space marking the start of the next word,
- or the terminating null. */
- while( *p != 0 && *p == ' ' ) p++;
-
-/* If we find the terminating null before we have found the i'th word,
- break out of the loop using the first word instead of the i'th word. */
- if( *p == 0 ) {
- exp = exp0;
- before = before0;
- after = after0;
- break;
- }
- }
- }
-
- if( exp ) {
- sprintf( fmt, "%%.%dg", before + after );
- } else {
- sprintf( fmt, "%%.%df", after );
- }
-}
-
-static int GetIndent( AstChannel *this, int *status ) {
-/*
-* Name:
-* GetIndent
-
-* Purpose:
-* Get the value of the Indent attribute for a StcsChan.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* int GetIndent( AstChannel *this, int *status )
-
-* Class Membership:
-* StcsChan member function (over-rides the protected astGetIndent
-* method inherited from the Channel class).
-
-* Description:
-* This function returns the value of the Indent attribute, supplying
-* a default value appropriate to an StcsChan.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* - The Indent value to use.
-
-*/
-
-/* If the attribute is set, return its value. Otherwise return a value of
- zero. */
- return astTestIndent( this ) ? (*parent_getindent)( this, status ) : 0;
-}
-
-static const char *GetNextWord( AstStcsChan *this, WordContext *con,
- int *status ){
-/*
-* Name:
-* GetNextWord
-
-* Purpose:
-* Get a pointer to the next input word read from an STC-S source.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* const char *GetNextWord( AstStcsChan *this, WordContext *con,
-* int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function returns a pointer to the next word of an STC-S
-* description.
-
-* Parameters:
-* this
-* Pointer to the StcsChan, or NULL (to initialise "con").
-* con
-* Pointer to a structure holding context. The structure should be
-* initialised by calling this function with a NULL "this" pointer
-* before making further use of this function. When finished, it
-* should be released using FreeContext.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* A pointer to the new word. NULL is returned if an error has already
-* occurred, of if "this" is NULL.
-*/
-
-/* Local Variables: */
- const char *result; /* Returned pointer. */
- int i; /* Word index */
- size_t len; /* Word length */
-
-/* Initialise. */
- result = NULL;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* If no StcChan was supplied, initialise the supplied WordContext. */
- if( !this ) {
- con->e = NULL;
- con->line = NULL;
- con->done = 0;
- con->next = 0;
- con->wnext = NULL;
- con->close = 0;
- con->open = 0;
- for( i = 0; i < NEWORD; i++ ) con->words[ i ] = NULL;
-
-/* Words that end with an opening parenthesis are treated as two words. If the
- previous word ended in an opening parenthesis, it will have been removed by
- the previous call to this function and the "con->open" flag set. In
- this case, we just return a pointer to the second of the two words - a
- single "(" character - and clear the "con->open" flag. */
- } else if( con->open && ! con->done ) {
- con->open = 0;
- result = "(";
-
-/* Likewise deal with words that end with a closing parenthesis. */
- } else if( con->close && ! con->done ) {
- con->close = 0;
- result = ")";
-
-/* Words that begin with an opening parenthesis are treated as two words. If
- the previous word was such an opening parenthesis, the rest of the word
- will have been removed by the previous call to this function and the
- "con->wnext" pointer set to the start of the remaining word. In
- this case, re-instate the original character that was replaced by a
- terminating null when the previous word was returned, return the
- "con->wnext" pointer, and then clear the pointer. */
- } else if( con->wnext && ! con->done ) {
- *(con->wnext) = con->f;
- result = con->wnext;
- con->wnext = NULL;
-
-/* Otherwise... */
- } else {
-
-/* If the previous invocation of this function converted a space
- character into a null character, change it back again. */
- if( con->e ) *(con->e) = ' ';
-
-/* Get a pointer to the next non-white character in the current line of
- input text. */
- result = con->e;
- if( result ) {
- while( *result && isspace( *result ) ) result++;
- }
-
-/* If we have exhausted the current line, get the next line by invoking
- the source function. We loop until we read a line that is not entirely
- blank. */
- while( ( !result || ! *result ) && astOK ) {
-
-/* First free the memory holding the previous line. */
- if( con->line ) con->line = astFree( con->line );
- con->e = NULL;
-
-/* Get the next line of text from the source function. */
- con->line = astGetNextText( this );
- result = con->line;
-
-/* Break when we reach the end of the input text. */
- if( !result ) break;
-
-/* Get a pointer to the first non-white character in the new line. */
- while( *result && isspace( *result ) ) result++;
- }
-
-/* Find the end of the word. */
- if( result && *result ) {
- con->e = (char *) result + 1;
- while( *(con->e) && !isspace( *(con->e) ) ) (con->e)++;
-
-/* If the word is already null-terminated, nullify the "e" pointer to
- indicate this. Otherwise, change the white-space character into a
- null. */
- if( *(con->e) ) {
- *(con->e) = 0;
- len = con->e - result;
- } else {
- con->e = NULL;
- len = strlen( result );
- }
-
-/* Add the word into the cyclic list of words used to form a document
- fragment to include in error and warning messages. */
- con->words[ con->next ] = astStore( con->words[ con->next ],
- result, len + 1 );
- if( ++(con->next) == NEWORD ) con->next = 0;
-
-/* Deal with words that include an opening or closing parenthesis at
- start or end. These words must have 2 or more characters. */
- if( len > 1 ) {
-
-/* If the word ends with an opening parenthesis, replace the parenthesis
- with a null character and set a flag indicating that the next word
- returned should consist of just an opening parenthesis. */
- if( result[ len - 1 ] == '(' ) {
- ((char *) result)[ len - 1 ] = 0;
- con->open = 1;
-
-/* If the word ends with a closing parenthesis, replace the parenthesis
- with a null character and set a flag indicating that the next word
- returned should consist of just a closing parenthesis. */
- } else if( result[ len - 1 ] == ')' ) {
- ((char *) result)[ len - 1 ] = 0;
- con->close = 1;
-
-/* If the word starts with an opening parenthesis, replace the parenthesis
- with a null character and set a flag indicating that the next word
- returned should consist of just a closing parenthesis. */
- } else if( result[ 0 ] == '(' ) {
- con->wnext = ( (char *) result ) + 1;
- con->f = *(con->wnext);
- *(con->wnext) = 0;
- }
- }
-
-/* If we have run out of input words, but we have not yet finished
- interpreting the previous word returned, return a null string, rather
- than a null pointer in order to allow further interpretation of the
- previous word. */
- } else if( ! con->done ) {
- result = "";
- }
- }
-
-/* Return the pointer to the next word. */
- return result;
-}
-
-static int GetRegionProps( AstStcsChan *this, AstRegion *spreg,
- AstKeyMap *spprops, int nspace, int defdigs,
- double scale, int issky, int *status ) {
-/*
-* Name:
-* GetRegionProps
-
-* Purpose:
-* Create STC-S properties to describe a given Region and store in a
-* KeyMap.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* int GetRegionProps( AstStcsChan *this, AstRegion *spreg,
-* AstKeyMap *spprops, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function creates a set of STC-S properties to describe the
-* supplied spatial (2D) Region, and stores them in the supplied KeyMap.
-
-* Parameters:
-* this
-* The StcsChan being used.
-* spreg
-* The 2-D spatial Region to be described.
-* spprops
-* A KeyMap in which to store the created properties.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* Returns the integer code for the spatial region, or NULL_ID if the
-* properties could not be created for any reason.
-
-*/
-
-
-/* Local Variables: */
- AstKeyMap *new_props; /* KeyMap holding component Region properties */
- AstMapping *sreg; /* Simplified Region */
- AstRegion **reg_list; /* Array of component Regioon pointers */
- char *prop; /* Formatted property string */
- char buf[ 100 ]; /* Buffer for formatted values */
- char fmt[ 10 ]; /* Buffer for format specifier */
- double *p; /* Pointer to next axis value */
- double *points; /* Pointer to array of Region axis values */
- double a; /* Circle or ellipse radius */
- double angle; /* Ellipse position angle */
- double b; /* Ellipse radius */
- double centre[ 3 ]; /* Circle or ellipse centre */
- double lbnd[ 3 ]; /* Region lower bounds */
- double ubnd[ 3 ]; /* Region upper bounds */
- int i; /* Loop index */
- int j; /* Loop index */
- int nc; /* Number of characters in "prop" string */
- int np; /* Number of points defining the Region */
- int nreg; /* Number of component Regions */
- int ok; /* Can the Region be written out? */
- int oper; /* Code for CmpRegion boolean operator */
- int spaceid; /* Identifier for STC-S spatial region type */
-
-/* Check inherited status */
- if( !astOK ) return NULL_ID;
-
-/* Initialise */
- spaceid = NULL_ID;
- ok = 1;
- prop = NULL;
-
-/* If the Region has been negated, temporarily negate the Region, and
- write its properties into a new KeyMap by calling this function
- recursively. Then store the new KeyMap in the supplied KeyMap. */
- if( astGetNegated( spreg ) ) {
- spaceid = NOT_ID;
- astNegate( spreg );
- new_props = astKeyMap( " ", status );
-
- if( GetRegionProps( this, spreg, new_props, nspace, defdigs,
- scale, issky, status ) == NULL_ID ) ok = 0;
-
- astMapPut0C( spprops, "ID", "Not", NULL );
- astMapPut0A( spprops, "REGION1", new_props, NULL );
- astMapPut0I( spprops, "NREG", 1, NULL );
- astNegate( spreg );
-
-/* Store properties that are specific to AllSky sub-phrases (i.e. none)... */
- } else if( astIsANullRegion( spreg ) && astGetNegated( spreg ) ) {
- spaceid = ALLSKY_ID;
- astMapPut0C( spprops, "ID", "AllSky", NULL );
-
-/* Store properties that are specific to Circle sub-phrases... */
- } else if( astIsACircle( spreg ) ) {
- spaceid = CIRCLE_ID;
- astMapPut0C( spprops, "ID", "Circle", NULL );
-
-/* Get the geometric parameters of the Circle. */
- astCirclePars( spreg, centre, &a, NULL );
-
-/* Create a string holding the formatted centre axis values, scaling
- to the required units. Use the Frame's Digits attribute to specify
- how many digits to use when formatting the axis values. */
- nc = 0;
- for( i = 0; i < nspace; i++ ) {
- if( centre[ i ] != AST__BAD ) {
- GetFmt( "CENTRE", spprops, i, defdigs, fmt, status );
- (void) sprintf( buf, fmt, scale*centre[ i ] );
- prop = astAppendString( prop, &nc, buf );
- prop = astAppendString( prop, &nc, " " );
-
- } else {
- ok = 0;
- astAddWarning( this, 1, "The supplied Circle contains "
- "one or more bad centre axis values.",
- "astWrite", status );
- break;
- }
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- prop[ nc - 1 ] = 0;
- astMapPut0C( spprops, "CENTRE", prop, NULL );
-
-/* Scale, format and store the radius. */
- if( a != AST__BAD ) {
- GetFmt( "RADIUS", spprops, 0, defdigs, fmt, status );
- (void) sprintf( buf, fmt, scale*a );
- astMapPut0C( spprops, "RADIUS", buf, NULL );
- } else {
- ok = 0;
- astAddWarning( this, 1, "The supplied Circle has an "
- "undefined radius.", "astWrite", status );
- }
-
-/* Store properties that are specific to PositionInterval sub-phrases... */
- } else if( astIsAInterval( spreg ) || astIsABox( spreg ) ) {
- spaceid = POSITION_INTERVAL_ID;
- astMapPut0C( spprops, "ID", "PositionInterval", NULL );
-
-/* Get the bounds of the Region. */
- astGetRegionBounds( spreg, lbnd, ubnd );
-
-/* Create a string holding the formatted low limits, scaling to the
- required units. Use the Frame's Digits attribute to specify how
- many digits to use when formatting the axis values. */
- nc = 0;
- for( i = 0; i < nspace; i++ ) {
- if( lbnd[ i ] == AST__BAD || lbnd[ i ] == DBL_MAX ||
- lbnd[ i ] == -DBL_MAX ) {
- astAddWarning( this, 1, "Spatial axis %d has an undefined "
- "lower limit.", "astWrite", status, i + 1 );
- ok = 0;
- break;
- } else {
- GetFmt( "LOLIMIT", spprops, i, defdigs, fmt, status );
- (void) sprintf( buf, fmt, scale*lbnd[ i ] );
- prop = astAppendString( prop, &nc, buf );
- prop = astAppendString( prop, &nc, " " );
- }
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- prop[ nc - 1 ] = 0;
- astMapPut0C( spprops, "LOLIMIT", prop, NULL );
-
-/* Do the same for the upper limits. */
- nc = 0;
- for( i = 0; i < nspace; i++ ) {
- if( ubnd[ i ] == AST__BAD || ubnd[ i ] == DBL_MAX ||
- ubnd[ i ] == -DBL_MAX ) {
- astAddWarning( this, 1, "Spatial axis %d has an undefined "
- "upper limit.", "astWrite", status, i + 1 );
- ok = 0;
- break;
- } else {
- GetFmt( "HILIMIT", spprops, i, defdigs, fmt, status );
- (void) sprintf( buf, fmt, scale*ubnd[ i ] );
- prop = astAppendString( prop, &nc, buf );
- prop = astAppendString( prop, &nc, " " );
- }
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- prop[ nc - 1 ] = 0;
- astMapPut0C( spprops, "HILIMIT", prop, NULL );
-
-/* Store properties that are specific to Ellipse sub-phrases... */
- } else if( astIsAEllipse( spreg ) ) {
- spaceid = ELLIPSE_ID;
- astMapPut0C( spprops, "ID", "Ellipse", NULL );
-
-/* Get the geometric parameters of the Ellipse. */
- astEllipsePars( spreg, centre, &a, &b, &angle, NULL, NULL );
-
-/* Create a string holding the formatted centre axis values, scaling
- to the required units. Use the Frame's Digits attribute to specify
- how many digits to use when formatting the axis values. */
- nc = 0;
- for( i = 0; i < nspace; i++ ) {
- if( centre[ i ] != AST__BAD ) {
- GetFmt( "CENTRE", spprops, i, defdigs, fmt, status );
- (void) sprintf( buf, fmt, scale*centre[ i ] );
- prop = astAppendString( prop, &nc, buf );
- prop = astAppendString( prop, &nc, " " );
-
- } else {
- ok = 0;
- astAddWarning( this, 1, "The supplied Ellipse contains "
- "one or more bad centre axis values.",
- "astWrite", status );
- break;
- }
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- prop[ nc - 1 ] = 0;
- astMapPut0C( spprops, "CENTRE", prop, NULL );
-
-/* Scale, format and store the two radii. */
- if( a != AST__BAD && b != AST__BAD && angle != AST__BAD ) {
- GetFmt( "RADIUS1", spprops, 0, defdigs, fmt, status );
- (void) sprintf( buf, fmt, scale*a );
- astMapPut0C( spprops, "RADIUS1", buf, NULL );
-
- GetFmt( "RADIUS2", spprops, 0, defdigs, fmt, status );
- (void) sprintf( buf, fmt, scale*b );
- astMapPut0C( spprops, "RADIUS2", buf, NULL );
-
-/* Convert the angle to degrees in the direction required by STC-S,
- format and store. */
- angle *= AST__DR2D;
- if( !issky ) angle = 90 - angle;
- while( angle < 0.0 ) angle += 360.0;
- while( angle >= 360.0 ) angle -= 360.0;
-
- GetFmt( "POSANGLE", spprops, 0, defdigs, fmt, status );
- (void) sprintf( buf, fmt, angle );
- astMapPut0C( spprops, "POSANGLE", buf, NULL );
-
- } else {
- astAddWarning( this, 1, "The gemeotric parameters of the "
- "supplied Ellipse are undefined.",
- "astWrite", status );
- ok = 0;
- }
-
-/* Store properties that are specific to Polygon sub-phrases... */
- } else if( astIsAPolygon( spreg ) ) {
- spaceid = POLYGON_ID;
- astMapPut0C( spprops, "ID", "Polygon", NULL );
-
-/* Get an array holding the axis values at the polygon vertices. */
- astGetRegionPoints( spreg, 0, 0, &np, NULL );
- points = astMalloc( sizeof( double )*np*nspace );
- astGetRegionPoints( spreg, np, nspace, &np, points );
-
-/* Create a string holding the formatted vertex axis values, scaling
- to the required units. Use the Frame's Digits attribute to specify
- how many digits to use when formatting the axis values. */
- GetFmt( "VERTICES", spprops, 0, defdigs, fmt, status );
- nc = 0;
- for( j = 0; j < np; j++ ) {
- p = points + j;
- for( i = 0; i < nspace; i++ ) {
- if( *p != AST__BAD ) {
- (void) sprintf( buf, fmt, scale*(*p) );
- prop = astAppendString( prop, &nc, buf );
- prop = astAppendString( prop, &nc, " " );
- p += np;
- } else {
- astAddWarning( this, 1, "The supplied Polygon contains "
- "one or more bad axis values.", "astWrite",
- status );
- ok = 0;
- break;
- }
- }
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- prop[ nc - 1 ] = 0;
- astMapPut0C( spprops, "VERTICES", prop, NULL );
-
-/* Free resources. */
- points = astFree( points );
-
-/* Store properties that are specific to Position sub-phrases... */
- } else if( astIsAPointList( spreg ) ) {
- spaceid = POSITION_ID;
- astMapPut0C( spprops, "ID", "Position", NULL );
-
-/* Check the PointList contains only a single point. */
- astGetRegionPoints( spreg, 0, 0, &np, NULL );
- if( np > 1 ) {
- astAddWarning( this, 1, "The supplied PointList contains "
- "more than one position.", "astWrite", status );
- ok = 0;
-
-/* If so, get the axis values at the point. */
- } else {
- astGetRegionPoints( spreg, 1, nspace, &np, centre );
-
-/* Create a string holding the formatted axis values, scaling to the
- required units. Use the Frame's Digits attribute to specify how many
- digits to use when formatting the axis values. */
- nc = 0;
- for( i = 0; i < nspace; i++ ) {
- if( centre[ i ] != AST__BAD ) {
- GetFmt( "POSITION", spprops, i, defdigs, fmt, status );
- (void) sprintf( buf, fmt, scale*centre[ i ] );
- prop = astAppendString( prop, &nc, buf );
- prop = astAppendString( prop, &nc, " " );
-
- } else {
- astAddWarning( this, 1, "The supplied PointList contains "
- "one or more bad axis values.", "astWrite",
- status );
- ok = 0;
- break;
- }
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- prop[ nc - 1 ] = 0;
- astMapPut0C( spprops, "POSITION", prop, NULL );
- }
-
-/* Store properties that are specific to compound Position sub-phrases... */
- } else {
-
-/* If the Region is not a CmpRegion (e.g. a Prism?) see if simplifying it
- produces a CmpRegion. */
- if( !astIsACmpRegion( spreg ) ) {
- sreg = astSimplify( spreg );
- } else {
- sreg = astClone( spreg );
- }
-
-/* If we now have a CmpRegion, write its properties into a new KeyMap by
- calling this function recursively. Then store the new KeyMap in the
- supplied KeyMap. */
- if( astIsACmpRegion( sreg ) ) {
-
-/* Get the list of Regions that the CmpRegion combines together. This
- also returns the boolean operator with which they are combined. */
- nreg = 0;
- reg_list = NULL;
- oper = astCmpRegionList( (AstCmpRegion *) sreg, &nreg, &reg_list );
-
-/* Store compound region type in the supplied KeyMap. */
- if( oper == AST__AND ) {
- spaceid = INTERSECTION_ID;
- astMapPut0C( spprops, "ID", "Intersection", NULL );
- } else if( oper == AST__OR ) {
- spaceid = UNION_ID;
- astMapPut0C( spprops, "ID", "Union", NULL );
- } else {
- spaceid = DIFFERENCE_ID;
- astMapPut0C( spprops, "ID", "Difference", NULL );
- }
-
-/* Loop round each of the combined Regions. */
- for( i = 0; i < nreg; i++ ) {
-
-/* Create a new KeyMap, and then call this function recursively to store
- the properties of the i'th component Region in the new KeyMap. */
- if( ok ) {
- new_props = astKeyMap( " ", status );
- if( GetRegionProps( this, reg_list[ i ], new_props, nspace,
- defdigs, scale, issky, status )
- == NULL_ID ) ok = 0;
-
-/* Store the new KeyMap in the supplied KeyMap. */
- sprintf( buf, "REGION%d", i + 1 );
- astMapPut0A( spprops, buf, new_props, NULL );
-
-/* Free resources. */
- new_props = astAnnul( new_props );
- }
- reg_list[ i ] = astAnnul( reg_list[ i ] );
- }
- reg_list = astFree( reg_list );
- astMapPut0I( spprops, "NREG", nreg, NULL );
-
-/* All other classes of Region are unsupported. */
- } else {
- astAddWarning( this, 1, "The supplied %s cannot be written "
- "out since STC-S does not support %s regions.",
- "astWrite", status, astGetClass( spreg ),
- astGetClass( spreg ) );
- ok = 0;
- }
-
-/* Free resources. */
- sreg = astAnnul( sreg );
- }
-
- if( prop ) prop = astFree( prop );
-
-/* If an error has occurred, return NULL_ID. */
- if( !ok || !astOK ) spaceid = NULL_ID;
-
-/* Return the identifier for the STC-S spatial region type. */
- return spaceid;
-}
-
-void astInitStcsChanVtab_( AstStcsChanVtab *vtab, const char *name, int *status ) {
-/*
-*+
-* Name:
-* astInitStcsChanVtab
-
-* Purpose:
-* Initialise a virtual function table for an StcsChan.
-
-* Type:
-* Protected function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void astInitStcsChanVtab( AstStcsChanVtab *vtab, const char *name )
-
-* Class Membership:
-* StcsChan vtab initialiser.
-
-* Description:
-* This function initialises the component of a virtual function
-* table which is used by the StcsChan class.
-
-* Parameters:
-* vtab
-* Pointer to the virtual function table. The components used by
-* all ancestral classes will be initialised if they have not already
-* been initialised.
-* name
-* Pointer to a constant null-terminated character string which contains
-* the name of the class to which the virtual function table belongs (it
-* is this pointer value that will subsequently be returned by the Object
-* astClass function).
-*-
-*/
-
-/* Local Variables: */
- astDECLARE_GLOBALS /* Pointer to thread-specific global data */
- AstObjectVtab *object; /* Pointer to Object component of Vtab */
- AstChannelVtab *channel; /* Pointer to Channel component of Vtab */
-
-/* Check the local error status. */
- if ( !astOK ) return;
-
-/* Get a pointer to the thread specific global data structure. */
- astGET_GLOBALS(NULL);
-
-/* Initialize the component of the virtual function table used by the
- parent class. */
- astInitChannelVtab( (AstChannelVtab *) vtab, name );
-
-/* Store a unique "magic" value in the virtual function table. This
- will be used (by astIsAStcsChan) to determine if an object belongs
- to this class. We can conveniently use the address of the (static)
- class_check variable to generate this unique value. */
- vtab->id.check = &class_check;
- vtab->id.parent = &(((AstChannelVtab *) vtab)->id);
-
-/* Initialise member function pointers. */
-/* ------------------------------------ */
-
- vtab->ClearStcsArea = ClearStcsArea;
- vtab->GetStcsArea = GetStcsArea;
- vtab->SetStcsArea = SetStcsArea;
- vtab->TestStcsArea = TestStcsArea;
-
- vtab->ClearStcsCoords = ClearStcsCoords;
- vtab->GetStcsCoords = GetStcsCoords;
- vtab->SetStcsCoords = SetStcsCoords;
- vtab->TestStcsCoords = TestStcsCoords;
-
- vtab->ClearStcsProps = ClearStcsProps;
- vtab->GetStcsProps = GetStcsProps;
- vtab->SetStcsProps = SetStcsProps;
- vtab->TestStcsProps = TestStcsProps;
-
- vtab->SetStcsLength = SetStcsLength;
- vtab->ClearStcsLength = ClearStcsLength;
- vtab->TestStcsLength = TestStcsLength;
- vtab->GetStcsLength = GetStcsLength;
-
-/* Save the inherited pointers to methods that will be extended, and
- replace them with pointers to the new member functions. */
- object = (AstObjectVtab *) vtab;
- channel = (AstChannelVtab *) vtab;
-
- parent_clearattrib = object->ClearAttrib;
- object->ClearAttrib = ClearAttrib;
- parent_getattrib = object->GetAttrib;
- object->GetAttrib = GetAttrib;
- parent_setattrib = object->SetAttrib;
- object->SetAttrib = SetAttrib;
- parent_testattrib = object->TestAttrib;
- object->TestAttrib = TestAttrib;
-
- channel->Write = Write;
- channel->Read = Read;
-
- parent_getindent = channel->GetIndent;
- channel->GetIndent = GetIndent;
-
-/* Declare the Dump function for this class. There is no destructor or
- copy constructor. */
- astSetDump( vtab, Dump, "StcsChan", "STC-S I/O Channel" );
-
-/* If we have just initialised the vtab for the current class, indicate
- that the vtab is now initialised, and store a pointer to the class
- identifier in the base "object" level of the vtab. */
- if( vtab == &class_vtab ) {
- class_init = 1;
- astSetVtabClassIdentifier( vtab, &(vtab->id) );
- }
-}
-
-static AstRegion *MakeSpaceRegion( AstKeyMap *props, AstFrame *frm,
- double scale, int *status ){
-/*
-* Name:
-* MakeSpaceRegion
-
-* Purpose:
-* Create a Region to describe the space coverage of the STC-S
-* description being read.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* AstRegion *MakeSpaceRegion( AstKeyMap *props, AstFrame *frm,
-* double scale, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function returns a pointer to a new Region that describes the
-* spatial coverage of an STC-S description.
-
-* Parameters:
-* props
-* A KeyMap holding properties read from the STC-S space sub-phrase.
-* frm
-* The Frame in which the Region is to be defined.
-* scale
-* A factor that must be applied to the raw axis values read from the
-* STC-S description in order to convert them into the units used by
-* the supplied Frame.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* The Region pointer.
-
-*/
-
-
-/* Local Variables: */
- AstKeyMap *reg_props; /* KeyMap holding argument properties */
- AstRegion *reg; /* Current argument Region */
- AstRegion *result; /* Returned Region */
- AstRegion *tmp; /* Temporary Region pointer */
- char key[ 20 ]; /* Key for argument region */
- const char *id; /* Sub-phrase identifier */
- double *p; /* Pointer to next axis value */
- double *temp; /* Pointer to array of reordered polygon vertex axis values */
- double *vertices; /* Pointer to array of polygon vertex axis values */
- double val1; /* Scalar value read from KeyMap */
- double val2; /* Scalar value read from KeyMap */
- double val3; /* Scalar value read from KeyMap */
- double vec1[ 10 ]; /* Vector read from KeyMap */
- double vec2[ 10 ]; /* Vector read from KeyMap */
- int iaxis; /* Axis index */
- int ireg; /* Index of argument regions */
- int ivert; /* Vertex index */
- int naxes; /* Number of spatial axes */
- int nreg; /* Number of argument regions */
- int nval; /* Number of values read from KeyMap */
- int nvert; /* Number of vertices */
- int spaceid; /* Integer identifier for spatial shape */
- int oper; /* Boolean operator code for CmpRegion */
-
-/* Initialise */
- result = NULL;
-
-/* Check inherited status */
- if( !astOK ) return result;
-
-/* Temporarily ensure that an error is reported if an attempt is made to
- access a non-existent KeyMap entry. */
- astSetKeyError( props, 1 );
-
-/* Get the space sub-phrase identifier from the properties KeyMap, and
- find the corresponding integer identifier. */
-
- astMapGet0C( props, "ID", &id );
- spaceid = SpaceId( id, status );
-
-/* Get the number of axes in the Frame. */
- naxes = astGetNaxes( frm );
-
-/* Create a suitable Region to enclose the space positions. This
- includes scaling the supplied axis values to the units used by
- the Frame. */
- if( spaceid == POSITION_INTERVAL_ID ) {
- astMapGet1D( props, "DLOLIMIT", naxes, &nval, vec1 );
- astMapGet1D( props, "DHILIMIT", naxes, &nval, vec2 );
-
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vec1[ iaxis ] *= scale;
- vec2[ iaxis ] *= scale;
- }
-
- result = (AstRegion *) astBox( frm, 1, vec1, vec2, NULL, " ", status );
-
- } else if( spaceid == ALLSKY_ID ) {
- result = (AstRegion *) astNullRegion( frm, NULL, "Negated=1", status );
-
- } else if( spaceid == CIRCLE_ID ) {
- astMapGet1D( props, "DCENTRE", naxes, &nval, vec1 );
- astMapGet0D( props, "RADIUS", &val1 );
- for( iaxis = 0; iaxis < naxes; iaxis++ ) vec1[ iaxis ] *= scale;
- val1 *= scale;
- result = (AstRegion *) astCircle( frm, 1, vec1, &val1, NULL, " ",
- status );
-
- } else if( spaceid == ELLIPSE_ID ) {
- astMapGet1D( props, "DCENTRE", naxes, &nval, vec1 );
- astMapGet0D( props, "RADIUS1", &val1 );
- astMapGet0D( props, "RADIUS2", &val2 );
- astMapGet0D( props, "POSANGLE", &val3 );
- for( iaxis = 0; iaxis < naxes; iaxis++ ) vec1[ iaxis ] *= scale;
- vec2[ 0 ] = val1*scale;
- vec2[ 1 ] = val2*scale;
- if( !astIsASkyFrame( frm ) ) val3 = 90.0 - val3;
- val3 *= AST__DD2R;
- result = (AstRegion *) astEllipse( frm, 1, vec1, vec2, &val3, NULL, " ",
- status );
-
- } else if( spaceid == BOX_ID ) {
- astMapGet1D( props, "DCENTRE", naxes, &nval, vec1 );
- astMapGet1D( props, "DBSIZE", naxes, &nval, vec2 );
-
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vec1[ iaxis ] *= scale;
- vec2[ iaxis ] *= scale;
- }
-
- vertices = BoxCorners( frm, vec1, vec2, status );
- result = (AstRegion *) astPolygon( frm, 4, 4, vertices, NULL, " ",
- status );
- vertices = astFree( vertices );
-
- } else if( spaceid == POLYGON_ID ) {
- nval = astMapLength( props, "DVERTICES" );
- temp = astMalloc( sizeof( double )*nval );
- astMapGet1D( props, "DVERTICES", nval, &nval, temp );
-
-/* An STC-S polygon description holds the vertex axis values in the wrong
- order for the AstPolygon constructor. Therefore, transpose the temp
- array (scale them at the same time). */
- vertices = astMalloc( sizeof( double )*nval );
- if( astOK ) {
- nvert = nval/naxes;
- p = temp;
- for( ivert = 0; ivert < nvert; ivert++ ) {
- for( iaxis = 0; iaxis < naxes; iaxis++,p++ ) {
- vertices[ iaxis*nvert + ivert ] = *p*scale;
- }
- }
-
- result = (AstRegion *) astPolygon( frm, nvert, nvert, vertices, NULL,
- " ", status );
- }
-
- vertices = astFree( vertices );
- temp = astFree( temp );
-
- } else if( spaceid == POSITION_ID ) {
- astMapGet1D( props, "DPOSITION", naxes, &nval, vec1 );
- for( iaxis = 0; iaxis < naxes; iaxis++ ) vec1[ iaxis ] *= scale;
- result = (AstRegion *) SinglePointList( frm, vec1, NULL, status );
-
- } else if( spaceid == CONVEX_ID ) {
- astError( AST__INTER, "astRead(StcsChan): No support for Convex in "
- "MakeSpaceRegion (internal AST programming error).", status );
-
-/* All remaining valid space id values are compound - their arguments are held
- within separate KeyMaps nested inside the supplied KeyMap. */
- } else if( spaceid != NULL_ID ) {
-
-/* The number of arguments is defined in the NREG entry. */
- astMapGet0I( props, "NREG", &nreg );
-
-/* Get the CmpRegion operator code. */
- if( spaceid == UNION_ID ) {
- oper = AST__OR;
- } else if( spaceid == INTERSECTION_ID ) {
- oper = AST__AND;
- } else if( spaceid == DIFFERENCE_ID ) {
- oper = AST__XOR;
- } else {
- oper = 0; /* To avoid compiler warnings */
- }
-
-/* Loop over all argument Regions. */
- for( ireg = 0; ireg < nreg; ireg++ ) {
-
-/* Get the KeyMap holding the STC-S properties of the current argument
- region. */
- sprintf( key, "REGION%d", ireg + 1 );
- astMapGet0A( props, key, &reg_props );
-
-/* Construct an AST Region from this list of STC-S properties. */
- reg = MakeSpaceRegion( reg_props, frm, scale, status );
-
-/* If we are creating a "Not" element, just negate the argument region
- and return it. */
- if( spaceid == NOT_ID ) {
- astNegate( reg );
- result = astClone( reg );
-
-/* If we are creating a "Union", "Difference" or "Intersection" element,
- combine the first two arguments into a CmpRegion, and then add in each
- subsequent argument. */
- } else {
- if( ireg == 0 ) {
- result = astClone( reg );
- } else {
- tmp = (AstRegion *) astCmpRegion( result, reg, oper, " ",
- status );
- (void) astAnnul( result );
- result = tmp;
- }
- }
-
-/* Free resources */
- reg = astAnnul( reg );
- reg_props = astAnnul( reg_props );
- }
- }
-
-/* Ensure that no error is reported if an attempt is made to access a
- non-existent KeyMap entry. */
- astSetKeyError( props, 0 );
-
-/* Return the Region. */
- return result;
-}
-
-static void MapPut0C( AstKeyMap *km, const char *key, const char *value,
- const char *def, int defs, int *status ){
-/*
-* Name:
-* MapPut0C
-
-* Purpose:
-* Store a text STC-S property in the supplied keymap.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void MapPut0C( AstKeyMap *km, const char *key, const char *value,
-* const char *def, int defs, int *status )
-
-* Class Membership:
-* StcsChan member function.
-
-* Description:
-* This function stors the supplied value in the given KeyMap,
-* handling default values.
-
-* Parameters:
-* km
-* Pointer to the KeyMap in which to store the value.
-* key
-* Pointer to a string holding the property name associated with
-* the value.
-* value
-* The property value. If this is NULL then the function
-* returns without action.
-* def
-* The default property value.
-* defs
-* If zero, then the value is not stored in the KeyMap if the value
-* is equal to the default value.
-* status
-* Pointer to the inherited status variable.
-
-*/
-
-/* Check the inherited status */
- if( !astOK ) return;
-
-/* If the value is NULL, ignore the entry. */
- if( value ) {
-
-/* If the value is equal to the default value, and we are NOT storing
- default values, ensure the KeyMap has no entry for the given key. */
- if( astChrMatch( value, def ) && !defs ) {
- astMapRemove( km, key );
-
-/* Otherwise, store the value. */
- } else {
- astMapPut0C( km, key, value, NULL );
- }
- }
-}
-
-static void MapPut0D( AstKeyMap *km, const char *key, double value, double def,
- int defs, int *status ){
-/*
-* Name:
-* MapPut0D
-
-* Purpose:
-* Store a floating point STC-S property in the supplied keymap.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void MapPut0D( AstKeyMap *km, const char *key, double value, double def,
-* int defs, int *status )
-
-* Class Membership:
-* StcsChan member function.
-
-* Description:
-* This function stors the supplied value in the given KeyMap,
-* handling default values.
-
-* Parameters:
-* km
-* Pointer to the KeyMap in which to store the value.
-* key
-* Pointer to a string holding the property name associated with
-* the value.
-* value
-* The property value. If this is AST__BAD then the function
-* returns without action.
-* def
-* The default property value.
-* defs
-* If zero, then the value is not stored in the KeyMap if the value
-* is equal to the default value.
-* status
-* Pointer to the inherited status variable.
-
-*/
-
-/* Check the inherited status */
- if( !astOK ) return;
-
-/* If the value is bad, ignore the entry. */
- if( value != AST__BAD ) {
-
-/* If the value is equal to the default value, and we are NOT storing
- default values, ensure the KeyMap has no entry for the given key. */
- if( value == def && !defs ) {
- astMapRemove( km, key );
-
-/* Otherwise, store the value. */
- } else {
- astMapPut0D( km, key, value, NULL );
- }
- }
-}
-
-static char *PutRegionProps( AstStcsChan *this, AstKeyMap *km, const char *id,
- int indent, char *line, int *nc, int *crem,
- int linelen, int *status ){
-/*
-* Name:
-* PutRegionProps
-
-* Purpose:
-* Append STC-S space sub-phrase properties to the end of a string.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* char *PutRegionProps( AstStcsChan *this, AstKeyMap *km, const char *id,
-* int indent, char *line, int *nc, int *crem,
-* int linelen, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function converts the STC-S properties for the space sub-phrase
-* supplied in a KeyMap into text, and appends them to the supplied
-* line of text in the order required by STC-S.
-*
-* It is assumed that the sub-phrase identifier has already been put
-* into the string.
-
-* Parameters:
-* this
-* The StcsChan.
-* km
-* Pointer to a KeyMap containing the STC-S properties.
-* id
-* Pointer to the sub-phrase identifier.
-* indent
-* If greater than or equal to zero, then it gives the number of
-* spaces indentation to place before the first word (also indicates
-* that a new-line should follow the last word of the argument). If
-* negative, never use indentation.
-* line
-* Pointer to the buffer to receive the property values.
-* nc
-* Pointer to an int in which to store the number of characaters in
-* the buffer. Updated on exit.
-* crem
-* Pointer to an int in which to store the maximum number of
-* characters before a new line. Ignored if zero. Updated on exit.
-* linelen
-* The maximum number of character per line, or zero if all text is
-* to be included in a single line.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* A pointer to the buffer. This will usually be "line", but may be
-* different to "line" if it was necessary to expand the memory to make
-* room for new properties.
-
-*/
-
-/* Local Variables: */
- AstKeyMap *reg_props;
- char *result;
- char key[ 20 ];
- int i;
- int ireg;
- int nreg;
- int spaceid;
-
-/* Initialise */
- result = line;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Temporarily ensure that an error is reported if an attempt is made to
- access a non-existent KeyMap entry. */
- astSetKeyError( km, 1 );
-
-/* Get the integer code for the space sub-phrase identifier. */
- spaceid = SpaceId( id, status );
-
-/* Do each type of space sub-phrase. */
- if( spaceid == NULL_ID ) {
- astError( AST__INTER, "astWrite(StcsChan): Illegal 'spaceid' value "
- "in function PutRegionProps (internal AST programming "
- "error).", status );
-
- } else if( spaceid == POSITION_INTERVAL_ID ) {
- result = AddItem( this, km, "LOLIMIT", NULL, result, nc, crem, linelen, status );
- result = AddItem( this, km, "HILIMIT", NULL, result, nc, crem, linelen, status );
-
- } else if( spaceid == ALLSKY_ID ) {
-
- } else if( spaceid == CIRCLE_ID ) {
- result = AddItem( this, km, "CENTRE", NULL, result, nc, crem, linelen, status );
- result = AddItem( this, km, "RADIUS", NULL, result, nc, crem, linelen, status );
-
- } else if( spaceid == ELLIPSE_ID ) {
- result = AddItem( this, km, "CENTRE", NULL, result, nc, crem, linelen, status );
- result = AddItem( this, km, "RADIUS1", NULL, result, nc, crem, linelen, status );
- result = AddItem( this, km, "RADIUS2", NULL, result, nc, crem, linelen, status );
- result = AddItem( this, km, "POSANGLE", NULL, result, nc, crem, linelen, status );
-
- } else if( spaceid == BOX_ID ) {
- result = AddItem( this, km, "CENTRE", NULL, result, nc, crem, linelen, status );
- result = AddItem( this, km, "BSIZE", NULL, result, nc, crem, linelen, status );
-
- } else if( spaceid == POLYGON_ID ) {
- result = AddItem( this, km, "VERTICES", NULL, result, nc, crem, linelen, status );
-
- } else if( spaceid == CONVEX_ID ) {
- astError( AST__INTER, "astWrite(StcsChan): No Convex support yet "
- "(internal AST programming error).", status );
-
- } else if( spaceid == POSITION_ID ) {
- result = AddItem( this, km, "POSITION", NULL, result, nc, crem, linelen, status );
-
-/* All remaining space id values are compound regions. */
- } else {
-
-/* Append an opening parenthesis. */
- result = astAppendString( result, nc, "( " );
-
-/* If required, write out the text through the Channel sink function,
- and start a new line. */
- if( indent >= 0 ) {
- astPutNextText( this, result );
- *nc = 0;
- *crem = linelen;
- }
-
-/* Set the indentation for the next level down. */
- if( indent == 0 ) {
- indent = 6;
- } else if( indent > 0 ){
- indent += 3;
- }
-
-/* Loop round all argument Regions. */
- astMapGet0I( km, "NREG", &nreg );
- for( ireg = 0; ireg < nreg; ireg++ ) {
- sprintf( key, "REGION%d", ireg + 1 );
- astMapGet0A( km, key, &reg_props );
-
-/* Put any required indentation at the start of the line. */
- if( indent > 0 ) {
- for( i = 0; i < indent; i++ ) {
- result = astAppendString( result, nc, " " );
- }
- *crem -= indent;
- }
-
-/* Append the identifier for the next argument to the string. */
- result = AddItem( this, reg_props, "ID", NULL, result, nc, crem,
- linelen, status );
-
-/* Append the arguments to the string. */
- astMapGet0C( reg_props, "ID", &id );
- result = PutRegionProps( this, reg_props, id, indent, result, nc,
- crem, linelen, status );
-
-/* Write the text out to the sink function, and start a new line. */
- if( indent > 0 ) {
- astPutNextText( this, result );
- *nc = 0;
- *crem = linelen;
- }
-
-/* Free resources. */
- reg_props = astAnnul( reg_props );
- }
-
-/* Decrease any indentation, and then append a closing parenthesis. */
- if( indent > 2 ) {
- indent -= 3;
- for( i = 0; i < indent; i++ ) {
- result = astAppendString( result, nc, " " );
- }
- }
- result = astAppendString( result, nc, ") " );
-
-/* If we are about to return fomr the top-level, start a new line. */
- if( indent > 0 && indent < 6 ) {
- astPutNextText( this, result );
- *nc = 0;
- for( i = 0; i < indent; i++ ) {
- result = astAppendString( result, nc, " " );
- }
- *crem = linelen - indent;
- }
- }
-
-/* Ensure that no error is reported if an attempt is made to access a
- non-existent KeyMap entry. */
- astSetKeyError( km, 0 );
-
-/* Return the buffer pointer. */
- return result;
-}
-
-static AstObject *Read( AstChannel *this_channel, int *status ) {
-/*
-* Name:
-* Read
-
-* Purpose:
-* Read an Object from a Channel.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* AstObject *Read( AstChannel *this_channel, int *status )
-
-* Class Membership:
-* StcsChan member function (over-rides the astRead method
-* inherited from the Channel class).
-
-* Description:
-* This function reads an Object from an StcsChan.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* A pointer to the new Object.
-*/
-
-/* Local Variables: */
- AstFrame *spacefrm; /* Pointer to SpaceFrame for space sub-phrase */
- AstFrameSet *fs; /* Temporary FrameSet */
- AstKeyMap *full_props; /* KeyMap holding all sub-phrase properties */
- AstKeyMap *props; /* KeyMap holding current sub-phrase properties */
- AstObject *new; /* Pointer to returned Object */
- AstObject *obj; /* Pointer to Object extracted from a KeyMap */
- AstPrism *tr; /* Temporary Region pointer */
- AstRegion *full_co; /* Region describing full coord position */
- AstRegion *full_enc; /* Region describing full enclosure */
- AstRegion *red_co; /* Region describing red-shift coord */
- AstRegion *red_enc; /* Region describing red-shift enclosure */
- AstRegion *space_co; /* Region describing space coord */
- AstRegion *space_enc; /* Region describing space enclosure */
- char **words; /* Array of pointers to individual words */
- int nword; /* Number of words returned */
- AstRegion *spec_co; /* Region describing spectral coord */
- AstRegion *spec_enc; /* Region describing spectral enclosure */
- AstRegion *time_co; /* Region describing time coord */
- AstRegion *time_enc; /* Region describing time enclosure */
- AstSpecFrame *redfrm; /* Pointer to SpecFrame for redshift sub-phrase */
- AstSpecFrame *specfrm; /* Pointer to SpecFrame for spectral sub-phrase */
- AstStcsChan *this; /* Pointer to the StcsChan structure */
- AstStdOfRestType sor; /* Standard of rest */
- AstSystemType sys; /* Frame System attribute value */
- AstTimeFrame *tf1; /* Temporary TimeFrame */
- AstTimeFrame *timefrm; /* Pointer to TimeFrame for time sub-phrase */
- AstTimeScaleType ts; /* TimeFrame TimeScale attribute value */
- WordContext con; /* Context for finding next source word */
- char *fbuf; /* Pointer to buffer holding document fragment */
- const char *new_ts; /* Time scale string */
- double epoch; /* Value to use for the Epoch attribue */
- double fill; /* Filling factor */
- double hilim; /* Axis upper limit */
- double lolim; /* Axis lower limit */
- double scale; /* Units scaling factor */
- int nval; /* No. of values read from KeyMap */
- double vals[ 10 ]; /* Values read from KeyMap */
- double start; /* Start time */
- double stop; /* Stop time */
- double time; /* Time value */
- double time_origin; /* Value to use as TimeFrame TimeOrigin*/
- double value; /* Axis value */
- int iaxis; /* Axis index */
- int is_skyframe; /* Is the space frame a SkyFrame? */
- int level; /* Warning reporting level */
- int naxes; /* No. of space Frame axes */
- int nwant; /* Number of objects to return */
- int use_co; /* Do we have a full coordinate position? */
- int use_enc; /* Do we have a full enclosure? */
- int want_co; /* Is the Coordinates component wanted? */
- int want_enc; /* Is the enclosure region wanted? */
- int want_props; /* Are the STC-S properties wanted? */
- const char *cval; /* Pointer to property value */
- const char *type; /* Type of redshift axis */
-
-/* Initialise. */
- new = NULL;
-
-/* Check the global error status. */
- if ( !astOK ) return new;
-
-/* Obtain a pointer to the StcsChan structure. */
- this = (AstStcsChan *) this_channel;
-
-/* Initialise. */
- epoch = AST__BAD;
- start = AST__BAD;
- stop = AST__BAD;
- time = AST__BAD;
- time_co = NULL;
- time_enc = NULL;
- space_co = NULL;
- space_enc = NULL;
- spacefrm = NULL;
- spec_co = NULL;
- spec_enc = NULL;
- red_co = NULL;
- red_enc = NULL;
- use_co = 1;
- use_enc = 0;
- scale = 1.0;
-
-/* Read the STC-S description from the external source, parse it, and
- create a KeyMap containing the parsed property values. */
- full_props = ReadProps( this, status );
-
-/* If the STC-S description contained a time sub-phrase, get the KeyMap
- containing the proprties of the time sub-phrase, and then create AST
- Regions describing the time coordinate value and its enclosing Region. */
- if( astMapGet0A( full_props, "TIME_PROPS", &obj ) ) {
- props = (AstKeyMap *) obj;
-
-/* Create the default TimeFrame */
- timefrm = astTimeFrame( " ", status );
-
-/* Get the TIMESCALE property from the KeyMap, and identify the corresponding
- AST TimeScale. */
- ts = AST__BADTS;
- new_ts = NULL;
- level = 3;
-
- if( astMapGet0C( props, "TIMESCALE", &cval ) ) {
-
- if( astChrMatch( cval, "TT" ) ) {
- ts = AST__TT;
-
- } else if( astChrMatch( cval, "TDT" ) ) {
- ts = AST__TT;
- new_ts = "TT";
-
- } else if( astChrMatch( cval, "ET" ) ) {
- ts = AST__TT;
- new_ts = "TT";
-
- } else if( astChrMatch( cval, "TAI" ) ) {
- ts = AST__TAI;
-
- } else if( astChrMatch( cval, "IAT" ) ) {
- ts = AST__TAI;
- new_ts = "TAI";
-
- } else if( astChrMatch( cval, "UTC" ) ) {
- ts = AST__UTC;
-
- } else if( astChrMatch( cval, "TEB" ) ) {
- ts = AST__TDB;
- new_ts = "TDB";
- level = 1;
-
- } else if( astChrMatch( cval, "TDB" ) ) {
- ts = AST__TDB;
-
- } else if( astChrMatch( cval, "TCG" ) ) {
- ts = AST__TCG;
-
- } else if( astChrMatch( cval, "TCB" ) ) {
- ts = AST__TCB;
-
- } else if( astChrMatch( cval, "LST" ) ) {
- ts = AST__LMST;
-
- } else if( astChrMatch( cval, "nil" ) ) {
- astAddWarning( this, 2, "Time scale defaulting to 'TAI'.",
- "astRead", status );
-
- } else if( astOK ){
- astError( AST__BADIN, "astRead(StcsChan): Unknown time scale '%s'.",
- status, cval );
- }
-
- } else {
- astAddWarning( this, 2, "Time scale defaulting to 'TAI'.",
- "astRead", status );
- }
-
-/* Issue a warning if a different time-scale was substituted for the supplied
- time-scale. */
- if( new_ts ) {
- astAddWarning( this, level, "AST does not support the '%s' time "
- "scale. The '%s' timescale is being used instead.",
- "astRead", status, cval, new_ts );
- }
-
-/* If we got a time scale, set the TimeScale attribute in the TimeFrame
- to the same value. */
- if( ts != AST__BADTS ) astSetTimeScale( timefrm, ts );
-
-/* The AST TimeFrame class has no reference position, so allow any reference
- position but issue a warning for anything other than "TOPOCENTER" and
- "UNKNOWNRefPos". */
- if( !astMapGet0C( props, "REFPOS", &cval ) ) cval = "UNKNOWNRefPos";
- if( !astChrMatch( cval, "TOPOCENTER" ) ) {
- astAddWarning( this, 1, "AST only supports topocentric time frames, "
- "so 'TOPOCENTER' will be used in place of '%s'.",
- "astRead", status, cval );
- }
-
-/* Get the times describes by the time sub-phrase as MJD values. */
- astMapGet0D( props, "MJDSTART", &start );
- astMapGet0D( props, "MJDTIME", &time );
- astMapGet0D( props, "MJDSTOP", &stop );
-
-/* Get the earliest time represented by the time sub-phrase. We use this
- as the TimeOrigin for the TimeFrame, and also as the Epoch for all
- frames. */
- time_origin = start;
- if( time_origin == AST__BAD ) time_origin = time;
- if( time_origin == AST__BAD ) time_origin = stop;
- epoch = time_origin;
-
-/* Store the TimeOrigin value in the TimeFrame, modifying the time values
- accordingly. */
- if( time_origin != AST__BAD ) {
- astSetTimeOrigin( timefrm, time_origin );
- if( start != AST__BAD ) start -= time_origin;
- if( stop != AST__BAD ) stop -= time_origin;
- if( time != AST__BAD ) time -= time_origin;
- }
-
-/* Convert the epoch to TDB. */
- if( epoch != AST__BAD && ts != AST__TDB ) {
- tf1 = astCopy( timefrm );
- astSetTimeScale( tf1, AST__TDB );
- fs = astConvert( timefrm, tf1, "" );
- astTran1( fs, 1, &epoch, 1, &epoch );
- fs = astAnnul( fs );
- tf1 = astAnnul( tf1 );
- }
-
-/* Store the epoch value in the TimeFrame. */
- if( epoch != AST__BAD ) astSetEpoch( timefrm, epoch );
-
-/* Create a suitable Region to describe the enclosure for the time coords */
- if( start != AST__BAD || stop != AST__BAD ) {
- time_enc = (AstRegion *) astInterval( timefrm, &start, &stop,
- NULL, "", status );
- use_enc = 1;
- }
-
-/* Create a suitable Region to describe the time coords contained within
- the above enclosure. */
- if( time != AST__BAD ) {
- time_co = (AstRegion *) SinglePointList( (AstFrame *) timefrm,
- &time, NULL, status);
- } else {
- use_co = 0;
- }
-
-/* If no enclosure Region was created for the time sub-phrase, use a
- copy of any coordinate region. This is because each sub-phrase needs
- to have an enclosure of some sort if they are to be combined in parallel
- into an enclose for the whole CmpFrame. */
- if( ! time_enc && time_co ) time_enc = astCopy( time_co );
-
-/* Set the filling factor. */
- if( time_enc && astMapGet0D( props, "FILLFACTOR", &fill ) ) {
- astSetFillFactor( time_enc, fill );
- }
-
-/* Get the units in which the time error values are given, and get the
- scaling factor that converts them into days. */
- if( astMapGet0C( props, "UNIT", &cval ) ) {
- if( !strcmp( cval, "s" ) ) {
- scale = 1.0/86400.0;
-
- } else if( !strcmp( cval, "d" ) ) {
- scale = 1.0;
-
- } else if( !strcmp( cval, "a" ) ) {
- scale = 365.25;
-
- } else if( !strcmp( cval, "yr" ) ) {
- scale = 365.25;
-
- } else if( !strcmp( cval, "cy" ) ) {
- scale = 36525.0;
-
- } else if( astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Unsupported "
- "units (%s) for the time axis within an "
- "STC-S description.", status, cval );
- }
-
- } else {
- scale = 1.0/86400.0;
- }
-
-/* Associate an uncertainty with the two Regions. */
- if( astMapGet1D( props, "DERROR", 2, &nval, vals ) ) {
- if( nval > 1 ) {
- astAddWarning( this, 1, "An STC-S time sub-phrase contains an "
- "Error range. AST does not support error ranges "
- "so the mid value will be used as the error.",
- "astRead", status );
- vals[ 0 ] = 0.5*( vals[ 0 ] + vals[ 1 ] );
- }
-
- SetUnc( time_enc, time_co, (AstFrame *) timefrm, 0, scale, vals, 1,
- status );
- }
-
-/* Free resources */
- props = astAnnul( props );
- timefrm = astAnnul( timefrm );
- }
-
-/* If the STC-S description contained a space sub-phrase, get the KeyMap
- containing the proprties of the space sub-phrase, and then create AST
- Regions describing the spatial position and its enclosing Region. */
- if( astMapGet0A( full_props, "SPACE_PROPS", &obj ) ) {
- props = (AstKeyMap *) obj;
-
-/* The class of Frame (SkyFrame or basic Frame) is determined by the
- "FLAVOR". */
- is_skyframe = 0;
- if( astMapGet0C( props, "FLAVOUR", &cval ) ) {
-
- if( astChrMatch( cval, "SPHER2" ) ) {
- spacefrm = (AstFrame *) astSkyFrame( "", status );
- is_skyframe = 1;
-
- } else if( astChrMatch( cval, "CART1" ) ) {
- spacefrm = astFrame( 1, "", status );
-
- } else if( astChrMatch( cval, "CART2" ) ) {
- spacefrm = astFrame( 2, "", status );
-
- } else if( astChrMatch( cval, "CART3" ) ) {
- spacefrm = astFrame( 3, "", status );
-
- } else {
- astError( AST__BADIN, "astRead(StcsChan): Unsupported "
- "space 'Flavor' (%s) found in STC-S description.",
- status, cval );
- }
-
- } else {
- spacefrm = (AstFrame *) astSkyFrame( "", status );
- is_skyframe = 1;
- }
-
-/* Consider each supported space frame. Report an error for frames
- not supported by AST. */
- if( astMapGet0C( props, "FRAME", &cval ) ) {
- if( astChrMatch( cval, "ICRS" ) ) {
- sys = AST__ICRS;
-
- } else if( astChrMatch( cval, "FK5" ) ) {
- sys = AST__FK5;
-
- } else if( astChrMatch( cval, "FK4" ) ) {
- sys = AST__FK4;
-
- } else if( astChrMatch( cval, "J2000" ) ) {
- sys = AST__FK5;
-
- } else if( astChrMatch( cval, "B1950" ) ) {
- sys = AST__FK4;
-
- } else if( astChrMatch( cval, "ECLIPTIC" ) ) {
- sys = AST__ECLIPTIC;
-
- } else if( astChrMatch( cval, "GALACTIC" ) ) {
- sys = AST__GALACTIC;
-
- } else if( astChrMatch( cval, "GALACTIC_II" ) ) {
- sys = AST__GALACTIC;
-
- } else if( astChrMatch( cval, "SUPER_GALACTIC" ) ) {
- sys = AST__SUPERGALACTIC;
-
- } else if( astChrMatch( cval, "UNKNOWNFrame" ) ) {
- sys = AST__UNKNOWN;
-
- } else {
- sys = AST__UNKNOWN;
- astAddWarning( this, 1, "'UNKNOWNFrame' being used in place of "
- "unsupported frame '%s' in an STC-S description.",
- "astRead", status, cval );
- }
-
- } else {
- cval = "UNKNOWNFrame";
- sys = AST__UNKNOWN;
- astAddWarning( this, 1, "Space frame defaulting to 'UNKNOWNFrame' "
- "in an STC-S description.", "astRead", status );
- }
-
-/* We can set the System (only needed for SkyFrames). */
- if( is_skyframe ) {
- astSetSystem( spacefrm, sys );
-
-/* If we have a basic Frame, set the Domain equal to the STC-S frame value. */
- } else {
- astSetDomain( spacefrm, cval );
- }
-
-/* Set the epoch of the space frame. */
- if( epoch != AST__BAD ) astSetEpoch( spacefrm, epoch );
-
-/* The AST Frame and SkyFrame class has no reference position, so for
- SkyFrames we consider "TOPOCENTER" and "UNKNOWN" acceptable and all
- other unsupported. For other Frames we allow any reference position. */
- if( !astMapGet0C( props, "REFPOS", &cval ) ) cval = "UNKNOWNRefPos";
- if( is_skyframe && !astChrMatch( cval, "TOPOCENTER" ) ) {
- astAddWarning( this, 1, "AST only supports topocentric sky frames, "
- "so 'TOPOCENTER' will be used in place of '%s'.",
- "astRead", status, cval );
- }
-
-/* Get the number of spatial axes. */
- naxes = astGetNaxes( spacefrm );
-
-/* Get the units strings. */
- if( !astMapGet0C( props, "UNIT", &cval ) ) {
- if( is_skyframe ) {
- cval = "deg";
- } else {
- cval = "m";
- }
- }
-
-/* In AST, SkyFrames always use radians, so set up a scaling factor to
- convert supplied axis values into radians. */
- if( is_skyframe ) {
-
- if( !strcmp( cval, "deg" ) || !strcmp( cval, "deg deg" ) ) {
- scale = AST__DD2R;
-
- } else if( !strcmp( cval, "arcmin" ) || !strcmp( cval, "arcmin arcmin" ) ) {
- scale = AST__DD2R/60.0;
-
- } else if( !strcmp( cval, "arcsec" ) || !strcmp( cval, "arcsec arcsec" ) ) {
- scale = AST__DD2R/3600.0;
-
- } else if( astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Unsupported "
- "units (%s) for a spherical co-ordinate system "
- "within an STC-S description: '%s'.", status,
- cval, ContextFragment( &con, &fbuf, status ) );
- }
-
-/* Basic Frames can use any of the allowed units, so use a scale factor of
- 1.0. Also set the active unit flag in the space frame to enable intelligent
- units conversion by astConvert etc. */
- } else {
- scale = 1.0;
- astSetActiveUnit( spacefrm, 1 );
-
-/* Basic Frames can have different units on different axes. So split the
- units property up into separate words. */
- words = astChrSplit( cval, &nword );
-
-/* Set values for the Unit attributes of the Frame. Replicate the last
- supplied unit string for any extra axes. */
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- if( iaxis < nword ) {
- astSetUnit( spacefrm, iaxis, words[ iaxis ] );
- } else {
- astSetUnit( spacefrm, iaxis, words[ nword - 1 ] );
- }
- }
-
-/* Free resources. */
- for( iaxis = 0; iaxis < nword; iaxis++ ) {
- words[ iaxis ] = astFree( words[ iaxis ] );
- }
- words = astFree( words );
- }
-
-/* Create a suitable Region to enclose the space positions. This
- includes scaling the supplied axis values to the units used by
- the Frame. */
- space_enc = MakeSpaceRegion( props, spacefrm, scale, status );
- if( space_enc ) use_enc = 1;
-
-/* Create a suitable Region to describe the space coords contained within
- the above enclosure. If any sub-phrase has no coordinate value, then
- we cannot produce a PointList describing the complete coordinate set. */
- if( astMapGet1D( props, "DPOSITION", naxes, &nval, vals ) ) {
- for( iaxis = 0; iaxis < nval; iaxis++ ) vals[ iaxis ] *= scale;
- space_co = (AstRegion *) SinglePointList( spacefrm, vals, NULL,
- status);
- } else {
- use_co = 0;
- }
-
-/* If no enclosure Region was created for the space sub-phrase, use a
- copy of any coordinate region. This is because each sub-phrase needs
- to have an enclosure of some sort if they are to be combined in parallel
- into an enclose for the whole CmpFrame. */
- if( ! space_enc && space_co ) space_enc = astCopy( space_co );
-
-/* Set the filling factor. */
- if( space_enc && astMapGet0D( props, "FILLFACTOR", &fill ) ) {
- astSetFillFactor( space_enc, fill );
- }
-
-/* Associate an uncertainty with the two Regions. */
- if( astMapGet1D( props, "DERROR", 2*naxes, &nval, vals ) ) {
- if( nval > naxes ) {
- astAddWarning( this, 1, "An STC-S space sub-phrase contains an "
- "Error range. AST does not support error ranges "
- "so the mid value will be used as the error.",
- "astRead", status );
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vals[ iaxis ] = 0.5*( vals[ iaxis ] + vals[ iaxis + naxes ] );
- }
-
-/* If insufficient error values have been supplied, replicate the last
- one. */
- } else {
- for( iaxis = nval; iaxis < naxes; iaxis++ ) {
- vals[ iaxis ] = vals[ nval - 1 ];
- }
- }
-
-/* Set the uncertainty in the two space regions. */
- SetUnc( space_enc, space_co, (AstFrame *) spacefrm, is_skyframe,
- scale, vals, naxes, status );
- }
-
-/* Free resources */
- props = astAnnul( props );
- spacefrm = astAnnul( spacefrm );
- }
-
-
-
-/* If the STC-S description contained a velocity sub-phrase, issue a
- warning. */
- if( astMapGet0A( full_props, "VELOCITY_PROPS", &obj ) ) {
- astAddWarning( this, 1, "Ignoring a velocity sub-phrase found in "
- "an STC-S description.", "astRead", status );
- obj = astAnnul( obj );
- }
-
-
-/* If the STC-S description contained a spectral sub-phrase, get the KeyMap
- containing the proprties of the spectral sub-phrase, and then create AST
- Regions describing the spectral coordinate value and its enclosing Region. */
- if( astMapGet0A( full_props, "SPECTRAL_PROPS", &obj ) ) {
- props = (AstKeyMap *) obj;
-
-/* Create the default SpecFrame */
- specfrm = astSpecFrame( " ", status );
-
-/* Get the REFPOS property from the KeyMap, and identify the corresponding
- AST StdOfRest. */
- sor = AST__BADSOR;
- if( astMapGet0C( props, "REFPOS", &cval ) ) {
-
- if( astChrMatch( cval, "GEOCENTER" ) ) {
- sor = AST__GESOR;
-
- } else if( astChrMatch( cval, "BARYCENTER" ) ) {
- sor = AST__BYSOR;
-
- } else if( astChrMatch( cval, "HELIOCENTER" ) ) {
- sor = AST__HLSOR;
-
- } else if( astChrMatch( cval, "TOPOCENTER" ) ) {
- sor = AST__TPSOR;
-
- } else if( astChrMatch( cval, "LSR" ) ||
- astChrMatch( cval, "LSRK" ) ) {
- sor = AST__LKSOR;
-
- } else if( astChrMatch( cval, "LSRD" ) ) {
- sor = AST__LDSOR;
-
- } else if( astChrMatch( cval, "GALACTIC_CENTER" ) ) {
- sor = AST__GLSOR;
-
- } else {
- astAddWarning( this, 1, "Using 'HELIOCENTER' in place of "
- "unsupported spectral reference position '%s' "
- "found in an STC-S description.", "astRead",
- status, cval );
- }
-
- } else {
- astAddWarning( this, 2, "Spectral reference position defaulting to "
- "'HELIOCENTER' in an STC-S description.", "astRead",
- status );
- }
-
-/* If we got a ref pos, set the StdOfRest attribute in the SpecFrame. */
- if( sor != AST__BADSOR ) astSetStdOfRest( specfrm, sor );
-
-/* Get the units. */
- if( !astMapGet0C( props, "UNIT", &cval ) ) cval = "Hz";
-
-
-/* Set the spectral system implied by the unit string. */
- if( !cval || !strcmp( cval, "Hz" ) || !strcmp( cval, "MHz" ) ||
- !strcmp( cval, "GHz" ) ) {
- astSetSystem( specfrm, AST__FREQ );
-
- } else if( !strcmp( cval, "m" ) || !strcmp( cval, "mm" ) ||
- !strcmp( cval, "um" ) || !strcmp( cval, "nm" ) ||
- !strcmp( cval, "Angstrom" ) ) {
- astSetSystem( specfrm, AST__WAVELEN );
-
- } else if( !strcmp( cval, "eV" ) || !strcmp( cval, "keV" ) ||
- !strcmp( cval, "MeV" ) ) {
- astSetSystem( specfrm, AST__ENERGY );
-
- } else if( astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Unsupported spectral "
- "units (%s) found within an STC-S description.",
- status, cval );
- }
-
-/* Set the units. */
- astSetUnit( specfrm, 0, cval );
-
-/* Set the epoch */
- if( epoch != AST__BAD ) astSetEpoch( specfrm, epoch );
-
-/* Create a suitable Region to describe the enclosure for the spectral
- coords */
- if( astMapGet0D( props, "LOLIMIT", &lolim ) ) {
- astMapGet0D( props, "HILIMIT", &hilim );
- spec_enc = (AstRegion *) astInterval( specfrm, &lolim, &hilim,
- NULL, "", status );
- use_enc = 1;
- }
-
-/* Create a suitable Region to describe the spectral coords contained within
- the above enclosure. If any sub-phrase has no coordinate value, then
- we cannot produce a PointList describing the complete coordinate set. */
- if( astMapGet0D( props, "SPECTRAL", &value ) ) {
- spec_co = (AstRegion *) SinglePointList( (AstFrame *) specfrm,
- &value, NULL, status);
- } else {
- use_co = 0;
- }
-
-/* If no enclosure Region was created for the spectral sub-phrase, use a
- copy of any coordinate region. This is because each sub-phrase needs
- to have an enclosure of some sort if they are to be combined in parallel
- into an enclose for the whole CmpFrame. */
- if( ! spec_enc && spec_co ) spec_enc = astCopy( spec_co );
-
-/* Set the filling factor. */
- if( spec_enc && astMapGet0D( props, "FILLFACTOR", &fill ) ) {
- astSetFillFactor( spec_enc, fill );
- }
-
-
-/* Associate an uncertainty with the two Regions. */
- if( astMapGet1D( props, "DERROR", 2, &nval, vals ) ) {
- if( nval > 1 ) {
- astAddWarning( this, 1, "An STC-S spectral sub-phrase contains an "
- "Error range. AST does not support error ranges "
- "so the mid value will be used as the error.",
- "astRead", status );
- vals[ 0 ] = 0.5*( vals[ 0 ] + vals[ 1 ] );
- }
-
- SetUnc( spec_enc, spec_co, (AstFrame *) specfrm, 0, 1.0, vals, 1,
- status );
- }
-
-/* Free resources */
- props = astAnnul( props );
- specfrm = astAnnul( specfrm );
- }
-
-
-
-
-/* If the STC-S description contained a redshift sub-phrase, get the KeyMap
- containing the properties of the redshift sub-phrase, and then create AST
- Regions describing the redshift coordinate value and its enclosing Region. */
- if( astMapGet0A( full_props, "REDSHIFT_PROPS", &obj ) ) {
- props = (AstKeyMap *) obj;
-
-/* Create the default SpecFrame */
- redfrm = astSpecFrame( "Domain=REDSHIFT", status );
-
-/* Get the REFPOS property from the KeyMap, and identify the corresponding
- AST StdOfRest. */
- sor = AST__BADSOR;
- if( astMapGet0C( props, "REFPOS", &cval ) ) {
-
- if( astChrMatch( cval, "GEOCENTER" ) ) {
- sor = AST__GESOR;
-
- } else if( astChrMatch( cval, "BARYCENTER" ) ) {
- sor = AST__BYSOR;
-
- } else if( astChrMatch( cval, "HELIOCENTER" ) ) {
- sor = AST__HLSOR;
-
- } else if( astChrMatch( cval, "TOPOCENTER" ) ) {
- sor = AST__TPSOR;
-
- } else if( astChrMatch( cval, "LSR" ) ||
- astChrMatch( cval, "LSRK" ) ) {
- sor = AST__LKSOR;
-
- } else if( astChrMatch( cval, "LSRD" ) ) {
- sor = AST__LDSOR;
-
- } else if( astChrMatch( cval, "GALACTIC_CENTER" ) ) {
- sor = AST__GLSOR;
-
- } else {
- astAddWarning( this, 1, "Using 'HELIOCENTER' in place of "
- "unsupported redshift reference position '%s' "
- "found in an STC-S description.", "astRead",
- status, cval );
- }
-
- } else {
- astAddWarning( this, 2, "Redshift reference position defaulting to "
- "'HELIOCENTER' in an STC-S description.", "astRead",
- status );
- }
-
-/* If we got a ref pos, set the StdOfRest attribute in the SpecFrame. */
- if( sor != AST__BADSOR ) astSetStdOfRest( redfrm, sor );
-
-/* Get the redshift type. */
- if( !astMapGet0C( props, "TYPE", &type ) ) type = "REDSHIFT";
-
-/* Now get the velocity definition, and set the equivalent SpecFrame
- System value. AST only supports optical redshift, so report an error
- or a warning for unsupported combinations. */
- if( astMapGet0C( props, "DOPPLERDEF", &cval ) ){
-
- if( astChrMatch( cval, "OPTICAL" ) ) {
- if( astChrMatch( type, "VELOCITY" ) ){
- astSetSystem( redfrm, AST__VOPTICAL );
- } else {
- astSetSystem( redfrm, AST__REDSHIFT );
- }
-
- } else if( astChrMatch( cval, "RADIO" ) ) {
- if( astChrMatch( type, "VELOCITY" ) ){
- astSetSystem( redfrm, AST__VRADIO );
- } else {
- astSetSystem( redfrm, AST__REDSHIFT );
- astAddWarning( this, 1, "STC-S RADIO redshift not supported. "
- "Assuming OPTICAL redshift instead.", "astRead",
- status );
- }
-
- } else if( astChrMatch( cval, "RELATIVISTIC" ) ) {
- if( astChrMatch( type, "VELOCITY" ) ){
- astSetSystem( redfrm, AST__VREL );
- } else {
- astSetSystem( redfrm, AST__REDSHIFT );
- astAddWarning( this, 1, "STC-S RELATIVISTIC redshift not supported. "
- "Assuming OPTICAL redshift instead.", "astRead",
- status );
- }
-
- } else {
- if( astChrMatch( type, "VELOCITY" ) ){
- astSetSystem( redfrm, AST__VOPTICAL );
- astAddWarning( this, 1, "Doppler velocity definition defaulting"
- " to 'OPTICAL' in an STC-S description.",
- "astRead", status );
-
- } else {
- astSetSystem( redfrm, AST__REDSHIFT );
- }
- }
- }
-
-/* Set the units. */
- if( astChrMatch( type, "VELOCITY" ) ){
- if( astMapGet0C( props, "UNIT", &cval ) ) {
- astSetUnit( redfrm, 0, cval );
- } else {
- astSetUnit( redfrm, 0, "km/s" );
- }
-
- } else if( astMapGet0C( props, "UNIT", &cval ) ) {
- astAddWarning( this, 1, "Ignoring units (%s) specified for REDSHIFT "
- "in an STC-S description.", "astRead", status, cval );
- }
-
-/* Set the epoch */
- if( epoch != AST__BAD ) astSetEpoch( redfrm, epoch );
-
-/* Create a suitable Region to describe the enclosure for the redshift
- coords */
- if( astMapGet0D( props, "LOLIMIT", &lolim ) ) {
- astMapGet0D( props, "HILIMIT", &hilim );
- red_enc = (AstRegion *) astInterval( redfrm, &lolim, &hilim,
- NULL, "", status );
- use_enc = 1;
- }
-
-/* Create a suitable Region to describe the redshift coords contained within
- the above enclosure. If any sub-phrase has no coordinate value, then
- we cannot produce a PointList describing the complete coordinate set. */
- if( astMapGet0D( props, "REDSHIFT", &value ) ) {
- red_co = (AstRegion *) SinglePointList( (AstFrame *) redfrm,
- &value, NULL, status);
- } else {
- use_co = 0;
- }
-
-/* If no enclosure Region was created for the redshift sub-phrase, use a
- copy of any coordinate region. This is because each sub-phrase needs
- to have an enclosure of some sort if they are to be combined in parallel
- into an enclose for the whole CmpFrame. */
- if( ! red_enc && red_co ) red_enc = astCopy( red_co );
-
-/* Set the filling factor. */
- if( red_enc && astMapGet0D( props, "FILLFACTOR", &fill ) ) {
- astSetFillFactor( red_enc, fill );
- }
-
-/* Associate an uncertainty with the two Regions. */
- if( astMapGet1D( props, "DERROR", 2, &nval, vals ) ) {
- if( nval > 1 ) {
- astAddWarning( this, 1, "An STC-S redshift sub-phrase contains an "
- "Error range. AST does not support error ranges "
- "so the mid value will be used as the error.",
- "astRead", status );
- vals[ 0 ] = 0.5*( vals[ 0 ] + vals[ 1 ] );
- }
-
- SetUnc( red_enc, red_co, (AstFrame *) redfrm, 0, 1.0, vals, 1,
- status );
- }
-
-/* Free resources */
- props = astAnnul( props );
- redfrm = astAnnul( redfrm );
- }
-
-/* If a particular position was specified by the STC_S document, create the
- full position from the individual sub-phrase position */
- if( use_co ) {
- new = time_co ? astClone( time_co ) : NULL;
-
- if( space_co ) {
- if( new ) {
- tr = astPrism( new, space_co, "", status );
- (void) astAnnul( new );
- new = (AstObject *) tr;
- } else {
- new = astClone( space_co );
- }
- }
-
- if( spec_co ) {
- if( new ) {
- tr = astPrism( new, spec_co, "", status );
- (void) astAnnul( new );
- new = (AstObject *) tr;
- } else {
- new = astClone( spec_co );
- }
- }
-
- if( red_co ) {
- if( new ) {
- tr = astPrism( new, red_co, "", status );
- (void) astAnnul( new );
- new = (AstObject *) tr;
- } else {
- new = astClone( red_co );
- }
- }
-
- if( new ) {
- full_co = astSimplify( new );
- new = astAnnul( new );
- } else {
- full_co = NULL;
- }
-
- } else {
- full_co = NULL;
- }
-
-/* If an enclosing volume was specified by the STC_S document, create the
- full enclosure Region from the individual sub-phrase enclosure Regions. */
- if( use_enc ) {
- new = time_enc ? astClone( time_enc ) : NULL;
-
- if( space_enc ) {
- if( new ) {
- tr = astPrism( new, space_enc, "", status );
- (void) astAnnul( new );
- new = (AstObject *) tr;
- } else {
- new = astClone( space_enc );
- }
- }
-
- if( spec_enc ) {
- if( new ) {
- tr = astPrism( new, spec_enc, "", status );
- (void) astAnnul( new );
- new = (AstObject *) tr;
- } else {
- new = astClone( spec_enc );
- }
- }
-
- if( red_enc ) {
- if( new ) {
- tr = astPrism( new, red_enc, "", status );
- (void) astAnnul( new );
- new = (AstObject *) tr;
- } else {
- new = astClone( red_enc );
- }
- }
- full_enc = astSimplify( new );
- new = astAnnul( new );
-
- } else {
- full_enc = NULL;
- }
-
-/* See which, and how many, items are to be returned. */
- nwant = 0;
- if( ( want_enc = astGetStcsArea( this ) ) ) nwant++;
- if( ( want_co = astGetStcsCoords( this ) ) ) nwant++;
- if( ( want_props = astGetStcsProps( this ) ) ) nwant++;
-
-/* If one, and only one, of the three items is to be returned, return it. */
- new = NULL;
- if( nwant == 1 ) {
- if( want_enc && full_enc ) {
- new = astClone( full_enc );
- } else if( want_co && full_co ) {
- new = astClone( full_co );
- } else if( want_props && full_props ){
- new = astClone( full_props );
- }
-
-/* If more than one item is to be returned, put them into a KeyMap and
- return the KeyMap. */
- } else if( nwant > 1 ) {
- new = (AstObject *) astKeyMap( " ", status );
- if( want_enc && full_enc ) astMapPut0A( new, "AREA", full_enc, NULL );
- if( want_co && full_co ) astMapPut0A( new, "COORDS", full_co, NULL );
- if( want_props && full_props ) astMapPut0A( new, "PROPS", full_props, NULL );
-
-/* Report an error if nothing is to be returned. */
- } else if( astOK ){
- astError( AST__ATTIN, "astRead(StcsChan): The StcsArea, StcsCoords "
- "and StcsProps attributes indicate that nothing is to be "
- "returned (possible programming error).", status );
- }
-
-/* Free resources */
- if( space_enc ) space_enc = astAnnul( space_enc );
- if( spec_enc ) spec_enc = astAnnul( spec_enc );
- if( time_enc ) time_enc = astAnnul( time_enc );
- if( red_enc ) red_enc = astAnnul( red_enc );
- if( space_co ) space_co = astAnnul( space_co );
- if( spec_co ) spec_co = astAnnul( spec_co );
- if( time_co ) time_co = astAnnul( time_co );
- if( red_co ) red_co = astAnnul( red_co );
- if( full_enc ) full_enc = astAnnul( full_enc );
- if( full_co ) full_co = astAnnul( full_co );
- if( full_props ) full_props = astAnnul( full_props );
-
-/* If an error occurred, clean up by deleting the new Object and
- return a NULL pointer. */
- if ( !astOK ) new = astDelete( new );
-
-/* Return the pointer to the new Object. */
- return new;
-}
-
-static AstKeyMap *ReadProps( AstStcsChan *this, int *status ) {
-/*
-* Name:
-* ReadProps
-
-* Purpose:
-* Read STC-S properties from the source and store in a KeyMap.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* AstKeyMap *ReadProps( AstStcsChan *this, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function parses the list of space-separated words read from the
-* source function, identifies the purpose of each word within the STC-S
-* description, and stores the words in a returned KeyMap.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* A pointer to the new KeyMap. This will contain up to five entries
-* with any or all of the following keys: TIME_PROPS, SPACE_PROPS,
-* VELOCITY_PROPS, SPECTRAL_PROPS, REDSHIFT_PROPS. If an entry is absent,
-* it means the STC-S description did not contain the corresponding
-* sub-phrase. The value associated with each of these entries will be a
-* KeyMap. These will contain values for the sub-phrase proprties read
-* from the STC-S description. Properties that are not specified in
-* the STC-S description will not be present in the KeyMap. The values
-* stored in the KeyMap are the words read form the STC-S description
-* without any conversion or other processing.
-*/
-
-/* Local Constants: */
-#define MAXVAL 6
-
-/* Local Variables: */
- AstKeyMap *props; /* KeyMap holding current sub-phrase properties */
- AstKeyMap *result; /* Returned KeyMap holding all properties */
- AstTimeFrame *timefrm; /* Used for unformatting ISO date-times */
- WordContext con; /* Context for finding next source word */
- char *fbuf; /* Pointer to buffer holding document fragment */
- char *prop; /* String holding complete property value */
- const char *subphrase; /* Name of current sub phrase */
- const char *t; /* Temporary character string pointer */
- const char *word; /* Pointer to next source word */
- double val[ MAXVAL ]; /* Array of numerical property values */
- double start; /* Start time (MJD) */
- double stop; /* Stop time (MJD) */
- double time; /* Time value (MJD) */
- double value; /* Axis value */
- int iaxis; /* Axis index */
- int is_jd; /* Is time value a JD rather than an MJD? */
- int nunit; /* Number of units strings supplied */
- int nval; /* Number of numerical values read */
- int naxes; /* No. of space Frame axes */
- int nc; /* Number of characters written to string */
- int new_word; /* Get a new word at the end of the pass? */
- int redid; /* Redshift sub-phrase component identifier */
- int spaceid; /* Space sub-phrase component identifier */
- int specid; /* Spectral sub-phrase component identifier */
- int timeid; /* Time sub-phrase component identifier */
- int velid; /* Velocity sub-phrase component identifier */
-
-/* The stage reached in the parsing of the STC-S description is indicated
- by the "look_for" variable. This variable is allowed the following
- values, indicating the item that is to be checked for next. */
- enum look_for_type {
- ERROR,
- FILL_FACTOR,
- FLAVOUR,
- FRAME,
- LIMITS,
- PIX_SIZE,
- POSITION,
- POSITION_INTERVAL,
- REDSHIFT_IDENTIFIER,
- RED_SPEC_LABEL,
- RED_SPEC_VALUE,
- REFPOS,
- RESOLUTION,
- SIZE,
- SPACE_IDENTIFIER,
- SPECTRAL_IDENTIFIER,
- START,
- STOP,
- TIME,
- TIME_IDENTIFIER,
- TIME_LABEL,
- TIME_SCALE,
- TYPE_DOPPLER,
- UNIT,
- VELOCITY_IDENTIFIER,
- VELOCITY
- } look_for;
-
-/* Check the global error status. */
- if ( !astOK ) return NULL;
-
-/* Create the returned KeyMap. */
- result = astKeyMap( " ", status );
-
-/* Initialise the word search context. */
- (void) GetNextWord( NULL, &con, status );
-
-/* Get a pointer to the first word in the STC-S description. */
- word = GetNextWord( this, &con, status );
-
-/* Indicate we are currently looking for the time sub-phrase (the first
- item in an STC-S description). */
- look_for = TIME_IDENTIFIER;
-
-/* Initialise everything else. */
- fbuf = NULL;
- naxes = 0;
- prop = NULL;
- props = NULL;
- redid = NULL_ID;
- spaceid = NULL_ID;
- specid = NULL_ID;
- subphrase = NULL;
- t = NULL;
- timeid = NULL_ID;
- velid = NULL_ID;
- timefrm = NULL;
-
-/* Loop until all words in the STC-S description have been interpreted or
- an error has occurred. */
- while( word && astOK ) {
-
-/* Initialise a flag to indicate that we have interpreted the current word
- sucesfully and so will need to get a new word before the next pass through
- this loop. If it turns out that we cannot interpret the current word
- in this pass, then this flag will be set to zero at some point, thus
- preventing a new word from being acquired and causing another attempt to
- re-interpret the current word in a different context. */
- new_word = 1;
-
-/* If we are currently looking for the time sub-phrase, see if the current
- word is any of the known time sub-phrase identifiers. Is so, move on
- to read the associated sub-phrase component. */
- if( look_for == TIME_IDENTIFIER ) {
-/* ------------------------------------------------------------------ */
-
-/* Assume that we will be moving on to read the fill factor (most time
- sub-phrases start with the fill factor ). */
- look_for = FILL_FACTOR;
-
-/* Now check the word to see if it a known time sub-phrase identifier. */
- if( astChrMatch( word, "TimeInterval" ) ) {
- timeid = TIME_INTERVAL_ID;
-
- } else if( astChrMatch( word, "StartTime" ) ) {
- timeid = START_TIME_ID;
-
- } else if( astChrMatch( word, "StopTime" ) ) {
- timeid = STOP_TIME_ID;
-
- } else if( astChrMatch( word, "Time" ) ) {
- look_for = TIME_SCALE; /* After "Time", we move on to find the
- timeid = TIME_ID; time-scale, not the fill factor */
-
-/* If the word is not a known time sub-phrase identifier, indicate that we
- should attempt to re-interpret the current word as a space sub-phrase
- identifier, rather than getting a new word. */
- } else {
- look_for = SPACE_IDENTIFIER;
- new_word = 0;
- }
-
-/* If we have found a time sub-phrase identifier, create a KeyMap to hold
- the properties of the time sub-phrase, and store the time sub-phrase
- identifier in the new KeyMap. */
- if( timeid != NULL_ID ) {
- subphrase = "time";
- props = astKeyMap( " ", status );
- astMapPut0A( result, "TIME_PROPS", props, NULL );
- astMapPut0C( props, "ID", word, NULL );
- naxes = 1;
- }
-
-
-
-/* If we are currently looking for the space sub-phrase, see if the current
- word is any of the known space sub-phrase identifiers. Is so, move on
- to read the associated sub-phrase component. */
- } else if( look_for == SPACE_IDENTIFIER ) {
-/* ------------------------------------------------------------------ */
-
-/* Indicate we have finished any preceding time sub-phrase. */
- timeid = NULL_ID;
-
-/* Now check the word to see if it a known space sub-phrase identifier. */
- spaceid = SpaceId( word, status );
-
-/* Decide what to look for next. */
- if( spaceid == POSITION_ID ) {
- look_for = FRAME;
-
- } else if( spaceid != NULL_ID ) {
- look_for = FILL_FACTOR;
-
-/* If the word is not a known space sub-phrase identifier, move on to
- re-interpret it as a Spectral sub-phrase identifier. */
- } else {
- look_for = SPECTRAL_IDENTIFIER;
- new_word = 0;
- }
-
-/* If we have found a space sub-phrase identifier, create a KeyMap to hold
- the properties of the space sub-phrase, and store the space sub-phrase
- identifier in the new KeyMap. */
- if( spaceid != NULL_ID ) {
- subphrase = "space";
- if( props ) props = astAnnul( props );
- props = astKeyMap( " ", status );
- astMapPut0A( result, "SPACE_PROPS", props, NULL );
- astMapPut0C( props, "ID", word, NULL );
- }
-
-
-
-/* If we are currently looking for the velocity sub-phrase, see if the current
- word is any of the known velocity sub-phrase identifiers. Is so, move on
- to read the associated sub-phrase component. */
- } else if( look_for == VELOCITY_IDENTIFIER ) {
-/* ------------------------------------------------------------------ */
-
-/* Indicate we have finished any preceding space sub-phrase. */
- spaceid = NULL_ID;
-
-/* Now check the word to see if it a known velocity sub-phrase identifier. */
- if( astChrMatch( word, "VelocityInterval" ) ) {
- velid = VELOCITY_INTERVAL_ID;
- look_for = FILL_FACTOR;
-
- } else if( astChrMatch( word, "Velocity" ) ) {
- velid = VELOCITY_ID;
- look_for = VELOCITY;
-
-/* If the word is not a known velocity sub-phrase identifier, move on to
- re-interpret it as a Spectral sub-phrase identifier. */
- } else {
- look_for = SPECTRAL_IDENTIFIER;
- new_word = 0;
- }
-
-/* If we have found a velocity sub-phrase identifier, create a KeyMap to
- hold the properties of the velocity sub-phrase, and store the velocity
- sub-phrase identifier in the new KeyMap. */
- if( velid != NULL_ID ) {
- subphrase = "velocity";
- if( props ) props = astAnnul( props );
- props = astKeyMap( " ", status );
- astMapPut0A( result, "VELOCITY_PROPS", props, NULL );
- astMapPut0C( props, "ID", word, NULL );
- }
-
-
-
-/* If we are currently looking for the spectral sub-phrase, see if the
- word is any of the known spectral sub-phrase identifiers. Is so, move
- on to read the associated sub-phrase component. */
- } else if( look_for == SPECTRAL_IDENTIFIER ) {
-/* ------------------------------------------------------------------ */
-
-/* Indicate we have finished any preceding velocity sub-phrase. */
- velid = NULL_ID;
-
-/* Now check the word to see if it a known spectral sub-phrase identifier. */
- if( astChrMatch( word, "SpectralInterval" ) ) {
- look_for = FILL_FACTOR; /* Move on to find the fill factor */
- specid = SPECTRAL_INTERVAL_ID;
-
- } else if( astChrMatch( word, "Spectral" ) ) {
- look_for = REFPOS; /* Move on to find the refpos */
- specid = SPECTRAL_ID;
-
-/* If the word is not a known spectral sub-phrase identifier, move on to
- look for the Redshift sub-phrase. */
- } else {
- look_for = REDSHIFT_IDENTIFIER;
- new_word = 0;
- }
-
-/* If we have found a spectral sub-phrase identifier, create a KeyMap to
- hold the properties of the spectral sub-phrase, and store the spectral
- sub-phrase identifier in the new KeyMap. */
- if( specid != NULL_ID ) {
- subphrase = "spectral";
- if( props ) props = astAnnul( props );
- props = astKeyMap( " ", status );
- astMapPut0A( result, "SPECTRAL_PROPS", props, NULL );
- astMapPut0C( props, "ID", word, NULL );
- naxes = 1;
- }
-
-
-
-/* If we are currently looking for the redshift sub-phrase, see if the
- word is any of the known redshift sub-phrase identifiers. Is so, move
- on to read the associated sub-phrase component. */
- } else if( look_for == REDSHIFT_IDENTIFIER ) {
-/* ------------------------------------------------------------------ */
-
-/* Indicate we have finished any preceding spectral sub-phrase. */
- specid = NULL_ID;
-
-/* Now check the word to see if it a known spectral sub-phrase identifier. */
- if( astChrMatch( word, "RedshiftInterval" ) ) {
- look_for = FILL_FACTOR; /* Move on to find the fill factor */
- redid = REDSHIFT_INTERVAL_ID;
-
- } else if( astChrMatch( word, "Redshift" ) ) {
- look_for = REFPOS; /* Move on to find the refpos */
- redid = REDSHIFT_ID;
-
-/* If the word is not a known redshift sub-phrase identifier, report a
- warning. */
- } else if( word[ 0 ] && astOK ) {
- astError( AST__BADIN, "astRead(%s): Unsupported or irrelevant "
- "word '%s' found in STC-S %s sub-phrase: '%s'.", status,
- astGetClass( this ), word, subphrase,
- ContextFragment( &con, &fbuf, status ) );
- new_word = 0;
- }
-
-/* If we have found a redshift sub-phrase identifier, create a KeyMap to
- hold the properties of the redshift sub-phrase, and store the redshift
- sub-phrase identifier in the new KeyMap. */
- if( redid != NULL_ID ) {
- subphrase = "redshift";
- if( props ) props = astAnnul( props );
- props = astKeyMap( " ", status );
- astMapPut0A( result, "REDSHIFT_PROPS", props, NULL );
- astMapPut0C( props, "ID", word, NULL );
- naxes = 1;
- }
-
-/* Indicate we can now end when we run out of input words. */
- con.done = 1;
-
-
-
-/* If we are currently looking for a fill factor... */
- } else if( look_for == FILL_FACTOR ) {
-/* ------------------------------------------------------------------ */
-
-/* If the current word is "fillfactor" attempt to read the numerical filling
- factor from the next word. If this fails, or if the current word is
- not "fillfactor", indicate that we will be re-interpreting the current
- word in a new context and so do not need a new word. */
- if( astChrMatch( word, "fillfactor" ) ) {
- word = GetNextWord( this, &con, status );
- if( astChr2Double( word ) == AST__BAD ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a numerical "
- "filling factor, but found '%s' in the %s "
- "sub-phrase of STC-S description: '%s'.", status,
- word, subphrase, ContextFragment( &con, &fbuf,
- status ) );
- new_word = 0;
- }
- } else {
- new_word = 0;
- }
-
-/* If we are reading a time sub-phrase, move on to read the timescale. */
- if( timeid != NULL_ID ) {
- look_for = TIME_SCALE;
-
-/* If we are reading a space sub-phrase, move on to read the frame. */
- } else if( spaceid != NULL_ID ) {
- look_for = FRAME;
-
-/* If we are reading a velocity sub-phrase, move on to read the limits. */
- } else if( velid != NULL_ID ) {
- look_for = LIMITS;
-
-/* Otherwise (i.e. for spectral and redshift sub-phrases) move on to read
- the refpos. */
- } else {
- look_for = REFPOS;
- }
-
-/* If the word was usable, record it as the fillfactor property. */
- if( new_word ) astMapPut0C( props, "FILLFACTOR", word, NULL );
-
-
-
-/* If we are currently looking for a time scale... */
- } else if( look_for == TIME_SCALE ) {
-/* ------------------------------------------------------------------ */
-
-/* If the current word is a recognised STC-S timescale, store it in the
- props KeyMap. Otherwise, indicate that the word can be re-used in the
- next context. */
- if( astChrMatch( word, "TT" ) ||
- astChrMatch( word, "TDT" ) ||
- astChrMatch( word, "ET" ) ||
- astChrMatch( word, "TAI" ) ||
- astChrMatch( word, "IAT" ) ||
- astChrMatch( word, "UTC" ) ||
- astChrMatch( word, "TEB" ) ||
- astChrMatch( word, "TDB" ) ||
- astChrMatch( word, "TCG" ) ||
- astChrMatch( word, "TCB" ) ||
- astChrMatch( word, "LST" ) ||
- astChrMatch( word, "nil" ) ) {
-
- astMapPut0C( props, "TIMESCALE", word, NULL );
-
- } else {
- new_word = 0;
- }
-
-/* Move on to look for a refpos */
- look_for = REFPOS;
-
-
-
-/* If we are currently looking for a space frame... */
- } else if( look_for == FRAME ) {
-/* ------------------------------------------------------------------ */
-
-/* If the current word is a recognised STC-S spatial frame, store it in
- the props KeyMap. Otherwise, indicate that the word can be re-used. */
- if( astChrMatch( word, "ICRS" ) ||
- astChrMatch( word, "FK5" ) ||
- astChrMatch( word, "FK4" ) ||
- astChrMatch( word, "J2000" ) ||
- astChrMatch( word, "B1950" ) ||
- astChrMatch( word, "ECLIPTIC" ) ||
- astChrMatch( word, "GALACTIC" ) ||
- astChrMatch( word, "GALACTIC_II" ) ||
- astChrMatch( word, "SUPER_GALACTIC" ) ||
- astChrMatch( word, "GEO_C" ) ||
- astChrMatch( word, "GEO_D" ) ||
- astChrMatch( word, "UNKNOWNFrame" ) ) {
-
- astMapPut0C( props, "FRAME", word, NULL );
-
- } else {
- new_word = 0;
- }
-
-/* Move on to look for a refpos */
- look_for = REFPOS;
-
-
-
-/* If we are currently looking for a refpos... */
- } else if( look_for == REFPOS ) {
-/* ------------------------------------------------------------------ */
-
-/* If the current word is a recognised STC-S reference position, store it in
- the props KeyMap. Otherwise, indicate that the word can be re-used. The
- first group of reference positions apply to all sub-phrases. */
- if( astChrMatch( word, "GEOCENTER" ) ||
- astChrMatch( word, "BARYCENTER" ) ||
- astChrMatch( word, "HELIOCENTER" ) ||
- astChrMatch( word, "TOPOCENTER" ) ||
- astChrMatch( word, "GALACTIC_CENTER" ) ||
- astChrMatch( word, "EMBARYCENTER" ) ||
- astChrMatch( word, "MOON" ) ||
- astChrMatch( word, "MERCURY" ) ||
- astChrMatch( word, "VENUS" ) ||
- astChrMatch( word, "MARS" ) ||
- astChrMatch( word, "JUPITER" ) ||
- astChrMatch( word, "SATURN" ) ||
- astChrMatch( word, "URANUS" ) ||
- astChrMatch( word, "NEPTUNE" ) ||
- astChrMatch( word, "PLUTO" ) ||
- astChrMatch( word, "UNKNOWNRefPos" ) ) {
-
- astMapPut0C( props, "REFPOS", word, NULL );
-
-/* This group of reference positions apply only to spectral and redshift
- sub-phrases. */
- } else if( astChrMatch( word, "LSR" ) ||
- astChrMatch( word, "LSRK" ) ||
- astChrMatch( word, "LSRD" ) ||
- astChrMatch( word, "LOCAL_GROUP_CENTER" ) ) {
-
- if( specid != NULL_ID || redid != NULL_ID ) {
- astMapPut0C( props, "REFPOS", word, NULL );
-
- } else if( astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Illegal reference "
- "position '%s' found in the %s sub-phrase of "
- "STC-S description: '%s'.", status, word,
- subphrase, ContextFragment( &con, &fbuf, status ) );
- new_word = 0;
- }
-
- } else {
- new_word = 0;
- }
-
-/* Choose what to look for next on the basis of the type of sub-phrase
- currently being interpreted. */
- if( timeid == TIME_INTERVAL_ID ){
- look_for = START; /* Move on to find the start time */
-
- } else if( timeid == START_TIME_ID ){
- look_for = START; /* Move on to find the start time */
-
- } else if( timeid == STOP_TIME_ID ){
- look_for = STOP; /* Move on to find the stop time */
-
- } else if( timeid == TIME_ID ){
- look_for = TIME; /* Move on to find the time */
-
- } else if( spaceid != NULL_ID ){
- look_for = FLAVOUR; /* Move on to find the spatial flavour */
-
- } else if( specid == SPECTRAL_INTERVAL_ID ) {
- look_for = LIMITS; /* Move on to find the spectral limits */
-
- } else if( specid == SPECTRAL_ID ) {
- look_for = RED_SPEC_VALUE; /* Move on to find the spectral value */
-
- } else if( redid == REDSHIFT_INTERVAL_ID ) {
- look_for = TYPE_DOPPLER; /* Move on to find the redshift type */
-
- } else if( redid == REDSHIFT_ID ) {
- look_for = TYPE_DOPPLER; /* Move on to find the redshift type */
-
- } else if( astOK ) { /* Should never happen */
- astError( AST__INTER, "astRead(StcsChan): Sanity check 1 fails in "
- "function ReadProps (AST internal programming error).",
- status );
- new_word = 0;
- }
-
-
-
-
-
-/* If we are currently looking for a start time... */
- } else if( look_for == START ) {
-/* ------------------------------------------------------------------ */
-
-/* Save the current word as the start of the START value. */
- nc = 0;
- prop = astAppendString( prop, &nc, word );
-
-/* If the current word is "JD" or "MJD", the following word should be
- numerical. */
- is_jd = astChrMatch( word, "JD" );
- if( is_jd || astChrMatch( word, "MJD" ) ) {
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
- if( value == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected numerical "
- "value in Start time, but found '%s %s' in STC-S "
- "description: '%s'.", status, prop, word,
- ContextFragment( &con, &fbuf, status ) );
-
-/* Append the second word to the first word. */
- } else {
- prop = astAppendString( prop, &nc, " " );
- prop = astAppendString( prop, &nc, word );
- }
-
-/* Convert JD to MJD if required. */
- start = is_jd ? value - 2400000.5 : value;
-
-/* Otherwise, the current word should be an ISO date. Use a TimeFrame
- to check the string. */
- } else {
- if( !timefrm ) timefrm = astTimeFrame( " ", status );
- if( !astUnformat( timefrm, 0, word, &start ) && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected ISO date "
- "string Start time, but found '%s' in an STC-S "
- "description: '%s'.", status, word,
- ContextFragment( &con, &fbuf, status ) );
- }
- }
-
-/* Record the START property. */
- astMapPut0C( props, "START", prop, NULL );
- astMapPut0D( props, "MJDSTART", start, NULL );
-
-/* Decide what to do next. */
- if( timeid == TIME_INTERVAL_ID ){
- look_for = STOP; /* Move on to find the stop time */
-
- } else if( timeid == START_TIME_ID ){
- look_for = TIME_LABEL; /* Move on to find the "coord" time */
-
- }
-
-
-
-/* If we are currently looking for a stop time... */
- } else if( look_for == STOP ) {
-/* ------------------------------------------------------------------ */
-
-/* Save the current word as the start of the STOP value. */
- nc = 0;
- prop = astAppendString( prop, &nc, word );
-
-/* If the current word is "JD" or "MJD", the following word should be
- numerical. */
- is_jd = astChrMatch( word, "JD" );
- if( is_jd || astChrMatch( word, "MJD" ) ) {
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
- if( value == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected numerical "
- "value in Stop time, but found '%s %s' in STC-S "
- "description: '%s'.", status, prop, word,
- ContextFragment( &con, &fbuf, status ) );
-
-/* Append the second word to the first word. */
- } else {
- prop = astAppendString( prop, &nc, " " );
- prop = astAppendString( prop, &nc, word );
- }
-
-/* Convert JD to MJD if required. */
- stop = is_jd ? value - 2400000.5 : value;
-
-/* Otherwise, the current word should be an ISO date. Use a TimeFrame
- to check the string. */
- } else {
- if( !timefrm ) timefrm = astTimeFrame( " ", status );
- if( !astUnformat( timefrm, 0, word, &stop ) && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected ISO date "
- "string Stop time, but found '%s' in an STC-S "
- "description: '%s'.", status, word,
- ContextFragment( &con, &fbuf, status ) );
- }
- }
-
-/* Record the STOP property. */
- astMapPut0C( props, "STOP", prop, NULL );
- astMapPut0D( props, "MJDSTOP", stop, NULL );
-
-/* Move on to find the "coord" time. */
- look_for = TIME_LABEL;
-
-
-
-/* If we are currently looking for the label before a time coord value... */
- } else if( look_for == TIME_LABEL ) {
-/* ------------------------------------------------------------------ */
- if( astChrMatch( word, "Time" ) ) {
- look_for = TIME;
- } else {
- new_word = 0;
- look_for = UNIT;
- }
-
-
-
-/* If we are currently looking for a time... */
- } else if( look_for == TIME ) {
-/* ------------------------------------------------------------------ */
-
-/* Save the current word as the start of the TIME value. */
- nc = 0;
- prop = astAppendString( prop, &nc, word );
-
-/* If the current word is "JD" or "MJD", the following word should be
- numerical. */
- is_jd = astChrMatch( word, "JD" );
- if( is_jd || astChrMatch( word, "MJD" ) ) {
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
- if( value == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected numerical "
- "value in Time value, but found '%s %s' in STC-S "
- "description: '%s'.", status, prop, word,
- ContextFragment( &con, &fbuf, status ) );
-
-/* Append the second word to the first word. */
- } else {
- prop = astAppendString( prop, &nc, " " );
- prop = astAppendString( prop, &nc, word );
- }
-
-/* Convert JD to MJD if required. */
- time = is_jd ? value - 2400000.5 : value;
-
-/* Otherwise, the current word should be an ISO date. Use a TimeFrame
- to check the string. */
- } else {
- if( !timefrm ) timefrm = astTimeFrame( " ", status );
- if( !astUnformat( timefrm, 0, word, &time ) && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected ISO date "
- "string Time value, but found '%s' in an STC-S "
- "description: '%s'.", status, word,
- ContextFragment( &con, &fbuf, status ) );
- }
- }
-
-/* Record the TIME property. */
- astMapPut0C( props, "TIME", prop, NULL );
- astMapPut0D( props, "MJDTIME", time, NULL );
-
-/* Move on to look for the units. */
- look_for = UNIT;
-
-
-
-/* If we are currently looking for a space "flavor"... */
- } else if( look_for == FLAVOUR ) {
-/* ------------------------------------------------------------------ */
-
-/* If the current word is a recognised flavour value, note how many axis
- values are required to specify a position. Otherwise, indicate that
- the word can be re-used. */
- if( astChrMatch( word, "SPHER2" ) ) {
- naxes = 2;
-
- } else if( astChrMatch( word, "UNITSPHER" ) ) {
- naxes = 2;
-
- } else if( astChrMatch( word, "CART1" ) ) {
- naxes = 1;
-
- } else if( astChrMatch( word, "CART2" ) ) {
- naxes = 2;
-
- } else if( astChrMatch( word, "CART3" ) ) {
- naxes = 3;
-
- } else if( astChrMatch( word, "SPHER3" ) ) {
- naxes = 3;
-
- } else {
- naxes = 2;
- new_word = 0;
- }
-
-/* If the word was recognised as a flavour, store it in the porperties
- KeyMap. */
- if( new_word ) {
- astMapPut0C( props, "FLAVOR", word, NULL );
- astMapPut0C( props, "FLAVOUR", word, NULL );
- }
-
-/* The next set of words to be read from the source function will specify
- the arguments of the region enclosing the spatial positions. This may
- contain nested regions, so use a recursive function to read the
- arguments and store them in the properties KeyMap. */
- if( new_word ) word = GetNextWord( this, &con, status );
- word = ReadSpaceArgs( this, word, spaceid, naxes, &con, props,
- status );
- new_word = 0;
-
-/* Move on to the next look_for (following the region argument list read
- by ReadSpaceArgs). */
- if( spaceid == POSITION_ID ) {
- look_for = UNIT;
- } else {
- look_for = POSITION;
- }
-
-
-
-/* If we are currently looking for interval "lolimit"and "hilimit" ... */
- } else if( look_for == LIMITS ) {
-/* ------------------------------------------------------------------ */
- if( velid != NULL_ID ) {
- t = "velocity";
- look_for = VELOCITY;
-
- } else if( specid != NULL_ID ) {
- t = "spectral";
- look_for = RED_SPEC_LABEL;
-
- } else {
- t = "redshift";
- look_for = RED_SPEC_LABEL;
- }
-
-/* The current word should be a numerical value (the low limit ). */
- if( astChr2Double( word ) == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a numerical "
- "value for a %s lolimit, but found '%s' in an STC-S "
- "description: '%s'.", status, t, word,
- ContextFragment( &con, &fbuf, status ) );
- } else {
- astMapPut0C( props, "LOLIMIT", word, NULL );
- }
-
-/* The next word should be a numerical value (the high limit ). */
- word = GetNextWord( this, &con, status );
- if( astChr2Double( word ) == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a numerical "
- "value for a %s hilimit, but found '%s' in an STC-S "
- "description: '%s'.", status, t, word,
- ContextFragment( &con, &fbuf, status ) );
- } else {
- astMapPut0C( props, "HILIMIT", word, NULL );
- }
-
-
-
-/* If we are currently looking for the label before a spectral or redshift
- value... */
- } else if( look_for == RED_SPEC_LABEL ) {
-/* ------------------------------------------------------------------ */
- if( specid != NULL_ID && astChrMatch( word, "Spectral" ) ) {
- look_for = RED_SPEC_VALUE;
-
- } else if( redid != NULL_ID && astChrMatch( word, "Redshift" ) ) {
- look_for = RED_SPEC_VALUE;
-
- } else {
- new_word = 0;
- look_for = UNIT;
- }
-
-
-
-/* If we are currently looking for an spectral or redshift value. */
- } else if( look_for == RED_SPEC_VALUE ) {
-/* ------------------------------------------------------------------ */
-
- t = ( specid != NULL_ID ) ? "spectral" : "redshift";
- if( astChr2Double( word ) == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a numerical "
- "%s value, but found '%s' in an STC-S "
- "description: '%s'.", status, t, word,
- ContextFragment( &con, &fbuf, status ) );
- } else {
- astMapPut0C( props, ( specid != NULL_ID ) ? "SPECTRAL" : "REDSHIFT",
- word, NULL );
- }
-
-/* Decide what to do next. */
- look_for = UNIT;
-
-
-
-/* If we are currently looking for information needed to create a spatial
- Position ... */
- } else if( look_for == POSITION ) {
-/* ------------------------------------------------------------------ */
-
-/* Check the current word is "Position". If so, get the next word. */
- if( astChrMatch( word, "Position" ) ) {
- word = GetNextWord( this, &con, status );
-
-/* Get a value for every space axis. */
- nc = 0;
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- val[ iaxis ] = astChr2Double( word );
- if( val[ iaxis ] == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected another "
- "axis value for a space Position, but found "
- "'%s' in an STC-S description: '%s'.", status,
- word, ContextFragment( &con, &fbuf, status ) );
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, &con, status );
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "POSITION", prop, NULL );
- astMapPut1D( props, "DPOSITION", naxes, val, NULL );
- }
-
-/* Move on to read the "unit" item. */
- new_word = 0;
- look_for = UNIT;
-
-
-
-/* If we are currently looking for the redshift type and doppler
- definition ... */
- } else if( look_for == TYPE_DOPPLER ) {
-/* ------------------------------------------------------------------ */
-
- if( astChrMatch( word, "VELOCITY" ) ||
- astChrMatch( word, "REDSHIFT" ) ) {
- astMapPut0C( props, "TYPE", word, NULL );
- word = GetNextWord( this, &con, status );
- }
-
- if( astChrMatch( word, "OPTICAL" ) ||
- astChrMatch( word, "RADIO" ) ||
- astChrMatch( word, "RELATIVISTIC" ) ) {
- astMapPut0C( props, "DOPPLERDEF", word, NULL );
- } else {
- new_word = 0;
- }
-
-/* Decide what to do next. */
- look_for = ( redid == REDSHIFT_INTERVAL_ID ) ? LIMITS : RED_SPEC_VALUE;
-
-
-
-/* If we are currently looking for a velocity label and value... */
- } else if( look_for == VELOCITY ) {
-/* ------------------------------------------------------------------ */
-
- if( astChrMatch( word, "Velocity" ) ) {
- word = GetNextWord( this, &con, status );
- if( astChr2Double( word ) == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a "
- "numerical Velocity value but found 'Velocity %s' "
- "in an STC-S description: '%s'.", status, word,
- ContextFragment( &con, &fbuf, status ) );
- }
-
- } else {
- new_word = 0;
- }
-
- look_for = UNIT;
-
-
-
-/* If we are currently looking for a "unit" string... */
- } else if( look_for == UNIT ) {
-/* ------------------------------------------------------------------ */
-
-/* See if the current word is "unit". If so, read the next word (which
- will be the unit string itself). Otherwise, indicate the current word
- can be re-used. */
- if( astChrMatch( word, "unit" ) ) {
- word = GetNextWord( this, &con, status );
- } else {
- new_word = 0;
- }
-
-/* If we have a unit string... */
- if( new_word ) {
-
-/* Check that the unit string is one of the allowed values (different
- values are allowed for different sub-phrases). Space frames can have
- multiple units strings (one for each axis) so loop round until a string
- is found which is not a valid unit string. */
- nc = 0;
- nunit = 0;
- while( ( timeid != NULL_ID && ( !strcmp( word, "s" ) ||
- !strcmp( word, "d" ) ||
- !strcmp( word, "a" ) ||
- !strcmp( word, "yr" ) ||
- !strcmp( word, "cy" ) ) ) ||
-
- ( spaceid != NULL_ID && ( !strcmp( word, "deg" ) ||
- !strcmp( word, "arcmin" ) ||
- !strcmp( word, "arcsec" ) ||
- !strcmp( word, "m" ) ||
- !strcmp( word, "mm" ) ||
- !strcmp( word, "m" ) ||
- !strcmp( word, "km" ) ||
- !strcmp( word, "AU" ) ||
- !strcmp( word, "pc" ) ||
- !strcmp( word, "kpc" ) ||
- !strcmp( word, "Mpc" ) ) ) ||
-
- ( velid != NULL_ID && ( !strcmp( word, "deg" ) ||
- !strcmp( word, "arcmin" ) ||
- !strcmp( word, "arcsec" ) ||
- !strcmp( word, "m" ) ||
- !strcmp( word, "mm" ) ||
- !strcmp( word, "km" ) ||
- !strcmp( word, "AU" ) ||
- !strcmp( word, "pc" ) ||
- !strcmp( word, "kpc" ) ||
- !strcmp( word, "Mpc" ) ) ) ||
-
- ( !strcmp( word, "Hz" ) ||
- !strcmp( word, "MHz" ) ||
- !strcmp( word, "GHz" ) ||
- !strcmp( word, "m" ) ||
- !strcmp( word, "mm" ) ||
- !strcmp( word, "um" ) ||
- !strcmp( word, "nm" ) ||
- !strcmp( word, "Angstrom" ) ||
- !strcmp( word, "eV" ) ||
- !strcmp( word, "keV" ) ||
- !strcmp( word, "MeV" ) ) ) {
-
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- nunit++;
- word = GetNextWord( this, &con, status );
- }
-
-/* Report an error if an inappropriate number of valid unit strings was
- found. */
- if( nunit == 0 && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Unsupported "
- "units (%s) for the %s sub-phrase within an "
- "STC-S description: '%s'.", status, word, subphrase,
- ContextFragment( &con, &fbuf, status ) );
-
- } else if( nunit != 1 && nunit != naxes && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Incorrect number of "
- "units string (%d) supplied for the %s sub-phrase within an "
- "STC-S description: '%s'.", status, nunit, subphrase,
- ContextFragment( &con, &fbuf, status ) );
-
-/* Otherwise, remove the trailing space, and store the property value in the
- KeyMap. */
- } else {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "UNIT", prop, NULL );
- }
-
-/* The current word is the first word that was not a valid unit string,
- and so can be re-used. */
- new_word = 0;
- }
-
-/* Move on to find the errors. */
- look_for = ERROR;
-
-
-
-/* If we are currently looking for an "Error" string... */
- } else if( look_for == ERROR ) {
-/* ------------------------------------------------------------------ */
-
-/* If the current word is "Error" read all subsequent words until the first
- non-numerical value is encountered. */
- if( astChrMatch( word, "Error" ) ) {
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
-
- nc = 0;
- nval = 0;
- while( value != AST__BAD ) {
- if( nval < MAXVAL ) {
- val[ nval++ ] = value;
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
- } else {
- astError( AST__BADIN, "astRead(StcsChan): Too many (more "
- "than %d) numerical values found for the Error "
- "property of the %s sub-phrase within an STC-S "
- "description: '%s'.", status, MAXVAL, subphrase,
- ContextFragment( &con, &fbuf, status ) );
- break;
- }
- }
-
-/* Report an error if no numerical error values were found. */
- if( nval == 0 && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a "
- "numerical error value but found 'Error %s' "
- "for the %s sub-phrase within an "
- "STC-S description: '%s'.", status, word, subphrase,
- ContextFragment( &con, &fbuf, status ) );
-
-/* Otherwise, remove the trailing space and store the concatenated
- string of formatted values in the properties KeyMap. Also store a
- corresponding vector of floating point values in the KeyMap. */
- } else {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "ERROR", prop, NULL );
- astMapPut1D( props, "DERROR", nval, val, NULL );
- }
- }
-
-/* Indicate that we do not need to get a new word (we can re-use the last
- one that turned out not to be a numerical value above). */
- new_word = 0;
-
-/* Next look for Resolution */
- look_for = RESOLUTION;
-
-
-
-/* If we are currently looking for a "Resolution" string... */
- } else if( look_for == RESOLUTION ) {
-/* ------------------------------------------------------------------ */
-
-/* If the current word is "Resolution" read all subsequent words until the
- first non-numerical value is encountered. */
- if( astChrMatch( word, "Resolution" ) ) {
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
-
- nc = 0;
- nval = 0;
- while( value != AST__BAD ) {
- if( nval < MAXVAL ) {
- val[ nval++ ] = value;
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
- } else {
- astError( AST__BADIN, "astRead(StcsChan): Too many (more "
- "than %d) numerical values found for the Resolution "
- "property of the %s sub-phrase within an STC-S "
- "description: '%s'.", status, MAXVAL, subphrase,
- ContextFragment( &con, &fbuf, status ) );
- break;
- }
- }
-
-/* Report an error if no numerical values were found. */
- if( nval == 0 && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a "
- "numerical resolution value but found 'Resolution %s' "
- "for the %s sub-phrase within an STC-S description:"
- " '%s'.", status, word, subphrase,
- ContextFragment( &con, &fbuf, status ) );
-
-/* Otherwise, remove the trailing space and store the concatenated
- string of formatted values in the properties KeyMap. Also store a
- corresponding vector of floating point values in the KeyMap. */
- } else {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "RESOLUTION", prop, NULL );
- astMapPut1D( props, "DRESOLUTION", nval, val, NULL );
- }
- }
-
-/* Indicate that we do not need to get a new word (we can re-use the last
- one that turned out not to be a numerical value above). */
- new_word = 0;
-
-/* Next look for Size. */
- look_for = SIZE;
-
-
-
-/* If we are currently looking for a spatial "Size" string... */
- } else if( look_for == SIZE ) {
-/* ------------------------------------------------------------------ */
-
-/* If the current word is "Size" read all subsequent words until the
- first non-numerical value is encountered. */
- if( astChrMatch( word, "Size" ) ) {
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
-
- nc = 0;
- nval = 0;
- while( value != AST__BAD ) {
- if( nval < MAXVAL ) {
- val[ nval++ ] = value;
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
- } else {
- astError( AST__BADIN, "astRead(StcsChan): Too many (more "
- "than %d) numerical values found for the Size "
- "property of the %s sub-phrase within an STC-S "
- "description: '%s'.", status, MAXVAL, subphrase,
- ContextFragment( &con, &fbuf, status ) );
- break;
- }
- }
-
-/* Report an error if no numerical values were found. */
- if( nval == 0 && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a "
- "numerical size value but found 'Size %s' "
- "for the %s sub-phrase within an STC-S description:"
- " '%s'.", status, word, subphrase,
- ContextFragment( &con, &fbuf, status ) );
-
-/* Otherwise, remove the trailing space and store the concatenated
- string of formatted values in the properties KeyMap. Also store a
- corresponding vector of floating point values in the KeyMap. */
- } else {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "SIZE", prop, NULL );
- astMapPut1D( props, "DSIZE", nval, val, NULL );
- }
- }
-
-/* Indicate that we do not need to get a new word (we can re-use the last
- one that turned out not to be a numerical value above). */
- new_word = 0;
-
-/* Next look for PixSize. */
- look_for = PIX_SIZE;
-
-
-
-/* If we are currently looking for a "PixSize" string... */
- } else if( look_for == PIX_SIZE ) {
-/* ------------------------------------------------------------------ */
-
-/* If the current word is "PixSize" read all subsequent words until the
- first non-numerical value is encountered. */
- if( astChrMatch( word, "PixSize" ) ) {
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
-
- nc = 0;
- nval = 0;
- while( value != AST__BAD ) {
- if( nval < MAXVAL ) {
- val[ nval++ ] = value;
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, &con, status );
- value = astChr2Double( word );
- } else {
- astError( AST__BADIN, "astRead(StcsChan): Too many (more "
- "than %d) numerical values found for the PixSize "
- "property of the %s sub-phrase within an STC-S "
- "description: '%s'.", status, MAXVAL, subphrase,
- ContextFragment( &con, &fbuf, status ) );
- break;
- }
- }
-
-/* Report an error if no numerical values were found. */
- if( nval == 0 && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a "
- "numerical pixel size but found 'PixSize %s' "
- "for the %s sub-phrase within an STC-S description:"
- " '%s'.", status, word, subphrase,
- ContextFragment( &con, &fbuf, status ) );
-
-/* Otherwise, remove the trailing space and store the concatenated
- string of formatted values in the properties KeyMap. Also store a
- corresponding vector of floating point values in the KeyMap. */
- } else {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "PIXSIZE", prop, NULL );
- astMapPut1D( props, "DPIXSIZE", nval, val, NULL );
- }
- }
-
-/* Indicate that we do not need to get a new word (we can re-use the last
- one that turned out not to be a numerical value above). */
- new_word = 0;
-
-/* Next look for the next sub-phrase. */
- if( timeid != NULL_ID ) {
- look_for = SPACE_IDENTIFIER;
-
- } else if( spaceid != NULL_ID ) {
- look_for = VELOCITY_IDENTIFIER;
-
- } else if( velid != NULL_ID ) {
- look_for = SPECTRAL_IDENTIFIER;
-
- } else if( specid != NULL_ID ) {
- look_for = REDSHIFT_IDENTIFIER;
-
- } else {
- break;
- }
-
-
-
-
-/* Report an error for any unknown look_for. */
-/* ------------------------------------------------------------------ */
- } else if( astOK ) {
- astError( AST__INTER, "astRead(StcsChan): Illegal look_for value "
- "(%d) encountered (internal AST programming error).",
- status, look_for );
- }
-
-/* If required, get the next word in the STC-S description. */
- if( new_word ) word = GetNextWord( this, &con, status );
- }
-
-/* Free resources stored in the GetNextWord context structure. */
- con.done = 1;
- (void) GetNextWord( this, &con, status );
- FreeContext( &con, status );
-
-/* Free other resources */
- if( fbuf ) fbuf = astFree( fbuf );
- if( prop ) prop = astFree( prop );
- if( props ) props = astAnnul( props );
- if( timefrm ) timefrm = astAnnul( timefrm );
-
-/* If an error occurred, clean up by deleting the new Object and
- return a NULL pointer. */
- if ( !astOK ) result = astDelete( result );
-
-/* Return the pointer to the properties KeyMap. */
- return result;
-
-/* Undefine Local Constants: */
-#undef MAXVAL
-}
-
-static const char *ReadSpaceArgs( AstStcsChan *this, const char *word,
- int spaceid, int naxes, WordContext *con,
- AstKeyMap *props, int *status ){
-/*
-* Name:
-* ReadSpaceArgs
-
-* Purpose:
-* Read space region arguments from an STC-S description.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* const char *ReadSpaceArgs( AstStcsChan *this, const char *word,
-* int spaceid, int naxes, WordContext *con,
-* AstKeyMap *props, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function parses the list of space-separated words that form
-* the argument list of a spatial region. These words are read from the
-* source function, and stored in the supplied KeyMap using keys that
-* identify their purpose.
-*
-* This function calls itself recursively to handle compound regions.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* word
-* The first word of the argument list.
-* spaceid
-* An integer identifier for the type of spatial region for which
-* arguments are being read.
-* naxes
-* Number of axes in the space frame.
-* con
-* Pointer to a structure holding context for use with the
-* GetNextWord function. On exit, the next word returned by the
-* GetNextWord function will be the first word following the
-* argument list.
-* props
-* Pointer to the KeyMap in which the argument values should be
-* stored.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* Pointer to the next wpord to be interpreted.
-
-*/
-
-
-/* Local Variables: */
- AstKeyMap *new_props; /* KeyMap holding properties of an argument region */
- char *fbuf; /* Pointer to buffer holding document fragment */
- char *prop; /* String property value */
- char key[ 20 ]; /* Key for argument region */
- double *p; /* Pointer to next polygon vertex axis value */
- double *temp; /* Array of polygon vertex axis values */
- double val; /* Single numerical value */
- double vals[ 6 ]; /* List of numerical values */
- int iaxis; /* Axis index */
- int nc; /* Used length of string */
- int new_spaceid; /* Type of next argument region */
- int nreg; /* Number of argument regions found */
- int nvert; /* Number of vertices in polygon */
-
-/* Check inherited status */
- if( !astOK ) return word;
-
-/* Initialise. */
- fbuf = NULL;
- prop = NULL;
- nc = 0;
-
-/* If we are looking for information needed to create a spatial
- Interval... */
- if( spaceid == POSITION_INTERVAL_ID ) {
-
-/* Get a lolimit value for every space axis. */
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vals[ iaxis ] = astChr2Double( word );
- if( vals[ iaxis ] == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected another "
- "'lolimit' value for a PositionInterval, but found "
- "'%s' in an STC-S description: '%s'.", status, word,
- ContextFragment( con, &fbuf, status ) );
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, con, status );
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "LOLIMIT", prop, NULL );
- astMapPut1D( props, "DLOLIMIT", naxes, vals, NULL );
- }
-
-/* Get a hilimit value for every space axis. */
- nc = 0;
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vals[ iaxis ] = astChr2Double( word );
- if( vals[ iaxis ] == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected another "
- "'hilimit' value for a PositionInterval, but found "
- "'%s' in an STC-S description: '%s'.", status, word,
- ContextFragment( con, &fbuf, status ) );
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, con, status );
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "HILIMIT", prop, NULL );
- astMapPut1D( props, "DLOLIMIT", naxes, vals, NULL );
- }
-
-/* If we are currently looking for information needed to create a spatial
- AllSky ... */
- } else if( spaceid == ALLSKY_ID ) {
-
-
-
-/* If we are currently looking for information needed to create a spatial
- Circle ... */
- } else if( spaceid == CIRCLE_ID ) {
-
-/* Get a centre value for every space axis. */
- nc = 0;
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vals[ iaxis ] = astChr2Double( word );
- if( vals[ iaxis ] == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected another "
- "'centre' value for a Circle, but found "
- "'%s' in an STC-S description: '%s'.", status, word,
- ContextFragment( con, &fbuf, status ) );
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, con, status );
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "CENTRE", prop, NULL );
- astMapPut1D( props, "DCENTRE", naxes, vals, NULL );
- }
-
-/* Get the radius value. */
- val = astChr2Double( word );
- if( val == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a radius "
- "value for a Circle, but found '%s' in an STC-S "
- "description: '%s'.", status, word,
- ContextFragment( con, &fbuf, status ) );
- }
-
-/* Store the property value in the KeyMap. */
- astMapPut0C( props, "RADIUS", word, NULL );
-
-/* Get the next word. */
- word = GetNextWord( this, con, status );
-
-
-
-/* If we are currently looking for information needed to create a spatial
- Ellipse ... */
- } else if( spaceid == ELLIPSE_ID ) {
-
-/* Get a centre value for every space axis. */
- nc = 0;
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vals[ iaxis ] = astChr2Double( word );
- if( vals[ iaxis ] == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected another "
- "centre value for an Ellipse, but found "
- "'%s' in an STC-S description: '%s'.", status, word,
- ContextFragment( con, &fbuf, status ) );
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, con, status );
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "CENTRE", prop, NULL );
- astMapPut1D( props, "DCENTRE", naxes, vals, NULL );
- }
-
-/* Get the first radius value . */
- val = astChr2Double( word );
- if( val == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected the first "
- "radius value for an Ellipse, but found "
- "'%s' in an STC-S description: '%s'.", status, word,
- ContextFragment( con, &fbuf, status ) );
- }
-
-/* Store the property value in the KeyMap. */
- astMapPut0C( props, "RADIUS1", word, NULL );
-
-/* Get the second radius value . */
- word = GetNextWord( this, con, status );
- val = astChr2Double( word );
- if( val == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected the second "
- "radius value for an Ellipse, but found "
- "'%s' in an STC-S description: '%s'.", status, word,
- ContextFragment( con, &fbuf, status ) );
- }
-
-/* Store the property value in the KeyMap. */
- astMapPut0C( props, "RADIUS2", word, NULL );
-
-/* Get the position angle value. */
- word = GetNextWord( this, con, status );
- val = astChr2Double( word );
- if( val == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected the position "
- "angle value for an Ellipse, but found "
- "'%s' in an STC-S description: '%s'.", status, word,
- ContextFragment( con, &fbuf, status ) );
- }
-
-/* Store the property value in the KeyMap. */
- astMapPut0C( props, "POSANGLE", word, NULL );
-
-/* Get the next word. */
- word = GetNextWord( this, con, status );
-
-
-
-/* If we are currently looking for information needed to create a spatial
- Box ... */
- } else if( spaceid == BOX_ID ) {
-
-/* Get a centre value for every space axis. */
- nc = 0;
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vals[ iaxis ] = astChr2Double( word );
- if( vals[ iaxis ] == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected another "
- "centre value for a Box, but found "
- "'%s' in an STC-S description: '%s'.", status,
- word, ContextFragment( con, &fbuf, status ) );
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, con, status );
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "CENTRE", prop, NULL );
- astMapPut1D( props, "DCENTRE", naxes, vals, NULL );
- }
-
-/* Get bsize value for every space axis. */
- nc = 0;
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vals[ iaxis ] = astChr2Double( word );
- if( vals[ iaxis ] == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected another "
- "'bsize' value for a Box, but found "
- "'%s' in an STC-S description: '%s'.", status,
- word, ContextFragment( con, &fbuf, status ) );
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, con, status );
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "BSIZE", prop, NULL );
- astMapPut1D( props, "DBSIZE", naxes, vals, NULL );
- }
-
-
-/* If we are currently looking for information needed to create a spatial
- Polygon ... */
- } else if( spaceid == POLYGON_ID ) {
-
-/* Read the first vertex into a dynamically allocated array. */
- temp = astMalloc( sizeof( *temp )*naxes );
- if( temp ) {
- nc = 0;
- p = temp;
- for( iaxis = 0; iaxis < naxes; iaxis++,p++ ) {
- val = astChr2Double( word );
- if( val == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected another "
- "vertex value for a Polygon, but found "
- "'%s' in an STC-S description: '%s'.", status,
- word, ContextFragment( con, &fbuf, status ) );
- } else {
- *p = val;
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, con, status );
- }
-
-/* Loop round reading remaining vertices, expanding the array as needed. */
- nvert = 1;
- val = astChr2Double( word );
- while( val != AST__BAD && astOK ) {
-
- temp = astGrow( temp, naxes*( nvert + 1 ), sizeof( *temp ) );
- if( astOK ) {
- p = temp + naxes*nvert;
-
- for( iaxis = 0; iaxis < naxes; iaxis++, p++ ) {
- if( val == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected "
- "another vertex value for a Polygon, but "
- "found '%s' in an STC-S description: '%s'.",
- status, word, ContextFragment( con, &fbuf,
- status ) );
- } else {
- *p = val;
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, con, status );
- val = astChr2Double( word );
- }
- nvert++;
- }
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "VERTICES", prop, NULL );
- astMapPut1D( props, "DVERTICES", naxes*nvert, temp, NULL );
- }
- temp = astFree( temp );
- }
-
-
-
-/* If we are currently looking for information needed to create a spatial
- Convex ... */
- } else if( spaceid == CONVEX_ID ) {
- astError( AST__BADIN, "astRead(StcsChan): A Convex was found "
- "within an STC-S description ('Convex' regions "
- "are not yet supported by AST): %s", status,
- ContextFragment( con, &fbuf, status ) );
-
-
-
-/* If we are currently looking for information needed to create a spatial
- Position ... */
- } else if( spaceid == POSITION_ID ) {
-
-/* Get a value for every space axis. */
- nc = 0;
- for( iaxis = 0; iaxis < naxes; iaxis++ ) {
- vals[ iaxis ] = astChr2Double( word );
- if( vals[ iaxis ] == AST__BAD && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected another "
- "axis value for a space Position, but found "
- "'%s' in an STC-S description: '%s'.", status,
- word, ContextFragment( con, &fbuf, status ) );
- }
- prop = astAppendString( prop, &nc, word );
- prop = astAppendString( prop, &nc, " " );
- word = GetNextWord( this, con, status );
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( props, "POSITION", prop, NULL );
- astMapPut1D( props, "DPOSITION", naxes, vals, NULL );
- }
-
-
-/* All remaining space id values require the argument list to be enclosed
- in parentheses. Report an error if the current word does not start
- with an opening parenthesis. */
- } else if( *word != '(' && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected an opening "
- "parenthesis but found '%s' in an STC-S description: '%s'.",
- status, word, ContextFragment( con, &fbuf, status ) );
-
-/* Skip over the opening parenthesis. If the first word consists of just the
- opening parenthesis, get the next word. */
- } else {
- if( *(++word) == 0 ) word = GetNextWord( this, con, status );
-
-/* Loop round all regions included in the compound region. */
- nreg = 0;
- while( astOK ) {
-
-/* If the next word starts with a closing parenthesis, we have reached
- the end of the argument list. */
- if( *word == ')' ) {
-
-/* Skip over the closing parenthesis. If the word consists of just the
- closing parenthesis, get the next word. */
- if( *(++word) == 0 ) word = GetNextWord( this, con, status );
-
-/* Leave the loop. */
- break;
- }
-
-/* Identify the region type from the current word. */
- new_spaceid = SpaceId( word, status );
- if( new_spaceid == NULL_ID && astOK ) {
- astError( AST__BADIN, "astRead(StcsChan): Expected a "
- "CoordinateArea or a closing parenthesis but found "
- "'%s' in an STC-S description: '%s'.", status, word,
- ContextFragment( con, &fbuf, status ) );
- }
-
-/* Create a new KeyMap to store the properties of the new region. Store
- this new KeyMap in the supplied KeyMap using a key of the form
- "REGION<n>". */
- new_props = astKeyMap( " ", status );
- astMapPut0C( new_props, "ID", word, NULL );
- sprintf( key, "REGION%d", ++nreg );
- astMapPut0A( props, key, new_props, NULL );
-
-/* Get the next word (i.e. the first word of the argument list for the
- region). */
- word = GetNextWord( this, con, status );
-
-/* Call this function recursively to read the argument list. */
- word = ReadSpaceArgs( this, word, new_spaceid, naxes, con,
- new_props, status );
-
-/* Free resources. */
- new_props = astAnnul( new_props );
- }
-
-/* Store the number of regions in the supplied KeyMap. */
- astMapPut0I( props, "NREG", nreg, NULL );
-
-/* Report an error if an in appropriate number of argument Regions were
- supplied. */
- if( spaceid == UNION_ID ) {
- if( nreg < 2 && astOK ){
- astError( AST__BADIN, "astRead(StcsChan): Less than two "
- "CoordinateAreas found within a 'Union' element in an "
- "STC-S description: '%s'.", status,
- ContextFragment( con, &fbuf, status ) );
- }
-
- } else if( spaceid == INTERSECTION_ID ) {
- if( nreg < 2 && astOK ){
- astError( AST__BADIN, "astRead(StcsChan): Less than two "
- "CoordinateAreas found within an 'Intersection' element "
- "in an STC-S description: '%s'.", status,
- ContextFragment( con, &fbuf, status ) );
- }
-
- } else if( spaceid == DIFFERENCE_ID ) {
- if( nreg != 2 && astOK ){
- astError( AST__BADIN, "astRead(StcsChan): %d CoordinateArea(s) "
- "found within a 'Difference' element in an STC-S "
- "description: '%s'.", status, nreg,
- ContextFragment( con, &fbuf, status ) );
- }
-
-
- } else if( spaceid == NOT_ID ) {
- if( nreg != 1 && astOK ){
- astError( AST__BADIN, "astRead(StcsChan): %d CoordinateAreas "
- "found within a 'Not' element in an STC-S description: "
- "'%s'.", status, nreg,
- ContextFragment( con, &fbuf, status ) );
- }
-
-/* Report an error for unknown spaceid values */
- } else if( astOK ) {
- astError( AST__INTER, "astRead(StcsChan): Illegal 'spaceid' value "
- "passed to function ReadSpaceArgs (internal AST "
- "programming error).", status );
- }
- }
-
-/* Free resources */
- if( prop ) prop = astFree( prop );
-
-/* Return a pointer to the next word to be interpreted. */
- return word;
-}
-
-static void SetAttrib( AstObject *this_object, const char *setting, int *status ) {
-/*
-* Name:
-* SetAttrib
-
-* Purpose:
-* Set an attribute value for a StcsChan.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void SetAttrib( AstObject *this, const char *setting )
-
-* Class Membership:
-* StcsChan member function (over-rides the astSetAttrib protected
-* method inherited from the Channel class).
-
-* Description:
-* This function assigns an attribute value for a StcsChan, the
-* attribute and its value being specified by means of a string of
-* the form:
-*
-* "attribute= value "
-*
-* Here, "attribute" specifies the attribute name and should be in
-* lower case with no white space present. The value to the right
-* of the "=" should be a suitable textual representation of the
-* value to be assigned and this will be interpreted according to
-* the attribute's data type. White space surrounding the value is
-* only significant for string attributes.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* setting
-* Pointer to a null terminated string specifying the new attribute
-* value.
-*/
-
-/* Local Variables: */
- AstStcsChan *this; /* Pointer to the StcsChan structure */
- int ival; /* Integer attribute value */
- int len; /* Length of setting string */
- int nc; /* Number of characters read by "astSscanf" */
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* Obtain a pointer to the StcsChan structure. */
- this = (AstStcsChan *) this_object;
-
-/* Obtain the length of the setting string. */
- len = (int) strlen( setting );
-
-/* Test for each recognised attribute in turn, using "astSscanf" to parse
- the setting string and extract the attribute value (or an offset to
- it in the case of string values). In each case, use the value set
- in "nc" to check that the entire string was matched. Once a value
- has been obtained, use the appropriate method to set it. */
-
-/* StcsArea. */
-/* --------- */
- if ( nc = 0,
- ( 1 == astSscanf( setting, "stcsarea= %d %n", &ival, &nc ) )
- && ( nc >= len ) ) {
- astSetStcsArea( this, ival );
-
-/* StcsCoords. */
-/* ----------- */
- } else if ( nc = 0,
- ( 1 == astSscanf( setting, "stcscoords= %d %n", &ival, &nc ) )
- && ( nc >= len ) ) {
- astSetStcsCoords( this, ival );
-
-/* StcsProps. */
-/* ----------- */
- } else if ( nc = 0,
- ( 1 == astSscanf( setting, "stcsprops= %d %n", &ival, &nc ) )
- && ( nc >= len ) ) {
- astSetStcsProps( this, ival );
-
-/* StcsLength */
-/* ----------*/
- } else if ( nc = 0,
- ( 1 == astSscanf( setting, "stcslength= %d %n", &ival, &nc ) )
- && ( nc >= len ) ) {
- astSetStcsLength( this, ival );
-
-/* If the attribute is still not recognised, pass it on to the parent
- method for further interpretation. */
- } else {
- (*parent_setattrib)( this_object, setting, status );
- }
-}
-
-static void SetUnc( AstRegion *reg1, AstRegion *reg2, AstFrame *frm,
- int is_skyframe, double scale, double *error, int nax,
- int *status ){
-/*
-* Name:
-* SetUnc
-
-* Purpose:
-* Store an uncertainty Box with a supplied Region.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void SetUnc( AstRegion *reg1, AstRegion *reg2, AstFrame *frm,
-* int is_skyframe, double scale, double *error, int nax,
-* int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function creates a new Box with dimensions specified by the
-* values in the "error" array, centred on a representative position
-* within one of the supplied Regions, and then stores the Box as the
-* uncertainty Region within both the supplied Regions.
-
-* Parameters:
-* reg1
-* Pointer to a Region to which the error values relate.
-* reg2
-* Pointer to another Region to which the error values relate.
-* frm
-* Pointer to the Frame encapsulated by both Regions.
-* is_skyframe
-* Should be non-zero if "frm" is a SkyFrame.
-* scale
-* A scale factor to apply to the error values before using them.
-* error
-* Pointer to an array of RMS error values, one for each axis in
-* "frm". These are modified on exit. For a SkyFrame, both values
-* (including the longitude axis value) should be given as an
-* arc-distance. This function will convert the arc-distance to
-* a longitude increment using a representative latitude for the
-* region.
-* nax
-* The numner of axes in "frm".
-* status
-* Pointer to the inherited status variable.
-
-*/
-
-/* Local Variables: */
- AstBox *unc; /* Uncertainty box */
- double dist; /* Diagonal length of Region bounding box */
- double lbnd[ 6 ]; /* Lower bounds of Region bounding box */
- double spos1[ 6 ]; /* A representative position in the Region */
- double spos2[ 6 ]; /* A second position in the Region */
- double ubnd[ 6 ]; /* Upper bounds of Region bounding box */
- int i; /* Axis index */
-
-/* Check the global error status. Also check an error value was supplied,
- and at least one of the Region pointers is not NULL. */
- if ( !astOK || error[ 0 ] == AST__BAD || ( !reg1 && !reg2 ) ) return;
-
-/* We need a representative position within the region. First get the
- coordinates at opposite corners of the region bounding box. */
- astRegBaseBox( reg1 ? reg1 : reg2, lbnd, ubnd );
-
-/* Find the diagonal length of the bounding box. */
- dist = astDistance( frm, lbnd, ubnd );
-
-/* Offset away from one corner towards the other by half the diagonal
- length. The resulting position returned in spos1 is our representative
- position for the region. */
- astOffset( frm, lbnd, ubnd, dist/2, spos1 );
-
-/* Scale the error values */
- for( i = 0; i < nax; i++ ) error[ i ] *= scale;
-
-/* If the region is defined within a SkyFrame, the supplied longitude
- error value will be an arc-distance value. But we need a longitude
- increment to create an uncertainty Region, so do the conversion. */
- if( is_skyframe ) {
-
-/* Offset away from the representative position found above along the
- first (i.e. longitude) axis by an arc-distance given by the Error
- value. */
- (void) astOffset2( frm, spos1, AST__DPIBY2, error[ 0 ], spos2 );
-
-/* Find the positive axis increment along the first axis. */
- error[ 0 ] = astAxDistance( frm, 1, spos1[ 0 ], spos2[ 0 ] );
- if( error[ 0 ] != AST__BAD ) error[ 0 ] = fabs( error[ 0 ] );
- }
-
-/* The uncertainty Region will be a Box centred at the representative
- position found above. Modify the "error" array to hold the corner
- axis values. */
- for( i = 0; i < nax; i++ ) error[ i ] += spos1[ i ];
-
-/* Create the box, and store it as the uncertainty Region in the supplied
- Region. */
- unc = astBox( frm, 0, spos1, error, NULL, " ", status );
- if( reg1 ) astSetUnc( reg1, unc );
- if( reg2 ) astSetUnc( reg2, unc );
-
-/* Free resources. */
- unc = astAnnul( unc );
-}
-
-static AstPointList *SinglePointList( AstFrame *frm, double *pos,
- AstRegion *unc, int *status){
-/*
-* Name:
-* SinglePointList
-
-* Purpose:
-* Create a PointList holding a single point.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* AstPointList *SinglePointList( AstFrame *frm, double *pos,
-* AstRegion *unc, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function creates a new PointList holding a single supplied
-* position.
-
-* Parameters:
-* frm
-* Pointer to the Frame in which the PointList is defined.
-* pos
-* Array holding the position. The length of this array must equal
-* the number of axes in "frm".
-* unc
-* Pointer to an uncertainty Region to associate with the new
-* PointList, or NULL.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* A pointer to the new PointList. NULL is returned if an error has
-* already occurred, of if this function fails for any reason.
-*/
-
-/* Local Variables: */
- AstPointList *result; /* Returned pointer. */
- AstPointSet *pset; /* PointSet holding axis values */
- double **ptr; /* Pointer to PointSet data arrays */
- int i; /* Axis index */
- int nax; /* Number of axes */
-
-/* Initialise. */
- result = NULL;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Get he number of axes. */
- nax = astGetNaxes( frm );
-
-/* Create a PointSet to hold the supplied point, and get a pointer to its
- data arrays. */
- pset = astPointSet( 1, nax, "", status );
- ptr = astGetPoints( pset );
- if( astOK ) {
-
-/* Copy the supplied axis values into the PointSet data arrays. */
- for( i = 0; i < nax; i++ ) ptr[ i ][ 0 ] = pos[ i ];
-
-/* Create the PointList. */
- result = astPointList( frm, pset, unc, "", status );
- }
-
-/* Free resources */
- pset = astAnnul( pset );
-
-/* Return the result. */
- return result;
-}
-
-static void SinkWrap( void (* sink)( const char * ), const char *line, int *status ) {
-/*
-* Name:
-* SinkWrap
-
-* Purpose:
-* Wrapper function to invoke a C StcsChan sink function.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void SinkWrap( void (* sink)( const char * ), const char *line, int *status )
-
-* Class Membership:
-* StcsChan member function.
-
-* Description:
-* This function invokes the sink function whose pointer is
-* supplied in order to write an output line to an external data
-* store.
-
-* Parameters:
-* sink
-* Pointer to a sink function, whose single parameter is a
-* pointer to a const, null-terminated string containing the
-* text to be written, and which returns void. This is the form
-* of StcsChan sink function employed by the C language interface
-* to the AST library.
-* status
-* Pointer to the inherited status variable.
-*/
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* Invoke the sink function. */
- ( *sink )( line );
-}
-
-static char *SourceWrap( const char *(* source)( void ), int *status ) {
-/*
-* Name:
-* SourceWrap
-
-* Purpose:
-* Wrapper function to invoke a C StcsChan source function.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* char *SourceWrap( const char *(* source)( void ), int *status )
-
-* Class Membership:
-* StcsChan member function.
-
-* Description:
-* This function invokes the source function whose pointer is
-* supplied in order to read the next input line from an external
-* data store. It then returns a pointer to a dynamic string
-* containing a copy of the text that was read.
-
-* Parameters:
-* source
-* Pointer to a source function, with no parameters, that
-* returns a pointer to a const, null-terminated string
-* containing the text that it read. This is the form of StcsChan
-* source function employed by the C language interface to the
-* AST library.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* A pointer to a dynamically allocated, null terminated string
-* containing a copy of the text that was read. This string must be
-* freed by the caller (using astFree) when no longer required.
-*
-* A NULL pointer will be returned if there is no more input text
-* to read.
-
-* Notes:
-* - A NULL pointer value will be returned if this function is
-* invoked with the global error status set or if it should fail
-* for any reason.
-*/
-
-/* Local Variables: */
- char *result; /* Pointer value to return */
- const char *line; /* Pointer to input line */
-
-/* Initialise. */
- result = NULL;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Invoke the source function to read the next input line and return a
- pointer to the resulting string. */
- line = ( *source )();
-
-/* If a string was obtained, make a dynamic copy of it and save the
- resulting pointer. */
- if ( line ) result = astString( line, (int) strlen( line ) );
-
-/* Return the result. */
- return result;
-}
-
-static int SpaceId( const char *word, int *status ){
-/*
-* Name:
-* SpaceId
-
-* Purpose:
-* Return the integer identifier for a given textual space identifier.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* int SpaceId( const char *word, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function returns an integer identifier for the given space
-* identifier.
-
-* Parameters:
-* word
-* The word holding the textual space identifier.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* The integer space identifier, or NULL_ID if the supplied word was
-* not a known space identifier.
-
-*/
-
-
-/* Local Variables: */
- int spaceid; /* Returned identifier */
-
-/* Check inherited status */
- if( !astOK ) return NULL_ID;
-
- if( astChrMatch( word, "PositionInterval" ) ) {
- spaceid = POSITION_INTERVAL_ID;
-
- } else if( astChrMatch( word, "AllSky" ) ) {
- spaceid = ALLSKY_ID;
-
- } else if( astChrMatch( word, "Circle" ) ) {
- spaceid = CIRCLE_ID;
-
- } else if( astChrMatch( word, "Ellipse" ) ) {
- spaceid = ELLIPSE_ID;
-
- } else if( astChrMatch( word, "Box" ) ) {
- spaceid = BOX_ID;
-
- } else if( astChrMatch( word, "Polygon" ) ) {
- spaceid = POLYGON_ID;
-
- } else if( astChrMatch( word, "Convex" ) ) {
- spaceid = CONVEX_ID;
-
- } else if( astChrMatch( word, "Union" ) ) {
- spaceid = UNION_ID;
-
- } else if( astChrMatch( word, "Intersection" ) ) {
- spaceid = INTERSECTION_ID;
-
- } else if( astChrMatch( word, "Difference" ) ) {
- spaceid = DIFFERENCE_ID;
-
- } else if( astChrMatch( word, "Not" ) ) {
- spaceid = NOT_ID;
-
- } else if( astChrMatch( word, "Position" ) ) {
- spaceid = POSITION_ID;
-
- } else {
- spaceid = NULL_ID;
- }
-
-/* Return the integer space identifier. */
- return spaceid;
-}
-
-static void StoreTimeProp( AstKeyMap *props, AstTimeFrame *frm,
- const char *key, double value, int *status ){
-/*
-* Name:
-* StoreTimeProp
-
-* Purpose:
-* Store a time value as an STC-S property, using the existing format.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void StoreTimeProp( AstKeyMap *props, AstTimeFrame *frm,
-* const char *key, double value, int *status )
-
-* Class Membership:
-* StcsChan member function.
-
-* Description:
-* This function formats the supplied time value and stores it in
-* the "props" KeyMap, using the supplied key name. If the KeyMap
-* already contains an entry for the given key, the new value is
-* written using the same format. Otherwise, the new value is written
-* as an ISO date and time string.
-
-* Parameters:
-* props
-* Pointer to the KeyMap in which to store the time value.
-* frm
-* Pointer to a TimeFrame that can be used to format the time value.
-* key
-* Pointer to a string holding the property name associated with
-* the time value.
-* value
-* The time value, in the system described by "frm".
-* status
-* Pointer to the inherited status variable.
-
-*/
-
-/* Local Variables: */
- AstFrame *fmtfrm; /* Frame defining Format/System for formatted value */
- AstFrame *fs; /* FrameSet connecting Frames */
- const char *fmttxt; /* Formatted text */
- const char *oldval; /* Pointer to old formatted time value */
- const char *p; /* Pointer to next character in formatted value */
- double fmtval; /* The time value in the formatting system */
- int ndp; /* Number of decimal places in formatted value */
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* We want a TimeFrame (fmtfrm) that describes how to format the time
- value. If the Format attribute of the supplied TimeFrame has been
- set, use it (and the current System). So just take a clone of the
- supplied frame pointer. */
- if( astTestFormat( frm, 0 ) ) {
- fmtfrm = astClone( frm );
-
-/* If the Format attribute has not been set, we create a copy of the
- supplied TimeFrame, and set its System and Format attributes to
- produce the required format. */
- } else {
- fmtfrm = astCopy( frm );
-
-/* If the KeyMap contains an entry for the specified key, determine the
- format of the time string it contains. */
- if( astMapGet0C( props, key, &oldval ) && oldval ) {
-
-/* See how many digits there are after the decimal place */
- p = strchr( oldval, '.' );
- ndp = 0;
- if( p ) {
- while( *(++p) ) {
- if( isdigit( *p ) ) {
- ndp++;
- } else {
- break;
- }
- }
- }
-
-/* If the string starts with "JD", the time is formatted as a numerical
- Julian date. */
- if( !strncmp( oldval, "JD", 2 ) ) {
- astSetSystem( fmtfrm, AST__JD );
- if( ndp > 0 ) {
- astSet( fmtfrm, "Format=JD %%.%df", status, ndp );
- } else {
- astSetFormat( fmtfrm, 0, "JD %d" );
- }
-
-/* If the string starts with "MJD", the time is formatted as a numerical
- Modified Julian date. */
- } else if( !strncmp( oldval, "MJD", 3 ) ) {
- astSetSystem( fmtfrm, AST__MJD );
- if( ndp > 0 ) {
- astSet( fmtfrm, "Format=MJD %%.%df", status, ndp );
- } else {
- astSetFormat( fmtfrm, 0, "MJD %d" );
- }
-
-/* Otherwise, the current word should be an ISO date. See how many
- decimal paces in the seconds field there are (if any). */
- } else {
- astSet( fmtfrm, "Format=iso.%dT", status, ndp );
- }
-
-/* If the KeyMap does not contain an entry for the specified key, an
- ISO date/time string with 1 decimal place in the seconds field
- is used. */
- } else {
- astSetFormat( fmtfrm, 0, "iso.1T" );
- }
- }
-
-/* Ensure the displayed value is an abolute value. */
- astClearTimeOrigin( fmtfrm );
-
-/* Convert the supplied time value into the required system. */
- fs = astConvert( frm, fmtfrm, "" );
- astTran1( fs, 1, &value, 1, &fmtval );
-
-/* Format the value. */
- fmttxt = astFormat( fmtfrm, 0, fmtval );
-
-/* Store it in the KeyMap. */
- astMapPut0C( props, key, fmttxt, NULL );
-
-/* Free resources. */
- fs = astAnnul( fs );
- fmtfrm = astAnnul( fmtfrm );
-}
-
-static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) {
-/*
-* Name:
-* TestAttrib
-
-* Purpose:
-* Test if a specified attribute value is set for a StcsChan.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* int TestAttrib( AstObject *this, const char *attrib, int *status )
-
-* Class Membership:
-* StcsChan member function (over-rides the astTestAttrib protected
-* method inherited from the Object class).
-
-* Description:
-* This function returns a boolean result (0 or 1) to indicate whether
-* a value has been set for one of a StcsChan's attributes.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* attrib
-* Pointer to a null terminated string specifying the attribute
-* name. This should be in lower case with no surrounding white
-* space.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* One if a value has been set, otherwise zero.
-
-* Notes:
-* - A value of zero will be returned if this function is invoked
-* with the global status set, or if it should fail for any reason.
-*/
-
-/* Local Variables: */
- AstStcsChan *this; /* Pointer to the StcsChan structure */
- int result; /* Result value to return */
-
-/* Initialise. */
- result = 0;
-
-/* Check the global error status. */
- if ( !astOK ) return result;
-
-/* Obtain a pointer to the StcsChan structure. */
- this = (AstStcsChan *) this_object;
-
-/* Check the attribute name and test the appropriate attribute. */
-
- if ( !strcmp( attrib, "stcsarea" ) ) {
- result = astTestStcsArea( this );
-
- } else if ( !strcmp( attrib, "stcscoords" ) ) {
- result = astTestStcsCoords( this );
-
- } else if ( !strcmp( attrib, "stcsprops" ) ) {
- result = astTestStcsProps( this );
-
- } else if ( !strcmp( attrib, "stcslength" ) ) {
- result = astTestStcsLength( this );
-
-/* If the attribute is still not recognised, pass it on to the parent
- method for further interpretation. */
- } else {
- result = (*parent_testattrib)( this_object, attrib, status );
- }
-
-/* Return the result, */
- return result;
-}
-
-static int Write( AstChannel *this_channel, AstObject *object, int *status ) {
-/*
-* Name:
-* Write
-
-* Purpose:
-* Write an Object to a StcsChan.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* int Write( AstChannel *this, AstObject *object, int *status )
-
-* Class Membership:
-* StcsChan member function (over-rides the astWrite method
-* inherited from the Channel class).
-
-* Description:
-* This function writes an Object to a StcsChan.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* object
-* Pointer to the Object which is to be written.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* The number of Objects written to the StcsChan by this invocation of
-* astWrite.
-
-* Notes:
-* - A value of zero will be returned if this function is invoked
-* with the AST error status set, or if it should fail for any
-* reason.
-*/
-
-/* Local Variables: */
- AstFrame *frm; /* AREA Frame */
- AstFrameSet *fs; /* FrameSet connecting AREA and COORDS */
- AstKeyMap *props; /* A KeyMap holding the STC-S properties list */
- AstMapping *map; /* Mapping connecting AREA and COORDS */
- AstObject *obj; /* A temporary Object pointer */
- AstRegion *area; /* The Region representing the STC CoordArea */
- AstRegion *coords; /* The Region representing the STC Coords */
- AstRegion *new_coords; /* COORDS Region mapped into frame of AREA */
- AstStcsChan *this; /* Pointer to the StcsChan structure */
- astDECLARE_GLOBALS /* Declare the thread specific global data */
- const char *class; /* Pointer to string holding object class */
- const char *errclass; /* Type of the failed entry */
- const char *errname; /* Name of the failed entry */
- const char *method; /* Pointer to string holding calling method */
- const char *wantclass; /* The expected type */
- int ret; /* Number of objects read */
-
-/* Initialise. */
- ret = 0;
-
-/* Check the global error status. */
- if ( !astOK ) return ret;
-
-/* Get a pointer to the structure holding thread-specific global data. */
- astGET_GLOBALS(this_channel);
-
-/* Obtain a pointer to the StcsChan structure. */
- this = (AstStcsChan *) this_channel;
-
-/* Store the calling method, and object class. */
- method = "astWrite";
- class = astGetClass( this );
-
-/* Initialise */
- area = NULL;
- coords = NULL;
- props = NULL;
-
-/* If the supplied Object is a Region, we will use it to define the AREA
- properties. */
- if( astIsARegion( object ) ) {
- area = (AstRegion *) astClone( object );
-
-/* If the supplied Object is a KeyMap... */
- } else if( astIsAKeyMap( object ) ) {
- errname = NULL;
- wantclass = NULL;
- errclass = NULL;
-
-/* If the supplied KeyMap contains an entry with key "AREA", and if it is
- a Region, use it to define the AREA properties. */
- if( astMapGet0A( (AstKeyMap *) object, "AREA", &obj ) ) {
- if( astIsARegion( obj ) ) {
- area = (AstRegion *) obj;
- } else {
- wantclass = "Region";
- errclass = astGetClass( obj );
- errname = "AREA";
- obj = astAnnul( obj );
- }
- }
-
-/* If the supplied KeyMap contains an entry with key "COORDS", and if it is
- a Region, use it to define the COORDS properties. */
- if( astMapGet0A( (AstKeyMap *) object, "COORDS", &obj ) ) {
- if( astIsARegion( obj ) ) {
- coords = (AstRegion *) obj;
- } else {
- wantclass = "Region";
- errclass = astGetClass( obj );
- errname = "COORDS";
- obj = astAnnul( obj );
- }
- }
-
-/* If the supplied KeyMap contains an entry with key "PROPS", and if it is
- a KeyMap, use it to define values for the properties that cannot be
- determined from the supplied Regions (Resolution, PixSize, etc). */
- if( astMapGet0A( (AstKeyMap *) object, "PROPS", &obj ) ) {
- if( astIsAKeyMap( obj ) ) {
- props = (AstKeyMap *) obj;
- } else {
- wantclass = "KeyMap";
- errclass = astGetClass( obj );
- errname = "PROPS";
- obj = astAnnul( obj );
- }
- }
-
-/* If the supplied KeyMap contains an entry with any of the keys
- "TIME_PROPS", "SPACE_PROPS", "SPECTRAL_PROPS" or "REDSHIFT_PROPS",
- use the supplied KeyMap to define values for all properties. */
- if( astMapGet0A( (AstKeyMap *) object, "TIME_PROPS", &obj ) ||
- astMapGet0A( (AstKeyMap *) object, "SPACE_PROPS", &obj ) ||
- astMapGet0A( (AstKeyMap *) object, "SPECTRAL_PROPS", &obj ) ||
- astMapGet0A( (AstKeyMap *) object, "REDSHIFT_PROPS", &obj ) ) {
- props = astClone( object );
- }
-
-/* Report an error if the Object in the keymap has the wrong type. */
- if( errname && astOK ) {
- astAddWarning( this, 1, "The supplied KeyMap contains a %s "
- "called '%s'. But '%s' should be a %s "
- "(programming error).", method, status,
- errclass, errname, errname, wantclass );
- }
-
-/* Report an error if the keymap contains none of the above. */
- if( !area && !coords && !props && astOK ) {
- astAddWarning( this, 1, "The supplied KeyMap does not "
- "contains anything that can be written out "
- "through a %s.", method, status, class );
- }
-
-/* If both COORDS and AREA were supplied, ensure they are in the same
- Frame by mapping the COORDS Region into the Frame of the AREA Region. */
- if( area && coords ) {
- fs = astConvert( coords, area, " " );
- if( fs ) {
- map = astGetMapping( fs, AST__BASE, AST__CURRENT );
- frm = astGetFrame( fs, AST__CURRENT );
-
- new_coords = astMapRegion( coords, map, frm );
-
- map = astAnnul( map );
- frm = astAnnul( frm );
- coords = astAnnul( coords );
- fs = astAnnul( fs );
-
- coords = new_coords;
-
- } else if( astOK ){
- astAddWarning( this, 1, "Cannot convert between the co-ordinate "
- "frame of the COORDS Region and the co-ordinate "
- "frame of the AREA Region.", method, status );
- }
- }
-
-/* Report an error if the supplied object is neither a KeyMap nor a
- Region. */
- } else if( astOK ) {
- astAddWarning( this, 1, "Failed to write out a %s through a %s. "
- "The %s class cannot be used to write out a %s.",
- method, status, astGetClass( object ), class, class,
- astGetClass( object ) );
- }
-
-
-/* If we do not have a KeyMap in which to store the STC-S properties,
- create one now. */
- if( astOK ) {
- if( ! props ) props = astKeyMap ( " ", status );
-
-/* Determine the set of STC-S properties that describe the COORDS Region,
- and add them into the properties keymap, over-writing any values for the
- same properties that are already in the props keymap. */
- ret = coords ? WriteRegion( this, coords, props, status ) : 1;
-
-/* Determine the set of STC-S properties that describe the AREA Region,
- and add them into the properties keymap, over-writing any values for the
- same properties that are already in the props keymap. NB, we need to
- do AREA after COORDS so that the sub-phrase identifier implied by the
- AREA is used in preference to that implied by the COORDS. */
- if( area && ret ) ret = WriteRegion( this, area, props, status );
-
-/* Convert the properties list into text and write it out through the
- parent Channel's sink function. */
- if( ret ) WriteProps( this, props, status );
- }
-
-/* Free resources. */
- if( area ) area = astAnnul( area );
- if( coords ) coords = astAnnul( coords );
- if( props ) props = astAnnul( props );
-
-/* If an error has occurred, return zero. */
- if( !astOK ) ret = 0;
-
-/* Return the answer. */
- return ret;
-}
-
-static void WriteProps( AstStcsChan *this, AstKeyMap *props, int *status ){
-/*
-* Name:
-* WriteProps
-
-* Purpose:
-* Write out a set of STC-S properties to the sink function.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* void WriteProps( AstStcsChan *this, AstKeyMap *props, int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function converts the STC-S properties supplied in a KeyMap
-* into text, and writes the text out through the sink function associated
-* with the parent Channel.
-
-* Parameters:
-* this
-* Pointer to the StcsChan.
-* props
-* Pointer to the KeyMap holding the STC-S properties.
-* status
-* Pointer to the inherited status variable.
-
-*/
-
-/* Local Variables: */
- AstKeyMap *spprops; /* Sub-phrase properties */
- AstObject *obj; /* Generic Object pointer */
- char *line; /* Dynamically allocated buffer for output text */
- const char *id; /* Sub-phrase identifier */
- const char *prefix; /* Prefix for property value */
- int nc; /* Number of characters in "line" */
- int pretty; /* Include new-lines and indentation in returned text? */
- int crem; /* Character remaining on current output line */
- int linelen; /* Line length */
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* Initialise things. */
- nc = 0;
- line = NULL;
-
-/* See if indentation and new-lines are to be added to the output text to
- make it look pretty. */
- pretty = astGetIndent( this );
-
-/* If so, get the line length to use, and initialise the number of
- remaining characters in the current output line. */
- if( pretty ) {
- linelen = astGetStcsLength( this );
- } else {
- linelen = 0;
- }
- crem = linelen;
-
-/* Add each word in the time sub-phrase into the output buffer, in the
- order defined by the STC-S standard. */
- if( astMapGet0A( props, "TIME_PROPS", &obj ) ) {
- spprops = (AstKeyMap *) obj;
-
- line = AddItem( this, spprops, "ID", NULL, line, &nc, &crem, linelen, status );
- astMapGet0C( spprops, "ID", &id );
-
- line = AddItem( this, spprops, "FILLFACTOR", "fillfactor ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "TIMESCALE", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "REFPOS", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "START", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "STOP", NULL, line, &nc, &crem, linelen, status );
-
- prefix = !astChrMatch( id, "Time" ) ? "Time " : NULL;
- line = AddItem( this, spprops, "TIME", prefix, line, &nc, &crem, linelen, status );
-
- line = AddItem( this, spprops, "UNIT", "unit ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "ERROR", "Error ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "RESOLUTION", "Resolution ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "PIXSIZE", "PixSize ", line, &nc, &crem, linelen, status );
-
- spprops = astAnnul( spprops );
-
-/* Write out the time sub-phrase text through the Channel sink function. */
- if( pretty && astChrLen( line ) ) {
- astPutNextText( this, line );
- nc = 0;
- crem = linelen;
- }
- }
-
-/* Add each word in the space sub-phrase into the output buffer, in the
- order defined by the STC-S standard. */
- if( astMapGet0A( props, "SPACE_PROPS", &obj ) ) {
- spprops = (AstKeyMap *) obj;
-
- line = AddItem( this, spprops, "ID", NULL, line, &nc, &crem, linelen, status );
- astMapGet0C( spprops, "ID", &id );
-
- line = AddItem( this, spprops, "FILLFACTOR", "fillfactor ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "FRAME", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "REFPOS", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "FLAVOUR", NULL, line, &nc, &crem, linelen, status );
-
- line = PutRegionProps( this, spprops, id, (pretty ? 0 : -1), line, &nc,
- &crem, linelen, status );
-
- prefix = !astChrMatch( id, "Position" ) ? "Position " : NULL;
- line = AddItem( this, spprops, "POSITION", prefix, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "UNIT", "unit ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "ERROR", "Error ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "RESOLUTION", "Resolution ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "SIZE", "Size ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "PIXSIZE", "PixSize ", line, &nc, &crem, linelen, status );
-
- spprops = astAnnul( spprops );
-
-/* Write out the spatial sub-phrase text through the Channel sink function. */
- if( pretty && astChrLen( line ) ) {
- astPutNextText( this, line );
- nc = 0;
- crem = linelen;
- }
- }
-
-/* Add each word in the spectral sub-phrase into the output buffer, in the
- order defined by the STC-S standard. */
- if( astMapGet0A( props, "SPECTRAL_PROPS", &obj ) ) {
- spprops = (AstKeyMap *) obj;
-
- line = AddItem( this, spprops, "ID", NULL, line, &nc, &crem, linelen, status );
- astMapGet0C( spprops, "ID", &id );
-
- line = AddItem( this, spprops, "FILLFACTOR", "fillfactor ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "REFPOS", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "LOLIMIT", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "HILIMIT", NULL, line, &nc, &crem, linelen, status );
-
- prefix = !astChrMatch( id, "Spectral" ) ? "Spectral " : NULL;
- line = AddItem( this, spprops, "SPECTRAL", prefix, line, &nc, &crem, linelen, status );
-
- line = AddItem( this, spprops, "UNIT", "unit ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "ERROR", "Error ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "RESOLUTION", "Resolution ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "PIXSIZE", "PixSize ", line, &nc, &crem, linelen, status );
-
- spprops = astAnnul( spprops );
-
-/* Write out the spectral sub-phrase text through the Channel sink function. */
- if( pretty && astChrLen( line ) ) {
- astPutNextText( this, line );
- nc = 0;
- crem = linelen;
- }
- }
-
-/* Add each word in the redshift sub-phrase into the output buffer, in the
- order defined by the STC-S standard. */
- if( astMapGet0A( props, "REDSHIFT_PROPS", &obj ) ) {
- spprops = (AstKeyMap *) obj;
-
- line = AddItem( this, spprops, "ID", NULL, line, &nc, &crem, linelen, status );
- astMapGet0C( spprops, "ID", &id );
-
- line = AddItem( this, spprops, "FILLFACTOR", "fillfactor ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "REFPOS", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "TYPE", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "DOPPLERDEF", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "LOLIMIT", NULL, line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "HILIMIT", NULL, line, &nc, &crem, linelen, status );
-
- prefix = !astChrMatch( id, "Redshift" ) ? "Redshift " : NULL;
- line = AddItem( this, spprops, "REDSHIFT", prefix, line, &nc, &crem, linelen, status );
-
- line = AddItem( this, spprops, "UNIT", "unit ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "ERROR", "Error ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "RESOLUTION", "Resolution ", line, &nc, &crem, linelen, status );
- line = AddItem( this, spprops, "PIXSIZE", "PixSize ", line, &nc, &crem, linelen, status );
-
- spprops = astAnnul( spprops );
-
-/* Write out the redshift sub-phrase text through the Channel sink function. */
- if( pretty && astChrLen( line ) ) {
- astPutNextText( this, line );
- nc = 0;
- crem = linelen;
- }
- }
-
-/* Write out any remaining text through the Channel sink function. */
- if( nc && astChrLen( line ) ) astPutNextText( this, line );
-
-/* Free resources. */
- line = astFree( line );
-
-}
-
-static int WriteRegion( AstStcsChan *this, AstRegion *reg, AstKeyMap *props,
- int *status ){
-/*
-* Name:
-* WriteRegion
-
-* Purpose:
-* Convert a Region into a set of STC-S properties and store them in a
-* KeyMap.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* int WriteRegion( AstStcsChan *this, AstRegion *reg, AstKeyMap *props,
-* int *status )
-
-* Class Membership:
-* StcsChan member function
-
-* Description:
-* This function attempts to convert the supplied Region nto a set of
-* STC-S properties, and stores them in the supplied KeyMap.
-
-* Parameters:
-* this
-* Pointer to the StcsChan being used.
-* reg
-* Pointer to the region to be converted.
-* props
-* Pointer to the KeyMap in which to store the STC-S properties.
-* On exit, each STC-S sub-phrase has an entry in this KeyMap,
-* and each of these entries has a value that is another KeyMap
-* holding the properties for the sub-phrase.
-* status
-* Pointer to the inherited status variable.
-
-* Returned Value:
-* A non-zero value is returned if the conversion was succesful, and
-* zero is returned otherwise.
-*/
-
-/* Local Variables: */
- AstFrame *efrm; /* Pointer to encapsulated Frame */
- AstFrame *pfrm; /* Pointer to primary Frame cntaining an axis */
- AstFrame *spfrm; /* The sub-phrase Frame */
- AstKeyMap *spprops; /* Sub-phrase properties */
- AstMapping *map; /* Base->current Region Mapping */
- AstMapping *sreg; /* Simplified Region */
- AstObject *obj; /* Generic object pointer */
- AstRegion *spreg; /* The sub-phrase Region */
- AstRegion *treg; /* Temporary Region pointer */
- AstRegion *unc; /* Uncertainty region */
- AstRegion *unca; /* Adaptive uncertainty region */
- AstStdOfRestType sor; /* StdOfRest attribute value */
- AstSystemType sys; /* System attribute value */
- char *prop; /* Formatted property string */
- char *unit1; /* Pointer to string holding first axis unit */
- char buf[ 100 ]; /* Buffer for formatted values */
- char fmt[ 10 ]; /* Buffer for format specifier */
- const char *class; /* Class name */
- const char *dom; /* Domain name */
- const char *dopdef; /* DopplerDef value */
- const char *flavour; /* The STC-S flavour for the space frame */
- const char *q; /* Pointer to next character */
- const char *tfrm; /* STC-S string for Frame */
- const char *tsor; /* STC-S string for RefPos */
- const char *tts; /* Time scale label */
- const char *type; /* Redshift Type value */
- const char *unit; /* Unit string */
- double *pcen; /* Pointer to Circle or ellipse centre */
- double equinox; /* The required equinox value */
- double error; /* Axis error value */
- double fill; /* Fill factor */
- double lbnd[ 3 ]; /* Region lower bounds */
- double lim; /* Unlimited bounds value */
- double p1[ 2 ]; /* End point of error line */
- double scale; /* Factor for scaling Region values into required units */
- double ubnd[ 3 ]; /* Region upper bounds */
- int allthesame; /* Do all axes have the same units? */
- int defdigs; /* Default number of digits */
- int defs; /* Include default values in output STC-S? */
- int i; /* Loop index */
- int issky; /* Do the space axes form a SkyFrame? */
- int nax; /* The number of axes */
- int nc; /* Number of characters in "prop" string */
- int nspace; /* Number of space axes */
- int ok; /* Can the Region be written out? */
- int pax; /* Index of axis in primary Frame */
- int redax; /* The index of the redshift axis */
- int retain_units; /* Retain the units/system in properties KeyMap? */
- int spaceax[ 3 ]; /* Indicies of the space axes */
- int spaceid; /* Code for space sub-phrase identifier */
- int specax; /* The index of the spectral axis */
- int timeax; /* Index of time axis */
- int ts; /* Time scale identifier */
-
-/* Check the global error status. */
- if ( !astOK ) return 0;
-
-/* Initialise things to avoid comiler warnings. */
- sys = AST__BADSYSTEM;
-
-/* Assume we can do the conversion. */
- ok = 1;
-
-/* See if default values are to be included in the output. */
- defs = ( astGetFull( this ) > 0 );
-
-/* STC-S requires that the spatial shape (circle, box. etc) refers to
- the coordinate system described by the STC-S. This is not quite like
- AST, in that the AST class type (Circle, Box, etc) defines the
- shape of the region in the base Frame, rather than the current Frame.
- So we can only write the Region out using STC-S if the shape in the
- current Frame is the same as the shape in the base Frame. This is the
- case if the simplified Mapping connecting base and current Frames is
- a UnitMap. Get the base->current Mapping from the Region. */
- map = astRegMapping( reg );
-
-/* If it is not UnitMap, see if simplifying the whole Region results in
- the base->current Mapping in the simplified Region being a UnitMap. */
- if( !astIsAUnitMap( map ) ) {
- map = astAnnul( map );
- sreg = astSimplify( reg );
- map = astRegMapping( sreg );
-
-/* If it is still not UnitMap, we cannot write out the region. */
- if( !astIsAUnitMap( map ) ) {
- astAddWarning( this, 1, "The supplied Region does not have a "
- "supported shape within its current coordinate "
- "system.", "astWrite", status );
- ok = 0;
- }
-
- } else {
- sreg = astClone( reg );
- }
- map = astAnnul( map );
-
-/* Store a safe value that can be used to test unbounded axes. */
- lim = sqrt( DBL_MAX );
-
-/* First job is to identify the Time, Space, Spectral and Redshift axes
- in the supplied Region.
- ------------------------------------------------------------------- */
-
-/* Initialise things. */
- timeax = -1;
- nspace = 0;
- issky = 0;
- specax = -1;
- redax = -1;
- prop = NULL;
-
-/* Get a pointer to the Frame encapsulated by the Region. */
- efrm = astRegFrame( sreg );
-
-/* Loop round all axes. */
- nax = astGetNaxes( sreg );
- for( i = 0; i < nax; i++ ) {
-
-/* Get the primary Frame that defines the current axis of the Region. */
- astPrimaryFrame( efrm, i, &pfrm, &pax );
-
-/* Get its class and domain. */
- class = astGetClass( pfrm );
- dom = astGetDomain( pfrm );
- if( astOK ) {
-
-/* The time axis is described by a TimeFrame with any domain. */
- if( !strcmp( class, "TimeFrame" ) ) {
- if( timeax == -1 ) {
- timeax = i;
- } else {
- astAddWarning( this, 1, "More than one time axis found. "
- "Extra axis (axis %d) will be ignored.",
- "astWrite", status, i + 1 );
- }
-
-/* The space axes are described by a SkyFrame or a basic Frame. If a
- mixture of both types are found, report a warning and ignore the later
- axes. */
- } else if( !strcmp( class, "SkyFrame" ) ) {
- if( issky || nspace == 0 ) {
- if( nspace < 2 ) {
- spaceax[ nspace++ ] = i;
- issky = 1;
- } else {
- astAddWarning( this, 1, "More than two sky frame axes "
- "found. Extra axis (axis %d) will be ignored.",
- "astWrite", status, i + 1 );
- }
-
- } else {
- astAddWarning( this, 1, "Mixture of basic and sky frame "
- "axes found. Sky frame axis %d will be "
- "ignored.", "astWrite", status, i + 1 );
- }
-
- } else if( !strcmp( class, "Frame" ) ) {
- if( !issky ) {
- if( nspace < 3 ) {
- spaceax[ nspace++ ] = i;
- } else {
- astAddWarning( this, 1, "More than three basic space frame axes "
- "found. Extra axis (axis %d) will be ignored.",
- "astWrite", status, i + 1 );
- }
-
- } else {
- astAddWarning( this, 1, "Mixture of basic and sky frame "
- "axes found. Basic frame axis %d will be "
- "ignored.", "astWrite", status, i + 1 );
- }
-
-/* The spectral axis is described by a SpecFrame with domain SPECTRUM. */
- } else if( !strcmp( class, "SpecFrame" ) &&
- !strcmp( dom, "SPECTRUM" ) ) {
- if( specax == -1 ) {
- specax = i;
- } else {
- astAddWarning( this, 1, "More than one spectral axis found. "
- "Extra axis (axis %d) will be ignored.",
- "astWrite", status, i + 1 );
- }
-
-/* The redshift axis is described by a SpecFrame with domain REDSHIFT. */
- } else if( !strcmp( class, "SpecFrame" ) &&
- !strcmp( dom, "REDSHIFT" ) ) {
- if( redax == -1 ) {
- redax = i;
- } else {
- astAddWarning( this, 1, "More than one redshift axis found. "
- "Extra axis (axis %d) will be ignored.",
- "astWrite", status, i + 1 );
- }
-
-/* Warn about unused axes. */
- } else {
- astAddWarning( this, 1, "Could not classify axis %d (class=%s "
- "domain=%s). It will be ignored.", "astWrite", status,
- i + 1, class, dom );
- }
- }
-
-/* Free resources. */
- pfrm = astAnnul( pfrm );
- }
- efrm = astAnnul( efrm );
-
-/* Set a flag indicating if there is anything to convert. */
- ok = ok && ( timeax != -1 || nspace > 0 || specax != -1 || redax != -1 );
-
-
-/* Now we have identified the axes, we convert each available STC-S
- sub-phrase, starting with the time sub-phrase.
- ---------------------------------------------------------------- */
- if( timeax != -1 ) {
-
-/* Create a Region by picking the time axis from the supplied Region. */
- spreg = astPickAxes( sreg, 1, &timeax, NULL );
-
-/* Check it is a Region. If not, we cannot convert anything. */
- if( !astIsARegion( spreg ) ) {
- astAddWarning( this, 1, "Cannot determine the region covered by "
- "the time axis.", "astWrite", status );
- ok = 0;
-
-/* Otherwise we add a description of the time sub-phrase to the
- properties keymap. */
- } else {
-
-/* Get a pointer to the Region's time phrase property KeyMap, creating
- one if necessary. */
- if( astMapGet0A( props, "TIME_PROPS", &obj ) ) {
- spprops = (AstKeyMap *) obj;
- } else {
- spprops = astKeyMap( " ", status );
- astMapPut0A( props, "TIME_PROPS", spprops, NULL );
- }
-
-/* Get the Region's fill factor. */
- fill = astGetFillFactor( spreg );
-
-/* Ensure the TimeFrame represents MJD. If not, take a deep copy (to
- avoid changing the supplied Region), and set its system to MJD. */
- if( astGetSystem( spreg ) != AST__MJD ) {
- treg = astCopy( spreg );
- (void) astAnnul( spreg );
- spreg = treg;
- astSetAdaptive( spreg, 1 );
- astSetSystem( spreg, AST__MJD );
- }
-
-/* Get the bounds of the Region (i.e. the time axis coverage). */
- astGetRegionBounds( spreg, lbnd, ubnd );
-
-/* Get a pointer to the time Region's encapsulated Frame. */
- spfrm = astRegFrame( spreg );
-
-/* Report a warning if the sub-phrase Frame is not a TimeFrame */
- if( !astIsATimeFrame( spfrm ) ) {
- ok = 0;
- astAddWarning( this, 1, "The time sub-phrase in the supplied "
- "KeyMap is not described using an AST TimeFrame.",
- "astWrite", status );
-
-/* Store properties that are specific to Time moments... */
- } else if( lbnd[ 0 ] == ubnd[ 0 ] ) {
- astMapPut0C( spprops, "ID", "Time", NULL );
- StoreTimeProp( spprops, (AstTimeFrame *) spfrm, "TIME", lbnd[ 0 ], status );
- fill = AST__BAD;
-
-/* Store properties that are specific to Time intervals... */
- } else if( lbnd[ 0 ] > -lim && ubnd[ 0 ] < lim ) {
- astMapPut0C( spprops, "ID", "TimeInterval", NULL );
- StoreTimeProp( spprops, (AstTimeFrame *) spfrm, "START", lbnd[ 0 ], status );
- StoreTimeProp( spprops, (AstTimeFrame *) spfrm, "STOP", ubnd[ 0 ], status );
-
-/* Store properties that are specific to Start times... */
- } else if( lbnd[ 0 ] > -lim ) {
- astMapPut0C( spprops, "ID", "StartTime", NULL );
- StoreTimeProp( spprops, (AstTimeFrame *) spfrm, "START", lbnd[ 0 ], status );
-
-/* Store properties that are specific to Stop times... */
- } else {
- astMapPut0C( spprops, "ID", "StopTime", NULL );
- StoreTimeProp( spprops, (AstTimeFrame *) spfrm, "STOP", ubnd[ 0 ], status );
-
- }
-
-/* Store properties that are common to all time sub-phrase types. First the
- fill factor. */
- MapPut0D( spprops, "FILLFACTOR", fill, 1.0, defs, status );
-
-/* Now the time scale. */
- ts = astGetTimeScale( spfrm );
- if( ts == AST__TT ) {
- tts = "TT";
-
- } else if( ts == AST__TAI ) {
- tts = "TAI";
-
- } else if( ts == AST__UTC ) {
- tts = "UTC";
-
- } else if( ts == AST__TDB ) {
- tts = "TDB";
-
- } else if( ts == AST__TCG ) {
- tts = "TCG";
-
- } else if( ts == AST__TCB ) {
- tts = "TCB";
-
- } else if( ts == AST__LMST ) {
- tts = "LST";
-
- } else {
- tts = "nil";
- astAddWarning( this, 1, "Timescale '%s' is unsupported by "
- "STC-S.", "astWrite", status,
- astGetC( spfrm, "TimeScale" ) );
- ok = 0;
- }
-
- MapPut0C( spprops, "TIMESCALE", tts, "nil", defs, status );
-
-/* RefPos. The AST TimeFrame class has no reference position, we leave
- unchanged any refpos already in the keymap. If there is no refpos in the
- keymap, we use "TOPOCENTER". */
- if( !astMapHasKey( spprops, "REFPOS" ) ) {
- astMapPut0C( spprops, "REFPOS", "TOPOCENTER", NULL );
- }
-
-/* That's it for the time sub-phrase, unless the supplied Region has an
- explicit (non-default) uncertainty. */
- unc = astGetUnc( spreg, 0 );
- if( unc ) {
-
-/* See if the supplied properties KeyMap contains any item that refers to
- the Unit included in the STC-S description, but which is not updated by
- this function. If it does, we need to retain any units specified
- within the KeyMap. */
- retain_units = ( astMapHasKey( spprops, "RESOLUTION" ) ||
- astMapHasKey( spprops, "PIXSIZE" ) ||
- astMapHasKey( spprops, "SIZE" ) );
-
- if( retain_units ) {
- if( !astMapGet0C( spprops, "UNIT", &unit ) ) unit = "s";
- } else {
- unit = "s";
- }
-
-/* Store the units string */
- MapPut0C( spprops, "UNIT", unit, "s", defs, status );
-
-/* If necessary, map the uncertainty region into the requied units. Take
- a deep copy to avoid changing the supplied Region. */
- if( strcmp( unit, astGetUnit( unc, 0 ) ) ) {
- unca = astCopy( unc );
- astSetAdaptive( unca, 0 );
- astSetUnit( unca, 0, unit );
- } else {
- unca = astClone( unc );
- }
-
-/* Get the bounds of the uncertainty. */
- astGetRegionBounds( unca, lbnd, ubnd );
-
-/* The error is half the width of the bounding box. */
- astMapPut0D( spprops, "ERROR", 0.5*( ubnd[ 0 ] - lbnd[ 0 ] ), NULL );
-
-/* Free resources. */
- unca = astAnnul( unca );
- unc = astAnnul( unc );
- }
-
-/* Free resources. */
- spfrm = astAnnul( spfrm );
- spprops = astAnnul( spprops );
- }
-
-/* Free resources. */
- spreg = astAnnul( spreg );
-
- }
-
-
-/* Now convert the space sub-phrase.
- ---------------------------------------------------------------- */
- if( nspace > 0 && ok ) {
-
-/* Create a Region by picking the space axes from the supplied Region. */
- spreg = astPickAxes( sreg, nspace, spaceax, NULL );
-
-/* Check it is a Region. If not, we cannot convert anything. */
- if( ! astIsARegion( spreg ) ) {
- astAddWarning( this, 1, "Cannot determine the region covered by "
- "the space axes.", "astWrite", status );
- ok = 0;
-
-/* Otherwise we add a description of the space sub-phrase to the
- properties keymap. */
- } else {
-
-/* Get a pointer to the Region's space phrase property KeyMap, creating
- one if necessary. */
- if( astMapGet0A( props, "SPACE_PROPS", &obj ) ) {
- spprops = (AstKeyMap *) obj;
- } else {
- spprops = astKeyMap( " ", status );
- astMapPut0A( props, "SPACE_PROPS", spprops, NULL );
- }
-
-/* If the space frame is a SkyFrame, ensure it refers to a coodinate
- system that is supported by STC-S. Take a deep copy before changing
- anything. */
- if( issky ) {
- sys = astGetSystem( spreg );
- if( sys != AST__FK4 &&
- sys != AST__FK5 &&
- sys != AST__ICRS &&
- sys != AST__ECLIPTIC &&
- sys != AST__GALACTIC &&
- sys != AST__SUPERGALACTIC &&
- sys != AST__UNKNOWN ) {
- treg = astCopy( spreg );
- (void) astAnnul( spreg );
- spreg = treg;
- astSetAdaptive( spreg, 1 );
- astSetSystem( spreg, AST__ICRS );
- }
- }
-
-/* Get a pointer to the Region's encapsulated Frame. */
- spfrm = astRegFrame( spreg );
-
-/* If the supplied Region is defined in a SkyFrame, choose the units to
- use when storing radius, error, etc in the KeyMap. If the props KeyMap
- already contains a unit specification, we use it. Otherwise we use the
- default (degrees). AST uses radians internally, so find the scaling
- factor. */
- if( issky ) {
- if( astMapGet0C( spprops, "UNIT", &unit ) ) {
- if( !strcmp( unit, "arcmin" ) ) {
- scale = AST__DR2D*60.0;
- } else if( !strcmp( unit, "arcsec" ) ) {
- scale = AST__DR2D*3600.0;
- } else {
- unit = "deg";
- scale = AST__DR2D;
- }
- } else {
- unit = "deg";
- scale = AST__DR2D;
- }
-
-/* Store the units string */
- MapPut0C( spprops, "UNIT", unit, "deg", defs, status );
-
-/* If the supplied Region is not defined in a SkyFrame, we will arrange
- that the Region and the KeyMap use the same units, so set a scale
- factor of 1.0. */
- } else {
- scale = 1.0;
-
-/* See if the supplied properties KeyMap contains any item that refers to
- the Unit included in the STC-S description, but which is not updated by
- this function. If it does, we need to retain any units specified
- within the KeyMap. */
- retain_units = ( astMapHasKey( spprops, "RESOLUTION" ) ||
- astMapHasKey( spprops, "PIXSIZE" ) ||
- astMapHasKey( spprops, "SIZE" ) );
-
-/* If so, and if the properties KeyMap already contains a Unit
- specification, we convert the Region to the same units. Take a deep
- copy of the Region first to avoid modifying the supplied Region. */
- if( retain_units ) {
- if( !astMapGet0C( spprops, "UNIT", &unit ) ) unit = "deg";
-
- treg = astCopy( spreg );
- (void) astAnnul( spreg );
- spreg = treg;
-
- for( i = 0; i < nspace; i++ ) {
- astSetUnit( spreg, i, unit );
-
-/* Space frames can have different units on different axes. So look for
- the start of the next word in the Unit propert. This will be the unit
- for the next axis. If there are no more words in the Unit property,
- re-use the last unit value. */
- q = unit;
- while( *q && !isspace( *q ) ) q++;
- while( *q && isspace( *q ) ) q++;
- if( *q ) unit = q;
- }
-
-/* If we are not retaining the units specified in the properties KeyMap, we
- retain the existing Region units instead, and store these units in the
- properties KeyMap. We also check that these units are supported by
- STC-S. */
- } else {
-
- nc = 0;
- allthesame = 1;
- unit1 = NULL;
-
- for( i = 0; i < nspace; i++ ) {
- unit = astGetUnit( spreg, i );
-
- if( !unit1 ) {
- unit1 = astStore( NULL, unit, strlen( unit ) + 1 );
- } else {
- if( strcmp( unit, unit1 ) ) allthesame = 0;
- }
-
- if( strcmp( unit, "deg" ) &&
- strcmp( unit, "arcmin" ) &&
- strcmp( unit, "arcsec" ) &&
- strcmp( unit, "m" ) &&
- strcmp( unit, "mm" ) &&
- strcmp( unit, "km" ) &&
- strcmp( unit, "AU" ) &&
- strcmp( unit, "pc" ) &&
- strcmp( unit, "kpc" ) &&
- strcmp( unit, "Mpc" ) ) {
- astAddWarning( this, 1, "Cannot use spatial units '%s'.",
- "astWrite", status, unit );
- ok = 0;
- break;
- }
- prop = astAppendString( prop, &nc, unit );
- prop = astAppendString( prop, &nc, " " );
- }
-
-/* Remove the trailing space, and store the property value in the KeyMap. */
- if( ! allthesame ) {
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( spprops, "UNIT", prop, NULL );
- }
- } else {
- astMapPut0C( spprops, "UNIT", unit1, NULL );
- }
-
- unit1 = astFree( unit1 );
-
- }
- }
-
-/* Get the fill factor. */
- fill = astGetFillFactor( spreg );
-
-/* Get the default number of digits. This is only used if the supplied
- properties KeyMap does not have a value for the item being stored. If
- it does, the number of digits is inherited form the value int he KeyMap. */
- defdigs = astGetDigits( spfrm );
-
-/* Store properties that are specific to the particular type of Region. */
- spaceid = GetRegionProps( this, spreg, spprops, nspace, defdigs,
- scale, issky, status );
- if( spaceid == NULL_ID ) ok = 0;
-
-/* If the above went OK, store values for the properties that are common
- to all types of space sub-phrase. */
- if( ok ) {
-
-/* First the fill factor. */
- if( spaceid != POSITION_ID ) {
- MapPut0D( spprops, "FILLFACTOR", fill, 1.0, defs, status );
- }
-
-/* Now the coordinate frame. */
- tfrm = NULL;
- sys = astGetSystem( spfrm );
- if( issky ) {
- if( sys == AST__FK4 ){
- tfrm = "B1950";
- equinox = 1950.0;
-
- } else if( sys == AST__FK5 ){
- tfrm = "J2000";
- equinox = 2000.0;
-
- } else if( sys == AST__ICRS ){
- tfrm = "ICRS";
- equinox = AST__BAD;
-
- } else if( sys == AST__ECLIPTIC ){
- tfrm = "ECLIPTIC";
- equinox = 2000.0;
-
- } else if( sys == AST__GALACTIC ){
- tfrm = "GALACTIC";
- equinox = AST__BAD;
-
- } else if( sys == AST__SUPERGALACTIC ){
- tfrm = "SUPER_GALACTIC";
- equinox = AST__BAD;
-
- } else if( sys == AST__UNKNOWN ){
- tfrm = NULL;
- equinox = AST__BAD;
-
- } else {
- tfrm = NULL;
- astAddWarning( this, 1, "Sky system '%s' is "
- "unsupported by STC-S.", "astWrite",
- status, astGetC( spfrm, "System" ) );
- ok = 0;
- }
-
- if( tfrm && equinox != AST__BAD ) {
- if( astGetD( spfrm, "Equinox" ) != equinox ) {
- astAddWarning( this, 1, "STC-S requires an equinox "
- "of %g for the %s frame, but the "
- "supplied %s equinox is %g.", "astWrite",
- status, equinox, tfrm,
- astGetClass( spfrm ),
- astGetD( spfrm, "Equinox" ) );
- ok = 0;
- tfrm = NULL;
- }
- }
- }
-
-/* If we do not yet have a Frame, use the Domain value if it is set (and
- is a legal STC-S Frame). */
- if( ! tfrm ) {
- if( astTestDomain( spfrm ) ) {
- tfrm = astGetDomain( spfrm );
- if( strcmp( tfrm, "ICRS" ) &&
- strcmp( tfrm, "FK5" ) &&
- strcmp( tfrm, "FK4" ) &&
- strcmp( tfrm, "J2000" ) &&
- strcmp( tfrm, "B1950" ) &&
- strcmp( tfrm, "ECLIPTIC" ) &&
- strcmp( tfrm, "GALACTIC" ) &&
- strcmp( tfrm, "GALACTIC_II" ) &&
- strcmp( tfrm, "SUPER_GALACTIC" ) &&
- strcmp( tfrm, "GEO_C" ) &&
- strcmp( tfrm, "GEO_D" ) ){
- astAddWarning( this, 1, "'UNKNOWNFrame' being used in "
- "place of unsupported frame '%s'.",
- "astWrite", status, tfrm );
- tfrm = NULL;
- }
- }
- }
-
-/* Store the Frame name in the props keymap. */
- if( !tfrm ) tfrm = "UNKNOWNFrame";
- astMapPut0C( spprops, "FRAME", tfrm, NULL );
-
-/* RefPos. The AST SkyFrame and Frame classes have no reference position, so
- we leave unchanged any refpos already in the props keymap. If there is
- no refpos in the keymap, we use "TOPOCENTER". */
- if( !astMapHasKey( spprops, "REFPOS" ) ) {
- astMapPut0C( spprops, "REFPOS", "TOPOCENTER", NULL );
- }
-
-/* Flavour. */
- if( issky ) {
- flavour = "SPHER2";
- } else if( nspace == 1 ){
- flavour = "CART1";
- } else if( nspace == 2 ){
- flavour = "CART2";
- } else {
- flavour = "CART3";
- }
- MapPut0C( spprops, "FLAVOUR", flavour, "SPHER2", defs, status );
-
-/* That's it for the space sub-phrase, unless the supplied Region has an
- explicit (non-default) uncertainty. */
- unc = astGetUnc( spreg, 0 );
- if( unc ) {
-
-/* Get the bounds of the uncertainty. */
- astGetRegionBounds( unc, lbnd, ubnd );
-
-/* If its a sky frame, find the position of the centre of the uncertainty
- region. */
- pcen = issky ? astRegCentre( unc, NULL, NULL, 0,
- AST__CURRENT ) : NULL;
-
-/* Find the half-width of the bounding box for each space axis, and
- concatenate their formatted values into a string. If any bound is
- undefined, quit the axis loop with nc=0. We need to convert longitude
- axis values from lingitude increments to arc-distance. */
- nc = 0;
- defdigs = astGetDigits( unc );
-
- for( i = 0; i < nspace; i++ ) {
- if( ubnd[ i ] != AST__BAD && lbnd[ i ] != AST__BAD ){
-
- if( ! issky ) {
- error = 0.5*( ubnd[ i ] - lbnd[ i ] );
- } else {
- if( i == 0 ) {
- p1[ 0 ] = ubnd[ 0 ];
- p1[ 1 ] = pcen[ 1 ];
- } else {
- p1[ 0 ] = pcen[ 0 ];
- p1[ 1 ] = ubnd[ 1 ];
- }
- error = astDistance( spfrm, pcen, p1 );
- }
-
- GetFmt( "ERROR", spprops, i, defdigs, fmt, status );
- (void) sprintf( buf, fmt, scale*error );
- prop = astAppendString( prop, &nc, buf );
- prop = astAppendString( prop, &nc, " " );
-
- } else {
- nc = 0;
- break;
- }
- }
-
-/* If the bounds were all good, store the string holding the formatted
- error values in the properties KeyMap. */
- if( prop && nc > 0 ) {
- prop[ nc - 1 ] = 0;
- astMapPut0C( spprops, "ERROR", prop, NULL );
- }
-
-/* Free resources. */
- pcen = astFree( pcen );
- unc = astAnnul( unc );
- }
- }
-
-/* Free resources. */
- spfrm = astAnnul( spfrm );
- spprops = astAnnul( spprops );
- }
-
-/* Free resources. */
- spreg = astAnnul( spreg );
-
- }
-
-
-
-/* Convert the spectral sub-phrase.
- ---------------------------------------------------------------- */
- if( specax != -1 ) {
-
-/* Create a Region by picking the spectral axis from the supplied Region. */
- spreg = astPickAxes( sreg, 1, &specax, NULL );
-
-/* Check it is a Region. If not, we cannot convert anything. */
- if( !astIsARegion( spreg ) ) {
- astAddWarning( this, 1, "Cannot determine the region covered by "
- "the spectral axis.", "astWrite", status );
- ok = 0;
-
-/* Otherwise we add a description of the spectral sub-phrase to the
- properties keymap. */
- } else {
-
-/* Get a pointer to the Region's spectral phrase property KeyMap, creating
- one if necessary. */
- if( astMapGet0A( props, "SPECTRAL_PROPS", &obj ) ) {
- spprops = (AstKeyMap *) obj;
- } else {
- spprops = astKeyMap( " ", status );
- astMapPut0A( props, "SPECTRAL_PROPS", spprops, NULL );
- }
-
-/* See if the supplied properties KeyMap contains any item that refers to
- the Unit included in the STC-S description, but which is not updated by
- this function. If it does, we need to retain any units specified
- within the KeyMap. */
- retain_units = ( astMapHasKey( spprops, "RESOLUTION" ) ||
- astMapHasKey( spprops, "PIXSIZE" ) ||
- astMapHasKey( spprops, "SIZE" ) );
-
-/* If so, and if the properties KeyMap already contains a Unit specification,
- we convert the Region to the same units and system. Determine the
- required system and units. */
- if( retain_units ) {
- if( !astMapGet0C( spprops, "UNIT", &unit ) ) unit = "Hz";
-
- if( !strcmp( unit, "Hz" ) ||
- !strcmp( unit, "MHz" ) ||
- !strcmp( unit, "GHz" ) ) {
- sys = AST__FREQ;
-
- } else if( !strcmp( unit, "m" ) ||
- !strcmp( unit, "mm" ) ||
- !strcmp( unit, "um" ) ||
- !strcmp( unit, "nm" ) ||
- !strcmp( unit, "Angstrom" ) ) {
- sys = AST__WAVELEN;
-
- } else if( !strcmp( unit, "eV" ) ||
- !strcmp( unit, "keV" ) ||
- !strcmp( unit, "MeV" ) ) {
- sys = AST__ENERGY;
-
- } else {
- astAddWarning( this, 1, "Illegal STC-S units '%s' found in "
- "supplied KeyMap", "astWrite", status, unit );
- ok = 0;
- }
-
-/* If we do not need to retain the units implied by the supplied KeyMap,
- use the Units and system in the supplied Region so long as they are
- supported by STC-S. If not, use a related supported system instead. */
- } else {
- sys = astGetSystem( spreg );
- unit = astGetUnit( spreg, 0 );
-
- if( sys == AST__ENERGY ) {
- sys = AST__ENERGY;
- if( strcmp( unit, "eV" ) &&
- strcmp( unit, "keV" ) &&
- strcmp( unit, "MeV" ) ) unit = "eV";
-
- } else if( sys == AST__WAVELEN || sys == AST__AIRWAVE ||
- sys == AST__VOPTICAL || sys == AST__REDSHIFT ){
- sys = AST__WAVELEN;
- if( strcmp( unit, "m" ) &&
- strcmp( unit, "mm" ) &&
- strcmp( unit, "um" ) &&
- strcmp( unit, "nm" ) &&
- strcmp( unit, "Angstrom" ) ) unit = "m";
-
- } else {
- sys = AST__FREQ;
- if( strcmp( unit, "Hz" ) &&
- strcmp( unit, "MHz" ) &&
- strcmp( unit, "GHz" ) ) unit = "Hz";
-
- }
- }
-
-/* Store the units string */
- MapPut0C( spprops, "UNIT", unit, "Hz", defs, status );
-
-/* If either the System or Unit needs to be changed in the Region, take a
- deep copy first in order to avoid changing the supplied Region. */
- if( sys != astGetSystem( spreg ) ||
- ( unit && strcmp( unit, astGetUnit( spreg, 0 ) ) ) ) {
- treg = astCopy( spreg );
- (void) astAnnul( spreg );
- spreg = treg;
- astSetAdaptive( spreg, 1 );
- astSetSystem( spreg, sys );
- astSetUnit( spreg, 0, unit );
- }
-
-/* Get the Region's fill factor. */
- fill = astGetFillFactor( spreg );
-
-/* Get the bounds of the Region (i.e. the spectral axis coverage). */
- astGetRegionBounds( spreg, lbnd, ubnd );
-
-/* Get a pointer to the spectral Region's encapsulated Frame. */
- spfrm = astRegFrame( spreg );
-
-/* Report a warning if the sub-phrase Frame is not a SpecFrame */
- if( !astIsASpecFrame( spfrm ) ) {
- ok = 0;
- astAddWarning( this, 1, "The spectral sub-phrase in the supplied "
- "KeyMap is not described using an AST SpecFrame.",
- "astWrite", status );
-
-/* Store properties that are specific to spectral positions... */
- } else if( lbnd[ 0 ] == ubnd[ 0 ] ) {
- astMapPut0C( spprops, "ID", "Spectral", NULL );
- astMapPut0D( spprops, "SPECTRAL", lbnd[ 0 ], NULL );
- fill = AST__BAD;
-
-/* Store properties that are specific to Spectral intervals... */
- } else if( lbnd[ 0 ] > -lim && ubnd[ 0 ] < lim ) {
- astMapPut0C( spprops, "ID", "SpectralInterval", NULL );
- astMapPut0D( spprops, "LOLIMIT", lbnd[ 0 ], NULL );
- astMapPut0D( spprops, "HILIMIT", ubnd[ 0 ], NULL );
-
- } else {
- ok = 0;
- astAddWarning( this, 1, "Cannot write out an unbounded "
- "spectral interval.", "astWrite", status );
- }
-
-/* Store properties that are common to all spectral sub-phrase types. First the
- fill factor. */
- MapPut0D( spprops, "FILLFACTOR", fill, 1.0, defs, status );
-
-/* Now the reference position. */
- sor = astGetStdOfRest( spfrm );
- if( sor == AST__GESOR ) {
- tsor = "GEOCENTER";
-
- } else if( sor == AST__BYSOR ) {
- tsor = "BARYCENTER";
-
- } else if( sor == AST__HLSOR ) {
- tsor = "HELIOCENTER";
-
- } else if( sor == AST__TPSOR ) {
- tsor = "TOPOCENTER";
-
- } else if( sor == AST__LKSOR ) {
- tsor = "LSRK";
-
- } else if( sor == AST__LDSOR ) {
- tsor = "LSRD";
-
- } else if( sor == AST__GLSOR ) {
- tsor = "GALACTIC_CENTER";
-
- } else {
- tsor = NULL;
- }
-
- if( !tsor ) tsor = "UNKNOWNRefPos";
- MapPut0C( spprops, "REFPOS", tsor, "UNKNOWNRefPos", defs,
- status );
-
-/* Now the unit string. */
- MapPut0C( spprops, "UNIT", unit, "Hz", defs, status );
-
-/* That's it for the spectral sub-phrase, unless the supplied Region has an
- explicit (non-default) uncertainty. */
- unc = astGetUnc( spreg, 0 );
- if( unc ) {
-
-/* Get the bounds of the uncertainty. */
- astGetRegionBounds( unc, lbnd, ubnd );
-
-/* The error is half the width of the bounding box. */
- astMapPut0D( spprops, "ERROR", 0.5*( ubnd[ 0 ] - lbnd[ 0 ] ), NULL );
-
-/* Free resources. */
- unc = astAnnul( unc );
- }
-
-/* Free resources. */
- spfrm = astAnnul( spfrm );
- spprops = astAnnul( spprops );
- }
-
-/* Free resources. */
- spreg = astAnnul( spreg );
-
- }
-
-
-
-/* Convert the redshift sub-phrase.
- ---------------------------------------------------------------- */
- if( redax != -1 ) {
-
-/* Create a Region by picking the redshift axis from the supplied Region. */
- spreg = astPickAxes( sreg, 1, &redax, NULL );
-
-/* Check it is a Region. If not, we cannot convert anything. */
- if( !astIsARegion( spreg ) ) {
- astAddWarning( this, 1, "Cannot determine the region covered by "
- "the redshift axis.", "astWrite", status );
- ok = 0;
-
-/* Otherwise we add a description of the redshift sub-phrase to the
- properties keymap. */
- } else {
-
-/* Get a pointer to the Region's redshift phrase property KeyMap, creating
- one if necessary. */
- if( astMapGet0A( props, "REDSHIFT_PROPS", &obj ) ) {
- spprops = (AstKeyMap *) obj;
- } else {
- spprops = astKeyMap( " ", status );
- astMapPut0A( props, "REDSHIFT_PROPS", spprops, NULL );
- }
-
-/* See if the supplied properties KeyMap contains any item that refers to
- the system included in the STC-S description, but which is not updated by
- this function. If it does, we need to retain any system specified
- within the KeyMap. */
- retain_units = ( astMapHasKey( spprops, "RESOLUTION" ) ||
- astMapHasKey( spprops, "PIXSIZE" ) ||
- astMapHasKey( spprops, "SIZE" ) );
-
-/* If so, and if the properties KeyMap already contains a DopplerDef or
- Type specification, we convert the Region to the same system. */
- if( retain_units ){
- if( !astMapGet0C( spprops, "DOPPLERDEF", &dopdef ) ) dopdef = "OPTICAL";
- if( !astMapGet0C( spprops, "TYPE", &type ) ) type = "VELOCITY";
-
- if( astChrMatch( type, "VELOCITY" ) ) {
- if( astChrMatch( dopdef, "OPTICAL" ) ) {
- sys = AST__VOPTICAL;
- } else if( astChrMatch( dopdef, "RADIO" ) ) {
- sys = AST__VRADIO;
- } else if( astChrMatch( dopdef, "RELATIVISTIC" ) ) {
- sys = AST__VREL;
- } else {
- astAddWarning( this, 1, "Illegal STC-S DopplerDef '%s' "
- "found in supplied KeyMap", "astWrite", status,
- dopdef );
- ok = 0;
- }
-
- } else if( astChrMatch( type, "REDSHIFT" ) ) {
- if( astChrMatch( dopdef, "OPTICAL" ) ) {
- sys = AST__REDSHIFT;
- } else {
- astAddWarning( this, 1, "Unsupported combination of "
- "DopplerDef='%s' and Type='%s' found in "
- "supplied KeyMap", "astWrite", status, dopdef,
- type );
- ok = 0;
- }
-
- } else {
- astAddWarning( this, 1, "Illegal STC-S Redshift Type '%s' "
- "found in supplied KeyMap", "astWrite", status,
- type );
- ok = 0;
- }
-
-/* If the supplied KeyMap does not imply the required system, use the
- system in the supplied Region. */
- } else {
- sys = astGetSystem( spreg );
- }
-
-/* Choose the requied units. */
- unit = ( sys == AST__REDSHIFT ) ? "": "km/s";
-
-/* Store the units string */
- MapPut0C( spprops, "UNIT", unit, unit, defs, status );
-
-/* If either the System or Unit needs to be changed in the Region, take a
- deep copy first in order to avoid changing the supplied Region. */
- if( sys != astGetSystem( spreg ) ||
- ( unit && strcmp( unit, astGetUnit( spreg, 0 ) ) ) ) {
- treg = astCopy( spreg );
- (void) astAnnul( spreg );
- spreg = treg;
- astSetAdaptive( spreg, 1 );
- astSetSystem( spreg, sys );
- astSetUnit( spreg, 0, unit );
- }
-
-/* Get the Region's fill factor. */
- fill = astGetFillFactor( spreg );
-
-/* Get the bounds of the Region (i.e. the redshift axis coverage). */
- astGetRegionBounds( spreg, lbnd, ubnd );
-
-/* Get a pointer to the spectral Region's encapsulated Frame. */
- spfrm = astRegFrame( spreg );
-
-/* Report a warning if the sub-phrase Frame is not a SpecFrame */
- if( !astIsASpecFrame( spfrm ) ) {
- ok = 0;
- astAddWarning( this, 1, "The redshift sub-phrase in the supplied "
- "KeyMap is not described using an AST SpecFrame.",
- "astWrite", status );
-
-/* Store properties that are specific to redshift positions... */
- } else if( lbnd[ 0 ] == ubnd[ 0 ] ) {
- astMapPut0C( spprops, "ID", "Redshift", NULL );
- astMapPut0D( spprops, "REDSHIFT", lbnd[ 0 ], NULL );
- fill = AST__BAD;
-
-/* Store properties that are specific to Redshift intervals... */
- } else if( lbnd[ 0 ] > -lim && ubnd[ 0 ] < lim ) {
- astMapPut0C( spprops, "ID", "RedshiftInterval", NULL );
- astMapPut0D( spprops, "LOLIMIT", lbnd[ 0 ], NULL );
- astMapPut0D( spprops, "HILIMIT", ubnd[ 0 ], NULL );
-
- } else {
- ok = 0;
- astAddWarning( this, 1, "Cannot write out an unbounded "
- "redshift interval.", "astWrite", status );
- }
-
-/* Store properties that are common to all redshift sub-phrase types. First the
- fill factor. */
- MapPut0D( spprops, "FILLFACTOR", fill, 1.0, defs, status );
-
-/* Now the reference position. */
- sor = astGetStdOfRest( spfrm );
-
- if( sor == AST__GESOR ) {
- tsor = "GEOCENTER";
-
- } else if( sor == AST__BYSOR ) {
- tsor = "BARYCENTER";
-
- } else if( sor == AST__HLSOR ) {
- tsor = "HELIOCENTER";
-
- } else if( sor == AST__TPSOR ) {
- tsor = "TOPOCENTER";
-
- } else if( sor == AST__LKSOR ) {
- tsor = "LSRK";
-
- } else if( sor == AST__LDSOR ) {
- tsor = "LSRD";
-
- } else if( sor == AST__GLSOR ) {
- tsor = "GALACTIC_CENTER";
-
- } else {
- tsor = NULL;
- }
-
- if( !tsor ) tsor = "UNKNOWNRefPos";
- MapPut0C( spprops, "REFPOS", tsor, "UNKNOWNRefPos", defs,
- status );
-
-/* Type and DopplerDef. */
- if( sys == AST__VOPTICAL ) {
- type = "VELOCITY";
- dopdef = "OPTICAL";
-
- } else if( sys == AST__VRADIO ) {
- type = "VELOCITY";
- dopdef = "RADIO";
-
- } else if( sys == AST__VREL ) {
- type = "VELOCITY";
- dopdef = "RELATIVISTIC";
-
- } else {
- type = "REDSHIFT";
- dopdef = "OPTICAL";
- }
- astMapPut0C( spprops, "DOPPLERDEF", dopdef, NULL );
- MapPut0C( spprops, "TYPE", type, "REDSHIFT", defs, status );
-
-/* Now the unit string. */
- MapPut0C( spprops, "UNIT", unit, unit, defs, status );
-
-/* That's it for the redshift sub-phrase, unless the supplied Region has an
- explicit (non-default) uncertainty. */
- unc = astGetUnc( spreg, 0 );
- if( unc ) {
-
-/* Get the bounds of the uncertainty. */
- astGetRegionBounds( unc, lbnd, ubnd );
-
-/* The error is half the width of the bounding box. */
- astMapPut0D( spprops, "ERROR", 0.5*( ubnd[ 0 ] - lbnd[ 0 ] ), NULL );
-
-/* Free resources. */
- unc = astAnnul( unc );
- }
-
-/* Free resources. */
- spfrm = astAnnul( spfrm );
- spprops = astAnnul( spprops );
- }
-
-/* Free resources. */
- spreg = astAnnul( spreg );
-
- }
-
-/* Free resources */
- if( sreg ) sreg = astAnnul( sreg );
- if( prop ) prop = astFree( prop );
-
-/* Return the result. */
- return ok;
-}
-
-/* Functions which access class attributes. */
-/* ---------------------------------------- */
-/* Implement member functions to access the attributes associated with
- this class using the macros defined for this purpose in the
- "object.h" file. For a description of each attribute, see the class
- interface (in the associated .h file). */
-
-/*
-*att++
-* Name:
-* StcsArea
-
-* Purpose:
-* Return the CoordinateArea component when reading an STC-S document?
-
-* Type:
-* Public attribute.
-
-* Synopsis:
-* Integer (boolean).
-
-* Description:
-* This is a boolean attribute which controls what is returned
-* by the
-c astRead
-f AST_READ
-* function when it is used to read from an StcsChan.
-* If StcsArea is set non-zero (the default), then a Region
-* representing the STC CoordinateArea will be returned by
-c astRead.
-f AST_READ.
-* If StcsArea is set to zero, then the STC CoordinateArea
-* will not be returned.
-
-* Notes:
-* - Other attributes such as StcsCoords and StcsProps can be used to
-* specify other Objects to be returned by
-c astRead.
-f AST_READ.
-* If more than one of these attributes is set non-zero, then the
-* actual Object returned by
-c astRead
-f AST_READ
-* will be a KeyMap, containing the requested Objects. In this
-* case, the Region representing the STC CoordinateArea will be
-* stored in the returned KeyMap using the key "AREA". If StcsArea
-* is the only attribute to be set non-zero, then the Object returned by
-c astRead
-f AST_READ
-* will be the CoordinateArea Region itself.
-* - The class of Region used to represent the CoordinateArea for each
-* STC-S sub-phrase is determined by the first word in the
-* sub-phrase (the "sub-phrase identifier"). The individual sub-phrase
-* Regions are combined into a single Prism, which is then simplified
-c using astSimplify
-f using AST_SIMPLIFY
-* to form the returned region.
-* - Sub-phrases that represent a single value ( that is, have
-* identifiers "Time", "Position", "Spectral" or "Redshift" ) are
-* considered to be be part of the STC CoordinateArea component.
-* - The TimeFrame used to represent a time STC-S sub-phrase will have
-* its TimeOrigin attribute set to the sub-phrase start time. If no
-* start time is specified by the sub-phrase, then the stop time will be
-* used instead. If no stop time is specified by the sub-phrase, then
-* the single time value specified in the sub-phrase will be used
-* instead. Subsequently clearing the TimeOrigin attribute (or setting
-* its value to zero) will cause the TimeFrame to reprsent absolute times.
-* - The Epoch attribute for the returned Region is set in the same
-* way as the TimeOrigin attribute (see above).
-
-* Applicability:
-* StcsChan
-* All StcsChans have this attribute.
-*att--
-*/
-
-/* This ia a boolean value (0 or 1) with a value of -INT_MAX when
- undefined but yielding a default of 1. */
-astMAKE_CLEAR(StcsChan,StcsArea,stcsarea,-INT_MAX)
-astMAKE_GET(StcsChan,StcsArea,int,1,( this->stcsarea != -INT_MAX ? this->stcsarea : 1 ))
-astMAKE_SET(StcsChan,StcsArea,int,stcsarea,( value != 0 ))
-astMAKE_TEST(StcsChan,StcsArea,( this->stcsarea != -INT_MAX ))
-
-/*
-*att++
-* Name:
-* StcsCoords
-
-* Purpose:
-* Return the Coordinates component when reading an STC-S document?
-
-* Type:
-* Public attribute.
-
-* Synopsis:
-* Integer (boolean).
-
-* Description:
-* This is a boolean attribute which controls what is returned
-* by the
-c astRead
-f AST_READ
-* function when it is used to read from an StcsChan.
-* If StcsCoords is set non-zero, then a PointList
-* representing the STC Coordinates will be returned by
-c astRead.
-f AST_READ.
-* If StcsCoords is set to zero (the default), then the STC
-* Coordinates will not be returned.
-
-* Notes:
-* - Other attributes such as StcsArea and StcsProps can be used to
-* specify other Objects to be returned by
-c astRead.
-f AST_READ.
-* If more than one of these attributes is set non-zero, then the
-* actual Object returned by
-c astRead
-f AST_READ
-* will be a KeyMap, containing the requested Objects. In this
-* case, the PointList representing the STC Coordinates will be
-* stored in the returned KeyMap using the key "COORDS". If StcsCoords
-* is the only attribute to be set non-zero, then the Object returned by
-c astRead
-f AST_READ
-* will be the Coordinates PointList itself.
-* - The Coordinates component is specified by the additional axis
-* values embedded within the body of each STC-S sub-phrase that
-* represents an extended area. Sub-phrases that represent a single
-* value ( that is, have identifiers "Time", "Position", "Spectral"
-* or "Redshift" ) are not considered to be be part of the STC
-* Coordinates component.
-* - If the STC-S documents does not contain a Coordinates component,
-* then a NULL object pointer
-f (AST__NULL)
-* will be returned by
-c astRead
-f AST_READ
-* if the Coordinates component is the only object being returned. If
-* other objects are also being returned (see attributes StcsProps and
-* StcsArea), then the returned KeyMap will contain a "COORDS" key
-* only if the Coordinates component is read succesfully.
-* - The TimeFrame used to represent a time STC-S sub-phrase will have
-* its TimeOrigin attribute set to the sub-phrase start time. If no
-* start time is specified by the sub-phrase, then the stop time will be
-* used instead. If no stop time is specified by the sub-phrase, then
-* the single time value specified in the sub-phrase will be used
-* instead. Subsequently clearing the TimeOrigin attribute (or setting
-* its value to zero) will cause the TimeFrame to reprsent absolute times.
-* - The Epoch attribute for the returned Region is set in the same
-* way as the TimeOrigin attribute (see above).
-
-* Applicability:
-* StcsChan
-* All StcsChans have this attribute.
-*att--
-*/
-
-/* This ia a boolean value (0 or 1) with a value of -INT_MAX when
- undefined but yielding a default of zero. */
-astMAKE_CLEAR(StcsChan,StcsCoords,stcscoords,-INT_MAX)
-astMAKE_GET(StcsChan,StcsCoords,int,0,( this->stcscoords != -INT_MAX ? this->stcscoords : 0 ))
-astMAKE_SET(StcsChan,StcsCoords,int,stcscoords,( value != 0 ))
-astMAKE_TEST(StcsChan,StcsCoords,( this->stcscoords != -INT_MAX ))
-
-/*
-*att++
-* Name:
-* StcsProps
-
-* Purpose:
-* Return all properties when reading an STC-S document?
-
-* Type:
-* Public attribute.
-
-* Synopsis:
-* Integer (boolean).
-
-* Description:
-* This is a boolean attribute which controls what is returned
-* by the
-c astRead
-f AST_READ
-* function when it is used to read from an StcsChan.
-* If StcsProps is set non-zero, then a KeyMap containing all the
-* properties read from the STC-S document will be returned by
-c astRead.
-f AST_READ.
-* If StcsProps is set to zero (the default), then the properties
-* will not be returned.
-
-* Notes:
-* - Other attributes such as StcsCoords and StcsArea can be used to
-* specify other Objects to be returned by
-c astRead.
-f AST_READ.
-* If more than one of these attributes is set non-zero, then the
-* actual Object returned by
-c astRead
-f AST_READ
-* will be a KeyMap containing the requested Objects. In this
-* case, the properties KeyMap will be stored in the returned KeyMap
-* using the key "PROPS". If StcsProps is the only attribute to be
-* set non-zero, then the Object returned by
-c astRead
-f AST_READ
-* will be the properties KeyMap itself.
-* - The KeyMap containing the properties will have entries for one or
-* more of the following keys: "TIME_PROPS", "SPACE_PROPS", "SPECTRAL_PROPS"
-* and "REDSHIFT_PROPS". Each of these entries will be another KeyMap
-* containing the properties of the corresponding STC-S sub-phrase.
-
-* Applicability:
-* StcsChan
-* All StcsChans have this attribute.
-*att--
-*/
-
-/* This ia a boolean value (0 or 1) with a value of -INT_MAX when
- undefined but yielding a default of zero. */
-astMAKE_CLEAR(StcsChan,StcsProps,stcsprops,-INT_MAX)
-astMAKE_GET(StcsChan,StcsProps,int,0,( this->stcsprops != -INT_MAX ? this->stcsprops : 0 ))
-astMAKE_SET(StcsChan,StcsProps,int,stcsprops,( value != 0 ))
-astMAKE_TEST(StcsChan,StcsProps,( this->stcsprops != -INT_MAX ))
-
-/*
-*att++
-* Name:
-* StcsLength
-
-* Purpose:
-* Controls output line length.
-
-* Type:
-* Public attribute.
-
-* Synopsis:
-* Integer.
-
-* Description:
-* This attribute specifies the maximum length to use when writing out
-* text through the sink function supplied when the StcsChan was created.
-* It is ignored if the Indent attribute is zero (in which case the text
-* supplied to the sink function can be of any length). The default value
-* is 70.
-*
-* The number of characters in each string written out through the sink
-* function will not usually be greater than the value of this attribute
-* (but may be less). However, if any single word in the STC-S
-* description exceeds the specified length, then the word will be
-* written out as a single line.
-*
-f Note, the default value of zero is unlikely to be appropriate when
-f an StcsChan is used within Fortran code. In this case, StcsLength
-f should usually be set to the size of the CHARACTER variable used to
-f receive the text returned by AST_GETLINE within the sink function.
-f In addition, the Indent attribute should be set non-zero. This
-f avoids the possibility of long lines being truncated invisibly
-f within AST_GETLINE.
-
-* Applicability:
-* StcsChan
-* All StcsChans have this attribute.
-*att--
-*/
-astMAKE_CLEAR(StcsChan,StcsLength,stcslength,-INT_MAX)
-astMAKE_GET(StcsChan,StcsLength,int,70,( ( this->stcslength != -INT_MAX ) ? this->stcslength : 70 ))
-astMAKE_SET(StcsChan,StcsLength,int,stcslength,(value<0?0:value))
-astMAKE_TEST(StcsChan,StcsLength,( this->stcslength != -INT_MAX ))
-
-/* Copy constructor. */
-/* ----------------- */
-
-/* Destructor. */
-/* ----------- */
-
-/* Dump function. */
-/* -------------- */
-
-static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
-/*
-* Name:
-* Dump
-
-* Purpose:
-* Dump function for StcsChan objects.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* void Dump( AstObject *this, AstChannel *channel, int *status )
-
-* Description:
-* This function implements the Dump function which writes out data
-* for the StcsChan class to an output Channel.
-
-* Parameters:
-* this
-* Pointer to the Object (an StcsChan) whose data are being written.
-* channel
-* Pointer to the Channel to which the data are being written.
-* status
-* Pointer to the inherited status variable.
-*/
-
-/* Local Variables: */
- AstStcsChan *this; /* Pointer to the StcsChan structure */
- int ival; /* Integer value */
- int set; /* Attribute value set? */
-
-/* Check the global error status. */
- if ( !astOK ) return;
-
-/* Obtain a pointer to the StcsChan structure. */
- this = (AstStcsChan *) this_object;
-
-/* Write out values representing the instance variables for the
- StcsChan class. Accompany these with appropriate comment strings,
- possibly depending on the values being written.*/
-
-/* In the case of attributes, we first use the appropriate (private)
- Test... member function to see if they are set. If so, we then use
- the (private) Get... function to obtain the value to be written
- out.
-
- For attributes which are not set, we use the astGet... method to
- obtain the value instead. This will supply a default value
- (possibly provided by a derived class which over-rides this method)
- which is more useful to a human reader as it corresponds to the
- actual default attribute value. Since "set" will be zero, these
- values are for information only and will not be read back. */
-
-/* StcsArea. */
-/* --------- */
- set = TestStcsArea( this, status );
- ival = set ? GetStcsArea( this, status ) : astGetStcsArea( this );
- astWriteInt( channel, "StcsArea", set, 0, ival,
- ival ? "Read the STC CoordinatesArea component" :
- "Do not read the STC CoordinatesArea component" );
-
-/* StcsCoords. */
-/* ----------- */
- set = TestStcsCoords( this, status );
- ival = set ? GetStcsCoords( this, status ) : astGetStcsCoords( this );
- astWriteInt( channel, "StcsCoords", set, 0, ival,
- ival ? "Read the STC Coordinates component" :
- "Do not read the STC Coordinates component" );
-
-/* StcsProps. */
-/* ---------- */
- set = TestStcsProps( this, status );
- ival = set ? GetStcsProps( this, status ) : astGetStcsProps( this );
- astWriteInt( channel, "StcsProps", set, 0, ival,
- ival ? "Read the STC-S properties" :
- "Do not read the STC-S properties" );
-
-/* StcsLength */
-/* ---------- */
- set = TestStcsLength( this, status );
- ival = set ? GetStcsLength( this, status ) : astGetStcsLength( this );
- astWriteInt( channel, "StcsLen", set, 0, ival, "STC-S buffer length" );
-
-}
-
-/* Standard class functions. */
-/* ========================= */
-/* Implement the astIsAStcsChan and astCheckStcsChan functions using the macros
- defined for this purpose in the "object.h" header file. */
-astMAKE_ISA(StcsChan,Channel)
-astMAKE_CHECK(StcsChan)
-
-AstStcsChan *astStcsChan_( const char *(* source)( void ),
- void (* sink)( const char * ),
- const char *options, int *status, ...) {
-/*
-*++
-* Name:
-c astStcsChan
-f AST_STCSCHAN
-
-* Purpose:
-* Create an StcsChan.
-
-* Type:
-* Public function.
-
-* Synopsis:
-c #include "stcschan.h"
-c AstStcsChan *astStcsChan( const char *(* source)( void ),
-c void (* sink)( const char * ),
-c const char *options, ... )
-f RESULT = AST_STCSCHAN( SOURCE, SINK, OPTIONS, STATUS )
-
-* Class Membership:
-* StcsChan constructor.
-
-* Description:
-* This function creates a new StcsChan and optionally initialises
-* its attributes.
-*
-* A StcsChan is a specialised form of Channel which supports STC-S
-* I/O operations. Writing an Object to an StcsChan (using
-c astWrite) will, if the Object is suitable, generate an
-f AST_WRITE) will, if the Object is suitable, generate an
-* STC-S description of that Object, and reading from an StcsChan will
-* create a new Object from its STC-S description.
-*
-* Normally, when you use an StcsChan, you should provide "source"
-c and "sink" functions which connect it to an external data store
-c by reading and writing the resulting text. These functions
-f and "sink" routines which connect it to an external data store
-f by reading and writing the resulting text. These routines
-* should perform any conversions needed between external character
-c encodings and the internal ASCII encoding. If no such functions
-f encodings and the internal ASCII encoding. If no such routines
-* are supplied, a Channel will read from standard input and write
-* to standard output.
-*
-* Alternatively, an XmlChan can be told to read or write from
-* specific text files using the SinkFile and SourceFile attributes,
-* in which case no sink or source function need be supplied.
-
-* Parameters:
-c source
-f SOURCE = SUBROUTINE (Given)
-c Pointer to a source function that takes no arguments and
-c returns a pointer to a null-terminated string. If no value
-c has been set for the SourceFile attribute, this function
-c will be used by the StcsChan to obtain lines of input text. On
-c each invocation, it should return a pointer to the next input
-c line read from some external data store, and a NULL pointer
-c when there are no more lines to read.
-c
-c If "source" is NULL and no value has been set for the SourceFile
-c attribute, the StcsChan will read from standard input instead.
-f A source routine, which is a subroutine which takes a single
-f integer error status argument. If no value has been set
-f for the SourceFile attribute, this routine will be used by
-f the StcsChan to obtain lines of input text. On each
-f invocation, it should read the next input line from some
-f external data store, and then return the resulting text to
-f the AST library by calling AST_PUTLINE. It should supply a
-f negative line length when there are no more lines to read.
-f If an error occurs, it should set its own error status
-f argument to an error value before returning.
-f
-f If the null routine AST_NULL is suppied as the SOURCE value,
-f and no value has been set for the SourceFile attribute,
-f the StcsChan will read from standard input instead.
-c sink
-f SINK = SUBROUTINE (Given)
-c Pointer to a sink function that takes a pointer to a
-c null-terminated string as an argument and returns void.
-c If no value has been set for the SinkFile attribute, this
-c function will be used by the StcsChan to deliver lines of
-c output text. On each invocation, it should deliver the
-c contents of the string supplied to some external data store.
-c
-c If "sink" is NULL, and no value has been set for the SinkFile
-c attribute, the StcsChan will write to standard output instead.
-f A sink routine, which is a subroutine which takes a single
-f integer error status argument. If no value has been set
-f for the SinkFile attribute, this routine will be used by
-f the StcsChan to deliver lines of output text. On each
-f invocation, it should obtain the next output line from the
-f AST library by calling AST_GETLINE, and then deliver the
-f resulting text to some external data store. If an error
-f occurs, it should set its own error status argument to an
-f error value before returning.
-f
-f If the null routine AST_NULL is suppied as the SINK value,
-f and no value has been set for the SinkFile attribute,
-f the StcsChan will write to standard output instead.
-c options
-f OPTIONS = CHARACTER * ( * ) (Given)
-c Pointer to a null-terminated string containing an optional
-c comma-separated list of attribute assignments to be used for
-c initialising the new StcsChan. The syntax used is identical to
-c that for the astSet function and may include "printf" format
-c specifiers identified by "%" symbols in the normal way.
-f A character string containing an optional comma-separated
-f list of attribute assignments to be used for initialising the
-f new StcsChan. The syntax used is identical to that for the
-f AST_SET routine.
-c ...
-c If the "options" string contains "%" format specifiers, then
-c an optional list of additional arguments may follow it in
-c order to supply values to be substituted for these
-c specifiers. The rules for supplying these are identical to
-c those for the astSet function (and for the C "printf"
-c function).
-f STATUS = INTEGER (Given and Returned)
-f The global status.
-
-* Returned Value:
-c astStcsChan()
-f AST_STCSCHAN = INTEGER
-* A pointer to the new StcsChan.
-
-* Notes:
-f - The names of the routines supplied for the SOURCE and SINK
-f arguments should appear in EXTERNAL statements in the Fortran
-f routine which invokes AST_STCSCHAN. However, this is not generally
-f necessary for the null routine AST_NULL (so long as the AST_PAR
-f include file has been used).
-* - If the external data source or sink uses a character encoding
-* other than ASCII, the supplied source and sink functions should
-* translate between the external character encoding and the internal
-* ASCII encoding used by AST.
-* - A null Object pointer (AST__NULL) will be returned if this
-* function is invoked with the AST error status set, or if it
-* should fail for any reason.
-f - Note that the null routine AST_NULL (one underscore) is
-f different to AST__NULL (two underscores), which is the null Object
-f pointer.
-*--
-*/
-
-/* Local Variables: */
- astDECLARE_GLOBALS /* Pointer to thread-specific global data */
- AstStcsChan *new; /* Pointer to new StcsChan */
- va_list args; /* Variable argument list */
-
-/* Get a pointer to the thread specific global data structure. */
- astGET_GLOBALS(NULL);
-
-/* Check the global status. */
- if ( !astOK ) return NULL;
-
-/* Initialise the StcsChan, allocating memory and initialising the
- virtual function table as well if necessary. This interface is for
- use by other C functions within AST, and uses the standard "wrapper"
- functions included in this class. */
- new = astInitStcsChan( NULL, sizeof( AstStcsChan ), !class_init,
- &class_vtab, "StcsChan", source, SourceWrap,
- sink, SinkWrap );
-
-/* If successful, note that the virtual function table has been
- initialised. */
- if ( astOK ) {
- class_init = 1;
-
-/* Obtain the variable argument list and pass it along with the
- options string to the astVSet method to initialise the new
- StcsChan's attributes. */
- va_start( args, status );
- astVSet( new, options, NULL, args );
- va_end( args );
-
-/* If an error occurred, clean up by deleting the new object. */
- if ( !astOK ) new = astDelete( new );
- }
-
-/* Return a pointer to the new StcsChan. */
- return new;
-}
-
-AstStcsChan *astStcsChanId_( const char *(* source)( void ),
- void (* sink)( const char * ),
- const char *options, ... ) {
-/*
-* Name:
-* astStcsChanId_
-
-* Purpose:
-* Create an StcsChan.
-
-* Type:
-* Private function.
-
-* Synopsis:
-* #include "stcschan.h"
-* AstStcsChan *astStcsChanId_( const char *(* source)( void ),
-* void (* sink)( const char * ),
-* const char *options, ... )
-
-* Class Membership:
-* StcsChan constructor.
-
-* Description:
-* This function implements the external (public) C interface to the
-* astStcsChan constructor function. Another function (astStcsChanForId)
-* should be called to create an StcsChan for use within other languages.
-* Both functions return an ID value (instead of a true C pointer) to
-* external users, and must be provided because astStcsChan_ has a variable
-* argument list which cannot be encapsulated in a macro (where this conversion would otherwise
-* occur).
-*
-* The variable argument list also prevents this function from
-* invoking astStcsChan_ directly, so it must be a re-implementation
-* of it in all respects, except for the final conversion of the
-* result to an ID value.
-
-* Parameters:
-* As for astStcsChan_.
-
-* Returned Value:
-* The ID value associated with the new StcsChan.
-*/
-
-/* Local Variables: */
- astDECLARE_GLOBALS /* Pointer to thread-specific global data */
- AstStcsChan *new; /* Pointer to new StcsChan */
- va_list args; /* Variable argument list */
-
- int *status; /* Pointer to inherited status value */
-
-/* Get a pointer to the inherited status value. */
- status = astGetStatusPtr;
-
-/* Get a pointer to the thread specific global data structure. */
- astGET_GLOBALS(NULL);
-
-/* Check the global status. */
- if ( !astOK ) return NULL;
-
-/* Initialise the StcsChan, allocating memory and initialising the
- virtual function table as well if necessary. This interface is for
- use by external C functions and uses the standard "wrapper"
- functions included in this class. */
- new = astInitStcsChan( NULL, sizeof( AstStcsChan ), !class_init,
- &class_vtab, "StcsChan", source, SourceWrap,
- sink, SinkWrap );
-
-/* If successful, note that the virtual function table has been
- initialised. */
- if ( astOK ) {
- class_init = 1;
-
-/* Obtain the variable argument list and pass it along with the
- options string to the astVSet method to initialise the new
- StcsChan's attributes. */
- va_start( args, options );
- astVSet( new, options, NULL, args );
- va_end( args );
-
-/* If an error occurred, clean up by deleting the new object. */
- if ( !astOK ) new = astDelete( new );
- }
-
-/* Return an ID value for the new StcsChan. */
- return astMakeId( new );
-}
-
-AstStcsChan *astStcsChanForId_( const char *(* source)( void ),
- char *(* source_wrap)( const char *(*)( void ), int * ),
- void (* sink)( const char * ),
- void (* sink_wrap)( void (*)( const char * ),
- const char *, int * ),
- const char *options, ... ) {
-/*
-*+
-* Name:
-* astStcsChanFor
-
-* Purpose:
-* Initialise an StcsChan from a foreign language interface.
-
-* Type:
-* Public function.
-
-* Synopsis:
-* #include "stcschan.h"
-* AstStcsChan *astStcsChanFor( const char *(* source)( void ),
-* char *(* source_wrap)( const char *(*)
-* ( void ), int * ),
-* void (* sink)( const char * ),
-* void (* sink_wrap)( void (*)( const char * ),
-* const char *, int * ),
-* const char *options, ... )
-
-* Class Membership:
-* StcsChan constructor.
-
-* Description:
-* This function creates a new StcsChan from a foreign language
-* interface and optionally initialises its attributes.
-*
-* A StcsChan is a specialised form of Channel which supports STC-S
-* I/O operations. Writing an Object to an StcsChan (using
-c astWrite) will, if the Object is suitable, generate an
-f AST_WRITE) will, if the Object is suitable, generate an
-* STC-S description of that Object, and reading from an StcsChan will
-* create a new Object from its STC-S description.
-*
-* Normally, when you use an StcsChan, you should provide "source"
-c and "sink" functions which connect it to an external data store
-c by reading and writing the resulting text. These functions
-f and "sink" routines which connect it to an external data store
-f by reading and writing the resulting text. These routines
-* should perform any conversions needed between external character
-c encodings and the internal ASCII encoding. If no such functions
-f encodings and the internal ASCII encoding. If no such routines
-* are supplied, a Channel will read from standard input and write
-* to standard output.
-
-* Parameters:
-* source
-* Pointer to a "source" function which will be used to obtain
-* lines of input text. Generally, this will be obtained by
-* casting a pointer to a source function which is compatible
-* with the "source_wrap" wrapper function (below). The pointer
-* should later be cast back to its original type by the
-* "source_wrap" function before the function is invoked.
-*
-* If "source" is NULL, the StcsChan will read from standard
-* input instead.
-* source_wrap
-* Pointer to a function which can be used to invoke the
-* "source" function supplied (above). This wrapper function is
-* necessary in order to hide variations in the nature of the
-* source function, such as may arise when it is supplied by a
-* foreign (non-C) language interface.
-*
-* The single parameter of the "source_wrap" function is a
-* pointer to the "source" function, and it should cast this
-* function pointer (as necessary) and invoke the function with
-* appropriate arguments to obtain the next line of input
-* text. The "source_wrap" function should then return a pointer
-* to a dynamically allocated, null terminated string containing
-* the text that was read. The string will be freed (using
-* astFree) when no longer required and the "source_wrap"
-* function need not concern itself with this. A NULL pointer
-* should be returned if there is no more input to read.
-*
-* If "source_wrap" is NULL, the StcsChan will read from standard
-* input instead.
-* sink
-* Pointer to a "sink" function which will be used to deliver
-* lines of output text. Generally, this will be obtained by
-* casting a pointer to a sink function which is compatible with
-* the "sink_wrap" wrapper function (below). The pointer should
-* later be cast back to its original type by the "sink_wrap"
-* function before the function is invoked.
-*
-* If "sink" is NULL, the StcsChan will write to standard output
-* instead.
-* sink_wrap
-* Pointer to a function which can be used to invoke the "sink"
-* function supplied (above). This wrapper function is necessary
-* in order to hide variations in the nature of the sink
-* function, such as may arise when it is supplied by a foreign
-* (non-C) language interface.
-*
-* The first parameter of the "sink_wrap" function is a pointer
-* to the "sink" function, and the second parameter is a pointer
-* to a const, null-terminated character string containing the
-* text to be written. The "sink_wrap" function should cast the
-* "sink" function pointer (as necessary) and invoke the
-* function with appropriate arguments to deliver the line of
-* output text. The "sink_wrap" function then returns void.
-*
-* If "sink_wrap" is NULL, the Channel will write to standard
-* output instead.
-* options
-* Pointer to a null-terminated string containing an optional
-* comma-separated list of attribute assignments to be used for
-* initialising the new StcsChan. The syntax used is identical to
-* that for the astSet function and may include "printf" format
-* specifiers identified by "%" symbols in the normal way.
-* ...
-* If the "options" string contains "%" format specifiers, then
-* an optional list of additional arguments may follow it in
-* order to supply values to be substituted for these
-* specifiers. The rules for supplying these are identical to
-* those for the astSet function (and for the C "printf"
-* function).
-
-* Returned Value:
-* astStcsChanFor()
-* A pointer to the new StcsChan.
-
-* Notes:
-* - A null Object pointer (AST__NULL) will be returned if this
-* function is invoked with the global error status set, or if it
-* should fail for any reason.
-* - This function is only available through the public interface
-* to the StcsChan class (not the protected interface) and is
-* intended solely for use in implementing foreign language
-* interfaces to this class.
-*-
-
-* Implememtation Notes:
-* - This function behaves exactly like astStcsChanId_, in that it
-* returns ID values and not true C pointers, but it has two
-* additional arguments. These are pointers to the "wrapper
-* functions" which are needed to accommodate foreign language
-* interfaces.
-*/
-
-/* Local Variables: */
- astDECLARE_GLOBALS /* Pointer to thread-specific global data */
- AstStcsChan *new; /* Pointer to new StcsChan */
- va_list args; /* Variable argument list */
- int *status; /* Pointer to inherited status value */
-
-/* Get a pointer to the inherited status value. */
- status = astGetStatusPtr;
-
-/* Check the global status. */
- if ( !astOK ) return NULL;
-
-/* Get a pointer to the thread specific global data structure. */
- astGET_GLOBALS(NULL);
-
-/* Initialise the StcsChan, allocating memory and initialising the
- virtual function table as well if necessary. */
- new = astInitStcsChan( NULL, sizeof( AstStcsChan ), !class_init,
- &class_vtab, "StcsChan", source, source_wrap,
- sink, sink_wrap );
-
-/* If successful, note that the virtual function table has been
- initialised. */
- if ( astOK ) {
- class_init = 1;
-
-/* Obtain the variable argument list and pass it along with the
- options string to the astVSet method to initialise the new
- StcsChan's attributes. */
- va_start( args, options );
- astVSet( new, options, NULL, args );
- va_end( args );
-
-/* If an error occurred, clean up by deleting the new object. */
- if ( !astOK ) new = astDelete( new );
- }
-
-/* Return an ID value for the new StcsChan. */
- return astMakeId( new );
-}
-
-AstStcsChan *astInitStcsChan_( void *mem, size_t size, int init,
- AstStcsChanVtab *vtab, const char *name,
- const char *(* source)( void ),
- char *(* source_wrap)( const char *(*)( void ), int * ),
- void (* sink)( const char * ),
- void (* sink_wrap)( void (*)( const char * ),
- const char *, int * ), int *status ) {
-/*
-*+
-* Name:
-* astInitStcsChan
-
-* Purpose:
-* Initialise an StcsChan.
-
-* Type:
-* Protected function.
-
-* Synopsis:
-* #include "stcschan.h"
-* AstStcsChan *astInitStcsChan( void *mem, size_t size, int init,
-* AstStcsChanVtab *vtab, const char *name,
-* const char *(* source)( void ),
-* char *(* source_wrap)( const char *(*)( void ), int * ),
-* void (* sink)( const char * ),
-* void (* sink_wrap)( void (*)( const char * ),
-* const char *, int * ) )
-
-* Class Membership:
-* StcsChan initialiser.
-
-* Description:
-* This function is provided for use by class implementations to
-* initialise a new StcsChan object. It allocates memory (if
-* necessary) to accommodate the StcsChan plus any additional data
-* associated with the derived class. It then initialises a
-* StcsChan structure at the start of this memory. If the "init"
-* flag is set, it also initialises the contents of a virtual
-* function table for an StcsChan at the start of the memory passed
-* via the "vtab" parameter.
-
-* Parameters:
-* mem
-* A pointer to the memory in which the StcsChan is to be
-* initialised. This must be of sufficient size to accommodate
-* the StcsChan data (sizeof(StcsChan)) plus any data used by the
-* derived class. If a value of NULL is given, this function
-* will allocate the memory itself using the "size" parameter to
-* determine its size.
-* size
-* The amount of memory used by the StcsChan (plus derived class
-* data). This will be used to allocate memory if a value of
-* NULL is given for the "mem" parameter. This value is also
-* stored in the StcsChan structure, so a valid value must be
-* supplied even if not required for allocating memory.
-* init
-* A boolean flag indicating if the StcsChan's virtual function
-* table is to be initialised. If this value is non-zero, the
-* virtual function table will be initialised by this function.
-* vtab
-* Pointer to the start of the virtual function table to be
-* associated with the new StcsChan.
-* name
-* Pointer to a constant null-terminated character string which
-* contains the name of the class to which the new object
-* belongs (it is this pointer value that will subsequently be
-* returned by the astGetClass method).
-* source
-* Pointer to a "source" function which will be used to obtain
-* lines of text. Generally, this will be obtained by
-* casting a pointer to a source function which is compatible
-* with the "source_wrap" wrapper function (below). The pointer
-* should later be cast back to its original type by the
-* "source_wrap" function before the function is invoked.
-*
-* If "source" is NULL, the Channel will read from standard
-* input instead.
-* source_wrap
-* Pointer to a function which can be used to invoke the
-* "source" function supplied (above). This wrapper function is
-* necessary in order to hide variations in the nature of the
-* source function, such as may arise when it is supplied by a
-* foreign (non-C) language interface.
-*
-* The single parameter of the "source_wrap" function is a
-* pointer to the "source" function, and it should cast this
-* function pointer (as necessary) and invoke the function with
-* appropriate arguments to obtain the next line of input
-* text. The "source_wrap" function should then return a pointer
-* to a dynamically allocated, null terminated string containing
-* the text that was read. The string will be freed (using
-* astFree) when no longer required and the "source_wrap"
-* function need not concern itself with this. A NULL pointer
-* should be returned if there is no more input to read.
-*
-* If "source_wrap" is NULL, the Channel will read from standard
-* input instead.
-* sink
-* Pointer to a "sink" function which will be used to deliver
-* lines of text. Generally, this will be obtained by
-* casting a pointer to a sink function which is compatible with
-* the "sink_wrap" wrapper function (below). The pointer should
-* later be cast back to its original type by the "sink_wrap"
-* function before the function is invoked.
-*
-* If "sink" is NULL, the contents of the StcsChan will not be
-* written out before being deleted.
-* sink_wrap
-* Pointer to a function which can be used to invoke the "sink"
-* function supplied (above). This wrapper function is necessary
-* in order to hide variations in the nature of the sink
-* function, such as may arise when it is supplied by a foreign
-* (non-C) language interface.
-*
-* The first parameter of the "sink_wrap" function is a pointer
-* to the "sink" function, and the second parameter is a pointer
-* to a const, null-terminated character string containing the
-* text to be written. The "sink_wrap" function should cast the
-* "sink" function pointer (as necessary) and invoke the
-* function with appropriate arguments to deliver the line of
-* output text. The "sink_wrap" function then returns void.
-*
-* If "sink_wrap" is NULL, the Channel will write to standard
-* output instead.
-
-* Returned Value:
-* A pointer to the new StcsChan.
-
-* Notes:
-* - A null pointer will be returned if this function is invoked
-* with the global error status set, or if it should fail for any
-* reason.
-*-
-*/
-
-/* Local Variables: */
- AstStcsChan *new; /* Pointer to new StcsChan */
-
-/* Check the global status. */
- if ( !astOK ) return NULL;
-
-/* If necessary, initialise the virtual function table. */
- if ( init ) astInitStcsChanVtab( vtab, name );
-
-/* Initialise a Channel structure (the parent class) as the first
- component within the StcsChan structure, allocating memory if
- necessary. */
- new = (AstStcsChan *) astInitChannel( mem, size, 0,
- (AstChannelVtab *) vtab, name,
- source, source_wrap, sink,
- sink_wrap );
-
- if ( astOK ) {
-
-/* Initialise the StcsChan data. */
-/* ---------------------------- */
- new->stcsarea = -INT_MAX;
- new->stcscoords = -INT_MAX;
- new->stcsprops = -INT_MAX;
- new->stcslength = -INT_MAX;
-
-/* If an error occurred, clean up by deleting the new object. */
- if ( !astOK ) new = astDelete( new );
- }
-
-/* Return a pointer to the new object. */
- return new;
-}
-
-AstStcsChan *astLoadStcsChan_( void *mem, size_t size,
- AstStcsChanVtab *vtab, const char *name,
- AstChannel *channel, int *status ) {
-/*
-*+
-* Name:
-* astLoadStcsChan
-
-* Purpose:
-* Load an StcsChan.
-
-* Type:
-* Protected function.
-
-* Synopsis:
-* #include "stcschan.h"
-* AstStcsChan *astLoadStcsChan( void *mem, size_t size,
-* AstStcsChanVtab *vtab, const char *name,
-* AstChannel *channel )
-
-* Class Membership:
-* StcsChan loader.
-
-* Description:
-* This function is provided to load a new StcsChan using data read
-* from a Channel. It first loads the data used by the parent class
-* (which allocates memory if necessary) and then initialises a
-* StcsChan structure in this memory, using data read from the input
-* Channel.
-*
-* If the "init" flag is set, it also initialises the contents of a
-* virtual function table for an StcsChan at the start of the memory
-* passed via the "vtab" parameter.
-
-* Parameters:
-* mem
-* A pointer to the memory into which the StcsChan is to be
-* loaded. This must be of sufficient size to accommodate the
-* StcsChan data (sizeof(StcsChan)) plus any data used by derived
-* classes. If a value of NULL is given, this function will
-* allocate the memory itself using the "size" parameter to
-* determine its size.
-* size
-* The amount of memory used by the StcsChan (plus derived class
-* data). This will be used to allocate memory if a value of
-* NULL is given for the "mem" parameter. This value is also
-* stored in the StcsChan structure, so a valid value must be
-* supplied even if not required for allocating memory.
-*
-* If the "vtab" parameter is NULL, the "size" value is ignored
-* and sizeof(AstStcsChan) is used instead.
-* vtab
-* Pointer to the start of the virtual function table to be
-* associated with the new StcsChan. If this is NULL, a pointer
-* to the (static) virtual function table for the StcsChan class
-* is used instead.
-* name
-* Pointer to a constant null-terminated character string which
-* contains the name of the class to which the new object
-* belongs (it is this pointer value that will subsequently be
-* returned by the astGetClass method).
-*
-* If the "vtab" parameter is NULL, the "name" value is ignored
-* and a pointer to the string "StcsChan" is used instead.
-
-* Returned Value:
-* A pointer to the new StcsChan.
-
-* Notes:
-* - A null pointer will be returned if this function is invoked
-* with the global error status set, or if it should fail for any
-* reason.
-*-
-*/
-
-/* Local Variables: */
- astDECLARE_GLOBALS /* Pointer to thread-specific global data */
- AstStcsChan *new; /* Pointer to the new StcsChan */
-
-/* Initialise. */
- new = NULL;
-
-/* Check the global error status. */
- if( !astOK ) return new;
-
-/* Get a pointer to the thread specific global data structure. */
- astGET_GLOBALS(channel);
-
-/* If a NULL virtual function table has been supplied, then this is
- the first loader to be invoked for this StcsChan. In this case the
- StcsChan belongs to this class, so supply appropriate values to be
- passed to the parent class loader (and its parent, etc.). */
- if ( !vtab ) {
- size = sizeof( AstStcsChan );
- vtab = &class_vtab;
- name = "StcsChan";
-
-/* If required, initialise the virtual function table for this class. */
- if ( !class_init ) {
- astInitStcsChanVtab( vtab, name );
- class_init = 1;
- }
- }
-
-/* Invoke the parent class loader to load data for all the ancestral
- classes of the current one, returning a pointer to the resulting
- partly-built StcsChan. */
- new = astLoadChannel( mem, size, (AstChannelVtab *) vtab, name,
- channel );
-
- if ( astOK ) {
-
-/* Read input data. */
-/* ================ */
-/* Request the input Channel to read all the input data appropriate to
- this class into the internal "values list". */
- astReadClassData( channel, "StcsChan" );
-
-/* Now read each individual data item from this list and use it to
- initialise the appropriate instance variable(s) for this class. */
-
-/* In the case of attributes, we first read the "raw" input value,
- supplying the "unset" value as the default. If a "set" value is
- obtained, we then use the appropriate (private) Set... member
- function to validate and set the value properly. */
-
-/* StcsArea. */
-/* --------- */
- new->stcsarea = astReadInt( channel, "stcsarea", -INT_MAX );
- if ( TestStcsArea( new, status ) ) SetStcsArea( new, new->stcsarea, status );
-
-/* StcsCoords. */
-/* ----------- */
- new->stcscoords = astReadInt( channel, "stcscoords", -INT_MAX );
- if ( TestStcsCoords( new, status ) ) SetStcsCoords( new, new->stcscoords, status );
-
-/* StcsProps. */
-/* ---------- */
- new->stcsprops = astReadInt( channel, "stcsprops", -INT_MAX );
- if ( TestStcsProps( new, status ) ) SetStcsProps( new, new->stcsprops, status );
-
-/* StcsLength */
-/* ---------- */
- new->stcslength = astReadInt( channel, "stcslen", -INT_MAX );
-
- }
-
-/* If an error occurred, clean up by deleting the new StcsChan. */
- if ( !astOK ) new = astDelete( new );
-
-/* Return the new StcsChan pointer. */
- return new;
-}
-
-/* Virtual function interfaces. */
-/* ============================ */
-/* These provide the external interface to the virtual functions defined by
- this class. Each simply checks the global error status and then locates and
- executes the appropriate member function, using the function pointer stored
- in the object's virtual function table (this pointer is located using the
- astMEMBER macro defined in "object.h").
-
- Note that the member function may not be the one defined here, as it may
- have been over-ridden by a derived class. However, it should still have the
- same interface. */
-
-
-
-
-
-
-
-