diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2018-01-09 19:28:07 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2018-01-09 19:28:07 (GMT) |
commit | 3bfbbb90d4d6ebd44cc5eac38af24d1f78318a58 (patch) | |
tree | f278119398ae5d67a6a338705a76db420f6b8f7e /ast/region.c | |
parent | 1332d38f2805d986ea130e43218c0d2e870b4dc1 (diff) | |
download | blt-3bfbbb90d4d6ebd44cc5eac38af24d1f78318a58.zip blt-3bfbbb90d4d6ebd44cc5eac38af24d1f78318a58.tar.gz blt-3bfbbb90d4d6ebd44cc5eac38af24d1f78318a58.tar.bz2 |
update ast 8.6.2
Diffstat (limited to 'ast/region.c')
-rw-r--r-- | ast/region.c | 13502 |
1 files changed, 13502 insertions, 0 deletions
diff --git a/ast/region.c b/ast/region.c new file mode 100644 index 0000000..5148917 --- /dev/null +++ b/ast/region.c @@ -0,0 +1,13502 @@ +/* +*class++ +* Name: +* Region + +* Purpose: +* Represents a region within a coordinate system. + +* Constructor Function: +* None. + +* Description: +* This class provides the basic facilities for describing a region within +* a specified coordinate system. However, the Region class does not +* have a constructor function of its own, as it is simply a container +* class for a family of specialised sub-classes such as Circle, Box, etc, +* which implement Regions with particular shapes. +* +* All sub-classes of Region require a Frame to be supplied when the Region +* is created. This Frame describes the coordinate system in which the +* Region is defined, and is referred to as the "encapsulated Frame" below. +* Constructors will also typically required one or more positions to be +* supplied which define the location and extent of the region. These +* positions must be supplied within the encapsulated Frame. +* +* The Region class inherits from the Frame class, and so a Region can be +* supplied where-ever a Frame is expected. In these cases, supplying a +* Region is equivalent to supplying a reference to its encapsulated Frame. +* Thus all the methods of the Frame class can be used on the Region class. +* For instance, the +c astFormat function +f AST_FORMAT routine +* may be used on a Region to format an axis value. +* +* In addition, since Frame inherits from Mapping, a Region is also a sort +* of Mapping. Transforming positions by supplying a Region to one of the +c astTran<X> functions +f AST_TRAN<X> routines +* is the way to determine if a given position is inside or outside the +* Region. When used as a Mapping, most classes of Frame are equivalent to +* a UnitMap. However, the Region class modifies this behaviour so that a +* Region acts like a UnitMap only for input positions which are within the +* area represented by the Region. Input positions which are outside the +* area produce bad output values (i.e. the output values are equal to +* AST__BAD). This behaviour is the same for both the forward and the +* inverse transformation. In this sense the "inverse transformation" +* is not a true inverse of the forward transformation, since applying +* the forward transformation to a point outside the Region, and then +* applying the inverse transformation results, in a set of AST__BAD axis +* values rather than the original axis values. If required, the +c astRemoveRegions +f AST_REMOVEREGIONS +* function can be used to remove the "masking" effect of any Regions +* contained within a compound Mapping or FrameSet. It does this by +* replacing each Region with a UnitMap or equivalent Frame (depending +* on the context in which the Region is used). +* +* If the coordinate system represented by the Region is changed (by +* changing the values of one or more of the attribute which the Region +* inherits from its encapsulated Frame), the area represented by +* the Region is mapped into the new coordinate system. For instance, let's +* say a Circle (a subclass of Region) is created, a SkyFrame being +* supplied to the constructor so that the Circle describes a circular +* area on the sky in FK4 equatorial coordinates. Since Region inherits +* from Frame, the Circle will have a System attribute and this attribute +* will be set to "FK4". If the System attribute of the Region is then +* changed from FK4 to FK5, the circular area represented by the Region +* will automatically be mapped from the FK4 system into the FK5 system. +* In general, changing the coordinate system in this way may result in the +* region changing shape - for instance, a circle may change into an +* ellipse if the transformation from the old to the new coordinate system +* is linear but with different scales on each axis. Thus the specific +* class of a Region cannot be used as a guarantee of the shape in any +* particular coordinate system. If the +c astSimplify function +f AST_SIMPLIFY routine +* is used on a Region, it will endeavour to return a new Region of +* a sub-class which accurately describes the shape in the current +* coordinate system of the Region (but this may not always be possible). +* +* It is possible to negate an existing Region so that it represents all +* areas of the encapsulated Frame except for the area specified when +* the Region was created. + +* Inheritance: +* The Region class inherits from the Frame class. + +* Attributes: +* In addition to those attributes common to all Frames, every +* Region also has the following attributes: +* +* - Adaptive: Should the area adapt to changes in the coordinate system? +* - Negated: Has the original region been negated? +* - Closed: Should the boundary be considered to be inside the region? +* - MeshSize: Number of points used to create a mesh covering the Region +* - FillFactor: Fraction of the Region which is of interest +* - Bounded: Is the Region bounded? +* +* Every Region also inherits any further attributes that belong +* to the encapsulated Frame, regardless of that Frame's class. (For +* example, the Equinox attribute, defined by the SkyFrame class, is +* inherited by any Region which represents a SkyFrame.) + +* Functions: +c In addition to those functions applicable to all Frames, the +c following functions may also be applied to all Regions: +f In addition to those routines applicable to all Frames, the +f following routines may also be applied to all Regions: +* +c - astGetRegionBounds: Get the bounds of a Region +f - AST_GETREGIONBOUNDS: Get the bounds of a Region +c - astGetRegionFrame: Get a copy of the Frame represent by a Region +f - AST_GETREGIONFRAME: Get a copy of the Frame represent by a Region +c - astGetRegionFrameSet: Get a copy of the Frameset encapsulated by a Region +f - AST_GETREGIONFRAMESET: Get a copy of the Frameset encapsulated by a Region +c - astGetRegionMesh: Get a mesh of points covering a Region +f - AST_GETREGIONMESH: Get a mesh of points covering a Region +c - astGetRegionPoints: Get the positions that define a Region +f - AST_GETREGIONPOINTS: Get the positions that define a Region +c - astGetUnc: Obtain uncertainty information from a Region +f - AST_GETUNC: Obtain uncertainty information from a Region +c - astMapRegion: Transform a Region into a new coordinate system +f - AST_MAPREGION: Transform a Region into a new coordinate system +c - astNegate: Toggle the value of the Negated attribute +f - AST_NEGATE: Toggle the value of the Negated attribute +c - astOverlap: Determines the nature of the overlap between two Regions +f - AST_OVERLAP: Determines the nature of the overlap between two Regions +c - astMask<X>: Mask a region of a data grid +f - AST_MASK<X>: Mask a region of a data grid +c - astSetUnc: Associate a new uncertainty with a Region +f - AST_SETUNC: Associate a new uncertainty with a Region +c - astShowMesh: Display a mesh of points on the surface of a Region +f - AST_SHOWMESH: Display a mesh of points on the surface of a Region + +* Copyright: +* Copyright (C) 1997-2006 Council for the Central Laboratory of the +* Research Councils +* Copyright (C) 2009 Science & Technology Facilities Council. +* All Rights Reserved. + +* Licence: +* This program is free software: you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation, either +* version 3 of the License, or (at your option) any later +* version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General +* License along with this program. If not, see +* <http://www.gnu.org/licenses/>. + +* Authors: +* DSB: David S. Berry (STARLINK) + +* History: +* 3-DEC-2003 (DSB): +* Original version. +* 12-MAY-2005 (DSB): +* Override astNormBox method. +* 12-AUG-2005 (DSB): +* Override ObsLat and ObsLon accessor methods. +* 14-FEB-2006 (DSB): +* Override astGetObjSize. +* 2-MAR-2006 (DSB): +* Changed AST_LONG_DOUBLE to HAVE_LONG_DOUBLE. +* 14-MAR-2006 (DSB): +* Added astGetRefFS. +* 28-MAY-2007 (DSB): +* - Added protected function astBndMesh. +* 14-JAN-2009 (DSB): +* Override the astIntersect method. +* 20-JAN-2009 (DSB): +* Change astPickAxes so that it returns a Region rather than a +* Frame if possible. This included adding method astRegBasePick. +* 9-FEB-2009 (DSB): +* Move PointList methods astGetEnclosure and astSetEnclosure to +* Region. +* 18-FEB-2009 (DSB): +* Remove methods astGetEnclosure and astSetEnclosure. +* 15-JUN-2009 (DSB): +* Modify MapRegion to use FrameSets properly. +* 18-JUN-2009 (DSB): +* Override ObsAlt accessor methods. +* 7-SEP-2009 (DSB): +* Fix astMask to avoid reading variance values from the data array. +* 8-SEP-2009 (DSB): +* Fix bugs in astOverlap that could result in wrong results if +* either region is unbounded. +* 4-JAN-2010 (DSB): +* Fix bug in GetRegionBounds (it was assumed implicitly that the base +* Frame had the same number of axes as the current Frame). +* 18-MAR-2011 (DSB): +* Added astGetRegionMesh public method. +* 22-MAR-2011 (DSB): +* Improve uniformity of points produced by astRegBaseGrid method. +* 29-APR-2011 (DSB): +* Prevent astFindFrame from matching a subclass template against a +* superclass target. +* 17-MAY-2011 (DSB): +* In RegBaseGrid, accept the final try even if it is not within 5% +* of the required meshsize. +* 27-APR-2012 (DSB): +* Store a negated copy of itself with each Region. Changing the Negated +* attribute of a Region causes the cached information to be reset, and +* re-calculating it can be an expensive operation. So instead of changing +* "Negatated" in "this", access the negated copy of "this" using the +* new protected method astGetNegation. +* 7-JUN-2012 (DSB): +* Added protected astRegSplit method to split a Region into disjoint +* component regions. +* 15-JUN-2012 (DSB): +* Guard against division by zero in RegBase Grid if "ipr" is zero. +* 7-NOV-2013 (DSB): +* Added method astGetRegionFrameSet. +* 3-FEB-2014 (DSB): +* Fix bug masking regions that have no overlap with the supplied array. +* 17-APR-2015 (DSB): +* Added Centre. +* 26-OCT-2016 (DSB): +* - Override the astAxNorm method. +* - Use astAxNorm to fix a bug in astGetRegionBounds for cases where +* the Region cross a longitude=0 singularity. +* 11-NOV-2016 (DSB): +* When loading a Region, use the dimensionality of the base Frame +* of the FrameSet (rather than the current Frame as it used to be) +* to define the number of axes required in the PointSet. +* 1-DEC-2016 (DSB): +* Changed MapRegion to remove any unnecessary base frame axes in +* the returned Region. +*class-- + +* Implementation Notes: +* - All sub-classes must over-ride the following abstract methods declared +* in this class: astRegBaseBox, astRegBaseMesh, astRegPins, astRegCentre. +* They must also extend the astTransform method. In addition they should +* usually extend astSimplify. + +*/ + +/* 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 Region + +/* Value for Ident attribute of of an encapsulated FrameSet which + indicates that it is a dummy FrameSet (see astRegDummy). */ +#define DUMMY_FS "ASTREGION-DUMMY" + +/* +* Name: +* MAKE_CLEAR + +* Purpose: +* Define a function to clear an attribute value for a Region. + +* Type: +* Private macro. + +* Synopsis: +* #include "region.h" +* MAKE_CLEAR(attribute) + +* Class Membership: +* Defined by the Region class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static void Clear<Attribute>( AstFrame *this ) +* +* that clears the value of a specified attribute for the encapsulated +* FrameSet within a Region (this). This function is intended to over-ride +* the astClear<Attribute> method inherited from the Frame class. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +*/ + +/* Define the macro. */ +#define MAKE_CLEAR(attribute) \ +static void Clear##attribute( AstFrame *this_frame, int *status ) { \ +\ +/* Local Variables: */ \ + AstRegion *this; /* Pointer to the Region structure */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return; \ +\ +/* Obtain a pointer to the Region structure. */ \ + this = (AstRegion *) this_frame; \ +\ +/* Obtain a pointer to the encapsulated FrameSet and invoke its \ + astClear method. The protected astClear##attribute method is not used \ + because we want the current Frame of the FrameSet tp be re-mapped if \ + necessary. */ \ + astClear( this->frameset, #attribute ); \ +} + +/* +* Name: +* MAKE_CLEAR_AXIS + +* Purpose: +* Define a function to clear an attribute value for a Region axis. + +* Type: +* Private macro. + +* Synopsis: +* #include "region.h" +* MAKE_CLEAR_AXIS(attribute) + +* Class Membership: +* Defined by the Region class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static void Clear<Attribute>( AstFrame *this, int axis ) +* +* that clears the value of a specified attribute for an axis of +* the encapsulated FrameSet within a Region (this). This function is +* intended to over-ride the astClear<Attribute> method inherited +* from the Frame class. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +*/ + +/* Define the macro. */ +#define MAKE_CLEAR_AXIS(attribute) \ +static void Clear##attribute( AstFrame *this_frame, int axis, int *status ) { \ +\ +/* Local Variables: */ \ + AstRegion *this; /* Pointer to the Region structure */ \ + char buf[100]; /* Buffer for attribute name */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return; \ +\ +/* Obtain a pointer to the Region structure. */ \ + this = (AstRegion *) this_frame; \ +\ +/* Validate the axis index supplied. */ \ + (void) astValidateAxis( this, axis, 1, "astClear" #attribute ); \ +\ +/* We use the public astSetx method rather than the protected \ + astSet#attribute method so that the current Frame in the encapsulated \ + FrameSet will be re-mapped if necessary. Construct the attribute name. */ \ + sprintf( buf, "%s(%d)", #attribute, axis + 1 ); \ +\ +/* Obtain a pointer to the Region's encapsulated FrameSet and invoke its \ + astClear method. The protected astClear#attribute method is notused \ + since we want the current Frame of the encapsulated FrameSet to be \ + remapped if required. */ \ + astClear( this->frameset, buf ); \ +} + +/* +* Name: +* MAKE_GET + +* Purpose: +* Define a function to get an attribute value for a Region. + +* Type: +* Private macro. + +* Synopsis: +* #include "region.h" +* MAKE_GET(attribute,type) + +* Class Membership: +* Defined by the Region class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static <type> Get<Attribute>( AstFrame *this ) +* +* that gets the value of a specified attribute for the encapsulated +* FrameSet of a Region (this). This function is intended to over-ride +* the astGet<Attribute> method inherited from the Frame class. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +* type +* The C type of the attribute. +*/ + +/* Define the macro. */ +#define MAKE_GET(attribute,type) \ +static type Get##attribute( AstFrame *this_frame, int *status ) { \ +\ +/* Local Variables: */ \ + AstRegion *this; /* Pointer to the Region structure */ \ + type result; /* Value to return */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return (type) 0; \ +\ +/* Obtain a pointer to the Region structure. */ \ + this = (AstRegion *) this_frame; \ +\ +/* Obtain a pointer to the encapsulated FrameSet and invoke its \ + astGet<Attribute> method. */ \ + result = astGet##attribute( this->frameset ); \ +\ +/* If an error occurred, clear the result value. */ \ + if ( !astOK ) result = (type) 0; \ +\ +/* Return the result. */ \ + return result; \ +} + +/* +* Name: +* MAKE_GET_AXIS + +* Purpose: +* Define a function to get an attribute value for a Region axis. + +* Type: +* Private macro. + +* Synopsis: +* #include "region.h" +* MAKE_GET_AXIS(attribute,type) + +* Class Membership: +* Defined by the Region class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static <type> Get<Attribute>( AstFrame *this, int axis ) +* +* that gets the value of a specified attribute for an axis of the +* encapsulated FrameSet within a Region (this). This function is intended +* to over-ride the astGet<Attribute> method inherited from the Frame +* class. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +* type +* The C type of the attribute. +*/ + +/* Define the macro. */ +#define MAKE_GET_AXIS(attribute,type) \ +static type Get##attribute( AstFrame *this_frame, int axis, int *status ) { \ +\ +/* Local Variables: */ \ + AstRegion *this; /* Pointer to the Region structure */ \ + type result; /* Value to return */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return (type) 0; \ +\ +/* Obtain a pointer to the Region structure. */ \ + this = (AstRegion *) this_frame; \ +\ +/* Validate the axis index supplied. */ \ + (void) astValidateAxis( this, axis, 1, "astGet" #attribute ); \ +\ +/* Obtain a pointer to the Region's encapsulated FrameSet and invoke its \ + astGet<Attribute> method. */ \ + result = astGet##attribute( this->frameset, axis ); \ +\ +/* If an error occurred, clear the result value. */ \ + if ( !astOK ) result = (type) 0; \ +\ +/* Return the result. */ \ + return result; \ +} + +/* +* Name: +* MAKE_SET_SYSTEM + +* Purpose: +* Define a function to set a System attribute value for a Region. + +* Type: +* Private macro. + +* Synopsis: +* #include "region.h" +* MAKE_SET_SYSTEM(attribute) + +* Class Membership: +* Defined by the Region class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static void Set<Attribute>( AstFrame *this, AstSystemType value ) +* +* that sets the value of a specified attribute for the encapsulated +* FrameSet of a Region (this). This function is intended to over-ride the +* astSet<Attribute> method inherited from the Frame class. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +*/ + +/* Define the macro. */ +#define MAKE_SET_SYSTEM(attribute) \ +static void Set##attribute( AstFrame *this_frame, AstSystemType value, int *status ) { \ +\ +/* Local Variables: */ \ + AstRegion *this; /* Pointer to the Region structure */ \ + const char *text; /* Pointer to system string */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return; \ +\ +/* Obtain a pointer to the Region structure. */ \ + this = (AstRegion *) this_frame; \ +\ +/* Convert the supplied value to a string using the astSystemString + method of the current Frame in the encapsulated FrameSet. */ \ + text = astSystemString( this->frameset, value ); \ +\ +/* Set the value by invoking the public astSetC method on the encapusulated \ + FrameSet. This ensures that the current Frame of the encapsulated \ + FrameSet is re-mapped if necessary. */ \ + astSetC( this->frameset, #attribute, text ); \ +} + +/* +* Name: +* MAKE_SET + +* Purpose: +* Define a function to set an attribute value for a Region. + +* Type: +* Private macro. + +* Synopsis: +* #include "region.h" +* MAKE_SET(attribute,type,x) + +* Class Membership: +* Defined by the Region class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static void Set<Attribute>( AstFrame *this, <type> value ) +* +* that sets the value of a specified attribute for the encapsulated +* FrameSet of a Region (this). This function is intended to over-ride the +* astSet<Attribute> method inherited from the Frame class. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +* type +* The C type of the attribute. +* x +* The single character code for the astSetx function for the given C +* type. +*/ + +/* Define the macro. */ +#define MAKE_SET(attribute,type,x) \ +static void Set##attribute( AstFrame *this_frame, type value, int *status ) { \ +\ +/* Local Variables: */ \ + AstRegion *this; /* Pointer to the Region structure */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return; \ +\ +/* Obtain a pointer to the Region structure. */ \ + this = (AstRegion *) this_frame; \ +\ +/* Set the value by invoking the public astSetx method on the encapusulated \ + FrameSet. This ensures that the current Frame of the encapsulated \ + FrameSet is re-mapped if necessary. */ \ + astSet##x( this->frameset, #attribute, value ); \ +} + +/* +* Name: +* MAKE_SET_AXIS + +* Purpose: +* Define a function to set an attribute value for a Region axis. + +* Type: +* Private macro. + +* Synopsis: +* #include "region.h" +* MAKE_SET_AXIS(attribute,type,x) + +* Class Membership: +* Defined by the Region class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static void Set<Attribute>( AstFrame *this, int axis, <type> value ) +* +* that sets the value of a specified attribute for an axis of the +* encapsulated FrameSet within a Region (this). This function is intended +* to over-ride the astSet<Attribute> method inherited from the Frame +* class. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +* type +* The C type of the attribute. +* x +* The single character code for the astSetx function for the given C +* type. +*/ + +/* Define the macro. */ +#define MAKE_SET_AXIS(attribute,type,x) \ +static void Set##attribute( AstFrame *this_frame, int axis, type value, int *status ) { \ +\ +/* Local Variables: */ \ + AstRegion *this; /* Pointer to the Region structure */ \ + char buf[100]; /* Buffer for attribute name */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return; \ +\ +/* Obtain a pointer to the Region structure. */ \ + this = (AstRegion *) this_frame; \ +\ +/* Validate the axis index supplied. */ \ + (void) astValidateAxis( this, axis, 1, "astSet" #attribute ); \ +\ +/* We use the public astSetx method rather than the protected \ + astSet#attribute method so that the current Frame in the encapsulated \ + FrameSet will be re-mapped if necessary. Construct the attribute name. */ \ + sprintf( buf, "%s(%d)", #attribute, axis + 1 ); \ +\ +/* Obtain a pointer to the Region's encapsulated FrameSet and invoke its \ + astSet<x> method. */ \ + astSet##x( this->frameset, buf, value ); \ +} + +/* +* Name: +* MAKE_TEST + +* Purpose: +* Define a function to test if an attribute value is set for a Region. + +* Type: +* Private macro. + +* Synopsis: +* #include "region.h" +* MAKE_TEST(attribute) + +* Class Membership: +* Defined by the Region class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static int Test<Attribute>( AstFrame *this ) +* +* that returns a boolean result (0 or 1) to indicate if the value +* of a specified attribute for the encapsulated FrameSet within a +* Region (this) is set. This function is intended to over-ride the +* astTest<Attribute> method inherited from the Frame class. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +*/ + +/* Define the macro. */ +#define MAKE_TEST(attribute) \ +static int Test##attribute( AstFrame *this_frame, int *status ) { \ +\ +/* Local Variables: */ \ + AstRegion *this; /* Pointer to Region structure */ \ + int result; /* Result to return */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return 0; \ +\ +/* Obtain a pointer to the Region structure. */ \ + this = (AstRegion *) this_frame; \ +\ +/* Obtain a pointer to the Region's encapsulated FrameSet and invoke its \ + astTest<Attribute> method. */ \ + result = astTest##attribute( this->frameset ); \ +\ +/* If an error occurred, clear the result value. */ \ + if ( !astOK ) result = 0; \ +\ +/* Return the result. */ \ + return result; \ +} + +/* +* Name: +* MAKE_TEST_AXIS + +* Purpose: +* Define a function to test if an attribute value is set for a Region +* axis. + +* Type: +* Private macro. + +* Synopsis: +* #include "region.h" +* MAKE_TEST_AXIS(attribute) + +* Class Membership: +* Defined by the Region class. + +* Description: +* This macro expands to an implementation of a private member function +* of the form: +* +* static int Test<Attribute>( AstFrame *this, int axis ) +* +* that returns a boolean result (0 or 1) to indicate if the value +* of a specified attribute for an axis of the encapsulated FrameSet +* within a Region (this) is set. This function is intended to over-ride +* the astTest<Attribute> method inherited from the Frame class. + +* Parameters: +* attribute +* Name of the attribute, as it appears in the function name. +*/ + +/* Define the macro. */ +#define MAKE_TEST_AXIS(attribute) \ +static int Test##attribute( AstFrame *this_frame, int axis, int *status ) { \ +\ +/* Local Variables: */ \ + AstRegion *this; /* Pointer to the Region structure */ \ + int result; /* Value to return */ \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return 0; \ +\ +/* Obtain a pointer to the Region structure. */ \ + this = (AstRegion *) this_frame; \ +\ +/* Validate the axis index supplied. */ \ + (void) astValidateAxis( this, axis, 1, "astTest" #attribute ); \ +\ +/* Obtain a pointer to the Region's encapsulated FrameSet and invoke its \ + astTest<Attribute> method. */ \ + result = astTest##attribute( this->frameset, axis ); \ +\ +/* If an error occurred, clear the result value. */ \ + if ( !astOK ) result = 0; \ +\ +/* Return the result. */ \ + return result; \ +} + +/* 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 "object.h" /* Base Object class */ +#include "mapping.h" /* Coordinate Mappings */ +#include "unitmap.h" /* Unit Mappings */ +#include "permmap.h" /* Coordinate permutation Mappings */ +#include "cmpmap.h" /* Compound Mappings */ +#include "frame.h" /* Parent Frame class */ +#include "frameset.h" /* Interconnected coordinate systems */ +#include "region.h" /* Interface definition for this class */ +#include "circle.h" /* Circular regions */ +#include "box.h" /* Box regions */ +#include "cmpregion.h" /* Compound regions */ +#include "ellipse.h" /* Elliptical regions */ +#include "pointset.h" /* Sets of points */ +#include "globals.h" /* Thread-safe global data access */ + +/* Error code definitions. */ +/* ----------------------- */ +#include "ast_err.h" /* AST error codes */ + +/* C header files. */ +/* --------------- */ +#include <ctype.h> +#include <limits.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <math.h> + +/* Module Variables. */ +/* ================= */ + +/* Address of this static variable is used as a unique identifier for + member of this class. */ +static int class_check; + +/* Pointers to parent class methods which are extended by this class. */ +static int (* parent_getobjsize)( AstObject *, int * ); +static int (* parent_getusedefs)( AstObject *, int * ); + +#if defined(THREAD_SAFE) +static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * ); +#endif + +/* Define macros for accessing each item of thread specific global data. */ +#ifdef THREAD_SAFE + +/* Define how to initialise thread-specific globals. */ +#define GLOBAL_inits \ + globals->Class_Init = 0; \ + globals->GetAttrib_Buff[ 0 ] = 0; + +/* Create the function that initialises global data for this module. */ +astMAKE_INITGLOBALS(Region) + +/* Define macros for accessing each item of thread specific global data. */ +#define class_init astGLOBAL(Region,Class_Init) +#define class_vtab astGLOBAL(Region,Class_Vtab) +#define getattrib_buff astGLOBAL(Region,GetAttrib_Buff) + + + +/* If thread safety is not needed, declare and initialise globals at static + variables. */ +#else + +static char getattrib_buff[ 101 ]; + + +/* Define the class virtual function table and its initialisation flag + as static variables. */ +static AstRegionVtab class_vtab; /* Virtual function table */ +static int class_init = 0; /* Virtual function table initialised? */ + +#endif + +/* Prototypes for Private Member Functions. */ +/* ======================================== */ +#if HAVE_LONG_DOUBLE /* Not normally implemented */ +static int MaskLD( AstRegion *, AstMapping *, int, int, const int[], const int ubnd[], long double [], long double, int * ); +#endif +static int MaskB( AstRegion *, AstMapping *, int, int, const int[], const int[], signed char[], signed char, int * ); +static int MaskD( AstRegion *, AstMapping *, int, int, const int[], const int[], double[], double, int * ); +static int MaskF( AstRegion *, AstMapping *, int, int, const int[], const int[], float[], float, int * ); +static int MaskI( AstRegion *, AstMapping *, int, int, const int[], const int[], int[], int, int * ); +static int MaskL( AstRegion *, AstMapping *, int, int, const int[], const int[], long int[], long int, int * ); +static int MaskS( AstRegion *, AstMapping *, int, int, const int[], const int[], short int[], short int, int * ); +static int MaskUB( AstRegion *, AstMapping *, int, int, const int[], const int[], unsigned char[], unsigned char, int * ); +static int MaskUI( AstRegion *, AstMapping *, int, int, const int[], const int[], unsigned int[], unsigned int, int * ); +static int MaskUL( AstRegion *, AstMapping *, int, int, const int[], const int[], unsigned long int[], unsigned long int, int * ); +static int MaskUS( AstRegion *, AstMapping *, int, int, const int[], const int[], unsigned short int[], unsigned short int, int * ); + +static AstAxis *GetAxis( AstFrame *, int, int * ); +static AstFrame *GetRegionFrame( AstRegion *, int * ); +static AstFrameSet *GetRegionFrameSet( AstRegion *, int * ); +static AstFrame *PickAxes( AstFrame *, int, const int[], AstMapping **, int * ); +static AstFrame *RegFrame( AstRegion *, int * ); +static AstFrameSet *Conv( AstFrameSet *, AstFrameSet *, int * ); +static AstFrameSet *Convert( AstFrame *, AstFrame *, const char *, int * ); +static AstFrameSet *ConvertX( AstFrame *, AstFrame *, const char *, int * ); +static AstFrameSet *FindFrame( AstFrame *, AstFrame *, const char *, int * ); +static AstFrameSet *GetRegFS( AstRegion *, int * ); +static AstLineDef *LineDef( AstFrame *, const double[2], const double[2], int * ); +static AstMapping *RegMapping( AstRegion *, int * ); +static AstMapping *RemoveRegions( AstMapping *, int * ); +static AstMapping *Simplify( AstMapping *, int * ); +static AstObject *Cast( AstObject *, AstObject *, int * ); +static AstPointSet *BTransform( AstRegion *, AstPointSet *, int, AstPointSet *, int * ); +static AstPointSet *BndBaseMesh( AstRegion *, double *, double *, int * ); +static AstPointSet *BndMesh( AstRegion *, double *, double *, int * ); +static AstPointSet *GetSubMesh( int *, AstPointSet *, int * ); +static AstPointSet *RegBaseGrid( AstRegion *, int * ); +static AstPointSet *RegBaseMesh( AstRegion *, int * ); +static AstPointSet *RegGrid( AstRegion *, int * ); +static AstPointSet *RegMesh( AstRegion *, int * ); +static AstPointSet *RegTransform( AstRegion *, AstPointSet *, int, AstPointSet *, AstFrame **, int * ); +static AstPointSet *ResolvePoints( AstFrame *, const double [], const double [], AstPointSet *, AstPointSet *, int * ); +static AstRegion *MapRegion( AstRegion *, AstMapping *, AstFrame *, int * ); +static AstRegion *RegBasePick( AstRegion *, int, const int *, int * ); +static AstRegion **RegSplit( AstRegion *, int *, int * ); +static AstSystemType SystemCode( AstFrame *, const char *, int * ); +static AstSystemType ValidateSystem( AstFrame *, AstSystemType, const char *, int * ); +static const char *Abbrev( AstFrame *, int, const char *, const char *, const char *, int * ); +static const char *Format( AstFrame *, int, double, int * ); +static const char *SystemString( AstFrame *, AstSystemType, int * ); +static const int *GetPerm( AstFrame *, int * ); +static double *RegCentre( AstRegion *, double *, double **, int, int, int * ); +static double Angle( AstFrame *, const double[], const double[], const double[], int * ); +static double AxAngle( AstFrame *, const double[], const double[], int, int * ); +static double AxDistance( AstFrame *, int, double, double, int * ); +static double AxOffset( AstFrame *, int, double, double, int * ); +static double Distance( AstFrame *, const double[], const double[], int * ); +static double Centre( AstFrame *, int, double, double, int * ); +static double Gap( AstFrame *, int, double, int *, int * ); +static double Offset2( AstFrame *, const double[2], double, double, double[2], int * ); +static int Equal( AstObject *, AstObject *, int * ); +static int GetNaxes( AstFrame *, int * ); +static int GetObjSize( AstObject *, int * ); +static int GetUseDefs( AstObject *, int * ); +static int IsUnitFrame( AstFrame *, int * ); +static int LineContains( AstFrame *, AstLineDef *, int, double *, int * ); +static int LineCrossing( AstFrame *, AstLineDef *, AstLineDef *, double **, int * ); +static int Match( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * ); +static int Overlap( AstRegion *, AstRegion *, int * ); +static int OverlapX( AstRegion *, AstRegion *, int * ); +static int RegDummyFS( AstRegion *, int * ); +static int RegPins( AstRegion *, AstPointSet *, AstRegion *, int **, int * ); +static int SubFrame( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * ); +static int RegTrace( AstRegion *, int, double *, double **, int * ); +static int Unformat( AstFrame *, int, const char *, double *, int * ); +static int ValidateAxis( AstFrame *, int, int, const char *, int * ); +static void AxNorm( AstFrame *, int, int, int, double *, int * ); +static void CheckPerm( AstFrame *, const int *, const char *, int * ); +static void Copy( const AstObject *, AstObject *, int * ); +static void Delete( AstObject *, int * ); +static void Dump( AstObject *, AstChannel *, int * ); +static void GetRegionBounds( AstRegion *, double *, double *, int * ); +static void GetRegionBounds2( AstRegion *, double *, double *, int * ); +static void GetRegionMesh( AstRegion *, int, int, int, int *, double *, int * ); +static void GetRegionPoints( AstRegion *, int, int, int *, double *, 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 MatchAxes( AstFrame *, AstFrame *, int *, int * ); +static void MatchAxesX( AstFrame *, AstFrame *, int *, int * ); +static void Negate( AstRegion *, 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 PermAxes( AstFrame *, const int[], int * ); +static void RegBaseBox( AstRegion *, double *, double *, int * ); +static void RegBaseBox2( AstRegion *, double *, double *, int * ); +static void RegClearAttrib( AstRegion *, const char *, char **, int * ); +static void RegOverlay( AstRegion *, AstRegion *, int, int * ); +static void RegSetAttrib( AstRegion *, const char *, char **, int * ); +static void ReportPoints( AstMapping *, int, AstPointSet *, AstPointSet *, int * ); +static void ResetCache( AstRegion *, int * ); +static void Resolve( AstFrame *, const double [], const double [], const double [], double [], double *, double *, int * ); +static void SetAxis( AstFrame *, int, AstAxis *, int * ); +static void SetRegFS( AstRegion *, AstFrame *, int * ); +static void ShowMesh( AstRegion *, int, const char *, int * ); +static void ValidateAxisSelection( AstFrame *, int, const int *, const char *, int * ); +static AstRegion *GetNegation( AstRegion *, int * ); + +static int GetBounded( AstRegion *, int * ); +static AstRegion *GetDefUnc( AstRegion *, int * ); + +static AstRegion *GetUncFrm( AstRegion *, int, int * ); +static AstRegion *GetUnc( AstRegion *, int, int * ); +static int TestUnc( AstRegion *, int * ); +static void ClearUnc( AstRegion *, int * ); +static void SetUnc( AstRegion *, AstRegion *, int * ); + +static const char *GetDomain( AstFrame *, int * ); +static int TestDomain( AstFrame *, int * ); +static void ClearDomain( AstFrame *, int * ); +static void SetDomain( AstFrame *, const char *, int * ); + +static const char *GetFormat( AstFrame *, int, int * ); +static int TestFormat( AstFrame *, int, int * ); +static void ClearFormat( AstFrame *, int, int * ); +static void SetFormat( AstFrame *, int, const char *, int * ); + +static const char *GetLabel( AstFrame *, int, int * ); +static int TestLabel( AstFrame *, int, int * ); +static void ClearLabel( AstFrame *, int, int * ); +static void SetLabel( AstFrame *, int, const char *, int * ); + +static const char *GetSymbol( AstFrame *, int, int * ); +static int TestSymbol( AstFrame *, int, int * ); +static void ClearSymbol( AstFrame *, int, int * ); +static void SetSymbol( AstFrame *, int, const char *, int * ); + +static const char *GetTitle( AstFrame *, int * ); +static void SetTitle( AstFrame *, const char *, int * ); +static void ClearTitle( AstFrame *, int * ); +static int TestTitle( AstFrame *, int * ); + +static const char *GetUnit( AstFrame *, int, int * ); +static int TestUnit( AstFrame *, int, int * ); +static void ClearUnit( AstFrame *, int, int * ); +static void SetUnit( AstFrame *, int, const char *, int * ); + +static int GetDigits( AstFrame *, int * ); +static int TestDigits( AstFrame *, int * ); +static void ClearDigits( AstFrame *, int * ); +static void SetDigits( AstFrame *, int, int * ); + +static int GetDirection( AstFrame *, int, int * ); +static int TestDirection( AstFrame *, int, int * ); +static void ClearDirection( AstFrame *, int, int * ); +static void SetDirection( AstFrame *, int, int, int * ); + +static int GetActiveUnit( AstFrame *, int * ); +static int TestActiveUnit( AstFrame *, int * ); +static void SetActiveUnit( AstFrame *, int, int * ); + +static int GetMatchEnd( AstFrame *, int * ); +static int TestMatchEnd( AstFrame *, int * ); +static void ClearMatchEnd( AstFrame *, int * ); +static void SetMatchEnd( AstFrame *, int, int * ); + +static int GetMaxAxes( AstFrame *, int * ); +static int TestMaxAxes( AstFrame *, int * ); +static void ClearMaxAxes( AstFrame *, int * ); +static void SetMaxAxes( AstFrame *, int, int * ); + +static int GetMinAxes( AstFrame *, int * ); +static int TestMinAxes( AstFrame *, int * ); +static void ClearMinAxes( AstFrame *, int * ); +static void SetMinAxes( AstFrame *, int, int * ); + +static int GetPermute( AstFrame *, int * ); +static int TestPermute( AstFrame *, int * ); +static void ClearPermute( AstFrame *, int * ); +static void SetPermute( AstFrame *, int, int * ); + +static int GetPreserveAxes( AstFrame *, int * ); +static int TestPreserveAxes( AstFrame *, int * ); +static void ClearPreserveAxes( AstFrame *, int * ); +static void SetPreserveAxes( AstFrame *, int, int * ); + +static double GetBottom( AstFrame *, int, int * ); +static int TestBottom( AstFrame *, int, int * ); +static void ClearBottom( AstFrame *, int, int * ); +static void SetBottom( AstFrame *, int, double, int * ); + +static double GetTop( AstFrame *, int, int * ); +static int TestTop( AstFrame *, int, int * ); +static void ClearTop( AstFrame *, int, int * ); +static void SetTop( AstFrame *, int, double, int * ); + +static double GetEpoch( AstFrame *, int * ); +static int TestEpoch( AstFrame *, int * ); +static void ClearEpoch( AstFrame *, int * ); +static void SetEpoch( AstFrame *, double, int * ); + +static double GetObsAlt( AstFrame *, int * ); +static int TestObsAlt( AstFrame *, int * ); +static void ClearObsAlt( AstFrame *, int * ); +static void SetObsAlt( AstFrame *, double, int * ); + +static double GetObsLat( AstFrame *, int * ); +static int TestObsLat( AstFrame *, int * ); +static void ClearObsLat( AstFrame *, int * ); +static void SetObsLat( AstFrame *, double, int * ); + +static double GetObsLon( AstFrame *, int * ); +static int TestObsLon( AstFrame *, int * ); +static void ClearObsLon( AstFrame *, int * ); +static void SetObsLon( AstFrame *, double, int * ); + +static AstSystemType GetSystem( AstFrame *, int * ); +static int TestSystem( AstFrame *, int * ); +static void ClearSystem( AstFrame *, int * ); +static void SetSystem( AstFrame *, AstSystemType, int * ); + +static AstSystemType GetAlignSystem( AstFrame *, int * ); +static int TestAlignSystem( AstFrame *, int * ); +static void ClearAlignSystem( AstFrame *, int * ); +static void SetAlignSystem( AstFrame *, AstSystemType, int * ); + +static const char *GetAttrib( AstObject *, const char *, int * ); +static int TestAttrib( AstObject *, const char *, int * ); +static void ClearAttrib( AstObject *, const char *, int * ); +static void SetAttrib( AstObject *, const char *, int * ); + +static int GetNegated( AstRegion *, int * ); +static int TestNegated( AstRegion *, int * ); +static void ClearNegated( AstRegion *, int * ); +static void SetNegated( AstRegion *, int, int * ); + +static int GetClosed( AstRegion *, int * ); +static int TestClosed( AstRegion *, int * ); +static void ClearClosed( AstRegion *, int * ); +static void SetClosed( AstRegion *, int, int * ); + +static int GetMeshSize( AstRegion *, int * ); +static int TestMeshSize( AstRegion *, int * ); +static void ClearMeshSize( AstRegion *, int * ); +static void SetMeshSize( AstRegion *, int, int * ); + +static double GetFillFactor( AstRegion *, int * ); +static int TestFillFactor( AstRegion *, int * ); +static void ClearFillFactor( AstRegion *, int * ); +static void SetFillFactor( AstRegion *, double, int * ); + +static int GetRegionFS( AstRegion *, int * ); +static int TestRegionFS( AstRegion *, int * ); +static void ClearRegionFS( AstRegion *, int * ); +static void SetRegionFS( AstRegion *, int, int * ); + +static int GetAdaptive( AstRegion *, int * ); +static int TestAdaptive( AstRegion *, int * ); +static void ClearAdaptive( AstRegion *, int * ); +static void SetAdaptive( AstRegion *, int, int * ); + +#if defined(THREAD_SAFE) +static int ManageLock( AstObject *, int, int, AstObject **, int * ); +#endif + + +/* Member functions. */ +/* ================= */ + +static const char *Abbrev( AstFrame *this_frame, int axis, const char *fmt, + const char *str1, const char *str2, int *status ) { +/* +* Name: +* Abbrev + +* Purpose: +* Abbreviate a formatted Region axis value by skipping leading fields. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* const char *Abbrev( AstFrame *this, int axis, const char *fmt, +* const char *str1, const char *str2, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astAbbrev +* method inherited from the Frame class). + +* Description: +* This function compares two Region axis values that have been +* formatted (using astFormat) and determines if they have any +* redundant leading fields (i.e. leading fields in common which +* can be suppressed when tabulating the values or plotting them on +* the axis of a graph). + +* Parameters: +* this +* Pointer to the Region +* axis +* The number of the Region axis for which the values have +* been formatted (axis numbering starts at zero for the first +* axis). +* fmt +* Pointer to a constant null-terminated string containing the +* format specification used to format the two values. +* str1 +* Pointer to a constant null-terminated string containing the +* first formatted value. +* str1 +* Pointer to a constant null-terminated string containing the +* second formatted value. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* A pointer into the "str2" string which locates the first +* character in the first field that differs between the two +* formatted values. +* +* If the two values have no leading fields in common, the returned +* value will point at the start of string "str2". If the two +* values are equal, it will point at the terminating null at the +* end of this string. + +* Notes: +* - This function assumes that the format specification used was +* the same when both values were formatted and that they both +* apply to the same Region axis. +* - A pointer to the start of "str2" will be returned if this +* function is invoked with the global error status set, or if it +* should fail for any reason. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + const char *result; /* Pointer value to return */ + +/* Check the global error status. */ + if ( !astOK ) return str2; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis, 1, "astAbbrev" ); + +/* Obtain a pointer to the Region's current Frame and invoke this + Frame's astAbbrev method to perform the processing. Annul the Frame + pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astAbbrev( fr, axis, fmt, str1, str2 ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result. */ + if ( !astOK ) result = str2; + +/* Return the result. */ + return result; +} + +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 "region.h" +* double Angle( AstFrame *this, const double a[], const double b[], +* const double c[], int *status ) + +* Class Membership: +* Region member function (over-rides the protected 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 appropriate to the Frame in use. For instance, in +* SkyFrame, they will be great circles. + +* Parameters: +* this +* Pointer to the Frame. +* a +* An array of double, with one element for each Frame axis +* (Naxes attribute) containing the coordinates of the first point. +* b +* An array of double, with one element for each Frame axis +* (Naxes attribute) containing the coordinates of the second point. +* c +* An array of double, with one element for each Frame axis +* (Naxes attribute) containing the coordinates of the third point. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* astAngle +* The angle in radians, from the line AB to the line CB. If the +* Frame is 2-dimensional, it will be in the range $\pm \pi$, +* and positive rotation is in the same sense as rotation from +* the positive direction of axis 2 to the positive direction of +* axis 1. If the Frame has more than 2 axes, a positive value will +* always be returned in the range zero to $\pi$. + +* Notes: +* - A value of AST__BAD will also be returned if points A and B are +* co-incident, or if points B and C are co-incident. +* - A value of AST__BAD 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + double result; /* Value to return */ + +/* Check the global error status. */ + if ( !astOK ) return AST__BAD; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke this + Frame's astAngle method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astAngle( fr, a, b, c ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result. */ + if ( !astOK ) result = AST__BAD; + +/* Return the result. */ + return result; +} + +static double AxAngle( AstFrame *this_frame, const double a[], const double b[], int axis, int *status ) { +/* +* Name: +* AxAngle + +* Purpose: +* Returns the angle from an axis, to a line through two points. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* double AxAngle( AstFrame *this, const double a[], const double b[], int axis, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astAxAngle +* method inherited from the Frame class). + +* Description: +* This function finds the angle, as seen from point A, between the positive +* direction of a specified axis, and the geodesic curve joining point +* A to point B. + +* Parameters: +* this +* Pointer to the Frame. +* a +* An array of double, with one element for each Frame axis +* (Naxes attribute) containing the coordinates of the first point. +* b +* An array of double, with one element for each Frame axis +* (Naxes attribute) containing the coordinates of the second point. +* axis +* The number of the Frame axis from which the angle is to be +* measured (one-based) +* status +* Pointer to the inherited status variable. + +* Returned Value: +* The angle in radians, from the positive direction of the +* specified axis, to the line AB. If the Frame is 2-dimensional, +* it will be in the range $\pm \pi$, and positive rotation is in +* the same sense as rotation from the positive direction of axis 2 +* to the positive direction of axis 1. If the Frame has more than 2 +* axes, a positive value will always be returned in the range zero +* to $\pi$. + +* 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, or if the require +* position angle is undefined. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + double result; /* Value to return */ + +/* Check the global error status. */ + if ( !astOK ) return AST__BAD; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis - 1, 1, "astAxAngle" ); + +/* Obtain a pointer to the Region's encapsulated Frame and invoke the + astAxAngle method for this Frame. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astAxAngle( fr, a, b, axis ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = AST__BAD; + +/* Return the result. */ + return result; +} + +static double AxDistance( AstFrame *this_frame, int axis, double v1, double v2, int *status ) { +/* +* Name: +* AxDistance + +* Purpose: +* Find the distance between two axis values. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* double AxDistance( AstFrame *this, int axis, double v1, double v2, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astAxDistance +* method inherited from the Frame class). + +* Description: +* This function returns a signed value representing the axis increment +* from axis value v1 to axis value v2. +* +* For a simple Frame, this is a trivial operation returning the +* difference between the two axis values. But for other derived classes +* of Frame (such as a SkyFrame) this is not the case. + +* Parameters: +* this +* Pointer to the Frame. +* axis +* The index of the axis to which the supplied values refer. The +* first axis has index 1. +* v1 +* The first axis value. +* v2 +* The second axis value. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* The distance between the two axis values. + +* Notes: +* - This function will return a "bad" result value (AST__BAD) if +* any of the input vaues 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + double result; /* Value to return */ + +/* Check the global error status. */ + if ( !astOK ) return AST__BAD; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis - 1, 1, "astAxDistance" ); + +/* Obtain a pointer to the Region's encapsulated Frame and invoke the + astAxDistance method for this Frame. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astAxDistance( fr, axis, v1, v2 ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = AST__BAD; + +/* Return the result. */ + return result; +} + +static void AxNorm( AstFrame *this_frame, int axis, int oper, int nval, + double *values, int *status ){ +/* +* Name: +* AxNorm + +* Purpose: +* Normalise an array of axis values. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void AxNorm( AstFrame *this, int axis, int oper, int nval, +* double *values, int *status ) + +* Class Membership: +* FrameSet member function (over-rides the protected astAxNorm +* method inherited from the Frame class). + +* Description: +* This function modifies a supplied array of axis values so that +* they are normalised in the manner indicated by parameter "oper". +* +* No normalisation is possible for a simple Frame and so the supplied +* values are returned unchanged. However, this may not be the case for +* specialised sub-classes of Frame. For instance, a SkyFrame has a +* discontinuity at zero longitude and so a longitude value can be +* expressed in the range [-Pi,+PI] or the range [0,2*PI]. + +* Parameters: +* this +* Pointer to the Frame. +* axis +* The index of the axis to which the supplied values refer. The +* first axis has index 1. +* oper +* Indicates the type of normalisation to be applied. If zero is +* supplied, the normalisation will be the same as that performed by +* function astNorm. If 1 is supplied, the normalisation will be +* chosen automatically so that the resulting list has the smallest +* range. +* nval +* The number of points in the values array. +* values +* On entry, the axis values to be normalised. Modified on exit to +* hold the normalised values. +* status +* Pointer to the inherited status variable. + +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis - 1, 1, "astAxNorm" ); + +/* Obtain a pointer to the Region's encapsulated Frame and invoke + the astAxNorm method for this Frame. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astAxNorm( fr, axis, oper, nval, values ); + fr = astAnnul( fr ); +} + +static double AxOffset( AstFrame *this_frame, int axis, double v1, double dist, int *status ) { +/* +* Name: +* AxOffset + +* Purpose: +* Add an increment onto a supplied axis value. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* double AxOffset( AstFrame *this, int axis, double v1, double dist, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astAxOffset +* method inherited from the Frame class). + +* Description: +* This function returns an axis value formed by adding a signed axis +* increment onto a supplied axis value. +* +* For a simple Frame, this is a trivial operation returning the +* sum of the two supplied values. But for other derived classes +* of Frame (such as a SkyFrame) this is not the case. + +* Parameters: +* this +* Pointer to the Frame. +* axis +* The index of the axis to which the supplied values refer. The +* first axis has index 1. +* v1 +* The original axis value. +* dist +* The axis increment to add to the original axis value. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* The incremented axis value. + +* Notes: +* - This function will return a "bad" result value (AST__BAD) if +* any of the input vaues 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + double result; /* Value to return */ + +/* Check the global error status. */ + if ( !astOK ) return AST__BAD; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis - 1, 1, "astAxOffset" ); + +/* Obtain a pointer to the Region's encapsulated Frame and invoke the + astAxOffset method for this Frame. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astAxOffset( fr, axis, v1, dist ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = AST__BAD; + +/* Return the result. */ + return result; +} + +static AstPointSet *BndBaseMesh( AstRegion *this, double *lbnd, double *ubnd, int *status ){ +/* +*+ +* Name: +* astBndBaseMesh + +* Purpose: +* Return a PointSet containing points spread around part of the boundary +* of a Region, in the base Frame. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstPointSet *astBndBaseMesh( AstRegion *this, double *lbnd, double *ubnd ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a PointSet containing a set of points on the +* boundary of the intersection between the supplied Region and the +* supplied (current Frame) box. The mesh points refer to the base +* Frame. If the boundary of the supplied Region does not intersect the +* supplied box, then a PointSet containing a single bad point is +* returned. + +* Parameters: +* this +* Pointer to the Region. +* lbnd +* Pointer to an array holding the lower limits of the axis values +* within the required box. Defined in the current Frame of the Region. +* ubnd +* Pointer to an array holding the upper limits of the axis values +* within the required box. Defined in the current Frame of the Region. + +* Returned Value: +* Pointer to the PointSet holding the base Frame mesh. The axis values +* in this PointSet will have associated accuracies derived from the +* uncertainties which were supplied when the Region was created. +* +* If the Region does not intersect the supplied box, the returned +* PointSet will contain a single point with a value of AST__BAD on +* every axis. + +* Notes: +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. +*- +*/ + +/* Local Variables: */ + AstBox *box; + AstCmpRegion *cmpreg; + AstPointSet *result; + double **ptr; + int ic; + int nc; + +/* Check the local error status. */ + if ( !astOK ) return NULL; + +/* Form a Box describing the required box. */ + box = astBox( this, 1, lbnd, ubnd, NULL, "", status ); + +/* Check there is partial overlap between the Regions.*/ + if( astOverlap( this, box ) > 3 ) { + +/* Form a CmpRegion representing the intersection between the supplied + Region and the above box. */ + cmpreg = astCmpRegion( this, box, AST__AND, "", status ); + +/* Get the boundary mesh. */ + result = astRegBaseMesh( cmpreg ); + +/* Free resources. */ + cmpreg = astAnnul( cmpreg ); + +/* If the boundary of the supplied Region does not intersect the box, + return a PointSet containing a single bad position. */ + } else { + nc = astGetNin( this->frameset ); + result = astPointSet( 1, nc, "", status ); + ptr = astGetPoints( result ); + if( ptr ) { + for( ic = 0; ic < nc; ic++ ) ptr[ ic ][ 0 ] = AST__BAD; + } + } + +/* Free resources. */ + box = astAnnul( box ); + +/* Return NULL if an error occurred. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the required pointer. */ + return result; +} + +static AstPointSet *BndMesh( AstRegion *this, double *lbnd, double *ubnd, int *status ){ +/* +*+ +* Name: +* astBndMesh + +* Purpose: +* Return a PointSet containing points spread around part of the boundary +* of a Region, in the current Frame. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstPointSet *astBndMesh( AstRegion *this, double *lbnd, double *ubnd ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a PointSet containing a set of points on the +* boundary of the intersection between the supplied Region and the +* supplied box. The points refer to the current Frame of the +* encapsulated FrameSet. If the boundary of the supplied Region does +* not intersect the supplied box, then a PointSet containing a single +* bad point is returned. + +* Parameters: +* this +* Pointer to the Region. +* lbnd +* Pointer to an array holding the lower limits of the axis values +* within the required box. Defined in the current Frame of the Region. +* ubnd +* Pointer to an array holding the upper limits of the axis values +* within the required box. Defined in the current base Frame of the +* Region. + +* Returned Value: +* Pointer to the PointSet. The axis values in this PointSet will have +* associated accuracies derived from the uncertainties which were +* supplied when the Region was created. +* +* If the Region does not intersect the supplied box, the returned +* PointSet will contain a single point with a value of AST__BAD on +* every axis. + +* Notes: +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. +*- +*/ + +/* Local Variables: */ + AstMapping *map; + AstPointSet *ps1; + AstPointSet *result; + +/* Initialise */ + result = NULL; + +/* Check the local error status. */ + if ( !astOK ) return result; + +/* Get the current->base Mapping from the Region. */ + map = astGetMapping( this->frameset, AST__CURRENT, AST__BASE ); + +/* Use astBndBaseMesh to get a mesh of base Frame points within this base + Frame bounding box. */ + ps1 = astBndBaseMesh( this, lbnd, ubnd ); + +/* Transform it into the current Frame. */ + if( ps1 ) result = astTransform( map, ps1, 0, NULL ); + +/* Free resources. */ + map = astAnnul( map ); + ps1 = astAnnul( ps1 ); + +/* Return NULL if an error occurred. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the required pointer. */ + return result; +} + +static AstPointSet *BTransform( AstRegion *this, AstPointSet *in, + int forward, AstPointSet *out, int *status ) { +/* +*+ +* Name: +* astBTransform + +* Purpose: +* Use a Region to transform a set of points in the base Frame. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "circle.h" +* AstPointSet *astBTransform( AstRegion *this, AstPointSet *in, + int forward, AstPointSet *out ) + +* Class Membership: +* Region member function + +* Description: +* This function takes a Region and a set of points within the base +* Frame of the Region, and transforms the points by setting axis values +* to AST__BAD for all points which are outside the region. Points inside +* the region are copied unchanged from input to output. + +* Parameters: +* this +* Pointer to the Region. +* in +* Pointer to the PointSet holding the input coordinate data. +* forward +* A non-zero value indicates that the forward coordinate transformation +* should be applied, while a zero value requests the inverse +* transformation. +* out +* Pointer to a PointSet which will hold the transformed (output) +* coordinate values. A NULL value may also be given, in which case a +* new PointSet will be created by this function. + +* Returned Value: +* Pointer to the output (possibly new) PointSet. + +* Notes: +* - This is identical to the astTransform method for a Region except +* that the supplied and returned points refer to the base Frame of +* the Region, rather than the current Frame. +*- +*/ + +/* Local Variables: */ + AstPointSet *result; /* Pointer to output PointSet */ + int old; /* Origial value of "nomap" flag */ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Save the current value of the "nomap" flag for this Region,and then + set it. Doing this tells the astRegMapping function (called by + astRegTransform) to assume a unit map connects base and current Frame. */ + old = this->nomap; + this->nomap = 1; + +/* Invoke the usual astTransform method. The above setting of the "nomap" + flag will cause the astTransform method to treat the base Frame as the + current Frame. */ + result = astTransform( this, in, forward, out ); + +/* Reset the "nomap" flag. */ + this->nomap = old; + +/* Return a pointer to the output PointSet. */ + return result; +} + +static AstObject *Cast( AstObject *this_object, AstObject *obj, int *status ) { +/* +* Name: +* Cast + +* Purpose: +* Cast an Object into an instance of a sub-class. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstObject *Cast( AstObject *this, AstObject *obj, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astCast +* method inherited from the Frame class). + +* Description: +* This function returns a deep copy of an ancestral component of the +* supplied object. The required class of the ancestral component is +* specified by another object. Specifically, if "this" and "new" are +* of the same class, a copy of "this" is returned. If "this" is an +* instance of a subclass of "obj", then a copy of the component +* of "this" that matches the class of "obj" is returned. Otherwise, +* a NULL pointer is returned without error. + +* Parameters: +* this +* Pointer to the Object to be cast. +* obj +* Pointer to an Object that defines the class of the returned Object. +* The returned Object will be of the same class as "obj". + +* Returned Value: +* A pointer to the new Object. NULL if "this" is not a sub-class of +* "obj", or if an error occurs. + +* 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; */ + AstFrame *cfrm; + AstObject *new; + astDECLARE_GLOBALS + int generation_gap; + +/* Initialise */ + new = NULL; + +/* Check inherited status */ + if( !astOK ) return new; + +/* Get a pointer to the thread specific global data structure. */ + astGET_GLOBALS(NULL); + +/* See how many steps up the class inheritance ladder it is from "obj" + to this class (Region). A positive value is returned if Region is + a sub-class of "obj". A negative value is returned if "obj" is a + sub-class of Region. Zero is returned if "obj" is a Region. + AST__COUSIN is returned if "obj" is not on the same line of descent + as Region. */ + generation_gap = astClassCompare( (AstObjectVtab *) &class_vtab, + astVTAB( obj ) ); + +/* If "obj" is a Region or a sub-class of Region, we can cast by + truncating the vtab for "this" so that it matches the vtab of "obJ", + and then taking a deep copy of "this". */ + if( generation_gap <= 0 && generation_gap != AST__COUSIN ) { + new = astCastCopy( this_object, obj ); + +/* If "obj" is not a Region or a sub-class of Region (e.g. a Frame or + some sub-class of Frame), we attempt to cast the current Frame of the + encapsulated FrameSet into the class indicated by "obj". */ + } else { + cfrm = astGetFrame( ((AstRegion *) this_object)->frameset, AST__CURRENT ); + new = astCast( cfrm, obj ); + cfrm = astAnnul( cfrm ); + } + +/* Return the new pointer. */ + return new; +} + +static double Centre( AstFrame *this_frame, int axis, double value, double gap, int *status ) { +/* +* Name: +* Centre + +* Purpose: +* Find a "nice" central value for tabulating Frame axis values. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* double Centre( AstFrame *this_frame, int axis, double value, +* double gap, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astCentre method +* inherited from the Frame class). + +* Description: +* This function returns an axis value which produces a nice formatted +* value suitable for a major tick mark on a plot axis, close to the +* supplied axis value. + +* Parameters: +* this +* Pointer to the Frame. +* axis +* The number of the axis (zero-based) for which a central value +* is to be found. +* value +* An arbitrary axis value in the section that is being plotted. +* gap +* The gap size. + +* Returned Value: +* The nice central axis value. + +* Notes: +* - A value of zero is returned if the supplied gap size is zero. +* - 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + double result; /* Value to return */ + +/* Check the global error status. */ + if ( !astOK ) return 0.0; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis, 1, "astCentre" ); + +/* Obtain a pointer to the Region's current Frame and invoke this + Frame's astCentre method to obtain the required value. Annul the + Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astCentre( fr, axis, value, gap ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result. */ + if ( !astOK ) result = 0.0; + +/* Return the result. */ + return result; +} + +static void CheckPerm( AstFrame *this_frame, const int *perm, const char *method, int *status ) { +/* +* Name: +* CheckPerm + +* Purpose: +* Check that an array contains a valid permutation. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void CheckPerm( AstFrame *this, const int *perm, const char *method, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astCheckPerm +* method inherited from the Frame class). + +* Description: +* This function checks the validity of a permutation array that +* will be used to permute the order of a Frame's axes. If the +* permutation specified by the array is not valid, an error is +* reported and the global error status is set. Otherwise, the +* function returns without further action. + +* Parameters: +* this +* Pointer to the Frame. +* perm +* Pointer to an array of integers with the same number of +* elements as there are axes in the Frame. For each axis, the +* corresponding integer gives the (zero based) axis index to be +* used to identify the information for that axis (using the +* un-permuted axis numbering). To be valid, the integers in +* this array should therefore all lie in the range zero to +* (naxes-1) inclusive, where "naxes" is the number of Frame +* axes, and each value should occur exactly once. +* method +* Pointer to a constant null-terminated character string +* containing the name of the method that invoked this function +* to validate a permutation array. This method name is used +* solely for constructing error messages. +* status +* Pointer to the inherited status variable. + +* Notes: +* - Error messages issued by this function refer to the external +* (public) numbering system used for axes (which is one-based), +* whereas zero-based axis indices are used internally. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke this + Frame's astCheckPerm method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astCheckPerm( fr, perm, method ); + fr = astAnnul( fr ); + +} + +static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) { +/* +* Name: +* ClearAttrib + +* Purpose: +* Clear an attribute value for a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void ClearAttrib( AstObject *this, const char *attrib, int *status ) + +* Class Membership: +* Region 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 +* Region, so that the default value will subsequently be used. + +* Parameters: +* this +* Pointer to the Region. +* attrib +* Pointer to a null terminated string specifying the attribute +* name. This should be in lower case with no surrounding white +* space. +* status +* Pointer to the inherited status variable. +*/ + +/* Local Variables: */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_object; + +/* Check the attribute name and clear the appropriate attribute. */ + +/* We first handle attributes that apply to the Region as a whole + (rather than to the encapsulated FrameSet). */ + +/* Negated */ +/* ------- */ + if ( !strcmp( attrib, "negated" ) ) { + astClearNegated( this ); + +/* Closed */ +/* ------ */ + } else if ( !strcmp( attrib, "closed" ) ) { + astClearClosed( this ); + +/* FillFactor */ +/* ---------- */ + } else if ( !strcmp( attrib, "fillfactor" ) ) { + astClearFillFactor( this ); + +/* MeshSize */ +/* -------- */ + } else if ( !strcmp( attrib, "meshsize" ) ) { + astClearMeshSize( this ); + +/* Adaptive */ +/* -------- */ + } else if ( !strcmp( attrib, "adaptive" ) ) { + astClearAdaptive( this ); + + +/* We now check for atttributes of superclasses which apply to the Region + as a whole. We do not want to pass these on to the encapsulated FrameSet. */ + +/* ID. */ +/* --- */ + } else if ( !strcmp( attrib, "id" ) ) { + astClearID( this ); + +/* Ident. */ +/* ------ */ + } else if ( !strcmp( attrib, "ident" ) ) { + astClearIdent( this ); + +/* Invert. */ +/* ------- */ + } else if ( !strcmp( attrib, "invert" ) ) { + astClearInvert( this ); + +/* Report. */ +/* ------- */ + } else if ( !strcmp( attrib, "report" ) ) { + astClearReport( this ); + + +/* If the name was not recognised, test if it matches any of the + read-only attributes of this class (including those of all superclasses). + If it does, then report an error. */ + } else if ( !strcmp( attrib, "class" ) || + !strcmp( attrib, "nin" ) || + !strcmp( attrib, "nobject" ) || + !strcmp( attrib, "nout" ) || + !strcmp( attrib, "bounded" ) || + !strcmp( attrib, "refcount" ) || + !strcmp( attrib, "tranforward" ) || + !strcmp( attrib, "traninverse" ) ) { + 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); + +/* Pass unrecognised attributes on to the Region's encapsulated FrameSet for + further interpretation. Do not pass on FrameSet attributes since we + pretend to the outside world that the encapsulated FrameSet is actually a + Frame. */ + } else if ( strcmp( attrib, "base" ) && + strcmp( attrib, "current" ) && + strcmp( attrib, "nframe" ) ) { + +/* If the Region is to adapt to coordinate system chanmges, use the public + astClear method so that the current Frame in the encapsulated FrameSet will + be re-mapped if the attribute changes require it. */ + if( astGetAdaptive( this ) ) { + astClear( this->frameset, attrib ); + +/* If the Region is not to adapt to coordinate system chanmges, use the + astRegSetAttrib method which assigns the attribute setting to both + current and base Frames in the FrameSet without causing any remapping to + be performed. */ + } else { + astRegClearAttrib( this, attrib, NULL ); + } + } +} + +static AstFrameSet *Conv( AstFrameSet *from, AstFrameSet *to, int *status ){ +/* +* Name: +* Conv + +* Purpose: +* Find Mapping between Frames + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstFrameSet *Conv( AstFrameSet *from, AstFrameSet *to, int *status ); + +* Class Membership: +* Region member function + +* Description: +* This function provides a convenient interface for astConvert. +* It is like astConvert except it does not alter the base Frames of +* the supplied FrameSets and does not require a Domain list. + +* Parameters: +* from +* Pointer to the source FrameSet. +* to +* Pointer to the source FrameSet. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* The conversion FrameSet (see astConvert). + +*/ + +/* Local Variables: */ + AstFrameSet *result; /* FrameSet to return */ + int from_base; /* Index of original base Frame in "from" */ + int to_base; /* Index of original base Frame in "to" */ + +/* Check the global error status. */ + if( !astOK ) return NULL; + +/* Note the indices of the base Frames in the FrameSets. */ + to_base = astGetBase( to ); + from_base = astGetBase( from ); + +/* Invoke astConvert. */ + result = astConvert( from, to, "" ); + +/* Re-instate original base Frames. */ + astSetBase( to, to_base ); + astSetBase( from, from_base ); + +/* Return the result. */ + return result; +} + +static AstFrameSet *Convert( AstFrame *from, AstFrame *to, + const char *domainlist, int *status ) { +/* +* Name: +* Convert + +* Purpose: +* Determine how to convert between two coordinate systems. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstFrameSet *Convert( AstFrame *from, AstFrame *to, +* const char *domainlist, int *status ) + +* Class Membership: +* Region member function (over-rides the public astConvert +* method inherited fromm the Frame class). + +* Description: +* This function compares two Regions and determines whether it +* is possible to convert between the coordinate systems which +* their current Frames represent. If conversion is possible, it +* returns a FrameSet which describes the conversion and which may +* be used (as a Mapping) to transform coordinate values in either +* direction. + +* Parameters: +* from +* Pointer to a Region whose current Frame represents the +* "source" coordinate system. Note that the Base attribute of +* the Region may be modified by this function. +* to +* Pointer to a Region whose current Frame represents the +* "destination" coordinate system. Note that the Base +* attribute of the Region may be modified by this function. +* domainlist +* Pointer to a null-terminated character string containing a +* comma-separated list of Frame domains. This may be used to +* define a priority order for the different intermediate +* coordinate systems that might be used to perform the +* conversion. +* +* The function will first try to obtain a conversion by making +* use only of intermediate Frames whose Domain attribute +* matches the first domain in this list. If this fails, the +* second domain in the list will be used, and so on, until +* conversion is achieved. A blank domain (e.g. two consecutive +* commas) indicates that all Frames should be considered, +* regardless of their Domain attributes. The list is +* case-insensitive and all white space is ignored. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* If the requested coordinate conversion is possible, the +* function returns a pointer to a FrameSet which describes the +* conversion. Otherwise, a null Object pointer (AST__NULL) is +* returned without error. +* +* If a FrameSet is returned, it will contain two Frames. Frame +* number 1 (its base Frame) will describe the source coordinate +* system, corresponding to the "from" parameter. Frame number 2 +* (its current Frame) will describe the destination coordinate +* system, corresponding to the "to" parameter. The Mapping +* which inter-relates these Frames will perform the required +* conversion between the two coordinate systems. + +* Notes: +* - The returned FrameSet will not contain any Regions. If one or +* more of the supplied Frames are in fact Regions, the corresponding +* Frames in any returned FrameSet will described the encapsulated +* Frame, without any region information. +* - 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: */ + AstFrameSet *result; /* Returned FrameSet */ + +/* Check the inherited status. */ + if ( !astOK ) return NULL; + +/* If the "from" pointer is a Region, get a pointer to the current Frame of + the encapsulated FrameSet and use it instead of the supplied pointer. */ + if( astIsARegion( from ) ) { + from = astGetFrame( ((AstRegion *) from)->frameset, AST__CURRENT ); + } else { + from = astClone( from ); + } + +/* If the "to" pointer is a Region, get a pointer to the current Frame of + the encapsulated FrameSet and use it instead of the supplied pointer. */ + if( astIsARegion( to ) ) { + to = astGetFrame( ((AstRegion *) to)->frameset, AST__CURRENT ); + } else { + to = astClone( to ); + } + +/* Now invoke astConvert on the above Frames. */ + result = astConvert( from, to, domainlist ); + +/* Annul the pointers used above. */ + from = astAnnul( from ); + to = astAnnul( to ); + +/* Return the result */ + return result; +} + +static AstFrameSet *ConvertX( AstFrame *to, AstFrame *from, + const char *domainlist, int *status ) { +/* +* Name: +* ConvertX + +* Purpose: +* Determine how to convert between two coordinate systems. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstFrameSet *astConvertX( AstFrame *to, AstFrame *from, +* const char *domainlist ) + +* Class Membership: +* Region member function (over-rides the protected astConvertX +* method inherited from the Frame class). + +* Description: +* This function performs the processing for the public astConvert +* method and has exactly the same interface except that the order +* of the first two arguments is swapped. This is a trick to allow +* the astConvert method to be over-ridden by derived classes on +* the basis of the class of either of its first two arguments. +* +* See the astConvert method for details of the interface. +*- +*/ + +/* Local Variables: */ + AstFrameSet *result; /* Returned FrameSet */ + +/* Check the inherited status. */ + if ( !astOK ) return NULL; + +/* If the "to" pointer is a Region, get a pointer to the current Frame of + the encapsulated FrameSet and use it instead of the supplied pointer. */ + if( astIsARegion( to ) ) { + to = astGetFrame( ((AstRegion *) to)->frameset, AST__CURRENT ); + } else { + to = astClone( to ); + } + +/* If the "from" pointer is a Region, get a pointer to the current Frame of + the encapsulated FrameSet and use it instead of the supplied pointer. */ + if( astIsARegion( from ) ) { + from = astGetFrame( ((AstRegion *) from)->frameset, AST__CURRENT ); + } else { + from = astClone( from ); + } + +/* Now invoke astConvertX on the above Frames. */ + result = astConvertX( to, from, domainlist ); + +/* Annul the pointers used above. */ + from = astAnnul( from ); + to = astAnnul( to ); + +/* Return the result */ + return result; +} + +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 "region.h" +* double Distance( AstFrame *this, const double point1[], +* const double point2[], int *status ) + +* Class Membership: +* Region member function (over-rides the protected astDistance +* method inherited from the Frame class). + +* Description: +* This function finds the distance between two points whose +* Region coordinates are given. The distance calculated is that +* along the geodesic curve that joins the two points. + +* Parameters: +* this +* Pointer to the Region. +* point1 +* An array of double, with one element for each Region axis +* containing the coordinates of the first point. +* point2 +* An array of double, with one element for each Region axis +* containing the coordinates of the second point. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* The distance between the two points. + +* 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + double result; /* Value to return */ + +/* Check the global error status. */ + if ( !astOK ) return AST__BAD; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's current Frame and invoke this + Frame's astDistance method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astDistance( fr, point1, point2 ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result. */ + if ( !astOK ) result = AST__BAD; + +/* Return the result. */ + return result; +} + +static int Equal( AstObject *this_object, AstObject *that_object, int *status ) { +/* +* Name: +* Equal + +* Purpose: +* Test if two Objects are equivalent. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int Equal( AstObject *this_object, AstObject *that_object, int *status ) + +* Class Membership: +* Region member function (over-rides the astEqual protected +* method inherited from the Frame class). + +* Description: +* This function returns a boolean result (0 or 1) to indicate whether +* two Regions are equivalent. + +* Parameters: +* this +* Pointer to the first Region. +* that +* Pointer to the second Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* One if the Regions are equivalent, zero otherwise. + +* Notes: +* - The Regions are equivalent if they are of the same class, have +* equal PointSets, have equal base Frames, have equal current Frames, +* and if the Mapping between base Frames is a UnitMap. In addition, the +* Negated attribute must have the same value in both Regions, as must +* the Closed attribute. +* - 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: */ + AstFrame *bf1; + AstFrame *bf2; + AstFrame *cf1; + AstFrame *cf2; + AstMapping *m1; + AstMapping *m2; + AstRegion *that; + AstRegion *this; + const char *class1; + const char *class2; + int result; + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Check that the two objects have the same class. */ + class1 = astGetClass( this_object ); + class2 = astGetClass( that_object ); + if( astOK && !strcmp( class1, class2 ) ) { + +/* Obtain pointers to the two Region structures. */ + this = (AstRegion *) this_object; + that = (AstRegion *) that_object; + +/* Test their PointSets for equality. */ + if( astEqual( this->points, that->points ) ){ + +/* Test their base Frames for equality. */ + bf1 = astGetFrame( this->frameset, AST__BASE ); + bf2 = astGetFrame( that->frameset, AST__BASE ); + if( astEqual( bf1, bf2 ) ){ + +/* Test their current Frames for equality. */ + cf1 = astGetFrame( this->frameset, AST__CURRENT ); + cf2 = astGetFrame( that->frameset, AST__CURRENT ); + if( astEqual( cf1, cf2 ) ){ + +/* Get the two Mappings and check that they are equal */ + m1 = astGetMapping( this->frameset, AST__BASE, AST__CURRENT ); + m2 = astGetMapping( that->frameset, AST__BASE, AST__CURRENT ); + if( astEqual( m1, m2 ) ) { + +/* Test the Negated and Closed flags are equal */ + if( astGetNegated( this ) == astGetNegated( that ) && + astGetClosed( this ) == astGetClosed( that ) ) { + result = 1; + } + } + +/* Free resources. */ + m1 = astAnnul( m1 ); + m2 = astAnnul( m2 ); + } + + cf1 = astAnnul( cf1 ); + cf2 = astAnnul( cf2 ); + } + + bf1 = astAnnul( bf1 ); + bf2 = astAnnul( bf2 ); + } + } + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = 0; + +/* Return the result, */ + return result; +} + +static void ClearUnc( AstRegion *this, int *status ){ +/* +*+ +* Name: +* astClearUnc + +* Purpose: +* Erase any uncertainty information in a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* void astClearUnc( AstRegion *this ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function erases all uncertainty information, whether default +* or not, from a Region. + +* Parameters: +* this +* Pointer to the Region. + +*- +*/ + +/* Check the inherited status. */ + if( !astOK ) return; + +/* Annul any user-supplied uncertainty. Also indicate that cached + information may now be out of date. */ + if( this->unc ) { + this->unc = astAnnul( this->unc ); + astResetCache( this ); + } + +/* Annul any default uncertainty. */ + if( this->defunc ) this->defunc = astAnnul( this->defunc ); + +} + +static AstFrameSet *FindFrame( AstFrame *target_frame, AstFrame *template, + const char *domainlist, int *status ) { +/* +* Name: +* FindFrame + +* Purpose: +* Find a coordinate system with specified characteristics. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstFrameSet *FindFrame( AstFrame *target, AstFrame *template, +* const char *domainlist, int *status ) + +* Class Membership: +* Region member function (over-rides the astFindFrame method +* inherited from the Frame class). + +* Description: +* This function uses a "template" Frame to search a Region to +* identify a coordinate system which has a specified set of +* characteristics. If a suitable coordinate system can be found, +* the function returns a pointer to a FrameSet which describes the +* required coordinate system and how to convert coordinates to and +* from it. + +* Parameters: +* target +* Pointer to the target Region. +* template +* Pointer to the template Frame, which should be an instance of +* the type of Frame you wish to find. +* domainlist +* Pointer to a null-terminated character string containing a +* comma-separated list of Frame domains. This may be used to +* establish a priority order for the different types of +* coordinate system that might be found. +* +* The function will first try to find a suitable coordinate +* system whose Domain attribute equals the first domain in this +* list. If this fails, the second domain in the list will be +* used, and so on, until a result is obtained. A blank domain +* (e.g. two consecutive commas) indicates that any coordinate +* system is acceptable (subject to the template) regardless of +* its domain. +* +* This list is case-insensitive and all white space is ignored. +* If you do not wish to restrict the domain in this way, you +* should supply an empty string. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* If the search is successful, the function returns a pointer to a +* FrameSet which contains the Frame found and a description of how +* to convert to (and from) the coordinate system it +* represents. Otherwise, a null Object pointer (AST__NULL) is +* returned without error. +* +* If a FrameSet is returned, it will contain two Frames. Frame +* number 1 (its base Frame) represents the target coordinate +* system and will be the same as the target. Frame number 2 (its +* current Frame) will be a Frame representing the coordinate system +* which the function found. The Mapping which inter-relates these two +* Frames will describe how to convert between their respective coordinate +* systems. Note, the Frames in this FrameSet will not be Regions - +* that is, they will be simple Frames or other derived classes. + +* Notes: +* - A null Object pointer (AST__NULL) will be returned if this +* function is invoked with the AST error status set, or if it +* should fail for any reason. +*/ + +/* Local Variables: */ + AstFrameSet *result; /* Pointer to result FrameSet */ + AstFrame *fr; /* Pointer to encapsulated Frame */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Invoke the astFindFrame method on the current Frame of the + encapsulated FrameSet within the target Region. */ + fr = astGetFrame( ((AstRegion *) target_frame)->frameset, AST__CURRENT ); + result = astFindFrame( fr, template, domainlist ); + fr = astAnnul( fr ); + +/* 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 Region axis. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* const char *Format( AstFrame *this, int axis, double value, int *status ) + +* Class Membership: +* Region 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 +* Region axis. The formatting applied is that specified by a +* previous invocation of the astSetFormat method. A suitable +* default format is applied if necessary. + +* Parameters: +* this +* Pointer to the Region. +* axis +* The number of the axis (zero-based) for which formatting is +* to be performed. +* value +* The coordinate value to be formatted. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* A pointer to a null-terminated string containing the formatted +* value. + +* Notes: +* - The returned string pointer may point at memory allocated +* within the Region object, 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 deletion +* of the Region. 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + const char *result; /* Pointer value to return */ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis, 1, "astFormat" ); + +/* Obtain a pointer to the Region's current Frame and invoke the + astFormat method for this Frame. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astFormat( fr, axis, value ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = NULL; + +/* Return the result. */ + 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 Region axis values. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* double Gap( AstFrame *this, int axis, double gap, int *ntick, int *status ) + +* Class Membership: +* Region 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 Region 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 Region. +* 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + double result; /* Gap value to return */ + +/* Check the global error status. */ + if ( !astOK ) return 0.0; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis, 1, "astGap" ); + +/* Obtain a pointer to the Region's current Frame and invoke this + Frame's astGap method to obtain the required gap value. Annul the + Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astGap( fr, axis, gap, ntick ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result. */ + 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 "region.h" +* int GetObjSize( AstObject *this, int *status ) + +* Class Membership: +* Region member function (over-rides the astGetObjSize protected +* method inherited from the parent class). + +* Description: +* This function returns the in-memory size of the supplied Region, +* in bytes. + +* Parameters: +* this +* Pointer to the Region. +* 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: */ + AstRegion *this; /* Pointer to Region structure */ + int result; /* Result value to return */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointers to the Region structure. */ + this = (AstRegion *) this_object; + +/* Invoke the GetObjSize method inherited from the parent class, and then + add on any components of the class structure defined by thsi class + which are stored in dynamically allocated memory. */ + result = (*parent_getobjsize)( this_object, status ); + + result += astGetObjSize( this->frameset ); + result += astGetObjSize( this->points ); + result += astGetObjSize( this->basemesh ); + result += astGetObjSize( this->basegrid ); + result += astGetObjSize( this->unc ); + result += astGetObjSize( this->negation ); + result += astGetObjSize( this->defunc ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = 0; + +/* Return the result, */ + return result; +} + +static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) { +/* +* Name: +* GetAttrib + +* Purpose: +* Get the value of a specified attribute for a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* const char *GetAttrib( AstObject *this, const char *attrib, int *status ) + +* Class Membership: +* Region 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 Region, formatted as a character string. + +* Parameters: +* this +* Pointer to the Region. +* attrib +* Pointer to a null-terminated string containing the name of +* the attribute whose value is required. This name should be in +* lower case, with all white space removed. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* - Pointer to a null-terminated string containing the attribute +* value. + +* Notes: +* - The returned string pointer may point at memory allocated +* within the Region, 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 Region. A copy of the string should +* therefore be made if necessary. +* - A NULL pointer will be returned if this function is invoked +* with the global error status set, or if it should fail for any +* reason. +*/ + +/* Local Variables: */ + astDECLARE_GLOBALS /* Pointer to thread-specific global data */ + AstRegion *this; /* Pointer to the Region structure */ + const char *result; /* Pointer value to return */ + double dval; /* Floating point attribute value */ + int ival; /* Integer attribute value */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Get a pointer to the thread specific global data structure. */ + astGET_GLOBALS(this_object); + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_object; + +/* Compare "attrib" with each recognised attribute name in turn, + obtaining the value of the required attribute. If necessary, write + the value into "getattrib_buff" as a null-terminated string in an appropriate + format. Set "result" to point at the result string. */ + +/* We first handle attributes that apply to the Region as a whole + (rather than to the encapsulated FrameSet). */ + +/* Negated */ +/* ------- */ + if ( !strcmp( attrib, "negated" ) ) { + ival = astGetNegated( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* Closed */ +/* ------ */ + } else if ( !strcmp( attrib, "closed" ) ) { + ival = astGetClosed( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* Adaptive */ +/* -------- */ + } else if ( !strcmp( attrib, "adaptive" ) ) { + ival = astGetAdaptive( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* FillFactor */ +/* ---------- */ + } else if ( !strcmp( attrib, "fillfactor" ) ) { + dval = astGetFillFactor( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%.*g", AST__DBL_DIG, dval ); + result = getattrib_buff; + } + +/* MeshSize */ +/* -------- */ + } else if ( !strcmp( attrib, "meshsize" ) ) { + ival = astGetMeshSize( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* Bounded */ +/* ------- */ + } else if ( !strcmp( attrib, "bounded" ) ) { + ival = astGetBounded( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* Now get the values of attributes inherited from parent classes. We do + this to avoid the request being passed on to the encapsulated FrameSet + below. */ + +/* Class. */ +/* ------ */ + } else if ( !strcmp( attrib, "class" ) ) { + result = astGetClass( this ); + +/* ID. */ +/* --- */ + } else if ( !strcmp( attrib, "id" ) ) { + result = astGetID( this ); + +/* Ident. */ +/* ------ */ + } else if ( !strcmp( attrib, "ident" ) ) { + result = astGetIdent( this ); + +/* Invert. */ +/* ------- */ + } else if ( !strcmp( attrib, "invert" ) ) { + ival = astGetInvert( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* Nin. */ +/* ---- */ + } else if ( !strcmp( attrib, "nin" ) ) { + ival = astGetNin( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* Nobject. */ +/* -------- */ + } else if ( !strcmp( attrib, "nobject" ) ) { + ival = astGetNobject( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* Nout. */ +/* ----- */ + } else if ( !strcmp( attrib, "nout" ) ) { + ival = astGetNout( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* RefCount. */ +/* --------- */ + } else if ( !strcmp( attrib, "refcount" ) ) { + ival = astGetRefCount( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* Report. */ +/* ------- */ + } else if ( !strcmp( attrib, "report" ) ) { + ival = astGetReport( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* TranForward. */ +/* ------------ */ + } else if ( !strcmp( attrib, "tranforward" ) ) { + ival = astGetTranForward( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* TranInverse. */ +/* ------------ */ + } else if ( !strcmp( attrib, "traninverse" ) ) { + ival = astGetTranInverse( this ); + if ( astOK ) { + (void) sprintf( getattrib_buff, "%d", ival ); + result = getattrib_buff; + } + +/* Pass unrecognised attributes on to the Region's encapsulated FrameSet for + further interpretation. Do not pass on FrameSet attributes since we + pretend to the outside world that the encapsulated FrameSet is actually a + Frame. */ + } else if ( strcmp( attrib, "base" ) && + strcmp( attrib, "current" ) && + strcmp( attrib, "nframe" ) ) { + result = astGetAttrib( this->frameset, attrib ); + } + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = NULL; + +/* Return the result. */ + return result; +} + +static int GetBounded( AstRegion *this, int *status ) { +/* +*+ +* Name: +* astGetBounded + +* Purpose: +* Is the Region bounded? + +* Type: +* Protected function. + +* Synopsis: +* int astGetBounded( AstRegion *this ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a flag indicating if the Region is bounded. +* The implementation provided by the base Region class is suitable +* for Region sub-classes representing the inside of a single closed +* curve (e.g. Circle, Ellipse, Box, etc). Other sub-classes (such as +* CmpRegion, PointList, etc ) may need to provide their own +* implementations. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* Non-zero if the Region is bounded. Zero otherwise. + +*- +*/ + +/* For Regions which are defined by one or more closed curves such as Circles, + Boxes, etc, the Region is bounded so long as it has not been negated. + Classes for which this is not true should over-ride this implementation. */ + return !astGetNegated( this ); +} + +static AstAxis *GetAxis( AstFrame *this_frame, int axis, int *status ) { +/* +* Name: +* GetAxis + +* Purpose: +* Obtain a pointer to a specified Axis from a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstAxis *GetAxis( AstFrame *this, int axis, int *status ) + +* Class Membership: +* Region member function (over-rides the astGetAxis method +* inherited from the Frame class). + +* Description: +* This function returns a pointer to the Axis object associated +* with one of the axes of the current Frame of a Region. This +* object describes the quantity which is represented along that +* axis. + +* Parameters: +* this +* Pointer to the Region. +* axis +* The number of the axis (zero-based) for which an Axis pointer +* is required. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* A pointer to the requested Axis object. + +* Notes: +* - The reference count of the requested Axis object will be +* incremented by one to reflect the additional pointer returned by +* this function. +* - 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: */ + AstAxis *result; /* Pointer to Axis */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis, 1, "astGetAxis" ); + +/* Obtain a pointer to the Region's encapsulated FrameSet and invoke + this FrameSet's astGetAxis method to obtain the required Axis + pointer. */ + result = astGetAxis( this->frameset, axis ); + +/* If an error occurred, annul the result. */ + if ( !astOK ) result = astAnnul( result ); + +/* Return the result. */ + return result; +} + +static AstRegion *GetDefUnc( AstRegion *this, int *status ) { +/* +*+ +* Name: +* astGetDefUnc + +* Purpose: +* Obtain a pointer to the default uncertainty Region for a given Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstRegion *astGetDefUnc( AstRegion *this ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a pointer to a Region which represents the +* default uncertainty associated with a position on the boundary of the +* given Region. The returned Region refers to the base Frame within the +* FrameSet encapsulated by the supplied Region. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* A pointer to the Region. This should be annulled (using astAnnul) +* when no longer needed. + +* Notes: +* - A NULL pointer will be returned if this function is invoked +* with the global error status set, or if it should fail for any +* reason. +*- +*/ + +/* Local Variables: */ + AstFrame *bfrm; /* Base Frame of supplied Region */ + AstRegion *result; /* Returned pointer */ + double *lbnd; /* Ptr. to array holding axis lower bounds */ + double *ubnd; /* Ptr. to array holding axis upper bounds */ + double c; /* Central axis value */ + double hw; /* Half width of uncertainty interval */ + int i; /* Axis index */ + int nax; /* Number of base Frame axes */ + +/* Initialise */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Get a pointer to the base Frame in the supplied Region. */ + bfrm = astGetFrame( this->frameset, AST__BASE ); + +/* Get the number of base Frame axes. */ + nax = astGetNaxes( bfrm ); + +/* Get the base frame bounding box of the supplied Region. The astRegBaseBox + assumes the supplied Region has not been inverted. But if the Region + contains other Regions (e.g. a Prism or CmpRegion, etc) then this + assumption needs to be propagated to the component Regions, which + astRegBaseBox does not do. For this reason we use astRegBaseBox2 + instead. */ + lbnd = astMalloc( sizeof( double)*(size_t) nax ); + ubnd = astMalloc( sizeof( double)*(size_t) nax ); + astRegBaseBox2( this, lbnd, ubnd ); + +/* Create a Box covering 1.0E-6 of this bounding box, centred on the + centre of the box. */ + if( astOK ) { + for( i = 0; i < nax; i++ ) { + if( ubnd[ i ] != DBL_MAX && lbnd[ i ] != -DBL_MAX ) { + hw = fabs( 0.5E-6*( ubnd[ i ] - lbnd[ i ] ) ); + c = 0.5*( ubnd[ i ] + lbnd[ i ] ); + if( hw == 0.0 ) hw = c*0.5E-6; + ubnd[ i ] = c + hw; + lbnd[ i ] = c - hw; + } else { + ubnd[ i ] = 0.0; + lbnd[ i ] = 0.0; + } + } + result = (AstRegion *) astBox( bfrm, 1, lbnd, ubnd, NULL, "", status ); + } + +/* Free resources. */ + lbnd = astFree( lbnd ); + ubnd = astFree( ubnd ); + bfrm = astAnnul( bfrm ); + +/* Return NULL if an error occurred. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the required pointer. */ + return result; +} + +static AstRegion *GetNegation( AstRegion *this, int *status ) { +/* +*+ +* Name: +* astGetNegation + +* Purpose: +* Obtain a pointer to a negated copy of the supplied Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstRegion *GetNegation( AstRegion *this, int *status ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a pointer to a Region which is a negated +* copy of "this". The copy is cached in the Region structure for +* future use. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* A pointer to the Region. This should be annulled (using astAnnul) +* when no longer needed. + +* Notes: +* - A NULL pointer will be returned if this function is invoked +* with the global error status set, or if it should fail for any +* reason. +*- +*/ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* If the Region struture does not contain a pointer to a negated copy of + itself, create one now. */ + if( ! this->negation ) { + this->negation = astCopy( this ); + astNegate( this->negation ); + } + +/* Return a clone of the negation pointer. */ + return astClone( this->negation ); +} + +static AstFrameSet *GetRegFS( AstRegion *this, int *status ) { +/* +*+ +* Name: +* astGetRegFS + +* Purpose: +* Obtain a pointer to the FrameSet encapsulated within a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstFrameSet *astGetRegFS( AstRegion *this ) + +* Class Membership: +* Region virtual function + +* Description: +* This function returns a pointer to the FrameSet encapsulated by the +* Region. This is a clone, not a deep copy, of the pointer stored +* in the Region. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* A pointer to the FrameSet. + +* 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. +*- +*/ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Return the required pointer. */ + return astClone( this->frameset ); +} + +static AstPointSet *GetSubMesh( int *mask, AstPointSet *in, int *status ) { +/* +* Name: +* GetSubMesh + +* Purpose: +* Extract a selection of points from a PointSet. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstPointSet *GetSubMesh( int *mask, AstPointSet *in, int *status ) + +* Class Membership: +* Region member function + +* Description: +* This function creates a new PointSet holding points selected from a +* supplied PointSet. An integer mask is supplied to indicate which +* points should be selected. + +* Parameters: +* mask +* Pointer to a mask array, Its size should be equal to the number +* of points in the supplied PointSet. Each corresponding point will +* be copied if the mask value is zero. +* in +* Pointer to the PointSet holding the input positions. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* Pointer to the output PointSet. + +* Notes: +* - A null pointer will be returned if this function is invoked +* with the global error status set, or if it should fail for any +* reason. +*/ + +/* Local Variables: */ + AstPointSet *result; /* Pointer to output PointSet */ + double **ptr_in; /* Pointers to input axis values */ + double **ptr_out; /* Pointers to output axis values */ + double *pin; /* Pointer to next input axis value */ + double *pout; /* Pointer to next output axis value */ + int *m; /* Pointer to next mask element */ + int ic; /* Axis index */ + int ip; /* Point index */ + int nc; /* Number of axes in both PointSets */ + int npin; /* Number of points in input PointSet */ + int npout; /* Number of points in output PointSet */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Get the length of the mask. */ + npin = astGetNpoint( in ); + +/* Count the number of zeros in the mask. */ + npout = 0; + m = mask; + for( ip = 0; ip < npin; ip++ ) { + if( *(m++) == 0 ) npout++; + } + +/* Create the output PointSet and get pointers to its data arrays. */ + nc = astGetNcoord( in ); + result = astPointSet( npout, nc, "", status ); + ptr_in = astGetPoints( in ); + ptr_out = astGetPoints( result ); + +/* Check pointers can be dereferenced safely. */ + if( astOK ) { + +/* Copy the required axis values from the input to the output. */ + for( ic = 0; ic < nc; ic++ ) { + pin = ptr_in[ ic ]; + pout = ptr_out[ ic ]; + m = mask; + for( ip = 0; ip < npin; ip++, pin++, m++ ) { + if( *m == 0 ) *(pout++) = *pin; + } + } + } + +/* Return a pointer to the output PointSet. */ + return result; + +} + +static AstRegion *GetUnc( AstRegion *this, int def, int *status ){ +/* +*++ +* Name: +c astGetUnc +f AST_GETUNC + +* Purpose: +* Obtain uncertainty information from a Region. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c AstRegion *astGetUnc( AstRegion *this, int def ) +f RESULT = AST_GETUNC( THIS, DEF, STATUS ) + +* Class Membership: +* Region method. + +* Description: +* This function returns a Region which represents the uncertainty +* associated with positions within the supplied Region. See +c astSetUnc +f AST_SETUNC +* for more information about Region uncertainties and their use. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region. +c def +f DEF = LOGICAL (Given) +* Controls what is returned if no uncertainty information has been +* associated explicitly with the supplied Region. If +c a non-zero value +f .TRUE. +* is supplied, then the default uncertainty Region used internally +* within AST is returned (see "Applicability" below). If +c zero is supplied, then NULL +f .FALSE. is supplied, then AST__NULL +* will be returned (without error). +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Returned Value: +c astGetUnc() +f AST_GETUNC = INTEGER +* A pointer to a Region describing the uncertainty in the supplied +* Region. + +* Applicability: +* CmpRegion +* The default uncertainty for a CmpRegion is taken from one of the +* two component Regions. If the first component Region has a +* non-default uncertainty, then it is used as the default uncertainty +* for the parent CmpRegion. Otherwise, if the second component Region +* has a non-default uncertainty, then it is used as the default +* uncertainty for the parent CmpRegion. If neither of the +* component Regions has non-default uncertainty, then the default +* uncertainty for the CmpRegion is 1.0E-6 of the bounding box of +* the CmpRegion. +* Prism +* The default uncertainty for a Prism is formed by combining the +* uncertainties from the two component Regions. If a component +* Region does not have a non-default uncertainty, then its default +* uncertainty will be used to form the default uncertainty of the +* parent Prism. +* Region +* For other classes of Region, the default uncertainty is 1.0E-6 +* of the bounding box of the Region. If the bounding box has zero +* width on any axis, then the uncertainty will be 1.0E-6 of the +* axis value. + +* Notes: +* - If uncertainty information is associated with a Region, and the +* coordinate system described by the Region is subsequently changed +* (e.g. by changing the value of its System attribute, or using the +c astMapRegion +f AST_MAPREGION +* function), then the uncertainty information returned by this function +* will be modified so that it refers to the coordinate system currently +* described by the supplied Region. +f - A null Object pointer (AST__NULL) will be returned if this +f function is invoked with STATUS set to an error value, or if it +c - A null Object pointer (NULL) will be returned if this +c function is invoked with the AST error status set, or if it +* should fail for any reason. + +*-- +*/ + +/* Local Variables: */ + AstRegion *result; /* Pointer to returned uncertainty Region */ + AstRegion *unc; /* Pointer to original uncertainty Region */ + +/* Initialise */ + result = NULL; + +/* Check inherited status */ + if( !astOK ) return result; + +/* Check that we have an uncertainty Region to return (either assigned or + default). */ + if( def || astTestUnc( this ) ) { + +/* Obtain the uncertainty Region and take a copy so that we can modify it + without affecting the supplied Region. */ + unc = astGetUncFrm( this, AST__CURRENT ); + result = astCopy( unc ); + unc = astAnnul( unc ); + +/* In its current context, the uncertainty region is known to refer to + the Frame of the supplied Region and so its RegionFS attribute will be + set to zero, indicating that the uncertainty FrameSet need not be + dumped. However, outside of AST this information cannot be implied, so + clear the RegionFS attribute so that the returned pointer will include + Frame information if it is dumped to a Channel. */ + astClearRegionFS( result ); + + } + +/* Return the result. */ + return result; + +} + +static AstRegion *GetUncFrm( AstRegion *this, int ifrm, int *status ) { +/* +*+ +* Name: +* astGetUncFrm + +* Purpose: +* Obtain a pointer to the uncertainty Region for a given Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstRegion *astGetUncFrm( AstRegion *this, int ifrm ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a pointer to a Region which represents the +* uncertainty associated with a position on the boundary of the given +* Region. The returned Region can refer to the either the base or +* the current Frame within the FrameSet encapsulated by the supplied +* Region as specified by the "ifrm" parameter. If the returned Region is +* re-centred at some point on the boundary of the supplied Region, then +* the re-centred Region will represent the region in which the true +* boundary position could be. + +* Parameters: +* this +* Pointer to the Region. +* ifrm +* The index of a Frame within the FrameSet encapsulated by "this". +* The returned Region will refer to the requested Frame. It should +* be either AST__CURRENT or AST__BASE. + +* Returned Value: +* A pointer to the Region. This should be annulled (using astAnnul) +* when no longer needed. + +* Notes: +* - A default uncertainty Region will be created if the supplied Region +* does not have an uncertainty Region. +* - 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: */ + AstFrame *frm; /* Current Frame from supplied Region */ + AstMapping *map; /* Supplied to uncertainty Mapping */ + AstRegion *result; /* Returned pointer */ + AstRegion *unc; /* Base frame uncertainty Region to use */ + +/* Initialise */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* If the Region has an explicitly assigned base-frame uncertainty Region, + use it. */ + if( this->unc ) { + unc = this->unc; + +/* If not, use the default base-frame uncertainty Region, creating it if + necessary. */ + } else { + if( !this->defunc ) this->defunc = astGetDefUnc( this ); + unc = this->defunc; + } + +/* If the uncertainty Region is the base Frame is required, just return a + clone of the uncertainty Region pointer. The Frame represented by an + uncertainty Region will always (barring bugs!) be the base Frame of + its parent Region. */ + if( ifrm == AST__BASE ) { + result = astClone( unc ); + +/* If the uncertainty Region is the current Frame is required... */ + } else { + +/* Get a Mapping from the Frame represented by the uncertainty Region + (the Region base Frame) to the Region current Frame. */ + map = astGetMapping( this->frameset, AST__BASE, AST__CURRENT ); + +/* If this is a UnitMap, the uncertainty Region is already in the correct + Frame, so just return the stored pointer. */ + if( astIsAUnitMap( map ) ) { + result = astClone( unc ); + +/* Otherwise, use this Mapping to map the uncertainty Region into the current + Frame. */ + } else { + frm = astGetFrame( this->frameset, AST__CURRENT ); + result = astMapRegion( unc, map, frm ); + +/* Free resources. */ + frm = astAnnul( frm ); + } + + map = astAnnul( map ); + } + +/* Return NULL if an error occurred. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the required pointer. */ + return result; +} + +static int GetUseDefs( AstObject *this_object, int *status ) { +/* +* Name: +* GetUseDefs + +* Purpose: +* Get the value of the UseDefs attribute for a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int GetUseDefs( AstObject *this_object, int *status ) { + +* Class Membership: +* Region member function (over-rides the protected astGetUseDefs +* method inherited from the Frame class). + +* Description: +* This function returns the value of the UseDefs attribute for a +* Region. supplying a suitable default. + +* Parameters: +* this +* Pointer to the Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* - The USeDefs value. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + int result; /* Value to return */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_object; + +/* If the UseDefs value for the Region has been set explicitly, use the + Get method inherited from the parent Frame class to get its value. */ + if( astTestUseDefs( this ) ) { + result = (*parent_getusedefs)( this_object, status ); + +/* Otherwise, supply a default value equal to the UseDefs value of the + encapsulated Frame. */ + } else { + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astGetUseDefs( fr ); + fr = astAnnul( fr ); + } + +/* Return the result. */ + return result; +} + +static int TestUnc( AstRegion *this, int *status ) { +/* +*+ +* Name: +* astTestUnc + +* Purpose: +* Does the Region contain non-default uncertainty information? + +* Type: +* Protected function. + +* Synopsis: +* int astTestUnc( AstRegion *this ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a flag indicating if the uncertainty Region in +* the supplied Region was supplied explicit (i.e. is not a default +* uncertainty Region). + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* Non-zero if the uncertainty Region was supplied explicitly. +* Zero otherwise. + +* Notes: +* - Classes of Region that encapsulate two or more other Regions +* inherit their default uncertainty from the encapsulated Regions. +* Non-default uncertainty in the component Regions does not imply +* that the parent Region has non-default uncertainty. +*- +*/ + +/* Check the global error status. */ + if ( !astOK ) return 0; + + return ( this->unc != NULL ); +} + +static AstFrame *RegFrame( AstRegion *this, int *status ) { +/* +*+ +* Name: +* astRegFrame + +* Purpose: +* Obtain a pointer to the current Frame for a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstFrame *astRegFrame( AstRegion *this ) + +* Class Membership: +* Region virtual function + +* Description: +* This function returns a pointer to the current Frame in the encapsulated +* FrameSet. This is a clone, not a deep copy, of the pointer stored +* in the FrameSet. For a deep copy, use astGetRegionFrame. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* A pointer to the Frame. + +* 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. +*- +*/ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Return the required pointer. */ + return astGetFrame( this->frameset, AST__CURRENT ); +} + +static AstMapping *RegMapping( AstRegion *this, int *status ) { +/* +*+ +* Name: +* astRegMapping + +* Purpose: +* Obtain a pointer to the simplified base->current Mapping for a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstMapping *astRegMapping( AstRegion *this ) + +* Class Membership: +* Region member function + +* Description: +* This function returns a pointer to the Mapping from the base to the +* current Frame int he encapsulated FrameSet. The returned Mapping is +* simplified before being returned. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* A pointer to the Mapping. + +* 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: */ + AstMapping *map; /* Unsimplified Mapping */ + AstMapping *result; /* Simplified Mapping */ + +/* Initialise */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* If the "nomap" flag is set in the Region structure, re return a + UnitMap. */ + if( this->nomap ) { + result = (AstMapping *) astUnitMap( astGetNin( this->frameset ), "", status ); + +/* Otherwise use the Mapping from the Region's FrameSet. */ + } else { + +/* Get the Mapping */ + map = astGetMapping( this->frameset, AST__BASE, AST__CURRENT ); + +/* Simplify it. */ + result = astSimplify( map ); + +/* Annul the pointer to the unsimplified Mapping */ + map = astAnnul( map ); + } + +/* Return the required pointer. */ + return result; +} + +static int GetNaxes( AstFrame *this_frame, int *status ) { +/* +* Name: +* GetNaxes + +* Purpose: +* Determine how many axes a Region has. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int GetNaxes( AstFrame *this, int *status ) + +* Class Membership: +* Region member function (over-rides the astGetNaxes method +* inherited from the Frame class). + +* Description: +* This function returns the number of axes for a Region. This is equal +* to the number of axes in its current Frame. + +* Parameters: +* this +* Pointer to the Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* The number of Region axes (zero or more). + +* 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + int result; /* Result to be returned */ + +/* Check the global error status. */ + if ( !astOK ) return 0; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's current Frame. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + +/* Obtain the number of axes in this Frame. */ + result = astGetNaxes( fr ); + +/* Annul the current Frame pointer. */ + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = 0; + +/* Return the result. */ + return result; +} + +static const int *GetPerm( AstFrame *this_frame, int *status ) { +/* +* Name: +* GetPerm + +* Purpose: +* Access the axis permutation array for the current Frame of a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* const int *GetPerm( AstFrame *this, int *status ) + +* Class Membership: +* Region member function (over-rides the astGetPerm protected +* method inherited from the Frame class). + +* Description: +* This function returns a pointer to the axis permutation array +* for the current Frame of a Region. This array constitutes a +* lookup-table that converts between an axis number supplied +* externally and the corresponding index in the Frame's internal +* axis arrays. + +* Parameters: +* this +* Pointer to the Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* Pointer to the current Frame's axis permutation array (a +* constant array of int). Each element of this contains the +* (zero-based) internal axis index to be used in place of the +* external index which is used to address the permutation +* array. If the current Frame has zero axes, this pointer will be +* NULL. + +* Notes: +* - The pointer returned by this function gives direct access to +* data internal to the Frame object. It remains valid only so long +* as the Frame exists. The permutation array contents may be +* modified by other functions which operate on the Frame and this +* may render the returned pointer invalid. +* - 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to Region structure */ + const int *result; /* Result pointer value */ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's current Frame and then obtain a + pointer to its axis permutation array. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astGetPerm( fr ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = NULL; + +/* Return the result. */ + return result; +} + +static AstFrame *GetRegionFrame( AstRegion *this, int *status ) { +/* +*++ +* Name: +c astGetRegionFrame +f AST_GETREGIONFRAME + +* Purpose: +* Obtain a pointer to the encapsulated Frame within a Region. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c AstFrame *astGetRegionFrame( AstRegion *this ) +f RESULT = AST_GETREGIONFRAME( THIS, STATUS ) + +* Class Membership: +* Region method. + +* Description: +* This function returns a pointer to the Frame represented by a +* Region. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region. +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Returned Value: +c astGetRegionFrame() +f AST_GETREGIONFRAME = INTEGER +* A pointer to a deep copy of the Frame represented by the Region. +* Using this pointer to modify the Frame will have no effect on +* the Region. To modify the Region, use the Region pointer directly. + +* 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstFrame *result; /* Pointer value to return */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Get a pointer to the current Frame of the encapsulated FrameSet. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + +/* Take a deep copy of it, and then annul the original pointer. */ + result = astCopy( fr ); + fr = astAnnul( fr ); + +/* If not OK, annul the returned pointer. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the result. */ + return result; +} + +static AstFrameSet *GetRegionFrameSet( AstRegion *this, int *status ) { +/* +*++ +* Name: +c astGetRegionFrameSet +f AST_GETREGIONFRAMESET + +* Purpose: +* Obtain a pointer to the encapsulated FrameSet within a Region. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c AstFrame *astGetRegionFrameSet( AstRegion *this ) +f RESULT = AST_GETREGIONFRAMESET( THIS, STATUS ) + +* Class Membership: +* Region method. + +* Description: +* This function returns a pointer to the FrameSet encapsulated by a +* Region. The base Frame is the Frame in which the box was originally +* defined, and the current Frame is the Frame into which the Region +* is currently mapped (i.e. it will be the same as the Frame returned +c by astGetRegionFrame). +f by AST_GETREGIONFRAME). + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region. +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Returned Value: +c astGetRegionFrameSet() +f AST_GETREGIONFRAMESET = INTEGER +* A pointer to a deep copy of the FrameSet represented by the Region. +* Using this pointer to modify the FrameSet will have no effect on +* the Region. + +* 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. +*-- +*/ + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* Return a deep copy of the encapsulated FrameSet. */ + return astCopy( this->frameset ); +} + +void astInitRegionVtab_( AstRegionVtab *vtab, const char *name, int *status ) { +/* +*+ +* Name: +* astInitRegionVtab + +* Purpose: +* Initialise a virtual function table for a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* void astInitRegionVtab( AstRegionVtab *vtab, const char *name ) + +* Class Membership: +* Region vtab initialiser. + +* Description: +* This function initialises the component of a virtual function +* table which is used by the Region class. + +* Parameters: +* vtab +* Pointer to the virtual function table. The components used by +* all ancestral classes will be initialised if they have not already +* been initialised. +* name +* Pointer to a constant null-terminated character string which contains +* the name of the class to which the virtual function table belongs (it +* is this pointer value that will subsequently be returned by the Object +* astClass function). +*- +*/ + +/* Local Variables: */ + astDECLARE_GLOBALS /* Pointer to thread-specific global data */ + AstFrameVtab *frame; /* Pointer to Frame component of Vtab */ + AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */ + AstObjectVtab *object; /* Pointer to Object component of Vtab */ + +/* 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 astIsARegion) 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->ClearNegated = ClearNegated; + vtab->GetNegated = GetNegated; + vtab->SetNegated = SetNegated; + vtab->TestNegated = TestNegated; + + vtab->ClearRegionFS = ClearRegionFS; + vtab->GetRegionFS = GetRegionFS; + vtab->SetRegionFS = SetRegionFS; + vtab->TestRegionFS = TestRegionFS; + + vtab->ClearClosed = ClearClosed; + vtab->GetClosed = GetClosed; + vtab->SetClosed = SetClosed; + vtab->TestClosed = TestClosed; + + vtab->ClearMeshSize = ClearMeshSize; + vtab->GetMeshSize = GetMeshSize; + vtab->SetMeshSize = SetMeshSize; + vtab->TestMeshSize = TestMeshSize; + + vtab->ClearAdaptive = ClearAdaptive; + vtab->GetAdaptive = GetAdaptive; + vtab->SetAdaptive = SetAdaptive; + vtab->TestAdaptive = TestAdaptive; + + vtab->ClearFillFactor = ClearFillFactor; + vtab->GetFillFactor = GetFillFactor; + vtab->SetFillFactor = SetFillFactor; + vtab->TestFillFactor = TestFillFactor; + + vtab->ResetCache = ResetCache; + vtab->RegTrace = RegTrace; + vtab->GetBounded = GetBounded; + vtab->TestUnc = TestUnc; + vtab->ClearUnc = ClearUnc; + vtab->GetRegionFrame = GetRegionFrame; + vtab->GetRegionFrameSet = GetRegionFrameSet; + vtab->MapRegion = MapRegion; + vtab->Overlap = Overlap; + vtab->OverlapX = OverlapX; + vtab->Negate = Negate; + vtab->BndMesh = BndMesh; + vtab->BndBaseMesh = BndBaseMesh; + vtab->RegBaseGrid = RegBaseGrid; + vtab->RegBaseMesh = RegBaseMesh; + vtab->RegSplit = RegSplit; + vtab->RegBaseBox = RegBaseBox; + vtab->RegBaseBox2 = RegBaseBox2; + vtab->RegBasePick = RegBasePick; + vtab->RegCentre = RegCentre; + vtab->RegGrid = RegGrid; + vtab->RegMesh = RegMesh; + vtab->RegClearAttrib = RegClearAttrib; + vtab->RegSetAttrib = RegSetAttrib; + vtab->GetDefUnc = GetDefUnc; + vtab->GetNegation = GetNegation; + vtab->GetUncFrm = GetUncFrm; + vtab->SetUnc = SetUnc; + vtab->GetUnc = GetUnc; + vtab->ShowMesh = ShowMesh; + vtab->GetRegionBounds = GetRegionBounds; + vtab->GetRegionBounds2 = GetRegionBounds2; + vtab->GetRegionMesh = GetRegionMesh; + vtab->GetRegionPoints = GetRegionPoints; + vtab->RegOverlay = RegOverlay; + vtab->RegFrame = RegFrame; + vtab->RegDummyFS = RegDummyFS; + vtab->RegMapping = RegMapping; + vtab->RegPins = RegPins; + vtab->RegTransform = RegTransform; + vtab->BTransform = BTransform; + vtab->GetRegFS = GetRegFS; + vtab->SetRegFS = SetRegFS; + vtab->MaskB = MaskB; + vtab->MaskD = MaskD; + vtab->MaskF = MaskF; + vtab->MaskI = MaskI; + vtab->MaskL = MaskL; + vtab->MaskS = MaskS; + vtab->MaskUB = MaskUB; + vtab->MaskUI = MaskUI; + vtab->MaskUL = MaskUL; + vtab->MaskUS = MaskUS; +#if HAVE_LONG_DOUBLE /* Not normally implemented */ + vtab->MaskLD = MaskLD; +#endif + +/* Save the inherited pointers to methods that will be extended, and store + replacement pointers for methods which will be over-ridden by new member + functions implemented here. */ + object = (AstObjectVtab *) vtab; + mapping = (AstMappingVtab *) vtab; + frame = (AstFrameVtab *) vtab; + + parent_getobjsize = object->GetObjSize; + object->GetObjSize = GetObjSize; + + parent_getusedefs = object->GetUseDefs; + object->GetUseDefs = GetUseDefs; + +#if defined(THREAD_SAFE) + parent_managelock = object->ManageLock; + object->ManageLock = ManageLock; +#endif + + object->Cast = Cast; + object->Equal = Equal; + object->ClearAttrib = ClearAttrib; + object->GetAttrib = GetAttrib; + object->SetAttrib = SetAttrib; + object->TestAttrib = TestAttrib; + + mapping->ReportPoints = ReportPoints; + mapping->RemoveRegions = RemoveRegions; + mapping->Simplify = Simplify; + + frame->Abbrev = Abbrev; + frame->Angle = Angle; + frame->AxAngle = AxAngle; + frame->AxDistance = AxDistance; + frame->AxNorm = AxNorm; + frame->AxOffset = AxOffset; + frame->CheckPerm = CheckPerm; + frame->ClearDigits = ClearDigits; + frame->ClearDirection = ClearDirection; + frame->ClearDomain = ClearDomain; + frame->ClearFormat = ClearFormat; + frame->ClearLabel = ClearLabel; + frame->ClearMatchEnd = ClearMatchEnd; + frame->ClearMaxAxes = ClearMaxAxes; + frame->ClearMinAxes = ClearMinAxes; + frame->ClearPermute = ClearPermute; + frame->ClearPreserveAxes = ClearPreserveAxes; + frame->ClearSymbol = ClearSymbol; + frame->ClearTitle = ClearTitle; + frame->ClearUnit = ClearUnit; + frame->Convert = Convert; + frame->ConvertX = ConvertX; + frame->Distance = Distance; + frame->FindFrame = FindFrame; + frame->Format = Format; + frame->Centre = Centre; + frame->Gap = Gap; + frame->GetAxis = GetAxis; + frame->GetDigits = GetDigits; + frame->GetDirection = GetDirection; + frame->GetDomain = GetDomain; + frame->GetFormat = GetFormat; + frame->GetLabel = GetLabel; + frame->GetMatchEnd = GetMatchEnd; + frame->GetMaxAxes = GetMaxAxes; + frame->GetMinAxes = GetMinAxes; + frame->GetNaxes = GetNaxes; + frame->GetPerm = GetPerm; + frame->GetPermute = GetPermute; + frame->GetPreserveAxes = GetPreserveAxes; + frame->GetSymbol = GetSymbol; + frame->GetTitle = GetTitle; + frame->GetUnit = GetUnit; + frame->Intersect = Intersect; + frame->IsUnitFrame = IsUnitFrame; + frame->Match = Match; + frame->Norm = Norm; + frame->NormBox = NormBox; + frame->Offset = Offset; + frame->Offset2 = Offset2; + frame->Overlay = Overlay; + frame->PermAxes = PermAxes; + frame->PickAxes = PickAxes; + frame->Resolve = Resolve; + frame->ResolvePoints = ResolvePoints; + frame->SetAxis = SetAxis; + frame->SetDigits = SetDigits; + frame->SetDirection = SetDirection; + frame->SetDomain = SetDomain; + frame->SetFormat = SetFormat; + frame->SetLabel = SetLabel; + frame->SetMatchEnd = SetMatchEnd; + frame->SetMaxAxes = SetMaxAxes; + frame->SetMinAxes = SetMinAxes; + frame->SetPermute = SetPermute; + frame->SetPreserveAxes = SetPreserveAxes; + frame->SetSymbol = SetSymbol; + frame->SetTitle = SetTitle; + frame->SetUnit = SetUnit; + frame->SubFrame = SubFrame; + frame->SystemCode = SystemCode; + frame->SystemString = SystemString; + frame->TestDigits = TestDigits; + frame->TestDirection = TestDirection; + frame->TestDomain = TestDomain; + frame->TestFormat = TestFormat; + frame->TestLabel = TestLabel; + frame->TestMatchEnd = TestMatchEnd; + frame->TestMaxAxes = TestMaxAxes; + frame->TestMinAxes = TestMinAxes; + frame->TestPermute = TestPermute; + frame->TestPreserveAxes = TestPreserveAxes; + frame->TestSymbol = TestSymbol; + frame->TestTitle = TestTitle; + frame->TestUnit = TestUnit; + frame->Unformat = Unformat; + frame->ValidateAxis = ValidateAxis; + frame->ValidateAxisSelection = ValidateAxisSelection; + frame->ValidateSystem = ValidateSystem; + frame->LineDef = LineDef; + frame->LineContains = LineContains; + frame->LineCrossing = LineCrossing; + frame->LineOffset = LineOffset; + frame->MatchAxes = MatchAxes; + frame->MatchAxesX = MatchAxesX; + + frame->GetActiveUnit = GetActiveUnit; + frame->SetActiveUnit = SetActiveUnit; + frame->TestActiveUnit = TestActiveUnit; + + frame->GetTop = GetTop; + frame->SetTop = SetTop; + frame->TestTop = TestTop; + frame->ClearTop = ClearTop; + + frame->GetBottom = GetBottom; + frame->SetBottom = SetBottom; + frame->TestBottom = TestBottom; + frame->ClearBottom = ClearBottom; + + frame->GetEpoch = GetEpoch; + frame->SetEpoch = SetEpoch; + frame->TestEpoch = TestEpoch; + frame->ClearEpoch = ClearEpoch; + + frame->ClearObsAlt = ClearObsAlt; + frame->TestObsAlt = TestObsAlt; + frame->GetObsAlt = GetObsAlt; + frame->SetObsAlt = SetObsAlt; + + frame->ClearObsLat = ClearObsLat; + frame->TestObsLat = TestObsLat; + frame->GetObsLat = GetObsLat; + frame->SetObsLat = SetObsLat; + + frame->ClearObsLon = ClearObsLon; + frame->TestObsLon = TestObsLon; + frame->GetObsLon = GetObsLon; + frame->SetObsLon = SetObsLon; + + frame->GetSystem = GetSystem; + frame->SetSystem = SetSystem; + frame->TestSystem = TestSystem; + frame->ClearSystem = ClearSystem; + + frame->GetAlignSystem = GetAlignSystem; + frame->SetAlignSystem = SetAlignSystem; + frame->TestAlignSystem = TestAlignSystem; + frame->ClearAlignSystem = ClearAlignSystem; + +/* Declare the copy constructor, destructor and class dump + functions. */ + astSetDelete( vtab, Delete ); + astSetCopy( vtab, Copy ); + astSetDump( vtab, Dump, "Region", + "An area within a coordinate system" ); + +/* 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 "region.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: +* Region 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke the + astIntersect method for this Frame. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astIntersect( fr, a1, a2, b1, b2, cross ); + fr = astAnnul( fr ); +} + +static int IsUnitFrame( AstFrame *this, int *status ){ +/* +* Name: +* IsUnitFrame + +* Purpose: +* Is this Frame equivalent to a UnitMap? + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int IsUnitFrame( AstFrame *this, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astIsUnitFrame +* method inherited from the Frame class). + +* Description: +* This function returns a flag indicating if the supplied Frame is +* equivalent to a UnitMap when treated as a Mapping (note, the Frame +* class inherits from Mapping and therefore every Frame is also a Mapping). + +* Parameters: +* this +* Pointer to the Frame. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* A non-zero value is returned if the supplied Frame is equivalent to +* a UnitMap when treated as a Mapping. + +*- +*/ + +/* Check the global error status. */ + if( !astOK ) return 0; + +/* The Region class is never equivalent to a UnitMap. */ + return 0; +} + +static int LineContains( AstFrame *this_frame, AstLineDef *l, int def, double *point, int *status ) { +/* +* Name: +* LineContains + +* Purpose: +* Determine if a line contains a point. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int LineContains( AstFrame *this, AstLineDef *l, int def, double *point, int *status ) + +* Class Membership: +* Region 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: */ + AstFrame *fr; /* Pointer to current Frame */ + int result; /* Returned value */ + +/* Initialise */ + result =0; + +/* Obtain a pointer to the Region's current Frame and then invoke the + method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( ((AstRegion *) this_frame)->frameset, AST__CURRENT ); + result = astLineContains( fr, l, def, point ); + fr = astAnnul( fr ); + +/* Return the result. */ + return result; +} + +static int LineCrossing( AstFrame *this_frame, AstLineDef *l1, AstLineDef *l2, + double **cross, int *status ) { +/* +* Name: +* LineCrossing + +* Purpose: +* Determine if two lines cross. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int LineCrossing( AstFrame *this, AstLineDef *l1, AstLineDef *l2, +* double **cross, int *status ) + +* Class Membership: +* Region 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: */ + AstFrame *fr; /* Pointer to current Frame */ + int result; /* Returned value */ + +/* Initialise */ + result =0; + +/* Obtain a pointer to the Region's current Frame and then invoke the + method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( ((AstRegion *) this_frame)->frameset, AST__CURRENT ); + result = astLineCrossing( fr, l1, l2, cross ); + fr = astAnnul( fr ); + +/* Return the result. */ + return result; +} + +static AstLineDef *LineDef( AstFrame *this_frame, 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 "region.h" +* AstLineDef *LineDef( AstFrame *this, const double start[2], +* const double end[2], int *status ) + +* Class Membership: +* Region 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstLineDef *result; /* Returned value */ + +/* Initialise */ + result = NULL; + +/* Obtain a pointer to the Region's current Frame and then invoke the + method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( ((AstRegion *) this_frame)->frameset, AST__CURRENT ); + result = astLineDef( fr, start, end ); + fr = astAnnul( fr ); + +/* Return the result. */ + return result; +} + +static void LineOffset( AstFrame *this_frame, 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 "region.h" +* void LineOffset( AstFrame *this, AstLineDef *line, double par, +* double prp, double point[2], int *status ) + +* Class Membership: +* Region 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: */ + AstFrame *fr; /* Pointer to current Frame */ + +/* Obtain a pointer to the Region's current Frame and then invoke the + method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( ((AstRegion *) this_frame)->frameset, AST__CURRENT ); + astLineOffset( fr, line, par, prp, point ); + fr = astAnnul( fr ); +} + + +#if defined(THREAD_SAFE) +static int ManageLock( AstObject *this_object, int mode, int extra, + AstObject **fail, int *status ) { +/* +* Name: +* ManageLock + +* Purpose: +* Manage the thread lock on an Object. + +* Type: +* Private function. + +* Synopsis: +* #include "object.h" +* AstObject *ManageLock( AstObject *this, int mode, int extra, +* AstObject **fail, int *status ) + +* Class Membership: +* Region member function (over-rides the astManageLock protected +* method inherited from the parent class). + +* Description: +* This function manages the thread lock on the supplied Object. The +* lock can be locked, unlocked or checked by this function as +* deteremined by parameter "mode". See astLock for details of the way +* these locks are used. + +* Parameters: +* this +* Pointer to the Object. +* mode +* An integer flag indicating what the function should do: +* +* AST__LOCK: Lock the Object for exclusive use by the calling +* thread. The "extra" value indicates what should be done if the +* Object is already locked (wait or report an error - see astLock). +* +* AST__UNLOCK: Unlock the Object for use by other threads. +* +* AST__CHECKLOCK: Check that the object is locked for use by the +* calling thread (report an error if not). +* extra +* Extra mode-specific information. +* fail +* If a non-zero function value is returned, a pointer to the +* Object that caused the failure is returned at "*fail". This may +* be "this" or it may be an Object contained within "this". Note, +* the Object's reference count is not incremented, and so the +* returned pointer should not be annulled. A NULL pointer is +* returned if this function returns a value of zero. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* A local status value: +* 0 - Success +* 1 - Could not lock or unlock the object because it was already +* locked by another thread. +* 2 - Failed to lock a POSIX mutex +* 3 - Failed to unlock a POSIX mutex +* 4 - Bad "mode" value supplied. + +* Notes: +* - This function attempts to execute even if an error has already +* occurred. +*/ + +/* Local Variables: */ + AstRegion *this; /* Pointer to Region structure */ + int result; /* Returned status value */ + +/* Initialise */ + result = 0; + +/* Check the supplied pointer is not NULL. */ + if( !this_object ) return result; + +/* Obtain a pointers to the Region structure. */ + this = (AstRegion *) this_object; + +/* Invoke the ManageLock method inherited from the parent class. */ + if( !result ) result = (*parent_managelock)( this_object, mode, extra, + fail, status ); + +/* Invoke the astManageLock method on any Objects contained within + the supplied Object. */ + if( !result ) result = astManageLock( this->frameset, mode, extra, fail ); + if( !result ) result = astManageLock( this->points, mode, extra, fail ); + if( !result ) result = astManageLock( this->unc, mode, extra, fail ); + if( !result ) result = astManageLock( this->negation, mode, extra, fail ); + if( !result ) result = astManageLock( this->defunc, mode, extra, fail ); + if( !result ) result = astManageLock( this->basemesh, mode, extra, fail ); + if( !result ) result = astManageLock( this->basegrid, mode, extra, fail ); + + return result; + +} +#endif + +static AstRegion *MapRegion( AstRegion *this, AstMapping *map0, + AstFrame *frame0, int *status ) { +/* +*+ +* Name: +* astMapRegion + +* Purpose: +* Transform a Region into a new Frame using a given Mapping. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "region.h" +* AstRegion *astMapRegion( AstRegion *this, AstMapping *map, +* AstFrame *frame ) + +* Class Membership: +* Region method. + +* Description: +* This function returns a pointer to a new Region which corresponds to +* supplied Region in some other specified coordinate system. A +* Mapping is supplied which transforms positions between the old and new +* coordinate systems. The new Region may not be of the same class as +* the original region. + +* Parameters: +* this +* Pointer to the Region. +* map +* Pointer to a Mapping which transforms positions from the +* coordinate system represented by the supplied Region to the +* coordinate system specified by "frame". The supplied Mapping should +* define both forward and inverse transformations, and these +* transformations should form a genuine inverse pair. That is, +* transforming a position using the forward transformation and then +* using the inverse transformation should produce the original input +* position. Some Mapping classes (such as PermMap, MathMap, SphMap) +* can result in Mappings for which this is not true. +* frame +* Pointer to a Frame describing the coordinate system in which +* the new Region is required. + +* Returned Value: +* astMapRegion() +* A pointer to a new Region. This Region will represent the area +* within the coordinate system specified by "frame" which corresponds +* to the supplied Region. + +* Notes: +* - This is the protected implementation of this function - it does +* not simplify the returned Region. The public implementation is +* astMapRegionID, which simplifies the returned Region. +* - A null Object pointer (AST__NULL) will be returned if this +* function is invoked with the AST error status set, or if it +* should fail for any reason. +*- +*/ + +/* Local Variables: */ + AstFrame *frame; + AstFrameSet *fs; + AstMapping *tmap; + AstMapping *usemap; + AstMapping *map; + AstPointSet *ps1; + AstPointSet *pst; + AstPointSet *ps2; + AstRegion *usethis; + AstRegion *result; + double **ptr1; + double **ptr2; + int *axflags; + int *inax; + int *keep; + int *outax; + int i; + int icurr; + int j; + int nax1; + int nkept; + int nnew; + int nold; + int np; + int ntotal; + int ok; + +/* Initialise returned value. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Initialise local variables */ + axflags = NULL; + +/* If a FrameSet was supplied for the Mapping, use the base->current + Mapping */ + if( astIsAFrameSet( map0 ) ) { + map = astGetMapping( (AstFrameSet *) map0, AST__BASE, AST__CURRENT ); + } else { + map = astClone( map0 ); + } + +/* If a FrameSet was supplied for the Frame, use the current Frame. */ + if( astIsAFrameSet( frame0 ) ) { + frame = astGetFrame( (AstFrameSet *) frame0, AST__CURRENT ); + } else { + frame = astClone( frame0 ); + } + +/* First check the Mapping is suitable. It must defined both a forward + and an inverse Mapping. */ + if( !astGetTranInverse( map ) ) { + astError( AST__NODEF, "astMapRegion(%s): The supplied %s does not " + "define an inverse transformation.", status, astGetClass( this ), + astGetClass( map ) ); + } else if( !astGetTranForward( map ) ) { + astError( AST__NODEF, "astMapRegion(%s): The supplied %s does not " + "define a forward transformation.", status, astGetClass( this ), + astGetClass( map ) ); + } + + +/* Get the number of axes in the supplied Region. */ + nold = astGetNaxes( this ); + +/* Get the number of axes in the returned Region. */ + nnew = astGetNaxes( frame ); + +/* The forward transformation must not introduce any bad axis values. We + can only perform this test reliably if the supplied Region has no bad + axis values. */ + ps1 = this->points; + if( ps1 ) { + nax1 = astGetNcoord( ps1 ); + np = astGetNpoint( ps1 ); + ptr1 = astGetPoints( ps1 ); + if( ptr1 ) { + +/* Check the axis values defining the Region are good. */ + ok = 1; + for( i = 0; i < nax1 && ok; i++ ){ + for( j = 0; j < np; j++ ) { + if( ptr1[ i ][ j ] == AST__BAD ){ + ok = 0; + break; + } + } + } + if( ok ) { + +/* Transform the points defining the supplied Region into the current Frame + of the Region. */ + pst = astRegTransform( this, ps1, 1, NULL, NULL ); + +/* The use the supplied Mapping to transfom them into the new Frame. */ + ps2 = astTransform( map, pst, 1, NULL ); + +/* Test if any of these axis values are bad. */ + ptr2 = astGetPoints( ps2 ); + if( ptr2 ) { + for( i = 0; i < nnew && ok; i++ ){ + for( j = 0; j < np; j++ ) { + if( ptr2[ i ][ j ] == AST__BAD ){ + ok = 0; + break; + } + } + } + if( !ok ) { + astError( AST__NODEF, "astMapRegion(%s): The region which " + "results from using the supplied %s to transform " + "the supplied %s is undefined.", status, astGetClass( this ), + astGetClass( map ), astGetClass( this ) ); + +/* If all axis values are good, use the inverse transformation of the + supplied Mapping to transform them back to the Frame of the supplied + Region. */ + } else { + pst = astAnnul( pst ); + pst = astTransform( map, ps2, 0, NULL ); + +/* Get a flag for each input of the supplied Mapping (i.e. each axis of + the supplied Region) which is non-zero if the inverse transformation + of the Mapping has produced any good axis values. */ + ptr1 = astGetPoints( pst ); + axflags = astCalloc( nold, sizeof(int) ); + if( astOK ) { + for( i = 0; i < nold; i++ ){ + for( j = 0; j < np; j++ ) { + if( ptr1[ i ][ j ] != AST__BAD ){ + axflags[ i ] = 1; + break; + } + } + } + } + } + } + ps2 = astAnnul( ps2 ); + pst = astAnnul( pst ); + } + } + } + +/* Assume we will be using the supplied Region (this) and Mapping (map). */ + usethis = astClone( this ); + usemap = astClone( map ); + +/* If the new Frame for the Region has fewer axes than the old Frame, see + if we can discard some base-frame axes. We only do this if the inverse + transformation would otherwise supply bad values for the unused axes. + Using bad axis values is not a good idea as some operations cannot be + performed if any bad values are supplied. Also having more axes than + needed is bad as it results in fewer mesh points per axis. */ + if( nnew < nold ) { + +/* First invert the Mapping since astMapSplit only allows selection of + inputs, and we want to select outputs. */ + astInvert( map ); + +/* Create an array holding the indices of the required inputs. */ + inax = astMalloc( nnew*sizeof(int) ); + if( astOK ) for( i = 0; i < nnew; i++ ) inax[i] = i; + +/* Attempt to split the mapping to extract a new mapping that omits any + unnecessary outputs (i.e. outputs that are indepenent of the selected + inputs). Check the Mapping was split successfully. */ + outax = astMapSplit( map, nnew, inax, &tmap ); + if( outax ) { + +/* Get the number of old axes that have been retained in the Mapping. */ + nkept = astGetNout( tmap ); + +/* Now we need to ensure that any unused axes for which the Mapping + creates non-bad values are retained (such values are significant + since they may determine whether the new Region is null or not). + We only need to do this if any of the outputs that were split off + above have been found to generate good values, as indicated by the + "axflags" array. Count the number of extra axes that need to be kept, + over and above those that are kept by the Mapping returned by + astMapSplit above. */ + ntotal = 0; + keep = NULL; + if( axflags ) { + keep = astMalloc( nold*sizeof(int) ); + if( astOK ) { + +/* Loop round each axis in the supplied Region. */ + for( i = 0; i < nold; i++ ) { + +/* Search the "outax" array to see if this axis was retained by astMapSplit. + If it was, append its index to the total list of axes to keep. */ + ok = 0; + for( j = 0; j < nkept; j++ ) { + if( outax[ j ] == i ) { + keep[ ntotal++ ] = i; + ok = 1; + break; + } + } + +/* If the axis was not retained by astMapSplit, but generates good axis + values, also append its index to the total list of axes to keep. */ + if( !ok && axflags[ i ] ) { + keep[ ntotal++ ] = i; + } + } + } + } + +/* If there are no extra axes to keep, then the Mapping returned by + astMapSplit above can be used as it is. */ + if( ntotal == nkept ) { + +/* The values in the "outax" array will hold the zero-based indices of + the original old axes that are retained by the new Mapping. We need to + create a copy of the supplied Region that includes only these axes. */ + usethis = astAnnul( usethis ); + usethis = astPickAxes( this, nkept, outax, NULL ); + +/* Use the temportary Mapping returned by astMapSplit in place of the + supplied Mapping (remember to invert to undo the inversion performed + above). */ + usemap = astAnnul( usemap ); + usemap = astClone( tmap ); + astInvert( usemap ); + +/* Free temporary resources. */ + tmap = astAnnul( tmap ); + outax = astFree( outax ); + +/* If we need to retain some extra axes because they generate good values + (even though they are independent of the new Frame axes)... */ + } else if( ntotal > nkept ){ + +/* We know the old Frame axes that we want to keep, so use astMapSplit + in the opposite direction - i.e. use it on the Mapping form old to + new. */ + astInvert( map ); + + tmap = astAnnul( tmap ); + outax = astFree( outax ); + + outax = astMapSplit( map, ntotal, keep, &tmap ); + if( outax ) { + + usethis = astAnnul( usethis ); + usethis = astPickAxes( this, ntotal, keep, NULL ); + + usemap = astAnnul( usemap ); + usemap = astClone( tmap ); + + tmap = astAnnul( tmap ); + outax = astFree( outax ); + + } + + astInvert( map ); + } + keep = astFree( keep ); + } + inax = astFree( inax ); + +/* Invert the Mapping again to bring it back to its original state. */ + astInvert( map ); + } + +/* Take a deep copy of the supplied Region. */ + result = astCopy( usethis ); + +/* Get a pointer to the encapsulated FrameSet. */ + if( astOK ) { + fs = result->frameset; + +/* Add in the new Frame and Mapping. First note the index of the original + current Frame. */ + icurr = astGetCurrent( fs ); + astAddFrame( fs, AST__CURRENT, usemap, frame ); + +/* Remove the original current Frame. */ + astRemoveFrame( fs, icurr ); + +/* The base and current Frames of the resulting FrameSet are now (in + general) different and so the Region should include its FrameSet in any + Dump. */ + astSetRegionFS( result, 1 ); + } + +/* Since the Mapping has been changed, any cached information calculated + on the basis of the Mapping properties may no longer be up to date. */ + astResetCache( result ); + +/* Free resources */ + usemap = astAnnul( usemap ); + usethis = astAnnul( usethis ); + map = astAnnul( map ); + frame = astAnnul( frame ); + axflags = astFree( axflags ); + +/* If not OK, annul the returned pointer. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the result. */ + return result; +} + +/* +*++ +* Name: +c astMask<X> +f AST_MASK<X> + +* Purpose: +* Mask a region of a data grid. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c int astMask<X>( AstRegion *this, AstMapping *map, int inside, int ndim, +c const int lbnd[], const int ubnd[], <Xtype> in[], +c <Xtype> val ) +f RESULT = AST_MASK<X>( THIS, MAP, INSIDE, NDIM, LBND, UBND, IN, VAL, +f STATUS ) + +* Class Membership: +* Mapping method. + +* Description: +* This is a set of functions for masking out regions within gridded data +* (e.g. an image). The functions modifies a given data grid by +* assigning a specified value to all samples which are inside (or outside +c if "inside" is zero) +f if INSIDE is .FALSE.) +* the specified Region. +* +* You should use a masking function which matches the numerical +* type of the data you are processing by replacing <X> in +c the generic function name astMask<X> by an appropriate 1- or +f the generic function name AST_MASK<X> by an appropriate 1- or +* 2-character type code. For example, if you are masking data +c with type "float", you should use the function astMaskF (see +f with type REAL, you should use the function AST_MASKR (see +* the "Data Type Codes" section below for the codes appropriate to +* other numerical types). + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to a Region. +c map +f MAP = INTEGER (Given) +* Pointer to a Mapping. The forward transformation should map +* positions in the coordinate system of the supplied Region +* into pixel coordinates as defined by the +c "lbnd" and "ubnd" parameters. A NULL pointer +f LBND and UBND arguments. A value of AST__NULL +* can be supplied if the coordinate system of the supplied Region +* corresponds to pixel coordinates. This is equivalent to +* supplying a UnitMap. +* +* The number of inputs for this Mapping (as given by its Nin attribute) +* should match the number of axes in the supplied Region (as given +* by the Naxes attribute of the Region). +* The number of outputs for the Mapping (as given by its Nout attribute) +* should match the number of +c grid dimensions given by the value of "ndim" +f grid dimensions given by the value of NDIM +* below. +c inside +f INSIDE = INTEGER (Given) +* A boolean value which indicates which pixel are to be masked. If +c a non-zero value +f .TRUE. +* is supplied, then all grid pixels with centres inside the supplied +* Region are assigned the value given by +c "val", +f VAL, +* and all other pixels are left unchanged. If +c zero +f .FALSE. +* is supplied, then all grid pixels with centres not inside the supplied +* Region are assigned the value given by +c "val", +f VAL, +* and all other pixels are left unchanged. Note, the Negated +* attribute of the Region is used to determine which pixel are +* inside the Region and which are outside. So the inside of a Region +* which has not been negated is the same as the outside of the +* corresponding negated Region. +* +* For types of Region such as PointList which have zero volume, +* pixel centres will rarely fall exactly within the Region. For +* this reason, the inclusion criterion is changed for zero-volume +* Regions so that pixels are included (or excluded) if any part of +* the Region passes through the pixel. For a PointList, this means +* that pixels are included (or excluded) if they contain at least +* one of the points listed in the PointList. +c ndim +f NDIM = INTEGER (Given) +* The number of dimensions in the input grid. This should be at +* least one. +c lbnd +f LBND( NDIM ) = INTEGER (Given) +c Pointer to an array of integers, with "ndim" elements, +f An array +* containing the coordinates of the centre of the first pixel +* in the input grid along each dimension. +c ubnd +f UBND( NDIM ) = INTEGER (Given) +c Pointer to an array of integers, with "ndim" elements, +f An array +* containing the coordinates of the centre of the last pixel in +* the input grid along each dimension. +* +c Note that "lbnd" and "ubnd" together define the shape +f Note that LBND and UBND together define the shape +* and size of the input grid, its extent along a particular +c (j'th) dimension being ubnd[j]-lbnd[j]+1 (assuming the +c index "j" to be zero-based). They also define +f (J'th) dimension being UBND(J)-LBND(J)+1. They also define +* the input grid's coordinate system, each pixel having unit +* extent along each dimension with integral coordinate values +* at its centre. +c in +f IN( * ) = <Xtype> (Given and Returned) +c Pointer to an array, with one element for each pixel in the +f An array, with one element for each pixel in the +* input grid, containing the data to be masked. The +* numerical type of this array should match the 1- or +* 2-character type code appended to the function name (e.g. if +c you are using astMaskF, the type of each array element +c should be "float"). +f you are using AST_MASKR, the type of each array element +f should be REAL). +* +* The storage order of data within this array should be such +* that the index of the first grid dimension varies most +* rapidly and that of the final dimension least rapidly +c (i.e. Fortran array indexing is used). +f (i.e. normal Fortran array storage order). +* +* On exit, the samples specified by +c "inside" are set to the value of "val". +f INSIDE are set to the value of VAL. +* All other samples are left unchanged. +c val +f VAL = <Xtype> (Given) +* This argument should have the same type as the elements of +c the "in" array. It specifies the value used to flag the +f the IN array. It specifies the value used to flag the +* masked data (see +c "inside"). +f INSIDE). +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Returned Value: +c astMask<X>() +f AST_MASK<X> = INTEGER +* The number of pixels to which a value of +c "badval" +f BADVAL +* has been assigned. + +* 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. +* - An error will be reported if the overlap of the Region and +* the array cannot be determined. + +* Data Type Codes: +* To select the appropriate masking function, you should +c replace <X> in the generic function name astMask<X> with a +f replace <X> in the generic function name AST_MASK<X> with a +* 1- or 2-character data type code, so as to match the numerical +* type <Xtype> of the data you are processing, as follows: +c - D: double +c - F: float +c - L: long int +c - UL: unsigned long int +c - I: int +c - UI: unsigned int +c - S: short int +c - US: unsigned short int +c - B: byte (signed char) +c - UB: unsigned byte (unsigned char) +f - D: DOUBLE PRECISION +f - R: REAL +f - I: INTEGER +f - UI: INTEGER (treated as unsigned) +f - S: INTEGER*2 (short integer) +f - US: INTEGER*2 (short integer, treated as unsigned) +f - B: BYTE (treated as signed) +f - UB: BYTE (treated as unsigned) +* +c For example, astMaskD would be used to process "double" +c data, while astMaskS would be used to process "short int" +c data, etc. +f For example, AST_MASKD would be used to process DOUBLE +f PRECISION data, while AST_MASKS would be used to process +f short integer data (stored in an INTEGER*2 array), etc. +f +f For compatibility with other Starlink facilities, the codes W +f and UW are provided as synonyms for S and US respectively (but +f only in the Fortran interface to AST). + +*-- +*/ +/* Define a macro to implement the function for a specific data + type. */ +#define MAKE_MASK(X,Xtype) \ +static int Mask##X( AstRegion *this, AstMapping *map, int inside, int ndim, \ + const int lbnd[], const int ubnd[], \ + Xtype in[], Xtype val, int *status ) { \ +\ +/* Local Variables: */ \ + AstFrame *grid_frame; /* Pointer to Frame describing grid coords */ \ + AstRegion *used_region; /* Pointer to Region to be used by astResample */ \ + Xtype *c; /* Pointer to next array element */ \ + Xtype *d; /* Pointer to next array element */ \ + Xtype *out; /* Pointer to the array used for resample output */ \ + Xtype *tmp_out; /* Pointer to temporary output array */ \ + double *lbndgd; /* Pointer to array holding lower grid bounds */ \ + double *ubndgd; /* Pointer to array holding upper grid bounds */ \ + int *lbndg; /* Pointer to array holding lower grid bounds */ \ + int *ubndg; /* Pointer to array holding upper grid bounds */ \ + int idim; /* Loop counter for coordinate dimensions */ \ + int ipix; /* Loop counter for pixel index */ \ + int nax; /* Number of Region axes */ \ + int nin; /* Number of Mapping input coordinates */ \ + int nout; /* Number of Mapping output coordinates */ \ + int npix; /* Number of pixels in supplied array */ \ + int npixg; /* Number of pixels in bounding box */ \ + int result; /* Result value to return */ \ +\ +/* Initialise. */ \ + result = 0; \ +\ +/* Check the global error status. */ \ + if ( !astOK ) return result; \ +\ +/* Obtain value for the Naxes attribute of the Region. */ \ + nax = astGetNaxes( this ); \ +\ +/* If supplied, obtain values for the Nin and Nout attributes of the Mapping. */ \ + if( map ) { \ + nin = astGetNin( map ); \ + nout = astGetNout( map ); \ +\ +/* If OK, check that the number of mapping inputs matches the \ + number of axes in the Region. Report an error if necessary. */ \ + if ( astOK && ( nax != nin ) ) { \ + astError( AST__NGDIN, "astMask"#X"(%s): Bad number of mapping " \ + "inputs (%d).", status, astGetClass( this ), nin ); \ + astError( AST__NGDIN, "The %s given requires %d coordinate value%s " \ + "to specify a position.", status, \ + astGetClass( this ), nax, ( nax == 1 ) ? "" : "s" ); \ + } \ +\ +/* If OK, check that the number of mapping outputs matches the \ + number of grid dimensions. Report an error if necessary. */ \ + if ( astOK && ( ndim != nout ) ) { \ + astError( AST__NGDIN, "astMask"#X"(%s): Bad number of mapping " \ + "outputs (%d).", status, astGetClass( this ), nout ); \ + astError( AST__NGDIN, "The pixel grid requires %d coordinate value%s " \ + "to specify a position.", status, \ + ndim, ( ndim == 1 ) ? "" : "s" ); \ + } \ +\ +/* Create a new Region by mapping the supplied Region with the supplied \ + Mapping. The resulting Region represents a region in grid coordinates. */ \ + grid_frame = astFrame( ndim, "Domain=grid", status ); \ + used_region = astMapRegion( this, map, grid_frame ); \ + grid_frame = astAnnul( grid_frame ); \ +\ +/* If no Mapping was supplied check that the number of grid dimensions \ + matches the number of axes in the Region.*/ \ + } else if ( astOK && ( ( ndim != nax ) || ( ndim < 1 ) ) ) { \ + used_region = NULL; \ + astError( AST__NGDIN, "astMask"#X"(%s): Bad number of input grid " \ + "dimensions (%d).", status, astGetClass( this ), ndim ); \ + if ( ndim != nax ) { \ + astError( AST__NGDIN, "The %s given requires %d coordinate value%s " \ + "to specify an input position.", status, \ + astGetClass( this ), nax, ( nax == 1 ) ? "" : "s" ); \ + } \ +\ +/* If no Mapping was supplied and the parameters look OK, clone the \ + supplied Region pointer for use later on. */ \ + } else { \ + used_region = astClone( this ); \ + } \ +\ +/* Check that the lower and upper bounds of the input grid are \ + consistent. Report an error if any pair is not. */ \ + if ( astOK ) { \ + for ( idim = 0; idim < ndim; idim++ ) { \ + if ( lbnd[ idim ] > ubnd[ idim ] ) { \ + astError( AST__GBDIN, "astMask"#X"(%s): Lower bound of " \ + "input grid (%d) exceeds corresponding upper bound " \ + "(%d).", status, astGetClass( this ), \ + lbnd[ idim ], ubnd[ idim ] ); \ + astError( AST__GBDIN, "Error in input dimension %d.", status, \ + idim + 1 ); \ + break; \ + } \ + } \ + } \ +\ +/* Allocate memory, and then get the bounding box of this new Region in its \ + current Frame (grid coordinates). This bounding box assumes the region \ + has not been negated. */ \ + lbndg = astMalloc( sizeof( int )*(size_t) ndim ); \ + ubndg = astMalloc( sizeof( int )*(size_t) ndim ); \ + lbndgd = astMalloc( sizeof( double )*(size_t) ndim ); \ + ubndgd = astMalloc( sizeof( double )*(size_t) ndim ); \ + if( astOK ) { \ + astGetRegionBounds( used_region, lbndgd, ubndgd ); \ +\ +/* We convert the floating point bounds to integer pixel bounds, and at \ + the same time expand the box by 2 pixels at each edge to ensure that \ + rounding errors etc do not cause any of the Region to fall outside (or \ + on) the box. Do not let the expanded box extend outside the supplied \ + array bounds. Also note the total number of pixels in the supplied \ + array, and in the bounding box. */ \ + npix = 1; \ + npixg = 1; \ + for ( idim = 0; idim < ndim; idim++ ) { \ + if( lbndgd[ idim ] != AST__BAD && ubndgd[ idim ] != AST__BAD ) { \ + lbndg[ idim ] = astMAX( lbnd[ idim ], (int)( lbndgd[ idim ] + 0.5 ) - 2 ); \ + ubndg[ idim ] = astMIN( ubnd[ idim ], (int)( ubndgd[ idim ] + 0.5 ) + 2 ); \ + } else { \ + lbndg[ idim ] = lbnd[ idim ]; \ + ubndg[ idim ] = ubnd[ idim ]; \ + } \ + npix *= ( ubnd[ idim ] - lbnd[ idim ] + 1 ); \ + if( npixg >= 0 ) npixg *= ( ubndg[ idim ] - lbndg[ idim ] + 1 ); \ + } \ +\ +/* If the bounding box is null, fill the mask with the supplied value if \ + we assigning the value to the outside of the region (do the opposite if \ + the Region has been negated). */ \ + if( npixg <= 0 && astOK ) { \ + if( ( inside != 0 ) == ( astGetNegated( used_region ) != 0 ) ) { \ + c = in; \ + for( ipix = 0; ipix < npix; ipix++ ) *(c++) = val; \ + result = npix; \ + } \ +\ +/* If the bounding box is null, return without action. */ \ + } else if( npixg > 0 && astOK ) { \ +\ +/* All points outside this box are either all inside, or all outside, the \ + Region. So we can speed up processing by setting all the points which are \ + outside the box to the supplied data value (if required). This is \ + faster than checking each point individually using the Transform method \ + of the Region. We do this by supplying an alternative output array to \ + the resampling function below, which has been pre-filled with "val" at \ + every pixel. */ \ + if( ( inside != 0 ) == ( astGetNegated( used_region ) != 0 ) ) { \ +\ +/* Allocate memory for the alternative output array, and fill it with \ + "val". */ \ + tmp_out = astMalloc( sizeof( Xtype )*(size_t) npix ); \ + if( tmp_out ) { \ + c = tmp_out; \ + for( ipix = 0; ipix < npix; ipix++ ) *(c++) = val; \ + result = npix - npixg; \ + } \ +\ +/* Indicate that we will use this temporary array rather than the \ + supplied array. */ \ + out = tmp_out; \ +\ +/* If the outside of the grid box is outside the region of interest it \ + will be unchanged in the resturned array. Therefore we can use the \ + supplied array as the output array below. */ \ + } else { \ + tmp_out = NULL; \ + out = in; \ + } \ +\ +/* Temporarily invert the Region if required. The Region Transform methods \ + leave interior points unchanged and assign AST__BAD to exterior points. \ + This is the opposite of what we want (which is to leave exterior \ + points unchanged and assign VAL to interior points), so we negate the \ + region if the inside is to be assigned the value VAL.*/ \ + if( inside ) astNegate( used_region ); \ +\ +/* Invoke astResample to mask just the region inside the bounding box found \ + above (specified by lbndg and ubndg), since all the points outside this \ + box will already contain their required value. */ \ + result += astResample##X( used_region, ndim, lbnd, ubnd, in, NULL, AST__NEAREST, \ + NULL, NULL, 0, 0.0, 100, val, ndim, \ + lbnd, ubnd, lbndg, ubndg, out, NULL ); \ +\ +/* Revert to the original setting of the Negated attribute. */ \ + if( inside ) astNegate( used_region ); \ +\ +/* If required, copy the output data from the temporary output array to \ + the supplied array, and then free the temporary output array. */ \ + if( tmp_out ) { \ + c = tmp_out; \ + d = in; \ + for( ipix = 0; ipix < npix; ipix++ ) *(d++) = *(c++); \ + tmp_out = astFree( tmp_out ); \ + }\ + }\ + } \ +\ +/* Free resources */ \ + ubndg = astFree( ubndg ); \ + lbndg = astFree( lbndg ); \ + ubndgd = astFree( ubndgd ); \ + lbndgd = astFree( lbndgd ); \ + used_region = astAnnul( used_region ); \ +\ +/* If an error occurred, clear the returned result. */ \ + if ( !astOK ) result = 0; \ +\ +/* Return the result. */ \ + return result; \ +} + +/* Expand the above macro to generate a function for each required + data type. */ +#if HAVE_LONG_DOUBLE /* Not normally implemented */ +MAKE_MASK(LD,long double) +#endif +MAKE_MASK(D,double) +MAKE_MASK(L,long int) +MAKE_MASK(UL,unsigned long int) +MAKE_MASK(I,int) +MAKE_MASK(UI,unsigned int) +MAKE_MASK(S,short int) +MAKE_MASK(US,unsigned short int) +MAKE_MASK(B,signed char) +MAKE_MASK(UB,unsigned char) +MAKE_MASK(F,float) + +/* Undefine the macro. */ +#undef MAKE_MASK + + + +static int Match( AstFrame *this_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 "region.h" +* int Match( AstFrame *template, AstFrame *target, int matchsub, +* int **template_axes, int **target_axes, +* AstMapping **map, AstFrame **result, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astMatch +* method inherited from the Frame class). + +* Description: +* This function matches the current Frame of a "template" Region +* 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 current Frame of the target +* Region. 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 Region, whose current Frame +* 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 axis in the +* template Region's current Frame from which it is +* derived. If it is not derived from any template Region +* 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 Frame and the current +* Frame of the template Region. 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. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to Region's current Frame */ + int match; /* Result to be returned */ + +/* 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; + +/* Invoke the parent astMatch method on the current Frame within the + encapsulated FrameSet within the Region. */ + fr = astGetFrame( ((AstRegion *) this_frame)->frameset, AST__CURRENT ); + match = astMatch( fr, target, matchsub, template_axes, target_axes, map, result ); + fr = astAnnul( fr ); + +/* Return the result. */ + return match; +} + +static void MatchAxes( AstFrame *frm1_frame, AstFrame *frm2, int *axes, + int *status ) { +/* +* Name: +* MatchAxes + +* Purpose: +* Find any corresponding axes in two Frames. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void MatchAxes( AstFrame *frm1, AstFrame *frm2, int *axes ) +* int *status ) + +* Class Membership: +* Region member function (over-rides the protected astMatchAxes +* method inherited from the Frame class). + +* Description: +* 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: +* frm1 +* Pointer to the first Frame. +* frm2 +* Pointer to the second Frame. +* axes +* Pointer to an +* integer array in which to return the indices of the axes (within +* the second Frame) that correspond to each axis within the first +* Frame. Axis indices start at 1. A value of zero will be stored +* in the returned array for each axis in the first Frame that has +* no corresponding axis in the second Frame. +* +* The number of elements in this array must be greater than or +* equal to the number of axes in the first 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 *frm1; /* Pointer to Region's current Frame */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Invoke the astMatchAxesX method on frm2, passing it the current Frame + within the encapsulated FrameSet within the Region as "frm1". */ + frm1 = astGetFrame( ((AstRegion *) frm1_frame)->frameset, AST__CURRENT ); + astMatchAxesX( frm2, frm1, axes ); + frm1 = astAnnul( frm1 ); +} + +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 "region.h" +* void MatchAxesX( AstFrame *frm2, AstFrame *frm1, int *axes ) +* int *status ) + +* Class Membership: +* Region 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 *frm2; + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Get a pointer to the current Frame in the FrameSet. */ + frm2 = astGetFrame( ((AstRegion *) frm2_frame)->frameset, AST__CURRENT ); + +/* Invoke the astMatchAxesX on the current Frame. */ + astMatchAxesX( frm2, frm1, axes ); + +/* Free resources */ + frm2 = astAnnul( frm2 ); +} + +static void Negate( AstRegion *this, int *status ) { +/* +*++ +* Name: +c astNegate +f AST_NEGATE + +* Purpose: +* Negate the area represented by a Region. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c void astNegate( AstRegion *this ) +f CALL AST_NEGATE( THIS, STATUS ) + +* Class Membership: +* Region method. + +* Description: +* This function negates the area represented by a Region. That is, +* points which were previously inside the region will then be +* outside, and points which were outside will be inside. This is +* acomplished by toggling the state of the Negated attribute for +* the supplied region. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region. +f STATUS = INTEGER (Given and Returned) +f The global status. + +*-- +*/ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Toggle the Negated attribute. */ + astSetNegated( this, astGetNegated( this ) ? 0 : 1 ); + +} + +static void Norm( AstFrame *this_frame, double value[], int *status ) { +/* +* Name: +* Norm + +* Purpose: +* Normalise a set of Region coordinates. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void Norm( AstAxis *this, double value[], int *status ) + +* Class Membership: +* Region member function (over-rides the astNorm method +* inherited from the Frame class). + +* Description: +* This function converts a set of coordinate values for the +* current Frame of a Region, 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. +* +* Typically, for Frames whose axes represent cyclic values (such +* as angles or positions on the sky), this function wraps an +* arbitrary set of coordinates, so that they lie within the first +* cycle (say zero to 2*pi or -pi/2 to +pi/2). For Frames with +* ordinary linear axes, without constraints, this function will +* typically return the original coordinate values unchanged. + +* Parameters: +* this +* Pointer to the Region. +* value +* An array of double, with one element for each Region 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: */ + AstFrame *fr; /* Pointer to the current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's current Frame and invoke this + Frame's astNorm method to obtain the new values. Annul the Frame + pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astNorm( fr, value ); + fr = astAnnul( fr ); +} + +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 "region.h" +* void astNormBox( AstFrame *this, double lbnd[], double ubnd[], +* AstMapping *reg, int *status ) + +* Class Membership: +* Region 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: */ + AstFrame *fr; /* Pointer to the current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's current Frame and invoke this + Frame's astNormBox method to obtain the new values. Annul the Frame + pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astNormBox( fr, lbnd, ubnd, reg ); + fr = astAnnul( fr ); +} + +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: +* Public virtual function. + +* Synopsis: +* #include "region.h" +* void Offset( AstFrame *this, +* const double point1[], const double point2[], +* double offset, double point3[], int *status ) + +* Class Membership: +* Region member function (over-rides the protected astOffset +* method inherited from the Frame class). + +* Description: +* This function finds the Region coordinate values of a point +* which is offset a specified distance along the geodesic curve +* between two other points. + +* Parameters: +* this +* Pointer to the Region. +* point1 +* An array of double, with one element for each Region 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 Region 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. 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 Region 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's current Frame and invoke this + Frame's astOffset method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astOffset( fr, point1, point2, offset, point3 ); + fr = astAnnul( fr ); +} + +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 in a 2D Frame. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* double Offset2( AstFrame *this, const double point1[2], double angle, +* double offset, double point2[2], int *status ); + +* Class Membership: +* Region member function (over-rides the protected astOffset2 +* method inherited from the Frame class). + +* Description: +* This function finds the Frame coordinate values of a point which +* is offset a specified distance along the geodesic curve at a +* given angle from a specified starting point. It can only be +* used with 2-dimensional Frames. +* +* For example, in a basic Frame, this offset will be along the +* straight line joining two points. For a more specialised Frame +* describing a sky coordinate system, however, it would be along +* the great circle passing through two sky positions. + +* Parameters: +* this +* Pointer to the Frame. +* point1 +* An array of double, with one element for each Frame axis +* (Naxes attribute). 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. If this is positive, it will be in the direction of the +* given angle. If it is negative, it will be in the opposite +* direction. +* point2 +* An array of double, with one element for each Frame 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. +* - An error will be reported if the Frame is not 2-dimensional. +* - This function will return "bad" coordinate values (AST__BAD) +* if any of the input coordinates has this value. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + double result; /* Value to return */ + +/* Check the global error status. */ + if ( !astOK ) return AST__BAD; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke the + astOffset2 method for this Frame. Annul the Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astOffset2( fr, point1, angle, offset, point2 ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = AST__BAD; + +/* Return the result. */ + return result; +} + +static int Overlap( AstRegion *this, AstRegion *that, int *status ){ +/* +*++ +* Name: +c astOverlap +f AST_OVERLAP + +* Purpose: +* Test if two regions overlap each other. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c int astOverlap( AstRegion *this, AstRegion *that ) +f RESULT = AST_OVERLAP( THIS, THAT, STATUS ) + +* Class Membership: +* Region method. + +* Description: +* This function returns an integer value indicating if the two +* supplied Regions overlap. The two Regions are converted to a commnon +* coordinate system before performing the check. If this conversion is +* not possible (for instance because the two Regions represent areas in +* different domains), then the check cannot be performed and a zero value +* is returned to indicate this. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the first Region. +c that +f THAT = INTEGER (Given) +* Pointer to the second Region. +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Returned Value: +c astOverlap() +f AST_OVERLAP = INTEGER +* A value indicating if there is any overlap between the two Regions. +* Possible values are: +* +* 0 - The check could not be performed because the second Region +* could not be mapped into the coordinate system of the first +* Region. +* +* 1 - There is no overlap between the two Regions. +* +* 2 - The first Region is completely inside the second Region. +* +* 3 - The second Region is completely inside the first Region. +* +* 4 - There is partial overlap between the two Regions. +* +* 5 - The Regions are identical to within their uncertainties. +* +* 6 - The second Region is the exact negation of the first Region +* to within their uncertainties. + +* Notes: +* - The returned values 5 and 6 do not check the value of the Closed +* attribute in the two Regions. +* - A value of zero will be returned if this function is invoked with the +* AST error status set, or if it should fail for any reason. +*-- + +* Implementation Notes: +* This function is simply a wrap-up for the protected astOverlapX +* method which performs the required processing but swaps the order +* of the two arguments. This is a trick to allow the astOverlap method +* to be over-ridden by derived classes on the basis of the class of either +* of the two arguments. +*/ + +/* Check the global error status. */ + if ( !astOK ) return 0; + +/* Invoke the "astOverlapX" method with the two arguments swapped. */ + return astOverlapX( that, this ); +} + +static int OverlapX( AstRegion *that, AstRegion *this, int *status ){ +/* +*+ +* Name: +* astOverlapX + +* Purpose: +* Test if two regions overlap each other. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "region.h" +* int astOverlapX( AstRegion *that, AstRegion *this ) + +* Class Membership: +* Region method. + +* Description: +* This function performs the processing for the public astOverlap +* method and has exactly the same interface except that the order +* of the two arguments is swapped. This is a trick to allow +* the astOverlap method to be over-ridden by derived classes on +* the basis of the class of either of its two arguments. +* +* See the astOverlap method for details of the interface. +*- +*/ + +/* Local Variables: */ + AstFrame *bfrm_reg1; /* Pointer to base Frame in "reg1" Frame */ + AstFrame *frm_reg1; /* Pointer to current Frame in "reg1" Frame */ + AstFrameSet *fs0; /* FrameSet connecting Region Frames */ + AstFrameSet *fs; /* FrameSet connecting Region Frames */ + AstMapping *cmap; /* Mapping connecting Region Frames */ + AstMapping *map; /* Mapping form "reg2" current to "reg1" base */ + AstMapping *map_reg1; /* Pointer to current->base Mapping in "reg1" */ + AstPointSet *ps1; /* Mesh covering second Region */ + AstPointSet *ps3; /* Mesh covering first Region */ + AstPointSet *ps4; /* Mesh covering first Region */ + AstPointSet *ps2; /* Mesh covering second Region */ + AstPointSet *reg2_mesh; /* Mesh covering second Region */ + AstPointSet *reg1_mesh; /* Mesh covering first Region */ + AstPointSet *reg2_submesh; /* Second Region mesh minus boundary points */ + AstRegion *reg1; /* Region to use as the first Region */ + AstRegion *reg2; /* Region to use as the second Region */ + AstRegion *unc1; /* "unc" mapped into Frame of first Region */ + AstRegion *unc; /* Uncertainty in second Region */ + double **ptr1; /* Pointer to mesh axis values */ + double **ptr; /* Pointer to pointset data */ + double *p; /* Pointer to next axis value */ + int *mask; /* Mask identifying common boundary points */ + int allbad; /* Were all axis values bad? */ + int allgood; /* Were all axis values good? */ + int bnd1; /* Does reg1 have a finite boundary */ + int bnd2; /* Does reg2 have a finite boundary */ + int bnd_that; /* Does "that" have a finite boundary */ + int bnd_this; /* Does "this" have a finite boundary */ + int case1; /* First region inside second region? */ + int first; /* First pass? */ + int good; /* Any good axis values found? */ + int i; /* Mesh axis index */ + int iax; /* Axis index */ + int inv0; /* Original FrameSet Invert flag */ + int ip; /* Index of point */ + int j; /* Mesh point index */ + int nc; /* Number of axis values per point */ + int np; /* Number of points in mesh */ + int result; /* Value to return */ + int reg1_neg; /* Was "reg1" negated to make it bounded? */ + int reg2_neg; /* Was "reg2" negated to make it bounded? */ + int that_neg; /* Was "that" negated to make it bounded? */ + int this_neg; /* Was "this" negated to make it bounded? */ + int touch; /* Do the Regions touch? */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Return 5 if the two Regions are equal using the astEqual method. */ + if( astEqual( this, that ) ) { + return 5; + +/* Return 6 if the two Regions are equal using the Equal method after + temporarily negating the first. */ + } else { + astNegate( this ); + result = astEqual( this, that ); + astNegate( this ); + if( result ) return 6; + } + +/* Get a FrameSet which connects the Frame represented by the second Region + to the Frame represented by the first Region. Check that the conection is + defined. */ + fs0 = astConvert( that, this, "" ); + if( !fs0 ) return 0; + inv0 = astGetInvert( fs0 ); + +/* The rest of this function tests for overlap by representing one of the + Regions as a mesh of points along its boundary, and then checking to see + if any of the points in this mesh fall inside or outside the other Region. + This can only be done if the Region has a boundary of finite length (e.g. + Circles, Boxes, etc). Other Regions (e.g. some Intervals) do not have + finite boundaries and consequently report an error if an attempt is made + to represent them using a boundary mesh. We now therefore check to see if + either of the two Regions has a finite boundary length. This will be the + case if the region is bounded, or if it can be made bounded simply by + negating it. If a Region is unbounded regardless of the setting of its + Negated flag, then it does not have a finite boundary. We leave the + Negated attributes (temporaily) set to the values that cause the + Regions to be bounded. Set flags to indicate if the Regions have been + negated. */ + bnd_this = astGetBounded( this ); + if( !bnd_this ) { + astNegate( this ); + bnd_this = astGetBounded( this ); + if( ! bnd_this ) { + astNegate( this ); + this_neg = 0; + } else { + this_neg = 1; + } + } else { + this_neg = 0; + } + + bnd_that = astGetBounded( that ); + if( !bnd_that ) { + astNegate( that ); + bnd_that = astGetBounded( that ); + if( ! bnd_that ) { + astNegate( that ); + that_neg = 0; + } else { + that_neg = 1; + } + } else { + that_neg = 0; + } + +/* If neither Regions has a finite boundary, then we cannot currently + determine any overlap, so report an error. Given more time, it + is probably possible to think of some way of determining overlap + between two unbounded Regions, but it will probably not be a common + requirement and so is currently put off to a rainy day. */ + if( !bnd_this && !bnd_that && astOK ) { + astError( AST__INTER, "astOverlap(Region): Neither of the two " + "supplied Regions (classes %s and %s) has a finite " + "boundary.", status, astGetClass(this), astGetClass(that) ); + astError( AST__INTER, "The current implementation of astOverlap " + "cannot determine the overlap between two Regions " + "unless at least one of them has a finite boundary." , status); + } + +/* If only one of the two Regions has a finite boundary, we must use its + mesh first. Choose the finite boundary Region as the "second" region. + Also store a flag indicating if the first Region has a finite boundary. */ + if( bnd_that ) { + reg1 = this; + reg2 = that; + bnd1 = bnd_this; + bnd2 = bnd_that; + reg1_neg = this_neg; + reg2_neg = that_neg; + } else { + reg1 = that; + reg2 = this; + bnd1 = bnd_that; + bnd2 = bnd_this; + reg1_neg = that_neg; + reg2_neg = this_neg; + } + +/* We may need to try again with the above selections swapped. We only do + this once though. Set a flag to indicate that we are about to start the + first pass. */ + first = 1; +L1: + +/* Get a FrameSet which connects the Frame represented by the second Region + to the Frame represented by the first Region. Check that the conection is + defined. */ + fs = astClone( fs0 ); + astSetInvert( fs, (reg2 == that ) ? inv0 : 1 - inv0 ); + if( fs ) { + +/* Get a pointer to the Frame represented by the first Region. */ + frm_reg1 = astGetFrame( reg1->frameset, AST__CURRENT ); + +/* Get a pointer to the Mapping from current to base Frame in the first + Region. */ + map_reg1 = astGetMapping( reg1->frameset, AST__CURRENT, AST__BASE ); + +/* Get the Mapping from the current Frame of the second Region to the + current Frame of the first Region. */ + cmap = astGetMapping( fs, AST__BASE, AST__CURRENT ); + +/* Combine these Mappings to get the Mapping from current Frame of the + second region to the base Frame of the first Region. */ + map = (AstMapping *) astCmpMap( cmap, map_reg1, 1, "", status ); + +/* Get a mesh of points covering the second Region. These points are + within the current Frame of the second Region. */ + reg2_mesh = astRegMesh( reg2 ); + +/* Transform this mesh into the base Frame of the first Region. */ + ps1 = astTransform( map, reg2_mesh, 1, NULL ); + +/* Check there are some good points in the transformed pointset. */ + good = 0; + np = astGetNpoint( ps1 ); + nc = astGetNcoord( ps1 ); + ptr1 = astGetPoints( ps1 ); + if( ptr1 ) { + for( i = 0; i < nc && !good; i++ ) { + for( j = 0; j < np; j++ ) { + if( ptr1[ i ][ j ] != AST__BAD ) { + good = 1; + break; + } + } + } + } + +/* If the transformed mesh contains no good points, swap the regions and + try again. */ + if( !good ) { + fs = astAnnul( fs ); + frm_reg1 = astAnnul( frm_reg1 ); + map_reg1 = astAnnul( map_reg1 ); + cmap = astAnnul( cmap ); + map = astAnnul( map ); + reg2_mesh = astAnnul( reg2_mesh ); + ps1 = astAnnul( ps1 ); + + if( first ) { + first = 0; + + if( !bnd_that ) { + reg1 = this; + reg2 = that; + bnd1 = bnd_this; + bnd2 = bnd_that; + reg1_neg = this_neg; + reg2_neg = that_neg; + } else { + reg1 = that; + reg2 = this; + bnd1 = bnd_that; + bnd2 = bnd_this; + reg1_neg = that_neg; + reg2_neg = this_neg; + } + goto L1; + + } else { + return 0; + } + } + +/* Also transform the Region describing the positional uncertainty within + the second supplied Region into the base Frame of the first supplied + Region. */ + unc = astGetUncFrm( reg2, AST__CURRENT ); + bfrm_reg1 = astGetFrame( reg1->frameset, AST__BASE ); + unc1 = astMapRegion( unc, map, bfrm_reg1 ); + +/* See if all points within this transformed mesh fall on the boundary of + the first Region, to within the joint uncertainty of the two Regions. If + so the two Regions have equivalent boundaries. We can only do this is + the first region is bounded. */ + if( astRegPins( reg1, ps1, unc1, &mask ) && good ) { + +/* If the boundaries are equivalent, the Regions are either identical or + are mutually exclusive. To distinguish between these cases, we + looked at the Bounded attributes. If the Bounded attribute is the same + for both Regions then they are identical, otherwise they are mutually + exclusive. */ + result = ( ( !reg1_neg && bnd1 ) == ( !reg2_neg && bnd2 ) ) ? 5 : 6; + +/* If the boundaries of the two Regions are not equivalent. */ + } else { + +/* Create a new PointSet containing those points from the mesh which are + not on the boundary of the first Region. These points are identified by + the mask array created by the astRegPins method above. */ + reg2_submesh = GetSubMesh( mask, reg2_mesh, status ); + +/* Transform the points in the submesh of the second Region into the + current Frame of the first Region. */ + (void ) astAnnul( ps1 ); + ps1 = astTransform( cmap, reg2_submesh, 1, NULL ); + +/* Transform this submesh using the first Region as a Mapping. Any points + outside the first region will be set bad in the output PointSet. */ + ps2 = astTransform( (AstMapping *) reg1, ps1, 1, NULL ); + +/* Get the number of axes and points in this PointSet. */ + nc = astGetNcoord( ps2 ); + np = astGetNpoint( ps2 ); + +/* Note if there were any common points (i.e. points on the boundary of + both regions). */ + touch = ( astGetNpoint( reg2_mesh ) != np ); + +/* Get pointers to the axis data in this PointSet, and check they can be + used safely. */ + ptr = astGetPoints( ps2 ); + if( astOK ) { + +/* Loop round all points checking if the axis values are bad. We want a + flag saying if there are any good axis values and another flag saying if + there are any bad axis values. */ + allbad = 1; + allgood = 1; + for( iax = 0; iax < nc; iax++ ) { + p = ptr[ iax ]; + for( ip = 0; ip < np; ip++,p++ ) { + if( *p == AST__BAD ) { + allgood = 0; + if( !allbad ) break; + } else { + allbad = 0; + if( !allgood ) break; + } + } + } + +/* If the entire mesh of the (potentially negated) second Region was either + on the boundary of, or inside, the (potentially negated) first region, + determine the result depending on whether the regions have been + negated and whether they are bounded. Check for impossible states (or + maybe just errors in my logic). */ + if( allgood ) { + +/* Second region has a mesh so it must be bounded. */ + if( !bnd2 && astOK ) { + astError( AST__INTER, "astOverlap(%s): Inconsistent " + "state 1 (internal AST programming error).", + status, astGetClass( this ) ); + +/* If the first region has been made bounded by negating it... */ + } else if( reg1_neg ) { + if( bnd1 ) { + +/* If the second region has been made bounded by negating it, then the + unnegated first region is completely inside the unnegated second region. */ + if( reg2_neg ) { + result = 2; + +/* If the second region was bounded without negating it, then there is + no overlap between the unnegated first region and the second region. */ + } else { + result = 1; + } + +/* If the first region has been negated then it should not be unbounded. + This is ensured by the nature of the code that sets the "this_neg" and + "that_neg" flags above. */ + } else if( astOK ) { + astError( AST__INTER, "astOverlap(%s): Inconsistent " + "state 2 (internal AST programming error).", + status, astGetClass( this ) ); + } + +/* If the first region was bounded without negating it, but the second + region was made bounded by negating it, there is partial overlap. */ + } else if( reg2_neg ) { + result = 4; + +/* If the first region was bounded without negating it, but the second + region was also bounded without negating it, the second region is + completely inside the first region. */ + } else { + result = 3; + } + +/* If part of the mesh of the second Region was inside the first region, + and part was outside, then there is partial ocverlap. */ + } else if( !allbad ) { + result = 4; + +/* If no part of the mesh of the (possibly negated) second Region was inside + the (possibly negated) first region ... */ + } else { + +/* First deal with cases where the first region is unbounded. */ + if( !bnd1 ) { + if( reg1_neg && astOK ) { + astError( AST__INTER, "astOverlap(%s): Inconsistent " + "state 5 (internal AST programming error).", + status, astGetClass( this ) ); + } else if( reg2_neg ){ + result = 2; + } else { + result = 1; + } + +/* The second region has a mesh so it must be bounded. */ + } else if( !bnd2 && astOK ) { + astError( AST__INTER, "astOverlap(%s): Inconsistent " + "state 6 (internal AST programming error).", + status, astGetClass( this ) ); + +/* So now we know both (possibly negated) regions are bounded. */ + } else { + +/* We know that none of the reg2 mesh points are inside the bounded reg1. + But this still leaves two cases: 1) reg1 could be contained completely + within reg2, or 2) there is no overlap between reg2 and reg1. To + distinguish between these two cases we use reg2 to transform a point + on the boundary of reg1. First get a mesh on the boundary of reg1. */ + reg1_mesh = astRegMesh( reg1 ); + +/* Transform this mesh into the coordinate system of the second Region. */ + ps3 = astTransform( cmap, reg1_mesh, 0, NULL ); + +/* Transform the points in this mesh using the second Region as a Mapping. + Any points outside the second region will be set bad in the output + PointSet. */ + ps4 = astTransform( (AstMapping *) reg2, ps3, 1, NULL ); + +/* Get pointers to the axis data in this PointSet,and check they can be + used safely. */ + ptr = astGetPoints( ps4 ); + if( astOK ) { + +/* Test the firts point and set a flag indicating if we are in case 1 (if + not, we must be in case 2). */ + case1 = ( ptr[ 0 ][ 0 ] != AST__BAD ); + +/* Apply logic similar to the other cases to determine the result. */ + if( reg1_neg ) { + if( case1 == ( reg2_neg != 0 ) ) { + result = 3; + } else { + result = 4; + } + } else { + if( case1 == ( reg2_neg != 0 ) ) { + result = 1; + } else { + result = 2; + } + } + } + +/* Free resources. */ + reg1_mesh = astAnnul( reg1_mesh ); + ps3 = astAnnul( ps3 ); + ps4 = astAnnul( ps4 ); + } + } + } + +/* If there was no intersection or overlap, but the regions touch, then we + consider there to be an intersection if either region is closed. */ + if( touch && result == 1 ) { + if( astGetClosed( this) || astGetClosed( that ) ) result = 4; + } + +/* Free resources.*/ + reg2_submesh = astAnnul( reg2_submesh ); + ps2 = astAnnul( ps2 ); + } + +/* Free resources.*/ + fs = astAnnul( fs ); + bfrm_reg1 = astAnnul( bfrm_reg1 ); + frm_reg1 = astAnnul( frm_reg1 ); + map_reg1 = astAnnul( map_reg1 ); + cmap = astAnnul( cmap ); + map = astAnnul( map ); + ps1 = astAnnul( ps1 ); + reg2_mesh = astAnnul( reg2_mesh ); + unc = astAnnul( unc ); + unc1 = astAnnul( unc1 ); + if( mask) mask = astFree( mask ); + } + fs0 = astAnnul( fs0 ); + +/* The returned value should take account of whether "this" or "that" is + the first Region. If "this" was used as the first Region, then the + result value calculated above is already correct. If "that" was used as + the first Region, then we need to change the result to swap "this" and + "that". */ + if( reg1 == that ) { + if( result == 2 ) { + result = 3; + } else if( result == 3 ) { + result = 2; + } + } + +/* Re-instate the original Negated flags. */ + if( this_neg ) astNegate( this ); + if( that_neg ) astNegate( that ); + +/* If not OK, return zero. */ + if( !astOK ) result = 0; + +/* Return the result. */ + return result; +} + +static void Overlay( AstFrame *template_frame, const int *template_axes, + AstFrame *result, int *status ) { +/* +* Name: +* Overlay + +* Purpose: +* Overlay the attributes of a template Region on to another Frame. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void Overlay( AstFrame *template, const int *template_axes, +* AstFrame *result, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astOverlay +* method inherited from the Frame class). + +* Description: +* This function overlays attributes from the current Frame of a +* Region 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. + +* Parameters: +* template +* Pointer to the template Region, for whose current Frame +* 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 axis in the current Frame of +* the template Region to which it corresponds. This array is +* used to establish from which template Frame axis any +* axis-dependent attributes should be obtained. +* +* If any axis in the result Frame is not associated with a +* template Frame 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. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the current Frame in the Region and invoke its + astOverlay method to overlay its attributes. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( ((AstRegion *) template_frame)->frameset, AST__CURRENT ); + astOverlay( fr, template_axes, result ); + fr = astAnnul( fr ); +} + +static void PermAxes( AstFrame *this_frame, const int perm[], int *status ) { +/* +* Name: +* PermAxes + +* Purpose: +* Permute the order of a Region's axes. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void PermAxes( AstFrame *this, const int perm[], int *status ) + +* Class Membership: +* Region member function (over-rides the astPermAxes method +* inherited from the Frame class). + +* Description: +* This function permutes the order in which the axes in the +* current Frame of a Region occur. + +* Parameters: +* this +* Pointer to the Region. +* perm +* An array of int (with one element for each axis of the +* Region's current Frame) which lists the axes in their new +* order. Each element of this array should be a (zero-based) +* axis index identifying the axes according to their old +* (un-permuted) order. +* status +* Pointer to the inherited status variable. + +* Notes: +* - Only genuine permutations of the axis order are permitted, so +* each axis must be referenced exactly once in the "perm" array. +* - If more than one axis permutation is applied to the same Frame +* in a Region, the effects are cumulative. +*/ + +/* Local Variables: */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Invoke the astPermAxes method on the encapsulated FrameSet. */ + astPermAxes( this->frameset, perm ); + +} + +static AstFrame *PickAxes( AstFrame *this_frame, int naxes, const int axes[], + AstMapping **map, int *status ) { +/* +* Name: +* PickAxes + +* Purpose: +* Create a new Frame by picking axes from a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstFrame *PickAxes( AstFrame *this, int naxes, const int axes[], +* AstMapping **map, int *status ) + +* Class Membership: +* Region member function (over-rides the astPickAxes protected +* method inherited from the Frame class). + +* Description: +* This function creates a new Frame whose axes are copies of axes +* picked from the encapsulated Frame of an existing Region. Other +* Frame attributes are also copied from this existing Frame to the +* new Frame. Zero or more of the original axes may be picked in +* any order, but each can be used only once. Additional axes (with +* default characteristics) may be included in the new Frame if +* required. +* +* Optionally, a Mapping that converts between the original Frame's +* axes and those of the new Frame may also be returned. + +* Parameters: +* this +* Pointer to the Region. +* naxes +* The number of axes required in the new Frame. +* axes +* Pointer to an array of int with naxes elements. This should +* contain (zero based) axis indices specifying the axes which +* are to be included in the new Frame, in the order +* required. Each axis index may occur only once. +* +* If additional (default) axes are also to be included, the +* corresponding elements of this array should be set to -1. +* map +* Address of a location to receive a pointer to a new +* Mapping. This will be a PermMap (or a UnitMap as a special +* case) that describes the axis permutation that has taken +* place between the current Frame of the Region and the new +* Frame. The forward transformation will convert from the +* original Region's axes to the new one's, and vice versa. +* +* If this Mapping is not required, a NULL value may be supplied +* for this parameter. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* Pointer to the new Frame. + +* Notes: +* - The class of object returned may differ from that of the +* original current Frame, depending on which axes are +* selected. For example, if a single axis is picked from a +* SkyFrame (which always has two axes), the resulting Frame cannot +* be a valid SkyFrame, so will revert to the parent class (Frame) +* instead. +* - The new Frame contains a deep copy of all the data selected +* from the original current Frame. Modifying the new Frame will +* therefore not affect the Region or the Frames it contains. +* - 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: */ + AstFrame *cfrm; /* Current Frame from input Region */ + AstFrame *frame; /* Pointer to Frame to be returned */ + AstMapping *cbmap; /* Base->current Mapping from input Region */ + AstMapping *fsmap; /* Mapping from selected current to base axes */ + AstRegion *breg; /* Region spanning selected base Frame axes */ + AstRegion *creg; /* Region spanning selected current Frame axes */ + AstRegion *this; /* Pointer to Region structure */ + int *base_axes; /* Holds selected base frame axis indices */ + int def; /* Were any default axes requested? */ + int i; /* Axis index */ + int nbase; /* No. of selected base Frame axes */ + +/* Initialise the returned pointers. */ + if ( map ) *map = NULL; + frame = NULL; + +/* Check the global error status. */ + if ( !astOK ) return frame; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Check that a valid set of axes is being selected . */ + astValidateAxisSelection( this, naxes, axes, "astPickAxes" ); + +/* Pick the required axes from the current Frame of the encapsulated + FrameSet. */ + cfrm = astGetFrame( this->frameset, AST__CURRENT ); + frame = astPickAxes( cfrm, naxes, axes, map ); + +/* See if any default axes are to be included in the returned Frame. */ + def = 0; + for( i = 0; i < naxes; i++ ) { + if( axes[ i ] < 0 ) def = 1; + } + +/* Regions cannot yet include extra default axes in the returned Frame + so return a basic Frame if any default axes were requested. */ + if( ! def ) { + +/* We now see if the requested set of current Frame axes correspond to a + unique set of base Frame axes. If they do, we may be able to return a + Region spanning the selected axes rather than just a Frame. The check + is performed by attempting to split the current->base Mapping. */ + cbmap = astGetMapping( this->frameset, AST__CURRENT, AST__BASE ); + base_axes = astMapSplit( cbmap, naxes, axes, &fsmap ); + +/* Check the Mapping could be split. */ + if( base_axes ) { + +/* Store the number of base Frame axes that correspond to the requested + set of current Frame axes. */ + nbase = astGetNout( fsmap ); + +/* Attempt to create a new Region that spans the corresponding set of + base Frame axes. */ + breg = astRegBasePick( this, nbase, base_axes ); + if( breg ) { + +/* Use the split Mapping to map the base Frame region into the requested + Frame. We invert the "fsmap" first so that it maps the selected base + Frame axes into the selected current Frame axes. */ + astInvert( fsmap ); + creg = astMapRegion( breg, fsmap, frame ); + +/* Copy properties from the old Region to the new Region. */ + astRegOverlay( creg, this, 0 ); + +/* Return this new Region in place of the simple Frame found above. */ + (void) astAnnul( frame ); + frame = (AstFrame *) creg; + +/* Free resources */ + breg = astAnnul( breg ); + } + fsmap = astAnnul( fsmap ); + base_axes = astFree( base_axes ); + } + cbmap = astAnnul( cbmap ); + } + cfrm = astAnnul( cfrm ); + +/* If an error occurred, annul the Mapping pointer (if requested) and + the new Frame pointer. */ + if ( !astOK ) { + if ( map ) *map = astAnnul( *map ); + frame = astAnnul( frame ); + } + +/* Return the pointer to the new Frame. */ + return frame; +} + +static void RegBaseBox( AstRegion *this, double *lbnd, double *ubnd, int *status ){ +/* +*+ +* Name: +* astRegBaseBox + +* Purpose: +* Returns the bounding box of an un-negated Region in the base Frame of +* the encapsulated FrameSet. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* void astRegBaseBox( AstRegion *this, double *lbnd, double *ubnd ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns the upper and lower axis bounds of a Region in +* the base Frame of the encapsulated FrameSet, assuming the Region +* has not been negated. That is, the value of the Negated attribute +* is ignored. + +* Parameters: +* this +* Pointer to the Region. +* lbnd +* Pointer to an array in which to return the lower axis bounds +* covered by the Region in the base Frame of the encapsulated +* FrameSet. It should have at least as many elements as there are +* axes in the base Frame. +* ubnd +* Pointer to an array in which to return the upper axis bounds +* covered by the Region in the base Frame of the encapsulated +* FrameSet. It should have at least as many elements as there are +* axes in the base Frame. + +*- +*/ + +/* Check the inherited status. */ + if( !astOK ) return; + +/* This abstract implementation simply reports an error. All sub-classes of + Region should over-ride this to return appropriate values. */ + astError( AST__INTER, "astRegBaseBox(%s): The %s class does not implement " + "the astRegBaseBox method inherited from the Region class " + "(internal AST programming error).", status, astGetClass( this ), + astGetClass( this ) ); +} + +static void RegBaseBox2( AstRegion *this, double *lbnd, double *ubnd, int *status ){ +/* +*+ +* Name: +* astRegBaseBox2 + +* Purpose: +* Returns the bounding box of an un-negated Region in the base Frame of +* the encapsulated FrameSet. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* void astRegBaseBox2( AstRegion *this, double *lbnd, double *ubnd ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function is similar to astRegBaseBox in that it returns the +* upper and lower axis bounds of a Region in the base Frame of the +* encapsulated FrameSet. But, in addition to assuming that the +* supplied Region has not been negated, it also assumes that any +* component Regions contained within the supplied Region have not been +* negated. + +* Parameters: +* this +* Pointer to the Region. +* lbnd +* Pointer to an array in which to return the lower axis bounds +* covered by the Region in the base Frame of the encapsulated +* FrameSet. It should have at least as many elements as there are +* axes in the base Frame. +* ubnd +* Pointer to an array in which to return the upper axis bounds +* covered by the Region in the base Frame of the encapsulated +* FrameSet. It should have at least as many elements as there are +* axes in the base Frame. + +*- +*/ + +/* This base class implementation simply calls astRegBaseBox. Sub-classes + which contain component Regions should override it. */ + astRegBaseBox( this, lbnd, ubnd ); + +} + +static AstPointSet *RegBaseGrid( AstRegion *this, int *status ){ +/* +*+ +* Name: +* astRegBaseGrid + +* Purpose: +* Return a PointSet containing points spread through the volume of a +* Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstPointSet *astRegBaseGrid( AstRegion *this ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a PointSet containing a set of points spread +* through the volume of the Region. The points refer to the base Frame of +* the encapsulated FrameSet. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* Pointer to the PointSet. If the Region is unbounded, a NULL pointer +* will be returned. + +* Notes: +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. +*- +*/ + +/* Local Variables: */ + AstBox *box; + AstFrame *frmb; + AstPointSet *ps1; + AstPointSet *ps2; + AstPointSet *result; + double **ptr2; + double **ptr; + double *lbnd; + double *ubnd; + int good; + int ic; + int ip; + int ipr; + int meshsize; + int naxb; + int np; + int npnt2; + int ntry; + +/* Initialise */ + result= NULL; + +/* Check the local error status. */ + if ( !astOK ) return NULL; + +/* If the Region structure contains a pointer to a PointSet holding + positions spread over the volume of the Region in the base Frame, + return it. */ + if( this->basegrid ) { + result = astClone( this->basegrid ); + +/* Otherwise, check the Region is bounded. */ + } else if( astGetBounded( this ) ) { + +/* Get the original MeshSize attribute. */ + meshsize = astGetMeshSize( this ); + +/* Get the base Frame bounding box. */ + naxb = astGetNin( this->frameset ); + lbnd = astMalloc( sizeof( double )*(size_t)naxb ); + ubnd = astMalloc( sizeof( double )*(size_t)naxb ); + astRegBaseBox( this, lbnd, ubnd ); + +/* Create a Box covering this bounding box. */ + frmb = astGetFrame( this->frameset, AST__BASE ); + box = astBox( frmb, 1, lbnd, ubnd, NULL, "", status ); + +/* Loop until we have a grid of nearly the right size. Make at most three + attempts. */ + ipr = 0; + np = meshsize; + ntry = 0; + while( ntry++ < 3 ) { + +/* Copy the MeshSize attribute to the new Box since this will be used by + the invocation of astRegBaseGrid below. */ + astSetMeshSize( box, np ); + +/* Invoke the Box astRegGrid method. Note, the Box class overrides this + implementation of astRegBaseGrid and does not (must not) invoke this + implementation, in order to avoid an infinite loop. */ + ps1 = astRegBaseGrid( box ); + +/* Some of the base Frame points in the above bounding box will fall outside + the supplied Region. Use the Region as a Mapping to determine which they + are. Since the points are base Frame points, use astBTransform rather + than astTransform. */ + ps2 = astBTransform( this, ps1, 1, NULL ); + +/* We now create a PointSet which is a copy of "ps2" but with all the bad + points (i.e. the points in the bounding box grid which are not inside + the supplied Region) removed. Create a result PointSet which is the same + size as "ps2", then copy just the good points from "ps2" to the result + PointSet, keeping a record of the number of points copied. */ + ptr2 = astGetPoints( ps2 ); + npnt2 = astGetNpoint( ps2 ); + result = astPointSet( npnt2, naxb, "", status ); + ptr = astGetPoints( result ); + if( astOK ) { + +/* Initialise the index of the next point to be stored in "result". */ + ipr = 0; + +/* Loop round all points in "ps2" */ + for( ip = 0; ip < npnt2; ip++ ) { + +/* Copy each axis value for this point from "ps2" to "result". If a bad + axis value is encountered, flag that the point is bad and break out of + the axis loop. */ + good = 1; + for( ic = 0; ic < naxb; ic++ ) { + if( ptr2[ ic ][ ip ] == AST__BAD ) { + good = 0; + break; + } else { + ptr[ ic ][ ipr ] = ptr2[ ic ][ ip ]; + } + } + +/* If the current point has no bad axis values, increment the index of + the next point to be stored in "result". */ + if( good ) ipr++; + } + } + +/* Free resources */ + ps1 = astAnnul( ps1 ); + ps2 = astAnnul( ps2 ); + +/* Leave the loop if an error has occurred. */ + if( !astOK ) break; + +/* If the number of points in the grid is within 5% of the target value, + it is good enough, so break. */ + if( fabs( (double)( ipr - meshsize ) )/meshsize < 0.05 ) break; + +/* Otherwise, adjust the target size of the grid by the ratio by which it + is in error. Don't do this if we have reached the maximum number of + re-tries. */ + if( ntry < 3 ) { + if( ipr == 0 ) { + np *= 10; + } else { + np *= (double)meshsize/(double)ipr; + } + result = astAnnul( result ); + } + } + +/* Truncate the "result" PointSet to exclude any unused space at the end + of the axis values arrays. */ + if( astOK ) astSetNpoint( result, ipr ); + +/* Free resources */ + lbnd = astFree( lbnd ); + ubnd = astFree( ubnd ); + frmb = astAnnul( frmb ); + box = astAnnul( box ); + +/* Cache the new grid for future use. */ + if( astOK ) this->basegrid = astClone( result ); + } + +/* Annul the result if an error occurred. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the result */ + return result; +} + +static AstRegion **RegSplit( AstRegion *this, int *nlist, int *status ){ +/* +*+ +* Name: +* astRegSplit + +* Purpose: +* Split a Region into a list of disjoint component Regions. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstRegion **astRegSplit( AstRegion *this, int *nlist ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function splits the supplied Region into a set of disjoint +* component Regions. If the Region cannot be split, then the returned +* array contains only one pointer - a clone of the supplied Region +* pointer. + +* Parameters: +* this +* Pointer to the Region. +* nlist +* Pointer to an int in which to return the number of elements in +* the returned array. + +* Returned Value: +* Pointer to dynamically alloctaed memory holding an array of Region +* pointers. The length of this array is given by the value returned +* in "*nlist". The pointers in the returned array should be annulled +* using astAnnul when no longer needed, and the memory used to hold +* the array should be freed using astFree. + +* Notes: +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. +*- +*/ + +/* Local Variables; */ + AstRegion **result; + +/* Initialise. */ + result = NULL; + *nlist = 0; + +/* Check the local error status. */ + if ( !astOK ) return result; + +/* The base class just returns an array containing a clone of the + supplied Region pointer. */ + result = astMalloc( sizeof( *result ) ); + if( astOK ) { + result[ 0 ] = astClone( this ); + *nlist = 1; + } + + if( !astOK ) { + result = astFree( result ); + *nlist = 0; + } + + return result; +} + +static AstPointSet *RegBaseMesh( AstRegion *this, int *status ){ +/* +*+ +* Name: +* astRegBaseMesh + +* Purpose: +* Return a PointSet containing points spread around the boundary of a +* Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstPointSet *astRegBaseMesh( AstRegion *this ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a PointSet containing a set of points on the +* boundary of the Region. The points refer to the base Frame of +* the encapsulated FrameSet. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* Pointer to the PointSet. The axis values in this PointSet will have +* associated accuracies derived from the uncertainties which were +* supplied when the Region was created. +* +* If the Region has no boundary (i.e. is equivalent to a NullRegion), the +* returned PointSet will contain a single point with a value of AST__BAD +* on every axis. + +* Notes: +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. +*- +*/ + +/* Check the local error status. */ + if ( !astOK ) return NULL; + +/* This abstract method must be over-ridden by each concrete sub-class. + Report an error if this null imlementation is called.*/ + astError( AST__INTER, "astRegBaseMesh(%s): The %s class does not implement " + "the astRegBaseMesh method inherited from the Region class " + "(internal AST programming error).", status, astGetClass( this ), + astGetClass( this ) ); + return NULL; +} + +static AstRegion *RegBasePick( AstRegion *this, int naxes, const int *axes, + int *status ){ +/* +*+ +* Name: +* astRegBasePick + +* Purpose: +* Return a Region formed by picking selected base Frame axes from the +* supplied Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstRegion *astRegBasePick( AstRegion *this, int naxes, const int *axes ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function attempts to return a Region that is spanned by selected +* axes from the base Frame of the encapsulated FrameSet of the supplied +* Region. This may or may not be possible, depending on the class of +* Region. If it is not possible a NULL pointer is returned. + +* Parameters: +* this +* Pointer to the Region. +* naxes +* The number of base Frame axes to select. +* axes +* An array holding the zero-based indices of the base Frame axes +* that are to be selected. + +* Returned Value: +* Pointer to the Region, or NULL if no region can be formed. + +* Notes: +* - This base implementation returns NULL unless all base Frame axes +* are selected (possibly in a permuted order). +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. +*- +*/ +/* Local Variables: */ + AstFrame *fr; /* Pointer to the Region's base Frame */ + AstRegion *result; /* The returned Region pointer */ + int found; /* Has the current axis index been found yet? */ + int i; /* Axis index */ + int j; /* Index into the "axes" array */ + int nax; /* No. of base Frame axes */ + int ok; /* Are we doing a genuine axis permutation? */ + int unit; /* Is the axis permutation a unit map? */ + +/* Initialise */ + result = NULL; + +/* Check the local error status. */ + if ( !astOK ) return result; + +/* Get a pointer to the base Frame int he encapsulated FrameSet. */ + fr = astGetFrame( this->frameset, AST__BASE ); + +/* See how many axes it has. We only proceed if we are selecting all axes + in the base Frame. */ + nax = astGetNaxes( fr ); + if( nax == naxes ) { + +/* We now check that the axes array is a genuine permutation of all axes. + This means that all axis indices must occur once, and only once, within + the "axes" array. Look for each axis index in turn. */ + unit = 1; + ok = 1; + for( i = 0; i < nax && ok; i++ ) { + +/* Check each element of the axes array to see if it holds the axis index + currently being looked for. */ + found = 0; + for( j = 0; j < nax; j++ ) { + +/* If so, if this axis index has already been found, break out of the + loop. */ + if( axes[ j ] == i ) { + if( found ) { + ok = 0; + break; + } + found = 1; + +/* Note if we do not have a unit map (i.e. each axis is permuted onto itself). */ + if( i != j ) unit = 0; + } + } + +/* If the axis index was not found, we do not have a genuine axis + permutation. */ + if( !found ) ok = 0; + } + +/* If we have a genuine axis permutation, create a Region which is a copy + of the supplied region and set it to represent its base Frame. */ + if( ok ) { + result = astCopy( this ); + astSetRegFS( result, fr ); + +/* If the axis selection is not equivalent to a unit mapping, we now + permute the axes. */ + if( !unit ) astPermAxes( result, axes ); + } + } + +/* Free resources. */ + fr = astAnnul( fr ); + +/* Returned the result. */ + return result; +} + +static double *RegCentre( AstRegion *this, double *cen, double **ptr, + int index, int ifrm, int *status ){ +/* +*+ +* Name: +* astRegCentre + +* Purpose: +* Re-centre a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* double *astRegCentre( AstRegion *this, double *cen, double **ptr, +* int index, int ifrm ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function shifts the centre of the supplied Region to a +* specified position, or returns the current centre of the Region. + +* Parameters: +* this +* Pointer to the Region. +* cen +* Pointer to an array of axis values, giving the new centre. +* Supply a NULL value for this in order to use "ptr" and "index" to +* specify the new centre. +* ptr +* Pointer to an array of pointers, one for each axis in the Region. +* Each pointer locates an array of axis values. This is the format +* returned by the PointSet method astGetPoints. Only used if "cen" +* is NULL. +* index +* The index of the point within the arrays identified by "ptr" at +* which is stored the coords for the new centre position. Only used +* if "cen" is NULL. +* ifrm +* Should be AST__BASE or AST__CURRENT. Indicates whether the centre +* position is supplied and returned in the base or current Frame of +* the FrameSet encapsulated within "this". + +* Returned Value: +* If both "cen" and "ptr" are NULL then a pointer to a newly +* allocated dynamic array is returned which contains the centre +* coords of the Region. This array should be freed using astFree when +* no longer needed. If either of "ptr" or "cen" is not NULL, then a +* NULL pointer is returned. + +* Notes: +* - Any bad (AST__BAD) centre axis values are ignored. That is, the +* centre value on such axes is left unchanged. +* - Some Region sub-classes do not have a centre. Such classes will report +* an AST__INTER error code if this method is called with either "ptr" or +* "cen" not NULL. If "ptr" and "cen" are both NULL, then no error is +* reported if this method is invoked on a Region of an unsuitable class, +* but NULL is always returned. + +*- +*/ + +/* Local Variables: */ + double *result; + +/* Initialise */ + result = NULL; + +/* Check the local error status. */ + if ( !astOK ) return result; + +/* This abstract method must be over-ridden by each concrete sub-class + which allows the centre to be shifted. Report an error if this null + imlementation is called to set a new centre. If it is called to + enquire the current centre, then return a NULL pointer. */ + if( ptr || cen ) astError( AST__INTER, "astRegCentre(%s): The %s " + "class does not implement the astRegCentre method " + "inherited from the Region class (internal AST " + "programming error).", status, astGetClass( this ), + astGetClass( this ) ); + + return NULL; +} + +static void RegClearAttrib( AstRegion *this, const char *aattrib, + char **base_attrib, int *status ) { +/* +*+ +* Name: +* astRegClearAttrib + +* Purpose: +* Clear an attribute value for a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* void astRegClearAttrib( AstRegion *this, const char *aattrib, +* char **base_attrib ) + +* Class Membership: +* Region virtual function + +* Description: +* This function clears the value of a named attribute in both the base +* and current Frame in the FrameSet encapsulated within a Region, without +* remapping either Frame. +* +* No error is reported if the attribute is not recognised by the base +* Frame. + +* Parameters: +* this +* Pointer to the Region. +* aattrib +* Pointer to a null terminated string holding the attribute name. +* base_attrib +* Address of a location at which to return a pointer to the null +* terminated string holding the attribute name which was cleared in +* the base Frame of the encapsulated FrameSet. This may differ from +* the supplied attribute if the supplied attribute contains an axis +* index and the current->base Mapping in the FrameSet produces an +* axis permutation. The returned pointer should be freed using +* astFree when no longer needed. A NULL pointer may be supplied in +* which case no pointer is returned. +*- +*/ + +/* Local Variables: */ + AstFrame *frm; + AstMapping *junkmap; + AstMapping *map; + AstRegion *unc; + char *attrib; + char *battrib; + char buf1[ 100 ]; + int *outs; + int axis; + int baxis; + int i; + int len; + int nc; + int rep; + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Produce a lower case version of the attribute name string */ + nc = strlen( aattrib ); + attrib = astMalloc( nc + 1 ); + for( i = 0; i < nc; i++ ) attrib[ i ] = tolower( aattrib[ i ] ); + attrib[ nc ] = 0; + +/* Clear the attribute in the current Frame in the encapsulated FrameSet. + Use the protected astClearAttrib method which does not cause the Frame + to be remapped within the FrameSet. */ + frm = astGetFrame( this->frameset, AST__CURRENT ); + astClearAttrib( frm, attrib ); + frm = astAnnul( frm ); + +/* Indicate that we should use the supplied attribute name with the base Frame. */ + battrib = NULL; + +/* If the attribute name contains an axis number, we need to create a new + attribute name which refers to the corresponding base Frame axis + (since the base<->current Mapping may permute the axes). First parse the + supplied attribute name to locate any axis index. */ + len = strlen( attrib ); + if( nc = 0, ( 2 == astSscanf( attrib, "%[^(](%d) %n", buf1, &axis, + &nc ) ) && ( nc >= len ) ) { + +/* If found, convert the axis index from one-based to zero-based. */ + axis--; + +/* See if the specified current Frame axis is connected to one and only + one base Frame axis. If so, get the index of the base Frame axis. */ + map = astGetMapping( this->frameset, AST__CURRENT, AST__BASE ); + outs = astMapSplit( map, 1, &axis, &junkmap ); + if( junkmap && astGetNout( junkmap ) == 1 ) { + baxis = outs[ 0 ]; + +/* If the base Frame axis index is different to the current Frame axis + index, create a new attribute name string using the base Frame axis index. */ + if( baxis != axis ) { + battrib = astMalloc( strlen( attrib ) + 10 ); + if( battrib ) sprintf( battrib, "%s(%d)", buf1, baxis + 1 ); + } + +/* If there is no one base Frame axis which corresponds to the supplied + current Frame axis, report an error. */ + } else if( astOK ) { + astError( AST__INTER, "astRegClearAttrib(%s): Unable to clear " + "attribute \"%s\" in the base Frame of the %s", status, + astGetClass( this ), attrib, astGetClass( this ) ); + astError( AST__INTER, "There is no base Frame axis corresponding " + "to current Frame axis %d\n", status, axis + 1 ); + } + +/* Free resources */ + outs = astFree( outs ); + if( junkmap ) junkmap = astAnnul( junkmap ); + map = astAnnul( map ); + } + +/* Clear the appropriate attribute name in the base Frame. This time ensure + that any error caused by the attribute name is annulled. Also clear it in + any uncertainty Region (the current Frame of the uncertainty Region is + assumed to be equivalent to the base Frame of the parent Region). */ + frm = astGetFrame( this->frameset, AST__BASE ); + if( frm ) { + rep = astReporting( 0 ); + astClearAttrib( frm, battrib ? battrib : attrib ); + if( astTestUnc( this ) ) { + unc = astGetUncFrm( this, AST__BASE ); + astRegClearAttrib( unc, battrib ? battrib : attrib, NULL ); + unc = astAnnul( unc ); + } + if( astStatus == AST__BADAT ) astClearStatus; + astReporting( rep ); + } + frm = astAnnul( frm ); + +/* If required return the modified base Frame attribute name. Otherwise, + free it. */ + if( base_attrib ) { + if( battrib ) { + *base_attrib = battrib; + } else { + *base_attrib = astStore( NULL, attrib, strlen( attrib ) + 1 ); + } + } else { + battrib = astFree( battrib ); + } + +/* Since the base Frame has been changed, any cached information calculated + on the basis of the base Frame properties may no longer be up to date. */ + astResetCache( this ); + +/* Free resources. */ + attrib = astFree( attrib ); + +} + +static AstPointSet *RegGrid( AstRegion *this, int *status ){ +/* +*+ +* Name: +* astRegGrid + +* Purpose: +* Return a PointSet containing points spread through the volume of a +* Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstPointSet *astRegGrid( AstRegion *this ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a PointSet containing a mesh of points spread +* throughout the volume of the Region. The points refer to the current +* Frame of the encapsulated FrameSet. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* Pointer to the PointSet. The axis values in this PointSet will have +* associated accuracies derived from the uncertainties which were +* supplied when the Region was created. Annul the pointer using +* astAnnul when it is no longer needed. + +* Notes: +* - It should not be assumed that the returned points are evenly +* spaced withint he volume. +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. +*- +*/ + +/* Local Variables; */ + AstMapping *map; /* Base -> current Frame Mapping */ + AstPointSet *result; /* Pointer to returned PointSet */ + +/* Initialise the returned pointer */ + result = NULL; + +/* Check the local error status. */ + if ( !astOK ) return result; + +/* If the Region structure does not contain a pointer to a PointSet holding + positions evenly spread over the volume of the Region in the base + Frame, create one now. Note, we cannot cache the grid in the current + Frame in this way since the current Frame grid depends on the proprties + of the current Frame (e.g. System) which can be changed at any time. */ + if( !this->basegrid ) this->basegrid = astRegBaseGrid( this ); + +/* Get the simplified base->current Mapping */ + map = astRegMapping( this ); + +/* If the Mapping is a UnitMap, just return a clone of the PointSet + pointer stored in the Region structure. */ + if( astIsAUnitMap( map ) ){ + result = astClone( this->basegrid ); + +/* Otherwise, create a new PointSet holding the above points transformed + into the current Frame. */ + } else { + result = astTransform( map, this->basegrid, 1, NULL ); + } + +/* Free resources.*/ + map = astAnnul( map ); + +/* If an error has occurred, annul the returned PointSet. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the result. */ + return result; +} + +static AstPointSet *RegMesh( AstRegion *this, int *status ){ +/* +*+ +* Name: +* astRegMesh + +* Purpose: +* Return a PointSet containing points spread over the boundary of a +* Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstPointSet *astRegMesh( AstRegion *this ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a PointSet containing a mesh of points on the +* boundary of the Region. The points refer to the current Frame of +* the encapsulated FrameSet. + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* Pointer to the PointSet. The axis values in this PointSet will have +* associated accuracies derived from the uncertainties which were +* supplied when the Region was created. Annul the pointer using +* astAnnul when it is no longer needed. + +* Notes: +* - It should not be assumed that the returned points are evenly +* spaced on the boundary. +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. +*- +*/ + +/* Local Variables; */ + AstMapping *map; /* Base -> current Frame Mapping */ + AstPointSet *bmesh; /* Base Frame mesh */ + AstPointSet *result; /* Pointer to returned PointSet */ + +/* Initialise the returned pointer */ + result = NULL; + +/* Check the local error status. */ + if ( !astOK ) return result; + +/* Get a pointer to a PointSet holding positions evenly spread over the + boundary of the Region in the base Frame. */ + bmesh = astRegBaseMesh( this ); + +/* Get the simplified base->current Mapping */ + map = astRegMapping( this ); + +/* If the Mapping is a UnitMap, just return a clone of the mesh PointSet + pointer. */ + if( astIsAUnitMap( map ) ){ + result = astClone( bmesh ); + +/* Otherwise, create a new PointSet holding the above points transformed + into the current Frame. */ + } else { + result = astTransform( map, bmesh, 1, NULL ); + } + +/* Free resources.*/ + bmesh = astAnnul( bmesh ); + map = astAnnul( map ); + +/* If an error has occurred, annul the returned PointSet. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the result. */ + return result; +} + +static int RegDummyFS( AstRegion *this, int *status ){ +/* +*+ +* Name: +* astRegDummyFS + +* Purpose: +* Check if a Region has a dummy FrameSet. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* int astRegDummyFS( AstRegion *this ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a flag indicating if the supplied Region has +* a dummy FrameSet. +* +* The astDump method for a Region may choose not to include the +* Region's FrameSet in the dump, depending on the value of the +* RegionFS attribute and the nature of the FrameSet. If the FrameSet +* is omitted from the Dump, then special action has to be taken when +* the dump is subsequently read in and used to re-create the Region. +* On encounterting such a dump, the astLoadRegion function will create +* a dummy FrameSet and associate it with the reconstructed Region. +* The new Region should not be used however until this dummy FrameSet +* has been replaced by the correct FrameSet. Performing this replacement +* is the responsibility of the parent class (i.e. the class which choose +* to omit the FrameSet from the dump). These will usually be Region +* classes which encapsulate other Regions, such as CmpRegion, Prism, +* Stc, etc. +* +* This function can be used by astLoad... methods in sub-classes to +* determine if a newly loaded component Region has a dummy FrameSet. If +* so the astLoad function should either use the astSetRegFS method to +* store a new FrameSet in the component Region. If the parent Region +* itself has a dummy FrameSet (i.e. is a component Region contained +* within a higher level Region) then it cannot do this and should +* ignore the presence of the dummy FrameSet (it then becomes the +* responsibility of hte parent Region to load appropriate FrameSets +* into all its components). + +* Parameters: +* this +* Pointer to the Region. + +* Returned Value: +* Non-zero if the Region has a dummy FrameSet. + +*- +*/ + +/* Check the inherited status. */ + if( !astOK ) return 0; + +/* The Ident attribute of the FrameSet will be set to DUMMY_FS if the + FrameSet is a dummy. */ + return !strcmp( astGetIdent( this->frameset ), DUMMY_FS ); +} + +static int RegPins( AstRegion *this, AstPointSet *pset, AstRegion *unc, + int **mask, int *status ){ +/* +*+ +* Name: +* astRegPins + +* Purpose: +* Check if a set of points fall on the boundary of a given Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* int astRegPins( AstRegion *this, AstPointSet *pset, AstRegion *unc, +* int **mask ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function returns a flag indicating if the supplied set of +* points all fall on the boundary of the given Region. +* +* Some tolerance is allowed, as specified by the uncertainty Region +* stored in the supplied Region "this", and the supplied uncertainty +* Region "unc" which describes the uncertainty of the supplied points. + +* Parameters: +* this +* Pointer to the Region. +* pset +* Pointer to the PointSet. The points are assumed to refer to the +* base Frame of the FrameSet encapsulated by "this". +* unc +* Pointer to a Region representing the uncertainties in the points +* given by "pset". The Region is assumed to represent the base Frame +* of the FrameSet encapsulated by "this". Zero uncertainity is assumed +* if NULL is supplied. +* mask +* Pointer to location at which to return a pointer to a newly +* allocated dynamic array of ints. The number of elements in this +* array is equal to the value of the Npoint attribute of "pset". +* Each element in the returned array is set to 1 if the +* corresponding position in "pset" is on the boundary of the Region +* and is set to zero otherwise. A NULL value may be supplied +* in which case no array is created. If created, the array should +* be freed using astFree when no longer needed. + +* Returned Value: +* Non-zero if the points all fall on the boundary of the given +* Region, to within the tolerance specified. Zero otherwise. + +*- +*/ + +/* Check the inherited status. */ + if( !astOK ) return 0; + +/* This abstract implementation simply reports an error. All sub-classes of + Region should over-ride this to return appropriate values. */ + astError( AST__INTER, "astRegPins(%s): The %s class does not implement " + "the astRegPins method inherited from the Region class " + "(internal AST programming error).", status, astGetClass( this ), + astGetClass( this ) ); + return 0; +} + +static void GetRegionBounds( AstRegion *this, double *lbnd, double *ubnd, int *status ){ +/* +*++ +* Name: +c astGetRegionBounds +f AST_GETREGIONBOUNDS + +* Purpose: +* Returns the bounding box of Region. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c void astGetRegionBounds( AstRegion *this, double *lbnd, double *ubnd ) +f CALL AST_GETREGIONBOUNDS( THIS, LBND, UBND, STATUS ) + +* Class Membership: +* Region method. + +* Description: +c This function +f This routine +* returns the upper and lower limits of a box which just encompasses +* the supplied Region. The limits are returned as axis values within +* the Frame represented by the Region. The value of the Negated +* attribute is ignored (i.e. it is assumed that the Region has not +* been negated). + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region. +c lbnd +f LBND() = DOUBLE PRECISION (Returned) +c Pointer to an +f An +* array in which to return the lower axis bounds covered by the Region. +* It should have at least as many elements as there are axes in the +* Region. If an axis has no lower limit, the returned value will +* be the largest possible negative value. +c ubnd +f UBND() = DOUBLE PRECISION (Returned) +c Pointer to an +f An +* array in which to return the upper axis bounds covered by the Region. +* It should have at least as many elements as there are axes in the +* Region. If an axis has no upper limit, the returned value will +* be the largest possible positive value. +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Notes: +* - The value of the Negated attribute is ignored (i.e. it is assumed that +* the Region has not been negated). +* - If an axis has no extent on an axis then the lower limit will be +* returned larger than the upper limit. Note, this is different to an +* axis which has a constant value (in which case both lower and upper +* limit will be returned set to the constant value). +* - If the bounds on an axis cannot be determined, AST__BAD is returned for +* both upper and lower bounds + +*-- +*/ + +/* Local Variables: */ + AstFrame *frm; /* Current Frame */ + AstMapping *smap; /* Simplified base -> current Mapping */ + AstPointSet *bmesh; /* PointSet holding base Frame mesh */ + AstPointSet *cmesh; /* PointSet holding current Frame mesh */ + double **bptr; /* Pointer to PointSet coord arrays */ + double **cptr; /* Pointer to PointSet coord arrays */ + double *blbnd; /* Lower bounds in base Frame */ + double *bubnd; /* Upper bounds in base Frame */ + double *p; /* Array of values for current axis */ + double width; /* Width of bounding box on i'th axis */ + int i; /* Axis count */ + int ip; /* Index of current corner */ + int j; /* Timer for low/high swaps */ + int jmax; /* Increment between low/high swaps */ + int lo; /* Assign low bound to next corner? */ + int nbase; /* Number of base Frame axes */ + int ncur; /* Number of current Frame axes */ + int npos; /* Number of box corners */ + +/* Check the inherited status. */ + if( !astOK ) return; + +/* Get the simplified base to current Mapping. */ + smap = astRegMapping( this ); + +/* If the simplified Mapping is a UnitMap, just store the base box bounds + in the returned arrays */ + if( astIsAUnitMap( smap ) ) { + astRegBaseBox( this, lbnd, ubnd ); + +/* Otherwise, we get a mesh of points over the boundary of the Region within + the base Frame, transform them into the current Frame, and find their bounds. */ + } else { + +/* If the Region is bounded, we can get a genuine mesh of points on the + boundary of the Region. */ + if( astGetBounded( this ) ) { + bmesh = astRegBaseMesh( this ); + +/* If the Region is not bounded, no mesh can be created so we use the + corners of the base frame bounding box instead. */ + } else { + +/* Get workspace to hold the bounds of the region within the base Frame. */ + nbase = astGetNin( smap ); + blbnd = astMalloc( sizeof( double )*nbase ); + bubnd = astMalloc( sizeof( double )*nbase ); + +/* Get the base Frame bounding box. */ + astRegBaseBox( this, blbnd, bubnd ); + +/* Get the number of corners in the base Frame bounding box. */ + npos = pow( 2, nbase ); + +/* Create a PointSet to hold the positions at the corners in the base + frame box. */ + bmesh = astPointSet( npos, nbase, " ", status ); + bptr = astGetPoints( bmesh ); + if( bptr ) { + +/* Store the coordinates of the box corners in the PointSet. */ + jmax = 1; + for( i = 0; i < nbase; i++ ) { + p = bptr[ i ]; + + lo = 1; + j = 0; + for( ip = 0; ip < npos; ip++,j++ ) { + if( j == jmax ) { + lo = 1 - lo; + j = 0; + } + p[ ip ] = lo ? blbnd[ i ] : bubnd[ i ]; + } + + jmax *= 2; + } + } + +/* Release resources. */ + blbnd = astFree( blbnd ); + bubnd = astFree( bubnd ); + } + +/* Create a new PointSet holding the above points transformed into the + current Frame. */ + cmesh = astTransform( smap, bmesh, 1, NULL ); + +/* There is a possibility that these points may span a singularity in the + coordinate system such as the RA=0 line in a SkyFrame. So ensure the + axis values are normalised into the shortest possible range. */ + frm = astGetFrame( this->frameset, AST__CURRENT ); + ncur = astGetNaxes( frm ); + + cptr = astGetPoints( cmesh ); + npos = astGetNpoint( cmesh ); + for( i = 0; i < ncur; i++ ) { + astAxNorm( frm, i+1, 1, npos, cptr[i] ); + } + +/* Get the axis bounds of this PointSet. */ + astBndPoints( cmesh, lbnd, ubnd ); + +/* There is again a possibility that these bounds may span a singularity in + the coordinate system such as the RA=0 line in a SkyFrame. So for each + axis we ensure the width (i.e. "ubnd-lbnd" ) is correct. */ + for( i = 0; i < ncur; i++ ) { + width = astAxDistance( frm, i + 1, lbnd[ i ], ubnd[ i ] ); + if( width != AST__BAD ) { + ubnd[ i ] = lbnd[ i ] + width; + } else { + ubnd[ i ] = AST__BAD; + lbnd[ i ] = AST__BAD; + } + } + +/* Release resources. */ + frm = astAnnul( frm ); + bmesh = astAnnul( bmesh ); + cmesh = astAnnul( cmesh ); + } + smap = astAnnul( smap ); +} + +static void GetRegionBounds2( AstRegion *this, double *lbnd, double *ubnd, int *status ){ +/* +*+ +* Name: +* astGetRegionBounds + +* Purpose: +* Returns the bounding box of Region. + +* Type: +* Protected virtual function. + +* Synopsis: +* #include "region.h" +* void astGetRegionBounds2( AstRegion *this, double *lbnd, double *ubnd ) + +* Class Membership: +* Region method. + +* Description: +* This function is like astGetRegionBounds, in that it returns the upper +* and lower limits of a box which just encompasses the supplied Region, +* as axis values within the Frame represented by the Region. But, in +* addition to assuming that the supplied Region has not been negated, it +* also assumes that any component Regions contained within the supplied +* Region have not been negated. + +* Parameters: +* this +* Pointer to the Region. +* lbnd +* Pointer to an array in which to return the lower axis bounds +* covered by the Region. It should have at least as many elements +* as there are axes in the Region. +* ubnd +* Pointer to an array in which to return the upper axis bounds +* covered by the Region. It should have at least as many elements +* as there are axes in the Region. + +* Notes: +* - The value of the Negated attribute is ignored (i.e. it is assumed that +* the Region has not been negated). The Nagated attributes of any +* component Regions are also ignored. + +*- +*/ + +/* Local Variables: */ + AstMapping *smap; /* Simplified base -> current Mapping */ + double *lbndb; /* Pointer to lower bounds on base box */ + double *ubndb; /* Pointer to upper bounds on base box */ + int i; /* Axis count */ + int nbase; /* Number of base Frame axes */ + int ncur; /* Number of current Frame axes */ + +/* Check the inherited status. */ + if( !astOK ) return; + +/* Find the number of axes in the base and current Frames of the + encapsulated FrameSet. */ + nbase = astGetNin( this->frameset ); + ncur = astGetNout( this->frameset ); + +/* Get the bounding box in the base Frame of the encapsulated FrameSet. */ + lbndb = astMalloc( sizeof( double )*(size_t) nbase ); + ubndb = astMalloc( sizeof( double )*(size_t) nbase ); + astRegBaseBox2( this, lbndb, ubndb ); + +/* Get the simplified base to current Mapping. */ + smap = astRegMapping( this ); + +/* Check pointers can be used safely. */ + if( smap ) { + +/* If the simplified Mapping is a UnitMap, just copy the base box bounds + to the returned arrays */ + if( astIsAUnitMap( smap ) ) { + for( i = 0; i < ncur; i++ ) { + lbnd[ i ] = lbndb[ i ]; + ubnd[ i ] = ubndb[ i ]; + } + +/* Otherwise, use astMapBox to find the corresponding current Frame + limits. */ + } else { + for( i = 0; i < ncur; i++ ) { + astMapBox( smap, lbndb, ubndb, 1, i, lbnd + i, ubnd + i, + NULL, NULL ); + } + } + } + +/* Release resources. */ + smap = astAnnul( smap ); + lbndb = astFree( lbndb ); + ubndb = astFree( ubndb ); +} + +static void GetRegionMesh( AstRegion *this, int surface, int maxpoint, + int maxcoord, int *npoint, double *points, + int *status ){ +/* +*++ +* Name: +c astGetRegionMesh +f AST_GETREGIONMESH + +* Purpose: +* Return a mesh of points covering the surface or volume of a Region. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c void astGetRegionMesh( AstRegion *this, int surface, int maxpoint, +c int maxcoord, int *npoint, double *points ) +f CALL AST_GETREGIONMESH( THIS, SURFACE, MAXPOINT, MAXCOORD, NPOINT, +f POINTS, STATUS ) + +* Class Membership: +* Region method. + +* Description: +c This function +f This routine +* returns the axis values at a mesh of points either covering the +* surface (i.e. boundary) of the supplied Region, or filling the +* interior (i.e. volume) of the Region. The number of points in +* the mesh is approximately equal to the MeshSize attribute. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region. +c surface +f SURFACE = LOGICAL (Given) +c If non-zero, +f If .TRUE., +* the returned points will cover the surface or the Region. +* Otherwise, they will fill the interior of the Region. +c maxpoint +f MAXPOINT = INTEGER (Given) +* If zero, the number of points in the mesh is returned in +c "*npoint", +f NPOINT, +* but no axis values are returned and all other parameters are ignored. +* If not zero, the supplied value should be the length of the +c second dimension of the "points" +f first dimension of the POINTS +* array. An error is reported if the number of points in the mesh +* exceeds this number. +c maxcoord +f MAXCOORD = INTEGER (Given) +* The length of the +c first dimension of the "points" array. +f second dimension of the POINTS array. +* An error is reported if the number of axes in the supplied Region +* exceeds this number. +c npoint +f NPOINT = INTEGER (Returned) +c A pointer to an integer in which to return the +f The +* number of points in the returned mesh. +c points +f POINTS( MAXPOINT, MAXCOORD ) = DOUBLE PRECISION (Returned) +c The address of the first element in a 2-dimensional array of +c shape "[maxcoord][maxpoint]", in which to return the coordinate +c values at the mesh positions. These are stored such that the +c value of coordinate number "coord" for point number "point" is +c found in element "points[coord][point]". +f An array in which to return the coordinates values at the mesh +f positions. These are stored such that the value of coordinate +f number COORD for point number POINT is found in element +f POINTS(POINT,COORD). +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Notes: +* - An error is reported if the Region is unbounded. +* - If the coordinate system represented by the Region has been +* changed since it was first created, the returned axis values refer +* to the new (changed) coordinate system, rather than the original +* coordinate system. Note however that if the transformation from +* original to new coordinate system is non-linear, the shape within +* the new coordinate system may be distorted, and so may not match +* that implied by the name of the Region subclass (Circle, Box, etc). + +*-- +*/ + +/* Local Variables: */ + AstPointSet *pset; /* PointSet holding mesh/grid axis values */ + double **ptr; /* Pointer to mesh/grid axes values */ + double *p; /* Pointer to next input axis value */ + double *q; /* Pointer to next output axis value */ + int j; /* Axis index */ + int nc; /* No. of axes to copy */ + +/* Initialise */ + *npoint = 0; + +/* Check the inherited status. */ + if( !astOK ) return; + +/* Report an error if the Region is unbounded. */ + if( !astGetBounded( this ) ) { + if( astOK ) astError( AST__MBBNF, "astGetRegionMesh(%s): The supplied %s" + " is unbounded so no mesh can be created to cover " + "it.", status, astGetClass( this ), astGetClass( this ) ); + } else { + +/* Get the mesh or grid as required. If only the size of the mesh or grid + is required, get it in the base Frame as there is no need to spend the + extra time transforming it into the current Frame. */ + if( maxpoint == 0 ){ + if( surface ) { + pset = astRegBaseMesh( this ); + } else { + pset = astRegBaseGrid( this ); + } + } else { + if( surface ) { + pset = astRegMesh( this ); + } else { + pset = astRegGrid( this ); + } + } + +/* Return the number of points in the mesh or grid. */ + *npoint = astGetNpoint( pset ); + +/* Do nothing more unless a non-zero array size was supplied. */ + if( *npoint > 0 && maxpoint != 0 && astOK ) { + +/* Check the supplied array is large enough. */ + if( *npoint > maxpoint ) { + astError( AST__DIMIN, "astGetRegionMesh(%s): The supplied " + "array can hold up to %d points but the %s supplied " + "has %d points on its mesh (programming error).", + status, astGetClass( this ), maxpoint, astGetClass( this ), + *npoint ); + } + +/* Get the dimensionality of the PointSet, and get a pointer to the axis + values. */ + nc = astGetNcoord( pset ); + ptr = astGetPoints( pset ); + +/* Check pointers can be used safely. */ + if ( astOK ) { + +/* Check the supplied array has room for all the axes. */ + if( nc > maxcoord ) { + astError( AST__DIMIN, "astGetRegionMesh(%s): The supplied " + "array can hold up to %d axes but the %s supplied " + "has %d axes (programming error).", status, + astGetClass( this ), maxcoord, astGetClass( this ), nc ); + +/* If all is OK, copy the current Frame axis values into the supplied array. */ + } else { + +/* Loop round the axes to be copied. */ + for( j = 0; j < nc; j++ ) { + +/* Get points to the first element of the input and output arrays. */ + p = ptr[ j ]; + q = points + j*maxpoint; + +/* Copying the axis values. */ + (void) memcpy( q, p, sizeof( double )*( *npoint ) ); + } + } + } + } + +/* Free resources. */ + pset = astAnnul( pset ); + } +} + +static void GetRegionPoints( AstRegion *this, int maxpoint, int maxcoord, + int *npoint, double *points, int *status ){ +/* +*++ +* Name: +c astGetRegionPoints +f AST_GETREGIONPOINTS + +* Purpose: +* Returns the positions that define the given Region. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c void astGetRegionPoints( AstRegion *this, int maxpoint, int maxcoord, +c int *npoint, double *points ) +f CALL AST_GETREGIONPOINTS( THIS, MAXPOINT, MAXCOORD, NPOINT, POINTS, +f STATUS ) + +* Class Membership: +* Region method. + +* Description: +c This function +f This routine +* returns the axis values at the points that define the supplied +* Region. The particular meaning of these points will depend on the +* type of class supplied, as listed below under "Applicability:". + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region. +c maxpoint +f MAXPOINT = INTEGER (Given) +* If zero, the number of points needed to define the Region is +* returned in +c "*npoint", +f NPOINT, +* but no axis values are returned and all other parameters are ignored. +* If not zero, the supplied value should be the length of the +c second dimension of the "points" +f first dimension of the POINTS +* array. An error is reported if the number of points needed to define +* the Region exceeds this number. +c maxcoord +f MAXCOORD = INTEGER (Given) +* The length of the +c first dimension of the "points" array. +f second dimension of the POINTS array. +* An error is reported if the number of axes in the supplied Region +* exceeds this number. +c npoint +f NPOINT = INTEGER (Returned) +c A pointer to an integer in which to return the +f The +* number of points defining the Region. +c points +f POINTS( MAXPOINT, MAXCOORD ) = DOUBLE PRECISION (Returned) +c The address of the first element in a 2-dimensional array of +c shape "[maxcoord][maxpoint]", in which to return +c the coordinate values at the positions that define the Region. +c These are stored such that the value of coordinate number +c "coord" for point number "point" is found in element +c "points[coord][point]". +f An array in which to return the coordinates values at the +f positions that define the Region. These are stored such that the +f value of coordinate number COORD for point number POINT +f is found in element POINTS(POINT,COORD). +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Applicability: +* Region +* All Regions have this attribute. +* Box +* The first returned position is the Box centre, and the second is +* a Box corner. +* Circle +* The first returned position is the Circle centre, and the second is +* a point on the circumference. +* CmpRegion +* Returns a value of zero for +c "*npoint" +f NPOINT +* and leaves the supplied array contents unchanged. To find the +* points defining a CmpRegion, use this method on the component +* Regions, which can be accessed by invoking +c astDecompose +f AST_DECOMPOSE +* on the CmpRegion. +* Ellipse +* The first returned position is the Ellipse centre. The second is +* the end of one of the axes of the ellipse. The third is some +* other point on the circumference of the ellipse, distinct from +* the second point. +* Interval +* The first point corresponds to the lower bounds position, and +* the second point corresponds to the upper bounds position. These +* are reversed to indicate an extcluded interval rather than an +* included interval. See the Interval constructor for more +* information. +* NullRegion +* Returns a value of zero for +c "*npoint" +f NPOINT +* and leaves the supplied array contents unchanged. +* PointList +* The positions returned are those that were supplied when the +* PointList was constructed. +* Polygon +* The positions returned are the vertex positions that were supplied +* when the Polygon was constructed. +* Prism +* Returns a value of zero for +c "*npoint" +f NPOINT +* and leaves the supplied array contents unchanged. To find the +* points defining a Prism, use this method on the component +* Regions, which can be accessed by invoking +c astDecompose +f AST_DECOMPOSE +* on the CmpRegion. + +* Notes: +* - If the coordinate system represented by the Region has been +* changed since it was first created, the returned axis values refer +* to the new (changed) coordinate system, rather than the original +* coordinate system. Note however that if the transformation from +* original to new coordinate system is non-linear, the shape within +* the new coordinate system may be distorted, and so may not match +* that implied by the name of the Region subclass (Circle, Box, etc). + +*-- +*/ + +/* Local Variables: */ + AstPointSet *pset; /* PointSet holding PointList axis values */ + double **ptr; /* Pointer to axes values in the PointList */ + double *p; /* Pointer to next input axis value */ + double *q; /* Pointer to next output axis value */ + int j; /* Axis index */ + int nc; /* No. of axes to copy */ + +/* Initialise */ + *npoint = 0; + +/* Check the inherited status. */ + if( !astOK ) return; + +/* Return the number of points used to define the Region, if any. */ + *npoint = this->points ? astGetNpoint( this->points ) : 0; + +/* Do nothing more unless a non-zero array size was supplied. */ + if( *npoint > 0 && maxpoint != 0 ) { + +/* Transform the base Frame axis values into the current Frame. */ + pset = astTransform( this->frameset, this->points, 1, NULL ); + +/* Get the dimensionality of this PointList, and get a pointer to the axis + values. */ + nc = astGetNcoord( pset ); + ptr = astGetPoints( pset ); + +/* Check pointers can be used safely. */ + if ( astOK ) { + +/* Check the supplied array has room for all the axis values. */ + if( nc > maxcoord ) { + astError( AST__DIMIN, "astGetRegionPoints(%s): The supplied " + "array can hold up to %d axes but the %s supplied " + "has %d axes (programming error).", status, + astGetClass( this ), maxcoord, astGetClass( this ), nc ); + + } else if( *npoint > maxpoint ) { + astError( AST__DIMIN, "astGetRegionPoints(%s): The supplied " + "array can hold up to %d points but the %s supplied " + "requires %d points to describe it (programming " + "error).", status, astGetClass( this ), maxpoint, + astGetClass( this ), *npoint ); + +/* If all is OK, copy the transformed axis values into the supplied array. */ + } else { + +/* Loop round the axes to be copied. */ + for( j = 0; j < nc; j++ ) { + +/* Get points to the first element of the input and output arrays. */ + p = ptr[ j ]; + q = points + j*maxpoint; + +/* Copying the axis values. */ + (void) memcpy( q, p, sizeof( double )*( *npoint ) ); + } + } + } + +/* Free resources. */ + pset = astAnnul( pset ); + + } +} + +static void RegOverlay( AstRegion *this, AstRegion *that, int unc, int *status ){ +/* +*+ +* Name: +* astRegOverlay + +* Purpose: +* Copy properties from one Region to another. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* void astRegOverlay( AstRegion *this, AstRegion *that, int unc ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function copies selected properties from "that" to "this". +* It is intended to be called by sub-classes which need to create a +* similar copy of an existing Region. For instance, subclass +* implementations of the Simplify method will usually use this +* function to ensure that the simplified Region loooks like the original +* Region. + +* Parameters: +* this +* Pointer to the new Region. +* that +* Pointer to the old Region. +* unc +* If non-zero, any uncertainty in "this" is cleared if "that" has +* no uncertainty. If zero, any uncertainty in "this" is left +* unchanged. +*- +*/ + +/* Check the inherited status. */ + if( !astOK ) return; + +/* Copy the required attribute values. */ + this->negated = that->negated; + this->closed = that->closed; + this->regionfs = that->regionfs; + this->adaptive = that->adaptive; + +/* Clear things that depend on the number of axes. */ + if( astGetNaxes( this ) == astGetNaxes( that ) ) { + if( astTestMeshSize( that ) ) astSetMeshSize( this, astGetMeshSize( that ) ); + if( astTestFillFactor( that ) ) astSetFillFactor( this, astGetFillFactor( that ) ); + } else { + astClearMeshSize( this ); + astClearFillFactor( this ); + } + +/* If required, clear uncertainty in "this" if "that" has no uncertainty. */ + if( unc && !astTestUnc( that ) ) astClearUnc( this ); + +} + +static void RegSetAttrib( AstRegion *this, const char *asetting, + char **base_setting, int *status ) { +/* +*+ +* Name: +* astRegSetAttrib + +* Purpose: +* Set an attribute value for a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* void astRegSetAttrib( AstRegion *this, const char *asetting, +* char **base_setting ) + +* Class Membership: +* Region virtual function + +* Description: +* This function assigns an attribute value to both the base and +* current Frame in the FrameSet encapsulated within a Region, without +* remapping either Frame. +* +* No error is reported if the attribute is not recognised by the base +* Frame. + +* Parameters: +* this +* Pointer to the Region. +* asetting +* Pointer to a null terminated attribute setting string. The supplied +* string will be interpreted using the public interpretation +* implemented by astSetAttrib. This can be different to the +* interpretation of the protected accessor functions. For instance, +* the public interpretation of an unqualified floating point value for +* the Epoch attribute is to interpet the value as a gregorian year, +* but the protected interpretation is to interpret the value as an +* MJD. +* base_setting +* Address of a location at which to return a pointer to the null +* terminated attribute setting string which was applied to the +* base Frame of the encapsulated FrameSet. This may differ from +* the supplied setting if the supplied setting contains an axis +* index and the current->base Mapping in the FrameSet produces an +* axis permutation. The returned pointer should be freed using +* astFree when no longer needed. A NULL pointer may be supplied in +* which case no pointer is returned. +*- +*/ + +/* Local Variables: */ + AstFrame *frm; + AstMapping *junkmap; + AstMapping *map; + AstRegion *unc; + char *setting; + char *bsetting; + char buf1[ 100 ]; + int *outs; + int axis; + int baxis; + int i; + int len; + int nc; + int rep; + int value; + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Produce a lower case version of the setting string */ + nc = strlen( asetting ); + setting = astMalloc( nc + 1 ); + for( i = 0; i < nc; i++ ) setting[ i ] = tolower( asetting[ i ] ); + setting[ nc ] = 0; + +/* Apply the setting to the current Frame in the encapsulated FrameSet. + Use the protected astSetAttrib method which does not cause the Frame + to be remapped within the FrameSet. */ + frm = astGetFrame( this->frameset, AST__CURRENT ); + astSetAttrib( frm, setting ); + frm = astAnnul( frm ); + +/* Indicate that we should use the supplied setting with the base Frame. */ + bsetting = NULL; + +/* If the attribute name contains an axis number, we need to create a new + attribute setting which refers to the corresponding base Frame axis + (since the base<->current Mapping may permute the axes). First parse the + supplied attribute setting to locate any axis index. */ + len = strlen( setting ); + if( nc = 0, ( 2 == astSscanf( setting, "%[^(](%d)= %n%*s %n", buf1, &axis, + &value, &nc ) ) && ( nc >= len ) ) { + +/* If found, convert the axis index from one-based to zero-based. */ + axis--; + +/* See if the specified current Frame axis is connected to one and only + one base Frame axis. If so, get the index of the base Frame axis. */ + map = astGetMapping( this->frameset, AST__CURRENT, AST__BASE ); + outs = astMapSplit( map, 1, &axis, &junkmap ); + if( junkmap && astGetNout( junkmap ) == 1 ) { + baxis = outs[ 0 ]; + +/* If the base Frame axis index is different to the current Frame axis + index, create a new setting string using the base Frame axis index. */ + if( baxis != axis ) { + bsetting = astMalloc( strlen( setting ) + 10 ); + if( bsetting ) { + sprintf( bsetting, "%s(%d)=%s", buf1, baxis + 1, setting + value ); + } + } + +/* If there is no one base Frame axis which corresponds to the supplied + current Frame axis, report an error. */ + } else if( astOK ) { + astError( AST__INTER, "astRegSetAttrib(%s): Unable to apply " + "attribute setting \"%s\" to the base Frame in the %s", status, + astGetClass( this ), setting, astGetClass( this ) ); + astError( AST__INTER, "There is no base Frame axis corresponding " + "to current Frame axis %d\n", status, axis + 1 ); + } + +/* Free resources */ + outs = astFree( outs ); + if( junkmap ) junkmap = astAnnul( junkmap ); + map = astAnnul( map ); + } + +/* Apply the appropriate attribute setting to the base Frame. This time + ensure that any error caused by the attribute setting is annulled. + Also apply it to any uncertainty Region (the current Frame of the + uncertainty Region is assumed to be equivalent to the base Frame of the + parent Region). */ + frm = astGetFrame( this->frameset, AST__BASE ); + if( frm ) { + rep = astReporting( 0 ); + astSetAttrib( frm, bsetting ? bsetting : setting ); + if( astTestUnc( this ) ) { + unc = astGetUncFrm( this, AST__BASE ); + astRegSetAttrib( unc, bsetting ? bsetting : setting, NULL ); + unc = astAnnul( unc ); + } + if( astStatus == AST__BADAT ) astClearStatus; + astReporting( rep ); + } + frm = astAnnul( frm ); + +/* If required return the modified base Frame setting. Otherwise, free it. */ + if( base_setting ) { + if( bsetting ) { + *base_setting = bsetting; + } else { + *base_setting = astStore( NULL, setting, strlen( setting ) + 1 ); + } + } else { + bsetting = astFree( bsetting ); + } + +/* Since the base Frame has been changed, any cached information calculated + on the basis of the base Frame properties may no longer be up to date. */ + astResetCache( this ); + +/* Free resources. */ + setting = astFree( setting ); + +} + +static AstMapping *RemoveRegions( AstMapping *this_mapping, int *status ) { +/* +* Name: +* RemoveRegions + +* Purpose: +* Remove any Regions from a Mapping. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstMapping *RemoveRegions( AstMapping *this, int *status ) + +* Class Membership: +* Region method (over-rides the astRemoveRegions method inherited +* from the Frame class). + +* Description: +* This function searches the supplied Mapping (which may be a +* compound Mapping such as a CmpMap) for any component Mappings +* that are instances of the AST Region class. It then creates a new +* Mapping from which all Regions have been removed. If a Region +* cannot simply be removed (for instance, if it is a component of a +* parallel CmpMap), then it is replaced with an equivalent UnitMap +* in the returned Mapping. +* +* The implementation provided by the Region class just returns the +* equivalent Frame. + +* Parameters: +* this +* Pointer to the original Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* A pointer to the modified mapping. + +* Notes: +* - A NULL pointer value will be returned if this function is +* invoked with the AST error status set, or if it should fail for +* any reason. +*/ + +/* The Region class just returns a pointer to a deep copy of the Region's + equivalent Frame. */ + return astGetRegionFrame( (AstRegion *)this_mapping ); +} + +static void ReportPoints( AstMapping *this_mapping, int forward, + AstPointSet *in_points, AstPointSet *out_points, int *status ) { +/* +* Name: +* ReportPoints + +* Purpose: +* Report the effect of transforming a set of points using a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void ReportPoints( AstMapping *this, int forward, +* AstPointSet *in_points, AstPointSet *out_points, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astReportPoints +* method inherited from the Frame class). + +* Description: +* This function reports the coordinates of a set of points before +* and after being transformed by a Region, by writing them to +* standard output. + +* Parameters: +* this +* Pointer to the Region. +* forward +* A non-zero value indicates that the Region's forward +* coordinate transformation has been applied, while a zero +* value indicates the inverse transformation. +* in_points +* Pointer to a PointSet which is associated with the +* coordinates of a set of points before the Region was +* applied. +* out_points +* Pointer to a PointSet which is associated with the +* coordinates of the same set of points after the Region has +* been applied. +* status +* Pointer to the inherited status variable. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_mapping; + +/* Obtain a pointer to the Region's current Frame and invoke its + astReportPoints method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astReportPoints( (AstMapping *) fr, forward, in_points, out_points ); + fr = astAnnul( fr ); + +} + +static void ResetCache( AstRegion *this, int *status ){ +/* +*+ +* Name: +* astResetCache + +* Purpose: +* Clear cached information within the supplied Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* void astResetCache( AstRegion *this ) + +* Class Membership: +* Region virtual function + +* Description: +* This function clears cached information from the supplied Region +* structure. + +* Parameters: +* this +* Pointer to the Region. +*- +*/ + if( this ) { + if( this->basemesh ) this->basemesh = astAnnul( this->basemesh ); + if( this->basegrid ) this->basegrid = astAnnul( this->basegrid ); + if( this->negation ) this->negation = astAnnul( this->negation ); + } +} + + +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 "region.h" +* void Resolve( AstFrame *this, const double point1[], +* const double point2[], const double point3[], +* double point4[], double *d1, double *d2, int *status ); + +* Class Membership: +* Region member function (over-rides the protected 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. + +* 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 value is always positive. +* status +* Pointer to the inherited status variable. + +* Notes: +* - Each vector used in 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, or if the required +* output values are undefined. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke this + Frame's astResolve method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astResolve( fr, point1, point2, point3, point4, d1, d2 ); + fr = astAnnul( fr ); + +} + +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 "region.h" +* AstPointSet *ResolvePoints( AstFrame *this, const double point1[], +* const double point2[], AstPointSet *in, +* AstPointSet *out ) + +* Class Membership: +* Region 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 always be positive. + +* 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. +*/ + +/* Local Variables: */ + AstPointSet *result; /* Pointer to output PointSet */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke this + Frame's astResolve method. Annul the Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astResolvePoints( fr, point1, point2, in, out ); + fr = astAnnul( fr ); + +/* Return a pointer to the output PointSet. */ + return result; + +} + +static void SetAttrib( AstObject *this_object, const char *setting, int *status ) { +/* +* Name: +* SetAttrib + +* Purpose: +* Set an attribute value for a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void SetAttrib( AstObject *this, const char *setting, int *status ) + +* Class Membership: +* Region member function (extends the astSetAttrib method +* inherited from the Frame class). + +* Description: +* This function assigns an attribute value for a Region, 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 Region. +* setting +* Pointer to a null terminated string specifying the new +* attribute value. +* status +* Pointer to the inherited status variable. + +* Notes: +* - This protected method is intended to be invoked by the Object +* astSet method and makes additional attributes accessible to it. +*/ + +/* Local Variables: */ + AstRegion *this; /* Pointer to the Region structure */ + double dval; /* Floating point attribute value */ + int ival; /* Integer attribute value */ + int id; /* Offset of ID string */ + int len; /* Length of setting string */ + int nc; /* Number of characters read by astSscanf */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) 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. */ + +/* We first handle attributes that apply to the Region as a whole + (rather than to the encapsulated Frame). */ + +/* Negated */ +/* ------- */ + if ( nc = 0, + ( 1 == astSscanf( setting, "negated= %d %n", &ival, &nc ) ) + && ( nc >= len ) ) { + astSetNegated( this, ival ); + +/* Closed */ +/*------- */ + } else if ( nc = 0, + ( 1 == astSscanf( setting, "closed= %d %n", &ival, &nc ) ) + && ( nc >= len ) ) { + astSetClosed( this, ival ); + +/* FillFactor */ +/* ---------- */ + } else if ( nc = 0, + ( 1 == astSscanf( setting, "fillfactor= %lg %n", &dval, &nc ) ) + && ( nc >= len ) ) { + astSetFillFactor( this, dval ); + +/* MeshSize */ +/* -------- */ + } else if ( nc = 0, + ( 1 == astSscanf( setting, "meshsize= %d %n", &ival, &nc ) ) + && ( nc >= len ) ) { + astSetMeshSize( this, ival ); + +/* Adaptive */ +/* -------- */ + } else if ( nc = 0, + ( 1 == astSscanf( setting, "adaptive= %d %n", &ival, &nc ) ) + && ( nc >= len ) ) { + astSetAdaptive( this, ival ); + +/* Now do attributes inherited from parent classes. We do these here to + avoid the settings being passed on to the encapsulated FrameSet below. */ + +/* ID. */ +/* --- */ + } else if ( nc = 0, ( 0 == astSscanf( setting, "id=%n%*[^\n]%n", &id, &nc ) ) + && ( nc >= len ) ) { + astSetID( this, setting + id ); + +/* Ident. */ +/* ------ */ + } else if ( nc = 0, ( 0 == astSscanf( setting, "ident=%n%*[^\n]%n", &id, &nc ) ) + && ( nc >= len ) ) { + astSetIdent( this, setting + id ); + +/* Invert. */ +/* ------- */ + } else if ( nc = 0, + ( 1 == astSscanf( setting, "invert= %d %n", &ival, &nc ) ) + && ( nc >= len ) ) { + astSetInvert( this, ival ); + +/* Report. */ +/* ------- */ + } else if ( nc = 0, + ( 1 == astSscanf( setting, "report= %d %n", &ival, &nc ) ) + && ( nc >= len ) ) { + astSetReport( this, ival ); + +/* Define macros to see if the setting string matches any of the + read-only attributes of this class. */ +#define MATCH(attrib) \ + ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \ + ( nc >= len ) ) + +#define AXISMATCH(attrib) \ + ( nc = 0, ( 0 == astSscanf( setting, attrib "(%*d)=%*[^\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 ( MATCH( "class" ) || + MATCH( "nin" ) || + MATCH( "nobject" ) || + MATCH( "bounded" ) || + MATCH( "nout" ) || + MATCH( "refcount" ) || + MATCH( "tranforward" ) || + MATCH( "traninverse" ) ) { + 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 unrecognised attributes on to the Region's encapsulated FrameSet for + further interpretation. Do not pass on FrameSet attributes since we + pretend to the outside world that the encapsulated FrameSet is actually a + Frame. */ + } else if ( !MATCH( "base" ) && + !MATCH( "current" ) && + !MATCH( "nframe" ) ) { + +/* If the Region is to adapt to coordinate system chanmges, use the public + astSet method so that the current Frame in the encapsulated FrameSet will + be re-mapped if the attribute changes require it. */ + if( astGetAdaptive( this ) ) { + astSet( this->frameset, setting, status ); + +/* If the Region is not to adapt to coordinate system chanmges, use the + astRegSetAttrib method which assigns the attribute setting to both + current and base Frames in the FrameSet without causing any remapping to + be performed. */ + } else { + astRegSetAttrib( this, setting, NULL ); + } + } + +/* Undefine macros local to this function. */ +#undef MATCH +} + +static void SetAxis( AstFrame *this_frame, int axis, AstAxis *newaxis, int *status ) { +/* +* Name: +* SetAxis + +* Purpose: +* Set a new Axis for a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void SetAxis( AstFrame *this, int axis, AstAxis *newaxis, int *status ) + +* Class Membership: +* Region member function (over-rides the astSetAxis method +* inherited from the Frame class). + +* Description: +* This function allows a new Axis object to be associated with one +* of the axes of the current Frame in a Region, replacing the +* previous one. Each Axis object contains a description of the +* quantity represented along one of the Frame's axes, so this +* function allows this description to be exchanged for another +* one. + +* Parameters: +* this +* Pointer to the Region. +* axis +* The index (zero-based) of the axis whose associated Axis +* object is to be replaced. +* newaxis +* Pointer to the new Axis object. +* status +* Pointer to the inherited status variable. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index supplied. */ + (void) astValidateAxis( this, axis, 1, "astSetAxis" ); + +/* Obtain a pointer to the Region's current Frame and invoke this + Frame's astSetAxis method to assign the new Axis object. Annul the + Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astSetAxis( fr, axis, newaxis ); + fr = astAnnul( fr ); +} + +static void SetRegFS( AstRegion *this, AstFrame *frm, int *status ) { +/* +*+ +* Name: +* astSetRegFS + +* Purpose: +* Stores a new FrameSet in a Region + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* void astSetRegFS( AstRegion *this, AstFrame *frm ) + +* Class Membership: +* Region virtual function. + +* Description: +* This function creates a new FrameSet and stores it in the supplied +* Region. The new FrameSet contains two copies of the supplied +* Frame, connected by a UnitMap. + +* Parameters: +* this +* Pointer to the Region. +* frm +* The Frame to use. +*- +*/ + +/* Local Variables: */ + AstFrame *f1; /* Copy of supplied Frame */ + AstFrame *f2; /* Copy of supplied Frame */ + AstFrameSet *fs; /* New FrameSet */ + AstRegion *unc; /* Uncertainty Region */ + AstUnitMap *um; /* UnitMap connecting base anc current Frames */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Take a copy of the supplied Frame. */ + f1 = astCopy( frm ); + +/* Create the new FrameSet. First take another copy of the supplied Frame + so that modifications using the supplied pointer will not affect the new + FrameSet. We create two copies (rather than 1) because the base and + current Frames must be independant objects - otherwise attribute changes + done to one will also appear in the other. Then construct the FrameSet + containing the two Frame copies connected by a UnitMap. */ + f2 = astCopy( f1 ); + fs = astFrameSet( f1, "", status ); + um = astUnitMap( astGetNaxes( f1 ), "", status ); + astAddFrame( fs, AST__BASE, um, f2 ); + um = astAnnul( um ); + f2 = astAnnul( f2 ); + +/* Annul any existing FrameSet */ + if( this->frameset ) (void) astAnnul( this->frameset ); + +/* Use the new FrameSet */ + this->frameset = fs; + +/* If any uncertainty Region has a zero value for its RegionFS attribute, + it will currently contain a dummy FrameSet rather than the correct + FrameSet. The correct FrameSet has copies of the base Frame of the new + Region as both its current and base Frames, and these are connected by + a UnitMap (this is equivalent to a FrameSet containing a single Frame). */ + if( astTestUnc( this ) ) { + unc = astGetUncFrm( this, AST__BASE ); + if( unc && !astGetRegionFS( unc ) ) astSetRegFS( unc, f1 ); + unc = astAnnul( unc ); + } + +/* Free remaining resourvces */ + f1 = astAnnul( f1 ); + +} + +static void SetUnc( AstRegion *this, AstRegion *unc, int *status ){ +/* +*++ +* Name: +c astSetUnc +f AST_SETUNC + +* Purpose: +* Store uncertainty information in a Region. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c void astSetUnc( AstRegion *this, AstRegion *unc ) +f CALL AST_SETUNC( THIS, UNC, STATUS ) + +* Class Membership: +* Region method. + +* Description: +* Each Region (of any class) can have an "uncertainty" which specifies +* the uncertainties associated with the boundary of the Region. This +* information is supplied in the form of a second Region. The uncertainty +* in any point on the boundary of a Region is found by shifting the +* associated "uncertainty" Region so that it is centred at the boundary +* point being considered. The area covered by the shifted uncertainty +* Region then represents the uncertainty in the boundary position. +* The uncertainty is assumed to be the same for all points. +* +* The uncertainty is usually specified when the Region is created, but +* this +c function +f routine +* allows it to be changed at any time. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region which is to be assigned a new uncertainty. +c unc +f UNC = INTEGER (Given) +* Pointer to the new uncertainty Region. This must be of a class for +* which all instances are centro-symetric (e.g. Box, Circle, Ellipse, +* etc.) or be a Prism containing centro-symetric component Regions. +* A deep copy of the supplied Region will be taken, so subsequent +* changes to the uncertainty Region using the supplied pointer will +* have no effect on the Region +c "this". +f THIS. +f STATUS = INTEGER (Given and Returned) +f The global status. + +*-- +*/ + +/* Local Variables: */ + AstFrame *frm; /* Current Frame from FrameSet */ + AstFrameSet *fs2; /* FrameSet from "unc" current Frame to "this" base Frame */ + AstFrameSet *fs; /* FrameSet in "this" supplied Region */ + AstMapping *map2; /* Base->current Mapping from FrameSet */ + AstMapping *map; /* Base->current Mapping from FrameSet */ + AstMapping *smap; /* Simplified base->current Mapping */ + double *cen0; /* Pointer to array holding original centre */ + double **ptr_reg; /* Pointer to axis values for Region's Pointset */ + int changed; /* Has the uncertainty been changed? */ + +/* Check the inherited status. */ + if( !astOK ) return; + +/* Annul any existing uncertainty Region. */ + if( this->unc ) { + this->unc = astIsAObject( this->unc ) ? + astAnnul( this->unc ) : NULL; + changed = 1; + } else { + changed = 0; + } + +/* Check an uncertainty Region was supplied, and is of a usable class + (i.e. a class which can be re-centred). */ + cen0 = unc ? astRegCentre( unc, NULL, NULL, 0, 0 ) : NULL; + if( cen0 ) { + cen0 = astFree( cen0 ); + +/* Map it into the same Frame as that represented by the base Frame in + the supplied Region. */ + fs = this->frameset; + astInvert( fs ); + fs2 = Conv( unc->frameset, fs, status ); + astInvert( fs ); + + if( fs2 ) { + map = astGetMapping( fs2, AST__BASE, AST__CURRENT ); + frm = astGetFrame( fs2, AST__CURRENT ); + this->unc = astMapRegion( unc, map, frm ); + if( this->unc ) { + +/* Ensure the Region is bounded. We know that negating an unbounded + Region will make it bounded because we know that the Region consists of + Circles, Boxes and/or Ellipses, all of which have this property. */ + if( !astGetBounded( this->unc ) ) astNegate( this->unc ); + +/* If the base Frame in the uncertainty Region is the same as the base + Frame in the Region being dumped, then we do no need to include the + FrameSet in the dump of the uncertainty Region. Since the current + Frame in the uncertainty Region always corresponds to the base Frame of + its parent Region, we only need to check if the base->current Mapping + in the uncertainty Region's FrameSet is a UnitMap or not (after + simplification). If it is, set the RegionFS attribute of the uncertainty + Region to zero (i.e. false). This will cause the FrameSet to be omitted + from the Dump. */ + map2 = astGetMapping( this->unc->frameset, AST__BASE, AST__CURRENT ); + smap = astSimplify( map2 ); + if( astIsAUnitMap( smap ) ) astSetRegionFS( this->unc, 0 ); + +/* Re-centre the uncertainty Region at the first position in the PointSet + associated with the Region structure (if any). */ + if( this->points ) { + ptr_reg = astGetPoints( this->points ); + astRegCentre( this->unc, NULL, ptr_reg, 0, AST__CURRENT ); + } + +/* Set a flag indicating that the uncertainty in the Region has changed. */ + changed = 1; + +/* Free resources */ + map2 = astAnnul( map2 ); + smap = astAnnul( smap ); + } + frm = astAnnul( frm ); + fs2 = astAnnul( fs2 ); + map = astAnnul( map ); + +/* Report error if conversion between Frames is not possible. */ + } else if( astOK ) { + astError( AST__BADIN, "astSetUnc(%s): Bad %d dimensional " + "uncertainty Frame (%s %s) supplied.", status, astGetClass(this), + astGetNaxes(unc), astGetDomain(unc), astGetTitle(unc) ); + astError( AST__NCPIN, "Cannot convert it to the Frame of the " + "new %s.", status, astGetClass( this ) ); + } + +/* Report an error if it is not of a usable class. */ + } else if( unc && astOK ){ + astError( AST__BADIN, "astSetUnc(%s): Bad uncertainty shape " + "(%s) supplied.", status, astGetClass( this ), astGetClass(unc) ); + astError( AST__NCPIN, "The uncertainty Region must be an instance of " + "a centro-symetric subclass of Region (e.g. Box, Circle, " + "Ellipse, etc)." , status); + } + +/* If the uncertainty in the Region has changed, indicate that any cached + information in the Region is now out of date. */ + if( changed ) astResetCache( this ); + +} + +static void ShowMesh( AstRegion *this, int format, const char *ttl, int *status ){ +/* +*++ +* Name: +c astShowMesh +f AST_SHOWMESH + +* Purpose: +* Display a mesh of points covering the surface of a Region. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c void astShowMesh( AstRegion *this, int format, const char *ttl ) +f CALL AST_SHOWMESH( THIS, FORMAT, TTL, STATUS ) + +* Class Membership: +* Region method. + +* Description: +c This function +f This routine +* writes a table to standard output containing the axis values at a +* mesh of points covering the surface of the supplied Region. Each row +* of output contains a tab-separated list of axis values, one for +* each axis in the Frame encapsulated by the Region. The number of +* points in the mesh is determined by the MeshSize attribute. +* +* The table is preceded by a given title string, and followed by a +* single line containing the word "ENDMESH". + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region. +c format +f FORMAT = LOGICAL (Given) +* A boolean value indicating if the displayed axis values should +* be formatted according to the Format attribute associated with +* the Frame's axis. Otherwise, they are displayed as simple +* floating point values. +c ttl +f TTL = CHARACTER * ( * ) (Given) +* A title to display before displaying the first position. +f STATUS = INTEGER (Given and Returned) +f The global status. + +*-- +*/ + +/* Local Variables: */ + AstPointSet *ps; /* PointSet holding mesh */ + char *buffer = NULL; /* Buffer for line output text */ + char buf[ 40 ]; /* Buffer for floating poitn value */ + double **ptr; /* Pointers to the mesh data */ + int i; /* Axis index */ + int j; /* Position index */ + int nax; /* Number of axes */ + int nc; /* Number of characters in buffer */ + int np; /* Number of axis values per position */ + +/* Check the inherited status. */ + if( !astOK ) return; + +/* Get a PointSet holding the mesh */ + ps = astRegMesh( this ); + if( ps ) { + +/* Get the number of axis values per position, and the number of positions. */ + nax = astGetNcoord( ps ); + np = astGetNpoint( ps ); + +/* Get a pointer to the mesh data, and check it can be used. */ + ptr = astGetPoints( ps ); + if( ptr ) { + +/* Display the title. */ + if( ttl ) printf( "\n%s\n\n", ttl ); + +/* Loop round all positions. */ + for( j = 0; j < np; j++ ) { + +/* Reset the current buffer length to zero. */ + nc = 0; + +/* Loop round all axes */ + for( i = 0; i < nax; i++ ){ + +/* If the axis value is bad, append "<bad> in the end of the output buffer. */ + if( ptr[ i ][ j ] == AST__BAD ){ + buffer = astAppendString( buffer, &nc, "<bad>" ); + +/* Otherwise, if required, append the formatted value to the end of the + buffer. */ + } else if( format ){ + buffer = astAppendString( buffer, &nc, + astFormat( this, i, ptr[ i ][ j ] ) ); + +/* Otherwise, append the floating point value to the end of the buffer. */ + } else { + sprintf( buf, "%g", ptr[ i ][ j ] ); + buffer = astAppendString( buffer, &nc, buf ); + } +/* Add a separating tab to the end of the buffer. */ + buffer = astAppendString( buffer, &nc, "\t" ); + } + +/* Display the line buffer. */ + printf( "%s\n", buffer ); + } + } + +/* Print out a marker for th eend of the list. */ + printf( "ENDMESH\n\n" ); + +/* Release resources. */ + ps = astAnnul( ps ); + buffer = astFree( buffer ); + } +} + +static AstMapping *Simplify( AstMapping *this_mapping, int *status ) { +/* +* Name: +* Simplify + +* Purpose: +* Simplify the Mapping represented by a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstMapping *Simplify( AstMapping *this, int *status ) + +* Class Membership: +* Region method (over-rides the astSimplify method inherited +* from the Frame class). + +* Description: +* This function simplifies the encapsulated FrameSet and any +* uncertainty Region in the supplied Region. This is different to +* the Simplify method in the parent Frame class which always returns +* a UnitMap. + +* Parameters: +* this +* Pointer to the original Region. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* A pointer to the simplified Region. A cloned pointer to the +* supplied Region will be returned if no simplication could be +* performed. + +* Notes: +* - This implementation just simplifies the encapsulated FrameSet +* and uncertainty Region. Sub-classes should usually provide their own +* implementation which invokes this implemetation, and then continues to +* check for further simplifications (such as fitting a new region to the +* current Frame). +* - A NULL pointer value will be returned if this function is +* invoked with the AST error status set, or if it should fail for +* any reason. +*/ + +/* Local Variables: */ + AstFrame *bfrm; /* Pointer to "this" baseFrame */ + AstFrameSet *fs; /* Pointer to encapsulated FrameSet */ + AstMapping *map; /* Base->current Mapping for "this" */ + AstMapping *result; /* Result pointer to return */ + AstPointSet *pset1; /* Base Frame centre position */ + AstPointSet *pset2; /* Current Frame centre position */ + AstRegion *new; /* Pointer to simplified Region */ + AstRegion *sunc; /* Simplified uncertainty Region */ + AstRegion *this; /* Pointer to original Region structure */ + AstRegion *unc; /* Original uncertainty Region */ + double **ptr1; /* Pointer to axis values in "pset1" */ + double *cen; /* Original centre of uncertainty Region */ + double *lbnd; /* Lower bounds of "this" bounding box */ + double *orig_cen; /* Original centre for uncertainty Region */ + double *s1_lbnd; /* Lower bounds of "unc" when centred at lbnd */ + double *s1_ubnd; /* Upper bounds of "unc" when centred at lbnd */ + double *s2_lbnd; /* Lower bounds of "unc" when centred at ubnd */ + double *s2_ubnd; /* Upper bounds of "unc" when centred at ubnd */ + double *ubnd; /* Upper bounds of "this" bounding box */ + double delta; /* Half width of test box */ + double w1; /* Width of "s1" bounding box */ + double w2; /* Width of "s2" bounding box */ + int ic; /* Axis index */ + int naxb; /* No. of base Frame axes in "this" */ + int nin; /* Number of base Frame axes in "this" */ + int nout; /* Number of current Frame axes in "this" */ + int ok; /* Can we use the simplified uncertainty? */ + int simpler; /* Has some simplication taken place? */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_mapping; + +/* Take a deep copy of the supplied Region. This is so that the returned + pointer will have a diferent value to the supplied pointer if any + simplication takes place. */ + new = astCopy( this ); + +/* Simplify the encapsulated FrameSet, and note if any simplification took + place. */ + fs = astSimplify( new->frameset ); + simpler = ( fs != new->frameset ); + +/* If so, annull the existing FrameSet and use the simpler FrameSet. */ + if( simpler ) { + (void) astAnnul( new->frameset ); + new->frameset = astClone( fs ); + } + fs = astAnnul( fs ); + +/* If the Region has default uncertainty, we simplify the uncertainty + Region simply by deleting it. It will be regenerated when needed, + using the simplified Region. */ + if( new->defunc ) new->defunc = astAnnul( new->defunc ); + +/* If the Region's uncertainty was supplied explicitly, try simplifying + the unncertainty Region. */ + if( astTestUnc( new ) ){ + +/* Obtain the Region's uncertainty. */ + unc = astGetUncFrm( new, AST__BASE ); + +/* Get the base->current Mapping from "this". */ + map = astGetMapping( this->frameset, AST__BASE, AST__CURRENT ); + +/* If it has different numbers of inputs and outputs (e.g. a PermMap used + to take a slice through a Region), we need to ensure that the + uncertainty Region is centred on the slice. */ + nin = astGetNin( map ); + nout = astGetNout( map ); + if( nin != nout ) { + +/* Get the current centre of the uncertainty Region in its current Frame + (the same as the base Frame of "this"). */ + cen = astRegCentre( unc, NULL, NULL, 0, AST__CURRENT ); + +/* Store it in a PointSet so it can be transformed. */ + pset1 = astPointSet( 1, nin, "", status ); + ptr1 = astGetPoints( pset1 ); + if( astOK ) for( ic = 0; ic < nin; ic++ ) ptr1[ ic ][ 0 ] = cen[ ic ]; + +/* Transform into the curent Frame of "this", and then back into the base + Frame. */ + pset2 = astTransform( map, pset1, 1, NULL ); + (void) astTransform( map, pset2, 0, pset1 ); + +/* Re-centre the uncertainty Region at this position. */ + astRegCentre( unc, NULL, ptr1, 0, AST__CURRENT ); + +/* Free resources. */ + cen = astFree( cen ); + pset1 = astAnnul( pset1 ); + pset2 = astAnnul( pset2 ); + } + +/* Free resources. */ + map = astAnnul( map ); + +/* Try simplifying the uncertainty. Only proceed if the uncertainty can + be simplified. */ + sunc = astSimplify( unc ); + if( sunc != unc ) { + +/* If the uncertainty can be simplified it means that the base->current + Mapping in the uncertainty Region is sufficiently linear to allow the + uncertainty shape to retain its form when transformed from the base to + the current Frane. But this has only been tested at the current centre + position in the uncertainty Region. The uncertainty Region should + describe the whole of "this" Region, and so we need to check that the + simplified uncertainty does not change as we move it around within "this" + Region. To do this, we re-centre the uncertainty region at opposite + corners of a large test box, and then we find the bounding box of the + re-centred uncertainty Region. If this uncertainty bounding box changes + from corner to corner of the test box, then we do not simplify the + uncertainty Region. If "this" is bounded, we use the bounding box of + "this" as the test box. Otherwise we use a box 100 times the size of the + uncertainty Region. */ + +/* Note the original base Frame centre of the simplified uncertainty Region. */ + orig_cen = astRegCentre( sunc, NULL, NULL, 0, AST__BASE ); + +/* Allocate memory to hold the bounds of the test box. */ + naxb = astGetNin( this->frameset ); + lbnd = astMalloc( sizeof( double )*(size_t)naxb ); + ubnd = astMalloc( sizeof( double )*(size_t)naxb ); + +/* If possible, get the base Frame bounding box of "this" and use it as + the test box. */ + if( astGetBounded( this ) ) { + astRegBaseBox( this, lbnd, ubnd ); + +/* Otherwise, store the bounds of a box which is 100 times the size of + the uncertainty region, centred on the current centre of the uncertainty + region (we know all uncertainty regions are bounded). */ + } else { + astGetRegionBounds( sunc, lbnd, ubnd ); + for( ic = 0; ic < naxb; ic++ ) { + delta = 0.5*fabs( ubnd[ ic ] - lbnd[ ic ] ); + lbnd[ ic ] = orig_cen[ ic ] - delta; + ubnd[ ic ] = orig_cen[ ic ] + delta; + } + } + +/* Re-centre it at the lower bounds of the test box. This is in the base Frame + of "this" which is the same as the current Frame of "sunc". */ + astRegCentre( sunc, lbnd, NULL, 0, AST__CURRENT ); + +/* Get the bounding box of the re-centred uncertainty Region, within its + current Frame, which is the same as the base Frame of "this". */ + s1_lbnd = astMalloc( sizeof( double )*(size_t)naxb ); + s1_ubnd = astMalloc( sizeof( double )*(size_t)naxb ); + astGetRegionBounds( sunc, s1_lbnd, s1_ubnd ); + +/* Now re-centre the uncertainty Region at the upper bounds of the test + box. */ + astRegCentre( sunc, ubnd, NULL, 0, AST__CURRENT ); + +/* Get the bounding box of the re-centred uncertainty Region. */ + s2_lbnd = astMalloc( sizeof( double )*(size_t)naxb ); + s2_ubnd = astMalloc( sizeof( double )*(size_t)naxb ); + astGetRegionBounds( sunc, s2_lbnd, s2_ubnd ); + +/* Get a pointer to the base Frame of "this". */ + bfrm = astGetFrame( this->frameset, AST__BASE ); + +/* The "ok" flag is initialised to indicate that the simplified uncertainty + Region should not be used. */ + ok = 0; + +/* Check pointers can be referenced safely */ + if( astOK ) { + +/* Now indicate that the simplified uncertainty Region should be used. */ + ok = 1; + +/* Loop round all axes of the base Frame of "this". */ + for( ic = 0; ic < naxb; ic++ ) { + +/* Get the width of the two bounding boxes on this axis. */ + w1 = s1_ubnd[ ic ] - s1_lbnd[ ic ]; + w2 = s2_ubnd[ ic ] - s2_lbnd[ ic ]; + +/* If these differ by more than 0.1% then we determine that the simplified + uncertainty Region varies in size across the bounding box of "this", and + so we do not use the simplified uncertainty Region. The figure of 0.1% + is arbitrary. */ + if( fabs( w1 - w2 ) > 0.005*( fabs( w1 ) + fabs( w2 ) ) ) { + ok = 0; + break; + } + } + } + +/* Reinstate the original base Frame centre of the simplified uncertainty Region. */ + astRegCentre( sunc, orig_cen, NULL, 0, AST__BASE ); + +/* Free resources. */ + orig_cen = astFree( orig_cen ); + lbnd = astFree( lbnd ); + ubnd = astFree( ubnd ); + s1_lbnd = astFree( s1_lbnd ); + s1_ubnd = astFree( s1_ubnd ); + s2_lbnd = astFree( s2_lbnd ); + s2_ubnd = astFree( s2_ubnd ); + bfrm = astAnnul( bfrm ); + +/* If we can use the simplified uncertainty Region, indicate that we have + performed some simplification, and store the new uncertainty Region. */ + if( ok ) { + simpler = 1; + astSetUnc( new, sunc ); + } + } + +/* Free resources */ + unc = astAnnul( unc ); + sunc = astAnnul( sunc ); + } + +/* If any simplification could be performed, return the new Region. + Otherwise, return a clone of the supplied pointer. */ + if( simpler ){ + result = (AstMapping *) new; + } else { + new = astAnnul( new ); + result = astClone( this ); + } + +/* If an error occurred, annul the returned pointer. */ + if ( !astOK ) result = astAnnul( result ); + +/* Return the result. */ + return result; +} + +static int SubFrame( AstFrame *this_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 Region and convert to the new coordinate system. + +* Type: +* Private function. + +* Synopsis: +* #include "region.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: +* Region 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 the current Frame of a "target" Region 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 current Frame of the target +* Region and the result Frame. 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 Region, from whose current Frame the +* 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 Region. This +* number may be greater than or less than the number of axes in +* the Region's current 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 current Frame of the target Region. 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 Region, 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 current Frame of the target Region +* 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 current Frame of the target Region 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. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to Region's current Frame */ + int match; /* Result to be returned */ + +/* Initialise. */ + *map = NULL; + *result = NULL; + match = 0; + +/* Check the global error status. */ + if ( !astOK ) return match; + +/* Invoke the parent astSubFrame method on the Frame represented by the + region. */ + fr = astGetFrame( ((AstRegion *) this_frame)->frameset, AST__CURRENT ); + match = astSubFrame( fr, template, result_naxes, target_axes, template_axes, + map, result ); + fr = astAnnul( fr ); + +/* Return the result. */ + return match; +} + +static AstSystemType SystemCode( AstFrame *this_frame, const char *system, int *status ) { +/* +* Name: +* SystemCode + +* Purpose: +* Convert a string into a coordinate system type code. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* AstSystemType SystemCode( AstFrame *this, const char *system, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astSystemCode +* method inherited from the Frame class). + +* Description: +* This function converts a string used for the external description of +* a coordinate system into a Frame coordinate system type code (System +* attribute value). It is the inverse of the astSystemString function. + +* Parameters: +* this +* Pointer to the Frame. +* system +* Pointer to a constant null-terminated string containing the +* external description of the 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 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 */ + AstFrame *fr; /* Pointer to FrameSet's current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Initialise. */ + result = AST__BADSYSTEM; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke the + astSystemCode method for this Frame. Annul the Frame pointer afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astSystemCode( fr, system ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = AST__BADSYSTEM; + +/* Return the result. */ + return result; +} + +static const char *SystemString( AstFrame *this_frame, AstSystemType system, int *status ) { +/* +* Name: +* SystemString + +* Purpose: +* Convert a coordinate system type code into a string. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* const char *SystemString( AstFrame *this, AstSystemType system, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astSystemString +* method inherited from the Frame class). + +* Description: +* This function converts a Frame coordinate system type code +* (System attribute value) into a string suitable for use as an +* external representation of the coordinate system type. + +* Parameters: +* this +* Pointer to 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 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: */ + AstFrame *fr; /* Pointer to FrameSet's current Frame */ + AstRegion *this; /* Pointer to the Region 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 FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke the + astSystemString method for this Frame. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astSystemString( fr, system ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = NULL; + +/* Return the result pointer. */ + return result; + +} + +static int RegTrace( AstRegion *this, int n, double *dist, double **ptr, int *status ){ +/* +*+ +* Name: +* astRegTrace + +* Purpose: +* Return requested positions on the boundary of a 2D Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* int astRegTrace( AstRegion *this, int n, double *dist, double **ptr ); + +* Class Membership: +* Region virtual function + +* Description: +* This function returns positions on the boundary of the supplied +* Region, if possible. The required positions are indicated by a +* supplied list of scalar parameter values in the range zero to one. +* Zero corresponds to some arbitrary starting point on the boundary, +* and one corresponds to the end (which for a closed region will be +* the same place as the start). + +* Parameters: +* this +* Pointer to the Region. +* n +* The number of positions to return. If this is zero, the function +* returns without action (but the returned function value still +* indicates if the method is supported or not). +* dist +* Pointer to an array of "n" scalar parameter values in the range +* 0 to 1.0. +* ptr +* A pointer to an array of pointers. The number of elements in +* this array should equal tthe number of axes in the Frame spanned +* by the Region. Each element of the array should be a pointer to +* an array of "n" doubles, in which to return the "n" values for +* the corresponding axis. The contents of the arrays are unchanged +* if the supplied Region belongs to a class that does not +* implement this method. + +* Returned Value: +* Non-zero if the astRegTrace method is implemented by the class +* of Region supplied, and zero if not. + +*- +*/ + +/* Concrete sub-classes of Region must over-ride this method. */ + return 0; +} + +static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) { +/* +* Name: +* TestAttrib + +* Purpose: +* Test if a specified attribute value is set for a Region. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int TestAttrib( AstObject *this, const char *attrib, int *status ) + +* Class Membership: +* Region 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 Region's attributes. + +* Parameters: +* this +* Pointer to the Region. +* attrib +* Pointer to a null terminated string specifying the attribute +* name. This should be in lower case with no surrounding white +* space. +* status +* Pointer to the inherited status variable. + +* Returned Value: +* One if a value has been set, otherwise zero. + +* Notes: +* - A value of zero will be returned if this function is invoked +* with the global status set, or if it should fail for any reason. +*/ + +/* Local Variables: */ + AstRegion *this; /* Pointer to the Region structure */ + int result; /* Result value to return */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_object; + +/* Check the attribute name and test the appropriate attribute. */ + +/* We first handle attributes that apply to the Region as a whole + (rather than to the encapsulated FrameSet). */ + +/* Negated. */ +/* -------- */ + if ( !strcmp( attrib, "negated" ) ) { + result = astTestNegated( this ); + +/* Closed. */ +/* ------- */ + } else if ( !strcmp( attrib, "closed" ) ) { + result = astTestClosed( this ); + +/* FillFactor */ +/* ---------- */ + } else if ( !strcmp( attrib, "fillfactor" ) ) { + result = astTestFillFactor( this ); + +/* MeshSize */ +/* -------- */ + } else if ( !strcmp( attrib, "meshsize" ) ) { + result = astTestMeshSize( this ); + +/* Adaptive */ +/* -------- */ + } else if ( !strcmp( attrib, "adaptive" ) ) { + result = astTestAdaptive( this ); + +/* Now do attributes inherited from parent classes. This is so that the + attribute test will not be passed on to the encpasulated FrameSet below. */ + +/* ID. */ +/* --- */ + } else if ( !strcmp( attrib, "id" ) ) { + result = astTestID( this ); + +/* Ident. */ +/* ------ */ + } else if ( !strcmp( attrib, "ident" ) ) { + result = astTestIdent( this ); + +/* Invert. */ +/* ------- */ + } else if ( !strcmp( attrib, "invert" ) ) { + result = astTestInvert( this ); + +/* Report. */ +/* ------- */ + } else if ( !strcmp( attrib, "report" ) ) { + result = astTestReport( 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 ( !strcmp( attrib, "class" ) || + !strcmp( attrib, "nin" ) || + !strcmp( attrib, "nobject" ) || + !strcmp( attrib, "bounded" ) || + !strcmp( attrib, "nout" ) || + !strcmp( attrib, "refcount" ) || + !strcmp( attrib, "tranforward" ) || + !strcmp( attrib, "traninverse" ) ) { + result = 0; + +/* Pass unrecognised attributes on to the Region's encapsulated FrameSet for + further interpretation. Do not pass on FrameSet attributes since we + pretend to the outside world that the encapsulated FrameSet is actually a + Frame. */ + } else if ( strcmp( attrib, "base" ) && + strcmp( attrib, "current" ) && + strcmp( attrib, "nframe" ) ) { + result = astTestAttrib( this->frameset, attrib ); + } + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = 0; + +/* Return the result, */ + return result; +} + +double *astRegTranPoint_( AstRegion *this, double *in, int np, int forward, int *status ){ +/* +*+ +* Name: +* astRegTranPoint + +* Purpose: +* Transform points between the base and current Frames in a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* double *astRegTranPoint( AstRegion *this, double *in, int np, int forward ) + +* Class Membership: +* Region member function + +* Description: +* This function transforms one or more points between the base and +* current Frames of the FrameSet encapsulated by the supplied Region. + +* Parameters: +* this +* The Region pointer. +* in +* Pointer to a 1-d array holding the axis values to be transformed. +* If "forward" is non-zero, the number of axis values supplied for +* each position should equal the number of axes in the base Frame +* of the FrameSet encapsulated by "this". If "forward" is zero, the +* number of axis values supplied for each position should equal the +* number of axes in the current Frame of the FrameSet encapsulated by +* "this". All the axis values for a position should be in adjacent +* elements of the array. +* np +* The number of points supplied in "in". +* forward +* If non-zero, the supplied points are assumed to refer to the base +* Frame of the encapsulated FrameSet, and they are transformed to the +* current Frame. If zero, the supplied points are assumed to refer to +* the current Frame of the encapsulated FrameSet, and they are +* transformed to the base Frame. + +* Returned Value: +* Pointer to a new dynamically allocated array holding the +* transformed axis values. If "forward" is non-zero, the number of axis +* values for each position will be equal the number of axes in the +* current Frame of the FrameSet encapsulated by "this". If "forward" is +* zero, the number of axis values for each position will be equal to the +* number of axes in the base Frame of the FrameSet encapsulated by "this". +* All the axis values for a position will be in adjacent elements of the +* array. The array should be freed using astFree when no longer needed. + +* Notes: +* - A NULL pointer is returned if an error has already occurred, or if +* this function should fail for any reason. + +*- +*/ + +/* Local Variables: */ + AstMapping *map; + AstPointSet *pset_in; + AstPointSet *pset_out; + double **ptr_in; + double **ptr_out; + double *p; + double *result; + int ic; + int ip; + int naxin; + int naxout; + +/* Initialise */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Get a pointer to the required Mapping. */ + if( forward ) { + map = astGetMapping( this->frameset, AST__BASE, AST__CURRENT ); + } else { + map = astGetMapping( this->frameset, AST__CURRENT, AST__BASE ); + } + +/* Get the number of axis values per input and per output point. */ + naxin = astGetNin( map ); + naxout = astGetNout( map ); + +/* Create a pointSet holding the supplied axis values. */ + pset_in = astPointSet( np, naxin, "", status ); + +/* Get pointers to the memory used to store axis values within this + PointSet. */ + ptr_in = astGetPoints( pset_in ); + +/* Allocate the output array. */ + result = astMalloc( sizeof( double )*(size_t)( naxout*np ) ); + +/* Check the pointers can be used. */ + if( astOK ) { + +/* Store the supplied axis values in the PointSet memory. */ + p = in; + for( ip = 0; ip < np; ip++ ) { + for( ic = 0; ic < naxin; ic++ ) ptr_in[ ic ][ ip ] = *(p++); + } + +/* Transform the PointSet. */ + pset_out = astTransform( map, pset_in, 1, NULL ); + +/* Get a pointer to the memory in the transformed PointSet. */ + ptr_out = astGetPoints( pset_out ); + + if( pset_out && astStatus == AST__INTER ) { + p = in; + for( ip = 0; ip < np; ip++ ) { + for( ic = 0; ic < naxin; ic++ ) printf("%.*g\n", AST__DBL_DIG, *(p++) ); + } + } + + if( astOK ) { + +/* Store the resulting axis values in the output array. */ + p = result; + for( ip = 0; ip < np; ip++ ) { + for( ic = 0; ic < naxout; ic++ ) *(p++) = ptr_out[ ic ][ ip ]; + } + } + +/* Free resources. */ + pset_out = astAnnul( pset_out ); + } + pset_in = astAnnul( pset_in ); + map = astAnnul( map ); + +/* Return NULL if anything went wrong. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the result.*/ + return result; +} + +static AstPointSet *RegTransform( AstRegion *this, AstPointSet *in, + int forward, AstPointSet *out, AstFrame **frm, int *status ) { +/* +*+ +* Name: +* astRegTransform + +* Purpose: +* Transform a set of points using the encapsulated FrameSet. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstPointSet *astRegTransform( AstRegion *this, AstPointSet *in, +* int forward, AstPointSet *out, +* AstFrameSet **frm ) + +* Class Membership: +* Region virtual function + +* Description: +* This function takes a Region and a set of points encapsulated +* in a PointSet, and applies either the forward or inverse +* coordinate transformation represented by the encapsulated FrameSet. +* It also returned a pointer to either the current or base Frame in +* the FrameSet. + +* Parameters: +* this +* Pointer to the Region. +* in +* Pointer to the PointSet holding the input coordinate data. If +* NULL then the "points" PointSet within the supplied Region +* ("this") is used. +* forward +* A non-zero value indicates that the forward coordinate transformation +* (from base to current) should be applied, while a zero value requests +* the inverse transformation (from current to base). +* out +* Pointer to a PointSet which will hold the transformed (output) +* coordinate values. A NULL value may also be given, in which case a +* new PointSet will be created by this function. +* frm +* Location at which to return a pointer to a Frame. If "forward" +* is non-zero, the current Frame in the encapsulated FrameSet will +* be returned. Otherwise, the base Frame is returned. The returned +* pointer should be annulled when no longer needed. May be NULL if +* no pointer is needed. + +* Returned Value: +* Pointer to the output (possibly new) PointSet. If "out" is NULL, +* the returned pointer will be a clone of "in" if the Mapping is a +* UnitMap. If "out" is not NULL, then the supplied "out" PointSet will +* be used and returned. + +* Notes: +* - An error will result if the Region supplied does not define +* the requested coordinate transformation (either forward or +* inverse). +* - The number of coordinate values per point in the input +* PointSet must match the number of input coordinates for the +* Region being applied (or number of output coordinates if the +* inverse transformation is requested). This will be equal to the +* number of axes in the Region's base Frame (or the current +* Frame for the inverse transformation). +* - If an output PointSet is supplied, it must have space for +* sufficient number of points and coordinate values per point to +* accommodate the result (e.g. the number of Region output +* coordinates, or number of input coordinates if the inverse +* transformation is requested). Any excess space will be ignored. +* - 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: */ + AstMapping *smap; /* Pointer to simplified Mapping */ + AstPointSet *result; /* Pointer value to return */ + +/* Initialise */ + if( frm ) *frm = NULL; + +/* Check the global error status. */ + if ( !astOK ) return NULL; + +/* If no input PointSet was provided, use the PointSet in the Region. */ + if( !in ) { + if( this->points ) { + in = this->points; + } else { + astError( AST__INTER, "astRegTransform(%s): No PointSet supplied " + "and the supplied %s has no PointSet (internal AST " + "programming error)", status, astGetClass( this ),astGetClass( this ) ); + } + } + +/* Get the simplified Mapping from base to current Frame. */ + smap = astRegMapping( this ); + +/* If it is a UnitMap, return a clone of the input PointSet unless an + explicit output PointSet has been supplied. */ + if( astIsAUnitMap( smap ) && !out ) { + result = astClone( in ); + +/* Otherwise use the Mapping to transform the supplied positions. */ + } else { + result = astTransform( smap, in, forward, out ); + } + +/* Return a pointer to the appropriate Frame. */ + if( frm ) *frm = astGetFrame( this->frameset, forward ? AST__CURRENT : AST__BASE ); + +/* Release resources. */ + smap = astAnnul( smap ); + +/* Return a pointer to the output PointSet. */ + 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 Region axis. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int Unformat( AstFrame *this, int axis, const char *string, +* double *value, int *status ) + +* Class Membership: +* Region member function (over-rides the public astUnformat +* method inherited from the Frame class). + +* Description: +* This function reads a formatted coordinate value for a Region +* 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 Region. +* axis +* The number of the Region 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. +* 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + double coord; /* Coordinate value read */ + int nc; /* Number of characters read */ + +/* Initialise. */ + nc = 0; + +/* Check the global error status. */ + if ( !astOK ) return nc; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Validate the axis index. */ + (void) astValidateAxis( this, axis, 1, "astUnformat" ); + +/* Obtain a pointer to the Region's current Frame and invoke the + astUnformat method for this Frame. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + nc = astUnformat( fr, axis, string, &coord ); + fr = astAnnul( fr ); + +/* 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 ValidateAxis( AstFrame *this_frame, int axis, int fwd, + const char *method, int *status ) { +/* +* Name: +* ValidateAxis + +* Purpose: +* Validate and permute a Region's axis index. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int ValidateAxis( AstFrame *this, int axis, int fwd, const char *method, +* int *status ) + +* Class Membership: +* Region member function (over-rides the protected +* astValidateAxis method inherited from the Frame class). + +* Description: +* This function checks the validity of an index (zero-based) which +* is to be used to address one of the coordinate axes of the +* current Frame in a Region. If the index is valid, it is +* permuted using the axis permutation array associated with the +* Region's current Frame and the (zero-based) permuted axis +* index is returned. This gives the index the axis had when the +* Frame was first created. If the axis index supplied is not +* valid, an error is reported and the global error status is set. + +* Parameters: +* this +* Pointer to the Region. +* axis +* The axis index (zero-based) to be checked. To be valid, it +* must lie between zero and (naxes-1) inclusive, where "naxes" +* is the number of coordinate axes associated with the +* Region's current Frame. +* fwd +* If non-zero, the suppplied axis index is assumed to be an +* "external" axis index, and the corresponding "internal" axis index +* is returned as the function value. Otherwise, the suppplied axis +* index is assumed to be an "internal" axis index, and the +* corresponding "external" axis index is returned as the function +* value. +* 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 permuted axis index - either "internal" or "external" as +* specified by "fwd". + +* 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: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + int naxes; /* Number of Region axes */ + int result; /* Permuted axis index */ + +/* Initialise. */ + result = 0; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_frame; + +/* Determine the number of Region axes. */ + naxes = astGetNaxes( this ); + if ( astOK ) { + +/* If the Region has no axes, report an error (convert to 1-based + axis numbering for the benefit of the public interface). */ + if ( naxes == 0 ) { + astError( AST__AXIIN, "%s(%s): Invalid attempt to use an axis index " + "(%d) for a %s which has no axes.", status, method, + astGetClass( this ), axis + 1, astGetClass( this ) ); + +/* Otherwise, check the axis index for validity and report an error if + it is not valid (again, convert to 1-based axis numbering). */ + } else if ( ( axis < 0 ) || ( axis >= naxes ) ) { + astError( AST__AXIIN, "%s(%s): Axis index (%d) invalid - it should " + "be in the range 1 to %d.", status, method, astGetClass( this ), + axis + 1, naxes ); + +/* If the axis index was valid, obtain a pointer to the Region's + current Frame and invoke this Frame's astValidateAxis method to + obtain the permuted axis index. Annul the Frame pointer + afterwards. */ + } else { + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astValidateAxis( fr, axis, fwd, "astValidateAxis" ); + fr = astAnnul( fr ); + } + } + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = 0; + +/* Return the result. */ + return result; +} + +static void ValidateAxisSelection( AstFrame *this_frame, int naxes, + const int *axes, const char *method, int *status ) { +/* +* Name: +* ValidateAxisSelection + +* Purpose: +* Check that a set of axes selected from a Frame is valid. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* void ValidateAxisSelection( AstFrame *this, int naxes, +* const int *axes, const char *method, int *status ) + +* Class Membership: +* Region member function (over-rides the protected astValidateAxisSelection +* method inherited from the Frame class). + +* Description: +* This function checks the validity of an array of (zero-based) +* axis indices that specify a set of axes to be selected from a +* Frame. To be valid, no axis should be selected more than +* once. In assessing this, any axis indices that do not refer to +* valid Frame axes (e.g. are set to -1) are ignored. +* +* If the axis selection is valid, this function returns without further +* action. Otherwise, an error is reported and the global error status is +* set. + +* Parameters: +* this +* Pointer to the Frame. +* naxes +* The number of axes to be selected (may be zero). +* axes +* Pointer to an array of int with naxes elements that contains the +* (zero based) axis indices 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 selection. This method name is used +* solely for constructing error messages. +* status +* Pointer to the inherited status variable. +*/ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke this + Frame's astValidateAxisSelection method. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + astValidateAxisSelection( fr, naxes, axes, method ); + fr = astAnnul( fr ); + +} + +static int ValidateSystem( AstFrame *this_frame, AstSystemType system, const char *method, int *status ) { +/* +* Name: +* ValidateSystem + +* Purpose: +* Validate a value for a Frame's System attribute. + +* Type: +* Private function. + +* Synopsis: +* #include "region.h" +* int ValidateSystem( AstFrame *this, AstSystemType system, +* const char *method, int *status ) + +* Class Membership: +* Region member function (over-rides the protected 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 */ + AstFrame *fr; /* Pointer to FrameSet's current Frame */ + AstRegion *this; /* Pointer to the Region structure */ + +/* Initialise. */ + result = AST__BADSYSTEM; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Obtain a pointer to the FrameSet structure. */ + this = (AstRegion *) this_frame; + +/* Obtain a pointer to the Region's encapsulated Frame and invoke the + astValidateSystem method for this Frame. Annul the Frame pointer + afterwards. */ + fr = astGetFrame( this->frameset, AST__CURRENT ); + result = astValidateSystem( this, system, method ); + fr = astAnnul( fr ); + +/* If an error occurred, clear the result value. */ + if ( !astOK ) result = AST__BADSYSTEM; + +/* Return the result. */ + return result; +} + +/* Region Attributes. */ +/* -------------------- */ + +/* +*att++ +* Name: +* Adaptive + +* Purpose: +* Should the area adapt to changes in the coordinate system? + +* Type: +* Public attribute. + +* Synopsis: +* Integer (boolean). + +* Description: +* The coordinate system represented by a Region may be changed by +* assigning new values to attributes such as System, Unit, etc. +* For instance, a Region representing an area on the sky in ICRS +* coordinates may have its System attribute changed so that it +* represents (say) Galactic coordinates instead of ICRS. This +* attribute controls what happens when the coordinate system +* represented by a Region is changed in this way. +* +* If Adaptive is non-zero (the default), then area represented by the +* Region adapts to the new coordinate system. That is, the numerical +* values which define the area represented by the Region are changed +* by mapping them from the old coordinate system into the new coordinate +* system. Thus the Region continues to represent the same physical +* area. +* +* If Adaptive is zero, then area represented by the Region does not adapt +* to the new coordinate system. That is, the numerical values which +* define the area represented by the Region are left unchanged. Thus +* the physical area represented by the Region will usually change. +* +* As an example, consider a Region describe a range of wavelength from +* 2000 Angstrom to 4000 Angstrom. If the Unit attribute for the Region +* is changed from Angstrom to "nm" (nanometre), what happens depends +* on the setting of Adaptive. If Adaptive is non-zero, the Mapping +* from the old to the new coordinate system is found. In this case it +* is a simple scaling by a factor of 0.1 (since 1 Angstrom is 0.1 nm). +* This Mapping is then used to modify the numerical values within the +* Region, changing 2000 to 200 and 4000 to 400. Thus the modified +* region represents 200 nm to 400 nm, the same physical space as +* the original 2000 Angstrom to 4000 Angstrom. However, if Adaptive +* had been zero, then the numerical values would not have been changed, +* resulting in the final Region representing 2000 nm to 4000 nm. +* +* Setting Adaptive to zero can be necessary if you want correct +* inaccurate attribute settings in an existing Region. For instance, +* when creating a Region you may not know what Epoch value to use, so +* you would leave Epoch unset resulting in some default value being used. +* If at some later point in the application, the correct Epoch value +* is determined, you could assign the correct value to the Epoch +* attribute. However, you would first need to set Adaptive temporarily +* to zero, because otherwise the area represented by the Region would +* be Mapped from the spurious default Epoch to the new correct Epoch, +* which is not what is required. + +* Applicability: +* Region +* All Regions have this attribute. +*att-- +*/ + +/* This is a boolean value (0 or 1) with a value of -INT_MAX when + undefined but yielding a default of 1. */ +astMAKE_CLEAR(Region,Adaptive,adaptive,-INT_MAX) +astMAKE_GET(Region,Adaptive,int,1,( ( this->adaptive == -INT_MAX ) ? + 1 : this->adaptive )) +astMAKE_SET(Region,Adaptive,int,adaptive,( value != 0 )) +astMAKE_TEST(Region,Adaptive,( this->adaptive != -INT_MAX )) + +/* +*att++ +* Name: +* Negated + +* Purpose: +* Region negation flag. + +* Type: +* Public attribute. + +* Synopsis: +* Integer (boolean). + +* Description: +* This attribute controls whether a Region represents the "inside" or +* the "outside" of the area which was supplied when the Region was +* created. If the attribute value is zero (the default), the Region +* represents the inside of the original area. However, if it is non-zero, +* it represents the outside of the original area. The value of this +* attribute may be toggled using the +c astNegate function. +f AST_NEGATE routine. + +* Note, whether the boundary is considered to be inside the Region or +* not is controlled by the Closed attribute. Changing the value of +* the Negated attribute does not change the value of the Closed attribute. +* Thus, if Region is closed, then the boundary of the Region will be +* inside the Region, whatever the setting of the Negated attribute. + +* Applicability: +* Region +* All Regions have this attribute. +*att-- +*/ + +/* This is a boolean value (0 or 1) with a value of -INT_MAX when + undefined but yielding a default of zero. */ +astMAKE_CLEAR(Region,Negated,negated,(astResetCache(this),-INT_MAX)) +astMAKE_GET(Region,Negated,int,0,( ( this->negated == -INT_MAX ) ? + 0 : this->negated )) +astMAKE_SET(Region,Negated,int,negated,(astResetCache(this),( value != 0 ))) +astMAKE_TEST(Region,Negated,( this->negated != -INT_MAX )) + +/* +*att++ +* Name: +* Bounded + +* Purpose: +* Is the Region bounded? + +* Type: +* Public attribute. + +* Synopsis: +* Integer (boolean), read-only. + +* Description: +* This is a read-only attribute indicating if the Region is bounded. +* A Region is bounded if it is contained entirely within some +* finite-size bounding box. + +* Applicability: +* Region +* All Regions have this attribute. +*att-- +*/ + +/* +*att+ +* Name: +* RegionFS + +* Purpose: +* Should Region FrameSet be dumped? + +* Type: +* Protected attribute. + +* Synopsis: +* Integer (boolean). + +* Description: +* This attribute indicates whether the FrameSet encapsulated by the +* Region should be included in the dump produced by the Dump function. +* +* If set to a non-zero value (the default), the FrameSet in the Region +* will always be included in the dump as usual. If set to zero, the +* FrameSet will only be included in the dump if the Mapping from base +* to current Frame is not a UnitMap. If the base->current Mapping is +* a UnitMap, the FrameSet is omitted from the dump. If the dump is +* subsequently used to re-create the Region, the new Region will have a +* default FrameSet containing a single default Frame with the appropriate +* number of axes. +* +* This facility is indended to reduce the size of textual dumps of +* Regions in situations where the Frame to which the Region refers can +* be implied by the context in which the Region is used. This is +* often the case when a Region is encapsulated within another Region. +* In such cases the current Frame of the encapsulated Region will +* usually be equivalent to the base Frame of the parent Region +* structure, and so can be re-instated (by calling the astSetRegFS +* method) even if the FrameSet is omitted from the dump of the +* encapsulated Region. Note if the base->current Mapping in the FrameSet +* in the encapsulated Region is not a UnitMap, then we should always +* dump the FrameSet regardless of the setting of RegionFS. This is because +* the parent Region structure will not know how to convert the PointSet +* stored in the encapsulated Region into its own base Frame if the +* FrameSet is not available. + +* Applicability: +* Region +* All Regions have this attribute. +*att- +*/ + +/* This is a boolean value (0 or 1) with a value of -INT_MAX when + undefined but yielding a default of one. */ +astMAKE_CLEAR(Region,RegionFS,regionfs,-INT_MAX) +astMAKE_TEST(Region,RegionFS,( this->regionfs != -INT_MAX )) +astMAKE_SET(Region,RegionFS,int,regionfs,( value != 0 )) +astMAKE_GET(Region,RegionFS,int,1,( ( this->regionfs == -INT_MAX ) ? + 1 : this->regionfs )) + +/* +*att++ +* Name: +* FillFactor + +* Purpose: +* Fraction of the Region which is of interest. + +* Type: +* Public attribute. + +* Synopsis: +* Floating point. + +* Description: +* This attribute indicates the fraction of the Region which is of +* interest. AST does not use this attribute internally for any purpose. +* Typically, it could be used to indicate the fraction of the Region for +* which data is available. +* +* The supplied value must be in the range 0.0 to 1.0, and the default +* value is 1.0 (except as noted below). + +* Applicability: +* Region +* All Regions have this attribute. +* CmpRegion +* The default FillFactor for a CmpRegion is the FillFactor of its +* first component Region. +* Prism +* The default FillFactor for a Prism is the product of the +* FillFactors of its two component Regions. +* Stc +* The default FillFactor for an Stc is the FillFactor of its +* encapsulated Region. +*att-- +*/ + +astMAKE_CLEAR(Region,FillFactor,fillfactor,AST__BAD) +astMAKE_GET(Region,FillFactor,double,1.0,( ( this->fillfactor == AST__BAD ) ? + 1.0 : this->fillfactor )) +astMAKE_TEST(Region,FillFactor,( this->fillfactor != AST__BAD )) +astMAKE_SET(Region,FillFactor,double,fillfactor,((value<0.0||value>1.0)?( + astError(AST__ATSER,"astSetFillFactor(%s): Invalid value (%g) supplied " + "for attribute FillFactor.", status,astGetClass(this),value), + astError(AST__ATSER,"FillFactor values should be in the range 0.0 to 1.0", status), + this->fillfactor):value)) + +/* +*att++ +* Name: +* MeshSize + +* Purpose: +* Number of points used to represent the boundary of a Region. + +* Type: +* Public attribute. + +* Synopsis: +* Integer. + +* Description: +* This attribute controls how many points are used when creating a +* mesh of points covering the boundary or volume of a Region. Such a +* mesh is returned by the +c astGetRegionMesh +f AST_GETREGIONMESH +* method. The boundary mesh is also used when testing for overlap +* between two Regions: each point in the bomdary mesh of the first +* Region is checked to see if it is inside or outside the second Region. +* Thus, the reliability of the overlap check depends on the value assigned +* to this attribute. If the value used is very low, it is possible for +* overlaps to go unnoticed. High values produce more reliable results, but +* can result in the overlap test being very slow. The default value is 200 +* for two dimensional Regions and 2000 for three or more dimensional +* Regions (this attribute is not used for 1-dimensional regions since the +* boundary of a simple 1-d Region can only ever have two points). A +* value of five is used if the supplied value is less than five. + +* Applicability: +* Region +* All Regions have this attribute. +* CmpRegion +* The default MeshSize for a CmpRegion is the MeshSize of its +* first component Region. +* Stc +* The default MeshSize for an Stc is the MeshSize of its +* encapsulated Region. +*att-- +*/ +/* If the value of MeshSize is set or cleared, annul the PointSet used to + cache a mesh of base Frame boundary points. This will force a new + PointSet to be created next time it is needed. See function RegMesh. */ +astMAKE_CLEAR(Region,MeshSize,meshsize,(astResetCache(this),-INT_MAX)) +astMAKE_SET(Region,MeshSize,int,meshsize,(astResetCache(this),( value > 5 ? value : 5 ))) +astMAKE_TEST(Region,MeshSize,( this->meshsize != -INT_MAX )) +astMAKE_GET(Region,MeshSize,int,0,( ( this->meshsize == -INT_MAX)?((astGetNaxes(this)==1)?2:((astGetNaxes(this)==2)?200:2000)): this->meshsize )) + +/* +*att++ +* Name: +* Closed + +* Purpose: +* Should the boundary be considered to be inside the region? + +* Type: +* Public attribute. + +* Synopsis: +* Integer (boolean). + +* Description: +* This attribute controls whether points on the boundary of a Region +* are considered to be inside or outside the region. If the attribute +* value is non-zero (the default), points on the boundary are considered +* to be inside the region (that is, the Region is "closed"). However, +* if the attribute value is zero, points on the bounary are considered +* to be outside the region. + +* Applicability: +* Region +* All Regions have this attribute. +* PointList +* The value of the Closed attribute is ignored by PointList regions. +* If the PointList region has not been negated, then it is always +* assumed to be closed. If the PointList region has been negated, then +* it is always assumed to be open. This is required since points +* have zero volume and therefore consist entirely of boundary. +* CmpRegion +* The default Closed value for a CmpRegion is the Closed value of its +* first component Region. +* Stc +* The default Closed value for an Stc is the Closed value of its +* encapsulated Region. +*att-- +*/ +/* This is a boolean value (0 or 1) with a value of -INT_MAX when + undefined but yielding a default of 1. */ +astMAKE_CLEAR(Region,Closed,closed,(astResetCache(this),-INT_MAX)) +astMAKE_GET(Region,Closed,int,1,( ( this->closed == -INT_MAX ) ? + 1 : this->closed )) +astMAKE_SET(Region,Closed,int,closed,(astResetCache(this),( value != 0 ))) +astMAKE_TEST(Region,Closed,( this->closed != -INT_MAX )) + +/* Access to attributes of the encapsulated Frame. */ +/* ----------------------------------------------- */ +/* Use the macros defined at the start of this file to implement + private member functions that give access to the attributes of the + encapsulated Frame of a Region and its axes. These functions over-ride + the attribute access methods inherited from the Frame class. */ + +/* Clear, Get, Set and Test axis-independent Frame attributes. */ +MAKE_CLEAR(Digits) +MAKE_CLEAR(Domain) +MAKE_CLEAR(MatchEnd) +MAKE_CLEAR(MaxAxes) +MAKE_CLEAR(MinAxes) +MAKE_CLEAR(Permute) +MAKE_CLEAR(PreserveAxes) +MAKE_CLEAR(Title) + +MAKE_GET(Digits,int) +MAKE_GET(Domain,const char *) +MAKE_GET(MatchEnd,int) +MAKE_GET(MaxAxes,int) +MAKE_GET(MinAxes,int) +MAKE_GET(Permute,int) +MAKE_GET(PreserveAxes,int) +MAKE_GET(Title,const char *) +MAKE_SET(Digits,int,I) +MAKE_SET(Domain,const char *,C) +MAKE_SET(MatchEnd,int,I) +MAKE_SET(MaxAxes,int,I) +MAKE_SET(MinAxes,int,I) +MAKE_SET(Permute,int,I) +MAKE_SET(PreserveAxes,int,I) +MAKE_SET(Title,const char *,C) +MAKE_TEST(Digits) +MAKE_TEST(Domain) +MAKE_TEST(MatchEnd) +MAKE_TEST(MaxAxes) +MAKE_TEST(MinAxes) +MAKE_TEST(Permute) +MAKE_TEST(PreserveAxes) +MAKE_TEST(Title) + +MAKE_GET(ActiveUnit,int) +MAKE_SET(ActiveUnit,int,I) +MAKE_TEST(ActiveUnit) + +MAKE_GET(System,AstSystemType) +MAKE_SET_SYSTEM(System) +MAKE_TEST(System) +MAKE_CLEAR(System) + +MAKE_GET(AlignSystem,AstSystemType) +MAKE_SET_SYSTEM(AlignSystem) +MAKE_TEST(AlignSystem) +MAKE_CLEAR(AlignSystem) + +MAKE_GET(Epoch,double) +MAKE_SET(Epoch,double,D) +MAKE_TEST(Epoch) +MAKE_CLEAR(Epoch) + +MAKE_GET(ObsLon,double) +MAKE_SET(ObsLon,double,D) +MAKE_TEST(ObsLon) +MAKE_CLEAR(ObsLon) + +MAKE_GET(ObsLat,double) +MAKE_SET(ObsLat,double,D) +MAKE_TEST(ObsLat) +MAKE_CLEAR(ObsLat) + +MAKE_GET(ObsAlt,double) +MAKE_SET(ObsAlt,double,D) +MAKE_TEST(ObsAlt) +MAKE_CLEAR(ObsAlt) + +/* Clear, Get, Set and Test axis-dependent Frame attributes. */ +MAKE_CLEAR_AXIS(Direction) +MAKE_CLEAR_AXIS(Format) +MAKE_CLEAR_AXIS(Label) +MAKE_CLEAR_AXIS(Symbol) +MAKE_CLEAR_AXIS(Unit) +MAKE_GET_AXIS(Direction,int) +MAKE_GET_AXIS(Format,const char *) +MAKE_GET_AXIS(Label,const char *) +MAKE_GET_AXIS(Symbol,const char *) +MAKE_GET_AXIS(Unit,const char *) +MAKE_SET_AXIS(Direction,int,I) +MAKE_SET_AXIS(Format,const char *,C) +MAKE_SET_AXIS(Label,const char *,C) +MAKE_SET_AXIS(Symbol,const char *,C) +MAKE_SET_AXIS(Unit,const char *,C) +MAKE_TEST_AXIS(Direction) +MAKE_TEST_AXIS(Format) +MAKE_TEST_AXIS(Label) +MAKE_TEST_AXIS(Symbol) +MAKE_TEST_AXIS(Unit) + +MAKE_GET_AXIS(Bottom,double) +MAKE_SET_AXIS(Bottom,double,D) +MAKE_TEST_AXIS(Bottom) +MAKE_CLEAR_AXIS(Bottom) + +MAKE_GET_AXIS(Top,double) +MAKE_SET_AXIS(Top,double,D) +MAKE_TEST_AXIS(Top) +MAKE_CLEAR_AXIS(Top) + +/* Copy constructor. */ +/* ----------------- */ +static void Copy( const AstObject *objin, AstObject *objout, int *status ) { +/* +* Name: +* Copy + +* Purpose: +* Copy constructor for Region objects. + +* Type: +* Private function. + +* Synopsis: +* void Copy( const AstObject *objin, AstObject *objout, int *status ) + +* Description: +* This function implements the copy constructor for Region 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: */ + AstRegion *in; /* Pointer to input Region */ + AstRegion *out; /* Pointer to output Region */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain pointers to the input and output Regions. */ + in = (AstRegion *) objin; + out = (AstRegion *) objout; + +/* For safety, first clear any references to the input memory from + the output Region. */ + out->basemesh = NULL; + out->basegrid = NULL; + out->frameset = NULL; + out->points = NULL; + out->unc = NULL; + out->negation = NULL; + out->defunc = NULL; + +/* Now copy each of the above structures. */ + out->frameset = astCopy( in->frameset ); + if( in->points ) out->points = astCopy( in->points ); + if( in->basemesh ) out->basemesh = astCopy( in->basemesh ); + if( in->basegrid ) out->basegrid = astCopy( in->basegrid ); + if( in->unc ) out->unc = astCopy( in->unc ); + if( in->negation ) out->negation = astCopy( in->negation ); + if( in->defunc ) out->defunc = astCopy( in->defunc ); +} + + +/* Destructor. */ +/* ----------- */ +static void Delete( AstObject *obj, int *status ) { +/* +* Name: +* Delete + +* Purpose: +* Destructor for Region objects. + +* Type: +* Private function. + +* Synopsis: +* void Delete( AstObject *obj, int *status ) + +* Description: +* This function implements the destructor for Region 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: */ + AstRegion *this; /* Pointer to Region */ + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) obj; + +/* Annul all resources. */ + this->frameset = astAnnul( this->frameset ); + if( this->points ) this->points = astAnnul( this->points ); + if( this->basemesh ) this->basemesh = astAnnul( this->basemesh ); + if( this->basegrid ) this->basegrid = astAnnul( this->basegrid ); + if( this->unc ) this->unc = astAnnul( this->unc ); + if( this->negation ) this->negation = astAnnul( this->negation ); + if( this->defunc ) this->defunc = astAnnul( this->defunc ); +} + +/* Dump function. */ +/* -------------- */ +static void Dump( AstObject *this_object, AstChannel *channel, int *status ) { +/* +* Name: +* Dump + +* Purpose: +* Dump function for Region 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 Region class to an output Channel. + +* Parameters: +* this +* Pointer to the Region 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 Constants: */ +#define KEY_LEN 50 /* Maximum length of a keyword */ +#define COM_LEN 50 /* Maximum length of a comment */ + +/* Local Variables: */ + AstFrame *fr; /* Pointer to the current Frame */ + AstMapping *smap; /* Base->current Mapping */ + AstRegion *this; /* Pointer to the Region structure */ + AstRegion *unc; /* Pointer to the uncertainty Region */ + double dval; /* Floating point attribute value */ + int ival; /* Integer attribute value */ + int set; /* Attribute value set? */ + int unit; /* Base->current is unitmap? */ + +/* Check the global error status. */ + if ( !astOK ) return; + +/* Obtain a pointer to the Region structure. */ + this = (AstRegion *) this_object; + +/* Write out values representing the instance variables for the + Region 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. */ + +/* Negated. */ +/* -------- */ + set = TestNegated( this, status ); + ival = set ? GetNegated( this, status ) : astGetNegated( this ); + astWriteInt( channel, "Negate", (ival != 0), 0, ival, + ival ? "Region negated" : "Region not negated" ); + +/* FillFactor */ +/* ---------- */ + set = TestFillFactor( this, status ); + dval = set ? GetFillFactor( this, status ) : astGetFillFactor( this ); + astWriteDouble( channel, "Fill", set, 0, dval,"Region fill factor" ); + +/* MeshSize. */ +/* --------- */ + set = TestMeshSize( this, status ); + ival = set ? GetMeshSize( this, status ) : astGetMeshSize( this ); + astWriteInt( channel, "MeshSz", set, 0, ival, + "No. of points used to represent boundary" ); + +/* Closed. */ +/* ------- */ + set = TestClosed( this, status ); + ival = set ? GetClosed( this, status ) : astGetClosed( this ); + astWriteInt( channel, "Closed", set, 0, ival, + ival ? "Boundary is inside" : "Boundary is outside" ); + +/* Adaptive */ +/* -------- */ + set = TestAdaptive( this, status ); + ival = set ? GetAdaptive( this, status ) : astGetAdaptive( this ); + astWriteInt( channel, "Adapt", (ival != 0), 0, ival, + ival ? "Region adapts to coord sys changes" : "Region does not adapt to coord sys changes" ); + +/* FrameSet */ +/* -------- */ + +/* If the vertices are the same in both base and current Frames (i.e. + if the Frames are connected by a UnitMap), then just dump the current + Frame (unless the RegionFS attribute is zero, in which case the + current Frame can be determined from the higher level context of the + Region and so does not need to be dumped- e.g. if the Region is contained + within another Region the parent Region will define the current Frame). + Otherwise, dump the whole FrameSet. */ + ival = astGetRegionFS( this ); + smap = astRegMapping( this ); + if( ( unit = astIsAUnitMap( smap ) ) ){ + set = 0; + if( ival ) { + fr = astGetFrame( this->frameset, AST__CURRENT ); + astWriteObject( channel, "Frm", 1, 1, fr, "Coordinate system" ); + fr = astAnnul( fr ); + } + } else { + set = ( ival == 0 ); + astWriteObject( channel, "FrmSet", 1, 1, this->frameset, + "Original & current coordinate systems" ); + } + +/* Annul the Mapping pointers */ + smap = astAnnul( smap ); + +/* RegionFS */ +/* -------- */ + astWriteInt( channel, "RegFS", set, 0, ival, + ival ? "Include Frame in dump" : "Do not include Frame in dump" ); + +/* Points */ +/* ------ */ + if( this->points ) { + astWriteObject( channel, "Points", 1, 1, this->points, + "Points defining the shape" ); + +/* If the FrameSet was not included in the dump, then the loader will use + the PointSet to determine the number of axes in the frame spanned by + the Region. If there is no PointSet, then we must explicitly include + an item giving the number of axes.*/ + } else { + astWriteInt( channel, "RegAxes", 1, 1, astGetNaxes( this ), + "Number of axes spanned by the Region" ); + } + +/* Uncertainty */ +/* ----------- */ +/* Only dump the uncertinaty Region if required. */ + if( astTestUnc( this ) ) { + unc = astGetUncFrm( this, AST__BASE ); + astWriteObject( channel, "Unc", 1, 1, unc, + "Region defining positional uncertainties." ); + unc = astAnnul( unc ); + } + +/* Undefine macros local to this function. */ +#undef KEY_LEN +} + + +/* Standard class functions. */ +/* ========================= */ +/* Implement the astIsARegion and astCheckRegion functions using + the macros defined for this purpose in the "object.h" header + file. */ +astMAKE_ISA(Region,Frame) +astMAKE_CHECK(Region) + +AstRegion *astInitRegion_( void *mem, size_t size, int init, + AstRegionVtab *vtab, const char *name, + AstFrame *frame, AstPointSet *pset, + AstRegion *unc, int *status ){ +/* +*+ +* Name: +* astInitRegion + +* Purpose: +* Initialise a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstRegion *astInitRegion( void *mem, size_t size, int init, +* AstRegionVtab *vtab, const char *name, +* AstFrame *frame, AstpointSet *pset, +* AstRegion *unc ) + +* Class Membership: +* Region initialiser. + +* Description: +* This function is provided for use by class implementations to +* initialise a new Region object. It allocates memory (if +* necessary) to accommodate the Region plus any additional data +* associated with the derived class. It then initialises a +* Region 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 Region at the start of the memory passed +* via the "vtab" parameter. + +* Parameters: +* mem +* A pointer to the memory in which the Region is to be +* created. This must be of sufficient size to accommodate the +* Region data (sizeof(Region)) 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 Region (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 Region structure, so a valid value must be +* supplied even if not required for allocating memory. +* init +* A logical flag indicating if the Region'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 Region. +* 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). +* frame +* Pointer to the encapsulated Frame. A deep copy of this Frame is +* taken. This means that subsequent changes to the supplied Frame +* will have no effect on the new Region. +* pset +* A PointSet holding the points which define the Region. These +* positions should refer to the given Frame. May be NULL. +* unc +* A pointer to a Region which specifies the uncertainty in the +* supplied positions (all points on the boundary of the new Region +* being initialised are assumed to have the same uncertainty). A NULL +* pointer can be supplied, in which case default uncertainties equal to +* 1.0E-6 of the dimensions of the new Region's bounding box are used. +* If an uncertainty Region is supplied, it must be of a class for +* which all instances are centro-symetric (e.g. Box, Circle, Ellipse, +* etc.) or be a Prism containing centro-symetric component Regions. +* Its encapsulated Frame must be related to the Frame supplied for +* parameter "frame" (i.e. astConvert should be able to find a Mapping +* between them). Two positions in the "frame" Frame are considered to be +* co-incident if their uncertainty Regions overlap. The centre of the +* supplied uncertainty Region is immaterial since it will be re-centred +* on the point being tested before use. A deep copy is taken of the +* supplied Region. + +* Returned Value: +* A pointer to the new Region. + +* 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: */ + AstFrame *f0; /* Frame to use */ + AstRegion *new; /* Pointer to new Region */ + int nax; /* No. of axes in supplied Frame */ + int ncoord; /* Coords per point */ + +/* Check the global status. */ + if ( !astOK ) return NULL; + +/* If necessary, initialise the virtual function table. */ + if( init ) astInitRegionVtab( vtab, name ); + +/* Note the number of axes in the supplied Frame. */ + nax = astGetNaxes( frame ); + +/* Check the pointset if supplied. */ + if( pset ) { + +/* Note the number of axes per point in the supplied PointSet */ + ncoord = astGetNcoord( pset ); + +/* If OK, check that the number of coordinates per point matches the number + of axes in the Frame. Report an error if these numbers do not match. */ + if ( astOK && ( ncoord != nax ) ) { + astError( AST__NCPIN, "astInitRegion(%s): Bad number of coordinate " + "values per point (%d).", status, name, ncoord ); + astError( AST__NCPIN, "The %s given requires %d coordinate value(s) " + "for each point.", status, astGetClass( frame ), nax ); + } + } + +/* Initialise a Frame structure (the parent class) as the first + component within the Region structure, allocating memory if + necessary. Give this Frame zero axes as the Frame information will be + specified by the encapsulated FrameSet. */ + new = (AstRegion *) astInitFrame( mem, size, 0, (AstFrameVtab *) vtab, + name, 0 ); + if ( astOK ) { + +/* Initialise the Region data. */ +/* ----------------------------- */ + new->frameset = NULL; + new->points = NULL; + new->unc = NULL; + new->meshsize = -INT_MAX; + new->adaptive = -INT_MAX; + new->basemesh = NULL; + new->basegrid = NULL; + new->negated = -INT_MAX; + new->closed = -INT_MAX; + new->regionfs = -INT_MAX; + new->fillfactor = AST__BAD; + new->defunc = NULL; + new->nomap = 0; + new->negation = NULL; + +/* If the supplied Frame is a Region, gets its encapsulated Frame. If a + FrameSet was supplied, use its current Frame, otherwise use the + supplied Frame. */ + if( astIsARegion( frame ) ) { + f0 = astGetFrame( ((AstRegion *) frame)->frameset, AST__CURRENT ); + + } else if( astIsAFrameSet( frame ) ) { + f0 = astGetFrame( (AstFrameSet *) frame, AST__CURRENT ); + + } else { + f0 = astClone( frame ); + } + +/* Store a clone of the supplied PointSet pointer. */ + new->points = pset ? astClone( pset ) : NULL; + + +#ifdef DEBUG + if( pset ) { + double **ptr; + double lim; + int ii,jj, np; + ptr = astGetPoints( pset ); + np = astGetNpoint( pset ); + lim = sqrt( DBL_MAX ); + for( ii = 0; astOK && ii < ncoord; ii++ ) { + for( jj = 0; jj < np; jj++ ) { + if( fabs( ptr[ ii ][ jj ] ) > lim ) { + if( !strcmp( name, "Interval" ) ) { + if( ptr[ ii ][ jj ] != AST__BAD && + ptr[ ii ][ jj ] != DBL_MAX && + ptr[ ii ][ jj ] != -DBL_MAX ) { + astError( AST__INTER, "astInitRegion(%s): suspicious " + "axis value (%g) supplied.", status, name, ptr[ ii ][ jj ] ); + break; + } + } else { + astError( AST__INTER, "astInitRegion(%s): suspicious " + "axis value (%g) supplied.", status, name, + ptr[ ii ][ jj ] ); + break; + } + } + } + } + } +#endif + +/* Form a FrameSet consisting of two copies of the supplied Frame connected + together by a UnitMap, and store in the Region structure. We use the + private SetRegFS rather than the protected astSetRegFS because this + initialiser may be being called from a subclass which over-rides + astSetRegFS. If this were the case, then the implementation of + astSetRegFS provided by the subclass may access information within the + subclass structure which has not yet been initialised. */ + SetRegFS( new, f0, status ); + f0 = astAnnul( f0 ); + +/* Store any uncertainty Region. Use the private SetUnc rather than + astSetUnc to avoid subclass implementations using subclass data which + has not yet been initialised. */ + SetUnc( new, unc, status ); + +/* 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; +} + +AstRegion *astLoadRegion_( void *mem, size_t size, + AstRegionVtab *vtab, const char *name, + AstChannel *channel, int *status ) { +/* +*+ +* Name: +* astLoadRegion + +* Purpose: +* Load a Region. + +* Type: +* Protected function. + +* Synopsis: +* #include "region.h" +* AstRegion *astLoadRegion( void *mem, size_t size, +* AstRegionVtab *vtab, const char *name, +* AstChannel *channel ) + +* Class Membership: +* Region loader. + +* Description: +* This function is provided to load a new Region 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 +* Region structure in this memory, using data read from the +* input Channel. + +* Parameters: +* mem +* A pointer to the memory into which the Region is to be +* loaded. This must be of sufficient size to accommodate the +* Region data (sizeof(Region)) 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 Region (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 Region 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(AstRegion) is used instead. +* vtab +* Pointer to the start of the virtual function table to be +* associated with the new Region. If this is NULL, a pointer +* to the (static) virtual function table for the Region 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 "Region" is used instead. + +* Returned Value: +* A pointer to the new Region. + +* 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 Constants: */ + astDECLARE_GLOBALS /* Pointer to thread-specific global data */ +#define KEY_LEN 50 /* Maximum length of a keyword */ + +/* Local Variables: */ + AstFrame *f1; /* Base Frame for encapsulated FrameSet */ + AstRegion *new; /* Pointer to the new Region */ + int nax; /* No. of axes in Frame, or FrameSet base Frame */ + int naxpt; /* No. of axes in per point */ + +/* Get a pointer to the thread specific global data structure. */ + astGET_GLOBALS(channel); + +/* Initialise. */ + new = NULL; + +/* Check the global error status. */ + if ( !astOK ) return new; + +/* If a NULL virtual function table has been supplied, then this is + the first loader to be invoked for this Region. In this case the + Region belongs to this class, so supply appropriate values to be + passed to the parent class loader (and its parent, etc.). */ + if ( !vtab ) { + size = sizeof( AstRegion ); + vtab = &class_vtab; + name = "Region"; + +/* If required, initialise the virtual function table for this class. */ + if ( !class_init ) { + astInitRegionVtab( 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 Region. */ + new = astLoadFrame( mem, size, (AstFrameVtab *) vtab, name, + channel ); + + if ( astOK ) { + +/* Read input data. */ +/* ================ */ +/* Request the input Channel to read all the input data appropriate to + this class into the internal "values list". */ + astReadClassData( channel, "Region" ); + +/* 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. */ + +/* Negated */ +/* ------- */ + new->negated = astReadInt( channel, "negate", -INT_MAX ); + if ( TestNegated( new, status ) ) SetNegated( new, new->negated, status ); + +/* FillFactor */ +/* ---------- */ + new->fillfactor = astReadDouble( channel, "fill", AST__BAD ); + if ( TestFillFactor( new, status ) ) SetFillFactor( new, new->fillfactor, status ); + +/* MeshSize */ +/* -------- */ + new->meshsize = astReadInt( channel, "meshsz", -INT_MAX ); + if ( TestMeshSize( new, status ) ) SetMeshSize( new, new->meshsize, status ); + +/* Closed */ +/* ------ */ + new->closed = astReadInt( channel, "closed", -INT_MAX ); + if ( TestClosed( new, status ) ) SetClosed( new, new->closed, status ); + +/* Adaptive */ +/* -------- */ + new->adaptive = astReadInt( channel, "adapt", -INT_MAX ); + if ( TestAdaptive( new, status ) ) SetAdaptive( new, new->adaptive, status ); + +/* Points */ +/* ------ */ + new->points = astReadObject( channel, "points", NULL ); + +/* If some points were found, ensure that they are in a PointSet and get + the number of axis values per point. */ + if( new->points ){ + if( astIsAPointSet( new->points) ) { + naxpt = astGetNcoord( new->points ); + } else { + naxpt = 0; + astError( AST__REGIN, "astLoadRegion(%s): Corrupt %s specifies points " + "using a %s (should be a PointSet).", status, astGetClass( new ), + astGetClass( new ), astGetClass( new->points ) ); + } + +/* If no PointSet was loaded, attempt to determine the number of axes + spanned by the Region by reading the RegAxes value. */ + } else { + naxpt = astReadInt( channel, "regaxes", 0 ); + } + +/* Uncertainty */ +/* ----------- */ + new->unc = astReadObject( channel, "unc", NULL ); + new->defunc = NULL; + +/* FrameSet */ +/* -------- */ +/* First see if the dump contains a single Frame. If so, create a + FrameSet from it and a copy of itself, using a UnitMap to connect the + two. */ + new->nomap = 0; + new->frameset = NULL; + f1 = astReadObject( channel, "frm", NULL ); + if( f1 ) { + new->regionfs = 1; + nax = astGetNaxes( f1 ); + astSetRegFS( new, f1 ); + f1 = astAnnul( f1 ); + +/* If no Frame was found in the dump, look for a FrameSet. Get the number + of axes spanning its base Frame ("Nin"). */ + } else { + new->frameset = astReadObject( channel, "frmset", NULL ); + if( new->frameset ) { + nax = astGetNin( new->frameset ); + +/* If a FrameSet was found, the value of the RegionFS attribute is still + unknown and so we must read it from an attribute as normal. */ + new->regionfs = astReadInt( channel, "regfs", 1 ); + if ( TestRegionFS( new, status ) ) SetRegionFS( new, new->regionfs, status ); + + } else { + nax = 0; + } + } + +/* If neither a Frame nor a FrameSet was found, create a default FrameSet + and set the RegionFS attribute false, to indicate that the FrameSet + should not be used. */ + if( !new->frameset ){ + nax = naxpt ? naxpt : 1; + f1 = astFrame( nax, "", status ); + new->frameset = astFrameSet( f1, "", status ); + astSetIdent( new->frameset, DUMMY_FS ); + f1 = astAnnul( f1 ); + new->regionfs = 0; + } + +/* Report an error if the number of axis values per point in the pointset is + incorrect. */ + if ( astOK && new->points && ( naxpt != nax ) ) { + astError( AST__REGIN, "astLoadRegion(%s): Corrupt %s contains " + " incorrect number of coordinate values per point (%d).", status, + astGetClass( new ), astGetClass( new ), naxpt ); + astError( AST__REGIN, "The %s requires %d coordinate value(s) " + "for each point.", status, astGetClass( new ), nax ); + } + +/* Initialise other fields which are used as caches for values derived + from the attributes set above. */ + new->basemesh = NULL; + new->basegrid = NULL; + +/* If an error occurred, clean up by deleting the new Region. */ + if ( !astOK ) new = astDelete( new ); + } + +/* Return the new Region pointer. */ + return new; + +/* Undefine macros local to this function. */ +#undef KEY_LEN +} + +/* Virtual function interfaces. */ +/* ============================ */ +/* These provide the external interface to the virtual functions defined by + this class. Each simply checks the global error status and then locates and + executes the appropriate member function, using the function pointer stored + in the object's virtual function table (this pointer is located using the + astMEMBER macro defined in "object.h"). + + Note that the member function may not be the one defined here, as it may + have been over-ridden by a derived class. However, it should still have the + same interface. */ + +void astRegClearAttrib_( AstRegion *this, const char *attrib, char **base_attrib, int *status ) { + if ( !astOK ) return; + (**astMEMBER(this,Region,RegClearAttrib))( this, attrib, base_attrib, status ); +} +void astRegSetAttrib_( AstRegion *this, const char *setting, char **base_setting, int *status ) { + if ( !astOK ) return; + (**astMEMBER(this,Region,RegSetAttrib))( this, setting, base_setting, status ); +} +void astNegate_( AstRegion *this, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,Negate))( this, status ); +} +AstFrame *astGetRegionFrame_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,GetRegionFrame))( this, status ); +} +AstFrameSet *astGetRegionFrameSet_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,GetRegionFrameSet))( this, status ); +} +AstRegion *astMapRegion_( AstRegion *this, AstMapping *map, AstFrame *frame, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,MapRegion))( this, map, frame, status ); +} +int astOverlap_( AstRegion *this, AstRegion *that, int *status ){ + if ( !astOK ) return 0; + return (**astMEMBER(this,Region,Overlap))( this, that, status ); +} +int astOverlapX_( AstRegion *that, AstRegion *this, int *status ){ + if ( !astOK ) return 0; + return (**astMEMBER(that,Region,OverlapX))( that, this, status ); +} +AstFrame *astRegFrame_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegFrame))( this, status ); +} +AstRegion *astRegBasePick_( AstRegion *this, int naxes, const int *axes, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegBasePick))( this, naxes, axes, status ); +} +AstPointSet *astBTransform_( AstRegion *this, AstPointSet *in, + int forward, AstPointSet *out, int *status ) { + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,BTransform))( this, in, forward, out, status ); +} +AstPointSet *astRegTransform_( AstRegion *this, AstPointSet *in, + int forward, AstPointSet *out, + AstFrame **frm, int *status ) { + if( frm ) *frm = NULL; + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegTransform))( this, in, forward, out, frm, status ); +} +int astRegPins_( AstRegion *this, AstPointSet *pset, AstRegion *unc, int **mask, int *status ){ + if( mask ) *mask = NULL; + if ( !astOK ) return 0; + return (**astMEMBER(this,Region,RegPins))( this, pset, unc, mask, status ); +} +AstMapping *astRegMapping_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegMapping))( this, status ); +} +int astRegDummyFS_( AstRegion *this, int *status ){ + if ( !astOK ) return 0; + return (**astMEMBER(this,Region,RegDummyFS))( this, status ); +} +int astGetBounded_( AstRegion *this, int *status ){ + if ( !astOK ) return 0; + return (**astMEMBER(this,Region,GetBounded))( this, status ); +} +int astTestUnc_( AstRegion *this, int *status ){ + if ( !astOK ) return 0; + return (**astMEMBER(this,Region,TestUnc))( this, status ); +} +void astClearUnc_( AstRegion *this, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,ClearUnc))( this, status ); +} +void astRegBaseBox_( AstRegion *this, double *lbnd, double *ubnd, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,RegBaseBox))( this, lbnd, ubnd, status ); +} +void astRegBaseBox2_( AstRegion *this, double *lbnd, double *ubnd, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,RegBaseBox2))( this, lbnd, ubnd, status ); +} +void astResetCache_( AstRegion *this, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,ResetCache))( this, status ); +} +int astRegTrace_( AstRegion *this, int n, double *dist, double **ptr, int *status ){ + if ( !astOK ) return 0; + return (**astMEMBER(this,Region,RegTrace))( this, n, dist, ptr, status ); +} +void astGetRegionBounds_( AstRegion *this, double *lbnd, double *ubnd, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,GetRegionBounds))( this, lbnd, ubnd, status ); +} +void astGetRegionMesh_( AstRegion *this, int surface, int maxpoint, + int maxcoord, int *npoint, double *points, + int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,GetRegionMesh))( this, surface, maxpoint, maxcoord, + npoint, points, status ); +} +void astGetRegionPoints_( AstRegion *this, int maxpoint, int maxcoord, + int *npoint, double *points, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,GetRegionPoints))( this, maxpoint, maxcoord, + npoint, points, status ); +} +void astShowMesh_( AstRegion *this, int format, const char *ttl, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,ShowMesh))( this, format,ttl, status ); +} +void astGetRegionBounds2_( AstRegion *this, double *lbnd, double *ubnd, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,GetRegionBounds2))( this, lbnd, ubnd, status ); +} +void astRegOverlay_( AstRegion *this, AstRegion *that, int unc, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,RegOverlay))( this, that, unc, status ); +} +AstPointSet *astRegGrid_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegGrid))( this, status ); +} +AstPointSet *astRegMesh_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegMesh))( this, status ); +} +double *astRegCentre_( AstRegion *this, double *cen, double **ptr, int index, + int ifrm, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegCentre))( this, cen, ptr, index, ifrm, status ); +} +AstRegion *astGetNegation_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,GetNegation))( this, status ); +} +AstRegion *astGetUncFrm_( AstRegion *this, int ifrm, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,GetUncFrm))( this, ifrm, status ); +} +AstRegion *astGetDefUnc_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,GetDefUnc))( this, status ); +} +AstRegion *astGetUnc_( AstRegion *this, int def, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,GetUnc))( this, def, status ); +} +void astSetUnc_( AstRegion *this, AstRegion *unc, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,SetUnc))( this, unc, status ); +} +AstFrameSet *astGetRegFS_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,GetRegFS))( this, status ); +} +void astSetRegFS_( AstRegion *this, AstFrame *frm, int *status ){ + if ( !astOK ) return; + (**astMEMBER(this,Region,SetRegFS))( this, frm, status ); +} +AstPointSet *astRegBaseMesh_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegBaseMesh))( this, status ); +} +AstRegion **astRegSplit_( AstRegion *this, int *nlist, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegSplit))( this, nlist, status ); +} +AstPointSet *astRegBaseGrid_( AstRegion *this, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,RegBaseGrid))( this, status ); +} +AstPointSet *astBndBaseMesh_( AstRegion *this, double *lbnd, double *ubnd, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,BndBaseMesh))( this, lbnd, ubnd, status ); +} +AstPointSet *astBndMesh_( AstRegion *this, double *lbnd, double *ubnd, int *status ){ + if ( !astOK ) return NULL; + return (**astMEMBER(this,Region,BndMesh))( this, lbnd, ubnd, status ); +} + +#define MAKE_MASK_(X,Xtype) \ +int astMask##X##_( AstRegion *this, AstMapping *map, int inside, int ndim, \ + const int lbnd[], const int ubnd[], Xtype in[], \ + Xtype val, int *status ) { \ + if ( !astOK ) return 0; \ + return (**astMEMBER(this,Region,Mask##X))( this, map, inside, ndim, lbnd, \ + ubnd, in, val, status ); \ +} +#if HAVE_LONG_DOUBLE /* Not normally implemented */ +MAKE_MASK_(LD,long double) +#endif +MAKE_MASK_(D,double) +MAKE_MASK_(F,float) +MAKE_MASK_(L,long int) +MAKE_MASK_(UL,unsigned long int) +MAKE_MASK_(I,int) +MAKE_MASK_(UI,unsigned int) +MAKE_MASK_(S,short int) +MAKE_MASK_(US,unsigned short int) +MAKE_MASK_(B,signed char) +MAKE_MASK_(UB,unsigned char) +#undef MAKE_MASK_ + +/* 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. */ + +/* Special interface function implementations. */ +/* ------------------------------------------- */ + + +AstRegion *astMapRegionId_( AstRegion *this, AstMapping *map, AstFrame *frame, int *status ) { +/* +*++ +* Name: +c astMapRegion +f AST_MAPREGION + +* Purpose: +* Transform a Region into a new Frame using a given Mapping. + +* Type: +* Public virtual function. + +* Synopsis: +c #include "region.h" +c AstRegion *astMapRegion( AstRegion *this, AstMapping *map, +c AstFrame *frame ) +f RESULT = AST_MAPREGION( THIS, MAP, FRAME, STATUS ) + +* Class Membership: +* Region method. + +* Description: +* This function returns a pointer to a new Region which corresponds to +* supplied Region described by some other specified coordinate system. A +* Mapping is supplied which transforms positions between the old and new +* coordinate systems. The new Region may not be of the same class as +* the original region. + +* Parameters: +c this +f THIS = INTEGER (Given) +* Pointer to the Region. +c map +f MAP = INTEGER (Given) +* Pointer to a Mapping which transforms positions from the +* coordinate system represented by the supplied Region to the +* coordinate system specified by +c "frame". +f FRAME. +* The supplied Mapping should define both forward and inverse +* transformations, and these transformations should form a genuine +* inverse pair. That is, transforming a position using the forward +* transformation and then using the inverse transformation should +* produce the original input position. Some Mapping classes (such +* as PermMap, MathMap, SphMap) can result in Mappings for which this +* is not true. +c frame +f FRAME = INTEGER (Given) +* Pointer to a Frame describing the coordinate system in which +* the new Region is required. +f STATUS = INTEGER (Given and Returned) +f The global status. + +* Returned Value: +c astMapRegion() +f AST_MAPREGION = INTEGER +* A pointer to a new Region. This Region will represent the area +* within the coordinate system specified by +c "frame" +f FRAME +* which corresponds to the supplied Region. + +* Notes: +* - The uncertainty associated with the supplied Region is modified +* using the supplied Mapping. +* - 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: +* - The only difference between this public interface and the protected +* astMapRegion interface is that this implementation additionally +* simplifies the returned Region. The protected implementation does +* not do this since doing so can lead to infinite recursion because +* it is sometimes necessary for Simplify to call astMapRegion. + +*/ + +/* Local Variables: */ + AstRegion *new; /* Pointer to new Region */ + AstRegion *result; /* Pointer value to return */ + +/* Initialise. */ + result = NULL; + +/* Check the global error status. */ + if ( !astOK ) return result; + +/* Invoke the protected astMapRegion function. */ + new = astMapRegion( this, map, frame ); + +/* Simplify the resulting Region. */ + result = astSimplify( new ); + +/* Free resources. */ + new = astAnnul( new ); + +/* If not OK, annul the returned pointer. */ + if( !astOK ) result = astAnnul( result ); + +/* Return the result. */ + return result; +} + + + + + + + + + + + + |