1 /*
2 *class++
3 * Name:
4 * SelectorMap
5
6 * Purpose:
7 * A Mapping that locates positions within one of a set of alternate
8 * Regions.
9
10 * Constructor Function:
11 c astSelectorMap
12 f AST_SELECTORMAP
13
14 * Description:
15 * A SelectorMap is a Mapping that identifies which Region contains
16 * a given input position.
17 *
18 * A SelectorMap encapsulates a number of Regions that all have the same
19 * number of axes and represent the same coordinate Frame. The number of
20 * inputs (Nin attribute) of the SelectorMap equals the number of axes
21 * spanned by one of the encapsulated Region. All SelectorMaps have only
22 * a single output. SelectorMaps do not define an inverse transformation.
23 *
24 * For each input position, the forward transformation of a SelectorMap
25 * searches through the encapsulated Regions (in the order supplied when
26 * the SelectorMap was created) until a Region is found which contains
27 * the input position. The index associated with this Region is
28 * returned as the SelectorMap output value (the index value is the
29 * position of the Region within the list of Regions supplied when the
30 * SelectorMap was created, starting at 1 for the first Region). If an
31 * input position is not contained within any Region, a value of zero is
32 * returned by the forward transformation.
33 *
34 * If a compound Mapping contains a SelectorMap in series with its own
35 * inverse, the combination of the two adjacent SelectorMaps will be
36 * replaced by a UnitMap when the compound Mapping is simplified using
37 c astSimplify.
38 f AST_SIMPLIFY.
39 *
40 * In practice, SelectorMaps are often used in conjunction with SwitchMaps.
41
42 * Inheritance:
43 * The SelectorMap class inherits from the Mapping class.
44
45 * Attributes:
46 * The SelectorMap class does not define any new attributes beyond those
47 * which are applicable to all Mappings.
48
49 * Functions:
50 c The SelectorMap class does not define any new functions beyond those
51 f The SelectorMap class does not define any new routines beyond those
52 * which are applicable to all Mappings.
53
54 * Copyright:
55 * Copyright (C) 1997-2006 Council for the Central Laboratory of the
56 * Research Councils
57
58 * Licence:
59 * This program is free software: you can redistribute it and/or
60 * modify it under the terms of the GNU Lesser General Public
61 * License as published by the Free Software Foundation, either
62 * version 3 of the License, or (at your option) any later
63 * version.
64 *
65 * This program is distributed in the hope that it will be useful,
66 * but WITHOUT ANY WARRANTY; without even the implied warranty of
67 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68 * GNU Lesser General Public License for more details.
69 *
70 * You should have received a copy of the GNU Lesser General
71 * License along with this program. If not, see
72 * <http://www.gnu.org/licenses/>.
73
74 * Authors:
75 * DSB: David S. Berry (Starlink)
76
77 * History:
78 * 15-MAR-2006 (DSB):
79 * Original version.
80 * 18-MAY-2006 (DSB):
81 * - Change logic for detecting interior points in function Transform.
82 * - Added BADVAL to contructor argument list.
83 *class--
84 */
85
86 /* Module Macros. */
87 /* ============== */
88 /* Set the name of the class we are implementing. This indicates to
89 the header files that define class interfaces that they should make
90 "protected" symbols available. */
91 #define astCLASS SelectorMap
92
93 /* Include files. */
94 /* ============== */
95 /* Interface definitions. */
96 /* ---------------------- */
97
98 #include "globals.h" /* Thread-safe global data access */
99 #include "error.h" /* Error reporting facilities */
100 #include "memory.h" /* Memory allocation facilities */
101 #include "object.h" /* Base Object class */
102 #include "pointset.h" /* Sets of points/coordinates */
103 #include "mapping.h" /* Coordinate Mappings (parent class) */
104 #include "unitmap.h" /* Unit Mappings */
105 #include "channel.h" /* I/O channels */
106 #include "selectormap.h" /* Interface definition for this class */
107
108 /* Error code definitions. */
109 /* ----------------------- */
110 #include "ast_err.h" /* AST error codes */
111
112 /* C header files. */
113 /* --------------- */
114 #include <stdarg.h>
115 #include <stddef.h>
116 #include <string.h>
117 #include <stdio.h>
118
119 /* Module Variables. */
120 /* ================= */
121
122 /* Address of this static variable is used as a unique identifier for
123 member of this class. */
124 static int class_check;
125
126 /* Pointers to parent class methods which are extended by this class. */
127 static int (* parent_getobjsize)( AstObject *, int * );
128 static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
129
130 #if defined(THREAD_SAFE)
131 static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * );
132 #endif
133
134
135 #ifdef THREAD_SAFE
136 /* Define how to initialise thread-specific globals. */
137 #define GLOBAL_inits \
138 globals->Class_Init = 0;
139
140 /* Create the function that initialises global data for this module. */
141 astMAKE_INITGLOBALS(SelectorMap)
142
143 /* Define macros for accessing each item of thread specific global data. */
144 #define class_init astGLOBAL(SelectorMap,Class_Init)
145 #define class_vtab astGLOBAL(SelectorMap,Class_Vtab)
146
147
148 #include <pthread.h>
149
150
151 #else
152
153
154 /* Define the class virtual function table and its initialisation flag
155 as static variables. */
156 static AstSelectorMapVtab class_vtab; /* Virtual function table */
157 static int class_init = 0; /* Virtual function table initialised? */
158
159 #endif
160
161 /* External Interface Function Prototypes. */
162 /* ======================================= */
163 /* The following functions have public prototypes only (i.e. no
164 protected prototypes), so we must provide local prototypes for use
165 within this module. */
166 AstSelectorMap *astSelectorMapId_( int, void **, double, const char *, ... );
167
168 /* Prototypes for Private Member Functions. */
169 /* ======================================== */
170 static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
171 static int Equal( AstObject *, AstObject *, int * );
172 static int GetObjSize( AstObject *, int * );
173 static int MapMerge( AstMapping *, int, int, int *, AstMapping ***, int **, int * );
174 static void Copy( const AstObject *, AstObject *, int * );
175 static void Delete( AstObject *, int * );
176 static void Dump( AstObject *, AstChannel *, int * );
177
178 #if defined(THREAD_SAFE)
179 static int ManageLock( AstObject *, int, int, AstObject **, int * );
180 #endif
181
182 /* Member functions. */
183 /* ================= */
Equal(AstObject * this_object,AstObject * that_object,int * status)184 static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
185 /*
186 * Name:
187 * Equal
188
189 * Purpose:
190 * Test if two SelectorMaps are equivalent.
191
192 * Type:
193 * Private function.
194
195 * Synopsis:
196 * #include "selectormap.h"
197 * int Equal( AstObject *this, AstObject *that, int *status )
198
199 * Class Membership:
200 * SelectorMap member function (over-rides the astEqual protected
201 * method inherited from the astMapping class).
202
203 * Description:
204 * This function returns a boolean result (0 or 1) to indicate whether
205 * two SelectorMaps are equivalent.
206
207 * Parameters:
208 * this
209 * Pointer to the first Object (a SelectorMap).
210 * that
211 * Pointer to the second Object.
212 * status
213 * Pointer to the inherited status variable.
214
215 * Returned Value:
216 * One if the SelectorMaps are equivalent, zero otherwise.
217
218 * Notes:
219 * - A value of zero will be returned if this function is invoked
220 * with the global status set, or if it should fail for any reason.
221 */
222
223 /* Local Variables: */
224 AstSelectorMap *that;
225 AstSelectorMap *this;
226 int i;
227 int nin;
228 int nreg;
229 int result;
230
231 /* Initialise. */
232 result = 0;
233
234 /* Check the global error status. */
235 if ( !astOK ) return result;
236
237 /* Obtain pointers to the two SelectorMap structures. */
238 this = (AstSelectorMap *) this_object;
239 that = (AstSelectorMap *) that_object;
240
241 /* Check the second object is a SelectorMap. We know the first is a
242 SelectorMap since we have arrived at this implementation of the virtual
243 function. */
244 if( astIsASelectorMap( that ) ) {
245
246 /* Check they have the same number of inputs. */
247 nin = astGetNin( this );
248 if( astGetNin( that ) == nin ) {
249
250 /* Check they contain the same number of Regions, and have the same badval. */
251 nreg = this->nreg;
252 if( that->nreg == nreg ||
253 astEQUAL( that->badval, this->badval) ) {
254
255 /* Loop over the Regions, breaking as soon as two unequal Regions are
256 found. */
257 result = 1;
258 for( i = 0; i < nreg; i++ ) {
259 if( !astEqual( this->reg[ i ], that->reg[ i ] ) ) {
260 result = 0;
261 break;
262 }
263 }
264 }
265 }
266 }
267
268 /* If an error occurred, clear the result value. */
269 if ( !astOK ) result = 0;
270
271 /* Return the result, */
272 return result;
273 }
274
GetObjSize(AstObject * this_object,int * status)275 static int GetObjSize( AstObject *this_object, int *status ) {
276 /*
277 * Name:
278 * GetObjSize
279
280 * Purpose:
281 * Return the in-memory size of an Object.
282
283 * Type:
284 * Private function.
285
286 * Synopsis:
287 * #include "selectormap.h"
288 * int GetObjSize( AstObject *this, int *status )
289
290 * Class Membership:
291 * SelectorMap member function (over-rides the astGetObjSize protected
292 * method inherited from the parent class).
293
294 * Description:
295 * This function returns the in-memory size of the supplied SelectorMap,
296 * in bytes.
297
298 * Parameters:
299 * this
300 * Pointer to the SelectorMap.
301 * status
302 * Pointer to the inherited status variable.
303
304 * Returned Value:
305 * The Object size, in bytes.
306
307 * Notes:
308 * - A value of zero will be returned if this function is invoked
309 * with the global status set, or if it should fail for any reason.
310 */
311
312 /* Local Variables: */
313 AstSelectorMap *this;
314 int i;
315 int result;
316
317 /* Initialise. */
318 result = 0;
319
320 /* Check the global error status. */
321 if ( !astOK ) return result;
322
323 /* Obtain a pointers to the SelectorMap structure. */
324 this = (AstSelectorMap *) this_object;
325
326 /* Invoke the GetObjSize method inherited from the parent class, and then
327 add on any components of the class structure defined by this class
328 which are stored in dynamically allocated memory. */
329 result = (*parent_getobjsize)( this_object, status );
330
331 for( i = 0; i < this->nreg; i++ ) {
332 result += astGetObjSize( this->reg[ i ] );
333 }
334
335 /* If an error occurred, clear the result value. */
336 if ( !astOK ) result = 0;
337
338 /* Return the result, */
339 return result;
340 }
341
astInitSelectorMapVtab_(AstSelectorMapVtab * vtab,const char * name,int * status)342 void astInitSelectorMapVtab_( AstSelectorMapVtab *vtab, const char *name, int *status ) {
343 /*
344 *+
345 * Name:
346 * astInitSelectorMapVtab
347
348 * Purpose:
349 * Initialise a virtual function table for a SelectorMap.
350
351 * Type:
352 * Protected function.
353
354 * Synopsis:
355 * #include "selectormap.h"
356 * void astInitSelectorMapVtab( AstSelectorMapVtab *vtab, const char *name )
357
358 * Class Membership:
359 * SelectorMap vtab initialiser.
360
361 * Description:
362 * This function initialises the component of a virtual function
363 * table which is used by the SelectorMap class.
364
365 * Parameters:
366 * vtab
367 * Pointer to the virtual function table. The components used by
368 * all ancestral classes will be initialised if they have not already
369 * been initialised.
370 * name
371 * Pointer to a constant null-terminated character string which contains
372 * the name of the class to which the virtual function table belongs (it
373 * is this pointer value that will subsequently be returned by the Object
374 * astClass function).
375 *-
376 */
377
378 /* Local Variables: */
379 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
380 AstObjectVtab *object; /* Pointer to Object component of Vtab */
381 AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */
382
383 /* Check the local error status. */
384 if ( !astOK ) return;
385
386 /* Get a pointer to the thread specific global data structure. */
387 astGET_GLOBALS(NULL);
388
389 /* Initialize the component of the virtual function table used by the
390 parent class. */
391 astInitMappingVtab( (AstMappingVtab *) vtab, name );
392
393 /* Store a unique "magic" value in the virtual function table. This
394 will be used (by astIsASelectorMap) to determine if an object belongs to
395 this class. We can conveniently use the address of the (static)
396 class_check variable to generate this unique value. */
397 vtab->id.check = &class_check;
398 vtab->id.parent = &(((AstMappingVtab *) vtab)->id);
399
400 /* Initialise member function pointers. */
401 /* ------------------------------------ */
402 /* Store pointers to the member functions (implemented here) that
403 provide virtual methods for this class. */
404
405 /* None. */
406
407 /* Save the inherited pointers to methods that will be extended, and
408 replace them with pointers to the new member functions. */
409 object = (AstObjectVtab *) vtab;
410 mapping = (AstMappingVtab *) vtab;
411 parent_getobjsize = object->GetObjSize;
412 object->GetObjSize = GetObjSize;
413
414 #if defined(THREAD_SAFE)
415 parent_managelock = object->ManageLock;
416 object->ManageLock = ManageLock;
417 #endif
418
419 parent_transform = mapping->Transform;
420 mapping->Transform = Transform;
421
422 /* Store replacement pointers for methods which will be over-ridden by
423 new member functions implemented here. */
424 object->Equal = Equal;
425 mapping->MapMerge = MapMerge;
426
427 /* Declare the copy constructor, destructor and class dump function. */
428 astSetCopy( vtab, Copy );
429 astSetDelete( vtab, Delete );
430 astSetDump( vtab, Dump, "SelectorMap", "Region identification Mapping" );
431
432 /* If we have just initialised the vtab for the current class, indicate
433 that the vtab is now initialised, and store a pointer to the class
434 identifier in the base "object" level of the vtab. */
435 if( vtab == &class_vtab ) {
436 class_init = 1;
437 astSetVtabClassIdentifier( vtab, &(vtab->id) );
438 }
439 }
440
441 #if defined(THREAD_SAFE)
ManageLock(AstObject * this_object,int mode,int extra,AstObject ** fail,int * status)442 static int ManageLock( AstObject *this_object, int mode, int extra,
443 AstObject **fail, int *status ) {
444 /*
445 * Name:
446 * ManageLock
447
448 * Purpose:
449 * Manage the thread lock on an Object.
450
451 * Type:
452 * Private function.
453
454 * Synopsis:
455 * #include "object.h"
456 * AstObject *ManageLock( AstObject *this, int mode, int extra,
457 * AstObject **fail, int *status )
458
459 * Class Membership:
460 * SelectorMap member function (over-rides the astManageLock protected
461 * method inherited from the parent class).
462
463 * Description:
464 * This function manages the thread lock on the supplied Object. The
465 * lock can be locked, unlocked or checked by this function as
466 * deteremined by parameter "mode". See astLock for details of the way
467 * these locks are used.
468
469 * Parameters:
470 * this
471 * Pointer to the Object.
472 * mode
473 * An integer flag indicating what the function should do:
474 *
475 * AST__LOCK: Lock the Object for exclusive use by the calling
476 * thread. The "extra" value indicates what should be done if the
477 * Object is already locked (wait or report an error - see astLock).
478 *
479 * AST__UNLOCK: Unlock the Object for use by other threads.
480 *
481 * AST__CHECKLOCK: Check that the object is locked for use by the
482 * calling thread (report an error if not).
483 * extra
484 * Extra mode-specific information.
485 * fail
486 * If a non-zero function value is returned, a pointer to the
487 * Object that caused the failure is returned at "*fail". This may
488 * be "this" or it may be an Object contained within "this". Note,
489 * the Object's reference count is not incremented, and so the
490 * returned pointer should not be annulled. A NULL pointer is
491 * returned if this function returns a value of zero.
492 * status
493 * Pointer to the inherited status variable.
494
495 * Returned Value:
496 * A local status value:
497 * 0 - Success
498 * 1 - Could not lock or unlock the object because it was already
499 * locked by another thread.
500 * 2 - Failed to lock a POSIX mutex
501 * 3 - Failed to unlock a POSIX mutex
502 * 4 - Bad "mode" value supplied.
503
504 * Notes:
505 * - This function attempts to execute even if an error has already
506 * occurred.
507 */
508
509 /* Local Variables: */
510 AstSelectorMap *this; /* Pointer to SelectorMap structure */
511 int i; /* Loop count */
512 int result; /* Returned status value */
513
514 /* Initialise */
515 result = 0;
516
517 /* Check the supplied pointer is not NULL. */
518 if( !this_object ) return result;
519
520 /* Obtain a pointers to the SelectorMap structure. */
521 this = (AstSelectorMap *) this_object;
522
523 /* Invoke the ManageLock method inherited from the parent class. */
524 if( !result ) result = (*parent_managelock)( this_object, mode, extra,
525 fail, status );
526
527 /* Invoke the astManageLock method on any Objects contained within
528 the supplied Object. */
529 for( i = 0; i < this->nreg; i++ ) {
530 if( !result ) result = astManageLock( this->reg[ i ], mode, extra, fail );
531 }
532
533 return result;
534
535 }
536 #endif
537
MapMerge(AstMapping * this,int where,int series,int * nmap,AstMapping *** map_list,int ** invert_list,int * status)538 static int MapMerge( AstMapping *this, int where, int series, int *nmap,
539 AstMapping ***map_list, int **invert_list, int *status ) {
540 /*
541 * Name:
542 * MapMerge
543
544 * Purpose:
545 * Simplify a sequence of Mappings containing a SelectorMap.
546
547 * Type:
548 * Private function.
549
550 * Synopsis:
551 * #include "mapping.h"
552 * int MapMerge( AstMapping *this, int where, int series, int *nmap,
553 * AstMapping ***map_list, int **invert_list, int *status )
554
555 * Class Membership:
556 * SelectorMap method (over-rides the protected astMapMerge method
557 * inherited from the Mapping class).
558
559 * Description:
560 * This function attempts to simplify a sequence of Mappings by
561 * merging a nominated SelectorMap in the sequence with its neighbours,
562 * so as to shorten the sequence if possible.
563 *
564 * In many cases, simplification will not be possible and the
565 * function will return -1 to indicate this, without further
566 * action.
567 *
568 * In most cases of interest, however, this function will either
569 * attempt to replace the nominated SelectorMap with one which it
570 * considers simpler, or to merge it with the Mappings which
571 * immediately precede it or follow it in the sequence (both will
572 * normally be considered). This is sufficient to ensure the
573 * eventual simplification of most Mapping sequences by repeated
574 * application of this function.
575 *
576 * In some cases, the function may attempt more elaborate
577 * simplification, involving any number of other Mappings in the
578 * sequence. It is not restricted in the type or scope of
579 * simplification it may perform, but will normally only attempt
580 * elaborate simplification in cases where a more straightforward
581 * approach is not adequate.
582
583 * Parameters:
584 * this
585 * Pointer to the nominated SelectorMap which is to be merged with
586 * its neighbours. This should be a cloned copy of the SelectorMap
587 * pointer contained in the array element "(*map_list)[where]"
588 * (see below). This pointer will not be annulled, and the
589 * SelectorMap it identifies will not be modified by this function.
590 * where
591 * Index in the "*map_list" array (below) at which the pointer
592 * to the nominated SelectorMap resides.
593 * series
594 * A non-zero value indicates that the sequence of Mappings to
595 * be simplified will be applied in series (i.e. one after the
596 * other), whereas a zero value indicates that they will be
597 * applied in parallel (i.e. on successive sub-sets of the
598 * input/output coordinates).
599 * nmap
600 * Address of an int which counts the number of Mappings in the
601 * sequence. On entry this should be set to the initial number
602 * of Mappings. On exit it will be updated to record the number
603 * of Mappings remaining after simplification.
604 * map_list
605 * Address of a pointer to a dynamically allocated array of
606 * Mapping pointers (produced, for example, by the astMapList
607 * method) which identifies the sequence of Mappings. On entry,
608 * the initial sequence of Mappings to be simplified should be
609 * supplied.
610 *
611 * On exit, the contents of this array will be modified to
612 * reflect any simplification carried out. Any form of
613 * simplification may be performed. This may involve any of: (a)
614 * removing Mappings by annulling any of the pointers supplied,
615 * (b) replacing them with pointers to new Mappings, (c)
616 * inserting additional Mappings and (d) changing their order.
617 *
618 * The intention is to reduce the number of Mappings in the
619 * sequence, if possible, and any reduction will be reflected in
620 * the value of "*nmap" returned. However, simplifications which
621 * do not reduce the length of the sequence (but improve its
622 * execution time, for example) may also be performed, and the
623 * sequence might conceivably increase in length (but normally
624 * only in order to split up a Mapping into pieces that can be
625 * more easily merged with their neighbours on subsequent
626 * invocations of this function).
627 *
628 * If Mappings are removed from the sequence, any gaps that
629 * remain will be closed up, by moving subsequent Mapping
630 * pointers along in the array, so that vacated elements occur
631 * at the end. If the sequence increases in length, the array
632 * will be extended (and its pointer updated) if necessary to
633 * accommodate any new elements.
634 *
635 * Note that any (or all) of the Mapping pointers supplied in
636 * this array may be annulled by this function, but the Mappings
637 * to which they refer are not modified in any way (although
638 * they may, of course, be deleted if the annulled pointer is
639 * the final one).
640 * invert_list
641 * Address of a pointer to a dynamically allocated array which,
642 * on entry, should contain values to be assigned to the Invert
643 * attributes of the Mappings identified in the "*map_list"
644 * array before they are applied (this array might have been
645 * produced, for example, by the astMapList method). These
646 * values will be used by this function instead of the actual
647 * Invert attributes of the Mappings supplied, which are
648 * ignored.
649 *
650 * On exit, the contents of this array will be updated to
651 * correspond with the possibly modified contents of the
652 * "*map_list" array. If the Mapping sequence increases in
653 * length, the "*invert_list" array will be extended (and its
654 * pointer updated) if necessary to accommodate any new
655 * elements.
656 * status
657 * Pointer to the inherited status variable.
658
659 * Returned Value:
660 * If simplification was possible, the function returns the index
661 * in the "map_list" array of the first element which was
662 * modified. Otherwise, it returns -1 (and makes no changes to the
663 * arrays supplied).
664
665 * Notes:
666 * - A value of -1 will be returned if this function is invoked
667 * with the global error status set, or if it should fail for any
668 * reason.
669 */
670
671 /* Local Variables: */
672 AstMapping *new;
673 AstRegion **sreg;
674 AstSelectorMap *map;
675 AstSelectorMap *slneb;
676 int equal;
677 int i;
678 int ilo;
679 int nreg;
680 int result;
681 int simp;
682
683 /* Initialise.*/
684 result = -1;
685
686 /* Check the inherited status. */
687 if ( !astOK ) return result;
688
689 /* Get a pointer to this SelectorMap, and note the number of Regions. */
690 map = (AstSelectorMap *) this;
691 nreg = map->nreg;
692
693 /* Attempt to simplify the SelectorMap on its own. */
694 /* ============================================= */
695
696 /* Try to simplify each of the encapsulated Regions, noting if any
697 simplification takes place. */
698 simp = 0;
699 sreg = astMalloc( sizeof( AstRegion * )*nreg );
700 if( astOK ) {
701 for( i = 0; i < nreg; i++ ) {
702 sreg[ i ] = astSimplify( map->reg[ i ] );
703 simp = simp || ( sreg[ i ] != map->reg[ i ] );
704 }
705
706 /* If any simplification took place, construct a new SelectorMap from these
707 simplified Mappings. */
708 if( simp ) {
709 (void) astAnnul( ( *map_list )[ where ] );
710 ( *map_list )[ where ] = (AstMapping *) astSelectorMap( nreg,
711 (void **) sreg,
712 map->badval, "", status );
713 result = where;
714 }
715
716 /* Release resources. */
717 if( sreg ) {
718 for( i = 0; i < nreg; i++ ) sreg[ i ] = astAnnul( sreg[ i ] );
719 sreg = astFree( sreg );
720 }
721 }
722
723 /* If possible, merge the SelectorMap with a neighbouring SelectorMap. */
724 /* =============================================================== */
725 /* Only do this if no change was made above, and we are combining the
726 Mappings in series. */
727 if( result == -1 && series ) {
728
729 /* Is the higher neighbour a SelectorMap? If so get a pointer to it, and
730 note the index of the lower of the two adjacent SelectorMaps. */
731 if( where < ( *nmap - 1 ) &&
732 astIsASelectorMap( ( *map_list )[ where + 1 ] ) ){
733 slneb = (AstSelectorMap *) ( *map_list )[ where + 1 ];
734 ilo = where;
735
736 /* If not, is the lower neighbour a SelectorMap? If so get a pointer to it, and
737 note the index of the lower of the two adjacent SelectorMaps. */
738 } else if( where > 0 &&
739 astIsASelectorMap( ( *map_list )[ where - 1 ] ) ){
740 slneb = (AstSelectorMap *) ( *map_list )[ where - 1 ];
741 ilo = where - 1;
742
743 } else {
744 slneb = NULL;
745 }
746
747 /* If a neighbouring SelectorMap was found, we can replace the pair by a
748 UnitMap if the two SelectorMaps are equal but have opposite values for
749 their Invert flags. Temporarily invert the neighbour, then compare
750 the two SelectorMaps for equality, then re-invert the neighbour. */
751 if( slneb ) {
752 astInvert( slneb );
753 equal = astEqual( map, slneb );
754 astInvert( slneb );
755
756 /* If the two SelectorMaps are equal but opposite, annul the first of the two
757 Mappings, and replace it with a UnitMap. Also set the invert flag. */
758 if( equal ) {
759 new = (AstMapping *) astUnitMap( astGetNin( ( *map_list )[ ilo ] ), "", status );
760 (void) astAnnul( ( *map_list )[ ilo ] );
761 ( *map_list )[ ilo ] = new;
762 ( *invert_list )[ ilo ] = 0;
763
764 /* Annul the second of the two Mappings, and shuffle down the rest of the
765 list to fill the gap. */
766 (void) astAnnul( ( *map_list )[ ilo + 1 ] );
767 for ( i = ilo + 2; i < *nmap; i++ ) {
768 ( *map_list )[ i - 1 ] = ( *map_list )[ i ];
769 ( *invert_list )[ i - 1 ] = ( *invert_list )[ i ];
770 }
771
772 /* Clear the vacated element at the end. */
773 ( *map_list )[ *nmap - 1 ] = NULL;
774 ( *invert_list )[ *nmap - 1 ] = 0;
775
776 /* Decrement the Mapping count and return the index of the first
777 modified element. */
778 ( *nmap )--;
779 result = where;
780 }
781 }
782 }
783
784 /* If an error occurred, clear the result value. */
785 if ( !astOK ) result = -1;
786
787 /* Return the result. */
788 return result;
789 }
790
Transform(AstMapping * this,AstPointSet * in,int forward,AstPointSet * out,int * status)791 static AstPointSet *Transform( AstMapping *this, AstPointSet *in,
792 int forward, AstPointSet *out, int *status ) {
793 /*
794 * Name:
795 * Transform
796
797 * Purpose:
798 * Apply a SelectorMap to transform a set of points.
799
800 * Type:
801 * Private function.
802
803 * Synopsis:
804 * #include "selectormap.h"
805 * AstPointSet *Transform( AstMapping *this, AstPointSet *in,
806 * int forward, AstPointSet *out, int *status )
807
808 * Class Membership:
809 * SelectorMap member function (over-rides the astTransform method inherited
810 * from the Mapping class).
811
812 * Description:
813 * This function takes a SelectorMap and a set of points encapsulated in a
814 * PointSet and transforms the points so as to apply the required Mapping.
815 * This implies applying each of the SelectorMap's component Mappings in turn,
816 * either in series or in parallel.
817
818 * Parameters:
819 * this
820 * Pointer to the SelectorMap.
821 * in
822 * Pointer to the PointSet associated with the input coordinate values.
823 * forward
824 * A non-zero value indicates that the forward coordinate transformation
825 * should be applied, while a zero value requests the inverse
826 * transformation.
827 * out
828 * Pointer to a PointSet which will hold the transformed (output)
829 * coordinate values. A NULL value may also be given, in which case a
830 * new PointSet will be created by this function.
831 * status
832 * Pointer to the inherited status variable.
833
834 * Returned Value:
835 * Pointer to the output (possibly new) PointSet.
836
837 * Notes:
838 * - A null pointer will be returned if this function is invoked with the
839 * global error status set, or if it should fail for any reason.
840 * - The number of coordinate values per point in the input PointSet must
841 * match the number of coordinates for the SelectorMap being applied.
842 * - If an output PointSet is supplied, it must have space for sufficient
843 * number of points and coordinate values per point to accommodate the
844 * result. Any excess space will be ignored.
845 */
846
847 /* Local Variables: */
848 AstPointSet *ps1;
849 AstPointSet *ps2;
850 AstPointSet *result;
851 AstPointSet *tps;
852 AstRegion *reg;
853 AstSelectorMap *map;
854 double **ptr_out;
855 double **ptr1;
856 double **ptr2;
857 double **tptr;
858 double *p2;
859 double *pout;
860 double badval;
861 int bad;
862 int closed;
863 int icoord;
864 int ipoint;
865 int ireg;
866 int ncoord;
867 int npoint;
868
869 /* Check the global error status. */
870 if ( !astOK ) return NULL;
871
872 /* Obtain a pointer to the SelectorMap. */
873 map = (AstSelectorMap *) this;
874
875 /* Apply the parent Mapping using the stored pointer to the Transform member
876 function inherited from the parent Mapping class. This function validates
877 all arguments and generates an output PointSet if necessary, but does not
878 actually transform any coordinate values. */
879 result = (*parent_transform)( this, in, forward, out, status );
880
881 /* We now extend the parent astTransform method by applying the component
882 Mappings of the SelectorMap to generate the output coordinate values. */
883
884 /* Check we are implementing the original forward transformation (the
885 inverse transformation is not defined). */
886 if( forward != astGetInvert( this ) ) {
887
888 /* Get the number of input axes and the number of points. */
889 ncoord = astGetNcoord( in );
890 npoint = astGetNpoint( in );
891
892 /* Create two temporary PointSets to hold copies of the input points. */
893 ps1 = astCopy( in );
894 ptr1 = astGetPoints( ps1 );
895 ps2 = astPointSet( npoint, ncoord, "", status );
896 ptr2 = astGetPoints( ps2 );
897
898 /* Get a pointer to the output data */
899 ptr_out = astGetPoints( result );
900 if( astOK ) {
901
902 /* Initialise the output array to hold -1 at any points that have
903 bad input axis values, and zero at all other points. */
904 pout = ptr_out[ 0 ];
905 for( ipoint = 0; ipoint < npoint; ipoint++ ) {
906 bad = 0;
907 for( icoord = 0; icoord < ncoord; icoord++ ) {
908 if( ptr1[ icoord ][ ipoint ] == AST__BAD ) {
909 bad = 1;
910 break;
911 }
912 }
913 *(pout++) = bad ? -1 : 0;
914 }
915
916 /* Loop round all Regions. */
917 for( ireg = 1; ireg <= map->nreg; ireg++ ) {
918 reg = map->reg[ ireg - 1 ];
919
920 /* Temporarily Negate the Region. */
921 astNegate( reg );
922 closed = astGetClosed( reg );
923 astSetClosed( reg, !closed );
924
925 /* Transform the remaining input positions. Good input positions which
926 are within the Region will be bad in the output. */
927 ps2 = astTransform( reg, ps1, 1, ps2 );
928
929 /* Loop round all positions. */
930 p2 = ptr2[ 0 ];
931 pout = ptr_out[ 0 ];
932 for( ipoint = 0; ipoint < npoint; ipoint++, p2++, pout++ ) {
933
934 /* Any position that has not already been assigned to a Region and is bad
935 in the output PointSet must be contained within the current Region, so
936 assign the (one-based) index of the current Region to the output element. */
937 if( *pout == 0 && *p2 == AST__BAD ) *pout = ireg;
938 }
939
940 /* Negate the Region to get it back to its original state. */
941 astSetClosed( reg, closed );
942 astNegate( reg );
943
944 /* Swap the input and output PointSets. */
945 tps = ps1;
946 ps1 = ps2;
947 ps2 = tps;
948 tptr = ptr1;
949 ptr1 = ptr2;
950 ptr2 = tptr;
951 }
952
953 /* Replace -1 values in the output (that indicate that the input position
954 had at least one bad axis value) with the "badval".*/
955 badval = map->badval;
956 pout = ptr_out[ 0 ];
957 for( ipoint = 0; ipoint < npoint; ipoint++, pout++ ) {
958 if( *pout == -1 ) *pout = badval;
959 }
960 }
961
962 /* Free resources. */
963 ps1 = astAnnul( ps1 );
964 ps2 = astAnnul( ps2 );
965 }
966
967 /* If an error occurred, clean up by deleting the output PointSet (if
968 allocated by this function) and setting a NULL result pointer. */
969 if ( !astOK ) {
970 if ( !out ) result = astDelete( result );
971 result = NULL;
972 }
973
974 /* Return a pointer to the output PointSet. */
975 return result;
976 }
977
978 /* Copy constructor. */
979 /* ----------------- */
Copy(const AstObject * objin,AstObject * objout,int * status)980 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
981 /*
982 * Name:
983 * Copy
984
985 * Purpose:
986 * Copy constructor for SelectorMap objects.
987
988 * Type:
989 * Private function.
990
991 * Synopsis:
992 * void Copy( const AstObject *objin, AstObject *objout, int *status )
993
994 * Description:
995 * This function implements the copy constructor for SelectorMap objects.
996
997 * Parameters:
998 * objin
999 * Pointer to the object to be copied.
1000 * objout
1001 * Pointer to the object being constructed.
1002 * status
1003 * Pointer to the inherited status variable.
1004
1005 * Returned Value:
1006 * void
1007
1008 * Notes:
1009 * - This constructor makes a deep copy, including a copy of the
1010 * Regions within the SelectorMap.
1011 */
1012
1013 /* Local Variables: */
1014 AstSelectorMap *in; /* Pointer to input SelectorMap */
1015 AstSelectorMap *out; /* Pointer to output SelectorMap */
1016 int i; /* Loop count */
1017
1018 /* Check the global error status. */
1019 if ( !astOK ) return;
1020
1021 /* Obtain pointers to the input and output SelectorMaps. */
1022 in = (AstSelectorMap *) objin;
1023 out = (AstSelectorMap *) objout;
1024
1025 /* For safety, start by clearing any references to the input Regions. */
1026 out->reg = NULL;
1027 out->nreg = 0;
1028
1029 /* Make copies of the Regions, and store pointers to them in the output
1030 SelectorMap structure. */
1031 out->reg = astMalloc( sizeof( AstRegion * )*( in->nreg ) );
1032 if( astOK ) {
1033 for( i = 0; i < in->nreg; i++ ) {
1034 out->reg[ i ] = astCopy( in->reg[ i ] );
1035 }
1036 out->nreg = in->nreg;
1037 }
1038
1039 }
1040
1041 /* Destructor. */
1042 /* ----------- */
Delete(AstObject * obj,int * status)1043 static void Delete( AstObject *obj, int *status ) {
1044 /*
1045 * Name:
1046 * Delete
1047
1048 * Purpose:
1049 * Destructor for SelectorMap objects.
1050
1051 * Type:
1052 * Private function.
1053
1054 * Synopsis:
1055 * void Delete( AstObject *obj, int *status )
1056
1057 * Description:
1058 * This function implements the destructor for SelectorMap objects.
1059
1060 * Parameters:
1061 * obj
1062 * Pointer to the object to be deleted.
1063 * status
1064 * Pointer to the inherited status variable.
1065
1066 * Returned Value:
1067 * void
1068
1069 * Notes:
1070 * This function attempts to execute even if the global error status is
1071 * set.
1072 */
1073
1074 /* Local Variables: */
1075 AstSelectorMap *this; /* Pointer to SelectorMap */
1076 int i;
1077
1078 /* Obtain a pointer to the SelectorMap structure. */
1079 this = (AstSelectorMap *) obj;
1080
1081 /* Free dynamically allocated resources. */
1082 for( i = 0; i < this->nreg; i++ ) {
1083 this->reg[ i ] = astAnnul( this->reg[ i ] );
1084 }
1085 this->reg = astFree( this->reg );
1086
1087 /* Clear the remaining SelectorMap variables. */
1088 this->nreg = 0;
1089 }
1090
1091 /* Dump function. */
1092 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)1093 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
1094 /*
1095 * Name:
1096 * Dump
1097
1098 * Purpose:
1099 * Dump function for SelectorMap objects.
1100
1101 * Type:
1102 * Private function.
1103
1104 * Synopsis:
1105 * void Dump( AstObject *this, AstChannel *channel, int *status )
1106
1107 * Description:
1108 * This function implements the Dump function which writes out data
1109 * for the SelectorMap class to an output Channel.
1110
1111 * Parameters:
1112 * this
1113 * Pointer to the SelectorMap whose data are being written.
1114 * channel
1115 * Pointer to the Channel to which the data are being written.
1116 * status
1117 * Pointer to the inherited status variable.
1118 */
1119
1120 /* Local Variables: */
1121 AstSelectorMap *this;
1122 int i;
1123 char buf[ 20 ];
1124
1125 /* Check the global error status. */
1126 if ( !astOK ) return;
1127
1128 /* Obtain a pointer to the SelectorMap structure. */
1129 this = (AstSelectorMap *) this_object;
1130
1131 /* Write out values representing the instance variables for the SelectorMap
1132 class. Accompany these with appropriate comment strings, possibly
1133 depending on the values being written.*/
1134
1135 /* In the case of attributes, we first use the appropriate (private)
1136 Test... member function to see if they are set. If so, we then use
1137 the (private) Get... function to obtain the value to be written
1138 out.
1139
1140 For attributes which are not set, we use the astGet... method to
1141 obtain the value instead. This will supply a default value
1142 (possibly provided by a derived class which over-rides this method)
1143 which is more useful to a human reader as it corresponds to the
1144 actual default attribute value. Since "set" will be zero, these
1145 values are for information only and will not be read back. */
1146
1147 /* Loop to dump each Region. */
1148 /* ------------------------- */
1149 /* The coordinate Frame of the Regions is defined by the first Region.
1150 The Frame information is omitted from the second and subsequent
1151 Regions by setting the protected RegionFS attribute to zero. */
1152 for( i = 0; i < this->nreg; i++ ) {
1153 sprintf( buf, "Reg%d", i + 1 );
1154 if( i > 0 ) astSetRegionFS( this->reg[ i ], 0 );
1155 astWriteObject( channel, buf, 1, 1, this->reg[ i ],
1156 "Region of input space" );
1157 if( i > 0 ) astClearRegionFS( this->reg[ i ] );
1158 }
1159
1160 /* BadVal. */
1161 /* ------- */
1162 if( this->badval != AST__BAD ) {
1163 astWriteDouble( channel, "BadVal", 1, 1, this->badval,
1164 "Output value for bad input positions" );
1165 }
1166
1167 }
1168
1169 /* Standard class functions. */
1170 /* ========================= */
1171 /* Implement the astIsASelectorMap and astCheckSelectorMap functions using the
1172 macros defined for this purpose in the "object.h" header file. */
astMAKE_ISA(SelectorMap,Mapping)1173 astMAKE_ISA(SelectorMap,Mapping)
1174 astMAKE_CHECK(SelectorMap)
1175
1176 AstSelectorMap *astSelectorMap_( int nreg, void **regs_void, double badval,
1177 const char *options, int *status, ...) {
1178 /*
1179 *+
1180 * Name:
1181 * astSelectorMap
1182
1183 * Purpose:
1184 * Create a SelectorMap.
1185
1186 * Type:
1187 * Protected function.
1188
1189 * Synopsis:
1190 * #include "selectormap.h"
1191 * AstSelectorMap *astSelectorMap( int nreg, AstRegion **regs,
1192 * double badval, const char *options, ... )
1193
1194 * Class Membership:
1195 * SelectorMap constructor.
1196
1197 * Description:
1198 * This function creates a new SelectorMap and optionally initialises its
1199 * attributes.
1200
1201 * Parameters:
1202 * nreg
1203 * The number of Regions supplied.
1204 * regs
1205 * An array of pointers to the Regions. Deep copies of these
1206 * Regions are taken.
1207 * badval
1208 * The value to be returned by the forward transformation of the
1209 * SelectorMap for any input positions that have a bad (AST__BAD)
1210 * value on any axis.
1211 * options
1212 * Pointer to a null terminated string containing an optional
1213 * comma-separated list of attribute assignments to be used for
1214 * initialising the new SelectorMap. The syntax used is the same as for the
1215 * astSet method and may include "printf" format specifiers identified
1216 * by "%" symbols in the normal way.
1217 * ...
1218 * If the "options" string contains "%" format specifiers, then an
1219 * optional list of arguments may follow it in order to supply values to
1220 * be substituted for these specifiers. The rules for supplying these
1221 * are identical to those for the astSet method (and for the C "printf"
1222 * function).
1223
1224 * Returned Value:
1225 * A pointer to the new SelectorMap.
1226
1227 * Notes:
1228 * - A null pointer will be returned if this function is invoked
1229 * with the global error status set, or if it should fail for any
1230 * reason.
1231 *-
1232
1233 * Implementation Notes:
1234 * - This function implements the basic SelectorMap constructor which is
1235 * available via the protected interface to the SelectorMap class. A
1236 * public interface is provided by the astSelectorMapId_ function.
1237 * - Because this function has a variable argument list, it is
1238 * invoked by a macro that evaluates to a function pointer (not a
1239 * function invocation) and no checking or casting of arguments is
1240 * performed before the function is invoked. Because of this, the
1241 * "map1" and "map2" parameters are of type (void *) and are
1242 * converted and validated within the function itself.
1243 */
1244
1245 /* Local Variables: */
1246 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1247 AstSelectorMap *new; /* Pointer to new SelectorMap */
1248 AstRegion **regs; /* Array of Region pointers */
1249 int i; /* Region index */
1250 va_list args; /* Variable argument list */
1251
1252 /* Initialise. */
1253 new = NULL;
1254
1255 /* Get a pointer to the thread specific global data structure. */
1256 astGET_GLOBALS(NULL);
1257
1258 /* Check the global status. */
1259 if ( !astOK ) return new;
1260
1261 /* Report an error if no Regions have been supplied. */
1262 if( nreg <= 0 ) astError( AST__BDPAR, "astSelectorMap(SelectorMap): "
1263 "Bad number of Regions (%d) specified.", status, nreg );
1264
1265 /* Otherwise create an array to hold the Region pointers. */
1266 regs = astMalloc( sizeof( AstRegion * )*nreg );
1267
1268 /* Obtain and validate pointers to the Region structures provided. */
1269 if( astOK ) {
1270 for( i = 0; i < nreg; i++ ) {
1271 regs[ i ] = astCheckRegion( regs_void[ i ] );
1272 }
1273 }
1274
1275 if ( astOK ) {
1276
1277 /* Initialise the SelectorMap, allocating memory and initialising the
1278 virtual function table as well if necessary. */
1279 new = astInitSelectorMap( NULL, sizeof( AstSelectorMap ), !class_init, &class_vtab,
1280 "SelectorMap", nreg, regs, badval );
1281
1282 /* If successful, note that the virtual function table has been
1283 initialised. */
1284 if ( astOK ) {
1285 class_init = 1;
1286
1287 /* Obtain the variable argument list and pass it along with the
1288 options string to the astVSet method to initialise the new SelectorMap's
1289 attributes. */
1290 va_start( args, status );
1291 astVSet( new, options, NULL, args );
1292 va_end( args );
1293
1294 /* If an error occurred, clean up by deleting the new object. */
1295 if ( !astOK ) new = astDelete( new );
1296 }
1297 }
1298
1299 /* Free memory used to hold the Regions pointers. */
1300 regs = astFree( regs );
1301
1302 /* Return a pointer to the new SelectorMap. */
1303 return new;
1304 }
1305
astSelectorMapId_(int nreg,void ** regs_void,double badval,const char * options,...)1306 AstSelectorMap *astSelectorMapId_( int nreg, void **regs_void, double badval,
1307 const char *options, ... ) {
1308 /*
1309 *++
1310 * Name:
1311 c astSelectorMap
1312 f AST_SELECTORMAP
1313
1314 * Purpose:
1315 * Create a SelectorMap.
1316
1317 * Type:
1318 * Public function.
1319
1320 * Synopsis:
1321 c #include "selectormap.h"
1322 c AstSelectorMap *astSelectorMap( int nreg, AstRegion *regs[],
1323 c double badval, const char *options, ... )
1324 f RESULT = AST_SELECTORMAP( NREG, REGS, BADVAL, OPTIONS, STATUS )
1325
1326 * Class Membership:
1327 * SelectorMap constructor.
1328
1329 * Description:
1330 * This function creates a new SelectorMap and optionally initialises
1331 * its attributes.
1332 *
1333 * A SelectorMap is a Mapping that identifies which Region contains
1334 * a given input position.
1335 *
1336 * A SelectorMap encapsulates a number of Regions that all have the same
1337 * number of axes and represent the same coordinate Frame. The number of
1338 * inputs (Nin attribute) of the SelectorMap equals the number of axes
1339 * spanned by one of the encapsulated Region. All SelectorMaps have only
1340 * a single output. SelectorMaps do not define an inverse transformation.
1341 *
1342 * For each input position, the forward transformation of a SelectorMap
1343 * searches through the encapsulated Regions (in the order supplied when
1344 * the SelectorMap was created) until a Region is found which contains
1345 * the input position. The index associated with this Region is
1346 * returned as the SelectorMap output value (the index value is the
1347 * position of the Region within the list of Regions supplied when the
1348 * SelectorMap was created, starting at 1 for the first Region). If an
1349 * input position is not contained within any Region, a value of zero is
1350 * returned by the forward transformation.
1351 *
1352 * If a compound Mapping contains a SelectorMap in series with its own
1353 * inverse, the combination of the two adjacent SelectorMaps will be
1354 * replaced by a UnitMap when the compound Mapping is simplified using
1355 c astSimplify.
1356 f AST_SIMPLIFY.
1357 *
1358 * In practice, SelectorMaps are often used in conjunction with SwitchMaps.
1359
1360 * Parameters:
1361 c nreg
1362 f NREG = INTEGER (Given)
1363 * The number of supplied Regions.
1364 c regs
1365 f REGS( NREG ) = INTEGER (Given)
1366 * An array of pointers to the Regions. All the supplied Regions must
1367 * relate to the same coordinate Frame. The number of axes in this
1368 * coordinate Frame defines the number of inputs for the SelectorMap.
1369 c badval
1370 f BADVAL = DOUBLE PRECISION (Given)
1371 * The value to be returned by the forward transformation of the
1372 * SelectorMap for any input positions that have a bad (AST__BAD)
1373 * value on any axis.
1374 c options
1375 f OPTIONS = CHARACTER * ( * ) (Given)
1376 c Pointer to a null-terminated string containing an optional
1377 c comma-separated list of attribute assignments to be used for
1378 c initialising the new SelectorMap. The syntax used is identical to
1379 c that for the astSet function and may include "printf" format
1380 c specifiers identified by "%" symbols in the normal way.
1381 f A character string containing an optional comma-separated
1382 f list of attribute assignments to be used for initialising the
1383 f new SelectorMap. The syntax used is identical to that for the
1384 f AST_SET routine.
1385 c ...
1386 c If the "options" string contains "%" format specifiers, then
1387 c an optional list of additional arguments may follow it in
1388 c order to supply values to be substituted for these
1389 c specifiers. The rules for supplying these are identical to
1390 c those for the astSet function (and for the C "printf"
1391 c function).
1392 f STATUS = INTEGER (Given and Returned)
1393 f The global status.
1394
1395 * Returned Value:
1396 c astSelectorMap()
1397 f AST_SELECTORMAP = INTEGER
1398 * A pointer to the new SelectorMap.
1399
1400 * Notes:
1401 * - Deep copies are taken of the supplied Regions. This means that
1402 * any subsequent changes made to the component Regions using the
1403 * supplied pointers will have no effect on the SelectorMap.
1404 * - A null Object pointer (AST__NULL) will be returned if this
1405 c function is invoked with the AST error status set, or if it
1406 f function is invoked with STATUS set to an error value, or if it
1407 * should fail for any reason.
1408 *--
1409
1410 * Implementation Notes:
1411 * - This function implements the external (public) interface to
1412 * the astSelectorMap constructor function. It returns an ID value
1413 * (instead of a true C pointer) to external users, and must be
1414 * provided because astSelectorMap_ has a variable argument list which
1415 * cannot be encapsulated in a macro (where this conversion would
1416 * otherwise occur).
1417 * - Because no checking or casting of arguments is performed
1418 * before the function is invoked, the "map1" and "map2" parameters
1419 * are of type (void *) and are converted from an ID value to a
1420 * pointer and validated within the function itself.
1421 * - The variable argument list also prevents this function from
1422 * invoking astSelectorMap_ directly, so it must be a re-implementation
1423 * of it in all respects, except for the conversions between IDs
1424 * and pointers on input/output of Objects.
1425 */
1426
1427 /* Local Variables: */
1428 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1429 AstSelectorMap *new; /* Pointer to new SelectorMap */
1430 AstRegion **regs; /* Array of Region pointers */
1431 int i; /* Region index */
1432 va_list args; /* Variable argument list */
1433
1434 int *status; /* Pointer to inherited status value */
1435
1436 /* Get a pointer to the thread specific global data structure. */
1437 astGET_GLOBALS(NULL);
1438
1439 /* Initialise. */
1440 new = NULL;
1441
1442 /* Get a pointer to the inherited status value. */
1443 status = astGetStatusPtr;
1444
1445 /* Check the global status. */
1446 if ( !astOK ) return new;
1447
1448 /* Report an error if no Regions have been supplied. */
1449 if( nreg <= 0 ) astError( AST__BDPAR, "astSelectorMap(SelectorMap): "
1450 "Bad number of Regions (%d) specified.", status, nreg );
1451
1452 /* Create an array to hold the Region pointers. */
1453 regs = astMalloc( sizeof( AstRegion * )*nreg );
1454
1455 /* Obtain and validate pointers to the Region structures provided. */
1456 if( astOK ) {
1457 for( i = 0; i < nreg; i++ ) {
1458 regs[ i ] = astVerifyRegion( astMakePointer(regs_void[ i ]) );
1459 }
1460 }
1461
1462 if ( astOK ) {
1463
1464 /* Initialise the SelectorMap, allocating memory and initialising the
1465 virtual function table as well if necessary. */
1466 new = astInitSelectorMap( NULL, sizeof( AstSelectorMap ), !class_init,
1467 &class_vtab, "SelectorMap", nreg, regs,
1468 badval );
1469
1470 /* If successful, note that the virtual function table has been
1471 initialised. */
1472 if ( astOK ) {
1473 class_init = 1;
1474
1475 /* Obtain the variable argument list and pass it along with the
1476 options string to the astVSet method to initialise the new SelectorMap's
1477 attributes. */
1478 va_start( args, options );
1479 astVSet( new, options, NULL, args );
1480 va_end( args );
1481
1482 /* If an error occurred, clean up by deleting the new object. */
1483 if ( !astOK ) new = astDelete( new );
1484 }
1485 }
1486
1487 /* Free memory used to hold the Regions pointers. */
1488 regs = astFree( regs );
1489
1490 /* Return an ID value for the new SelectorMap. */
1491 return astMakeId( new );
1492 }
1493
astInitSelectorMap_(void * mem,size_t size,int init,AstSelectorMapVtab * vtab,const char * name,int nreg,AstRegion ** regs,double badval,int * status)1494 AstSelectorMap *astInitSelectorMap_( void *mem, size_t size, int init,
1495 AstSelectorMapVtab *vtab, const char *name,
1496 int nreg, AstRegion **regs, double badval, int *status ) {
1497 /*
1498 *+
1499 * Name:
1500 * astInitSelectorMap
1501
1502 * Purpose:
1503 * Initialise a SelectorMap.
1504
1505 * Type:
1506 * Protected function.
1507
1508 * Synopsis:
1509 * #include "selectormap.h"
1510 * AstSelectorMap *astInitSelectorMap( void *mem, size_t size, int init,
1511 * AstSelectorMapVtab *vtab, const char *name,
1512 * int nreg, AstRegion **regs, double badval )
1513
1514 * Class Membership:
1515 * SelectorMap initialiser.
1516
1517 * Description:
1518 * This function is provided for use by class implementations to initialise
1519 * a new SelectorMap object. It allocates memory (if necessary) to
1520 * accommodate the SelectorMap plus any additional data associated with the
1521 * derived class. It then initialises a SelectorMap structure at the start
1522 * of this memory. If the "init" flag is set, it also initialises the
1523 * contents of a virtual function table for a SelectorMap at the start of
1524 * the memory passed via the "vtab" parameter.
1525
1526 * Parameters:
1527 * mem
1528 * A pointer to the memory in which the SelectorMap is to be initialised.
1529 * This must be of sufficient size to accommodate the SelectorMap data
1530 * (sizeof(SelectorMap)) plus any data used by the derived class. If a
1531 * value of NULL is given, this function will allocate the memory itself
1532 * using the "size" parameter to determine its size.
1533 * size
1534 * The amount of memory used by the SelectorMap (plus derived class
1535 * data). This will be used to allocate memory if a value of NULL is
1536 * given for the "mem" parameter. This value is also stored in the
1537 * SelectorMap structure, so a valid value must be supplied even if not
1538 * required for allocating memory.
1539 * init
1540 * A logical flag indicating if the SelectorMap's virtual function table
1541 * is to be initialised. If this value is non-zero, the virtual function
1542 * table will be initialised by this function.
1543 * vtab
1544 * Pointer to the start of the virtual function table to be associated
1545 * with the new SelectorMap.
1546 * name
1547 * Pointer to a constant null-terminated character string which contains
1548 * the name of the class to which the new object belongs (it is this
1549 * pointer value that will subsequently be returned by the Object
1550 * astClass function).
1551 * nreg
1552 * The number of Regions supplied.
1553 * regs
1554 * An array holdiong pointers to the Regions. Deep copies are taken
1555 * of these Regions.
1556 * badval
1557 * The value to be returned by the forward transformation of the
1558 * SelectorMap for any input positions that have a bad (AST__BAD)
1559 * value on any axis.
1560
1561 * Returned Value:
1562 * A pointer to the new SelectorMap.
1563
1564 * Notes:
1565 * - A null pointer will be returned if this function is invoked with the
1566 * global error status set, or if it should fail for any reason.
1567 *-
1568 */
1569
1570 /* Local Variables: */
1571 AstFrame *f0; /* Frame from first Region */
1572 AstFrame *f1; /* Frame from current Region */
1573 AstSelectorMap *new; /* Pointer to new SelectorMap */
1574 int equal; /* Are Frames equal? */
1575 int i; /* Loop count */
1576 int nin; /* No. input coordinates for SelectorMap */
1577
1578 /* Check the global status. */
1579 if ( !astOK ) return NULL;
1580
1581 /* If necessary, initialise the virtual function table. */
1582 if ( init ) astInitSelectorMapVtab( vtab, name );
1583
1584 /* Initialise. */
1585 new = NULL;
1586
1587 /* Check that all Regions refer to the same Frame. */
1588 f0 = astRegFrame( regs[ 0 ] );
1589 for( i = 1; i < nreg; i++ ) {
1590 f1 = astRegFrame( regs[ i ] );
1591 equal = astEqual( f1, f0 );
1592 f1 = astAnnul( f1 );
1593
1594 if( !equal ) {
1595 if( astOK ) {
1596 astError( AST__BADNI, "astInitSelectorMap(%s): Region "
1597 "number %d does not refer to the same coordinate "
1598 "Frame as the first Region.", status, name, i + 1 );
1599 }
1600 }
1601 }
1602
1603 nin = astGetNin( regs[ 0 ] );
1604 f0 = astAnnul( f0 );
1605
1606 /* Initialise a Mapping structure (the parent class) as the first component
1607 within the SelectorMap structure, allocating memory if necessary. Specify
1608 the number of input and output coordinates and in which directions the
1609 Mapping should be defined. */
1610 if ( astOK ) {
1611 new = (AstSelectorMap *) astInitMapping( mem, size, 0,
1612 (AstMappingVtab *) vtab, name,
1613 nin, 1, 1, 0 );
1614 if ( astOK ) {
1615
1616 /* Initialise the SelectorMap data. */
1617 /* -------------------------------- */
1618
1619 /* Create an array for the Region pointers. */
1620 new->reg = astMalloc( sizeof( AstRegion * )*nreg );
1621
1622 /* Store pointers to deep copies of the Regions. */
1623 if( astOK ) {
1624 new->nreg = nreg;
1625 for( i = 0; i < nreg; i++ ) {
1626 new->reg[ i ] = astCopy( regs[ i ] );
1627 }
1628 } else {
1629 new->nreg = 0;
1630 }
1631
1632 /* Store other items */
1633 new->badval = badval;
1634
1635 /* If an error occurred, clean up by deleting the new object. */
1636 if ( !astOK ) new = astDelete( new );
1637 }
1638 }
1639
1640 /* Return a pointer to the new object. */
1641 return new;
1642 }
1643
astLoadSelectorMap_(void * mem,size_t size,AstSelectorMapVtab * vtab,const char * name,AstChannel * channel,int * status)1644 AstSelectorMap *astLoadSelectorMap_( void *mem, size_t size,
1645 AstSelectorMapVtab *vtab, const char *name,
1646 AstChannel *channel, int *status ) {
1647 /*
1648 *+
1649 * Name:
1650 * astLoadSelectorMap
1651
1652 * Purpose:
1653 * Load a SelectorMap.
1654
1655 * Type:
1656 * Protected function.
1657
1658 * Synopsis:
1659 * #include "selectormap.h"
1660 * AstSelectorMap *astLoadSelectorMap( void *mem, size_t size,
1661 * AstSelectorMapVtab *vtab, const char *name,
1662 * AstChannel *channel )
1663
1664 * Class Membership:
1665 * SelectorMap loader.
1666
1667 * Description:
1668 * This function is provided to load a new SelectorMap using data read
1669 * from a Channel. It first loads the data used by the parent class
1670 * (which allocates memory if necessary) and then initialises a
1671 * SelectorMap structure in this memory, using data read from the input
1672 * Channel.
1673 *
1674 * If the "init" flag is set, it also initialises the contents of a
1675 * virtual function table for a SelectorMap at the start of the memory
1676 * passed via the "vtab" parameter.
1677
1678
1679 * Parameters:
1680 * mem
1681 * A pointer to the memory into which the SelectorMap is to be
1682 * loaded. This must be of sufficient size to accommodate the
1683 * SelectorMap data (sizeof(SelectorMap)) plus any data used by derived
1684 * classes. If a value of NULL is given, this function will
1685 * allocate the memory itself using the "size" parameter to
1686 * determine its size.
1687 * size
1688 * The amount of memory used by the SelectorMap (plus derived class
1689 * data). This will be used to allocate memory if a value of
1690 * NULL is given for the "mem" parameter. This value is also
1691 * stored in the SelectorMap structure, so a valid value must be
1692 * supplied even if not required for allocating memory.
1693 *
1694 * If the "vtab" parameter is NULL, the "size" value is ignored
1695 * and sizeof(AstSelectorMap) is used instead.
1696 * vtab
1697 * Pointer to the start of the virtual function table to be
1698 * associated with the new SelectorMap. If this is NULL, a pointer to
1699 * the (static) virtual function table for the SelectorMap class is
1700 * used instead.
1701 * name
1702 * Pointer to a constant null-terminated character string which
1703 * contains the name of the class to which the new object
1704 * belongs (it is this pointer value that will subsequently be
1705 * returned by the astGetClass method).
1706 *
1707 * If the "vtab" parameter is NULL, the "name" value is ignored
1708 * and a pointer to the string "SelectorMap" is used instead.
1709
1710 * Returned Value:
1711 * A pointer to the new SelectorMap.
1712
1713 * Notes:
1714 * - A null pointer will be returned if this function is invoked
1715 * with the global error status set, or if it should fail for any
1716 * reason.
1717 *-
1718 */
1719
1720 /* Local Variables: */
1721 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1722 AstSelectorMap *new;
1723 AstFrameSet *fs;
1724 AstRegion *reg;
1725 int i;
1726 char buf[ 20 ];
1727
1728 /* Initialise. */
1729 new = NULL;
1730
1731 /* Check the global error status. */
1732 if ( !astOK ) return new;
1733
1734 /* Get a pointer to the thread specific global data structure. */
1735 astGET_GLOBALS(channel);
1736
1737 /* If a NULL virtual function table has been supplied, then this is
1738 the first loader to be invoked for this SelectorMap. In this case the
1739 SelectorMap belongs to this class, so supply appropriate values to be
1740 passed to the parent class loader (and its parent, etc.). */
1741 if ( !vtab ) {
1742 size = sizeof( AstSelectorMap );
1743 vtab = &class_vtab;
1744 name = "SelectorMap";
1745
1746 /* If required, initialise the virtual function table for this class. */
1747 if ( !class_init ) {
1748 astInitSelectorMapVtab( vtab, name );
1749 class_init = 1;
1750 }
1751 }
1752
1753 /* Invoke the parent class loader to load data for all the ancestral
1754 classes of the current one, returning a pointer to the resulting
1755 partly-built SelectorMap. */
1756 new = astLoadMapping( mem, size, (AstMappingVtab *) vtab, name,
1757 channel );
1758 if ( astOK ) {
1759
1760 /* Read input data. */
1761 /* ================ */
1762 /* Request the input Channel to read all the input data appropriate to
1763 this class into the internal "values list". */
1764 astReadClassData( channel, "SelectorMap" );
1765
1766 /* Now read each individual data item from this list and use it to
1767 initialise the appropriate instance variable(s) for this class. */
1768
1769 /* In the case of attributes, we first read the "raw" input value,
1770 supplying the "unset" value as the default. If a "set" value is
1771 obtained, we then use the appropriate (private) Set... member
1772 function to validate and set the value properly. */
1773
1774
1775 /* Loop to load each Region. */
1776 /* ------------------------- */
1777 new->reg = NULL;
1778 i = 0;
1779 fs = NULL;
1780 while( astOK ) {
1781 sprintf( buf, "reg%d", i + 1 );
1782 reg = astReadObject( channel, buf, NULL );
1783 if( reg ) {
1784 new->reg = astGrow( new->reg, i + 1, sizeof( AstRegion *) );
1785 if( astOK ) {
1786 new->reg[ i ] = reg;
1787
1788 /* All but the first Region may have a dummy FrameSet rather than the
1789 correct FrameSet. The correct FrameSet will be a copy of the FrameSet
1790 from the first Region. */
1791 if( i == 0 ) {
1792 fs = astGetRegFS( reg );
1793 } else if( astRegDummyFS( reg ) ){
1794 astSetRegFS( reg, fs );
1795 }
1796
1797 i++;
1798 }
1799 } else {
1800 break;
1801 }
1802 }
1803
1804 fs = astAnnul( fs );
1805
1806 /* Number of Regions. */
1807 new->nreg = i;
1808
1809
1810 /* BadVal. */
1811 /* ------- */
1812 new->badval = astReadDouble( channel, "badval", AST__BAD );
1813
1814 /* If an error occurred, clean up by deleting the new SelectorMap. */
1815 if ( !astOK ) new = astDelete( new );
1816 }
1817
1818 /* Return the new SelectorMap pointer. */
1819 return new;
1820 }
1821
1822 /* Virtual function interfaces. */
1823 /* ============================ */
1824 /* These provide the external interface to the virtual functions defined by
1825 this class. Each simply checks the global error status and then locates and
1826 executes the appropriate member function, using the function pointer stored
1827 in the object's virtual function table (this pointer is located using the
1828 astMEMBER macro defined in "object.h").
1829
1830 Note that the member function may not be the one defined here, as it may
1831 have been over-ridden by a derived class. However, it should still have the
1832 same interface. */
1833
1834 /* None. */
1835
1836
1837
1838
1839