diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2018-09-21 17:02:41 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2018-09-21 17:02:41 (GMT) |
commit | bd7d67f66c53df36bb50e3423bfc91eae8618201 (patch) | |
tree | 343b06f7a9f2decdfa8d3e4aae885be3e909aa14 /ast/prism.c | |
parent | f2f490ba0f98917b590fd7e538b9514e4119e640 (diff) | |
download | blt-bd7d67f66c53df36bb50e3423bfc91eae8618201.zip blt-bd7d67f66c53df36bb50e3423bfc91eae8618201.tar.gz blt-bd7d67f66c53df36bb50e3423bfc91eae8618201.tar.bz2 |
update ast
Diffstat (limited to 'ast/prism.c')
-rw-r--r-- | ast/prism.c | 4448 |
1 files changed, 0 insertions, 4448 deletions
diff --git a/ast/prism.c b/ast/prism.c deleted file mode 100644 index f4e26c9..0000000 --- a/ast/prism.c +++ /dev/null @@ -1,4448 +0,0 @@ -/* -*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, ®1, ®2, &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, ®1, ®2, &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, ®1, ®2, &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 = astAnnul( *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, ®1, ®2, &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, ®1, ®2, &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. */ - - - |