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