1 /*
2 *class++
3 *  Name:
4 *     Circle
5 
6 *  Purpose:
7 *     A circular or spherical region within a Frame.
8 
9 *  Constructor Function:
10 c     astCircle
11 f     AST_CIRCLE
12 
13 *  Description:
14 *     The Circle class implements a Region which represents a circle or
15 *     sphere within a Frame.
16 
17 *  Inheritance:
18 *     The Circle class inherits from the Region class.
19 
20 *  Attributes:
21 *     The Circle class does not define any new attributes beyond
22 *     those which are applicable to all Regions.
23 
24 *  Functions:
25 c     In addition to those functions applicable to all Regions, the
26 c     following functions may also be applied to all Circles:
27 f     In addition to those routines applicable to all Regions, the
28 f     following routines may also be applied to all Circles:
29 *
30 c     - astCirclePars: Get the geometric parameters of the Circle
31 c     - AST_CIRCLEPARS: Get the geometric parameters of the Circle
32 
33 *  Copyright:
34 *     Copyright (C) 1997-2006 Council for the Central Laboratory of the
35 *     Research Councils
36 *     Copyright (C) 2009 Science & Technology Facilities Council.
37 *     All Rights Reserved.
38 
39 *  Licence:
40 *     This program is free software: you can redistribute it and/or
41 *     modify it under the terms of the GNU Lesser General Public
42 *     License as published by the Free Software Foundation, either
43 *     version 3 of the License, or (at your option) any later
44 *     version.
45 *
46 *     This program is distributed in the hope that it will be useful,
47 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
48 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
49 *     GNU Lesser General Public License for more details.
50 *
51 *     You should have received a copy of the GNU Lesser General
52 *     License along with this program.  If not, see
53 *     <http://www.gnu.org/licenses/>.
54 
55 *  Authors:
56 *     DSB: David S. Berry (Starlink)
57 
58 *  History:
59 *     31-AUG-2004 (DSB):
60 *        Original version.
61 *     4-NOV-2013 (DSB):
62 *        Modify RegPins so that it can handle uncertainty regions that straddle
63 *        a discontinuity. Previously, such uncertainty Regions could have a huge
64 *        bounding box resulting in matching region being far too big.
65 *class--
66 */
67 
68 /* Module Macros. */
69 /* ============== */
70 /* Set the name of the class we are implementing. This indicates to
71    the header files that define class interfaces that they should make
72    "protected" symbols available. */
73 #define astCLASS Circle
74 
75 /* Macros which return the maximum and minimum of two values. */
76 #define MAX(aa,bb) ((aa)>(bb)?(aa):(bb))
77 #define MIN(aa,bb) ((aa)<(bb)?(aa):(bb))
78 
79 /* Macro to check for equality of floating point values. We cannot
80    compare bad values directory because of the danger of floating point
81    exceptions, so bad values are dealt with explicitly. */
82 #define EQUAL(aa,bb) (((aa)==AST__BAD)?(((bb)==AST__BAD)?1:0):(((bb)==AST__BAD)?0:(fabs((aa)-(bb))<=1.0E9*MAX((fabs(aa)+fabs(bb))*DBL_EPSILON,DBL_MIN))))
83 
84 /* Include files. */
85 /* ============== */
86 /* Interface definitions. */
87 /* ---------------------- */
88 
89 #include "globals.h"             /* Thread-safe global data access */
90 #include "error.h"               /* Error reporting facilities */
91 #include "memory.h"              /* Memory allocation facilities */
92 #include "object.h"              /* Base Object class */
93 #include "pointset.h"            /* Sets of points/coordinates */
94 #include "region.h"              /* Coordinate regions (parent class) */
95 #include "channel.h"             /* I/O channels */
96 #include "box.h"                 /* Box Regions */
97 #include "wcsmap.h"              /* Definitons of AST__DPI etc */
98 #include "circle.h"              /* Interface definition for this class */
99 #include "ellipse.h"             /* Interface definition for ellipse class */
100 #include "mapping.h"             /* Position mappings */
101 #include "unitmap.h"             /* Unit Mapping */
102 
103 /* Error code definitions. */
104 /* ----------------------- */
105 #include "ast_err.h"             /* AST error codes */
106 
107 /* C header files. */
108 /* --------------- */
109 #include <float.h>
110 #include <math.h>
111 #include <stdarg.h>
112 #include <stddef.h>
113 #include <stdio.h>
114 #include <string.h>
115 
116 /* Module Variables. */
117 /* ================= */
118 
119 /* Address of this static variable is used as a unique identifier for
120    member of this class. */
121 static int class_check;
122 
123 /* Pointers to parent class methods which are extended by this class. */
124 static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
125 static AstMapping *(* parent_simplify)( AstMapping *, int * );
126 static void (* parent_setregfs)( AstRegion *, AstFrame *, int * );
127 static void (* parent_resetcache)( AstRegion *, int * );
128 
129 
130 #ifdef THREAD_SAFE
131 /* Define how to initialise thread-specific globals. */
132 #define GLOBAL_inits \
133    globals->Class_Init = 0;
134 
135 /* Create the function that initialises global data for this module. */
136 astMAKE_INITGLOBALS(Circle)
137 
138 /* Define macros for accessing each item of thread specific global data. */
139 #define class_init astGLOBAL(Circle,Class_Init)
140 #define class_vtab astGLOBAL(Circle,Class_Vtab)
141 
142 
143 #include <pthread.h>
144 
145 
146 #else
147 
148 
149 /* Define the class virtual function table and its initialisation flag
150    as static variables. */
151 static AstCircleVtab class_vtab;   /* Virtual function table */
152 static int class_init = 0;       /* Virtual function table initialised? */
153 
154 #endif
155 
156 /* External Interface Function Prototypes. */
157 /* ======================================= */
158 /* The following functions have public prototypes only (i.e. no
159    protected prototypes), so we must provide local prototypes for use
160    within this module. */
161 AstCircle *astCircleId_( void *, int, const double[], const double[], void *, const char *, ... );
162 
163 /* Prototypes for Private Member Functions. */
164 /* ======================================== */
165 static AstMapping *Simplify( AstMapping *, int * );
166 static AstPointSet *RegBaseMesh( AstRegion *, int * );
167 static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
168 static double *CircumPoint( AstFrame *, int, const double *, double, int * );
169 static double *RegCentre( AstRegion *this, double *, double **, int, int, int * );
170 static int RegPins( AstRegion *, AstPointSet *, AstRegion *, int **, int * );
171 static int RegTrace( AstRegion *, int, double *, double **, int * );
172 static void Cache( AstCircle *, int * );
173 static void CalcPars( AstFrame *, AstPointSet *, double *, double *, double *, int * );
174 static void CirclePars( AstCircle *, double *, double *, double *, int * );
175 static void Copy( const AstObject *, AstObject *, int * );
176 static void Delete( AstObject *, int * );
177 static void Dump( AstObject *, AstChannel *, int * );
178 static void RegBaseBox( AstRegion *this, double *, double *, int * );
179 static void ResetCache( AstRegion *this, int * );
180 static void SetRegFS( AstRegion *, AstFrame *, int * );
181 
182 /* Member functions. */
183 /* ================= */
184 
astBestCircle_(AstPointSet * mesh,double * cen,AstRegion * unc,int * status)185 AstRegion *astBestCircle_( AstPointSet *mesh, double *cen, AstRegion *unc, int *status ){
186 /*
187 *+
188 *  Name:
189 *     astBestCircle
190 
191 *  Purpose:
192 *     Find the best fitting Circle through a given mesh of points.
193 
194 *  Type:
195 *     Protected function.
196 
197 *  Synopsis:
198 *     #include "circle.h"
199 *     AstRegion *astBestCircle( AstPointSet *mesh, double *cen, AstRegion *unc )
200 
201 *  Class Membership:
202 *     Circle member function
203 
204 *  Description:
205 *     This function finds the best fitting Circle through a given mesh of
206 *     points.
207 
208 *  Parameters:
209 *     mesh
210 *        Pointer to a PointSet holding the mesh of points. They are
211 *        assumed to be in the Frame represented by "unc".
212 *     cen
213 *        Pointer to an array holding the coordinates of the new Circle
214 *        centre.
215 *     unc
216 *        A Region representing the uncertainty associated with each point
217 *        on the mesh.
218 
219 *  Returned Value:
220 *     Pointer to the best fitting Circle. It will inherit the positional
221 *     uncertainty and Frame represented by "unc".
222 
223 *  Notes:
224 *    - A NULL pointer is returned if an error has already occurred, or if
225 *    this function should fail for any reason.
226 
227 *-
228 */
229 
230 /* Local Variables: */
231    AstRegion *result;
232    double *p;
233    double rad;
234    double **ptr;
235    double d;
236    double s2r;
237    double p0;
238    int ic;
239    int ip;
240    int n;
241    int nc;
242    int np;
243 
244 /* Initialise */
245    result = NULL;
246 
247 /* Check the global error status. */
248    if ( !astOK ) return result;
249 
250 /* Get no. of points in the mesh, and the number of axis values per point. */
251    np = astGetNpoint( mesh );
252    nc = astGetNcoord( mesh );
253 
254 /* Get pointers to the axis values. */
255    ptr = astGetPoints( mesh );
256 
257 /* Check pointers can be used safely */
258    if( astOK ) {
259 
260 /* We find ther sum of the squared axis increments from the supplied
261    centre to each of the supplied points. Initialise the sum to zero. */
262       s2r = 0.0;
263       n = 0;
264 
265 /* Loop round all axes. */
266       for( ic = 0; ic < nc; ic++ ) {
267          p = ptr[ ic ];
268          p0 = cen[ ic ];
269 
270 /* Loop round all values for this axis. */
271          for( ip = 0; ip < np; ip++, p++ ) {
272             if( *p != AST__BAD ) {
273 
274 /* Increment the sums */
275                d = *p - p0;
276                s2r += d*d;
277                n++;
278 
279             }
280          }
281       }
282 
283 /* Find the RMS distance of the points from the supplied centre. This is
284    the radius of the best fitting circle. */
285       if( n > 0 ) {
286          rad = sqrt( nc*s2r/n );
287 
288 /* Create the returned Region. */
289          result = (AstRegion *) astCircle( unc, 1, cen, &rad, unc, "", status );
290       }
291    }
292 
293 /* Return NULL if anything went wrong. */
294    if( !astOK ) result = astAnnul( result );
295 
296 /* Return the result.*/
297    return result;
298 }
299 
Cache(AstCircle * this,int * status)300 static void Cache( AstCircle *this, int *status ){
301 /*
302 *  Name:
303 *     Cache
304 
305 *  Purpose:
306 *     Calculate intermediate values and cache them in the Circle structure.
307 
308 *  Type:
309 *     Private function.
310 
311 *  Synopsis:
312 *     #include "circle.h"
313 *     void Cache( AstCircle *this, int *status )
314 
315 *  Class Membership:
316 *     Circle member function
317 
318 *  Description:
319 *     This function uses the PointSet stored in the parent Region to calculate
320 *     some intermediate values which are useful in other methods. These
321 *     values are stored within the Circle structure.
322 
323 *  Parameters:
324 *     this
325 *        Pointer to the Circle.
326 *     status
327 *        Pointer to the inherited status variable.
328 
329 */
330 
331 /* Local Variables: */
332    AstFrame *frm;
333    double *centre;
334    double *lb;
335    double *ub;
336    double radius;
337    int i;
338    int nc;
339 
340 /* Check the global error status. */
341    if ( !astOK ) return;
342 
343 /* Do Nothing if the cached information is up to date. */
344    if( this->stale ) {
345 
346 /* Get a pointer to the base Frame and the number of base axes. */
347       frm = astGetFrame( ((AstRegion *) this)->frameset, AST__BASE );
348       nc = astGetNaxes( frm );
349 
350 /* Allocate memory to hold the centre coords. */
351       centre = astMalloc( sizeof( double )*astGetNaxes( frm ) );
352 
353 /* Get the radius and centre of the Circle in the base Frame, using the
354    centre and circumference positions stored in the parent Region structure. */
355       CalcPars( frm, ( (AstRegion *) this)->points, centre, &radius, NULL,
356                 status );
357 
358 /* Allocate memory to store the base frame bounding box. This is just
359    initialised here. It is set properly when the astRegBaseMesh
360    function is called. This box should not be used unless the "basemesh"
361    component of the parent Region structure is set to a non-null value. */
362       lb = (double *) astMalloc( sizeof( double )*(size_t) nc );
363       ub = (double *) astMalloc( sizeof( double )*(size_t) nc );
364 
365 /* Initialise the bounding box. */
366       for( i = 0; astOK && i < nc; i++ ) {
367          lb[ i ] = -DBL_MAX;
368          ub[ i ] = DBL_MAX;
369       }
370 
371 /* If everything went OK, store these values in the Circle structure. */
372       if( astOK ) {
373          this->radius = radius;
374 
375          astFree( this->centre );
376          this->centre = centre;
377          centre = NULL;
378 
379          astFree( this->lb );
380          this->lb = lb;
381          lb = NULL;
382 
383          astFree( this->ub );
384          this->ub = ub;
385          ub = NULL;
386       }
387 
388 /* Free resources */
389       frm = astAnnul( frm );
390       if( centre ) centre = astFree( centre );
391 
392 /* Indicate cached information is up to date. */
393       this->stale = 0;
394    }
395 }
396 
CalcPars(AstFrame * frm,AstPointSet * pset,double * centre,double * radius,double * p1,int * status)397 static void CalcPars( AstFrame *frm, AstPointSet *pset, double *centre,
398                       double *radius, double *p1, int *status ){
399 /*
400 *  Name:
401 *     CalcPars
402 
403 *  Purpose:
404 *     Calculate the geometric parameters of the supplied Circle.
405 
406 *  Type:
407 *     Private function.
408 
409 *  Synopsis:
410 *     #include "circle.h"
411 *     double *CalcPars( AstFrame *frm, AstPointSet *pset, double *centre,
412 *                       double *radius, double *p1, int *status )
413 
414 *  Class Membership:
415 *     Circle member function
416 
417 *  Description:
418 *     This function uses the supplied PointSet to calculate the geometric
419 *     parameters that describe the a crcle. These values are returned in
420 *     a newly allocated dynamic array.
421 
422 *  Parameters:
423 *     frm
424 *        Pointer to the Frame in which the circle is defined.
425 *     pset
426 *        Pointer to a PointSet. The first point should be the circle
427 *        centre, and the second point should be a point on the circle
428 *        circumference.
429 *     centre
430 *        An array in which to return the axis values at the circle centre.
431 *        The length of this array should be no less than the number of
432 *        axes in "frm".
433 *     radius
434 *        Pointer to a double in which to return the circle radius,
435 *        expressed as a geodesic distance in the supplied Frame.
436 *     p1
437 *        An array in which to return the coordinates of a point on the
438 *        circumference of the circle. The length of this array should be
439 *        no less than the number of axes in "frm". Can be NULL if the
440 *        circumference position is not needed.
441 *     status
442 *        Pointer to the inherited status variable.
443 
444 */
445 
446 /* Local Variables: */
447    double **ptr;
448    double *circum;
449    int i;
450    int nc;
451 
452 /* Check the global error status. */
453    if ( !astOK ) return;
454 
455 /* Get and the number of axes. */
456    nc = astGetNaxes( frm );
457 
458 /* Get pointers to the coordinate data in the supplied PointSet. */
459    ptr = astGetPoints( pset );
460 
461 /* If no p1 array was supplied, create a temporary work array to hold the
462    circumference position. */
463    if( !p1 ) {
464       circum = astMalloc( sizeof( double )*nc );
465    } else {
466       circum = p1;
467    }
468 
469 /* Check pointers can be used safely. */
470    if( ptr ) {
471 
472 /* Copy the two points in to the allocated memory. */
473       for( i = 0; i < nc; i++ ) {
474          centre[ i ] = ptr[ i ][ 0 ];
475          circum[ i ] = ptr[ i ][ 1 ];
476       }
477 
478 /* Return the geodesic distance between these two points as the radius. */
479       *radius = astDistance( frm, centre, circum );
480    }
481 
482 /* Free any work array. */
483    if( !p1 ) circum = astFree( circum );
484 }
485 
CirclePars(AstCircle * this,double * centre,double * radius,double * p1,int * status)486 static void CirclePars( AstCircle *this, double *centre, double *radius,
487                         double *p1, int *status ){
488 /*
489 *++
490 *  Name:
491 c     astCirclePars
492 f     AST_CIRCLEPARS
493 
494 *  Purpose:
495 *     Returns the geometric parameters of an Circle.
496 
497 *  Type:
498 *     Public virtual function.
499 
500 *  Synopsis:
501 c     #include "circle.h"
502 c     void astCirclePars( AstCircle *this, double *centre, double *radius,
503 c                         double *p1 )
504 f     CALL AST_CIRCLEPARS( THIS, CENTRE, RADIUS, P1, STATUS )
505 
506 *  Class Membership:
507 *     Region method.
508 
509 *  Description:
510 c     This function
511 f     This routine
512 *     returns the geometric parameters describing the supplied Circle.
513 
514 *  Parameters:
515 c     this
516 f     THIS = INTEGER (Given)
517 *        Pointer to the Region.
518 c     centre
519 f     CENTRE( * ) = DOUBLE PRECISION (Returned)
520 c        Pointer to an array
521 f        An array
522 *        in which to return the coordinates of the Circle centre.
523 *        The length of this array should be no less than the number of
524 *        axes in the associated coordinate system.
525 c     radius
526 f     RADIUS = DOUBLE PRECISION (Returned)
527 *        Returned holding the radius of the Circle, as an geodesic
528 *        distance in the associated coordinate system.
529 c     p1
530 f     P1( * ) = DOUBLE PRECISION (Returned)
531 c        Pointer to an array
532 f        An array
533 *        in which to return the coordinates of a point on the
534 *        circumference of the Circle. The length of this array should be
535 *        no less than the number of axes in the associated coordinate system.
536 c        A NULL pointer can be supplied if the circumference position is
537 c        not needed.
538 f     STATUS = INTEGER (Given and Returned)
539 f        The global status.
540 
541 *  Notes:
542 *     - If the coordinate system represented by the Circle has been
543 *     changed since it was first created, the returned parameters refer
544 *     to the new (changed) coordinate system, rather than the original
545 *     coordinate system. Note however that if the transformation from
546 *     original to new coordinate system is non-linear, the shape
547 *     represented by the supplied Circle object may not be an accurate
548 *     circle.
549 *--
550 */
551 
552 /* Local Variables: */
553    AstRegion *this_region;  /* Parent Region pointer */
554    AstFrame *frm;           /* Current Frame represented by the Circle */
555    AstPointSet *pset;       /* PointSet holding PointList axis values */
556 
557 /* Check the inherited status. */
558    if( !astOK ) return;
559 
560 /* Store a pointer to the parent region structure. */
561    this_region = (AstRegion *) this;
562 
563 /* Transform the base Frame axis values into the current Frame. */
564    pset = astTransform( this_region->frameset, this_region->points, 1, NULL );
565 
566 /* Get the Circle frame. */
567    frm = astGetFrame( this_region->frameset, AST__CURRENT );
568 
569 /* Calculate the required parameters. */
570    CalcPars( frm, pset, centre, radius, p1, status );
571 
572 /* Free resources */
573    frm = astAnnul( frm );
574    pset = astAnnul( pset );
575 }
576 
CircumPoint(AstFrame * frm,int nax,const double * centre,double radius,int * status)577 static double *CircumPoint( AstFrame *frm, int nax, const double *centre,
578                             double radius, int *status ){
579 /*
580 *  Name:
581 *     CircumPoint
582 
583 *  Purpose:
584 *     Find a point on the circumference of the circle.
585 
586 *  Type:
587 *     Private function.
588 
589 *  Synopsis:
590 *     #include "circle.h"
591 *     double *CircumPoint( AstFrame *frm, int nax, const double *centre,
592 *                          double radius, int *status )
593 
594 *  Class Membership:
595 *     Circle member function
596 
597 *  Description:
598 *     This function returns a dynamically allocated array containing the
599 *     axis values at a point on the circumference of the circle specified
600 *     by a given centre and radius. The returned point is the point at
601 *     which the circle crosses the first axis.
602 
603 *  Parameters:
604 *     frm
605 *        Pointer to the Frame in which the circle is defined.
606 *     nax
607 *        The number of axes in the Frame.
608 *     centre
609 *        An array holding the axis values at the circle centre.
610 *     radius
611 *        The circle radius, expressed as a geodesic distance in the
612 *        supplied Frame.
613 *     status
614 *        Pointer to the inherited status variable.
615 
616 *  Returned Value:
617 *     A pointer to a 1D array holding the axis values at the point where
618 *     the circle crosses the first frame axis. The length of this array
619 *     will equal the number of axes in the supsplied Frame. It should be
620 *     freed using astFree when no longer needed.
621 
622 */
623 
624 /* Local Variables: */
625    double *circum;
626    double *work;
627    int i;
628 
629 /* Check the global error status. */
630    if ( !astOK ) return NULL;
631 
632 /* Allocate the returned array. */
633    circum = astMalloc( sizeof( double)*(size_t) nax );
634 
635 /* Allocate work space */
636    work = astMalloc( sizeof( double)*(size_t) nax );
637 
638 /* Check pointers can be used safely. */
639    if( astOK ) {
640 
641 /* Find the coords of a point that is offset away from the centre
642    position along the first axis. We use the supplied radius value as a
643    convenient offset length, but the actual length used is not critical. */
644       for( i = 0; i < nax; i++ ) work[ i ] = centre[ i ];
645       work[ 0 ] = astAxOffset( frm, 1, work[ 0 ], radius );
646 
647 /* Offset away from the centre position, towards the position found
648    above, going the distance specified by the supplied radius. */
649       astOffset( frm, centre, work, radius, (double *) circum );
650    }
651 
652 /* Free resources. */
653    work = astFree( work );
654 
655 /* Return the result. */
656    return circum;
657 }
658 
astInitCircleVtab_(AstCircleVtab * vtab,const char * name,int * status)659 void astInitCircleVtab_(  AstCircleVtab *vtab, const char *name, int *status ) {
660 /*
661 *+
662 *  Name:
663 *     astInitCircleVtab
664 
665 *  Purpose:
666 *     Initialise a virtual function table for a Circle.
667 
668 *  Type:
669 *     Protected function.
670 
671 *  Synopsis:
672 *     #include "circle.h"
673 *     void astInitCircleVtab( AstCircleVtab *vtab, const char *name )
674 
675 *  Class Membership:
676 *     Circle vtab initialiser.
677 
678 *  Description:
679 *     This function initialises the component of a virtual function
680 *     table which is used by the Circle class.
681 
682 *  Parameters:
683 *     vtab
684 *        Pointer to the virtual function table. The components used by
685 *        all ancestral classes will be initialised if they have not already
686 *        been initialised.
687 *     name
688 *        Pointer to a constant null-terminated character string which contains
689 *        the name of the class to which the virtual function table belongs (it
690 *        is this pointer value that will subsequently be returned by the Object
691 *        astClass function).
692 *-
693 */
694 
695 /* Local Variables: */
696    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
697    AstMappingVtab *mapping;      /* Pointer to Mapping component of Vtab */
698    AstRegionVtab *region;        /* Pointer to Region component of Vtab */
699 
700 /* Check the local error status. */
701    if ( !astOK ) return;
702 
703 /* Get a pointer to the thread specific global data structure. */
704    astGET_GLOBALS(NULL);
705 
706 /* Initialize the component of the virtual function table used by the
707    parent class. */
708    astInitRegionVtab( (AstRegionVtab *) vtab, name );
709 
710 /* Store a unique "magic" value in the virtual function table. This
711    will be used (by astIsACircle) to determine if an object belongs
712    to this class.  We can conveniently use the address of the (static)
713    class_check variable to generate this unique value. */
714    vtab->id.check = &class_check;
715    vtab->id.parent = &(((AstRegionVtab *) vtab)->id);
716 
717 /* Initialise member function pointers. */
718 /* ------------------------------------ */
719 /* Store pointers to the member functions (implemented here) that provide
720    virtual methods for this class. */
721    vtab->CirclePars = CirclePars;
722 
723 /* Save the inherited pointers to methods that will be extended, and
724    replace them with pointers to the new member functions. */
725    mapping = (AstMappingVtab *) vtab;
726    region = (AstRegionVtab *) vtab;
727 
728    parent_transform = mapping->Transform;
729    mapping->Transform = Transform;
730 
731    parent_simplify = mapping->Simplify;
732    mapping->Simplify = Simplify;
733 
734    parent_setregfs = region->SetRegFS;
735    region->SetRegFS = SetRegFS;
736 
737    parent_resetcache = region->ResetCache;
738    region->ResetCache = ResetCache;
739 
740    region->RegPins = RegPins;
741    region->RegTrace = RegTrace;
742    region->RegBaseMesh = RegBaseMesh;
743    region->RegBaseBox = RegBaseBox;
744    region->RegCentre = RegCentre;
745 
746 /* Store replacement pointers for methods which will be over-ridden by
747    new member functions implemented here. */
748 
749 /* Declare the copy constructor, destructor and class dump
750    functions. */
751    astSetDelete( vtab, Delete );
752    astSetCopy( vtab, Copy );
753    astSetDump( vtab, Dump, "Circle", "Circular or spherical region" );
754 
755 /* If we have just initialised the vtab for the current class, indicate
756    that the vtab is now initialised, and store a pointer to the class
757    identifier in the base "object" level of the vtab. */
758    if( vtab == &class_vtab ) {
759       class_init = 1;
760       astSetVtabClassIdentifier( vtab, &(vtab->id) );
761    }
762 }
763 
RegBaseBox(AstRegion * this_region,double * lbnd,double * ubnd,int * status)764 static void RegBaseBox( AstRegion *this_region, double *lbnd, double *ubnd, int *status ){
765 /*
766 *  Name:
767 *     RegBaseBox
768 
769 *  Purpose:
770 *     Returns the bounding box of an un-negated Region in the base Frame of
771 *     the encapsulated FrameSet.
772 
773 *  Type:
774 *     Private function.
775 
776 *  Synopsis:
777 *     #include "circle.h"
778 *     void RegBaseBox( AstRegion *this, double *lbnd, double *ubnd, int *status )
779 
780 *  Class Membership:
781 *     Circle member function (over-rides the astRegBaseBox protected
782 *     method inherited from the Region class).
783 
784 *  Description:
785 *     This function returns the upper and lower axis bounds of a Region in
786 *     the base Frame of the encapsulated FrameSet, assuming the Region
787 *     has not been negated. That is, the value of the Negated attribute
788 *     is ignored.
789 
790 *  Parameters:
791 *     this
792 *        Pointer to the Region.
793 *     lbnd
794 *        Pointer to an array in which to return the lower axis bounds
795 *        covered by the Region in the base Frame of the encapsulated
796 *        FrameSet. It should have at least as many elements as there are
797 *        axes in the base Frame.
798 *     ubnd
799 *        Pointer to an array in which to return the upper axis bounds
800 *        covered by the Region in the base Frame of the encapsulated
801 *        FrameSet. It should have at least as many elements as there are
802 *        axes in the base Frame.
803 *     status
804 *        Pointer to the inherited status variable.
805 
806 */
807 
808 /* Local Variables: */
809    AstCircle *this;              /* Pointer to Circle structure */
810    AstFrame *frm;                /* Pointer to base Frame */
811    const char *class;            /* Pointer to class name */
812    int i;                        /* Axis index */
813    int nb;                       /* No. of axes in base Frame */
814 
815 /* Check the global error status. */
816    if ( !astOK ) return;
817 
818 /* Get a pointer to the Circle structure */
819    this = (AstCircle *) this_region;
820 
821 /* Ensure cached information is available. */
822    Cache( this, status );
823 
824 /* Get a pointer to the base Frame in the Region, and get the number of
825    axes. */
826    frm = astGetFrame( this_region->frameset, AST__BASE );
827    nb = astGetNaxes( frm );
828 
829 /* If the Frame is a simple Frame, we can assume plane geometry. */
830    class = astGetClass( frm );
831    if( class && !strcmp( class, "Frame" ) ) {
832       for( i = 0; i < nb; i++ ) {
833          lbnd[ i ] = ( this->centre )[ i ] - this->radius;
834          ubnd[ i ] = ( this->centre )[ i ] + this->radius;
835       }
836 
837 /* If the Frame is not a simple Frame we cannot assume plane geometry. */
838    } else {
839 
840 /* The bounding box of the mesh returned by astRegBaseMesh is used as the
841    bounding box of the Circle. These bounds are cached in the Circle
842    structure by astRegBaseMesh. Ensure astRegBaseMesh has been invoked,
843    so that it is safe to use the cached bounding box. */
844       if( !this_region->basemesh ) (void) astAnnul( astRegBaseMesh( this ) );
845 
846 /* Store the bounding box. */
847       for( i = 0; i < nb; i++ ) {
848          lbnd[ i ] = this->lb[ i ];
849          ubnd[ i ] = this->ub[ i ];
850       }
851    }
852 
853 /* Free resources. */
854    frm = astAnnul( frm );
855 }
856 
RegBaseMesh(AstRegion * this_region,int * status)857 static AstPointSet *RegBaseMesh( AstRegion *this_region, int *status ){
858 /*
859 *  Name:
860 *     RegBaseMesh
861 
862 *  Purpose:
863 *     Return a PointSet containing a mesh of points on the boundary of a
864 *     Region in its base Frame.
865 
866 *  Type:
867 *     Private function.
868 
869 *  Synopsis:
870 *     #include "circle.h"
871 *     AstPointSet *astRegBaseMesh( AstRegion *this, int *status )
872 
873 *  Class Membership:
874 *     Circle member function (over-rides the astRegBaseMesh protected
875 *     method inherited from the Region class).
876 
877 *  Description:
878 *     This function returns a PointSet containing a mesh of points on the
879 *     boundary of the Region. The points refer to the base Frame of
880 *     the encapsulated FrameSet.
881 
882 *  Parameters:
883 *     this
884 *        Pointer to the Region.
885 *     status
886 *        Pointer to the inherited status variable.
887 
888 *  Returned Value:
889 *     Pointer to the PointSet. The axis values in this PointSet will have
890 *     associated accuracies derived from the accuracies which were
891 *     supplied when the Region was created.
892 
893 *  Notes:
894 *    - A NULL pointer is returned if an error has already occurred, or if
895 *    this function should fail for any reason.
896 
897 */
898 
899 /* Local Constants: */
900 #define NP_EDGE 50                /* No. of points for determining geodesic */
901 
902 /* Local Variables: */
903    AstBox *box;                   /* Bounding box for this Circle */
904    AstCircle *this;               /* The Circle structure */
905    AstRegion *reg;                /* Copy of supplied Circle */
906    AstFrame *frm;                 /* Base Frame in encapsulated FrameSet */
907    AstPointSet *result;           /* Returned pointer */
908    double **ptr;                  /* Pointers to data */
909    double *p1;                    /* Pointer to array holding a single point */
910    double *p2;                    /* Pointer to array holding a single point */
911    double angle;                  /* Angular position of point */
912    double delta;                  /* Angular separation of points */
913    double dist;                   /* Offset along an axis */
914    double lbx;                    /* Lower x bound of mesh bounding box */
915    double lby;                    /* Lower y bound of mesh bounding box */
916    double p[ 2 ];                 /* Position in 2D Frame */
917    double ubx;                    /* Upper x bound of mesh bounding box */
918    double uby;                    /* Upper y bound of mesh bounding box */
919    int i;                         /* Point index */
920    int j;                         /* Axis index */
921    int naxes;                     /* No. of axes in base Frame */
922    int np;                        /* No. of points in returned PointSet */
923 
924 /* Initialise */
925    result= NULL;
926 
927 /* Check the global error status. */
928    if ( !astOK ) return result;
929 
930 /* If the Region structure contains a pointer to a PointSet holding
931    a previously created mesh, return it. */
932    if( this_region->basemesh ) {
933       result = astClone( this_region->basemesh );
934 
935 /* Otherwise, create a new mesh. */
936    } else {
937 
938 /* Get a pointer to the Circle structure. */
939       this = (AstCircle *) this_region;
940 
941 /* Get a pointer to the base Frame in the encapsulated FrameSet. */
942       frm = astGetFrame( this_region->frameset, AST__BASE );
943 
944 /* Get the number of axes in the base Frame */
945       naxes = astGetNaxes( frm );
946 
947 /* Get the requested number of points to put on the mesh. */
948       np = astGetMeshSize( this );
949 
950 /* Ensure cached information is available. */
951       Cache( (AstCircle *) this, status );
952 
953 /* First deal with 1-D "circles" (where we ignore MeshSize). */
954       if( naxes == 1 ) {
955 
956 /* The boundary of a 1-D circle consists of 2 points - the two extreme values.
957    Create a PointSet to hold 2 1-D values, and store the extreme values. */
958          result = astPointSet( 2, 1, "", status );
959          ptr = astGetPoints( result );
960          if( astOK ) {
961             ptr[ 0 ][ 0 ] = ( this->centre )[ 0 ] - this->radius;
962             ptr[ 0 ][ 1 ] = ( this->centre )[ 0 ] + this->radius;
963          }
964 
965 /* Store the bounding box in the Circle structure. */
966          this->lb[ 0 ] = ptr[ 0 ][ 0 ];
967          this->ub[ 0 ] = ptr[ 0 ][ 1 ];
968 
969 /* Now deal with 2-D circles. */
970       } else if( naxes == 2 ){
971 
972 /* Store the angular increment between points. */
973          delta = 2*AST__DPI/np;
974 
975 /* Create a suitable PointSet to hold the returned positions. */
976          result = astPointSet( np, 2, "", status );
977          ptr = astGetPoints( result );
978          if( astOK ) {
979 
980 /* Initialise the bounding box of the mesh points. */
981             lbx = DBL_MAX;
982             ubx = -DBL_MAX;
983             lby = DBL_MAX;
984             uby = -DBL_MAX;
985 
986 /* Loop round each point. */
987             angle = 0.0;
988             for( i = 0; i < np; i++ ) {
989 
990 /* Work out where the end of the radius vector at this angle is, and
991    store in the returned PointSet. */
992                astOffset2( frm, this->centre, angle, this->radius, p );
993                ptr[ 0 ][ i ] = p[ 0 ];
994                ptr[ 1 ][ i ] = p[ 1 ];
995 
996 /* Update the bounds of the mesh bounding box. The box is expressed in
997    terms of axis offsets from the centre, in order to avoid problems with
998    boxes that cross RA=0 or RA=12h */
999                if( p[ 0 ] != AST__BAD && p[ 1 ] != AST__BAD ){
1000                   dist =  astAxDistance( frm, 1, this->centre[ 0 ], p[ 0 ] );
1001                   if( dist < lbx ) {
1002                      lbx = dist;
1003                   } else if( dist > ubx ) {
1004                      ubx = dist;
1005                   }
1006                   dist =  astAxDistance( frm, 2, this->centre[ 1 ], p[ 1 ] );
1007                   if( dist < lby ) {
1008                      lby = dist;
1009                   } else if( dist > uby ) {
1010                      uby = dist;
1011                   }
1012                }
1013 
1014 /* Increment the angular position of the next mesh point. */
1015                angle += delta;
1016             }
1017 
1018 /* Store the bounding box in the Circle structure. */
1019             this->lb[ 0 ] = this->centre[ 0 ] + lbx;
1020             this->lb[ 1 ] = this->centre[ 1 ] + lby;
1021             this->ub[ 0 ] = this->centre[ 0 ] + ubx;
1022             this->ub[ 1 ] = this->centre[ 1 ] + uby;
1023          }
1024 
1025 /* Now deal with circles with more than 2 dimensions. Producing an evenly
1026    spread mesh of points over a sphere is a complex task (see e.g.
1027    http://www.eso.org/science/healpix/ ). This implementation does not
1028    attempt to produce a genuinely even spread. Instead it simply uses the
1029    mesh for the bounding box of the sphere, and projects each point on to
1030    the surface of the sphere. */
1031       } else {
1032 
1033 /* Allocate memory to hold an approximation of the circle bounding box. */
1034          p1 = astMalloc( sizeof( double )*(size_t) naxes );
1035          p2 = astMalloc( sizeof( double )*(size_t) naxes );
1036 
1037 /* Get an approximation to the bounding box, and initialise the real
1038    bounding box of the mesh points. */
1039          if( astOK ) {
1040             memcpy( p1, this->centre, sizeof( double )*(size_t) naxes );
1041             for( j = 0; j < naxes; j++ ) {
1042                p1[ j ] += this->radius;
1043                astOffset( frm, this->centre, p1, this->radius, p2 );
1044                p1[ j ] = this->centre[ j ];
1045                this->ub[ j ] = p2[ j ];
1046             }
1047          }
1048 
1049 /* Create a Box region which just encompasses the circle. */
1050          box = astBox( frm, 0, this->centre, this->ub, NULL, "", status );
1051 
1052 /* Get a mesh covering this box. */
1053          astSetMeshSize( box, np );
1054          result = astRegBaseMesh( box );
1055          ptr = astGetPoints( result );
1056          np = astGetNpoint( result  );
1057 
1058 /* Allocate memory for a single point */
1059          if( astOK ) {
1060 
1061 /* Initialise the real bounding box of the mesh points. */
1062             for( j = 0; j < naxes; j++ ) {
1063                this->lb[ j ] = DBL_MAX;
1064                this->ub[ j ] = -DBL_MAX;
1065             }
1066 
1067 /* Move each point in this mesh radially so that its distance from the centre
1068    equals the radius of this Circle. */
1069             for( i = 0; i < np; i++ ) {
1070                for( j = 0; j < naxes; j++ ) p1[ j ] = ptr[ j ][ i ];
1071                astOffset( frm, this->centre, p1, this->radius, p2 );
1072 
1073                for( j = 0; j < naxes; j++ ) {
1074                   ptr[ j ][ i ] = p2[ j ];
1075 
1076 /* Update the bounds of the mesh bounding box. */
1077                   if( p2[ j ] != AST__BAD ){
1078                      if( p2[ j ] < this->lb[ j ] ) {
1079                         this->lb[ j ] = p2[ j ];
1080                      } else if( p2[ j ] > this->ub[ j ] ) {
1081                         this->ub[ j ] = p2[ j ];
1082                      }
1083                   }
1084                }
1085             }
1086          }
1087 
1088 /* Same the returned pointer in the Region structure so that it does not
1089    need to be created again next time this function is called. */
1090          if( astOK && result ) this_region->basemesh = astClone( result );
1091 
1092 /* Free resources. */
1093          p1 = astFree( p1 );
1094          p2 = astFree( p2 );
1095          box = astAnnul( box );
1096       }
1097 
1098 /* Extend the bounding box if it contains any singularies. The astNormBox
1099    requires a Mapping which can be used to test points in the base Frame.
1100    Create a copy of the Circle and then set its FrameSet so that the current
1101    Frame in the copy is the same as the base Frame in the original. */
1102       reg = astCopy( this );
1103       astSetRegFS( reg, frm );
1104       astSetNegated( reg, 0 );
1105 
1106 /* Normalise this box. */
1107       astNormBox( frm, this->lb, this->ub, reg );
1108 
1109 /* Free resources. */
1110       reg = astAnnul( reg );
1111       frm = astAnnul( frm );
1112    }
1113 
1114 /* Annul the result if an error has occurred. */
1115    if( !astOK ) result = astAnnul( result );
1116 
1117 /* Return a pointer to the output PointSet. */
1118    return result;
1119 }
1120 
RegCentre(AstRegion * this_region,double * cen,double ** ptr,int index,int ifrm,int * status)1121 static double *RegCentre( AstRegion *this_region, double *cen, double **ptr,
1122                           int index, int ifrm, int *status ){
1123 /*
1124 *  Name:
1125 *     RegCentre
1126 
1127 *  Purpose:
1128 *     Re-centre a Region.
1129 
1130 *  Type:
1131 *     Private function.
1132 
1133 *  Synopsis:
1134 *     #include "circle.h"
1135 *     double *RegCentre( AstRegion *this, double *cen, double **ptr,
1136 *                        int index, int ifrm, int *status )
1137 
1138 *  Class Membership:
1139 *     Circle member function (over-rides the astRegCentre protected
1140 *     method inherited from the Region class).
1141 
1142 *  Description:
1143 *     This function shifts the centre of the supplied Region to a
1144 *     specified position, or returns the current centre of the Region.
1145 
1146 *  Parameters:
1147 *     this
1148 *        Pointer to the Region.
1149 *     cen
1150 *        Pointer to an array of axis values, giving the new centre.
1151 *        Supply a NULL value for this in order to use "ptr" and "index" to
1152 *        specify the new centre.
1153 *     ptr
1154 *        Pointer to an array of pointers, one for each axis in the Region.
1155 *        Each pointer locates an array of axis values. This is the format
1156 *        returned by the PointSet method astGetPoints. Only used if "cen"
1157 *        is NULL.
1158 *     index
1159 *        The index of the point within the arrays identified by "ptr" at
1160 *        which is stored the coords for the new centre position. Only used
1161 *        if "cen" is NULL.
1162 *     ifrm
1163 *        Should be AST__BASE or AST__CURRENT. Indicates whether the centre
1164 *        position is supplied and returned in the base or current Frame of
1165 *        the FrameSet encapsulated within "this".
1166 *     status
1167 *        Pointer to the inherited status variable.
1168 
1169 *  Returned Value:
1170 *     If both "cen" and "ptr" are NULL then a pointer to a newly
1171 *     allocated dynamic array is returned which contains the centre
1172 *     coords of the Region. This array should be freed using astFree when
1173 *     no longer needed. If either of "ptr" or "cen" is not NULL, then a
1174 *     NULL pointer is returned.
1175 
1176 *  Notes:
1177 *    - Some Region sub-classes do not have a centre. Such classes will report
1178 *    an AST__INTER error code if this method is called.
1179 */
1180 
1181 /* Local Variables: */
1182    AstFrame *frm;      /* Pointer to base Frame */
1183    AstCircle *this;    /* Pointer to Circle structure */
1184    double **rptr;      /* Data pointers for Region PointSet */
1185    double *bc;         /* Base Frame centre position */
1186    double *circum;     /* Base frame circumference position */
1187    double *result;     /* Returned pointer */
1188    double *tmp;        /* Temporary array pointer */
1189    double axval;       /* Axis value */
1190    int ic;             /* Coordinate index */
1191    int ncb;            /* Number of base frame coordinate values per point */
1192    int ncc;            /* Number of current frame coordinate values per point */
1193 
1194 /* Initialise */
1195    result = NULL;
1196 
1197 /* Check the local error status. */
1198    if ( !astOK ) return result;
1199 
1200 /* Get a pointer to the Circle structure. */
1201    this = (AstCircle *) this_region;
1202 
1203 /* Get the number of axis values per point in the base and current Frames. */
1204    ncb = astGetNin( this_region->frameset );
1205    ncc = astGetNout( this_region->frameset );
1206 
1207 /* Ensure cached information is available. */
1208    Cache( this, status );
1209 
1210 /* If the centre coords are to be returned, return either a copy of the
1211    base Frame centre coords, or transform the base Frame centre coords
1212    into the current Frame. */
1213    if( !ptr && !cen ) {
1214       if( ifrm == AST__CURRENT ) {
1215          result = astRegTranPoint( this_region, this->centre, 1, 1 );
1216       } else {
1217          result = astStore( NULL, this->centre, sizeof( double )*ncb );
1218       }
1219 
1220 /* Otherwise, we store the supplied new centre coords and return a NULL
1221    pointer. */
1222    } else {
1223 
1224 /* Get a pointer to the base Frame in the Region's FrameSet. */
1225       frm = astGetFrame( this_region->frameset, AST__BASE );
1226 
1227 /* Get a pointer to the axis values stored in the Region structure. */
1228       rptr = astGetPoints( this_region->points );
1229 
1230 /* Check pointers can be used safely */
1231       if( astOK ) {
1232 
1233 /* If the centre position was supplied in the current Frame, find the
1234    corresponding base Frame position... */
1235          if( ifrm == AST__CURRENT ) {
1236             if( cen ) {
1237                bc = astRegTranPoint( this_region, cen, 1, 0 );
1238             } else {
1239                tmp = astMalloc( sizeof( double)*(size_t)ncc );
1240                if( astOK ) {
1241                   for( ic = 0; ic < ncc; ic++ ) tmp[ ic ] = ptr[ ic ][ index ];
1242                }
1243                bc = astRegTranPoint( this_region, tmp, 1, 0 );
1244                tmp = astFree( tmp );
1245             }
1246 
1247 /* Replace any bad centre values with their current values. */
1248             for( ic = 0; ic < ncb; ic++ ) {
1249                if( bc[ ic ] ==  AST__BAD ) bc[ ic ] = this->centre[ ic ];
1250             }
1251 
1252 /* ... and change the coords in the parent Region structure and the cached
1253    coords in the Circle structure. */
1254             circum = CircumPoint( frm, ncb, bc, this->radius, status );
1255             if( circum ) {
1256                for( ic = 0; ic < ncb; ic++ ) {
1257                   rptr[ ic ][ 0 ] = bc[ ic ];
1258                   rptr[ ic ][ 1 ] = circum[ ic ];
1259                   this->centre[ ic ] = bc[ ic ];
1260                }
1261             }
1262 
1263 /* Free resources */
1264             circum = astFree( circum );
1265             bc = astFree( bc );
1266 
1267 /* If the centre position was supplied in the base Frame, use the
1268    supplied "cen" or "ptr" pointer directly to change the coords in the
1269    parent Region structure and the cached coords in the Circle structure. */
1270          } else {
1271             for( ic = 0; ic < ncb; ic++ ) {
1272                axval = cen ? cen[ ic ] : ptr[ ic ][ index ];
1273                if( axval != AST__BAD ) this->centre[ ic ] = axval;
1274             }
1275 
1276             circum = CircumPoint( frm, ncb, this->centre, this->radius,
1277                                   status );
1278             if( circum ) {
1279                for( ic = 0; ic < ncb; ic++ ) {
1280                   rptr[ ic ][ 0 ] = this->centre[ ic ];
1281                   rptr[ ic ][ 1 ] = circum[ ic ];
1282                }
1283                circum = astFree( circum );
1284             }
1285          }
1286       }
1287 
1288 /* Free resources */
1289       frm = astAnnul( frm );
1290    }
1291 
1292 /* Return the result. */
1293    return result;
1294 }
1295 
RegPins(AstRegion * this_region,AstPointSet * pset,AstRegion * unc,int ** mask,int * status)1296 static int RegPins( AstRegion *this_region, AstPointSet *pset, AstRegion *unc,
1297                     int **mask, int *status ){
1298 /*
1299 *  Name:
1300 *     RegPins
1301 
1302 *  Purpose:
1303 *     Check if a set of points fall on the boundary of a given Circle.
1304 
1305 *  Type:
1306 *     Private function.
1307 
1308 *  Synopsis:
1309 *     #include "circle.h"
1310 *     int RegPins( AstRegion *this, AstPointSet *pset, AstRegion *unc,
1311 *                  int **mask, int *status ){
1312 
1313 *  Class Membership:
1314 *     Circle member function (over-rides the astRegPins protected
1315 *     method inherited from the Region class).
1316 
1317 *  Description:
1318 *     This function returns a flag indicating if the supplied set of
1319 *     points all fall on the boundary of the given Circle.
1320 *
1321 *     Some tolerance is allowed, as specified by the uncertainty Region
1322 *     stored in the supplied Circle "this", and the supplied uncertainty
1323 *     Region "unc" which describes the uncertainty of the supplied points.
1324 
1325 *  Parameters:
1326 *     this
1327 *        Pointer to the Circle.
1328 *     pset
1329 *        Pointer to the PointSet. The points are assumed to refer to the
1330 *        base Frame of the FrameSet encapsulated by "this".
1331 *     unc
1332 *        Pointer to a Region representing the uncertainties in the points
1333 *        given by "pset". The Region is assumed to represent the base Frame
1334 *        of the FrameSet encapsulated by "this". Zero uncertainity is assumed
1335 *        if NULL is supplied.
1336 *     mask
1337 *        Pointer to location at which to return a pointer to a newly
1338 *        allocated dynamic array of ints. The number of elements in this
1339 *        array is equal to the value of the Npoint attribute of "pset".
1340 *        Each element in the returned array is set to 1 if the
1341 *        corresponding position in "pset" is on the boundary of the Region
1342 *        and is set to zero otherwise. A NULL value may be supplied
1343 *        in which case no array is created. If created, the array should
1344 *        be freed using astFree when no longer needed.
1345 *     status
1346 *        Pointer to the inherited status variable.
1347 
1348 *  Returned Value:
1349 *     Non-zero if the points all fall on the boundary of the given
1350 *     Region, to within the tolerance specified. Zero otherwise.
1351 
1352 */
1353 
1354 /* Local variables: */
1355    AstCircle *large_circle;     /* Circle slightly larger than "this" */
1356    AstCircle *small_circle;     /* Circle slightly smaller than "this" */
1357    AstCircle *this;             /* Pointer to the Circle structure. */
1358    AstFrame *frm;               /* Base Frame in supplied Circle */
1359    AstPointSet *ps1;            /* Points masked by larger Circle */
1360    AstPointSet *ps2;            /* Points masked by larger and smaller Circlees */
1361    AstRegion *tunc;             /* Uncertainity Region from "this" */
1362    double **ptr;                /* Pointer to axis values in "ps2" */
1363    double *lbnd_tunc;           /* Lower bounds of "this" uncertainty Region */
1364    double *lbnd_unc;            /* Lower bounds of supplied uncertainty Region */
1365    double *p;                   /* Pointer to next axis value */
1366    double *safe;                /* An interior point in "this" */
1367    double *ubnd_tunc;           /* Upper bounds of "this" uncertainty Region */
1368    double *ubnd_unc;            /* Upper bounds of supplied uncertainty Region */
1369    double drad;                 /* Radius increment corresponding to border width */
1370    double l1;                   /* Length of bounding box diagonal */
1371    double l2;                   /* Length of bounding box diagonal */
1372    double rad;                  /* Radius of Circle */
1373    int i;                       /* Axis index */
1374    int j;                       /* Point index */
1375    int nc;                      /* No. of axes in Circle base frame */
1376    int np;                      /* No. of supplied points */
1377    int result;                  /* Returned flag */
1378 
1379 /* Initialise */
1380    result = 0;
1381    if( mask ) *mask = NULL;
1382 
1383 /* Check the inherited status. */
1384    if( !astOK ) return result;
1385 
1386 /* Get a pointer to the Circle structure. */
1387    this = (AstCircle *) this_region;
1388 
1389 /* Get the number of base Frame axes in the Circle, and check the supplied
1390    PointSet has the same number of axis values per point. */
1391    frm = astGetFrame( this_region->frameset, AST__BASE );
1392    nc = astGetNaxes( frm );
1393    if( astGetNcoord( pset ) != nc && astOK ) {
1394       astError( AST__INTER, "astRegPins(%s): Illegal number of axis "
1395                 "values per point (%d) in the supplied PointSet - should be "
1396                 "%d (internal AST programming error).", status, astGetClass( this ),
1397                 astGetNcoord( pset ), nc );
1398    }
1399 
1400 /* Get the number of axes in the uncertainty Region and check it is the
1401    same as above. */
1402    if( unc && astGetNaxes( unc ) != nc && astOK ) {
1403       astError( AST__INTER, "astRegPins(%s): Illegal number of axes (%d) "
1404                 "in the supplied uncertainty Region - should be "
1405                 "%d (internal AST programming error).", status, astGetClass( this ),
1406                 astGetNaxes( unc ), nc );
1407    }
1408 
1409 /* Get the centre of the region in the base Frame. We use this as a "safe"
1410    interior point within the region. */
1411    safe = astRegCentre( this, NULL, NULL, 0, AST__BASE );
1412 
1413 /* We now find the maximum distance on each axis that a point can be from the
1414    boundary of the Circle for it still to be considered to be on the boundary.
1415    First get the Region which defines the uncertainty within the Circle being
1416    checked (in its base Frame), re-centre it on the interior point found
1417    above (to avoid problems if the uncertainty region straddles a
1418    discontinuity), and get its bounding box. */
1419    tunc = astGetUncFrm( this, AST__BASE );
1420    if( safe ) astRegCentre( tunc, safe, NULL, 0, AST__CURRENT );
1421    lbnd_tunc = astMalloc( sizeof( double )*(size_t) nc );
1422    ubnd_tunc = astMalloc( sizeof( double )*(size_t) nc );
1423    astGetRegionBounds( tunc, lbnd_tunc, ubnd_tunc );
1424 
1425 /* Find the geodesic length within the base Frame of "this" of the diagonal of
1426    the bounding box. */
1427    l1 = astDistance( frm, lbnd_tunc, ubnd_tunc );
1428 
1429 /* Also get the Region which defines the uncertainty of the supplied
1430    points and get its bounding box. First re-centre the uncertainty at the
1431    interior position to avoid problems from uncertainties that straddle a
1432    discontinuity. */
1433    if( unc ) {
1434       if( safe ) astRegCentre( unc, safe, NULL, 0, AST__CURRENT );
1435       lbnd_unc = astMalloc( sizeof( double )*(size_t) nc );
1436       ubnd_unc = astMalloc( sizeof( double )*(size_t) nc );
1437       astGetRegionBounds( unc, lbnd_unc, ubnd_unc );
1438 
1439 /* Find the geodesic length of the diagonal of this bounding box. */
1440       l2 = astDistance( frm, lbnd_unc, ubnd_unc );
1441 
1442 /* Use a zero sized box "unc" if no box was supplied. */
1443    } else {
1444       lbnd_unc = NULL;
1445       ubnd_unc = NULL;
1446       l2 = 0.0;
1447    }
1448 
1449 /* Ensure cached information is available. */
1450    Cache( this, status );
1451 
1452 /* The required border width is half of the total diagonal of the two bounding
1453    boxes. */
1454    if( astOK ) {
1455       drad = 0.5*( l1 + l2 );
1456 
1457 /* Create two new Circle, one of which is larger than "this" by the amount
1458    found above, and the other of which is smaller than "this" by the amount
1459    found above. */
1460       rad = this->radius + 0.5*drad;
1461       large_circle = astCircle( frm, 1, this->centre, &rad, NULL, "", status );
1462       rad = this->radius - 0.5*drad;
1463       small_circle = astCircle( frm, 1, this->centre, &rad, NULL, "", status );
1464 
1465 /* Negate the smaller region.*/
1466       astNegate( small_circle );
1467 
1468 /* Points are on the boundary of "this" if they are inside both the large
1469    Circle and the negated small Circle. First transform the supplied PointSet
1470    using the large Circle, then transform them using the negated smaller
1471    Circle. */
1472       ps1 = astTransform( large_circle, pset, 1, NULL );
1473       ps2 = astTransform( small_circle, ps1, 1, NULL );
1474 
1475 /* Get a point to the resulting axis values, and the number of axis
1476    values per axis. */
1477       ptr = astGetPoints( ps2 );
1478       np = astGetNpoint( ps2 );
1479 
1480 /* If a mask array is to be returned, create one. */
1481       if( mask ) {
1482          *mask = astMalloc( sizeof(int)*(size_t) np );
1483 
1484 /* Check all the resulting points, setting mask values for all of them. */
1485          if( astOK ) {
1486 
1487 /* Initialise the mask elements on the basis of the first axis values */
1488             result = 1;
1489             p = ptr[ 0 ];
1490             for( j = 0; j < np; j++ ) {
1491                if( *(p++) == AST__BAD ) {
1492                   result = 0;
1493                   (*mask)[ j ] = 0;
1494                } else {
1495                   (*mask)[ j ] = 1;
1496                }
1497             }
1498 
1499 /* Now check for bad values on other axes. */
1500             for( i = 1; i < nc; i++ ) {
1501                p = ptr[ i ];
1502                for( j = 0; j < np; j++ ) {
1503                   if( *(p++) == AST__BAD ) {
1504                      result = 0;
1505                      (*mask)[ j ] = 0;
1506                   }
1507                }
1508             }
1509          }
1510 
1511 /* If no output mask is to be made, we can break out of the check as soon
1512    as the first bad value is found. */
1513       } else if( astOK ) {
1514          result = 1;
1515          for( i = 0; i < nc && result; i++ ) {
1516             p = ptr[ i ];
1517             for( j = 0; j < np; j++ ) {
1518                if( *(p++) == AST__BAD ) {
1519                   result = 0;
1520                   break;
1521                }
1522             }
1523          }
1524       }
1525 
1526 /* Free resources. */
1527       large_circle = astAnnul( large_circle );
1528       small_circle = astAnnul( small_circle );
1529       ps1 = astAnnul( ps1 );
1530       ps2 = astAnnul( ps2 );
1531    }
1532 
1533    tunc = astAnnul( tunc );
1534    frm = astAnnul( frm );
1535    lbnd_tunc = astFree( lbnd_tunc );
1536    ubnd_tunc = astFree( ubnd_tunc );
1537    if( unc ) lbnd_unc = astFree( lbnd_unc );
1538    if( unc ) ubnd_unc = astFree( ubnd_unc );
1539    safe = astFree( safe );
1540 
1541 /* If an error has occurred, return zero. */
1542    if( !astOK ) {
1543       result = 0;
1544       if( mask ) *mask = astAnnul( *mask );
1545    }
1546 
1547 /* Return the result. */
1548    return result;
1549 }
1550 
RegTrace(AstRegion * this_region,int n,double * dist,double ** ptr,int * status)1551 static int RegTrace( AstRegion *this_region, int n, double *dist, double **ptr,
1552                      int *status ){
1553 /*
1554 *+
1555 *  Name:
1556 *     RegTrace
1557 
1558 *  Purpose:
1559 *     Return requested positions on the boundary of a 2D Region.
1560 
1561 *  Type:
1562 *     Private function.
1563 
1564 *  Synopsis:
1565 *     #include "circle.h"
1566 *     int astTraceRegion( AstRegion *this, int n, double *dist, double **ptr );
1567 
1568 *  Class Membership:
1569 *     Circle member function (overrides the astTraceRegion method
1570 *     inherited from the parent Region class).
1571 
1572 *  Description:
1573 *     This function returns positions on the boundary of the supplied
1574 *     Region, if possible. The required positions are indicated by a
1575 *     supplied list of scalar parameter values in the range zero to one.
1576 *     Zero corresponds to some arbitrary starting point on the boundary,
1577 *     and one corresponds to the end (which for a closed region will be
1578 *     the same place as the start).
1579 
1580 *  Parameters:
1581 *     this
1582 *        Pointer to the Region.
1583 *     n
1584 *        The number of positions to return. If this is zero, the function
1585 *        returns without action (but the returned function value still
1586 *        indicates if the method is supported or not).
1587 *     dist
1588 *        Pointer to an array of "n" scalar parameter values in the range
1589 *        0 to 1.0.
1590 *     ptr
1591 *        A pointer to an array of pointers. The number of elements in
1592 *        this array should equal tthe number of axes in the Frame spanned
1593 *        by the Region. Each element of the array should be a pointer to
1594 *        an array of "n" doubles, in which to return the "n" values for
1595 *        the corresponding axis. The contents of the arrays are unchanged
1596 *        if the supplied Region belongs to a class that does not
1597 *        implement this method.
1598 
1599 *  Returned Value:
1600 *     Non-zero if the astTraceRegion method is implemented by the class
1601 *     of Region supplied, and zero if not.
1602 
1603 *-
1604 */
1605 
1606 /* Local Variables; */
1607    AstCircle *this;
1608    AstFrame *frm;
1609    AstMapping *map;
1610    AstPointSet *bpset;
1611    AstPointSet *cpset;
1612    double **bptr;
1613    double angle;
1614    double p[ 2 ];
1615    int i;
1616    int ncur;
1617    int result;
1618 
1619 /* Initialise */
1620    result = 0;
1621 
1622 /* Check inherited status. */
1623    if( ! astOK ) return result;
1624 
1625 /* Get a pointer to the base Frame in the encapsulated FrameSet. */
1626    frm = astGetFrame( this_region->frameset, AST__BASE );
1627 
1628 /* Check it is 2-dimensional. */
1629    if( astGetNaxes( frm ) == 2 ) result = 1;
1630 
1631 /* Check we have some points to find. */
1632    if( result && n > 0 ) {
1633 
1634 /* Get a pointer to the Circle structure. */
1635       this = (AstCircle *) this_region;
1636 
1637 /* Ensure cached information is available. */
1638       Cache( this, status );
1639 
1640 /* We first determine the required positions in the base Frame of the
1641    Region, and then transform them into the current Frame. Get the
1642    base->current Mapping, and the number of current Frame axes. */
1643       map = astGetMapping( this_region->frameset, AST__BASE, AST__CURRENT );
1644 
1645 /* If it's a UnitMap we do not need to do the transformation, so put the
1646    base Frame positions directly into the supplied arrays. */
1647       if( astIsAUnitMap( map ) ) {
1648          bpset = NULL;
1649          bptr = ptr;
1650          ncur = 2;
1651 
1652 /* Otherwise, create a PointSet to hold the base Frame positions. */
1653       } else {
1654          bpset = astPointSet( n, 2, " ", status );
1655          bptr = astGetPoints( bpset );
1656          ncur = astGetNout( map );
1657       }
1658 
1659 /* Check the pointers can be used safely. */
1660       if( astOK ) {
1661 
1662 /* Loop round each point. Get the angle around the circle, and offset
1663    along that angle to find the point that is one radius away from the
1664    centre. Copy the results into the required arrays. */
1665          for( i = 0; i < n; i++ ) {
1666             angle = dist[ i ]*2*AST__DPI;
1667             astOffset2( frm, this->centre, angle, this->radius, p );
1668             bptr[ 0 ][ i ] = p[ 0 ];
1669             bptr[ 1 ][ i ] = p[ 1 ];
1670          }
1671 
1672       }
1673 
1674 /* If required, transform the base frame positions into the current
1675    Frame, storing them in the supplied array. Then free resources. */
1676       if( bpset ) {
1677          cpset = astPointSet( n, ncur, " ", status );
1678          astSetPoints( cpset, ptr );
1679 
1680          (void) astTransform( map, bpset, 1, cpset );
1681 
1682          cpset = astAnnul( cpset );
1683          bpset = astAnnul( bpset );
1684       }
1685 
1686 /* Free remaining resources. */
1687       map = astAnnul( map );
1688    }
1689    frm = astAnnul( frm );
1690 
1691 /* Return the result. */
1692    return result;
1693 }
1694 
ResetCache(AstRegion * this,int * status)1695 static void ResetCache( AstRegion *this, int *status ){
1696 /*
1697 *  Name:
1698 *     ResetCache
1699 
1700 *  Purpose:
1701 *     Clear cached information within the supplied Region.
1702 
1703 *  Type:
1704 *     Private function.
1705 
1706 *  Synopsis:
1707 *     #include "circle.h"
1708 *     void ResetCache( AstRegion *this, int *status )
1709 
1710 *  Class Membership:
1711 *     Region member function (overrides the astResetCache method
1712 *     inherited from the parent Region class).
1713 
1714 *  Description:
1715 *     This function clears cached information from the supplied Region
1716 *     structure.
1717 
1718 *  Parameters:
1719 *     this
1720 *        Pointer to the Region.
1721 *     status
1722 *        Pointer to the inherited status variable.
1723 */
1724    if( this ) {
1725       ( (AstCircle *) this )->stale = 1;
1726       (*parent_resetcache)( this, status );
1727    }
1728 }
1729 
SetRegFS(AstRegion * this_region,AstFrame * frm,int * status)1730 static void SetRegFS( AstRegion *this_region, AstFrame *frm, int *status ) {
1731 /*
1732 *  Name:
1733 *     SetRegFS
1734 
1735 *  Purpose:
1736 *     Stores a new FrameSet in a Region
1737 
1738 *  Type:
1739 *     Private function.
1740 
1741 *  Synopsis:
1742 *     #include "circle.h"
1743 *     void SetRegFS( AstRegion *this_region, AstFrame *frm, int *status )
1744 
1745 *  Class Membership:
1746 *     Circle method (over-rides the astSetRegFS method inherited from
1747 *     the Region class).
1748 
1749 *  Description:
1750 *     This function creates a new FrameSet and stores it in the supplied
1751 *     Region. The new FrameSet contains two copies of the supplied
1752 *     Frame, connected by a UnitMap.
1753 
1754 *  Parameters:
1755 *     this
1756 *        Pointer to the Region.
1757 *     frm
1758 *        The Frame to use.
1759 *     status
1760 *        Pointer to the inherited status variable.
1761 
1762 */
1763 
1764 
1765 /* Check the global error status. */
1766    if ( !astOK ) return;
1767 
1768 /* Invoke the parent method to store the FrameSet in the parent Region
1769    structure. */
1770    (* parent_setregfs)( this_region, frm, status );
1771 
1772 /* Re-calculate cached information. */
1773    astResetCache( this_region );
1774 }
1775 
Simplify(AstMapping * this_mapping,int * status)1776 static AstMapping *Simplify( AstMapping *this_mapping, int *status ) {
1777 /*
1778 *  Name:
1779 *     Simplify
1780 
1781 *  Purpose:
1782 *     Simplify the Mapping represented by a Region.
1783 
1784 *  Type:
1785 *     Private function.
1786 
1787 *  Synopsis:
1788 *     #include "circle.h"
1789 *     AstMapping *Simplify( AstMapping *this, int *status )
1790 
1791 *  Class Membership:
1792 *     Circle method (over-rides the astSimplify method inherited
1793 *     from the Region class).
1794 
1795 *  Description:
1796 *     This function invokes the parent Region Simplify method, and then
1797 *     performs any further region-specific simplification.
1798 *
1799 *     If the Mapping from base to current Frame is not a UnitMap, this
1800 *     will include attempting to fit a new Region to the boundary defined
1801 *     in the current Frame.
1802 
1803 *  Parameters:
1804 *     this
1805 *        Pointer to the original Region.
1806 *     status
1807 *        Pointer to the inherited status variable.
1808 
1809 *  Returned Value:
1810 *     A pointer to the simplified Region. A cloned pointer to the
1811 *     supplied Region will be returned if no simplication could be
1812 *     performed.
1813 
1814 *  Notes:
1815 *     - A NULL pointer value will be returned if this function is
1816 *     invoked with the AST error status set, or if it should fail for
1817 *     any reason.
1818 */
1819 
1820 /* Local Variables: */
1821    AstMapping *map;           /* Base -> current Mapping */
1822    AstMapping *result;        /* Result pointer to return */
1823    AstPointSet *mesh;         /* Mesh of current Frame positions */
1824    AstPointSet *ps2;          /* Circle PointSet in current Frame */
1825    AstRegion *new;            /* Pointer to simplified Region */
1826    AstRegion *newreg;         /* Equivalent circle or ellipse */
1827    AstRegion *this;           /* Pointer to supplied Region structure */
1828    AstRegion *unc;            /* Pointer to uncertainty Region */
1829    double **ptr2;             /* Pointer axis values in "ps2" */
1830    double *cen;               /* Pointer to array holding new centre coords */
1831    int ic;                    /* Axis index */
1832    int nc;                    /* No. of axis values per point */
1833    int ok;                    /* Was the new centre found OK? */
1834    int simpler;               /* Has some simplication taken place? */
1835 
1836 /* Initialise. */
1837    result = NULL;
1838 
1839 /* Check the global error status. */
1840    if ( !astOK ) return result;
1841 
1842 /* Get a pointer to the supplied Region structure. */
1843    this = (AstRegion *) this_mapping;
1844 
1845 /* Invoke the parent Simplify method inherited from the Region class. This
1846    will simplify the encapsulated FrameSet and uncertainty Region. */
1847    new = (AstRegion *) (*parent_simplify)( this_mapping, status );
1848 
1849 /* Note if any simplification took place. This is assumed to be the case
1850    if the pointer returned by the above call is different to the supplied
1851    pointer. */
1852    simpler = ( new != this );
1853 
1854 /* If the Mapping from base to current Frame is not a UnitMap, we attempt
1855    to simplify the Circle by re-defining it within its current Frame.
1856    Transforming the Circle from its base to its current Frame may result in
1857    the region no longer being a circle. We test this by transforming a set of
1858    bounds on the Circle boundary. */
1859    map = astGetMapping( new->frameset, AST__BASE, AST__CURRENT );
1860    if( !astIsAUnitMap( map ) ){
1861 
1862 /* Get a mesh of points covering the Circle in its current Frame. */
1863       mesh = astRegMesh( new );
1864 
1865 /* Get the Region describing the positional uncertainty within the Circle in
1866    its current Frame. */
1867       unc = astGetUncFrm( new, AST__CURRENT );
1868 
1869 /* Transform the PointSet holding the circle centre into the current
1870    Frame, and copy the axis values into a new array. */
1871       ps2 = astRegTransform( this, this->points, 1, NULL, NULL );
1872       nc = astGetNcoord( ps2 );
1873       cen = astMalloc( sizeof( double )*(size_t) nc );
1874       ptr2 = astGetPoints( ps2 );
1875       if( astOK ) {
1876 
1877          ok = 1;
1878          for( ic = 0; ic < nc; ic++ ) {
1879             cen[ ic ] = ptr2[ ic ][ 0 ];
1880             if( cen[ ic ] == AST__BAD ) ok = 0;
1881          }
1882 
1883 /* Find the best fitting Circle (defined in the current Frame) through these
1884    points */
1885          newreg = ok ? astBestCircle( mesh, cen, unc ) : NULL;
1886 
1887 /* See if all points within this mesh fall on the boundary of the best
1888    fitting Circle, to within the uncertainty of the Region. */
1889          if( newreg && astRegPins( newreg, mesh, NULL, NULL ) ) {
1890 
1891 /* If so, use the new Circle in place of the original. */
1892             (void) astAnnul( new );
1893             new = astClone( newreg );
1894 
1895 /* Otherwise, if the region is 2-d we see if an Ellipse can represent the
1896    mesh. */
1897          } else if( ok && nc == 2 ){
1898 
1899 /* Find the best fitting Ellipse (defined in the current Frame) through these
1900    points */
1901             if( newreg ) (void) astAnnul( newreg );
1902             newreg = astBestEllipse( mesh, cen, unc );
1903 
1904 /* See if all points within this mesh fall on the boundary of the best
1905    fitting Ellipse, to within the uncertainty of the Region. */
1906             if( newreg && astRegPins( newreg, mesh, NULL, NULL ) ) {
1907 
1908 /* If so, use the new Ellipse in place of the original. */
1909                (void) astAnnul( new );
1910                new = astClone( newreg );
1911                simpler = 1;
1912             }
1913          }
1914 
1915 /* Free resources. */
1916          if( newreg ) newreg = astAnnul( newreg );
1917       }
1918 
1919       ps2 = astAnnul( ps2 );
1920       cen = astFree( cen );
1921       mesh = astAnnul( mesh );
1922       unc = astAnnul( unc );
1923    }
1924    map = astAnnul( map );
1925 
1926 /* If any simplification could be performed, copy Region attributes from
1927    the supplied Region to the returned Region, and return a pointer to it.
1928    If the supplied Region had no uncertainty, ensure the returned Region
1929    has no uncertainty. Otherwise, return a clone of the supplied pointer. */
1930    if( simpler ){
1931       astRegOverlay( new, this, 1 );
1932       result = (AstMapping *) new;
1933 
1934    } else {
1935       new = astAnnul( new );
1936       result = astClone( this );
1937    }
1938 
1939 /* If an error occurred, annul the returned pointer. */
1940    if ( !astOK ) result = astAnnul( result );
1941 
1942 /* Return the result. */
1943    return result;
1944 }
1945 
Transform(AstMapping * this_mapping,AstPointSet * in,int forward,AstPointSet * out,int * status)1946 static AstPointSet *Transform( AstMapping *this_mapping, AstPointSet *in,
1947                                int forward, AstPointSet *out, int *status ) {
1948 /*
1949 *  Name:
1950 *     Transform
1951 
1952 *  Purpose:
1953 *     Apply a Circle to transform a set of points.
1954 
1955 *  Type:
1956 *     Private function.
1957 
1958 *  Synopsis:
1959 *     #include "circle.h"
1960 *     AstPointSet *Transform( AstMapping *this, AstPointSet *in,
1961 *                             int forward, AstPointSet *out, int *status )
1962 
1963 *  Class Membership:
1964 *     Circle member function (over-rides the astTransform protected
1965 *     method inherited from the Mapping class).
1966 
1967 *  Description:
1968 *     This function takes a Circle and a set of points encapsulated in a
1969 *     PointSet and transforms the points by setting axis values to
1970 *     AST__BAD for all points which are outside the region. Points inside
1971 *     the region are copied unchanged from input to output.
1972 
1973 *  Parameters:
1974 *     this
1975 *        Pointer to the Circle.
1976 *     in
1977 *        Pointer to the PointSet holding the input coordinate data.
1978 *     forward
1979 *        A non-zero value indicates that the forward coordinate transformation
1980 *        should be applied, while a zero value requests the inverse
1981 *        transformation.
1982 *     out
1983 *        Pointer to a PointSet which will hold the transformed (output)
1984 *        coordinate values. A NULL value may also be given, in which case a
1985 *        new PointSet will be created by this function.
1986 *     status
1987 *        Pointer to the inherited status variable.
1988 
1989 *  Returned Value:
1990 *     Pointer to the output (possibly new) PointSet.
1991 
1992 *  Notes:
1993 *     -  The forward and inverse transformations are identical for a
1994 *     Region.
1995 *     -  A null pointer will be returned if this function is invoked with the
1996 *     global error status set, or if it should fail for any reason.
1997 *     -  The number of coordinate values per point in the input PointSet must
1998 *     match the number of axes in the Frame represented by the Circle.
1999 *     -  If an output PointSet is supplied, it must have space for sufficient
2000 *     number of points and coordinate values per point to accommodate the
2001 *     result. Any excess space will be ignored.
2002 */
2003 
2004 /* Local Variables: */
2005    AstCircle *this;            /* Pointer to Circle */
2006    AstFrame *frm;                /* Pointer to base Frame in FrameSet */
2007    AstPointSet *pset_tmp;        /* Pointer to PointSet holding base Frame positions*/
2008    AstPointSet *result;          /* Pointer to output PointSet */
2009    double **ptr_out;             /* Pointer to output coordinate data */
2010    double **ptr_tmp;             /* Pointer to base Frame coordinate data */
2011    double *work;                 /* Pointer to array holding single base point */
2012    double d;                     /* Base-Frame distance from centre to point */
2013    int closed;                   /* Is the boundary part of the Region? */
2014    int coord;                    /* Zero-based index for coordinates */
2015    int inside;                   /* Is the point inside the Region? */
2016    int ncoord_out;               /* No. of coordinates per output point */
2017    int ncoord_tmp;               /* No. of coordinates per base Frame point */
2018    int neg;                      /* Has the Region been negated? */
2019    int npoint;                   /* No. of points */
2020    int point;                    /* Loop counter for points */
2021 
2022 /* Check the global error status. */
2023    if ( !astOK ) return NULL;
2024 
2025 /* Obtain a pointer to the Circle structure. */
2026    this = (AstCircle *) this_mapping;
2027 
2028 /* Apply the parent mapping using the stored pointer to the Transform member
2029    function inherited from the parent Region class. This function validates
2030    all arguments and generates an output PointSet if necessary,
2031    containing a copy of the input PointSet. */
2032    result = (*parent_transform)( this_mapping, in, forward, out, status );
2033 
2034 /* We will now extend the parent astTransform method by performing the
2035    calculations needed to generate the output coordinate values. */
2036 
2037 /* First use the encapsulated FrameSet to transform the supplied positions
2038    from the current Frame in the encapsulated FrameSet (the Frame
2039    represented by the Region), to the base Frame (the Frame in which the
2040    Region is defined). This call also returns a pointer to the base Frame
2041    of the encapsulated FrameSet. Note, the returned pointer may be a
2042    clone of the "in" pointer, and so we must be carefull not to modify the
2043    contents of the returned PointSet. */
2044    pset_tmp = astRegTransform( this, in, 0, NULL, &frm );
2045 
2046 /* Determine the numbers of points and coordinates per point from the base
2047    Frame PointSet and obtain pointers for accessing the base Frame and output
2048    coordinate values. */
2049    npoint = astGetNpoint( pset_tmp );
2050    ncoord_tmp = astGetNcoord( pset_tmp );
2051    ptr_tmp = astGetPoints( pset_tmp );
2052    ncoord_out = astGetNcoord( result );
2053    ptr_out = astGetPoints( result );
2054 
2055 /* Get work space for one base Frame position */
2056    work = astMalloc( sizeof( double )*(size_t) ncoord_tmp );
2057 
2058 /* See if the boundary is part of the Region. */
2059    closed = astGetClosed( this );
2060 
2061 /* See if the Region has been negated. */
2062    neg = astGetNegated( this );
2063 
2064 /* Perform coordinate arithmetic. */
2065 /* ------------------------------ */
2066    if ( astOK ) {
2067 
2068 /* Ensure cached information is available. */
2069       Cache( this, status );
2070 
2071 /* Loop round each point */
2072       for ( point = 0; point < npoint; point++ ) {
2073 
2074 /* Copy the base Frame position into a work array. */
2075          for ( coord = 0; coord < ncoord_tmp; coord++ ) {
2076             work[ coord ] = ptr_tmp[ coord ][ point ];
2077          }
2078 
2079 /* Find the geodesic distance from the centre of the Circle in the base
2080    Frame. */
2081          d = astDistance( frm, this->centre, work );
2082 
2083 /* Now consider whether this radius value puts the point in or out of the
2084    Circle. */
2085          if( d != AST__BAD ){
2086             if( neg ) {
2087                if( closed ) {
2088                   inside = ( d >= this->radius );
2089                } else {
2090                   inside = ( d > this->radius );
2091                }
2092             } else {
2093                if( closed ) {
2094                   inside = ( d <= this->radius );
2095                } else {
2096                   inside = ( d < this->radius );
2097                }
2098             }
2099          } else {
2100             inside = 0;
2101          }
2102 
2103 /* If the point is outside, store bad output values. */
2104          if( !inside ) {
2105             for ( coord = 0; coord < ncoord_out; coord++ ) {
2106                ptr_out[ coord ][ point ] = AST__BAD;
2107             }
2108          }
2109       }
2110    }
2111 
2112 /* Free resources */
2113    work = astFree( work );
2114    pset_tmp = astAnnul( pset_tmp );
2115    frm = astAnnul( frm );
2116 
2117 /* Annul the result if an error has occurred. */
2118    if( !astOK ) result = astAnnul( result );
2119 
2120 /* Return a pointer to the output PointSet. */
2121    return result;
2122 }
2123 
2124 /* Functions which access class attributes. */
2125 /* ---------------------------------------- */
2126 /* Implement member functions to access the attributes associated with
2127    this class using the macros defined for this purpose in the
2128    "object.h" file. For a description of each attribute, see the class
2129    interface (in the associated .h file). */
2130 
2131 /* Copy constructor. */
2132 /* ----------------- */
Copy(const AstObject * objin,AstObject * objout,int * status)2133 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
2134 /*
2135 *  Name:
2136 *     Copy
2137 
2138 *  Purpose:
2139 *     Copy constructor for Region objects.
2140 
2141 *  Type:
2142 *     Private function.
2143 
2144 *  Synopsis:
2145 *     void Copy( const AstObject *objin, AstObject *objout, int *status )
2146 
2147 *  Description:
2148 *     This function implements the copy constructor for Region objects.
2149 
2150 *  Parameters:
2151 *     objin
2152 *        Pointer to the object to be copied.
2153 *     objout
2154 *        Pointer to the object being constructed.
2155 *     status
2156 *        Pointer to the inherited status variable.
2157 
2158 *  Notes:
2159 *     -  This constructor makes a deep copy.
2160 */
2161 
2162 /* Local Variables: */
2163    AstCircle *in;             /* Pointer to input Circle */
2164    AstCircle *out;            /* Pointer to output Circle */
2165    int nax;                   /* Number of base Frame axes */
2166 
2167 /* Check the global error status. */
2168    if ( !astOK ) return;
2169 
2170 /* Obtain pointers to the input and output Circles. */
2171    in = (AstCircle *) objin;
2172    out = (AstCircle *) objout;
2173 
2174 /* For safety, first clear any references to the input memory from
2175    the output Circle. */
2176    out->centre = NULL;
2177    out->lb = NULL;
2178    out->ub = NULL;
2179 
2180 /* Copy dynamic memory contents */
2181    nax = astGetNin( ((AstRegion *) in)->frameset );
2182    out->centre = astStore( NULL, in->centre,
2183                            sizeof( double )*(size_t)nax );
2184    out->lb = astStore( NULL, in->lb, sizeof( double )*(size_t)nax );
2185    out->ub = astStore( NULL, in->ub, sizeof( double )*(size_t)nax );
2186 }
2187 
2188 
2189 /* Destructor. */
2190 /* ----------- */
Delete(AstObject * obj,int * status)2191 static void Delete( AstObject *obj, int *status ) {
2192 /*
2193 *  Name:
2194 *     Delete
2195 
2196 *  Purpose:
2197 *     Destructor for Circle objects.
2198 
2199 *  Type:
2200 *     Private function.
2201 
2202 *  Synopsis:
2203 *     void Delete( AstObject *obj, int *status )
2204 
2205 *  Description:
2206 *     This function implements the destructor for Circle objects.
2207 
2208 *  Parameters:
2209 *     obj
2210 *        Pointer to the object to be deleted.
2211 *     status
2212 *        Pointer to the inherited status variable.
2213 
2214 *  Notes:
2215 *     This function attempts to execute even if the global error status is
2216 *     set.
2217 */
2218 
2219 /* Local Variables: */
2220    AstCircle *this;                 /* Pointer to Circle */
2221 
2222 /* Obtain a pointer to the Circle structure. */
2223    this = (AstCircle *) obj;
2224 
2225 /* Annul all resources. */
2226    this->centre = astFree( this->centre );
2227    this->lb = astFree( this->lb );
2228    this->ub = astFree( this->ub );
2229 }
2230 
2231 /* Dump function. */
2232 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)2233 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
2234 /*
2235 *  Name:
2236 *     Dump
2237 
2238 *  Purpose:
2239 *     Dump function for Circle objects.
2240 
2241 *  Type:
2242 *     Private function.
2243 
2244 *  Synopsis:
2245 *     void Dump( AstObject *this, AstChannel *channel, int *status )
2246 
2247 *  Description:
2248 *     This function implements the Dump function which writes out data
2249 *     for the Circle class to an output Channel.
2250 
2251 *  Parameters:
2252 *     this
2253 *        Pointer to the Circle whose data are being written.
2254 *     channel
2255 *        Pointer to the Channel to which the data are being written.
2256 *     status
2257 *        Pointer to the inherited status variable.
2258 */
2259 
2260 /* Local Variables: */
2261    AstCircle *this;                 /* Pointer to the Circle structure */
2262 
2263 /* Check the global error status. */
2264    if ( !astOK ) return;
2265 
2266 /* Obtain a pointer to the Circle structure. */
2267    this = (AstCircle *) this_object;
2268 
2269 /* Write out values representing the instance variables for the
2270    Circle class.  Accompany these with appropriate comment strings,
2271    possibly depending on the values being written.*/
2272 
2273 /* In the case of attributes, we first use the appropriate (private)
2274    Test...  member function to see if they are set. If so, we then use
2275    the (private) Get... function to obtain the value to be written
2276    out.
2277 
2278    For attributes which are not set, we use the astGet... method to
2279    obtain the value instead. This will supply a default value
2280    (possibly provided by a derived class which over-rides this method)
2281    which is more useful to a human reader as it corresponds to the
2282    actual default attribute value.  Since "set" will be zero, these
2283    values are for information only and will not be read back. */
2284 
2285 /* There are no values to write, so return without further action. */
2286 }
2287 
2288 /* Standard class functions. */
2289 /* ========================= */
2290 /* Implement the astIsACircle and astCheckCircle functions using the macros
2291    defined for this purpose in the "object.h" header file. */
astMAKE_ISA(Circle,Region)2292 astMAKE_ISA(Circle,Region)
2293 astMAKE_CHECK(Circle)
2294 
2295 AstCircle *astCircle_( void *frame_void, int form, const double centre[],
2296                        const double point[], AstRegion *unc,
2297                        const char *options, int *status, ...) {
2298 /*
2299 *++
2300 *  Name:
2301 c     astCircle
2302 f     AST_CIRCLE
2303 
2304 *  Purpose:
2305 *     Create a Circle.
2306 
2307 *  Type:
2308 *     Public function.
2309 
2310 *  Synopsis:
2311 c     #include "circle.h"
2312 c     AstCircle *astCircle( AstFrame *frame, int form, const double centre[],
2313 c                           const double point[], AstRegion *unc,
2314 c                           const char *options, ... )
2315 f     RESULT = AST_CIRCLE( FRAME, FORM, CENTRE, POINT, UNC, OPTIONS, STATUS )
2316 
2317 *  Class Membership:
2318 *     Circle constructor.
2319 
2320 *  Description:
2321 *     This function creates a new Circle and optionally initialises its
2322 *     attributes.
2323 *
2324 *     A Circle is a Region which represents a circle or sphere within the
2325 *     supplied Frame.
2326 
2327 *  Parameters:
2328 c     frame
2329 f     FRAME = INTEGER (Given)
2330 *        A pointer to the Frame in which the region is defined. A deep
2331 *        copy is taken of the supplied Frame. This means that any
2332 *        subsequent changes made to the Frame using the supplied pointer
2333 *        will have no effect the Region.
2334 c     form
2335 f     FORM = INTEGER (Given)
2336 *        Indicates how the circle is described by the remaining parameters.
2337 *        A value of zero indicates that the circle is specified by a
2338 *        centre position and a position on the circumference. A value of one
2339 *        indicates that the circle is specified by a centre position and a
2340 *        scalar radius.
2341 c     centre
2342 f     CENTRE( * ) = DOUBLE PRECISION (Given)
2343 c        An array of double, with one element for each Frame axis
2344 f        An array with one element for each Frame axis
2345 *        (Naxes attribute) containing the coordinates at the centre of
2346 *        the circle or sphere.
2347 c     point
2348 f     POINT( * ) = DOUBLE PRECISION (Given)
2349 c        If "form"
2350 f        If FORM
2351 *        is zero, then this array should have one element for each Frame
2352 *        axis (Naxes attribute), and should be supplied holding the
2353 *        coordinates at a point on the circumference of the circle or sphere.
2354 c        If "form"
2355 f        If FORM
2356 *        is one, then this array should have one element only which should
2357 *        be supplied holding the scalar radius of the circle or sphere,
2358 *        as a geodesic distance within the Frame.
2359 c     unc
2360 f     UNC = INTEGER (Given)
2361 *        An optional pointer to an existing Region which specifies the
2362 *        uncertainties associated with the boundary of the Circle being created.
2363 *        The uncertainty in any point on the boundary of the Circle is found by
2364 *        shifting the supplied "uncertainty" Region so that it is centred at
2365 *        the boundary point being considered. The area covered by the
2366 *        shifted uncertainty Region then represents the uncertainty in the
2367 *        boundary position. The uncertainty is assumed to be the same for
2368 *        all points.
2369 *
2370 *        If supplied, the uncertainty Region must be of a class for which
2371 *        all instances are centro-symetric (e.g. Box, Circle, Ellipse, etc.)
2372 *        or be a Prism containing centro-symetric component Regions. A deep
2373 *        copy of the supplied Region will be taken, so subsequent changes to
2374 *        the uncertainty Region using the supplied pointer will have no
2375 *        effect on the created Circle. Alternatively,
2376 f        a null Object pointer (AST__NULL)
2377 c        a NULL Object pointer
2378 *        may be supplied, in which case a default uncertainty is used
2379 *        equivalent to a box 1.0E-6 of the size of the Circle being created.
2380 *
2381 *        The uncertainty Region has two uses: 1) when the
2382 c        astOverlap
2383 f        AST_OVERLAP
2384 *        function compares two Regions for equality the uncertainty
2385 *        Region is used to determine the tolerance on the comparison, and 2)
2386 *        when a Region is mapped into a different coordinate system and
2387 *        subsequently simplified (using
2388 c        astSimplify),
2389 f        AST_SIMPLIFY),
2390 *        the uncertainties are used to determine if the transformed boundary
2391 *        can be accurately represented by a specific shape of Region.
2392 c     options
2393 f     OPTIONS = CHARACTER * ( * ) (Given)
2394 c        Pointer to a null-terminated string containing an optional
2395 c        comma-separated list of attribute assignments to be used for
2396 c        initialising the new Circle. The syntax used is identical to
2397 c        that for the astSet function and may include "printf" format
2398 c        specifiers identified by "%" symbols in the normal way.
2399 f        A character string containing an optional comma-separated
2400 f        list of attribute assignments to be used for initialising the
2401 f        new Circle. The syntax used is identical to that for the
2402 f        AST_SET routine.
2403 c     ...
2404 c        If the "options" string contains "%" format specifiers, then
2405 c        an optional list of additional arguments may follow it in
2406 c        order to supply values to be substituted for these
2407 c        specifiers. The rules for supplying these are identical to
2408 c        those for the astSet function (and for the C "printf"
2409 c        function).
2410 f     STATUS = INTEGER (Given and Returned)
2411 f        The global status.
2412 
2413 *  Returned Value:
2414 c     astCircle()
2415 f     AST_CIRCLE = INTEGER
2416 *        A pointer to the new Circle.
2417 
2418 *  Notes:
2419 *     - A null Object pointer (AST__NULL) will be returned if this
2420 c     function is invoked with the AST error status set, or if it
2421 f     function is invoked with STATUS set to an error value, or if it
2422 *     should fail for any reason.
2423 *--
2424 */
2425 
2426 /* Local Variables: */
2427    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
2428    AstFrame *frame;              /* Pointer to Frame structure */
2429    AstCircle *new;               /* Pointer to new Circle */
2430    va_list args;                 /* Variable argument list */
2431 
2432 /* Get a pointer to the thread specific global data structure. */
2433    astGET_GLOBALS(NULL);
2434 
2435 /* Check the global status. */
2436    if ( !astOK ) return NULL;
2437 
2438 /* Obtain and validate a pointer to the supplied Frame structure. */
2439    frame = astCheckFrame( frame_void );
2440 
2441 /* Initialise the Circle, allocating memory and initialising the
2442    virtual function table as well if necessary. */
2443    new = astInitCircle( NULL, sizeof( AstCircle ), !class_init, &class_vtab,
2444                      "Circle", frame, form, centre, point, unc );
2445 
2446 /* If successful, note that the virtual function table has been
2447    initialised. */
2448    if ( astOK ) {
2449       class_init = 1;
2450 
2451 /* Obtain the variable argument list and pass it along with the options string
2452    to the astVSet method to initialise the new Circle's attributes. */
2453       va_start( args, status );
2454       astVSet( new, options, NULL, args );
2455       va_end( args );
2456 
2457 /* If an error occurred, clean up by deleting the new object. */
2458       if ( !astOK ) new = astDelete( new );
2459    }
2460 
2461 /* Return a pointer to the new Circle. */
2462    return new;
2463 }
2464 
astCircleId_(void * frame_void,int form,const double centre[],const double point[],void * unc_void,const char * options,...)2465 AstCircle *astCircleId_( void *frame_void, int form, const double centre[],
2466                          const double point[], void *unc_void,
2467                          const char *options, ... ) {
2468 /*
2469 *  Name:
2470 *     astCircleId_
2471 
2472 *  Purpose:
2473 *     Create a Circle.
2474 
2475 *  Type:
2476 *     Private function.
2477 
2478 *  Synopsis:
2479 *     #include "circle.h"
2480 *     AstCircle *astCircleId_( AstFrame *frame, int form, const double centre[],
2481 *                              const double point[], AstRegion *unc,
2482 *                              const char *options, ... )
2483 
2484 *  Class Membership:
2485 *     Circle constructor.
2486 
2487 *  Description:
2488 *     This function implements the external (public) interface to the
2489 *     astCircle constructor function. It returns an ID value (instead
2490 *     of a true C pointer) to external users, and must be provided
2491 *     because astCircle_ has a variable argument list which cannot be
2492 *     encapsulated in a macro (where this conversion would otherwise
2493 *     occur).
2494 *
2495 *     The variable argument list also prevents this function from
2496 *     invoking astCircle_ directly, so it must be a re-implementation
2497 *     of it in all respects, except for the final conversion of the
2498 *     result to an ID value.
2499 
2500 *  Parameters:
2501 *     As for astCircle_.
2502 
2503 *  Returned Value:
2504 *     The ID value associated with the new Circle.
2505 */
2506 
2507 /* Local Variables: */
2508    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
2509    AstFrame *frame;              /* Pointer to Frame structure */
2510    AstCircle *new;               /* Pointer to new Circle */
2511    AstRegion *unc;               /* Pointer to Region structure */
2512    va_list args;                 /* Variable argument list */
2513 
2514    int *status;                  /* Get a pointer to the thread specific global data structure. */
2515    astGET_GLOBALS(NULL);
2516 
2517 /* Pointer to inherited status value */
2518 
2519 /* Get a pointer to the inherited status value. */
2520    status = astGetStatusPtr;
2521 
2522 /* Check the global status. */
2523    if ( !astOK ) return NULL;
2524 
2525 /* Obtain a Frame pointer from the supplied ID and validate the
2526    pointer to ensure it identifies a valid Frame. */
2527    frame = astVerifyFrame( astMakePointer( frame_void ) );
2528 
2529 /* Obtain a Region pointer from the supplied "unc" ID and validate the
2530    pointer to ensure it identifies a valid Region . */
2531    unc = unc_void ? astCheckRegion( astMakePointer( unc_void ) ) : NULL;
2532 
2533 /* Initialise the Circle, allocating memory and initialising the
2534    virtual function table as well if necessary. */
2535    new = astInitCircle( NULL, sizeof( AstCircle ), !class_init, &class_vtab,
2536                         "Circle", frame, form, centre, point, unc );
2537 
2538 /* If successful, note that the virtual function table has been
2539    initialised. */
2540    if ( astOK ) {
2541       class_init = 1;
2542 
2543 /* Obtain the variable argument list and pass it along with the options string
2544    to the astVSet method to initialise the new Circle's attributes. */
2545       va_start( args, options );
2546       astVSet( new, options, NULL, args );
2547       va_end( args );
2548 
2549 /* If an error occurred, clean up by deleting the new object. */
2550       if ( !astOK ) new = astDelete( new );
2551    }
2552 
2553 /* Return an ID value for the new Circle. */
2554    return astMakeId( new );
2555 }
2556 
astInitCircle_(void * mem,size_t size,int init,AstCircleVtab * vtab,const char * name,AstFrame * frame,int form,const double centre[],const double point[],AstRegion * unc,int * status)2557 AstCircle *astInitCircle_( void *mem, size_t size, int init, AstCircleVtab *vtab,
2558                            const char *name, AstFrame *frame, int form,
2559                            const double centre[], const double point[],
2560                            AstRegion *unc, int *status ) {
2561 /*
2562 *+
2563 *  Name:
2564 *     astInitCircle
2565 
2566 *  Purpose:
2567 *     Initialise a Circle.
2568 
2569 *  Type:
2570 *     Protected function.
2571 
2572 *  Synopsis:
2573 *     #include "circle.h"
2574 *     AstCircle *astInitCircle_( void *mem, size_t size, int init, AstCircleVtab *vtab,
2575 *                                const char *name, AstFrame *frame, int form,
2576 *                                const double centre[], const double point[],
2577 *                                AstRegion *unc )
2578 
2579 *  Class Membership:
2580 *     Circle initialiser.
2581 
2582 *  Description:
2583 *     This function is provided for use by class implementations to initialise
2584 *     a new Circle object. It allocates memory (if necessary) to accommodate
2585 *     the Circle plus any additional data associated with the derived class.
2586 *     It then initialises a Circle structure at the start of this memory. If
2587 *     the "init" flag is set, it also initialises the contents of a virtual
2588 *     function table for a Circle at the start of the memory passed via the
2589 *     "vtab" parameter.
2590 
2591 *  Parameters:
2592 *     mem
2593 *        A pointer to the memory in which the Circle is to be initialised.
2594 *        This must be of sufficient size to accommodate the Circle data
2595 *        (sizeof(Circle)) plus any data used by the derived class. If a value
2596 *        of NULL is given, this function will allocate the memory itself using
2597 *        the "size" parameter to determine its size.
2598 *     size
2599 *        The amount of memory used by the Circle (plus derived class data).
2600 *        This will be used to allocate memory if a value of NULL is given for
2601 *        the "mem" parameter. This value is also stored in the Circle
2602 *        structure, so a valid value must be supplied even if not required for
2603 *        allocating memory.
2604 *     init
2605 *        A logical flag indicating if the Circle's virtual function table is
2606 *        to be initialised. If this value is non-zero, the virtual function
2607 *        table will be initialised by this function.
2608 *     vtab
2609 *        Pointer to the start of the virtual function table to be associated
2610 *        with the new Circle.
2611 *     name
2612 *        Pointer to a constant null-terminated character string which contains
2613 *        the name of the class to which the new object belongs (it is this
2614 *        pointer value that will subsequently be returned by the astGetClass
2615 *        method).
2616 *     frame
2617 *        A pointer to the Frame in which the region is defined.
2618 *     form
2619 *        Indicates how the "point" parameter should be interpreted.
2620 *        Should be either 0 or 1.
2621 *     centre
2622 *        An array of double, with one element for each Frame axis (Naxes
2623 *        attribute) containing the coordinates of the circle centre.
2624 *     point
2625 *        If "form" is zero, this should be an array of double, with one
2626 *        element for each Frame axis (Naxes attribute) containing the
2627 *        coordinates at any point on the circumference. If "form" is one,
2628 *        this should be the address of a double containing the scalar
2629 *        radius of the circle or sphere.
2630 *     unc
2631 *        A pointer to a Region which specifies the uncertainty in the
2632 *        supplied positions (all points on the boundary of the new Circle
2633 *        being initialised are assumed to have the same uncertainty). A NULL
2634 *        pointer can be supplied, in which case default uncertainties equal to
2635 *        1.0E-6 of the dimensions of the new Circle's bounding box are used.
2636 *        If an uncertainty Region is supplied, it must be either a Box, a
2637 *        Circle or an Ellipse, and its encapsulated Frame must be related
2638 *        to the Frame supplied for parameter "frame" (i.e. astConvert
2639 *        should be able to find a Mapping between them). Two positions
2640 *        the "frame" Frame are considered to be co-incident if their
2641 *        uncertainty Regions overlap. The centre of the supplied
2642 *        uncertainty Region is immaterial since it will be re-centred on the
2643 *        point being tested before use. A deep copy is taken of the supplied
2644 *        Region.
2645 
2646 *  Returned Value:
2647 *     A pointer to the new Circle.
2648 
2649 *  Notes:
2650 *     -  A null pointer will be returned if this function is invoked with the
2651 *     global error status set, or if it should fail for any reason.
2652 *-
2653 */
2654 
2655 /* Local Variables: */
2656    AstCircle *new;           /* Pointer to new Circle */
2657    AstPointSet *pset;        /* PointSet to pass to Region initialiser */
2658    const double *circum;     /* Pointer to circumference position */
2659    double **ptr;             /* Pointer to coords data in pset */
2660    int i;                    /* Axis index */
2661    int nc;                   /* No. of axes */
2662 
2663 /* Check the global status. */
2664    if ( !astOK ) return NULL;
2665 
2666 /* If necessary, initialise the virtual function table. */
2667    if ( init ) astInitCircleVtab( vtab, name );
2668 
2669 /* Initialise. */
2670    new = NULL;
2671 
2672 /* Check the supplied value for "form" is legal. */
2673    if( form != 0 && form != 1 && astOK ) {
2674       astError( AST__BADIN, "astInitCircle(%s): The value supplied for "
2675                 "parameter \"form\" (%d) is illegal - it should be 0 or 1 "
2676                 "(programming error).", status, name, form );
2677    }
2678 
2679 /* Get the number of axis values required for each position. */
2680    nc = astGetNaxes( frame );
2681 
2682 /* If the circle radius has been supplied, find a point on the circle
2683    circumference. */
2684    if( form == 1 ) {
2685       circum = CircumPoint( frame, nc, centre, *point, status );
2686 
2687 /* Otherwise, use the supplied circumference point. */
2688    } else {
2689       circum = point;
2690    }
2691 
2692 /* Create a PointSet to hold the centre position, and a point on the
2693    circumference, and get points to the data arrays. */
2694    pset = astPointSet( 2, nc, "", status );
2695    ptr = astGetPoints( pset );
2696 
2697 /* Copy the centre and circumference coordinates into the PointSet, checking
2698    that no bad values have been supplied. */
2699    for( i = 0; astOK && i < nc; i++ ) {
2700       if( centre[ i ] == AST__BAD ) {
2701          astError( AST__BADIN, "astInitCircle(%s): The value of axis %d is "
2702                    "undefined at the circle centre.", status, name, i + 1 );
2703       }
2704       if( astOK && circum[ i ] == AST__BAD ) {
2705          astError( AST__BADIN, "astInitCircle(%s): The value of axis %d is "
2706                    "undefined on the circumference of the circle.", status, name, i + 1 );
2707       }
2708       ptr[ i ][ 0 ] = centre[ i ];
2709       ptr[ i ][ 1 ] = circum[ i ];
2710    }
2711 
2712 /* Check pointers can be used safely. */
2713    if( astOK ) {
2714 
2715 /* Initialise a Region structure (the parent class) as the first component
2716    within the Circle structure, allocating memory if necessary. */
2717       new = (AstCircle *) astInitRegion( mem, size, 0, (AstRegionVtab *) vtab,
2718                                          name, frame, pset, unc );
2719 
2720       if ( astOK ) {
2721 
2722 /* Initialise the Circle data. */
2723 /* ------------------------ */
2724          new->stale = 1;
2725          new->centre = NULL;
2726          new->lb = NULL;
2727          new->ub = NULL;
2728          Cache( new, status );
2729 
2730 /* If an error occurred, clean up by deleting the new Circle. */
2731          if ( !astOK ) new = astDelete( new );
2732       }
2733    }
2734 
2735 /* Free resources. */
2736    pset = astAnnul( pset );
2737    if( form == 1 ) circum = astFree( (void *) circum );
2738 
2739 /* Return a pointer to the new Circle. */
2740    return new;
2741 }
2742 
astLoadCircle_(void * mem,size_t size,AstCircleVtab * vtab,const char * name,AstChannel * channel,int * status)2743 AstCircle *astLoadCircle_( void *mem, size_t size, AstCircleVtab *vtab,
2744                            const char *name, AstChannel *channel, int *status ) {
2745 /*
2746 *+
2747 *  Name:
2748 *     astLoadCircle
2749 
2750 *  Purpose:
2751 *     Load a Circle.
2752 
2753 *  Type:
2754 *     Protected function.
2755 
2756 *  Synopsis:
2757 *     #include "circle.h"
2758 *     AstCircle *astLoadCircle( void *mem, size_t size, AstCircleVtab *vtab,
2759 *                               const char *name, AstChannel *channel )
2760 
2761 *  Class Membership:
2762 *     Circle loader.
2763 
2764 *  Description:
2765 *     This function is provided to load a new Circle using data read
2766 *     from a Channel. It first loads the data used by the parent class
2767 *     (which allocates memory if necessary) and then initialises a
2768 *     Circle structure in this memory, using data read from the input
2769 *     Channel.
2770 *
2771 *     If the "init" flag is set, it also initialises the contents of a
2772 *     virtual function table for a Circle at the start of the memory
2773 *     passed via the "vtab" parameter.
2774 
2775 *  Parameters:
2776 *     mem
2777 *        A pointer to the memory into which the Circle is to be
2778 *        loaded.  This must be of sufficient size to accommodate the
2779 *        Circle data (sizeof(Circle)) plus any data used by derived
2780 *        classes. If a value of NULL is given, this function will
2781 *        allocate the memory itself using the "size" parameter to
2782 *        determine its size.
2783 *     size
2784 *        The amount of memory used by the Circle (plus derived class
2785 *        data).  This will be used to allocate memory if a value of
2786 *        NULL is given for the "mem" parameter. This value is also
2787 *        stored in the Circle structure, so a valid value must be
2788 *        supplied even if not required for allocating memory.
2789 *
2790 *        If the "vtab" parameter is NULL, the "size" value is ignored
2791 *        and sizeof(AstCircle) is used instead.
2792 *     vtab
2793 *        Pointer to the start of the virtual function table to be
2794 *        associated with the new Circle. If this is NULL, a pointer
2795 *        to the (static) virtual function table for the Circle class
2796 *        is used instead.
2797 *     name
2798 *        Pointer to a constant null-terminated character string which
2799 *        contains the name of the class to which the new object
2800 *        belongs (it is this pointer value that will subsequently be
2801 *        returned by the astGetClass method).
2802 *
2803 *        If the "vtab" parameter is NULL, the "name" value is ignored
2804 *        and a pointer to the string "Circle" is used instead.
2805 
2806 *  Returned Value:
2807 *     A pointer to the new Circle.
2808 
2809 *  Notes:
2810 *     - A null pointer will be returned if this function is invoked
2811 *     with the global error status set, or if it should fail for any
2812 *     reason.
2813 *-
2814 */
2815 
2816 /* Local Variables: */
2817    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
2818    AstCircle *new;              /* Pointer to the new Circle */
2819 
2820 /* Initialise. */
2821    new = NULL;
2822 
2823 /* Check the global error status. */
2824    if ( !astOK ) return new;
2825 
2826 /* Get a pointer to the thread specific global data structure. */
2827    astGET_GLOBALS(channel);
2828 
2829 /* If a NULL virtual function table has been supplied, then this is
2830    the first loader to be invoked for this Circle. In this case the
2831    Circle belongs to this class, so supply appropriate values to be
2832    passed to the parent class loader (and its parent, etc.). */
2833    if ( !vtab ) {
2834       size = sizeof( AstCircle );
2835       vtab = &class_vtab;
2836       name = "Circle";
2837 
2838 /* If required, initialise the virtual function table for this class. */
2839       if ( !class_init ) {
2840          astInitCircleVtab( vtab, name );
2841          class_init = 1;
2842       }
2843    }
2844 
2845 /* Invoke the parent class loader to load data for all the ancestral
2846    classes of the current one, returning a pointer to the resulting
2847    partly-built Circle. */
2848    new = astLoadRegion( mem, size, (AstRegionVtab *) vtab, name,
2849                         channel );
2850 
2851    if ( astOK ) {
2852 
2853 /* Read input data. */
2854 /* ================ */
2855 /* Request the input Channel to read all the input data appropriate to
2856    this class into the internal "values list". */
2857       astReadClassData( channel, "Circle" );
2858 
2859 /* Now read each individual data item from this list and use it to
2860    initialise the appropriate instance variable(s) for this class. */
2861 
2862 /* In the case of attributes, we first read the "raw" input value,
2863    supplying the "unset" value as the default. If a "set" value is
2864    obtained, we then use the appropriate (private) Set... member
2865    function to validate and set the value properly. */
2866 
2867 /* There are no values to read. */
2868 /* ---------------------------- */
2869 
2870 /* Cache intermediate results in the Circle structure */
2871       new->centre = NULL;
2872       new->lb = NULL;
2873       new->ub = NULL;
2874       new->stale = 1;
2875       Cache( new, status );
2876 
2877 /* If an error occurred, clean up by deleting the new Circle. */
2878       if ( !astOK ) new = astDelete( new );
2879    }
2880 
2881 /* Return the new Circle pointer. */
2882    return new;
2883 }
2884 
2885 /* Virtual function interfaces. */
2886 /* ============================ */
2887 /* These provide the external interface to the virtual functions defined by
2888    this class. Each simply checks the global error status and then locates and
2889    executes the appropriate member function, using the function pointer stored
2890    in the object's virtual function table (this pointer is located using the
2891    astMEMBER macro defined in "object.h").
2892 
2893    Note that the member function may not be the one defined here, as it may
2894    have been over-ridden by a derived class. However, it should still have the
2895    same interface. */
2896 
2897 
astCirclePars_(AstCircle * this,double * centre,double * radius,double * p1,int * status)2898 void astCirclePars_( AstCircle *this, double *centre, double *radius,
2899                      double *p1, int *status ){
2900    if ( !astOK ) return;
2901    (**astMEMBER(this,Circle,CirclePars))( this, centre, radius,
2902                                           p1, status );
2903 }
2904 
2905 
2906 
2907 
2908 
2909 
2910