summaryrefslogtreecommitdiffstats
path: root/ast/prism.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2019-05-10 18:45:23 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2019-05-10 18:45:23 (GMT)
commit0b1addf5643c828955a6add53f2a4f7a7a813e41 (patch)
tree94fe32a76399be787746c3c403cca2076a253e29 /ast/prism.c
parent75fab9d80911f74aaab738fa9ab8a4f9b0f57a6b (diff)
downloadblt-0b1addf5643c828955a6add53f2a4f7a7a813e41.zip
blt-0b1addf5643c828955a6add53f2a4f7a7a813e41.tar.gz
blt-0b1addf5643c828955a6add53f2a4f7a7a813e41.tar.bz2
upgrade ast 8.7.1
Diffstat (limited to 'ast/prism.c')
-rw-r--r--ast/prism.c4448
1 files changed, 4448 insertions, 0 deletions
diff --git a/ast/prism.c b/ast/prism.c
new file mode 100644
index 0000000..38281f3
--- /dev/null
+++ b/ast/prism.c
@@ -0,0 +1,4448 @@
+/*
+*class++
+* Name:
+* Prism
+
+* Purpose:
+* An extrusion of a region into higher dimensions.
+
+* Constructor Function:
+c astPrism
+f AST_PRISM
+
+* Description:
+* A Prism is a Region which represents an extrusion of an existing Region
+* into one or more orthogonal dimensions (specified by another Region).
+* If the Region to be extruded has N axes, and the Region defining the
+* extrusion has M axes, then the resulting Prism will have (M+N) axes.
+* A point is inside the Prism if the first N axis values correspond to
+* a point inside the Region being extruded, and the remaining M axis
+* values correspond to a point inside the Region defining the extrusion.
+*
+* As an example, a cylinder can be represented by extruding an existing
+* Circle, using an Interval to define the extrusion. Ih this case, the
+* Interval would have a single axis and would specify the upper and
+* lower limits of the cylinder along its length.
+
+* Inheritance:
+* The Prism class inherits from the Region class.
+
+* Attributes:
+* The Prism class does not define any new attributes beyond those
+* which are applicable to all Regions.
+
+* Functions:
+c The Prism class does not define any new functions beyond those
+f The Prism class does not define any new routines beyond those
+* which are applicable to all Regions.
+
+* Copyright:
+* Copyright (C) 1997-2006 Council for the Central Laboratory of the
+* Research Councils
+* 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 S. Berry (Starlink)
+
+* History:
+* 17-DEC-2004 (DSB):
+* Original version.
+* 11-MAY-2005 (DSB):
+* Overlap modified to allow testing of overlap between prisms and
+* intervals.
+* 14-FEB-2006 (DSB):
+* Override astGetObjSize.
+* 9-OCT-2007 (DSB):
+* Guard against all axes being extrusion axes in EquivPrism.
+* 20-JAN-2009 (DSB):
+* Over-ride astRegBasePick.
+* 22-JAN-2009 (DSB):
+* - Allow any class of Region to be used to define the extrusion axes.
+* - Over-ride the astMapList method.
+* 19-MAR-2009 (DSB):
+* Over-ride the astDecompose method.
+* 14-AUG-2014 (DSB):
+* Over-ride the astGetRegionBounds method.
+* 9-SEP-2014 (DSB):
+* Record the pointer to the Prism implementation of RegBaseMesh
+* within the class virtual function table.
+*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 Prism
+
+/* Include files. */
+/* ============== */
+/* Interface definitions. */
+/* ---------------------- */
+
+#include "globals.h" /* Thread-safe global data access */
+#include "error.h" /* Error reporting facilities */
+#include "memory.h" /* Memory allocation facilities */
+#include "object.h" /* Base Object class */
+#include "pointset.h" /* Sets of points/coordinates */
+#include "region.h" /* Regions (parent class) */
+#include "channel.h" /* I/O channels */
+#include "prism.h" /* Interface definition for this class */
+#include "cmpmap.h" /* Compound Mappings */
+#include "cmpframe.h" /* Compound Frames */
+#include "unitmap.h" /* Unit Mappings */
+#include "interval.h" /* Axis intervals */
+#include "pointlist.h" /* Points within Frames */
+#include "permmap.h" /* Axis permutations */
+
+/* Error code definitions. */
+/* ----------------------- */
+#include "ast_err.h" /* AST error codes */
+
+/* C header files. */
+/* --------------- */
+#include <stdarg.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <limits.h>
+
+/* Module Variables. */
+/* ================= */
+
+/* Address of this static variable is used as a unique identifier for
+ member of this class. */
+static int class_check;
+
+/* Pointers to parent class methods which are extended by this class. */
+static AstMapping *(* parent_simplify)( AstMapping *, int * );
+static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
+static AstRegion *(* parent_getdefunc)( AstRegion *, int * );
+static double (*parent_getfillfactor)( AstRegion *, int * );
+static int (* parent_equal)( AstObject *, AstObject *, int * );
+static int (* parent_getobjsize)( AstObject *, int * );
+static int (* parent_maplist)( AstMapping *, int, int, int *, AstMapping ***, int **, int * );
+static int (* parent_overlapx)( AstRegion *, AstRegion *, int * );
+static void (* parent_clearclosed)( AstRegion *, int * );
+static void (* parent_clearmeshsize)( AstRegion *, int * );
+static void (* parent_setclosed)( AstRegion *, int, int * );
+static void (* parent_setmeshsize)( AstRegion *, int, int * );
+static void (* parent_setregfs)( AstRegion *, AstFrame *, int * );
+static void (*parent_getregionbounds)( AstRegion *, double *, double *, int * );
+static void (*parent_regclearattrib)( AstRegion *, const char *, char **, int * );
+static void (*parent_regsetattrib)( AstRegion *, const char *, char **, int * );
+
+#if defined(THREAD_SAFE)
+static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * );
+#endif
+
+
+#ifdef THREAD_SAFE
+/* Define how to initialise thread-specific globals. */
+#define GLOBAL_inits \
+ globals->Class_Init = 0;
+
+/* Create the function that initialises global data for this module. */
+astMAKE_INITGLOBALS(Prism)
+
+/* Define macros for accessing each item of thread specific global data. */
+#define class_init astGLOBAL(Prism,Class_Init)
+#define class_vtab astGLOBAL(Prism,Class_Vtab)
+
+
+#include <pthread.h>
+
+
+#else
+
+
+/* Define the class virtual function table and its initialisation flag
+ as static variables. */
+static AstPrismVtab class_vtab; /* Virtual function table */
+static int class_init = 0; /* Virtual function table initialised? */
+
+#endif
+
+/* External Interface Function Prototypes. */
+/* ======================================= */
+/* The following functions have public prototypes only (i.e. no
+ protected prototypes), so we must provide local prototypes for use
+ within this module. */
+AstPrism *astPrismId_( void *, void *, const char *, ... );
+
+/* Prototypes for Private Member Functions. */
+/* ======================================== */
+static AstMapping *Simplify( AstMapping *, int * );
+static AstPointSet *RegBaseMesh( AstRegion *, int * );
+static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
+static AstRegion *GetDefUnc( AstRegion *, int * );
+static AstRegion *RegBasePick( AstRegion *this, int, const int *, int * );
+static double *RegCentre( AstRegion *this, double *, double **, int, int, int * );
+static double GetFillFactor( AstRegion *, int * );
+static int Equal( AstObject *, AstObject *, int * );
+static int GetBounded( AstRegion *, int * );
+static int GetObjSize( AstObject *, int * );
+static int MapList( AstMapping *, int, int, int *, AstMapping ***, int **, int * );
+static int Overlap( AstRegion *, AstRegion *, int * );
+static int OverlapX( AstRegion *, AstRegion *, int * );
+static int RegPins( AstRegion *, AstPointSet *, AstRegion *, int **, int * );
+static void ClearClosed( AstRegion *, int * );
+static void ClearMeshSize( AstRegion *, int * );
+static void Copy( const AstObject *, AstObject *, int * );
+static void Decompose( AstMapping *, AstMapping **, AstMapping **, int *, int *, int *, int * );
+static void Delete( AstObject *, int * );
+static void Dump( AstObject *, AstChannel *, int * );
+static void GetRegions( AstPrism *, AstRegion **, AstRegion **, int *, int * );
+static void GetRegionBounds( AstRegion *, double *, double *, int * );
+static void RegBaseBox( AstRegion *, double *, double *, int * );
+static void RegClearAttrib( AstRegion *, const char *, char **, int * );
+static void RegSetAttrib( AstRegion *, const char *, char **, int * );
+static void SetClosed( AstRegion *, int, int * );
+static void SetMeshSize( AstRegion *, int, int * );
+static void SetRegFS( AstRegion *, AstFrame *, int * );
+
+#if defined(THREAD_SAFE)
+static int ManageLock( AstObject *, int, int, AstObject **, int * );
+#endif
+
+
+/* Member functions. */
+/* ================= */
+AstRegion *astConvertToPrism_( AstRegion *this, int *status ) {
+/*
+*+
+* Name:
+* astConvertToPrism
+
+* Purpose:
+* Convert a supplied Region into a Prism if possible.
+
+* Type:
+* Protected function.
+
+* Synopsis:
+* #include "prism.h"
+* AstRegion *astConvertToPrism( AstRegion *this, int *status )
+
+* Description:
+* This function attempts to split the supplied Region into two
+* regions defined within separate coordinate system. If this is
+* possible, and if either one of the two resulting Regions can be
+* simplified, then the two simplified Regions are joined into a Prism
+* equivalent to the supplied Region. The Prism is then simplified and
+* returned.
+*
+* If the supplied Region cannot be split into two components, or if
+* neither of the two components can eb simplified, then a clone of the
+* supplied Region pointer is returned.
+
+* Parameters:
+* this
+* Pointer to the original Region.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* A pointer to the equivalent simplified Prism, or a clone of the
+* supplied Region pointer.
+
+* Notes:
+* - A NULL pointer value will be returned if this function is
+* invoked with the AST error status set, or if it should fail for
+* any reason.
+*-
+*/
+
+/* Local Variables: */
+ AstFrame *frm; /* Current Frame in supplied Region */
+ AstFrame *pickfrm1; /* Frame formed by picking current subset of axes */
+ AstFrame *pickfrm2; /* Frame formed by picking all other axes */
+ AstMapping *junk; /* Unused Mapping pointer */
+ AstMapping *map; /* Base -> current Mapping */
+ AstPrism *prism; /* Prism combining all axes */
+ AstPrism *newprism; /* Prism combining all axes, in original Frame */
+ AstRegion *result; /* Result pointer to return */
+ AstRegion *sp1; /* Simplified region spanning selected axes */
+ AstRegion *sp2; /* Simplified region spanning unselected axes */
+ AstUnitMap *um; /* A UnitMap */
+ int *ax; /* Pointer to array of selecte axis indices */
+ int *perm; /* Axis permutation array */
+ int axis; /* Axis index */
+ int bitmask; /* Integer with set bits for selected axes */
+ int i; /* Loop index */
+ int mask; /* Integer with a set bit at current axis */
+ int nax; /* Number of selected axes */
+ int nin; /* No. of base Frame axes (Mapping inputs) */
+ int nout; /* No. of current Frame axes (Mapping outputs) */
+ int topmask; /* Integer that selects all axes */
+
+/* Initialise. */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Get the Mapping from base to current Frame. */
+ map = astGetMapping( this->frameset, AST__BASE, AST__CURRENT );
+
+/* Get the number of inputs and outputs for the Mapping. */
+ nin = astGetNin( map );
+ nout = astGetNout( map );
+
+/* Allocate memory to hold the indices of the current Frame axes in the
+ current subset */
+ ax = astMalloc( sizeof( int )* nout );
+ if( ax ) {
+
+/* We need to scan through all possible subsets of the current Frame
+ axes, looking for a subset that results in the Region being split.
+ We use the binary pattern of bits in "bitmask" to indicate if the
+ corresponding axes should be included in the subset of axes.
+ Loop round all possible combinations, until a combination is found
+ that results in a Prism being formed. */
+ topmask = pow( 2, nout );
+ for( bitmask = 1; bitmask < topmask && !result; bitmask++ ) {
+
+/* Store the indices of the axes forming the current subset. */
+ nax = 0;
+ mask = 1;
+ for( axis = 0; axis < nout; axis++ ) {
+ if( bitmask & mask ) ax[ nax++ ] = axis;
+ mask <<= 1;
+ }
+
+/* See if the current subset of current Frame axes can be split off from
+ the Region. If it can, the Frame pointer returned by astPickAxes will identify
+ a Region. */
+ pickfrm1 = astPickAxes( this, nax, ax, &junk );
+ junk = astAnnul( junk );
+ if( astIsARegion( pickfrm1 ) ) {
+
+/* Check that the remaining (unselected) axes can also be picked into a
+ new Region. */
+ nax = 0;
+ mask = 1;
+ for( axis = 0; axis < nout; axis++ ) {
+ if( ( bitmask & mask ) == 0 ) ax[ nax++ ] = axis;
+ mask <<= 1;
+ }
+
+ pickfrm2 = astPickAxes( this, nax, ax, &junk );
+ junk = astAnnul( junk );
+ if( astIsARegion( pickfrm2 ) ) {
+
+/* See if either of these picked Regions can be simplified. */
+ sp1 = astSimplify( pickfrm1 );
+ sp2 = astSimplify( pickfrm2 );
+ if( (AstFrame *) sp1 != pickfrm1 ||
+ (AstFrame *) sp2 != pickfrm2 ) {
+
+/* If so form a Prism containing the simplified Regions. */
+ prism = astPrism( sp1, sp2, " ", status );
+
+/* Permute the axes of the Prism so that they are in the same order as
+ in the Box. */
+ perm = astMalloc( sizeof( int )*nout );
+ if( perm ) {
+
+ for( i = 0; i < nout; i++ ) perm[ i ] = -1;
+
+ for( i = 0; i < nax; i++ ) {
+ perm[ ax[ i ] ] = i + ( nout - nax );
+ }
+
+ nax = 0;
+ for( i = 0; i < nout; i++ ) {
+ if( perm[ i ] == -1 ) perm[ i ] = nax++;
+ }
+
+ astPermAxes( prism, perm );
+ perm = astFree( perm );
+ }
+
+/* Put the original current Frame back in (in place of the CmpFrame
+ containined in the Prism). */
+ frm = astGetFrame( this->frameset, AST__CURRENT );
+ um = astUnitMap( nout, " ", status );
+ newprism = astMapRegion( prism, um, frm );
+ um = astAnnul( um );
+ frm = astAnnul( frm );
+
+/* Attempt to simplify the Prism. */
+ result = astSimplify( newprism );
+
+/* Free resources */
+ prism = astAnnul( prism );
+ newprism = astAnnul( newprism );
+ }
+
+ sp1 = astAnnul( sp1 );
+ sp2 = astAnnul( sp2 );
+ }
+ pickfrm2 = astAnnul( pickfrm2 );
+ }
+
+ pickfrm1 = astAnnul( pickfrm1 );
+ }
+
+ ax = astFree( ax );
+ }
+
+ map = astAnnul( map );
+
+/* If no Prism could be made, return a clone of the supplied Region
+ pointer. */
+ if( !result ) result = astClone( this );
+
+/* If an error occurred, annul the returned pointer. */
+ if ( !astOK ) result = astAnnul( result );
+
+/* Return the result. */
+ return result;
+}
+
+static void Decompose( AstMapping *this_mapping, AstMapping **map1,
+ AstMapping **map2, int *series, int *invert1,
+ int *invert2, int *status ) {
+/*
+*
+* Name:
+* Decompose
+
+* Purpose:
+* Decompose a Prism into two component Regions.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "cmpregion.h"
+* void Decompose( AstMapping *this, AstMapping **map1,
+* AstMapping **map2, int *series,
+* int *invert1, int *invert2, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the protected astDecompose
+* method inherited from the Mapping class).
+
+* Description:
+* This function returns pointers to two Mappings which, when applied
+* either in series or parallel, are equivalent to the supplied Mapping.
+*
+* Since the Frame class inherits from the Mapping class, Frames can
+* be considered as special types of Mappings and so this method can
+* be used to decompose either CmpMaps, CmpFrames, CmpRegions or Prisms.
+
+* Parameters:
+* this
+* Pointer to the Mapping.
+* map1
+* Address of a location to receive a pointer to first component
+* Mapping.
+* map2
+* Address of a location to receive a pointer to second component
+* Mapping.
+* series
+* Address of a location to receive a value indicating if the
+* component Mappings are applied in series or parallel. A non-zero
+* value means that the supplied Mapping is equivalent to applying map1
+* followed by map2 in series. A zero value means that the supplied
+* Mapping is equivalent to applying map1 to the lower numbered axes
+* and map2 to the higher numbered axes, in parallel.
+* invert1
+* The value of the Invert attribute to be used with map1.
+* invert2
+* The value of the Invert attribute to be used with map2.
+* status
+* Pointer to the inherited status variable.
+
+* Notes:
+* - Any changes made to the component rames using the returned
+* pointers will be reflected in the supplied CmpFrame.
+
+*-
+*/
+
+/* Local Variables: */
+ AstPrism *this; /* Pointer to Prism structure */
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Obtain a pointer to the CmpMap structure. */
+ this = (AstPrism *) this_mapping;
+
+/* The components Frames of a Prism are considered to be parallel
+ Mappings. */
+ if( series ) *series = 0;
+
+/* The Frames are returned in their original order whether or not the
+ Prism has been inverted. */
+ if( map1 ) *map1 = astClone( this->region1 );
+ if( map2 ) *map2 = astClone( this->region2 );
+
+/* The invert flags dont mean anything for a Region, but we return them
+ anyway. If the Prism has been inverted, return inverted Invert flags. */
+ if( astGetInvert( this ) ) {
+ if( invert1 ) *invert1 = astGetInvert( this->region1 ) ? 0 : 1;
+ if( invert2 ) *invert2 = astGetInvert( this->region2 ) ? 0 : 1;
+
+/* If the Prism has not been inverted, return the current Invert flags. */
+ } else {
+ if( invert1 ) *invert1 = astGetInvert( this->region1 );
+ if( invert2 ) *invert2 = astGetInvert( this->region2 );
+ }
+}
+
+static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
+/*
+* Name:
+* Equal
+
+* Purpose:
+* Test if two Objects are equivalent.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* int Equal( AstObject *this_object, AstObject *that_object, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astEqual protected
+* method inherited from the Region class).
+
+* Description:
+* This function returns a boolean result (0 or 1) to indicate whether
+* two Prisms are equivalent.
+
+* Parameters:
+* this
+* Pointer to the first Prism.
+* that
+* Pointer to the second Prism.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* One if the Prisms are equivalent, zero otherwise.
+
+* Notes:
+* - The Prisms are equivalent if their component Regions are
+* equivalent and if they have the same boolean operation, negation
+* and closed flags.
+* - A value of zero will be returned if this function is invoked
+* with the global status set, or if it should fail for any reason.
+*/
+
+/* Local Variables: */
+ AstPrism *that;
+ AstPrism *this;
+ int result;
+
+/* Initialise. */
+ result = 0;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Invoke the Equal method inherited from the parent Region class. This checks
+ that the Objects are both of the same class, and have the same Negated
+ and Closed flags (amongst other things). */
+ if( (*parent_equal)( this_object, that_object, status ) ) {
+
+/* Obtain pointers to the two Prism structures. */
+ this = (AstPrism *) this_object;
+ that = (AstPrism *) that_object;
+
+/* Test their first component Regions for equality. */
+ if( astEqual( this->region1, that->region1 ) ) {
+
+/* Test their second component Regions for equality. */
+ if( astEqual( this->region2, that->region2 ) ) result = 1;
+ }
+ }
+
+/* If an error occurred, clear the result value. */
+ if ( !astOK ) result = 0;
+
+/* Return the result, */
+ return result;
+}
+
+/*
+* Name:
+* MAKE_SET
+
+* Purpose:
+* Define a function to set an attribute value for a Prism.
+
+* Type:
+* Private macro.
+
+* Synopsis:
+* #include "prism.h"
+* MAKE_SET(attribute,lattribute,type)
+
+* Class Membership:
+* Defined by the Prism class.
+
+* Description:
+* This macro expands to an implementation of a private member function
+* of the form:
+*
+* static void Set<Attribute>( AstRegion *this, <Type> value )
+*
+* that sets the value of a specified Region attribute in the parent
+* Region structure and also in the component Regions.
+
+* Parameters:
+* attribute
+* Name of the attribute, as it appears in the function name.
+* lattribute
+* Name of the attribute, all in lower case.
+* type
+* The C type of the attribute.
+*/
+
+/* Define the macro. */
+#define MAKE_SET(attribute,lattribute,type) \
+static void Set##attribute( AstRegion *this_region, type value, int *status ) { \
+\
+/* Local Variables: */ \
+ AstPrism *this; /* Pointer to the Prism structure */ \
+\
+/* Check the global error status. */ \
+ if ( !astOK ) return; \
+\
+/* Use the parent method to set the value in the parent Region structure. */ \
+ (*parent_set##lattribute)( this_region, value, status ); \
+\
+/* Also set the value in the two component Regions. */ \
+ this = (AstPrism *) this_region; \
+ astSet##attribute( this->region1, value ); \
+ astSet##attribute( this->region2, value ); \
+}
+
+/* Use the above macro to create accessors for the MeshSize and Closed
+ attributes. */
+MAKE_SET(MeshSize,meshsize,int)
+MAKE_SET(Closed,closed,int)
+
+/* Undefine the macro. */
+#undef MAKE_SET
+
+/*
+* Name:
+* MAKE_CLEAR
+
+* Purpose:
+* Define a function to clear an attribute value for a Prism.
+
+* Type:
+* Private macro.
+
+* Synopsis:
+* #include "prism.h"
+* MAKE_CLEAR(attribute,lattribute)
+
+* Class Membership:
+* Defined by the Prism class.
+
+* Description:
+* This macro expands to an implementation of a private member function
+* of the form:
+*
+* static void Clear<Attribute>( AstRegion *this )
+*
+* that sets the value of a specified Region attribute in the parent
+* Region structure and also in the component Regions.
+
+* Parameters:
+* attribute
+* Name of the attribute, as it appears in the function name.
+* lattribute
+* Name of the attribute, all in lower case.
+*/
+
+/* Define the macro. */
+#define MAKE_CLEAR(attribute,lattribute) \
+static void Clear##attribute( AstRegion *this_region, int *status ) { \
+\
+/* Local Variables: */ \
+ AstPrism *this; /* Pointer to the Prism structure */ \
+\
+/* Check the global error status. */ \
+ if ( !astOK ) return; \
+\
+/* Use the parent method to clear the value in the parent Region structure. */ \
+ (*parent_clear##lattribute)( this_region, status ); \
+\
+/* Also clear the value in the two component Regions. */ \
+ this = (AstPrism *) this_region; \
+ astClear##attribute( this->region1 ); \
+ astClear##attribute( this->region2 ); \
+}
+
+/* Use the above macro to create accessors for the MeshSize and Closed
+ attributes. */
+MAKE_CLEAR(MeshSize,meshsize)
+MAKE_CLEAR(Closed,closed)
+
+/* Undefine the macro. */
+#undef MAKE_CLEAR
+
+static int GetObjSize( AstObject *this_object, int *status ) {
+/*
+* Name:
+* GetObjSize
+
+* Purpose:
+* Return the in-memory size of an Object.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* int GetObjSize( AstObject *this, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astGetObjSize protected
+* method inherited from the parent class).
+
+* Description:
+* This function returns the in-memory size of the supplied Prism,
+* in bytes.
+
+* Parameters:
+* this
+* Pointer to the Prism.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* The Object size, in bytes.
+
+* Notes:
+* - A value of zero will be returned if this function is invoked
+* with the global status set, or if it should fail for any reason.
+*/
+
+/* Local Variables: */
+ AstPrism *this; /* Pointer to Prism structure */
+ int result; /* Result value to return */
+
+/* Initialise. */
+ result = 0;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Obtain a pointers to the Prism structure. */
+ this = (AstPrism *) this_object;
+
+/* Invoke the GetObjSize method inherited from the parent class, and then
+ add on any components of the class structure defined by thsi class
+ which are stored in dynamically allocated memory. */
+ result = (*parent_getobjsize)( this_object, status );
+ result += astGetObjSize( this->region1 );
+ result += astGetObjSize( this->region2 );
+
+/* If an error occurred, clear the result value. */
+ if ( !astOK ) result = 0;
+
+/* Return the result, */
+ return result;
+}
+
+static int GetBounded( AstRegion *this_region, int *status ) {
+/*
+* Name:
+* GetBounded
+
+* Purpose:
+* Is the Region bounded?
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* int GetBounded( AstRegion *this, int *status )
+
+* Class Membership:
+* Prism method (over-rides the astGetBounded method inherited from
+* the Region class).
+
+* Description:
+* This function returns a flag indicating if the Region is bounded.
+* The implementation provided by the base Region class is suitable
+* for Region sub-classes representing the inside of a single closed
+* curve (e.g. Circle, Ellipse, Box, etc). Other sub-classes (such as
+* Prism, PointList, etc ) may need to provide their own
+* implementations.
+
+* Parameters:
+* this
+* Pointer to the Region.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Non-zero if the Region is bounded. Zero otherwise.
+
+*/
+
+/* Local Variables: */
+ AstPrism *this; /* Pointer to Prism structure */
+ AstRegion *reg1; /* Pointer to first component Region */
+ AstRegion *reg2; /* Pointer to second component Region */
+ int neg; /* Negated flag to use with the Prism */
+ int reg1b; /* Is the first component Region bounded?*/
+ int reg2b; /* Is the second component Region bounded?*/
+ int result; /* Returned result */
+
+/* Initialise */
+ result = 0;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Get a pointer to the Prism structure. */
+ this = (AstPrism *) this_region;
+
+/* Get the component Regions, and the Negated value for the Prism. The
+ returned Regions represent a region within the base Frame of the FrameSet
+ encapsulated by the parent Region structure. */
+ GetRegions( this, &reg1, &reg2, &neg, status );
+
+/* If the Prism has been inverted, temporarily invert the components. */
+ if( neg ) {
+ astNegate( reg1 );
+ astNegate( reg2 );
+ }
+
+/* See if either of the component Regions is bounded. */
+ reg1b = astGetBounded( reg1 );
+ reg2b = astGetBounded( reg2 );
+
+/* If the Prism has been inverted, re-invert the components to bring them
+ back to their original states. */
+ if( neg ) {
+ astNegate( reg1 );
+ astNegate( reg2 );
+ }
+
+/* The Prism is bounded only if both of the component Regions are bounded. */
+ result = ( reg1b && reg2b );
+
+/* Free resources. */
+ reg1 = astAnnul( reg1 );
+ reg2 = astAnnul( reg2 );
+
+/* Return zero if an error occurred. */
+ if( !astOK ) result = 0;
+
+/* Return the required pointer. */
+ return result;
+}
+
+static double GetFillFactor( AstRegion *this_region, int *status ) {
+/*
+* Name:
+* GetFillFactor
+
+* Purpose:
+* Obtain the value of the FillFactor attribute for a Prism.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* double GetFillFactor( AstRegion *this, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astGetFillFactor method inherited
+* from the Region class).
+
+* Description:
+* This function returns the value of the FillFactor attribute for a
+* Prism. A suitable default value is returned if no value has
+* previously been set.
+
+* Parameters:
+* this
+* Pointer to the Prism.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* The FillFactor value to use.
+
+*/
+
+/* Local Variables: */
+ AstPrism *this;
+ double f1;
+ double f2;
+ double result;
+
+/* Check the global error status. */
+ if ( !astOK ) return AST__BAD;
+
+/* Initialise. */
+ result = AST__BAD;
+
+/* Obtain a pointer to the Prism structure. */
+ this = (AstPrism *) this_region;
+
+/* See if a FillFactor value has been set. If so, use the parent
+ astGetFillFactor method to obtain it. */
+ if ( astTestFillFactor( this ) ) {
+ result = (*parent_getfillfactor)( this_region, status );
+
+/* Otherwise, we will generate a default value equal to the product of
+ the FillFactor values of the two component Regions. */
+ } else {
+ f1 = astGetFillFactor( this->region1 );
+ f2 = astGetFillFactor( this->region2 );
+ if( f1 != AST__BAD && f2 != AST__BAD ) result = f1*f2;
+ }
+
+/* If an error occurred, clear the returned value. */
+ if ( !astOK ) result = AST__BAD;
+
+/* Return the result. */
+ return result;
+}
+
+static void GetRegionBounds( AstRegion *this_region, double *lbnd,
+ double *ubnd, int *status ){
+/*
+*
+* Name:
+* GetRegionBounds
+
+* Purpose:
+* Returns the bounding box of Prism.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "cmpregion.h"
+* void GetRegionBounds( AstRegion *this_region, double *lbnd,
+* double *ubnd, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the protected astGetRegionBounds
+* method inherited from the Region class).
+
+* Description:
+* This function returns the upper and lower limits of a box which just
+* encompasses the supplied Prism. The limits are returned as axis
+* values within the Frame represented by the Prism. The value of the
+* Negated attribute is ignored (i.e. it is assumed that the Prism has
+* not been negated).
+
+* Parameters:
+* this
+* Pointer to the Prism.
+* lbnd
+* Pointer to an array in which to return the lower axis bounds
+* covered by the Prism. It should have at least as many elements as
+* there are axes in the Prism. If an axis has no lower limit, the
+* returned value will be the largest possible negative value.
+* ubnd
+* Pointer to an array in which to return the upper axis bounds
+* covered by the Prism. It should have at least as many elements as
+* there are axes in the Prism. If an axis has no upper limit, the
+* returned value will be the largest possible positive value.
+
+* Notes:
+* - The value of the Negated attribute is ignored (i.e. it is assumed that
+* the Prism has not been negated).
+* - If an axis has no extent on an axis then the lower limit will be
+* returned larger than the upper limit. Note, this is different to an
+* axis which has a constant value (in which case both lower and upper
+* limit will be returned set to the constant value).
+* - If the bounds on an axis cannot be determined, AST__BAD is returned for
+* both upper and lower bounds
+* - The implementation of this method for Prisms attempts to split the Prism
+* into two separate Regions spanning indepenent sets of axes, and then uses
+* the astGetRegionBouinds method to get the bounds on these two Regions. Care
+* has to be taken because the Prism may have been remapped into a different
+* Frame since it was created.
+
+*-
+*/
+
+/* Local Variables: */
+ AstFrame *cfrm1; /* Frame spanning current axes for 1st component Region */
+ AstFrame *cfrm2; /* Frame spanning current axes for 2nd component Region */
+ AstFrame *cfrm; /* Current Frame for total Prism */
+ AstMapping *map1; /* Base->Current Mapping for axes of 1st component Region */
+ AstMapping *map2; /* Base->Current Mapping for axes of 2nd component Region */
+ AstMapping *map; /* Case->Current mapping for total Prism */
+ AstPrism *this; /* Pointer to Prism structure */
+ AstRegion *reg1; /* 1st component Region Mapping into Prism's Frame */
+ AstRegion *reg2; /* 2nd component Region Mapping into Prism's Frame */
+ int *baxes; /* Indicies of Base Frame axes to be picked */
+ int *caxes; /* Indicies of Current Frame axes to be picked */
+ int iax; /* Axis index */
+ int nax1; /* Number of axes in first component Region */
+ int nax1_out; /* Number of current Frame axes in first component Region */
+ int nax2; /* Number of axes in second component Region */
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Obtain a pointer to the Prism structure. */
+ this = (AstPrism *) this_region;
+
+/* Initialise */
+ cfrm1 = NULL;
+ cfrm2 = NULL;
+ map1 = NULL;
+ map2 = NULL;
+ nax1_out = 0;
+
+/* The number of base-frame axes spanned by the two component Regions. */
+ nax1 = astGetNaxes( this->region1 );
+ nax2 = astGetNaxes( this->region2 );
+
+/* Work space to hold the base frame indices for a single component
+ FrameSet. */
+ baxes = astMalloc( ( nax1 + nax2 )*sizeof( int ) );
+ if( astOK ) {
+
+/* Get the Mapping from Base to Current Frame from the Prism's FrameSet,
+ and get a pointer to the current Frame. */
+ map = astGetMapping( this_region->frameset, AST__BASE, AST__CURRENT );
+ cfrm = astGetFrame( this_region->frameset, AST__CURRENT );
+
+/* Attempt to split the FrameSet encapsulated within the Prism into two -
+ one containing the axes spanned by the first component Region and
+ another containing the axes spanned by the second component Region.
+ First store the zero-based indices of the base Frame axes
+ corresponding to the first component Region. */
+ for( iax = 0; iax < nax1; iax++ ) baxes[ iax ] = iax;
+
+/* Attempt to split these inputs from the total Mapping, thus creating a
+ Mapping that converts just the axes spanned by the first component
+ Region. */
+ caxes = astMapSplit( map, nax1, baxes, &map1 );
+
+/* If the Mapping could be split, get a Frame spanning the current Frame
+ axes corresponding to the first component Region. */
+ if( caxes ) {
+ nax1_out = astGetNout( map1 );
+ cfrm1 = astPickAxes( cfrm, nax1_out, caxes, NULL );
+ caxes = astFree( caxes );
+ }
+
+/* Do the same thing for the second component Region. */
+ for( iax = 0; iax < nax2; iax++ ) baxes[ iax ] = iax + nax1;
+ caxes = astMapSplit( map, nax2, baxes, &map2 );
+ if( caxes ) {
+ cfrm2 = astPickAxes( cfrm, astGetNout( map2 ), caxes, NULL );
+ caxes = astFree( caxes );
+ }
+
+/* Free resources. */
+ cfrm = astAnnul( cfrm );
+ map = astAnnul( map );
+ }
+ baxes = astFree( baxes );
+
+/* If the Prism mapping could not be split, use the parent GetRegionBounds
+ method. */
+ if( !map1 || !map2 ) {
+ (*parent_getregionbounds)( this_region, lbnd, ubnd, status );
+
+/* Otherwise, we get the bounds of the two component Regions separately. */
+ } else {
+
+/* Remap the first component Region using the FrameSet created above. */
+ reg1 = astMapRegion( this->region1, map1, cfrm1 );
+
+/* Get the bounds of this Region, storing the results at the start of the
+ returned lbnd/ubnd arrays. */
+ astGetRegionBounds( reg1, lbnd, ubnd );
+ reg1 = astAnnul( reg1 );
+
+/* Do the same thing for the second component Region, storing the results
+ at the end of the returned lbnd/ubnd arrays. */
+ reg2 = astMapRegion( this->region2, map2, cfrm2 );
+ astGetRegionBounds( reg2, lbnd + nax1_out, ubnd + nax1_out );
+ reg2 = astAnnul( reg2 );
+
+/* What about the possibility that the axes of the Prism have been
+ permuted? */
+
+ }
+
+/* Free resources. */
+ if( map1 ) map1 = astAnnul( map1 );
+ if( map2 ) map2 = astAnnul( map2 );
+ if( cfrm1 ) cfrm1 = astAnnul( cfrm1 );
+ if( cfrm2 ) cfrm2 = astAnnul( cfrm2 );
+
+}
+
+static void GetRegions( AstPrism *this, AstRegion **reg1, AstRegion **reg2,
+ int *neg, int *status ) {
+/*
+*
+* Name:
+* GetRegions
+
+* Purpose:
+* Get the component Regions of a Prism.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "region.h"
+* void GetRegions( AstPrism *this, AstRegion **reg1, AstRegion **reg2,
+* int *neg, int *status )
+
+* Class Membership:
+* Prism member function
+
+* Description:
+* This function returns pointers to the two Regions in a Prism, together
+* with the Negated flag for the Prism.
+*
+* The current Frames in both the returned component Regions will be
+* equivalent to componets of the base Frame in the FrameSet encapsulated
+* by the parent Region structure.
+
+* Parameters:
+* this
+* Pointer to the Prism.
+* reg1
+* Address of a location to receive a pointer to first component
+* Region. This is the region which is to be extruded.
+* reg2
+* Address of a location to receive a pointer to second component
+* Region. This will be an Interval defining the axes along which
+* the first Region is to be extruded.
+* neg
+* Pointer to an int in which to return the value of the Negated
+* attribute of the Prism.
+* status
+* Pointer to the inherited status variable.
+
+* Notes:
+* - The returned pointers should be annuled using astAnnul when no
+* longer needed.
+* - The Frames represented by the returned Regions (that is, the
+* current Frames in their encapsulated FrameSets) are equivalent to the
+* base Frame in the FrameSet encapsulated within the parent Region.
+* - Any changes made to the component Regions using the returned
+* pointers will be reflected in the supplied Prism.
+
+*-
+*/
+
+/* Initialise */
+ if( reg1 ) *reg1 = NULL;
+ if( reg2 ) *reg2 = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Store the required values.*/
+ *reg1 = astClone( this->region1 );
+ *reg2 = astClone( this->region2 );
+ *neg = astGetNegated( (AstRegion *) this );
+}
+
+static AstRegion *GetDefUnc( AstRegion *this_region, int *status ) {
+/*
+* Name:
+* GetDefUnc
+
+* Purpose:
+* Obtain a pointer to the default uncertainty Region for a given Region.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* AstRegion *GetDefUnc( AstRegion *this )
+
+* Class Membership:
+* Prism method (over-rides the astGetDefUnc method inherited from
+* the Region class).
+
+* This function returns a pointer to a Region which represents the
+* default uncertainty associated with a position on the boundary of the
+* given Region. The returned Region refers to the base Frame within the
+* FrameSet encapsulated by the supplied Region.
+
+* Parameters:
+* this
+* Pointer to the Region.
+
+* Returned Value:
+* A pointer to the Region. This should be annulled (using astAnnul)
+* when no longer needed.
+
+* Notes:
+* - A NULL pointer will be returned if this function is invoked
+* with the global error status set, or if it should fail for any
+* reason.
+*/
+
+/* Local Variables: */
+ AstPrism *this; /* Pointer to Prism structure */
+ AstRegion *bunc1; /* Uncertainty Region for 1st component */
+ AstRegion *bunc2; /* Uncertainty Region for 2nd component */
+ AstRegion *result; /* Returned pointer */
+
+/* Initialise */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Get a pointer to the Prism structure. */
+ this = (AstPrism *) this_region;
+
+/* Construct a default uncertainty Region from the uncertainty Regions
+ in the two component Regions. The current Frames in the component
+ Regions are equivalent to the base Frame in the parent Region structure.
+ So we may need to map the component uncertainty into the current Region of
+ the parent if required later on. */
+ bunc1 = astGetUncFrm( this->region1, AST__CURRENT );
+ bunc2 = astGetUncFrm( this->region2, AST__CURRENT );
+
+/* Combine them into a Prism. */
+ result = (AstRegion *) astPrism( bunc1, bunc2, "", status );
+
+/* Free resources. */
+ bunc1 = astAnnul( bunc1 );
+ bunc2 = astAnnul( bunc2 );
+
+/* Return NULL if an error occurred. */
+ if( !astOK ) result = astAnnul( result );
+
+/* Return the required pointer. */
+ return result;
+}
+
+void astInitPrismVtab_( AstPrismVtab *vtab, const char *name, int *status ) {
+/*
+*+
+* Name:
+* astInitPrismVtab
+
+* Purpose:
+* Initialise a virtual function table for a Prism.
+
+* Type:
+* Protected function.
+
+* Synopsis:
+* #include "prism.h"
+* void astInitPrismVtab( AstPrismVtab *vtab, const char *name )
+
+* Class Membership:
+* Prism vtab initialiser.
+
+* Description:
+* This function initialises the component of a virtual function
+* table which is used by the Prism 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 */
+ AstFrameVtab *frame; /* Pointer to Frame component of Vtab */
+ AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */
+ AstObjectVtab *object; /* Pointer to Object component of Vtab */
+ AstRegionVtab *region; /* Pointer to Region component of Vtab */
+
+/* Check the local error status. */
+ if ( !astOK ) return;
+
+/* Get a pointer to the thread specific global data structure. */
+ astGET_GLOBALS(NULL);
+
+/* Initialize the component of the virtual function table used by the
+ parent class. */
+ astInitRegionVtab( (AstRegionVtab *) vtab, name );
+
+/* Store a unique "magic" value in the virtual function table. This
+ will be used (by astIsAPrism) to determine if an object belongs to
+ this class. We can conveniently use the address of the (static)
+ class_check variable to generate this unique value. */
+ vtab->id.check = &class_check;
+ vtab->id.parent = &(((AstRegionVtab *) vtab)->id);
+
+/* Initialise member function pointers. */
+/* ------------------------------------ */
+/* Store pointers to the member functions (implemented here) that
+ provide virtual methods for this class. */
+
+/* None. */
+
+/* Save the inherited pointers to methods that will be extended, and
+ replace them with pointers to the new member functions. */
+ object = (AstObjectVtab *) vtab;
+ mapping = (AstMappingVtab *) vtab;
+ region = (AstRegionVtab *) vtab;
+ frame = (AstFrameVtab *) vtab;
+
+ parent_getobjsize = object->GetObjSize;
+ object->GetObjSize = GetObjSize;
+
+#if defined(THREAD_SAFE)
+ parent_managelock = object->ManageLock;
+ object->ManageLock = ManageLock;
+#endif
+
+ parent_transform = mapping->Transform;
+ mapping->Transform = Transform;
+
+ parent_simplify = mapping->Simplify;
+ mapping->Simplify = Simplify;
+
+ parent_maplist = mapping->MapList;
+ mapping->MapList = MapList;
+
+ parent_getdefunc = region->GetDefUnc;
+ region->GetDefUnc = GetDefUnc;
+
+ parent_setregfs = region->SetRegFS;
+ region->SetRegFS = SetRegFS;
+
+ parent_equal = object->Equal;
+ object->Equal = Equal;
+
+ parent_clearclosed = region->ClearClosed;
+ region->ClearClosed = ClearClosed;
+
+ parent_clearmeshsize = region->ClearMeshSize;
+ region->ClearMeshSize = ClearMeshSize;
+
+ parent_setclosed = region->SetClosed;
+ region->SetClosed = SetClosed;
+
+ parent_setmeshsize = region->SetMeshSize;
+ region->SetMeshSize = SetMeshSize;
+
+ parent_getfillfactor = region->GetFillFactor;
+ region->GetFillFactor = GetFillFactor;
+
+ parent_overlapx = region->OverlapX;
+ region->OverlapX = OverlapX;
+
+ parent_regsetattrib = region->RegSetAttrib;
+ region->RegSetAttrib = RegSetAttrib;
+
+ parent_regclearattrib = region->RegClearAttrib;
+ region->RegClearAttrib = RegClearAttrib;
+
+ parent_getregionbounds = region->GetRegionBounds;
+ region->GetRegionBounds = GetRegionBounds;
+
+/* Store replacement pointers for methods which will be over-ridden by
+ new member functions implemented here. */
+ mapping->Decompose = Decompose;
+ region->RegBaseBox = RegBaseBox;
+ region->RegBaseMesh = RegBaseMesh;
+ region->RegPins = RegPins;
+ region->GetBounded = GetBounded;
+ region->RegCentre = RegCentre;
+ region->Overlap = Overlap;
+ region->RegBasePick = RegBasePick;
+
+/* Declare the copy constructor, destructor and class dump function. */
+ astSetCopy( vtab, Copy );
+ astSetDelete( vtab, Delete );
+ astSetDump( vtab, Dump, "Prism", "Region extrusion into higher dimensions" );
+
+/* 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) );
+ }
+}
+
+#if defined(THREAD_SAFE)
+static int ManageLock( AstObject *this_object, int mode, int extra,
+ AstObject **fail, int *status ) {
+/*
+* Name:
+* ManageLock
+
+* Purpose:
+* Manage the thread lock on an Object.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "object.h"
+* AstObject *ManageLock( AstObject *this, int mode, int extra,
+* AstObject **fail, int *status )
+
+* Class Membership:
+* CmpMap member function (over-rides the astManageLock protected
+* method inherited from the parent class).
+
+* Description:
+* This function manages the thread lock on the supplied Object. The
+* lock can be locked, unlocked or checked by this function as
+* deteremined by parameter "mode". See astLock for details of the way
+* these locks are used.
+
+* Parameters:
+* this
+* Pointer to the Object.
+* mode
+* An integer flag indicating what the function should do:
+*
+* AST__LOCK: Lock the Object for exclusive use by the calling
+* thread. The "extra" value indicates what should be done if the
+* Object is already locked (wait or report an error - see astLock).
+*
+* AST__UNLOCK: Unlock the Object for use by other threads.
+*
+* AST__CHECKLOCK: Check that the object is locked for use by the
+* calling thread (report an error if not).
+* extra
+* Extra mode-specific information.
+* fail
+* If a non-zero function value is returned, a pointer to the
+* Object that caused the failure is returned at "*fail". This may
+* be "this" or it may be an Object contained within "this". Note,
+* the Object's reference count is not incremented, and so the
+* returned pointer should not be annulled. A NULL pointer is
+* returned if this function returns a value of zero.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* A local status value:
+* 0 - Success
+* 1 - Could not lock or unlock the object because it was already
+* locked by another thread.
+* 2 - Failed to lock a POSIX mutex
+* 3 - Failed to unlock a POSIX mutex
+* 4 - Bad "mode" value supplied.
+
+* Notes:
+* - This function attempts to execute even if an error has already
+* occurred.
+*/
+
+/* Local Variables: */
+ AstPrism *this; /* Pointer to Prism structure */
+ int result; /* Returned status value */
+
+/* Initialise */
+ result = 0;
+
+/* Check the supplied pointer is not NULL. */
+ if( !this_object ) return result;
+
+/* Obtain a pointers to the Prism structure. */
+ this = (AstPrism *) this_object;
+
+/* Invoke the ManageLock method inherited from the parent class. */
+ if( !result ) result = (*parent_managelock)( this_object, mode, extra,
+ fail, status );
+
+/* Invoke the astManageLock method on any Objects contained within
+ the supplied Object. */
+ if( !result ) result = astManageLock( this->region1, mode, extra, fail );
+ if( !result ) result = astManageLock( this->region2, mode, extra, fail );
+
+ return result;
+
+}
+#endif
+
+static int MapList( AstMapping *this_mapping, int series, int invert,
+ int *nmap, AstMapping ***map_list, int **invert_list,
+ int *status ) {
+/*
+* Name:
+* MapList
+
+* Purpose:
+* Decompose a Prism into a sequence of simpler Regions.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "mapping.h"
+* int MapList( AstMapping *this, int series, int invert, int *nmap,
+* AstMapping ***map_list, int **invert_list )
+
+* Class Membership:
+* Prism member function (over-rides the protected astMapList
+* method inherited from the Region class).
+
+* Description:
+* This function decomposes a Prism into a sequence of simpler
+* Regions which may be applied in parallel to achieve the same
+* effect. The Prism is decomposed as far as possible, but it is
+* not guaranteed that this will necessarily yield any more than
+* one Region, which may actually be the original Prism supplied.
+
+* Parameters:
+* this
+* Pointer to the Prism to be decomposed (the Prism is not
+* actually modified by this function).
+* series
+* Prisms always apply their component Regions in parallel, so this
+* value should always be zero. This function will return without
+* action if it is non-zero.
+* invert
+* Inverting a Region has no effect on the properties of the Region
+* and so this parameter is ignored.
+* nmap
+* The address of an int which holds a count of the number of
+* individual Regions in the decomposition. On entry, this
+* should count the number of Regions already in the
+* "*map_list" array (below). On exit, it is updated to include
+* any new Regions appended by this function.
+* map_list
+* Address of a pointer to an array of Region pointers. On
+* entry, this array pointer should either be NULL (if no
+* Regions have yet been obtained) or should point at a
+* dynamically allocated array containing Region pointers
+* ("*nmap" in number) which have been obtained from a previous
+* invocation of this function.
+*
+* On exit, the dynamic array will be enlarged to contain any
+* new Region pointers that result from the decomposition
+* requested. These pointers will be appended to any previously
+* present, and the array pointer will be updated as necessary
+* to refer to the enlarged array (any space released by the
+* original array will be freed automatically).
+*
+* The new Region pointers returned will identify a sequence of
+* Regions which, when applied (in parallel) in order, will be
+* equivalent to the original Prism.
+*
+* All the Region pointers returned by this function should be
+* annulled by the caller, using astAnnul, when no longer
+* required. The dynamic array holding these pointers should
+* also be freed, using astFree.
+* invert_list
+* Address of a pointer to an array of int. On entry, this array
+* pointer should either be NULL (if no Regions have yet been
+* obtained) or should point at a dynamically allocated array
+* containing Invert attribute values ("*nmap" in number) which
+* have been obtained from a previous invocation of this
+* function.
+*
+* On exit, the dynamic array will be enlarged to contain any
+* new Invert attribute values that result from the
+* decomposition requested. These values will be appended to any
+* previously present, and the array pointer will be updated as
+* necessary to refer to the enlarged array (any space released
+* by the original array will be freed automatically).
+*
+* The new Invert values returned will always be zero since a
+* Region is unaffected by its Invert setting.
+*
+* The dynamic array holding these values should be freed by the
+* caller, using astFree, when no longer required.
+
+* Returned Value:
+* Zero is always returned.
+
+* Notes:
+* - It is unspecified to what extent the original Prism and the
+* individual (decomposed) Regions are
+* inter-dependent. Consequently, the individual Regions cannot be
+* modified without risking modification of the original Prism.
+* - If this function is invoked with the global error status set,
+* or if it should fail for any reason, then the *nmap value, the
+* list of Region pointers and the list of Invert values will all
+* be returned unchanged.
+*/
+
+/* Local Variables: */
+ AstPrism *this; /* Pointer to Prism structure */
+
+/* Check the global error status. */
+ if ( !astOK ) return 0;
+
+/* Obtain a pointer to the Prism structure. */
+ this = (AstPrism *) this_mapping;
+
+/* When considered as a CmpMap, a Prism always combines its component
+ Mappings (Regions) in parallel. So check that a parallel decomposition
+ was requested. */
+ if ( ! series ) {
+
+/* Concatenate the Mapping lists obtained from each component Region. */
+ (void) astMapList( (AstMapping *) this->region1, 0, 0, nmap, map_list,
+ invert_list );
+ (void) astMapList( (AstMapping *) this->region2, 0, 0, nmap, map_list,
+ invert_list );
+
+/* If the Prism does not combine its components in the way required
+ by the decomposition (series or parallel), then we cannot decompose
+ it. In this case it must be appended to the Mapping list as a
+ single entity. We can use the parent class method to do this. */
+ } else {
+ (void) ( *parent_maplist )( this_mapping, series, invert, nmap,
+ map_list, invert_list, status );
+ }
+
+ return 0;
+}
+
+static int Overlap( AstRegion *this, AstRegion *that, int *status ){
+/*
+* Name:
+* Overlap
+
+* Purpose:
+* Test if two regions overlap each other.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* int Overlap( AstRegion *this, AstRegion *that, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astOverlap method inherited
+* from the Region class).
+
+* Description:
+* This function returns an integer value indicating if the two
+* supplied Regions overlap. The two Regions are converted to a commnon
+* coordinate system before performing the check. If this conversion is
+* not possible (for instance because the two Regions represent areas in
+* different domains), then the check cannot be performed and a zero value
+* is returned to indicate this.
+
+* Parameters:
+* this
+* Pointer to the first Region.
+* that
+* Pointer to the second Region.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* astOverlap()
+* A value indicating if there is any overlap between the two Regions.
+* Possible values are:
+*
+* 0 - The check could not be performed because the second Region
+* could not be mapped into the coordinate system of the first
+* Region.
+*
+* 1 - There is no overlap between the two Regions.
+*
+* 2 - The first Region is completely inside the second Region.
+*
+* 3 - The second Region is completely inside the first Region.
+*
+* 4 - There is partial overlap between the two Regions.
+*
+* 5 - The Regions are identical.
+*
+* 6 - The second Region is the negation of the first Region.
+
+* Notes:
+* - The returned values 5 and 6 do not check the value of the Closed
+* attribute in the two Regions.
+* - A value of zero will be returned if this function is invoked with the
+* AST error status set, or if it should fail for any reason.
+
+*/
+
+/* Local Variables: */
+ AstFrame *bfrm;
+ AstFrame *efrm;
+ AstFrameSet *fs;
+ AstMapping *bmap;
+ AstMapping *emap;
+ AstMapping *map1;
+ AstMapping *map2;
+ AstMapping *map;
+ AstMapping *smap;
+ AstRegion *that_base2;
+ AstRegion *that_base;
+ AstRegion *that_ext2;
+ AstRegion *that_ext;
+ AstRegion *this_reg1;
+ AstRegion *this_reg2;
+ int *inax;
+ int *outax;
+ int i;
+ int nbase;
+ int next;
+ int rbase;
+ int result;
+ int rext;
+ int that_neg;
+ int this_neg;
+
+/* A table indicating how to combine together the overlap state of the
+ extrusion Regions with the overlap state of the other (base) Region.
+ The first index represents the value returned by the astOverlap method
+ when used to determine the overlap of the base Regions in the two
+ supplied Prisms. The second index represents the value returned by the
+ astOverlap method when used to determine the overlap of the extrusion
+ Regions in the two supplied Prisms. The integer values stored in the
+ array represent the astOverlap value describing the overlap of the two
+ Prisms. */
+ static int rtable[ 7 ][ 7 ] = { { 0, 0, 0, 0, 0, 0, 0 },
+ { 0, 1, 1, 1, 1, 1, 1 },
+ { 0, 1, 2, 4, 4, 2, 1 },
+ { 0, 1, 4, 3, 4, 3, 1 },
+ { 0, 1, 4, 4, 4, 4, 1 },
+ { 0, 1, 2, 3, 4, 5, 1 },
+ { 0, 1, 1, 1, 1, 1, 6 } };
+
+/* Initialise */
+ result = 0;
+
+/* Check the inherited status. */
+ if ( !astOK ) return result;
+
+/* Get pointers to the base and extrusion Regions within "this", and also
+ the nagated flag. */
+ GetRegions( (AstPrism *) this, &this_reg1, &this_reg2, &this_neg, status );
+
+/* Get the number of axes in the base and extrusion Regions of "this". */
+ nbase = astGetNaxes( this_reg1 );
+ next = astGetNaxes( this_reg2 );
+
+/* Get a FrameSet which goes from the Frame represented by "this" to the
+ Frame represented by "that". Check that the conection is defined. */
+ fs = astConvert( this, that, "" );
+ if( fs ) {
+
+/* Get the forward Mapping from the above FrameSet. */
+ map2 = astGetMapping( fs, AST__BASE, AST__CURRENT );
+
+/* Get a pointer to the Mapping from base to current Frame in "this". */
+ map1 = astGetMapping( this->frameset, AST__BASE, AST__CURRENT );
+
+/* Combine these Mappings to get the Mapping from the base Frame of "this"
+ to the current Frame of "that". */
+ map = (AstMapping *) astCmpMap( map1, map2, 1, "", status );
+
+/* Simplify this Mapping. */
+ smap = astSimplify( map );
+
+/* See if the extrusion axes in "this" correspond to a unique set of axes
+ in the current Frame of "that". */
+ inax = astMalloc( sizeof(int)*(size_t)next );
+ for( i = 0; i < next; i++ ) inax[ i ] = nbase + i;
+ outax = astMapSplit( smap, next, inax, &emap );
+
+/* If they do, attempt to create a Region by picking the axes from "that"
+ that correspond to the extrusion axes in "this". */
+ if( emap && astGetNout( emap ) == next ) {
+ that_ext = (AstRegion *) astPickAxes( that, next, outax, NULL );
+
+/* If the picked axes formed a Region, see if the base axes can also be
+ picked in the same way. */
+ if( astIsARegion( that_ext ) ) {
+ outax = astFree( outax );
+ inax = astGrow( inax, (size_t)nbase, sizeof( int ) );
+ for( i = 0; i < nbase; i++ ) inax[ i ] = i;
+ outax = astMapSplit( smap, nbase, inax, &bmap );
+ if( bmap && astGetNout( bmap ) == nbase ) {
+ that_base = (AstRegion *) astPickAxes( that, nbase, outax, NULL );
+ if( astIsARegion( that_base ) ) {
+
+/* Map the two Regions picked from "that" into the Frames of the two
+ sub-regions within "this". */
+ astInvert( emap );
+ efrm = astGetFrame( this_reg2->frameset, AST__CURRENT );
+ that_ext2 = astMapRegion( that_ext, emap, efrm );
+
+ astInvert( bmap );
+ bfrm = astGetFrame( this_reg1->frameset, AST__CURRENT );
+ that_base2 = astMapRegion( that_base, bmap, bfrm );
+
+/* We can test separately for overlap of the two extrusion Regions, and for
+ overlap of the two base Regions, and then combine the returned flags to
+ represent overlap of the whole Prism. */
+ rbase = astOverlap( this_reg1, that_base2 );
+ rext = astOverlap( this_reg2, that_ext2 );
+ result = rtable[ rbase ][ rext ];
+
+/* The values in the rtable array assume that neither of the supplied
+ Prisms have been negated. Modify the value obtained from rtable to
+ take account of negation of either or both of the supplied Prisms. */
+ that_neg = astGetNegated( that );
+ if( this_neg ) {
+ if( that_neg ) {
+ if( result == 1 ) {
+ result = 4;
+ } else if( result == 2 ) {
+ result = 3;
+ } else if( result == 3 ) {
+ result = 2;
+ }
+ } else {
+ if( result == 1 ) {
+ result = 3;
+ } else if( result == 2 ) {
+ result = 4;
+ } else if( result == 3 ) {
+ result = 1;
+ } else if( result == 5 ) {
+ result = 6;
+ } else if( result == 6 ) {
+ result = 5;
+ }
+ }
+ } else if( that_neg ){
+ if( result == 1 ) {
+ result = 2;
+ } else if( result == 2 ) {
+ result = 1;
+ } else if( result == 3 ) {
+ result = 4;
+ } else if( result == 5 ) {
+ result = 6;
+ } else if( result == 6 ) {
+ result = 5;
+ }
+ }
+
+/* Free resources */
+ efrm = astAnnul( efrm );
+ that_ext2 = astAnnul( that_ext2 );
+ bfrm = astAnnul( bfrm );
+ that_base2 = astAnnul( that_base2 );
+ }
+ that_base = astAnnul( that_base );
+ bmap = astAnnul( bmap );
+ }
+ }
+ emap = astAnnul( emap );
+ that_ext = astAnnul( that_ext );
+ }
+ outax = astFree( outax );
+ inax = astFree( inax );
+ smap = astAnnul( smap );
+ map = astAnnul( map );
+ map1 = astAnnul( map1 );
+ map2 = astAnnul( map2 );
+ fs = astAnnul( fs );
+ }
+ this_reg1 = astAnnul( this_reg1 );
+ this_reg2 = astAnnul( this_reg2 );
+
+/* If overlap could not be determined using the above implementation, try
+ using the implementation inherited from the parent Region class. Use
+ OverlapX rather than Overlap since a) it is OverlapX that does the work,
+ and b) calling Overlap could end us in an infinite loop. */
+ if( !result ) result = (*parent_overlapx)( this, that, status );
+
+/* If not OK, return zero. */
+ if( !astOK ) result = 0;
+
+/* Return the result. */
+ return result;
+}
+
+static int OverlapX( AstRegion *that, AstRegion *this, int *status ){
+/*
+* Name:
+* OverlapX
+
+* Purpose:
+* Test if two regions overlap each other.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* int OverlapX( AstRegion *that, AstRegion *this )
+
+* Class Membership:
+* Prism member function (over-rides the astOverlapX method inherited
+* from the Region class).
+
+* Description:
+* This function performs the processing for the public astOverlap
+* method and has exactly the same interface except that the order
+* of the two arguments is swapped. This is a trick to allow
+* the astOverlap method to be over-ridden by derived classes on
+* the basis of the class of either of its two arguments.
+*
+* See the astOverlap method for details of the interface.
+*/
+
+/* Local Variables; */
+ int result;
+
+/* Check the global error status. */
+ if ( !astOK ) return 0;
+
+/* We know that "that" is a Prism, so call the private Overlap method,
+ and then modify the returned value to take account of the fact that the
+ two Regions are swapped. */
+ result = Overlap( that, this, status );
+
+ if( result == 2 ){
+ result = 3;
+ } else if( result == 3 ){
+ result = 2;
+ }
+
+ return result;
+}
+
+
+static void RegBaseBox( AstRegion *this_region, double *lbnd, double *ubnd,
+ int *status ){
+/*
+* Name:
+* RegBaseBox
+
+* Purpose:
+* Returns the bounding box of an un-negated Region in the base Frame of
+* the encapsulated FrameSet.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* void RegBaseBox( AstRegion *this, double *lbnd, double *ubnd,
+* int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astRegBaseBox protected
+* method inherited from the Region class).
+
+* Description:
+* This function returns the upper and lower axis bounds of a Region in
+* the base Frame of the encapsulated FrameSet, assuming the Region
+* has not been negated. That is, the value of the Negated attribute
+* is ignored.
+
+* Parameters:
+* this
+* Pointer to the Region.
+* lbnd
+* Pointer to an array in which to return the lower axis bounds
+* covered by the Region in the base Frame of the encapsulated
+* FrameSet. It should have at least as many elements as there are
+* axes in the base Frame.
+* ubnd
+* Pointer to an array in which to return the upper axis bounds
+* covered by the Region in the base Frame of the encapsulated
+* FrameSet. It should have at least as many elements as there are
+* axes in the base Frame.
+* status
+* Pointer to the inherited status variable.
+
+*/
+
+/* Local Variables: */
+ AstPrism *this; /* Pointer to Prism structure */
+ AstRegion *reg1; /* Pointer to first component Region */
+ AstRegion *reg2; /* Pointer to second component Region */
+ int nax; /* Number of axes in Frame */
+ int neg; /* Negated flag for Prism */
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Get a pointer to the Prism structure */
+ this = (AstPrism *) this_region;
+
+/* Get pointers to the component Regions. */
+ GetRegions( this, &reg1, &reg2, &neg, status );
+
+/* The base Frame of the parent Region structure is equivalent to a
+ CmpFrame containing the current Frames of the component Regions.
+ Get the no. of axes in the first component Frame. */
+ nax = astGetNaxes( reg1 );
+
+/* Get the bounding boxes of the component Regions in these Frame,
+ storing the values in the supplied arrays. */
+ astGetRegionBounds( reg1, lbnd, ubnd );
+ astGetRegionBounds( reg2, lbnd + nax, ubnd + nax );
+
+/* Free resources.*/
+ reg1 = astAnnul( reg1 );
+ reg2 = astAnnul( reg2 );
+}
+
+static AstPointSet *RegBaseMesh( AstRegion *this_region, int *status ){
+/*
+* Name:
+* RegBaseMesh
+
+* Purpose:
+* Return a PointSet containing a mesh of points on the boundary of a
+* Region in its base Frame.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* AstPointSet *RegBaseMesh( AstRegion *this, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astRegBaseMesh protected
+* method inherited from the Region class).
+
+* Description:
+* This function returns a PointSet containing a mesh of points on the
+* boundary of the Region. The points refer to the base Frame of
+* the encapsulated FrameSet.
+
+* Parameters:
+* this
+* Pointer to the Region.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Pointer to the PointSet. Annul the pointer using astAnnul when it
+* is no longer needed.
+
+* Notes:
+* - A NULL pointer is returned if an error has already occurred, or if
+* this function should fail for any reason.
+
+*/
+
+
+/* Local Variables: */
+ AstPointSet *grid1; /* PointSet holding grid for region1 */
+ AstPointSet *grid2; /* PointSet holding grid for region2 */
+ AstPointSet *mesh1; /* PointSet holding mesh for region1 */
+ AstPointSet *mesh2; /* PointSet holding mesh for region2 */
+ AstPointSet *result; /* Returned pointer */
+ AstPrism *this; /* The Prism structure */
+ AstRegion *reg1; /* Pointer to first component Region */
+ AstRegion *reg2; /* Pointer to second component Region */
+ double **pg1; /* Pointer to grid1 arrays */
+ double **pg2; /* Pointer to grid2 arrays */
+ double **pm1; /* Pointer to mesh1 arrays */
+ double **pm2; /* Pointer to mesh2 arrays */
+ double **ptr; /* Pointer to returned mesh arrays */
+ int gsz1; /* Preferred grid size for region1 */
+ int gsz2; /* Preferred grid size for region2 */
+ int hasMesh1; /* Does 1st component Region have a mesh? */
+ int hasMesh2; /* Does 2nd component Region have a mesh? */
+ int i; /* Index of next mesh position */
+ int ii; /* Index of next results position */
+ int j; /* Index of next grid position */
+ int jc; /* Axis index */
+ int msz1; /* Preferred mesh size for region1 */
+ int msz2; /* Preferred mesh size for region2 */
+ int msz; /* Original MeshSize */
+ int mszp; /* MeshSize value for Prism */
+ int nax1; /* Number of axes in region1 */
+ int nax2; /* Number of axes in region2 */
+ int nax; /* Number of axes in Prism */
+
+/* Initialise */
+ result= NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Get a pointer to the Prism structure. */
+ this = (AstPrism *) this_region;
+
+/* If the Region structure contains a pointer to a PointSet holding
+ a previously created mesh, return it. */
+ if( this_region->basemesh ) {
+ result = astClone( this_region->basemesh );
+
+/* Otherwise, create a new mesh. */
+ } else {
+
+/* Get pointers to the component regions. */
+ reg1 = this->region1;
+ reg2 = this->region2;
+
+/* A mesh can only be produced for a Region if it is bounded when either
+ negated or un-negated. See if meshes can be produced for the component
+ Regions. */
+ hasMesh1 = astGetBounded( reg1 );
+ if( !hasMesh1 ){
+ astNegate( reg1 );
+ hasMesh1 = astGetBounded( reg1 );
+ astNegate( reg1 );
+ }
+
+ hasMesh2 = astGetBounded( reg2 );
+ if( !hasMesh2 ){
+ astNegate( reg2 );
+ hasMesh2 = astGetBounded( reg2 );
+ astNegate( reg2 );
+ }
+
+/* If either Region does not have a mesh we cannot produce a mesh for the
+ Prism. */
+ if( !hasMesh1 || !hasMesh2 ) {
+ if( astOK ) astError( AST__INTER, "astRegBaseMesh(%s): No mesh "
+ "can be produced for the %s bacause one of its component "
+ "Regions is unbounded.", status, astGetClass( this ), astGetClass( this ) );
+
+/* Otherwise we can create a mesh for the Prism. */
+ } else {
+
+/* Determine the grid sizes and mesh sizes to use for the two components.
+ This aims to produce a total number of points in the returned Prism
+ mesh roughly equal to the MeshSize attribute of the Prism. It also
+ aims to divide the mesh points equally between the end faces of the
+ prism, and the side walls. We remember that the grid used to represent
+ any 1-D region always has a size of 2, regardless of the setting of
+ MeshSize. */
+ mszp = astGetMeshSize( this );
+ msz1 = ( astGetNaxes( reg1 ) == 1 ) ? 2 : sqrt( 0.5*mszp );
+ gsz2 = 0.5*mszp/msz1;
+ msz2 = ( astGetNaxes( reg2 ) == 1 ) ? 2 : sqrt( 0.5*mszp );
+ gsz1 = 0.5*mszp/msz2;
+
+/* First, get a boundary mesh for the second component Region defining the
+ prism extrusion. For instance, if the Region is 1-dimensional, this mesh
+ will consist of the two values on the Region axis: the lower and upper
+ bounds of the Region. */
+ msz = astTestMeshSize( reg2 ) ? astGetMeshSize( reg2 ) : -1;
+ astSetMeshSize( reg2, msz2 );
+ mesh2 = astRegMesh( reg2 );
+
+/* Also get a grid of points spread throughout the extent (i.e. not
+ merely on the boundary) of the second Region. */
+ astSetMeshSize( reg2, gsz2 );
+ grid2 = astRegGrid( reg2 );
+
+/* Re-instate the original MeshSize for the second Region. */
+ if( msz == -1 ) {
+ astClearMeshSize( reg2 );
+ } else {
+ astSetMeshSize( reg2, msz );
+ }
+
+/* Similarly, get a boundary mesh and a volume grid for the first Region. */
+ msz = astTestMeshSize( reg1 ) ? astGetMeshSize( reg1 ) : -1;
+ astSetMeshSize( reg1, msz1 );
+ mesh1 = astRegMesh( reg1 );
+
+ astSetMeshSize( reg1, gsz1 );
+ grid1 = astRegGrid( reg1 );
+
+ if( msz == -1 ) {
+ astClearMeshSize( reg1 );
+ } else {
+ astSetMeshSize( reg1, msz );
+ }
+
+/* Note the number of axes in the two component Regions. */
+ nax1 = astGetNcoord( mesh1 );
+ nax2 = astGetNcoord( mesh2 );
+
+/* The above mesh and grid sizes are only approximate. Find the values
+ actually used. */
+ msz1 = astGetNpoint( mesh1 );
+ gsz1 = astGetNpoint( grid1 );
+ msz2 = astGetNpoint( mesh2 );
+ gsz2 = astGetNpoint( grid2 );
+
+/* Create the returned PointSet. */
+ msz = gsz1*msz2 + msz1*gsz2;
+ nax= astGetNaxes( this );
+ result = astPointSet( msz, nax, "", status );
+
+/* Get pointers to the data in all 5 PointSets. */
+ ptr = astGetPoints( result );
+ pm1 = astGetPoints( mesh1 );
+ pg1 = astGetPoints( grid1 );
+ pm2 = astGetPoints( mesh2 );
+ pg2 = astGetPoints( grid2 );
+
+/* Check pointers can be de-referenced safely. */
+ if( astOK ) {
+
+/* Initialise the index of the next point to be written to the results
+ array. */
+ ii = 0;
+
+/* First, replicate the volume grid covering the first region at every
+ point in the boundary mesh covering the second Region. */
+ for( i = 0; i < msz2; i++ ) {
+ for( j = 0; j < gsz1; j++, ii++ ) {
+ for( jc = 0; jc < nax1; jc++ ) {
+ ptr[ jc ][ ii ] = pg1[ jc ][ j ];
+ }
+ for( ; jc < nax; jc++ ) {
+ ptr[ jc ][ ii ] = pm2[ jc - nax1 ][ i ];
+ }
+ }
+ }
+
+/* Now, replicate the volume grid covering the second region at every
+ point in the boundary mesh covering the first Region. */
+ for( i = 0; i < msz1; i++ ) {
+ for( j = 0; j < gsz2; j++, ii++ ) {
+ for( jc = 0; jc < nax1; jc++ ) {
+ ptr[ jc ][ ii ] = pm1[ jc ][ i ];
+ }
+ for( ; jc < nax; jc++ ) {
+ ptr[ jc ][ ii ] = pg2[ jc -nax1 ][ j ];
+ }
+ }
+ }
+ }
+
+/* Free resources. */
+ mesh1 = astAnnul( mesh1 );
+ mesh2 = astAnnul( mesh2 );
+ grid1 = astAnnul( grid1 );
+ grid2 = astAnnul( grid2 );
+ }
+
+/* Save the returned pointer in the Region structure so that it does not
+ need to be created again next time this function is called. */
+ if( astOK && result ) this_region->basemesh = astClone( result );
+ }
+
+/* Annul the result if an error has occurred. */
+ if( !astOK ) result = astAnnul( result );
+
+/* Return a pointer to the output PointSet. */
+ return result;
+}
+
+static AstRegion *RegBasePick( AstRegion *this_region, int naxes,
+ const int *axes, int *status ){
+/*
+* Name:
+* RegBasePick
+
+* Purpose:
+* Return a Region formed by picking selected base Frame axes from the
+* supplied Region.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* AstRegion *RegBasePick( AstRegion *this, int naxes, const int *axes,
+* int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astRegBasePick protected
+* method inherited from the Region class).
+
+* Description:
+* This function attempts to return a Region that is spanned by selected
+* axes from the base Frame of the encapsulated FrameSet of the supplied
+* Region. This may or may not be possible, depending on the class of
+* Region. If it is not possible a NULL pointer is returned.
+
+* Parameters:
+* this
+* Pointer to the Region.
+* naxes
+* The number of base Frame axes to select.
+* axes
+* An array holding the zero-based indices of the base Frame axes
+* that are to be selected.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Pointer to the Region, or NULL if no region can be formed.
+
+* Notes:
+* - A NULL pointer is returned if an error has already occurred, or if
+* this function should fail for any reason.
+*/
+
+/* Local Variables: */
+ AstFrame *frm1; /* Axes picked from the 1st encapsulated Region */
+ AstFrame *frm2; /* Axes picked from the 2nd encapsulated Region */
+ AstPrism *this; /* Pointer to Prism structure */
+ AstRegion *result; /* Returned Region */
+ int *axes1; /* Axes to pick from 1st input encapsulated Region */
+ int *axes2; /* Axes to pick from 2nd input encapsulated Region */
+ int i; /* Output axis index */
+ int j; /* Input axis index */
+ int nax1; /* No. of axes in 1st input encapsulated Region */
+ int nax2; /* No. of axes in 2nd input encapsulated Region */
+ int naxes1; /* No. of axes in 1st output encapsulated Region */
+ int naxes2; /* No. of axes in 2nd output encapsulated Region */
+
+/* Initialise */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Get a pointer to the Prism information. */
+ this = (AstPrism *) this_region;
+
+/* Get the number of axes in each of the two encapsulated Regions. */
+ nax1 = astGetNaxes( this->region1 );
+ nax2 = astGetNaxes( this->region2 );
+
+/* Allocate memory to hold the indices of the axes selected from each of
+ the two encapsulated Regions. */
+ axes1 = astMalloc( sizeof( *axes1 )*nax1 );
+ axes2 = astMalloc( sizeof( *axes2 )*nax2 );
+
+/* Check pointers can be used safely. */
+ if( astOK ) {
+
+/* Initialise the counters that count the number of axes selected from
+ each of the two encapsulated Regions. */
+ naxes1 = 0;
+ naxes2 = 0;
+
+/* For each of the axes to be selected from the prism... */
+ for( i = 0; i < naxes; i++ ) {
+ j = axes[ i ];
+
+/* ... if the current selected axis is part of the first encapsulated
+ Region, add its index into the array that holds the axes to be selected
+ from the first encapsulated region. Increment the number of axes
+ selected from the first encapsulated region. */
+ if( j < nax1 ) {
+ axes1[ naxes1++ ] = j;
+
+/* If the current selected axis is part of the second encapsulated Region,
+ add its index into the array that holds the axes to be selected from
+ the second encapsulated region. Note, the index is converted from a
+ Prism axis index to a sub-region axis index by subtracting "nax1".
+ Also increment the number of axes selected from the second encapsulated
+ region. */
+ } else {
+ axes2[ naxes2++ ] = j - nax1;
+ }
+ }
+
+/* Pick any required axes from the first sub-region. If the result of the
+ selection is not a Region, we cannot pick the required axes, so annul
+ the object holding the selected axes. */
+ if( naxes1 ) {
+ frm1 = astPickAxes( this->region1, naxes1, axes1, NULL );
+ if( frm1 && !astIsARegion( frm1 ) ) frm1 = astAnnul( frm1 );
+ } else {
+ frm1 = NULL;
+ }
+
+/* Pick any required axes from the second sub-region. If the result of the
+ selection is not a Region, we cannot pick the required axes, so annul
+ the object holding the selected axes. */
+ if( naxes2 ) {
+ frm2 = astPickAxes( this->region2, naxes2, axes2, NULL );
+ if( frm2 && !astIsARegion( frm2 ) ) frm2 = astAnnul( frm2 );
+ } else {
+ frm2 = NULL;
+ }
+
+/* If we are selecting axes only from the first sub-region, and the above
+ selection was succesful, just return a clone of the Region holding the
+ axes selected from the first sub-region. */
+ if( naxes1 > 0 && naxes2 == 0 && frm1 ) {
+ result = astClone( frm1 );
+
+/* If we are selecting axes only from the second sub-region, and the above
+ selection was succesful, just return a clone of the Region holding the
+ axes selected from the second sub-region. */
+ } else if( naxes1 == 0 && naxes2 > 0 && frm2 ) {
+ result = astClone( frm2 );
+
+/* If we are selecting axes from both sub-regions, and both the above
+ selections were succesful, joing them together into a Prism. */
+ } else if( naxes1 > 0 && naxes2 > 0 && frm1 && frm2 ) {
+ result = (AstRegion *) astPrism( (AstRegion *) frm1,
+ (AstRegion *) frm2,
+ "", status );
+ }
+
+/* Free resources */
+ if( frm1 ) frm1 = astAnnul( frm1 );
+ if( frm2 ) frm2 = astAnnul( frm2 );
+ }
+
+ axes1 = astFree( axes1 );
+ axes2 = astFree( axes2 );
+
+/* Return a NULL pointer if an error has occurred. */
+ if( !astOK ) result = astAnnul( result );
+
+/* Return the result. */
+ return result;
+}
+
+static double *RegCentre( AstRegion *this_region, double *cen, double **ptr,
+ int index, int ifrm, int *status ){
+/*
+* Name:
+* RegCentre
+
+* Purpose:
+* Re-centre a Region.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* double *RegCentre( AstRegion *this, double *cen, double **ptr,
+* int index, int ifrm, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astRegCentre protected
+* method inherited from the Region class).
+
+* Description:
+* This function shifts the centre of the supplied Region to a
+* specified position, or returns the current centre of the Region.
+
+* Parameters:
+* this
+* Pointer to the Region.
+* cen
+* Pointer to an array of axis values, giving the new centre.
+* Supply a NULL value for this in order to use "ptr" and "index" to
+* specify the new centre.
+* ptr
+* Pointer to an array of points, one for each axis in the Region.
+* Each pointer locates an array of axis values. This is the format
+* returned by the PointSet method astGetPoints. Only used if "cen"
+* is NULL.
+* index
+* The index of the point within the arrays identified by "ptr" at
+* which is stored the coords for the new centre position. Only used
+* if "cen" is NULL.
+* ifrm
+* Should be AST__BASE or AST__CURRENT. Indicates whether the centre
+* position is supplied and returned in the base or current Frame of
+* the FrameSet encapsulated within "this".
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* If both "cen" and "ptr" are NULL then a pointer to a newly
+* allocated dynamic array is returned which contains the centre
+* coords of the Region. This array should be freed using astFree when
+* no longer needed. If either of "ptr" or "cen" is not NULL, then a
+* NULL pointer is returned.
+
+* Notes:
+* - Some Region sub-classes do not have a centre. Such classes will report
+* an AST__INTER error code if this method is called with either "ptr" or
+* "cen" not NULL. If "ptr" and "cen" are both NULL, then no error is
+* reported if this method is invoked on a Region of an unsuitable class,
+* but NULL is always returned.
+*/
+
+/* Local Variables: */
+ AstPrism *this; /* Pointer to Prism structure */
+ AstRegion *reg1; /* Pointer to first component Region */
+ AstRegion *reg2; /* Pointer to second component Region */
+ double *bc; /* Base Frame centre position */
+ double *cen1; /* Centre of first component Region */
+ double *cen2; /* Centre of second component Region */
+ double *result; /* Returned pointer */
+ double *tmp; /* Temporary array pointer */
+ double *total; /* Pointer to total base Frame centre array */
+ int i; /* Coordinate index */
+ int nax1; /* Number of axes in first component Region */
+ int nax2; /* Number of axes in second component Region */
+ int ncb; /* Number of base frame coordinate values per point */
+ int ncc; /* Number of current frame coordinate values per point */
+ int neg; /* Prism negated flag */
+
+/* Initialise */
+ result = NULL;
+
+/* Check the local error status. */
+ if ( !astOK ) return result;
+
+/* Get a pointer to the Prism structure. */
+ this = (AstPrism *) this_region;
+
+/* Get the component Regions, and the Negated flag for the Prism. */
+ GetRegions( this, &reg1, &reg2, &neg, status );
+
+/* Get the number of current Frame axes in each component Region. The sum
+ of these will equal the number of base Frame axes in the parent Region
+ structure. */
+ nax1 = astGetNaxes( reg1 );
+ nax2 = astGetNaxes( reg2 );
+ ncb = nax1 + nax2;
+
+/* If we are getting (not setting) the current centre... */
+ if( !ptr && !cen ) {
+
+/* Get the centre from the two component Regions in their current Frames. */
+ cen1 = astRegCentre( reg1, NULL, NULL, 0, AST__CURRENT );
+ cen2 = astRegCentre( reg2, NULL, NULL, 0, AST__CURRENT );
+
+/* If both component regions are re-centerable, join the two centre
+ arrays together into a single array. */
+ if( cen1 && cen2 ) {
+ total = astMalloc( sizeof(double)*(size_t)ncb );
+ if( total ) {
+ for( i = 0; i < nax1; i++ ) total[ i ] = cen1[ i ];
+ for( i = 0; i < nax2; i++ ) total[ i + nax1 ] = cen2[ i ];
+
+/* The current Frames of the component Regions correspond to the base
+ Frame of the parent Region structure. If the original centre is
+ required in the current Frame, transform it using the base->current
+ Mapping from the parent Region structure. */
+ if( ifrm == AST__CURRENT ) {
+ result = astRegTranPoint( this_region, total, 1, 1 );
+ total = astFree( total );
+ } else {
+ result = total;
+ }
+ }
+ }
+
+/* Free the individual centre arrays. */
+ cen1 = astFree( cen1 );
+ cen2 = astFree( cen2 );
+
+/* If we are setting a new centre... */
+ } else {
+
+/* If the new centre is supplied in the current Frame of the parent
+ Region structure, transform it into the base Frame (i.e. the Frames
+ represented by the component Regions). */
+ if( ifrm == AST__CURRENT ) {
+ if( cen ) {
+ bc = astRegTranPoint( this_region, cen, 1, 0 );
+ } else {
+ ncc = astGetNaxes( this_region );
+ tmp = astMalloc( sizeof( double)*(size_t)ncc );
+ if( astOK ) {
+ for( i = 0; i < ncc; i++ ) tmp[ i ] = ptr[ i ][ index ];
+ }
+ bc = astRegTranPoint( this_region, tmp, 1, 0 );
+ tmp = astFree( tmp );
+ }
+
+ } else {
+ if( cen ) {
+ bc = cen;
+ } else {
+ bc = astMalloc( sizeof( double)*(size_t)ncb );
+ if( astOK ) {
+ for( i = 0; i < ncb; i++ ) bc[ i ] = ptr[ i ][ index ];
+ }
+ }
+ }
+
+/* Set the centre in the two component Regions in their current Frames. */
+ astRegCentre( reg1, bc, NULL, 0, AST__CURRENT );
+ astRegCentre( reg2, bc + nax1, NULL, 0, AST__CURRENT );
+
+/* Free resources. */
+ if( bc != cen ) bc = astFree( bc );
+ }
+
+ reg1 = astAnnul( reg1 );
+ reg2 = astAnnul( reg2 );
+
+/* Return the result. */
+ return result;
+}
+
+static int RegPins( AstRegion *this_region, AstPointSet *pset, AstRegion *unc,
+ int **mask, int *status ){
+/*
+* Name:
+* RegPins
+
+* Purpose:
+* Check if a set of points fall on the boundary of a given Prism.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* int RegPins( AstRegion *this, AstPointSet *pset, AstRegion *unc,
+* int **mask, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astRegPins protected
+* method inherited from the Region class).
+
+* Description:
+* This function returns a flag indicating if the supplied set of
+* points all fall on the boundary of the given Prism.
+*
+* Some tolerance is allowed, as specified by the uncertainty Region
+* stored in the supplied Prism "this", and the supplied uncertainty
+* Region "unc" which describes the uncertainty of the supplied points.
+
+* Parameters:
+* this
+* Pointer to the Prism.
+* pset
+* Pointer to the PointSet. The points are assumed to refer to the
+* base Frame of the FrameSet encapsulated by "this".
+* unc
+* Pointer to a Region representing the uncertainties in the points
+* given by "pset". The Region is assumed to represent the base Frame
+* of the FrameSet encapsulated by "this". Zero uncertainity is assumed
+* if NULL is supplied.
+* mask
+* Pointer to location at which to return a pointer to a newly
+* allocated dynamic array of ints. The number of elements in this
+* array is equal to the value of the Npoint attribute of "pset".
+* Each element in the returned array is set to 1 if the
+* corresponding position in "pset" is on the boundary of the Region
+* and is set to zero otherwise. A NULL value may be supplied
+* in which case no array is created. If created, the array should
+* be freed using astFree when no longer needed.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Non-zero if the points all fall on the boundary of the given
+* Region, to within the tolerance specified. Zero otherwise.
+
+*/
+
+/* Local variables: */
+ AstPointSet *ps1; /* Points projected into 1st component Region */
+ AstPointSet *ps1b; /* "ps1" in base Frame of 1st component Region */
+ AstPointSet *ps1b2; /* "ps1b" transformed using 1st Region */
+ AstPointSet *ps2b2; /* "ps2b" transformed using 2nd Region */
+ AstPointSet *ps2; /* Points projected into 2nd component Region */
+ AstPointSet *ps2b; /* "ps2" in base Frame of 2nd component Region */
+ AstPrism *this; /* Pointer to the Prism structure. */
+ AstRegion *reg1; /* Pointer to first component Region */
+ AstRegion *reg2; /* Pointer to second component Region */
+ AstRegion *unc1; /* Base Frame uncertainty in 1st component Region */
+ AstRegion *unc2; /* Base Frame uncertainty in 2nd component Region */
+ double **ptr1b2; /* Pointer to axis values in "ps1b2" */
+ double **ptr2b2; /* Pointer to axis values in "ps2b2" */
+ int *mask1; /* Mask for first component boundary */
+ int *mask2; /* Mask for second component boundary */
+ int cl1; /* Original Closed flag for reg1 */
+ int cl2; /* Original Closed flag for reg2 */
+ int i; /* Point index */
+ int j; /* Axis index */
+ int nax1; /* Number of axes in first component Region */
+ int nax2; /* Number of axes in second component Region */
+ int np; /* Number of points in supplied PointSet */
+ int on; /* Is this point on the Prism boundary? */
+ int result; /* Returned flag */
+
+/* Initialise */
+ result = 0;
+ if( mask ) *mask = NULL;
+
+/* Check the inherited status. */
+ if( !astOK ) return result;
+
+/* Get a pointer to the Prism structure. */
+ this = (AstPrism *) this_region;
+
+/* Get pointers to the two component Regions. */
+ reg1 = this->region1;
+ reg2 = this->region2;
+
+/* Temporarily ensure the components are closed. */
+ cl1 = astTestClosed( reg1 ) ? astGetClosed( reg1 ) : INT_MAX;
+ cl2 = astTestClosed( reg2 ) ? astGetClosed( reg2 ) : INT_MAX;
+ astSetClosed( reg1, cl1 );
+ astSetClosed( reg2, cl2 );
+
+/* A point in the coordinate system represented by the Prism is on the
+ boundary of the Prism if:
+ 1) it is on the boundary of one of the coomponent Regions AND
+ 2) it is on or within the boundary of the other component Region.
+
+ First look for points on the boundary of the first component Region.
+ Create a PointSet holding just the axes from the supplied PointSet
+ which relate to the first component Region. */
+ np = astGetNpoint( pset );
+ nax1 = astGetNaxes( reg1 );
+ ps1 = astPointSet( np, nax1, "", status );
+ astSetSubPoints( pset, 0, 0, ps1 );
+
+/* Get a mask which indicates if each supplied point is on or off the
+ boundary of the first component Region. astRegPins expects its "pset"
+ argument to contain positions in the base Frame of the Region, so
+ we must first transform the supplied points into the base Frame of
+ "reg1". We must also get the uncertainty in the base Frame of the
+ component Region. */
+ ps1b = astRegTransform( reg1, ps1, 0, NULL, NULL );
+ unc1 = astGetUncFrm( reg1, AST__BASE );
+ astRegPins( reg1, ps1b, unc1, &mask1 );
+
+/* Also determine which of the points are on or in the boundary by using
+ "reg1" as a Mapping to transform the supplied points. */
+ ps1b2 = astTransform( reg1, ps1b, 1, NULL );
+
+/* Do the same for the second component Region */
+ nax2 = astGetNaxes( reg2 );
+ ps2 = astPointSet( np, nax2, "", status );
+ astSetSubPoints( pset, 0, nax1, ps2 );
+ ps2b = astRegTransform( reg2, ps2, 0, NULL, NULL );
+ unc2 = astGetUncFrm( reg2, AST__BASE );
+ astRegPins( reg2, ps2b, unc2, &mask2 );
+ ps2b2 = astTransform( reg2, ps2b, 1, NULL );
+
+/* Get pointers to the data in all the relevant PointSets. */
+ ptr1b2 = astGetPoints( ps1b2 );
+ ptr2b2 = astGetPoints( ps2b2 );
+
+/* Check pointers can be dereferenced safely. */
+ if( astOK ) {
+
+/* Assume all points are on the boundary of the Prism. */
+ result = 1;
+
+/* Check each point. */
+ for( i = 0; i < np; i++ ) {
+
+/* Assume this point is on the boundary of the Prism. */
+ on = 1;
+
+/* If this point is on the boundary of both component Regions, it is on
+ the boundary of the Prism. If it is on the boundary of the first
+ component Region but not on the boundary of the second, then it is
+ still on the boundary of the Prism if it is within the volume
+ reporesented by the second. */
+ if( mask1[ i ] ) {
+ if( !mask2[ i ] ) {
+ for( j = 0; j < nax2; j++ ) {
+ if( ptr2b2[ j ][ i ] == AST__BAD ) {
+ on = 0;
+ break;
+ }
+ }
+ }
+
+/* If this point is on the boundary of the second component Region but
+ not the first, it is on the boundary of the Prism if it is within the
+ volume reporesented by the first. */
+ } else {
+ if( mask2[ i ] ) {
+ for( j = 0; j < nax1; j++ ) {
+ if( ptr1b2[ j ][ i ] == AST__BAD ) {
+ on = 0;
+ break;
+ }
+ }
+
+/* If this point is on the boundary of neither component Region, it is not
+ on the boundary of the Prism. */
+ } else {
+ on = 0;
+ }
+ }
+
+/* Use "mask1" to return the Prism's mask. Clear the returned flag if
+ this point is not on the boundary of the Prism. */
+ mask1[ i ] = on;
+ if( !on ) result = 0;
+ }
+ }
+
+/* Re-instate the original values of the Closed attribute for the
+ component Regions. */
+ if( cl1 == INT_MAX ) {
+ astClearClosed( reg1 );
+ } else {
+ astSetClosed( reg1, cl1 );
+ }
+ if( cl2 == INT_MAX ) {
+ astClearClosed( reg2 );
+ } else {
+ astSetClosed( reg2, cl2 );
+ }
+
+/* Return "mask1" as the Prism's mask if required. Otherwise free it. */
+ if( mask ) {
+ *mask = mask1;
+ } else {
+ mask1 = astFree( mask1 );
+ }
+
+/* Free other resources */
+ mask2 = astFree( mask2 );
+ ps1 = astAnnul( ps1 );
+ ps1b = astAnnul( ps1b );
+ ps1b2 = astAnnul( ps1b2 );
+ ps2 = astAnnul( ps2 );
+ unc1 = astAnnul( unc1 );
+ ps2b = astAnnul( ps2b );
+ ps2b2 = astAnnul( ps2b2 );
+ unc2 = astAnnul( unc2 );
+
+/* If an error has occurred, return zero. */
+ if( !astOK ) {
+ result = 0;
+ if( mask ) *mask = astFree( *mask );
+ }
+
+/* Return the result. */
+ return result;
+}
+
+static void RegClearAttrib( AstRegion *this_region, const char *attrib,
+ char **base_attrib, int *status ) {
+/*
+* Name:
+* RegClearAttrib
+
+* Purpose:
+* Clear an attribute value for a Region.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* void RegClearAttrib( AstRegion *this, const char *attrib,
+* char **base_attrib, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astRegClearAttrib method
+* inherited from the Region class).
+
+* Description:
+* This function clears the value of a named attribute in both the base
+* and current Frame in the FrameSet encapsulated within a Region, without
+* remapping either Frame.
+*
+* No error is reported if the attribute is not recognised by the base
+* Frame.
+
+* Parameters:
+* this
+* Pointer to the Region.
+* attrib
+* Pointer to a null terminated string holding the attribute name.
+* NOTE, IT SHOULD BE ENTIRELY LOWER CASE.
+* base_attrib
+* Address of a location at which to return a pointer to the null
+* terminated string holding the attribute name which was cleared in
+* the base Frame of the encapsulated FrameSet. This may differ from
+* the supplied attribute if the supplied attribute contains an axis
+* index and the current->base Mapping in the FrameSet produces an
+* axis permutation. The returned pointer should be freed using
+* astFree when no longer needed. A NULL pointer may be supplied in
+* which case no pointer is returned.
+* status
+* Pointer to the inherited status variable.
+
+*/
+
+/* Local Variables: */
+ AstPrism *this;
+ AstRegion *creg;
+ char *batt;
+ char buf1[ 100 ];
+ char buf2[ 255 ];
+ int axis;
+ int len;
+ int nax1;
+ int nc;
+ int rep;
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Get a pointer to the Prism structure. */
+ this = (AstPrism *) this_region;
+
+/* Use the RegClearAttrib method inherited from the parent class to clear the
+ attribute in the current and base Frames in the FrameSet encapsulated by
+ the parent Region structure. */
+ (*parent_regclearattrib)( this_region, attrib, &batt, status );
+
+/* We now propagate the setting down to the component Regions. The current
+ Frames in the component Regions together form a CmpFrame which is
+ equivalent to the base Frame in the parent FrameSet. Switch off error
+ reporting whilst we apply the setting to the component Regions. */
+ rep = astReporting( 0 );
+
+/* If the setting which was applied to the base Frame of the parent FrameSet
+ is qualified by an axis index, modify the axis index to refer to component
+ Region which defines the axis. First parse the base Frame attribute setting
+ to locate any axis index. */
+ len = strlen( batt );
+ if( nc = 0, ( 2 == astSscanf( batt, "%[^(](%d) %n", buf1, &axis,
+ &nc ) ) && ( nc >= len ) ) {
+
+/* If found, convert the axis index from one-based to zero-based. */
+ axis--;
+
+/* Get a pointer to the component Region containing the specified axis, and
+ create a new setting with the same attribute name but with the axis index
+ appropriate to the component Region which defines the axis. */
+ nax1 = astGetNaxes( this->region1 );
+ if( axis < nax1 ) {
+ creg = this->region1;
+ } else {
+ creg = this->region2;
+ axis -= nax1;
+ }
+ sprintf( buf2, "%s(%d)", buf1, axis + 1 );
+
+/* Apply the setting to the relevant component Region. */
+ astRegClearAttrib( creg, buf2, NULL );
+
+/* If the setting is not qualified by an axis index, apply it to both
+ component Regions. */
+ } else {
+ astRegClearAttrib( this->region1, batt, NULL );
+ astRegClearAttrib( this->region2, batt, NULL );
+ }
+
+/* Annul the error if the attribute was not recognised by the component
+ Regions. Then switch error reporting back on. */
+ if( astStatus == AST__BADAT ) astClearStatus;
+ astReporting( rep );
+
+/* If required, return the base Frame setting string. Otherwise free it. */
+ if( base_attrib ) {
+ *base_attrib = batt;
+ } else {
+ batt = astFree( batt );
+ }
+
+}
+
+static void RegSetAttrib( AstRegion *this_region, const char *setting,
+ char **base_setting, int *status ) {
+/*
+* Name:
+* RegSetAttrib
+
+* Purpose:
+* Set an attribute value for a Region.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* void RegSetAttrib( AstRegion *this, const char *setting,
+* char **base_setting, int *status )
+
+* Class Membership:
+* Prism method (over-rides the astRegSetAttrib method inherited from
+* the Region class).
+
+* Description:
+* This function assigns an attribute value to both the base and
+* current Frame in the FrameSet encapsulated within a Region, without
+* remapping either Frame.
+*
+* No error is reported if the attribute is not recognised by the base
+* Frame.
+
+* Parameters:
+* this
+* Pointer to the Region.
+* setting
+* Pointer to a null terminated attribute setting string. NOTE, IT
+* SHOULD BE ENTIRELY LOWER CASE. The supplied string will be
+* interpreted using the public interpretation implemented by
+* astSetAttrib. This can be different to the interpretation of the
+* protected accessor functions. For instance, the public
+* interpretation of an unqualified floating point value for the
+* Epoch attribute is to interpet the value as a gregorian year,
+* but the protected interpretation is to interpret the value as an
+* MJD.
+* base_setting
+* Address of a location at which to return a pointer to the null
+* terminated attribute setting string which was applied to the
+* base Frame of the encapsulated FrameSet. This may differ from
+* the supplied setting if the supplied setting contains an axis
+* index and the current->base Mapping in the FrameSet produces an
+* axis permutation. The returned pointer should be freed using
+* astFree when no longer needed. A NULL pointer may be supplied in
+* which case no pointer is returned.
+* status
+* Pointer to the inherited status variable.
+
+*/
+
+/* Local Variables: */
+ AstPrism *this;
+ AstRegion *creg;
+ char *bset;
+ char buf1[ 100 ];
+ char buf2[ 255 ];
+ int axis;
+ int len;
+ int nax1;
+ int nc;
+ int rep;
+ int value;
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Get a pointer to the Prism structure. */
+ this = (AstPrism *) this_region;
+
+/* Use the RegSetAttrib method inherited from the parent class to apply the
+ setting to the current and base Frames in the FrameSet encapsulated by the
+ parent Region structure. */
+ (*parent_regsetattrib)( this_region, setting, &bset, status );
+
+/* We now propagate the setting down to the component Regions. The current
+ Frames in the component Regions together form a CmpFrame which is
+ equivalent to the base Frame in the parent FrameSet. Switch off error
+ reporting whilst we apply the setting to the component Regions. */
+ rep = astReporting( 0 );
+
+/* If the setting which was applied to the base Frame of the parent FrameSet
+ is qualified by an axis index, modify the axis index to refer to component
+ Region which defines the axis. First parse the base Frame attribute setting
+ to locate any axis index. */
+ len = strlen( bset );
+ if( nc = 0, ( 2 == astSscanf( bset, "%[^(](%d)= %n%*s %n", buf1, &axis,
+ &value, &nc ) ) && ( nc >= len ) ) {
+
+/* If found, convert the axis index from one-based to zero-based. */
+ axis--;
+
+/* Get a pointer to the component Region containing the specified axis, and
+ create a new setting with the same attribute name but with the axis index
+ appropriate to the component Region which defines the axis. */
+ nax1 = astGetNaxes( this->region1 );
+ if( axis < nax1 ) {
+ creg = this->region1;
+ } else {
+ creg = this->region2;
+ axis -= nax1;
+ }
+ sprintf( buf2, "%s(%d)=%s", buf1, axis + 1, bset + value );
+
+/* Apply the setting to the relevant component Region. */
+ astRegSetAttrib( creg, buf2, NULL );
+
+/* If the setting is not qualified by an axis index, apply it to both
+ component Regions. */
+ } else {
+ astRegSetAttrib( this->region1, bset, NULL );
+ astRegSetAttrib( this->region2, bset, NULL );
+ }
+
+/* Annul the error if the attribute was not recognised by the component
+ Regions. Then switch error reporting back on. */
+ if( astStatus == AST__BADAT ) astClearStatus;
+ astReporting( rep );
+
+/* If required, return the base Frame setting string. Otherwise free it. */
+ if( base_setting ) {
+ *base_setting = bset;
+ } else {
+ bset = astFree( bset );
+ }
+
+}
+
+static void SetRegFS( AstRegion *this_region, AstFrame *frm, int *status ) {
+/*
+* Name:
+* SetRegFS
+
+* Purpose:
+* Stores a new FrameSet in a Region
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* void SetRegFS( AstRegion *this_region, AstFrame *frm, int *status )
+
+* Class Membership:
+* Prism method (over-rides the astSetRegFS method inherited from
+* the Region class).
+
+* Description:
+* This function creates a new FrameSet and stores it in the supplied
+* Region. The new FrameSet contains two copies of the supplied
+* Frame, connected by a UnitMap.
+
+* Parameters:
+* this
+* Pointer to the Region.
+* frm
+* The Frame to use.
+* status
+* Pointer to the inherited status variable.
+
+*/
+
+/* Local Variables: */
+ AstFrame *cfrm; /* Frame containing required axes */
+ AstRegion *creg; /* Pointer to component Region structure */
+ int *axes; /* Pointer to array of axis indices */
+ int i; /* Loop count */
+ int nax1; /* No.of axes in 1st component Frame */
+ int nax2; /* No.of axes in 2nd component Frame */
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Invoke the parent method to store the FrameSet in the parent Region
+ structure. */
+ (* parent_setregfs)( this_region, frm, status );
+
+/* If either component Region has a dummy FrameSet use this method
+ recursively to give them a FrameSet containing the corresponding axes
+ from the supplied Frame. */
+ creg = ((AstPrism *) this_region )->region1;
+ if( creg ) {
+ nax1 = astGetNaxes( creg );
+ if( !astGetRegionFS( creg ) ) {
+ axes = astMalloc( sizeof( int )*(size_t) nax1 );
+ if( astOK ) for( i = 0; i < nax1; i++ ) axes[ i ] = i;
+ cfrm = astPickAxes( frm, nax1, axes, NULL );
+ astSetRegFS( creg, cfrm );
+ axes = astFree( axes );
+ cfrm = astAnnul( cfrm );
+ }
+
+ } else {
+ nax1 = 0;
+ }
+
+ creg = ((AstPrism *) this_region )->region2;
+ if( creg && !astGetRegionFS( creg ) ) {
+ nax2 = astGetNaxes( creg );
+ axes = astMalloc( sizeof( int )*(size_t) nax2 );
+ if( astOK ) for( i = 0; i < nax2; i++ ) axes[ i ] = nax1 + i;
+ cfrm = astPickAxes( frm, nax2, axes, NULL );
+ astSetRegFS( creg, cfrm );
+ axes = astFree( axes );
+ cfrm = astAnnul( cfrm );
+ }
+
+}
+
+static AstMapping *Simplify( AstMapping *this_mapping, int *status ) {
+/*
+* Name:
+* Simplify
+
+* Purpose:
+* Simplify a Region.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "region.h"
+* AstMapping *Simplify( AstMapping *this, int *status )
+
+* Class Membership:
+* Prism method (over-rides the astSimplify method inherited from
+* the Region class).
+
+* Description:
+* This function simplifies a Prism to eliminate redundant
+* computational steps, or to merge separate steps which can be
+* performed more efficiently in a single operation.
+
+* Parameters:
+* this
+* Pointer to the original Region.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* A new pointer to the (possibly simplified) Region.
+
+* Notes:
+* - A NULL pointer value will be returned if this function is
+* invoked with the AST error status set, or if it should fail for
+* any reason.
+
+* Deficiencies:
+* - Currently, this function does not attempt to map the component
+* Regions into the current Frame of the parent Region structure.
+
+*/
+
+/* Local Variables: */
+ AstFrame *cfrm; /* Current Frame */
+ AstFrame *newfrm1; /* Current Frame axes for reg1 */
+ AstFrame *newfrm2; /* Current Frame axes for reg2 */
+ AstFrameSet *fs; /* Parent FrameSet */
+ AstMapping *bcmap; /* Base->current Mapping */
+ AstMapping *nmap1; /* Reg1->current Mapping */
+ AstMapping *map1; /* First component Region from a CmpMap */
+ AstMapping *map2; /* Second component Region from a CmpMap */
+ int series; /* Apply component Mappings in series? */
+ int invert1; /* Use inverted first component Mapping? */
+ int invert2; /* Use inverted second component Mapping? */
+ AstMapping *nmap2; /* Reg2->current Mapping */
+ AstMapping *result; /* Result pointer to return */
+ AstCmpMap *cmpmap; /* Result pointer to return */
+ AstMapping *smap; /* Simplified CmpMap */
+ AstRegion *new2; /* New simplified Region */
+ AstRegion *new; /* New Region */
+ AstRegion *newreg1; /* Reg1 mapped into current Frame */
+ AstRegion *newreg2; /* Reg2 mapped into current Frame */
+ AstRegion *reg1; /* First component Region */
+ AstRegion *reg2; /* Second component Region */
+ AstRegion *reg; /* This Region */
+ AstRegion *snewreg1; /* Simplified newreg1 */
+ AstRegion *snewreg2; /* Simplified newreg2 */
+ AstRegion *unc; /* Uncertainty Region from supplied Prism */
+ int *axin; /* Indices of Mapping inputs to use */
+ int *axout1; /* Indices of cfrm axes corresponding to reg1 */
+ int *axout2; /* Indices of cfrm axes corresponding to reg2 */
+ int *perm; /* Axis permutation array */
+ int i; /* Loop count */
+ int nax1; /* Number of axes in first component Region */
+ int nax2; /* Number of axes in second component Region */
+ int naxt; /* Total number of axes in current Frame */
+ int naxout1; /* Number of current axes for reg1 */
+ int naxout2; /* Number of current axes for reg2 */
+ int neg; /* Negated flag for supplied Prism */
+
+/* Initialise. */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Get a pointer to the Region structure */
+ reg = (AstRegion *) this_mapping;
+
+/* Get the component Regions, and the Negated flag for the Prism. */
+ GetRegions( (AstPrism *) this_mapping, &reg1, &reg2, &neg, status );
+
+/* The above Regions describe areas within the base Frame of the FrameSet
+ encapsulated by the parent Region structure. Get the current Frame in
+ this FrameSet and the base->current Mapping. */
+ fs = reg->frameset;
+ cfrm = astGetFrame( fs, AST__CURRENT );
+ bcmap = astGetMapping( fs, AST__BASE, AST__CURRENT );
+
+/* Combine the two Regions into a parallel CmpMap (this uses the fact
+ that a Region is a type of Mapping). Then simplify the CmpMap. This
+ will result in the astMapMerge methods defined by sub-classes of
+ Regions being used to merge adjacent regions. */
+ cmpmap = astCmpMap( reg1, reg2, 0, "", status );
+ smap = astSimplify( cmpmap );
+ cmpmap = astAnnul( cmpmap );
+
+/* Initially, assume we cannot form a new Region from the simplified
+ CmpMap. */
+ new = NULL;
+
+/* If the result is a region, use it. */
+ if( astIsARegion( smap ) ) {
+ new = astClone( smap );
+
+/* If the result is a parallel CmpMap, get its two components and check
+ they are Regions. If so, and if they are not the same as the original
+ two component Regions, form a new Prism from them. */
+ } else if( astIsACmpMap( smap ) ) {
+ astDecompose( smap, &map1, &map2, &series, &invert1, &invert2 );
+ if( ! series && astIsARegion( map1 ) && astIsARegion( map2 ) ) {
+ if( (AstRegion *) map1 != reg1 || (AstRegion *) map2 != reg2 ) {
+ new = (AstRegion *) astPrism( (AstRegion *) map1,
+ (AstRegion *) map2, "", status );
+ }
+ }
+
+/* Free resources */
+ map1 = astAnnul( map1 );
+ map2 = astAnnul( map2 );
+ }
+
+ smap = astAnnul( smap );
+
+/* If the above produced a simplified Region, map it into the current Frame
+ of "this" and simplify it. */
+ if( new ) {
+ new2 = astMapRegion( new, bcmap, cfrm );
+ (void) astAnnul( new );
+ new = astSimplify( new2 );
+ new2 = astAnnul( new2 );
+
+/* If the above did not produced a result, try a different approach. */
+ } else {
+
+/* Get the number of axes in each component Region. */
+ nax1 = astGetNaxes( reg1 );
+ nax2 = astGetNaxes( reg2 );
+
+/* Use astMapSplit to see if the axes of the first component Region correspond
+ to a distinct set of axes within the current Frame. If this is the case,
+ then a Mapping is returned by astMapSplit which maps the axes of the first
+ component Region into the corresponding current Frame axes. Also returned
+ is a list of the axes within the current Frame which correspnd to the
+ axes of the first component Region. */
+ nmap1 = NULL;
+ axout1 = NULL;
+ axin = astMalloc( sizeof( int )*(size_t)nax1 );
+ if( astOK ) {
+ for( i = 0; i < nax1; i++ ) axin[ i ] = i;
+ axout1 = astMapSplit( bcmap, nax1, axin, &nmap1 );
+ axin = astFree( axin );
+ }
+
+/* Do the same for the second component. */
+ nmap2 = NULL;
+ axout2 = NULL;
+ axin = astMalloc( sizeof( int )*(size_t)nax2 );
+ if( astOK ) {
+ for( i = 0; i < nax2; i++ ) axin[ i ] = i + nax1;
+ axout2 = astMapSplit( bcmap, nax2, axin, &nmap2 );
+ axin = astFree( axin );
+ }
+
+/* Assume for the moment that the component Regions cannot be simplified.
+ In this case we will use a clone of the supplied Prism. */
+ new = astClone( this_mapping );
+
+/* Determine the number of outputs from these Mappings. */
+ if( nmap1 ){
+ naxout1 = astGetNout( nmap1 );
+ } else {
+ naxout1 = 0;
+ }
+ if( nmap2 ){
+ naxout2 = astGetNout( nmap2 );
+ } else {
+ naxout2 = 0;
+ }
+
+/* Determine the number of axes in the current Frame of the Prism. */
+ naxt = astGetNout( bcmap );
+
+/* If the second component does not contribute any axes to the total
+ Prism, we can ignore it. */
+ if( naxout1 == naxt && naxout2 == 0 ) {
+ newfrm1 = astPickAxes( cfrm, naxout1, axout1, NULL );
+ newreg1 = astMapRegion( reg1, nmap1, newfrm1 );
+ (void) astAnnul( new );
+ new = astSimplify( newreg1 );
+ if( neg ) astNegate( new );
+ perm = astMalloc( sizeof( int )*(size_t) ( naxout1 ) );
+ if( astOK ) {
+ for( i = 0; i < naxout1; i++ ) perm[ i ] = axout1[ i ];
+ astPermAxes( new, perm );
+ perm = astFree( perm );
+ }
+ newfrm1 = astAnnul( newfrm1 );
+ newreg1 = astAnnul( newreg1 );
+
+/* If the first component does not contribute any axes to the total
+ Prism, we can ignore it. */
+ } else if( naxout1 == 0 && naxout2 == naxt ) {
+ newfrm2 = astPickAxes( cfrm, naxout2, axout2, NULL );
+ newreg2 = astMapRegion( reg2, nmap2, newfrm2 );
+ (void) astAnnul( new );
+ new = astSimplify( newreg2 );
+ if( neg ) astNegate( new );
+ perm = astMalloc( sizeof( int )*(size_t) ( naxout2 ) );
+ if( astOK ) {
+ for( i = 0; i < naxout2; i++ ) perm[ i ] = axout2[ i ];
+ astPermAxes( new, perm );
+ perm = astFree( perm );
+ }
+ newfrm2 = astAnnul( newfrm2 );
+ newreg2 = astAnnul( newreg2 );
+
+/* If both component Regions correspond to a distinct subspace within the
+ current Frame, then we can try to express each component Region within
+ the current Frame. */
+ } else if( nmap1 && nmap2 ) {
+
+/* Create a Frame representing the subspace of the current Frame which
+ corresponds to the axes of the first component Region. */
+ newfrm1 = astPickAxes( cfrm, naxout1, axout1, NULL );
+
+/* Remap the first component Region so that it represents an area in this
+ subspace. */
+ newreg1 = astMapRegion( reg1, nmap1, newfrm1 );
+
+/* Attempt to simplify the remapped Region. */
+ snewreg1 = astSimplify( newreg1 );
+
+/* Do the same for the second component Region. */
+ naxout2 = astGetNout( nmap2 );
+ newfrm2 = astPickAxes( cfrm, naxout2, axout2, NULL );
+ newreg2 = astMapRegion( reg2, nmap2, newfrm2 );
+ snewreg2 = astSimplify( newreg2 );
+
+/* If either component Region was simplified, create a new Prism from the
+ simplified Regions. */
+ if( snewreg1 != newreg1 || snewreg2 != newreg2 ) {
+ (void) astAnnul( new );
+ new = (AstRegion *) astPrism( snewreg1, snewreg2, "", status );
+
+/* Ensure the new Prism has the same Negated attribute as the original. */
+ if( neg ) astNegate( new );
+
+/* Ensure that the new Prism has the same axis order as the original
+ current Frame. */
+ perm = astMalloc( sizeof( int )*(size_t) ( naxout1 + naxout2 ) );
+ if( astOK ) {
+ for( i = 0; i < naxout1; i++ ) perm[ i ] = axout1[ i ];
+ for( ; i < naxout1 + naxout2; i++ ) perm[ i ] = axout2[ i - naxout1 ];
+ astPermAxes( new, perm );
+ perm = astFree( perm );
+ }
+ }
+
+/* Free resources. */
+ newfrm1 = astAnnul( newfrm1 );
+ newfrm2 = astAnnul( newfrm2 );
+ newreg1 = astAnnul( newreg1 );
+ newreg2 = astAnnul( newreg2 );
+ snewreg1 = astAnnul( snewreg1 );
+ snewreg2 = astAnnul( snewreg2 );
+ }
+
+/* Free resources. */
+ if( axout1 ) axout1 = astFree( axout1 );
+ if( axout2 ) axout2 = astFree( axout2 );
+ if( nmap1 ) nmap1 = astAnnul( nmap1 );
+ if( nmap2 ) nmap2 = astAnnul( nmap2 );
+ }
+
+/* If we have created a new Region, ensure any user-supplied uncertainty
+ that has been stored explicitly with the supplied Prism is passed on
+ to the new Region. */
+ if( new ) {
+ if( astTestUnc( reg ) ) {
+ unc = astGetUnc( reg, 0 );
+ astSetUnc( new, unc );
+ }
+
+/* Now invoke the parent Simplify method inherited from the Region class.
+ This will simplify the encapsulated FrameSet and uncertainty Region. */
+ result = (*parent_simplify)( (AstMapping *) new, status );
+ new = astAnnul( new );
+ }
+
+/* Free resources. */
+ reg1 = astAnnul( reg1 );
+ reg2 = astAnnul( reg2 );
+ cfrm = astAnnul( cfrm );
+ bcmap = astAnnul( bcmap );
+
+/* If any simplification could be performed, copy Region attributes from
+ the supplied Region to the returned Region, and return a pointer to it. */
+ if( result != this_mapping ) astRegOverlay( result, (AstRegion *) this_mapping, 0 );
+
+/* If an error occurred, annul the returned Mapping. */
+ if ( !astOK ) result = astAnnul( result );
+
+/* Return the result. */
+ return result;
+}
+
+static AstPointSet *Transform( AstMapping *this_mapping, AstPointSet *in,
+ int forward, AstPointSet *out, int *status ) {
+/*
+* Name:
+* Transform
+
+* Purpose:
+* Apply a Prism to transform a set of points.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* #include "prism.h"
+* AstPointSet *Transform( AstMapping *this, AstPointSet *in,
+* int forward, AstPointSet *out, int *status )
+
+* Class Membership:
+* Prism member function (over-rides the astTransform method inherited
+* from the Region class).
+
+* Description:
+* This function takes a Prism and a set of points encapsulated in a
+* PointSet and transforms the points so as to apply the required Region.
+* This implies applying each of the Prism's component Regions in turn,
+* either in series or in parallel.
+
+* Parameters:
+* this
+* Pointer to the Prism.
+* in
+* Pointer to the PointSet associated with the input coordinate values.
+* forward
+* A non-zero value indicates that the forward coordinate transformation
+* should be applied, while a zero value requests the inverse
+* transformation.
+* out
+* Pointer to a PointSet which will hold the transformed (output)
+* coordinate values. A NULL value may also be given, in which case a
+* new PointSet will be created by this function.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* Pointer to the output (possibly new) PointSet.
+
+* Notes:
+* - A null pointer will be returned if this function is invoked with the
+* global error status set, or if it should fail for any reason.
+* - The number of coordinate values per point in the input PointSet must
+* match the number of coordinates for the Prism being applied.
+* - If an output PointSet is supplied, it must have space for sufficient
+* number of points and coordinate values per point to accommodate the
+* result. Any excess space will be ignored.
+*/
+
+/* Local Variables: */
+ AstCmpMap *map; /* CmpMap containing component Regions */
+ AstPointSet *psb; /* Pointer to base Frame PointSet */
+ AstPointSet *pset_tmp; /* Pointer to PointSet holding base Frame positions*/
+ AstPointSet *result; /* Pointer to output PointSet */
+ AstPrism *this; /* Pointer to the Prism structure */
+ AstRegion *reg1; /* Pointer to first component Region */
+ AstRegion *reg2; /* Pointer to second component Region */
+ double **ptr_out; /* Pointer to output coordinate data */
+ double **ptrb; /* Pointer to base Frame axis values */
+ int coord; /* Zero-based index for coordinates */
+ int good; /* Is the point inside the Prism? */
+ int ncoord_out; /* No. of coordinates per output point */
+ int ncoord_tmp; /* No. of coordinates per base Frame point */
+ int neg; /* Has Prism been negated? */
+ int npoint; /* No. of points */
+ int point; /* Loop counter for points */
+
+/* Initialise. */
+ result = NULL;
+
+/* Check the global error status. */
+ if ( !astOK ) return result;
+
+/* Get a Pointer to the Prism structure */
+ this = (AstPrism *) this_mapping;
+
+/* Get the component Regions, and the Negated value for the Prism. */
+ GetRegions( this, &reg1, &reg2, &neg, status );
+
+/* Apply the parent mapping using the stored pointer to the Transform member
+ function inherited from the parent Region class. This function validates
+ all arguments and generates an output PointSet if necessary, containing
+ a copy of the input PointSet. */
+ result = (*parent_transform)( this_mapping, in, forward, out, status );
+
+/* We will now extend the parent astTransform method by performing the
+ calculations needed to generate the output coordinate values. */
+
+/* First use the encapsulated FrameSet in the parent Region structure to
+ transform the supplied positions from the current Frame in the
+ encapsulated FrameSet (the Frame represented by the Prism), to the
+ base Frame (the Frame in which the component Regions are defined). Note,
+ the returned pointer may be a clone of the "in" pointer, and so we
+ must be carefull not to modify the contents of the returned PointSet. */
+ pset_tmp = astRegTransform( this, in, 0, NULL, NULL );
+
+/* Form a parallel CmpMap from the two component Regions. */
+ map = astCmpMap( reg1, reg2, 0, "", status );
+
+/* Apply the Mapping to the PointSet containing positions in the base Frame
+ of the parent Region structure (which is the same as the combination of
+ the current Frames of the component Regions). */
+ psb = astTransform( map, pset_tmp, 1, NULL );
+
+/* Annul the Mapping pointer. */
+ map = astAnnul( map );
+
+/* Determine the numbers of points and coordinates per point for these base
+ Frame PointSets and obtain pointers for accessing the base Frame and output
+ coordinate values. */
+ npoint = astGetNpoint( pset_tmp );
+ ncoord_tmp = astGetNcoord( pset_tmp );
+ ptrb = astGetPoints( psb );
+ ncoord_out = astGetNcoord( result );
+ ptr_out = astGetPoints( result );
+
+/* Perform coordinate arithmetic. */
+/* ------------------------------ */
+ if ( astOK ) {
+ for ( point = 0; point < npoint; point++ ) {
+ good = 1;
+
+ for ( coord = 0; coord < ncoord_tmp; coord++ ) {
+ if( ptrb[ coord ][ point ] == AST__BAD ){
+ good = 0;
+ break;
+ }
+ }
+
+ if( good == neg ) {
+ for ( coord = 0; coord < ncoord_out; coord++ ) {
+ ptr_out[ coord ][ point ] = AST__BAD;
+ }
+ }
+ }
+ }
+
+/* Free resources. */
+ reg1 = astAnnul( reg1 );
+ reg2 = astAnnul( reg2 );
+ psb = astAnnul( psb );
+ pset_tmp = astAnnul( pset_tmp );
+
+/* If an error occurred, clean up by deleting the output PointSet (if
+ allocated by this function) and setting a NULL result pointer. */
+ if ( !astOK ) {
+ if ( !out ) result = astDelete( result );
+ result = NULL;
+ }
+
+/* Return a pointer to the output PointSet. */
+ return result;
+}
+
+/* Copy constructor. */
+/* ----------------- */
+static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
+/*
+* Name:
+* Copy
+
+* Purpose:
+* Copy constructor for Prism objects.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* void Copy( const AstObject *objin, AstObject *objout, int *status )
+
+* Description:
+* This function implements the copy constructor for Prism objects.
+
+* Parameters:
+* objin
+* Pointer to the object to be copied.
+* objout
+* Pointer to the object being constructed.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* void
+
+* Notes:
+* - This constructor makes a deep copy, including a copy of the component
+* Regions within the Prism.
+*/
+
+/* Local Variables: */
+ AstPrism *in; /* Pointer to input Prism */
+ AstPrism *out; /* Pointer to output Prism */
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Obtain pointers to the input and output Prisms. */
+ in = (AstPrism *) objin;
+ out = (AstPrism *) objout;
+
+/* For safety, start by clearing any references to the input component
+ Regions from the output Prism. */
+ out->region1 = NULL;
+ out->region2 = NULL;
+
+/* Make copies of these Regions and store pointers to them in the output
+ Prism structure. */
+ out->region1 = astCopy( in->region1 );
+ out->region2 = astCopy( in->region2 );
+}
+
+/* Destructor. */
+/* ----------- */
+static void Delete( AstObject *obj, int *status ) {
+/*
+* Name:
+* Delete
+
+* Purpose:
+* Destructor for Prism objects.
+
+* Type:
+* Private function.
+
+* Synopsis:
+* void Delete( AstObject *obj, int *status )
+
+* Description:
+* This function implements the destructor for Prism objects.
+
+* Parameters:
+* obj
+* Pointer to the object to be deleted.
+* status
+* Pointer to the inherited status variable.
+
+* Returned Value:
+* void
+
+* Notes:
+* This function attempts to execute even if the global error status is
+* set.
+*/
+
+/* Local Variables: */
+ AstPrism *this; /* Pointer to Prism */
+
+/* Obtain a pointer to the Prism structure. */
+ this = (AstPrism *) obj;
+
+/* Annul the pointers to the component Regions. */
+ this->region1 = astAnnul( this->region1 );
+ this->region2 = astAnnul( this->region2 );
+}
+
+/* Dump function. */
+/* -------------- */
+static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
+/*
+* Name:
+* Dump
+
+* Purpose:
+* Dump function for Prism 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 Prism class to an output Channel.
+
+* Parameters:
+* this
+* Pointer to the Prism 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: */
+ AstPrism *this; /* Pointer to the Prism structure */
+
+/* Check the global error status. */
+ if ( !astOK ) return;
+
+/* Obtain a pointer to the Prism structure. */
+ this = (AstPrism *) this_object;
+
+/* Write out values representing the instance variables for the Prism
+ 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. */
+
+/* First Region. */
+/* -------------- */
+ astWriteObject( channel, "RegionA", 1, 1, this->region1,
+ "First component Region" );
+
+/* Second Region. */
+/* --------------- */
+ astWriteObject( channel, "RegionB", 1, 1, this->region2,
+ "Second component Region" );
+}
+
+/* Standard class functions. */
+/* ========================= */
+/* Implement the astIsAPrism and astCheckPrism functions using the
+ macros defined for this purpose in the "object.h" header file. */
+astMAKE_ISA(Prism,Region)
+astMAKE_CHECK(Prism)
+
+AstPrism *astPrism_( void *region1_void, void *region2_void,
+ const char *options, int *status, ...) {
+/*
+*+
+* Name:
+* astPrism
+
+* Purpose:
+* Create a Prism.
+
+* Type:
+* Protected function.
+
+* Synopsis:
+* #include "prism.h"
+* AstPrism *astPrism( AstRegion *region1, AstRegion *region2,
+* const char *options, ..., int *status )
+
+* Class Membership:
+* Prism constructor.
+
+* Description:
+* This function creates a new Prism and optionally initialises its
+* attributes.
+
+* Parameters:
+* region1
+* Pointer to the Region to be extruded.
+* region2
+* Pointer to the Region defining the extent of the extrusion.
+* options
+* Pointer to a null terminated string containing an optional
+* comma-separated list of attribute assignments to be used for
+* initialising the new Prism. The syntax used is the same as for the
+* astSet method and may include "printf" format specifiers identified
+* by "%" symbols in the normal way.
+* status
+* Pointer to the inherited status variable.
+* ...
+* If the "options" string contains "%" format specifiers, then an
+* optional list of arguments may follow it in order to supply values to
+* be substituted for these specifiers. The rules for supplying these
+* are identical to those for the astSet method (and for the C "printf"
+* function).
+
+* Returned Value:
+* A pointer to the new Prism.
+
+* 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.
+*-
+
+* Implementation Notes:
+* - This function implements the basic Prism constructor which is
+* available via the protected interface to the Prism class. A
+* public interface is provided by the astPrismId_ function.
+* - Because this function has a variable argument list, it is
+* invoked by a macro that evaluates to a function pointer (not a
+* function invocation) and no checking or casting of arguments is
+* performed before the function is invoked. Because of this, the
+* "region1" and "region2" parameters are of type (void *) and are
+* converted and validated within the function itself.
+*/
+
+/* Local Variables: */
+ astDECLARE_GLOBALS /* Pointer to thread-specific global data */
+ AstPrism *new; /* Pointer to new Prism */
+ AstRegion *region1; /* Pointer to first Region structure */
+ AstRegion *region2; /* Pointer to second Region structure */
+ va_list args; /* Variable argument list */
+
+/* Initialise. */
+ new = NULL;
+
+/* Get a pointer to the thread specific global data structure. */
+ astGET_GLOBALS(NULL);
+
+/* Check the global status. */
+ if ( !astOK ) return new;
+
+/* Obtain and validate pointers to the Region structures provided. */
+ region1 = astCheckRegion( region1_void );
+ region2 = astCheckRegion( region2_void );
+ if ( astOK ) {
+
+/* Initialise the Prism, allocating memory and initialising the
+ virtual function table as well if necessary. */
+ new = astInitPrism( NULL, sizeof( AstPrism ), !class_init,
+ &class_vtab, "Prism", region1, region2 );
+
+/* 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 Prism'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 Prism. */
+ return new;
+}
+
+AstPrism *astPrismId_( void *region1_void, void *region2_void,
+ const char *options, ... ) {
+/*
+*++
+* Name:
+c astPrism
+f AST_PRISM
+
+* Purpose:
+* Create a Prism.
+
+* Type:
+* Public function.
+
+* Synopsis:
+c #include "prism.h"
+c AstPrism *astPrism( AstRegion *region1, AstRegion *region2,
+c const char *options, ... )
+f RESULT = AST_PRISM( REGION1, REGION2, OPTIONS, STATUS )
+
+* Class Membership:
+* Prism constructor.
+
+* Description:
+* This function creates a new Prism and optionally initialises
+* its attributes.
+*
+* A Prism is a Region which represents an extrusion of an existing Region
+* into one or more orthogonal dimensions (specified by another Region).
+* If the Region to be extruded has N axes, and the Region defining the
+* extrusion has M axes, then the resulting Prism will have (M+N) axes.
+* A point is inside the Prism if the first N axis values correspond to
+* a point inside the Region being extruded, and the remaining M axis
+* values correspond to a point inside the Region defining the extrusion.
+*
+* As an example, a cylinder can be represented by extruding an existing
+* Circle, using an Interval to define the extrusion. Ih this case, the
+* Interval would have a single axis and would specify the upper and
+* lower limits of the cylinder along its length.
+
+* Parameters:
+c region1
+f REGION1 = INTEGER (Given)
+* Pointer to the Region to be extruded.
+c region2
+f REGION2 = INTEGER (Given)
+* Pointer to the Region defining the extent of the extrusion.
+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 Prism. 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 Prism. 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 astPrism()
+f AST_PRISM = INTEGER
+* A pointer to the new Prism.
+
+* Notes:
+* - Deep copies are taken of the supplied Regions. This means that
+* any subsequent changes made to the component Regions using the
+* supplied pointers will have no effect on the Prism.
+* - A null Object pointer (AST__NULL) will be returned if this
+c function is invoked with the AST error status set, or if it
+f function is invoked with STATUS set to an error value, or if it
+* should fail for any reason.
+*--
+
+* Implementation Notes:
+* - This function implements the external (public) interface to
+* the astPrism constructor function. It returns an ID value
+* (instead of a true C pointer) to external users, and must be
+* provided because astPrism_ has a variable argument list which
+* cannot be encapsulated in a macro (where this conversion would
+* otherwise occur).
+* - Because no checking or casting of arguments is performed
+* before the function is invoked, the "region1" and "region2" parameters
+* are of type (void *) and are converted from an ID value to a
+* pointer and validated within the function itself.
+* - The variable argument list also prevents this function from
+* invoking astPrism_ directly, so it must be a re-implementation
+* of it in all respects, except for the conversions between IDs
+* and pointers on input/output of Objects.
+*/
+
+/* Local Variables: */
+ astDECLARE_GLOBALS /* Pointer to thread-specific global data */
+ AstPrism *new; /* Pointer to new Prism */
+ AstRegion *region1; /* Pointer to first Region structure */
+ AstRegion *region2; /* Pointer to second Region structure */
+ int *status; /* Pointer to inherited status value */
+ va_list args; /* Variable argument list */
+
+/* Get a pointer to the thread specific global data structure. */
+ astGET_GLOBALS(NULL);
+
+/* Initialise. */
+ new = NULL;
+
+/* Get a pointer to the inherited status value. */
+ status = astGetStatusPtr;
+
+/* Check the global status. */
+ if ( !astOK ) return new;
+
+/* Obtain the Region pointers from the ID's supplied and validate the
+ pointers to ensure they identify valid Regions. */
+ region1 = astVerifyRegion( astMakePointer( region1_void ) );
+ region2 = astVerifyRegion( astMakePointer( region2_void ) );
+ if ( astOK ) {
+
+/* Initialise the Prism, allocating memory and initialising the
+ virtual function table as well if necessary. */
+ new = astInitPrism( NULL, sizeof( AstPrism ), !class_init,
+ &class_vtab, "Prism", region1, region2 );
+
+/* 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 Prism'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 Prism. */
+ return astMakeId( new );
+}
+
+AstPrism *astInitPrism_( void *mem, size_t size, int init, AstPrismVtab *vtab,
+ const char *name, AstRegion *region1,
+ AstRegion *region2, int *status ) {
+/*
+*+
+* Name:
+* astInitPrism
+
+* Purpose:
+* Initialise a Prism.
+
+* Type:
+* Protected function.
+
+* Synopsis:
+* #include "prism.h"
+* AstPrism *astInitPrism_( void *mem, size_t size, int init,
+* AstPrismVtab *vtab, const char *name,
+* AstRegion *region1, AstRegion *region2 )
+
+* Class Membership:
+* Prism initialiser.
+
+* Description:
+* This function is provided for use by class implementations to initialise
+* a new Prism object. It allocates memory (if necessary) to
+* accommodate the Prism plus any additional data associated with the
+* derived class. It then initialises a Prism structure at the start
+* of this memory. If the "init" flag is set, it also initialises the
+* contents of a virtual function table for a Prism at the start of
+* the memory passed via the "vtab" parameter.
+
+* Parameters:
+* mem
+* A pointer to the memory in which the Prism is to be initialised.
+* This must be of sufficient size to accommodate the Prism data
+* (sizeof(Prism)) 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 Prism (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
+* Prism structure, so a valid value must be supplied even if not
+* required for allocating memory.
+* init
+* A logical flag indicating if the Prism'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 Prism.
+* name
+* Pointer to a constant null-terminated character string which contains
+* the name of the class to which the new object belongs (it is this
+* pointer value that will subsequently be returned by the Object
+* astClass function).
+* region1
+* Pointer to the first Region.
+* region2
+* Pointer to the second Region.
+
+* Returned Value:
+* A pointer to the new Prism.
+
+* 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: */
+ AstPrism *new; /* Pointer to new Prism */
+ AstFrame *frm1; /* Frame encapsulated by 1st Region */
+ AstFrame *frm2; /* Frame encapsulated by 2nd Region */
+ AstFrame *frm; /* CmpFrame formed from frm1 and frm2 */
+ AstMapping *map; /* Mapping between two supplied Regions */
+ AstRegion *reg1; /* Copy of first supplied Region */
+ AstRegion *reg2; /* Copy of second supplied Region */
+
+/* Check the global status. */
+ if ( !astOK ) return NULL;
+
+/* If necessary, initialise the virtual function table. */
+ if ( init ) astInitPrismVtab( vtab, name );
+
+/* Initialise. */
+ new = NULL;
+ reg2 = NULL;
+
+/* Take a copy of the two supplied Regions. */
+ reg1 = astCopy( region1 );
+ reg2 = astCopy( region2 );
+
+/* Form a CmpFrame representing the combined Frame of these two Regions. */
+ frm1 = astRegFrame( reg1 );
+ frm2 = astRegFrame( reg2 );
+ frm = (AstFrame *) astCmpFrame( frm1, frm2, "", status );
+
+/* Initialise a Region structure (the parent class) as the first component
+ within the Prism structure, allocating memory if necessary. A NULL
+ PointSet is suppled as the two component Regions will perform the function
+ of defining the Region shape. The base Frame of the FrameSet in the
+ parent Region structure will be the CmpFrame formed from the two component
+ Regions. */
+ if ( astOK ) {
+ new = (AstPrism *) astInitRegion( mem, size, 0, (AstRegionVtab *) vtab,
+ name, frm, NULL, NULL );
+
+/* Initialise the Prism data. */
+/* --------------------------- */
+/* Store pointers to the component Regions. */
+ new->region1 = reg1;
+ new->region2 = reg2;
+
+/* If the base->current Mapping in the FrameSet within a component Region
+ is a UnitMap, then the FrameSet does not need to be included in the
+ Dump of the new Prism. Set the RegionFS attribute of the component
+ Region to zero to flag this. */
+ map = astGetMapping( reg1->frameset, AST__BASE, AST__CURRENT );
+ if( astIsAUnitMap( map ) ) astSetRegionFS( reg1, 0 );
+ map = astAnnul( map );
+
+ map = astGetMapping( reg2->frameset, AST__BASE, AST__CURRENT );
+ if( astIsAUnitMap( map ) ) astSetRegionFS( reg2, 0 );
+ map = astAnnul( map );
+
+/* If an error occurred, clean up by annulling the Region pointers and
+ deleting the new object. */
+ if ( !astOK ) {
+ new->region1 = astAnnul( new->region1 );
+ new->region2 = astAnnul( new->region2 );
+ new = astDelete( new );
+ }
+ }
+
+/* Free resources */
+ frm = astAnnul( frm );
+ frm1 = astAnnul( frm1 );
+ frm2 = astAnnul( frm2 );
+
+/* Return a pointer to the new object. */
+ return new;
+}
+
+AstPrism *astLoadPrism_( void *mem, size_t size, AstPrismVtab *vtab,
+ const char *name, AstChannel *channel, int *status ) {
+/*
+*+
+* Name:
+* astLoadPrism
+
+* Purpose:
+* Load a Prism.
+
+* Type:
+* Protected function.
+
+* Synopsis:
+* #include "prism.h"
+* AstPrism *astLoadPrism( void *mem, size_t size, AstPrismVtab *vtab,
+* const char *name, AstChannel *channel )
+
+* Class Membership:
+* Prism loader.
+
+* Description:
+* This function is provided to load a new Prism 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
+* Prism structure in this memory, using data read from the input
+* Channel.
+*
+* If the "init" flag is set, it also initialises the contents of a
+* virtual function table for a Prism at the start of the memory
+* passed via the "vtab" parameter.
+
+
+* Parameters:
+* mem
+* A pointer to the memory into which the Prism is to be
+* loaded. This must be of sufficient size to accommodate the
+* Prism data (sizeof(Prism)) 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 Prism (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 Prism 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(AstPrism) is used instead.
+* vtab
+* Pointer to the start of the virtual function table to be
+* associated with the new Prism. If this is NULL, a pointer to
+* the (static) virtual function table for the Prism 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 "Prism" is used instead.
+
+* Returned Value:
+* A pointer to the new Prism.
+
+* 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 */
+ AstFrame *cfrm; /* Frame containing required axes */
+ AstFrame *f1; /* Base Frame in parent Region */
+ AstPrism *new; /* Pointer to the new Prism */
+ AstRegion *creg; /* Pointer to component Region */
+ int *axes; /* Pointer to array of axis indices */
+ int i; /* Loop count */
+ int nax1; /* No.of axes in 1st component Frame */
+ int nax2; /* No.of axes in 2nd component Frame */
+
+/* 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 Prism. In this case the
+ Prism belongs to this class, so supply appropriate values to be
+ passed to the parent class loader (and its parent, etc.). */
+ if ( !vtab ) {
+ size = sizeof( AstPrism );
+ vtab = &class_vtab;
+ name = "Prism";
+
+/* If required, initialise the virtual function table for this class. */
+ if ( !class_init ) {
+ astInitPrismVtab( 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 Prism. */
+ new = astLoadRegion( mem, size, (AstRegionVtab *) vtab, name,
+ channel );
+
+ if ( astOK ) {
+
+/* Read input data. */
+/* ================ */
+/* Request the input Channel to read all the input data appropriate to
+ this class into the internal "values list". */
+ astReadClassData( channel, "Prism" );
+
+/* 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. */
+
+/* First Region. */
+/* -------------- */
+ new->region1 = astReadObject( channel, "regiona", NULL );
+
+/* Second Region. */
+/* --------------- */
+ new->region2 = astReadObject( channel, "regionb", NULL );
+
+/* Either component Region may currently contain a dummy FrameSet rather than
+ the correct FrameSet (see the Dump function for this class). In this case,
+ the correct FrameSet will have copies of selected axes from the base Frame
+ of the new Prism as both its current and base Frames, and these are
+ connected by a UnitMap (this is equivalent to a FrameSet containing a
+ single Frame). However if the new Prism being loaded has itself got a dummy
+ FrameSet, then we do not do this since we do not yet know what the correct
+ FrameSet is. In this case we wait until the parent Region invokes the
+ astSetRegFS method on the new Prism. */
+ if( !astRegDummyFS( new ) ) {
+ f1 = astGetFrame( ((AstRegion *) new)->frameset, AST__BASE );
+
+ creg = new->region1;
+ nax1 = astGetNaxes( creg );
+ if( astRegDummyFS( creg ) ) {
+ axes = astMalloc( sizeof( int )*(size_t) nax1 );
+ if( astOK ) for( i = 0; i < nax1; i++ ) axes[ i ] = i;
+ cfrm = astPickAxes( f1, nax1, axes, NULL );
+ astSetRegFS( creg, cfrm );
+ axes = astFree( axes );
+ cfrm = astAnnul( cfrm );
+ }
+
+ creg = new->region2;
+ if( astRegDummyFS( creg ) ) {
+ nax2 = astGetNaxes( creg );
+ axes = astMalloc( sizeof( int )*(size_t) nax2 );
+ if( astOK ) for( i = 0; i < nax2; i++ ) axes[ i ] = nax1 + i;
+ cfrm = astPickAxes( f1, nax2, axes, NULL );
+ astSetRegFS( creg, cfrm );
+ axes = astFree( axes );
+ cfrm = astAnnul( cfrm );
+ }
+
+ f1 = astAnnul( f1 );
+ }
+
+/* If an error occurred, clean up by deleting the new Prism. */
+ if ( !astOK ) new = astDelete( new );
+ }
+
+/* Return the new Prism 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. */
+
+/* None. */
+
+
+