diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 19:01:49 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2019-05-10 19:01:49 (GMT) |
commit | beb90b7d3f526440250bba67e5ab07bb7eb7bbc3 (patch) | |
tree | 8d0d428ac62291f834ea8927bfa82c115ff1689d /ast/skyframe.c | |
parent | a213dadabce2b2e02eca8376765fa425f01792f5 (diff) | |
download | blt-beb90b7d3f526440250bba67e5ab07bb7eb7bbc3.zip blt-beb90b7d3f526440250bba67e5ab07bb7eb7bbc3.tar.gz blt-beb90b7d3f526440250bba67e5ab07bb7eb7bbc3.tar.bz2 |
upgrade ast 8.7.1
Diffstat (limited to 'ast/skyframe.c')
-rw-r--r-- | ast/skyframe.c | 12592 |
1 files changed, 0 insertions, 12592 deletions
diff --git a/ast/skyframe.c b/ast/skyframe.c deleted file mode 100644 index 1c20839..0000000 --- a/ast/skyframe.c +++ /dev/null @@ -1,12592 +0,0 @@ -/* -*class++ -* Name: -* SkyFrame - -* Purpose: -* Celestial coordinate system description. - -* Constructor Function: -c astSkyFrame -f AST_SKYFRAME - -* Description: -* A SkyFrame is a specialised form of Frame which describes -* celestial longitude/latitude coordinate systems. The particular -* celestial coordinate system to be represented is specified by -* setting the SkyFrame's System attribute (currently, the default -* is ICRS) qualified, as necessary, by a mean Equinox value and/or -* an Epoch. -* -* For each of the supported celestial coordinate systems, a SkyFrame -* can apply an optional shift of origin to create a coordinate system -* representing offsets within the celestial coordinate system from some -* specified reference point. This offset coordinate system can also be -* rotated to define new longitude and latitude axes. See attributes -* SkyRef, SkyRefIs, SkyRefP and AlignOffset. -* -* All the coordinate values used by a SkyFrame are in -* radians. These may be formatted in more conventional ways for -c display by using astFormat. -f display by using AST_FORMAT. -* For a SkyFrame, the Unit attribute describes the formatted value of -* a SkyFrame axis, and may for instance be "h:m:s", indicating that a -* formatted axis value contains colon-separated fields for hours, minutes -* and seconds. On the other hand, the InternalUnit attribute for a -* SkyFrame is always set to "rad" (i.e. radians), indicating that the -* unformatted (i.e. floating point) axis values used by application code -* are always in units of radians - -* Inheritance: -* The SkyFrame class inherits from the Frame class. - -* Attributes: -* In addition to those attributes common to all Frames, every -* SkyFrame also has the following attributes: -* -* - AlignOffset: Align SkyFrames using the offset coordinate system? -* - AsTime(axis): Format celestial coordinates as times? -* - Equinox: Epoch of the mean equinox -* - IsLatAxis: Is the specified axis the latitude axis? -* - IsLonAxis: Is the specified axis the longitude axis? -* - LatAxis: Index of the latitude axis -* - LonAxis: Index of the longitude axis -* - NegLon: Display longitude values in the range [-pi,pi]? -* - Projection: Sky projection description. -* - SkyRef: Position defining location of the offset coordinate system -* - SkyRefIs: Selects the nature of the offset coordinate system -* - SkyRefP: Position defining orientation of the offset coordinate system -* - SkyTol: Smallest significant shift in sky coordinates - -* Functions: -* In addition to those -c functions -f routines -* applicable to all Frames, the following -c functions -f routines -* may also be applied to all SkyFrames: -* -c - astSkyOffsetMap: Obtain a Mapping from absolute to offset coordinates -f - AST_SKYOFFSETMAP: Obtain a Mapping from absolute to offset coordinates - -* Copyright: -* Copyright (C) 1997-2006 Council for the Central Laboratory of the -* Research Councils -* Copyright (C) 2010 Science & Technology Facilities Council. -* All Rights Reserved. - -* Licence: -* This program is free software: you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation, either -* version 3 of the License, or (at your option) any later -* version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General -* License along with this program. If not, see -* <http://www.gnu.org/licenses/>. - -* Authors: -* RFWS: R.F. Warren-Smith (Starlink) -* DSB: David S. Berry (Starlink) -* BEC: Brad Cavanagh (JAC, Hawaii) - -* History: -* 4-MAR-1996 (RFWS): -* Original version. -* 17-MAY-1996 (RFWS): -* Tidied up, etc. -* 31-JUL-1996 (RFWS): -* Added support for attributes and a public interface. -* 11-SEP-1996 (RFWS): -* Added Gap (written by DSB). -* 24-SEP-1996 (RFWS): -* Added I/O facilities. -* 27-FEB-1997 (RFWS): -* Improved the public prologues. -* 27-MAY-1997 (RFWS): -* Modified to use a new public interface to the SlaMap class -* and to use the astSimplify method to remove redundant -* conversions. -* 16-JUN-1997 (RFWS): -* Fixed bug in axis associations returned by astMatch if axes -* were swapped. -* 16-JUL-1997 (RFWS): -* Added Projection attribute. -* 14-NOV-1997 (RFWS): -* Corrected the omission of axis permutations from astNorm. -* 21-JAN-1998 (RFWS): -* Ensure that Title and Domain values appropriate to a SkyFrame -* are preserved if a Frame result is generated by SubFrame. -* 26-FEB-1998 (RFWS): -* Over-ride the astUnformat method. -* 3-APR-2001 (DSB): -* Added "Unknown" option for the System attribute. Added read-only -* attributes LatAxis and LonAxis. -* 21-JUN-2001 (DSB): -* Added astAngle and astOffset2. -* 4-SEP-2001 (DSB): -* Added NegLon attribute, and astResolve method. -* 9-SEP-2001 (DSB): -* Added astBear method. -* 21-SEP-2001 (DSB): -* Removed astBear method. -* 10-OCT-2002 (DSB): -* Moved definitions of macros for SkyFrame system values from -* this file into skyframe.h. -* 24-OCT-2002 (DSB): -* Modified MakeSkyMapping so that any two SkyFrames with system=unknown -* are assumed to be related by a UnitMap. previously, they were -* considered to be unrelated, resulting in no ability to convert from -* one to the other. This could result for instance in astConvert -* being unable to find a maping from a SkyFrame to itself. -* 15-NOV-2002 (DSB): -* Moved System and Epoch attributes to the Frame class. -* 8-JAN-2003 (DSB): -* Changed private InitVtab method to protected astInitSkyFrameVtab -* method. -* 11-JUN-2003 (DSB): -* Added ICRS option for System attribute, and made it the default -* in place of FK5. -* 27-SEP-2003 (DSB): -* Added HELIOECLIPTIC option for System attribute. -* 19-APR-2004 (DSB): -* Added SkyRef, SkyRefIs, SkyRefP and AlignOffset attributes. -* 8-SEP-2004 (DSB): -* Added astResolvePoints method. -* 2-DEC-2004 (DSB): -* Added System "J2000" -* 27-JAN-2005 (DSB): -* Fix memory leaks in astLoadSkyFrame_ and Match. -* 7-APR-2005 (DSB): -* Allow SkyRefIs to be set to "Ignored". -* 12-MAY-2005 (DSB): -* Override astNormBox method. -* 15-AUG-2005 (DSB): -* Added AZEL system. -* 13-SEP-2005 (DSB): -* Override astClearSystem so that SkyRef/SkyRefPcan be converted -* from the original System to the default System. -* 19-SEP-2005 (DSB): -* Changed default for SkyRefIs from ORIGIN to IGNORED. -* 14-FEB-2006 (DSB): -* Override astGetObjSize. -* 22-FEB-2006 (DSB): -* Store the Local Apparent Sidereal Time in the SkyFrame structure -* in order to avoid expensive re-computations. -* 22-AUG-2006 (DSB): -* Ensure the cached Local Apparent Siderial Time is initialised -* when initialising or loading a SkyFrame. -* 22-SEP-2006 (DSB): -* Report an error in SetSystem if it is not possible to convert -* from old to new systems. -* 3-OCT-2006 (DSB): -* Added Equation of Equinoxes to the SkyFrame structure. -* 6-OCT-2006 (DSB): -* - Guard against annulling null pointers in subFrame. -* - Add Dut1 attribute -* - Use linear approximation for LAST over short periods (less -* than 0.001 of a day) -* - Remove Equation of Equinoxes from the SkyFrame structure. -* 10-OCT-2006 (DSB): -* Use "AlOff" instead of "AlignOffset" as the external channel name -* for the AlignOffset attribute. The longer form exceeded the -* limit that can be used by the Channel class. -* 14-OCT-2006 (DSB): -* - Move Dut1 attribute to the Frame class. -* - Use the TimeFrame class to do the TDB->LAST conversions. -* 17-JAN-2007 (DSB): -* - Use a UnitMap to align offset coordinate systems in two -* SkyFrames, regardless of other attribute values. -* - Only align in offset coordinates if both target and template -* have a non-zero value for AlignOffset. -* 23-JAN-2007 (DSB): -* Modified so that a SkyFrame can be used as a template to find a -* SkyFrame contained within a CmpFrame. This involves changes in -* Match and the removal of the local versions of SetMaxAxes and -* SetMinAxes. -* 4-JUL-2007 (DSB): -* Modified GetLast to use the correct solar to sidereal conversion -* factor. As a consequence the largest acceptable epoch gap before -* the LAST needs to be recalculated has been increased. -* 11-JUL-2007 (DSB): -* Override astSetEpoch and astClearEpoch by implementations which -* update the LAST value stored in the SkyFrame. -* 7-AUG-2007 (DSB): -* - Set a value for the CentreZero attribute when extracting a -* SkyAxis from a SkyFrame in function SubFrame. -* - In SubFrame, clear extended attributes such as System after -* all axis attributes have been "fixated. -* 30-AUG-2007 (DSB): -* Override astSetDut1 and astClearDut1 by implementations which -* update the LAST value stored in the SkyFrame. -* 31-AUG-2007 (DSB): -* - Cache the magnitude of the diurnal aberration vector in the -* SkyFrame structure for use when correcting for diurnal aberration. -* - Modify the azel conversions to include correction for diurnal -* aberration. -* - Override astClearObsLat and astSetObsLat by implementations which -* reset the magnitude of the diurnal aberration vector. -* 3-SEP-2007 (DSB): -* In SubFrame, since AlignSystem is extended by the SkyFrame class -* it needs to be cleared before invoking the parent SubFrame -* method in cases where the result Frame is not a SkyFrame. -* 2-OCT-2007 (DSB): -* In Overlay, clear AlignSystem as well as System before calling -* the parent overlay method. -* 10-OCT-2007 (DSB): -* In MakeSkyMapping, correct the usage of variables "system" and -* "align_sys" when aligning in AZEL. -* 18-OCT-2007 (DSB): -* Compare target and template AlignSystem values in Match, rather -* than comparing target and result AlignSystem values in MakeSkyMapping -* (since result is basically a copy of target). -* 27-NOV-2007 (DSB): -* - Modify SetSystem to ensure that SkyRef and SkyRefP position are -* always transformed as absolute values, rather than as offset -* values. -* - Modify SubMatch so that a value of zero is assumed for -* AlignOffset when restoring thre integrity of a FrameSet. -* 15-DEC-2008 (DSB): -* Improve calculation of approximate Local Apparent Sidereal time -* by finding and using the ratio of solar to sidereal time -* independently for each approximation period. -* 14-JAN-2009 (DSB): -* Override the astIntersect method. -* 21-JAN-2009 (DSB): -* Fix mis-use of results buffers for GetFormat and GetAttrib. -* 16-JUN-2009 (DSB): -* All sky coordinate systems currently supported by SkyFrame are -* left handed. So fix GetDirection method to return zero for all -* longitude axes and 1 for all latitude axes. -* 18-JUN-2009 (DSB): -* Incorporate the new ObsAlt attribute. -* 23-SEP-2009 (DSB): -* Allow some rounding error when checking for changes in SetObsLon -* and SetDut1. This reduces the number of times the expensive -* calculation of LAST is performed. -* 24-SEP-2009 (DSB); -* Create a static cache of LAST values stored in the class virtual -* function table. These are used in preference to calculating a new -* value from scratch. -* 25-SEP-2009 (DSB); -* Do not calculate LAST until it is needed. -* 12-OCT-2009 (DSB); -* - Handle 2.PI->0 discontinuity in cached LAST values. -* 12-OCT-2009 (BEC); -* - Fix bug in caching LAST value. -* 31-OCT-2009 (DSB); -* Correct SetCachedLAST to handle cases where the epoch to be -* stored is smaller than any epoch already in the table. -* 24-NOV-2009 (DSB): -* - In CalcLast, only use end values form the table of stored -* LAST values if the corresponding epochs are within 0.001 of -* a second of the required epoch (this tolerance used to be -* 0.1 seconds). -* - Do not clear the cached LAST value in SetEpoch and ClearEpoch. -* 8-MAR-2010 (DSB): -* Add astSkyOffsetMap method. -* 7-APR-2010 (DSB): -* Add IsLatAxis and IsLonAxis attributes. -* 11-MAY-2010 (DSB): -* In SetSystem, clear SkyRefP as well as SkyRef. -* 22-MAR-2011 (DSB): -* Override astFrameGrid method. -* 29-APR-2011 (DSB): -* Prevent astFindFrame from matching a subclass template against a -* superclass target. -* 23-MAY-2011 (DSB): -* Truncate returned PointSet in function FrameGrid to exclude unused points. -* 24-MAY-2011 (DSB): -* When clearing or setting the System attribute, clear SkyRef rather -* than reporting an error if the Mapping from the old System to the -* new System is unknown. -* 30-NOV-2011 (DSB): -* When aligning two SkyFrames in the system specified by AlignSystem, -* do not assume inappropriate default equinox values for systems -* that are not referred to the equinox specified by the Equinox attribute. -* 26-APR-2012 (DSB): -* - Correct Dump function so that any axis permutation is taken into -* account when dumping SkyFrame attributes that have a separate value -* for each axis (e.g. SkyRef and SkyRefP). -* - Take axis permutation into account when setting a new value -* for attributes that have a separate value for each axis (e.g. -* SkyRef and SkyRefP). -* - Remove the code that overrides ClearEpoch and SetEpoch (these -* overrides have not been needed since the changes made on -* 24/11/2009). -* 27-APR-2012 (DSB): -* - Correct astLoadSkyFrame function so that any axis permutation is -* taken into account when loading SkyFrame attributes that have a -* separate value for each axis. -* 25-JUL-2013 (DSB): -* Use a single table of cached LAST values for all threads, rather -* than a separate table for each thread. The problem with a table per -* thread is that if you have N threads, each table contains only -* one N'th of the total number of cached values, resulting in -* poorer accuracy, and small variations in interpolated LAST value -* depending on the way the cached values are distributed amongst the -* N threads. -* 6-AST-2013 (DSB): -* Fix the use of the read-write lock that is used to serialise -* access to the table of cached LAST values. This bug could -* cause occasional problems where an AST pointer would became -* invalid for no apparent reason. -* 21-FEB-2014 (DSB): -* Rounding errors in the SkyLineDef constructor could result in the line -* between coincident points being given a non-zero length. -* 6-JUL-2015 (DSB): -* Added SkyTol attribute. -* 3-FEB-2017 (GSB): -* Override astSetDtai and astClearDtai. -* 6-APR-2017 (GSB): -* Added dtai to AstSkyLastTable. -* 10-APR-2017 (GSB): -* Added macro to test floating point equality and used it for Dtai. -*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 SkyFrame - -/* Define the first and last acceptable System values. */ -#define FIRST_SYSTEM AST__FK4 -#define LAST_SYSTEM AST__AZEL - -/* Speed of light (AU per day) (from SLA_AOPPA) */ -#define C 173.14463331 - -/* Ratio between solar and sidereal time (from SLA_AOPPA) */ -#define SOLSID 1.00273790935 - -/* Define values for the different values of the SkyRefIs attribute. */ -#define POLE_STRING "Pole" -#define ORIGIN_STRING "Origin" -#define IGNORED_STRING "Ignored" - -/* Define other numerical constants for use in this module. */ -#define GETATTRIB_BUFF_LEN 200 -#define GETFORMAT_BUFF_LEN 50 -#define GETLABEL_BUFF_LEN 40 -#define GETSYMBOL_BUFF_LEN 20 -#define GETTITLE_BUFF_LEN 200 - -/* A macro which returns a flag indicating if the supplied system is - references to the equinox specified by the Equinox attribute. */ -#define EQREF(system) \ -((system==AST__FK4||system==AST__FK4_NO_E||system==AST__FK5||system==AST__ECLIPTIC)?1:0) - -/* Check for floating point equality (within the given tolerance), taking - bad values into account. */ -#define EQUAL(aa,bb,tol) (((aa)==AST__BAD)?(((bb)==AST__BAD)?1:0):(((bb)==AST__BAD)?0:(fabs((aa)-(bb))<=(tol)))) - -/* -* -* Name: -* MAKE_CLEAR - -* Purpose: -* Implement a method to clear a single value in a multi-valued attribute. - -* Type: -* Private macro. - -* Synopsis: -* #include "skyframe.h" -* MAKE_CLEAR(attr,component,assign,nval) - -* Class Membership: -* Defined by the SkyFrame class. - -* Description: -* This macro expands to an implementation of a private member function of -* the form: -* -* static void Clear<Attribute>( AstSkyFrame *this, int axis ) -* -* and an external interface function of the form: -* -* void astClear<Attribute>_( AstSkyFrame *this, int axis ) -* -* which implement a method for clearing a single value in a specified -* multi-valued attribute for an axis of a SkyFrame. - -* 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. -* 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( AstSkyFrame *this, int axis, int *status ) { \ -\ - int axis_p; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Validate and permute the axis index. */ \ - axis_p = astValidateAxis( this, axis, 1, "astClear" #attr ); \ -\ -/* Assign the "clear" value. */ \ - if( astOK ) { \ - this->component[ axis_p ] = (assign); \ - } \ -} \ -\ -/* External interface. */ \ -/* ------------------- */ \ -void astClear##attr##_( AstSkyFrame *this, int axis, int *status ) { \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Invoke the required method via the virtual function table. */ \ - (**astMEMBER(this,SkyFrame,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 "skyframe.h" -* MAKE_GET(attr,type,bad_value,assign,nval) - -* Class Membership: -* Defined by the SkyFrame class. - -* Description: -* This macro expands to an implementation of a private member function of -* the form: -* -* static <Type> Get<Attribute>( AstSkyFrame *this, int axis ) -* -* and an external interface function of the form: -* -* <Type> astGet<Attribute>_( AstSkyFrame *this, int axis ) -* -* which implement a method for getting a single value from a specified -* multi-valued attribute for an axis of a SkyFrame. - -* 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( AstSkyFrame *this, int axis, int *status ) { \ - int axis_p; /* Permuted axis index */ \ - type result; /* Result to be returned */ \ -\ -/* Initialise */\ - result = (bad_value); \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Validate and permute the axis index. */ \ - axis_p = astValidateAxis( this, axis, 1, "astGet" #attr ); \ -\ -/* Assign the result value. */ \ - if( astOK ) { \ - 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##_( AstSkyFrame *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,SkyFrame,Get##attr))( this, axis, status ); \ -} - -/* -* -* Name: -* MAKE_SET - -* Purpose: -* Implement a method to set a single value in a multi-valued attribute -* for a SkyFrame. - -* Type: -* Private macro. - -* Synopsis: -* #include "skyframe.h" -* MAKE_SET(attr,type,component,assign,nval) - -* Class Membership: -* Defined by the SkyFrame class. - -* Description: -* This macro expands to an implementation of a private member function of -* the form: -* -* static void Set<Attribute>( AstSkyFrame *this, int axis, <Type> value ) -* -* and an external interface function of the form: -* -* void astSet<Attribute>_( AstSkyFrame *this, int axis, <Type> value ) -* -* which implement a method for setting a single value in a specified -* multi-valued attribute for a SkyFrame. - -* 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( AstSkyFrame *this, int axis, type value, int *status ) { \ -\ - int axis_p; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return; \ -\ -/* Validate and permute the axis index. */ \ - axis_p = astValidateAxis( this, axis, 1, "astSet" #attr ); \ -\ -/* Store the new value in the structure component. */ \ - if( astOK ) { \ - this->component[ axis_p ] = (assign); \ - } \ -} \ -\ -/* External interface. */ \ -/* ------------------- */ \ -void astSet##attr##_( AstSkyFrame *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,SkyFrame,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 "skyframe.h" -* MAKE_TEST(attr,assign,nval) - -* Class Membership: -* Defined by the SkyFrame class. - -* Description: -* This macro expands to an implementation of a private member function of -* the form: -* -* static int Test<Attribute>( AstSkyFrame *this, int axis ) -* -* and an external interface function of the form: -* -* int astTest<Attribute>_( AstSkyFrame *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( AstSkyFrame *this, int axis, int *status ) { \ - int result; /* Value to return */ \ - int axis_p; /* Permuted axis index */ \ -\ -/* Initialise */ \ - result =0; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Validate and permute the axis index. */ \ - axis_p = astValidateAxis( this, axis, 1, "astTest" #attr ); \ -\ -/* Assign the result value. */ \ - if( astOK ) { \ - 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##_( AstSkyFrame *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,SkyFrame,Test##attr))( this, axis, status ); \ -} - - -/* Header 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 (for AST__BAD) */ -#include "unitmap.h" /* Unit Mappings */ -#include "permmap.h" /* Coordinate permutations */ -#include "cmpmap.h" /* Compound Mappings */ -#include "slamap.h" /* SLALIB sky coordinate Mappings */ -#include "timemap.h" /* Time conversions */ -#include "skyaxis.h" /* Sky axes */ -#include "frame.h" /* Parent Frame class */ -#include "matrixmap.h" /* Matrix multiplication */ -#include "sphmap.h" /* Cartesian<->Spherical transformations */ -#include "skyframe.h" /* Interface definition for this class */ -#include "pal.h" /* SLALIB library interface */ -#include "wcsmap.h" /* Factors of PI */ -#include "timeframe.h" /* Time system transformations */ - -/* Error code definitions. */ -/* ----------------------- */ -#include "ast_err.h" /* AST error codes */ - -/* C header files. */ -/* --------------- */ -#include <ctype.h> -#include <float.h> -#include <limits.h> -#include <math.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <string.h> - -/* Type Definitions. */ -/* ================= */ - -/* Cached Line structure. */ -/* ---------------------- */ -/* This structure contains information describing a line segment within a - SkyFrame. It differs from the AstLineDef defined in frame.h because - positions are represented by 3D (x,y,z) cartesian coords rather than - 2D (long,lat) coords. */ - -typedef struct SkyLineDef { - AstFrame *frame; /* Pointer to Frame in which the line is defined */ - double length; /* Line length */ - int infinite; /* Disregard the start and end of the line? */ - double start[3]; /* Unit vector defining start of line */ - double end[3]; /* Unit vector defining end of line */ - double dir[3]; /* Unit vector defining line direction */ - double q[3]; /* Unit vector perpendicular to line */ - double start_2d[2]; - double end_2d[2]; -} SkyLineDef; - -/* 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 used or extended by this - class. */ -static AstSystemType (* parent_getalignsystem)( AstFrame *, int * ); -static AstSystemType (* parent_getsystem)( AstFrame *, int * ); -static const char *(* parent_format)( AstFrame *, int, double, int * ); -static const char *(* parent_getattrib)( AstObject *, const char *, int * ); -static const char *(* parent_getdomain)( AstFrame *, int * ); -static const char *(* parent_getformat)( AstFrame *, int, int * ); -static const char *(* parent_getlabel)( AstFrame *, int, int * ); -static const char *(* parent_getsymbol)( AstFrame *, int, int * ); -static const char *(* parent_gettitle)( AstFrame *, int * ); -static const char *(* parent_getunit)( AstFrame *, int, int * ); -static double (* parent_gap)( AstFrame *, int, double, int *, int * ); -static double (* parent_getbottom)( AstFrame *, int, int * ); -static double (* parent_getepoch)( AstFrame *, int * ); -static double (* parent_gettop)( AstFrame *, int, int * ); -static int (* parent_getdirection)( AstFrame *, int, int * ); -static int (* parent_getobjsize)( AstObject *, int * ); -static int (* parent_match)( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * ); -static int (* parent_subframe)( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * ); -static int (* parent_testattrib)( AstObject *, const char *, int * ); -static int (* parent_testformat)( AstFrame *, int, int * ); -static int (* parent_unformat)( AstFrame *, int, const char *, double *, int * ); -static void (* parent_clearattrib)( AstObject *, const char *, int * ); -static void (* parent_cleardtai)( AstFrame *, int * ); -static void (* parent_cleardut1)( AstFrame *, int * ); -static void (* parent_clearformat)( AstFrame *, int, int * ); -static void (* parent_clearobsalt)( AstFrame *, int * ); -static void (* parent_clearobslat)( AstFrame *, int * ); -static void (* parent_clearobslon)( AstFrame *, int * ); -static void (* parent_clearsystem)( AstFrame *, int * ); -static void (* parent_overlay)( AstFrame *, const int *, AstFrame *, int * ); -static void (* parent_setattrib)( AstObject *, const char *, int * ); -static void (* parent_setdtai)( AstFrame *, double, int * ); -static void (* parent_setdut1)( AstFrame *, double, int * ); -static void (* parent_setformat)( AstFrame *, int, const char *, int * ); -static void (* parent_setobsalt)( AstFrame *, double, int * ); -static void (* parent_setobslat)( AstFrame *, double, int * ); -static void (* parent_setobslon)( AstFrame *, double, int * ); -static void (* parent_setsystem)( AstFrame *, AstSystemType, int * ); - -/* Factors for converting between hours, degrees and radians. */ -static double hr2rad; -static double deg2rad; -static double pi; -static double piby2; - -/* Table of cached Local Apparent Sidereal Time values and corresponding - epochs. */ -static int nlast_tables = 0; -static AstSkyLastTable **last_tables = NULL; - - -/* 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; \ - globals->GetFormat_Buff[ 0 ] = 0; \ - globals->GetLabel_Buff[ 0 ] = 0; \ - globals->GetSymbol_Buff[ 0 ] = 0; \ - globals->GetTitle_Buff[ 0 ] = 0; \ - globals->GetTitle_Buff2[ 0 ] = 0; \ - globals->TDBFrame = NULL; \ - globals->LASTFrame = NULL; \ - -/* Create the function that initialises global data for this module. */ -astMAKE_INITGLOBALS(SkyFrame) - -/* Define macros for accessing each item of thread specific global data. */ -#define class_init astGLOBAL(SkyFrame,Class_Init) -#define class_vtab astGLOBAL(SkyFrame,Class_Vtab) -#define getattrib_buff astGLOBAL(SkyFrame,GetAttrib_Buff) -#define getformat_buff astGLOBAL(SkyFrame,GetFormat_Buff) -#define getlabel_buff astGLOBAL(SkyFrame,GetLabel_Buff) -#define getsymbol_buff astGLOBAL(SkyFrame,GetSymbol_Buff) -#define gettitle_buff astGLOBAL(SkyFrame,GetTitle_Buff) -#define gettitle_buff2 astGLOBAL(SkyFrame,GetTitle_Buff2) -#define tdbframe astGLOBAL(SkyFrame,TDBFrame) -#define lastframe astGLOBAL(SkyFrame,LASTFrame) - - - -static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_MUTEX2 pthread_mutex_lock( &mutex2 ); -#define UNLOCK_MUTEX2 pthread_mutex_unlock( &mutex2 ); - -/* A read-write lock used to protect the table of cached LAST values so - that multiple threads can read simultaneously so long as no threads are - writing to the table. */ -static pthread_rwlock_t rwlock1=PTHREAD_RWLOCK_INITIALIZER; -#define LOCK_WLOCK1 pthread_rwlock_wrlock( &rwlock1 ); -#define LOCK_RLOCK1 pthread_rwlock_rdlock( &rwlock1 ); -#define UNLOCK_RWLOCK1 pthread_rwlock_unlock( &rwlock1 ); - -/* If thread safety is not needed, declare and initialise globals at static - variables. */ -#else - -/* Buffer returned by GetAttrib. */ -static char getattrib_buff[ GETATTRIB_BUFF_LEN + 1 ]; - -/* Buffer returned by GetFormat. */ -static char getformat_buff[ GETFORMAT_BUFF_LEN + 1 ]; - -/* Default GetLabel string buffer */ -static char getlabel_buff[ GETLABEL_BUFF_LEN + 1 ]; - -/* Default GetSymbol buffer */ -static char getsymbol_buff[ GETSYMBOL_BUFF_LEN + 1 ]; - -/* Default Title string buffer */ -static char gettitle_buff[ AST__SKYFRAME_GETTITLE_BUFF_LEN + 1 ]; -static char gettitle_buff2[ AST__SKYFRAME_GETTITLE_BUFF_LEN + 1 ]; - -/* TimeFrames for doing TDB<->LAST conversions. */ -static AstTimeFrame *tdbframe = NULL; -static AstTimeFrame *lastframe = NULL; - - -/* Define the class virtual function table and its initialisation flag - as static variables. */ -static AstSkyFrameVtab class_vtab; /* Virtual function table */ -static int class_init = 0; /* Virtual function table initialised? */ - -#define LOCK_MUTEX2 -#define UNLOCK_MUTEX2 - -#define LOCK_WLOCK1 -#define LOCK_RLOCK1 -#define UNLOCK_RWLOCK1 - -#endif - - -/* Prototypes for Private Member Functions. */ -/* ======================================== */ -static AstLineDef *LineDef( AstFrame *, const double[2], const double[2], int * ); -static AstMapping *SkyOffsetMap( AstSkyFrame *, int * ); -static AstPointSet *FrameGrid( AstFrame *, int, const double *, const double *, int * ); -static AstPointSet *ResolvePoints( AstFrame *, const double [], const double [], AstPointSet *, AstPointSet *, int * ); -static AstSystemType GetAlignSystem( AstFrame *, int * ); -static AstSystemType GetSystem( AstFrame *, int * ); -static AstSystemType SystemCode( AstFrame *, const char *, int * ); -static AstSystemType ValidateSystem( AstFrame *, AstSystemType, const char *, int * ); -static const char *Format( AstFrame *, int, double, int * ); -static const char *GetAttrib( AstObject *, const char *, int * ); -static const char *GetDomain( AstFrame *, int * ); -static const char *GetFormat( AstFrame *, int, int * ); -static const char *GetLabel( AstFrame *, int, int * ); -static const char *GetProjection( AstSkyFrame *, int * ); -static const char *GetSymbol( AstFrame *, int, int * ); -static const char *GetTitle( AstFrame *, int * ); -static const char *GetUnit( AstFrame *, int, int * ); -static const char *SystemString( AstFrame *, AstSystemType, int * ); -static double Angle( AstFrame *, const double[], const double[], const double[], int * ); -static double CalcLAST( AstSkyFrame *, double, double, double, double, double, double, int * ); -static double Distance( AstFrame *, const double[], const double[], int * ); -static double Gap( AstFrame *, int, double, int *, int * ); -static double GetBottom( AstFrame *, int, int * ); -static double GetCachedLAST( AstSkyFrame *, double, double, double, double, double, double, int * ); -static double GetEpoch( AstFrame *, int * ); -static double GetEquinox( AstSkyFrame *, int * ); -static void SetCachedLAST( AstSkyFrame *, double, double, double, double, double, double, double, int * ); -static void SetLast( AstSkyFrame *, int * ); -static double GetTop( AstFrame *, int, int * ); -static double Offset2( AstFrame *, const double[2], double, double, double[2], int * ); -static double GetDiurab( AstSkyFrame *, int * ); -static double GetLAST( AstSkyFrame *, int * ); -static int GetActiveUnit( AstFrame *, int * ); -static int GetAsTime( AstSkyFrame *, int, int * ); -static int GetDirection( AstFrame *, int, int * ); -static int GetIsLatAxis( AstSkyFrame *, int, int * ); -static int GetIsLonAxis( AstSkyFrame *, int, int * ); -static int GetLatAxis( AstSkyFrame *, int * ); -static int GetLonAxis( AstSkyFrame *, int * ); -static int GetNegLon( AstSkyFrame *, int * ); -static int GetObjSize( AstObject *, int * ); -static int IsEquatorial( AstSystemType, int * ); -static int LineContains( AstFrame *, AstLineDef *, int, double *, int * ); -static int LineCrossing( AstFrame *, AstLineDef *, AstLineDef *, double **, int * ); -static int LineIncludes( SkyLineDef *, double[3], int * ); -static int MakeSkyMapping( AstSkyFrame *, AstSkyFrame *, AstSystemType, AstMapping **, int * ); -static int Match( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * ); -static int SubFrame( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * ); -static int TestActiveUnit( AstFrame *, int * ); -static int TestAsTime( AstSkyFrame *, int, int * ); -static int TestAttrib( AstObject *, const char *, int * ); -static int TestEquinox( AstSkyFrame *, int * ); -static int TestNegLon( AstSkyFrame *, int * ); -static int TestProjection( AstSkyFrame *, int * ); -static int TestSlaUnit( AstSkyFrame *, AstSkyFrame *, AstSlaMap *, int * ); -static int Unformat( AstFrame *, int, const char *, double *, int * ); -static void ClearAsTime( AstSkyFrame *, int, int * ); -static void ClearAttrib( AstObject *, const char *, int * ); -static void ClearDtai( AstFrame *, int * ); -static void ClearDut1( AstFrame *, int * ); -static void ClearEquinox( AstSkyFrame *, int * ); -static void ClearNegLon( AstSkyFrame *, int * ); -static void ClearObsAlt( AstFrame *, int * ); -static void ClearObsLat( AstFrame *, int * ); -static void ClearObsLon( AstFrame *, int * ); -static void ClearProjection( AstSkyFrame *, int * ); -static void ClearSystem( AstFrame *, int * ); -static void Copy( const AstObject *, AstObject *, int * ); -static void Delete( AstObject *, int * ); -static void Dump( AstObject *, AstChannel *, int * ); -static void Intersect( AstFrame *, const double[2], const double[2], const double[2], const double[2], double[2], int * ); -static void LineOffset( AstFrame *, AstLineDef *, double, double, double[2], int * ); -static void MatchAxesX( AstFrame *, AstFrame *, int *, int * ); -static void Norm( AstFrame *, double[], int * ); -static void NormBox( AstFrame *, double[], double[], AstMapping *, int * ); -static void Offset( AstFrame *, const double[], const double[], double, double[], int * ); -static void Overlay( AstFrame *, const int *, AstFrame *, int * ); -static void Resolve( AstFrame *, const double [], const double [], const double [], double [], double *, double *, int * ); -static void SetAsTime( AstSkyFrame *, int, int, int * ); -static void SetAttrib( AstObject *, const char *, int * ); -static void SetDtai( AstFrame *, double, int * ); -static void SetDut1( AstFrame *, double, int * ); -static void SetEquinox( AstSkyFrame *, double, int * ); -static void SetNegLon( AstSkyFrame *, int, int * ); -static void SetObsAlt( AstFrame *, double, int * ); -static void SetObsLat( AstFrame *, double, int * ); -static void SetObsLon( AstFrame *, double, int * ); -static void SetProjection( AstSkyFrame *, const char *, int * ); -static void SetSystem( AstFrame *, AstSystemType, int * ); -static void Shapp( double, double *, double *, double, double *, int * ); -static void Shcal( double, double, double, double *, double *, int * ); -static void VerifyMSMAttrs( AstSkyFrame *, AstSkyFrame *, int, const char *, const char *, int * ); - -static double GetSkyRef( AstSkyFrame *, int, int * ); -static int TestSkyRef( AstSkyFrame *, int, int * ); -static void SetSkyRef( AstSkyFrame *, int, double, int * ); -static void ClearSkyRef( AstSkyFrame *, int, int * ); - -static double GetSkyRefP( AstSkyFrame *, int, int * ); -static int TestSkyRefP( AstSkyFrame *, int, int * ); -static void SetSkyRefP( AstSkyFrame *, int, double, int * ); -static void ClearSkyRefP( AstSkyFrame *, int, int * ); - -static int GetSkyRefIs( AstSkyFrame *, int * ); -static int TestSkyRefIs( AstSkyFrame *, int * ); -static void SetSkyRefIs( AstSkyFrame *, int, int * ); -static void ClearSkyRefIs( AstSkyFrame *, int * ); - -static int GetAlignOffset( AstSkyFrame *, int * ); -static int TestAlignOffset( AstSkyFrame *, int * ); -static void SetAlignOffset( AstSkyFrame *, int, int * ); -static void ClearAlignOffset( AstSkyFrame *, int * ); - -static double GetSkyTol( AstSkyFrame *, int * ); -static int TestSkyTol( AstSkyFrame *, int * ); -static void SetSkyTol( AstSkyFrame *, double, int * ); -static void ClearSkyTol( AstSkyFrame *, int * ); - -/* Member functions. */ -/* ================= */ -static double Angle( AstFrame *this_frame, const double a[], - const double b[], const double c[], int *status ) { -/* -* Name: -* Angle - -* Purpose: -* Calculate the angle subtended by two points at a third point. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double Angle( AstFrame *this_frame, const double a[], -* const double b[], const double c[], int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astAngle method -* inherited from the Frame class). - -* Description: -* This function finds the angle at point B between the line -* joining points A and B, and the line joining points C -* and B. These lines will in fact be geodesic curves (great circles). - -* Parameters: -* this -* Pointer to the SkyFrame. -* a -* An array of double, with one element for each SkyFrame axis, -* containing the coordinates of the first point. -* b -* An array of double, with one element for each SkyFrame axis, -* containing the coordinates of the second point. -* c -* An array of double, with one element for each SkyFrame axis, -* containing the coordinates of the third point. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The angle in radians, from the line AB to the line CB, in -* the range $\pm \pi$ with positive rotation is in the same sense -* as rotation from axis 2 to axis 1. - -* Notes: -* - This function will return a "bad" result value (AST__BAD) if -* any of the input coordinates has this value. -* - A "bad" value will also be returned if points A and B are -* co-incident, or if points B and C are co-incident. -* - A "bad" value will also be returned if this function is -* invoked with the AST error status set, or if it should fail for -* any reason. -*/ - - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - const int *perm; /* Axis permutation array */ - double aa[ 2 ]; /* Permuted a coordinates */ - double anga; /* Angle from north to the line BA */ - double angc; /* Angle from north to the line BC */ - double bb[ 2 ]; /* Permuted b coordinates */ - double cc[ 2 ]; /* Permuted c coordinates */ - double result; /* Value to return */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( astOK ) { - -/* Check that all supplied coordinates are OK. */ - if ( ( a[ 0 ] != AST__BAD ) && ( a[ 1 ] != AST__BAD ) && - ( b[ 0 ] != AST__BAD ) && ( b[ 1 ] != AST__BAD ) && - ( c[ 0 ] != AST__BAD ) && ( c[ 1 ] != AST__BAD ) ) { - -/* Apply the axis permutation array to obtain the coordinates of the - three points in the required (longitude,latitude) order. */ - aa[ perm[ 0 ] ] = a[ 0 ]; - aa[ perm[ 1 ] ] = a[ 1 ]; - bb[ perm[ 0 ] ] = b[ 0 ]; - bb[ perm[ 1 ] ] = b[ 1 ]; - cc[ perm[ 0 ] ] = c[ 0 ]; - cc[ perm[ 1 ] ] = c[ 1 ]; - -/* Check that A and B are not co-incident. */ - if( aa[ 0 ] != bb[ 0 ] || aa[ 1 ] != bb[ 1 ] ) { - -/* Check that C and B are not co-incident. */ - if( cc[ 0 ] != bb[ 0 ] || cc[ 1 ] != bb[ 1 ] ) { - -/* Find the angle from north to the line BA. */ - anga = palDbear( bb[ 0 ], bb[ 1 ], aa[ 0 ], aa[ 1 ] ); - -/* Find the angle from north to the line BC. */ - angc = palDbear( bb[ 0 ], bb[ 1 ], cc[ 0 ], cc[ 1 ] ); - -/* Find the difference. */ - result = angc - anga; - -/* This value is the angle from north, but we want the angle from axis 2. - If the axes have been swapped so that axis 2 is actually the longitude - axis, then we need to correct this result. */ - if( perm[ 0 ] != 0 ) result = piby2 - result; - -/* Fold the result into the range +/- PI. */ - result = palDrange( result ); - } - } - } - } - -/* Return the result. */ - return result; -} - -static double CalcLAST( AstSkyFrame *this, double epoch, double obslon, - double obslat, double obsalt, double dut1, double dtai, - int *status ) { -/* -* Name: -* CalcLAST - -* Purpose: -* Calculate the Local Appearent Sidereal Time for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double CalcLAST( AstSkyFrame *this, double epoch, double obslon, -* double obslat, double obsalt, double dut1, double dtai, -* int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function calculates and returns the Local Apparent Sidereal Time -* at the given epoch, etc. - -* Parameters: -* this -* Pointer to the SkyFrame. -* epoch -* The epoch (MJD). -* obslon -* Observatory geodetic longitude (radians) -* obslat -* Observatory geodetic latitude (radians) -* obsalt -* Observatory geodetic altitude (metres) -* dut1 -* The UT1-UTC correction, in seconds. -* dtai -* The TAI-UTC correction, in seconds. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The Local Apparent Sidereal Time, in radians. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstFrameSet *fs; /* Mapping from TDB offset to LAST offset */ - double epoch0; /* Supplied epoch value */ - double result; /* Returned LAST value */ - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this); - -/* Check the global error status. */ - if ( !astOK ) return AST__BAD; - -/* See if the required LAST value can be determined from the cached LAST - values in the SkyFrame virtual function table. */ - result = GetCachedLAST( this, epoch, obslon, obslat, obsalt, dut1, dtai, - status ); - -/* If not, we do an exact calculation from scratch. */ - if( result == AST__BAD ) { - -/* If not yet done, create two TimeFrames. Note, this is done here - rather than in astInitSkyFrameVtab in order to avoid infinite vtab - initialisation loops (caused by the TimeFrame class containing a - static SkyFrame). */ - if( ! tdbframe ) { - astBeginPM; - tdbframe = astTimeFrame( "system=mjd,timescale=tdb", status ); - lastframe = astTimeFrame( "system=mjd,timescale=last", status ); - astEndPM; - } - -/* For better accuracy, use this integer part of the epoch as the origin of - the two TimeFrames. */ - astSetTimeOrigin( tdbframe, (int) epoch ); - astSetTimeOrigin( lastframe, (int) epoch ); - -/* Convert the absolute Epoch value to an offset from the above origin. */ - epoch0 = epoch; - epoch -= (int) epoch; - -/* Store the observers position in the two TimeFrames. */ - astSetObsLon( tdbframe, obslon ); - astSetObsLon( lastframe, obslon ); - - astSetObsLat( tdbframe, obslat ); - astSetObsLat( lastframe, obslat ); - - astSetObsAlt( tdbframe, obsalt ); - astSetObsAlt( lastframe, obsalt ); - -/* Store the DUT1 value. */ - astSetDut1( tdbframe, dut1 ); - astSetDut1( lastframe, dut1 ); - -/* Store the DTAI value. */ - if ( dtai == AST__BAD ) { - astClearDtai( tdbframe ); - astClearDtai( lastframe ); - } - else { - astSetDtai( tdbframe, dtai ); - astSetDtai( lastframe, dtai ); - } - -/* Get the conversion from tdb mjd offset to last mjd offset. */ - fs = astConvert( tdbframe, lastframe, "" ); - -/* Use it to transform the SkyFrame Epoch from TDB offset to LAST offset. */ - astTran1( fs, 1, &epoch, 1, &epoch ); - fs = astAnnul( fs ); - -/* Convert the LAST offset from days to radians. */ - result = ( epoch - (int) epoch )*2*AST__DPI; - -/* Cache the new LAST value in the SkyFrame virtual function table. */ - SetCachedLAST( this, result, epoch0, obslon, obslat, obsalt, dut1, dtai, - status ); - } - -/* Return the required LAST value. */ - return result; -} - -static void ClearAsTime( AstSkyFrame *this, int axis, int *status ) { -/* -* Name: -* ClearAsTime - -* Purpose: -* Clear the value of the AsTime attribute for a SkyFrame's axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void ClearAsTime( AstSkyFrame *this, int axis, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function clears any value that has been set for the AsTime -* attribute for a specified axis of a SkyFrame. This attribute indicates -* whether axis values should be formatted as times (as opposed to angles) -* by default. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Index of the axis for which the value is to be cleared (zero based). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* void. -*/ - -/* Local Variables: */ - AstAxis *ax; /* Pointer to Axis object */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Validate the axis index. */ - (void) astValidateAxis( this, axis, 1, "astClearAsTime" ); - -/* Obtain a pointer to the Axis object. */ - ax = astGetAxis( this, axis ); - -/* If the Axis is a SkyAxis, clear the AsTime attribute (if it is not a - SkyAxis, it will not have this attribute anyway). */ - if ( astIsASkyAxis( ax ) ) astClearAxisAsTime( ax ); - -/* Annul the Axis pointer. */ - ax = astAnnul( ax ); -} - -static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* ClearAttrib - -* Purpose: -* Clear an attribute value for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void ClearAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astClearAttrib protected -* method inherited from the Frame class). - -* Description: -* This function clears the value of a specified attribute for a -* SkyFrame, so that the default value will subsequently be used. - -* Parameters: -* this -* Pointer to the SkyFrame. -* 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. - -* Notes: -* - This function uses one-based axis numbering so that it is -* suitable for external (public) use. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - int axis; /* SkyFrame axis number */ - int len; /* Length of attrib string */ - int nc; /* No. characters read by astSscanf */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_object; - -/* Obtain the length of the "attrib" string. */ - len = strlen( attrib ); - -/* Check the attribute name and clear the appropriate attribute. */ - -/* AsTime(axis). */ -/* ------------- */ - if ( nc = 0, - ( 1 == astSscanf( attrib, "astime(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - astClearAsTime( this, axis - 1 ); - -/* Equinox. */ -/* -------- */ - } else if ( !strcmp( attrib, "equinox" ) ) { - astClearEquinox( this ); - -/* NegLon. */ -/* ------- */ - } else if ( !strcmp( attrib, "neglon" ) ) { - astClearNegLon( this ); - -/* Projection. */ -/* ----------- */ - } else if ( !strcmp( attrib, "projection" ) ) { - astClearProjection( this ); - -/* SkyRef. */ -/* ------- */ - } else if ( !strcmp( attrib, "skyref" ) ) { - astClearSkyRef( this, 0 ); - astClearSkyRef( this, 1 ); - -/* SkyTol. */ -/* ------- */ - } else if ( !strcmp( attrib, "skytol" ) ) { - astClearSkyTol( this ); - -/* SkyRef(axis). */ -/* ------------- */ - } else if ( nc = 0, - ( 1 == astSscanf( attrib, "skyref(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - astClearSkyRef( this, axis - 1 ); - -/* SkyRefP. */ -/* -------- */ - } else if ( !strcmp( attrib, "skyrefp" ) ) { - astClearSkyRefP( this, 0 ); - astClearSkyRefP( this, 1 ); - -/* SkyRefP(axis). */ -/* ------------- */ - } else if ( nc = 0, - ( 1 == astSscanf( attrib, "skyrefp(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - astClearSkyRefP( this, axis - 1 ); - -/* SkyRefIs. */ -/* --------- */ - } else if ( !strcmp( attrib, "skyrefis" ) ) { - astClearSkyRefIs( this ); - -/* AlignOffset. */ -/* ------------ */ - } else if ( !strcmp( attrib, "alignoffset" ) ) { - astClearAlignOffset( this ); - -/* 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 ( !strncmp( attrib, "islataxis", 9 ) || - !strncmp( attrib, "islonaxis", 9 ) || - !strcmp( attrib, "lataxis" ) || - !strcmp( attrib, "lonaxis" ) ) { - 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 not recognised, pass it on to the parent method - for further interpretation. */ - } else { - (*parent_clearattrib)( this_object, attrib, status ); - } -} - -static void ClearDtai( AstFrame *this, int *status ) { -/* -* Name: -* ClearDtai - -* Purpose: -* Clear the value of the Dtai attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void ClearDtai( AstFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astClearDtai method -* inherited from the Frame class). - -* Description: -* This function clears the Dtai value and updates the LAST value -* stored in the SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Note the original value */ - orig = astGetDtai( this ); - -/* Invoke the parent method to clear the Frame Dtai */ - (*parent_cleardtai)( this, status ); - -/* If the DTAI value has changed significantly, indicate that the LAST value - will need to be re-calculated when it is next needed. */ - if( ! EQUAL( orig, astGetDtai( this ), 1.0E-6 ) ) { - ( (AstSkyFrame *) this )->last = AST__BAD; - ( (AstSkyFrame *) this )->eplast = AST__BAD; - ( (AstSkyFrame *) this )->klast = AST__BAD; - } -} - -static void ClearDut1( AstFrame *this, int *status ) { -/* -* Name: -* ClearDut1 - -* Purpose: -* Clear the value of the Dut1 attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void ClearDut1( AstFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astClearDut1 method -* inherited from the Frame class). - -* Description: -* This function clears the Dut1 value and updates the LAST value -* stored in the SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Note the original value */ - orig = astGetDut1( this ); - -/* Invoke the parent method to clear the Frame Dut1 */ - (*parent_cleardut1)( this, status ); - -/* If the DUT1 value has changed significantly, indicate that the LAST value - will need to be re-calculated when it is next needed. */ - if( fabs( orig - astGetDut1( this ) ) > 1.0E-6 ) { - ( (AstSkyFrame *) this )->last = AST__BAD; - ( (AstSkyFrame *) this )->eplast = AST__BAD; - ( (AstSkyFrame *) this )->klast = AST__BAD; - } -} - -static void ClearObsAlt( AstFrame *this, int *status ) { -/* -* Name: -* ClearObsAlt - -* Purpose: -* Clear the value of the ObsAlt attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void ClearObsAlt( AstFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astClearObsAlt method -* inherited from the Frame class). - -* Description: -* This function clears the ObsAlt value. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Note the original value */ - orig = astGetObsAlt( this ); - -/* Invoke the parent method to clear the Frame ObsAlt. */ - (*parent_clearobsalt)( this, status ); - -/* If the altitude has changed significantly, indicate that the LAST value - and magnitude of the diurnal aberration vector will need to be - re-calculated when next needed. */ - if( fabs( orig - astGetObsAlt( this ) ) > 0.001 ) { - ( (AstSkyFrame *) this )->last = AST__BAD; - ( (AstSkyFrame *) this )->eplast = AST__BAD; - ( (AstSkyFrame *) this )->klast = AST__BAD; - ( (AstSkyFrame *) this )->diurab = AST__BAD; - } -} - -static void ClearObsLat( AstFrame *this, int *status ) { -/* -* Name: -* ClearObsLat - -* Purpose: -* Clear the value of the ObsLat attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void ClearObsLat( AstFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astClearObsLat method -* inherited from the Frame class). - -* Description: -* This function clears the ObsLat value. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Note the original value */ - orig = astGetObsLat( this ); - -/* Invoke the parent method to clear the Frame ObsLat. */ - (*parent_clearobslat)( this, status ); - -/* If the altitude has changed significantly, indicate that the LAST value - and magnitude of the diurnal aberration vector will need to be - re-calculated when next needed. */ - if( fabs( orig - astGetObsLat( this ) ) > 1.0E-8 ) { - ( (AstSkyFrame *) this )->last = AST__BAD; - ( (AstSkyFrame *) this )->eplast = AST__BAD; - ( (AstSkyFrame *) this )->klast = AST__BAD; - ( (AstSkyFrame *) this )->diurab = AST__BAD; - } -} - -static void ClearObsLon( AstFrame *this, int *status ) { -/* -* Name: -* ClearObsLon - -* Purpose: -* Clear the value of the ObsLon attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void ClearObsLon( AstFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astClearObsLon method -* inherited from the Frame class). - -* Description: -* This function clears the ObsLon value. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Note the original value */ - orig = astGetObsLon( this ); - -/* Invoke the parent method to clear the Frame ObsLon. */ - (*parent_clearobslon)( this, status ); - -/* If the longitude has changed significantly, indicate that the LAST value - will need to be re-calculated when it is next needed. */ - if( fabs( orig - astGetObsLon( this ) ) > 1.0E-8 ) { - ( (AstSkyFrame *) this )->last = AST__BAD; - ( (AstSkyFrame *) this )->eplast = AST__BAD; - ( (AstSkyFrame *) this )->klast = AST__BAD; - } -} - -static void ClearSystem( AstFrame *this_frame, int *status ) { -/* -* Name: -* ClearSystem - -* Purpose: -* Clear the System attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void ClearSystem( AstFrame *this_frame, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astClearSystem protected -* method inherited from the Frame class). - -* Description: -* This function clears the System attribute for a SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstFrameSet *fs; /* FrameSet to be used as the Mapping */ - AstSkyFrame *sfrm; /* Copy of original SkyFrame */ - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - double xin[ 2 ]; /* Axis 0 values */ - double yin[ 2 ]; /* Axis 1 values */ - double xout[ 2 ]; /* Axis 0 values */ - double yout[ 2 ]; /* Axis 1 values */ - int skyref_set; /* Is either SkyRef attribute set? */ - int skyrefp_set; /* Is either SkyRefP attribute set? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* See if either the SkyRef or SkyRefP attribute is set. */ - skyref_set = astTestSkyRef( this, 0 ) || astTestSkyRef( this, 1 ); - skyrefp_set = astTestSkyRefP( this, 0 ) || astTestSkyRefP( this, 1 ); - -/* If so, we will need to transform their values into the new coordinate - system. Save a copy of the SkyFrame with its original System value. */ - sfrm = ( skyref_set || skyrefp_set )?astCopy( this ):NULL; - -/* Use the parent method to clear the System value. */ - (*parent_clearsystem)( this_frame, status ); - -/* Now modify the SkyRef and SkyRefP attributes if necessary. */ - if( sfrm ) { - -/* Save the SkyRef and SkyRefP values. */ - xin[ 0 ] = astGetSkyRef( sfrm, 0 ); - xin[ 1 ] = astGetSkyRefP( sfrm, 0 ); - yin[ 0 ] = astGetSkyRef( sfrm, 1 ); - yin[ 1 ] = astGetSkyRefP( sfrm, 1 ); - -/* Clear the SkyRef values to avoid infinite recursion in the following - call to astConvert. */ - if( skyref_set ) { - astClearSkyRef( sfrm, 0 ); - astClearSkyRef( sfrm, 1 ); - astClearSkyRef( this, 0 ); - astClearSkyRef( this, 1 ); - } - -/* Get the Mapping from the original System to the default System. Invoking - astConvert will recursively invoke ClearSystem again. This is why we need - to be careful to ensure that SkyRef is cleared above - doing so ensure - we do not end up with infinite recursion. */ - fs = astConvert( sfrm, this, "" ); - -/* Check the Mapping was found. */ - if( fs ) { - -/* Use the Mapping to find the SkyRef and SkyRefP positions in the default - coordinate system. */ - astTran2( fs, 2, xin, yin, 1, xout, yout ); - -/* Store the values as required. */ - if( skyref_set ) { - astSetSkyRef( this, 0, xout[ 0 ] ); - astSetSkyRef( this, 1, yout[ 0 ] ); - } - - if( skyrefp_set ) { - astSetSkyRefP( this, 0, xout[ 1 ] ); - astSetSkyRefP( this, 1, yout[ 1 ] ); - } - -/* Free resources. */ - fs = astAnnul( fs ); - -/* If the Mapping is not defined, we cannot convert the SkyRef or SkyRefP - positions in the new Frame so clear them. */ - } else { - if( skyref_set ) { - astClearSkyRef( this, 0 ); - astClearSkyRef( this, 1 ); - } - if( skyrefp_set ) { - astClearSkyRefP( this, 0 ); - astClearSkyRefP( this, 1 ); - } - } - -/* Free resources. */ - sfrm = astAnnul( sfrm ); - } -} - -static double Distance( AstFrame *this_frame, - const double point1[], const double point2[], int *status ) { -/* -* Name: -* Distance - -* Purpose: -* Calculate the distance between two points. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double Distance( AstFrame *this, -* const double point1[], const double point2[], int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astDistance method -* inherited from the Frame class). - -* Description: -* This function finds the distance between two points whose -* SkyFrame coordinates are given. The distance calculated is that -* along the geodesic curve (i.e. great circle) that joins the two -* points. - -* Parameters: -* this -* Pointer to the SkyFrame. -* point1 -* An array of double, with one element for each SkyFrame axis, -* containing the coordinates of the first point. -* point2 -* An array of double, with one element for each SkyFrame axis, -* containing the coordinates of the second point. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The distance between the two points, in radians. - -* Notes: -* - This function will return a "bad" result value (AST__BAD) if -* any of the input coordinates has this value. -* - A "bad" value will also be returned if this function is -* invoked with the AST error status set or if it should fail for -* any reason. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - const int *perm; /* Axis permutation array */ - double p1[ 2 ]; /* Permuted point1 coordinates */ - double p2[ 2 ]; /* Permuted point2 coordinates */ - double result; /* Value to return */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( astOK ) { - -/* Check that all supplied coordinates are OK. */ - if ( ( point1[ 0 ] != AST__BAD ) && ( point1[ 1 ] != AST__BAD ) && - ( point2[ 0 ] != AST__BAD ) && ( point2[ 1 ] != AST__BAD ) ) { - -/* Apply the axis permutation array to obtain the coordinates of the - two points in the required (longitude,latitude) order. */ - p1[ perm[ 0 ] ] = point1[ 0 ]; - p1[ perm[ 1 ] ] = point1[ 1 ]; - p2[ perm[ 0 ] ] = point2[ 0 ]; - p2[ perm[ 1 ] ] = point2[ 1 ]; - -/* Calculate the great circle distance between the points in radians. */ - result = palDsep( p1[ 0 ], p1[ 1 ], p2[ 0 ], p2[ 1 ] ); - } - } - -/* Return the result. */ - return result; -} - -static const char *Format( AstFrame *this_frame, int axis, double value, int *status ) { -/* -* Name: -* Format - -* Purpose: -* Format a coordinate value for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* const char *Format( AstFrame *this, int axis, double value, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astFormat method inherited -* from the Frame class). - -* Description: -* This function returns a pointer to a string containing the formatted -* (character) version of a coordinate value for a SkyFrame axis. The -* formatting applied is that specified by a previous invocation of the -* astSetFormat method. A suitable default format is applied if necessary, -* and this may depend on which sky coordinate system the SkyFrame -* describes. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* The number of the axis (zero-based) for which formatting is to be -* performed. -* value -* The coordinate value to be formatted, in radians. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to a null-terminated string containing the formatted value. - -* 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: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const char *result; /* Pointer value to return */ - int format_set; /* Format attribute set? */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Validate the axis index. */ - (void) astValidateAxis( this, axis, 1, "astFormat" ); - -/* Determine if a Format value has been set for the axis and set a temporary - value if it has not. Use the GetFormat member function for this class - together with member functions inherited from the parent class (rather than - using the object's methods directly) because if any of these methods have - been over-ridden by a derived class the Format string syntax may no longer - be compatible with this class. */ - format_set = (*parent_testformat)( this_frame, axis, status ); - if ( !format_set ) { - (*parent_setformat)( this_frame, axis, GetFormat( this_frame, axis, status ), status ); - } - -/* Use the Format member function inherited from the parent class to format the - value and return a pointer to the resulting string. */ - result = (*parent_format)( this_frame, axis, value, status ); - -/* If necessary, clear any temporary Format value that was set above. */ - if ( !format_set ) (*parent_clearformat)( this_frame, axis, status ); - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = NULL; - -/* Return the result. */ - return result; -} - -static AstPointSet *FrameGrid( AstFrame *this_object, int size, const double *lbnd, - const double *ubnd, int *status ){ -/* -* Name: -* FrameGrid - -* Purpose: -* Return a grid of points covering a rectangular area of a Frame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* AstPointSet *FrameGrid( AstFrame *this_frame, int size, -* const double *lbnd, const double *ubnd, -* int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astFrameGrid -* method inherited from the Frame class). - -* Description: -* This function returns a PointSet containing positions spread -* approximately evenly throughtout a specified rectangular area of -* the Frame. - -* Parameters: -* this -* Pointer to the Frame. -* size -* The preferred number of points in the returned PointSet. The -* actual number of points in the returned PointSet may be -* different, but an attempt is made to stick reasonably closely to -* the supplied value. -* lbnd -* Pointer to an array holding the lower bound of the rectangular -* area on each Frame axis. The array should have one element for -* each Frame axis. -* ubnd -* Pointer to an array holding the upper bound of the rectangular -* area on each Frame axis. The array should have one element for -* each Frame axis. - -* Returned Value: -* A pointer to a new PointSet holding the grid of points. - -* Notes: -* - A NULL pointer is returned if an error occurs. -*/ - -/* Local Variables: */ - AstPointSet *result; - AstSkyFrame *this; - double **ptr; - double box_area; - double cl; - double dlon; - double hilat; - double hilon; - double inclon; - double lat_size; - double lat; - double lon; - double lolon; - double lon_size; - double lolat; - double totlen; - int ilat; - int ilon; - int imer; - int ip; - int ipar; - int ipmax; - int nmer; - int npar; - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_object; - -/* Get the zero-based indices of the longitude and latitude axes. */ - ilon = astGetLonAxis( this ); - ilat = 1 - ilon; - -/* The latitude bounds may not be the right way round so check for it. */ - if( lbnd[ ilat ] <= ubnd[ ilat ] ) { - lolat = lbnd[ ilat ]; - hilat = ubnd[ ilat ]; - } else { - lolat = ubnd[ ilat ]; - hilat = lbnd[ ilat ]; - } - -/* Check all bounds are good. Also check the size is positive. */ - lolon = lbnd[ ilon ]; - hilon = ubnd[ ilon ]; - if( size > 0 && lolat != AST__BAD && hilat != AST__BAD && - lolon != AST__BAD && hilon != AST__BAD ) { - -/* Ensure the longitude bounds are in the range 0-2PI. */ - lolon = palDranrm( lolon ); - hilon = palDranrm( hilon ); - -/* If the upper longitude limit is less than the lower limit, add 2.PI */ - if( hilon <= lolon && - ubnd[ ilon ] != lbnd[ ilon ] ) hilon += 2*AST__DPI; - -/* Get the total area of the box in steradians. */ - dlon = hilon - lolon; - box_area = fabs( dlon*( sin( hilat ) - sin( lolat ) ) ); - -/* Get the nominal size of a square grid cell, in radians. */ - lat_size = sqrt( box_area/size ); - -/* How many parallels should we use to cover the box? Ensure we use at - least two. These parallels pass through the centre of the grid cells. */ - npar = (int)( 0.5 + ( hilat - lolat )/lat_size ); - if( npar < 2 ) npar = 2; - -/* Find the actual sample size implied by this number of parallels. */ - lat_size = ( hilat - lolat )/npar; - -/* Find the total arc length of the parallels. */ - totlen = 0.0; - lat = lolat + 0.5*lat_size; - for( ipar = 0; ipar < npar; ipar++ ) { - totlen += dlon*cos( lat ); - lat += lat_size; - } - -/* If we space "size" samples evenly over this total arc-length, what is - the arc-distance between samples? */ - lon_size = totlen/size; - -/* Create a PointSet in which to store the grid. Make it bigger than - necessary in order to leave room for extra samples caused by integer - truncation. */ - ipmax = 2*size; - result = astPointSet( ipmax, 2, " ", status ); - ptr = astGetPoints( result ); - if( astOK ) { - -/* Loop over all the parallels. */ - ip = 0; - lat = lolat + 0.5*lat_size; - for( ipar = 0; ipar < npar; ipar++ ) { - -/* Get the longitude increment between samples on this parallel. */ - cl = cos( lat ); - inclon = ( cl != 0.0 ) ? lon_size/cl : 0.0; - -/* Get the number of longitude samples for this parallel. Reduce it if - it would extend beyond the end of the PointSet. */ - nmer = dlon/inclon; - if( ip + nmer >= ipmax ) nmer = ipmax - ip; - -/* Adjust the longitude increment to take up any slack caused by the - above integer division. */ - inclon = dlon/nmer; - -/* Produce the samples for the current parallel. */ - lon = lolon + 0.5*inclon; - for( imer = 0; imer < nmer; imer++ ) { - ptr[ ilon ][ ip ] = lon; - ptr[ ilat ][ ip ] = lat; - - lon += inclon; - ip++; - } - -/* Get the latitude on the next parallel. */ - lat += lat_size; - } - -/* Truncate the PointSet to exclude unused elements at the end. */ - astSetNpoint( result, ip ); - } - -/* Report error if supplied values were bad. */ - } else if( astOK ) { - if( size < 1 ) { - astError( AST__ATTIN, "astFrameGrid(%s): The supplied grid " - "size (%d) is invalid (programming error).", - status, astGetClass( this ), size ); - } else { - astError( AST__ATTIN, "astFrameGrid(%s): One of more of the " - "supplied bounds is AST__BAD (programming error).", - status, astGetClass( this ) ); - } - } - -/* Annul the returned PointSet if an error has occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return the PointSet holding the grid. */ - return result; -} - -static double Gap( AstFrame *this_frame, int axis, double gap, int *ntick, int *status ) { -/* -* Name: -* Gap - -* Purpose: -* Find a "nice" gap for tabulating SkyFrame axis values. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double Gap( AstFrame *this, int axis, double gap, int *ntick, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astGap method -* inherited from the Frame class). - -* Description: -* This function returns a gap size which produces a nicely spaced -* series of formatted values for a SkyFrame axis, the returned gap -* size being as close as possible to the supplied target gap -* size. It also returns a convenient number of divisions into -* which the gap can be divided. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* The number of the axis (zero-based) for which a gap is to be found. -* gap -* The target gap size. -* ntick -* Address of an int in which to return a convenient number of -* divisions into which the gap can be divided. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The nice gap size. - -* Notes: -* - A value of zero is returned if the target gap size is zero. -* - A negative gap size is returned if the supplied gap size is negative. -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - double result; /* Gap value to return */ - int format_set; /* Format attribute set? */ - -/* Check the global error status. */ - if ( !astOK ) return 0.0; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Validate the axis index. */ - (void) astValidateAxis( this, axis, 1, "astGap" ); - -/* Determine if a Format value has been set for the axis and set a - temporary value if it has not. Use the GetFormat member function - for this class together with member functions inherited from the - parent class (rather than using the object's methods directly) - because if any of these methods have been over-ridden by a derived - class the Format string syntax may no longer be compatible with - this class. */ - format_set = (*parent_testformat)( this_frame, axis, status ); - if ( !format_set ) { - (*parent_setformat)( this_frame, axis, GetFormat( this_frame, axis, status ), status ); - } - -/* Use the Gap member function inherited from the parent class to find - the gap size. */ - result = (*parent_gap)( this_frame, axis, gap, ntick, status ); - -/* If necessary, clear any temporary Format value that was set above. */ - if ( !format_set ) (*parent_clearformat)( this_frame, axis, status ); - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = 0.0; - -/* Return the result. */ - return result; -} - -static int GetObjSize( AstObject *this_object, int *status ) { -/* -* Name: -* GetObjSize - -* Purpose: -* Return the in-memory size of an Object. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int GetObjSize( AstObject *this, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetObjSize protected -* method inherited from the parent class). - -* Description: -* This function returns the in-memory size of the supplied SkyFrame, -* in bytes. - -* Parameters: -* this -* Pointer to the SkyFrame. -* 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: */ - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointers to the SkyFrame structure. */ - this = (AstSkyFrame *) 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->projection ); - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = 0; - -/* Return the result, */ - return result; -} - -static int GetActiveUnit( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetActiveUnit - -* Purpose: -* Obtain the value of the ActiveUnit flag for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int GetActiveUnit( AstFrame *this_frame, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetActiveUnit protected -* method inherited from the Frame class). - -* Description: -* This function returns the value of the ActiveUnit flag for a -* SkyFrame, which is always 0. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The value to use for the ActiveUnit flag (0). - -*/ - return 0; -} - -static int GetAsTime( AstSkyFrame *this, int axis, int *status ) { -/* -* Name: -* GetAsTime - -* Purpose: -* Obtain the value of the AsTime attribute for a SkyFrame's axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int GetAsTime( AstSkyFrame *this, int axis, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function returns the boolean value of the AsTime attribute for a -* specified axis of a SkyFrame. This value indicates whether axis values -* should be formatted as times (as opposed to angles) by default. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Index of the axis for which information is required (zero based). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Zero or one, according to the setting of the AsTime attribute (if no -* value has previously been set, a suitable default is returned). - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstAxis *ax; /* Pointer to Axis object */ - int axis_p; /* Permuted axis index */ - int result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Initialise. */ - result = 0; - -/* Validate and permute the axis index. */ - axis_p = astValidateAxis( this, axis, 1, "astGetAsTime" ); - -/* Obtain a pointer to the required Axis object. */ - ax = astGetAxis( this, axis ); - -/* Determine if the AsTime attribute has been set for the axis (this can only - be the case if the object is a SkyAxis). If the attribute is set, obtain its - value. */ - if ( astIsASkyAxis( ax ) && astTestAxisAsTime( ax ) ) { - result = astGetAxisAsTime( ax ); - -/* Otherwise, check which (permuted) axis is involved. Only the first - (longitude) axis may be displayed as a time by default. */ - } else if ( axis_p == 0 ) { - -/* Test for those coordinate systems which normally have their longitude axes - displayed as times (basically, those that involve the Earth's equator) and - set the returned value appropriately. */ - result = IsEquatorial( astGetSystem( this ), status ); - } - -/* Annul the Axis object pointer. */ - ax = astAnnul( ax ); - -/* 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 SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* const char *GetAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astGetAttrib -* method inherited from the Frame class). - -* Description: -* This function returns a pointer to the value of a specified -* attribute for a SkyFrame, formatted as a character string. - -* Parameters: -* this -* Pointer to the SkyFrame. -* 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: -* - This function uses one-based axis numbering so that it is -* suitable for external (public) use. -* - The returned string pointer may point at memory allocated -* within the SkyFrame, 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 SkyFrame. A copy of the string should -* therefore be made if necessary. -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const char *cval; /* Pointer to character attribute value */ - const char *result; /* Pointer value to return */ - double dval; /* Floating point attribute value */ - double equinox; /* Equinox attribute value (as MJD) */ - int as_time; /* AsTime attribute value */ - int axis; /* SkyFrame axis number */ - int ival; /* Integer attribute value */ - int len; /* Length of attrib string */ - int nc; /* No. characters read by astSscanf */ - int neglon; /* Display long. values as [-pi,pi]? */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this_object); - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) 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. */ - -/* AsTime(axis). */ -/* ------------- */ - if ( nc = 0, - ( 1 == astSscanf( attrib, "astime(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - as_time = astGetAsTime( this, axis - 1 ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", as_time ); - result = getattrib_buff; - } - -/* Equinox. */ -/* -------- */ - } else if ( !strcmp( attrib, "equinox" ) ) { - equinox = astGetEquinox( this ); - if ( astOK ) { - -/* Format the Equinox as decimal years. Use a Besselian epoch if it - will be less than 1984.0, otherwise use a Julian epoch. */ - result = astFmtDecimalYr( ( equinox < palEpj2d( 1984.0 ) ) ? - palEpb( equinox ) : palEpj( equinox ), - AST__DBL_DIG ); - } - -/* IsLatAxis(axis) */ -/* --------------- */ - } else if ( nc = 0, - ( 1 == astSscanf( attrib, "islataxis(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - ival = astGetIsLatAxis( this, axis - 1 ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", ival ); - result = getattrib_buff; - } - -/* IsLonAxis(axis) */ -/* --------------- */ - } else if ( nc = 0, - ( 1 == astSscanf( attrib, "islonaxis(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - ival = astGetIsLonAxis( this, axis - 1 ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", ival ); - result = getattrib_buff; - } - -/* LatAxis */ -/* -------- */ - } else if ( !strcmp( attrib, "lataxis" ) ) { - axis = astGetLatAxis( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", axis + 1 ); - result = getattrib_buff; - } - -/* LonAxis */ -/* -------- */ - } else if ( !strcmp( attrib, "lonaxis" ) ) { - axis = astGetLonAxis( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", axis + 1 ); - result = getattrib_buff; - } - -/* NegLon */ -/* ------ */ - } else if ( !strcmp( attrib, "neglon" ) ) { - neglon = astGetNegLon( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", neglon ); - result = getattrib_buff; - } - -/* SkyTol */ -/* ------ */ - } else if ( !strcmp( attrib, "skytol" ) ) { - dval = astGetSkyTol( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); - result = getattrib_buff; - } - -/* Projection. */ -/* ----------- */ - } else if ( !strcmp( attrib, "projection" ) ) { - result = astGetProjection( this ); - -/* SkyRef. */ -/* ------- */ - } else if ( !strcmp( attrib, "skyref" ) ) { - cval = astFormat( this, 0, astGetSkyRef( this, 0 ) ); - if ( astOK ) { - nc = sprintf( getattrib_buff, "%s, ", cval ); - cval = astFormat( this, 1, astGetSkyRef( this, 1 ) ); - if ( astOK ) { - (void) sprintf( getattrib_buff + nc, "%s", cval ); - result = getattrib_buff; - } - } - -/* SkyRef(axis). */ -/* ------------- */ - } else if ( nc = 0, - ( 1 == astSscanf( attrib, "skyref(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - dval = astGetSkyRef( this, axis - 1 ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); - result = getattrib_buff; - } - -/* SkyRefP. */ -/* -------- */ - } else if ( !strcmp( attrib, "skyrefp" ) ) { - cval = astFormat( this, 0, astGetSkyRefP( this, 0 ) ); - if ( astOK ) { - nc = sprintf( getattrib_buff, "%s, ", cval ); - cval = astFormat( this, 1, astGetSkyRefP( this, 1 ) ); - if ( astOK ) { - (void) sprintf( getattrib_buff + nc, "%s", cval ); - result = getattrib_buff; - } - } - -/* SkyRefP(axis). */ -/* -------------- */ - } else if ( nc = 0, - ( 1 == astSscanf( attrib, "skyrefp(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - dval = astGetSkyRefP( this, axis - 1 ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); - result = getattrib_buff; - } - -/* SkyRefIs. */ -/* --------- */ - } else if ( !strcmp( attrib, "skyrefis" ) ) { - ival = astGetSkyRefIs( this ); - if ( astOK ) { - if( ival == AST__POLE_REF ){ - result = POLE_STRING; - } else if( ival == AST__IGNORED_REF ){ - result = IGNORED_STRING; - } else { - result = ORIGIN_STRING; - } - } - -/* AlignOffset */ -/* ----------- */ - } else if ( !strcmp( attrib, "alignoffset" ) ) { - ival = astGetAlignOffset( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", ival ); - result = getattrib_buff; - } - -/* If the attribute name was not recognised, pass it on to the parent - method for further interpretation. */ - } else { - result = (*parent_getattrib)( this_object, attrib, status ); - } - -/* Return the result. */ - return result; -} - -static int GetDirection( AstFrame *this_frame, int axis, int *status ) { -/* -* Name: -* GetDirection - -* Purpose: -* Obtain the value of the Direction attribute for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int GetDirection( AstFrame *this_frame, int axis, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetDirection method inherited -* from the Frame class). - -* Description: -* This function returns the value of the Direction attribute for a -* specified axis of a SkyFrame. A suitable default value is returned if no -* Direction value has previously been set. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Axis index (zero-based) identifying the axis for which information is -* required. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Zero or one, depending on the Direction attribute value. - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - int axis_p; /* Permuted axis index */ - int result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Initialise. */ - result = 0; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Validate and permute the axis index. */ - axis_p = astValidateAxis( this, axis, 1, "astGetDirection" ); - -/* Check if a value has been set for the axis Direction attribute. If so, - obtain its value. */ - if ( astTestDirection( this, axis ) ) { - result = (*parent_getdirection)( this_frame, axis, status ); - -/* Otherwise, we will generate a default Direction value. Currently all - systems supported by SkyFrame are left handed, so all longitude axes - are reversed and all latitude axes are not reversed. */ - } else if( axis_p == 0 ) { - result = 0; - } else { - result = 1; - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = 0; - -/* Return the result. */ - return result; -} - -static double GetBottom( AstFrame *this_frame, int axis, int *status ) { -/* -* Name: -* GetBottom - -* Purpose: -* Obtain the value of the Bottom attribute for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double GetBottom( AstFrame *this_frame, int axis, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetBottom method inherited -* from the Frame class). - -* Description: -* This function returns the value of the Bottom attribute for a -* specified axis of a SkyFrame. A suitable default value is returned if no -* value has previously been set. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Axis index (zero-based) identifying the axis for which information is -* required. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The Bottom value to use. - -* Notes: -* - A value of -DBL_MAX will be returned if this function is invoked -* with the global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - int axis_p; /* Permuted axis index */ - double result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return -DBL_MAX; - -/* Initialise. */ - result = -DBL_MAX; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Validate and permute the axis index. */ - axis_p = astValidateAxis( this, axis, 1, "astGetBottom" ); - -/* Check if a value has been set for the axis Bottom attribute. If so, - obtain its value. */ - if ( astTestBottom( this, axis ) ) { - result = (*parent_getbottom)( this_frame, axis, status ); - -/* Otherwise, we will return a default Bottom value appropriate to the - SkyFrame class. */ - } else { - -/* If it is a latitude axis return -pi/2. */ - if( axis_p == 1 ) { - result = -piby2; - -/* If it is a longitude value return -DBL_MAX (i.e. no lower limit). */ - } else { - result = -DBL_MAX; - } - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = -DBL_MAX; - -/* Return the result. */ - return result; -} - -static double GetCachedLAST( AstSkyFrame *this, double epoch, double obslon, - double obslat, double obsalt, double dut1, - double dtai, int *status ) { -/* -* Name: -* GetCachedLAST - -* Purpose: -* Attempt to get a LAST value from the cache in the SkyFrame vtab. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double GetCachedLAST( AstSkyFrame *this, double epoch, double obslon, -* double obslat, double obsalt, double dut1, -* double dtai, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function searches the static cache of LAST values held in the -* SkyFrame virtual function table for a value that corresponds to the -* supplied parameter values. If one is found, it is returned. -* Otherwise AST__BAD is found. - -* Parameters: -* this -* Pointer to the SkyFrame. -* epoch -* The epoch (MJD). -* obslon -* Observatory geodetic longitude (radians) -* obslat -* Observatory geodetic latitude (radians) -* obsalt -* Observatory geodetic altitude (metres) -* dut1 -* The UT1-UTC correction, in seconds. -* dtai -* The TAI-UTC correction, in seconds. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The Local Apparent Sidereal Time, in radians. - -* Notes: -* - A value of AST__BAD 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 - AstSkyLastTable *table; - double *ep; - double *lp; - double dep; - double result; - int ihi; - int ilo; - int itable; - int itest; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this); - -/* Initialise */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Wait until the table is not being written to by any thread. This also - prevents a thread from writing to the table whilst we are reading it. */ - LOCK_RLOCK1 - -/* Loop round every LAST table held in the vtab. Each table refers to a - different observatory position and/or DUT1 and/or DTAI value. */ - for( itable = 0; itable < nlast_tables; itable++ ) { - table = last_tables[ itable ]; - -/* See if the table refers to the given position, dut1 and dtai value, allowing - some small tolerance. */ - if( fabs( table->obslat - obslat ) < 2.0E-7 && - fabs( table->obslon - obslon ) < 2.0E-7 && - fabs( table->obsalt - obsalt ) < 1.0 && - fabs( table->dut1 - dut1 ) < 1.0E-5 && - EQUAL( table->dtai, dtai, 1.0E-5 ) ) { - -/* Get pointers to the array of epoch and corresponding LAST values in - the table. */ - ep = table->epoch; - lp = table->last; - -/* The values in the epoch array are monotonic increasing. Do a binary chop - within the table's epoch array to find the earliest entry that has a - value equal to or greater than the supplied epoch value. */ - ilo = 0; - ihi = table->nentry - 1; - while( ihi > ilo ) { - itest = ( ilo + ihi )/2; - if( ep[ itest ] >= epoch ) { - ihi = itest; - } else { - ilo = itest + 1; - } - } - -/* Get the difference between the epoch at the entry selected above and - the requested epoch. */ - dep = ep[ ilo ] - epoch; - -/* If the entry selected above is the first entry in the table, it can - only be used if it is within 0.001 second of the requested epoch. */ - if( ilo == 0 ) { - if( fabs( dep ) < 0.001/86400.0 ) { - result = lp[ 0 ]; - } - -/* If the list of epoch values contained no value that was greater than - the supplied epoch value, then we can use the last entry if - it is no more than 0.001 second away from the requested epoch. */ - } else if( dep <= 0.0 ) { - if( fabs( dep ) < 0.001/86400.0 ) { - result = lp[ ilo ]; - } - - -/* Otherwise, see if the entry selected above is sufficiently close to - its lower neighbour (i.e. closer than 0.4 days) to allow a reasonably - accurate LAST value to be determined by interpolation. */ - } else if( ep[ ilo ] - ep[ ilo - 1 ] < 0.4 ) { - ep += ilo - 1; - lp += ilo - 1; - result = *lp + ( epoch - *ep )*( lp[ 1 ] - *lp )/( ep[ 1 ] - *ep ); - -/* If the neighbouring point is too far away for interpolation to be - reliable, then we can only use the point if it is within 0.001 seconds of - the requested epoch. */ - } else if( fabs( dep ) < 0.001/86400.0 ) { - result = lp[ ilo ]; - } - -/* If we have found the right table, we do not need to look at any other - tables, so leave the table loop. */ - break; - } - } - -/* Indicate that threads may now write to the table. */ - UNLOCK_RWLOCK1 - -/* Ensure the returned value is within the range 0 - 2.PI. */ - if( result != AST__BAD ) { - while( result > 2*AST__DPI ) result -= 2*AST__DPI; - while( result < 0.0 ) result += 2*AST__DPI; - } - -/* Return the required LAST value. */ - return result; -} - -static double GetEpoch( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetEpoch - -* Purpose: -* Obtain the value of the Epoch attribute for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double GetEpoch( AstFrame *this_frame, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetEpoch method inherited -* from the Frame class). - -* Description: -* This function returns the value of the Epoch attribute for a -* SkyFrame. A suitable default value is returned if no value has -* previously been set. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The Epoch value to use. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - AstSystemType system; /* System attribute */ - double result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return AST__BAD; - -/* Initialise. */ - result = AST__BAD; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Check if a value has been set for the Epoch attribute. If so, obtain its - value. */ - if ( astTestEpoch( this ) ) { - result = (*parent_getepoch)( this_frame, status ); - -/* Otherwise, we will return a default Epoch value appropriate to the - SkyFrame class. */ - } else { - -/* Provide a default value of B1950.0 or J2000.0 depending on the System - setting. */ - system = astGetSystem( this ); - if( system == AST__FK4 || system == AST__FK4_NO_E ) { - result = palEpb2d( 1950.0 ); - } else { - result = palEpj2d( 2000.0 ); - } - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = AST__BAD; - -/* Return the result. */ - return result; -} - -static double GetTop( AstFrame *this_frame, int axis, int *status ) { -/* -* Name: -* GetTop - -* Purpose: -* Obtain the value of the Top attribute for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double GetTop( AstFrame *this_frame, int axis, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetTop method inherited -* from the Frame class). - -* Description: -* This function returns the value of the Top attribute for a -* specified axis of a SkyFrame. A suitable default value is returned if no -* value has previously been set. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Axis index (zero-based) identifying the axis for which information is -* required. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The Top value to use. - -* Notes: -* - A value of DBL_MAX will be returned if this function is invoked -* with the global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - int axis_p; /* Permuted axis index */ - double result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return DBL_MAX; - -/* Initialise. */ - result = DBL_MAX; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Validate and permute the axis index. */ - axis_p = astValidateAxis( this, axis, 1, "astGetTop" ); - -/* Check if a value has been set for the axis Top attribute. If so, - obtain its value. */ - if ( astTestTop( this, axis ) ) { - result = (*parent_gettop)( this_frame, axis, status ); - -/* Otherwise, we will return a default Top value appropriate to the - SkyFrame class. */ - } else { - -/* If this is a latitude axis return pi/2. */ - if( axis_p == 1 ) { - result = piby2; - -/* If it is a longitude value return DBL_MAX (i.e. no upper limit). */ - } else { - result = DBL_MAX; - } - } - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = DBL_MAX; - -/* Return the result. */ - return result; -} - -static const char *GetDomain( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetDomain - -* Purpose: -* Obtain a pointer to the Domain attribute string for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* const char *GetDomain( AstFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetDomain protected -* method inherited from the Frame class). - -* Description: -* This function returns a pointer to the Domain attribute string -* for a SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A pointer to a constant null-terminated string containing the -* Domain value. - -* Notes: -* - The returned pointer or the string it refers to may become -* invalid following further invocation of this function or -* modification of the SkyFrame. -* - A NULL pointer is returned if this function is invoked with -* the global error status set or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - const char *result; /* Pointer value to return */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* If a Domain attribute string has been set, invoke the parent method - to obtain a pointer to it. */ - if ( astTestDomain( this ) ) { - result = (*parent_getdomain)( this_frame, status ); - -/* Otherwise, provide a pointer to a suitable default string. */ - } else { - result = "SKY"; - } - -/* Return the result. */ - return result; -} - -static const char *GetFormat( AstFrame *this_frame, int axis, int *status ) { -/* -* Name: -* GetFormat - -* Purpose: -* Access the Format string for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* const char *GetFormat( AstFrame *this, int axis ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetFormat method inherited -* from the Frame class). - -* Description: -* This function returns a pointer to the Format string for a specified axis -* of a SkyFrame. A pointer to a suitable default string is returned if no -* Format value has previously been set. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Axis index (zero-based) identifying the axis for which information is -* required. - -* Returned Value: -* Pointer to a null-terminated character string containing the requested -* information. - -* Notes: -* - A NULL pointer will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstAxis *ax; /* Pointer to Axis object */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const char *result; /* Pointer value to return */ - int as_time; /* Value of AsTime attribute */ - int as_time_set; /* AsTime attribute set? */ - int axis_p; /* Permuted axis index */ - int digits; /* Number of digits of precision */ - int is_latitude; /* Value of IsLatitude attribute */ - int is_latitude_set; /* IsLatitude attribute set? */ - int parent; /* Use parent method? */ - int skyaxis; /* Is the Axis a SkyAxis? */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this_frame); - -/* Initialise. */ - result = NULL; - as_time_set = 0; - is_latitude = 0; - is_latitude_set = 0; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Validate and permute the axis index. */ - axis_p = astValidateAxis( this, axis, 1, "astGetFormat" ); - -/* Obtain a pointer to the Axis structure. */ - ax = astGetAxis( this, axis ); - -/* Decide whether the parent astGetFormat method is able to provide the format - string we require. We must use the parent method if the Axis is not a - SkyAxis, because the syntax of the Format string would become unsuitable - for use with the Axis astFormat method if it was over-ridden here. We also - use the parent method to return a Format pointer if an explicit Format - string has already been set. */ - skyaxis = astIsASkyAxis( ax ); - parent = ( !skyaxis || (*parent_testformat)( this_frame, axis, status ) ); - -/* If neither of the above conditions apply, we may still be able to use the - parent method if the Axis (actually a SkyAxis) is required to behave as a - normal RA or DEC axis, as this is the standard behaviour provided by the - SkyAxis class. Examine the SkyFrame's System attribute to determine if its - axes should behave in this way. */ - if ( !parent ) parent = IsEquatorial( astGetSystem( this ), status ); - -/* If using the parent method and dealing with a SkyAxis, determine the - settings of any attributes that may affect the Format string. */ - if ( astOK ) { - if ( parent ) { - if ( skyaxis ) { - as_time_set = astTestAsTime( this, axis ); - is_latitude_set = astTestAxisIsLatitude( ax ); - is_latitude = astGetAxisIsLatitude( ax ); - -/* If no AsTime value is set for the axis, set a temporary value as determined - by the astGetAsTime method, which supplies suitable defaults for the axes of - a SkyFrame. */ - if ( !as_time_set ) { - astSetAsTime( this, axis, astGetAsTime( this, axis ) ); - } - -/* Temporarly over-ride the SkyAxis IsLatitude attribute, regardless of its - setting, as the second axis of a SkyFrame is always the latitude axis. */ - astSetAxisIsLatitude( ax, axis_p == 1 ); - } - -/* Invoke the parent method to obtain a pointer to the Format string. */ - result = (*parent_getformat)( this_frame, axis, status ); - -/* Now restore the attributes that were temporarily over-ridden above to their - previous states. */ - if ( skyaxis ) { - if ( !as_time_set ) astClearAsTime( this, axis ); - if ( !is_latitude_set ) { - astClearAxisIsLatitude( ax ); - } else { - astSetAxisIsLatitude( ax, is_latitude ); - } - } - -/* If the parent method is unsuitable, we must construct a new Format string - here. This affects only those coordinate systems whose axes do not behave - like standard RA/DEC axes (e.g. typically ecliptic, galactic and - supergalactic coordinates). For these, we format values as decimal degrees - (or decimal hours if the AsTime attribute is set). Obtain the AsTime - value. */ - } else { - as_time = astGetAsTime( this, axis ); - -/* Determine how many digits of precision to use. This is obtained from the - SkyAxis Digits attribute (if set), otherwise from the Digits attribute of - the enclosing SkyFrame. */ - if ( astTestAxisDigits( ax ) ) { - digits = astGetAxisDigits( ax ); - } else { - digits = astGetDigits( this ); - } - -/* If a time format is required, generate a Format string using decimal - hours. */ - if ( astOK ) { - if ( as_time ) { - if ( digits <= 2 ) { - result = "h"; - } else { - (void) sprintf( getformat_buff, "h.%d", digits - 2 ); - result = getformat_buff; - } - -/* Otherwise use decimal degrees. */ - } else { - if ( digits <= 3 ) { - result = "d"; - } else { - (void) sprintf( getformat_buff, "d.%d", digits - 3 ); - result = getformat_buff; - } - } - } - } - } - -/* Annul the Axis pointer. */ - ax = astAnnul( ax ); - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = NULL; - -/* Return the result. */ - return result; -} - -static const char *GetLabel( AstFrame *this, int axis, int *status ) { -/* -* Name: -* GetLabel - -* Purpose: -* Access the Label string for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* const char *GetLabel( AstFrame *this, int axis, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetLabel method inherited -* from the Frame class). - -* Description: -* This function returns a pointer to the Label string for a specified axis -* of a SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Axis index (zero-based) identifying the axis for which information is -* required. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to a constant null-terminated character string containing the -* requested information. - -* Notes: -* - A NULL pointer will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstSystemType system; /* Code identifying type of sky coordinates */ - const char *result; /* Pointer to label string */ - int axis_p; /* Permuted axis index */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this); - -/* Initialise. */ - result = NULL; - -/* Validate and permute the axis index. */ - axis_p = astValidateAxis( this, axis, 1, "astGetLabel" ); - -/* Check if a value has been set for the required axis label string. If so, - invoke the parent astGetLabel method to obtain a pointer to it. */ - if ( astTestLabel( this, axis ) ) { - result = (*parent_getlabel)( this, axis, status ); - -/* Otherwise, identify the sky coordinate system described by the SkyFrame. */ - } else { - system = astGetSystem( this ); - -/* If OK, supply a pointer to a suitable default label string. */ - if ( astOK ) { - -/* Equatorial coordinate systems. */ - if ( IsEquatorial( system, status ) ) { - result = ( axis_p == 0 ) ? "Right ascension" : - "Declination"; - -/* Ecliptic coordinates. */ - } else if ( system == AST__ECLIPTIC ) { - result = ( axis_p == 0 ) ? "Ecliptic longitude" : - "Ecliptic latitude"; - -/* Helio-ecliptic coordinates. */ - } else if ( system == AST__HELIOECLIPTIC ) { - result = ( axis_p == 0 ) ? "Helio-ecliptic longitude" : - "Helio-ecliptic latitude"; - -/* AzEl coordinates. */ - } else if ( system == AST__AZEL ) { - result = ( axis_p == 0 ) ? "Azimuth" : - "Elevation"; - -/* Galactic coordinates. */ - } else if ( system == AST__GALACTIC ) { - result = ( axis_p == 0 ) ? "Galactic longitude" : - "Galactic latitude"; - -/* Supergalactic coordinates. */ - } else if ( system == AST__SUPERGALACTIC ) { - result = ( axis_p == 0 ) ? "Supergalactic longitude" : - "Supergalactic latitude"; - -/* Unknown spherical coordinates. */ - } else if ( system == AST__UNKNOWN ) { - result = ( axis_p == 0 ) ? "Longitude" : - "Latitude"; - -/* Report an error if the coordinate system was not recognised. */ - } else { - astError( AST__SCSIN, "astGetLabel(%s): Corrupt %s contains " - "invalid sky coordinate system identification code " - "(%d).", status, astGetClass( this ), astGetClass( this ), - (int) system ); - } - -/* If the SkyRef attribute has a set value, append " offset" to the label. */ - if( astGetSkyRefIs( this ) != AST__IGNORED_REF && - ( astTestSkyRef( this, 0 ) || astTestSkyRef( this, 1 ) ) ) { - sprintf( getlabel_buff, "%s offset", result ); - result = getlabel_buff; - } - } - } - -/* Return the result. */ - return result; -} - -static double GetDiurab( AstSkyFrame *this, int *status ) { -/* -* Name: -* GetDiurab - -* Purpose: -* Return the magnitude of the diurnal aberration vector. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double GetDiurab( AstSkyFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function - -* Description: -* This function returns the magnitude of the diurnal aberration -* vector. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The magnitude of the diurnal aberration vector. - -*/ - -/* Local Variables: */ - double uau; - double vau; - -/* Check the global error status. */ - if ( !astOK ) return AST__BAD; - -/* If the magnitude of the diurnal aberration vector has not yet been - found, find it now, and cache it in the SkyFrame structure. The cached - value will be reset to AST__BAD if the ObsLat attribute value is - changed. This code is transliterated from SLA_AOPPA. */ - if( this->diurab == AST__BAD ) { - palGeoc( astGetObsLat( this ), astGetObsAlt( this ), &uau, &vau ); - this->diurab = 2*AST__DPI*uau*SOLSID/C; - } - -/* Return the result, */ - return this->diurab; -} - -static double GetLAST( AstSkyFrame *this, int *status ) { -/* -* Name: -* GetLAST - -* Purpose: -* Return the Local Apparent Sidereal Time for the SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double GetLAST( AstSkyFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function - -* Description: -* This function returns the Local Apparent Sidereal Time (LAST) -* at the moment intime given by the Epoch attribute of the SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The LAST value. - -*/ - -/* Local Variables: */ - double dlast; /* Change in LAST */ - double epoch; /* Epoch (TDB MJD) */ - double last1; /* LAST at end of current interval */ - double result; /* Result value to return */ - double delta_epoch; /* Change in Epoch */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* The "last" component of the SkyFrame structure holds the accurate - LAST at the moment in time given by the "eplast" (a TDB MJD) component - of the SkyFrame structure. If the current value of the SkyFrame's - Epoch attribute is not much different to "eplast" (within 0.4 of a day), - then the returned LAST value is the "last" value plus the difference - between Epoch and "eplast", converted from solar to sidereal time, - then converted to radians. This approximation seems to be good to less - than a tenth of an arcsecond. If this approximation cannot be used, - invoke SetLast to recalculate the accurate LAST and update the "eplast" - and "last" values. */ - if( this->eplast != AST__BAD ) { - epoch = astGetEpoch( this ); - delta_epoch = epoch - this->eplast; - -/* Return the current LAST value if the epoch has not changed. */ - if( delta_epoch == 0.0 ) { - result = this->last; - -/* If the previous full calculation of LAST was less than 0.4 days ago, - use a linear approximation to LAST. */ - } else if( fabs( delta_epoch ) < 0.4 ) { - -/* If we do not know the ratio of sidereal to solar time at the current - epoch, calculate it now. This involves a full calculation of LAST at - the end of the current linear approximation period. */ - if( this->klast == AST__BAD ) { - last1 = CalcLAST( this, this->eplast + 0.4, astGetObsLon( this ), - astGetObsLat( this ), astGetObsAlt( this ), - astGetDut1( this ), astGetDtai( this ), status ); - -/* Ensure the change in LAST is positive so that we get a positive ratio. */ - dlast = last1 - this->last; - if( dlast < 0.0 ) dlast += 2*AST__DPI; - this->klast = 2*AST__DPI*0.4/dlast; - } - -/* Now use the ratio of solar to sidereal time to calculate the linear - approximation to LAST. */ - result = this->last + 2*AST__DPI*delta_epoch/this->klast; - -/* If the last accurate calculation of LAST was more than 0.4 days ago, - do a full accurate calculation. */ - } else { - SetLast( this, status ); - result = this->last; - } - -/* If we have not yet done an accurate calculation of LAST, do one now. */ - } else { - SetLast( this, status ); - result = this->last; - } - -/* Return the result, */ - return result; -} - -static int GetIsLatAxis( AstSkyFrame *this, int axis, int *status ) { -/* -* Name: -* GetIsLatAxis - -* Purpose: -* Test an axis to see if it is a latitude axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int GetIsLatAxis( AstSkyFrame *this, int axis, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function tests if a SkyFrame axis is a celestial latitude axis. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Zero based axis index. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if the supplied axis is a celestial latitude axis, and zero -* otherwise. - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - int result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Get the index of the latitude axis and compare to the supplied axis - index. */ - result = ( axis == astGetLatAxis( this ) ); - -/* Return the result. */ - return astOK ? result : 0; - -} - -static int GetIsLonAxis( AstSkyFrame *this, int axis, int *status ) { -/* -* Name: -* GetIsLonAxis - -* Purpose: -* Test an axis to see if it is a longitude axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int GetIsLonAxis( AstSkyFrame *this, int axis, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function tests if a SkyFrame axis is a celestial longitude axis. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Zero based axis index. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* One if the supplied axis is a celestial longitude axis, and zero -* otherwise. - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - int result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Get the index of the longitude axis and compare to the supplied axis - index. */ - result = ( axis == astGetLonAxis( this ) ); - -/* Return the result. */ - return astOK ? result : 0; - -} - -static int GetLatAxis( AstSkyFrame *this, int *status ) { -/* -* Name: -* GetLatAxis - -* Purpose: -* Obtain the index of the latitude axis of a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int GetLatAxis( AstSkyFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function returns the zero-based index of the latitude axis of -* a SkyFrame, taking into account any current axis permutation. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The zero based axis index (0 or 1) of the latitude axis. - -* Notes: -* - A value of one will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - int result; /* Result to be returned */ - const int *perm; /* Axis permutation array */ - -/* Check the global error status. */ - if ( !astOK ) return 1; - -/* Initialise. */ - result = 1; - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( astOK ) { - -/* Identify the latitude axis. */ - if( perm[ 0 ] == 1 ) { - result = 0; - } else { - result = 1; - } - - } - -/* Return the result. */ - return result; - -} - -static int GetLonAxis( AstSkyFrame *this, int *status ) { -/* -* Name: -* GetLonAxis - -* Purpose: -* Obtain the index of the longitude axis of a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int GetLonAxis( AstSkyFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function returns the zero-based index of the longitude axis of -* a SkyFrame, taking into account any current axis permutation. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The zero based axis index (0 or 1) of the longitude axis. - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - int result; /* Result to be returned */ - const int *perm; /* Axis permutation array */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Initialise. */ - result = 0; - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( astOK ) { - -/* Identify the longitude axis. */ - if( perm[ 0 ] == 0 ) { - result = 0; - } else { - result = 1; - } - - } - -/* Return the result. */ - return result; - -} - -static double GetSkyRefP( AstSkyFrame *this, int axis, int *status ) { -/* -* Name: -* GetSkyRefP - -* Purpose: -* Obtain the value of the SkyRefP attribute for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double GetSkyRefP( AstSkyFrame *this, int axis, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function returns the value of the SkyRefP attribute for a -* SkyFrame axis, providing suitable defaults. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Axis index (zero-based) identifying the axis for which information is -* required. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The SkyRefP value to be used. - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - double result; /* Returned value */ - int axis_p; /* Permuted axis index */ - -/* Initialise. */ - result = 0.0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Validate and permute the axis index. */ - axis_p = astValidateAxis( this, axis, 1, "astGetSkyRefP" ); - -/* Check if a value has been set for the required axis. If so, return it. */ - if( this->skyrefp[ axis_p ] != AST__BAD ) { - result = this->skyrefp[ axis_p ]; - -/* Otherwise, return the default value */ - } else { - -/* The default longitude value is always zero. */ - if( axis_p == 0 ) { - result= 0.0; - -/* The default latitude value depends on SkyRef. The usual default is the - north pole. The exception to this is if the SkyRef attribute identifies - either the north or the south pole, in which case the origin is used as - the default. Allow some tolerance. */ - } else if( fabs( cos( this->skyref[ 1 ] ) ) > 1.0E-10 ) { - result = pi/2; - - } else { - result = 0.0; - } - } - -/* Return the result. */ - return result; -} - -static const char *GetSymbol( AstFrame *this, int axis, int *status ) { -/* -* Name: -* GetSymbol - -* Purpose: -* Obtain a pointer to the Symbol string for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* const char *GetSymbol( AstFrame *this, int axis, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetSymbol method inherited -* from the Frame class). - -* Description: -* This function returns a pointer to the Symbol string for a specified axis -* of a SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Axis index (zero-based) identifying the axis for which information is -* required. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to a constant null-terminated character string containing the -* requested information. - -* Notes: -* - A NULL pointer will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstSystemType system; /* Code identifying type of sky coordinates */ - const char *result; /* Pointer to symbol string */ - int axis_p; /* Permuted axis index */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this); - -/* Initialise. */ - result = NULL; - -/* Validate and permute the axis index. */ - axis_p = astValidateAxis( this, axis, 1, "astGetSymbol" ); - -/* Check if a value has been set for the required axis symbol string. If so, - invoke the parent astGetSymbol method to obtain a pointer to it. */ - if ( astTestSymbol( this, axis ) ) { - result = (*parent_getsymbol)( this, axis, status ); - -/* Otherwise, identify the sky coordinate system described by the SkyFrame. */ - } else { - system = astGetSystem( this ); - -/* If OK, supply a pointer to a suitable default Symbol string. */ - if ( astOK ) { - -/* Equatorial coordinate systems. */ - if ( IsEquatorial( system, status ) ) { - result = ( axis_p == 0 ) ? "RA" : "Dec"; - -/* Ecliptic coordinates. */ - } else if ( system == AST__ECLIPTIC ) { - result = ( axis_p == 0 ) ? "Lambda" : "Beta"; - -/* Helio-ecliptic coordinates. */ - } else if ( system == AST__HELIOECLIPTIC ) { - result = ( axis_p == 0 ) ? "Lambda" : "Beta"; - -/* AzEl coordinates. */ - } else if ( system == AST__AZEL ) { - result = ( axis_p == 0 ) ? "Az" : "El"; - -/* Galactic coordinates. */ - } else if ( system == AST__GALACTIC ) { - result = ( axis_p == 0 ) ? "l" : "b"; - -/* Supergalactic coordinates. */ - } else if ( system == AST__SUPERGALACTIC ) { - result = ( axis_p == 0 ) ? "SGL" : "SGB"; - -/* Unknown spherical coordinates. */ - } else if ( system == AST__UNKNOWN ) { - result = ( axis_p == 0 ) ? "Lon" : "Lat"; - -/* Report an error if the coordinate system was not recognised. */ - } else { - astError( AST__SCSIN, "astGetSymbol(%s): Corrupt %s contains " - "invalid sky coordinate system identification code " - "(%d).", status, astGetClass( this ), astGetClass( this ), - (int) system ); - } - -/* If the SkyRef attribute had a set value, prepend "D" (for "delta") to the - Symbol. */ - if( astGetSkyRefIs( this ) != AST__IGNORED_REF && - ( astTestSkyRef( this, 0 ) || astTestSkyRef( this, 1 ) ) ) { - sprintf( getsymbol_buff, "D%s", result ); - result = getsymbol_buff; - } - } - } - -/* Return the result. */ - return result; -} - -static AstSystemType GetAlignSystem( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetAlignSystem - -* Purpose: -* Obtain the AlignSystem attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* AstSystemType GetAlignSystem( AstFrame *this_frame, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetAlignSystem protected -* method inherited from the Frame class). - -* Description: -* This function returns the AlignSystem attribute for a SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The AlignSystem value. - -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - AstSystemType result; /* Value to return */ - -/* Initialise. */ - result = AST__BADSYSTEM; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* If a AlignSystem attribute has been set, invoke the parent method to obtain - it. */ - if ( astTestAlignSystem( this ) ) { - result = (*parent_getalignsystem)( this_frame, status ); - -/* Otherwise, provide a suitable default. */ - } else { - result = AST__ICRS; - } - -/* Return the result. */ - return result; -} - -static AstSystemType GetSystem( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetSystem - -* Purpose: -* Obtain the System attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* AstSystemType GetSystem( AstFrame *this_frame, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetSystem protected -* method inherited from the Frame class). - -* Description: -* This function returns the System attribute for a SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The System value. - -* Notes: -* - AST__BADSYSTEM is returned if this function is invoked with -* the global error status set or if it should fail for any reason. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - AstSystemType result; /* Value to return */ - -/* Initialise. */ - result = AST__BADSYSTEM; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* If a System attribute has been set, invoke the parent method to obtain - it. */ - if ( astTestSystem( this ) ) { - result = (*parent_getsystem)( this_frame, status ); - -/* Otherwise, provide a suitable default. */ - } else { - result = AST__ICRS; - } - -/* Return the result. */ - return result; -} - -static const char *GetTitle( AstFrame *this_frame, int *status ) { -/* -* Name: -* GetTitle - -* Purpose: -* Obtain a pointer to the Title string for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* const char *GetTitle( AstFrame *this_frame, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetTitle method inherited -* from the Frame class). - -* Description: -* This function returns a pointer to the Title string for a SkyFrame. -* A pointer to a suitable default string is returned if no Title value has -* previously been set. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to a null-terminated character string containing the requested -* information. - -* Notes: -* - A NULL pointer will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Declare the thread specific global data */ - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - AstSystemType system; /* Code identifying type of sky coordinates */ - const char *extra; /* Pointer to extra information */ - const char *p; /* Character pointer */ - const char *projection; /* Pointer to sky projection description */ - const char *result; /* Pointer to result string */ - const char *word; /* Pointer to critical word */ - double epoch; /* Value of Epoch attribute */ - double equinox; /* Value of Equinox attribute */ - int lextra; /* Length of extra information */ - int offset; /* Using offset coordinate system? */ - int pos; /* Buffer position to enter text */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this_frame); - -/* Initialise. */ - result = NULL; - pos = 0; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* See if a Title string has been set. If so, use the parent astGetTitle - method to obtain a pointer to it. */ - if ( astTestTitle( this ) ) { - result = (*parent_gettitle)( this_frame, status ); - -/* Otherwise, we will generate a default Title string. Obtain the values of the - SkyFrame's attributes that determine what this string will be. */ - } else { - epoch = astGetEpoch( this ); - equinox = astGetEquinox( this ); - projection = astGetProjection( this ); - system = astGetSystem( this ); - -/* See if an offset coordinate system is being used.*/ - offset = ( astTestSkyRef( this, 0 ) || astTestSkyRef( this, 1 ) ) - && ( astGetSkyRefIs( this ) != AST__IGNORED_REF ); - -/* Use this to determine if the word "coordinates" or "offsets" should be - used.*/ - word = offset ? "offsets" : "coordinates"; - -/* Classify the coordinate system type and create an appropriate Title - string. (Note that when invoking the astFmtDecimalYr function we must - use a separate sprintf on each occasion so as not to over-write its - internal buffer before the result string has been used.) */ - if ( astOK ) { - result = gettitle_buff; - switch ( system ) { - -/* FK4 equatorial coordinates. */ -/* --------------------------- */ -/* Display the Equinox and Epoch values. */ - case AST__FK4: - pos = sprintf( gettitle_buff, "FK4 equatorial %s", word ); - if( astTestEquinox( this ) || astGetUseDefs( this ) ) { - pos += sprintf( gettitle_buff + pos, "; mean equinox B%s", - astFmtDecimalYr( palEpb( equinox ), 9 ) ); - } - if( astTestEpoch( this ) || astGetUseDefs( this ) ) { - pos += sprintf( gettitle_buff + pos, - "; epoch B%s", astFmtDecimalYr( palEpb( epoch ), 9 ) ); - } - break; - -/* FK4 coordinates with no E-terms of aberration. */ -/* ---------------------------------------------- */ -/* Display the Equinox and Epoch values. */ - case AST__FK4_NO_E: - pos = sprintf( gettitle_buff, "FK4 equatorial %s; no E-terms", word ); - if( astTestEquinox( this ) || astGetUseDefs( this ) ) { - pos += sprintf( gettitle_buff + pos, "; mean equinox B%s", - astFmtDecimalYr( palEpb( equinox ), 9 ) ); - } - if( astTestEpoch( this ) || astGetUseDefs( this ) ) { - pos += sprintf( gettitle_buff + pos, - "; epoch B%s", astFmtDecimalYr( palEpb( epoch ), 9 ) ); - } - break; - -/* FK5 equatorial coordinates. */ -/* --------------------------- */ -/* Display only the Equinox value. */ - case AST__FK5: - pos = sprintf( gettitle_buff, "FK5 equatorial %s", word ); - if( astTestEquinox( this ) || astGetUseDefs( this ) ) { - pos += sprintf( gettitle_buff + pos, "; mean equinox J%s", - astFmtDecimalYr( palEpj( equinox ), 9 ) ); - } - break; - -/* J2000 equatorial coordinates. */ -/* ----------------------------- */ -/* Based on the dynamically determined mean equator and equinox of J2000, - rather than on a model such as FK4 or FK5 */ - case AST__J2000: - pos = sprintf( gettitle_buff, "J2000 equatorial %s", word ); - break; - -/* ICRS coordinates. */ -/* ----------------- */ -/* ICRS is only like RA/Dec by co-incidence, it is not really an - equatorial system by definition. */ - case AST__ICRS: - pos = sprintf( gettitle_buff, "ICRS %s", word ); - break; - -/* AzEl coordinates. */ -/* ----------------- */ - case AST__AZEL: - pos = sprintf( gettitle_buff, "Horizon (Azimuth/Elevation) %s", word ); - break; - -/* Geocentric apparent equatorial coordinates. */ -/* ------------------------------------------ */ -/* Display only the Epoch value. */ - case AST__GAPPT: - pos = sprintf( gettitle_buff, - "Geocentric apparent equatorial %s; " - "; epoch J%s", word, astFmtDecimalYr( palEpj( epoch ), 9 ) ); - break; - -/* Ecliptic coordinates. */ -/* --------------------- */ -/* Display only the Equinox value. */ - case AST__ECLIPTIC: - pos = sprintf( gettitle_buff, "Ecliptic %s", word ); - if( astTestEquinox( this ) || astGetUseDefs( this ) ) { - pos += sprintf( gettitle_buff + pos, "; mean equinox J%s", - astFmtDecimalYr( palEpj( equinox ), 9 ) ); - } - break; - -/* Helio-ecliptic coordinates. */ -/* --------------------------- */ -/* Display only the Epoch value (equinox is fixed). */ - case AST__HELIOECLIPTIC: - pos = sprintf( gettitle_buff, "Helio-ecliptic %s; mean equinox J2000", word ); - if( astTestEpoch( this ) || astGetUseDefs( this ) ) { - pos += sprintf( gettitle_buff + pos, "; epoch J%s", - astFmtDecimalYr( palEpj( epoch ), 9 ) ); - } - break; - -/* Galactic coordinates. */ -/* --------------------- */ -/* Do not display an Equinox or Epoch value. */ - case AST__GALACTIC: - pos = sprintf( gettitle_buff, "IAU (1958) galactic %s", word ); - break; - -/* Supergalactic coordinates. */ -/* -------------------------- */ -/* Do not display an Equinox or Epoch value. */ - case AST__SUPERGALACTIC: - pos = sprintf( gettitle_buff, - "De Vaucouleurs supergalactic %s", word ); - break; - -/* Unknown coordinates. */ -/* -------------------------- */ - case AST__UNKNOWN: - pos = sprintf( gettitle_buff, - "Spherical %s", word ); - break; - -/* Report an error if the coordinate system was not recognised. */ - default: - astError( AST__SCSIN, "astGetTitle(%s): Corrupt %s contains " - "invalid sky coordinate system identification code " - "(%d).", status, astGetClass( this ), astGetClass( this ), - (int) system ); - break; - } - -/* If OK, we add either a description of the sky projection, or (if used) - a description of the origin or pole of the offset coordinate system. - We include only one of these two strings in order to keep the length - of the title down to a reasonable value.*/ - if ( astOK ) { - -/* If the SkyRef attribute has set values, create a description of the offset - coordinate system. */ - if( offset ){ - word = ( astGetSkyRefIs( this ) == AST__POLE_REF )?"pole":"origin"; - lextra = sprintf( gettitle_buff2, "%s at %s ", word, - astFormat( this, 0, astGetSkyRef( this, 0 ) ) ); - lextra += sprintf( gettitle_buff2 + lextra, "%s", - astFormat( this, 1, astGetSkyRef( this, 1 ) ) ); - extra = gettitle_buff2; - -/* Otherwise, get the sky projection description. */ - } else { - extra = projection; - -/* Determine the length of the extra information, after removing trailing - white space. */ - for ( lextra = (int) strlen( extra ); lextra > 0; lextra-- ) { - if ( !isspace( extra[ lextra - 1 ] ) ) break; - } - } - -/* If non-blank extra information is available, append it to the title string, - checking that the end of the buffer is not over-run. */ - if ( lextra ) { - p = "; "; - while ( ( pos < AST__SKYFRAME_GETTITLE_BUFF_LEN ) && *p ) gettitle_buff[ pos++ ] = *p++; - p = extra; - while ( ( pos < AST__SKYFRAME_GETTITLE_BUFF_LEN ) && - ( p < ( extra + lextra ) ) ) gettitle_buff[ pos++ ] = *p++; - if( extra == projection ) { - p = " projection"; - while ( ( pos < AST__SKYFRAME_GETTITLE_BUFF_LEN ) && *p ) gettitle_buff[ pos++ ] = *p++; - } - gettitle_buff[ pos ] = '\0'; - } - } - } - } - -/* If an error occurred, clear the returned pointer value. */ - if ( !astOK ) result = NULL; - -/* Return the result. */ - return result; -} - -static const char *GetUnit( AstFrame *this_frame, int axis, int *status ) { -/* -* Name: -* GetUnit - -* Purpose: -* Obtain a pointer to the Unit string for a SkyFrame's axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* const char *GetUnit( AstFrame *this_frame, int axis ) - -* Class Membership: -* SkyFrame member function (over-rides the astGetUnit method inherited -* from the Frame class). - -* Description: -* This function returns a pointer to the Unit string for a specified axis -* of a SkyFrame. If the Unit attribute has not been set for the axis, a -* pointer to a suitable default string is returned instead. This string may -* depend on the value of the Format attribute for the axis and, in turn, on -* the type of sky coordinate system that the SkyFrame describes. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* The number of the axis (zero-based) for which information is required. - -* Returned Value: -* A pointer to a null-terminated string containing the Unit value. - -* 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: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const char *result; /* Pointer value to return */ - int format_set; /* Format attribute set? */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Validate the axis index. */ - (void) astValidateAxis( this, axis, 1, "astGetUnit" ); - -/* The Unit value may depend on the value of the Format attribute, so - determine if a Format value has been set for the axis and set a - temporary value if it has not. Use the GetFormat member function - for this class together with member functions inherited from the - parent class (rather than using the object's methods directly) - because if any of these methods have been over-ridden by a derived - class the Format string syntax may no longer be compatible with - this class. */ - format_set = (*parent_testformat)( this_frame, axis, status ); - if ( !format_set ) { - (*parent_setformat)( this_frame, axis, GetFormat( this_frame, axis, status ), status ); - } - -/* Use the parent GetUnit method to return a pointer to the required Unit - string. */ - result = (*parent_getunit)( this_frame, axis, status ); - -/* If necessary, clear any temporary Format value that was set above. */ - if ( !format_set ) (*parent_clearformat)( this_frame, axis, status ); - -/* If an error occurred, clear the returned value. */ - if ( !astOK ) result = NULL; - -/* Return the result. */ - return result; -} - -void astInitSkyFrameVtab_( AstSkyFrameVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitSkyFrameVtab - -* Purpose: -* Initialise a virtual function table for a SkyFrame. - -* Type: -* Protected function. - -* Synopsis: -* #include "skyframe.h" -* void astInitSkyFrameVtab( AstSkyFrameVtab *vtab, const char *name ) - -* Class Membership: -* SkyFrame vtab initialiser. - -* Description: -* This function initialises the component of a virtual function -* table which is used by the SkyFrame class. - -* Parameters: -* vtab -* Pointer to the virtual function table. The components used by -* all ancestral classes will be initialised if they have not already -* been initialised. -* name -* Pointer to a constant null-terminated character string which contains -* the name of the class to which the virtual function table belongs (it -* is this pointer value that will subsequently be returned by the Object -* astClass function). -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstFrameVtab *frame; /* Pointer to Frame component of Vtab */ - AstObjectVtab *object; /* Pointer to Object component of Vtab */ - int stat; /* SLALIB status */ - -/* 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. */ - astInitFrameVtab( (AstFrameVtab *) vtab, name ); - -/* Store a unique "magic" value in the virtual function table. This - will be used (by astIsASkyFrame) 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 = &(((AstFrameVtab *) vtab)->id); - -/* Initialise member function pointers. */ -/* ------------------------------------ */ -/* Store pointers to the member functions (implemented here) that - provide virtual methods for this class. */ - vtab->ClearAsTime = ClearAsTime; - vtab->ClearEquinox = ClearEquinox; - vtab->ClearNegLon = ClearNegLon; - vtab->ClearProjection = ClearProjection; - vtab->GetAsTime = GetAsTime; - vtab->GetEquinox = GetEquinox; - vtab->GetNegLon = GetNegLon; - vtab->GetIsLatAxis = GetIsLatAxis; - vtab->GetIsLonAxis = GetIsLonAxis; - vtab->GetLatAxis = GetLatAxis; - vtab->GetLonAxis = GetLonAxis; - vtab->GetProjection = GetProjection; - vtab->SetAsTime = SetAsTime; - vtab->SetEquinox = SetEquinox; - vtab->SetNegLon = SetNegLon; - vtab->SetProjection = SetProjection; - vtab->SkyOffsetMap = SkyOffsetMap; - vtab->TestAsTime = TestAsTime; - vtab->TestEquinox = TestEquinox; - vtab->TestNegLon = TestNegLon; - vtab->TestProjection = TestProjection; - - vtab->TestSkyTol = TestSkyTol; - vtab->SetSkyTol = SetSkyTol; - vtab->GetSkyTol = GetSkyTol; - vtab->ClearSkyTol = ClearSkyTol; - - vtab->TestSkyRef = TestSkyRef; - vtab->SetSkyRef = SetSkyRef; - vtab->GetSkyRef = GetSkyRef; - vtab->ClearSkyRef = ClearSkyRef; - - vtab->TestSkyRefP = TestSkyRefP; - vtab->SetSkyRefP = SetSkyRefP; - vtab->GetSkyRefP = GetSkyRefP; - vtab->ClearSkyRefP = ClearSkyRefP; - - vtab->TestSkyRefIs = TestSkyRefIs; - vtab->SetSkyRefIs = SetSkyRefIs; - vtab->GetSkyRefIs = GetSkyRefIs; - vtab->ClearSkyRefIs = ClearSkyRefIs; - - vtab->TestAlignOffset = TestAlignOffset; - vtab->SetAlignOffset = SetAlignOffset; - vtab->GetAlignOffset = GetAlignOffset; - vtab->ClearAlignOffset = ClearAlignOffset; - -/* Save the inherited pointers to methods that will be extended, and - replace them with pointers to the new member functions. */ - object = (AstObjectVtab *) vtab; - frame = (AstFrameVtab *) 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_gettop = frame->GetTop; - frame->GetTop = GetTop; - - parent_setobsalt = frame->SetObsAlt; - frame->SetObsAlt = SetObsAlt; - - parent_setobslat = frame->SetObsLat; - frame->SetObsLat = SetObsLat; - - parent_setobslon = frame->SetObsLon; - frame->SetObsLon = SetObsLon; - - parent_clearobslon = frame->ClearObsLon; - frame->ClearObsLon = ClearObsLon; - - parent_clearobsalt = frame->ClearObsAlt; - frame->ClearObsAlt = ClearObsAlt; - - parent_clearobslat = frame->ClearObsLat; - frame->ClearObsLat = ClearObsLat; - - parent_getbottom = frame->GetBottom; - frame->GetBottom = GetBottom; - - parent_getepoch = frame->GetEpoch; - frame->GetEpoch = GetEpoch; - - parent_format = frame->Format; - frame->Format = Format; - parent_gap = frame->Gap; - frame->Gap = Gap; - parent_getdirection = frame->GetDirection; - frame->GetDirection = GetDirection; - parent_getdomain = frame->GetDomain; - frame->GetDomain = GetDomain; - parent_getsystem = frame->GetSystem; - frame->GetSystem = GetSystem; - parent_setsystem = frame->SetSystem; - frame->SetSystem = SetSystem; - parent_clearsystem = frame->ClearSystem; - frame->ClearSystem = ClearSystem; - parent_getalignsystem = frame->GetAlignSystem; - frame->GetAlignSystem = GetAlignSystem; - parent_getformat = frame->GetFormat; - frame->GetFormat = GetFormat; - parent_getlabel = frame->GetLabel; - frame->GetLabel = GetLabel; - parent_getsymbol = frame->GetSymbol; - frame->GetSymbol = GetSymbol; - parent_gettitle = frame->GetTitle; - frame->GetTitle = GetTitle; - parent_getunit = frame->GetUnit; - frame->GetUnit = GetUnit; - parent_match = frame->Match; - frame->Match = Match; - parent_overlay = frame->Overlay; - frame->Overlay = Overlay; - parent_subframe = frame->SubFrame; - frame->SubFrame = SubFrame; - parent_unformat = frame->Unformat; - frame->Unformat = Unformat; - - parent_setdtai = frame->SetDtai; - frame->SetDtai = SetDtai; - parent_setdut1 = frame->SetDut1; - frame->SetDut1 = SetDut1; - - parent_cleardtai = frame->ClearDtai; - frame->ClearDtai = ClearDtai; - parent_cleardut1 = frame->ClearDut1; - frame->ClearDut1 = ClearDut1; - -/* Store replacement pointers for methods which will be over-ridden by new - member functions implemented here. */ - frame->Angle = Angle; - frame->Distance = Distance; - frame->FrameGrid = FrameGrid; - frame->Intersect = Intersect; - frame->Norm = Norm; - frame->NormBox = NormBox; - frame->Resolve = Resolve; - frame->ResolvePoints = ResolvePoints; - frame->Offset = Offset; - frame->Offset2 = Offset2; - frame->ValidateSystem = ValidateSystem; - frame->SystemString = SystemString; - frame->SystemCode = SystemCode; - frame->LineDef = LineDef; - frame->LineContains = LineContains; - frame->LineCrossing = LineCrossing; - frame->LineOffset = LineOffset; - frame->GetActiveUnit = GetActiveUnit; - frame->TestActiveUnit = TestActiveUnit; - frame->MatchAxesX = MatchAxesX; - -/* Store pointers to inherited methods that will be invoked explicitly - by this class. */ - parent_clearformat = frame->ClearFormat; - parent_setformat = frame->SetFormat; - parent_testformat = frame->TestFormat; - -/* Declare the copy constructor, destructor and class dump - function. */ - astSetCopy( vtab, Copy ); - astSetDelete( vtab, Delete ); - astSetDump( vtab, Dump, "SkyFrame", - "Description of celestial coordinate system" ); - -/* Initialize constants for converting between hours, degrees and - radians, etc.. */ - LOCK_MUTEX2 - palDtf2r( 1, 0, 0.0, &hr2rad, &stat ); - palDaf2r( 1, 0, 0.0, °2rad, &stat ); - palDaf2r( 180, 0, 0.0, &pi, &stat ); - piby2 = 0.5*pi; - UNLOCK_MUTEX2 - -/* 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 void Intersect( AstFrame *this_frame, const double a1[2], - const double a2[2], const double b1[2], - const double b2[2], double cross[2], - int *status ) { -/* -* Name: -* Intersect - -* Purpose: -* Find the point of intersection between two geodesic curves. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void Intersect( AstFrame *this_frame, const double a1[2], -* const double a2[2], const double b1[2], -* const double b2[2], double cross[2], -* int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astIntersect method -* inherited from the Frame class). - -* Description: -* This function finds the coordinate values at the point of -* intersection between two geodesic curves. Each curve is specified -* by two points on the curve. - -* Parameters: -* this -* Pointer to the SkyFrame. -* a1 -* An array of double, with one element for each Frame axis. -* This should contain the coordinates of a point on the first -* geodesic curve. -* a2 -* An array of double, with one element for each Frame axis. -* This should contain the coordinates of a second point on the -* first geodesic curve. -* b1 -* An array of double, with one element for each Frame axis. -* This should contain the coordinates of a point on the second -* geodesic curve. -* b2 -* An array of double, with one element for each Frame axis. -* This should contain the coordinates of a second point on -* the second geodesic curve. -* cross -* An array of double, with one element for each Frame axis -* in which the coordinates of the required intersection -* point will be returned. These will be AST__BAD if the curves do -* not intersect. -* status -* Pointer to the inherited status variable. - -* Notes: -* - The geodesic curve used by this function is the path of -* shortest distance between two points, as defined by the -* astDistance function. -* - This function will return "bad" coordinate values (AST__BAD) -* if any of the input coordinates has this value. -* - For SkyFrames each curve will be a great circle, and in general -* each pair of curves will intersect at two diametrically opposite -* points on the sky. The returned position is the one which is -* closest to point "a1". -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const int *perm; /* Pointer to axis permutation array */ - double aa1[ 2 ]; /* Permuted coordinates for a1 */ - double aa2[ 2 ]; /* Permuted coordinates for a2 */ - double bb1[ 2 ]; /* Permuted coordinates for b1 */ - double bb2[ 2 ]; /* Permuted coordinates for b2 */ - double cc[ 2 ]; /* Permuted coords at intersection */ - double d1; /* Cos(distance from a1 to vp) */ - double d2; /* Cos(distance from a1 to -vp) */ - double na[ 3 ]; /* Normal to the a1/a2 great circle */ - double nb[ 3 ]; /* Normal to the b1/b2 great circle */ - double va1[ 3 ]; /* Vector pointing at a1 */ - double va2[ 3 ]; /* Vector pointing at a2 */ - double vb1[ 3 ]; /* Vector pointing at b1 */ - double vb2[ 3 ]; /* Vector pointing at b2 */ - double vmod; /* Length of "vp" */ - double vp[ 3 ]; /* Vector pointing at the intersection */ - double vpn[ 3 ]; /* Normalised vp */ - int iaxis; /* Axis index */ - -/* Initialise. */ - cross[ 0 ] = AST__BAD; - cross[ 1 ] = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Check that all supplied values are OK. */ - if ( ( a1[ 0 ] != AST__BAD ) && ( a1[ 1 ] != AST__BAD ) && - ( a2[ 0 ] != AST__BAD ) && ( a2[ 1 ] != AST__BAD ) && - ( b1[ 0 ] != AST__BAD ) && ( b1[ 1 ] != AST__BAD ) && - ( b2[ 0 ] != AST__BAD ) && ( b2[ 1 ] != AST__BAD ) ) { - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( astOK ) { - -/* Apply the axis permutation array to obtain the coordinates of - the points in the required (longitude,latitude) order. */ - for( iaxis = 0; iaxis < 2; iaxis++ ) { - aa1[ perm[ iaxis ] ] = a1[ iaxis ]; - aa2[ perm[ iaxis ] ] = a2[ iaxis ]; - bb1[ perm[ iaxis ] ] = b1[ iaxis ]; - bb2[ perm[ iaxis ] ] = b2[ iaxis ]; - } - -/* Convert each (lon,lat) pair into a unit length 3-vector. */ - palDcs2c( aa1[ 0 ], aa1[ 1 ], va1 ); - palDcs2c( aa2[ 0 ], aa2[ 1 ], va2 ); - palDcs2c( bb1[ 0 ], bb1[ 1 ], vb1 ); - palDcs2c( bb2[ 0 ], bb2[ 1 ], vb2 ); - -/* Find the normal vectors to the two great cicles. */ - palDvxv( va1, va2, na ); - palDvxv( vb1, vb2, nb ); - -/* The cross product of the two normal vectors points to one of the - two diametrically opposite intersections. */ - palDvxv( na, nb, vp ); - -/* Normalise the "vp" vector, also obtaining its original modulus. */ - palDvn( vp, vpn, &vmod ); - if( vmod != 0.0 ) { - -/* We want the intersection which is closest to "a1". The dot product - gives the cos(distance) between two positions. So find the dot - product between "a1" and "vpn", and then between "a1" and the point - diametrically opposite "vpn". */ - d1 = palDvdv( vpn, va1 ); - vpn[ 0 ] = -vpn[ 0 ]; - vpn[ 1 ] = -vpn[ 1 ]; - vpn[ 2 ] = -vpn[ 2 ]; - d2 = palDvdv( vpn, va1 ); - -/* Revert to "vpn" if it is closer to "a1". */ - if( d1 > d2 ) { - vpn[ 0 ] = -vpn[ 0 ]; - vpn[ 1 ] = -vpn[ 1 ]; - vpn[ 2 ] = -vpn[ 2 ]; - } - -/* Convert the vector back into a (lon,lat) pair, and put the longitude - into the range 0 to 2.pi. */ - palDcc2s( vpn, cc, cc + 1 ); - *cc = palDranrm( *cc ); - -/* Permute the result coordinates to undo the effect of the SkyFrame - axis permutation array. */ - cross[ 0 ] = cc[ perm[ 0 ] ]; - cross[ 1 ] = cc[ perm[ 1 ] ]; - } - } - } -} - -static int IsEquatorial( AstSystemType system, int *status ) { -/* -* Name: -* IsEquatorial - -* Purpose: -* Test for an equatorial sky coordinate system. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int IsEquatorial( AstSystemType system, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function returns a boolean value to indicate if a sky coordinate -* system is equatorial. - -* Parameters: -* system -* Code to identify the sky coordinate system. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Non-zero if the sky coordinate system is equatorial, otherwise zero. - -* Notes: -* - A value of zero is returned if this function is invoked with the -* global error status set or if it should fail for any reason. -*/ - -/* Local Variables: */ - int result; /* Result value to return */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Determine if the sky coordinate system is an equatorial one. Note, - ICRS is not equatorial by definition, but is included here because it - is normally treated as an equatorial system in terms of the axis - labels, formats, etc. */ - result = ( ( system == AST__FK4 ) || - ( system == AST__FK4_NO_E ) || - ( system == AST__ICRS ) || - ( system == AST__FK5 ) || - ( system == AST__J2000 ) || - ( system == AST__GAPPT ) ); - -/* Return the result. */ - return result; -} - -static int LineContains( AstFrame *this, AstLineDef *l, int def, double *point, int *status ) { -/* -* Name: -* LineContains - -* Purpose: -* Determine if a line contains a point. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int LineContains( AstFrame *this, AstLineDef *l, int def, double *point, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astLineContains -* method inherited from the Frame class). - -* Description: -* This function determines if the supplied point is on the supplied -* line within the supplied Frame. The start point of the line is -* considered to be within the line, but the end point is not. The tests -* are that the point of closest approach of the line to the point should -* be between the start and end, and that the distance from the point to -* the point of closest aproach should be less than 1.0E-7 of the length -* of the line. - -* Parameters: -* this -* Pointer to the Frame. -* l -* Pointer to the structure defining the line. -* def -* Should be set non-zero if the "point" array was created by a -* call to astLineCrossing (in which case it may contain extra -* information following the axis values),and zero otherwise. -* point -* Point to an array containing the axis values of the point to be -* tested, possibly followed by extra cached information (see "def"). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if the line contains the point. - -* Notes: -* - The pointer supplied for "l" should have been created using the -* astLineDef method. These structures contained cached information about -* the lines which improve the efficiency of this method when many -* repeated calls are made. An error will be reported if the structure -* does not refer to the Frame specified by "this". -* - Zero will be returned if this function is invoked with the global -* error status set, or if it should fail for any reason. -*- -*/ - -/* Local Variables: */ - SkyLineDef *sl; /* SkyLine information */ - const int *perm; /* Pointer to axis permutation array */ - double *b; /* Pointer to Cartesian coords array */ - double bb[3]; /* Buffer for Cartesian coords */ - double p1[2]; /* Buffer for Spherical coords */ - double t1, t2; - int result; /* Returned value */ - -/* Initialise */ - result =0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Check that the line refers to the supplied Frame. */ - if( l->frame != this ) { - astError( AST__INTER, "astLineContains(%s): The supplied line does " - "not relate to the supplied %s (AST internal programming " - "error).", status, astGetClass( this ), astGetClass( this ) ); - -/* Check the axis values are good */ - } else if( point[ 0 ] != AST__BAD && point[ 1 ] != AST__BAD ){ - -/* Get a pointer to an array holding the corresponding Cartesian coords. */ - if( def ) { - b = point + 2; - - } else { - perm = astGetPerm( this ); - if ( perm ) { - p1[ perm[ 0 ] ] = point[ 0 ]; - p1[ perm[ 1 ] ] = point[ 1 ]; - palDcs2c( p1[ 0 ], p1[ 1 ], bb ); - b = bb; - } else { - b = NULL; - } - } - -/* Recast the supplied AstLineDef into a SkyLineDef to get the different - structure (we know from the above check on the Frame that it is safe to - do this). */ - sl = (SkyLineDef *) l; - -/* Check that the point of closest approach of the line to the point is - within the limits of the line. */ - if( LineIncludes( sl, b, status ) ){ - -/* Check that the point is 90 degrees away from the pole of the great - circle containing the line. */ - t1 = palDvdv( sl->q, b ); - t2 = 1.0E-7*sl->length; - if( t2 < 1.0E-10 ) t2 = 1.0E-10; - if( fabs( t1 ) <= t2 ) result = 1; - } - } - -/* Return the result. */ - return result; -} - -static int LineCrossing( AstFrame *this, AstLineDef *l1, AstLineDef *l2, - double **cross, int *status ) { -/* -* Name: -* LineCrossing - -* Purpose: -* Determine if two lines cross. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int LineCrossing( AstFrame *this, AstLineDef *l1, AstLineDef *l2, -* double **cross, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astLineCrossing -* method inherited from the Frame class). - -* Description: -* This function determines if the two suplied line segments cross, -* and if so returns the axis values at the point where they cross. -* A flag is also returned indicating if the crossing point occurs -* within the length of both line segments, or outside one or both of -* the line segments. - -* Parameters: -* this -* Pointer to the Frame. -* l1 -* Pointer to the structure defining the first line. -* l2 -* Pointer to the structure defining the second line. -* cross -* Pointer to a location at which to put a pointer to a dynamically -* alocated array containing the axis values at the crossing. If -* NULL is supplied no such array is returned. Otherwise, the returned -* array should be freed using astFree when no longer needed. If the -* lines are parallel (i.e. do not cross) then AST__BAD is returned for -* all axis values. Note usable axis values are returned even if the -* lines cross outside the segment defined by the start and end points -* of the lines. The order of axes in the returned array will take -* account of the current axis permutation array if appropriate. Note, -* sub-classes such as SkyFrame may append extra values to the end -* of the basic frame axis values. A NULL pointer is returned if an -* error occurs. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if the lines cross at a point which is -* within the [start,end) segment of both lines. If the crossing point -* is outside this segment on either line, or if the lines are parallel, -* zero is returned. Note, the start point is considered to be inside -* the length of the segment, but the end point is outside. - -* Notes: -* - The pointers supplied for "l1" and "l2" should have been created -* using the astLineDef method. These structures contained cached -* information about the lines which improve the efficiency of this method -* when many repeated calls are made. An error will be reported if -* either structure does not refer to the Frame specified by "this". -* - Zero will be returned if this function is invoked with the global -* error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - SkyLineDef *sl1; /* SkyLine information for line 1 */ - SkyLineDef *sl2; /* SkyLine information for line 2 */ - const int *perm; /* Pointer to axis permutation array */ - double *crossing; /* Pointer to returned array */ - double *b; /* Pointer to Cartesian coords */ - double len; /* Vector length */ - double p[ 2 ]; /* Temporary (lon,lat) pair */ - double temp[ 3 ]; /* Temporary vector */ - int result; /* Returned value */ - -/* Initialise */ - result = 0; - if( cross ) *cross = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Allocate returned array (2 elements for the lon and lat values, plus 3 - for the corresponding (x,y,z) coords). */ - crossing = astMalloc( sizeof(double)*5 ); - -/* Check that both lines refer to the supplied Frame. */ - if( l1->frame != this ) { - astError( AST__INTER, "astLineCrossing(%s): First supplied line does " - "not relate to the supplied %s (AST internal programming " - "error).", status, astGetClass( this ), astGetClass( this ) ); - - } else if( l2->frame != this ) { - astError( AST__INTER, "astLineCrossing(%s): Second supplied line does " - "not relate to the supplied %s (AST internal programming " - "error).", status, astGetClass( this ), astGetClass( this ) ); - -/* Recast the supplied AstLineDefs into a SkyLineDefs to get the different - structure (we know from the above check on the Frame that it is safe to - do this). */ - } else if( crossing ){ - sl1 = (SkyLineDef *) l1; - sl2 = (SkyLineDef *) l2; - -/* Point of intersection of the two great circles is perpendicular to the - pole vectors of both great circles. Put the Cartesian coords in elements - 2 to 4 of the returned array. */ - palDvxv( sl1->q, sl2->q, temp ); - b = crossing + 2; - palDvn( temp, b, &len ); - -/* See if this point is within the length of both arcs. If so return it. */ - if( LineIncludes( sl2, b, status ) && LineIncludes( sl1, b, status ) ) { - result = 1; - -/* If not, see if the negated b vector is within the length of both arcs. - If so return it. Otherwise, we return zero. */ - } else { - b[ 0 ] *= -1.0; - b[ 1 ] *= -1.0; - b[ 2 ] *= -1.0; - if( LineIncludes( sl2, b, status ) && LineIncludes( sl1, b, status ) ) result = 1; - } - -/* Store the spherical coords in elements 0 and 1 of the returned array. */ - palDcc2s( b, p, p + 1 ); - -/* Permute the spherical axis value into the order used by the SkyFrame. */ - perm = astGetPerm( this ); - if( perm ){ - crossing[ 0 ] = p[ perm[ 0 ] ]; - crossing[ 1 ] = p[ perm[ 1 ] ]; - } - } - -/* If an error occurred, return 0. */ - if( !astOK ) { - result = 0; - crossing = astFree( crossing ); - } - -/* Return the array */ - if( cross ) { - *cross = crossing; - } else { - crossing = astFree( crossing ); - } - -/* Return the result. */ - return result; -} - -static AstLineDef *LineDef( AstFrame *this, const double start[2], - const double end[2], int *status ) { -/* -* Name: -* LineDef - -* Purpose: -* Creates a structure describing a line segment in a 2D Frame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* AstLineDef *LineDef( AstFrame *this, const double start[2], -* const double end[2], int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astLineDef -* method inherited from the Frame class). - -* Description: -* This function creates a structure containing information describing a -* given line segment within the supplied 2D Frame. This may include -* information which allows other methods such as astLineCrossing to -* function more efficiently. Thus the returned structure acts as a -* cache to store intermediate values used by these other methods. - -* Parameters: -* this -* Pointer to the Frame. Must have 2 axes. -* start -* An array of 2 doubles marking the start of the line segment. -* end -* An array of 2 doubles marking the end of the line segment. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to the memory structure containing the description of the -* line. This structure should be freed using astFree when no longer -* needed. A NULL pointer is returned (without error) if any of the -* supplied axis values are AST__BAD. - -* 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: */ - SkyLineDef *result; /* Returned value */ - const int *perm; /* Axis permutation array */ - double le; /* Length of end vector */ - double len; /* Permuted point1 coordinates */ - double ls; /* Length of start vector */ - double p1[ 2 ]; /* Permuted point1 coordinates */ - double p2[ 2 ]; /* Permuted point2 coordinates */ - double temp[3]; /* Cartesian coords at offset position */ - -/* Initialise */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Check the axis values are good */ - if( start[ 0 ] != AST__BAD && start[ 1 ] != AST__BAD && - end[ 0 ] != AST__BAD && end[ 1 ] != AST__BAD ) { - -/* Allocate memory for the returned structure. */ - result = astMalloc( sizeof( SkyLineDef ) ); - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( perm ) { - -/* Apply the axis permutation array to obtain the coordinates of the two - input points in the required (longitude,latitude) order. */ - p1[ perm[ 0 ] ] = start[ 0 ]; - p1[ perm[ 1 ] ] = start[ 1 ]; - p2[ perm[ 0 ] ] = end[ 0 ]; - p2[ perm[ 1 ] ] = end[ 1 ]; - -/* Convert each point into a 3-vector of unit length and store in the - returned structure. */ - palDcs2c( p1[ 0 ], p1[ 1 ], result->start ); - palDcs2c( p2[ 0 ], p2[ 1 ], result->end ); - -/* Calculate the great circle distance between the points in radians and - store in the result structure. Correct for rounding errors in palDcs2c - that can result in the vectors not having exactly unit length. */ - result->length = palDvdv( result->start, result->end ); - ls = result->start[0]*result->start[0] + - result->start[1]*result->start[1] + - result->start[2]*result->start[2]; - le = result->end[0]*result->end[0] + - result->end[1]*result->end[1] + - result->end[2]*result->end[2]; - result->length = acos( result->length/sqrt( ls*le ) ); - -/* Find a unit vector representing the pole of the system in which the - equator is given by the great circle. This is such that going the - short way from the start to the end, the pole is to the left of the - line as seen by the observer (i.e. from the centre of the sphere). - If the line has zero length, or 180 degrees length, the pole is - undefined, so we use an arbitrary value. */ - if( result->length == 0.0 || result->length > pi - 5.0E-11 ) { - palDcs2c( p1[ 0 ] + 0.01, p1[ 1 ] + 0.01, temp ); - palDvxv( temp, result->start, result->dir ); - } else { - palDvxv( result->end, result->start, result->dir ); - } - palDvn( result->dir, result->q, &len ); - -/* Also store a point which is 90 degrees along the great circle from the - start. */ - palDvxv( result->start, result->q, result->dir ); - -/* Store a pointer to the defining SkyFrame. */ - result->frame = this; - -/* Indicate that the line is considered to be terminated at the start and - end points. */ - result->infinite = 0; - -/* Normalise the spherical start and end positions stored in the returned - structure. */ - result->start_2d[ 0 ] = start[ 0 ]; - result->start_2d[ 1 ] = start[ 1 ]; - result->end_2d[ 0 ] = end[ 0 ]; - result->end_2d[ 1 ] = end[ 1 ]; - - astNorm( this, result->start_2d ); - astNorm( this, result->end_2d ); - } - } - -/* Free the returned pointer if an error occurred. */ - if( !astOK ) result = astFree( result ); - -/* Return a pointer to the output structure. */ - return (AstLineDef *) result; -} - -static int LineIncludes( SkyLineDef *l, double point[3], int *status ) { -/* -* Name: -* LineIncludes - -* Purpose: -* Determine if a line includes a point which is known to be in the -* great circle. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int LineIncludes( SkyLineDef *l, double point[3], int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astLineIncludes -* method inherited from the Frame class). - -* Description: -* The supplied point is assumed to be a point on the great circle of -* which the supplied line is a segment. This function returns true if -* "point" is within the bounds of the segment (the end point of the -* line is assumed * not to be part of the segment). - -* Parameters: -* l -* Pointer to the structure defining the line. -* point -* An array holding the Cartesian coords of the point to be tested. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if the line includes the point. - -* Notes: -* - Zero will be returned if this function is invoked with the global -* error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - double t1, t2, t3; - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* If the line is of infite length, it is assumed to include the supplied - point. */ - if( l->infinite ) return 1; - -/* Otherwise, get the unsigned distance of the point from the start of the - line in the range 0 - 180 degs. Check it is less than the line length. - Then check that the point is not more than 90 degs away from the quarter - point. */ - t1 = palDvdv( l->start, point ); - t2 = acos( t1 ); - t3 = palDvdv( l->dir, point ); - return ( ((l->length > 0) ? t2 < l->length : t2 == 0.0 ) && t3 >= -1.0E-8 ); -} - -static void LineOffset( AstFrame *this, AstLineDef *line, double par, - double prp, double point[2], int *status ){ -/* -* Name: -* LineOffset - -* Purpose: -* Find a position close to a line. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void LineOffset( AstFrame *this, AstLineDef *line, double par, -* double prp, double point[2], int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astLineOffset -* method inherited from the Frame class). - -* Description: -* This function returns a position formed by moving a given distance along -* the supplied line, and then a given distance away from the supplied line. - -* Parameters: -* this -* Pointer to the Frame. -* line -* Pointer to the structure defining the line. -* par -* The distance to move along the line from the start towards the end. -* prp -* The distance to move at right angles to the line. Positive -* values result in movement to the left of the line, as seen from -* the observer, when moving from start towards the end. -* status -* Pointer to the inherited status variable. - -* Notes: -* - The pointer supplied for "line" should have been created using the -* astLineDef method. This structure contains cached information about the -* line which improves the efficiency of this method when many repeated -* calls are made. An error will be reported if the structure does not -* refer to the Frame specified by "this". -*- -*/ - -/* Local Variables; */ - SkyLineDef *sl; - const int *perm; - double c; - double nx; - double ny; - double nz; - double p[2]; - double s; - double v[3]; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Check that the line refers to the supplied Frame. */ - if( line->frame != this ) { - astError( AST__INTER, "astLineOffset(%s): The supplied line does " - "not relate to the supplied %s (AST internal programming " - "error).", status, astGetClass( this ), astGetClass( this ) ); - -/* This implementation uses spherical geometry. */ - } else { - -/* Get a pointer to the SkyLineDef structure. */ - sl = (SkyLineDef *) line; - -/* Move a distance par from start to end. */ - c = cos( par ); - s = sin( par ); - nx = c * sl->start[ 0 ] + s * sl->dir[ 0 ]; - ny = c * sl->start[ 1 ] + s * sl->dir[ 1 ]; - nz = c * sl->start[ 2 ] + s * sl->dir[ 2 ]; - -/* Move a distance prp from this point towards the pole point. */ - if( prp != 0.0 ) { - c = cos( prp ); - s = sin( prp ); - v[ 0 ] = c * nx + s * sl->q[ 0 ]; - v[ 1 ] = c * ny + s * sl->q[ 1 ]; - v[ 2 ] = c * nz + s * sl->q[ 2 ]; - } else { - v[ 0 ] = nx; - v[ 1 ] = ny; - v[ 2 ] = nz; - } - -/* Convert to lon/lat */ - palDcc2s( v, p, p + 1 ); - -/* Permute the spherical axis value into the order used by the SkyFrame. */ - perm = astGetPerm( this ); - if( perm ){ - point[ 0 ] = p[ perm[ 0 ] ]; - point[ 1 ] = p[ perm[ 1 ] ]; - } - } -} - -static int MakeSkyMapping( AstSkyFrame *target, AstSkyFrame *result, - AstSystemType align_sys, AstMapping **map, int *status ) { -/* -* Name: -* MakeSkyMapping - -* Purpose: -* Generate a Mapping between two SkyFrames. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int MakeSkyMapping( AstSkyFrame *target, AstSkyFrame *result, -* AstSystemType align_sys, AstMapping **map, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function takes two SkyFrames and generates a Mapping that -* converts between them, taking account of differences in their -* coordinate systems, equinox value, epoch, etc. (but not allowing -* for any axis permutations). - -* Parameters: -* target -* Pointer to the first SkyFrame. -* result -* Pointer to the second SkyFrame. -* align_sys -* The system in which to align the two SkyFrames. -* map -* Pointer to a location which is to receive a pointer to the -* returned Mapping. The forward transformation of this Mapping -* will convert from "target" coordinates to "result" -* coordinates, and the inverse transformation will convert in -* the opposite direction (all coordinate values in radians). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Non-zero if the Mapping could be generated, or zero if the two -* SkyFrames are sufficiently un-related that no meaningful Mapping -* can be produced. - -* Notes: -* A value of zero is returned if this function is invoked with the -* global error status set or if it should fail for any reason. -*/ - -/* Local Constants: */ -#define MAX_ARGS 4 /* Max arguments for an SlaMap conversion */ - -/* Local Variables: */ - AstMapping *omap; /* Mapping from coorinates to offsets */ - AstMapping *tmap2; /* Temporary Mapping */ - AstMapping *tmap; /* Temporary Mapping */ - AstSlaMap *slamap; /* Pointer to SlaMap */ - AstSystemType result_system; /* Code to identify result coordinate system */ - AstSystemType system; /* Code to identify coordinate system */ - AstSystemType target_system; /* Code to identify target coordinate system */ - double args[ MAX_ARGS ]; /* Conversion argument array */ - double epoch; /* Epoch as Modified Julian Date */ - double epoch_B; /* Besselian epoch as decimal years */ - double epoch_J; /* Julian epoch as decimal years */ - double equinox; /* Equinox as Modified Julian Date */ - double equinox_B; /* Besselian equinox as decimal years */ - double equinox_J; /* Julian equinox as decimal years */ - double diurab; /* Magnitude of diurnal aberration vector */ - double last; /* Local Apparent Sidereal Time */ - double lat; /* Observers latitude */ - double result_epoch; /* Result frame Epoch */ - double result_equinox; /* Result frame Epoch */ - double target_epoch; /* Target frame Epoch */ - double target_equinox; /* Target frame Epoch */ - int isunit; /* Is the SlaMap effectively a unit mapping? */ - int match; /* Mapping can be generated? */ - int step1; /* Convert target to FK5 J2000? */ - int step2; /* Convert FK5 J2000 to align sys? */ - int step3; /* Convert align sys to FK5 J2000? */ - int step4; /* Convert FK5 J2000 to result? */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Initialise the returned values. */ - match = 1; - *map = NULL; - -/* Initialise variables to avoid "used of uninitialised variable" - messages from dumb compilers. */ - epoch_B = 0.0; - epoch_J = 0.0; - equinox_B = 0.0; - equinox_J = 0.0; - -/* Get the two epoch values. */ - result_epoch = astGetEpoch( result ); - target_epoch = astGetEpoch( target ); - -/* Get the two equinox values. */ - result_equinox = astGetEquinox( result ); - target_equinox = astGetEquinox( target ); - -/* Get the two system values. */ - result_system = astGetSystem( result ); - target_system = astGetSystem( target ); - -/* If either system is not references to the equinox given by the Equinox - attribute, then use the equinox of the other system rather than - adopting the arbitrary default of J2000. */ - if( !EQREF(result_system) ) result_equinox = target_equinox; - if( !EQREF(target_system) ) target_equinox = result_equinox; - -/* If both systems are unknown, assume they are the same. Return a UnitMap. - We need to do this, otherwise a simple change of Title (for instance) - will result in a FrameSet whose current Frame has System=AST__UNKNOWN - loosing its integrity. */ - if( target_system == AST__UNKNOWN && result_system == AST__UNKNOWN ) { - *map = (AstMapping *) astUnitMap( 2, "", status ); - return 1; - } - -/* The total Mapping is divided into two parts in series; the first part - converts from the target SkyFrame to the alignment system, using the - Epoch and Equinox of the target Frame, the second part converts from - the alignment system to the result SkyFrame, using the Epoch and Equinox - of the result Frame. Each of these parts has an arbitrary input and an - output system, and therefore could be implemented using a collection - of NxN conversions. To reduce the complexity, each part is implement - by converting from the input system to FK5 J2000, and then from FK5 - J2000 to the output system. This scheme required only N conversions - rather than NxN. Thus overall the total Mapping is made up of 4 steps - in series. Some of these steps may be ommitted if they are effectively - a UnitMap. Determine which steps need to be included. Assume all need - to be done to begin with. */ - step1 = 1; - step2 = 1; - step3 = 1; - step4 = 1; - -/* If the target system is the same as the alignment system, neither of the - first 2 steps need be done. */ - if( target_system == align_sys ) { - step1 = 0; - step2 = 0; - } - -/* If the result system is the same as the alignment system, neither of the - last 2 steps need be done. */ - if( result_system == align_sys ) { - step3 = 0; - step4 = 0; - } - -/* If the two epochs are the same, or if the alignment system is FK5 J2000, - steps 2 and 3 are not needed. */ - if( step2 && step3 ) { - if( align_sys == AST__FK5 || result_epoch == target_epoch ) { - step2 = 0; - step3 = 0; - } - } - -/* None are needed if the target and result SkyFrames have the same - System, Epoch and Equinox. */ - if( result_system == target_system && - result_epoch == target_epoch && - result_equinox == target_equinox ) { - step1 = 0; - step2 = 0; - step3 = 0; - step4 = 0; - } - -/* Create an initial (null) SlaMap. */ - slamap = astSlaMap( 0, "", status ); - -/* Define local macros as shorthand for adding sky coordinate - conversions to this SlaMap. Each macro simply stores details of - the additional arguments in the "args" array and then calls - astSlaAdd. The macros differ in the number of additional argument - values. */ - #define TRANSFORM_0(cvt) \ - astSlaAdd( slamap, cvt, 0, NULL ); - - #define TRANSFORM_1(cvt,arg0) \ - args[ 0 ] = arg0; \ - astSlaAdd( slamap, cvt, 1, args ); - - #define TRANSFORM_2(cvt,arg0,arg1) \ - args[ 0 ] = arg0; \ - args[ 1 ] = arg1; \ - astSlaAdd( slamap, cvt, 2, args ); - - #define TRANSFORM_3(cvt,arg0,arg1,arg2) \ - args[ 0 ] = arg0; \ - args[ 1 ] = arg1; \ - args[ 2 ] = arg2; \ - astSlaAdd( slamap, cvt, 3, args ); - - #define TRANSFORM_4(cvt,arg0,arg1,arg2,arg3) \ - args[ 0 ] = arg0; \ - args[ 1 ] = arg1; \ - args[ 2 ] = arg2; \ - args[ 3 ] = arg3; \ - astSlaAdd( slamap, cvt, 4, args ); - -/* Convert _to_ FK5 J2000.0 coordinates. */ -/* ===================================== */ -/* The overall conversion is formulated in four phases. In this first - phase, we convert from the target coordinate system to intermediate sky - coordinates expressed using the FK5 system, mean equinox J2000.0. */ - -/* Obtain the sky coordinate system, equinox, epoch, etc, of the target - SkyFrame. */ - system = target_system; - equinox = target_equinox; - epoch = target_epoch; - last = GetLAST( target, status ); - diurab = GetDiurab( target, status ); - lat = astGetObsLat( target ); - if( astOK && step1 ) { - -/* Convert the equinox and epoch values (stored as Modified Julian - Dates) into the equivalent Besselian and Julian epochs (as decimal - years). */ - equinox_B = palEpb( equinox ); - equinox_J = palEpj( equinox ); - epoch_B = palEpb( epoch ); - epoch_J = palEpj( epoch ); - -/* Formulate the conversion... */ - -/* From FK4. */ -/* --------- */ -/* If necessary, apply the old-style FK4 precession model to bring the - equinox to B1950.0, with rigorous handling of the E-terms of - aberration. Then convert directly to FK5 J2000.0 coordinates. */ - if ( system == AST__FK4 ) { - VerifyMSMAttrs( target, result, 1, "Equinox Epoch", "astMatch", status ); - if ( equinox_B != 1950.0 ) { - TRANSFORM_1( "SUBET", equinox_B ) - TRANSFORM_2( "PREBN", equinox_B, 1950.0 ) - TRANSFORM_1( "ADDET", 1950.0 ) - } - TRANSFORM_1( "FK45Z", epoch_B ) - -/* From FK4 with no E-terms. */ -/* ------------------------- */ -/* This is the same as above, except that we do not need to subtract - the E-terms initially as they are already absent. */ - } else if ( system == AST__FK4_NO_E ) { - VerifyMSMAttrs( target, result, 1, "Equinox Epoch", "astMatch", status ); - if ( equinox_B != 1950.0 ) { - TRANSFORM_2( "PREBN", equinox_B, 1950.0 ) - } - TRANSFORM_1( "ADDET", 1950.0 ) - TRANSFORM_1( "FK45Z", epoch_B ) - -/* From FK5. */ -/* --------- */ -/* We simply need to apply a precession correction for the change of - equinox. Omit even this if the equinox is already J2000.0. */ - } else if ( system == AST__FK5 ) { - VerifyMSMAttrs( target, result, 1, "Equinox", "astMatch", status ); - if ( equinox_J != 2000.0 ) { - TRANSFORM_2( "PREC", equinox_J, 2000.0 ); - } - -/* From J2000. */ -/* ----------- */ -/* Convert from J2000 to ICRS, then from ICRS to FK5. */ - } else if ( system == AST__J2000 ) { - VerifyMSMAttrs( target, result, 1, "Epoch", "astMatch", status ); - TRANSFORM_0( "J2000H" ) - TRANSFORM_1( "HFK5Z", epoch_J ); - -/* From geocentric apparent. */ -/* ------------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( system == AST__GAPPT ) { - VerifyMSMAttrs( target, result, 1, "Epoch", "astMatch", status ); - TRANSFORM_2( "AMP", epoch, 2000.0 ) - -/* From ecliptic coordinates. */ -/* -------------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( system == AST__ECLIPTIC ) { - VerifyMSMAttrs( target, result, 1, "Equinox", "astMatch", status ); - TRANSFORM_1( "ECLEQ", equinox ) - -/* From helio-ecliptic coordinates. */ -/* -------------------------------- */ - } else if ( system == AST__HELIOECLIPTIC ) { - VerifyMSMAttrs( target, result, 1, "Epoch", "astMatch", status ); - TRANSFORM_1( "HEEQ", epoch ) - -/* From galactic coordinates. */ -/* -------------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( system == AST__GALACTIC ) { - TRANSFORM_0( "GALEQ" ) - -/* From ICRS. */ -/* ---------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( system == AST__ICRS ) { - VerifyMSMAttrs( target, result, 1, "Epoch", "astMatch", status ); - TRANSFORM_1( "HFK5Z", epoch_J ); - -/* From supergalactic coordinates. */ -/* ------------------------------- */ -/* Convert to galactic coordinates and then to FK5 J2000.0 - equatorial. */ - } else if ( system == AST__SUPERGALACTIC ) { - TRANSFORM_0( "SUPGAL" ) - TRANSFORM_0( "GALEQ" ) - -/* From AzEl. */ -/* ---------- */ -/* Rotate from horizon to equator (H2E), shift hour angle into RA (H2R), - go from geocentric apparent to FK5 J2000. */ - } else if ( system == AST__AZEL ) { - VerifyMSMAttrs( target, result, 1, "ObsLon ObsLat Epoch", "astMatch", status ); - TRANSFORM_2( "H2E", lat, diurab ) - TRANSFORM_1( "H2R", last ) - TRANSFORM_2( "AMP", epoch, 2000.0 ) - -/* From unknown coordinates. */ -/* ------------------------- */ -/* No conversion is possible. */ - } else if ( system == AST__UNKNOWN ) { - match = 0; - } - } - -/* Convert _from_ FK5 J2000.0 coordinates _to_ the alignment system. */ -/* ============================================================ */ -/* In this second phase, we convert to the system given by the align_sys - argument (if required), still using the properties of the target Frame. */ - if ( astOK && match && step2 ) { - -/* Align in FK4. */ -/* --------------- */ -/* Convert directly from FK5 J2000.0 to FK4 B1950.0 coordinates at the - appropriate epoch. Then, if necessary, apply the old-style FK4 - precession model to bring the equinox to that required, with - rigorous handling of the E-terms of aberration. */ - if ( align_sys == AST__FK4 ) { - VerifyMSMAttrs( target, result, 1, "Equinox Epoch", "astMatch", status ); - TRANSFORM_1( "FK54Z", epoch_B ) - if ( equinox_B != 1950.0 ) { - TRANSFORM_1( "SUBET", 1950.0 ) - TRANSFORM_2( "PREBN", 1950.0, equinox_B ) - TRANSFORM_1( "ADDET", equinox_B ) - } - -/* Align in FK4 with no E-terms. */ -/* ------------------------------- */ -/* This is the same as above, except that we do not need to add the - E-terms at the end. */ - } else if ( align_sys == AST__FK4_NO_E ) { - VerifyMSMAttrs( target, result, 1, "Equinox Epoch", "astMatch", status ); - TRANSFORM_1( "FK54Z", epoch_B ) - TRANSFORM_1( "SUBET", 1950.0 ) - if ( equinox_B != 1950.0 ) { - TRANSFORM_2( "PREBN", 1950.0, equinox_B ) - } - -/* Align in FK5. */ -/* ------------- */ -/* We simply need to apply a precession correction for the change of - equinox. Omit even this if the required equinox is J2000.0. */ - } else if ( align_sys == AST__FK5 ) { - VerifyMSMAttrs( target, result, 1, "Equinox", "astMatch", status ); - if ( equinox_J != 2000.0 ) { - TRANSFORM_2( "PREC", 2000.0, equinox_J ) - } - -/* Align in J2000. */ -/* --------------- */ -/* Mov from FK5 to ICRS, and from ICRS to J2000. */ - } else if ( align_sys == AST__J2000 ) { - VerifyMSMAttrs( target, result, 1, "Epoch", "astMatch", status ); - TRANSFORM_1( "FK5HZ", epoch_J ) - TRANSFORM_0( "HJ2000" ) - -/* Align in geocentric apparent. */ -/* ------------------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( align_sys == AST__GAPPT ) { - VerifyMSMAttrs( target, result, 1, "Epoch", "astMatch", status ); - TRANSFORM_2( "MAP", 2000.0, epoch ) - -/* Align in ecliptic coordinates. */ -/* -------------------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( align_sys == AST__ECLIPTIC ) { - VerifyMSMAttrs( target, result, 1, "Equinox", "astMatch", status ); - TRANSFORM_1( "EQECL", equinox ) - -/* Align in helio-ecliptic coordinates. */ -/* ------------------------------------ */ - } else if ( align_sys == AST__HELIOECLIPTIC ) { - VerifyMSMAttrs( target, result, 1, "Epoch", "astMatch", status ); - TRANSFORM_1( "EQHE", epoch ) - -/* Align in galactic coordinates. */ -/* -------------------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( align_sys == AST__GALACTIC ) { - TRANSFORM_0( "EQGAL" ) - -/* Align in ICRS. */ -/* -------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( align_sys == AST__ICRS ) { - VerifyMSMAttrs( target, result, 1, "Epoch", "astMatch", status ); - TRANSFORM_1( "FK5HZ", epoch_J ) - -/* Align in supergalactic coordinates. */ -/* ------------------------------------- */ -/* Convert to galactic coordinates and then to supergalactic. */ - } else if ( align_sys == AST__SUPERGALACTIC ) { - TRANSFORM_0( "EQGAL" ) - TRANSFORM_0( "GALSUP" ) - -/* Align in AzEl coordinates. */ -/* -------------------------- */ -/* Go from FK5 J2000 to geocentric apparent (MAP), shift RA into hour angle - (R2H), rotate from equator to horizon (E2H). */ - } else if ( align_sys == AST__AZEL ) { - VerifyMSMAttrs( target, result, 1, "ObsLon ObsLat Epoch", "astMatch", status ); - TRANSFORM_2( "MAP", 2000.0, epoch ) - TRANSFORM_1( "R2H", last ) - TRANSFORM_2( "E2H", lat, diurab ) - -/* Align in unknown coordinates. */ -/* ------------------------------- */ -/* No conversion is possible. */ - } else if ( align_sys == AST__UNKNOWN ) { - match = 0; - } - } - -/* Convert _from_ the alignment system _to_ FK5 J2000.0 coordinates */ -/* =========================================================== */ -/* In this third phase, we convert from the alignment system (if required) - to the intermediate FK5 J2000 system, using the properties of the - result SkyFrame. */ - -/* Obtain the sky coordinate system, equinox, epoch, etc, of the result - SkyFrame. */ - system = result_system; - equinox = result_equinox; - epoch = result_epoch; - diurab = GetDiurab( result, status ); - last = GetLAST( result, status ); - lat = astGetObsLat( result ); - -/* Convert the equinox and epoch values (stored as Modified Julian - Dates) into the equivalent Besselian and Julian epochs (as decimal - years). */ - if( astOK ) { - equinox_B = palEpb( equinox ); - equinox_J = palEpj( equinox ); - epoch_B = palEpb( epoch ); - epoch_J = palEpj( epoch ); - } - -/* Check we need to do the conversion. */ - if ( astOK && match && step3 ) { - -/* Formulate the conversion... */ - -/* From FK4. */ -/* --------- */ -/* If necessary, apply the old-style FK4 precession model to bring the - equinox to B1950.0, with rigorous handling of the E-terms of - aberration. Then convert directly to FK5 J2000.0 coordinates. */ - if ( align_sys == AST__FK4 ) { - VerifyMSMAttrs( target, result, 3, "Equinox Epoch", "astMatch", status ); - if ( equinox_B != 1950.0 ) { - TRANSFORM_1( "SUBET", equinox_B ) - TRANSFORM_2( "PREBN", equinox_B, 1950.0 ) - TRANSFORM_1( "ADDET", 1950.0 ) - } - TRANSFORM_1( "FK45Z", epoch_B ) - -/* From FK4 with no E-terms. */ -/* ------------------------- */ -/* This is the same as above, except that we do not need to subtract - the E-terms initially as they are already absent. */ - } else if ( align_sys == AST__FK4_NO_E ) { - VerifyMSMAttrs( target, result, 3, "Equinox Epoch", "astMatch", status ); - if ( equinox_B != 1950.0 ) { - TRANSFORM_2( "PREBN", equinox_B, 1950.0 ) - } - TRANSFORM_1( "ADDET", 1950.0 ) - TRANSFORM_1( "FK45Z", epoch_B ) - -/* From FK5. */ -/* --------- */ -/* We simply need to apply a precession correction for the change of - equinox. Omit even this if the equinox is already J2000.0. */ - } else if ( align_sys == AST__FK5 ) { - VerifyMSMAttrs( target, result, 3, "Equinox", "astMatch", status ); - if ( equinox_J != 2000.0 ) { - TRANSFORM_2( "PREC", equinox_J, 2000.0 ); - } - -/* From geocentric apparent. */ -/* ------------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( align_sys == AST__GAPPT ) { - VerifyMSMAttrs( target, result, 3, "Epoch", "astMatch", status ); - TRANSFORM_2( "AMP", epoch, 2000.0 ) - -/* From ecliptic coordinates. */ -/* -------------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( align_sys == AST__ECLIPTIC ) { - VerifyMSMAttrs( target, result, 3, "Equinox", "astMatch", status ); - TRANSFORM_1( "ECLEQ", equinox ) - -/* From helio-ecliptic coordinates. */ -/* -------------------------------- */ - } else if ( align_sys == AST__HELIOECLIPTIC ) { - VerifyMSMAttrs( target, result, 3, "Epoch", "astMatch", status ); - TRANSFORM_1( "HEEQ", epoch ) - -/* From galactic coordinates. */ -/* -------------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( align_sys == AST__GALACTIC ) { - TRANSFORM_0( "GALEQ" ) - -/* From ICRS. */ -/* ---------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( align_sys == AST__ICRS ) { - VerifyMSMAttrs( target, result, 3, "Epoch", "astMatch", status ); - TRANSFORM_1( "HFK5Z", epoch_J ) - -/* From J2000. */ -/* ----------- */ -/* From J2000 to ICRS, and from ICRS to FK5. */ - } else if ( align_sys == AST__J2000 ) { - VerifyMSMAttrs( target, result, 3, "Epoch", "astMatch", status ); - TRANSFORM_0( "J2000H" ) - TRANSFORM_1( "HFK5Z", epoch_J ) - -/* From supergalactic coordinates. */ -/* ------------------------------- */ -/* Convert to galactic coordinates and then to FK5 J2000.0 - equatorial. */ - } else if ( align_sys == AST__SUPERGALACTIC ) { - TRANSFORM_0( "SUPGAL" ) - TRANSFORM_0( "GALEQ" ) - -/* From AzEl. */ -/* ---------- */ -/* Rotate from horizon to equator (H2E), shift hour angle into RA (H2R), - go from geocentric apparent to FK5 J2000. */ - } else if ( align_sys == AST__AZEL ) { - VerifyMSMAttrs( target, result, 3, "ObsLon ObsLat Epoch", "astMatch", status ); - TRANSFORM_2( "H2E", lat, diurab ) - TRANSFORM_1( "H2R", last ) - TRANSFORM_2( "AMP", epoch, 2000.0 ) - -/* From unknown coordinates. */ -/* ------------------------------- */ -/* No conversion is possible. */ - } else if ( align_sys == AST__UNKNOWN ) { - match = 0; - } - } - -/* Convert _from_ FK5 J2000.0 coordinates. */ -/* ======================================= */ -/* In this fourth and final phase, we convert to the result coordinate - system from the intermediate FK5 J2000 sky coordinates generated above. */ - if ( astOK && match && step4 ) { - -/* To FK4. */ -/* ------- */ -/* Convert directly from FK5 J2000.0 to FK4 B1950.0 coordinates at the - appropriate epoch. Then, if necessary, apply the old-style FK4 - precession model to bring the equinox to that required, with - rigorous handling of the E-terms of aberration. */ - if ( system == AST__FK4 ) { - VerifyMSMAttrs( target, result, 3, "Equinox Epoch", "astMatch", status ); - TRANSFORM_1( "FK54Z", epoch_B ) - if ( equinox_B != 1950.0 ) { - TRANSFORM_1( "SUBET", 1950.0 ) - TRANSFORM_2( "PREBN", 1950.0, equinox_B ) - TRANSFORM_1( "ADDET", equinox_B ) - } - -/* To FK4 with no E-terms. */ -/* ----------------------- */ -/* This is the same as above, except that we do not need to add the - E-terms at the end. */ - } else if ( system == AST__FK4_NO_E ) { - VerifyMSMAttrs( target, result, 3, "Equinox Epoch", "astMatch", status ); - TRANSFORM_1( "FK54Z", epoch_B ) - TRANSFORM_1( "SUBET", 1950.0 ) - if ( equinox_B != 1950.0 ) { - TRANSFORM_2( "PREBN", 1950.0, equinox_B ) - } - -/* To FK5. */ -/* ------- */ -/* We simply need to apply a precession correction for the change of - equinox. Omit even this if the required equinox is J2000.0. */ - } else if ( system == AST__FK5 ) { - VerifyMSMAttrs( target, result, 3, "Equinox", "astMatch", status ); - if ( equinox_J != 2000.0 ) { - TRANSFORM_2( "PREC", 2000.0, equinox_J ) - } - -/* To geocentric apparent. */ -/* ----------------------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( system == AST__GAPPT ) { - VerifyMSMAttrs( target, result, 3, "Epoch", "astMatch", status ); - TRANSFORM_2( "MAP", 2000.0, epoch ) - -/* To ecliptic coordinates. */ -/* ------------------------ */ -/* This conversion is supported directly by SLALIB. */ - } else if ( system == AST__ECLIPTIC ) { - VerifyMSMAttrs( target, result, 3, "Equinox", "astMatch", status ); - TRANSFORM_1( "EQECL", equinox ) - -/* To helio-ecliptic coordinates. */ -/* ------------------------------ */ - } else if ( system == AST__HELIOECLIPTIC ) { - VerifyMSMAttrs( target, result, 3, "Epoch", "astMatch", status ); - TRANSFORM_1( "EQHE", epoch ) - -/* To galactic coordinates. */ -/* ------------------------ */ -/* This conversion is supported directly by SLALIB. */ - } else if ( system == AST__GALACTIC ) { - TRANSFORM_0( "EQGAL" ) - -/* To ICRS. */ -/* -------- */ -/* This conversion is supported directly by SLALIB. */ - } else if ( system == AST__ICRS ) { - VerifyMSMAttrs( target, result, 3, "Epoch", "astMatch", status ); - TRANSFORM_1( "FK5HZ", epoch_J ) - -/* To J2000. */ -/* --------- */ -/* From FK5 to ICRS, then from ICRS to J2000. */ - } else if ( system == AST__J2000 ) { - VerifyMSMAttrs( target, result, 3, "Epoch", "astMatch", status ); - TRANSFORM_1( "FK5HZ", epoch_J ) - TRANSFORM_0( "HJ2000" ) - -/* To supergalactic coordinates. */ -/* ----------------------------- */ -/* Convert to galactic coordinates and then to supergalactic. */ - } else if ( system == AST__SUPERGALACTIC ) { - TRANSFORM_0( "EQGAL" ) - TRANSFORM_0( "GALSUP" ) - -/* To AzEl */ -/* ------- */ -/* Go from FK5 J2000 to geocentric apparent (MAP), shift RA into hour angle - (R2H), rotate from equator to horizon (E2H). */ - } else if ( system == AST__AZEL ) { - VerifyMSMAttrs( target, result, 3, "ObsLon ObsLat Epoch", "astMatch", status ); - TRANSFORM_2( "MAP", 2000.0, epoch ) - TRANSFORM_1( "R2H", last ) - TRANSFORM_2( "E2H", lat, diurab ) - -/* To unknown coordinates. */ -/* ----------------------------- */ -/* No conversion is possible. */ - } else if ( system == AST__UNKNOWN ) { - match = 0; - } - } - -/* See of the slamap created above is effectively a unit mapping to - within the tolerance of the more accurate SkyFrame (target or result). */ - isunit = TestSlaUnit( target, result, slamap, status ); - -/* Now need to take account of the possibility that the input or output - SkyFrame may represent an offset system rather than a coordinate system. - Form the Mapping from the target coordinate system to the associated - offset system. A UnitMap is returned if the target does not use an - offset system. */ - omap = SkyOffsetMap( target, status ); - -/* Invert it to get the Mapping from the actual used system (whther - offsets or coordinates) to the coordinate system. */ - astInvert( omap ); - -/* Combine it with the slamap created earlier, so that its coordinate - outputs feed the inputs of the slamap. We only do this if the slamap - is not effectively a unit mapping. Annul redundant pointers afterwards. */ - if( ! isunit ) { - tmap = (AstMapping *) astCmpMap( omap, slamap, 1, "", status ); - } else { - tmap = astClone( omap ); - } - omap = astAnnul( omap ); - slamap =astAnnul( slamap ); - -/* Now form the Mapping from the result coordinate system to the associated - offset system. A UnitMap is returned if the result does not use an - offset system. */ - omap = SkyOffsetMap( result, status ); - -/* Combine it with the above CmpMap, so that the CmpMap outputs feed the - new Mapping inputs. Annul redundant pointers afterwards. */ - tmap2 = (AstMapping *) astCmpMap( tmap, omap, 1, "", status ); - omap =astAnnul( omap ); - tmap =astAnnul( tmap ); - -/* Simplify the Mapping produced above (this eliminates any redundant - conversions) and annul the original pointer. */ - *map = astSimplify( tmap2 ); - tmap2 = astAnnul( tmap2 ); - -/* If an error occurred, annul the returned Mapping and clear the - returned values. */ - if ( !astOK ) { - *map = astAnnul( *map ); - match = -1; - } - -/* Return the result. */ - return match; - -/* Undefine macros local to this function. */ -#undef MAX_ARGS -#undef TRANSFORM_0 -#undef TRANSFORM_1 -#undef TRANSFORM_2 -#undef TRANSFORM_3 -} - -static int Match( AstFrame *template_frame, AstFrame *target, int matchsub, - int **template_axes, int **target_axes, AstMapping **map, - AstFrame **result, int *status ) { -/* -* Name: -* Match - -* Purpose: -* Determine if conversion is possible between two coordinate systems. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int Match( AstFrame *template, AstFrame *target, int matchsub, -* int **template_axes, int **target_axes, -* AstMapping **map, AstFrame **result, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astMatch method -* inherited from the Frame class). - -* Description: -* This function matches a "template" SkyFrame to a "target" Frame and -* determines whether it is possible to convert coordinates between them. -* If it is, a mapping that performs the transformation is returned along -* with a new Frame that describes the coordinate system that results when -* this mapping is applied to the "target" coordinate system. In addition, -* information is returned to allow the axes in this "result" Frame to be -* associated with the corresponding axes in the "target" and "template" -* Frames from which they are derived. - -* Parameters: -* template -* Pointer to the template SkyFrame. This describes the coordinate system -* (or set of possible coordinate systems) into which we wish to convert -* our coordinates. -* target -* Pointer to the target Frame. This describes the coordinate system in -* which we already have coordinates. -* matchsub -* If zero then a match only occurs if the template is of the same -* class as the target, or of a more specialised class. If non-zero -* then a match can occur even if this is not the case. -* template_axes -* Address of a location where a pointer to int will be returned if the -* requested coordinate conversion is possible. This pointer will point -* at a dynamically allocated array of integers with one element for each -* axis of the "result" Frame (see below). It must be freed by the caller -* (using astFree) when no longer required. -* -* For each axis in the result Frame, the corresponding element of this -* array will return the index of the template SkyFrame axis from which -* it is derived. If it is not derived from any template SkyFrame axis, -* a value of -1 will be returned instead. -* target_axes -* Address of a location where a pointer to int will be returned if the -* requested coordinate conversion is possible. This pointer will point -* at a dynamically allocated array of integers with one element for each -* axis of the "result" Frame (see below). It must be freed by the caller -* (using astFree) when no longer required. -* -* For each axis in the result Frame, the corresponding element of this -* array will return the index of the target Frame axis from which it -* is derived. If it is not derived from any target Frame axis, a value -* of -1 will be returned instead. -* map -* Address of a location where a pointer to a new Mapping will be -* returned if the requested coordinate conversion is possible. If -* returned, the forward transformation of this Mapping may be used to -* convert coordinates between the "target" Frame and the "result" -* Frame (see below) and the inverse transformation will convert in the -* opposite direction. -* result -* Address of a location where a pointer to a new Frame will be returned -* if the requested coordinate conversion is possible. If returned, this -* Frame describes the coordinate system that results from applying the -* returned Mapping (above) to the "target" coordinate system. In -* general, this Frame will combine attributes from (and will therefore -* be more specific than) both the target and the template Frames. In -* particular, when the template allows the possibility of transformaing -* to any one of a set of alternative coordinate systems, the "result" -* Frame will indicate which of the alternatives was used. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if the requested coordinate conversion is -* possible. Otherwise zero is returned (this will not in itself result in -* an error condition). - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. - -* Implementation Notes: -* This implementation addresses the matching of a SkyFrame class object to -* any other class of Frame. A SkyFrame will match any class of SkyFrame -* (i.e. possibly from a derived class) but will not match a less -* specialised class of Frame. -*/ - -/* Local Variables: */ - AstFrame *frame0; /* Pointer to Frame underlying axis 0 */ - AstFrame *frame1; /* Pointer to Frame underlying axis 1 */ - AstSkyFrame *template; /* Pointer to template SkyFrame structure */ - int iaxis; /* Axis index */ - int iaxis0; /* Axis index underlying axis 0 */ - int iaxis1; /* Axis index underlying axis 1 */ - int match; /* Coordinate conversion possible? */ - int swap1; /* Template axes swapped? */ - int swap2; /* Target axes swapped? */ - int swap; /* Additional axis swap needed? */ - int target_axis0; /* Index of 1st SkyFrame axis in the target */ - int target_axis1; /* Index of 2nd SkyFrame axis in the target */ - int target_naxes; /* Number of target axes */ - -/* Initialise the returned values. */ - *template_axes = NULL; - *target_axes = NULL; - *map = NULL; - *result = NULL; - match = 0; - -/* Check the global error status. */ - if ( !astOK ) return match; - -/* Initialise variables to avoid "used of uninitialised variable" - messages from dumb compilers. */ - swap = 0; - target_axis0 = -1; - target_axis1 = -1; - -/* Obtain a pointer to the template SkyFrame structure. */ - template = (AstSkyFrame *) template_frame; - -/* Obtain the number of axes in the target Frame. */ - target_naxes = astGetNaxes( target ); - -/* The first criterion for a match is that the template matches as a - Frame class object. This ensures that the number of axes (2) and - domain, etc. of the target Frame are suitable. Invoke the parent - "astMatch" method to verify this. */ - match = (*parent_match)( template_frame, target, matchsub, - template_axes, target_axes, map, result, status ); - -/* If a match was found, annul the returned objects, which are not - needed, but keep the memory allocated for the axis association - arrays, which we will re-use. */ - if ( astOK && match ) { - *map = astAnnul( *map ); - *result = astAnnul( *result ); - } - -/* If OK so far, obtain pointers to the primary Frames which underlie - all target axes. Stop when a SkyFrame axis is found. */ - if ( match && astOK ) { - - match = 0; - for( iaxis = 0; iaxis < target_naxes; iaxis++ ) { - astPrimaryFrame( target, iaxis, &frame0, &iaxis0 ); - if( astIsASkyFrame( frame0 ) ) { - target_axis0 = iaxis; - match = 1; - break; - } else { - frame0 = astAnnul( frame0 ); - } - } - -/* Check at least one SkyFrame axis was found it the target. */ - if( match ) { - -/* If so, search the remaining target axes for another axis that is - derived from the same SkyFrame. */ - match = 0; - for( iaxis++ ; iaxis < target_naxes; iaxis++ ) { - astPrimaryFrame( target, iaxis, &frame1, &iaxis1 ); - if( frame1 == frame0 ) { - target_axis1 = iaxis; - frame1 = astAnnul( frame1 ); - match = 1; - break; - } else { - frame1 = astAnnul( frame1 ); - } - } - -/* Annul the remaining Frame pointer used in the above tests. */ - frame0 = astAnnul( frame0 ); - } - -/* If this test is passed, we can now test that the underlying axis indices - are 0 and 1, in either order. This then ensures that we have a - single SkyFrame (not a compound Frame) with both axes present. */ - if ( match && astOK ) { - match = ( ( ( iaxis0 == 0 ) && ( iaxis1 == 1 ) ) || - ( ( iaxis1 == 0 ) && ( iaxis0 == 1 ) ) ); - } - - } - -/* If a possible match has been detected, we must now decide how the - order of the axes in the result Frame relates to the order of axes - in the target Frame. There are two factors involved. The first - depends on whether the axis permutation array for the template - SkyFrame (whose method we are executing) causes an axis - reversal. Determine this by permuting axis index zero. */ - if ( astOK && match ) { - swap1 = ( astValidateAxis( template, 0, 1, "astMatch" ) != 0 ); - -/* The second factor depends on whether the axes of the underlying - primary SkyFrame are reversed when seen in the target Frame. */ - swap2 = ( iaxis0 != 0 ); - -/* Combine these to determine if an additional axis swap will be - needed. */ - swap = ( swap1 != swap2 ); - -/* Now check to see if this additional swap is permitted by the - template's Permute attribute. */ - match = ( !swap || astGetPermute( template ) ); - } - -/* If the Frames still match, we next set up the axis association - arrays. */ - if ( astOK && match ) { - -/* If the target axis order is to be preserved, then the target axis - association involves no permutation but the template axis - association may involve an axis swap. */ - if ( astGetPreserveAxes( template ) ) { - (*template_axes)[ 0 ] = swap; - (*template_axes)[ 1 ] = !swap; - (*target_axes)[ 0 ] = target_axis0; - (*target_axes)[ 1 ] = target_axis1; - -/* Otherwise, any swap applies to the target axis association - instead. */ - } else { - (*template_axes)[ 0 ] = 0; - (*template_axes)[ 1 ] = 1; - (*target_axes)[ 0 ] = swap ? target_axis1 : target_axis0; - (*target_axes)[ 1 ] = swap ? target_axis0 : target_axis1; - } - -/* Use the target's "astSubFrame" method to create a new Frame (the - result Frame) with copies of the target axes in the required - order. This process also overlays the template attributes on to the - target Frame and returns a Mapping between the target and result - Frames which effects the required coordinate conversion. */ - match = astSubFrame( target, template, 2, *target_axes, *template_axes, - map, result ); - } - -/* If an error occurred, or conversion to the result Frame's - coordinate system was not possible, then free all memory, annul the - returned objects, and reset the returned value. */ - if ( !astOK || !match ) { - *template_axes = astFree( *template_axes ); - *target_axes = astFree( *target_axes ); - if( *map ) *map = astAnnul( *map ); - if( *result ) *result = astAnnul( *result ); - match = 0; - } - -/* Return the result. */ - return match; -} - -static void MatchAxesX( AstFrame *frm2_frame, AstFrame *frm1, int *axes, - int *status ) { -/* -* Name: -* MatchAxesX - -* Purpose: -* Find any corresponding axes in two Frames. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void MatchAxesX( AstFrame *frm2, AstFrame *frm1, int *axes ) -* int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astMatchAxesX -* method inherited from the Frame class). - -* This function looks for corresponding axes within two supplied -* Frames. An array of integers is returned that contains an element -* for each axis in the second supplied Frame. An element in this array -* will be set to zero if the associated axis within the second Frame -* has no corresponding axis within the first Frame. Otherwise, it -* will be set to the index (a non-zero positive integer) of the -* corresponding axis within the first supplied Frame. - -* Parameters: -* frm2 -* Pointer to the second Frame. -* frm1 -* Pointer to the first Frame. -* axes -* Pointer to an integer array in which to return the indices of -* the axes (within the first Frame) that correspond to each axis -* within the second Frame. Axis indices start at 1. A value of zero -* will be stored in the returned array for each axis in the second -* Frame that has no corresponding axis in the first Frame. -* -* The number of elements in this array must be greater than or -* equal to the number of axes in the second Frame. -* status -* Pointer to inherited status value. - -* Notes: -* - Corresponding axes are identified by the fact that a Mapping -* can be found between them using astFindFrame or astConvert. Thus, -* "corresponding axes" are not necessarily identical. For instance, -* SkyFrame axes in two Frames will match even if they describe -* different celestial coordinate systems -*/ - -/* Local Variables: */ - AstFrame *resfrm; - AstMapping *resmap; - AstSkyFrame *frm2; - int *frm2_axes; - int *frm1_axes; - int max_axes; - int min_axes; - int preserve_axes; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to the SkyFrame. */ - frm2 = (AstSkyFrame *) frm2_frame; - -/* Temporarily ensure that the PreserveAxes attribute is non-zero in - the first supplied Frame. This means thte result Frame returned by - astMatch below will have the axis count and order of the target Frame - (i.e. "pfrm"). */ - if( astTestPreserveAxes( frm1 ) ) { - preserve_axes = astGetPreserveAxes( frm1 ) ? 1 : 0; - } else { - preserve_axes = -1; - } - astSetPreserveAxes( frm1, 1 ); - -/* Temporarily ensure that the MaxAxes and MinAxes attributes in the - first supplied Frame are set so the Frame can be used as a template - in astMatch for matching any number of axes. */ - if( astTestMaxAxes( frm1 ) ) { - max_axes = astGetMaxAxes( frm1 ); - } else { - max_axes = -1; - } - astSetMaxAxes( frm1, 10000 ); - - if( astTestMinAxes( frm1 ) ) { - min_axes = astGetMinAxes( frm1 ); - } else { - min_axes = -1; - } - astSetMinAxes( frm1, 1 ); - -/* Attempt to find a sub-frame within the first supplied Frame that - corresponds to the supplied SkyFrame. */ - if( astMatch( frm1, frm2, 1, &frm1_axes, &frm2_axes, &resmap, &resfrm ) ) { - -/* If successfull, Store the one-based index within "frm1" of the - corresponding axes. */ - axes[ 0 ] = frm1_axes[ 0 ] + 1; - axes[ 1 ] = frm1_axes[ 1 ] + 1; - -/* Free resources */ - frm1_axes = astFree( frm1_axes ); - frm2_axes = astFree( frm2_axes ); - resmap = astAnnul( resmap ); - resfrm = astAnnul( resfrm ); - -/* If no corresponding SkyFrame was found store zeros in the returned array. */ - } else { - axes[ 0 ] = 0; - axes[ 1 ] = 0; - } - -/* Re-instate the original attribute values in the first supplied Frame. */ - if( preserve_axes == -1 ) { - astClearPreserveAxes( frm1 ); - } else { - astSetPreserveAxes( frm1, preserve_axes ); - } - - if( max_axes == -1 ) { - astClearMaxAxes( frm1 ); - } else { - astSetMaxAxes( frm1, max_axes ); - } - - if( min_axes == -1 ) { - astClearMinAxes( frm1 ); - } else { - astSetMinAxes( frm1, min_axes ); - } -} - -static void Norm( AstFrame *this_frame, double value[], int *status ) { -/* -* Name: -* Norm - -* Purpose: -* Normalise a set of SkyFrame coordinates. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void Norm( AstAxis *this, double value[], int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astNorm method inherited -* from the Frame class). - -* Description: -* This function converts a set of SkyFrame coordinate values, -* which might potentially be unsuitable for display to a user (for -* instance, may lie outside the expected range of values) into a -* set of acceptable alternative values suitable for display. -* -* This is done by wrapping coordinates so that the latitude lies -* in the range (-pi/2.0) <= latitude <= (pi/2.0). If the NegLon -* attribute is zero (the default), then the wrapped longitude value -* lies in the range 0.0 <= longitude < (2.0*pi). Otherwise, it lies -* in the range -pi <= longitude < pi. - -* Parameters: -* this -* Pointer to the SkyFrame. -* value -* An array of double, with one element for each SkyFrame axis. -* This should contain the initial set of coordinate values, -* which will be modified in place. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const int *perm; /* Axis permutation array */ - double sky_lat; /* Sky latitude value */ - double sky_long; /* Sky longitude value */ - double v[ 2 ]; /* Permuted value coordinates */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( astOK ) { - -/* Obtain the sky longitude and latitude values, allowing for any axis - permutation. */ - v[ perm[ 0 ] ] = value[ 0 ]; - v[ perm[ 1 ] ] = value[ 1 ]; - sky_long = v[ 0 ]; - sky_lat = v[ 1 ]; - -/* Test if both values are OK (i.e. not "bad"). */ - if ( ( sky_long != AST__BAD ) && ( sky_lat != AST__BAD ) ) { - -/* Fold the longitude value into the range 0 to 2*pi and the latitude into - the range -pi to +pi. */ - sky_long = palDranrm( sky_long ); - sky_lat = palDrange( sky_lat ); - -/* If the latitude now exceeds pi/2, shift the longitude by pi in whichever - direction will keep it in the range 0 to 2*pi. */ - if ( sky_lat > ( pi / 2.0 ) ) { - sky_long += ( sky_long < pi ) ? pi : -pi; - -/* Reflect the latitude value through the pole, so it lies in the range 0 to - pi/2. */ - sky_lat = pi - sky_lat; - -/* If the latitude is less than -pi/2, shift the longitude in the same way - as above. */ - } else if ( sky_lat < -( pi / 2.0 ) ) { - sky_long += ( sky_long < pi ) ? pi : -pi; - -/* But reflect the latitude through the other pole, so it lies in the range - -pi/2 to 0. */ - sky_lat = -pi - sky_lat; - } - -/* If only the longitude value is valid, wrap it into the range 0 to 2*pi. */ - } else if ( sky_long != AST__BAD ) { - sky_long = palDranrm( sky_long ); - -/* If only the latitude value is valid, wrap it into the range -pi to +pi. */ - } else if ( sky_lat != AST__BAD ) { - sky_lat = palDrange( sky_lat ); - -/* Then refect through one of the poles (as above), if necessary, to move it - into the range -pi/2 to +pi/2. */ - if ( sky_lat > ( pi / 2.0 ) ) { - sky_lat = pi - sky_lat; - } else if ( sky_lat < -( pi / 2.0 ) ) { - sky_lat = -pi - sky_lat; - } - } - -/* Convert 2*pi longitude into zero. Allow for a small error. */ - if ( fabs( sky_long - ( 2.0 * pi ) ) <= - ( 2.0 * pi ) * ( DBL_EPSILON * (double) FLT_RADIX ) ) sky_long = 0.0; - -/* If the NegLon attribute is set, and the longitude value is good, - convert it into the range -pi to +pi. */ - if( sky_long != AST__BAD && astGetNegLon( this ) ) { - sky_long = palDrange( sky_long ); - } - -/* Return the new values, allowing for any axis permutation. */ - v[ 0 ] = sky_long; - v[ 1 ] = sky_lat; - value[ 0 ] = v[ perm[ 0 ] ]; - value[ 1 ] = v[ perm[ 1 ] ]; - } -} - -static void NormBox( AstFrame *this_frame, double lbnd[], double ubnd[], - AstMapping *reg, int *status ) { -/* -* Name: -* NormBox - -* Purpose: -* Extend a box to include effect of any singularities in the Frame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void astNormBox( AstFrame *this, double lbnd[], double ubnd[], -* AstMapping *reg, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astNormBox method inherited -* from the Frame class). - -* Description: -* This function modifies a supplied box to include the effect of any -* singularities in the co-ordinate system represented by the Frame. -* For a normal Cartesian coordinate system, the box will be returned -* unchanged. Other classes of Frame may do other things. For instance, -* a SkyFrame will check to see if the box contains either the north -* or south pole and extend the box appropriately. - -* Parameters: -* this -* Pointer to the Frame. -* lbnd -* An array of double, with one element for each Frame axis -* (Naxes attribute). Initially, this should contain a set of -* lower axis bounds for the box. They will be modified on exit -* to include the effect of any singularities within the box. -* ubnd -* An array of double, with one element for each Frame axis -* (Naxes attribute). Initially, this should contain a set of -* upper axis bounds for the box. They will be modified on exit -* to include the effect of any singularities within the box. -* reg -* A Mapping which should be used to test if any singular points are -* inside or outside the box. The Mapping should leave an input -* position unchanged if the point is inside the box, and should -* set all bad if the point is outside the box. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const int *perm; /* Axis permutation array */ - double lb[ 2 ]; /* Permuted lower bounds */ - double t; /* Temporary storage */ - double t2; /* Temporary storage */ - double ub[ 2 ]; /* Permuted upper bounds */ - double x[2]; /* 1st axis values at poles */ - double xo[2]; /* Tested 1st axis values at poles */ - double y[2]; /* 2nd axis values at poles */ - double yo[2]; /* Tested 2nd axis values at poles */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if( perm ) { - -/* Obtain the sky longitude and latitude limits, allowing for any axis - permutation. */ - lb[ perm[ 0 ] ] = lbnd[ 0 ]; - lb[ perm[ 1 ] ] = lbnd[ 1 ]; - ub[ perm[ 0 ] ] = ubnd[ 0 ]; - ub[ perm[ 1 ] ] = ubnd[ 1 ]; - -/* Use the supplied Mapping to test if box includes either pole. */ - if( perm[ 0 ] == 0 ) { - x[ 0 ] = 0.0; - y[ 0 ] = AST__DPIBY2; - x[ 1 ] = 0.0; - y[ 1 ] = -AST__DPIBY2; - } else { - x[ 0 ] = AST__DPIBY2; - y[ 0 ] = 0.0; - x[ 1 ] = -AST__DPIBY2; - y[ 1 ] = 0.0; - } - astTran2( reg, 2, x, y, 1, xo, yo ); - -/* If the box includes the north pole... */ - if( xo[ 0 ] != AST__BAD ) { - -/* Find the lowest latitude after normalisation. */ - if( ub[ 1 ] != AST__BAD && lb[ 1 ] != AST__BAD ){ - t = palDrange( ub[ 1 ] ); - t2 = palDrange( lb[ 1 ] ); - if( t2 < t ) t = t2; - } else { - t = AST__BAD; - } - -/* Set the lower returned limit to this value and the upper returned limit - to +90 degs */ - lb[ 1 ] = t; - ub[ 1 ] = AST__DPIBY2; - -/* Set the longitude range to 0 to 2PI */ - lb[ 0 ] = 0; - ub[ 0 ] = 2*AST__DPI; - - } - -/* If the box includes the south pole... */ - if( xo[ 1 ] != AST__BAD ) { - -/* Find the highest latitude after normalisation. */ - if( ub[ 1 ] != AST__BAD && lb[ 1 ] != AST__BAD ){ - t = palDrange( ub[ 1 ] ); - t2 = palDrange( lb[ 1 ] ); - if( t2 > t ) t = t2; - } else { - t = AST__BAD; - } - -/* Set the upper returned limit to this value and the lower returned limit - to -90 degs */ - lb[ 1 ] = -AST__DPIBY2; - ub[ 1 ] = t; - -/* Set the longitude range to 0 to 2PI */ - lb[ 0 ] = 0; - ub[ 0 ] = 2*AST__DPI; - } - -/* Return the modified limits. */ - lbnd[ 0 ] = lb[ perm[ 0 ] ]; - lbnd[ 1 ] = lb[ perm[ 1 ] ]; - ubnd[ 0 ] = ub[ perm[ 0 ] ]; - ubnd[ 1 ] = ub[ perm[ 1 ] ]; - } -} - -static void Offset( AstFrame *this_frame, const double point1[], - const double point2[], double offset, double point3[], int *status ) { -/* -* Name: -* Offset - -* Purpose: -* Calculate an offset along a geodesic curve. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void Offset( AstFrame *this, -* const double point1[], const double point2[], -* double offset, double point3[], int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astOffset method -* inherited from the Frame class). - -* Description: -* This function finds the SkyFrame coordinate values of a point -* which is offset a specified distance along the geodesic curve -* (i.e. great circle) between two other points. - -* Parameters: -* this -* Pointer to the SkyFrame. -* point1 -* An array of double, with one element for each SkyFrame axis. -* This should contain the coordinates of the point marking the -* start of the geodesic curve. -* point2 -* An array of double, with one element for each SkyFrame axis. -* This should contain the coordinates of the point marking the -* end of the geodesic curve. -* offset -* The required offset from the first point along the geodesic -* curve, in radians. If this is positive, it will be towards -* the second point. If it is negative, it will be in the -* opposite direction. This offset need not imply a position -* lying between the two points given, as the curve will be -* extrapolated if necessary. -* point3 -* An array of double, with one element for each SkyFrame axis -* in which the coordinates of the required point will be -* returned. -* status -* Pointer to the inherited status variable. - -* Notes: -* - The geodesic curve used by this function is the path of -* shortest distance between two points, as defined by the -* astDistance function. -* - This function will return "bad" coordinate values (AST__BAD) -* if any of the input coordinates has this value. -* - "Bad" coordinate values will also be returned if the two -* points supplied are coincident (or otherwise fail to uniquely -* specify a geodesic curve) but the requested offset is non-zero. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const int *perm; /* Pointer to axis permutation array */ - double mrot[ 3 ][ 3 ]; /* Rotation matrix */ - double p1[ 2 ]; /* Permuted coordinates for point1 */ - double p2[ 2 ]; /* Permuted coordinates for point2 */ - double p3[ 2 ]; /* Permuted coordinates for point3 */ - double scale; /* Scale factor */ - double v1[ 3 ]; /* 3-vector for p1 */ - double v2[ 3 ]; /* 3-vector for p2 */ - double v3[ 3 ]; /* 3-vector for p3 */ - double vmod; /* Modulus of vector */ - double vrot[ 3 ]; /* Vector along rotation axis */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( astOK ) { - -/* Check that all supplied coordinates are OK. If not, generate "bad" - output coordinates. */ - if ( ( point1[ 0 ] == AST__BAD ) || ( point1[ 1 ] == AST__BAD ) || - ( point2[ 0 ] == AST__BAD ) || ( point2[ 1 ] == AST__BAD ) ) { - point3[ 0 ] = AST__BAD; - point3[ 1 ] = AST__BAD; - -/* Otherwise, apply the axis permutation array to obtain the - coordinates of the two input points in the required - (longitude,latitude) order. */ - } else { - p1[ perm[ 0 ] ] = point1[ 0 ]; - p1[ perm[ 1 ] ] = point1[ 1 ]; - p2[ perm[ 0 ] ] = point2[ 0 ]; - p2[ perm[ 1 ] ] = point2[ 1 ]; - -/* Convert each point into a 3-vector of unit length. */ - palDcs2c( p1[ 0 ], p1[ 1 ], v1 ); - palDcs2c( p2[ 0 ], p2[ 1 ], v2 ); - -/* Find the cross product between these two vectors (the vector order - is reversed here to compensate for the sense of rotation introduced - by palDav2m and palDmxv below). */ - palDvxv( v2, v1, v3 ); - -/* Normalise the cross product vector, also obtaining its original - modulus. */ - palDvn( v3, vrot, &vmod ); - -/* If the original modulus was zero, the input points are either - coincident or diametrically opposite, so do not uniquely define a - great circle. In either case, we can only generate output - coordinates if the offset required is an exact multiple of pi. If - it is, generate the 3-vector that results from rotating the first - input point through this angle. */ - if ( vmod == 0.0 ) { - if ( sin( offset ) == 0.0 ) { - scale = cos( offset ); - v3[ 0 ] = v1[ 0 ] * scale; - v3[ 1 ] = v1[ 1 ] * scale; - v3[ 2 ] = v1[ 2 ] * scale; - -/* Convert the 3-vector back into spherical cooordinates and then - constrain the longitude result to lie in the range 0 to 2*pi - (palDcc2s doesn't do this itself). */ - palDcc2s( v3, &p3[ 0 ], &p3[ 1 ] ); - p3[ 0 ] = palDranrm( p3[ 0 ] ); - -/* If the offset was not a multiple of pi, generate "bad" output - coordinates. */ - } else { - p3[ 0 ] = AST__BAD; - p3[ 1 ] = AST__BAD; - } - -/* If the two input points define a great circle, scale the normalised - cross product vector to make its length equal to the required - offset (angle) between the first input point and the result. */ - } else { - vrot[ 0 ] *= offset; - vrot[ 1 ] *= offset; - vrot[ 2 ] *= offset; - -/* Generate the rotation matrix that implements this rotation and use - it to rotate the first input point (3-vector) to give the required - result (3-vector). */ - palDav2m( vrot, mrot ); - palDmxv( mrot, v1, v3 ); - -/* Convert the 3-vector back into spherical cooordinates and then - constrain the longitude result to lie in the range 0 to 2*pi. */ - palDcc2s( v3, &p3[ 0 ], &p3[ 1 ] ); - p3[ 0 ] = palDranrm( p3[ 0 ] ); - } - -/* Permute the result coordinates to undo the effect of the SkyFrame - axis permutation array. */ - point3[ 0 ] = p3[ perm[ 0 ] ]; - point3[ 1 ] = p3[ perm[ 1 ] ]; - } - } -} - -static AstMapping *SkyOffsetMap( AstSkyFrame *this, int *status ){ -/* -*++ -* Name: -c astSkyOffsetMap -f AST_SKYOFFSETMAP - -* Purpose: -* Returns a Mapping which goes from absolute coordinates to offset -* coordinates. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "skyframe.h" -c AstMapping *astSkyOffsetMap( AstSkyFrame *this ) -f RESULT = AST_SKYOFFSETMAP( THIS, STATUS ) - -* Class Membership: -* SkyFrame method. - -* Description: -* This function returns a Mapping in which the forward transformation -* transforms a position in the coordinate system given by the System -* attribute of the supplied SkyFrame, into the offset coordinate system -* specified by the SkyRef, SkyRefP and SkyRefIs attributes of the -* supplied SkyFrame. -* -* A UnitMap is returned if the SkyFrame does not define an offset -* coordinate system. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the SkyFrame. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astSkyOffsetMap() -f AST_SKYOFFSETMAP = INTEGER -* Pointer to the returned Mapping. - -* Notes: -* - 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. -*-- -*/ - -/* Local Variables: */ - AstCmpMap *map3; /* Partial Mapping. */ - AstMapping *result; /* The returned Mapping. */ - AstMatrixMap *map1; /* Spherical rotation in 3D cartesian space */ - AstSphMap *map2; /* 3D Cartesian to 2D spherical Mapping */ - double *vx; /* Pointer to x unit vector. */ - double *vy; /* Pointer to y unit vector. */ - double *vz; /* Pointer to z unit vector. */ - double mat[ 9 ]; /* Spherical rotation matrix */ - double vmod; /* Length of vector (+ve) */ - double vp[ 3 ]; /* Unit vector representin SkyRefP position. */ - int lataxis; /* Index of the latitude axis */ - int lonaxis; /* Index of the longitude axis */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Return a UnitMap if the offset coordinate system is not defined. */ - if( astGetSkyRefIs( this ) == AST__IGNORED_REF || - ( !astTestSkyRef( this, 0 ) && !astTestSkyRef( this, 1 ) ) ) { - result = (AstMapping *) astUnitMap( 2, "", status ); - -/* Otherwise... */ - } else { - -/* Get the longitude and latitude at the reference point and at a point - on the primary meridian. */ - lataxis = astGetLatAxis( this ); - lonaxis = 1 - lataxis; - -/* Initialise pointers to the rows of the 3x3 matrix. Each row will be - used to store a unit vector. */ - vx = mat; - vy = mat + 3; - vz = mat + 6; - -/* The following trig converts between (longitude,latitude) and (x,y,z) - on a unit sphere, in which (0,0) is at (1,0,0), (0,pi/2) is (0,0,1) - and (pi/2,0) is at (0,1,0). */ - -/* First deal with cases where the SkyRef attribute holds the standard - coords at the origin of the offset coordinate system. */ - if( astGetSkyRefIs( this ) == AST__ORIGIN_REF ) { - -/* Convert each point into a 3-vector of unit length. The SkyRef position - defines the X axis in the offset coord system. */ - palDcs2c( astGetSkyRef( this, lonaxis ), astGetSkyRef( this, lataxis ), vx ); - palDcs2c( astGetSkyRefP( this, lonaxis ), astGetSkyRefP( this, lataxis ), vp ); - -/* The Y axis is perpendicular to both the X axis and the skyrefp - position. That is, it is parallel to the cross product of the 2 above - vectors.*/ - palDvxv( vp, vx, vy ); - -/* Normalize the y vector. */ - palDvn( vy, vy, &vmod ); - -/* Report an error if the modulus of the vector is zero.*/ - if( vmod == 0.0 ) { - astError( AST__BADOC, "astConvert(%s): The position specified by the SkyRefP " - "attribute is either coincident, with or opposite to, the " - "position specified by the SkyRef attribute.", status, astGetClass( this ) ); - -/* If OK, form the Z axis as the cross product of the x and y axes. */ - } else { - palDvxv( vx, vy, vz ); - - } - -/* Now deal with cases where the SkyRef attribute holds the standard - coords at the north pole of the offset coordinate system. */ - } else { - -/* Convert each point into a 3-vector of unit length. The SkyRef position - defines the Z axis in the offset coord system. */ - palDcs2c( astGetSkyRef( this, lonaxis ), astGetSkyRef( this, lataxis ), vz ); - palDcs2c( astGetSkyRefP( this, lonaxis ), astGetSkyRefP( this, lataxis ), vp ); - -/* The Y axis is perpendicular to both the Z axis and the skyrefp - position. That is, it is parallel to the cross product of the 2 above - vectors.*/ - palDvxv( vz, vp, vy ); - -/* Normalize the y vector. */ - palDvn( vy, vy, &vmod ); - -/* Report an error if the modulus of the vector is zero.*/ - if( vmod == 0.0 ) { - astError( AST__BADOC, "astConvert(%s): The position specified by the SkyRefP " - "attribute is either coincident, with or opposite to, the " - "position specified by the SkyRef attribute.", status, astGetClass( this ) ); - -/* If OK, form the X axis as the cross product of the y and z axes. */ - } else { - palDvxv( vy, vz, vx ); - } - } - -/* Create a MatrixMap which implements the above spherical rotation. Each - row in this matrix represents one of the unit axis vectors found above. */ - map1 = astMatrixMap( 3, 3, 0, mat, "", status ); - -/* Create a 3D cartesian to 2D spherical Mapping. */ - map2 = astSphMap( "UnitRadius=1", status ); - -/* Form a series CmpMap which converts from 2D (long,lat) in the base - System to 2D (long,lat) in the offset coordinate system. */ - map3 = astCmpMap( map1, map2, 1, "", status ); - astInvert( map2 ); - result = (AstMapping *) astCmpMap( map2, map3, 1, "", status ); - -/* Free resources. */ - map1 = astAnnul( map1 ); - map2 = astAnnul( map2 ); - map3 = astAnnul( map3 ); - } - -/* Annul the returned Mapping if anything has gone wrong. */ - if( !astOK ) result = astAnnul( result ); - -/* Return the result. */ - return result; - -} - -static double Offset2( AstFrame *this_frame, const double point1[2], - double angle, double offset, double point2[2], int *status ) { -/* -* Name: -* Offset2 - -* Purpose: -* Calculate an offset along a geodesic curve at a given bearing. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* double Offset2( AstFrame *this_frame, const double point1[2], -* double angle, double offset, double point2[2], int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astOffset2 method -* inherited from the Frame class). - -* Description: -* This function finds the SkyFrame coordinate values of a point -* which is offset a specified distance along the geodesic curve -* (i.e. great circle) at a given angle from a given starting point. - -* Parameters: -* this -* Pointer to the SkyFrame. -* point1 -* An array of double, with one element for each SkyFrame axis. -* This should contain the coordinates of the point marking the -* start of the geodesic curve. -* angle -* The angle (in radians) from the positive direction of the second -* axis, to the direction of the required position, as seen from -* the starting position. Positive rotation is in the sense of -* rotation from the positive direction of axis 2 to the positive -* direction of axis 1. -* offset -* The required offset from the first point along the geodesic -* curve, in radians. If this is positive, it will be towards -* the given angle. If it is negative, it will be in the -* opposite direction. -* point2 -* An array of double, with one element for each SkyFrame axis -* in which the coordinates of the required point will be -* returned. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The direction of the geodesic curve at the end point. That is, the -* angle (in radians) between the positive direction of the second -* axis and the continuation of the geodesic curve at the requested -* end point. Positive rotation is in the sense of rotation from -* the positive direction of axis 2 to the positive direction of axis -* 1. - -* Notes: -* - The geodesic curve used by this function is the path of -* shortest distance between two points, as defined by the -* astDistance function. -* - This function will return "bad" coordinate values (AST__BAD) -* if any of the input coordinates has this value. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const int *perm; /* Pointer to axis permutation array */ - double p1[ 2 ]; /* Permuted coordinates for point1 */ - double p2[ 2 ]; /* Permuted coordinates for point2 */ - double result; /* The returned answer */ - double cosoff; /* Cosine of offset */ - double cosa1; /* Cosine of longitude at start */ - double cosb1; /* Cosine of latitude at start */ - double pa; /* A position angle measured from north */ - double q1[ 3 ]; /* Vector PI/2 away from R4 in meridian of R4 */ - double q2[ 3 ]; /* Vector PI/2 away from R4 on equator */ - double q3[ 3 ]; /* Vector PI/2 away from R4 on great circle */ - double r0[ 3 ]; /* Reference position vector */ - double r3[ 3 ]; /* Vector PI/2 away from R0 on great circle */ - double sinoff; /* Sine of offset */ - double sina1; /* Sine of longitude at start */ - double sinb1; /* Sine of latitude at start */ - -/* Initialise. */ - result = AST__BAD; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( astOK ) { - -/* Check that all supplied values are OK. If not, generate "bad" - output coordinates. */ - if ( ( point1[ 0 ] == AST__BAD ) || ( point1[ 1 ] == AST__BAD ) || - ( angle == AST__BAD ) || ( offset == AST__BAD ) ) { - point2[ 0 ] = AST__BAD; - point2[ 1 ] = AST__BAD; - -/* Otherwise, apply the axis permutation array to obtain the - coordinates of the starting point in the required (longitude,latitude) - order. */ - } else { - p1[ perm[ 0 ] ] = point1[ 0 ]; - p1[ perm[ 1 ] ] = point1[ 1 ]; - -/* If the axes are permuted, convert the supplied angle into a position - angle. */ - pa = ( perm[ 0 ] == 0 )? angle: piby2 - angle; - -/* Use Shcal to calculate the required vectors R0 (representing - the reference point) and R3 (representing the point which is 90 - degrees away from the reference point, along the required great - circle). The XY plane defines zero latitude, Z is in the direction - of increasing latitude, X is towards zero longitude, and Y is - towards longitude 90 degrees. */ - Shcal( p1[ 0 ], p1[ 1 ], pa, r0, r3, status ); - -/* Use Shapp to use R0 and R3 to calculate the new position. */ - Shapp( offset, r0, r3, p1[ 0 ], p2, status ); - -/* Normalize the result. */ - astNorm( this, p2 ); - -/* Create the vector Q1 representing the point in the meridian of the - required point which has latitude 90 degrees greater than the - required point. */ - sina1 = sin( p2[ 0 ] ); - cosa1 = cos( p2[ 0 ] ); - sinb1 = sin( p2[ 1 ] ); - cosb1 = cos( p2[ 1 ] ); - - q1[ 0 ] = -sinb1*cosa1; - q1[ 1 ] = -sinb1*sina1; - q1[ 2 ] = cosb1; - -/* Create the vector Q2 representing the point on the equator (i.e. a - latitude of zero), which has a longitude 90 degrees to the west of - the required point. */ - q2[ 0 ] = -sina1; - q2[ 1 ] = cosa1; - q2[ 2 ] = 0.0; - -/* Create the vector Q3 representing the point which is 90 degrees away - from the required point, along the required great circle. */ - cosoff = cos( offset ); - sinoff = sin( offset ); - - q3[ 0 ] = -sinoff*r0[ 0 ] + cosoff*r3[ 0 ]; - q3[ 1 ] = -sinoff*r0[ 1 ] + cosoff*r3[ 1 ]; - q3[ 2 ] = -sinoff*r0[ 2 ] + cosoff*r3[ 2 ]; - -/* Calculate the position angle of the great circle at the required - point. */ - pa = atan2( palDvdv( q3, q2 ), palDvdv( q3, q1 ) ); - -/* Convert this from a pa into the required angle. */ - result = ( perm[ 0 ] == 0 )? pa: piby2 - pa; - -/* Ensure that the end angle is in the range 0 to 2*pi. */ - result = palDranrm( result ); - -/* Permute the result coordinates to undo the effect of the SkyFrame - axis permutation array. */ - point2[ 0 ] = p2[ perm[ 0 ] ]; - point2[ 1 ] = p2[ perm[ 1 ] ]; - } - } - -/* Return the result. */ - return result; - -} - -static void Overlay( AstFrame *template, const int *template_axes, - AstFrame *result, int *status ) { -/* -* Name: -* Overlay - -* Purpose: -* Overlay the attributes of a template SkyFrame on to another Frame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void Overlay( AstFrame *template, const int *template_axes, -* AstFrame *result, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astOverlay method -* inherited from the Frame class). - -* Description: -* This function overlays attributes of a SkyFrame (the "template") on to -* another Frame, so as to over-ride selected attributes of that second -* Frame. Normally only those attributes which have been specifically set -* in the template will be transferred. This implements a form of -* defaulting, in which a Frame acquires attributes from the template, but -* retains its original attributes (as the default) if new values have not -* previously been explicitly set in the template. -* -* Note that if the result Frame is a SkyFrame and a change of sky -* coordinate system occurs as a result of overlaying its System -* attribute, then some of its original attribute values may no -* longer be appropriate (e.g. the Title, or attributes describing -* its axes). In this case, these will be cleared before overlaying -* any new values. - -* Parameters: -* template -* Pointer to the template SkyFrame, for which values should have been -* explicitly set for any attribute which is to be transferred. -* template_axes -* Pointer to an array of int, with one element for each axis of the -* "result" Frame (see below). For each axis in the result frame, the -* corresponding element of this array should contain the (zero-based) -* index of the template axis to which it corresponds. This array is used -* to establish from which template axis any axis-dependent attributes -* should be obtained. -* -* If any axis in the result Frame is not associated with a template -* axis, the corresponding element of this array should be set to -1. -* -* If a NULL pointer is supplied, the template and result axis -* indices are assumed to be identical. -* result -* Pointer to the Frame which is to receive the new attribute values. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* void - -* Notes: -* - In general, if the result Frame is not from the same class as the -* template SkyFrame, or from a class derived from it, then attributes may -* exist in the template SkyFrame which do not exist in the result Frame. In -* this case, these attributes will not be transferred. -*/ - - -/* Local Variables: */ - AstSystemType new_alignsystem;/* Code identifying new alignment coords */ - AstSystemType new_system; /* Code identifying new sky cordinates */ - AstSystemType old_system; /* Code identifying old sky coordinates */ - int axis; /* Loop counter for result SkyFrame axes */ - int skyref_changed; /* Has the SkyRef attribute changed? */ - int reset_system; /* Was the template System value cleared? */ - int skyframe; /* Result Frame is a SkyFrame? */ - int tax0; /* Template axis for result axis 0 */ - int tax1; /* Template axis for result axis 1 */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Indicate that we do not need to reset the System attribute of the - template. */ - reset_system = 0; - new_system = AST__UNKNOWN; - -/* If the result Frame is a SkyFrame, we must test to see if overlaying its - System attribute will change the type of sky coordinate system it - describes. Determine the value of this attribute for the result and template - SkyFrames. We also need to do this if either SkyRef attribute would - change. */ - skyframe = astIsASkyFrame( result ); - if ( skyframe ) { - old_system = astGetSystem( result ); - new_system = astGetSystem( template ); - skyref_changed = ( astGetSkyRef( result, 0 ) != - astGetSkyRef( template, 0 ) ) || - ( astGetSkyRef( result, 1 ) != - astGetSkyRef( template, 1 ) ); - -/* If the coordinate system will change, any value already set for the result - SkyFrame's Title will no longer be appropriate, so clear it. */ - if ( new_system != old_system || skyref_changed ) { - astClearTitle( result ); - -/* Test if the old and new sky coordinate systems are similar enough to make - use of the same axis attribute values (e.g. if they are both equatorial - systems, then they can both use the same axis labels, etc.,so long as - the SKyRefIs value has not changed). */ - if ( IsEquatorial( new_system, status ) != IsEquatorial( old_system, status ) || - skyref_changed ) { - -/* If necessary, clear inappropriate values for all those axis attributes - whose access functions are over-ridden by this class (these access functions - will then provide suitable defaults appropriate to the new coordinate system - instead). */ - for ( axis = 0; axis < 2; axis++ ) { - astClearAsTime( result, axis ); - astClearDirection( result, axis ); - astClearFormat( result, axis ); - astClearLabel( result, axis ); - astClearSymbol( result, axis ); - astClearUnit( result, axis ); - } - } - } - -/* If the result Frame is not a SkyFrame, we must temporarily clear the - System and AlignSystem values since the values used by this class are only - appropriate to this class. */ - } else { - if( astTestSystem( template ) ) { - new_system = astGetSystem( template ); - astClearSystem( template ); - new_alignsystem = astGetAlignSystem( template ); - astClearAlignSystem( template ); - reset_system = 1; - } - } - -/* Invoke the parent class astOverlay method to transfer attributes inherited - from the parent class. */ - (*parent_overlay)( template, template_axes, result, status ); - -/* Reset the System and AlignSystem values if necessary */ - if( reset_system ) { - astSetSystem( template, new_system ); - astSetAlignSystem( template, new_alignsystem ); - } - -/* Check if the result Frame is a SkyFrame or from a class derived from - SkyFrame. If not, we cannot transfer SkyFrame attributes to it as it is - insufficiently specialised. In this case simply omit these attributes. */ - if ( skyframe && astOK ) { - -/* Define a macro that tests whether an attribute is set in the template and, - if so, transfers its value to the result. */ -#define OVERLAY(attr) \ - if ( astTest##attr( template ) ) { \ - astSet##attr( result, astGet##attr( template ) ); \ - } - -/* Store template axis indices */ - if( template_axes ) { - tax0 = template_axes[ 0 ]; - tax1 = template_axes[ 1 ]; - } else { - tax0 = 0; - tax1 = 1; - } - -/* Define a similar macro that does the same for SkyFrame specific axis - attributes. */ -#define OVERLAY2(attr) \ - if( astTest##attr( template, tax0 ) ) { \ - astSet##attr( result, 0, astGet##attr( template, tax0 ) ); \ - } \ - if( astTest##attr( template, tax1 ) ) { \ - astSet##attr( result, 1, astGet##attr( template, tax1 ) ); \ - } - -/* Use the macro to transfer each SkyFrame attribute in turn. */ - OVERLAY(Equinox); - OVERLAY(Projection); - OVERLAY(NegLon); - OVERLAY(SkyTol); - OVERLAY(AlignOffset); - OVERLAY(SkyRefIs); - OVERLAY2(SkyRef); - OVERLAY2(SkyRefP); - } - -/* Undefine macros local to this function. */ -#undef OVERLAY -#undef OVERLAY2 -} - -static void Resolve( AstFrame *this_frame, const double point1[], - const double point2[], const double point3[], - double point4[], double *d1, double *d2, int *status ){ -/* -* Name: -* Resolve - -* Purpose: -* Resolve a vector into two orthogonal components - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void Resolve( AstFrame *this, const double point1[], -* const double point2[], const double point3[], -* double point4[], double *d1, double *d2, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astResolve method -* inherited from the Frame class). - -* Description: -* This function resolves a vector into two perpendicular components. -* The vector from point 1 to point 2 is used as the basis vector. -* The vector from point 1 to point 3 is resolved into components -* parallel and perpendicular to this basis vector. The lengths of the -* two components are returned, together with the position of closest -* aproach of the basis vector to point 3. -* -* Each vector is a geodesic curve. For a SkyFrame, these are great -* circles on the celestial sphere. - -* Parameters: -* this -* Pointer to the Frame. -* point1 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the start of the basis vector, -* and of the vector to be resolved. -* point2 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the end of the basis vector. -* point3 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the end of the vector to be -* resolved. -* point4 -* An array of double, with one element for each Frame axis -* in which the coordinates of the point of closest approach of the -* basis vector to point 3 will be returned. -* d1 -* The address of a location at which to return the distance from -* point 1 to point 4 (that is, the length of the component parallel -* to the basis vector). Positive values are in the same sense as -* movement from point 1 to point 2. -* d2 -* The address of a location at which to return the distance from -* point 4 to point 3 (that is, the length of the component -* perpendicular to the basis vector). The returned value is always -* positive. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function will return "bad" coordinate values (AST__BAD) -* if any of the input coordinates has this value, or if the required -* output values are undefined. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - const int *perm; /* Pointer to axis permutation array */ - double n1[ 3 ]; /* Unit normal to grt crcl thru p1 and p2 */ - double n2[ 3 ]; /* Unit normal to grt crcl thru p3 and p4 */ - double p1[ 2 ]; /* Permuted coordinates for point1 */ - double p2[ 2 ]; /* Permuted coordinates for point2 */ - double p3[ 2 ]; /* Permuted coordinates for point3 */ - double p4[ 2 ]; /* Permuted coordinates for point4 */ - double v1[ 3 ]; /* 3-vector for p1 */ - double v2[ 3 ]; /* 3-vector for p2 */ - double v3[ 3 ]; /* 3-vector for p3 */ - double v4[ 3 ]; /* 3-vector for p4 */ - double v5[ 3 ]; /* 3-vector 90 degs away from p1 */ - double vmod; /* Modulus of vector */ - double vtemp[ 3 ]; /* Temporary vector workspace */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Store initial bad output values. */ - point4[ 0 ] = AST__BAD; - point4[ 1 ] = AST__BAD; - *d1 = AST__BAD; - *d2 = AST__BAD; - -/* Check that all supplied values are OK. */ - if ( ( point1[ 0 ] != AST__BAD ) && ( point1[ 1 ] != AST__BAD ) && - ( point2[ 0 ] != AST__BAD ) && ( point2[ 1 ] != AST__BAD ) && - ( point3[ 0 ] != AST__BAD ) && ( point3[ 1 ] != AST__BAD ) ) { - -/* If so, obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - if ( astOK ) { - -/* Apply the axis permutation array to obtain the coordinates of the - three supplied point in the required (longitude,latitude) order. */ - p1[ perm[ 0 ] ] = point1[ 0 ]; - p1[ perm[ 1 ] ] = point1[ 1 ]; - p2[ perm[ 0 ] ] = point2[ 0 ]; - p2[ perm[ 1 ] ] = point2[ 1 ]; - p3[ perm[ 0 ] ] = point3[ 0 ]; - p3[ perm[ 1 ] ] = point3[ 1 ]; - -/* Convert each point into a 3-vector of unit length. */ - palDcs2c( p1[ 0 ], p1[ 1 ], v1 ); - palDcs2c( p2[ 0 ], p2[ 1 ], v2 ); - palDcs2c( p3[ 0 ], p3[ 1 ], v3 ); - -/* Find the cross product between the first two vectors, and normalize is. - This is the unit normal to the great circle plane defining parallel - distance. */ - palDvxv( v2, v1, vtemp ); - palDvn( vtemp, n1, &vmod ); - -/* Return with bad values if the normal is undefined (i.e. if the first two - vectors are identical or diametrically opposite). */ - if( vmod > 0.0 ) { - -/* Now take the cross product of the normal vector and v1. This gives a - point, v5, on the great circle which is 90 degrees away from v1, in the - direction of v2. */ - palDvxv( v1, n1, v5 ); - -/* Find the cross product of the outlying point (point 3), and the vector - n1 found above, and normalize it. This is the unit normal to the great - circle plane defining perpendicular distance. */ - palDvxv( v3, n1, vtemp ); - palDvn( vtemp, n2, &vmod ); - -/* Return with bad values if the normal is undefined (i.e. if the - outlying point is normal to the great circle defining the basis - vector). */ - if( vmod > 0.0 ) { - -/* The point of closest approach, point 4, is the point which is normal - to both normal vectors (i.e. the intersection of the two great circles). - This is the cross product of n1 and n2. No need to normalize this time - since both n1 and n2 are unit vectors, and so v4 will already be a - unit vector. */ - palDvxv( n1, n2, v4 ); - -/* The dot product of v4 and v1 is the cos of the parallel distance, - d1, whilst the dot product of v4 and v5 is the sin of the parallel - distance. Use these to get the parallel distance with the correct - sign, in the range -PI to +PI. */ - *d1 = atan2( palDvdv( v4, v5 ), palDvdv( v4, v1 ) ); - -/* The dot product of v4 and v3 is the cos of the perpendicular distance, - d2, whilst the dot product of n1 and v3 is the sin of the perpendicular - distance. Use these to get the perpendicular distance. */ - *d2 = fabs( atan2( palDvdv( v3, n1 ), palDvdv( v3, v4 ) ) ); - -/* Convert the 3-vector representing the intersection of the two planes - back into spherical cooordinates and then constrain the longitude result - to lie in the range 0 to 2*pi. */ - palDcc2s( v4, &p4[ 0 ], &p4[ 1 ] ); - p4[ 0 ] = palDranrm( p4[ 0 ] ); - -/* Permute the result coordinates to undo the effect of the SkyFrame - axis permutation array. */ - point4[ 0 ] = p4[ perm[ 0 ] ]; - point4[ 1 ] = p4[ perm[ 1 ] ]; - } - } - } - } - - return; - -} - -static AstPointSet *ResolvePoints( AstFrame *this_frame, const double point1[], - const double point2[], AstPointSet *in, - AstPointSet *out, int *status ) { -/* -* Name: -* ResolvePoints - -* Purpose: -* Resolve a set of vectors into orthogonal components - -* Type: -* Private function. - -* Synopsis: -* #include "frame.h" -* AstPointSet *astResolvePoints( AstFrame *this, const double point1[], -* const double point2[], AstPointSet *in, -* AstPointSet *out ) - -* Class Membership: -* SkyFrame member function (over-rides the astResolvePoints method -* inherited from the Frame class). - -* Description: -* This function takes a Frame and a set of vectors encapsulated -* in a PointSet, and resolves each one into two orthogonal components, -* returning these two components in another PointSet. -* -* This is exactly the same as the public astResolve method, except -* that this method allows many vectors to be processed in a single call, -* thus reducing the computational cost of overheads of many -* individual calls to astResolve. - -* Parameters: -* this -* Pointer to the Frame. -* point1 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the start of the basis vector, -* and of the vectors to be resolved. -* point2 -* An array of double, with one element for each Frame axis -* (Naxes attribute). This marks the end of the basis vector. -* in -* Pointer to the PointSet holding the ends of the vectors to be -* resolved. -* out -* Pointer to a PointSet which will hold the length of the two -* resolved components. A NULL value may also be given, in which -* case a new PointSet will be created by this function. - -* Returned Value: -* Pointer to the output (possibly new) PointSet. The first axis will -* hold the lengths of the vector components parallel to the basis vector. -* These values will be signed (positive values are in the same sense as -* movement from point 1 to point 2. The second axis will hold the lengths -* of the vector components perpendicular to the basis vector. These -* values will be signed only if the Frame is 2-dimensional, in which -* case a positive value indicates that rotation from the basis vector -* to the tested vector is in the same sense as rotation from the first -* to the second axis of the Frame. - -* Notes: -* - The number of coordinate values per point in the input -* PointSet must match the number of axes in the supplied Frame. -* - If an output PointSet is supplied, it must have space for -* sufficient number of points and 2 coordinate values per point. -* - 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. -* - We assume spherical geometry throughout this function. -*/ - -/* Local Variables: */ - AstPointSet *result; /* Pointer to output PointSet */ - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - const int *perm; /* Pointer to axis permutation array */ - double **ptr_in; /* Pointers to input axis values */ - double **ptr_out; /* Pointers to returned axis values */ - double *d1; /* Pointer to next parallel component value */ - double *d2; /* Pointer to next perpendicular component value */ - double *point3x; /* Pointer to next first axis value */ - double *point3y; /* Pointer to next second axis value */ - double n1[ 3 ]; /* Unit normal to grt crcl thru p1 and p2 */ - double n2[ 3 ]; /* Unit normal to grt crcl thru p3 and p4 */ - double p1[ 2 ]; /* Permuted coordinates for point1 */ - double p2[ 2 ]; /* Permuted coordinates for point2 */ - double p3[ 2 ]; /* Permuted coordinates for point3 */ - double sign; /* Sign for perpendicular distances */ - double v1[ 3 ]; /* 3-vector for p1 */ - double v2[ 3 ]; /* 3-vector for p2 */ - double v3[ 3 ]; /* 3-vector for p3 */ - double v4[ 3 ]; /* 3-vector for p4 */ - double v5[ 3 ]; /* 3-vector 90 degs away from p1 */ - double vmod; /* Modulus of vector */ - double vtemp[ 3 ]; /* Temporary vector workspace */ - int ipoint; /* Index of next point */ - int ncoord_in; /* Number of input PointSet coordinates */ - int ncoord_out; /* Number of coordinates in output PointSet */ - int npoint; /* Number of points to transform */ - int npoint_out; /* Number of points in output PointSet */ - int ok; /* OK to proceed? */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Obtain the number of input vectors to resolve and the number of coordinate - values per vector. */ - npoint = astGetNpoint( in ); - ncoord_in = astGetNcoord( in ); - -/* If OK, check that the number of input coordinates matches the number - required by the Frame. Report an error if these numbers do not match. */ - if ( astOK && ( ncoord_in != 2 ) ) { - astError( AST__NCPIN, "astResolvePoints(%s): Bad number of coordinate " - "values (%d) in input %s.", status, astGetClass( this ), ncoord_in, - astGetClass( in ) ); - astError( AST__NCPIN, "The %s given requires 2 coordinate values for " - "each input point.", status, astGetClass( this ) ); - } - -/* If still OK, and a non-NULL pointer has been given for the output PointSet, - then obtain the number of points and number of coordinates per point for - this PointSet. */ - if ( astOK && out ) { - npoint_out = astGetNpoint( out ); - ncoord_out = astGetNcoord( out ); - -/* Check that the dimensions of this PointSet are adequate to accommodate the - output coordinate values and report an error if they are not. */ - if ( astOK ) { - if ( npoint_out < npoint ) { - astError( AST__NOPTS, "astResolvePoints(%s): Too few points (%d) in " - "output %s.", status, astGetClass( this ), npoint_out, - astGetClass( out ) ); - astError( AST__NOPTS, "The %s needs space to hold %d transformed " - "point(s).", status, astGetClass( this ), npoint ); - } else if ( ncoord_out < 2 ) { - astError( AST__NOCTS, "astResolvePoints(%s): Too few coordinate " - "values per point (%d) in output %s.", status, - astGetClass( this ), ncoord_out, astGetClass( out ) ); - astError( AST__NOCTS, "The %s supplied needs space to store 2 " - "coordinate value(s) per transformed point.", status, - astGetClass( this ) ); - } - } - } - -/* If all the validation stages are passed successfully, and a NULL output - pointer was given, then create a new PointSet to encapsulate the output - coordinate data. */ - if ( astOK ) { - if ( !out ) { - result = astPointSet( npoint, 2, "", status ); - -/* Otherwise, use the PointSet supplied. */ - } else { - result = out; - } - } - -/* Get pointers to the input and output axis values */ - ptr_in = astGetPoints( in ); - ptr_out = astGetPoints( result ); - -/* Obtain a pointer to the SkyFrame's axis permutation array. */ - perm = astGetPerm( this ); - -/* If the axes have been swapped we need to swap the sign of the returned - perpendicular distances. */ - sign = ( perm[ 0 ] == 0 ) ? -1.0 : 1.0; - -/* Check pointers can be used safely */ - if( astOK ) { - -/* Apply the axis permutation array to obtain the coordinates of the - two supplied points in the required (longitude,latitude) order. */ - p1[ perm[ 0 ] ] = point1[ 0 ]; - p1[ perm[ 1 ] ] = point1[ 1 ]; - p2[ perm[ 0 ] ] = point2[ 0 ]; - p2[ perm[ 1 ] ] = point2[ 1 ]; - -/* Convert these points into 3-vectors of unit length. */ - palDcs2c( p1[ 0 ], p1[ 1 ], v1 ); - palDcs2c( p2[ 0 ], p2[ 1 ], v2 ); - -/* Find the cross product between the vectors, and normalize it. This is the - unit normal to the great circle plane defining parallel distance. */ - palDvxv( v2, v1, vtemp ); - palDvn( vtemp, n1, &vmod ); - -/* Return with bad values if the normal is undefined (i.e. if the first two - vectors are identical or diametrically opposite). */ - ok = 0; - if( vmod > 0.0 ) { - ok = 1; - -/* Now take the cross product of the normal vector and v1. This gives a - point, v5, on the great circle which is 90 degrees away from v1, in the - direction of v2. */ - palDvxv( v1, n1, v5 ); - } - -/* Store pointers to the first two axis arrays in the returned PointSet. */ - d1 = ptr_out[ 0 ]; - d2 = ptr_out[ 1 ]; - -/* Store pointers to the axis values in the supplied PointSet. */ - point3x = ptr_in[ 0 ]; - point3y = ptr_in[ 1 ]; - -/* Check supplied values can be used */ - if( ok ) { - -/* Loop round each supplied vector. */ - for( ipoint = 0; ipoint < npoint; ipoint++, d1++, d2++, - point3x++, point3y++ ) { - -/* Store bad output values if either input axis value is bad. */ - if( *point3x == AST__BAD || *point3y == AST__BAD ){ - *d1 = AST__BAD; - *d2 = AST__BAD; - -/* If both are good... */ - } else { - -/* Apply the axis permutation array to obtain the coordinates in the - required (longitude,latitude) order. */ - p3[ perm[ 0 ] ] = *point3x; - p3[ perm[ 1 ] ] = *point3y; - -/* Convert into a 3-vector of unit length. */ - palDcs2c( p3[ 0 ], p3[ 1 ], v3 ); - -/* Find the cross product of the outlying point (point 3), and the vector - n1 found above, and normalize it. This is the unit normal to the great - circle plane defining perpendicular distance. */ - palDvxv( v3, n1, vtemp ); - palDvn( vtemp, n2, &vmod ); - -/* Return with bad values if the normal is undefined (i.e. if the - outlying point is normal to the great circle defining the basis - vector). */ - if( vmod <= 0.0 ) { - *d1 = AST__BAD; - *d2 = AST__BAD; - } else { - -/* The point of closest approach, point 4, is the point which is normal - to both normal vectors (i.e. the intersection of the two great circles). - This is the cross product of n1 and n2. No need to normalize this time - since both n1 and n2 are unit vectors, and so v4 will already be a - unit vector. */ - palDvxv( n1, n2, v4 ); - -/* The dot product of v4 and v1 is the cos of the parallel distance, - d1, whilst the dot product of v4 and v5 is the sin of the parallel - distance. Use these to get the parallel distance with the correct - sign, in the range -PI to +PI. */ - *d1 = atan2( palDvdv( v4, v5 ), palDvdv( v4, v1 ) ); - -/* The dot product of v4 and v3 is the cos of the perpendicular distance, - d2, whilst the dot product of n1 and v3 is the sin of the perpendicular - distance. Use these to get the perpendicular distance. */ - *d2 = sign*atan2( palDvdv( v3, n1 ), palDvdv( v3, v4 ) ); - } - } - } - -/* If supplied values cannot be used, fill the returned PointSet with bad - values */ - } else { - for( ipoint = 0; ipoint < npoint; ipoint++, d1++, d2++ ) { - *d1 = AST__BAD; - *d2 = AST__BAD; - } - } - } - -/* Annul the returned PointSet if an error occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return a pointer to the output PointSet. */ - return result; -} - -static void SetAsTime( AstSkyFrame *this, int axis, int value, int *status ) { -/* -* Name: -* SetAsTime - -* Purpose: -* Set a value for the AsTime attribute for a SkyFrame's axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetAsTime( AstSkyFrame *this, int axis, int value, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function sets the boolean value of the AsTime attribute for a -* specified axis of a SkyFrame. This value indicates whether axis values -* should be formatted as times (as opposed to angles) by default. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Index of the axis for which a value is to be set (zero based). -* value -* The boolean value to be set. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* void. -*/ - -/* Local Variables: */ - AstAxis *ax; /* Pointer to Axis object */ - AstSkyAxis *new_ax; /* Pointer to new SkyAxis object */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Validate the axis index. */ - (void) astValidateAxis( this, axis, 1, "astSetAsTime" ); - -/* Obtain a pointer to the Axis object. */ - ax = astGetAxis( this, axis ); - -/* Check if the Axis object is a SkyAxis. If not, we will replace it with - one. */ - if ( !astIsASkyAxis( ax ) ) { - -/* Create a new SkyAxis and overlay the attributes of the original Axis. */ - new_ax = astSkyAxis( "", status ); - astAxisOverlay( ax, new_ax ); - -/* Modify the SkyFrame to use the new Skyaxis and annul the original Axis - pointer. Retain a pointer to the new SkyAxis. */ - astSetAxis( this, axis, new_ax ); - ax = astAnnul( ax ); - ax = (AstAxis *) new_ax; - } - -/* Set a value for the Axis AsTime attribute. */ - astSetAxisAsTime( ax, value ); - -/* Annul the Axis pointer. */ - ax = astAnnul( ax ); -} - -static void SetAttrib( AstObject *this_object, const char *setting, int *status ) { -/* -* Name: -* SetAttrib - -* Purpose: -* Set an attribute value for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetAttrib( AstObject *this, const char *setting, int *status ) - -* Class Membership: -* SkyFrame member function (extends the astSetAttrib method inherited from -* the Mapping class). - -* Description: -* This function assigns an attribute value for a SkyFrame, 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 SkyFrame. -* setting -* Pointer to a null terminated string specifying the new attribute -* value. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* void - -* Attributes: -* As well as those attributes inherited from the parent class, this -* function also accepts values for the following additional attributes: -* -* Equinox (double, read as a string) - -* Notes: -* This protected method is intended to be invoked by the Object astSet -* method and makes additional attributes accessible to it. -*/ - -/* Local Vaiables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - double dval; /* Floating point attribute value */ - double dval1; /* Floating point attribute value */ - double dval2; /* Floating point attribute value */ - double mjd; /* Modified Julian Date */ - int astime; /* Value of AsTime attribute */ - int axis; /* Axis index */ - int equinox; /* Offset of Equinox attribute value */ - int ival; /* Integer attribute value */ - int len; /* Length of setting string */ - int nc; /* Number of characters read by astSscanf */ - int neglon; /* Display -ve longitudes? */ - int ok; /* Can string be used? */ - int offset; /* Offset of start of attribute value */ - int projection; /* Offset of projection attribute value */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_object; - -/* Obtain the length of the setting string. */ - len = 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. */ - -/* AsTime(axis). */ -/* ------------- */ - if ( nc = 0, - ( 2 == astSscanf( setting, "astime(%d)= %d %n", &axis, &astime, &nc ) ) - && ( nc >= len ) ) { - astSetAsTime( this, axis - 1, astime ); - -/* Equinox. */ -/* -------- */ - } else if ( nc = 0, - ( 0 == astSscanf( setting, "equinox=%n%*[^\n]%n", - &equinox, &nc ) ) && ( nc >= len ) ) { - -/* Convert the Equinox value to a Modified Julian Date before use. */ - mjd = astReadDateTime( setting + equinox ); - if ( astOK ) { - astSetEquinox( this, mjd ); - -/* Report contextual information if the conversion failed. */ - } else { - astError( AST__ATTIN, "astSetAttrib(%s): Invalid equinox value " - "\"%s\" given for sky coordinate system.", status, - astGetClass( this ), setting + equinox ); - } - -/* NegLon. */ -/* ------- */ - } else if ( nc = 0, - ( 1 == astSscanf( setting, "neglon= %d %n", &neglon, &nc ) ) - && ( nc >= len ) ) { - astSetNegLon( this, neglon ); - -/* SkyTol. */ -/* ------- */ - } else if ( nc = 0, - ( 1 == astSscanf( setting, "skytol= %lg %n", &dval, &nc ) ) - && ( nc >= len ) ) { - astSetSkyTol( this, dval ); - -/* Projection. */ -/* ----------- */ - } else if ( nc = 0, - ( 0 == astSscanf( setting, "projection=%n%*[^\n]%n", - &projection, &nc ) ) - && ( nc >= len ) ) { - astSetProjection( this, setting + projection ); - -/* SkyRef. */ -/* ------- */ - } else if ( nc = 0, - ( 0 == astSscanf( setting, "skyref=%n%*[^\n]%n", - &offset, &nc ) ) - && ( nc >= len ) ) { - ok = 0; - nc = astUnformat( this, 0, setting + offset, &dval1 ); - if( setting[ offset + nc ] == ',' ) { - nc++; - nc += astUnformat( this, 1, setting + offset + nc, &dval2 ); - if( nc == strlen( setting + offset ) ) { - astSetSkyRef( this, 0, dval1 ); - astSetSkyRef( this, 1, dval2 ); - ok = 1; - } - } - - if( !ok && astOK ) { - astError( AST__BADOC, "astSetAttrib(%s): Invalid axis values string " - "\"%.*s\" given for SkyRef attribute.", status, astGetClass( this ), - (int) astChrLen( setting + offset ), setting + offset ); - } - -/* SkyRef(axis). */ -/* ------------- */ - } else if ( nc = 0, - ( 2 == astSscanf( setting, "skyref(%d)= %lg %n", - &axis, &dval, &nc ) ) - && ( nc >= len ) ) { - astSetSkyRef( this, axis - 1, dval ); - -/* SkyRefIs. */ -/* --------- */ - } else if ( nc = 0, - ( 0 == astSscanf( setting, "skyrefis=%n%*[^\n]%n", - &offset, &nc ) ) - && ( nc >= len ) ) { - - if( astChrMatch( setting + offset, POLE_STRING ) ) { - astSetSkyRefIs( this, AST__POLE_REF ); - - } else if( astChrMatch( setting + offset, ORIGIN_STRING ) ) { - astSetSkyRefIs( this, AST__ORIGIN_REF ); - - } else if( astChrMatch( setting + offset, IGNORED_STRING ) ) { - astSetSkyRefIs( this, AST__IGNORED_REF ); - - } else if( astOK ) { - astError( AST__OPT, "astSet(%s): option '%s' is unknown in '%s'.", status, - astGetClass( this ), setting+offset, setting ); - } - -/* SkyRefP. */ -/* -------- */ - } else if ( nc = 0, - ( 0 == astSscanf( setting, "skyrefp=%n%*[^\n]%n", - &offset, &nc ) ) - && ( nc >= len ) ) { - - ok = 0; - nc = astUnformat( this, 0, setting + offset, &dval1 ); - if( setting[ offset + nc ] == ',' ) { - nc++; - nc += astUnformat( this, 1, setting + offset + nc, &dval2 ); - if( nc == strlen( setting + offset ) ) { - astSetSkyRefP( this, 0, dval1 ); - astSetSkyRefP( this, 1, dval2 ); - ok = 1; - } - } - - if( !ok && astOK ) { - astError( AST__BADOC, "astSetAttrib(%s): Invalid axis values string " - "\"%.*s\" given for SkyRefP attribute.", status, astGetClass( this ), - (int) astChrLen( setting + offset ), setting + offset ); - } - - -/* SkyRefP(axis). */ -/* -------------- */ - } else if ( nc = 0, - ( 2 == astSscanf( setting, "skyrefp(%d)= %lg %n", - &axis, &dval, &nc ) ) - && ( nc >= len ) ) { - astSetSkyRefP( this, axis - 1, dval ); - -/* AlignOffset. */ -/* ------------ */ - } else if ( nc = 0, - ( 1 == astSscanf( setting, "alignoffset= %d %n", &ival, &nc ) ) - && ( nc >= len ) ) { - astSetAlignOffset( this, ival ); - -/* Define a macro 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 ) ) - -/* If the attribute was not recognised, use this macro to report an error - if a read-only attribute has been specified. */ - } else if ( !strncmp( setting, "islataxis", 9 ) || - !strncmp( setting, "islonaxis", 9 ) || - MATCH( "lataxis" ) || - MATCH( "lonaxis" ) ) { - 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); - -/* Pass any unrecognised setting to the parent method for further - interpretation. */ - } else { - (*parent_setattrib)( this_object, setting, status ); - } -} - -static void SetCachedLAST( AstSkyFrame *this, double last, double epoch, - double obslon, double obslat, double obsalt, - double dut1, double dtai, int *status ) { -/* -* Name: -* SetCachedLAST - -* Purpose: -* Store a LAST value in the cache in the SkyFrame vtab. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetCachedLAST( AstSkyFrame *this, double last, double epoch, -* double obslon, double obslat, double obsalt, -* double dut1, double dtai, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function stores the supplied LAST value in a cache in the -* SkyFrame virtual function table for later use by GetCachedLAST. - -* Parameters: -* this -* Pointer to the SkyFrame. -* last -* The Local Apparent Sidereal Time (radians). -* epoch -* The epoch (MJD). -* obslon -* Observatory geodetic longitude (radians) -* obslat -* Observatory geodetic latitude (radians) -* obsalt -* Observatory geodetic altitude (metres) -* dut1 -* The UT1-UTC correction, in seconds. -* dtai -* The TAI-UTC correction, in seconds. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS - AstSkyLastTable *table; - double *ep; - double *lp; - double lp_ref; - int i; - int itable; - -/* Get a pointer to the structure holding thread-specific global data. */ - astGET_GLOBALS(this); - -/* Initialise */ - table = NULL; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Ensure no threads are allowed to read the table whilst we are writing - to it. */ - LOCK_WLOCK1 - -/* Loop round every LAST table held in the vtab. Each table refers to a - different observatory position and/or DUT1 and/or DTAI value. */ - for( itable = 0; itable < nlast_tables; itable++ ) { - table = last_tables[ itable ]; - -/* See if the table refers to the given position, dut1 and dtai value, allowing - some small tolerance. If it does, leave the loop. */ - if( fabs( table->obslat - obslat ) < 2.0E-7 && - fabs( table->obslon - obslon ) < 2.0E-7 && - fabs( table->obsalt - obsalt ) < 1.0 && - fabs( table->dut1 - dut1 ) < 1.0E-5 && - EQUAL( table->dtai, dtai, 1.0E-5 ) ) break; - -/* Ensure "table" ends up NULL if no suitable table is found. */ - table = NULL; - } - -/* If no table was found, create one now, and add it into the vtab cache. */ - if( !table ) { - - astBeginPM; - table = astMalloc( sizeof( AstSkyLastTable ) ); - itable = nlast_tables++; - last_tables = astGrow( last_tables, nlast_tables, - sizeof( AstSkyLastTable * ) ); - astEndPM; - - if( astOK ) { - last_tables[ itable ] = table; - table->obslat = obslat; - table->obslon = obslon; - table->obsalt = obsalt; - table->dut1 = dut1; - table->dtai = dtai; - table->nentry = 1; - - astBeginPM; - table->epoch = astMalloc( sizeof( double ) ); - table->last = astMalloc( sizeof( double ) ); - astEndPM; - - if( astOK ) { - table->epoch[ 0 ] = epoch; - table->last[ 0 ] = last; - } - } - - -/* If we have a table, add the new point into it. */ - } else { - -/* Extend the epoch and last arrays. */ - astBeginPM; - table->epoch = astGrow( table->epoch, ++(table->nentry), sizeof( double ) ); - table->last = astGrow( table->last, table->nentry, sizeof( double ) ); - astEndPM; - -/* Check memory allocation was successful. */ - if( astOK ) { - -/* Get pointers to the last original elements in the arrays of epoch and - corresponding LAST values in the table. */ - ep = table->epoch + table->nentry - 2; - lp = table->last + table->nentry - 2; - -/* Starting from the end of the arrays, shuffle all entries up one - element until an element is found which is less than the supplied epoch - value. This maintains the epoch array in monotonic increasing order. */ - for( i = table->nentry - 2; i >= 0; i--,ep--,lp-- ) { - if( *ep <= epoch ) break; - ep[ 1 ] = *ep; - lp[ 1 ] = *lp; - } - -/* Store the new epoch and LAST value. Add or subtract 2.PI as needed - from the new LAST value to ensure it is continuous with an adjacent - LAST value. This is needed for interpolation between the two values - to be meaningful. */ - ep[ 1 ] = epoch; - -/* For most cases, compare with the previous LAST value. If the new epoch - value is smaller than any epoch already in the table, there will be no - previous LAST value. So compare with the next value instead. */ - if( i >= 0 ) { - lp_ref = lp[ 0 ]; - } else { - lp_ref = lp[ 2 ]; - } - - if( last > lp_ref + AST__DPI ) { - lp[ 1 ] = last - 2*AST__DPI; - - } else if( last < lp_ref - AST__DPI ) { - lp[ 1 ] = last + 2*AST__DPI; - - } else { - lp[ 1 ] = last; - } - } - } - -/* Indicate other threads are now allowed to read the table. */ - UNLOCK_RWLOCK1 - -} - -static void SetDtai( AstFrame *this_frame, double val, int *status ) { -/* -* Name: -* SetDtai - -* Purpose: -* Set the value of the Dtai attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetDtai( AstFrame *this, double val, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astSetDtai method -* inherited from the Frame class). - -* Description: -* This function clears the Dtai value and updates the LAST value -* stored in the SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* val -* New Dtai value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstSkyFrame *this; - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Note the original Dtai value. */ - orig = astGetDtai( this ); - -/* Invoke the parent method to set the Frame Dtai value. */ - (*parent_setdtai)( this_frame, val, status ); - -/* If the DTAI value has changed significantly, indicate that the LAST value - will need to be re-calculated when it is next needed. */ - if( ! EQUAL( orig, val, 1.0E-6 ) ) { - this->last = AST__BAD; - this->eplast = AST__BAD; - this->klast = AST__BAD; - } -} - -static void SetDut1( AstFrame *this_frame, double val, int *status ) { -/* -* Name: -* SetDut1 - -* Purpose: -* Set the value of the Dut1 attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetDut1( AstFrame *this, double val, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astSetDut1 method -* inherited from the Frame class). - -* Description: -* This function clears the Dut1 value and updates the LAST value -* stored in the SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* val -* New Dut1 value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstSkyFrame *this; - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Note the original Dut1 value. */ - orig = astGetDut1( this ); - -/* Invoke the parent method to set the Frame Dut1 value. */ - (*parent_setdut1)( this_frame, val, status ); - -/* If the DUT1 value has changed significantly, indicate that the LAST value - will need to be re-calculated when it is next needed. */ - if( fabs( orig - val ) > 1.0E-6 ) { - this->last = AST__BAD; - this->eplast = AST__BAD; - this->klast = AST__BAD; - } -} - -static void SetLast( AstSkyFrame *this, int *status ) { -/* -* Name: -* SetLast - -* Purpose: -* Set the Local Appearent Sidereal Time for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetLast( AstSkyFrame *this, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function sets the Local Apparent Sidereal Time at the epoch -* and geographical longitude given by the current values of the Epoch -* and ObsLon attributes associated with the supplied SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Notes: -* - A value of AST__BAD will be returned if this function is invoked -* with the global error status set, or if it should fail for any reason. -*/ - -/* Local Variables: */ - double epoch; /* Epoch as a TDB MJD */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get the SkyFrame Epoch as a TDB MJD. */ - epoch = astGetEpoch( this ); - -/* Calculate the LAST value (in rads) and store in the SkyFrame structure. */ - this->last = CalcLAST( this, epoch, astGetObsLon( this ), - astGetObsLat( this ), astGetObsAlt( this ), - astGetDut1( this ), astGetDtai( this ), status ); - -/* Save the TDB MJD to which this LAST corresponds. */ - this->eplast = epoch; - -/* The ratio between solar and sidereal time is a slowly varying function - of epoch. The GetLAST function returns a fast approximation to LAST - by using the ratio between solar and sidereal time. Indicate that - GetLAST should re-calculate the ratio by setting the ratio value bad. */ - this->klast = AST__BAD; -} - -static void SetObsAlt( AstFrame *this, double val, int *status ) { -/* -* Name: -* SetObsAlt - -* Purpose: -* Set the value of the ObsAlt attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetObsAlt( AstFrame *this, double val, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astSetObsAlt method -* inherited from the Frame class). - -* Description: -* This function sets the ObsAlt value. - -* Parameters: -* this -* Pointer to the SkyFrame. -* val -* New ObsAlt value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Note the original ObsAlt value. */ - orig = astGetObsAlt( this ); - -/* Invoke the parent method to set the Frame ObsAlt. */ - (*parent_setobsalt)( this, val, status ); - -/* If the altitude has changed significantly, indicate that the LAST value - and magnitude of the diurnal aberration vector will need to be - re-calculated when next needed. */ - if( fabs( orig - val ) > 0.001 ) { - ( (AstSkyFrame *) this )->last = AST__BAD; - ( (AstSkyFrame *) this )->eplast = AST__BAD; - ( (AstSkyFrame *) this )->klast = AST__BAD; - ( (AstSkyFrame *) this )->diurab = AST__BAD; - } -} - -static void SetObsLat( AstFrame *this, double val, int *status ) { -/* -* Name: -* SetObsLat - -* Purpose: -* Set the value of the ObsLat attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetObsLat( AstFrame *this, double val, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astSetObsLat method -* inherited from the Frame class). - -* Description: -* This function sets the ObsLat value. - -* Parameters: -* this -* Pointer to the SkyFrame. -* val -* New ObsLat value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Note the original ObsLat value. */ - orig = astGetObsLat( this ); - -/* Invoke the parent method to set the Frame ObsLat. */ - (*parent_setobslat)( this, val, status ); - -/* If the altitude has changed significantly, indicate that the LAST value - and magnitude of the diurnal aberration vector will need to be - re-calculated when next needed. */ - if( fabs( orig - val ) > 1.0E-8 ) { - ( (AstSkyFrame *) this )->last = AST__BAD; - ( (AstSkyFrame *) this )->eplast = AST__BAD; - ( (AstSkyFrame *) this )->klast = AST__BAD; - ( (AstSkyFrame *) this )->diurab = AST__BAD; - } -} - -static void SetObsLon( AstFrame *this, double val, int *status ) { -/* -* Name: -* SetObsLon - -* Purpose: -* Set the value of the ObsLon attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetObsLon( AstFrame *this, double val, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astSetObsLon method -* inherited from the Frame class). - -* Description: -* This function sets the ObsLon value. - -* Parameters: -* this -* Pointer to the SkyFrame. -* val -* New ObsLon value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double orig; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Note the original ObsLon value. */ - orig = astGetObsLon( this ); - -/* Invoke the parent method to set the Frame ObsLon. */ - (*parent_setobslon)( this, val, status ); - -/* If the longitude has changed significantly, indicate that the LAST value - will need to be re-calculated when it is next needed. */ - if( fabs( orig - val ) > 1.0E-8 ) { - ( (AstSkyFrame *) this )->last = AST__BAD; - ( (AstSkyFrame *) this )->eplast = AST__BAD; - ( (AstSkyFrame *) this )->klast = AST__BAD; - } -} - -static void SetSystem( AstFrame *this_frame, AstSystemType system, int *status ) { -/* -* Name: -* SetSystem - -* Purpose: -* Set the System attribute for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void SetSystem( AstFrame *this_frame, AstSystemType system, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astSetSystem protected -* method inherited from the Frame class). - -* Description: -* This function assigns a new value to the System attribute for a SkyFrame. - -* Parameters: -* this -* Pointer to the SkyFrame. -* system -* The new System value. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - AstFrameSet *fs; /* FrameSet to be used as the Mapping */ - AstSkyFrame *sfrm; /* Copy of original SkyFrame */ - AstSkyFrame *this; /* Pointer to SkyFrame structure */ - double xin[ 2 ]; /* Axis 0 values */ - double xout[ 2 ]; /* Axis 0 values */ - double yin[ 2 ]; /* Axis 1 values */ - double yout[ 2 ]; /* Axis 1 values */ - int aloff; /* The AlignOffset attribute value */ - int aloff_set; /* Is the AlignOffset attribute set? */ - int skyref_set; /* Is either SkyRef attribute set? */ - int skyrefis; /* The SkyRefIs attribute value */ - int skyrefis_set; /* Is the SkyRefIs attribute set? */ - int skyrefp_set; /* Is either SkyRefP attribute set? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* See if either the SkyRef or SkyRefP attribute is set. */ - skyref_set = astTestSkyRef( this, 0 ) || astTestSkyRef( this, 1 ); - skyrefp_set = astTestSkyRefP( this, 0 ) || astTestSkyRefP( this, 1 ); - -/* If so, we will need to transform their values into the new coordinate - system. Save a copy of the SkyFrame with its original System value. */ - sfrm = ( skyref_set || skyrefp_set )?astCopy( this ):NULL; - -/* Use the parent method to set the new System value. */ - (*parent_setsystem)( this_frame, system, status ); - -/* Now modify the SkyRef and SkyRefP attributes if necessary. */ - if( sfrm ) { - -/* Save the AlignOffset, SkyRefIs, SkyRef and SkyRefP values. */ - aloff_set = astTestAlignOffset( sfrm ); - aloff = astGetAlignOffset( sfrm ); - skyrefis_set = astTestSkyRefIs( sfrm ); - skyrefis = astGetSkyRefIs( sfrm ); - - xin[ 0 ] = astGetSkyRef( sfrm, 0 ); - xin[ 1 ] = astGetSkyRefP( sfrm, 0 ); - yin[ 0 ] = astGetSkyRef( sfrm, 1 ); - yin[ 1 ] = astGetSkyRefP( sfrm, 1 ); - -/* Clear the SkyRef and SkyRefP values to avoid infinite recursion in the - following call to astConvert. */ - if( skyref_set ) { - astClearSkyRef( sfrm, 0 ); - astClearSkyRef( sfrm, 1 ); - astClearSkyRef( this, 0 ); - astClearSkyRef( this, 1 ); - } - - if( skyrefp_set ) { - astClearSkyRefP( sfrm, 0 ); - astClearSkyRefP( sfrm, 1 ); - astClearSkyRefP( this, 0 ); - astClearSkyRefP( this, 1 ); - } - -/* Also set AlignOffset and SkyRefIs so that the following call to - astConvert does not align in offset coords. */ - astSetAlignOffset( sfrm, 0 ); - astSetSkyRefIs( sfrm, AST__IGNORED_REF ); - -/* Get the Mapping from the original System to the new System. Invoking - astConvert will recursively invoke SetSystem again. This is why we need - to be careful to ensure that SkyRef and SKyRefP are cleared above - doing - so ensure we do not end up with infinite recursion. */ - fs = astConvert( sfrm, this, "" ); - -/* If the conversion is not possible, clear the SkyRef and SkyRefP - values. */ - if( !fs ) { - if( skyref_set ) { - astClearSkyRef( this, 0 ); - astClearSkyRef( this, 1 ); - } - if( skyrefp_set ) { - astClearSkyRefP( this, 0 ); - astClearSkyRefP( this, 1 ); - } - -/* Use the Mapping to find the SkyRef and SkyRefP positions in the new - coordinate system. */ - } else { - astTran2( fs, 2, xin, yin, 1, xout, yout ); - -/* Store the values as required. */ - if( skyref_set ) { - astSetSkyRef( this, 0, xout[ 0 ] ); - astSetSkyRef( this, 1, yout[ 0 ] ); - } - - if( skyrefp_set ) { - astSetSkyRefP( this, 0, xout[ 1 ] ); - astSetSkyRefP( this, 1, yout[ 1 ] ); - } - -/* Restore the original SkyRefIs and AlignOffset values. */ - if( aloff_set ) { - astSetAlignOffset( this, aloff ); - } else { - astClearAlignOffset( this ); - } - - if( skyrefis_set ) { - astSetSkyRefIs( this, skyrefis ); - } else { - astClearSkyRefIs( this ); - } - -/* Free resources. */ - fs = astAnnul( fs ); - } - sfrm = astAnnul( sfrm ); - } -} - -static void Shapp( double dist, double *r0, double *r3, double a0, - double *p4, int *status ){ -/* -* Name: -* Shapp - -* Purpose: -* Use the vectors calculated by Shcal to find a sky position -* which is offset along a given position angle. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void Shapp( double dist, double *r0, double *r3, double a0, -* double *p4, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function uses the vectors R0 and R3 calculated previously by -* Shcal to find the sky position which is offset away from the -* "reference" position (see function Offset2) by a given arc -* distance, along a given great circle. -* -* No checks are made for AST__BAD values. - -* Parameters: -* dist -* The arc distance to move away from the reference position -* in the given direction, in radians. -* r0 -* Pointer to an array holding the 3-vector representing the reference -* position. -* r3 -* Pointer to an array holding the 3-vector representing the -* point which is 90 degrees away from the reference point, along -* the required great circle. -* a0 -* The sky longitude of the reference position, in radians. -* p4 -* Pointer to an array of 2 doubles in which to put the sky longitude -* and latitude of the required point, in radians. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double cosdst; /* Cosine of DIST */ - double r4[ 3 ]; /* Required position vector */ - double sindst; /* Sine of DIST */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Store commonly used values. */ - sindst = sin( dist ); - cosdst = cos( dist ); - -/* The vector R4 representing the required point is produced as a - linear sum of R0 and R3. */ - r4[ 0 ] = cosdst*r0[ 0 ] + sindst*r3[ 0 ]; - r4[ 1 ] = cosdst*r0[ 1 ] + sindst*r3[ 1 ]; - r4[ 2 ] = cosdst*r0[ 2 ] + sindst*r3[ 2 ]; - -/* Create the longitude of the required point. If this point is at - a pole it is assigned the same longitude as the reference point. */ - if( r4[ 0 ] != 0.0 || r4[ 1 ] != 0.0 ) { - p4[ 0 ] = atan2( r4[ 1 ], r4[ 0 ] ); - } else { - p4[ 0 ] = a0; - } - -/* Create the latitude of the required point. */ - if( r4[ 2 ] > 1.0 ) { - r4[ 2 ] = 1.0; - } else if( r4[ 2 ] < -1.0 ) { - r4[ 2 ] = -1.0; - } - p4[ 1 ] = asin( r4[ 2 ] ); - -} - -static void Shcal( double a0, double b0, double angle, double *r0, - double *r3, int *status ) { -/* -* Name: -* Shcal - -* Purpose: -* Calculate vectors required by Offset2. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void Shcal( double a0, double b0, double angle, double *r0, -* double *r3, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function calculates the 3-vector R0, representing the given -* sky position (A0,B0), and the 3-vector R3, representing the sky -* position which is 90 degrees away from R0, along a great circle -* passing through R0 at a position angle given by ANGLE. Each -* 3-vector holds Cartesian (X,Y,Z) values with origin at the centre -* of the celestial sphere. The XY plane is the "equator", the Z -* axis is in the direction of the "north pole", X is towards zero -* longitude (A=0), and Y is towards longitude 90 degrees. -* -* No checks are made for AST__BAD input values. - -* Parameters: -* a0 -* The sky longitude of the given position, in radians. -* b0 -* The sky latitude of the given position, in radians. -* angle -* The position angle of a great circle passing through the given -* position. That is, the angle from north to the required -* direction, in radians. Positive angles are in the sense of -* rotation from north to east. -* r0 -* A pointer to an array to receive 3-vector R0. See above. -* r3 -* A pointer to an array to receive 3-vector R3. See above. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - double cosa0; /* Cosine of A0 */ - double cosb0; /* Cosine of B0 */ - double cospa; /* Cosine of ANGLE */ - double r1[ 3 ]; /* Vector PI/2 away from R0 in meridian of R0 */ - double r2[ 3 ]; /* Vector PI/2 away from R0 on equator */ - double sinpa; /* Sine of ANGLE */ - double sina0; /* Sine of A0 */ - double sinb0; /* Sine of B0 */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Store commonly used values. */ - sina0 = sin( a0 ); - cosa0 = cos( a0 ); - sinb0 = sin( b0 ); - cosb0 = cos( b0 ); - sinpa = sin( angle ); - cospa = cos( angle ); - -/* Create the vector R0 representing the given point. The XY plane - defines zero latitude, Z is in the direction of increasing latitude, - X is towards zero longitude, and Y is towards longitude 90 degrees. */ - r0[ 0 ] = cosb0*cosa0; - r0[ 1 ] = cosb0*sina0; - r0[ 2 ] = sinb0; - -/* Create the vector R1 representing the point in the meridian of the - given point which has latitude 90 degrees greater than the - given point. */ - r1[ 0 ] = -sinb0*cosa0; - r1[ 1 ] = -sinb0*sina0; - r1[ 2 ] = cosb0; - -/* Create the vector R2 representing the point on the equator (i.e. a - latitude of zero), which has a longitude 90 degrees to the west of - the given point. */ - r2[ 0 ] = -sina0; - r2[ 1 ] = cosa0; - r2[ 2 ] = 0.0; - -/* Create the vector R3 representing the point which is 90 degrees away - from the given point, along the required great circle. */ - r3[ 0 ] = cospa*r1[ 0 ] + sinpa*r2[ 0 ]; - r3[ 1 ] = cospa*r1[ 1 ] + sinpa*r2[ 1 ]; - r3[ 2 ] = cospa*r1[ 2 ] + sinpa*r2[ 2 ]; - -/* Return */ - return; -} - -static int SubFrame( AstFrame *target_frame, AstFrame *template, - int result_naxes, const int *target_axes, - const int *template_axes, AstMapping **map, - AstFrame **result, int *status ) { -/* -* Name: -* SubFrame - -* Purpose: -* Select axes from a SkyFrame and convert to the new coordinate system. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int SubFrame( AstFrame *target, AstFrame *template, -* int result_naxes, const int *target_axes, -* const int *template_axes, AstMapping **map, -* AstFrame **result, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the protected astSubFrame method -* inherited from the Frame class). - -* Description: -* This function selects a requested sub-set (or super-set) of the axes from -* a "target" SkyFrame and creates a new Frame with copies of the selected -* axes assembled in the requested order. It then optionally overlays the -* attributes of a "template" Frame on to the result. It returns both the -* resulting Frame and a Mapping that describes how to convert between the -* coordinate systems described by the target and result Frames. If -* necessary, this Mapping takes account of any differences in the Frames' -* attributes due to the influence of the template. - -* Parameters: -* target -* Pointer to the target SkyFrame, from which axes are to be selected. -* template -* Pointer to the template Frame, from which new attributes for the -* result Frame are to be obtained. Optionally, this may be NULL, in -* which case no overlaying of template attributes will be performed. -* result_naxes -* Number of axes to be selected from the target Frame. This number may -* be greater than or less than the number of axes in this Frame (or -* equal). -* target_axes -* Pointer to an array of int with result_naxes elements, giving a list -* of the (zero-based) axis indices of the axes to be selected from the -* target SkyFrame. The order in which these are given determines the -* order in which the axes appear in the result Frame. If any of the -* values in this array is set to -1, the corresponding result axis will -* not be derived from the target Frame, but will be assigned default -* attributes instead. -* template_axes -* Pointer to an array of int with result_naxes elements. This should -* contain a list of the template axes (given as zero-based axis indices) -* with which the axes of the result Frame are to be associated. This -* array determines which axes are used when overlaying axis-dependent -* attributes of the template on to the result. If any element of this -* array is set to -1, the corresponding result axis will not receive any -* template attributes. -* -* If the template argument is given as NULL, this array is not used and -* a NULL pointer may also be supplied here. -* map -* Address of a location to receive a pointer to the returned Mapping. -* The forward transformation of this Mapping will describe how to -* convert coordinates from the coordinate system described by the target -* SkyFrame to that described by the result Frame. The inverse -* transformation will convert in the opposite direction. -* result -* Address of a location to receive a pointer to the result Frame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* A non-zero value is returned if coordinate conversion is possible -* between the target and the result Frame. Otherwise zero is returned and -* *map and *result are returned as NULL (but this will not in itself -* result in an error condition). In general, coordinate conversion should -* always be possible if no template Frame is supplied but may not always -* be possible otherwise. - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. - -* Implementation Notes: -* - This implementation addresses the selection of axes from a SkyFrame -* object. This results in another object of the same class only if both -* axes of the SkyFrame are selected, once each. Otherwise, the result is a -* Frame class object which inherits the SkyFrame's axis information (if -* appropriate) but none of the other properties of a SkyFrame. -* - In the event that a SkyFrame results, the returned Mapping will take -* proper account of the relationship between the target and result sky -* coordinate systems. -* - In the event that a Frame class object results, the returned Mapping -* will only represent a selection/permutation of axes. - -* Implementation Deficiencies: -* - Any axis selection is currently permitted. Probably this should be -* restricted so that each axis can only be selected once. The -* astValidateAxisSelection method will do this but currently there are bugs -* in the CmpFrame class that cause axis selections which will not pass this -* test. Install the validation when these are fixed. -*/ - -/* Local Variables: */ - AstAxis *ax; /* Pointer to result Frame Axis object */ - AstMapping *tmpmap; /* Temporary Mapping pointer */ - AstPermMap *permmap; /* Pointer to PermMap */ - AstSkyFrame *target; /* Pointer to the SkyFrame structure */ - AstSkyFrame *temp; /* Pointer to copy of target SkyFrame */ - AstSystemType align_sys; /* System in which to align the SkyFrames */ - int match; /* Coordinate conversion is possible? */ - int perm[ 2 ]; /* Permutation array for axis swap */ - int result_swap; /* Swap result SkyFrame coordinates? */ - int set_usedefs; /* Set the returned UseDefs attribute zero?*/ - int target_axis; /* Target SkyFrame axis index */ - int target_swap; /* Swap target SkyFrame coordinates? */ - -/* Initialise the returned values. */ - *map = NULL; - *result = NULL; - match = 0; - -/* Check the global error status. */ - if ( !astOK ) return match; - -/* Obtain a pointer to the target SkyFrame structure. */ - target = (AstSkyFrame *) target_frame; - -/* Result is a SkyFrame. */ -/* --------------------- */ -/* Check if the result Frame is to have two axes obtained by selecting - both of the target SkyFrame axes, in either order. If so, the - result will also be a SkyFrame. */ - if ( ( result_naxes == 2 ) && - ( ( ( target_axes[ 0 ] == 0 ) && ( target_axes[ 1 ] == 1 ) ) || - ( ( target_axes[ 0 ] == 1 ) && ( target_axes[ 1 ] == 0 ) ) ) ) { - -/* If a template has not been supplied, or is the same object as the - target, we are simply extracting axes from the supplied SkyFrame. In - this case we temporarily force the UseDefs attribute to 1 so that (for - instance) the astPickAxes method can function correctly. E.g. if you - have a SkyFrame with no set Epoch and UseDefs set zero, and you try to - swap the axes, the attempt would fail because MakeSkyMapping would be - unable to determine the Mapping from original to swapped SkyFrame, - because of the lack of an Epoch value. */ - set_usedefs = 0; - if( !template || template == target_frame ) { - if( !astGetUseDefs( target ) ) { - astClearUseDefs( target ); - set_usedefs = 1; - } - } - -/* Form the result from a copy of the target and then permute its axes - into the order required. */ - *result = astCopy( target ); - astPermAxes( *result, target_axes ); - -/* If required, overlay the template attributes on to the result SkyFrame. - Also get the system in which to align the two SkyFrames. This is the - value of the AlignSystem attribute from the template (if there is a - template). */ - if ( template ) { - astOverlay( template, template_axes, *result ); - align_sys = astGetAlignSystem( template ); - - } else { - align_sys = astGetAlignSystem( target ); - } - -/* See whether alignment occurs in offset coordinates or absolute - coordinates. If the current call to this function is part of the - process of restoring a FrameSet's integrity following changes to - the FrameSet's current Frame, then we ignore the setting of the - AlignOffset attributes and use 0. This ensures that when the System - attribute (for instance) is changed via a FrameSet pointer, the - Mappings within the FrameSet are modified to produce offsets in the - new System. If we are not currently restoring a FrameSet's integrity, - then we align in offsets if the template is a SkyFrame and both template - and target want alignment to occur in the offset coordinate system. In - this case we use a UnitMap to connect them. */ - if( ( astGetFrameFlags( target_frame ) & AST__INTFLAG ) == 0 ) { - if( astGetAlignOffset( target ) && - astGetSkyRefIs( target ) != AST__IGNORED_REF && - template && astIsASkyFrame( template ) ){ - if( astGetAlignOffset( (AstSkyFrame *) template ) && - astGetSkyRefIs( (AstSkyFrame *) template ) != AST__IGNORED_REF ) { - match = 1; - *map = (AstMapping *) astUnitMap( 2, "", status ); - } - } - } - -/* Otherwise, generate a Mapping that takes account of changes in the sky - coordinate system (equinox, epoch, etc.) between the target SkyFrame and - the result SkyFrame. If this Mapping can be generated, set "match" to - indicate that coordinate conversion is possible. */ - if( ! *map ) { - match = ( MakeSkyMapping( target, (AstSkyFrame *) *result, - align_sys, map, status ) != 0 ); - } - -/* If required, re-instate the original zero value of UseDefs. */ - if( set_usedefs ) { - astSetUseDefs( target, 0 ); - astSetUseDefs( *result, 0 ); - } - -/* If a Mapping has been obtained, it will expect coordinate values to be - supplied in (longitude,latitude) pairs. Test whether we need to swap the - order of the target SkyFrame coordinates to conform with this. */ - if ( astOK && match ) { - target_swap = ( astValidateAxis( target, 0, 1, "astSubFrame" ) != 0 ); - -/* Coordinates will also be delivered in (longitude,latitude) pairs, so check - to see whether the result SkyFrame coordinate order should be swapped. */ - result_swap = ( target_swap != ( target_axes[ 0 ] != 0 ) ); - -/* If either set of coordinates needs swapping, create a PermMap that - will swap a pair of coordinates. */ - permmap = NULL; - if ( target_swap || result_swap ) { - perm[ 0 ] = 1; - perm[ 1 ] = 0; - permmap = astPermMap( 2, perm, 2, perm, NULL, "", status ); - } - -/* If necessary, prefix this PermMap to the main Mapping. */ - if ( target_swap ) { - tmpmap = (AstMapping *) astCmpMap( permmap, *map, 1, "", status ); - *map = astAnnul( *map ); - *map = tmpmap; - } - -/* Also, if necessary, append it to the main Mapping. */ - if ( result_swap ) { - tmpmap = (AstMapping *) astCmpMap( *map, permmap, 1, "", status ); - *map = astAnnul( *map ); - *map = tmpmap; - } - -/* Annul the pointer to the PermMap (if created). */ - if ( permmap ) permmap = astAnnul( permmap ); - } - -/* Result is not a SkyFrame. */ -/* ------------------------- */ -/* In this case, we select axes as if the target were from the Frame - class. However, since the resulting data will then be separated - from their enclosing SkyFrame, default attribute values may differ - if the methods for obtaining them were over-ridden by the SkyFrame - class. To overcome this, we ensure that these values are explicitly - set for the result Frame (rather than relying on their - defaults). */ - } else { - -/* Make a temporary copy of the target SkyFrame. We will explicitly - set the attribute values in this copy so as not to modify the - original. */ - temp = astCopy( target ); - -/* Define a macro to test if an attribute is set. If not, set it - explicitly to its default value. */ -#define SET(attribute) \ - if ( !astTest##attribute( temp ) ) { \ - astSet##attribute( temp, astGet##attribute( temp ) ); \ - } - -/* Set attribute values which apply to the Frame as a whole and which - we want to retain, but whose defaults are over-ridden by the - SkyFrame class. */ - SET(Domain) - SET(Title) - -/* Now loop to set explicit attribute values for each axis. */ - for ( target_axis = 0; target_axis < 2; target_axis++ ) { - -/* Define a macro to test if an axis attribute is set. If not, set it - explicitly to its default value. */ -#define SET_AXIS(attribute) \ - if ( !astTest##attribute( temp, target_axis ) ) { \ - astSet##attribute( temp, target_axis, \ - astGet##attribute( temp, target_axis ) ); \ - } - -/* Use this macro to set explicit values for all the axis attributes - for which the SkyFrame class over-rides the default value. */ - SET_AXIS(AsTime) - SET_AXIS(Format) - SET_AXIS(Label) - SET_AXIS(Symbol) - SET_AXIS(Unit) - -/* Now handle axis attributes for which there are no SkyFrame access - methods. For these we require a pointer to the temporary - SkyFrame's Axis object. */ - ax = astGetAxis( temp, target_axis ); - -/* Set an explicit value for the IsLatitude and CentreZero attributes. */ - if( astValidateAxis( temp, target_axis, 1, "astSubFrame" ) == 1 ) { - astSetAxisIsLatitude( ax, 1 ); - astSetAxisCentreZero( ax, 1 ); - - } else { - astSetAxisIsLatitude( ax, 0 ); - astSetAxisCentreZero( ax, astGetNegLon( temp ) ); - } - -/* Annul the Axis object pointer. */ - ax = astAnnul( ax ); - } - -/* Clear attributes which have an extended range of values allowed by - this class. */ - astClearSystem( temp ); - astClearAlignSystem( temp ); - -/* Invoke the astSubFrame method inherited from the Frame class to - produce the result Frame by selecting the required set of axes and - overlaying the template Frame's attributes. */ - match = (*parent_subframe)( (AstFrame *) temp, template, - result_naxes, target_axes, template_axes, - map, result, status ); - -/* Delete the temporary copy of the target SkyFrame. */ - temp = astDelete( temp ); - } - -/* Ensure the returned Frame does not have active units. */ - astSetActiveUnit( *result, 0 ); - -/* If an error occurred or no match was found, annul the returned - objects and reset the returned result. */ - if ( !astOK || !match ) { - if( *map ) *map = astAnnul( *map ); - if( *result ) *result = astAnnul( *result ); - match = 0; - } - -/* Return the result. */ - return match; - -/* Undefine macros local to this function. */ -#undef SET -#undef SET_AXIS -} - -static AstSystemType SystemCode( AstFrame *this, const char *system, int *status ) { -/* -* Name: -* SystemCode - -* Purpose: -* Convert a string into a coordinate system type code. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* AstSystemType SystemCode( AstFrame *this, const char *system, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astSystemCode method -* inherited from the Frame class). - -* Description: -* This function converts a string used for the external -* description of a sky coordinate system into a SkyFrame -* coordinate system type code (System attribute value). It is the -* inverse of the astSystemString function. - -* Parameters: -* this -* The Frame. -* system -* Pointer to a constant null-terminated string containing the -* external description of the sky coordinate system. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The System type code. - -* Notes: -* - A value of AST__BADSYSTEM is returned if the sky coordinate -* system description was not recognised. This does not produce an -* error. -* - A value of AST__BADSYSTEM is also returned if this function -* is invoked with the global error status set or if it should fail -* for any reason. -*/ - -/* Local Variables: */ - AstSystemType result; /* Result value to return */ - -/* Initialise. */ - result = AST__BADSYSTEM; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Match the "system" string against each possibility and assign the - result. */ - if ( astChrMatch( "FK4", system ) ) { - result = AST__FK4; - - } else if ( astChrMatch( "FK4_NO_E", system ) || - astChrMatch( "FK4-NO-E", system ) ) { - result = AST__FK4_NO_E; - - } else if ( astChrMatch( "FK5", system ) || - astChrMatch( "Equatorial", system ) ) { - result = AST__FK5; - - } else if ( astChrMatch( "J2000", system ) ) { - result = AST__J2000; - - } else if ( astChrMatch( "ICRS", system ) ) { - result = AST__ICRS; - - } else if ( astChrMatch( "AZEL", system ) ) { - result = AST__AZEL; - - } else if ( astChrMatch( "GAPPT", system ) || - astChrMatch( "GEOCENTRIC", system ) || - astChrMatch( "APPARENT", system ) ) { - result = AST__GAPPT; - - } else if ( astChrMatch( "ECLIPTIC", system ) ) { - result = AST__ECLIPTIC; - - } else if ( astChrMatch( "HELIOECLIPTIC", system ) ) { - result = AST__HELIOECLIPTIC; - - } else if ( astChrMatch( "GALACTIC", system ) ) { - result = AST__GALACTIC; - - } else if ( astChrMatch( "SUPERGALACTIC", system ) ) { - result = AST__SUPERGALACTIC; - - } else if ( astChrMatch( "UNKNOWN", system ) ) { - result = AST__UNKNOWN; - } - -/* Return the result. */ - return result; -} - -static const char *SystemString( AstFrame *this, AstSystemType system, int *status ) { -/* -* Name: -* SystemString - -* Purpose: -* Convert a coordinate system type code into a string. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* const char *SystemString( AstFrame *this, AstSystemType system, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astSystemString method -* inherited from the Frame class). - -* Description: -* This function converts a SkyFrame coordinate system type code -* (System attribute value) into a string suitable for use as an -* external representation of the coordinate system type. - -* Parameters: -* this -* The Frame. -* system -* The coordinate system type code. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Pointer to a constant null-terminated string containing the -* textual equivalent of the type code supplied. - -* Notes: -* - A NULL pointer value is returned if the sky coordinate system -* code was not recognised. This does not produce an error. -* - A NULL pointer value is also returned if this function is -* invoked with the global error status set or if it should fail -* for any reason. -*/ - -/* Local Variables: */ - const char *result; /* Pointer value to return */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Match the "system" value against each possibility and convert to a - string pointer. (Where possible, return the same string as would be - used in the FITS WCS representation of the coordinate system). */ - switch ( system ) { - case AST__FK4: - result = "FK4"; - break; - - case AST__FK4_NO_E: - result = "FK4-NO-E"; - break; - - case AST__FK5: - result = "FK5"; - break; - - case AST__J2000: - result = "J2000"; - break; - - case AST__ICRS: - result = "ICRS"; - break; - - case AST__GAPPT: - result = "GAPPT"; - break; - - case AST__AZEL: - result = "AZEL"; - break; - - case AST__ECLIPTIC: - result = "ECLIPTIC"; - break; - - case AST__HELIOECLIPTIC: - result = "HELIOECLIPTIC"; - break; - - case AST__GALACTIC: - result = "GALACTIC"; - break; - - case AST__SUPERGALACTIC: - result = "SUPERGALACTIC"; - break; - - case AST__UNKNOWN: - result = "Unknown"; - break; - } - -/* Return the result pointer. */ - return result; -} - -static int TestActiveUnit( AstFrame *this_frame, int *status ) { -/* -* Name: -* TestActiveUnit - -* Purpose: -* Test the ActiveUnit flag for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int TestActiveUnit( AstFrame *this_frame, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astTestActiveUnit protected -* method inherited from the Frame class). - -* Description: -* This function test the value of the ActiveUnit flag for a SkyFrame, -* which is always "unset". - -* Parameters: -* this -* Pointer to the SkyFrame. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The result of the test (0). - -*/ - return 0; -} - -static int TestAsTime( AstSkyFrame *this, int axis, int *status ) { -/* -* Name: -* TestAsTime - -* Purpose: -* Determine if a value has been set for a SkyFrame's AsTime attribute. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int TestAsTime( AstSkyFrame *this, int axis, int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function returns a boolean value to indicate if a value has -* previously been set for the AsTime attribute for a specified axis of a -* SkyFrame. This attribute indicates whether axis values should be -* formatted as times (as opposed to angles) by default. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* Index of the axis for which information is required (zero based). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Zero or one, according to whether the AsTime attribute has been set. - -* Notes: -* - A value of zero will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*/ - -/* Local Variables. */ - AstAxis *ax; /* Pointer to Axis object */ - int result; /* Result to be returned */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Validate the axis index. */ - (void) astValidateAxis( this, axis, 1, "astTestAsTime" ); - -/* Obtain a pointer to the Axis object. */ - ax = astGetAxis( this, axis ); - -/* Determine if the AsTime attribute has been set for it (it cannot have been - set unless the object is a SkyAxis). */ - result = ( astIsASkyAxis( ax ) && astTestAxisAsTime( ax ) ); - -/* Annul the Axis pointer. */ - ax = astAnnul( ax ); - -/* Return the result. */ - return result; -} - -static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) { -/* -* Name: -* TestAttrib - -* Purpose: -* Test if a specified attribute value is set for a SkyFrame. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int TestAttrib( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astTestAttrib protected -* method inherited from the Frame class). - -* Description: -* This function returns a boolean result (0 or 1) to indicate whether -* a value has been set for one of a SkyFrame's attributes. - -* Parameters: -* this -* Pointer to the SkyFrame. -* 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: -* - This function uses one-based axis numbering so that it is -* suitable for external (public) use. -* - 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: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - int axis; /* SkyFrame axis number */ - int len; /* Length of attrib string */ - int nc; /* No. 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 SkyFrame structure. */ - this = (AstSkyFrame *) this_object; - -/* Obtain the length of the attrib string. */ - len = strlen( attrib ); - -/* Check the attribute name and test the appropriate attribute. */ - -/* AsTime(axis). */ -/* ------------- */ - if ( nc = 0, - ( 1 == astSscanf( attrib, "astime(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - result = astTestAsTime( this, axis - 1 ); - -/* Equinox. */ -/* -------- */ - } else if ( !strcmp( attrib, "equinox" ) ) { - result = astTestEquinox( this ); - -/* NegLon. */ -/* ------- */ - } else if ( !strcmp( attrib, "neglon" ) ) { - result = astTestNegLon( this ); - -/* SkyTol. */ -/* ------- */ - } else if ( !strcmp( attrib, "skytol" ) ) { - result = astTestSkyTol( this ); - -/* Projection. */ -/* ----------- */ - } else if ( !strcmp( attrib, "projection" ) ) { - result = astTestProjection( this ); - -/* SkyRefIs. */ -/* --------- */ - } else if ( !strcmp( attrib, "skyrefis" ) ) { - result = astTestSkyRefIs( this ); - -/* SkyRef. */ -/* ------- */ - } else if ( !strcmp( attrib, "skyref" ) ) { - result = astTestSkyRef( this, 0 ) || astTestSkyRef( this, 1 ); - -/* SkyRef(axis). */ -/* ------------- */ - } else if ( nc = 0, - ( 1 == astSscanf( attrib, "skyref(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - result = astTestSkyRef( this, axis - 1 ); - -/* SkyRefP. */ -/* -------- */ - } else if ( !strcmp( attrib, "skyrefp" ) ) { - result = astTestSkyRefP( this, 0 ) || astTestSkyRefP( this, 1 ); - -/* SkyRefP(axis). */ -/* ------------- */ - } else if ( nc = 0, - ( 1 == astSscanf( attrib, "skyrefp(%d)%n", &axis, &nc ) ) - && ( nc >= len ) ) { - result = astTestSkyRefP( this, axis - 1 ); - -/* AlignOffset */ -/* ----------- */ - } else if ( !strcmp( attrib, "alignoffset" ) ) { - result = astTestAlignOffset( this ); - -/* 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 ( !strncmp( attrib, "islataxis", 9 ) || - !strncmp( attrib, "islonaxis", 9 ) || - !strcmp( attrib, "lataxis" ) || - !strcmp( attrib, "lonaxis" ) ) { - result = 0; - -/* If the attribute is 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 TestSlaUnit( AstSkyFrame *sf1, AstSkyFrame *sf2, AstSlaMap *slamap, - int *status ){ -/* -* Name: -* Unformat - -* Purpose: -* See if a slamap is effectively a unit mapping. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int TestSlaUnit( AstSkyFrame *sf1, AstSkyFrame *sf2, AstSlaMap *slamap, -* int *status ) - -* Class Membership: -* SkyFrame member function. - -* Description: -* This function tests a SlaMap to see if it is effectively a unit -* transformatuon to within a tolerance given by the smaller tolerance -* of the two supplied SkyFrames. - -* Parameters: -* sf1 -* Pointer to the first SkyFrame. -* sf2 -* Pointer to the second SkyFrame (may be NULL) -* slamap -* Pointer to the SlaMap to test. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* Non-zero if the SlaMap is effectively a unit mapping, and zero -* otherwise. - -*/ - -/* Number of test points. */ -#define NTEST 14 - -/* Local Variables: */ - double maxshift; /* Max. shift produced by slamap (rads) */ - double olat[NTEST]; /* Transformed latitudes */ - double olon[NTEST]; /* Transformed longitudes */ - double shift; /* Shift produced by slamap (rads) */ - double tol2; /* Second tolerance (in radians) */ - double tol; /* Used tolerance (in radians) */ - int i; /* Loop count */ - int result; /* Returned flag */ - -/* A grid of lon/lat points covering the sphere. */ - double lat[ NTEST ] = { 0.0, 0.0, 0.0, 0.0, - 0.8, 0.8, 0.8, 0.8, - -0.8, -0.8, -0.8, -0.8, - 1.570796, -1.570796 }; - double lon[ NTEST ] = { 0.0, 1.57, 3.14, 4.71, - 0.8, 2.37, 3.94, 5.51, - 0.8, 2.37, 3.94, 5.51, - 0.0, 0.0 }; - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* If the SlaMap is empty (i.e. has no conversions in it), then is it a - UnitMap. So save time by not transforming the test values. */ - if( astSlaIsEmpty( slamap ) ) { - result = 1; - -/* Otherwise, get the smaller of the tolerances associated with the - supplied SkyFrames, in radians. */ - } else { - tol = astGetSkyTol( sf1 ); - if( sf2 ) { - tol2 = astGetSkyTol( sf2 ); - if( tol2 < tol ) tol = tol2; - } - -/* If the tolerance is zero, there is no need to do the test. */ - if( tol > 0.0 ) { - -/* Transform the test point using the SlaMap. */ - astTran2( slamap, NTEST, lon, lat, 1, olon, olat ); - -/* Find the maximum shift produced by the SlaMap at any of the test - positions. Again, to avoid the slow-down produced by checking for - axis permutation, use palDsep rather than astDistance. */ - maxshift = 0.0; - for( i = 0; i < NTEST; i++ ) { - shift = palDsep( lon[ i ], lat[ i ], olon[ i ], olat[ i ] ); - if( shift > maxshift ) maxshift = shift; - } - -/* Convert the max shift to arc-seconds and do the check. */ - result = ( maxshift*AST__DR2D*3600 < tol ); - } - } - - return result; -} - -static int Unformat( AstFrame *this_frame, int axis, const char *string, - double *value, int *status ) { -/* -* Name: -* Unformat - -* Purpose: -* Read a formatted coordinate value for a SkyFrame axis. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* int Unformat( AstFrame *this, int axis, const char *string, -* double *value, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the public astUnformat -* method inherited from the Frame class). - -* Description: -* This function reads a formatted coordinate value for a SkyFrame -* axis (supplied as a string) and returns the equivalent numerical -* value as a double. It also returns the number of characters read -* from the string. - -* Parameters: -* this -* Pointer to the SkyFrame. -* axis -* The number of the SkyFrame axis for which the coordinate -* value is to be read (axis numbering starts at zero for the -* first axis). -* string -* Pointer to a constant null-terminated string containing the -* formatted coordinate value. -* value -* Pointer to a double in which the coordinate value read will -* be returned (in radians). -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The number of characters read from the string to obtain the -* coordinate value. - -* Notes: -* - Any white space at the beginning of the string will be -* skipped, as also will any trailing white space following the -* coordinate value read. The function's return value will reflect -* this. -* - A function value of zero (and no coordinate value) will be -* returned, without error, if the string supplied does not contain -* a suitably formatted value. -* - The string "<bad>" is recognised as a special case and will -* generate the value AST__BAD, without error. The test for this -* string is case-insensitive and permits embedded white space. -* - A function result of zero will be returned and no coordinate -* value will be returned via the "value" pointer if this function -* is invoked with the global error status set, or if it should -* fail for any reason. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - double coord; /* Coordinate value read */ - int format_set; /* Format attribute set? */ - int nc; /* Number of characters read */ - -/* Initialise. */ - nc = 0; - -/* Check the global error status. */ - if ( !astOK ) return nc; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_frame; - -/* Validate the axis index. */ - (void) astValidateAxis( this, axis, 1, "astUnformat" ); - -/* Determine if a Format value has been set for the axis and set a - temporary value if it has not. Use the GetFormat member function - for this class together with member functions inherited from the - parent class (rather than using the object's methods directly) - because if any of these methods have been over-ridden by a derived - class the Format string syntax may no longer be compatible with - this class. */ - format_set = (*parent_testformat)( this_frame, axis, status ); - if ( !format_set ) { - (*parent_setformat)( this_frame, axis, GetFormat( this_frame, axis, status ), status ); - } - -/* Use the Unformat member function inherited from the parent class to - read the coordinate value. */ - nc = (*parent_unformat)( this_frame, axis, string, &coord, status ); - -/* If necessary, clear any temporary Format value that was set above. */ - if ( !format_set ) (*parent_clearformat)( this_frame, axis, status ); - -/* If an error occurred, clear the number of characters read. */ - if ( !astOK ) { - nc = 0; - -/* Otherwise, if characters were read, return the coordinate value. */ - } else if ( nc ) { - *value = coord; - } - -/* Return the number of characters read. */ - return nc; -} - -static int ValidateSystem( AstFrame *this, AstSystemType system, const char *method, int *status ) { -/* -* -* Name: -* ValidateSystem - -* Purpose: -* Validate a value for a Frame's System attribute. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "frame.h" -* int ValidateSystem( AstFrame *this, AstSystemType system, -* const char *method, int *status ) - -* Class Membership: -* SkyFrame member function (over-rides the astValidateSystem method -* inherited from the Frame class). - -* Description: -* This function checks the validity of the supplied system value. -* If the value is valid, it is returned unchanged. Otherwise, an -* error is reported and a value of AST__BADSYSTEM is returned. - -* Parameters: -* this -* Pointer to the Frame. -* system -* The system value to be checked. -* method -* Pointer to a constant null-terminated character string -* containing the name of the method that invoked this function -* to validate an axis index. This method name is used solely -* for constructing error messages. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The validated system value. - -* Notes: -* - A value of AST__BADSYSTEM will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstSystemType result; /* Validated system value */ - -/* Initialise. */ - result = AST__BADSYSTEM; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* If the value is out of bounds, report an error. */ - if ( system < FIRST_SYSTEM || system > LAST_SYSTEM ) { - astError( AST__AXIIN, "%s(%s): Bad value (%d) given for the System " - "or AlignSystem attribute of a %s.", status, method, - astGetClass( this ), (int) system, astGetClass( this ) ); - -/* Otherwise, return the supplied value. */ - } else { - result = system; - } - -/* Return the result. */ - return result; -} - -static void VerifyMSMAttrs( AstSkyFrame *target, AstSkyFrame *result, - int which, const char *attrs, const char *method, int *status ) { -/* -* Name: -* VerifyMSMAttrs - -* Purpose: -* Verify that usable attribute values are available. - -* Type: -* Private function. - -* Synopsis: -* #include "skyframe.h" -* void VerifyMSMAttrs( AstSkyFrame *target, AstSkyFrame *result, -* int which, const char *attrs, const char *method, int *status ) - -* Class Membership: -* SkyFrame member function - -* Description: -* This function tests each attribute listed in "attrs". It returns -* without action if 1) an explicit value has been set for each attribute -* in the SkyFrame indicated by "which" or 2) the UseDefs attribute of the -* "which" SkyFrame is non-zero. -* -* If UseDefs is zero (indicating that default values should not be -* used for attributes), and any of the named attributes does not have -* an explicitly set value, then an error is reported. -* -* The displayed error message assumes that tjis function was called -* as part of the process of producing a Mapping from "target" to "result". - -* Parameters: -* target -* Pointer to the target SkyFrame. -* result -* Pointer to the result SkyFrame. -* which -* If 2, both the target and result SkyFrames are checked for the -* supplied attributes. If less than 2, only the target SkyFrame is -* checked. If greater than 2, only the result SkyFrame is checked. -* attrs -* A string holding a space separated list of attribute names. -* method -* A string holding the name of the calling method for use in error -* messages. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - const char *a; - const char *p; - const char *desc; - int len; - int set1; - int set2; - int state; - int usedef1; - int usedef2; - -/* Check inherited status */ - if( !astOK ) return; - -/* Get the UseDefs attributes of the two SkyFrames. */ - usedef1 = astGetUseDefs( target ); - usedef2 = astGetUseDefs( result ); - -/* If both SkyFrames have a non-zero value for its UseDefs attribute, then - all attributes are assumed to have usable values, since the defaults - will be used if no explicit value has been set. So we only need to do - any checks if UseDefs is zero for either SkyFrame. */ - if( !usedef1 || !usedef2 ) { - -/* Stop compiler warnings about uninitialised variables */ - a = NULL; - desc = NULL; - len = 0; - set1 = 0; - set2 = 0; - -/* Loop round the "attrs" string identifying the start and length of each - non-blank word in the string. */ - state = 0; - p = attrs; - while( 1 ) { - if( state == 0 ) { - if( !isspace( *p ) ) { - a = p; - len = 1; - state = 1; - } - } else { - if( isspace( *p ) || !*p ) { - -/* The end of a word has just been reached. Compare it to each known - attribute value. Get a flag indicating if the attribute has a set - value, and a string describing the attribute.*/ - if( len > 0 ) { - - if( !strncmp( "Equinox", a, len ) ) { - set1 = astTestEquinox( target ); - set2 = astTestEquinox( result ); - desc = "reference equinox"; - - } else if( !strncmp( "Dtai", a, len ) ) { - set1 = astTestDtai( target ); - set2 = astTestDtai( result ); - desc = "TAI-UTC correction"; - - } else if( !strncmp( "Dut1", a, len ) ) { - set1 = astTestDut1( target ); - set2 = astTestDut1( result ); - desc = "UT1-UTC correction"; - - } else if( !strncmp( "Epoch", a, len ) ) { - set1 = astTestEpoch( target ); - set2 = astTestEpoch( result ); - desc = "epoch of observation"; - - } else if( !strncmp( "ObsLon", a, len ) ) { - set1 = astTestObsLon( target ); - set2 = astTestObsLon( result ); - desc = "longitude of observer"; - - } else if( !strncmp( "ObsLat", a, len ) ) { - set1 = astTestObsLat( target ); - set2 = astTestObsLat( result ); - desc = "latitude of observer"; - - } else if( !strncmp( "ObsAlt", a, len ) ) { - set1 = astTestObsAlt( target ); - set2 = astTestObsAlt( result ); - desc = "altitude of observer"; - - } else { - astError( AST__INTER, "VerifyMSMAttrs(SkyFrame): " - "Unknown attribute name \"%.*s\" supplied (AST " - "internal programming error).", status, len, a ); - } - -/* If the attribute is not set in the target but should be, report an - error. */ - if( !usedef1 && !set1 && which < 3 ) { - astClearTitle( target ); - astClearTitle( result ); - astError( AST__NOVAL, "%s(%s): Cannot convert " - "celestial coordinates from %s to %s.", status, - method, astGetClass( target ), - astGetC( target, "Title" ), - astGetC( result, "Title" ) ); - astError( AST__NOVAL, "No value has been set for " - "the \"%.*s\" attribute (%s) in the input %s.", status, - len, a, desc, astGetClass( target ) ); - break; - } - -/* If the attribute is not set in the result but should be, report an - error. */ - if( !usedef2 && !set2 && which > 1 ) { - astClearTitle( target ); - astClearTitle( result ); - astError( AST__NOVAL, "%s(%s): Cannot convert " - "celestial coordinates from %s to %s.", status, - method, astGetClass( result ), - astGetC( target, "Title" ), - astGetC( result, "Title" ) ); - astError( AST__NOVAL, "No value has been set for " - "the \"%.*s\" attribute (%s) in the output %s.", status, - len, a, desc, astGetClass( result ) ); - break; - } - -/* Continue the word search algorithm. */ - } - len = 0; - state = 0; - } else { - len++; - } - } - if( !*(p++) ) break; - } - } -} - -/* Functions which access class attributes. */ -/* ---------------------------------------- */ -/* -*att++ -* Name: -* AlignOffset - -* Purpose: -* Align SkyFrames using the offset coordinate system? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean). - -* Description: -* This attribute is a boolean value which controls how a SkyFrame -* behaves when it is used (by -c astFindFrame or astConvert) as a template to match another (target) -f AST_FINDFRAME or AST_CONVERT) as a template to match another (target) -* SkyFrame. It determines the coordinate system in which the two -* SkyFrames are aligned if a match occurs. -* -* If the template and target SkyFrames both have defined offset coordinate -* systems (i.e. the SkyRefIs attribute is set to either "Origin" or " -* Pole"), and they both have a non-zero value for AlignOffset, then -* alignment occurs within the offset coordinate systems (that is, a -* UnitMap will always be used to align the two SkyFrames). If either -* the template or target SkyFrame has zero (the default value) for -* AlignOffset, or if either SkyFrame has SkyRefIs set to "Ignored", then -* alignment occurring within the coordinate system specified by the -* AlignSystem attribute. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. -*att-- -*/ -astMAKE_CLEAR(SkyFrame,AlignOffset,alignoffset,-INT_MAX) -astMAKE_GET(SkyFrame,AlignOffset,int,0,( ( this->alignoffset != -INT_MAX ) ? - this->alignoffset : 0 )) -astMAKE_SET(SkyFrame,AlignOffset,int,alignoffset,( value != 0 )) -astMAKE_TEST(SkyFrame,AlignOffset,( this->alignoffset != -INT_MAX )) - -/* -*att++ -* Name: -* AsTime(axis) - -* Purpose: -* Format celestal coordinates as times? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean). - -* Description: -* This attribute specifies the default style of formatting to be -c used (e.g. by astFormat) for the celestial coordinate values -f used (e.g. by AST_FORMAT) for the celestial coordinate values -* described by a SkyFrame. It takes a separate boolean value for -* each SkyFrame axis so that, for instance, the setting -* "AsTime(2)=0" specifies the default formatting style for -* celestial latitude values. -* -* If the AsTime attribute for a SkyFrame axis is zero, then -* coordinates on that axis will be formatted as angles by default -* (using degrees, minutes and seconds), otherwise they will be -* formatted as times (using hours, minutes and seconds). -* -* The default value of AsTime is chosen according to the sky -* coordinate system being represented, as determined by the -* SkyFrame's System attribute. This ensures, for example, that -* right ascension values will be formatted as times by default, -* following normal conventions. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. - -* Notes: -* - The AsTime attribute operates by changing the default value of -* the corresponding Format(axis) attribute. This, in turn, may -* also affect the value of the Unit(axis) attribute. -* - Only the default style of formatting is affected by the AsTime -* value. If an explicit Format(axis) value is set, it will -* over-ride any effect from the AsTime attribute. -*att-- -*/ - -/* -*att++ -* Name: -* Equinox - -* Purpose: -* Epoch of the mean equinox. - -* Type: -* Public attribute. - -* Synopsis: -* Floating point. - -* Description: -* This attribute is used to qualify those celestial coordinate -* systems described by a SkyFrame which are notionally based on -* the ecliptic (the plane of the Earth's orbit around the Sun) -* and/or the Earth's equator. -* -* Both of these planes are in motion and their positions are -* difficult to specify precisely. In practice, therefore, a model -* ecliptic and/or equator are used instead. These, together with -* the point on the sky that defines the coordinate origin (the -* intersection of the two planes termed the "mean equinox") move -* with time according to some model which removes the more rapid -* fluctuations. The SkyFrame class supports both the FK4 and -* FK5 models. -* -* The position of a fixed source expressed in any of these -* coordinate systems will appear to change with time due to -* movement of the coordinate system itself (rather than motion of -* the source). Such coordinate systems must therefore be -* qualified by a moment in time (the "epoch of the mean equinox" -* or "equinox" for short) which allows the position of the model -* coordinate system on the sky to be determined. This is the role -* of the Equinox attribute. -* -* The Equinox attribute is stored as a Modified Julian Date, but -* when setting or getting its value you may use the same formats -* as for the Epoch attribute (q.v.). -* -* The default Equinox value is B1950.0 (Besselian) for the old -* FK4-based coordinate systems (see the System attribute) and -* J2000.0 (Julian) for all others. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. - -* Notes: -* - Care must be taken to distinguish the Equinox value, which -* relates to the definition of a time-dependent coordinate system -* (based on solar system reference planes which are in motion), -* from the superficially similar Epoch value. The latter is used -* to qualify coordinate systems where the positions of sources -* change with time (or appear to do so) for a variety of other -* reasons, such as aberration of light caused by the observer's -* motion, etc. -* - See the description of the System attribute for details of -* which qualifying attributes apply to each celestial coordinate -* system. -*att-- -*/ -/* Clear the Equinox value by setting it to AST__BAD. */ -astMAKE_CLEAR(SkyFrame,Equinox,equinox,AST__BAD) - -/* Provide a default value of B1950.0 or J2000.0 depending on the System - setting. */ -astMAKE_GET(SkyFrame,Equinox,double,AST__BAD,( - ( this->equinox != AST__BAD ) ? this->equinox : - ( ( ( astGetSystem( this ) == AST__FK4 ) || - ( astGetSystem( this ) == AST__FK4_NO_E ) ) ? - palEpb2d( 1950.0 ) : palEpj2d( 2000.0 ) ) )) - -/* Allow any Equinox value to be set, unless the System is Helio-ecliptic - (in which case clear the value so that J2000 is used). */ -astMAKE_SET(SkyFrame,Equinox,double,equinox,((astGetSystem(this)!=AST__HELIOECLIPTIC)?value:AST__BAD)) - -/* An Equinox value is set if it is not equal to AST__BAD. */ -astMAKE_TEST(SkyFrame,Equinox,( this->equinox != AST__BAD )) - - -/* -*att++ -* Name: -* IsLatAxis(axis) - -* Purpose: -* Is the specified celestial axis a latitude axis? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean), read-only. - -* Description: -* This is a read-only boolean attribute that indicates the nature of -* the specified axis. The attribute has a non-zero value if the -* specified axis is a celestial latitude axis (Declination, Galactic -* latitude, etc), and is zero otherwise. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. - -* Notes: -* - When specifying this attribute by name, it should be -* subscripted with the number of the SkyFrame axis to be tested. -*att-- -*/ - -/* -*att++ -* Name: -* IsLonAxis(axis) - -* Purpose: -* Is the specified celestial axis a longitude axis? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean), read-only. - -* Description: -* This is a read-only boolean attribute that indicates the nature of -* the specified axis. The attribute has a non-zero value if the -* specified axis is a celestial longitude axis (Right Ascension, Galactic -* longitude, etc), and is zero otherwise. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. - -* Notes: -* - When specifying this attribute by name, it should be -* subscripted with the number of the SkyFrame axis to be tested. -*att-- -*/ - -/* -*att++ -* Name: -* LatAxis - -* Purpose: -* Index of the latitude axis. - -* Type: -* Public attribute. - -* Synopsis: -* Integer. - -* Description: -* This read-only attribute gives the index (1 or 2) of the latitude -* axis within the SkyFrame (taking into account any current axis -* permutations). - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. - -*att-- -*/ - -/* -*att++ -* Name: -* LonAxis - -* Purpose: -* Index of the longitude axis. - -* Type: -* Public attribute. - -* Synopsis: -* Integer. - -* Description: -* This read-only attribute gives the index (1 or 2) of the longitude -* axis within the SkyFrame (taking into account any current axis -* permutations). - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. - -*att-- -*/ - -/* -*att++ -* Name: -* NegLon - -* Purpose: -* Display negative longitude values? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean). - -* Description: -* This attribute is a boolean value which controls how longitude values -c are normalized for display by astNorm. -f are normalized for display by AST_NORM. -* -* If the NegLon attribute is zero, then normalized -* longitude values will be in the range zero to 2.pi. If NegLon is -* non-zero, then normalized longitude values will be in the range -pi -* to pi. -* -* The default value depends on the current value of the SkyRefIs -* attribute, If SkyRefIs has a value of "Origin", then the default for -* NegLon is one, otherwise the default is zero. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. -*att-- -*/ -/* Clear the NegLon value by setting it to -INT_MAX. */ -astMAKE_CLEAR(SkyFrame,NegLon,neglon,-INT_MAX) - -/* Supply a default of 0 for absolute coords and 1 for offset coords if - no NegLon value has been set. */ -astMAKE_GET(SkyFrame,NegLon,int,0,( ( this->neglon != -INT_MAX ) ? -this->neglon : (( astGetSkyRefIs( this ) == AST__ORIGIN_REF )? 1 : 0))) - -/* Set a NegLon value of 1 if any non-zero value is supplied. */ -astMAKE_SET(SkyFrame,NegLon,int,neglon,( value != 0 )) - -/* The NegLon value is set if it is not -INT_MAX. */ -astMAKE_TEST(SkyFrame,NegLon,( this->neglon != -INT_MAX )) - -/* -*att++ -* Name: -* SkyTol - -* Purpose: -* The smallest significant shift in sky coordinates. - -* Type: -* Public attribute. - -* Synopsis: -* Floating point. - -* Description: -* This attribute indicates the accuracy of the axis values that will -* be represented by the SkyFrame. If the arc-distance between two -* positions within the SkyFrame is smaller than the value of SkyTol, -* then the two positions will (for the puposes indicated below) be -* considered to be co-incident. -* -* This value is used only when constructing the Mapping between -* two different SkyFrames (for instance, when calling -c astConvert or astFindFrame). -f AST_CONVERT or AST_FINDFRAME). -* If the transformation between the two SkyFrames causes positions to -* shift by less than SkyTol arc-seconds, then the transformation is -* replaced by a UnitMap. This could in certain circumatances allow -* major simplifications to be made to the transformation between -* any pixel grids associated with the two SkyFrames (for instance, if -* each SkyFrame is part of the WCS FrameSet associated with an image). -* -* A common case is when two SkyFrames use the FK5 system, but have -* slightly different Epoch values. If the AlignSystem attribute has -* its default value of "ICRS", then the transformation between the -* two SkyFrames will include a very small rotation (FK5 rotates with -* respect to ICRS as a rate of about 0.0005 arc-seconds per year). In -* most circumstances such a small rotation is insignificant. Setting -* SkyTol to some suitably small non-zero value will cause this -* rotation to be ignored, allowing much simpler transformations to -* be used. -* -* The test to determine the shift introduced by transforming between -* the two SkyFrames is performed by transforming a set of 14 position -* spread evenly over the whole sky. The largest shift produced at any -* of these 14 positions is compared to the value of SkyTol. -* -* The SkyTol value is in units of arc-seconds, and the default value -* is 0.001. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. -*att-- -*/ -astMAKE_CLEAR(SkyFrame,SkyTol,skytol,AST__BAD) -astMAKE_GET(SkyFrame,SkyTol,double,0.001,((this->skytol!=AST__BAD)?this->skytol:0.001)) -astMAKE_SET(SkyFrame,SkyTol,double,skytol,fabs(value)) -astMAKE_TEST(SkyFrame,SkyTol,(this->skytol!=AST__BAD)) - -/* -*att++ -* Name: -* Projection - -* Purpose: -* Sky projection description. - -* Type: -* Public attribute. - -* Synopsis: -* String. - -* Description: -* This attribute provides a place to store a description of the -* type of sky projection used when a SkyFrame is attached to a -* 2-dimensional object, such as an image or plotting surface. For -* example, typical values might be "orthographic", "Hammer-Aitoff" -* or "cylindrical equal area". -* -* The Projection value is purely descriptive and does not affect -* the celestial coordinate system represented by the SkyFrame in -* any way. If it is set to a non-blank string, the description -* provided may be used when forming the default value for the -* SkyFrame's Title attribute (so that typically it will appear in -* graphical output, for instance). The default value is an empty -* string. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. -*att-- -*/ -/* Clear the Projection value by freeing the allocated memory and - assigning a NULL pointer. */ -astMAKE_CLEAR(SkyFrame,Projection,projection,astFree( this->projection )) - -/* If the Projection value is not set, return a pointer to an empty - string. */ -astMAKE_GET(SkyFrame,Projection,const char *,NULL,( this->projection ? - this->projection : "" )) - -/* Set a Projection value by freeing any previously allocated memory, - allocating new memory, storing the string and saving the pointer to - the copy. */ -astMAKE_SET(SkyFrame,Projection,const char *,projection,astStore( - this->projection, value, strlen( value ) + (size_t) 1 )) - -/* The Projection value is set if the pointer to it is not NULL. */ -astMAKE_TEST(SkyFrame,Projection,( this->projection != NULL )) - -/* -*att++ -* Name: -* SkyRefIs - -* Purpose: -* Selects the nature of the offset coordinate system. - -* Type: -* Public attribute. - -* Synopsis: -* String. - -* Description: -* This attribute controls how the values supplied for the SkyRef and -* SkyRefP attributes are used. These three attributes together allow -* a SkyFrame to represent offsets relative to some specified origin -* or pole within the coordinate system specified by the System attribute, -* rather than absolute axis values. SkyRefIs can take one of the -* case-insensitive values "Origin", "Pole" or "Ignored". -* -* If SkyRefIs is set to "Origin", then the coordinate system -* represented by the SkyFrame is modified to put the origin of longitude -* and latitude at the position specified by the SkyRef attribute. -* -* If SkyRefIs is set to "Pole", then the coordinate system represented -* by the SkyFrame is modified to put the north pole at the position -* specified by the SkyRef attribute. -* -* If SkyRefIs is set to "Ignored" (the default), then any value set for the -* SkyRef attribute is ignored, and the SkyFrame represents the coordinate -* system specified by the System attribute directly without any rotation. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. - -*att-- -*/ -astMAKE_CLEAR(SkyFrame,SkyRefIs,skyrefis,AST__BAD_REF) -astMAKE_SET(SkyFrame,SkyRefIs,int,skyrefis,value) -astMAKE_TEST(SkyFrame,SkyRefIs,( this->skyrefis != AST__BAD_REF )) -astMAKE_GET(SkyFrame,SkyRefIs,int,AST__IGNORED_REF,(this->skyrefis == AST__BAD_REF ? AST__IGNORED_REF : this->skyrefis)) - -/* -*att++ -* Name: -* SkyRef(axis) - -* Purpose: -* Position defining the offset coordinate system. - -* Type: -* Public attribute. - -* Synopsis: -* Floating point. - -* Description: -* This attribute allows a SkyFrame to represent offsets, rather than -* absolute axis values, within the coordinate system specified by the -* System attribute. If supplied, SkyRef should be set to hold the -* longitude and latitude of a point within the coordinate system -* specified by the System attribute. The coordinate system represented -* by the SkyFrame will then be rotated in order to put the specified -* position at either the pole or the origin of the new coordinate system -* (as indicated by the SkyRefIs attribute). The orientation of the -* modified coordinate system is then controlled using the SkyRefP -* attribute. -* -* If an integer axis index is included in the attribute name (e.g. -* "SkyRef(1)") then the attribute value should be supplied as a single -* floating point axis value, in radians, when setting a value for the -* attribute, and will be returned in the same form when getting the value -* of the attribute. In this case the integer axis index should be "1" -* or "2" (the values to use for longitude and latitude axes are -* given by the LonAxis and LatAxis attributes). -* -* If no axis index is included in the attribute name (e.g. "SkyRef") then -* the attribute value should be supplied as a character string -* containing two formatted axis values (an axis 1 value followed by a -* comma, followed by an axis 2 value). The same form -* will be used when getting the value of the attribute. -* -* The default values for SkyRef are zero longitude and zero latitude. - -* Aligning SkyFrames with Offset Coordinate Systems: -* The offset coordinate system within a SkyFrame should normally be -* considered as a superficial "re-badging" of the axes of the coordinate -* system specified by the System attribute - it merely provides an -* alternative numerical "label" for each position in the System coordinate -* system. The SkyFrame retains full knowledge of the celestial coordinate -* system on which the offset coordinate system is based (given by the -* System attribute). For instance, the SkyFrame retains knowledge of the -* way that one celestial coordinate system may "drift" with respect to -* another over time. Normally, if you attempt to align two SkyFrames (e.g. -f using the AST_CONVERT or AST_FINDFRAME routine), -c using the astConvert or astFindFrame routine), -* the effect of any offset coordinate system defined in either SkyFrame -* will be removed, resulting in alignment being performed in the -* celestial coordinate system given by the AlignSystem attribute. -* However, by setting the AlignOffset attribute to a non-zero value, it -* is possible to change this behaviour so that the effect of the offset -* coordinate system is not removed when aligning two SkyFrames. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. - -* Notes: -* - If the System attribute of the SkyFrame is changed, any position -* given for SkyRef is transformed into the new System. -* - If a value has been assigned to SkyRef attribute, then -* the default values for certain attributes are changed as follows: -* the default axis Labels for the SkyFrame are modified by appending -* " offset" to the end, the default axis Symbols for the SkyFrame are -* modified by prepending the character "D" to the start, and the -* default title is modified by replacing the projection information by the -* origin information. - -*att-- -*/ -MAKE_CLEAR(SkyRef,skyref,AST__BAD,2) -MAKE_SET(SkyRef,double,skyref,value,2) -MAKE_TEST(SkyRef,( this->skyref[axis_p] != AST__BAD ),2) -MAKE_GET(SkyRef,double,0.0,((this->skyref[axis_p]!=AST__BAD)?this->skyref[axis_p]:0.0),2) - -/* -*att++ -* Name: -* SkyRefP(axis) - -* Purpose: -* Position on primary meridian of offset coordinate system. - -* Type: -* Public attribute. - -* Synopsis: -* Floating point. - -* Description: -* This attribute is used to control the orientation of the offset -* coordinate system defined by attributes SkyRef and SkyRefIs. If used, -* it should be set to hold the longitude and latitude of a point within -* the coordinate system specified by the System attribute. The offset -* coordinate system represented by the SkyFrame will then be rotated in -* order to put the position supplied for SkyRefP on the zero longitude -* meridian. This rotation is about an axis from the centre of the -* celestial sphere to the point specified by the SkyRef attribute. -* The default value for SkyRefP is usually the north pole (that is, a -* latitude of +90 degrees in the coordinate system specified by the System -* attribute). The exception to this is if the SkyRef attribute is -* itself set to either the north or south pole. In these cases the -* default for SkyRefP is the origin (that is, a (0,0) in the coordinate -* system specified by the System attribute). -* -* If an integer axis index is included in the attribute name (e.g. -* "SkyRefP(1)") then the attribute value should be supplied as a single -* floating point axis value, in radians, when setting a value for the -* attribute, and will be returned in the same form when getting the value -* of the attribute. In this case the integer axis index should be "1" -* or "2" (the values to use for longitude and latitude axes are -* given by the LonAxis and LatAxis attributes). -* -* If no axis index is included in the attribute name (e.g. "SkyRefP") then -* the attribute value should be supplied as a character string -* containing two formatted axis values (an axis 1 value followed by a -* comma, followed by an axis 2 value). The same form -* will be used when getting the value of the attribute. - -* Applicability: -* SkyFrame -* All SkyFrames have this attribute. - -* Notes: -* - If the position given by the SkyRef attribute defines the origin -* of the offset coordinate system (that is, if the SkyRefIs attribute -* is set to "origin"), then there will in general be two orientations -* which will put the supplied SkyRefP position on the zero longitude -* meridian. The orientation which is actually used is the one which -* gives the SkyRefP position a positive latitude in the offset coordinate -* system (the other possible orientation would give the SkyRefP position -* a negative latitude). -* - An error will be reported if an attempt is made to use a -* SkyRefP value which is co-incident with SkyRef or with the point -* diametrically opposite to SkyRef on the celestial sphere. The -* reporting of this error is deferred until the SkyRef and SkyRefP -* attribute values are used within a calculation. -* - If the System attribute of the SkyFrame is changed, any position -* given for SkyRefP is transformed into the new System. - -*att-- -*/ -MAKE_CLEAR(SkyRefP,skyrefp,AST__BAD,2) -MAKE_SET(SkyRefP,double,skyrefp,value,2) -MAKE_TEST(SkyRefP,( this->skyrefp[axis_p] != AST__BAD ),2) - -/* Copy constructor. */ -/* ----------------- */ -static void Copy( const AstObject *objin, AstObject *objout, int *status ) { -/* -* Name: -* Copy - -* Purpose: -* Copy constructor for SkyFrame objects. - -* Type: -* Private function. - -* Synopsis: -* void Copy( const AstObject *objin, AstObject *objout, int *status ) - -* Description: -* This function implements the copy constructor for SkyFrame objects. - -* Parameters: -* objin -* Pointer to the object to be copied. -* objout -* Pointer to the object being constructed. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This constructor makes a deep copy. -*/ - -/* Local Variables: */ - AstSkyFrame *in; /* Pointer to input SkyFrame */ - AstSkyFrame *out; /* Pointer to output SkyFrame */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain pointers to the input and output SkyFrames. */ - in = (AstSkyFrame *) objin; - out = (AstSkyFrame *) objout; - -/* For safety, first clear any references to the input memory from - the output SkyFrame. */ - out->projection = NULL; - -/* If necessary, allocate memory in the output SkyFrame and store a - copy of the input Projection string. */ - if ( in->projection ) out->projection = astStore( NULL, in->projection, - strlen( in->projection ) + (size_t) 1 ); - -/* If an error occurred, free any allocated memory. */ - if ( !astOK ) { - out->projection = astFree( out->projection ); - } -} - -/* Destructor. */ -/* ----------- */ -static void Delete( AstObject *obj, int *status ) { -/* -* Name: -* Delete - -* Purpose: -* Destructor for SkyFrame objects. - -* Type: -* Private function. - -* Synopsis: -* void Delete( AstObject *obj, int *status ) - -* Description: -* This function implements the destructor for SkyFrame objects. - -* Parameters: -* obj -* Pointer to the object to be deleted. -* status -* Pointer to the inherited status variable. - -* Notes: -* This function attempts to execute even if the global error status is -* set. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to SkyFrame */ - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) obj; - -/* Free the memory used for the Projection string if necessary. */ - this->projection = astFree( this->projection ); -} - -/* Dump function. */ -/* -------------- */ -static void Dump( AstObject *this_object, AstChannel *channel, int *status ) { -/* -* Name: -* Dump - -* Purpose: -* Dump function for SkyFrame 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 SkyFrame class to an output Channel. - -* Parameters: -* this -* Pointer to the SkyFrame whose data are being written. -* channel -* Pointer to the Channel to which the data are being written. -* status -* Pointer to the inherited status variable. -*/ - -/* Local Variables: */ - AstSkyFrame *this; /* Pointer to the SkyFrame structure */ - AstSystemType system; /* System attribute value */ - char buf[ 100 ]; /* Comment buffer */ - char key[ 10 ]; /* Buffer for keywords */ - const char *sval; /* Pointer to string value */ - const int *perm; /* Pointer to axis permutation array */ - double dval; /* Double value */ - int bessyr; /* Use a Besselian year value ?*/ - int helpful; /* Helpful to display un-set value? */ - int invperm[ 2 ]; /* Inverse permutation array */ - int ival; /* Integer value */ - int set; /* Attribute value set? */ - int axis; /* External (i.e. permuted) zero-based axis index */ - int axis_p; /* Internal zero-based axis index */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain a pointer to the SkyFrame structure. */ - this = (AstSkyFrame *) this_object; - -/* Get a pointer to the SkyFrame's axis permutation array (using a method, - to allow for any over-ride by a derived class). */ - perm = astGetPerm( this ); - -/* Generate an inverse axis permutation array from the forward permutation - values. This will be used to determine which axis should be enquired - about (using possibly over-ridden methods) to obtain data to - correspond with a particular internal value (i.e. instance variable) - relating to an axis. This step is needed so that the effect of any - axis permutation can be un-done before values are written out, as - output values are written by this function in un-permuted order. */ - for ( axis = 0; axis < 2; axis++ ) invperm[ perm[ axis ] ] = axis; - -/* Write out values representing the instance variables for the - SkyFrame class. Accompany these with appropriate comment strings, - possibly depending on the values being written.*/ - -/* In the case of attributes, we first use the appropriate (private) - Test... member function to see if they are set. If so, we then use - the (private) Get... function to obtain the value to be written - out. - - For attributes which are not set, we use the astGet... method to - obtain the value instead. This will supply a default value - (possibly provided by a derived class which over-rides this method) - which is more useful to a human reader as it corresponds to the - actual default attribute value. Since "set" will be zero, these - values are for information only and will not be read back. */ - -/* Projection. */ -/* ----------- */ - set = TestProjection( this, status ); - sval = set ? GetProjection( this, status ) : astGetProjection( this ); - astWriteString( channel, "Proj", set, 0, sval, - "Description of sky projection" ); - -/* NegLon. */ -/* ------- */ - set = TestNegLon( this, status ); - ival = set ? GetNegLon( this, status ) : astGetNegLon( this ); - astWriteInt( channel, "NegLon", set, 0, ival, - ival ? "Display negative longitude values" : - "Display positive longitude values" ); - -/* SkyTol. */ -/* ------- */ - set = TestSkyTol( this, status ); - dval = set ? GetSkyTol( this, status ) : astGetSkyTol( this ); - astWriteDouble( channel, "SkyTol", set, 1, dval, - "Smallest significant separation [arc-sec]"); - -/* Equinox. */ -/* -------- */ - set = TestEquinox( this, status ); - dval = set ? GetEquinox( this, status ) : astGetEquinox( this ); - -/* Decide whether the Equinox value is relevant to the current - coordinate system. */ - system = astGetSystem( this ); - helpful = ( ( system == AST__FK4 ) || - ( system == AST__FK4_NO_E ) || - ( system == AST__FK5 ) || - ( system == AST__ECLIPTIC ) ); - -/* Convert MJD to Besselian or Julian years, depending on the value. */ - bessyr = ( dval < palEpj2d( 1984.0 ) ); - dval = bessyr ? palEpb( dval ) : palEpj( dval ); - astWriteDouble( channel, "Eqnox", set, helpful, dval, - bessyr ? "Besselian epoch of mean equinox" : - "Julian epoch of mean equinox" ); - -/* SkyRefIs. */ -/* --------- */ - set = TestSkyRefIs( this, status ); - ival = set ? GetSkyRefIs( this, status ) : astGetSkyRefIs( this ); - if( ival == AST__POLE_REF ) { - astWriteString( channel, "SRefIs", set, 0, POLE_STRING, - "Rotated to put pole at ref. pos." ); - - } else if( ival == AST__IGNORED_REF ) { - astWriteString( channel, "SRefIs", set, 0, IGNORED_STRING, - "Not rotated (ref. pos. is ignored)" ); - - } else { - astWriteString( channel, "SRefIs", set, 0, ORIGIN_STRING, - "Rotated to put origin at ref. pos." ); - } - -/* SkyRef. */ -/* ------- */ -/* The inverse axis permutation array is used to obtain the axis index - to use when accessing the SkyRef attribute. This reverses the effect - of the SkyFrame's axis permutation array and yields a value appropriate - to the axis with internal index "axis". */ - for ( axis_p = 0; axis_p < 2; axis_p++ ) { - axis = invperm[ axis_p ]; - - set = TestSkyRef( this, axis, status ); - dval = set ? GetSkyRef( this, axis, status ) : astGetSkyRef( this, axis ); - sprintf( buf, "Ref. pos. %s %s", astGetSymbol( this, axis ), - astFormat( this, axis, dval ) ); - sprintf( key, "SRef%d", axis_p + 1 ); - astWriteDouble( channel, key, set, 0, dval, buf ); - } - -/* SkyRefP. */ -/* -------- */ - for ( axis_p = 0; axis_p < 2; axis_p++ ) { - axis = invperm[ axis_p ]; - - set = TestSkyRefP( this, axis, status ); - dval = set ? GetSkyRefP( this, axis, status ) : astGetSkyRefP( this, axis ); - sprintf( buf, "Ref. north %s %s", astGetSymbol( this, axis ), - astFormat( this, axis, dval ) ); - sprintf( key, "SRefP%d", axis_p + 1 ); - astWriteDouble( channel, key, set, 0, dval, buf ); - } - -/* AlignOffset. */ -/* ------------ */ - set = TestAlignOffset( this, status ); - ival = set ? GetAlignOffset( this, status ) : astGetAlignOffset( this ); - astWriteInt( channel, "AlOff", set, 0, ival, - ival ? "Align in offset coords" : - "Align in system coords" ); -} - -/* Standard class functions. */ -/* ========================= */ -/* Implement the astIsASkyFrame and astCheckSkyFrame functions using the macros - defined for this purpose in the "object.h" header file. */ -astMAKE_ISA(SkyFrame,Frame) -astMAKE_CHECK(SkyFrame) - -AstSkyFrame *astSkyFrame_( const char *options, int *status, ...) { -/* -*+ -* Name: -* astSkyFrame - -* Purpose: -* Create a SkyFrame. - -* Type: -* Protected function. - -* Synopsis: -* #include "skyframe.h" -* AstSkyFrame *astSkyFrame( const char *options, int *status, ... ) - -* Class Membership: -* SkyFrame constructor. - -* Description: -* This function creates a new SkyFrame and optionally initialises its -* attributes. - -* Parameters: -* options -* Pointer to a null terminated string containing an optional -* comma-separated list of attribute assignments to be used for -* initialising the new SkyFrame. The syntax used is the same as for the -* astSet method and may include "printf" format specifiers identified -* by "%" symbols in the normal way. -* status -* Pointer to the inherited status variable. -* ... -* If the "options" string contains "%" format specifiers, then an -* optional list of arguments may follow it in order to supply values to -* be substituted for these specifiers. The rules for supplying these -* are identical to those for the astSet method (and for the C "printf" -* function). - -* Returned Value: -* A pointer to the new SkyFrame. - -* Notes: -* - A NULL pointer will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*- - -* Implementation Notes: -* - This function implements the basic SkyFrame constructor which -* is available via the protected interface to the SkyFrame class. -* A public interface is provided by the astSkyFrameId_ function. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstSkyFrame *new; /* Pointer to new SkyFrame */ - va_list args; /* Variable argument list */ - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(NULL); - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* Initialise the SkyFrame, allocating memory and initialising the virtual - function table as well if necessary. */ - new = astInitSkyFrame( NULL, sizeof( AstSkyFrame ), !class_init, &class_vtab, - "SkyFrame" ); - -/* 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 SkyFrame'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 SkyFrame. */ - return new; -} - -AstSkyFrame *astInitSkyFrame_( void *mem, size_t size, int init, - AstSkyFrameVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitSkyFrame - -* Purpose: -* Initialise a SkyFrame. - -* Type: -* Protected function. - -* Synopsis: -* #include "skyframe.h" -* AstSkyFrame *astInitSkyFrame( void *mem, size_t size, int init, -* AstFrameVtab *vtab, const char *name ) - -* Class Membership: -* SkyFrame initialiser. - -* Description: -* This function is provided for use by class implementations to initialise -* a new SkyFrame object. It allocates memory (if necessary) to accommodate -* the SkyFrame plus any additional data associated with the derived class. -* It then initialises a SkyFrame 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 SkyFrame at the start of the memory passed via the -* "vtab" parameter. - -* Parameters: -* mem -* A pointer to the memory in which the SkyFrame is to be created. This -* must be of sufficient size to accommodate the SkyFrame data -* (sizeof(SkyFrame)) 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 SkyFrame (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 SkyFrame -* structure, so a valid value must be supplied even if not required for -* allocating memory. -* init -* A logical flag indicating if the SkyFrame'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 SkyFrame. -* 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). - -* Returned Value: -* A pointer to the new SkyFrame. - -* 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: */ - AstSkyAxis *ax; /* Pointer to SkyAxis object */ - AstSkyFrame *new; /* Pointer to the new SkyFrame */ - int axis; /* Loop counter for axes */ - -/* Check the global status. */ - if ( !astOK ) return NULL; - -/* If necessary, initialise the virtual function table. */ - if ( init ) astInitSkyFrameVtab( vtab, name ); - -/* Initialise a Frame structure (the parent class) as the first component - within the SkyFrame structure, allocating memory if necessary. */ - new = (AstSkyFrame *) astInitFrame( mem, size, 0, - (AstFrameVtab *) vtab, name, 2 ); - - if ( astOK ) { - -/* Initialise the SkyFrame data. */ -/* ----------------------------- */ -/* Initialise all attributes to their "undefined" values. */ - new->equinox = AST__BAD; - new->projection = NULL; - new->neglon = -INT_MAX; - new->skytol = AST__BAD; - new->alignoffset = -INT_MAX; - new->skyrefis = AST__BAD_REF; - new->skyref[ 0 ] = AST__BAD; - new->skyref[ 1 ] = AST__BAD; - new->skyrefp[ 0 ] = AST__BAD; - new->skyrefp[ 1 ] = AST__BAD; - new->last = AST__BAD; - new->eplast = AST__BAD; - new->klast = AST__BAD; - new->diurab = AST__BAD; - -/* Loop to replace the Axis object associated with each SkyFrame axis with - a SkyAxis object instead. */ - for ( axis = 0; axis < 2; axis++ ) { - -/* Create the new SkyAxis, assign it to the required SkyFrame axis and then - annul the SkyAxis pointer. */ - ax = astSkyAxis( "", status ); - astSetAxis( new, axis, ax ); - ax = astAnnul( ax ); - } - -/* If an error occurred, clean up by deleting the new object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return a pointer to the new object. */ - return new; -} - -AstSkyFrame *astLoadSkyFrame_( void *mem, size_t size, - AstSkyFrameVtab *vtab, const char *name, - AstChannel *channel, int *status ) { -/* -*+ -* Name: -* astLoadSkyFrame - -* Purpose: -* Load a SkyFrame. - -* Type: -* Protected function. - -* Synopsis: -* #include "skyframe.h" -* AstSkyFrame *astLoadSkyFrame( void *mem, size_t size, -* AstSkyFrameVtab *vtab, const char *name, -* AstChannel *channel ) - -* Class Membership: -* SkyFrame loader. - -* Description: -* This function is provided to load a new SkyFrame 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 -* SkyFrame structure in this memory, using data read from the -* input Channel. - -* Parameters: -* mem -* A pointer to the memory into which the SkyFrame is to be -* loaded. This must be of sufficient size to accommodate the -* SkyFrame data (sizeof(SkyFrame)) 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 SkyFrame (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 SkyFrame 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(AstSkyFrame) is used instead. -* vtab -* Pointer to the start of the virtual function table to be -* associated with the new SkyFrame. If this is NULL, a pointer -* to the (static) virtual function table for the SkyFrame 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 "SkyFrame" is used instead. - -* Returned Value: -* A pointer to the new SkyFrame. - -* 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: */ - AstSkyFrame *new; /* Pointer to the new SkyFrame */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - char *sval; /* Pointer to string value */ - const int *perm; /* Pointer to axis permutation array */ - double dval; /* Floating point attribute value */ - int axis; /* External axis index */ - int invperm[ 2 ]; /* Inverse permutation array */ - -/* Initialise. */ - new = NULL; - -/* Get a pointer to the thread specific global data structure. */ - astGET_GLOBALS(channel); - -/* 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 SkyFrame. In this case the - SkyFrame belongs to this class, so supply appropriate values to be - passed to the parent class loader (and its parent, etc.). */ - if ( !vtab ) { - size = sizeof( AstSkyFrame ); - vtab = &class_vtab; - name = "SkyFrame"; - -/* If required, initialise the virtual function table for this class. */ - if ( !class_init ) { - astInitSkyFrameVtab( 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 SkyFrame. */ - new = astLoadFrame( mem, size, (AstFrameVtab *) vtab, name, - channel ); - - if ( astOK ) { - -/* Get a pointer to the SkyFrame's axis permutation array (using a method, - to allow for any over-ride by a derived class). */ - perm = astGetPerm( new ); - -/* Generate an inverse axis permutation array from the forward permutation - values. This will be used to determine which axis should be enquired - about (using possibly over-ridden methods) to obtain data to - correspond with a particular internal value (i.e. instance variable) - relating to an axis. This step is needed so that the effect of any - axis permutation can be un-done before values are written out, as - output values are written by this function in un-permuted order. */ - for( axis = 0; axis < 2; axis++ ) invperm[ perm[ axis ] ] = axis; - -/* Read input data. */ -/* ================ */ -/* Request the input Channel to read all the input data appropriate to - this class into the internal "values list". */ - astReadClassData( channel, "SkyFrame" ); - -/* 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. */ - -/* The attributes defining the offset coordinate system must be loaded - before the System attrivbute, since SetSystem uses them. */ - -/* AlignOffset */ -/* ----------- */ - new->alignoffset = astReadInt( channel, "aloff", -INT_MAX ); - if ( TestAlignOffset( new, status ) ) SetAlignOffset( new, new->alignoffset, status ); - -/* SkyRefIs. */ -/* --------- */ - sval = astReadString( channel, "srefis", " " ); - if( sval ){ - new->skyrefis = AST__BAD_REF; - if( astChrMatch( sval, POLE_STRING ) ) { - new->skyrefis = AST__POLE_REF; - } else if( astChrMatch( sval, ORIGIN_STRING ) ) { - new->skyrefis = AST__ORIGIN_REF; - } else if( astChrMatch( sval, IGNORED_STRING ) ) { - new->skyrefis = AST__IGNORED_REF; - } else if( !astChrMatch( sval, " " ) && astOK ){ - astError( AST__INTER, "astRead(SkyFrame): Corrupt SkyFrame contains " - "invalid SkyRefIs attribute value (%s).", status, sval ); - } - if( TestSkyRefIs( new, status ) ) SetSkyRefIs( new, new->skyrefis, status ); - sval = astFree( sval ); - } - -/* SkyRef. */ -/* ------- */ - new->skyref[ 0 ] = astReadDouble( channel, "sref1", AST__BAD ); - axis = invperm[ 0 ]; - if ( TestSkyRef( new, axis, status ) ) SetSkyRef( new, axis, new->skyref[ 0 ], status ); - - new->skyref[ 1 ] = astReadDouble( channel, "sref2", AST__BAD ); - axis = invperm[ 1 ]; - if ( TestSkyRef( new, axis, status ) ) SetSkyRef( new, axis, new->skyref[ 1 ], status ); - -/* SkyRefP. */ -/* -------- */ - new->skyrefp[ 0 ] = astReadDouble( channel, "srefp1", AST__BAD ); - axis = invperm[ 0 ]; - if ( TestSkyRefP( new, axis, status ) ) SetSkyRefP( new, axis, new->skyrefp[ 0 ], status ); - - new->skyrefp[ 1 ] = astReadDouble( channel, "srefp2", AST__BAD ); - axis = invperm[ 1 ]; - if ( TestSkyRefP( new, axis, status ) ) SetSkyRefP( new, axis, new->skyrefp[ 1 ], status ); - -/* System. */ -/* ------- */ -/* The System attribute is now part of the Frame class, but this code is - retained to allow this version of AST to read SkyFrames dumped by - previous versions. */ - -/* Check a value has not already been assigned to the Frames System - attribute. */ - if( !astTestSystem( new ) ){ - -/* Read the external representation as a string. */ - sval = astReadString( channel, "system", NULL ); - -/* If a value was read, use the SetAttrib method to validate and store the - new value in the correct place, then free the string. */ - if ( sval ) { - astSet( new, "System=%s", status, sval); - sval = astFree( sval ); - } - } - -/* Epoch. */ -/* ------ */ -/* The Epoch attribute is now part of the Frame class, but this code is - retained to allow this version of AST to read SkyFrames dumped by - previous versions. */ - -/* Check a value has not already been assigned to the Frames Epoch - attribute. */ - if( !astTestEpoch( new ) ){ - -/* Get the value. */ - dval = astReadDouble( channel, "epoch", AST__BAD ); - -/* If a value was read, use the SetAttrib method to validate and store the - new value in the correct place. */ - if( dval != AST__BAD ) { - if( dval < 1984.0 ) { - astSet( new, "Epoch=B%.*g", status, AST__DBL_DIG, dval); - } else { - astSet( new, "Epoch=J%.*g", status, AST__DBL_DIG, dval); - } - } - } - -/* Projection. */ -/* ----------- */ - new->projection = astReadString( channel, "proj", NULL ); - -/* Equinox. */ -/* -------- */ -/* Interpret this as Besselian or Julian depending on its value. */ - new->equinox = astReadDouble( channel, "eqnox", AST__BAD ); - if ( TestEquinox( new, status ) ) { - SetEquinox( new, ( new->equinox < 1984.0 ) ? palEpb2d( new->equinox ) : - palEpj2d( new->equinox ), status ); - } - -/* NegLon. */ -/* ------- */ - new->neglon = astReadInt( channel, "neglon", -INT_MAX ); - if ( TestNegLon( new, status ) ) SetNegLon( new, new->neglon, status ); - -/* SkyTol. */ -/* ------- */ - new->skytol = astReadDouble( channel, "skytol", AST__BAD ); - if ( TestSkyTol( new, status ) ) SetSkyTol( new, new->skytol, status ); - -/* Other values */ -/* ------------ */ - new->last = AST__BAD; - new->eplast = AST__BAD; - new->klast = AST__BAD; - new->diurab = AST__BAD; - -/* If an error occurred, clean up by deleting the new SkyFrame. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return the new SkyFrame pointer. */ - return new; -} - -/* Virtual function interfaces. */ -/* ============================ */ -/* These provide the external interface to the virtual functions defined by - this class. Each simply checks the global error status and then locates and - executes the appropriate member function, using the function pointer stored - in the object's virtual function table (this pointer is located using the - astMEMBER macro defined in "object.h"). - - Note that the member function may not be the one defined here, as it may - have been over-ridden by a derived class. However, it should still have the - same interface. */ -void astClearAsTime_( AstSkyFrame *this, int axis, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,SkyFrame,ClearAsTime))( this, axis, status ); -} -int astGetAsTime_( AstSkyFrame *this, int axis, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,SkyFrame,GetAsTime))( this, axis, status ); -} -void astSetAsTime_( AstSkyFrame *this, int axis, int value, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,SkyFrame,SetAsTime))( this, axis, value, status ); -} -int astTestAsTime_( AstSkyFrame *this, int axis, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,SkyFrame,TestAsTime))( this, axis, status ); -} -int astGetIsLatAxis_( AstSkyFrame *this, int axis, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,SkyFrame,GetIsLatAxis))( this, axis, status ); -} -int astGetIsLonAxis_( AstSkyFrame *this, int axis, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,SkyFrame,GetIsLonAxis))( this, axis, status ); -} -int astGetLatAxis_( AstSkyFrame *this, int *status ) { - if ( !astOK ) return 1; - return (**astMEMBER(this,SkyFrame,GetLatAxis))( this, status ); -} -int astGetLonAxis_( AstSkyFrame *this, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,SkyFrame,GetLonAxis))( this, status ); -} -double astGetSkyRefP_( AstSkyFrame *this, int axis, int *status ) { - if ( !astOK ) return 0.0; - return (**astMEMBER(this,SkyFrame,GetSkyRefP))( this, axis, status ); -} -AstMapping *astSkyOffsetMap_( AstSkyFrame *this, int *status ) { - if ( !astOK ) return NULL; - return (**astMEMBER(this,SkyFrame,SkyOffsetMap))( this, status ); -} - -/* Special public interface functions. */ -/* =================================== */ -/* These provide the public interface to certain special functions - whose public interface cannot be handled using macros (such as - astINVOKE) alone. In general, they are named after the - corresponding protected version of the function, but with "Id" - appended to the name. */ - -/* Public 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. */ -AstSkyFrame *astSkyFrameId_( const char *, ... ); - -/* Special interface function implementations. */ -/* ------------------------------------------- */ -AstSkyFrame *astSkyFrameId_( const char *options, ... ) { -/* -*++ -* Name: -c astSkyFrame -f AST_SKYFRAME - -* Purpose: -* Create a SkyFrame. - -* Type: -* Public function. - -* Synopsis: -c #include "skyframe.h" -c AstSkyFrame *astSkyFrame( const char *options, ... ) -f RESULT = AST_SKYFRAME( OPTIONS, STATUS ) - -* Class Membership: -* SkyFrame constructor. - -* Description: -* This function creates a new SkyFrame and optionally initialises -* its attributes. -* -* A SkyFrame is a specialised form of Frame which describes -* celestial longitude/latitude coordinate systems. The particular -* celestial coordinate system to be represented is specified by -* setting the SkyFrame's System attribute (currently, the default -* is ICRS) qualified, as necessary, by a mean Equinox value and/or -* an Epoch. -* -* For each of the supported celestial coordinate systems, a SkyFrame -* can apply an optional shift of origin to create a coordinate system -* representing offsets within the celestial coordinate system from some -* specified point. This offset coordinate system can also be rotated to -* define new longitude and latitude axes. See attributes SkyRef, SkyRefIs -* and SkyRefP -* -* All the coordinate values used by a SkyFrame are in -* radians. These may be formatted in more conventional ways for -c display by using astFormat. -f display by using AST_FORMAT. - -* Parameters: -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 SkyFrame. 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. -c If no initialisation is required, a zero-length string may be -c supplied. -f A character string containing an optional comma-separated -f list of attribute assignments to be used for initialising the -f new SkyFrame. The syntax used is identical to that for the -f AST_SET routine. If no initialisation is required, a blank -f value may be supplied. -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 astSkyFrame() -f AST_SKYFRAME = INTEGER -* A pointer to the new SkyFrame. - -* Examples: -c frame = astSkyFrame( "" ); -c Creates a SkyFrame to describe the default ICRS celestial -c coordinate system. -c frame = astSkyFrame( "System = FK5, Equinox = J2005, Digits = 10" ); -c Creates a SkyFrame to describe the FK5 celestial -c coordinate system, with a mean Equinox of J2005.0. -c Because especially accurate coordinates will be used, -c additional precision (10 digits) has been requested. This will -c be used when coordinate values are formatted for display. -c frame = astSkyFrame( "System = FK4, Equinox = 1955-sep-2" ); -c Creates a SkyFrame to describe the old FK4 celestial -c coordinate system. A default Epoch value (B1950.0) is used, -c but the mean Equinox value is given explicitly as "1955-sep-2". -c frame = astSkyFrame( "System = GAPPT, Epoch = %s", date ); -c Creates a SkyFrame to describe the Geocentric Apparent -c celestial coordinate system. The Epoch value, which specifies -c the date of observation, is obtained from a date/time string -c supplied via the string pointer "date". -f FRAME = AST_SKYFRAME( ' ', STATUS ) -f Creates a SkyFrame to describe the default ICRS celestial -f coordinate system. -f FRAME = AST_SKYFRAME( 'System = FK5, Equinox = J2005, Digits = 10', STATUS ) -f Creates a SkyFrame to describe the FK5 celestial -f coordinate system, with a mean Equinox of J2005.0. -f Because especially accurate coordinates will be used, -f additional precision (10 digits) has been requested. This will -f be used when coordinate values are formatted for display. -f FRAME = AST_SKYFRAME( 'System = FK4, Equinox = 1955-SEP-2', STATUS ) -f Creates a SkyFrame to describe the old FK4 celestial -f coordinate system. A default Epoch value (B1950.0) is used, -f but the mean Equinox value is given explicitly as "1955-SEP-2". -f FRAME = AST_SKYFRAME( 'System = GAPPT, Epoch = ' // DATE, STATUS ) -f Creates a SkyFrame to describe the Geocentric Apparent -f celestial coordinate system. The Epoch value, which specifies -f the date of observation, is obtained from a date/time string -f contained in the character variable DATE. - -* Notes: -* - Currently, the default celestial coordinate system is -* ICRS. However, this default may change in future as new -* astrometric standards evolve. The intention is to track the most -* modern appropriate standard. For this reason, you should use the -* default only if this is what you intend (and can tolerate any -* associated slight change in behaviour with future versions of -* this function). If you intend to use the ICRS system -* indefinitely, then you should specify it explicitly using an -c "options" value of "System=ICRS". -f OPTIONS value of "System=ICRS". -* - Whichever celestial coordinate system is represented, it will -* have two axes. The first of these will be the longitude axis -* and the second will be the latitude axis. This order can be -c changed using astPermAxes if required. -f changed using AST_PERMAXES if required. -* - When conversion between two SkyFrames is requested (as when -c supplying SkyFrames to astConvert), -f supplying SkyFrames AST_CONVERT), -* account will be taken of the nature of the celestial coordinate -* systems they represent, together with any qualifying mean Equinox or -* Epoch values, etc. The AlignSystem attribute will also be taken into -* account. The results will therefore fully reflect the -* relationship between positions on the sky measured in the two -* systems. -* - A null Object pointer (AST__NULL) will be returned if this -c function is invoked with the AST error status set, or if it -f function is invoked with STATUS set to an error value, or if it -* should fail for any reason. -*-- - -* Implementation Notes: -* - This function implements the external (public) interface to -* the astSkyFrame constructor function. It returns an ID value -* (instead of a true C pointer) to external users, and must be -* provided because astSkyFrame_ 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 astSkyFrame_ 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. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Pointer to thread-specific global data */ - AstSkyFrame *new; /* Pointer to new SkyFrame */ - 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 SkyFrame, allocating memory and initialising the virtual - function table as well if necessary. */ - new = astInitSkyFrame( NULL, sizeof( AstSkyFrame ), !class_init, &class_vtab, - "SkyFrame" ); - -/* 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 SkyFrame'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 SkyFrame. */ - return astMakeId( new ); -} - - - - - - - |