diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 15:55:01 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 15:55:01 (GMT) |
commit | 9646e8d50bc1481de77459d59738826f9c256ad6 (patch) | |
tree | e47684c08ae346d96e3c6ea8780f3886fe74e6f6 /ast/wcsmap.c | |
parent | 37e757832a7f2c690cea41df5bf9cfa9ee18f67f (diff) | |
download | blt-9646e8d50bc1481de77459d59738826f9c256ad6.zip blt-9646e8d50bc1481de77459d59738826f9c256ad6.tar.gz blt-9646e8d50bc1481de77459d59738826f9c256ad6.tar.bz2 |
upgrade ast 8.7.1
Diffstat (limited to 'ast/wcsmap.c')
-rw-r--r-- | ast/wcsmap.c | 6094 |
1 files changed, 0 insertions, 6094 deletions
diff --git a/ast/wcsmap.c b/ast/wcsmap.c deleted file mode 100644 index 6ba3811..0000000 --- a/ast/wcsmap.c +++ /dev/null @@ -1,6094 +0,0 @@ -/* -*class++ -* Name: -* WcsMap - -* Purpose: -* Implement a FITS-WCS sky projection. - -* Constructor Function: -c astWcsMap -f AST_WCSMAP - -* Description: -* This class is used to represent sky coordinate projections as -* described in the FITS world coordinate system (FITS-WCS) paper II -* "Representations of Celestial Coordinates in FITS" by M. Calabretta -* and E.W. Griesen. This paper defines a set of functions, or sky -* projections, which transform longitude-latitude pairs representing -* spherical celestial coordinates into corresponding pairs of Cartesian -* coordinates (and vice versa). -* -* A WcsMap is a specialised form of Mapping which implements these -* sky projections and applies them to a specified pair of coordinates. -* All the projections in the FITS-WCS paper are supported, plus the now -* deprecated "TAN with polynomial correction terms" projection which -* is refered to here by the code "TPN". Using the FITS-WCS terminology, -* the transformation is between "native spherical" and "projection -* plane" coordinates (also called "intermediate world coordinates". -* These coordinates may, optionally, be embedded in a space with more -* than two dimensions, the remaining coordinates being copied unchanged. -* Note, however, that for consistency with other AST facilities, a -* WcsMap handles coordinates that represent angles in radians (rather -* than the degrees used by FITS-WCS). -* -* The type of FITS-WCS projection to be used and the coordinates -* (axes) to which it applies are specified when a WcsMap is first -* created. The projection type may subsequently be determined -* using the WcsType attribute and the coordinates on which it acts -* may be determined using the WcsAxis(lonlat) attribute. -* -* Each WcsMap also allows up to 100 "projection parameters" to be -* associated with each axis. These specify the precise form of the -* projection, and are accessed using PVi_m attribute, where "i" is -* the integer axis index (starting at 1), and m is an integer -* "parameter index" in the range 0 to 99. The number of projection -* parameters required by each projection, and their meanings, are -* dependent upon the projection type (most projections either do not -* use any projection parameters, or use parameters 1 and 2 associated -* with the latitude axis). Before creating a WcsMap you should consult -* the FITS-WCS paper for details of which projection parameters are -* required, and which have defaults. When creating the WcsMap, you must -* explicitly set values for all those required projection parameters -* which do not have defaults defined in this paper. - -* Inheritance: -* The WcsMap class inherits from the Mapping class. - -* Attributes: -* In addition to those attributes common to all Mappings, every -* WcsMap also has the following attributes: -* -* - NatLat: Native latitude of the reference point of a FITS-WCS projection -* - NatLon: Native longitude of the reference point of a FITS-WCS projection -* - PVi_m: FITS-WCS projection parameters -* - PVMax: Maximum number of FITS-WCS projection parameters -* - WcsAxis(lonlat): FITS-WCS projection axes -* - WcsType: FITS-WCS projection type - -* Functions: -c The WcsMap class does not define any new functions beyond those -f The WcsMap class does not define any new routines beyond those -* which are applicable to all Mappings. - -* Copyright: -* Copyright (C) 1997-2006 Council for the Central Laboratory of the -* Research Councils - -* Licence: -* This program is free software: you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation, either -* version 3 of the License, or (at your option) any later -* version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General -* License along with this program. If not, see -* <http://www.gnu.org/licenses/>. - -* Authors: -* DSB: D.S. Berry (Starlink) -* RFWS: R.F. Warren-Smith (Starlink) - -* History: -* 15-FEB-1996 (DSB): -* Original version. -* 23-MAR-1996 (DSB): -* Added support for PointSets with more than 2 axes. -* 14-NOV-1996 (DSB): -* Added I/O facilities, external interface, attributes, etc. -* 16-JAN-1997 (DSB): -* Allowed WCSBAD as a projection type in astWcsMap. -* 24-APR-1997 (RFWS): -* Tidied prologues. -* 26-SEP-1997 (DSB): -* o Long descriptions of projections changed to include a textual -* description as well as the three letter acronym. -* o Added protected function astPrjDesc. -* o String values now used instead of integers to represent -* "choice" attributes externally (eg WcsType). -* 8-APR-1998 (DSB): -* Modified MapMerge so that a WcsMap can merge with its own -* inverse when astSimplify is used. -* 20-APR-1998 (DSB): -* Modified MapMerge to avoid the possibility of returning an -* empty mappings list. -* 4-SEP-1998 (DSB): -* Changed MapMerge to allow WcsMaps to swap with PermMaps in -* order to bring mergable WcsMaps closer together. -* 5-MAY-1999 (DSB): -* More corrections to MapMerge: Cleared up errors in the use of the -* supplied invert flags, and corrected logic for deciding which -* neighbouring Mapping to swap with. -* 12-JUL-1999 (DSB): -* - Report an error if too many or two few projection parameters are -* supplied in a WcsMap. -* - Corrected MapMerge to prevent unset projection parameters -* being copied to any new WcsMaps. -* - Correct handling of invert flags in WcsPerm. -* 16-JUL-1999 (DSB): -* Fixed memory leak in MapMerge. -* 11-FEB-2000 (DSB): -* Added PVj_m attributes. Attributes ProjP(0) to ProjP(9) are now -* aliases for PV(axlat)_0 to PV(axlat)_9. Renamed GLS projection -* as SFL (GLS retained as alias for SFL). -* 10-AUG-2000 (DSB): -* MapMerge no longer simplifies a CAR projection. Previously they -* were replaced by a UnitMap, but this removed the cylic nature of -* the mapping (i.e. 2.PI == 0 ). -* 6-OCT-2000 (DSB): -* Ignore leading and trailing spaces in astWCsPrjType (some -* CTYPE FITS keywords have appeared with trailing white space). -* 26-SEP-2001 (DSB): -* Changed names of all functions and structure to avoid name clashes -* with wcslib. -* 10-OCT-2002 (DSB): -* Added astIsZenithal. -* 22-OCT-2002 (DSB): -* - GetPV now returns the FITS default value instead of AST__BAD -* if a defaultable latitude projection parameter has not been set. -* - A number of changes needed to support WcsLib v2.9. -* - Added AST__TPN projection. -* 8-JAN-2003 (DSB): -* Changed private InitVtab method to protected astInitWcsMapVtab -* method. -* 4-JUN-2003 (DSB): -* - Added attribute "NatLon". -* - Changed to allow a user-specified fiducial point to be stored -* in projection parameter PVi_1 and PVi_2 for the longitude axis. -* - Changed "PVj_m" to "PVi_m" for consistency with FITS-WCS paper II. -* 18-AUG-2003 (DSB): -* In function Map, assign zero longitude to output positions which -* are very close to a pole. -* 23-SEP-2003 (DSB): -* - Changed so that the NatLat and NatLon attributes refer to the -* fixed values for the projections defined in FITS-WCS paper II, rather -* than the user-defined values stored in projection parameter PVi_1 and -* PVi_2 for the longitude axis. -* 11-FEB-2004 (DSB): -* Corrected axis numbering when reporting missing keywords in -* Transform. -* 23-APR-2004 (DSB): -* Changes to simplification algorithm. -* 1-SEP-2004 (DSB): -* CopyPV rewritten to avoid assumption that the input and output -* WcsMaps have the same number of axes and that the lon/lat axes have -* the same indices. -* 7-DEC-2005 (DSB): -* Free memory allocated by calls to astReadString. -* 14-FEB-2006 (DSB): -* Override astGetObjSize. -* 15-FEB-2006 (DSB): -* Use dynamic rather than static memory for the parameter arrays in -* the AstPrjPrm structure.Override astGetObjSize. This is to -* reduce the in-memory size of a WcsMap. -* 10-MAY-2006 (DSB): -* Override astEqual. -* 10-AUG-2006 (DSB): -* Correct astLoadWcsMap to take acount of the different number of -* PVi_m values that can be associated with each axis. -* 4-JAN-2007 (DSB): -* Correct astLoadWcsMap to load the projection parameter with -* highest index correctly. -* 23-FEB-2007 (DSB): -* Added HPX projection. -* 1-MAR-2011 (DSB): -* In function Map, do not allow valid longitude range to include both -* the high limit and the low limt (since they are both the same point on -* the sky). -* 7-MAR-2011 (DSB): -* In function Map, only do the longitude check if the projection -* is not cyclic. -* 24-MAY-2011 (DSB): -* Added protected FITSProj and TPNTan attributes (they should be -* removed when the PolyMap class has an iterative inverse). -* 6-MAR-2014 (DSB): -* Revert the change made on 18-AUG-2003 since setting the -* longitude arbitrarily to zero for points close to the pole -* causes significant round trip errors when doing pixel->sky->pixel -* transformation for points very close to the pole, if the pixel -* size is very small. The longitude at the pole is indeterminate, -* but whatever random numerical value is returned by atan2 is -* no less useful (and no more useful) than a fixed value of zero. -* 12-JUN-2014 (DSB): -* Added XPH projection. -* 30-DEC-2017 (DSB): -* Improve merging of WcsMaps and PermMaps. -*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 WcsMap - -/* Macros which return the maximum and minimum of two values. */ -#define MAX(aa,bb) ((aa)>(bb)?(aa):(bb)) -#define MIN(aa,bb) ((aa)<(bb)?(aa):(bb)) - -/* Macros to check for equality of floating point values. We cannot - compare bad values directory because of the danger of floating point - exceptions, so bad values are dealt with explicitly. */ -#define EQUAL(aa,bb) (((aa)==AST__BAD)?(((bb)==AST__BAD)?1:0):(((bb)==AST__BAD)?0:(fabs((aa)-(bb))<=1.0E5*MAX((fabs(aa)+fabs(bb))*DBL_EPSILON,DBL_MIN)))) - -/* -* -* Name: -* MAKE_CLEAR - -* Purpose: -* Implement a method to clear a single value in a multi-valued attribute. - -* Type: -* Private macro. - -* Synopsis: -* #include "wcsmap.h" -* MAKE_CLEAR(attr,component,assign,nval) - -* Class Membership: -* Defined by the WcsMap class. - -* Description: -* This macro expands to an implementation of a private member function of -* the form: -* -* static void Clear<Attribute>( AstWcsMap *this, int axis ) -* -* and an external interface function of the form: -* -* void astClear<Attribute>_( AstWcsMap *this, int axis ) -* -* which implement a method for clearing a single value in a specified -* multi-valued attribute for an axis of a WcsMap. - -* Parameters: -* attr -* The name of the attribute to be cleared, as it appears in the function -* name (e.g. Label in "astClearLabelAt"). -* component -* The name of the class structure component that holds the attribute -* value. -* assign -* An expression that evaluates to the value to assign to the component -* to clear its value. The variable "axis" can be used to refer to -* the zero-based index of the attribute component being cleared. -* nval -* Specifies the number of values in the multi-valued attribute. The -* "axis" values supplied to the created function should be in the -* range zero to (nval - 1). - -* Notes: -* - To avoid problems with some compilers, you should not leave any white -* space around the macro arguments. -* -*/ - -/* Define the macro. */ -#define MAKE_CLEAR(attr,component,assign,nval) \ -\ -/* Private member function. */ \ -/* ------------------------ */ \ -static void Clear##attr( AstWcsMap *this, int axis, int *status ) { \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Validate the axis index. */ \ - if( axis < 0 || axis >= nval ){ \ - astError( AST__AXIIN, "%s(%s): Index (%d) is invalid for attribute " \ - #attr " - it should be in the range 1 to %d.", status, \ - "astClear" #attr, astGetClass( this ), \ - axis + 1, nval ); \ -\ -/* Assign the "clear" value. */ \ - } else { \ - this->component[ axis ] = (assign); \ - } \ -} \ -\ -/* External interface. */ \ -/* ------------------- */ \ -void astClear##attr##_( AstWcsMap *this, int axis, int *status ) { \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Invoke the required method via the virtual function table. */ \ - (**astMEMBER(this,WcsMap,Clear##attr))( this, axis, status ); \ -} - - -/* -* -* Name: -* MAKE_GET - -* Purpose: -* Implement a method to get a single value in a multi-valued attribute. - -* Type: -* Private macro. - -* Synopsis: -* #include "wcsmap.h" -* MAKE_GET(attr,type,bad_value,assign,nval) - -* Class Membership: -* Defined by the WcsMap class. - -* Description: -* This macro expands to an implementation of a private member function of -* the form: -* -* static <Type> Get<Attribute>( AstWcsMap *this, int axis ) -* -* and an external interface function of the form: -* -* <Type> astGet<Attribute>_( AstWcsMap *this, int axis ) -* -* which implement a method for getting a single value from a specified -* multi-valued attribute for an axis of a WcsMap. - -* Parameters: -* attr -* The name of the attribute whose value is to be obtained, as it -* appears in the function name (e.g. Label in "astGetLabel"). -* type -* The C type of the attribute. -* bad_value -* A constant value to return if the global error status is set, or if -* the function fails. -* assign -* An expression that evaluates to the value to be returned. This can -* use the string "axis" to represent the zero-based value index. -* nval -* Specifies the number of values in the multi-valued attribute. The -* "axis" values supplied to the created function should be in the -* range zero to (nval - 1). - -* Notes: -* - To avoid problems with some compilers, you should not leave any white -* space around the macro arguments. -* -*/ - -/* Define the macro. */ -#define MAKE_GET(attr,type,bad_value,assign,nval) \ -\ -/* Private member function. */ \ -/* ------------------------ */ \ -static type Get##attr( AstWcsMap *this, int axis, int *status ) { \ - type result; /* Result to be returned */ \ -\ -/* Initialise */ \ - result = (bad_value); \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Validate the axis index. */ \ - if( axis < 0 || axis >= nval ){ \ - astError( AST__AXIIN, "%s(%s): Index (%d) is invalid for attribute " \ - #attr " - it should be in the range 1 to %d.", status, \ - "astGet" #attr, astGetClass( this ), \ - axis + 1, nval ); \ -\ -/* Assign the result value. */ \ - } else { \ - result = (assign); \ - } \ -\ -/* Check for errors and clear the result if necessary. */ \ - if ( !astOK ) result = (bad_value); \ -\ -/* Return the result. */ \ - return result; \ -} \ -/* External interface. */ \ -/* ------------------- */ \ -type astGet##attr##_( AstWcsMap *this, int axis, int *status ) { \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return (bad_value); \ -\ -/* Invoke the required method via the virtual function table. */ \ - return (**astMEMBER(this,WcsMap,Get##attr))( this, axis, status ); \ -} - -/* -* -* Name: -* MAKE_SET - -* Purpose: -* Implement a method to set a single value in a multi-valued attribute -* for a WcsMap. - -* Type: -* Private macro. - -* Synopsis: -* #include "wcsmap.h" -* MAKE_SET(attr,type,component,assign,nval) - -* Class Membership: -* Defined by the WcsMap class. - -* Description: -* This macro expands to an implementation of a private member function of -* the form: -* -* static void Set<Attribute>( AstWcsMap *this, int axis, <Type> value ) -* -* and an external interface function of the form: -* -* void astSet<Attribute>_( AstWcsMap *this, int axis, <Type> value ) -* -* which implement a method for setting a single value in a specified -* multi-valued attribute for a WcsMap. - -* Parameters: -* attr -* The name of the attribute to be set, as it appears in the function -* name (e.g. Label in "astSetLabelAt"). -* type -* The C type of the attribute. -* component -* The name of the class structure component that holds the attribute -* value. -* assign -* An expression that evaluates to the value to be assigned to the -* component. -* nval -* Specifies the number of values in the multi-valued attribute. The -* "axis" values supplied to the created function should be in the -* range zero to (nval - 1). - -* Notes: -* - To avoid problems with some compilers, you should not leave any white -* space around the macro arguments. -*- -*/ - -/* Define the macro. */ -#define MAKE_SET(attr,type,component,assign,nval) \ -\ -/* Private member function. */ \ -/* ------------------------ */ \ -static void Set##attr( AstWcsMap *this, int axis, type value, int *status ) { \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Validate the axis index. */ \ - if( axis < 0 || axis >= nval ){ \ - astError( AST__AXIIN, "%s(%s): Index (%d) is invalid for attribute " \ - #attr " - it should be in the range 1 to %d.", status, \ - "astSet" #attr, astGetClass( this ), \ - axis + 1, nval ); \ -\ -/* Store the new value in the structure component. */ \ - } else { \ - this->component[ axis ] = (assign); \ - } \ -} \ -\ -/* External interface. */ \ -/* ------------------- */ \ -void astSet##attr##_( AstWcsMap *this, int axis, type value, int *status ) { \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Invoke the required method via the virtual function table. */ \ - (**astMEMBER(this,WcsMap,Set##attr))( this, axis, value, status ); \ -} - -/* -* -* Name: -* MAKE_TEST - -* Purpose: -* Implement a method to test if a single value has been set in a -* multi-valued attribute for a class. - -* Type: -* Private macro. - -* Synopsis: -* #include "wcsmap.h" -* MAKE_TEST(attr,assign,nval) - -* Class Membership: -* Defined by the WcsMap class. - -* Description: -* This macro expands to an implementation of a private member function of -* the form: -* -* static int Test<Attribute>( AstWcsMap *this, int axis ) -* -* and an external interface function of the form: -* -* int astTest<Attribute>_( AstWcsMap *this, int axis ) -* -* which implement a method for testing if a single value in a specified -* multi-valued attribute has been set for a class. - -* Parameters: -* attr -* The name of the attribute to be tested, as it appears in the function -* name (e.g. Label in "astTestLabelAt"). -* assign -* An expression that evaluates to 0 or 1, to be used as the returned -* value. This can use the string "axis" to represent the zero-based -* index of the value within the attribute. -* nval -* Specifies the number of values in the multi-valued attribute. The -* "axis" values supplied to the created function should be in the -* range zero to (nval - 1). - -* Notes: -* - To avoid problems with some compilers, you should not leave any white -* space around the macro arguments. -*- -*/ - -/* Define the macro. */ -#define MAKE_TEST(attr,assign,nval) \ -\ -/* Private member function. */ \ -/* ------------------------ */ \ -static int Test##attr( AstWcsMap *this, int axis, int *status ) { \ - int result; /* Value to return */ \ -\ -/* Initialise */ \ - result = 0; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -\ -/* Validate the axis index. */ \ - if( axis < 0 || axis >= nval ){ \ - astError( AST__AXIIN, "%s(%s): Index (%d) is invalid for attribute " \ - #attr " - it should be in the range 1 to %d.", status, \ - "astTest" #attr, astGetClass( this ), \ - axis + 1, nval ); \ -\ -/* Assign the result value. */ \ - } else { \ - result = (assign); \ - } \ -\ -/* Check for errors and clear the result if necessary. */ \ - if ( !astOK ) result = 0; \ -\ -/* Return the result. */ \ - return result; \ -} \ -/* External interface. */ \ -/* ------------------- */ \ -int astTest##attr##_( AstWcsMap *this, int axis, int *status ) { \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return 0; \ -\ -/* Invoke the required method via the virtual function table. */ \ - return (**astMEMBER(this,WcsMap,Test##attr))( this, axis, status ); \ -} - - -/* 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 "globals.h" /* Thread-safe global data access */ -#include "object.h" /* Base Object class */ -#include "pointset.h" /* Sets of points/coordinates */ -#include "mapping.h" /* Coordinate mappings (parent class) */ -#include "unitmap.h" /* Unit mappings */ -#include "permmap.h" /* Axis permutation mappings */ -#include "wcsmap.h" /* Interface definition for this class */ -#include "pal.h" /* SLALIB function prototypes */ -#include "channel.h" /* I/O channels */ -#include "proj.h" /* WCSLIB projections and WCSLIB_MXPAR */ - -/* Error code definitions. */ -/* ----------------------- */ -#include "ast_err.h" /* AST error codes */ - -/* C header files. */ -/* --------------- */ -#include <ctype.h> -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits.h> - -/* Local Type Definitions. */ -/* ----------------------- */ -/* This structure is used to hold information describing a WCSLIB - projection. */ -typedef struct PrjData { - int prj; /* WCSLIB projection identifier value */ - int mxpar; /* Max index for a lat axis projection param */ - int mxpar2; /* Max index for a lon axis projection param */ - char desc[60]; /* Long projection description */ - char ctype[5]; /* FITS CTYPE identifying string */ - int (* WcsFwd)(double, double, struct AstPrjPrm *, double *, double *); - /* Pointer to forward projection function */ - int (* WcsRev)(double, double, struct AstPrjPrm *, double *, double *); - /* Pointer to reverse projection function */ - double theta0; /* Default native latitude of fiducial point */ -} PrjData; - -/* Module Variables. */ -/* ================= */ - -/* Address of this static variable is used as a unique identifier for - member of this class. */ -static int class_check; - -/* Pointers to parent class methods which are extended by this class. */ -static int (* parent_getobjsize)( AstObject *, int * ); -static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * ); -static const char *(* parent_getattrib)( AstObject *, const char *, int * ); -static int (* parent_testattrib)( AstObject *, const char *, int * ); -static void (* parent_clearattrib)( AstObject *, const char *, int * ); -static void (* parent_setattrib)( AstObject *, const char *, int * ); -static int *(* parent_mapsplit)( AstMapping *, int, const int *, AstMapping **, int * ); - -/* The following array of PrjData structured describes each of the WCSLIB - projections. The last entry in the list should be for the AST__WCSBAD - projection. This marks the end of the list. */ -static PrjData PrjInfo[] = { - { AST__AZP, 2, 4, "zenithal perspective", "-AZP", astAZPfwd, astAZPrev, AST__DPIBY2 }, - { AST__SZP, 3, 4, "slant zenithal perspective", "-SZP", astSZPfwd, astSZPrev, AST__DPIBY2 }, - { AST__TAN, 0, 4, "gnomonic", "-TAN", astTANfwd, astTANrev, AST__DPIBY2 }, - { AST__STG, 0, 4, "stereographic", "-STG", astSTGfwd, astSTGrev, AST__DPIBY2 }, - { AST__SIN, 2, 4, "orthographic", "-SIN", astSINfwd, astSINrev, AST__DPIBY2 }, - { AST__ARC, 0, 4, "zenithal equidistant", "-ARC", astARCfwd, astARCrev, AST__DPIBY2 }, - { AST__ZPN, WCSLIB_MXPAR, 4, "zenithal polynomial", "-ZPN", astZPNfwd, astZPNrev, AST__DPIBY2 }, - { AST__ZEA, 0, 4, "zenithal equal area", "-ZEA", astZEAfwd, astZEArev, AST__DPIBY2 }, - { AST__AIR, 1, 4, "Airy", "-AIR", astAIRfwd, astAIRrev, AST__DPIBY2 }, - { AST__CYP, 2, 4, "cylindrical perspective", "-CYP", astCYPfwd, astCYPrev, 0.0 }, - { AST__CEA, 1, 4, "cylindrical equal area", "-CEA", astCEAfwd, astCEArev, 0.0 }, - { AST__CAR, 0, 4, "Cartesian", "-CAR", astCARfwd, astCARrev, 0.0 }, - { AST__MER, 0, 4, "Mercator", "-MER", astMERfwd, astMERrev, 0.0 }, - { AST__SFL, 0, 4, "Sanson-Flamsteed", "-SFL", astSFLfwd, astSFLrev, 0.0 }, - { AST__PAR, 0, 4, "parabolic", "-PAR", astPARfwd, astPARrev, 0.0 }, - { AST__MOL, 0, 4, "Mollweide", "-MOL", astMOLfwd, astMOLrev, 0.0 }, - { AST__AIT, 0, 4, "Hammer-Aitoff", "-AIT", astAITfwd, astAITrev, 0.0 }, - { AST__COP, 2, 4, "conical perspective", "-COP", astCOPfwd, astCOPrev, AST__BAD }, - { AST__COE, 2, 4, "conical equal area", "-COE", astCOEfwd, astCOErev, AST__BAD }, - { AST__COD, 2, 4, "conical equidistant", "-COD", astCODfwd, astCODrev, AST__BAD }, - { AST__COO, 2, 4, "conical orthomorphic", "-COO", astCOOfwd, astCOOrev, AST__BAD }, - { AST__BON, 1, 4, "Bonne's equal area", "-BON", astBONfwd, astBONrev, 0.0 }, - { AST__PCO, 0, 4, "polyconic", "-PCO", astPCOfwd, astPCOrev, 0.0 }, - { AST__TSC, 0, 4, "tangential spherical cube", "-TSC", astTSCfwd, astTSCrev, 0.0 }, - { AST__CSC, 0, 4, "cobe quadrilateralized spherical cube", "-CSC", astCSCfwd, astCSCrev, 0.0 }, - { AST__QSC, 0, 4, "quadrilateralized spherical cube", "-QSC", astQSCfwd, astQSCrev, 0.0 }, - { AST__NCP, 2, 4, "AIPS north celestial pole", "-NCP", NULL, NULL, 0.0 }, - { AST__GLS, 0, 4, "sinusoidal", "-GLS", astSFLfwd, astSFLrev, 0.0 }, - { AST__HPX, 2, 4, "HEALPix", "-HPX", astHPXfwd, astHPXrev, 0.0 }, - { AST__XPH, 0, 4, "polar HEALPix", "-XPH", astXPHfwd, astXPHrev, AST__DPIBY2 }, - { AST__TPN, WCSLIB_MXPAR, WCSLIB_MXPAR, "gnomonic polynomial", "-TPN", astTPNfwd, astTPNrev, AST__DPIBY2 }, - { AST__WCSBAD, 0, 4, "<null>", " ", NULL, NULL, 0.0 } }; - -/* Define macros for accessing each item of thread specific global data. */ -#ifdef THREAD_SAFE - -/* Define how to initialise thread-specific globals. */ -#define GLOBAL_inits \ - globals->Class_Init = 0; \ - globals->GetAttrib_Buff[ 0 ] = 0; - -/* Create the function that initialises global data for this module. */ -astMAKE_INITGLOBALS(WcsMap) - -/* Define macros for accessing each item of thread specific global data. */ -#define class_init astGLOBAL(WcsMap,Class_Init) -#define class_vtab astGLOBAL(WcsMap,Class_Vtab) -#define getattrib_buff astGLOBAL(WcsMap,GetAttrib_Buff) - - - -/* If thread safety is not needed, declare and initialise globals at static - variables. */ -#else - -static char getattrib_buff[ 101 ]; - - -/* Define the class virtual function table and its initialisation flag - as static variables. */ -static AstWcsMapVtab 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. */ -AstWcsMap *astWcsMapId_( int, int, int, int, const char *options, ... ); - -/* Prototypes for Private Member Functions. */ -/* ======================================== */ -static int GetObjSize( AstObject *, int * ); -static double GetPV( AstWcsMap *, int, int, int * ); -static int TestPV( AstWcsMap *, int, int, int * ); -static void ClearPV( AstWcsMap *, int, int, int * ); -static void SetPV( AstWcsMap *, int, int, double, int * ); - -static int GetPVMax( AstWcsMap *, int, int * ); -static int GetWcsType( AstWcsMap *, int * ); -static double GetNatLat( AstWcsMap *, int * ); -static double GetNatLon( AstWcsMap *, int * ); -static int GetWcsAxis( AstWcsMap *, int, int * ); - -static int GetFITSProj( AstWcsMap *, int * ); -static int TestFITSProj( AstWcsMap *, int * ); -static void ClearFITSProj( AstWcsMap *, int * ); -static void SetFITSProj( AstWcsMap *, int, int * ); - -static int GetTPNTan( AstWcsMap *, int * ); -static int TestTPNTan( AstWcsMap *, int * ); -static void ClearTPNTan( AstWcsMap *, int * ); -static void SetTPNTan( AstWcsMap *, int, int * ); - -static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * ); -static const PrjData *FindPrjData( int, int * ); -static const char *GetAttrib( AstObject *, const char *, int * ); -static int CanMerge( AstMapping *, int, AstMapping *, int, int * ); -static int CanSwap( AstMapping *, AstMapping *, int, int, int *, AstWcsMap **, int * ); -static int Equal( AstObject *, AstObject *, int * ); -static int GetNP( AstWcsMap *, int, int * ); -static int IsZenithal( AstWcsMap *, int * ); -static int LongRange( const PrjData *, struct AstPrjPrm *, double *, double *, int * ); -static int Map( AstWcsMap *, int, int, double *, double *, double *, double *, int * ); -static int MapMerge( AstMapping *, int, int, int *, AstMapping ***, int **, int * ); -static int TestAttrib( AstObject *, const char *, int * ); -static void ClearAttrib( AstObject *, const char *, int * ); -static void Copy( const AstObject *, AstObject *, int * ); -static void CopyPV( AstWcsMap *, AstWcsMap *, int * ); -static void Delete( AstObject *obj, int * ); -static void Dump( AstObject *, AstChannel *, int * ); -static void FreePV( AstWcsMap *, int * ); -static void InitPrjPrm( AstWcsMap *, int * ); -static void PermGet( AstPermMap *, int **, int **, double **, int * ); -static void SetAttrib( AstObject *, const char *, int * ); -static void WcsPerm( AstMapping **, int *, int, int * ); -static int *MapSplit( AstMapping *, int, const int *, AstMapping **, int * ); - -/* Member functions. */ -/* ================= */ -static int CanMerge( AstMapping *map1, int inv1, AstMapping *map2, int inv2, int *status ){ -/* -* -* Name: -* CanMerge - -* Purpose: -* Checks if two WcsMaps can be merged. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* int CanMerge( AstMapping *map1, int inv1, AstMapping *map2, int inv2, int *status ) - -* Class Membership: -* WcsMap internal utility function. - -* Description: -* This function checks the two supplied Mappings to see if they are -* two WcsMaps which can be merged. This is only possible if they -* form an inverse pair. - -* Parameters: -* map1 -* A pointer to the first mapping. -* map2 -* A pointer to the second mapping. -* inv1 -* The invert flag to use with the first mapping. -* inv2 -* The invert flag to use with the second mapping. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* 1 if the WcsMaps can be merged, zero otherwise. - -*/ - -/* Local Variables: */ - AstWcsMap *wcs1; /* Pointer to first WcsMap */ - AstWcsMap *wcs2; /* Pointer to second WcsMap */ - int m; /* Projection parameter index */ - int ret; /* Can the Mappings be merged? */ - int i; /* Axis index */ - -/* Initialise the returned value. */ - ret = 0; - -/* Check the global error status. */ - if ( !astOK ) return ret; - -/* Both Mappings must be WcsMaps to merge. */ - if( !strcmp( "WcsMap", astGetClass( map1 ) ) && - !strcmp( "WcsMap", astGetClass( map2 ) ) ) { - -/* Get pointers to the WcsMaps. */ - wcs1 = (AstWcsMap *) map1; - wcs2 = (AstWcsMap *) map2; - -/* Check that the two WcsMaps performs the same sort of projection, and - have the same number of axes. */ - if( astGetWcsType( wcs1 ) == astGetWcsType( wcs2 ) && - astGetNin( wcs1 ) == astGetNin( wcs2 ) ) { - -/* Check that the Mappings are applied in opposite senses. */ - if( inv1 != inv2 ) { - -/* Check that the latitude and longitude axes have the same indices in - both WcsMaps. */ - if( astGetWcsAxis( wcs1, 0 ) == astGetWcsAxis( wcs2, 0 ) && - astGetWcsAxis( wcs1, 1 ) == astGetWcsAxis( wcs2, 1 ) ){ - -/* We nopw check the projection parameters are equal. Assume they are for - the moment. */ - ret = 1; - -/* Check the parameters for each axis in turn. */ - for( i = 0; i < astGetNin( wcs1 ); i++ ){ - -/* If the two WcsMaps have a different number of parameters for this axes, - they cannot merge. */ - if( GetNP( wcs1, i, status ) != GetNP( wcs1, i, status ) ){ - ret = 0; - break; - -/* Otherwise, check each parameter value in turn. If any are found which - are not equal, the WcsMaps cannot merge. */ - } else { - for( m = 0; m < GetNP( wcs1, i, status ); m++ ){ - if( !EQUAL( astGetPV( wcs1, i, m ), - astGetPV( wcs2, i, m ) ) ){ - ret = 0; - break; - } - } - if( !ret ) break; - } - } - } - } - } - } - -/* Return the answer. */ - return ret; -} - -static int CanSwap( AstMapping *map1, AstMapping *map2, int inv1, int inv2, - int *simpler, AstWcsMap **newwcsmap, int *status ){ -/* -* Name: - -* CanSwap - -* Purpose: -* Determine if two Mappings could be swapped. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* int CanSwap( AstMapping *map1, AstMapping *map2, int inv1, int inv2, -* int *simpler, AstWcsMap **newwcssmap ) - -* Class Membership: -* WcsMap member function - -* Description: -* This function returns a flag indicating if the pair of supplied -* Mappings could be replaced by an equivalent pair of Mappings from the -* same classes as the supplied pair, but in reversed order. Each pair -* of Mappings is considered to be compunded in series. The supplied -* Mapings are not changed in any way. - -* Parameters: -* map1 -* The Mapping to be applied first. -* map2 -* The Mapping to be applied second. -* inv1 -* The invert flag to use with map1. A value of zero causes the forward -* mapping to be used, and a non-zero value causes the inverse -* mapping to be used. -* inv2 -* The invert flag to use with map2. -* simpler -* Addresss of a location at which to return a flag indicating if -* the swapped Mappings would be intrinsically simpler than the -* original Mappings. -* newwcsmap -* Addresss of a location at which to return a pointer to the -* WcsMap that would be produced if the two Mappings were swapped. -* Returned holding NULL if the supplied Mappings cannot be swapped. - -* Returned Value: -* 1 if the Mappings could be swapped, 0 otherwise. - -* Notes: -* - One of the supplied pair of Mappings must be a WcsMap. -* - A value of 0 is returned if the two Mappings could be merged into -* a single Mapping. -* - A value of 0 is returned if an error has already occurred, or if -* this function should fail for any reason. -*/ - -/* Local Variables: */ - AstMapping *maps[2]; /* Pointer to Mappign list */ - AstMapping *nowcs; /* Pointer to non-WcsMap Mapping */ - AstWcsMap *wcs; /* Pointer to WcsMap Mapping */ - const char *class1; /* Pointer to map1 class string */ - const char *class2; /* Pointer to map2 class string */ - const char *nowcs_class; /* Pointer to non-WcsMap class string */ - double *consts; /* Pointer to constants array */ - int *inperm; /* Pointer to input axis permutation array */ - int *outperm; /* Pointer to output axis permutation array */ - int i; /* Loop count */ - int invert[ 2 ]; /* Original invert flags */ - int iwm; /* Index of WcsMap within "maps" */ - int latax; /* Index of latitude axis in WcsMap */ - int lonax; /* Index of longitude axis in WcsMap */ - int nin; /* No. of input coordinates for the PermMap */ - int nout; /* No. of output coordinates for the PermMap */ - int ret; /* Returned flag */ - -/* Initialise */ - ret = 0; - *simpler = 0; - *newwcsmap = NULL; - -/* Check the global error status. */ - if ( !astOK ) return ret; - -/* Temporarily set the Invert attributes of both Mappings to the supplied - values. */ - invert[ 0 ] = astGetInvert( map1 ); - astSetInvert( map1, inv1 ); - - invert[ 1 ] = astGetInvert( map2 ); - astSetInvert( map2, inv2 ); - -/* Get the classes of the two mappings. */ - class1 = astGetClass( map1 ); - class2 = astGetClass( map2 ); - if( astOK ){ - -/* Get a pointer to the non-WcsMap Mapping. */ - if( !strcmp( class1, "WcsMap" ) ){ - iwm = 0; - wcs = (AstWcsMap *) map1; - nowcs = map2; - nowcs_class = class2; - } else { - iwm = 1; - nowcs = map1; - wcs = (AstWcsMap *) map2; - nowcs_class = class1; - } - -/* If it is a PermMap, the Mappings can be swapped so long as: - 1) all links between input and output axes in the PermMap are - bi-directional. This does not preclude the existence of unconnected axes, - which do not have links (bi-directional or otherwise). - 2) The PermMap passesd though both the longitude and latitude axes of - the WcsMap */ - if( !strcmp( nowcs_class, "PermMap" ) ){ - -/* Get the number of input and output coordinates. */ - nin = astGetNin( nowcs ); - nout = astGetNout( nowcs ); - -/* We need to know the axis permutation arrays and constants array for - the PermMap. */ - PermGet( (AstPermMap *) nowcs, &outperm, &inperm, &consts, status ); - if( astOK ) { - -/* Indicate we can swap with the PermMap. */ - ret = 1; - -/* Check each output axis. If any links between axes are found which are - not bi-directional, indicate that we cannot swap with the PermMap. */ - for( i = 0; i < nout; i++ ){ - if( outperm[ i ] >= 0 && outperm[ i ] < nin ) { - if( inperm[ outperm[ i ] ] != i ) { - ret = 0; - break; - } - } - } - -/* Check each input axis. If any links between axes are found which are - not bi-directional, indicate that we cannot swap with the PermMap. */ - for( i = 0; i < nin; i++ ){ - if( inperm[ i ] >= 0 && inperm[ i ] < nout ) { - if( outperm[ inperm[ i ] ] != i ) { - ret = 0; - break; - } - } - } - -/* Check that the longitude and latitude axes both have bi-directional - links in the PermMap, or are both unassigned. */ - if( ret ) { - -/* Get the indices of the longitude and latitude axes in the WcsMap */ - lonax = astGetWcsAxis( wcs, 0 ); - latax = astGetWcsAxis( wcs, 1 ); - -/* If the WcsMap is applied first... */ - if( wcs == (AstWcsMap *) map1 ) { - if( inperm[ lonax] < 0 && inperm[ latax ] < 0 ) { - ret = 1; - } else if( inperm[ lonax ] < 0 || inperm[ lonax ] >= nout || - inperm[ latax ] < 0 || inperm[ latax ] >= nout ) { - ret = 0; - } - -/* If the WcsMap is applied second ... */ - } else { - if( outperm[ lonax ] < 0 && outperm[ latax ] < 0 ) { - ret = 1; - } else if( outperm[ lonax ] < 0 || outperm[ lonax ] >= nin || - outperm[ latax ] < 0 || outperm[ latax ] >= nin ) { - ret = 0; - } - } - } - -/* If we can swap with the PermMap, the swapped Mappings may be - intrinsically simpler than the original mappings. */ - if( ret ) { - -/* If the PermMap precedes the WcsMap, this will be the case if the PermMap - has more outputs than inputs. If the WcsMap precedes the PermMap, this - will be the case if the PermMap has more inputs than outputs. */ - *simpler = ( nowcs == map1 ) ? nout > nin : nin > nout; - } - -/* Free the axis permutation and constants arrays. */ - outperm = (int *) astFree( (void *) outperm ); - inperm = (int *) astFree( (void *) inperm ); - consts = (double *) astFree( (void *) consts ); - } - } - } - -/* Re-instate the original settings of the Invert attributes for the - supplied MatrixMaps. */ - astSetInvert( map1, invert[ 0 ] ); - astSetInvert( map2, invert[ 1 ] ); - -/* If the Mappings can swap, get the equivalent swapped mappings. */ - if( ret ) { - maps[ 0 ] = astClone( map1 ); - maps[ 1 ] = astClone( map2 ); - invert[ 0 ] = inv1; - invert[ 1 ] = inv2; - WcsPerm( maps, invert, iwm, status ); - -/* Return a pointer to the swapped WcsMap. */ - *newwcsmap = astClone( maps[ 1 - iwm ] ); - -/* Free resources */ - maps[ 0 ] = astAnnul( maps[ 0 ] ); - maps[ 1 ] = astAnnul( maps[ 1 ] ); - } - -/* Return the answer. */ - return astOK ? ret : 0; -} - -static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* ClearAttrib - -* Purpose: -* Clear an attribute value for a WcsMap. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* void ClearAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* WcsMap member function (over-rides the astClearAttrib protected -* method inherited from the Mapping class). - -* Description: -* This function clears the value of a specified attribute for a -* WcsMap, so that the default value will subsequently be used. - -* Parameters: -* this -* Pointer to the WcsMap. -* attrib -* Pointer to a null terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstWcsMap *this; /* Pointer to the WcsMap structure */ - int i; /* Axis index */ - int len; /* Length of the attribute name */ - int m; /* Projection parameter index */ - int nc; /* No. of characters read by astSscanf */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the WcsMap structure. */ - this = (AstWcsMap *) this_object; - -/* Obtain the length of the attrib string. */ - len = strlen( attrib ); - -/* Check the attribute name and clear the appropriate attribute. */ - -/* ProjP. */ -/* ------ */ - if ( nc = 0, ( 1 == astSscanf( attrib, "prpjp(%d)%n", &m, &nc ) ) - && ( nc >= len ) ) { - astClearPV( this, astGetWcsAxis( this, 1 ), m ); - -/* PV. */ -/* ------ */ - } else if ( nc = 0, ( 2 == astSscanf( attrib, "pv%d_%d%n", &i, &m, &nc ) ) - && ( nc >= len ) ) { - astClearPV( this, i - 1, m ); - -/* If the name was not recognised, test if it matches any of the - read-only attributes of this class. If it does, then report an - error. */ - } else if ( ( nc = 0, ( 1 == astSscanf( attrib, "wcsaxis(%d)%n", &i, &nc ) ) - && ( nc >= len ) ) || - !strcmp( attrib, "wcstype" ) || - !strcmp( attrib, "natlat" ) || - !strcmp( attrib, "natlon" ) ){ - astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" " - "value for a %s.", status, attrib, astGetClass( this ) ); - astError( AST__NOWRT, "This is a read-only attribute." , status); - -/* If the attribute is still not recognised, pass it on to the parent - method for further interpretation. */ - } else { - (*parent_clearattrib)( this_object, attrib, status ); - } -} - -static void ClearPV( AstWcsMap *this, int i, int m, int *status ) { -/* -*+ -* Name: -* astClearPV - -* Purpose: -* Clear a PVi_m attribute. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* void astClearPV( AstWcsMap *this, int i, int m ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function clears a specified member of the PV attribute array, by -* resetting its value to AST__BAD. - -* Parameters: -* this -* A pointer to the WcsMap. -* i -* Zero based axis index. -* m -* Zero based parameter index. - -*- -*/ -/* Local Variables; */ - int npar; - int mxpar; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Report an error if the object has been cloned (i.e. has a reference - count that is greater than one). */ - if( astGetRefCount( this ) > 1 ) { - astError( AST__IMMUT, "astClear(%s): Projection parameter values " - "within the supplied %s cannot be cleared because the %s has " - "been cloned (programming error).", status, - astGetClass(this), astGetClass(this), astGetClass(this) ); - -/* Validate the axis index. */ - } else if( i < 0 || i >= astGetNin( this ) ){ - astError( AST__AXIIN, "astClearPV(%s): Axis index (%d) is invalid in " - "attribute PV%d_%d - it should be in the range 1 to %d.", - status, astGetClass( this ), i + 1, i + 1, m, - astGetNin( this ) ); - - } else { - -/* Find the maximum number of parameters allowed for the axis. */ - mxpar = astGetPVMax( this, i ); - -/* Ignore unused parameters. */ - if( m < 0 || m > mxpar ){ - -/* See if the parameter is currently set. Is so, set its value to - AST__BAD. */ - } else if( this->np && this->p ){ - npar = this->np[ i ]; - if( m < npar && this->p[ i ] ) this->p[ i ][ m ] = AST__BAD; - } - -/* Re-initialize the values stored in the "AstPrjPrm" structure. */ - InitPrjPrm( this, status ); - } -} - -static void ClearTPNTan( AstWcsMap *this, int *status ) { -/* -*+ -* Name: -* astClearTPNTan - -* Purpose: -* Clear the TPNTan attribute. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* void ClearTPNTan( AstWcsMap *this, int *status ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function clears the TPNTan attribute, ensuring the projection -* parameters used by WCSLIB are adjusted accordingly. - -* Parameters: -* this -* A pointer to the WcsMap. - -*- -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Clear the value. */ - this->tpn_tan = -INT_MAX; - -/* Re-initialize the values stored in the "AstPrjPrm" structure. */ - InitPrjPrm( this, status ); -} - -static void CopyPV( AstWcsMap *in, AstWcsMap *out, int *status ) { -/* -* Name: -* CopyPV - -* Purpose: -* Copy projection parameter information from one WcsMap to another. - -* Type: -* Private function. - -* Synopsis: -* void CopyPV( AstWcsMap *in, AstWcsMap *out ) - -* Description: -* This function copies projection parameter information from one -* WcsMap to another. - -* Parameters: -* in -* Pointer to the input WcsMap. -* out -* Pointer to the output WcsMap. - -*/ - - -/* Local Variables: */ - int i; /* Axis index */ - int latax_in; /* Index of input latitude axis */ - int latax_out; /* Index of output latitude axis */ - int lonax_in; /* Index of input longitude axis */ - int lonax_out; /* Index of output longitude axis */ - int nax_out; /* No. of axis in the output WcsMap */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Nullify the pointers stored in the output WcsMap since these may - currently be pointing at good data. Otherwise, the good data could be - freed by accident if the output object is deleted due to an error - occuring in this function. */ - out->np = NULL; - out->p = NULL; - -/* Do nothing more if either of the input pointers are null (i.e. if there - are no projection parameters. */ - if( in->np && in->p ){ - -/* Store the number of axes in the input and output WcsMaps */ - nax_out = astGetNin( out ); - -/* Allocate memory for the array holding the number of projection parameters - associated with each axis. */ - out->np = (int *) astMalloc( sizeof( int )*nax_out ); - -/* Allocate memory for the array of pointers which identify the arrays - holding the parameter values. */ - out->p = (double **) astMalloc( sizeof( double *)*nax_out ); - -/* Check pointers can be used */ - if( astOK ) { - -/* Initialise the above arrays. */ - for( i = 0; i < nax_out; i++ ) { - (out->np)[ i ] = 0; - (out->p)[ i ] = NULL; - } - -/* Copy the longitude and latitude values from in to out (other axes do - not have projection parameters). */ - lonax_in = astGetWcsAxis( in, 0 ); - latax_in = astGetWcsAxis( in, 1 ); - lonax_out = astGetWcsAxis( out, 0 ); - latax_out = astGetWcsAxis( out, 1 ); - - (out->np)[ lonax_out ] = (in->np)[ lonax_in ]; - (out->p)[ lonax_out ] = (double *) astStore( NULL, - (void *) (in->p)[ lonax_in ], - sizeof(double)*(in->np)[ lonax_in ] ); - - (out->np)[ latax_out ] = (in->np)[ latax_in ]; - (out->p)[ latax_out ] = (double *) astStore( NULL, - (void *) (in->p)[ latax_in ], - sizeof(double)*(in->np)[ latax_in ] ); - } - -/* If an error has occurred, free the output arrays. */ - if( !astOK ) FreePV( out, status ); - - } - -/* Re-initialize the values stored in the "AstPrjPrm" structure. */ - InitPrjPrm( out, status ); - -} - -static int Equal( AstObject *this_object, AstObject *that_object, int *status ) { -/* -* Name: -* Equal - -* Purpose: -* Test if two WcsMaps are equivalent. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* int Equal( AstObject *this, AstObject *that, int *status ) - -* Class Membership: -* WcsMap member function (over-rides the astEqual protected -* method inherited from the astMapping class). - -* Description: -* This function returns a boolean result (0 or 1) to indicate whether -* two WcsMaps are equivalent. - -* Parameters: -* this -* Pointer to the first Object (a WcsMap). -* that -* Pointer to the second Object. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if the WcsMaps are equivalent, zero otherwise. - -* 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: */ - AstWcsMap *that; - AstWcsMap *this; - int i, j; - int nin; - int nout; - int result; - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain pointers to the two WcsMap structures. */ - this = (AstWcsMap *) this_object; - that = (AstWcsMap *) that_object; - -/* Check the second object is a WcsMap. We know the first is a - WcsMap since we have arrived at this implementation of the virtual - function. */ - if( astIsAWcsMap( that ) ) { - -/* Get the number of inputs and outputs and check they are the same for both. */ - nin = astGetNin( this ); - nout = astGetNout( this ); - if( astGetNin( that ) == nin && astGetNout( that ) == nout ) { - -/* If the Invert flags for the two WcsMaps differ, it may still be possible - for them to be equivalent. First compare the WcsMaps if their Invert - flags are the same. In this case all the attributes of the two WcsMaps - must be identical. */ - if( astGetInvert( this ) == astGetInvert( that ) ) { - - if( this->type == that->type && - this->wcsaxis[ 0 ] == that->wcsaxis[ 0 ] && - this->wcsaxis[ 1 ] == that->wcsaxis[ 1 ] ) { - - result = 1; - - if( this->np && that->np ){ - - for( i = 0; i < nout && result; i++ ) { - - if( (this->np)[ i ] != (that->np)[ i ] ) { - result = 0; - - } else if( (this->p)[ i ] && !(this->p)[ i ] ) { - result = 0; - - } else if( !(this->p)[ i ] && (this->p)[ i ] ) { - result = 0; - - } else if( (this->p)[ i ] && (this->p)[ i ] ) { - - for( j = 0; j < (this->np)[ i ]; j++ ) { - if( !astEQUAL( (this->p)[ i ][ j ], - (that->p)[ i ][ j ] ) ) { - result = 0; - break; - } - } - } - } - } - - } else if( this->np || that->np ){ - result = 0; - } - -/* If the Invert flags for the two WcsMaps differ, the attributes of the two - WcsMaps must be inversely related to each other. */ - } else { - -/* In the specific case of a WcsMap, Invert flags must be equal. */ - result = 0; - - } - } - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = 0; - -/* Return the result, */ - return result; -} - -static const PrjData *FindPrjData( int type, int *status ){ -/* -*+ -* Name: -* FindPrjData - -* Purpose: -* Get information about a WCSLIB projection given a projection type. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* const PrjData *FindPrjData( int type, int *status ) - -* Class Membership: -* WcsMap member function - -* Description: -* This function returns a pointer to an PrjData structure describing -* the WCSLIB projection with the supplied type. - -* Parameters: -* type -* The projection type. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to the "const" PrjData structure describing the projection. - -* Notes: -* - The returned pointer points to an element in a static array and -* should not be freed. -* - This function attempts to execute even if an error has already -* occurred. A description of a "null" projection will be returned if -* this function subsequently fails (for instance if the projection is -* not recognised). -*- -*/ - - const PrjData *data; - data = PrjInfo; - while( data->prj != AST__WCSBAD && data->prj != type ) data++; - return data; -} - -static void FreePV( AstWcsMap *this, int *status ) { -/* -* -* Name: -* FreePV - -* Purpose: -* Free memory used to hold projection parameters - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* FreePV( AstWcsMap *this, int *status ) - -* Class Membership: -* WcsMap private function - -* Description: -* This function frees all the dynamic memory used to store projection -* parameter information in the supplied WcsMap. - -* Parameters: -* this -* A pointer to the WcsMap. -* status -* Pointer to the inherited status variable. - -* Notes: -* This function attempts to execute even if an error has already occurred. - -* -*/ - int i; /* Axis index */ - - if( this->np ) this->np = (int *) astFree( (void *) this->np ); - if( this->p ){ - for( i = 0; i < astGetNin( this ); i++ ){ - this->p[ i ] = (double *) astFree( (void *) this->p[ i ] ); - } - this->p = (double **) astFree( (void *) this->p ); - } - -/* Re-initialize the values stored in the "AstPrjPrm" structure. */ - InitPrjPrm( this, status ); - - -} - -static int GetObjSize( AstObject *this_object, int *status ) { -/* -* Name: -* GetObjSize - -* Purpose: -* Return the in-memory size of an Object. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* int GetObjSize( AstObject *this, int *status ) - -* Class Membership: -* WcsMap member function (over-rides the astGetObjSize protected -* method inherited from the parent class). - -* Description: -* This function returns the in-memory size of the supplied WcsMap, -* in bytes. - -* Parameters: -* this -* Pointer to the WcsMap. -* 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: */ - AstWcsMap *this; /* Pointer to WcsMap structure */ - int result; /* Result value to return */ - int i; /* Axis index */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointers to the WcsMap structure. */ - this = (AstWcsMap *) this_object; - -/* Invoke the GetObjSize method inherited from the parent class, and then - add on any components of the class structure defined by thsi class - which are stored in dynamically allocated memory. */ - result = (*parent_getobjsize)( this_object, status ); - - result += astTSizeOf( this->np ); - if( this->p ){ - for( i = 0; i < astGetNin( this ); i++ ){ - result += astTSizeOf( (void *) this->p[ i ] ); - } - result += astTSizeOf( this->p ); - } - - result += astTSizeOf( this->params.p ); - result += astTSizeOf( this->params.p2 ); - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = 0; - -/* Return the result, */ - return result; -} - -static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* GetAttrib - -* Purpose: -* Get the value of a specified attribute for a WcsMap. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* const char *GetAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* WcsMap member function (over-rides the protected astGetAttrib -* method inherited from the Mapping class). - -* Description: -* This function returns a pointer to the value of a specified -* attribute for a WcsMap, formatted as a character string. - -* Parameters: -* this -* Pointer to the WcsMap. -* attrib -* Pointer to a null-terminated string containing the name of -* the attribute whose value is required. This name should be in -* lower case, with all white space removed. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* - Pointer to a null-terminated string containing the attribute -* value. - -* Notes: -* - The returned string pointer may point at memory allocated -* within the WcsMap, or at static memory. The contents of the -* string may be over-written or the pointer may become invalid -* following a further invocation of the same function or any -* modification of the WcsMap. A copy of the string should -* therefore be made if necessary. -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstWcsMap *this; /* Pointer to the WcsMap structure */ - const char *result; /* Pointer value to return */ - double dval; /* Floating point attribute value */ - int i; /* Axis index */ - int ival; /* Integer attribute value */ - int len; /* Length of attribute string */ - int m; /* Projection parameter index */ - int nc; /* No. of characters read by astSscanf */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(this_object); - -/* Obtain a pointer to the WcsMap structure. */ - this = (AstWcsMap *) this_object; - -/* Obtain the length of the attrib string. */ - len = strlen( attrib ); - -/* Compare "attrib" with each recognised attribute name in turn, - obtaining the value of the required attribute. If necessary, write - the value into "getattrib_buff" as a null-terminated string in an appropriate - format. Set "result" to point at the result string. */ - -/* ProjP. */ -/* ------ */ - if ( nc = 0, ( 1 == astSscanf( attrib, "projp(%d)%n", &m, &nc ) ) - && ( nc >= len ) ) { - dval = astGetPV( this, astGetWcsAxis( this, 1 ), m ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); - result = getattrib_buff; - } - -/* PV. */ -/* --- */ - } else if ( nc = 0, ( 2 == astSscanf( attrib, "pv%d_%d%n", &i, &m, &nc ) ) - && ( nc >= len ) ) { - dval = astGetPV( this, i - 1, m ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); - result = getattrib_buff; - } - -/* WcsType */ -/* ======= */ - } else if ( !strcmp( attrib, "wcstype" ) ) { - ival = astGetWcsType( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", ival ); - result = getattrib_buff; - } - -/* PVMax */ -/* ===== */ - } else if ( nc = 0, ( 1 == astSscanf( attrib, "pvmax(%d)%n", &i, &nc ) ) - && ( nc >= len ) ) { - ival = astGetPVMax( this, i - 1 ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", ival ); - result = getattrib_buff; - } - -/* NatLat */ -/* ====== */ - } else if ( !strcmp( attrib, "natlat" ) ) { - dval = astGetNatLat( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); - result = getattrib_buff; - } - -/* NatLon */ -/* ====== */ - } else if ( !strcmp( attrib, "natlon" ) ) { - dval = astGetNatLon( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); - result = getattrib_buff; - } - - -/* WcsAxis */ -/* ======= */ - } else if ( nc = 0, ( 1 == astSscanf( attrib, "wcsaxis(%d)%n", &i, &nc ) ) - && ( nc >= len ) ) { - ival = astGetWcsAxis( this, i - 1 ) + 1; - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", ival ); - result = getattrib_buff; - } - -/* If the attribute name was not recognised, pass it on to the parent - method for further interpretation. */ - } else { - result = (*parent_getattrib)( this_object, attrib, status ); - } - -/* Return the result. */ - return result; -} - -static double GetNatLat( AstWcsMap *this, int *status ) { -/* -*+ -* Name: -* GetNatLat - -* Purpose: -* Get the value of the NatLat attribute. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* double GetNatLat( AstWcsMap *this, int *status ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns the value of the NatLat attribute. This is -* fixed value for most projection types , defined in the FITS-WCS paper -* II. For instance, all zenithal projections have NatLat = PI/2 (90 -* degrees). For some prjections (e.g. conics), the value is defined -* by a projection parameter. - -* Parameters: -* this -* A pointer to the WcsMap. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The attribute value, in radians. - -*- -*/ - double ret; /* Returned value */ - -/* The native latitude of the reference point of the projection is - constant for most projection, but for some (the conics) it is - specified by projection one on the latitude axis. */ - ret = FindPrjData( this->type, status )->theta0; - if( ret == AST__BAD ){ - ret = astGetPV( this, astGetWcsAxis( this, 1 ), 1 ); - if( ret != AST__BAD ) ret *= AST__DD2R; - } - -/* Return the result. */ - return ret; -} - -static double GetNatLon( AstWcsMap *this, int *status ) { -/* -*+ -* Name: -* GetNatLon - -* Purpose: -* Get the value of the NatLon attribute. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* double GetNatLon( AstWcsMap *this, int *status ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns the value of the NatLon attribute. This is -* fixed value of zero for all projection types. - -* Parameters: -* this -* A pointer to the WcsMap. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The attribute value, in radians. - -*- -*/ - return 0.0; -} - -static int GetNP( AstWcsMap *this, int i, int *status ) { -/* -*+ -* Name: -* GetNP - -* Purpose: -* Get the number of projection parameters for a specified axis. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* int GetNP( AstWcsMap *this, int i, int *status ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns the current number of projection parameters -* associated with the speified axis. Some of these may be unset (i.e. -* equal to AST__BAD). The returned number is the size of the array -* holding the projection parameters. - -* Parameters: -* this -* A pointer to the WcsMap. -* i -* Zero based axis index. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The number of projection parameters for the specified axis. - -*- -*/ - double ret; - -/* Initialise */ - ret = 0; - -/* Check the global error status. */ - if ( !astOK ) return ret; - -/* Validate the axis index, and get the count. */ - if( i >= 0 && this->np && i < astGetNin( this ) ) ret = this->np[ i ]; - - return ret; - -} - -static double GetPV( AstWcsMap *this, int i, int m, int *status ) { -/* -*+ -* Name: -* astGetPV - -* Purpose: -* Get the value of a PVi_m attribute. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* double astGetPV( AstWcsMap *this, int i, int m ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns the current value of a specified member of the -* PV attribute array. A value of AST__BAD is returned if no value has -* been set for the parameter. - -* Parameters: -* this -* A pointer to the WcsMap. -* i -* Zero based axis index. -* m -* Zero based parameter index. - -* Returned Value: -* The value of the requested attribute, of AST__BAD if not set. - -*- -*/ - -/* Local Variables: */ - double ret; - int npar; - int mxpar; - -/* Initialise */ - ret = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return ret; - -/* Validate the axis index. */ - if( i < 0 || i >= astGetNin( this ) ){ - astError( AST__AXIIN, "astGetPV(%s): Axis index (%d) is invalid in " - "attribute PV%d_%d - it should be in the range 1 to %d.", - status, astGetClass( this ), i + 1, i + 1, m, astGetNin( this ) ); - -/* Find the maximum number of parameters allowed for the axis. */ - } else { - mxpar = astGetPVMax( this, i ); - -/* Validate the parameter index. */ - if( m < 0 || m > mxpar ){ - astError( AST__AXIIN, "astGetPV(%s): Parameter index (%d) is invalid " - "in attribute PV%d_%d for a \"%s\" projection - it should be " - "in the range 0 to %d.", status, astGetClass( this ), m, i + 1, m, - FindPrjData( this->type, status )->ctype, mxpar ); - -/* For latitude parameters use the values in the "params" structure which will - have been defaulted. */ - } else if( i == astGetWcsAxis( this, 1 ) ) { - ret = (this->params).p[ m ]; - -/* For other axes, see if the arrays stored in the WcsMap structure extend as - far as the requested parameter. If so, return the required attribute value. - Otherwise the AST__BAD value initialised above is retained. */ - } else if( this->np && this->p ){ - npar = this->np[ i ]; - if( m < npar && this->p[ i ] ) ret = this->p[ i ][ m ]; - } - -/* FITS-WCS paper II gives defaults for the first 3 longitude axis - parameters. The AST-specific TPN projection does not use this - convention since it needs all projection parameters to specify - correction terms. */ - if( ret == AST__BAD && i == astGetWcsAxis( this, 0 ) && - astGetWcsType( this ) != AST__TPN ) { - -/* Parameter zero has a default of zero. */ - if( m == 0 ) { - ret = 0.0; - -/* Parameter one has a default equal to the native longitude of the - reference point of the projection, in degrees. */ - } else if( m == 1 ) { - ret = astGetNatLon( this )*AST__DR2D; - -/* Parameter two has a default equal to the native latitude of the - reference point of the projection (in degrees). This is constant for - most projection, but for some (the conics) it is specified by - projection one on the latitude axis. */ - } else if( m == 2 ) { - ret = astGetNatLat( this )*AST__DR2D; - } - } - } - - return ret; - -} - -static int GetPVMax( AstWcsMap *this, int i, int *status ) { -/* -*+ -* Name: -* astGetPVMax - -* Purpose: -* Get the maximum projection parameter index for a WcsMap. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* int astGetPVMax( AstWcsMap *this, int i ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns the largest legal projection parameter index -* for a specified axis of the given WcsMap (i.e. the largest value of -* "m" in the attribute "PVi_m"). - -* Parameters: -* this -* A pointer to the WcsMap. -* i -* Zero based axis index. - -* Returned Value: -* The largest legal projection parameter index, or -1 if no -* projection parameters are allowed on the specified axis. - -*- -*/ - -/* Local Variables: */ - int mxpar; - -/* Initialise */ - mxpar = 0; - -/* Check the global error status. */ - if ( !astOK ) return -1; - -/* Validate the axis index. */ - if( i < 0 || i >= astGetNin( this ) ){ - astError( AST__AXIIN, "astGetPVMax(%s): Axis index (%d) is invalid in " - "attribute PVMax(%d) - it should be in the range 1 to %d.", - status, astGetClass( this ), i + 1, i + 1, astGetNin( this ) ); - -/* Find the maximum number of parameters allowed for the axis. */ - } else if( i == astGetWcsAxis( this, 0 ) ) { - mxpar = astSizeOf( this->params.p2 )/sizeof( double ); - - } else if( i == astGetWcsAxis( this, 1 ) ) { - mxpar = astSizeOf( this->params.p )/sizeof( double ); - - } - -/* The mxpar variable holds the max number of parameters. Return the the - largest legal parameter index (one less than the max number of - parameters). */ - return mxpar - 1; -} - -static void InitPrjPrm( AstWcsMap *this, int *status ) { -/* -* Name: -* InitPrjPrm - -* Purpose: -* Initialise the WcsLib PrjPrm structure, assigning default values for -* missing parameters. - -* Type: -* Private function. - -* Synopsis: -* void InitPrjPrm( AstWcsMap *this, int *status ) - -* Description: -* This function initializes the projection parameter information -* stored within the WcsLib AstPrjPrm structure associated with the -* supplied WcsMap. Default values are assigned to any unspecified -* parameter values. AST__BAD values are assigned if any parameters -* have not been supplied for which there is no default. - -* Parameters: -* this -* The WcsMap. -* status -* Pointer to the inherited status variable. - -*/ - - -/* Local Variables: */ - struct AstPrjPrm *params; /* The AstPrjPrm structure from the WcsMap */ - int i; /* Loop index */ - int latax; /* Index of latitude axis */ - int lonax; /* Index of longitude axis */ - int npar; /* No. of parameters supplied */ - int plen; /* Length of params array */ - int plen2; /* Length of latitude params array */ - int type; /* Projection type */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to the AstPrjPrm structure*/ - params = &(this->params); - -/* Tell the routines within the WcsLib "proj.c" module to re-calculate - intermediate values. */ - params->flag = 0; - params->r0 = 0; - -/* If this is a TPN projection, indicate whether or not the - transformation should include the TAN projection or just the - polynomial transformation. */ - if( this->type == AST__TPN ) params->n = astGetTPNTan( this ); - -/* Find the max number of projection parameters associated with each - axis.*/ - plen2 = astSizeOf( params->p2 )/sizeof( double ); - plen = astSizeOf( params->p )/sizeof( double ); - -/* Initially set all parameter to AST__BAD. */ - for( i = 0; i < plen; i++ ) (params->p)[i] = AST__BAD; - for( i = 0; i < plen2; i++ ) (params->p2)[i] = AST__BAD; - -/* If the WcsMap contains any projection parameter values... */ - if( this->np && this->p ){ - -/* Get the index of the latitude axis. Currently, all projection - parameters are associated with the latitude axis (except for - the TPN projection, which is a hang-over from a earlier draft of the - FITS-WCS paper). */ - latax = astGetWcsAxis( this, 1 ); - -/* Find the number of projection parameters in the WcsMap for the - latitude axis. */ - npar = (this->np)[ latax ]; - if( npar > plen ) { - astError( AST__INTER, "InitPrjPrm(WcsMap): Too many projection " - "parameters on the latitude axis (%d > %d) (internal " - "AST programming error).", status, npar, plen ); - } - -/* Copy the parameters to the AstPrjPrm structure. Do not copy more than - can be stored in the AstPrjPrm structure. */ - for( i = 0; i < npar && i < plen; i++ ) { - (params->p)[ i ] = (this->p)[ latax ][ i ]; - } - -/* Do the same for the longitude axis (for the benefit of the TPN projection). */ - lonax = astGetWcsAxis( this, 0 ); - npar = (this->np)[ lonax ]; - - if( npar > plen2 ) { - astError( AST__INTER, "InitPrjPrm(WcsMap): Too many projection " - "parameters on the longitude axis (%d > %d) (internal " - "AST programming error).", status, npar, plen2 ); - } - - for( i = 0; i < npar && i < plen2; i++ ) { - (params->p2)[ i ] = (this->p)[ lonax ][ i ]; - } - - } - -/* Get the projection type. */ - type = astGetWcsType( this ); - -/* First supply default values for any missing projection parameters which - do not default to zero. */ - if( type == AST__SZP ){ - if( (params->p)[ 3 ] == AST__BAD ) (params->p)[ 3 ] = 90.0; - - } else if( type == AST__AIR ){ - if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 90.0; - - } else if( type == AST__CYP ){ - if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 1.0; - if( (params->p)[ 2 ] == AST__BAD ) (params->p)[ 2 ] = 1.0; - - } else if( type == AST__CEA ){ - if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 1.0; - - } else if( type == AST__TPN ){ - if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 1.0; - if( (params->p2)[ 1 ] == AST__BAD ) (params->p2)[ 1 ] = 1.0; - - } else if( type == AST__HPX ){ - if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 4.0; - if( (params->p)[ 2 ] == AST__BAD ) (params->p)[ 2 ] = 3.0; - - } - -/* Now use a default value of zero for any remaining unspecified values, - except for un-defaultable projection parameters. */ - for( i = 0; i < plen; i++ ){ - -/* Retain any AST__BAD value for these undefaultable parameters. */ - if( i == 1 && ( type == AST__BON || - type == AST__COP || type == AST__COE || - type == AST__COD || type == AST__COO ) ){ - -/* Use a default of zero for all other parameters. */ - } else { - if( (params->p)[ i ] == AST__BAD ) (params->p)[ i ] = 0.0; - } - } - -/* Do the same for the latitude projection parameters (if any) */ - for( i = 0; i < plen2; i++ ){ - if( i == 1 && ( type == AST__BON || - type == AST__COP || type == AST__COE || - type == AST__COD || type == AST__COO ) ){ - } else { - if( (params->p2)[ i ] == AST__BAD ) (params->p2)[ i ] = 0.0; - } - } -} - -void astInitWcsMapVtab_( AstWcsMapVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitWcsMapVtab - -* Purpose: -* Initialise a virtual function table for a WcsMap. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* void astInitWcsMapVtab( AstWcsMapVtab *vtab, const char *name ) - -* Class Membership: -* WcsMap vtab initialiser. - -* Description: -* This function initialises the component of a virtual function -* table which is used by the WcsMap class. - -* Parameters: -* vtab -* Pointer to the virtual function table. The components used by -* all ancestral classes will be initialised if they have not already -* been initialised. -* name -* Pointer to a constant null-terminated character string which contains -* the name of the class to which the virtual function table belongs (it -* is this pointer value that will subsequently be returned by the Object -* astClass function). -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstObjectVtab *object; /* Pointer to Object component of Vtab */ - AstMappingVtab *mapping; /* Pointer to Mapping 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. */ - astInitMappingVtab( (AstMappingVtab *) vtab, name ); - -/* Store a unique "magic" value in the virtual function table. This - will be used (by astIsAWcsMap) 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 = &(((AstMappingVtab *) vtab)->id); - -/* Initialise member function pointers. */ -/* ------------------------------------ */ -/* Store pointers to the member functions (implemented here) that provide - virtual methods for this class. */ - vtab->ClearPV = ClearPV; - vtab->GetNatLat = GetNatLat; - vtab->GetNatLon = GetNatLon; - vtab->GetPV = GetPV; - vtab->GetWcsAxis = GetWcsAxis; - vtab->GetPVMax = GetPVMax; - vtab->GetWcsType = GetWcsType; - vtab->SetPV = SetPV; - vtab->TestPV = TestPV; - vtab->IsZenithal = IsZenithal; - - vtab->ClearFITSProj = ClearFITSProj; - vtab->TestFITSProj = TestFITSProj; - vtab->GetFITSProj = GetFITSProj; - vtab->SetFITSProj = SetFITSProj; - - vtab->ClearTPNTan = ClearTPNTan; - vtab->TestTPNTan = TestTPNTan; - vtab->GetTPNTan = GetTPNTan; - vtab->SetTPNTan = SetTPNTan; - -/* 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; - parent_getobjsize = object->GetObjSize; - object->GetObjSize = GetObjSize; - - parent_clearattrib = object->ClearAttrib; - object->ClearAttrib = ClearAttrib; - parent_getattrib = object->GetAttrib; - object->GetAttrib = GetAttrib; - parent_setattrib = object->SetAttrib; - object->SetAttrib = SetAttrib; - parent_testattrib = object->TestAttrib; - object->TestAttrib = TestAttrib; - - parent_transform = mapping->Transform; - mapping->Transform = Transform; - - parent_mapsplit = mapping->MapSplit; - mapping->MapSplit = MapSplit; - -/* Store replacement pointers for methods which will be over-ridden by - new member functions implemented here. */ - object->Equal = Equal; - mapping->MapMerge = MapMerge; - -/* Declare the destructor and copy constructor. */ - astSetDelete( (AstObjectVtab *) vtab, Delete ); - astSetCopy( (AstObjectVtab *) vtab, Copy ); - -/* Declare the class dump function. */ - astSetDump( vtab, Dump, "WcsMap", "FITS-WCS sky projection" ); - -/* If we have just initialised the vtab for the current class, indicate - that the vtab is now initialised, and store a pointer to the class - identifier in the base "object" level of the vtab. */ - if( vtab == &class_vtab ) { - class_init = 1; - astSetVtabClassIdentifier( vtab, &(vtab->id) ); - } -} - -static int IsZenithal( AstWcsMap *this, int *status ){ -/* -*+ -* Name: -* IsZenithal - -* Purpose: -* Determine if this WcsMap represents a zenithal projection. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* int IsZenithal( AstWcsMap *this, int *status ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns a flag indicating if this WcsMap is a zenithal -* projection. Some projections which are classed as zenithal in the -* Calabretta and Greisen paper are only genuinely zenithal if the -* projection parameters have certain values. These projections are -* not considered to be zenithal unless the projection parameters have -* appropriate values. - -* Parameters: -* this -* The WcsMap. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value if the WcsMap represents a zenithal projection. - -*- -*/ - -/* Local Variables: */ - double p1; /* PVi_1 */ - double p2; /* PVi_2 */ - double p3; /* PVi_3 */ - int latax; /* Index of latitude axis */ - int ret; /* Returned flag */ - int type; /* Projection type */ - -/* Initialise the returned value. */ - ret = 0; - -/* Check the global error status. */ - if ( !astOK ) return ret; - -/* Get the projection type. */ - type = astGetWcsType( this ); - -/* Get the index of the latitude axis. */ - latax = astGetWcsAxis( this, 1 ); - -/* The following are always zenithal... */ - if( type == AST__TAN || type == AST__STG || type == AST__ARC || - type == AST__ZPN || type == AST__ZEA || type == AST__AIR || - type == AST__TPN ) { - ret = 1; - -/* The following are sometimes zenithal... */ - } else if( type == AST__AZP ) { - p2 = astGetPV( this, latax, 2 ); - if( p2 == AST__BAD || p2 == 0.0 ) ret = 1; - - } else if( type == AST__SIN ) { - p1 = astGetPV( this, latax, 1 ); - p2 = astGetPV( this, latax, 2 ); - if( p1 == AST__BAD ) p1 = 0.0; - if( p2 == AST__BAD ) p2 = 0.0; - if( p1 == 0.0 && p2 == 0.0 ) ret = 1; - - } else if( type == AST__SZP ) { - p3 = astGetPV( this, latax, 2 ); - if( p3 == AST__BAD ) p3 = 90.0; - if( p3 == 90.0 || p3 == -90.0 ) ret = 1; - - } - - return ret; -} - -static int LongRange( const PrjData *prjdata, struct AstPrjPrm *params, - double *high, double *low, int *status ){ -/* -* -* Name: -* LongRange - -* Purpose: -* See if primary range of longitude produced by a WCSLIB mapping is -* [0,360] or [-180,+180]. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* void LongRange( const PrjData *prjdata, struct AstPrjPrm *params, -* double *high, double *low, int *status ) - -* Class Membership: -* WcsMap internal utility function. - -* Description: -* This function uses the WCSLIB library to transform the supplied input -* positions. - -* Parameters: -* prjdata -* A pointer to information about the mapping. -* params -* Pointer to a WCSLIB "AstPrjPrm" structure containing the projection -* parameters, etc. -* high -* A pointer to a location at which is returned the upper bound of -* the primary longitude range. -* low -* A pointer to a location at which is returned the lower bound of -* the primary longitude range. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A flag indicating if the sky->xy transformation is cyclic (i.e. -* [a,0] gets mapped to the same (x,y) position as [a+2.PI,0]). -*/ - - -/* Local Variables: */ - int point; /* Loop counter for points */ - static double xx[ 4 ] = { -1.0E-6, 0.0, 1.0E-6, 0.0 }; - static double yy[ 4 ] = { 0.0, 1.0E-6, 0.0, -1.0E-6 }; - double aa; - double bb; - double xxx[ 2 ]; - double yyy[ 2 ]; - int cyclic; - -/* Initialise the returned values. */ - *high = 180.0; - *low = -180.0; - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Project each of the points. If any longitude value is found which is - greater than 180 degrees, return [0,360] as the longitude range. */ - for( point = 0; point < 4; point++ ){ - if( !prjdata->WcsRev( xx[ point ], yy[ point ], params, &aa, &bb ) ){ - if( aa > 180.0 ){ - *high = 360.0; - *low = 0.0; - break; - } - } - } - -/* See if the projection is cyclic. Transform the sky positions [90,bb] and - [450,bb] into cartesian positions and see if they are the same. */ - prjdata->WcsFwd( 90.0, bb, params, xxx, yyy ); - prjdata->WcsFwd( 450.0, bb, params, xxx + 1, yyy + 1 ); - cyclic = ( fabs( xxx[ 0 ] - xxx[ 1 ] ) < 1.0E-10 && - fabs( yyy[ 0 ] - yyy[ 1 ] ) < 1.0E-10 ); - -/* Return. */ - return cyclic; - -} - -static int Map( AstWcsMap *this, int forward, int npoint, double *in0, - double *in1, double *out0, double *out1, int *status ){ -/* -* -* Name: -* Map - -* Purpose: -* Transform a set of points using a function from the WCSLIB library. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* int Map( AstWcsMap *this, int forward, int npoint, double *in0, -* double *in1, double *out0, double *out1 ) - -* Class Membership: -* WcsMap internal utility function. - -* Description: -* This function uses the WCSLIB library to transform the supplied input -* positions. - -* Parameters: -* this -* Pointer to the WcsMap. -* forward -* A non-zero value indicates that the forward projection from -* (long,lat) to (x,y) is required, while a zero value requests the -* reverse transformation. -* npoint -* The number of points to transform (i.e. the size of the -* in0, in1, out0 and out1 arrays). -* in0 -* A pointer to the input coordinate data for the 0th axis (i.e. -* longitude or X depending on "forward"). -* in1 -* A pointer to the input coordinate data for the 1st axis (i.e. -* latitude or Y depending on "forward"). -* out0 -* A pointer to the returned output coordinate data for the 0th axis -* (i.e. X or longitude depending on "forward"). -* out1 -* A pointer to the returned output coordinate data for the 1st axis -* (i.e. Y or latitude depending on "forward"). - -* Returned Value: -* The status value: 0 - Success -* 1 - Unrecognised projection type -* 2 - Invalid projection parameters values. -* 4 - Error existed on entry -* 100 - 399: Longitude axis projection parameter -* (status-100) not supplied. -* 400 - 699: Latitude axis projection parameter -* (status-400) not supplied. - - -* Notes: -* - This function does not report any errors. Reporting of suitable -* error messages is the responsibility of the calling function. -* - The value 4 will be returned if this function is invoked with the -* global error status set. -* -*/ - -/* Local Variables: */ - const PrjData *prjdata; /* Information about the projection */ - double factor; /* Factor that scales input into radians. */ - double latitude; /* Latitude value in degrees */ - double longhi; /* Upper longitude limit in degrees */ - double longitude; /* Longitude value in degrees */ - double longlo; /* Lower longitude limit in degrees */ - double x; /* X Cartesian coordinate in degrees */ - double y; /* Y Cartesian coordinate in degrees */ - int cyclic; /* Is sky->xy transformation cyclic? */ - int i; /* Loop count */ - int plen; /* Length of proj par array */ - int point; /* Loop counter for points */ - int type; /* Projection type */ - int wcs_status; /* Status from WCSLIB functions */ - struct AstPrjPrm *params; /* Pointer to structure holding WCSLIB info */ - -/* Check the global error status. */ - if ( !astOK ) return 4; - -/* Initialise variables to avoid compiler warnings. */ - longlo = AST__BAD; - longhi = AST__BAD; - -/* Store the projection type. */ - type = astGetWcsType( this ); - -/* Get information about the projection. */ - prjdata = FindPrjData( type, status ); - -/* Return if there are no WcsLib mapping functons associated with the - projection. */ - if( ( !prjdata->WcsFwd && forward ) || - ( !prjdata->WcsRev && !forward ) ) return 1; - -/* Check that all necessary projection parameters have been supplied, or - can be defaulted. */ - params = &(this->params); - plen = astSizeOf( params->p )/sizeof( double ); - for( i = 0; i < plen; i++ ) { - if( ( params->p)[ i ] == AST__BAD ) return 400+i; - } - -/* If we are doing a reverse mapping, get the acceptable range of longitude - values. */ - cyclic = forward ? 0 : LongRange( prjdata, params, &longhi, &longlo, - status ); - -/* The WcsMap input and output values are normally in radians, but if - the TPNTan attribute has been reset then they are in degrees. The - WCSLIB projection functions always expect and return degrees. Get - the factor that scales the WcsMap input into radians. */ - factor = astGetTPNTan( this ) ? 1.0 : AST__DD2R; - -/* Loop to apply the projection to each point in turn, checking for - (and propagating) bad values in the process. */ - for ( point = 0; point < npoint; point++ ) { - if ( in0[ point ] == AST__BAD || - in1[ point ] == AST__BAD ){ - out0[ point ] = AST__BAD; - out1[ point ] = AST__BAD; - } else { - -/* First deal with forward projection calls */ - if ( forward ){ - -/* The input coordinates are assumed to be longitude and latitude, in - radians or degrees (as specified by the TPNTan attribute). Convert them - to degrees ensuring that the longitude value is in the range [-180,180] - and the latitude is in the range [-90,90] (as required by the WCSLIB - library). Any point with a latitude outside the range [-90,90] is - converted to the equivalent point on the complementary meridian. */ - latitude = AST__DR2D*palDrange( factor*in1[ point ] ); - if ( latitude > 90.0 ){ - latitude = 180.0 - latitude; - longitude = AST__DR2D*palDrange( AST__DPI + factor*in0[ point ] ); - - } else if ( latitude < -90.0 ){ - latitude = -180.0 - latitude; - longitude = AST__DR2D*palDrange( AST__DPI + factor*in0[ point ] ); - - } else { - longitude = AST__DR2D*palDrange( factor*in0[ point ] ); - } - -/* Call the relevant WCSLIB forward projection function. */ - wcs_status = prjdata->WcsFwd( longitude, latitude, params, &x, &y ); - -/* Store the returned Cartesian coordinates, converting them from degrees - to radians. If the position could not be projected, use the value - AST__BAD. Abort for any other bad status. */ - if( wcs_status == 0 ){ - out0[ point ] = (AST__DD2R/factor)*x; - out1[ point ] = (AST__DD2R/factor)*y; - - } else if( wcs_status == 1 ){ - return 2; - - } else if( wcs_status == 2 ){ - out0[ point ] = AST__BAD; - out1[ point ] = AST__BAD; - - } else { - return wcs_status; - } - -/* Now deal with reverse projection calls */ - } else { - -/* Convert the supplied Cartesian coordinates from radians to degrees. */ - x = (AST__DR2D*factor)*in0[ point ]; - y = (AST__DR2D*factor)*in1[ point ]; - -/* Call the relevant WCSLIB reverse projection function. */ - wcs_status = prjdata->WcsRev( x, y, params, &longitude, &latitude ); - -/* Store the returned longitude and latitude, converting them from degrees - to radians. Many projections (ARC, AIT, ZPN, etc) are not cyclic (i.e. - [long,lat]=[0,0] does not get mapped to the same place as - [long,lat]=[360,0] ). Only accept values in the primary longitude or - latitude ranges. This avoids (x,y) points outside the physical domain - of the mapping being assigned valid (long,lat) values. */ - if( wcs_status == 0 ){ - if( ( cyclic || ( longitude < longhi && - longitude >= longlo ) ) && - fabs( latitude ) <= 90.0 ){ - - out0[ point ] = (AST__DD2R/factor)*longitude; - out1[ point ] = (AST__DD2R/factor)*latitude; - - } else { - out0[ point ] = AST__BAD; - out1[ point ] = AST__BAD; - } - -/* Abort if projection parameters were unusable. */ - } else if( wcs_status == 1 ){ - return 2; - -/* If the position could not be projected, use the value AST__BAD. */ - } else if( wcs_status == 2 ){ - out0[ point ] = AST__BAD; - out1[ point ] = AST__BAD; - -/* Abort if projection parameters were not supplied. */ - } else { - return wcs_status; - } - - } - - } - - } - - return 0; -} - -static int MapMerge( AstMapping *this, int where, int series, int *nmap, - AstMapping ***map_list, int **invert_list, int *status ) { -/* -* Name: -* MapMerge - -* Purpose: -* Simplify a sequence of Mappings containing a WcsMap. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* int MapMerge( AstMapping *this, int where, int series, int *nmap, -* AstMapping ***map_list, int **invert_list, int *status ) - -* Class Membership: -* WcsMap method (over-rides the protected astMapMerge method -* inherited from the Mapping class). - -* Description: -* This function attempts to simplify a sequence of Mappings by -* merging a nominated WcsMap in the sequence with its neighbours, -* so as to shorten the sequence if possible. -* -* In many cases, simplification will not be possible and the -* function will return -1 to indicate this, without further -* action. -* -* In most cases of interest, however, this function will either -* attempt to replace the nominated WcsMap with a Mapping which it -* considers simpler, or to merge it with the Mappings which -* immediately precede it or follow it in the sequence (both will -* normally be considered). This is sufficient to ensure the -* eventual simplification of most Mapping sequences by repeated -* application of this function. -* -* In some cases, the function may attempt more elaborate -* simplification, involving any number of other Mappings in the -* sequence. It is not restricted in the type or scope of -* simplification it may perform, but will normally only attempt -* elaborate simplification in cases where a more straightforward -* approach is not adequate. - -* Parameters: -* this -* Pointer to the nominated WcsMap which is to be merged with -* its neighbours. This should be a cloned copy of the WcsMap -* pointer contained in the array element "(*map_list)[where]" -* (see below). This pointer will not be annulled, and the -* WcsMap it identifies will not be modified by this function. -* where -* Index in the "*map_list" array (below) at which the pointer -* to the nominated WcsMap resides. -* series -* A non-zero value indicates that the sequence of Mappings to -* be simplified will be applied in series (i.e. one after the -* other), whereas a zero value indicates that they will be -* applied in parallel (i.e. on successive sub-sets of the -* input/output coordinates). -* nmap -* Address of an int which counts the number of Mappings in the -* sequence. On entry this should be set to the initial number -* of Mappings. On exit it will be updated to record the number -* of Mappings remaining after simplification. -* map_list -* Address of a pointer to a dynamically allocated array of -* Mapping pointers (produced, for example, by the astMapList -* method) which identifies the sequence of Mappings. On entry, -* the initial sequence of Mappings to be simplified should be -* supplied. -* -* On exit, the contents of this array will be modified to -* reflect any simplification carried out. Any form of -* simplification may be performed. This may involve any of: (a) -* removing Mappings by annulling any of the pointers supplied, -* (b) replacing them with pointers to new Mappings, (c) -* inserting additional Mappings and (d) changing their order. -* -* The intention is to reduce the number of Mappings in the -* sequence, if possible, and any reduction will be reflected in -* the value of "*nmap" returned. However, simplifications which -* do not reduce the length of the sequence (but improve its -* execution time, for example) may also be performed, and the -* sequence might conceivably increase in length (but normally -* only in order to split up a Mapping into pieces that can be -* more easily merged with their neighbours on subsequent -* invocations of this function). -* -* If Mappings are removed from the sequence, any gaps that -* remain will be closed up, by moving subsequent Mapping -* pointers along in the array, so that vacated elements occur -* at the end. If the sequence increases in length, the array -* will be extended (and its pointer updated) if necessary to -* accommodate any new elements. -* -* Note that any (or all) of the Mapping pointers supplied in -* this array may be annulled by this function, but the Mappings -* to which they refer are not modified in any way (although -* they may, of course, be deleted if the annulled pointer is -* the final one). -* invert_list -* Address of a pointer to a dynamically allocated array which, -* on entry, should contain values to be assigned to the Invert -* attributes of the Mappings identified in the "*map_list" -* array before they are applied (this array might have been -* produced, for example, by the astMapList method). These -* values will be used by this function instead of the actual -* Invert attributes of the Mappings supplied, which are -* ignored. -* -* On exit, the contents of this array will be updated to -* correspond with the possibly modified contents of the -* "*map_list" array. If the Mapping sequence increases in -* length, the "*invert_list" array will be extended (and its -* pointer updated) if necessary to accommodate any new -* elements. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* If simplification was possible, the function returns the index -* in the "map_list" array of the first element which was -* modified. Otherwise, it returns -1 (and makes no changes to the -* arrays supplied). - -* Notes: -* - A value of -1 will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstMapping *mc[2]; /* Copies of supplied Mappings to swap */ - AstMapping *smc0; /* Simplied Mapping */ - AstMapping *smc1; /* Simplied Mapping */ - AstWcsMap *newwcsmap; /* The WcsMap after swapping */ - const char *nclass; /* Pointer to neighbouring Mapping class */ - const char *class1; /* Pointer to first Mapping class string */ - const char *class2; /* Pointer to second Mapping class string */ - int do1; /* Would a backward swap make a simplification? */ - int do2; /* Would a forward swap make a simplification? */ - int i1; /* Lower index of the two WcsMaps being merged */ - int i2; /* Upper index of the two WcsMaps being merged */ - int i; /* Mapping index */ - int ic[2]; /* Copies of supplied invert flags to swap */ - int merge; /* Can WcsMap merge with a neighbour? */ - int nin; /* Number of coordinates for WcsMap */ - int nstep1; /* No. of Mappings backwards to next mergable Mapping */ - int nstep2; /* No. of Mappings forward to next mergable Mapping */ - int result; /* Result value to return */ - int swaphi; /* Can WcsMap be swapped with higher neighbour? */ - int swaplo; /* Can WcsMap be swapped with lower neighbour? */ - int type; /* Projection type */ - -/* Initialise. */ - result = -1; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Initialise variables to avoid "used of uninitialised variable" - messages from dumb compilers. */ - i1 = 0; - i2 = 0; - -/* Get the number of axes for the WcsMap. */ - nin = astGetNin( ( *map_list )[ where ] ); - -/* First of all, see if the WcsMap can be replaced by a simpler Mapping, - without reference to the neighbouring Mappings in the list. */ -/* ======================================================================*/ -/* WcsMaps with map type of AST__WCSBAD are equivalent to a UnitMap. */ - type = astGetWcsType( this ); - if( type == AST__WCSBAD ){ - -/* Annul the WcsMap pointer in the list and replace it with a UnitMap - pointer, and indicate that the forward transformation of the returned - UnitMap should be used. */ - (void) astAnnul( ( *map_list )[ where ] ); - ( *map_list )[ where ] = (AstMapping *) astUnitMap( nin, "", status ); - ( *invert_list )[ where ] = 0; - -/* Return the index of the first modified element. */ - result = where; - -/* If the WcsMap itself could not be simplified, see if it can be merged - with the Mappings on either side of it in the list. This can only be - done in series for a WcsMap. */ -/* ===================================================================== */ - } else if( series && *nmap > 1 ) { - -/* Store the classes of the neighbouring Mappings in the list. */ - class1 = ( where > 0 ) ? astGetClass( ( *map_list )[ where - 1 ] ) : NULL; - class2 = ( where < *nmap - 1 ) ? astGetClass( ( *map_list )[ where + 1 ] ) : NULL; - -/* A WcsMap can only combine with its own inverse. Set a flag indicating - that we have not yet found a neighbour with which the WcsMap can be - merged. */ - merge = 0; - -/* First check the lower neighbour (if any). */ - if( where > 0 ) { - i1 = where - 1; - i2 = where; - merge = CanMerge( ( *map_list )[ i1 ], (* invert_list)[ i1 ], - ( *map_list )[ i2 ], (* invert_list)[ i2 ], status ); - } - -/* If the WcsMap can not be merged with its lower neighbour, check its - upper neighbour (if any) in the same way. */ - if( !merge && where < *nmap - 1 ) { - i1 = where; - i2 = where + 1; - merge = CanMerge( ( *map_list )[ i1 ], (* invert_list)[ i1 ], - ( *map_list )[ i2 ], (* invert_list)[ i2 ], status ); - } - -/* If either neighbour has passed these checks, it is the inverse of the - WcsMap being checked. The pair of WcsMaps can be replaced by a single - UnitMap. */ - if( merge ) { - -/* Annul the two WcsMaps. */ - (void) astAnnul( ( *map_list )[ i1 ] ); - (void) astAnnul( ( *map_list )[ i2 ] ); - -/* Create a UnitMap, and store a pointer for it in place of the first - WcsMap. */ - ( *map_list )[ i1 ] = (AstMapping *) astUnitMap( nin, "", status ); - ( *invert_list )[ i1 ] = 0; - -/* Shuffle down the remaining Mappings to fill the hole left by the - second WcsMap. */ - for ( i = i2 + 1; i < *nmap; i++ ) { - ( *map_list )[ i - 1 ] = ( *map_list )[ i ]; - ( *invert_list )[ i - 1 ] = ( *invert_list )[ i ]; - } - -/* Clear the vacated element at the end. */ - ( *map_list )[ *nmap - 1 ] = NULL; - ( *invert_list )[ *nmap - 1 ] = 0; - -/* Decrement the Mapping count and return the index of the first - modified element. */ - (*nmap)--; - result = i1; - -/* If the WcsMap could not merge directly with either of its neighbours, - we consider whether it would be worthwhile to swap the WcsMap with - either of its neighbours. This can only be done for certain PermMaps, - and will usually require both Mappings to be modified (unless they are - commutative). The advantage of swapping the order of the Mappings is that - it may result in the WcsMap being adjacent to a Mapping with which it can - merge directly on the next invocation of this function, thus reducing the - number of Mappings in the list. */ - } else { - -/* Set a flag if we could swap the WcsMap with its higher neighbour. "do2" - is returned if swapping the Mappings would simplify either of the - Mappings. */ - if( where + 1 < *nmap ){ - swaphi = CanSwap( ( *map_list )[ where ], - ( *map_list )[ where + 1 ], - ( *invert_list )[ where ], - ( *invert_list )[ where + 1 ], &do2, - &newwcsmap, status ); - } else { - do2 = 0; - swaphi = 0; - newwcsmap = NULL; - } - -/* If so, step through each of the Mappings which follow the WcsMap, - looking for a Mapping with which the WcsMap could merge directly. Stop - when such a Mapping is found, or if a Mapping is found with which the - WcsMap could definitely not swap. Note the number of Mappings which - separate the WcsMap from the Mapping with which it could merge (if - any). */ - nstep2 = -1; - if( swaphi ){ - for( i2 = where + 1; i2 < *nmap; i2++ ){ - -/* See if we can merge with this Mapping. If so, note the number of steps - between the two Mappings and leave the loop. */ - if( CanMerge( ( *map_list )[ i2 ], ( *invert_list )[ i2 ], - (AstMapping *) newwcsmap, astGetInvert(newwcsmap), status ) ) { - nstep2 = i2 - where - 1; - break; - } - -/* If there is no chance that we can swap with this Mapping, leave the loop - with -1 for the number of steps to indicate that no merging is possible. - WcsMaps can swap only with some PermMaps. */ - nclass = astGetClass( ( *map_list )[ i2 ] ); - if( strcmp( nclass, "PermMap" ) ) { - break; - } - } - } - - if( newwcsmap ) newwcsmap = astAnnul( newwcsmap ); - -/* Do the same working forward from the WcsMap towards the start of the map - list. */ - if( where > 0 ){ - swaplo = CanSwap( ( *map_list )[ where - 1 ], - ( *map_list )[ where ], - ( *invert_list )[ where - 1 ], - ( *invert_list )[ where ], &do1, - &newwcsmap, status ); - } else { - do1 = 0; - swaplo = 0; - newwcsmap = NULL; - } - - nstep1 = -1; - if( swaplo ){ - for( i1 = where - 1; i1 >= 0; i1-- ){ - - if( CanMerge( ( *map_list )[ i1 ], ( *invert_list )[ i1 ], - (AstMapping *) newwcsmap, astGetInvert(newwcsmap), status ) ) { - nstep1 = where - 1 - i1; - break; - } - - nclass = astGetClass( ( *map_list )[ i1 ] ); - if( strcmp( nclass, "PermMap" ) ) { - break; - } - } - } - - if( newwcsmap ) newwcsmap = astAnnul( newwcsmap ); - -/* Choose which neighbour to swap with so that the WcsMap moves towards the - nearest Mapping with which it can merge. */ - if( do1 || ( - nstep1 != -1 && ( nstep2 == -1 || nstep2 > nstep1 ) ) ){ - nclass = class1; - i1 = where - 1; - i2 = where; - } else if( do2 || nstep2 != -1 ){ - nclass = class2; - i1 = where; - i2 = where + 1; - } else { - nclass = NULL; - } - -/* If there is a target Mapping in the list with which the WcsMap could - merge, replace the supplied Mappings with swapped Mappings to bring a - WcsMap closer to the target Mapping. */ - if( nclass ){ - WcsPerm( (*map_list) + i1, (*invert_list) + i1, where - i1, status ); - -/* Store the index of the first modified Mapping. */ - result = i1; - -/* If there is no Mapping available for merging, it may still be - advantageous to swap with a neighbour because the swapped Mapping may - be simpler than the original Mappings. */ - } else if( swaphi || swaplo ) { - -/* Choose a neightbour to swap with. If both are suitable for swapping, - swap with the lower. */ - if( swaplo ){ - nclass = class1; - i1 = where - 1; - i2 = where; - } else { - nclass = class2; - i1 = where; - i2 = where + 1; - } - -/* Take copies of the Mapping and Invert flag arrays so we do not change - the supplied values. */ - mc[ 0 ] = (AstMapping *) astCopy( ( (*map_list) + i1 )[0] ); - mc[ 1 ] = (AstMapping *) astCopy( ( (*map_list) + i1 )[1] ); - ic[ 0 ] = ( (*invert_list) + i1 )[0]; - ic[ 1 ] = ( (*invert_list) + i1 )[1]; - -/* Swap these Mappings. */ - WcsPerm( mc, ic, where - i1, status ); - -/* If neither of the swapped Mappings can be simplified further, then there - is no point in swapping the Mappings, so just annul the map copies. */ - smc0 = astSimplify( mc[0] ); - smc1 = astSimplify( mc[1] ); - - if( astGetClass( smc0 ) == astGetClass( mc[0] ) && - astGetClass( smc1 ) == astGetClass( mc[1] ) ) { - - mc[ 0 ] = (AstMapping *) astAnnul( mc[ 0 ] ); - mc[ 1 ] = (AstMapping *) astAnnul( mc[ 1 ] ); - -/* If one or both of the swapped Mappings could be simplified, then annul - the supplied Mappings and return the swapped mappings, storing the index - of the first modified Mapping. */ - } else { - (void ) astAnnul( ( (*map_list) + i1 )[0] ); - (void ) astAnnul( ( (*map_list) + i1 )[1] ); - - ( (*map_list) + i1 )[0] = mc[ 0 ]; - ( (*map_list) + i1 )[1] = mc[ 1 ]; - - ( (*invert_list) + i1 )[0] = ic[ 0 ]; - ( (*invert_list) + i1 )[1] = ic[ 1 ]; - - result = i1; - - } - -/* Annul the simplied Mappings */ - smc0 = astAnnul( smc0 ); - smc1 = astAnnul( smc1 ); - - } - } - } - -/* Return the result. */ - return result; -} - -static int *MapSplit( AstMapping *this_map, int nin, const int *in, AstMapping **map, int *status ){ -/* -* Name: -* MapSplit - -* Purpose: -* Create a Mapping representing a subset of the inputs of an existing -* WcsMap. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* int *MapSplit( AstMapping *this, int nin, const int *in, AstMapping **map, int *status ) - -* Class Membership: -* WcsMap method (over-rides the protected astMapSplit method -* inherited from the Mapping class). - -* Description: -* This function creates a new Mapping by picking specified inputs from -* an existing WcsMap. This is only possible if the specified inputs -* correspond to some subset of the WcsMap outputs. That is, there -* must exist a subset of the WcsMap outputs for which each output -* depends only on the selected WcsMap inputs, and not on any of the -* inputs which have not been selected. If this condition is not met -* by the supplied WcsMap, then a NULL Mapping is returned. - -* Parameters: -* this -* Pointer to the WcsMap to be split (the WcsMap is not actually -* modified by this function). -* nin -* The number of inputs to pick from "this". -* in -* Pointer to an array of indices (zero based) for the inputs which -* are to be picked. This array should have "nin" elements. If "Nin" -* is the number of inputs of the supplied WcsMap, then each element -* should have a value in the range zero to Nin-1. -* map -* Address of a location at which to return a pointer to the new -* Mapping. This Mapping will have "nin" inputs (the number of -* outputs may be different to "nin"). A NULL pointer will be -* returned if the supplied WcsMap has no subset of outputs which -* depend only on the selected inputs. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to a dynamically allocated array of ints. The number of -* elements in this array will equal the number of outputs for the -* returned Mapping. Each element will hold the index of the -* corresponding output in the supplied WcsMap. The array should be -* freed using astFree when no longer needed. A NULL pointer will -* be returned if no output Mapping can be created. - -* Notes: -* - If this function is invoked with the global error status set, -* or if it should fail for any reason, then NULL values will be -* returned as the function value and for the "map" pointer. -*/ - -/* Local Variables: */ - AstWcsMap *newwcs; /* Pointer to returned WcsMap */ - AstWcsMap *this; /* Pointer to WcsMap structure */ - int *result; /* Pointer to returned array */ - int *inperm; /* Input axis permutation array */ - int *outperm; /* Output axis permutation array */ - int i; /* Loop count */ - int iin; /* Mapping input index */ - int ilat; /* Index of latitude axis in new WcsMap */ - int ilatlon; /* Index of last lat or lon axis */ - int ilon; /* Index of longitude axis in new WcsMap */ - int latax; /* Index of latitude axis in supplied WcsMap */ - int lonax; /* Index of longitude axis in supplied WcsMap */ - int mnin; /* No. of Mapping inputs */ - int ok; /* Are input indices OK? */ - -/* Initialise */ - result = NULL; - *map = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Invoke the parent astMapSplit method to see if it can do the job. */ - result = (*parent_mapsplit)( this_map, nin, in, map, status ); - -/* If not, we provide a special implementation here. */ - if( !result ) { - -/* Get a pointer to the WcsMap structure. */ - this = (AstWcsMap *) this_map; - -/* Prevent compiler warnings. */ - ilatlon = -1; - -/* Allocate memory for the returned array. */ - result = astMalloc( sizeof( int )*(size_t) nin ); - if( astOK ) { - -/* Get the indices of the longitude and latitude axes in the WcsMap */ - lonax = astGetWcsAxis( this, 0 ); - latax = astGetWcsAxis( this, 1 ); - -/* See if the selected axes include the longitude and/or latitude axis. - At the same time check the axis indices are ok, and set up the output - axis array. */ - ilat = -1; - ilon = -1; - mnin = astGetNin( this ); - ok = 1; - for( i = 0; i < nin; i++ ) { - iin = in[ i ]; - if( iin < 0 || iin >= mnin ) { - ok = 0; - break; - } else if( iin == lonax ) { - ilon = i; - ilatlon = i; - } else if( iin == latax ) { - ilat = i; - ilatlon = i; - } - result[ i ] = iin; - } - -/* If any of the input indices were invalid, free the returned array. */ - if( !ok ) { - result = astFree( result ); - -/* If both longitude and latitude axes are selected, then the returned Mapping - is a WcsMap. Create one based on the supplied WcsMap. */ - } else if( ilat != -1 && ilon != -1 ) { - newwcs = astWcsMap( nin, astGetWcsType( this ), ilon + 1, ilat + 1, - "", status ); - CopyPV( this, newwcs, status ); - astSetInvert( newwcs, astGetInvert( this ) ); - *map = (AstMapping *) newwcs; - -/* If neither the longitude nor the latitude axis has been selected, then - the returned Mapping is a UnitMap. */ - } else if( ilat == -1 && ilon == -1 ) { - *map = (AstMapping *) astUnitMap( nin, "", status ); - -/* If only one of the latitude and longitude axes was selected we remove - it from the returned Mapping (a PermMap) and list of outputs */ - } else if( nin > 1 ) { - - for( i = ilatlon; i < nin - 1; i++ ) { - result[ i ] = result[ i + 1 ]; - } - result[ i ] = -1; - - inperm = astMalloc( sizeof( int )*(size_t) nin ); - outperm = astMalloc( sizeof( int )*(size_t) ( nin - 1 ) ); - if( outperm ) { - for( i = 0; i < ilatlon; i++ ) { - inperm[ i ] = i; - outperm[ i ] = i; - } - inperm[ ilatlon ] = INT_MAX; - for( i = ilatlon + 1; i < nin; i++ ) { - inperm[ i ] = i - 1; - outperm[ i - 1 ] = i; - } - - *map = (AstMapping *) astPermMap( nin, inperm, nin - 1, outperm, NULL, " ", status ); - - } - inperm = astFree( inperm ); - outperm = astFree( outperm ); - - } else { - result = astFree( result ); - } - } - } - -/* Free returned resources if an error has occurred. */ - if( !astOK ) { - result = astFree( result ); - *map = astAnnul( *map ); - } - -/* Return the list of output indices. */ - return result; -} - -static void PermGet( AstPermMap *map, int **outperm, int **inperm, - double **consts, int *status ){ -/* -* Name: -* PermGet - -* Purpose: -* Get the axis permutation and constants array for a PermMap. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* void PermGet( AstPermMap *map, int **outperm, int **inperm, -* double **const, int *status ) - -* Class Membership: -* WcsMap member function - -* Description: -* This function returns axis permutation and constants arrays which can -* be used to create a PermMap which is equivalent to the supplied PermMap. - -* Parameters: -* map -* The PermMap. -* outperm -* An address at which to return a popinter to an array of ints -* holding the output axis permutation array. The array should be -* released using astFree when no longer needed. -* inperm -* An address at which to return a popinter to an array of ints -* holding the input axis permutation array. The array should be -* released using astFree when no longer needed. -* consts -* An address at which to return a popinter to an array of doubles -* holding the constants array. The array should be released using -* astFree when no longer needed. -* status -* Pointer to the inherited status variable. - -* Notes: -* - NULL pointers are returned if an error has already occurred, or if -* this function should fail for any reason. -*/ - -/* Local Variables: */ - AstPointSet *pset1; /* PointSet holding input positions for PermMap */ - AstPointSet *pset2; /* PointSet holding output positions for PermMap */ - double **ptr1; /* Pointer to pset1 data */ - double **ptr2; /* Pointer to pset2 data */ - double *cnst; /* Pointer to constants array */ - double cn; /* Potential new constant value */ - double ip; /* Potential output axis index */ - double op; /* Potential input axis index */ - int *inprm; /* Pointer to input axis permutation array */ - int *outprm; /* Pointer to output axis permutation array */ - int i; /* Axis count */ - int nc; /* Number of constants stored so far */ - int nin; /* No. of input coordinates for the PermMap */ - int nout; /* No. of output coordinates for the PermMap */ - -/* Initialise. */ - if( outperm ) *outperm = NULL; - if( inperm ) *inperm = NULL; - if( consts ) *consts = NULL; - -/* Check the global error status and the supplied pointers. */ - if ( !astOK || !outperm || !inperm || !consts ) return; - -/* Initialise variables to avoid "used of uninitialised variable" - messages from dumb compilers. */ - nc = 0; - -/* Get the number of input and output axes for the supplied PermMap. */ - nin = astGetNin( map ); - nout = astGetNout( map ); - -/* Allocate the memory for the returned arrays. */ - outprm = (int *) astMalloc( sizeof( int )* (size_t) nout ); - inprm = (int *) astMalloc( sizeof( int )* (size_t) nin ); - cnst = (double *) astMalloc( sizeof( double )* (size_t) ( nout + nin ) ); - -/* Returned the pointers to these arrays.*/ - *outperm = outprm; - *inperm = inprm; - *consts = cnst; - -/* Create two PointSets, each holding two points, which can be used for - input and output positions with the PermMap. */ - pset1 = astPointSet( 2, nin, "", status ); - pset2 = astPointSet( 2, nout, "", status ); - -/* Set up the two input positions to be [0,1,2...] and [-1,-1,-1,...]. The - first position is used to enumerate the axes, and the second is used to - check for constant axis values. */ - ptr1 = astGetPoints( pset1 ); - if( astOK ){ - for( i = 0; i < nin; i++ ){ - ptr1[ i ][ 0 ] = ( double ) i; - ptr1[ i ][ 1 ] = -1.0; - } - } - -/* Use the PermMap to transform these positions in the forward direction. */ - (void) astTransform( map, pset1, 1, pset2 ); - -/* Look at the mapped positions to determine the output axis permutation - array. */ - ptr2 = astGetPoints( pset2 ); - if( astOK ){ - -/* No constant axis valeus found yet. */ - nc = 0; - -/* Do each output axis. */ - for( i = 0; i < nout; i++ ){ - -/* If the output axis value is copied from an input axis value, the index - of the appropriate input axis will be in the mapped first position. */ - op = ptr2[ i ][ 0 ]; - -/* If the output axis value is assigned a constant value, the result of - mapping the two different input axis values will be the same. */ - cn = ptr2[ i ][ 1 ]; - if( op == cn ) { - -/* We have found another constant. Store it in the constants array, and - store the index of the constant in the output axis permutation array. */ - cnst[ nc ] = cn; - outprm[ i ] = -( nc + 1 ); - nc++; - -/* If the output axis values are different, then the output axis value - must be copied from the input axis value. */ - } else { - outprm[ i ] = (int) ( op + 0.5 ); - } - } - } - -/* Now do the same thing to determine the input permutation array. */ - if( astOK ){ - for( i = 0; i < nout; i++ ){ - ptr2[ i ][ 0 ] = ( double ) i; - ptr2[ i ][ 1 ] = -1.0; - } - } - - (void) astTransform( map, pset2, 0, pset1 ); - - if( astOK ){ - - for( i = 0; i < nin; i++ ){ - - ip = ptr1[ i ][ 0 ]; - cn = ptr1[ i ][ 1 ]; - if( ip == cn ) { - - cnst[ nc ] = cn; - inprm[ i ] = -( nc + 1 ); - nc++; - - } else { - inprm[ i ] = (int) ( ip + 0.5 ); - } - } - } - -/* Annul the PointSets. */ - pset1 = astAnnul( pset1 ); - pset2 = astAnnul( pset2 ); - -/* If an error has occurred, attempt to free the returned arrays. */ - if( !astOK ) { - *outperm = (int *) astFree( (void *) *outperm ); - *inperm = (int *) astFree( (void *) *inperm ); - *consts = (double *) astFree( (void *) *consts ); - } - -/* Return. */ - return; -} - -static void SetAttrib( AstObject *this_object, const char *setting, int *status ) { -/* -* Name: -* SetAttrib - -* Purpose: -* Set an attribute value for a WcsMap. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* void SetAttrib( AstObject *this, const char *setting ) - -* Class Membership: -* WcsMap member function (over-rides the astSetAttrib protected -* method inherited from the Mapping class). - -* Description: -* This function assigns an attribute value for a WcsMap, the -* attribute and its value being specified by means of a string of -* the form: -* -* "attribute= value " -* -* Here, "attribute" specifies the attribute name and should be in -* lower case with no white space present. The value to the right -* of the "=" should be a suitable textual representation of the -* value to be assigned and this will be interpreted according to -* the attribute's data type. White space surrounding the value is -* only significant for string attributes. - -* Parameters: -* this -* Pointer to the WcsMap. -* setting -* Pointer to a null-terminated string specifying the new attribute -* value. -*/ - -/* Local Variables: */ - AstWcsMap *this; /* Pointer to the WcsMap structure */ - double dval; /* Attribute value */ - int len; /* Length of setting string */ - int nc; /* Number of characters read by astSscanf */ - int i; /* Axis index */ - int m; /* Projection parameter number */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the WcsMap structure. */ - this = (AstWcsMap *) this_object; - -/* Obtain the length of the setting string. */ - len = (int) strlen( setting ); - -/* Test for each recognised attribute in turn, using "astSscanf" to parse - the setting string and extract the attribute value (or an offset to - it in the case of string values). In each case, use the value set - in "nc" to check that the entire string was matched. Once a value - has been obtained, use the appropriate method to set it. */ - -/* ProjP(i). */ -/* --------- */ - if ( nc = 0, ( 2 == astSscanf( setting, "projp(%d)= %lg %n", &m, &dval, &nc ) ) - && ( nc >= len ) ) { - astSetPV( this, astGetWcsAxis( this, 1 ), m, dval ); - -/* PV. */ -/* --- */ - } else if ( nc = 0, ( 3 == astSscanf( setting, "pv%d_%d= %lg %n", &i, &m, &dval, &nc ) ) - && ( nc >= len ) ) { - astSetPV( this, i - 1, m, dval ); - -/* Define macros to see if the setting string matches any of the - read-only attributes of this class. */ -#define MATCH(attrib) \ - ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \ - ( nc >= len ) ) - -#define MATCH2(attrib) \ - ( nc = 0, ( 1 == astSscanf( setting, attrib "(%d)=%*[^\n]%n", &i, &nc ) ) && \ - ( nc >= len ) ) - -/* If the attribute was not recognised, use this macro to report an error - if a read-only attribute has been specified. */ - } else if ( MATCH( "wcstype" ) || - MATCH( "natlat" ) || - MATCH( "natlon" ) || - MATCH2( "wcsaxis" ) ) { - astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status, - setting, astGetClass( this ) ); - astError( AST__NOWRT, "This is a read-only attribute." , status); - -/* If the attribute is still not recognised, pass it on to the parent - method for further interpretation. */ - } else { - (*parent_setattrib)( this_object, setting, status ); - } - -/* Undefine macros local to this function. */ -#undef MATCH -#undef MATCH2 -} - -static void SetPV( AstWcsMap *this, int i, int m, double val, int *status ) { -/* -*+ -* Name: -* astSetPV - -* Purpose: -* Set the value of a PVi_m attribute. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* void astSetPV( AstWcsMap *this, int i, int m, double val ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function stores a value for the specified member of the PV -* attribute array. - -* Parameters: -* this -* A pointer to the WcsMap. -* i -* Zero based axis index. -* m -* Zero based parameter index. - -*- -*/ -/* Local Variables: */ - int naxis; /* No. of axes in WcsMap */ - int mm; /* Loop count */ - int mxpar; /* Max number of parameters allowed for the axis */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Find the number of axes in the WcsMap. */ - naxis = astGetNin( this ); - -/* Report an error if the object has been cloned (i.e. has a reference - count that is greater than one). */ - if( astGetRefCount( this ) > 1 ) { - astError( AST__IMMUT, "astSet(%s): Projection parameter values " - "within the supplied %s cannot be changed because the %s has " - "been cloned (programming error).", status, - astGetClass(this), astGetClass(this), astGetClass(this) ); - -/* Validate the axis index. */ - } else if( i < 0 || i >= naxis ){ - astError( AST__AXIIN, "astSetPV(%s): Axis index (%d) is invalid in " - "attribute PV%d_%d - it should be in the range 1 to %d.", - status, astGetClass( this ), i + 1, i + 1, m, naxis ); - -/* Validate the parameter index. */ - } else { - mxpar = astGetPVMax( this, i ); - if( m < 0 || m > mxpar ){ - astError( AST__AXIIN, "astSetPV(%s): Parameter index (%d) is invalid " - "in attribute PV%d_%d for a \"%s\" projection - it should be " - "in the range 0 to %d.", status, astGetClass( this ), m, i + 1, m, - FindPrjData( this->type, status )->ctype, mxpar ); - -/* If the dynamic arrays used to hold the parameters have not yet been - created, create them now, and store pointers to them in the WcsMap - structure. */ - } else { - if( !this->np || !this->p ) { - this->np = (int *) astMalloc( sizeof(int)*naxis ); - this->p = (double **) astMalloc( sizeof(double *)*naxis ); - if( astOK ) { - for( mm = 0; mm < naxis; mm++ ) { - this->np[ mm ] = 0; - this->p[ mm ] = NULL; - } - } - -/* Release the dynamic arrays if an error has occurred. */ - if( !astOK ) FreePV( this, status ); - - } - } - -/* Check we can use the arrays. */ - if( astOK ) { - -/* Ensure the dynamic array used to hold parameter values for the - specified axis is big enough to hold the specified parameter. */ - this->p[ i ] = (double *) astGrow( (void *) this->p[ i ], - m + 1, sizeof(double) ); - -/* Check we can use this array. */ - if( astOK ) { - -/* Store the supplied value in the relevant element of this array. */ - this->p[ i ][ m ] = val; - -/* If the array was extended to hold this parameter... */ - if( this->np[ i ] <= m ) { - -/* Fill any other new elements in this array with AST__BAD */ - for( mm = this->np[ i ]; mm < m; mm++ ) this->p[ i ][ mm ] = AST__BAD; - -/* Remember the new array size. */ - this->np[ i ] = m + 1; - } - } - } - } - -/* Re-initialize the values stored in the "AstPrjPrm" structure. */ - InitPrjPrm( this, status ); -} - -static void SetTPNTan( AstWcsMap *this, int val, int *status ) { -/* -*+ -* Name: -* astSetTPNTan - -* Purpose: -* Set the value of a TPNTan attribute. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* void astSetTPNTan( AstWcsMap *this, int val ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function stores a value for the TPNTan attribute and updates -* the projection parameters used by WCSLIB accordingly. - -* Parameters: -* this -* A pointer to the WcsMap. -* val -* New attribute value. - -*- -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Store the new value. */ - this->tpn_tan = ( val != 0 ); - -/* Re-initialize the values stored in the "AstPrjPrm" structure. */ - InitPrjPrm( this, status ); -} - -static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* TestAttrib - -* Purpose: -* Test if a specified attribute value is set for a WcsMap. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* int TestAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* WcsMap member function (over-rides the astTestAttrib protected -* method inherited from the Mapping class). - -* Description: -* This function returns a boolean result (0 or 1) to indicate whether -* a value has been set for one of a WcsMap's attributes. - -* Parameters: -* this -* Pointer to the WcsMap. -* attrib -* Pointer to a null-terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if a value has been set, otherwise zero. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstWcsMap *this; /* Pointer to the WcsMap structure */ - int i; /* Axis index */ - int m; /* Projection parameter index */ - int len; /* Length os supplied string */ - int nc; /* No. of characters read by astSscanf */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the WcsMap structure. */ - this = (AstWcsMap *) this_object; - -/* Obtain the length of the attrib string. */ - len = strlen( attrib ); - -/* Check the attribute name and test the appropriate attribute. */ - - -/* ProjP(i). */ -/* --------- */ - if ( nc = 0, ( 1 == astSscanf( attrib, "projp(%d)%n", &m, &nc ) ) - && ( nc >= len ) ) { - result = astTestPV( this, astGetWcsAxis( this, 1 ), m ); - -/* PV. */ -/* --- */ - } else if ( nc = 0, ( 2 == astSscanf( attrib, "pv%d_%d%n", &i, &m, &nc ) ) - && ( nc >= len ) ) { - result = astTestPV( this, i - 1, m ); - -/* If the name is not recognised, test if it matches any of the - read-only attributes of this class. If it does, then return - zero. */ - } else if ( !strcmp( attrib, "wcstype" ) || - !strcmp( attrib, "natlat" ) || - !strcmp( attrib, "natlon" ) || - ( nc = 0, ( 1 == astSscanf( attrib, "wcsaxis(%d)%n", &i, &nc ) ) - && ( nc >= len ) ) ) { - result = 0; - -/* If the attribute is still not recognised, pass it on to the parent - method for further interpretation. */ - } else { - result = (*parent_testattrib)( this_object, attrib, status ); - } - -/* Return the result, */ - return result; -} - -static int TestPV( AstWcsMap *this, int i, int m, int *status ) { -/* -*+ -* Name: -* astTestPV - -* Purpose: -* Test a PVi_m attribute. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* int astTestPV( AstWcsMap *this, int i, int m ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns 1 if a specified member of the PV attribute -* array is currently set, and 0 otherwise. - -* Parameters: -* this -* A pointer to the WcsMap. -* i -* Zero based axis index. -* m -* Zero based parameter index. - -* Returned Value: -* 1 if the attribute is set, 0 otherwise. - -*- -*/ -/* Local Variables: */ - int ret; - int npar; - int mxpar; - -/* Initialise */ - ret = 0; - -/* Check the global error status. */ - if ( !astOK ) return ret; - -/* Validate the axis index. */ - if( i < 0 || i >= astGetNin( this ) ){ - astError( AST__AXIIN, "astTestPV(%s): Axis index (%d) is invalid in " - "attribute PV%d_%d - it should be in the range 1 to %d.", - status, astGetClass( this ), i + 1, i + 1, m, astGetNin( this ) ); - -/* Find the maximum number of parameters allowed for the axis. */ - } else { - mxpar = astGetPVMax( this, i ); - -/* Ignore unused parameters. */ - if( m < 0 || m > mxpar ){ - -/* See if the parameter is currently set. */ - } else if( this->np && this->p ){ - npar = this->np[ i ]; - if( m < npar && this->p[ i ] ){ - ret = ( this->p[ i ][ m ] != AST__BAD ); - } - } - } - - return ret; -} - -static AstPointSet *Transform( AstMapping *this, AstPointSet *in, - int forward, AstPointSet *out, int *status ) { -/* -*+ -* Name: -* Transform - -* Purpose: -* Apply a WcsMap to a set of points. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* AstPointSet *Transform( AstMapping *this, AstPointSet *in, -* int forward, AstPointSet *out, int *status ) - -* Class Membership: -* WcsMap member function (over-rides the astTransform method inherited -* from the Mapping class). - -* Description: -* This function takes a WcsMap and a set of points encapsulated in a -* PointSet and transforms the points using the requested projection. - -* Parameters: -* this -* Pointer to the WcsMap. -* in -* Pointer to the PointSet holding the input coordinate data. -* 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: -* - Assuming the WcsMap has not been inverted, the forward mapping -* transforms spherical (longitude,latitude) pairs into Cartesian (x,y) -* pairs. Longitude and latitude values are given and returned in radians, -* and no restrictions are imposed on their ranges. X and Y values are -* also given and returned in radians, with no restrictions imposed on -* their ranges. -* - 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 WcsMap 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: */ - AstPointSet *result; /* Pointer to output PointSet */ - AstWcsMap *map; /* Pointer to WcsMap to be applied */ - double **ptr_in; /* Pointer to input coordinate data */ - double **ptr_out; /* Pointer to output coordinate data */ - int i; /* Axis count */ - int latax; /* Latitude axis index */ - int lonax; /* Longitude axis index */ - int npoint; /* Number of points */ - int status_value; /* Status from Map function */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Obtain a pointer to the WcsMap. */ - map = (AstWcsMap *) this; - -/* Apply the parent mapping using the stored pointer to the Transform member - function inherited from the parent Mapping class. This function validates - all arguments and generates an output PointSet if necessary, but does not - actually transform any coordinate values. */ - result = (*parent_transform)( this, in, forward, out, status ); - -/* We will now extend the parent astTransform method by performing the - calculations needed to generate the output coordinate values. */ - -/* Determine the numbers of points from the input PointSet and obtain pointers - for accessing the input and output coordinate values. */ - npoint = astGetNpoint( in ); - ptr_in = astGetPoints( in ); - ptr_out = astGetPoints( result ); - -/* If a genuine FITS-WCS projection is being performed... */ - if( astGetWcsType( map ) != AST__WCSBAD ){ - -/* Determine whether to apply the forward or inverse mapping, according to the - direction specified and whether the mapping has been inverted. */ - if ( astGetInvert( map ) ) forward = !forward; - -/* Do the coordinate transformation. */ - lonax = astGetWcsAxis( map, 0 ); - latax = astGetWcsAxis( map, 1 ); - status_value = Map( map, forward, npoint, ptr_in[ lonax ], ptr_in[ latax ], - ptr_out[ lonax ], ptr_out[ latax ], status ); - -/* Report an error if the projection type was unrecognised. */ - if ( status_value == 1 ) { - astError( AST__WCSTY, "astTransform(%s): The %s specifies an " - "illegal projection type ('%s').", status, astClass( this ), - astClass( this ), FindPrjData( map->type, status )->desc ); - -/* Report an error if the projection parameters were invalid. */ - } else if ( status_value == 2 ) { - astError( AST__WCSPA, "astTransform(%s): The %s projection " - "parameter values in this %s are unusable.", status, - astClass( this ), FindPrjData( map->type, status )->desc, - astClass( this ) ); - -/* Report an error if required projection parameters were not supplied. */ - } else if ( status_value >= 400 ) { - astError( AST__WCSPA, "astTransform(%s): Required projection " - "parameter PV%d_%d was not supplied for a %s " - "projection.", status, astClass( this ), latax+1, status_value - 400, - FindPrjData( map->type, status )->desc ); - - } else if ( status_value >= 100 ) { - astError( AST__WCSPA, "astTransform(%s): Required projection " - "parameter PV%d_%d was not supplied for a %s " - "projection.", status, astClass( this ), lonax+1, status_value - 100, - FindPrjData( map->type, status )->desc ); - } - -/* Copy the remaining axes (i.e. all axes except the longitude and latitude - axes) from the input to the output. */ - for( i = 0; i < astGetNcoord( in ); i++ ){ - if( ( i != lonax && i != latax ) ){ - (void) memcpy( ptr_out[ i ], ptr_in[ i ], sizeof( double )* - (size_t) npoint ); - } - - } - -/* If there is no FITS-WCS projection, just copy all the axes from input to - output. */ - } else { - for( i = 0; i < astGetNcoord( in ); i++ ){ - (void) memcpy( ptr_out[ i ], ptr_in[ i ], sizeof( double )* - (size_t) npoint ); - } - } - -/* If an error has occurred, attempt to delete the results PointSet. */ - if ( !astOK ) result = astDelete( result ); - -/* Return a pointer to the output PointSet. */ - return result; - -} - -int astWcsPrjType_( const char *ctype, int *status ){ -/* -*+ -* Name: -* astWcsPrjType - -* Purpose: -* Get the integer identifier for a WCSLIB projection given by a FITS -* CTYPE keyword value. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* int astWcsPrjType( const char *ctype ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns the integer identifier for the WCSLIB projection -* specified by the supplied FITS CTYPE keyword value. The returned -* value can be passed to astWcsMap to create a WcsMap which implements -* the corresponding projection. - -* Parameters: -* ctype -* A pointer to the last 4 characters of a FITS CTYPE1 (etc) keyword. - -* Returned Value: -* The integer identifier associated with the projection. - -* Notes: -* - A value of AST__WCSBAD is returned if the projection type is -* unknown, but no error is reported. -*- -*/ - - PrjData *data; - char buffer[81]; - const char *a; - char *b; - -/* Remove leading and trailing blanks from the supplied string. */ - a = ctype; - b = buffer; - while( *a && (b - buffer) < 80 ){ - if( !isspace( (int) *a ) ) { - *(b++) = *a; - } - a++; - } - *b = 0; - -/* Search for the projection in the list of available projectons. */ - data = PrjInfo; - while( data->prj != AST__WCSBAD && strcmp( data->ctype, buffer ) ) data ++; - - return data->prj; -} - -const char *astWcsPrjName_( int type, int *status ){ -/* -*+ -* Name: -* astWcsPrjName - -* Purpose: -* Get the name of a projection given its integer identifier. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* const char *astWcsPrjName( int type ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns a string holding 4 characters which can be -* used as the last 4 characters of a FITS CTYPE keyword value -* describing the WCSLIB projection specified by the supplied type. - -* Parameters: -* type -* The projection type. - -* Returned Value: -* A pointer to a null-terminated const character string holding the -* last 4 CTYPE characters describing the projection. - -* Notes: -* - This function attempts to execute even if an error has already -* occurred. -*- -*/ - - PrjData *data; - data = PrjInfo; - while( data->prj != AST__WCSBAD && data->prj != type ) data ++; - return data->ctype; -} - -const char *astWcsPrjDesc_( int type, int *status ){ -/* -*+ -* Name: -* astWcsPrjDesc - -* Purpose: -* Get a textual description of a projection given its integer -* identifier. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* const char *astWcsPrjDesc( int type ) - -* Class Membership: -* WcsMap protected function - -* Description: -* This function returns a pointer to a string string holding a -* textual description of the specified projection type. - -* Parameters: -* type -* The projection type. - -* Returned Value: -* A pointer to a null-terminated const character string holding the -* projection description. - -* Notes: -* - This function attempts to execute even if an error has already -* occurred. -*- -*/ - - PrjData *data; - data = PrjInfo; - while( data->prj != AST__WCSBAD && data->prj != type ) data ++; - return data->desc; -} - -static void WcsPerm( AstMapping **maps, int *inverts, int iwm, int *status ){ -/* -* Name: -* WcsPerm - -* Purpose: -* Swap a WcsMap and a PermMap. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* void WcsPerm( AstMapping **maps, int *inverts, int iwm, int *status ) - -* Class Membership: -* WcsMap member function - -* Description: -* A list of two Mappings is supplied containing a WcsMap and a -* PermMap. These Mappings are annulled, and replaced with -* another pair of Mappings consisting of a WcsMap and a PermMap -* in the opposite order. These Mappings are chosen so that their -* combined effect is the same as the original pair of Mappings. - -* Parameters: -* maps -* A pointer to an array of two Mapping pointers. -* inverts -* A pointer to an array of two invert flags. -* iwm -* The index within "maps" of the WcsMap. -* status -* Pointer to the inherited status variable. - -* Notes: -* - All links between input and output axes in the PermMap must -* be bi-directional, but there can be unconnected axes, and there -* need not be the same number of input and output axes. Both -* longitude and latitude axes must be passed by the PermMap. - -*/ - -/* Local Variables: */ - AstPermMap *pm; /* Pointer to the supplied PermMap */ - AstPermMap *newpm; /* Pointer to the returned PermMap */ - AstMapping *newwm; /* Pointer to the returned WcsMap */ - AstWcsMap *wm; /* Pointer to the supplied WcsMap */ - double *consts; /* Pointer to constants array */ - int *inperm; /* Pointer to input axis permutation array */ - int *outperm; /* Pointer to output axis permutation array */ - int latax; /* Index of latitude axis */ - int lonax; /* Index of longitude axis */ - int npin; /* No. of input axes in supplied PermMap */ - int npout; /* No. of output axes in supplied PermMap */ - int old_pinv; /* Invert value for the supplied PermMap */ - int old_winv; /* Invert value for the supplied WcsMap */ - int type; /* Projection type */ - int done; /* Have Mappings been swapped? */ - int i; /* AXis index */ - double *p; /* Pointer to input position */ - double *q; /* Pointer to output position */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Initialise variables to avoid "used of uninitialised variable" - messages from dumb compilers. */ - newpm = NULL; - newwm = NULL; - -/* Store pointers to the supplied WcsMap and the PermMap. */ - wm = (AstWcsMap *) maps[ iwm ]; - pm = (AstPermMap *) maps[ 1 - iwm ]; - -/* Temporarily set the Invert attribute of the supplied PermMap to the - supplied values. */ - old_pinv = astGetInvert( pm ); - astSetInvert( pm, inverts[ 1 - iwm ] ); - old_winv = astGetInvert( wm ); - astSetInvert( wm, inverts[ iwm ] ); - -/* Get the projection type of the supplied WcsMap and the indices of the - longitude and latitude axes. */ - type = astGetWcsType( wm ); - lonax = astGetWcsAxis( wm, 0 ); - latax = astGetWcsAxis( wm, 1 ); - -/* Get the axis permutation and constants arrays representing the - PermMap. Note, no constants are used more than once in the returned - arrays (i.e. duplicate constants are returned in "consts" if more than - one axis uses a given constant). */ - PermGet( pm, &outperm, &inperm, &consts, status ); - - if( astOK ) { - -/* Get the number of input and output axes in the PermMap. */ - npin = astGetNin( pm ); - npout = astGetNout( pm ); - -/* If the lon and lat axes of the WcsMap are unassigned, we return a - UnitMap instead of a WcsMap. - ================================================================ */ - done = 0; - -/* If the PermMap comes after the WcsMap... */ - if( iwm == 0 ) { - if( inperm[ lonax ] < 0 && inperm[ latax ] < 0 ) { - done = 1; - -/* Transform the constant values, using AST__BAD for other axes. */ - p = (double *) astMalloc( sizeof( double )*(size_t) npin ); - q = (double *) astMalloc( sizeof( double )*(size_t) npin ); - if( astOK ) { - for( i = 0; i < npin; i++ ) { - if( inperm[ i ] < 0 ) { - p[ i ] = consts[ -inperm[ i ] - 1 ]; - } else { - p[ i ] = AST__BAD; - } - } - -/* Transform this position using the inverse WcsMap. */ - astTranN( wm, 1, npin, 1, p, 0, npin, 1, q ); - -/* The new PermMap has the same axis permutations as the original, but it - has different constants. */ - for( i = 0; i < npin; i++ ) { - if( inperm[ i ] < 0 ) { - consts[ -inperm[ i ] - 1 ] = q[ i ]; - } - } - - newpm = astPermMap( npin, inperm, npout, outperm, consts, "", status ); - -/* Use a UnitMap instead of the WcsMap. */ - newwm = (AstMapping *) astUnitMap( npout, "", status ); - - } - -/* Free memory */ - p = astFree( p ); - q = astFree( q ); - - } - -/* If the WcsMap comes after the PermMap... */ - } else { - if( outperm[ lonax ] < 0 && outperm[ latax ] < 0 ) { - done = 1; - -/* Transform the constant values, using AST__BAD for other axes. */ - p = (double *) astMalloc( sizeof( double )*(size_t) npout ); - q = (double *) astMalloc( sizeof( double )*(size_t) npout ); - if( astOK ) { - for( i = 0; i < npout; i++ ) { - if( outperm[ i ] < 0 ) { - p[ i ] = consts[ -outperm[ i ] - 1 ]; - } else { - p[ i ] = AST__BAD; - } - } - -/* Transform this position using the forward WcsMap. */ - astTranN( wm, 1, npout, 1, p, 1, npout, 1, q ); - -/* The new PermMap has the same axis permutations as the original, but it - has different constants. */ - for( i = 0; i < npout; i++ ) { - if( outperm[ i ] < 0 ) { - consts[ -outperm[ i ] - 1 ] = q[ i ]; - } - } - - newpm = astPermMap( npin, inperm, npout, outperm, consts, "", status ); - -/* Use a UnitMap instead ofhte WcsMap. */ - newwm = (AstMapping *) astUnitMap( npin, "", status ); - - } - -/* Free memory */ - p = astFree( p ); - q = astFree( q ); - - } - } - -/* If the lon and lat axes of the WcsMap are both assigned, we return a - WcsMap. - ================================================================ */ - if( !done ) { - -/* Create the new WcsMap with permuted longitude and latitude axes. Note, - the private interface to astWcsMap uses 1-based axis indices. */ - if( iwm == 0 ) { - newwm = (AstMapping *) astWcsMap( npout, type, inperm[ lonax ] + 1, - inperm[ latax ] + 1, "", status ); - } else { - newwm = (AstMapping *) astWcsMap( npin, type, outperm[ lonax ] + 1, - outperm[ latax ] + 1, "", status ); - } - -/* Copy any projection parameters which have been set. */ - CopyPV( wm, (AstWcsMap *) newwm, status ); - -/* Set the invert flag. */ - astSetInvert( newwm, inverts[ iwm ] ); - -/* The returned PermMap is a clone of the supplied PermMap */ - newpm = astClone( pm ); - } - -/* Free the axis permutation and constants arrays. */ - outperm = (int *) astFree( (void *) outperm ); - inperm = (int *) astFree( (void *) inperm ); - consts = (double *) astFree( (void *) consts ); - } - -/* Re-instate the original value of the Invert attributes. */ - astSetInvert( pm, old_pinv ); - astSetInvert( wm, old_winv ); - -/* Annul the supplied pointers */ - pm = astAnnul( pm ); - wm = astAnnul( wm ); - -/* Store the returned Mappings. */ - maps[ iwm ] = (AstMapping *) newpm; - inverts[ iwm ] = astGetInvert( newpm ); - maps[ 1 - iwm ] = newwm; - inverts[ 1 - iwm ] = astGetInvert( newwm ); - -/* Return. */ - return; -} - -/* Functions which access class attributes. */ -/* ---------------------------------------- */ -/* Implement member functions to access the attributes associated with - this class using the macros defined for this purpose in the - "object.h" file. For a description of each attribute, see the class - interface (in the associated .h file). */ - - -/* -*att+ -* Name: -* FITSProj - -* Purpose: -* Is this WcsMap used as a FITS-WCS projection? - -* Type: -* Protected attribute. - -* Synopsis: -* Integer (boolean). - -* Description: -* This attribute controls how a WcsMap is used when creating a set -* of FITS headers. If the WcsMap is contained within a FrameSet -* that is to be converted into a set of FITS headers using the -c astWrite funtion, -f AST_WRITE routine, -* the WcsMap will be used to define the projection code appended to -* the FITS "CTYPEi" keywords if, and only if, the FITSProj attribute -* is set non-zero in the WcsMap. In order for the conversion to be -* successful, the compound Mapping connecting the base and current -* Frames in the FrameSet must contained one (and only one) WcsMap -* that has a non-zero value for its FITSProj attribute. -* -* The default value is one. - -* Applicability: -* WcsMap -* All Frames have this attribute. -*att- -*/ -astMAKE_CLEAR(WcsMap,FITSProj,fits_proj,-INT_MAX) -astMAKE_GET(WcsMap,FITSProj,int,1,( ( this->fits_proj != -INT_MAX ) ? - this->fits_proj : 1 )) -astMAKE_SET(WcsMap,FITSProj,int,fits_proj,( value != 0 )) -astMAKE_TEST(WcsMap,FITSProj,( this->fits_proj != -INT_MAX )) - -/* -*att+ -* Name: -* TPNTan - -* Purpose: -* Should the TPN projection include a TAN projection? - -* Type: -* Protected attribute. - -* Synopsis: -* Integer (boolean). - -* Description: -* This attribute controls how a WcsMap with a AST__TPN projection -* type behaves. If the attribute value is non-zero (the default), -* the complete projection is performed as described in the draft -* version of FITS-WCS paper II. If it is zero, then the TAN -* projection from (psi,theta) to (xi,eta) is replaced by a unit -* transformation, so that the WcsMap implements the polynomial -* transformation only, without any preceding TAN projection. -* -* In addition if the TPNTan value is zero, then the WcsMap -* assumes that the input and output values are in degrees rather -* than radians. - -* Applicability: -* WcsMap -* All Frames have this attribute. -*att- -*/ -astMAKE_GET(WcsMap,TPNTan,int,1,( ( this->tpn_tan != -INT_MAX ) ? - this->tpn_tan : 1 )) -astMAKE_TEST(WcsMap,TPNTan,( this->tpn_tan != -INT_MAX )) - -/* ProjP. */ -/* ------ */ -/* -*att++ -* Name: -* ProjP(m) - -* Purpose: -* FITS-WCS projection parameters. - -* Type: -* Public attribute. - -* Synopsis: -* Floating point. - -* Description: -* This attribute provides aliases for the PV attributes, which -* specifies the projection parameter values to be used by a WcsMap -* when implementing a FITS-WCS sky projection. ProjP is retained for -* compatibility with previous versions of FITS-WCS and AST. New -* applications should use the PV attibute instead. -* -* Attributes ProjP(0) to ProjP(9) correspond to attributes PV<axlat>_0 -* to PV<axlat>_9, where <axlat> is replaced by the index of the -* latitude axis (given by attribute WcsAxis(2)). See PV for further -* details. -* -* Note, the value of this attribute may changed only if the WcsMap -* has no more than one reference. That is, an error is reported if the -* WcsMap has been cloned, either by including it within another object -* such as a CmpMap or FrameSet or by calling the -c astClone -f AST_CLONE -* function. - -* Applicability: -* WcsMap -* All WcsMaps have this attribute. - -*att-- -*/ - -/* PV. */ -/* --- */ -/* -*att++ -* Name: -* PVi_m - -* Purpose: -* FITS-WCS projection parameters. - -* Type: -* Public attribute. - -* Synopsis: -* Floating point. - -* Description: -* This attribute specifies the projection parameter values to be -* used by a WcsMap when implementing a FITS-WCS sky projection. -* Each PV attribute name should include two integers, i and m, -* separated by an underscore. The axis index is specified -* by i, and should be in the range 1 to 99. The parameter number -* is specified by m, and should be in the range 0 to 99. For -* example, "PV2_1=45.0" would specify a value for projection -* parameter 1 of axis 2 in a WcsMap. -* -* These projection parameters correspond exactly to the values -* stored using the FITS-WCS keywords "PV1_1", "PV1_2", etc. This -* means that projection parameters which correspond to angles must -* be given in degrees (despite the fact that the angular -* coordinates and other attributes used by a WcsMap are in -* radians). -* -* The set of projection parameters used by a WcsMap depends on the -* type of projection, which is determined by its WcsType -* parameter. Most projections either do not require projection -* parameters, or use parameters 1 and 2 associated with the latitude -* axis. You should consult the FITS-WCS paper for details. -* -* Some projection parameters have default values (as defined in -* the FITS-WCS paper) which apply if no explicit value is given. -* You may omit setting a value for these "optional" parameters and the -* default will apply. Some projection parameters, however, have no -* default and a value must be explicitly supplied. This is most -* conveniently -c done using the "options" argument of astWcsMap (q.v.) when a WcsMap -f done using the OPTIONS argument of AST_WCSMAP (q.v.) when a WcsMap -* is first created. An error will result when a WcsMap is used to -* transform coordinates if any of its required projection -* parameters has not been set and lacks a default value. - -* A "get" operation for a parameter which has not been assigned a value -* will return the default value defined in the FITS-WCS paper, or -* AST__BAD if the paper indicates that the parameter has no default. -* A default value of zero is returned for parameters which are not -* accessed by the projection. -* -* Note, the FITS-WCS paper reserves parameters 1 and 2 on the longitude -* axis to hold the native longitude and latitude of the fiducial -* point of the projection, in degrees. The default values for these -* parameters are determined by the projection type. The AST-specific -* TPN projection does not use this convention - all projection -* parameters for both axes are used to represent polynomical correction -* terms, and the native longitude and latitude at the fiducial point may -* not be changed from the default values of zero and 90 degrees. - -* Applicability: -* WcsMap -* All WcsMaps have this attribute. - -* Notes: -* - The value of this attribute may changed only if the WcsMap -* has no more than one reference. That is, an error is reported if the -* WcsMap has been cloned, either by including it within another object -* such as a CmpMap or FrameSet or by calling the -c astClone -f AST_CLONE -* function. -* - If the projection parameter values given for a WcsMap do not -* satisfy all the required constraints (as defined in the FITS-WCS -* paper), then an error will result when the WcsMap is used to -* transform coordinates. -*att-- -*/ - -/* PVMax. */ -/* ------ */ -/* -*att++ -* Name: -* PVMax(i) - -* Purpose: -* Maximum number of FITS-WCS projection parameters. - -* Type: -* Public attribute. - -* Synopsis: -* Integer, read-only. - -* Description: -* This attribute specifies the largest legal index for a PV projection -* parameter attached to a specified axis of the WcsMap (i.e. the -* largest legal value for "m" when accessing the "PVi_m" attribute). -* The axis index is specified by i, and should be in the range 1 to 99. -* The value for each axis is determined by the projection type specified -* when the WcsMap -c is first created using astWcsMap and cannot subsequently be -f is first created using AST_WCSMAP and cannot subsequently be -* changed. - -* Applicability: -* WcsMap -* All WcsMaps have this attribute. -*att-- -*/ - -/* WcsType. */ -/* -------- */ -/* -*att++ -* Name: -* WcsType - -* Purpose: -* FITS-WCS projection type. - -* Type: -* Public attribute. - -* Synopsis: -* Integer, read-only. - -* Description: -* This attribute specifies which type of FITS-WCS projection will -* be performed by a WcsMap. The value is specified when a WcsMap -c is first created using astWcsMap and cannot subsequently be -f is first created using AST_WCSMAP and cannot subsequently be -* changed. -* -c The values used are represented by macros with names of -f The values used are represented by symbolic constants with names of -* the form "AST__XXX", where "XXX" is the (upper case) 3-character -* code used by the FITS-WCS "CTYPEi" keyword to identify the -* projection. For example, possible values are AST__TAN (for the -* tangent plane or gnomonic projection) and AST__AIT (for the -* Hammer-Aitoff projection). AST__TPN is an exception in that it -* is not part of the FITS-WCS standard (it represents a TAN -* projection with polynomial correction terms as defined in an early -* draft of the FITS-WCS paper). - -* Applicability: -* WcsMap -* All WcsMaps have this attribute. - -* Notes: -* - For a list of available projections, see the FITS-WCS paper. -*att-- -*/ - -/* Type of FITS-WCS projection. Read only. */ -astMAKE_GET(WcsMap,WcsType,int,AST__WCSBAD,this->type) - -/* NatLat. */ -/* ------- */ -/* -*att++ -* Name: -* NatLat - -* Purpose: -* Native latitude of the reference point of a FITS-WCS projection. - -* Type: -* Public attribute. - -* Synopsis: -* Floating point, read-only. - -* Description: -* This attribute gives the latitude of the reference point of the -* FITS-WCS projection implemented by a WcsMap. The value is in -* radians in the "native spherical" coordinate system. This value is -* fixed for most projections, for instance it is PI/2 (90 degrees) -* for all zenithal projections. For some projections (e.g. the conics) -* the value is not fixed, but is specified by parameter one on the -* latitude axis. -* -* FITS-WCS paper II introduces the concept of a "fiducial point" -* which is logical distinct from the projection reference point. -* It is easy to confuse the use of these two points. The fiducial -* point is the point which has celestial coordinates given by the -* CRVAL FITS keywords. The native spherical coordinates for this point -* default to the values of the NatLat and NatLon, but these defaults -* mey be over-ridden by values stored in the PVi_j keywords. Put -* another way, the CRVAL keywords will by default give the celestial -* coordinates of the projection reference point, but may refer to -* some other point if alternative native longitude and latitude values -* are provided through the PVi_j keywords. -* -* The NatLat attribute is read-only. - -* Applicability: -* WcsMap -* All WcsMaps have this attribute. - -* Notes: -* - A default value of AST__BAD is used if no latitude value is available. -*att-- -*/ - -/* -*att++ -* Name: -* NatLon - -* Purpose: -* Native longitude of the reference point of a FITS-WCS projection. - -* Type: -* Public attribute. - -* Synopsis: -* Floating point, read-only. - -* Description: -* This attribute gives the longitude of the reference point of the -* FITS-WCS projection implemented by a WcsMap. The value is in -* radians in the "native spherical" coordinate system, and will -* usually be zero. See the description of attribute NatLat for further -* information. -* -* The NatLon attribute is read-only. - -* Applicability: -* WcsMap -* All WcsMaps have this attribute. - -* Notes: -*att-- -*/ - -/* WcsAxis. */ -/* -------- */ -/* -*att++ -* Name: -* WcsAxis(lonlat) - -* Purpose: -* FITS-WCS projection axes. - -* Type: -* Public attribute. - -* Synopsis: -* Integer, read-only. - -* Description: -* This attribute gives the indices of the longitude and latitude -* coordinates of the FITS-WCS projection within the coordinate -* space used by a WcsMap. These indices are defined when the -c WcsMap is first created using astWcsMap and cannot -f WcsMap is first created using AST_WCSMAP and cannot -* subsequently be altered. -* -* If "lonlat" is 1, the index of the longitude axis is -* returned. Otherwise, if it is 2, the index of the latitude axis -* is returned. - -* Applicability: -* WcsMap -* All WcsMaps have this attribute. -*att-- -*/ - -/* Index of the latitude or longitude axis. */ -MAKE_GET(WcsAxis,int,0,this->wcsaxis[ axis ],2) - -/* Copy constructor. */ -/* ----------------- */ -static void Copy( const AstObject *objin, AstObject *objout, int *status ) { -/* -* Name: -* Copy - -* Purpose: -* Copy constructor for WcsMap objects. - -* Type: -* Private function. - -* Synopsis: -* void Copy( const AstObject *objin, AstObject *objout, int *status ) - -* Description: -* This function implements the copy constructor for WcsMap 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 -* projection parameter values associated with the input WcsMap. -*/ - - -/* Local Variables: */ - AstWcsMap *in; /* Pointer to input WcsMap */ - AstWcsMap *out; /* Pointer to output WcsMap */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain pointers to the input and output WcsMaps. */ - in = (AstWcsMap *) objin; - out = (AstWcsMap *) objout; - -/* Allocate memory to hold the projection parameters within the AstPrjPrm - structure used by WCSLIB. */ - (out->params).p = astMalloc( astSizeOf( (in->params).p ) ); - (out->params).p2 = astMalloc( astSizeOf( (in->params).p2 ) ); - -/* Copy the projection parameter information. */ - CopyPV( in, out, status ); - - return; - -} - -/* Destructor. */ -/* ----------- */ -static void Delete( AstObject *obj, int *status ) { -/* -* Name: -* Delete - -* Purpose: -* Destructor for WcsMap objects. - -* Type: -* Private function. - -* Synopsis: -* void Delete( AstObject *obj, int *status ) - -* Description: -* This function implements the destructor for WcsMap 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: */ - AstWcsMap *this; /* Pointer to WcsMap */ - -/* Obtain a pointer to the WcsMap structure. */ - this = (AstWcsMap *) obj; - -/* Free the arrays used to store projection parameters. */ - FreePV( this, status ); - -/* Free memory used to hold the projection parameters within the AstPrjPrm - structure used by WCSLIB. */ - this->params.p = astFree( this->params.p ); - this->params.p2 = astFree( this->params.p2 ); - -} - -/* Dump function. */ -/* -------------- */ -static void Dump( AstObject *this_object, AstChannel *channel, int *status ) { -/* -* Name: -* Dump - -* Purpose: -* Dump function for WcsMap 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 WcsMap class to an output Channel. - -* Parameters: -* this -* Pointer to the WcsMap whose data are being written. -* channel -* Pointer to the Channel to which the data are being written. -* status -* Pointer to the inherited status variable. -*/ - -#define COMMENT_LEN 150 /* Maximum length of a keyword comment */ -#define KEY_LEN 50 /* Maximum length of a keyword */ - -/* Local Variables: */ - AstWcsMap *this; /* Pointer to the WcsMap structure */ - char *comment; /* Pointer to comment string */ - char buff[ KEY_LEN + 1 ]; /* Buffer for keyword string */ - char comment_buff[ COMMENT_LEN + 1 ]; /* Buffer for keyword comment */ - const PrjData *prjdata; /* Information about the projection */ - double dval; /* Double precision value */ - int axis; /* Zero based axis index */ - int i; /* Axis index */ - int m; /* Parameter index */ - int ival; /* Integer value */ - int set; /* Attribute value set? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the WcsMap structure. */ - this = (AstWcsMap *) this_object; - -/* Write out values representing the instance variables for the - WcsMap 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. Note, all read-only attributes are considered to be set. - - 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. */ - -/* WcsType. */ -/* -------- */ - ival = GetWcsType( this, status ); - prjdata = FindPrjData( ival, status ); - (void) sprintf( comment_buff, "%s projection", prjdata->desc ); - comment_buff[ 0 ] = toupper( comment_buff[ 0 ] ); - astWriteString( channel, "Type", 1, 1, prjdata->ctype + 1, comment_buff ); - -/* FITSProj */ -/* -------- */ - set = TestFITSProj( this, status ); - ival = set ? GetFITSProj( this, status ) : astGetFITSProj( this ); - astWriteInt( channel, "FitsPrj", set, 0, ival, - ival ? "Defines the FITS-WCS projection" : - "Does not define the FITS-WCS projection" ); - -/* TPNTan */ -/* ------ */ - set = TestTPNTan( this, status ); - ival = set ? GetTPNTan( this, status ) : astGetTPNTan( this ); - astWriteInt( channel, "TpnTan", set, 0, ival, - ival ? "Include TAN projection in TPN mapping" : - "Exclude TAN projection from TPN mapping" ); - -/* PVi_m. */ -/* ------ */ - for( i = 0; i < astGetNin( this ); i++ ){ - if( this->np ) { - for( m = 0; m < this->np[ i ]; m++ ){ - set = TestPV( this, i, m, status ); - if( set ) { - dval = set ? GetPV( this, i, m, status ) : astGetPV( this, i, m ); - (void) sprintf( buff, "PV%d_%d", i + 1, m ); - (void) sprintf( comment_buff, "Projection parameter %d for axis %d", m, i + 1 ); - astWriteDouble( channel, buff, set, 0, dval, comment_buff ); - } - } - } - } - -/* WcsAxis(axis). */ -/* -------------- */ - for( axis = 0; axis < 2; axis++ ){ - ival = GetWcsAxis( this, axis, status ); - (void) sprintf( buff, "WcsAx%d", axis + 1 ); - if( axis == 0 ) { - comment = "Index of celestial longitude axis"; - } else { - comment = "Index of celestial latitude axis"; - } - astWriteInt( channel, buff, (axis!=ival), 0, ival + 1, comment ); - } - -/* Note, the "params" component of the AstWcsMap structure is not written out - because it can be re-generated from the other components. */ - -/* Return. */ - return; - -/* Undefine macros local to this function. */ -#undef COMMENT_LEN -#undef KEY_LEN -} - -/* Standard class functions. */ -/* ========================= */ -/* Implement the astIsAWcsMap and astCheckWcsMap functions using the macros - defined for this purpose in the "object.h" header file. */ -astMAKE_ISA(WcsMap,Mapping) -astMAKE_CHECK(WcsMap) - -AstWcsMap *astWcsMap_( int ncoord, int type, int lonax, int latax, - const char *options, int *status, ...){ -/* -*++ -* Name: -c astWcsMap -f AST_WCSMAP - -* Purpose: -* Create a WcsMap. - -* Type: -* Public function. - -* Synopsis: -c #include "wcsmap.h" -c AstWcsMap *astWcsMap( int ncoord, int type, int lonax, int latax, -c const char *options, ... ) -f RESULT = AST_WCSMAP( NCOORD, TYPE, LONAX, LATAX, OPTIONS, STATUS ) - -* Class Membership: -* WcsMap constructor. - -* Description: -* This function creates a new WcsMap and optionally initialises its -* attributes. -* -* A WcsMap is used to represent sky coordinate projections as -* described in the (draft) FITS world coordinate system (FITS-WCS) -* paper by E.W. Griesen and M. Calabretta (A & A, in preparation). -* This paper defines a set of functions, or sky projections, which -* transform longitude-latitude pairs representing spherical -* celestial coordinates into corresponding pairs of Cartesian -* coordinates (and vice versa). -* -* A WcsMap is a specialised form of Mapping which implements these -* sky projections and applies them to a specified pair of coordinates. -* All the projections in the FITS-WCS paper are supported, plus the now -* deprecated "TAN with polynomial correction terms" projection which -* is refered to here by the code "TPN". Using the FITS-WCS terminology, -* the transformation is between "native spherical" and "projection -* plane" coordinates. These coordinates may, optionally, be embedded in -* a space with more than two dimensions, the remaining coordinates being -* copied unchanged. Note, however, that for consistency with other AST -* facilities, a WcsMap handles coordinates that represent angles -* in radians (rather than the degrees used by FITS-WCS). -* -* The type of FITS-WCS projection to be used and the coordinates -* (axes) to which it applies are specified when a WcsMap is first -* created. The projection type may subsequently be determined -* using the WcsType attribute and the coordinates on which it acts -* may be determined using the WcsAxis(lonlat) attribute. -* -* Each WcsMap also allows up to 100 "projection parameters" to be -* associated with each axis. These specify the precise form of the -* projection, and are accessed using PVi_m attribute, where "i" is -* the integer axis index (starting at 1), and m is an integer -* "parameter index" in the range 0 to 99. The number of projection -* parameters required by each projection, and their meanings, are -* dependent upon the projection type (most projections either do not -* use any projection parameters, or use parameters 1 and 2 associated -* with the latitude axis). Before creating a WcsMap you should consult -* the FITS-WCS paper for details of which projection parameters are -* required, and which have defaults. When creating the WcsMap, you must -* explicitly set values for all those required projection parameters -* which do not have defaults defined in this paper. - -* Parameters: -c ncoord -f NCOORD = INTEGER (Given) -* The number of coordinate values for each point to be -* transformed (i.e. the number of dimensions of the space in -* which the points will reside). This must be at least 2. The -* same number is applicable to both input and output points. -c type -f TYPE = INTEGER (Given) -* The type of FITS-WCS projection to apply. This should be -c given using a macro value such as AST__TAN (for a tangent -f given as a symbolic value such as AST__TAN (for a tangent -* plane projection), where the characters following the double -* underscore give the projection type code (in upper case) as -* used in the FITS-WCS "CTYPEi" keyword. You should consult the -* FITS-WCS paper for a list of the available projections. The -* additional code of AST__TPN can be supplied which represents a -* TAN projection with polynomial correction terms as defined in an -* early draft of the FITS-WCS paper. -c lonax -f LONAX = INTEGER (Given) -* The index of the longitude axis. This should lie in the range -c 1 to "ncoord". -f 1 to NCOORD. -c latax -f LATAX = INTEGER (Given) -* The index of the latitude axis. This should lie in the range -c 1 to "ncoord" and be distinct from "lonax". -f 1 to NCOORD and be distinct from LONAX. -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 WcsMap. 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 WcsMap. The syntax used is identical to that for the -f AST_SET routine. -* -* If the sky projection to be implemented requires projection -* parameter values to be set, then this should normally be done -* here via the PVi_m attribute (see the "Examples" -* section). Setting values for these parameters is mandatory if -* they do not have default values (as defined in the FITS-WCS -* paper). -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 astWcsMap() -f AST_WCSMAP = INTEGER -* A pointer to the new WcsMap. - -* Examples: -c wcsmap = astWcsMap( 2, AST__MER, 1, 2, "" ); -f WCSMAP = AST_WCSMAP( 2, AST__MER, 1, 2, ' ', STATUS ) -* Creates a WcsMap that implements a FITS-WCS Mercator -* projection on pairs of coordinates, with coordinates 1 and 2 -* representing the longitude and latitude respectively. Note -* that the FITS-WCS Mercator projection does not require any -* projection parameters. -c wcsmap = astWcsMap( 3, AST__COE, 2, 3, "PV3_1=40.0" ); -f WCSMAP = AST_WCSMAP( 3, AST__COE, 2, 3, 'PV3_1=40.0', STATUS ) -* Creates a WcsMap that implements a FITS-WCS conical equal -* area projection. The WcsMap acts on points in a 3-dimensional -* space; coordinates 2 and 3 represent longitude and latitude -* respectively, while the values of coordinate 1 are copied -* unchanged. Projection parameter 1 associatyed with the latitude -* axis (corresponding to FITS keyword "PV3_1") is required and has -* no default, so is set explicitly to 40.0 degrees. Projection -* parameter 2 (corresponding to FITS keyword "PV3_2") is required -* but has a default of zero, so need not be specified. - -* Notes: -* - The forward transformation of a WcsMap converts between -* FITS-WCS "native spherical" and "relative physical" coordinates, -* while the inverse transformation converts in the opposite -* direction. This arrangement may be reversed, if required, by -c using astInvert or by setting the Invert attribute to a non-zero -f using AST_INVERT or by setting the Invert attribute to a non-zero -* value. -* - If any set of coordinates cannot be transformed (for example, -* many projections do not cover the entire celestial sphere), then -* a WcsMap will yield coordinate values of AST__BAD. -* - The validity of any projection parameters given via the PVi_m -c parameter in the "options" string is not checked by this -f parameter in the OPTIONS string is not checked by this -* function. However, their validity is checked when the resulting -* WcsMap is used to transform coordinates, and an error will -* result if the projection parameters do not satisfy all the -* required constraints (as defined in the FITS-WCS paper). -* - 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. - -* Status Handling: -* The protected interface to this function includes an extra -* parameter at the end of the parameter list descirbed above. This -* parameter is a pointer to the integer inherited status -* variable: "int *status". - -*-- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstWcsMap *new; /* Pointer to new WcsMap */ - va_list args; /* Variable argument list */ - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Initialise the WcsMap, allocating memory and initialising the - virtual function table as well if necessary. */ - new = astInitWcsMap( NULL, sizeof( AstWcsMap ), !class_init, &class_vtab, - "WcsMap", ncoord, type, lonax - 1, latax - 1 ); - -/* 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 WcsMap'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 WcsMap. */ - return new; -} - -AstWcsMap *astWcsMapId_( int ncoord, int type, int lonax, int latax, - const char *options, ... ){ -/* -* Name: -* astWcsMapId_ - -* Purpose: -* Create a WcsMap. - -* Type: -* Private function. - -* Synopsis: -* #include "wcsmap.h" -* AstWcsMap *astWcsMap_( int ncoord, int type, int lonax, int latax, -* const char *options, ... ) - -* Class Membership: -* WcsMap constructor. - -* Description: -* This function implements the external (public) interface to the -* astWcsMap constructor function. It returns an ID value (instead -* of a true C pointer) to external users, and must be provided -* because astWcsMap_ has a variable argument list which cannot be -* encapsulated in a macro (where this conversion would otherwise -* occur). -* -* The variable argument list also prevents this function from -* invoking astWcsMap_ directly, so it must be a re-implementation -* of it in all respects, except for the final conversion of the -* result to an ID value. - -* Parameters: -* As for astWcsMap_. - -* Returned Value: -* The ID value associated with the new WcsMap. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstWcsMap *new; /* Pointer to new WcsMap */ - va_list args; /* Variable argument list */ - int *status; /* Pointer to inherited status value */ - -/* Get a pointer to the inherited status value. */ - status = astGetStatusPtr; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* Initialise the WcsMap, allocating memory and initialising the - virtual function table as well if necessary. */ - new = astInitWcsMap( NULL, sizeof( AstWcsMap ), !class_init, &class_vtab, - "WcsMap", ncoord, type, lonax - 1, latax - 1 ); - -/* 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 WcsMap'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 WcsMap. */ - return astMakeId( new ); -} - -AstWcsMap *astInitWcsMap_( void *mem, size_t size, int init, - AstWcsMapVtab *vtab, const char *name, - int ncin, int type, int lonax, int latax, int *status ) { -/* -*+ -* Name: -* astInitWcsMap - -* Purpose: -* Initialise a WcsMap. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* AstWcsMap *astInitWcsMap( void *mem, size_t size, int init, -* AstWcsMapVtab *vtab, const char *name, -* int ncin, int type, int lonax, int latax ) - -* Class Membership: -* WcsMap initialiser. - -* Description: -* This function is provided for use by class implementations to initialise -* a new WcsMap object. It allocates memory (if necessary) to accommodate -* the WcsMap plus any additional data associated with the derived class. -* It then initialises a WcsMap 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 WcsMap at the start of the memory passed via the -* "vtab" parameter. - -* Parameters: -* mem -* A pointer to the memory in which the WcsMap is to be initialised. -* This must be of sufficient size to accommodate the WcsMap data -* (sizeof(WcsMap)) 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 WcsMap (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 WcsMap -* structure, so a valid value must be supplied even if not required for -* allocating memory. -* init -* A logical flag indicating if the WcsMap'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 WcsMap. -* 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). -* ncin -* The number of coordinate values per point. -* type -* The type of projection to use, choosen from the list available -* in the FITS celestial coordinates system. These are specified by -* symbolic values such as AST__TAN (specifying a tangent plane -* projection), where the characters following the double underscore -* gives the FITS projection type (in upper case) as used in the FITS -* "CTYPEn" keyword. -* lonax -* The index of the longitude axis. The first axis has index 0. -* latax -* The index of the latitude axis. The first axis has index 0. - -* Returned Value: -* A pointer to the new WcsMap. - -* 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: */ - const PrjData *prjdata; /* Information about the projection */ - AstWcsMap *new; /* Pointer to new WcsMap */ - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* If necessary, initialise the virtual function table. */ - if ( init ) astInitWcsMapVtab( vtab, name ); - -/* Initialise. */ - new = NULL; - -/* If a genuine FITS-WCS projection has been specified, check the initialisation - value(s) for validity, reporting an error if necessary. Prefix the error - report with the name of the function and the class of object being - processed. First check that at least two dimensions are to be mapped. */ - if( type != AST__WCSBAD ){ - if ( ncin < 2 ){ - astError( AST__WCSNC, "astInitWcsMap(%s): Too few axes (%d) " - "specified. Must be at least 2.", status, name, ncin ); - -/* Report an error if either the longitude or latitude axes are out of - bounds. */ - } else if ( lonax < 0 || lonax >= ncin ){ - astError( AST__WCSAX, "astInitWcsMap(%s): Specified longitude axis (%d) " - "does not exist within a %d dimensional coordinate system. ", status, - name, lonax + 1, ncin ); - - } else if ( latax < 0 || latax >= ncin ){ - astError( AST__WCSAX, "astInitWcsMap(%s): Specified latitude axis (%d) " - "does not exist within a %d dimensional coordinate system. ", status, - name, latax + 1, ncin ); - -/* Report an error if the longitude or latitude axes are the same. */ - } else if ( lonax == latax ){ - astError( AST__WCSAX, "astInitWcsMap(%s): The same axis (%d) has been " - "given for both the longitude and the latitude axis.", status, name, - lonax + 1 ); - -/* Report an error if projection type is unknown. */ - } else if ( type < 1 || type >= AST__WCSBAD ){ - astError( AST__WCSTY, "astInitWcsMap(%s): Projection type %d is " - "undefined. Projection types must be in the range 1 to %d.", status, - name, type, AST__WCSBAD - 1 ); - } - } - -/* Get a description of the requeste dprojection type. */ - prjdata = FindPrjData( type, status ); - -/* If all the above checks have been passed succesfully... */ - if( astOK ){ - -/* Initialise a Mapping structure (the parent class) as the first component - within the WcsMap structure, allocating memory if necessary. Specify that - the Mapping should be defined in both the forward and inverse directions. */ - new = (AstWcsMap *) astInitMapping( mem, size, 0, - (AstMappingVtab *) vtab, name, - ncin, ncin, 1, 1 ); - - if ( astOK ) { - -/* Initialise the WcsMap data. */ -/* ---------------------------- */ -/* Store the projection type. */ - new->type = type; - -/* Store the "use as FITS-WCS projection" flag. */ - new->fits_proj = -INT_MAX; - -/* Store the "include TAN component in TPN Mapping" flag. */ - new->tpn_tan = -INT_MAX; - -/* Store the axes associated with longitude and latitude. */ - new->wcsaxis[0] = lonax; - new->wcsaxis[1] = latax; - -/* Store NULL pointers for the arrays holding projection parameters. */ - new->p = NULL; - new->np = NULL; - -/* Allocate memory of the right size to hold the maximum number of - projection parameters needed by the projection. */ - new->params.p = astMalloc( sizeof( double ) * (prjdata->mxpar + 1) ); - new->params.p2 = astMalloc( sizeof( double ) * (prjdata->mxpar2 + 1) ); - -/* Initialise the "AstPrjPrm" structure (defined in proj.h). */ - InitPrjPrm( new, status ); - -/* If an error occurred, clean up by deleting the new WcsMap. */ - if ( !astOK ) new = astDelete( new ); - } - } - -/* Return a pointer to the new WcsMap. */ - return new; -} - -AstWcsMap *astLoadWcsMap_( void *mem, size_t size, - AstWcsMapVtab *vtab, const char *name, - AstChannel *channel, int *status ) { -/* -*+ -* Name: -* astLoadWcsMap - -* Purpose: -* Load a WcsMap. - -* Type: -* Protected function. - -* Synopsis: -* #include "wcsmap.h" -* AstWcsMap *astLoadWcsMap( void *mem, size_t size, -* AstWcsMapVtab *vtab, const char *name, -* AstChannel *channel ) - -* Class Membership: -* WcsMap loader. - -* Description: -* This function is provided to load a new WcsMap 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 -* WcsMap 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 WcsMap at the start of the memory -* passed via the "vtab" parameter. - - -* Parameters: -* mem -* A pointer to the memory into which the WcsMap is to be -* loaded. This must be of sufficient size to accommodate the -* WcsMap data (sizeof(WcsMap)) 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 WcsMap (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 WcsMap 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(AstWcsMap) is used instead. -* vtab -* Pointer to the start of the virtual function table to be -* associated with the new WcsMap. If this is NULL, a pointer -* to the (static) virtual function table for the WcsMap 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 "WcsMap" is used instead. - -* Returned Value: -* A pointer to the new WcsMap. - -* 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. -*- -*/ - -#define KEY_LEN 50 /* Maximum length of a keyword */ - - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ -/* Local Variables: */ - const PrjData *prjdata; /* Information about the projection */ - AstWcsMap *new; /* Pointer to the new WcsMap */ - char *text; /* Textual form of an integer value */ - char buff[ KEY_LEN + 1 ]; /* Buffer for keyword string */ - double pv; /* Projection parameter */ - int axis; /* Axis index */ - int i; /* Axis index */ - int m; /* Parameter index */ - int mxpar; /* Maximum number of PVi_m values */ - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(channel); - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* If a NULL virtual function table has been supplied, then this is - the first loader to be invoked for this WcsMap. In this case the - WcsMap belongs to this class, so supply appropriate values to be - passed to the parent class loader (and its parent, etc.). */ - if ( !vtab ) { - size = sizeof( AstWcsMap ); - vtab = &class_vtab; - name = "WcsMap"; - -/* If required, initialise the virtual function table for this class. */ - if ( !class_init ) { - astInitWcsMapVtab( 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 WcsMap. */ - new = astLoadMapping( mem, size, (AstMappingVtab *) 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, "WcsMap" ); - -/* 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. Note, this is only - done for read/write attributes, not read-only ones. */ - -/* FITSProj */ -/* -------- */ - new->fits_proj = astReadInt( channel, "fitsprj", -INT_MAX ); - if ( TestFITSProj( new, status ) ) { - SetFITSProj( new, new->fits_proj, status ); - } - -/* TPNTan */ -/* -------- */ - new->tpn_tan = astReadInt( channel, "tpntan", -INT_MAX ); - if ( TestTPNTan( new, status ) ) { - SetTPNTan( new, new->tpn_tan, status ); - } - -/* WcsType */ -/* ------- */ - text = astReadString( channel, "type", " " ); - if( strcmp( text, " " ) ){ - char tmp[ 10 ]; - (void) sprintf( tmp, "-%.8s", text ); - new->type = astWcsPrjType( tmp ); - } else { - new->type = AST__WCSBAD; - } - text = astFree( text ); - prjdata = FindPrjData( new->type, status ); - -/* WcsAxis(axis). */ -/* -------------- */ - for( axis = 0; axis < 2; axis++ ){ - (void) sprintf( buff, "wcsax%d", axis + 1 ); - new->wcsaxis[ axis ] = astReadInt( channel, buff, axis + 1 ) - 1; - } - -/* Initialise the pointers to the projection parameter information. */ - new->p = NULL; - new->np = NULL; - new->params.p = astMalloc( sizeof( double ) * (prjdata->mxpar + 1) ); - new->params.p2 = astMalloc( sizeof( double ) * (prjdata->mxpar2 + 1) ); - -/* Initialise the structure used by WCSLIB to hold intermediate values, - so that the values will be re-calculated on the first invocation of a - mapping function. */ - InitPrjPrm( new, status ); - -/* ProjP(m). */ -/* --------- */ - for( m = 0; m < AST__WCSMX; m++ ){ - (void) sprintf( buff, "projp%d", m ); - pv = astReadDouble( channel, buff, AST__BAD ); - if( pv != AST__BAD ) SetPV( new, new->wcsaxis[ 1 ], m, pv, status ); - } - -/* PVi_m. */ -/* -------*/ - for( i = 0; i < astGetNin( new ); i++ ){ - - if( i == new->wcsaxis[ 0 ] ) { - mxpar = prjdata->mxpar2; - } else if( i == new->wcsaxis[ 1 ] ) { - mxpar = prjdata->mxpar; - } else { - mxpar = 0; - } - - for( m = 0; m <= mxpar; m++ ){ - (void) sprintf( buff, "pv%d_%d", i + 1, m ); - pv = astReadDouble( channel, buff, AST__BAD ); - if( pv != AST__BAD ) SetPV( new, i, m, pv, status ); - } - } - -/* If an error occurred, clean up by deleting the new WcsMap. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return the new WcsMap pointer. */ - return new; - -/* Undefine macros local to this function. */ -#undef KEY_LEN -} - -/* 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. */ - -void astClearPV_( AstWcsMap *this, int i, int m, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,WcsMap,ClearPV))( this, i, m, status ); -} - -void astClearTPNTan_( AstWcsMap *this, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,WcsMap,ClearTPNTan))( this, status ); -} - -double astGetPV_( AstWcsMap *this, int i, int m, int *status ) { - if ( !astOK ) return AST__BAD; - return (**astMEMBER(this,WcsMap,GetPV))( this, i, m, status ); -} - -void astSetPV_( AstWcsMap *this, int i, int m, double val, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,WcsMap,SetPV))( this, i, m, val, status ); -} - -void astSetTPNTan_( AstWcsMap *this, int val, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,WcsMap,SetTPNTan))( this, val, status ); -} - -int astTestPV_( AstWcsMap *this, int i, int m, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,WcsMap,TestPV))( this, i, m, status ); -} - -int astIsZenithal_( AstWcsMap *this, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,WcsMap,IsZenithal))( this, status ); -} - -double astGetNatLat_( AstWcsMap *this, int *status ) { - if ( !astOK ) return AST__BAD; - return (**astMEMBER(this,WcsMap,GetNatLat))( this, status ); -} - -double astGetNatLon_( AstWcsMap *this, int *status ) { - if ( !astOK ) return AST__BAD; - return (**astMEMBER(this,WcsMap,GetNatLon))( this, status ); -} - -int astGetPVMax_( AstWcsMap *this, int i, int *status ) { - if ( !astOK ) return -1; - return (**astMEMBER(this,WcsMap,GetPVMax))( this, i, status ); -} - - - - - - - |