1 /*
2 *class++
3 *  Name:
4 *     FrameSet
5 
6 *  Purpose:
7 *     Set of inter-related coordinate systems.
8 
9 *  Constructor Function:
10 c     astFrameSet
11 f     AST_FRAMESET
12 
13 *  Description:
14 *     A FrameSet consists of a set of one or more Frames (which
15 *     describe coordinate systems), connected together by Mappings
16 *     (which describe how the coordinate systems are inter-related). A
17 *     FrameSet makes it possible to obtain a Mapping between any pair
18 *     of these Frames (i.e. to convert between any of the coordinate
19 *     systems which it describes).  The individual Frames are
20 *     identified within the FrameSet by an integer index, with Frames
21 *     being numbered consecutively from one as they are added to the
22 *     FrameSet.
23 *
24 *     Every FrameSet has a "base" Frame and a "current" Frame (which
25 *     are allowed to be the same). Any of the Frames may be nominated
26 *     to hold these positions, and the choice is determined by the
27 *     values of the FrameSet's Base and Current attributes, which hold
28 *     the indices of the relevant Frames.  By default, the first Frame
29 *     added to a FrameSet is its base Frame, and the last one added is
30 *     its current Frame.
31 *
32 *     The base Frame describes the "native" coordinate system of
33 *     whatever the FrameSet is used to calibrate (e.g. the pixel
34 *     coordinates of an image) and the current Frame describes the
35 *     "apparent" coordinate system in which it should be viewed
36 *     (e.g. displayed, etc.). Any further Frames represent a library
37 *     of alternative coordinate systems, which may be selected by
38 *     making them current.
39 *
40 *     When a FrameSet is used in a context that requires a Frame,
41 *     (e.g. obtaining its Title value, or number of axes), the current
42 *     Frame is used. A FrameSet may therefore be used in place of its
43 *     current Frame in most situations.
44 *
45 *     When a FrameSet is used in a context that requires a Mapping,
46 *     the Mapping used is the one between its base Frame and its
47 *     current Frame. Thus, a FrameSet may be used to convert "native"
48 *     coordinates into "apparent" ones, and vice versa. Like any
49 c     Mapping, a FrameSet may also be inverted (see astInvert), which
50 f     Mapping, a FrameSet may also be inverted (see AST_INVERT), which
51 *     has the effect of interchanging its base and current Frames and
52 *     hence of reversing the Mapping between them.
53 *
54 *     Regions may be added into a FrameSet (since a Region is a type of
55 *     Frame), either explicitly or as components within CmpFrames. In this
56 *     case the Mapping between a pair of Frames within a FrameSet will
57 *     include the effects of the clipping produced by any Regions included
58 *     in the path between the Frames.
59 
60 *  Inheritance:
61 *     The FrameSet class inherits from the Frame class.
62 
63 *  Attributes:
64 *     In addition to those attributes common to all Frames, every
65 *     FrameSet also has the following attributes:
66 *
67 *     - AllVariants: List of all variant mappings store with current Frame
68 *     - Base: FrameSet base Frame index
69 *     - Current: FrameSet current Frame index
70 *     - Nframe: Number of Frames in a FrameSet
71 *     - Variant: Name of variant mapping in use by current Frame
72 
73 *     Every FrameSet also inherits any further attributes that belong
74 *     to its current Frame, regardless of that Frame's class. (For
75 *     example, the Equinox attribute, defined by the SkyFrame class, is
76 *     inherited by any FrameSet which has a SkyFrame as its current
77 *     Frame.) The set of attributes belonging to a FrameSet may therefore
78 *     change when a new current Frame is selected.
79 
80 *  Functions:
81 c     In addition to those functions applicable to all Frames, the
82 c     following functions may also be applied to all FrameSets:
83 f     In addition to those routines applicable to all Frames, the
84 f     following routines may also be applied to all FrameSets:
85 *
86 c     - astAddFrame: Add a Frame to a FrameSet to define a new coordinate
87 c     system
88 c     - astAddVariant: Add a variant Mapping to the current Frame
89 c     - astGetFrame: Obtain a pointer to a specified Frame in a FrameSet
90 c     - astGetMapping: Obtain a Mapping between two Frames in a FrameSet
91 c     - astMirrorVariants: Make the current Frame mirror variant Mappings in another Frame
92 c     - astRemapFrame: Modify a Frame's relationship to the other Frames in a
93 c     FrameSet
94 c     - astRemoveFrame: Remove a Frame from a FrameSet
95 f     - AST_ADDFRAME: Add a Frame to a FrameSet to define a new coordinate
96 f     system
97 f     - AST_ADDVARIANT: Add a variant Mapping to the current Frame
98 f     - AST_GETFRAME: Obtain a pointer to a specified Frame in a FrameSet
99 f     - AST_GETMAPPING: Obtain a Mapping between two Frames in a FrameSet
100 f     - AST_MIRRORVARIANTS: Make the current Frame mirror variant Mappings in another Frame
101 f     - AST_REMAPFRAME: Modify a Frame's relationship to the other Frames in a
102 f     FrameSet
103 f     - AST_REMOVEFRAME: Remove a Frame from a FrameSet
104 
105 *  Copyright:
106 *     Copyright (C) 1997-2006 Council for the Central Laboratory of the
107 *     Research Councils
108 
109 *  Licence:
110 *     This program is free software: you can redistribute it and/or
111 *     modify it under the terms of the GNU Lesser General Public
112 *     License as published by the Free Software Foundation, either
113 *     version 3 of the License, or (at your option) any later
114 *     version.
115 *
116 *     This program is distributed in the hope that it will be useful,
117 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
118 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
119 *     GNU Lesser General Public License for more details.
120 *
121 *     You should have received a copy of the GNU Lesser General
122 *     License along with this program.  If not, see
123 *     <http://www.gnu.org/licenses/>.
124 
125 *  Authors:
126 *     RFWS: R.F. Warren-Smith (Starlink)
127 
128 *  History:
129 *     16-FEB-1996 (RFWS):
130 *        Original version.
131 *     5-JUN-1996 (RFWS):
132 *        Tidied up, etc.
133 *     2-JUL-1996 (RFWS):
134 *        Fixed bug in astRemoveFrame which caused the base/current
135 *        Frame index to be wrong.
136 *     12-JUL-1996 (RFWS):
137 *        Over-ride the astReportPoints method to provide
138 *        Frame-specific formatting.
139 *     12-AUG-1996 (RFWS):
140 *        Upgraded to provide a public interface, plus improvements to
141 *        astAlign and the handling of nodes as Frames are
142 *        added/removed.
143 *     11-SEP-1996 (RFWS):
144 *        Added Gap.
145 *     25-SEP-1996 (RFWS):
146 *        Added I/O facilities.
147 *     30-MAY-1997 (RFWS):
148 *        Add special treatment for the ID attribute (which is not
149 *        derived from the current Frame).
150 *     10-JUN-1997 (RFWS):
151 *        Rationalised the astConvert implementation.
152 *     11-JUN-1997 (RFWS):
153 *        Added the FindFrame implementation.
154 *     27-JUN-1997 (RFWS):
155 *        Fixed bug which caused certain Mapping attributes to be
156 *        handled by the current Frame instead of by the member
157 *        functions defined by this class.
158 *     3-JUL-1997 (RFWS):
159 *        Fixed bug: failing to extend the invert array in
160 *        astRemapFrame.
161 *     10-JUL-1997 (RFWS):
162 *        Over-ride the astSimplify method.
163 *     14-NOV-1997 (RFWS):
164 *        Fixed error in loop implementing search over domains in
165 *        FindFrame.
166 *     20-NOV-1997 (RFWS):
167 *        Fixed bug in default Base and Current attribute values when a
168 *        FrameSet has been inverted.
169 *     20-NOV-1997 (RFWS):
170 *        Modified astConvert to use the current Frame of the "to"
171 *        FrameSet as the destination coordinate system (instead of the
172 *        base Frame) and to modify its Base attribute instead of its
173 *        Current attribute.
174 *     22-DEC-1997 (RFWS):
175 *        Further modified astConvert to convert from the Current Frame
176 *        of the "from" FrameSet and to modify its Base
177 *        attribute. Frame search order also reversed if the Invert
178 *        attribute is non-zero for either FrameSet.
179 *     19-JAN-1998 (RFWS):
180 *        Installed the TidyNodes function.
181 *     20-JAN-1998 (RFWS):
182 *        Implemented preservation of FrameSet integrity when attribute
183 *        values associated with the current Frame are modified.
184 *     24-FEB-1998 (RFWS):
185 *        Added the ForceCopy function to allow integrity to be preserved
186 *        when there are multiple references to the same Frame.
187 *     25-FEB-1998 (RFWS):
188 *        Over-ride the astUnformat method.
189 *     24-MAR-1998 (RFWS):
190 *        Fixed unterminated comment causing problems in CombineMaps.
191 *     6-APR-1998 (RFWS):
192 *        Fixed another unterminated comment in CombineMaps.
193 *     27-MAY-1998 (RFWS):
194 *        Fixed bug: failure to record new invert flag value after
195 *        simplifying a CmpMap in TidyNodes.
196 *     17-DEC-2002 (DSB):
197 *        Override accessors for Frame attributes Top, Bottom, Epoch,
198 *        System, AlignSystem and ActiveUnit.
199 *     8-JAN-2003 (DSB):
200 *        Changed private InitVtab method to protected astInitFrameSetVtab
201 *        method.
202 *     24-JAN-2004 (DSB):
203 *        o  Override the astFields method.
204 *        o  Add argument "fmt" to Abbrev.
205 *     23-MAR-2004 (DSB):
206 *        Modified astGetMapping and Span to include the clipping effect of
207 *        any Regions in the path between the two supplied Frames.
208 *     24-AUG-2004 (DSB):
209 *        - Override various methods inherited from Frame (astAngle,
210 *	astAxAngle, astAxDistance, astAxOffset, astCheckPerm, astOffset2,
211 *	astResolve, astSystemCode, astSystemString, astValidateSystem,
212 *	astValidateAxisSelection). These should have been overridden a
213 *       long time ago!
214 *     8-SEP-2004 (DSB):
215 *       Override astResolvePoints.
216 *     12-MAY-2005 (DSB):
217 *        Override astNormBox method.
218 *     12-AUG-2005 (DSB):
219 *        Override ObsLat and ObsLon accessor methods.
220 *     14-FEB-2006 (DSB):
221 *        Override astGetObjSize.
222 *     15-MAY-2006 (DSB):
223 *        Override astEqual.
224 *     30-JUN-2006 (DSB):
225 *        Allow astAbbrev to have a null "str1" value.
226 *     22-JUN-2007 (DSB):
227 *        Modify VSet to avoid using the args va_list twice since the
228 *        first use (by the parent VSet function) invalidates the va_list
229 *        causing a segvio to be generated by the second use (when
230 *        formatting an error message).
231 *     11-JAN-2008 (DSB):
232 *        Override the astRate method.
233 *     17-NOV-2008 (DSB):
234 *        Correct parent class in invocation of astMAKE_ISA.
235 *     14-JAN-2009 (DSB):
236 *        Override the astIntersect method.
237 *     18-JUN-2009 (DSB):
238 *        Override ObsAlt accessor methods.
239 *     30-OCT-2009 (DSB):
240 *        Make the Ident attribute relate to the FrameSet, not the current
241 *        Frame.
242 *     22-MAR-2011 (DSB):
243 *        Override astFrameGrid method.
244 *     29-APR-2011 (DSB):
245 *        Prevent astFindFrame from matching a subclass template against a
246 *        superclass target.
247 *     2-SEP-2011 (DSB):
248 *        Fix FrameSet implememntation of astEqual (mapping comparison
249 *        tests were logically inverted).
250 *     3-OCT-2012 (DSB):
251 *        Fix bug in AppendAxes that could cause internal Mappings to
252 *        be inverted unintentionally when astAddFrame is called with
253 *        iframe=AST__ALLFRAMES.
254 *     29-APR-2013 (DSB):
255 *        Added attributes AllVariants and Variant. Also added methods
256 *        astAddVariant and astMirrorVariants.
257 *class--
258 */
259 
260 /* Module Macros. */
261 /* ============== */
262 /* Set the name of the class we are implementing. This indicates to
263    the header files that define class interfaces that they should make
264    "protected" symbols available. */
265 #define astCLASS FrameSet
266 
267 #define GETALLVARIANTS_BUFF_LEN 200
268 
269 /*
270 *  Name:
271 *     MAKE_CLEAR
272 
273 *  Purpose:
274 *     Define a function to clear an attribute value for a FrameSet.
275 
276 *  Type:
277 *     Private macro.
278 
279 *  Synopsis:
280 *     #include "frameset.h"
281 *     MAKE_CLEAR(attribute)
282 
283 *  Class Membership:
284 *     Defined by the FrameSet class.
285 
286 *  Description:
287 *     This macro expands to an implementation of a private member function
288 *     of the form:
289 *
290 *        static void Clear<Attribute>( AstFrame *this )
291 *
292 *     that clears the value of a specified attribute for the current Frame
293 *     of a FrameSet (this). This function is intended to over-ride the
294 *     astClear<Attribute> method inherited from the Frame class.
295 
296 *  Parameters:
297 *     attribute
298 *        Name of the attribute, as it appears in the function name.
299 */
300 
301 /* Define the macro. */
302 #define MAKE_CLEAR(attribute) \
303 static void Clear##attribute( AstFrame *this_frame, int *status ) { \
304 \
305 /* Local Variables: */ \
306    AstFrame *fr;                 /* Pointer to current Frame */ \
307    AstFrameSet *this;            /* Pointer to the FrameSet structure */ \
308 \
309 /* Check the global error status. */ \
310    if ( !astOK ) return; \
311 \
312 /* Obtain a pointer to the FrameSet structure. */ \
313    this = (AstFrameSet *) this_frame; \
314 \
315 /* Obtain a pointer to the current Frame and invoke its astClear<Attribute> \
316    method. Annul the Frame pointer afterwards. */ \
317    fr = astGetFrame( this, AST__CURRENT ); \
318    astClear##attribute( fr ); \
319    fr = astAnnul( fr ); \
320 }
321 
322 /*
323 *  Name:
324 *     MAKE_CLEAR_AXIS
325 
326 *  Purpose:
327 *     Define a function to clear an attribute value for a FrameSet axis.
328 
329 *  Type:
330 *     Private macro.
331 
332 *  Synopsis:
333 *     #include "frameset.h"
334 *     MAKE_CLEAR_AXIS(attribute)
335 
336 *  Class Membership:
337 *     Defined by the FrameSet class.
338 
339 *  Description:
340 *     This macro expands to an implementation of a private member function
341 *     of the form:
342 *
343 *        static void Clear<Attribute>( AstFrame *this, int axis )
344 *
345 *     that clears the value of a specified attribute for an axis of
346 *     the current Frame of a FrameSet (this). This function is
347 *     intended to over-ride the astClear<Attribute> method inherited
348 *     from the Frame class.
349 
350 *  Parameters:
351 *     attribute
352 *        Name of the attribute, as it appears in the function name.
353 */
354 
355 /* Define the macro. */
356 #define MAKE_CLEAR_AXIS(attribute) \
357 static void Clear##attribute( AstFrame *this_frame, int axis, int *status ) { \
358 \
359 /* Local Variables: */ \
360    AstFrame *fr;                 /* Pointer to current Frame */ \
361    AstFrameSet *this;            /* Pointer to the FrameSet structure */ \
362 \
363 /* Check the global error status. */ \
364    if ( !astOK ) return; \
365 \
366 /* Obtain a pointer to the FrameSet structure. */ \
367    this = (AstFrameSet *) this_frame; \
368 \
369 /* Validate the axis index supplied. */ \
370    (void) astValidateAxis( this, axis, 1, "astClear" #attribute ); \
371 \
372 /* Obtain a pointer to the FrameSet's current Frame and invoke its \
373    astClear<Attribute> method. Annul the Frame pointer afterwards. */ \
374    fr = astGetFrame( this, AST__CURRENT ); \
375    astClear##attribute( fr, axis ); \
376    fr = astAnnul( fr ); \
377 }
378 
379 /*
380 *  Name:
381 *     MAKE_GET
382 
383 *  Purpose:
384 *     Define a function to get an attribute value for a FrameSet.
385 
386 *  Type:
387 *     Private macro.
388 
389 *  Synopsis:
390 *     #include "frameset.h"
391 *     MAKE_GET(attribute,type)
392 
393 *  Class Membership:
394 *     Defined by the FrameSet class.
395 
396 *  Description:
397 *     This macro expands to an implementation of a private member function
398 *     of the form:
399 *
400 *        static <type> Get<Attribute>( AstFrame *this )
401 *
402 *     that gets the value of a specified attribute for the current Frame
403 *     of a FrameSet (this). This function is intended to over-ride the
404 *     astGet<Attribute> method inherited from the Frame class.
405 
406 *  Parameters:
407 *     attribute
408 *        Name of the attribute, as it appears in the function name.
409 *     type
410 *        The C type of the attribute.
411 */
412 
413 /* Define the macro. */
414 #define MAKE_GET(attribute,type) \
415 static type Get##attribute( AstFrame *this_frame, int *status ) { \
416 \
417 /* Local Variables: */ \
418    AstFrame *fr;                 /* Pointer to current Frame */ \
419    AstFrameSet *this;            /* Pointer to the FrameSet structure */ \
420    type result;                  /* Value to return */ \
421 \
422 /* Check the global error status. */ \
423    if ( !astOK ) return (type) 0; \
424 \
425 /* Obtain a pointer to the FrameSet structure. */ \
426    this = (AstFrameSet *) this_frame; \
427 \
428 /* Obtain a pointer to the current Frame and invoke its \
429    astGet<Attribute> method.  Annul the Frame pointer afterwards. */ \
430    fr = astGetFrame( this, AST__CURRENT ); \
431    result = astGet##attribute( fr ); \
432    fr = astAnnul( fr ); \
433 \
434 /* If an error occurred, clear the result value. */ \
435    if ( !astOK ) result = (type) 0; \
436 \
437 /* Return the result. */ \
438    return result; \
439 }
440 
441 /*
442 *  Name:
443 *     MAKE_GET_AXIS
444 
445 *  Purpose:
446 *     Define a function to get an attribute value for a FrameSet axis.
447 
448 *  Type:
449 *     Private macro.
450 
451 *  Synopsis:
452 *     #include "frameset.h"
453 *     MAKE_GET_AXIS(attribute,type)
454 
455 *  Class Membership:
456 *     Defined by the FrameSet class.
457 
458 *  Description:
459 *     This macro expands to an implementation of a private member function
460 *     of the form:
461 *
462 *        static <type> Get<Attribute>( AstFrame *this, int axis )
463 *
464 *     that gets the value of a specified attribute for an axis of the
465 *     current Frame of a FrameSet (this). This function is intended to
466 *     over-ride the astGet<Attribute> method inherited from the Frame
467 *     class.
468 
469 *  Parameters:
470 *     attribute
471 *        Name of the attribute, as it appears in the function name.
472 *     type
473 *        The C type of the attribute.
474 */
475 
476 /* Define the macro. */
477 #define MAKE_GET_AXIS(attribute,type) \
478 static type Get##attribute( AstFrame *this_frame, int axis, int *status ) { \
479 \
480 /* Local Variables: */ \
481    AstFrame *fr;                 /* Pointer to current Frame */ \
482    AstFrameSet *this;            /* Pointer to the FrameSet structure */ \
483    type result;                  /* Value to return */ \
484 \
485 /* Check the global error status. */ \
486    if ( !astOK ) return (type) 0; \
487 \
488 /* Obtain a pointer to the FrameSet structure. */ \
489    this = (AstFrameSet *) this_frame; \
490 \
491 /* Validate the axis index supplied. */ \
492    (void) astValidateAxis( this, axis, 1, "astGet" #attribute ); \
493 \
494 /* Obtain a pointer to the FrameSet's current Frame and invoke its \
495    astGet<Attribute> method.  Annul the Frame pointer afterwards. */ \
496    fr = astGetFrame( this, AST__CURRENT ); \
497    result = astGet##attribute( fr, axis ); \
498    fr = astAnnul( fr ); \
499 \
500 /* If an error occurred, clear the result value. */ \
501    if ( !astOK ) result = (type) 0; \
502 \
503 /* Return the result. */ \
504    return result; \
505 }
506 
507 /*
508 *  Name:
509 *     MAKE_SET
510 
511 *  Purpose:
512 *     Define a function to set an attribute value for a FrameSet.
513 
514 *  Type:
515 *     Private macro.
516 
517 *  Synopsis:
518 *     #include "frameset.h"
519 *     MAKE_SET(attribute,type)
520 
521 *  Class Membership:
522 *     Defined by the FrameSet class.
523 
524 *  Description:
525 *     This macro expands to an implementation of a private member function
526 *     of the form:
527 *
528 *        static void Set<Attribute>( AstFrame *this, <type> value )
529 *
530 *     that sets the value of a specified attribute for the current Frame
531 *     of a FrameSet (this). This function is intended to over-ride the
532 *     astSet<Attribute> method inherited from the Frame class.
533 
534 *  Parameters:
535 *     attribute
536 *        Name of the attribute, as it appears in the function name.
537 *     type
538 *        The C type of the attribute.
539 */
540 
541 /* Define the macro. */
542 #define MAKE_SET(attribute,type) \
543 static void Set##attribute( AstFrame *this_frame, type value, int *status ) { \
544 \
545 /* Local Variables: */ \
546    AstFrame *fr;                 /* Pointer to current Frame */ \
547    AstFrameSet *this;            /* Pointer to the FrameSet structure */ \
548 \
549 /* Check the global error status. */ \
550    if ( !astOK ) return; \
551 \
552 /* Obtain a pointer to the FrameSet structure. */ \
553    this = (AstFrameSet *) this_frame; \
554 \
555 /* Obtain a pointer to the FrameSet's current Frame and invoke its \
556    astSet<Attribute> method.  Annul the Frame pointer afterwards. */ \
557    fr = astGetFrame( this, AST__CURRENT ); \
558    astSet##attribute( fr, value ); \
559    fr = astAnnul( fr ); \
560 }
561 
562 /*
563 *  Name:
564 *     MAKE_SET_AXIS
565 
566 *  Purpose:
567 *     Define a function to set an attribute value for a FrameSet axis.
568 
569 *  Type:
570 *     Private macro.
571 
572 *  Synopsis:
573 *     #include "frameset.h"
574 *     MAKE_SET_AXIS(attribute,type)
575 
576 *  Class Membership:
577 *     Defined by the FrameSet class.
578 
579 *  Description:
580 *     This macro expands to an implementation of a private member function
581 *     of the form:
582 *
583 *        static void Set<Attribute>( AstFrame *this, int axis, <type> value )
584 *
585 *     that sets the value of a specified attribute for an axis of the
586 *     current Frame of a FrameSet (this). This function is intended to
587 *     over-ride the astSet<Attribute> method inherited from the Frame
588 *     class.
589 
590 *  Parameters:
591 *     attribute
592 *        Name of the attribute, as it appears in the function name.
593 *     type
594 *        The C type of the attribute.
595 */
596 
597 /* Define the macro. */
598 #define MAKE_SET_AXIS(attribute,type) \
599 static void Set##attribute( AstFrame *this_frame, int axis, type value, int *status ) { \
600 \
601 /* Local Variables: */ \
602    AstFrame *fr;                 /* Pointer to current Frame */ \
603    AstFrameSet *this;            /* Pointer to the FrameSet structure */ \
604 \
605 /* Check the global error status. */ \
606    if ( !astOK ) return; \
607 \
608 /* Obtain a pointer to the FrameSet structure. */ \
609    this = (AstFrameSet *) this_frame; \
610 \
611 /* Validate the axis index supplied. */ \
612    (void) astValidateAxis( this, axis, 1, "astSet" #attribute ); \
613 \
614 /* Obtain a pointer to the FrameSet's current Frame and invoke its \
615    astSet<Attribute> method.  Annul the Frame pointer afterwards. */ \
616    fr = astGetFrame( this, AST__CURRENT ); \
617    astSet##attribute( fr, axis, value ); \
618    fr = astAnnul( fr ); \
619 }
620 
621 /*
622 *  Name:
623 *     MAKE_TEST
624 
625 *  Purpose:
626 *     Define a function to test if an attribute value is set for a FrameSet.
627 
628 *  Type:
629 *     Private macro.
630 
631 *  Synopsis:
632 *     #include "frameset.h"
633 *     MAKE_TEST(attribute)
634 
635 *  Class Membership:
636 *     Defined by the FrameSet class.
637 
638 *  Description:
639 *     This macro expands to an implementation of a private member function
640 *     of the form:
641 *
642 *        static int Test<Attribute>( AstFrame *this )
643 *
644 *     that returns a boolean result (0 or 1) to indicate if the value
645 *     of a specified attribute for the current Frame of a FrameSet
646 *     (this) is set. This function is intended to over-ride the
647 *     astTest<Attribute> method inherited from the Frame class.
648 
649 *  Parameters:
650 *     attribute
651 *        Name of the attribute, as it appears in the function name.
652 */
653 
654 /* Define the macro. */
655 #define MAKE_TEST(attribute) \
656 static int Test##attribute( AstFrame *this_frame, int *status ) { \
657 \
658 /* Local Variables: */ \
659    AstFrame *fr;                 /* Pointer to current Frame */ \
660    AstFrameSet *this;            /* Pointer to FrameSet structure */ \
661    int result;                   /* Result to return */ \
662 \
663 /* Check the global error status. */ \
664    if ( !astOK ) return 0; \
665 \
666 /* Obtain a pointer to the FrameSet structure. */ \
667    this = (AstFrameSet *) this_frame; \
668 \
669 /* Obtain a pointer to the FrameSet's current Frame and invoke its \
670    astTest<Attribute> method.  Annul the Frame pointer afterwards. */ \
671    fr = astGetFrame( this, AST__CURRENT ); \
672    result = astTest##attribute( fr ); \
673    fr = astAnnul( fr ); \
674 \
675 /* If an error occurred, clear the result value. */ \
676    if ( !astOK ) result = 0; \
677 \
678 /* Return the result. */ \
679    return result; \
680 }
681 
682 /*
683 *  Name:
684 *     MAKE_TEST_AXIS
685 
686 *  Purpose:
687 *     Define a function to test if an attribute value is set for a FrameSet
688 *     axis.
689 
690 *  Type:
691 *     Private macro.
692 
693 *  Synopsis:
694 *     #include "frameset.h"
695 *     MAKE_TEST_AXIS(attribute)
696 
697 *  Class Membership:
698 *     Defined by the FrameSet class.
699 
700 *  Description:
701 *     This macro expands to an implementation of a private member function
702 *     of the form:
703 *
704 *        static int Test<Attribute>( AstFrame *this, int axis )
705 *
706 *     that returns a boolean result (0 or 1) to indicate if the value
707 *     of a specified attribute for an axis of the current Frame of a
708 *     FrameSet (this) is set. This function is intended to over-ride
709 *     the astTest<Attribute> method inherited from the Frame class.
710 
711 *  Parameters:
712 *     attribute
713 *        Name of the attribute, as it appears in the function name.
714 */
715 
716 /* Define the macro. */
717 #define MAKE_TEST_AXIS(attribute) \
718 static int Test##attribute( AstFrame *this_frame, int axis, int *status ) { \
719 \
720 /* Local Variables: */ \
721    AstFrame *fr;                 /* Pointer to current Frame */ \
722    AstFrameSet *this;            /* Pointer to the FrameSet structure */ \
723    int result;                   /* Value to return */ \
724 \
725 /* Check the global error status. */ \
726    if ( !astOK ) return 0; \
727 \
728 /* Obtain a pointer to the FrameSet structure. */ \
729    this = (AstFrameSet *) this_frame; \
730 \
731 /* Validate the axis index supplied. */ \
732    (void) astValidateAxis( this, axis, 1, "astTest" #attribute ); \
733 \
734 /* Obtain a pointer to the FrameSet's current Frame and invoke its \
735    astTest<Attribute> method.  Annul the Frame pointer afterwards. */ \
736    fr = astGetFrame( this, AST__CURRENT ); \
737    result = astTest##attribute( fr, axis ); \
738    fr = astAnnul( fr ); \
739 \
740 /* If an error occurred, clear the result value. */ \
741    if ( !astOK ) result = 0; \
742 \
743 /* Return the result. */ \
744    return result; \
745 }
746 
747 /* Header files. */
748 /* ============= */
749 /* Interface definitions. */
750 /* ---------------------- */
751 
752 #include "globals.h"             /* Thread-safe global data access */
753 #include "error.h"               /* Error reporting facilities */
754 #include "memory.h"              /* Memory allocation facilities */
755 #include "object.h"              /* Base Object class */
756 #include "mapping.h"             /* Coordinate Mappings */
757 #include "unitmap.h"             /* Unit Mappings */
758 #include "permmap.h"             /* Coordinate permutation Mappings */
759 #include "cmpmap.h"              /* Compound Mappings */
760 #include "frame.h"               /* Parent Frame class */
761 #include "frameset.h"            /* Interface definition for this class */
762 #include "cmpframe.h"            /* Compound coordinate frames */
763 
764 /* Error code definitions. */
765 /* ----------------------- */
766 #include "ast_err.h"             /* AST error codes */
767 
768 /* C header files. */
769 /* --------------- */
770 #include <ctype.h>
771 #include <limits.h>
772 #include <stdarg.h>
773 #include <stddef.h>
774 #include <stdio.h>
775 #include <string.h>
776 
777 /* Module Variables. */
778 /* ================= */
779 
780 /* Address of this static variable is used as a unique identifier for
781    member of this class. */
782 static int class_check;
783 
784 /* Pointers to parent class methods which are extended by this class. */
785 static int (* parent_getobjsize)( AstObject *, int * );
786 static void (* parent_clear)( AstObject *, const char *, int * );
787 static int (* parent_getusedefs)( AstObject *, int * );
788 static void (* parent_vset)( AstObject *, const char *, char **, va_list, int * );
789 
790 #if defined(THREAD_SAFE)
791 static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * );
792 #endif
793 
794 /* Define macros for accessing each item of thread specific global data. */
795 #ifdef THREAD_SAFE
796 
797 /* Define how to initialise thread-specific globals. */
798 #define GLOBAL_inits \
799    globals->Class_Init = 0; \
800    globals->GetAttrib_Buff[ 0 ] = 0; \
801    globals->Integrity_Frame = NULL; \
802    globals->Integrity_Method = ""; \
803    globals->Integrity_Lost = 0; \
804    globals->GetAllVariants_Buff[ 0 ] = 0; \
805 
806 /* Create the function that initialises global data for this module. */
807 astMAKE_INITGLOBALS(FrameSet)
808 
809 /* Define macros for accessing each item of thread specific global data. */
810 #define class_init astGLOBAL(FrameSet,Class_Init)
811 #define class_vtab astGLOBAL(FrameSet,Class_Vtab)
812 #define getattrib_buff astGLOBAL(FrameSet,GetAttrib_Buff)
813 #define integrity_frame astGLOBAL(FrameSet,Integrity_Frame)
814 #define integrity_method astGLOBAL(FrameSet,Integrity_Method)
815 #define integrity_lost astGLOBAL(FrameSet,Integrity_Lost)
816 #define getallvariants_buff astGLOBAL(FrameSet,GetAllVariants_Buff)
817 
818 
819 
820 /* If thread safety is not needed, declare and initialise globals at static
821    variables. */
822 #else
823 
824 /* Buffer returned by GetAttrib. */
825 static char getattrib_buff[ AST__FRAMESET_GETATTRIB_BUFF_LEN + 1 ];
826 
827 /* Variables associated with preserving FrameSet integrity. */
828 static AstFrame *integrity_frame = NULL; /* Pointer to copy of current Frame */
829 static const char *integrity_method = ""; /* Name of method being used */
830 static int integrity_lost = 0;   /* Current Frame modified? */
831 
832 
833 /* Define the class virtual function table and its initialisation flag
834    as static variables. */
835 static AstFrameSetVtab class_vtab;   /* Virtual function table */
836 static int class_init = 0;       /* Virtual function table initialised? */
837 
838 /* String buffers. */
839 static char getallvariants_buff[ AST__FRAMESET_GETALLVARIANTS_BUFF_LEN + 1 ];
840 
841 #endif
842 
843 
844 /* Prototypes for Private Member Functions. */
845 /* ======================================== */
846 static AstAxis *GetAxis( AstFrame *, int, int * );
847 static AstFrame *GetFrame( AstFrameSet *, int, int * );
848 static AstFrame *PickAxes( AstFrame *, int, const int[], AstMapping **, int * );
849 static AstFrameSet *Convert( AstFrame *, AstFrame *, const char *, int * );
850 static AstFrameSet *ConvertX( AstFrame *, AstFrame *, const char *, int * );
851 static AstFrameSet *FindFrame( AstFrame *, AstFrame *, const char *, int * );
852 static AstLineDef *LineDef( AstFrame *, const double[2], const double[2], int * );
853 static AstMapping *CombineMaps( AstMapping *, int, AstMapping *, int, int, int * );
854 static AstMapping *GetMapping( AstFrameSet *, int, int, int * );
855 static AstMapping *RemoveRegions( AstMapping *, int * );
856 static AstMapping *Simplify( AstMapping *, int * );
857 static AstObject *Cast( AstObject *, AstObject *, int * );
858 static AstPointSet *FrameGrid( AstFrame *, int, const double *, const double *, int * );
859 static AstPointSet *ResolvePoints( AstFrame *, const double [], const double [], AstPointSet *, AstPointSet *, int * );
860 static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
861 static AstSystemType SystemCode( AstFrame *, const char *, int * );
862 static AstSystemType ValidateSystem( AstFrame *, AstSystemType, const char *, int * );
863 static const char *Abbrev( AstFrame *, int, const char *, const char *, const char *, int * );
864 static const char *Format( AstFrame *, int, double, int * );
865 static const char *GetAttrib( AstObject *, const char *, int * );
866 static const char *GetDomain( AstFrame *, int * );
867 static const char *GetFormat( AstFrame *, int, int * );
868 static const char *GetLabel( AstFrame *, int, int * );
869 static const char *GetSymbol( AstFrame *, int, int * );
870 static const char *GetTitle( AstFrame *, int * );
871 static const char *GetUnit( AstFrame *, int, int * );
872 static const char *GetAllVariants( AstFrameSet *, int * );
873 static const char *SystemString( AstFrame *, AstSystemType, int * );
874 static const int *GetPerm( AstFrame *, int * );
875 static double Angle( AstFrame *, const double[], const double[], const double[], int * );
876 static double AxAngle( AstFrame *, const double[], const double[], int, int * );
877 static double AxDistance( AstFrame *, int, double, double, int * );
878 static double AxOffset( AstFrame *, int, double, double, int * );
879 static double Distance( AstFrame *, const double[], const double[], int * );
880 static double Gap( AstFrame *, int, double, int *, int * );
881 static double Offset2( AstFrame *, const double[2], double, double, double[2], int * );
882 static double Rate( AstMapping *, double *, int, int, int * );
883 static int *MapSplit( AstMapping *, int, const int *, AstMapping **, int * );
884 static int Equal( AstObject *, AstObject *, int * );
885 static int Fields( AstFrame *, int, const char *, const char *, int, char **, int *, double *, int * );
886 static int ForceCopy( AstFrameSet *, int, int * );
887 static int GetActiveUnit( AstFrame *, int * );
888 static int GetBase( AstFrameSet *, int * );
889 static int GetCurrent( AstFrameSet *, int * );
890 static int GetDigits( AstFrame *, int * );
891 static int GetDirection( AstFrame *, int, int * );
892 static int GetIsLinear( AstMapping *, int * );
893 static int GetMatchEnd( AstFrame *, int * );
894 static int GetMaxAxes( AstFrame *, int * );
895 static int GetMinAxes( AstFrame *, int * );
896 static int GetNaxes( AstFrame *, int * );
897 static int GetNframe( AstFrameSet *, int * );
898 static int GetNin( AstMapping *, int * );
899 static int GetNout( AstMapping *, int * );
900 static int GetObjSize( AstObject *, int * );
901 static int GetPermute( AstFrame *, int * );
902 static int GetPreserveAxes( AstFrame *, int * );
903 static int GetTranForward( AstMapping *, int * );
904 static int GetTranInverse( AstMapping *, int * );
905 static int GetVarFrm( AstFrameSet *, int, int * );
906 static int IsUnitFrame( AstFrame *, int * );
907 static int LineContains( AstFrame *, AstLineDef *, int, double *, int * );
908 static int LineCrossing( AstFrame *, AstLineDef *, AstLineDef *, double **, int * );
909 static int Match( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * );
910 static int Span( AstFrameSet *, AstFrame **, int, int, int, AstMapping **, int *, int * );
911 static int SubFrame( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * );
912 static int TestActiveUnit( AstFrame *, int * );
913 static int TestAttrib( AstObject *, const char *, int * );
914 static int TestBase( AstFrameSet *, int * );
915 static int TestCurrent( AstFrameSet *, int * );
916 static int TestDigits( AstFrame *, int * );
917 static int TestDirection( AstFrame *, int, int * );
918 static int TestDomain( AstFrame *, int * );
919 static int TestFormat( AstFrame *, int, int * );
920 static int TestLabel( AstFrame *, int, int * );
921 static int TestMatchEnd( AstFrame *, int * );
922 static int TestMaxAxes( AstFrame *, int * );
923 static int TestMinAxes( AstFrame *, int * );
924 static int TestPermute( AstFrame *, int * );
925 static int TestPreserveAxes( AstFrame *, int * );
926 static int TestSymbol( AstFrame *, int, int * );
927 static int TestTitle( AstFrame *, int * );
928 static int TestUnit( AstFrame *, int, int * );
929 static int Unformat( AstFrame *, int, const char *, double *, int * );
930 static int ValidateAxis( AstFrame *, int, int, const char *, int * );
931 static int ValidateFrameIndex( AstFrameSet *, int, const char *, int * );
932 static void AddFrame( AstFrameSet *, int, AstMapping *, AstFrame *, int * );
933 static void AppendAxes( AstFrameSet *, AstFrame *, int * );
934 static void CheckPerm( AstFrame *, const int *, const char *, int * );
935 static void Clear( AstObject *, const char *, int * );
936 static void ClearAttrib( AstObject *, const char *, int * );
937 static void ClearBase( AstFrameSet *, int * );
938 static void ClearCurrent( AstFrameSet *, int * );
939 static void ClearDigits( AstFrame *, int * );
940 static void ClearDirection( AstFrame *, int, int * );
941 static void ClearDomain( AstFrame *, int * );
942 static void ClearFormat( AstFrame *, int, int * );
943 static void ClearLabel( AstFrame *, int, int * );
944 static void ClearMatchEnd( AstFrame *, int * );
945 static void ClearMaxAxes( AstFrame *, int * );
946 static void ClearMinAxes( AstFrame *, int * );
947 static void ClearPermute( AstFrame *, int * );
948 static void ClearPreserveAxes( AstFrame *, int * );
949 static void ClearSymbol( AstFrame *, int, int * );
950 static void ClearTitle( AstFrame *, int * );
951 static void ClearUnit( AstFrame *, int, int * );
952 static void Copy( const AstObject *, AstObject *, int * );
953 static void Delete( AstObject *, int * );
954 static void Dump( AstObject *, AstChannel *, int * );
955 static void Intersect( AstFrame *, const double[2], const double[2], const double[2], const double[2], double[2], int * );
956 static void LineOffset( AstFrame *, AstLineDef *, double, double, double[2], int * );
957 static void MatchAxes( AstFrame *, AstFrame *, int *, int * );
958 static void MatchAxesX( AstFrame *, AstFrame *, int *, int * );
959 static void Norm( AstFrame *, double[], int * );
960 static void NormBox( AstFrame *, double[], double[], AstMapping *, int * );
961 static void Offset( AstFrame *, const double[], const double[], double, double[], int * );
962 static void Overlay( AstFrame *, const int *, AstFrame *, int * );
963 static void PermAxes( AstFrame *, const int[], int * );
964 static void PrimaryFrame( AstFrame *, int, AstFrame **, int *, int * );
965 static void RecordIntegrity( AstFrameSet *, int * );
966 static void AddVariant( AstFrameSet *, AstMapping *, const char *, int * );
967 static void MirrorVariants( AstFrameSet *, int, int * );
968 static void RemapFrame( AstFrameSet *, int, AstMapping *, int * );
969 static void RemoveFrame( AstFrameSet *, int, int * );
970 static void RemoveMirrors( AstFrameSet *, int, int * );
971 static void ReportPoints( AstMapping *, int, AstPointSet *, AstPointSet *, int * );
972 static void Resolve( AstFrame *, const double [], const double [], const double [], double [], double *, double *, int * );
973 static void RestoreIntegrity( AstFrameSet *, int * );
974 static void SetActiveUnit( AstFrame *, int, int * );
975 static void SetAttrib( AstObject *, const char *, int * );
976 static void SetAxis( AstFrame *, int, AstAxis *, int * );
977 static void SetBase( AstFrameSet *, int, int * );
978 static void SetCurrent( AstFrameSet *, int, int * );
979 static void SetDigits( AstFrame *, int, int * );
980 static void SetDirection( AstFrame *, int, int, int * );
981 static void SetDomain( AstFrame *, const char *, int * );
982 static void SetFormat( AstFrame *, int, const char *, int * );
983 static void SetLabel( AstFrame *, int, const char *, int * );
984 static void SetMatchEnd( AstFrame *, int, int * );
985 static void SetMaxAxes( AstFrame *, int, int * );
986 static void SetMinAxes( AstFrame *, int, int * );
987 static void SetPermute( AstFrame *, int, int * );
988 static void SetPreserveAxes( AstFrame *, int, int * );
989 static void SetSymbol( AstFrame *, int, const char *, int * );
990 static void SetTitle( AstFrame *, const char *, int * );
991 static void SetUnit( AstFrame *, int, const char *, int * );
992 static void TidyNodes( AstFrameSet *, int * );
993 static void VSet( AstObject *, const char *, char **, va_list, int * );
994 static void ValidateAxisSelection( AstFrame *, int, const int *, const char *, int * );
995 
996 static double GetBottom( AstFrame *, int, int * );
997 static int TestBottom( AstFrame *, int, int * );
998 static void ClearBottom( AstFrame *, int, int * );
999 static void SetBottom( AstFrame *, int, double, int * );
1000 
1001 static double GetTop( AstFrame *, int, int * );
1002 static int TestTop( AstFrame *, int, int * );
1003 static void ClearTop( AstFrame *, int, int * );
1004 static void SetTop( AstFrame *, int, double, int * );
1005 
1006 static double GetEpoch( AstFrame *, int * );
1007 static int TestEpoch( AstFrame *, int * );
1008 static void ClearEpoch( AstFrame *, int * );
1009 static void SetEpoch( AstFrame *, double, int * );
1010 
1011 static double GetObsAlt( AstFrame *, int * );
1012 static int TestObsAlt( AstFrame *, int * );
1013 static void ClearObsAlt( AstFrame *, int * );
1014 static void SetObsAlt( AstFrame *, double, int * );
1015 
1016 static double GetObsLat( AstFrame *, int * );
1017 static int TestObsLat( AstFrame *, int * );
1018 static void ClearObsLat( AstFrame *, int * );
1019 static void SetObsLat( AstFrame *, double, int * );
1020 
1021 static double GetObsLon( AstFrame *, int * );
1022 static int TestObsLon( AstFrame *, int * );
1023 static void ClearObsLon( AstFrame *, int * );
1024 static void SetObsLon( AstFrame *, double, int * );
1025 
1026 static int GetUseDefs( AstObject *, int * );
1027 
1028 static AstSystemType GetSystem( AstFrame *, int * );
1029 static int TestSystem( AstFrame *, int * );
1030 static void ClearSystem( AstFrame *, int * );
1031 static void SetSystem( AstFrame *, AstSystemType, int * );
1032 
1033 static AstSystemType GetAlignSystem( AstFrame *, int * );
1034 static int TestAlignSystem( AstFrame *, int * );
1035 static void ClearAlignSystem( AstFrame *, int * );
1036 static void SetAlignSystem( AstFrame *, AstSystemType, int * );
1037 
1038 static const char *GetVariant( AstFrameSet *, int * );
1039 static int TestVariant( AstFrameSet *, int * );
1040 static void ClearVariant( AstFrameSet *, int * );
1041 static void SetVariant( AstFrameSet *, const char *, int * );
1042 
1043 #if defined(THREAD_SAFE)
1044 static int ManageLock( AstObject *, int, int, AstObject **, int * );
1045 #endif
1046 
1047 /* Member functions. */
1048 /* ================= */
Abbrev(AstFrame * this_frame,int axis,const char * fmt,const char * str1,const char * str2,int * status)1049 static const char *Abbrev( AstFrame *this_frame, int axis, const char *fmt,
1050                            const char *str1, const char *str2, int *status ) {
1051 /*
1052 *  Name:
1053 *     Abbrev
1054 
1055 *  Purpose:
1056 *     Abbreviate a formatted FrameSet axis value by skipping leading fields.
1057 
1058 *  Type:
1059 *     Private function.
1060 
1061 *  Synopsis:
1062 *     #include "frameset.h"
1063 *     const char *Abbrev( AstFrame *this, int axis, const char *fmt,
1064 *                         const char *str1, const char *str2, int *status )
1065 
1066 *  Class Membership:
1067 *     FrameSet member function (over-rides the protected astAbbrev
1068 *     method inherited from the Frame class).
1069 
1070 *  Description:
1071 *     This function compares two FrameSet axis values that have been
1072 *     formatted (using astFormat) and determines if they have any
1073 *     redundant leading fields (i.e. leading fields in common which
1074 *     can be suppressed when tabulating the values or plotting them on
1075 *     the axis of a graph).
1076 
1077 *  Parameters:
1078 *     this
1079 *        Pointer to the FrameSet.
1080 *     axis
1081 *        The number of the FrameSet axis for which the values have
1082 *        been formatted (axis numbering starts at zero for the first
1083 *        axis).
1084 *     fmt
1085 *        Pointer to a constant null-terminated string containing the
1086 *        format specification used to format the two values.
1087 *     str1
1088 *        Pointer to a constant null-terminated string containing the
1089 *        first formatted value. If this is null, the returned pointer
1090 *        points to the start of the final field in str2.
1091 *     str2
1092 *        Pointer to a constant null-terminated string containing the
1093 *        second formatted value.
1094 *     status
1095 *        Pointer to the inherited status variable.
1096 
1097 *  Returned Value:
1098 *     A pointer into the "str2" string which locates the first
1099 *     character in the first field that differs between the two
1100 *     formatted values.
1101 *
1102 *     If the two values have no leading fields in common, the returned
1103 *     value will point at the start of string "str2". If the two
1104 *     values are equal, it will point at the terminating null at the
1105 *     end of this string.
1106 
1107 *  Notes:
1108 *     - This function assumes that the format specification used was
1109 *     the same when both values were formatted and that they both
1110 *     apply to the same FrameSet axis.
1111 *     - A pointer to the start of "str2" will be returned if this
1112 *     function is invoked with the global error status set, or if it
1113 *     should fail for any reason.
1114 */
1115 
1116 /* Local Variables: */
1117    AstFrame *fr;                 /* Pointer to current Frame */
1118    AstFrameSet *this;            /* Pointer to the FrameSet structure */
1119    const char *result;           /* Pointer value to return */
1120 
1121 /* Check the global error status. */
1122    if ( !astOK ) return str2;
1123 
1124 /* Obtain a pointer to the FrameSet structure. */
1125    this = (AstFrameSet *) this_frame;
1126 
1127 /* Validate the axis index. */
1128    (void) astValidateAxis( this, axis, 1, "astAbbrev" );
1129 
1130 /* Obtain a pointer to the FrameSet's current Frame and invoke this
1131    Frame's astAbbrev method to perform the processing. Annul the Frame
1132    pointer afterwards. */
1133    fr = astGetFrame( this, AST__CURRENT );
1134    result = astAbbrev( fr, axis, fmt, str1, str2 );
1135    fr = astAnnul( fr );
1136 
1137 /* If an error occurred, clear the result. */
1138    if ( !astOK ) result = str2;
1139 
1140 /* Return the result. */
1141    return result;
1142 }
1143 
AddFrame(AstFrameSet * this,int iframe,AstMapping * map,AstFrame * frame,int * status)1144 static void AddFrame( AstFrameSet *this, int iframe, AstMapping *map,
1145                       AstFrame *frame, int *status ) {
1146 /*
1147 *++
1148 *  Name:
1149 c     astAddFrame
1150 f     AST_ADDFRAME
1151 
1152 *  Purpose:
1153 *     Add a Frame to a FrameSet to define a new coordinate system.
1154 
1155 *  Type:
1156 *     Public virtual function.
1157 
1158 *  Synopsis:
1159 c     #include "frameset.h"
1160 c     void astAddFrame( AstFrameSet *this, int iframe, AstMapping *map,
1161 c                       AstFrame *frame )
1162 f     CALL AST_ADDFRAME( THIS, IFRAME, MAP, FRAME, STATUS )
1163 
1164 *  Class Membership:
1165 *     FrameSet method.
1166 
1167 *  Description:
1168 c     This function adds a new Frame and an associated Mapping to a
1169 f     This routine adds a new Frame and an associated Mapping to a
1170 *     FrameSet so as to define a new coordinate system, derived from
1171 *     one which already exists within the FrameSet. The new Frame then
1172 *     becomes the FrameSet's current Frame.
1173 *
1174 c     This function
1175 f     This routine
1176 *     may also be used to merge two FrameSets, or to append extra axes
1177 *     to every Frame in a FrameSet.
1178 
1179 *  Parameters:
1180 c     this
1181 f     THIS = INTEGER (Given)
1182 *        Pointer to the FrameSet.
1183 c     iframe
1184 f     IFRAME = INTEGER (Given)
1185 *        The index of the Frame within the FrameSet which describes
1186 *        the coordinate system upon which the new one is to be based.
1187 *        This value should lie in the range from 1 to the number of
1188 *        Frames already in the FrameSet (as given by its Nframe
1189 *        attribute). As a special case, AST__ALLFRAMES may be supplied,
1190 *        in which case the axes defined by the supplied Frame are appended
1191 *        to every Frame in the FrameSet (see the Notes section for details).
1192 c     map
1193 f     MAP = INTEGER (Given)
1194 *        Pointer to a Mapping which describes how to convert
1195 *        coordinates from the old coordinate system (described by the
1196 c        Frame with index "iframe") into coordinates in the new
1197 f        Frame with index IFRAME) into coordinates in the new
1198 *        system. The Mapping's forward transformation should perform
1199 *        this conversion, and its inverse transformation should
1200 *        convert in the opposite direction. The supplied Mapping is ignored
1201 c        if parameter "iframe"is equal to AST__ALLFRAMES.
1202 f        if parameter IFRAME is equal to AST__ALLFRAMES.
1203 c     frame
1204 f     FRAME = INTEGER (Given)
1205 *        Pointer to a Frame that describes the new coordinate system.
1206 *        Any class of Frame may be supplied (including Regions and
1207 *        FrameSets).
1208 *
1209 c        This function may also be used to merge two FrameSets by
1210 c        supplying a pointer to a second FrameSet for this parameter
1211 f        This routine may also be used to merge two FrameSets by
1212 f        supplying a pointer to a second FrameSet for this argument
1213 *        (see the Notes section for details).
1214 f     STATUS = INTEGER (Given and Returned)
1215 f        The global status.
1216 
1217 *  Notes:
1218 *     - A value of AST__BASE or AST__CURRENT may be given for the
1219 c     "iframe" parameter to specify the base Frame or the current
1220 f     IFRAME argument to specify the base Frame or the current
1221 *     Frame respectively.
1222 c     - This function sets the value of the Current attribute for the
1223 f     - This routine sets the value of the Current attribute for the
1224 *     FrameSet so that the new Frame subsequently becomes the current
1225 *     Frame.
1226 *     - The number of input coordinate values accepted by the supplied
1227 *     Mapping (its Nin attribute) must match the number of axes in the
1228 c     Frame identified by the "iframe" parameter. Similarly, the
1229 f     Frame identified by the IFRAME argument. Similarly, the
1230 *     number of output coordinate values generated by this Mapping
1231 *     (its Nout attribute) must match the number of axes in the new
1232 *     Frame.
1233 *     - As a special case, if a pointer to a FrameSet is given for the
1234 c     "frame" parameter, this is treated as a request to merge a pair of
1235 f     FRAME argument, this is treated as a request to merge a pair of
1236 *     FrameSets.  This is done by appending all the new Frames (in the
1237 c     "frame" FrameSet) to the original FrameSet, while preserving
1238 f     FRAME FrameSet) to the original FrameSet, while preserving
1239 *     their order and retaining all the inter-relationships
1240 *     (i.e. Mappings) between them. The two sets of Frames are
1241 *     inter-related within the merged FrameSet by using the Mapping
1242 *     supplied. This should convert between the Frame identified by
1243 c     the "iframe" parameter (in the original FrameSet) and the current
1244 c     Frame of the "frame" FrameSet. This latter Frame becomes the
1245 f     the IFRAME argument (in the original FrameSet) and the current
1246 f     Frame of the FRAME FrameSet. This latter Frame becomes the
1247 *     current Frame in the merged FrameSet.
1248 *     - As another special case, if a value of AST__ALLFRAMES is supplied
1249 *     for parameter
1250 c     "iframe",
1251 f     IFRAME,
1252 *     then the supplied Mapping is ignored, and the axes defined by the
1253 *     supplied Frame are appended to each Frame in the FrameSet. In detail,
1254 *     each Frame in the FrameSet is replaced by a CmpFrame containing the
1255 *     original Frame and the Frame specified by parameter
1256 c     "frame".
1257 f     FRAME.
1258 *     In addition, each Mapping in the FrameSet is replaced by a CmpMap
1259 *     containing the original Mapping and a UnitMap in parallel. The Nin and
1260 *     Nout attributes of the UnitMap are set equal to the number of axes
1261 *     in the supplied Frame. Each new CmpMap is simplified using
1262 c     astSimplify
1263 f     AST_SIMPLIFY
1264 *     before being stored in the FrameSet.
1265 
1266 
1267 
1268 *--
1269 */
1270 
1271 /* Local Variables: */
1272    AstFrame *fr;                 /* Pointer to Frame identified by "iframe" */
1273    AstFrameSet *frameset;        /* Pointer to new FrameSet (if given) */
1274    AstMapping *inode_map;        /* Temporarily saved Mapping pointer */
1275    AstMapping *next_map;         /* Temporarily saved Mapping pointer */
1276    int current;                  /* Current Frame index in merged FrameSet */
1277    int current_node;             /* Node number for current Frame */
1278    int ifr;                      /* Loop counter for Frames */
1279    int inode;                    /* Loop counter for nodes */
1280    int inode_invert;             /* Temporarily saved invert flag value */
1281    int inode_link;               /* Temporarily saved link value */
1282    int naxes;                    /* Number of Frame axes */
1283    int ncoord;                   /* Number of Mapping coordinates per point */
1284    int next;                     /* Number of next node in path */
1285    int next_invert;              /* Temporarily saved invert flag value */
1286    int next_link;                /* Temporarily saved link value */
1287    int nframe;                   /* Number of Frames in merged FrameSet */
1288    int nnode;                    /* Number of nodes in merged FrameSet */
1289    int node_zero;                /* Location of "node zero" after merging */
1290 
1291 /* Check the global error status. */
1292    if ( !astOK ) return;
1293 
1294 /* First handle cases where we are appending axes to the existing
1295    Frames in a FrameSet. */
1296    if( iframe == AST__ALLFRAMES ) {
1297       AppendAxes( this, frame, status );
1298       return;
1299    }
1300 
1301 /* Now handle cases where we are adding a new Frame into the FrameSet.
1302    Initialise variables to avoid "used of uninitialised variable"
1303    messages from dumb compilers. */
1304    inode_map = NULL;
1305    next_map = NULL;
1306    inode_invert = 0;
1307    next = 0;
1308    next_invert = 0;
1309    next_link = 0;
1310 
1311 /* Validate and translate the Frame index supplied. */
1312    iframe = astValidateFrameIndex( this, iframe, "astAddFrame" );
1313 
1314 /* Obtain a pointer to the Frame from which the new coordinate system
1315    will be derived and determine how many axes it has. Annul the Frame
1316    pointer afterwards. */
1317    if ( astOK ) {
1318       fr = astGetFrame( this, iframe );
1319       naxes = astGetNaxes( fr );
1320       fr = astAnnul( fr );
1321 
1322 /* Obtain the number of input coordinate values per point for the
1323    Mapping supplied and check that this matches the number of axes
1324    obtained above. Report an error if it does not. */
1325       ncoord = astGetNin( map );
1326       if ( astOK && ( naxes != ncoord ) ) {
1327          astError( AST__NCPIN, "astAddFrame(%s): Bad number of %s input "
1328                    "coordinate values (%d).", status, astGetClass( this ),
1329                    astGetClass( map ), ncoord );
1330          astError( AST__NCPIN, "The %s given should accept %d coordinate "
1331                    "value%s for each input point.", status, astGetClass( map ), naxes,
1332                    ( naxes == 1 ) ? "" : "s" );
1333       }
1334    }
1335 
1336 /* Similarly, obtain the number of output coordinate values per point
1337    for the Mapping and check that this equals the number of axes for
1338    the Frame supplied. Report an error if necessary. */
1339    if ( astOK ) {
1340       ncoord = astGetNout( map );
1341       naxes = astGetNaxes( frame );
1342       if ( astOK && ( ncoord != naxes ) ) {
1343          astError( AST__NCPIN, "astAddFrame(%s): Bad number of %s output "
1344                    "coordinate values (%d).", status, astGetClass( this ),
1345                    astGetClass( map ), ncoord );
1346          astError( AST__NCPIN, "The %s given should generate %d "
1347                    "coordinate value%s for each output point.", status,
1348                    astGetClass( map ), naxes, ( naxes == 1 ) ? "" : "s" );
1349       }
1350    }
1351 
1352 /* Normal Frame supplied. */
1353 /* ====================== */
1354 /* Check that the Frame supplied is not a FrameSet (handling a
1355    FrameSet is a special case which is addressed later). */
1356    if ( !astIsAFrameSet( frame ) && astOK ) {
1357 
1358 /* Increase the size of the FrameSet's arrays to accommodate one new
1359    Frame. */
1360       this->frame = astGrow( this->frame, this->nframe + 1,
1361                              sizeof( AstFrame * ) );
1362       this->varfrm = astGrow( this->varfrm, this->nframe + 1,
1363                              sizeof( int ) );
1364       this->node = astGrow( this->node, this->nframe + 1, sizeof( int ) );
1365       this->map = astGrow( this->map, this->nnode, sizeof( AstMapping * ) );
1366       this->link = astGrow( this->link, this->nnode, sizeof( int ) );
1367       this->invert = astGrow( this->invert, this->nnode, sizeof( int ) );
1368       if ( astOK ) {
1369 
1370 /* Clone pointers to the Frame and Mapping supplied and store these pointers
1371    in the FrameSet arrays. */
1372          this->frame[ this->nframe ] = astClone( frame );
1373          this->map[ this->nnode - 1 ] = astClone( map );
1374 
1375 /* Indicate the Frame does not reflect the variant Mappings of any other
1376    Frame. */
1377          this->varfrm[ this->nframe ] = 0;
1378 
1379 /* Associate the Frame with the Mapping via the "node" array. */
1380          this->node[ this->nframe ] = this->nnode;
1381 
1382 /* Add a "link" value which identifies the node from which the new
1383    node is derived and store the current value of the Invert attribute
1384    for the Mapping. */
1385          this->link[ this->nnode - 1 ] = this->node[ iframe - 1 ];
1386          this->invert[ this->nnode - 1 ] = astGetInvert( map );
1387 
1388 /* If successful, increment the FrameSet's Frame and node counts and
1389    set the Current attribute so that the new Frame becomes the current
1390    Frame. */
1391          if ( astOK ) {
1392             this->nframe++;
1393             this->nnode++;
1394             astSetCurrent( this, this->nframe );
1395 
1396 /* If an error occurred while filling the FrameSet's arrays, clear any values
1397    that may have been added, annulling any cloned pointers. */
1398          } else {
1399             this->frame[ this->nframe ] =
1400                   astAnnul( this->frame[ this->nframe ] );
1401             this->node[ this->nframe ] = -1;
1402             this->map[ this->nnode - 1 ] =
1403                   astAnnul( this->map[ this->nnode - 1 ] );
1404             this->link[ this->nnode - 1 ] = -1;
1405 	 }
1406       }
1407 
1408 /* FrameSet supplied. */
1409 /* ================== */
1410 /* If the Frame supplied is a FrameSet, we handle this as a special
1411    case by merging the two FrameSets (so that the final result
1412    contains references to all the Frames from both FrameSets). */
1413    } else if ( astOK ) {
1414 
1415 /* Obtain a pointer to the FrameSet structure containing the new Frame
1416    references and calculate how many Frames and nodes the combined
1417    FrameSet will contain. */
1418       frameset = (AstFrameSet *) frame;
1419       nframe = this->nframe + frameset->nframe;
1420       nnode = this->nnode + frameset->nnode;
1421 
1422 /* Extend the original FrameSet's arrays to accommodate the new Frames
1423    and nodes. */
1424       this->frame = astGrow( this->frame, nframe, sizeof( AstFrame * ) );
1425       this->varfrm = astGrow( this->varfrm, nframe, sizeof( int ) );
1426       this->node = astGrow( this->node, nframe, sizeof( int ) );
1427       this->map = astGrow( this->map, nnode - 1, sizeof( AstMapping * ) );
1428       this->link = astGrow( this->link, nnode - 1, sizeof( int ) );
1429       this->invert = astGrow( this->invert, nnode - 1, sizeof( int ) );
1430 
1431 /* If OK, loop to transfer the new Frame data into the new array
1432    elements, cloning each Frame pointer. Increment each "node" value
1433    to allow for the new node numbering which will apply when the new
1434    node data is appended to the new arrays. */
1435       if ( astOK ) {
1436          for ( ifr = 1; ifr <= frameset->nframe; ifr++ ) {
1437             this->frame[ this->nframe + ifr - 1 ] =
1438                astClone( frameset->frame[ ifr - 1 ] );
1439             this->node[ this->nframe + ifr - 1 ] =
1440                frameset->node[ ifr - 1 ] + this->nnode;
1441             if( frameset->varfrm[ ifr - 1 ] > 0 ) {
1442                this->varfrm[ this->nframe + ifr - 1 ] =
1443                   frameset->varfrm[ ifr - 1 ] + this->nframe;
1444             } else {
1445                this->varfrm[ this->nframe + ifr - 1 ] = 0;
1446             }
1447          }
1448 
1449 /* Similarly, transfer the new node data, cloning each Mapping
1450    pointer. Increment each "link" value to allow for the new node
1451    numbering. */
1452          for ( inode = 1; inode < frameset->nnode; inode++ ) {
1453             this->map[ this->nnode + inode - 1 ] =
1454                astClone( frameset->map[ inode - 1 ] );
1455             this->link[ this->nnode + inode - 1 ] =
1456                frameset->link[ inode - 1 ] + this->nnode;
1457             this->invert[ this->nnode + inode - 1 ] =
1458                frameset->invert[ inode - 1 ];
1459          }
1460 
1461 /* In transferring the node data (above), we left an empty array
1462    element which will later be filled with data corresponding to node
1463    zero in the new FrameSet (there are no data to be copied for this
1464    node). Initialise the data for this element to null values. */
1465          this->map[ this->nnode - 1 ] = NULL;
1466          this->link[ this->nnode - 1 ] = -1;
1467          this->invert[ this->nnode - 1 ] = -1;
1468 
1469 /* Determine which is the current Frame in the new FrameSet and
1470    convert this into the corresponding Frame number in the combined
1471    one. */
1472          current = astGetCurrent( frameset ) + this->nframe;
1473 
1474 /* We must now form a new link between this Frame and Frame "iframe"
1475    (using the Mapping supplied) in order to inter-relate the Frames
1476    from the two FrameSets. However, this cannot be done immediately
1477    because in general the node corresponding to Frame "current" will
1478    already have a link pointing to another node. Moreover, the node
1479    which was originally node zero (in the new FrameSet) still has
1480    no data in our merged FrameSet.
1481 
1482    To overcome this, we must re-structure the links within the
1483    transferred data.  We do this by starting at the node corresponding
1484    to Frame "current" and working back through each link until the
1485    original node zero is reached. At each step along this path, we
1486    reverse the direction of the link. This involves shifting the
1487    associated data by one step along the path, so that it becomes
1488    associated with the next node. This results in the final
1489    (initialised-to-null) node acquiring some data, and the starting
1490    node being left free to receive our new link.
1491 
1492    We compensate for reversing the links by reversing the sense of the
1493    "invert" flag associated with each Mapping along the path, so that
1494    the overall structure of the FrameSet is unchanged. */
1495 
1496 /* Identify the starting node (the one corresponding to Frame
1497    "current"). */
1498          if ( astOK ) {
1499             current_node = this->node[ current - 1 ];
1500 
1501 /* Obtain the value which a "link" element will now have if it
1502    originally identified node zero in the new FrameSet. We will use
1503    this value to detect the end of the path. */
1504             node_zero = this->nnode;
1505 
1506 /* If we are not already at "node zero", save the data for the current
1507    node. */
1508             if ( current_node != node_zero ) {
1509                inode_map = this->map[ current_node - 1 ];
1510                inode_link = this->link[ current_node - 1 ];
1511                inode_invert = this->invert[ current_node - 1 ];
1512 
1513 /* Reset the node's data to null values (pending setting up the new
1514    link using the Mapping supplied). */
1515                this->map[ current_node - 1 ] = NULL;
1516                this->link[ current_node - 1 ] = -1;
1517                this->invert[ current_node - 1 ] = -1;
1518 
1519 /* Identify the next node in the path. */
1520                next = inode_link;
1521             }
1522 
1523 /* Follow the path until "node zero" is reached. */
1524             inode = current_node;
1525             while( inode != node_zero ) {
1526 
1527 /* If the next node on the path is not "node zero", save its data
1528    (because we are about to write over it). */
1529                if ( next != node_zero ) {
1530                   next_map = this->map[ next - 1 ];
1531                   next_link = this->link[ next - 1 ];
1532                   next_invert = this->invert[ next - 1 ];
1533                }
1534 
1535 /* Reverse the link from the current node to the "next" node. This
1536    involves transferring the "map" and "invert" values to the "next"
1537    node and inverting the sense of the latter to compensate. Make the
1538    "next" node point back to the current one. */
1539                this->map[ next - 1 ] = inode_map;
1540                this->link[ next - 1 ] = inode;
1541                this->invert[ next - 1 ] = !inode_invert;
1542 
1543 /* Move on to consider the next node. */
1544                inode = next;
1545 
1546 /* If we have not reached "node zero" yet, transfer the node data we
1547    saved above into the variables from which it will be transferred to
1548    the following node on the next pass through this loop. */
1549                if ( inode != node_zero ) {
1550                   inode_map = next_map;
1551                   inode_link = next_link;
1552                   inode_invert = next_invert;
1553 
1554 /* Identify the node that follows the next one. */
1555                   next = inode_link;
1556                }
1557             }
1558 
1559 /* Once the necessary links have been re-structured, establish the new
1560    link that inter-relates the Frames from the two FrameSets. */
1561             this->map[ current_node - 1 ] = astClone( map );
1562             this->link[ current_node - 1 ] = this->node[ iframe - 1 ];
1563             this->invert[ current_node - 1 ] = astGetInvert( map );
1564          }
1565 
1566 /* If successful, update the Frame and node counts and make the
1567    appropriate Frame current. */
1568          if ( astOK ) {
1569             this->nframe = nframe;
1570             this->nnode = nnode;
1571             astSetCurrent( this, current );
1572 
1573 /* If an error occurred, loop through all the new Frame and node array
1574    elements and clear them, ensuring that any remaining Object
1575    pointers are annulled. */
1576          } else {
1577             for ( ifr = 1; ifr <= frameset->nframe; ifr++ ) {
1578                this->frame[ this->nframe + ifr - 1 ] =
1579                   astAnnul( this->frame[ this->nframe + ifr - 1 ] );
1580                this->node[ this->nframe + ifr - 1 ] = -1;
1581                this->varfrm[ this->nframe + ifr - 1 ] = 0;
1582             }
1583             for ( inode = 0; inode < frameset->nnode; inode++ ) {
1584                this->map[ this->nnode + inode - 1 ] =
1585                   astAnnul( this->map[ this->nnode + inode - 1 ] );
1586                this->link[ this->nnode + inode - 1 ] = -1;
1587                this->invert[ this->nnode + inode - 1 ] = -1;
1588             }
1589          }
1590       }
1591    }
1592 }
1593 
AddVariant(AstFrameSet * this,AstMapping * map,const char * name,int * status)1594 static void AddVariant( AstFrameSet *this, AstMapping *map,
1595                         const char *name, int *status ) {
1596 /*
1597 *++
1598 *  Name:
1599 c     astAddVariant
1600 f     AST_ADDVARIANT
1601 
1602 *  Purpose:
1603 *     Store a new variant Mapping for the current Frame in a FrameSet.
1604 
1605 *  Type:
1606 *     Public virtual function.
1607 
1608 *  Synopsis:
1609 c     #include "frameset.h"
1610 c     void astAddVariant( AstFrameSet *this, AstMapping *map,
1611 c                         const char *name, int *status )
1612 f     CALL AST_ADDVARIANT( THIS, MAP, NAME, STATUS )
1613 
1614 *  Class Membership:
1615 *     FrameSet method.
1616 
1617 *  Description:
1618 c     This function
1619 f     This routine
1620 *     allows a new variant Mapping to be stored with the current Frame
1621 *     in a FrameSet. See the "Variant" attribute for more details. It can
1622 *     also be used to rename the currently selected variant Mapping.
1623 
1624 *  Parameters:
1625 c     this
1626 f     THIS = INTEGER (Given)
1627 *        Pointer to the FrameSet.
1628 c     map
1629 f     MAP = INTEGER (Given)
1630 *        Pointer to a Mapping which describes how to convert
1631 *        coordinates from the current Frame to the new variant of the
1632 *        current Frame. If
1633 c        NULL
1634 f        AST__NULL
1635 *        is supplied, then the name associated with the currently selected
1636 *        variant of the current Frame is set to the value supplied for
1637 c        "name", but no new variant is added.
1638 f        NAME, but no new variant is added.
1639 c     name
1640 f     NAME = CHARACTER * ( * ) (Given)
1641 *        The name to associate with the new variant Mapping (or the currently
1642 *        selected variant Mapping if
1643 c        "map" is NULL).
1644 f        MAP is AST__NULL).
1645 f     STATUS = INTEGER (Given and Returned)
1646 f        The global status.
1647 
1648 *  Notes:
1649 *     - The newly added Variant becomes the current variant on exit (this is
1650 *     equivalent to setting the Variant attribute to the value supplied for
1651 c     "name).
1652 f     NAME).
1653 *     - An error is reported if a variant with the supplied name already
1654 *     exists in the current Frame.
1655 *     - An error is reported if the current Frame is a mirror for the
1656 *     variant Mappings in another Frame. This is only the case if the
1657 c     astMirrorVariants function
1658 f     AST_MIRRORVARIANTS routine
1659 *     has been called to make the current Frame act as a mirror.
1660 
1661 *--
1662 */
1663 
1664 /* Local Variables: */
1665    AstCmpMap *map2;
1666    AstFrame *frm;
1667    AstFrame *tfrm;
1668    AstFrame *vfrm;
1669    AstFrameSet *tfs;
1670    AstFrameSet *vfs;
1671    AstMapping *map1;
1672    AstMapping *map3;
1673    char *myname;
1674    const char *dom;
1675    int icur;
1676    int ifrm;
1677    int new;
1678    int nfrm;
1679 
1680 /* Check the global error status. */
1681    if ( !astOK ) return;
1682 
1683 /* Get the one-based index of the current Frame. */
1684    icur = astGetCurrent( this );
1685 
1686 /* Report an error if the current Frame is just a mirror. */
1687    if( this->varfrm[ icur - 1 ] > 0 && astOK ) {
1688       astError( AST__MIRRO, "astAddVariant(%s): Illegal attempt to "
1689                 "add a variant Mapping to a mirror Frame (programming "
1690                 "error).", status, astGetClass( this ) );
1691    }
1692 
1693 /* Get a copy of the supplied string and clean it. */
1694    myname = astStore( NULL, name, strlen( name ) + 1 );
1695    astRemoveLeadingBlanks( myname );
1696    astChrCase( NULL, myname, 1, 0 );
1697    if( astOK ) {
1698       myname[ astChrLen( myname ) ] = 0;
1699 
1700 /* Get the Variants FrameSet for the current Frame in "this". */
1701       frm = astGetFrame( this, icur );
1702       vfs = astGetFrameVariants( frm );
1703 
1704 /* If current Frame of this has no Variant FrameSet, create a Variants
1705    FrameSet containing a copy of the current Frame (retain its Domain
1706    as the default variant name). */
1707       if( !vfs ) {
1708          tfrm = astCopy( frm );
1709          vfs = astFrameSet( tfrm, " ", status );
1710          tfrm = astAnnul( tfrm );
1711          new = 1;
1712       } else {
1713          new = 0;
1714       }
1715 
1716 /* Check the Variants FrameSet does not already contain a Frame with
1717    a Domain equal to the supplied name. */
1718       nfrm = astGetNframe( vfs );
1719       for( ifrm = 0; ifrm < nfrm && astOK; ifrm++ ) {
1720          vfrm = astGetFrame( vfs, ifrm + 1 );
1721          dom = astGetDomain( vfrm );
1722          if( astOK && !strcmp( dom, myname ) ) {
1723             astError( AST__BDVNM, "astAddVariant(%s): Cannot add a "
1724                       "variant %s Frame with name '%s' because one "
1725                       "already exists in the %s (programming "
1726                       "error).", status, astGetClass( this ),
1727                       astGetDomain( frm ), myname,  astGetClass( this ) );
1728          }
1729          vfrm = astAnnul( vfrm );
1730       }
1731 
1732 /* If no Mapping was supplied, just set the name of the currently
1733    selected variant. The names are stored in the Domain attribute of
1734    the Frames in the variants FrameSet, so set teh DOmain for the current
1735    Frame. */
1736       if( !map ){
1737          vfrm = astGetFrame( vfs, AST__CURRENT );
1738          astSetDomain( vfrm, name );
1739          vfrm = astAnnul( vfrm );
1740 
1741 /* If a Mapping was supplied.... */
1742       } else {
1743 
1744 /* Get the Mapping from the current Frame in the variants FrameSet to the
1745    current Frame in "this". Temporarily match the Domains so that
1746    astConvert can work. */
1747          vfrm = astGetFrame( vfs, AST__CURRENT );
1748          dom = astGetDomain( frm );
1749          if( dom ) dom = astStore( NULL, dom, strlen( dom ) + 1 );
1750          astSetDomain( frm, astGetDomain( vfrm ) );
1751          tfs = astConvert( vfrm, frm, "" );
1752          astSetDomain( frm, dom );
1753          if( tfs ) {
1754             map1 = astGetMapping( tfs, AST__BASE, AST__CURRENT );
1755             tfs = astAnnul( tfs );
1756 
1757 /* Concatenate it with the supplied Mapping to get the mapping from the
1758    current Frame in the Variants FrameSet to the new variant Frame. */
1759             map2 = astCmpMap( map1, map, 1, " ", status );
1760             map3 = astSimplify( map2 );
1761 
1762 /* Add a copy of parent Frame into Variants FrameSet, using the above
1763    mapping to connect it to the original current Variants Frame. Set
1764    its Domain to the supplied name. Re-instate the original current Frame
1765    afterwards. Remove the variant frame info before adding it. */
1766             (void) astAnnul( vfrm );
1767             vfrm = astCopy( frm );
1768             astSetFrameVariants( vfrm, NULL );
1769             astSetDomain( vfrm, name );
1770             icur = astGetCurrent( vfs );
1771             astAddFrame( vfs, AST__CURRENT, map3, vfrm );
1772             astSetCurrent( vfs, icur );
1773 
1774 /* Free resources. */
1775             map1 = astAnnul( map1 );
1776             map2 = astAnnul( map2 );
1777             map3 = astAnnul( map3 );
1778 
1779 /* Report an error if a Mapping cannot be found from the new variant Frame
1780    to the current Frame in "this". */
1781          } else if( astOK ) {
1782             astError( AST__INTER, "astAddVariant(%s): Cannot convert "
1783                       "from a %s with Domain '%s' to a %s with Domain "
1784                       "'%s' (internal programming error).", status,
1785                       astGetClass( this ), astGetClass( vfrm ),
1786                       astGetDomain( vfrm ), astGetClass( frm ),
1787                       astGetDomain( frm ) );
1788          }
1789 
1790 /* Free resources. */
1791          dom = astFree( (void *) dom );
1792          vfrm = astAnnul( vfrm );
1793       }
1794 
1795 /* If all is well, and the Variants FrameSet is new, store a pointer to
1796    it in the current Frame of "this". */
1797       if( new ) astSetFrameVariants( frm, vfs );
1798 
1799 /* Make the new Variant the current variant. */
1800       if( map ) astSetVariant( this, name );
1801 
1802 /* Free remaining resources. */
1803       frm = astAnnul( frm );
1804       vfs = astAnnul( vfs );
1805    }
1806    myname = astFree( myname );
1807 }
1808 
Angle(AstFrame * this_frame,const double a[],const double b[],const double c[],int * status)1809 static double Angle( AstFrame *this_frame, const double a[],
1810                      const double b[], const double c[], int *status ) {
1811 /*
1812 *  Name:
1813 *     Angle
1814 
1815 *  Purpose:
1816 *     Calculate the angle subtended by two points at a third point.
1817 
1818 *  Type:
1819 *     Private function.
1820 
1821 *  Synopsis:
1822 *     #include "frameset.h"
1823 *     double Angle( AstFrame *this, const double a[], const double b[],
1824 *                   const double c[], int *status )
1825 
1826 *  Class Membership:
1827 *     FrameSet member function (over-rides the protected astAngle
1828 *     method inherited from the Frame class).
1829 
1830 *  Description:
1831 *     This function finds the angle at point B between the line joining points
1832 *     A and B, and the line joining points C and B. These lines will in fact be
1833 *     geodesic curves appropriate to the Frame in use. For instance, in
1834 *     SkyFrame, they will be great circles.
1835 
1836 *  Parameters:
1837 *     this
1838 *        Pointer to the Frame.
1839 *     a
1840 *        An array of double, with one element for each Frame axis
1841 *        (Naxes attribute) containing the coordinates of the first point.
1842 *     b
1843 *        An array of double, with one element for each Frame axis
1844 *        (Naxes attribute) containing the coordinates of the second point.
1845 *     c
1846 *        An array of double, with one element for each Frame axis
1847 *        (Naxes attribute) containing the coordinates of the third point.
1848 *     status
1849 *        Pointer to the inherited status variable.
1850 
1851 *  Returned Value:
1852 *     astAngle
1853 *        The angle in radians, from the line AB to the line CB. If the
1854 *        Frame is 2-dimensional, it will be in the range $\pm \pi$,
1855 *        and positive rotation is in the same sense as rotation from
1856 *        the positive direction of axis 2 to the positive direction of
1857 *        axis 1. If the Frame has more than 2 axes, a positive value will
1858 *        always be returned in the range zero to $\pi$.
1859 
1860 *  Notes:
1861 *     - A value of AST__BAD will also be returned if points A and B are
1862 *     co-incident, or if points B and C are co-incident.
1863 *     - A value of AST__BAD will also be returned if this function is
1864 *     invoked with the AST error status set, or if it should fail for
1865 *     any reason.
1866 */
1867 
1868 /* Local Variables: */
1869    AstFrame *fr;                 /* Pointer to current Frame */
1870    AstFrameSet *this;            /* Pointer to the FrameSet structure */
1871    double result;                /* Value to return */
1872 
1873 /* Check the global error status. */
1874    if ( !astOK ) return AST__BAD;
1875 
1876 /* Obtain a pointer to the FrameSet structure. */
1877    this = (AstFrameSet *) this_frame;
1878 
1879 /* Obtain a pointer to the FrameSet's current Frame and invoke this
1880    Frame's astAngle method. Annul the Frame pointer afterwards. */
1881    fr = astGetFrame( this, AST__CURRENT );
1882    result = astAngle( fr, a, b, c );
1883    fr = astAnnul( fr );
1884 
1885 /* If an error occurred, clear the result. */
1886    if ( !astOK ) result = AST__BAD;
1887 
1888 /* Return the result. */
1889    return result;
1890 }
1891 
AppendAxes(AstFrameSet * this,AstFrame * frame,int * status)1892 static void AppendAxes( AstFrameSet *this, AstFrame *frame, int *status ) {
1893 /*
1894 *  Name:
1895 *     AppendAxes
1896 
1897 *  Purpose:
1898 *     Append axes to every Frame in a FrameSet.
1899 
1900 *  Type:
1901 *     Private function.
1902 
1903 *  Synopsis:
1904 *     #include "frameset.h"
1905 *     void AppendAxes( AstFrameSet *this, AstFrame *frame, int *status )
1906 
1907 *  Class Membership:
1908 *     FrameSet member function
1909 
1910 *  Description:
1911 *     This function replaces every Frame in the FrameSet with a CmpFrame
1912 *     holding the original Frame and the supplied Frame. It also replaces
1913 *     every Mapping in the FrameSet with a parallel CmpMap holding the
1914 *     original Mapping and a UnitMap. The Nin and Nout attributes of every
1915 *     UnitMap are equal to the number of axes in the supplied Frame. Each
1916 *     CmpMap is simplified before being stored in the FrameSet.
1917 
1918 
1919 *  Parameters:
1920 *     this
1921 *        Pointer to the Frame.
1922 *     frame
1923 *        Pointer to a Frame holding the new axes to add to every Frame in
1924 *        the FrameSet.
1925 *     status
1926 *        Pointer to the inherited status variable.
1927 
1928 */
1929 
1930 /* Local Variables: */
1931    AstCmpFrame *frm;             /* Pointer to new Frame */
1932    AstCmpMap *map;               /* UnitMap to new Mapping */
1933    AstUnitMap *umap;             /* UnitMap to feed the new axes */
1934    int iframe;                   /* Frame index */
1935    int imap;                     /* Mapping index */
1936    int inv_orig;                 /* Original value of Invert attribute */
1937 
1938 /* Check the global error status. */
1939    if ( !astOK ) return;
1940 
1941 /* Loop round every Frame in the FrameSet. */
1942    for ( iframe = 0; iframe < this->nframe; iframe++ ) {
1943 
1944 /* Create a CmpFrame holding the original Frame and the new Frame. */
1945       frm = astCmpFrame( this->frame[ iframe ], frame, " ", status );
1946 
1947 /* Annul the original Frame pointer and store the new CmpFrame pointer. */
1948       (void) astAnnul( this->frame[ iframe ] );
1949       this->frame[ iframe ] = (AstFrame *) frm;
1950    }
1951 
1952 /* Create a UnitMap with the number of inputs and outputs equal to the
1953    number of axes in the supplied Frame. */
1954    umap = astUnitMap( astGetNaxes( frame ), " ", status );
1955 
1956 /* Loop round every Mapping in the FrameSet. */
1957    for ( imap = 0; imap < this->nnode - 1; imap++ ) {
1958 
1959 /* The Invert attribute of the Mapping may have been changed via a
1960    different pointer since it was first added into the FrameSet. To
1961    ensure that the FrameSet continues to behave as was originally
1962    intended, we set the Invert attribute back to the value it had when
1963    the Mapping was first added into the FrameSet. First, note the
1964    current value of the Invert flag so that it can be re-instated later. */
1965       inv_orig = astGetInvert( this->map[ imap ] );
1966       astSetInvert( this->map[ imap ], this->invert[ imap ] );
1967 
1968 /*  Create a parallel CmpMap holding the original Mapping and the UnitMap. */
1969       map = astCmpMap( this->map[ imap ], umap, 0, " ", status );
1970 
1971 /* Re-instate the original value for the Invert flag, and then annul the
1972    original Mapping pointer. */
1973       astSetInvert( this->map[ imap ], inv_orig );
1974       (void) astAnnul( this->map[ imap ] );
1975 
1976 /* Simplify the new Mapping, and store it in the FrameSet. */
1977       this->map[ imap ] = astSimplify( map );
1978 
1979 /* Store a copy of the Invert attribute that should be used with this
1980    Mapping within the FrameSet (just in case it  is modified via some
1981    excternal reference). */
1982       this->invert[ imap ] = astGetInvert( this->map[ imap ] );
1983 
1984 /* Annul the un-simplified Mapping pointer. */
1985       map = astAnnul( map );
1986    }
1987 
1988 /* Annul the UnitMap pointer. */
1989    umap = astAnnul( umap );
1990 }
1991 
AxAngle(AstFrame * this_frame,const double a[],const double b[],int axis,int * status)1992 static double AxAngle( AstFrame *this_frame, const double a[], const double b[], int axis, int *status ) {
1993 /*
1994 *  Name:
1995 *     AxAngle
1996 
1997 *  Purpose:
1998 *     Returns the angle from an axis, to a line through two points.
1999 
2000 *  Type:
2001 *     Private function.
2002 
2003 *  Synopsis:
2004 *     #include "frameset.h"
2005 *     double AxAngle( AstFrame *this, const double a[], const double b[], int axis, int *status )
2006 
2007 *  Class Membership:
2008 *     FrameSet member function (over-rides the protected astAxAngle
2009 *     method inherited from the Frame class).
2010 
2011 *  Description:
2012 *     This function finds the angle, as seen from point A, between the positive
2013 *     direction of a specified axis, and the geodesic curve joining point
2014 *     A to point B.
2015 
2016 *  Parameters:
2017 *     this
2018 *        Pointer to the Frame.
2019 *     a
2020 *        An array of double, with one element for each Frame axis
2021 *        (Naxes attribute) containing the coordinates of the first point.
2022 *     b
2023 *        An array of double, with one element for each Frame axis
2024 *        (Naxes attribute) containing the coordinates of the second point.
2025 *     axis
2026 *        The number of the Frame axis from which the angle is to be
2027 *        measured (one-based).
2028 *     status
2029 *        Pointer to the inherited status variable.
2030 
2031 *  Returned Value:
2032 *        The angle in radians, from the positive direction of the
2033 *        specified axis, to the line AB. If the Frame is 2-dimensional,
2034 *        it will be in the range $\pm \pi$, and positive rotation is in
2035 *        the same sense as rotation from the positive direction of axis 2
2036 *        to the positive direction of axis 1. If the Frame has more than 2
2037 *        axes, a positive value will always be returned in the range zero
2038 *        to $\pi$.
2039 
2040 *  Notes:
2041 *     - The geodesic curve used by this function is the path of
2042 *     shortest distance between two points, as defined by the
2043 *     astDistance function.
2044 *     - This function will return "bad" coordinate values (AST__BAD)
2045 *     if any of the input coordinates has this value, or if the require
2046 *     position angle is undefined.
2047 */
2048 
2049 /* Local Variables: */
2050    AstFrame *fr;                 /* Pointer to current Frame */
2051    AstFrameSet *this;            /* Pointer to the FrameSet structure */
2052    double result;                /* Value to return */
2053 
2054 /* Check the global error status. */
2055    if ( !astOK ) return AST__BAD;
2056 
2057 /* Obtain a pointer to the FrameSet structure. */
2058    this = (AstFrameSet *) this_frame;
2059 
2060 /* Validate the axis index. */
2061    (void) astValidateAxis( this, axis - 1, 1, "astAxAngle" );
2062 
2063 /* Obtain a pointer to the FrameSet's current Frame and invoke the
2064    astAxAngle method for this Frame. Annul the Frame pointer
2065    afterwards. */
2066    fr = astGetFrame( this, AST__CURRENT );
2067    result = astAxAngle( fr, a, b, axis );
2068    fr = astAnnul( fr );
2069 
2070 /* If an error occurred, clear the result value. */
2071    if ( !astOK ) result = AST__BAD;
2072 
2073 /* Return the result. */
2074    return result;
2075 }
2076 
AxDistance(AstFrame * this_frame,int axis,double v1,double v2,int * status)2077 static double AxDistance( AstFrame *this_frame, int axis, double v1, double v2, int *status ) {
2078 /*
2079 *  Name:
2080 *     AxDistance
2081 
2082 *  Purpose:
2083 *     Find the distance between two axis values.
2084 
2085 *  Type:
2086 *     Private function.
2087 
2088 *  Synopsis:
2089 *     #include "frameset.h"
2090 *     double AxDistance( AstFrame *this, int axis, double v1, double v2, int *status )
2091 
2092 *  Class Membership:
2093 *     FrameSet member function (over-rides the protected astAxDistance
2094 *     method inherited from the Frame class).
2095 
2096 *  Description:
2097 *     This function returns a signed value representing the axis increment
2098 *     from axis value v1 to axis value v2.
2099 *
2100 *     For a simple Frame, this is a trivial operation returning the
2101 *     difference between the two axis values. But for other derived classes
2102 *     of Frame (such as a SkyFrame) this is not the case.
2103 
2104 *  Parameters:
2105 *     this
2106 *        Pointer to the Frame.
2107 *     axis
2108 *        The index of the axis to which the supplied values refer. The
2109 *        first axis has index 1.
2110 *     v1
2111 *        The first axis value.
2112 *     v2
2113 *        The second axis value.
2114 *     status
2115 *        Pointer to the inherited status variable.
2116 
2117 *  Returned Value:
2118 *     The distance between the two axis values.
2119 
2120 *  Notes:
2121 *     - This function will return a "bad" result value (AST__BAD) if
2122 *     any of the input vaues has this value.
2123 *     - A "bad" value will also be returned if this function is
2124 *     invoked with the AST error status set, or if it should fail for
2125 *     any reason.
2126 */
2127 
2128 /* Local Variables: */
2129    AstFrame *fr;                 /* Pointer to current Frame */
2130    AstFrameSet *this;            /* Pointer to the FrameSet structure */
2131    double result;                /* Value to return */
2132 
2133 /* Check the global error status. */
2134    if ( !astOK ) return AST__BAD;
2135 
2136 /* Obtain a pointer to the FrameSet structure. */
2137    this = (AstFrameSet *) this_frame;
2138 
2139 /* Validate the axis index. */
2140    (void) astValidateAxis( this, axis - 1, 1, "astAxDistance" );
2141 
2142 /* Obtain a pointer to the FrameSet's current Frame and invoke the
2143    astAxDistance method for this Frame. Annul the Frame pointer
2144    afterwards. */
2145    fr = astGetFrame( this, AST__CURRENT );
2146    result = astAxDistance( fr, axis, v1, v2 );
2147    fr = astAnnul( fr );
2148 
2149 /* If an error occurred, clear the result value. */
2150    if ( !astOK ) result = AST__BAD;
2151 
2152 /* Return the result. */
2153    return result;
2154 }
2155 
AxOffset(AstFrame * this_frame,int axis,double v1,double dist,int * status)2156 static double AxOffset( AstFrame *this_frame, int axis, double v1, double dist, int *status ) {
2157 /*
2158 *  Name:
2159 *     AxOffset
2160 
2161 *  Purpose:
2162 *     Add an increment onto a supplied axis value.
2163 
2164 *  Type:
2165 *     Private function.
2166 
2167 *  Synopsis:
2168 *     #include "frameset.h"
2169 *     double AxOffset( AstFrame *this, int axis, double v1, double dist, int *status )
2170 
2171 *  Class Membership:
2172 *     FrameSet member function (over-rides the protected astAxOffset
2173 *     method inherited from the Frame class).
2174 
2175 *  Description:
2176 *     This function returns an axis value formed by adding a signed axis
2177 *     increment onto a supplied axis value.
2178 *
2179 *     For a simple Frame, this is a trivial operation returning the
2180 *     sum of the two supplied values. But for other derived classes
2181 *     of Frame (such as a SkyFrame) this is not the case.
2182 
2183 *  Parameters:
2184 *     this
2185 *        Pointer to the Frame.
2186 *     axis
2187 *        The index of the axis to which the supplied values refer. The
2188 *        first axis has index 1.
2189 *     v1
2190 *        The original axis value.
2191 *     dist
2192 *        The axis increment to add to the original axis value.
2193 *     status
2194 *        Pointer to the inherited status variable.
2195 
2196 *  Returned Value:
2197 *     The incremented axis value.
2198 
2199 *  Notes:
2200 *     - This function will return a "bad" result value (AST__BAD) if
2201 *     any of the input vaues has this value.
2202 *     - A "bad" value will also be returned if this function is
2203 *     invoked with the AST error status set, or if it should fail for
2204 *     any reason.
2205 */
2206 
2207 /* Local Variables: */
2208    AstFrame *fr;                 /* Pointer to current Frame */
2209    AstFrameSet *this;            /* Pointer to the FrameSet structure */
2210    double result;                /* Value to return */
2211 
2212 /* Check the global error status. */
2213    if ( !astOK ) return AST__BAD;
2214 
2215 /* Obtain a pointer to the FrameSet structure. */
2216    this = (AstFrameSet *) this_frame;
2217 
2218 /* Validate the axis index. */
2219    (void) astValidateAxis( this, axis - 1, 1, "astAxOffset" );
2220 
2221 /* Obtain a pointer to the FrameSet's current Frame and invoke the
2222    astAxOffset method for this Frame. Annul the Frame pointer
2223    afterwards. */
2224    fr = astGetFrame( this, AST__CURRENT );
2225    result = astAxOffset( fr, axis, v1, dist );
2226    fr = astAnnul( fr );
2227 
2228 /* If an error occurred, clear the result value. */
2229    if ( !astOK ) result = AST__BAD;
2230 
2231 /* Return the result. */
2232    return result;
2233 }
2234 
Cast(AstObject * this_object,AstObject * obj,int * status)2235 static AstObject *Cast( AstObject *this_object, AstObject *obj, int *status ) {
2236 /*
2237 *  Name:
2238 *     Cast
2239 
2240 *  Purpose:
2241 *     Cast an Object into an instance of a sub-class.
2242 
2243 *  Type:
2244 *     Private function.
2245 
2246 *  Synopsis:
2247 *     #include "frameset.h"
2248 *     AstObject *Cast( AstObject *this, AstObject *obj, int *status )
2249 
2250 *  Class Membership:
2251 *     FrameSet member function (over-rides the protected astCast
2252 *     method inherited from the Frame class).
2253 
2254 *  Description:
2255 *     This function returns a deep copy of an ancestral component of the
2256 *     supplied object. The required class of the ancestral component is
2257 *     specified by another object. Specifically, if "this" and "new" are
2258 *     of the same class, a copy of "this" is returned. If "this" is an
2259 *     instance of a subclass of "obj", then a copy of the component
2260 *     of "this" that matches the class of "obj" is returned. Otherwise,
2261 *     a NULL pointer is returned without error.
2262 
2263 *  Parameters:
2264 *     this
2265 *        Pointer to the Object to be cast.
2266 *     obj
2267 *        Pointer to an Object that defines the class of the returned Object.
2268 *        The returned Object will be of the same class as "obj".
2269 
2270 *  Returned Value:
2271 *     A pointer to the new Object. NULL if "this" is not a sub-class of
2272 *     "obj", or if an error occurs.
2273 
2274 *  Notes:
2275 *     - A NULL pointer will be returned if this function is invoked
2276 *     with the global error status set, or if it should fail for any
2277 *     reason.
2278 */
2279 
2280 /* Local Variables; */
2281    AstFrame *cfrm;
2282    AstObject *new;
2283    astDECLARE_GLOBALS
2284    int generation_gap;
2285 
2286 /* Initialise */
2287    new = NULL;
2288 
2289 /* Check inherited status */
2290    if( !astOK ) return new;
2291 
2292 /* Get a pointer to the thread specific global data structure. */
2293    astGET_GLOBALS(NULL);
2294 
2295 /* See how many steps up the class inheritance ladder it is from "obj"
2296    to this class (FrameSet). A positive value is returned if FrameSet
2297    is a sub-class of "obj". A negative value is returned if "obj" is
2298    a sub-class of FrameSet. Zero is returned if "obj" is a FrameSet.
2299    AST__COUSIN is returned if "obj" is not on the same line of descent
2300    as FrameSet. */
2301    generation_gap = astClassCompare( (AstObjectVtab *) &class_vtab,
2302                                      astVTAB( obj ) );
2303 
2304 /* If "obj" is a FrameSet or a sub-class of FrameSet, we can cast by
2305    truncating the vtab for "this" so that it matches the vtab of "obJ",
2306    and then taking a deep copy of "this". */
2307    if( generation_gap <= 0 && generation_gap != AST__COUSIN ) {
2308       new = astCastCopy( this_object, obj );
2309 
2310 /* If "obj" is not a FrameSet or a sub-class of FrameSet (e.g. a Frame or
2311    some sub-class of Frame), we attempt to cast the current Frame into
2312    the class indicated by "obj". */
2313    } else {
2314       cfrm = astGetFrame( (AstFrameSet *) this_object, AST__CURRENT );
2315       new = astCast( cfrm, obj );
2316       cfrm = astAnnul( cfrm );
2317    }
2318 
2319 /* Return the new pointer. */
2320    return new;
2321 }
2322 
CheckPerm(AstFrame * this_frame,const int * perm,const char * method,int * status)2323 static void CheckPerm( AstFrame *this_frame, const int *perm, const char *method, int *status ) {
2324 /*
2325 *  Name:
2326 *     CheckPerm
2327 
2328 *  Purpose:
2329 *     Check that an array contains a valid permutation.
2330 
2331 *  Type:
2332 *     Private function.
2333 
2334 *  Synopsis:
2335 *     #include "frameset.h"
2336 *     void CheckPerm( AstFrame *this, const int *perm, const char *method, int *status )
2337 
2338 *  Class Membership:
2339 *     FrameSet member function (over-rides the protected astCheckPerm
2340 *     method inherited from the Frame class).
2341 
2342 *  Description:
2343 *     This function checks the validity of a permutation array that
2344 *     will be used to permute the order of a Frame's axes. If the
2345 *     permutation specified by the array is not valid, an error is
2346 *     reported and the global error status is set. Otherwise, the
2347 *     function returns without further action.
2348 
2349 *  Parameters:
2350 *     this
2351 *        Pointer to the Frame.
2352 *     perm
2353 *        Pointer to an array of integers with the same number of
2354 *        elements as there are axes in the Frame. For each axis, the
2355 *        corresponding integer gives the (zero based) axis index to be
2356 *        used to identify the information for that axis (using the
2357 *        un-permuted axis numbering). To be valid, the integers in
2358 *        this array should therefore all lie in the range zero to
2359 *        (naxes-1) inclusive, where "naxes" is the number of Frame
2360 *        axes, and each value should occur exactly once.
2361 *     method
2362 *        Pointer to a constant null-terminated character string
2363 *        containing the name of the method that invoked this function
2364 *        to validate a permutation array. This method name is used
2365 *        solely for constructing error messages.
2366 *     status
2367 *        Pointer to the inherited status variable.
2368 
2369 *  Notes:
2370 *     - Error messages issued by this function refer to the external
2371 *     (public) numbering system used for axes (which is one-based),
2372 *     whereas zero-based axis indices are used internally.
2373 */
2374 
2375 /* Local Variables: */
2376    AstFrame *fr;                 /* Pointer to current Frame */
2377    AstFrameSet *this;            /* Pointer to the FrameSet structure */
2378 
2379 /* Check the global error status. */
2380    if ( !astOK ) return;
2381 
2382 /* Obtain a pointer to the FrameSet structure. */
2383    this = (AstFrameSet *) this_frame;
2384 
2385 /* Obtain a pointer to the FrameSet's current Frame and invoke this
2386    Frame's astCheckPerm method. Annul the Frame pointer afterwards. */
2387    fr = astGetFrame( this, AST__CURRENT );
2388    astCheckPerm( fr, perm, method );
2389    fr = astAnnul( fr );
2390 
2391 }
2392 
Clear(AstObject * this_object,const char * attrib,int * status)2393 static void Clear( AstObject *this_object, const char *attrib, int *status ) {
2394 /*
2395 *  Name:
2396 *     Clear
2397 
2398 *  Purpose:
2399 *     Clear attribute values for a FrameSet.
2400 
2401 *  Type:
2402 *     Private function.
2403 
2404 *  Synopsis:
2405 *     #include "frameset.h"
2406 *     void Clear( AstObject *this, const char *attrib, int *status )
2407 
2408 *  Class Membership:
2409 *     FrameSet member function (over-rides the public astClear method
2410 *     inherited from the Object class).
2411 
2412 *  Description:
2413 *     This function clears the values of a specified set of attributes
2414 *     for a FrameSet. Clearing an attribute cancels any value that has
2415 *     previously been explicitly set for it, so that the standard
2416 *     default attribute value will subsequently be used instead. This
2417 *     also causes the astTest function to return the value zero for
2418 *     the attribute, indicating that no value has been set.
2419 
2420 *  Parameters:
2421 *     this
2422 *        Pointer to the FrameSet.
2423 *     attrib
2424 *        Pointer to a null-terminated character string containing a
2425 *        comma-separated list of the names of the attributes to be
2426 *        cleared.
2427 *     status
2428 *        Pointer to the inherited status variable.
2429 
2430 *  Notes:
2431 *     - This function preserves the integrity of the FrameSet (if
2432 *     possible) by appropriately remapping its current Frame to take
2433 *     account of its changed attribute values.
2434 */
2435 
2436 /* Local Variables: */
2437    astDECLARE_GLOBALS            /* Declare the thread specific global data */
2438    AstFrame *save_frame;         /* Saved pointer to integrity Frame */
2439    AstFrameSet *this;            /* Pointer to FrameSet structure */
2440    const char *save_method;      /* Saved pointer to method name */
2441    int ok;                       /* Status OK? */
2442    int save_lost;                /* Saved integrity modified flag */
2443 
2444 /* Check the global error status. */
2445    if ( !astOK ) return;
2446 
2447 /* Get a pointer to the structure holding thread-specific global data. */
2448    astGET_GLOBALS(this_object);
2449 
2450 /* Obtain a pointer to the FrameSet structure. */
2451    this = (AstFrameSet *) this_object;
2452 
2453 /* To allow this function to be invoked recursively, we first save any
2454    existing FrameSet integrity information in local variables. */
2455    save_frame = integrity_frame;
2456    save_lost= integrity_lost;
2457    save_method = integrity_method;
2458 
2459 /* Set the name of the method being used (for use in error
2460    messages). */
2461    integrity_method = "astClear";
2462 
2463 /* Record the initial integrity state of the FrameSet. */
2464    RecordIntegrity( this, status );
2465 
2466 /* Invoke the parent astClear method to clear the FrameSet's attribute
2467    values and note if this succeeds. */
2468    (*parent_clear)( this_object, attrib, status );
2469    ok = astOK;
2470 
2471 /* Restore the FrameSet's integrity. */
2472    RestoreIntegrity( this, status );
2473 
2474 /* If integrity could not be restored, then add contextual error
2475    information. */
2476    if ( !astOK && ok ) {
2477       astError( astStatus, "Unable to accommodate clearing the \"%s\" "
2478                            "attribute(s).", status, attrib );
2479    }
2480 
2481 /* Restore any saved FrameSet integrity information. */
2482    integrity_frame = save_frame;
2483    integrity_lost = save_lost;
2484    integrity_method = save_method;
2485 }
2486 
ClearAttrib(AstObject * this_object,const char * attrib,int * status)2487 static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) {
2488 /*
2489 *  Name:
2490 *     ClearAttrib
2491 
2492 *  Purpose:
2493 *     Clear an attribute value for a FrameSet.
2494 
2495 *  Type:
2496 *     Private function.
2497 
2498 *  Synopsis:
2499 *     #include "frameset.h"
2500 *     void ClearAttrib( AstObject *this, const char *attrib )
2501 
2502 *  Class Membership:
2503 *     FrameSet member function (over-rides the astClearAttrib protected
2504 *     method inherited from the Frame class).
2505 
2506 *  Description:
2507 *     This function clears the value of a specified attribute for a
2508 *     FrameSet, so that the default value will subsequently be used.
2509 
2510 *  Parameters:
2511 *     this
2512 *        Pointer to the FrameSet.
2513 *     attrib
2514 *        Pointer to a null terminated string specifying the attribute
2515 *        name.  This should be in lower case with no surrounding white
2516 *        space.
2517 */
2518 
2519 /* Local Variables: */
2520    astDECLARE_GLOBALS            /* Declare the thread specific global data */
2521    AstFrame *fr;                 /* Pointer to current Frame */
2522    AstFrameSet *this;            /* Pointer to the FrameSet structure */
2523 
2524 /* Check the global error status. */
2525    if ( !astOK ) return;
2526 
2527 
2528 /* Get a pointer to the structure holding thread-specific global data. */
2529    astGET_GLOBALS(this_object);
2530 /* Obtain a pointer to the FrameSet structure. */
2531    this = (AstFrameSet *) this_object;
2532 
2533 /* Check the attribute name and clear the appropriate attribute. */
2534 
2535 /* We first handle attributes that apply to the FrameSet as a whole
2536    (rather than to the current Frame). */
2537 
2538 /* Base. */
2539 /* ----- */
2540    if ( !strcmp( attrib, "base" ) ) {
2541       astClearBase( this );
2542 
2543 /* Current. */
2544 /* -------- */
2545 /* Since this determines the choice of current Frame, we must restore
2546    the integrity state of the FrameSet before changing this attribute
2547    and record the new integrity state afterwards. */
2548    } else if ( !strcmp( attrib, "current" ) ) {
2549       RestoreIntegrity( this, status );
2550       astClearCurrent( this );
2551       RecordIntegrity( this, status );
2552 
2553 /* ID. */
2554 /* --- */
2555    } else if ( !strcmp( attrib, "id" ) ) {
2556       astClearID( this );
2557 
2558 /* Ident. */
2559 /* ------ */
2560    } else if ( !strcmp( attrib, "ident" ) ) {
2561       astClearIdent( this );
2562 
2563 /* Invert. */
2564 /* ------- */
2565 /* Since this affects the choice of current Frame, we must restore the
2566    integrity state of the FrameSet before changing this attribute and
2567    record the new integrity state afterwards. */
2568    } else if ( !strcmp( attrib, "invert" ) ) {
2569       RestoreIntegrity( this, status );
2570       astClearInvert( this );
2571       RecordIntegrity( this, status );
2572 
2573 /* Report. */
2574 /* ------- */
2575    } else if ( !strcmp( attrib, "report" ) ) {
2576       astClearReport( this );
2577 
2578 /* Variant. */
2579 /* -------- */
2580    } else if ( !strcmp( attrib, "variant" ) ) {
2581       astClearVariant( this );
2582 
2583 /* If the name was not recognised, test if it matches any of the
2584    read-only attributes of this class. If it does, then report an
2585    error. */
2586    } else if ( !strcmp( attrib, "allvariants" ) ||
2587                !strcmp( attrib, "class" ) ||
2588                !strcmp( attrib, "nframe" ) ||
2589                !strcmp( attrib, "nin" ) ||
2590                !strcmp( attrib, "nobject" ) ||
2591                !strcmp( attrib, "nout" ) ||
2592                !strcmp( attrib, "refcount" ) ||
2593                !strcmp( attrib, "tranforward" ) ||
2594                !strcmp( attrib, "traninverse" ) ) {
2595       astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" "
2596                 "value for a %s.", status, attrib, astGetClass( this ) );
2597       astError( AST__NOWRT, "This is a read-only attribute." , status);
2598 
2599 /* Pass unrecognised attributes on to the FrameSet's current Frame for
2600    further interpretation. */
2601    } else {
2602 
2603 /* Force a copy to be made of the current Frame, if needed, to make it
2604    independent of other Frames within the FrameSet. */
2605       (void) ForceCopy( this, AST__CURRENT, status );
2606 
2607 /* Obtain a pointer to the current Frame and invoke its astClearAttrib
2608    method. Annul the Frame pointer afterwards. */
2609       fr = astGetFrame( this, AST__CURRENT );
2610       astClearAttrib( fr, attrib );
2611       fr = astAnnul( fr );
2612 
2613 /* Note that the current Frame has been modified. */
2614       integrity_lost = 1;
2615    }
2616 }
2617 
ClearBase(AstFrameSet * this,int * status)2618 static void ClearBase( AstFrameSet *this, int *status ) {
2619 /*
2620 *+
2621 *  Name:
2622 *     astClearBase
2623 
2624 *  Purpose:
2625 *     Clear the value of the Base attribute of a FrameSet.
2626 
2627 *  Type:
2628 *     Protected virtual function.
2629 
2630 *  Synopsis:
2631 *     #include "frameset.h"
2632 *     void astClearBase( AstFrameSet *this )
2633 
2634 *  Class Membership:
2635 *     FrameSet method.
2636 
2637 *  Description:
2638 *     This function clears the value of the Base attribute of a
2639 *     FrameSet. This value is an index that identifies the base Frame
2640 *     for the FrameSet.
2641 
2642 *  Parameters:
2643 *     this
2644 *        Pointer to the FrameSet.
2645 *-
2646 */
2647 
2648 /* Local Variables: */
2649    int invert;                    /* FrameSet is inverted? */
2650 
2651 /* Check the global error status. */
2652    if ( !astOK ) return;
2653 
2654 /* Determine if the FrameSet has been inverted. */
2655    invert = astGetInvert( this );
2656 
2657 /* If it has not been inverted, clear the base Frame index, otherwise
2658    clear the current Frame index instead. */
2659    if ( astOK ) *( invert ? &this->current : &this->base ) = -INT_MAX;
2660 }
2661 
ClearCurrent(AstFrameSet * this,int * status)2662 static void ClearCurrent( AstFrameSet *this, int *status ) {
2663 /*
2664 *+
2665 *  Name:
2666 *     astClearCurrent
2667 
2668 *  Purpose:
2669 *     Clear the value of the Current attribute for a FrameSet.
2670 
2671 *  Type:
2672 *     Protected function.
2673 
2674 *  Synopsis:
2675 *     #include "frameset.h"
2676 *     int astClearCurrent( AstFrameSet *this )
2677 
2678 *  Class Membership:
2679 *     FrameSet method.
2680 
2681 *  Description:
2682 *     This function clears the value of the Current attribute for a
2683 *     FrameSet. This attribute is an index that identifies the current
2684 *     Frame for the FrameSet.
2685 
2686 *  Parameters:
2687 *     this
2688 *        Pointer to the FrameSet.
2689 *-
2690 */
2691 
2692 /* Local Variables: */
2693    int invert;                   /* FrameSet is inverted? */
2694 
2695 /* Check the global error status. */
2696    if ( !astOK ) return;
2697 
2698 /* Determine if the FrameSet has been inverted. */
2699    invert = astGetInvert( this );
2700 
2701 /* If it has not been inverted, clear the current frame index,
2702    otherwise clear the base Frame index instead. */
2703    if ( astOK ) *( invert ? &this->base : &this->current ) = -INT_MAX;
2704 }
2705 
ClearVariant(AstFrameSet * this,int * status)2706 static void ClearVariant( AstFrameSet *this, int *status ) {
2707 /*
2708 *+
2709 *  Name:
2710 *     astClearVariant
2711 
2712 *  Purpose:
2713 *     Clear the value of the Variant attribute of a FrameSet.
2714 
2715 *  Type:
2716 *     Protected virtual function.
2717 
2718 *  Synopsis:
2719 *     #include "frameset.h"
2720 *     void astClearVariant( AstFrameSet *this )
2721 
2722 *  Class Membership:
2723 *     FrameSet method.
2724 
2725 *  Description:
2726 *     This function clears the value of the Variant attribute of a
2727 *     FrameSet.
2728 
2729 *  Parameters:
2730 *     this
2731 *        Pointer to the FrameSet.
2732 *-
2733 */
2734 
2735 /* Local Variables: */
2736    AstFrame *frm;
2737    int icur;
2738 
2739 /* Check the global error status. */
2740    if ( !astOK ) return;
2741 
2742 /* Get the one-based index of the Frame to use. */
2743    icur = GetVarFrm( this, astGetCurrent( this ), status );
2744 
2745 /* Get a pointer to the current Frame in the FrameSet. */
2746    frm = astGetFrame( this, icur );
2747 
2748 /* Replace any Variants FrameSet in the Frame with a NULL pointer. */
2749    astSetFrameVariants( frm, NULL );
2750 
2751 /* Annul the current Frame pointer. */
2752    frm = astAnnul( frm );
2753 
2754 }
2755 
CombineMaps(AstMapping * mapping1,int invert1,AstMapping * mapping2,int invert2,int series,int * status)2756 static AstMapping *CombineMaps( AstMapping *mapping1, int invert1,
2757                                 AstMapping *mapping2, int invert2,
2758                                 int series, int *status ) {
2759 /*
2760 *  Name:
2761 *     CombineMaps
2762 
2763 *  Purpose:
2764 *     Combine two Mappings with specified Invert flags into a CmpMap.
2765 
2766 *  Type:
2767 *     Private function.
2768 
2769 *  Synopsis:
2770 *     #include "frameset.h"
2771 *     AstMapping *CombineMaps( AstMapping *mapping1, int invert1,
2772 *                              AstMapping *mapping2, int invert2,
2773 *                              int series )
2774 
2775 *  Class Membership:
2776 *     FrameSet member function.
2777 
2778 *  Description:
2779 *     This function combines two Mappings into a CmpMap (compound
2780 *     Mapping) as if their Invert flags were set to specified values
2781 *     when the CmpMap is created. However, the individual Mappings are
2782 *     returned with their Invert flag values unchanged from their
2783 *     original state.
2784 
2785 *  Parameters:
2786 *     mapping1
2787 *        Pointer to the first Mapping.
2788 *     invert1
2789 *        The (boolean) Invert flag value required for the first Mapping.
2790 *     mapping2
2791 *        Pointer to the second Mapping.
2792 *     invert2
2793 *        The (boolean) Invert flag value required for the second Mapping.
2794 *     series
2795 *        Whether the Mappings are to be combined in series (as opposed to
2796 *        in parallel).
2797 
2798 *  Returned Value:
2799 *     A pointer to the resulting compound Mapping (a CmpMap).
2800 
2801 *  Notes:
2802 *     - This function is a wrap-up for the astCmpMap constructor and
2803 *     temporarily assigns the required Invert flag values while
2804 *     creating the required CmpMap. However, it also takes account of
2805 *     the possibility that the two Mapping pointers supplied may point
2806 *     at the same Mapping.
2807 *     - A null Object pointer (AST__NULL) will be returned if this
2808 *     function is invoked with the AST error status set, or if it
2809 *     should fail for any reason.
2810 */
2811 
2812 /* Local Variables: */
2813    AstMapping *map1;             /* First temporary Mapping pointer */
2814    AstMapping *map2;             /* Second temporary Mapping pointer */
2815    AstMapping *result;           /* Pointer to result Mapping */
2816    int copy;                     /* Copy needed? */
2817    int inv1;                     /* First original Invert flag value */
2818    int inv2;                     /* Second original Invert flag value */
2819    int set1;                     /* First Invert flag originally set? */
2820    int set2;                     /* Second Invert flag originally set? */
2821 
2822 /* Initialise */
2823    result = NULL;
2824 
2825 /* Check the global error status. */
2826    if ( !astOK ) return result;
2827 
2828 /* Limit incoming values to 0 or 1. */
2829    invert1 = ( invert1 != 0 );
2830    invert2 = ( invert2 != 0 );
2831 
2832 /* Obtain the Invert flag values for each Mapping. */
2833    inv1 = astGetInvert( mapping1 );
2834    inv2 = astGetInvert( mapping2 );
2835 
2836 /* Also determine if these values are explicitly set. */
2837    set1 = astTestInvert( mapping1 );
2838    set2 = astTestInvert( mapping2 );
2839 
2840 /* If both Mappings are actually the same but we need different Invert
2841    flag values to be set, then this can only be achieved by making a
2842    copy. Note if this is necessary. */
2843    copy = ( ( mapping1 == mapping2 ) && ( invert1 != invert2 ) );
2844 
2845 /* Clone the first Mapping pointer. Do likewise for the second but
2846    make a copy instead if necessary. */
2847    map1 = astClone( mapping1 );
2848    map2 = copy ? astCopy( mapping2 ) : astClone( mapping2 );
2849 
2850 /* If the Invert value for the first Mapping needs changing, make the
2851    change. */
2852    if ( invert1 != inv1 ) {
2853       if ( invert1 ) {
2854          astSetInvert( map1, 1 );
2855       } else {
2856          astClearInvert( map1 );
2857       }
2858    }
2859 
2860 /* Similarly, change the Invert flag for the second Mapping if
2861    necessary. */
2862    if ( invert2 != inv2 ) {
2863       if ( invert2 ) {
2864          astSetInvert( map2, 1 );
2865       } else {
2866          astClearInvert( map2 );
2867       }
2868    }
2869 
2870 /* Combine the two Mappings into a CmpMap. */
2871    result = (AstMapping *) astCmpMap( map1, map2, series, "", status );
2872 
2873 /* If the first Mapping's Invert value was changed, restore it to its
2874    original state. */
2875    if ( invert1 != inv1 ) {
2876       if ( set1 ) {
2877          astSetInvert( map1, inv1 );
2878       } else {
2879          astClearInvert( map1 );
2880       }
2881    }
2882 
2883 /* Similarly, restore the second Mapping's Invert value if
2884    necessary. This step is not needed, however, if a copy was made. */
2885    if ( ( invert2 != inv2 ) && !copy ) {
2886       if ( set2 ) {
2887          astSetInvert( map2, inv2 );
2888       } else {
2889          astClearInvert( map2 );
2890       }
2891    }
2892 
2893 /* Annul the temporary Mapping pointers. */
2894    map1 = astAnnul( map1 );
2895    map2 = astAnnul( map2 );
2896 
2897 /* If an error occurred, then annul the result pointer. */
2898    if ( !astOK ) result = astAnnul( result );
2899 
2900 /* Return the result. */
2901    return result;
2902 }
2903 
Convert(AstFrame * from,AstFrame * to,const char * domainlist,int * status)2904 static AstFrameSet *Convert( AstFrame *from, AstFrame *to,
2905                              const char *domainlist, int *status ) {
2906 /*
2907 *  Name:
2908 *     Convert
2909 
2910 *  Purpose:
2911 *     Determine how to convert between two coordinate systems.
2912 
2913 *  Type:
2914 *     Private function.
2915 
2916 *  Synopsis:
2917 *     #include "frameset.h"
2918 *     AstFrameSet *Convert( AstFrame *from, AstFrame *to,
2919 *                           const char *domainlist, int *status )
2920 
2921 *  Class Membership:
2922 *     FrameSet member function (over-rides the public astConvert
2923 *     method inherited fromm the Frame class).
2924 
2925 *  Description:
2926 *     This function compares two FrameSets and determines whether it
2927 *     is possible to convert between the coordinate systems which
2928 *     their current Frames represent. If conversion is possible, it
2929 *     returns a FrameSet which describes the conversion and which may
2930 *     be used (as a Mapping) to transform coordinate values in either
2931 *     direction.
2932 *
2933 *     If conversion is possible, the Base attributes of both FrameSets
2934 *     will be modified on exit to identify the Frames which were used
2935 *     as the intermediate coordinate system.
2936 
2937 *  Parameters:
2938 *     from
2939 *        Pointer to a FrameSet whose current Frame represents the
2940 *        "source" coordinate system.  Note that the Base attribute of
2941 *        the FrameSet may be modified by this function.
2942 *     to
2943 *        Pointer to a FrameSet whose current Frame represents the
2944 *        "destination" coordinate system.  Note that the Base
2945 *        attribute of the FrameSet may be modified by this function.
2946 *     domainlist
2947 *        Pointer to a null-terminated character string containing a
2948 *        comma-separated list of Frame domains. This may be used to
2949 *        define a priority order for the different intermediate
2950 *        coordinate systems that might be used to perform the
2951 *        conversion.
2952 *
2953 *        The function will first try to obtain a conversion by making
2954 *        use only of intermediate Frames whose Domain attribute
2955 *        matches the first domain in this list. If this fails, the
2956 *        second domain in the list will be used, and so on, until
2957 *        conversion is achieved. A blank domain (e.g. two consecutive
2958 *        commas) indicates that all Frames should be considered,
2959 *        regardless of their Domain attributes. The list is
2960 *        case-insensitive and all white space is ignored.
2961 *     status
2962 *        Pointer to the inherited status variable.
2963 
2964 *  Returned Value:
2965 *        If the requested coordinate conversion is possible, the
2966 *        function returns a pointer to a FrameSet which describes the
2967 *        conversion. Otherwise, a null Object pointer (AST__NULL) is
2968 *        returned without error.
2969 *
2970 *        If a FrameSet is returned, it will contain two Frames. Frame
2971 *        number 1 (its base Frame) will describe the source coordinate
2972 *        system, corresponding to the "from" parameter. Frame number 2
2973 *        (its current Frame) will describe the destination coordinate
2974 *        system, corresponding to the "to" parameter. The Mapping
2975 *        which inter-relates these Frames will perform the required
2976 *        conversion between the two coordinate systems.
2977 
2978 *  Notes:
2979 *     - Either of the "from" and "to" pointers may identify a basic
2980 *     Frame instead of a FrameSet, in which case the function behaves
2981 *     as if it were a FrameSet containing only a single Frame.
2982 *     - A NULL pointer will be returned if this function is invoked
2983 *     with the global error status set, or if it should fail for any
2984 *     reason.
2985 
2986 * Implementation Notes:
2987 *    - This function is simply a wrap-up for the ConvertX function
2988 *    which performs the required processing but swaps the order of the
2989 *    first two arguments. This is a trick to allow the astConvert
2990 *    method to be over-ridden by derived classes on the basis of the
2991 *    class of either of the first two arguments.
2992 */
2993 
2994 /* Check the inherited status. */
2995    if ( !astOK ) return NULL;
2996 
2997 /* Invoke the private "ConvertX" member function with the first two
2998    arguments swapped. */
2999    return ConvertX( to, from, domainlist, status );
3000 }
3001 
ConvertX(AstFrame * to,AstFrame * from,const char * domainlist,int * status)3002 static AstFrameSet *ConvertX( AstFrame *to, AstFrame *from,
3003                               const char *domainlist, int *status ) {
3004 /*
3005 *  Name:
3006 *     ConvertX
3007 
3008 *  Purpose:
3009 *     Determine how to convert between two coordinate systems.
3010 
3011 *  Type:
3012 *     Private function.
3013 
3014 *  Synopsis:
3015 *     #include "frameset.h"
3016 *     AstFrameSet *ConvertX( AstFrame *to, AstFrame *from,
3017 *                            const char *domainlist )
3018 
3019 *  Class Membership:
3020 *     FrameSet member function (over-rides the protected "astConvertX"
3021 *     method inherited from the Frame class).
3022 
3023 *  Description:
3024 *     This function performs the processing for the public astConvert
3025 *     method (as inherited from the Frame class and over-ridden by the
3026 *     FrameSet class) and has exactly the same interface except that
3027 *     the order of the first two arguments is swapped. This is a trick
3028 *     to allow the astConvert method to be over-ridden by derived
3029 *     classes on the basis of the class of either of its first two
3030 *     arguments.
3031 *
3032 *     See the astConvert method for details of the interface.
3033 */
3034 
3035 /* Local Variables: */
3036    AstFrame *from_frame;         /* Pointer to "from" Frame */
3037    AstFrame *to_frame;           /* Pointer to "to" Frame */
3038    AstFrameSet *cvt;             /* Pointer to conversion FrameSet */
3039    AstFrameSet *result;          /* Pointer to FrameSet to be returned */
3040    AstMapping *from_map;         /* Pointer to "from" Mapping */
3041    AstMapping *map;              /* Pointer to conversion Mapping */
3042    AstMapping *result_map;       /* Pointer to result Mapping */
3043    AstMapping *tmp;              /* Temporary Mapping pointer */
3044    AstMapping *to_map;           /* Pointer to "to" Mapping */
3045    char *domain;                 /* Pointer to individual domain string */
3046    char *domain_end;             /* Pointer to final null of domain string */
3047    char *domainlist_copy;        /* Pointer to copy of domains list */
3048    int *from_order;              /* List of Frame indices in search order */
3049    int *to_order;                /* List of Frame indices in search order */
3050    int best_score;               /* Score from best match */
3051    int from_base;                /* Index of "from" base Frame */
3052    int from_current;             /* Index of "from" current Frame */
3053    int from_index;               /* Index of "from" Frame */
3054    int from_isframe;             /* "from" is a Frame (not a FrameSet)? */
3055    int from_nframe;              /* Number of "from" Frames */
3056    int from_number;              /* Loop counter for "from" Frames */
3057    int iframe_from;              /* Index of best "from" Frame */
3058    int iframe_to;                /* Index of best "to" Frame */
3059    int match;                    /* Possible match found? */
3060    int n;                        /* Count of Frames */
3061    int perfect;                  /* Perfect match found? */
3062    int score;                    /* Score from latest match */
3063    int to_base;                  /* Index of "to" base Frame */
3064    int to_current;               /* Index of "to" current Frame */
3065    int to_index;                 /* Index of "to" Frame */
3066    int to_isframe;               /* "to" is a Frame (not a FrameSet)? */
3067    int to_nframe;                /* Number of "to" Frames */
3068    int to_number;                /* Loop counter for "to" Frames */
3069 
3070 /* Initialise. */
3071    result = NULL;
3072 
3073 /* Check the global error status. */
3074    if ( !astOK ) return result;
3075 
3076 /* Initialise variables to avoid "used of uninitialised variable"
3077    messages from dumb compilers. */
3078    result_map = NULL;
3079    iframe_from = 0;
3080    iframe_to = 0;
3081 
3082 /* Determine the number of Frames in "from" and the indices of its
3083    base and current Frames. Use values of 1 if "from" is a Frame and
3084    not a FrameSet. */
3085    from_isframe = !astIsAFrameSet( from );
3086    from_nframe = from_isframe ? 1 : astGetNframe( from );
3087    from_base = from_isframe ? 1 : astGetBase( from );
3088    from_current = from_isframe ? 1 : astGetCurrent( from );
3089 
3090 /* Obtain similar values for "to". */
3091    to_isframe = !astIsAFrameSet( to );
3092    to_nframe = to_isframe ? 1 : astGetNframe( to );
3093    to_base = to_isframe ? 1 : astGetBase( to );
3094    to_current = to_isframe ? 1 : astGetCurrent( to );
3095 
3096 /* Allocate memory for arrays which will hold the indices of "from"
3097    and "to" Frames. */
3098    from_order = astMalloc( sizeof( int ) * (size_t) from_nframe );
3099    to_order = astMalloc( sizeof( int ) * (size_t) to_nframe );
3100 
3101 /* Make a temporary copy of the domains list. */
3102    domainlist_copy = astStore( NULL, domainlist,
3103                                strlen( domainlist ) + (size_t) 1 );
3104    if ( astOK ) {
3105 
3106 /* Fill the "from_order" array with the indices of all the Frames in
3107    "from", in the order in which they will be used for searching. Use
3108    the base Frame first. */
3109       n = 0;
3110       from_order[ n++ ] = from_base;
3111 
3112 /* Then add all the "from" Frames in the appropriate order, omitting
3113    the base and current Frames. */
3114       if ( !astGetInvert( from ) ) {
3115          for ( from_index = 1; from_index <= from_nframe; from_index++ ) {
3116             if ( ( from_index != from_base ) &&
3117                  ( from_index != from_current ) ) {
3118                from_order[ n++ ] = from_index;
3119             }
3120          }
3121       } else {
3122          for ( from_index = from_nframe; from_index >= 1; from_index-- ) {
3123             if ( ( from_index != from_base ) &&
3124                  ( from_index != from_current ) ) {
3125                from_order[ n++ ] = from_index;
3126             }
3127          }
3128       }
3129 
3130 /* Finish with the current Frame, if different from the base Frame. */
3131       if ( from_current != from_base ) from_order[ n++ ] = from_current;
3132 
3133 /* Repeat this process for the "to" Frame. */
3134       n = 0;
3135       to_order[ n++ ] = to_base;
3136       if ( !astGetInvert( to ) ) {
3137          for ( to_index = 1; to_index <= to_nframe; to_index++ ) {
3138             if ( ( to_index != to_base ) && ( to_index != to_current ) ) {
3139                to_order[ n++ ] = to_index;
3140             }
3141          }
3142       } else {
3143          for ( to_index = to_nframe; to_index >= 1; to_index-- ) {
3144             if ( ( to_index != to_base ) && ( to_index != to_current ) ) {
3145                to_order[ n++ ] = to_index;
3146             }
3147          }
3148       }
3149       if ( to_current != to_base ) to_order[ n++ ] = to_current;
3150 
3151 /* Loop to inspect each comma-separated field in the domains list
3152    until an error occurs, all the domains are used up, or a match is
3153    found. */
3154       domain = domainlist_copy;
3155       match = 0;
3156       while ( astOK && domain && !match ) {
3157 
3158 /* Change the comma at the end of each field to a null to terminate
3159    the domain. */
3160          if ( ( domain_end = strchr( domain, ',' ) ) ) *domain_end = '\0';
3161 
3162 /* For any given domain, we will ignore imperfect matches in favour of
3163    better ones by assigning a score to each match. Initialise the best
3164    score value for the current domain. */
3165          best_score = -1;
3166 
3167 /* Loop through each Frame in "to". Quit looping early if an error
3168    occurs or a perfect match is found. */
3169          perfect = 0;
3170          for ( to_number = 0;
3171                astOK && !perfect && ( to_number < to_nframe );
3172                to_number++ ) {
3173 
3174 /* Permute the "to" Frame number into a Frame index to implement the
3175    required search order, and obtain a pointer to the required "to"
3176    Frame. */
3177             to_index = to_order[ to_number ];
3178             to_frame = to_isframe ? astClone( to ) :
3179                                     astGetFrame( to, to_index );
3180 
3181 /* Loop through each Frame in "from". Quit looping early if an error
3182    occurs or a perfect match is found. */
3183             for ( from_number = 0;
3184                   astOK && !perfect && ( from_number < from_nframe );
3185                   from_number++ ) {
3186 
3187 /* Permute the "from" Frame number into a Frame index to implement the
3188    required search order, and obtain a pointer to the required "from"
3189    Frame. */
3190                from_index = from_order[ from_number ];
3191                from_frame = from_isframe ? astClone( from ) :
3192                                            astGetFrame( from, from_index );
3193 
3194 /* Attempt to obtain a FrameSet which describes the conversion between
3195    the selected "from" and "to" Frames and test if successful. If so,
3196    we have a potential route to construct the overall Mapping we
3197    want. */
3198                cvt = astConvert( from_frame, to_frame, domain );
3199                if ( astOK && cvt ) {
3200 
3201 /* Extract the required Mapping from the returned FrameSet. */
3202                   map = astGetMapping( cvt, AST__BASE, AST__CURRENT );
3203 
3204 /* If necessary, prefix the Mapping between the "from" current Frame
3205    and the individual "from" Frame we have selected. */
3206                   if ( from_index != from_current ) {
3207                      from_map = astGetMapping( from, AST__CURRENT,
3208                                                from_index );
3209                      tmp = (AstMapping *) astCmpMap( from_map, map, 1, "", status );
3210                      from_map = astAnnul( from_map );
3211                      map = astAnnul( map );
3212                      map = tmp;
3213                   }
3214 
3215 /* Similarly, if necessary, append the Mapping between the selected
3216    "to" Frame and the "to" current Frame. */
3217                   if ( to_index != to_current ) {
3218                      to_map = astGetMapping( to, to_index, AST__CURRENT );
3219                      tmp = (AstMapping *) astCmpMap( map, to_map, 1, "", status );
3220                      to_map = astAnnul( to_map );
3221                      map = astAnnul( map );
3222                      map = tmp;
3223                   }
3224 
3225 /* Simplify the resulting overall Mapping (this is done here because
3226    it may sometimes affect the attribute values used to assign a score
3227    below). */
3228                   tmp = astSimplify( map );
3229                   map = astAnnul( map );
3230                   map = tmp;
3231 
3232 /* Assign a score that favours Mappings with both transformations
3233    available over those with only one, and Mappings with only a
3234    forward transformation over those with only an inverse
3235    transformation. */
3236                   score = ( astGetTranForward( map ) ? 2 : 0 ) +
3237                           ( astGetTranInverse( map ) ? 1 : 0 );
3238 
3239 /* If the new score is better than the previous one (or is the first
3240    one), note that we have a possible match. */
3241                   if ( astOK && ( score > best_score ) ) {
3242                      match = 1;
3243 
3244 /* Update the best score and note if it indicates a perfect match (in
3245    which case we can stop searching at this point). */
3246                      best_score = score;
3247                      perfect = ( best_score >= 3 );
3248 
3249 /* Annul any previous result Mapping pointer and replace it with this
3250    better one. */
3251                      if ( result_map ) result_map = astAnnul( result_map );
3252                      result_map = astClone( map );
3253 
3254 /* Note which "from" and "to" Frames were used. */
3255                      iframe_from = from_index;
3256                      iframe_to = to_index;
3257                   }
3258 
3259 /* Annul pointers to the intermediate Objects. */
3260                   map = astAnnul( map );
3261                   cvt = astAnnul( cvt );
3262                }
3263                from_frame = astAnnul( from_frame );
3264             }
3265             to_frame = astAnnul( to_frame );
3266          }
3267 
3268 /* Go on to consider the next field in the domains list. */
3269          domain = domain_end ? domain_end + 1 : NULL;
3270       }
3271    }
3272 
3273 /* Free the memory allocated for temporary arrays. */
3274    domainlist_copy = astFree( domainlist_copy );
3275    from_order = astFree( from_order );
3276    to_order = astFree( to_order );
3277 
3278 /* If a result is being returned, then obtain a pointer to the current
3279    "from" Frame and use it to start constructing the result
3280    FrameSet. */
3281    if ( result_map ) {
3282       from_frame = from_isframe ? astClone( from ) :
3283                                   astGetFrame( from, AST__CURRENT );
3284       result = astFrameSet( from_frame, "", status );
3285       from_frame = astAnnul( from_frame );
3286 
3287 /* Similarly. obtain a pointer to the current "to" frame and add it to
3288    the result FrameSet (related to the base Frame by the result
3289    Mapping). */
3290       to_frame = to_isframe ? astClone( to ) :
3291                               astGetFrame( to, AST__CURRENT );
3292       astAddFrame( result, AST__BASE, result_map, to_frame );
3293       to_frame = astAnnul( to_frame );
3294 
3295 /* Annul the result Mapping pointer. */
3296       result_map = astAnnul( result_map );
3297    }
3298 
3299 /* If successful, and a FrameSet is being returned, then set the base
3300    Frames of "from" and "to" (if they are FrameSets) to indicate the
3301    route used to generate the result Mapping. */
3302    if ( astOK && result ) {
3303       if ( !from_isframe ) astSetBase( from, iframe_from );
3304       if ( !to_isframe ) astSetBase( to, iframe_to );
3305    }
3306 
3307 /* If an error occurred, annul the returned FrameSet pointer. */
3308    if ( !astOK && result ) result = astAnnul( result );
3309 
3310 /* Return the result. */
3311    return result;
3312 }
3313 
Distance(AstFrame * this_frame,const double point1[],const double point2[],int * status)3314 static double Distance( AstFrame *this_frame,
3315                         const double point1[], const double point2[], int *status ) {
3316 /*
3317 *  Name:
3318 *     Distance
3319 
3320 *  Purpose:
3321 *     Calculate the distance between two points.
3322 
3323 *  Type:
3324 *     Private function.
3325 
3326 *  Synopsis:
3327 *     #include "frameset.h"
3328 *     double Distance( AstFrame *this,
3329 *                      const double point1[], const double point2[], int *status )
3330 
3331 *  Class Membership:
3332 *     FrameSet member function (over-rides the protected astDistance
3333 *     method inherited from the Frame class).
3334 
3335 *  Description:
3336 *     This function finds the distance between two points whose
3337 *     FrameSet coordinates are given. The distance calculated is that
3338 *     along the geodesic curve that joins the two points.
3339 
3340 *  Parameters:
3341 *     this
3342 *        Pointer to the FrameSet.
3343 *     point1
3344 *        An array of double, with one element for each FrameSet axis
3345 *        containing the coordinates of the first point.
3346 *     point2
3347 *        An array of double, with one element for each FrameSet axis
3348 *        containing the coordinates of the second point.
3349 *     status
3350 *        Pointer to the inherited status variable.
3351 
3352 *  Returned Value:
3353 *     The distance between the two points.
3354 
3355 *  Notes:
3356 *     - This function will return a "bad" result value (AST__BAD) if
3357 *     any of the input coordinates has this value.
3358 *     - A "bad" value will also be returned if this function is
3359 *     invoked with the AST error status set or if it should fail for
3360 *     any reason.
3361 */
3362 
3363 /* Local Variables: */
3364    AstFrame *fr;                 /* Pointer to current Frame */
3365    AstFrameSet *this;            /* Pointer to the FrameSet structure */
3366    double result;                /* Value to return */
3367 
3368 /* Check the global error status. */
3369    if ( !astOK ) return AST__BAD;
3370 
3371 /* Obtain a pointer to the FrameSet structure. */
3372    this = (AstFrameSet *) this_frame;
3373 
3374 /* Obtain a pointer to the FrameSet's current Frame and invoke this
3375    Frame's astDistance method. Annul the Frame pointer afterwards. */
3376    fr = astGetFrame( this, AST__CURRENT );
3377    result = astDistance( fr, point1, point2 );
3378    fr = astAnnul( fr );
3379 
3380 /* If an error occurred, clear the result. */
3381    if ( !astOK ) result = AST__BAD;
3382 
3383 /* Return the result. */
3384    return result;
3385 }
3386 
Equal(AstObject * this_object,AstObject * that_object,int * status)3387 static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
3388 /*
3389 *  Name:
3390 *     Equal
3391 
3392 *  Purpose:
3393 *     Test if two FrameSets are equivalent.
3394 
3395 *  Type:
3396 *     Private function.
3397 
3398 *  Synopsis:
3399 *     #include "frameset.h"
3400 *     int Equal( AstObject *this, AstObject *that, int *status )
3401 
3402 *  Class Membership:
3403 *     FrameSet member function (over-rides the astEqual protected
3404 *     method inherited from the Mapping class).
3405 
3406 *  Description:
3407 *     This function returns a boolean result (0 or 1) to indicate whether
3408 *     two FrameSets are equivalent.
3409 
3410 *  Parameters:
3411 *     this
3412 *        Pointer to the first FrameSet.
3413 *     that
3414 *        Pointer to the second FrameSet.
3415 *     status
3416 *        Pointer to the inherited status variable.
3417 
3418 *  Returned Value:
3419 *     One if the FrameSets are equivalent, zero otherwise.
3420 
3421 *  Notes:
3422 *     - The two FrameSets are considered equivalent if all the encapsulated
3423 *     Frames are equal and all the encapsulated Mappings are equal.
3424 *     - A value of zero will be returned if this function is invoked
3425 *     with the global status set, or if it should fail for any reason.
3426 */
3427 
3428 /* Local Variables: */
3429    AstFrameSet *that;            /* Pointer to the second FrameSet structure */
3430    AstFrameSet *this;            /* Pointer to the first FrameSet structure */
3431    int i;                        /* Loop index */
3432    int result;                   /* Result value to return */
3433 
3434 /* Initialise. */
3435    result = 0;
3436 
3437 /* Check the global error status. */
3438    if ( !astOK ) return result;
3439 
3440 /* Checks that the second object is of the same class as the first . */
3441    if( !strcmp( astGetClass( this_object ), astGetClass( that_object ) ) ){
3442 
3443 /* Obtain pointers to the two FrameSet structures. */
3444       this = (AstFrameSet *) this_object;
3445       that = (AstFrameSet *) that_object;
3446 
3447 /* Check the number of nodes and frames are equal. Also check the indices
3448    of the base and current Frames are equal */
3449       if( this->nframe == that->nframe &&
3450           this->nnode == that->nnode &&
3451           this->base == that->base &&
3452           this->current == that->current ) {
3453 
3454 /* Check the Frames and nodes are equal. */
3455           result = 1;
3456           for ( i = 0; i < this->nframe; i++ ) {
3457              if( !astEqual( this->frame[ i ], that->frame[ i ] ) ||
3458                  this->node[ i ] != that->node[ i ] ){
3459                 result = 0;
3460                 break;
3461              }
3462           }
3463 
3464 /* Check the Mappings, links and invert flags are equal. */
3465          if( result ) {
3466             for ( i = 0; i < this->nnode - 1; i++ ) {
3467                if( !astEqual( this->map[ i ], that->map[ i ] ) ||
3468                    this->link[ i ] != that->link[ i ] ||
3469                    this->invert[ i ] != that->invert[ i ] ) {
3470                   result = 0;
3471                   break;
3472                }
3473             }
3474          }
3475       }
3476    }
3477 
3478 /* If an error occurred, clear the result value. */
3479    if ( !astOK ) result = 0;
3480 
3481 /* Return the result, */
3482    return result;
3483 }
3484 
Fields(AstFrame * this_frame,int axis,const char * fmt,const char * str,int maxfld,char ** fields,int * nc,double * val,int * status)3485 static int Fields( AstFrame *this_frame, int axis, const char *fmt,
3486                    const char *str, int maxfld, char **fields,
3487                    int *nc, double *val, int *status ) {
3488 /*
3489 *+
3490 *  Name:
3491 *     astFields
3492 
3493 *  Purpose:
3494 *     Identify numerical fields within a formatted FrameSet axis value.
3495 
3496 *  Type:
3497 *     Protected virtual function.
3498 
3499 *  Synopsis:
3500 *     #include "frameset.h"
3501 *     int astFields( AstFrame *this, int axis, const char *fmt,
3502 *                    const char *str, int maxfld, char **fields,
3503 *                    int *nc, double *val )
3504 
3505 *  Class Membership:
3506 *     FrameSet member function (over-rides the protected astFields
3507 *     method inherited from the Frame class).
3508 
3509 *  Description:
3510 *     This function identifies the numerical fields within a FrameSet axis
3511 *     value that has been formatted using astAxisFormat. It assumes that
3512 *     the value was formatted using the supplied format string. It also
3513 *     returns the equivalent floating point value.
3514 
3515 *  Parameters:
3516 *     this
3517 *        Pointer to the FrameSet.
3518 *     axis
3519 *        The number of the FrameSet axis for which the values have been
3520 *        formatted (axis numbering starts at zero for the first axis).
3521 *     fmt
3522 *        Pointer to a constant null-terminated string containing the
3523 *        format used when creating "str".
3524 *     str
3525 *        Pointer to a constant null-terminated string containing the
3526 *        formatted value.
3527 *     maxfld
3528 *        The maximum number of fields to identify within "str".
3529 *     fields
3530 *        A pointer to an array of at least "maxfld" character pointers.
3531 *        Each element is returned holding a pointer to the start of the
3532 *        corresponding field  in "str" (in the order in which they occur
3533 *        within "str"), or NULL if no corresponding field can be found.
3534 *     nc
3535 *        A pointer to an array of at least "maxfld" integers. Each
3536 *        element is returned holding the number of characters in the
3537 *        corresponding field, or zero if no corresponding field can be
3538 *        found.
3539 *     val
3540 *        Pointer to a location at which to store the value
3541 *        equivalent to the returned field values. If this is NULL,
3542 *        it is ignored.
3543 
3544 *  Returned Value:
3545 *     The number of fields succesfully identified and returned.
3546 
3547 *  Notes:
3548 *     - Leading and trailing spaces are ignored.
3549 *     - If the formatted value is not consistent with the supplied format
3550 *     string, then a value of zero will be returned, "fields" will be
3551 *     returned holding NULLs, "nc" will be returned holding zeros, and
3552 *     "val" is returned holding VAL__BAD.
3553 *     - Fields are counted from the start of the formatted string. If the
3554 *     string contains more than "maxfld" fields, then trailing fields are
3555 *     ignored.
3556 *     - If this function is invoked with the global error status set, or
3557 *     if it should fail for any reason, then a value of zero will be returned
3558 *     as the function value, and "fields", "nc" and "val"  will be returned
3559 *     holding their supplied values
3560 *-
3561 */
3562 
3563 /* Local Variables: */
3564    AstFrame *fr;                 /* Pointer to current Frame */
3565    AstFrameSet *this;            /* Pointer to the FrameSet structure */
3566    int result;                   /* Result field count to return */
3567 
3568 /* Check the global error status. */
3569    if ( !astOK ) return 0;
3570 
3571 /* Obtain a pointer to the FrameSet structure. */
3572    this = (AstFrameSet *) this_frame;
3573 
3574 /* Validate the axis index. */
3575    (void) astValidateAxis( this, axis, 1, "astFields" );
3576 
3577 /* Obtain a pointer to the FrameSet's current Frame and invoke this
3578    Frame's astFields method to perform the processing. Annul the Frame
3579    pointer afterwards. */
3580    fr = astGetFrame( this, AST__CURRENT );
3581    result = astFields( fr, axis, fmt, str, maxfld, fields, nc, val );
3582    fr = astAnnul( fr );
3583 
3584 /* If an error occurred, clear the result. */
3585    if ( !astOK ) result = 0;
3586 
3587 /* Return the result. */
3588    return result;
3589 }
3590 
FindFrame(AstFrame * target_frame,AstFrame * template,const char * domainlist,int * status)3591 static AstFrameSet *FindFrame( AstFrame *target_frame, AstFrame *template,
3592                                const char *domainlist, int *status ) {
3593 /*
3594 *  Name:
3595 *     FindFrame
3596 
3597 *  Purpose:
3598 *     Find a coordinate system with specified characteristics.
3599 
3600 *  Type:
3601 *     Private function.
3602 
3603 *  Synopsis:
3604 *     #include "frameset.h"
3605 *     AstFrameSet *FindFrame( AstFrame *target, AstFrame *template,
3606 *                             const char *domainlist, int *status )
3607 
3608 *  Class Membership:
3609 *     FrameSet member function (over-rides the astFindFrame method
3610 *     inherited from the Frame class).
3611 
3612 *  Description:
3613 *     This function uses a "template" Frame to search a FrameSet to
3614 *     identify a coordinate system which has a specified set of
3615 *     characteristics. If a suitable coordinate system can be found,
3616 *     the function returns a pointer to a FrameSet which describes the
3617 *     required coordinate system and how to convert coordinates to and
3618 *     from it.
3619 
3620 *  Parameters:
3621 *     target
3622 *        Pointer to the target FrameSet.  Note that if a suitable
3623 *        coordinate system is found, then the FrameSet's Current
3624 *        attribute will be modified to indicate which Frame was used
3625 *        to obtain attribute values which were not specified by the
3626 *        template.
3627 *     template
3628 *        Pointer to the template Frame, which should be an instance of
3629 *        the type of Frame you wish to find.
3630 *     domainlist
3631 *        Pointer to a null-terminated character string containing a
3632 *        comma-separated list of Frame domains. This may be used to
3633 *        establish a priority order for the different types of
3634 *        coordinate system that might be found.
3635 *
3636 *        The function will first try to find a suitable coordinate
3637 *        system whose Domain attribute equals the first domain in this
3638 *        list. If this fails, the second domain in the list will be
3639 *        used, and so on, until a result is obtained. A blank domain
3640 *        (e.g. two consecutive commas) indicates that any coordinate
3641 *        system is acceptable (subject to the template) regardless of
3642 *        its domain.
3643 *
3644 *        This list is case-insensitive and all white space is ignored.
3645 *        If you do not wish to restrict the domain in this way, you
3646 *        should supply an empty string.
3647 *     status
3648 *        Pointer to the inherited status variable.
3649 
3650 *  Returned Value:
3651 *     If the search is successful, the function returns a pointer to a
3652 *     FrameSet which contains the Frame found and a description of how
3653 *     to convert to (and from) the coordinate system it
3654 *     represents. Otherwise, a null Object pointer (AST__NULL) is
3655 *     returned without error.
3656 *
3657 *     If a FrameSet is returned, it will contain two Frames. Frame
3658 *     number 1 (its base Frame) represents the target coordinate
3659 *     system and will be the same as the (base Frame of the)
3660 *     target. Frame number 2 (its current Frame) will be a Frame
3661 *     representing the coordinate system which the function found. The
3662 *     Mapping which inter-relates these two Frames will describe how
3663 *     to convert between their respective coordinate systems.
3664 
3665 *  Notes:
3666 *     - A null Object pointer (AST__NULL) will be returned if this
3667 *     function is invoked with the AST error status set, or if it
3668 *     should fail for any reason.
3669 */
3670 
3671 /* Local Variables: */
3672    AstFrame *base_frame;         /* Pointer to target base Frame */
3673    AstFrame *frame;              /* Pointer to result Frame */
3674    AstFrame *selected_frame;     /* Pointer to selected target Frame */
3675    AstFrameSet *found;           /* FrameSet pointer (result of search) */
3676    AstFrameSet *result;          /* Pointer to result FrameSet */
3677    AstFrameSet *target;          /* Pointer to target FrameSet structure */
3678    AstMapping *map;              /* Pointer to result Mapping */
3679    AstMapping *prefix;           /* Pointer to prefix Mapping */
3680    AstMapping *tmp;              /* Temporary Mapping pointer */
3681    char *domain;                 /* Pointer to individual domain field */
3682    char *domain_end;             /* Pointer to null at end of domain */
3683    char *domainlist_copy;        /* Pointer to copy of domains list */
3684    int *target_order;            /* Array of indices defining search order */
3685    int match;                    /* Match obtained? */
3686    int n;                        /* Count of target_order elements */
3687    int target_base;              /* Index of target base Frame */
3688    int target_current;           /* Index of target current Frame */
3689    int target_index;             /* Index of selected target Frame */
3690    int target_nframe;            /* Number of Frames in target FrameSet */
3691    int target_number;            /* Loop index for search */
3692 
3693 /* Initialise. */
3694    result = NULL;
3695 
3696 /* Check the global error status. */
3697    if ( !astOK ) return result;
3698 
3699 /* Initialise variables to avoid "used of uninitialised variable"
3700    messages from dumb compilers. */
3701    target_index = 0;
3702 
3703 /* Obtain a pointer to the target FrameSet structure. */
3704    target = (AstFrameSet *) target_frame;
3705 
3706 /* Determine the number of Frames in the target FrameSet and the
3707    indices of the current and base Frames. */
3708    target_nframe = astGetNframe( target );
3709    target_current = astGetCurrent( target );
3710    target_base = astGetBase( target );
3711 
3712 /* Allocate an array to hold a list of all the target Frame indices. */
3713    target_order = astMalloc( sizeof( int ) * (size_t) target_nframe );
3714 
3715 /* Make a temporary copy of the domains list. */
3716    domainlist_copy = astStore( NULL, domainlist,
3717                                strlen( domainlist ) + (size_t) 1 );
3718    if ( astOK ) {
3719 
3720 /* Form a list of the indices of all the Frames in the target in the
3721    order they will be searched for a match. Add the current Frame
3722    index first. */
3723       n = 0;
3724       target_order[ n++ ] = target_current;
3725 
3726 /* Follow this by the base Frame index, if different. */
3727       if ( target_base != target_current ) target_order[ n++ ] = target_base;
3728 
3729 /* Then add all the remaining target Frame indices. */
3730       for ( target_index = 1; target_index <= target_nframe; target_index++ ) {
3731          if ( ( target_index != target_current ) &&
3732               ( target_index != target_base ) ) {
3733             target_order[ n++ ] = target_index;
3734          }
3735       }
3736 
3737 /* Loop to inspect each comma-separated field in the domains list
3738    until an error occurs, all the domains are used up, or a match is
3739    found. */
3740       domain = domainlist_copy;
3741       match = 0;
3742       while ( astOK && domain && !match ) {
3743 
3744 /* Change the comma at the end of each field to a null to terminate
3745    the domain. */
3746          if ( ( domain_end = strchr( domain, ',' ) ) ) *domain_end = '\0';
3747 
3748 /* Loop to try and match each target Frame in turn, in the order
3749    identified above. Quit the loop early if an error occurs or a match
3750    is found. */
3751          for ( target_number = 0;
3752                astOK && !match && ( target_number < target_nframe );
3753                target_number++ ) {
3754 
3755 /* Permute the target Frame number into a Frame index to implement the
3756    required search order. Then obtain a pointer to the selected target
3757    Frame. */
3758             target_index = target_order[ target_number ];
3759             selected_frame = astGetFrame( target, target_index );
3760 
3761 /* Search the target Frame using the template supplied, together with
3762    the current domain. */
3763             found = astFindFrame( selected_frame, template, domain );
3764 
3765 /* Note if a match is found, and extract pointers to the conversion
3766    Mapping and the result Frame from the FrameSet produced. */
3767             if ( astOK && found ) {
3768                match = 1;
3769                map = astGetMapping( found, AST__BASE, AST__CURRENT );
3770                frame = astGetFrame( found, AST__CURRENT );
3771 
3772 /* Obtain a pointer to the Mapping between the target base Frame and
3773    the selected target Frame, and prefix this Mapping to the one
3774    obtained above. */
3775                prefix = astGetMapping( target, AST__BASE, target_index );
3776                tmp = (AstMapping *) astCmpMap( prefix, map, 1, "", status );
3777                prefix = astAnnul( prefix );
3778                map = astAnnul( map );
3779                map = tmp;
3780 
3781 /* Simplify the resulting Mapping. */
3782                tmp = astSimplify( map );
3783                map = astAnnul( map );
3784                map = tmp;
3785 
3786 /* Obtain a pointer to the target base Frame, and use this to start
3787    building the result FrameSet. */
3788                base_frame = astGetFrame( target, AST__BASE );
3789                result = astFrameSet( base_frame, "", status );
3790                base_frame = astAnnul( base_frame );
3791 
3792 /* Add the result Frame, which is related to the base Frame by the
3793    result Mapping. */
3794                astAddFrame( result, AST__BASE, map, frame );
3795 
3796 /* Annul pointers to all intermediate Objects. */
3797                map = astAnnul( map );
3798                frame = astAnnul( frame );
3799                found = astAnnul( found );
3800             }
3801             selected_frame = astAnnul( selected_frame );
3802          }
3803 
3804 /* Go on to consider the next field in the domains list. */
3805          domain = domain_end ? domain_end + 1 : NULL;
3806       }
3807    }
3808 
3809 /* Free the temporary arrays. */
3810    target_order = astFree( target_order );
3811    domainlist_copy = astFree( domainlist_copy );
3812 
3813 /* If a result is being returned, set the current Frame of the target
3814    to indicate where the result Frame was found. */
3815    if ( astOK && result ) astSetCurrent( target, target_index );
3816 
3817 /* If an error occurred, annul any result FrameSet pointer. */
3818    if ( !astOK && result ) result = astAnnul( result );
3819 
3820 /* Return the result. */
3821    return result;
3822 }
3823 
FrameGrid(AstFrame * this_frame,int size,const double * lbnd,const double * ubnd,int * status)3824 static AstPointSet *FrameGrid( AstFrame *this_frame, int size, const double *lbnd,
3825                                const double *ubnd, int *status ){
3826 /*
3827 *  Name:
3828 *     FrameGrid
3829 
3830 *  Purpose:
3831 *     Return a grid of points covering a rectangular area of a Frame.
3832 
3833 *  Type:
3834 *     Private function.
3835 
3836 *  Synopsis:
3837 *     #include "frameset.h"
3838 *     AstPointSet *FrameGrid( AstFrame *this_frame, int size,
3839 *                             const double *lbnd, const double *ubnd,
3840 *                             int *status )
3841 
3842 *  Class Membership:
3843 *     FrameSet member function (over-rides the protected astFrameGrid
3844 *     method inherited from the Frame class).
3845 
3846 *  Description:
3847 *     This function returns a PointSet containing positions spread
3848 *     approximately evenly throughtout a specified rectangular area of
3849 *     the Frame.
3850 
3851 *  Parameters:
3852 *     this
3853 *        Pointer to the Frame.
3854 *     size
3855 *        The preferred number of points in the returned PointSet. The
3856 *        actual number of points in the returned PointSet may be
3857 *        different, but an attempt is made to stick reasonably closely to
3858 *        the supplied value.
3859 *     lbnd
3860 *        Pointer to an array holding the lower bound of the rectangular
3861 *        area on each Frame axis. The array should have one element for
3862 *        each Frame axis.
3863 *     ubnd
3864 *        Pointer to an array holding the upper bound of the rectangular
3865 *        area on each Frame axis. The array should have one element for
3866 *        each Frame axis.
3867 
3868 *  Returned Value:
3869 *     A pointer to a new PointSet holding the grid of points.
3870 
3871 *  Notes:
3872 *     - A NULL pointer is returned if an error occurs.
3873 */
3874 
3875 /* Local Variables: */
3876    AstFrame *fr;                 /* Pointer to current Frame */
3877    AstFrameSet *this;            /* Pointer to the FrameSet structure */
3878    AstPointSet *result;          /* Value to return */
3879 
3880 /* Check the global error status. */
3881    if ( !astOK ) return NULL;
3882 
3883 /* Obtain a pointer to the FrameSet structure. */
3884    this = (AstFrameSet *) this_frame;
3885 
3886 /* Obtain a pointer to the FrameSet's current Frame and invoke this
3887    Frame's astFrameGrid method. Annul the Frame pointer afterwards. */
3888    fr = astGetFrame( this, AST__CURRENT );
3889    result = astFrameGrid( fr, size, lbnd, ubnd );
3890    fr = astAnnul( fr );
3891 
3892 /* If an error occurred, clear the result. */
3893    if ( !astOK ) result = astAnnul( result );
3894 
3895 /* Return the result. */
3896    return result;
3897 }
3898 
ForceCopy(AstFrameSet * this,int iframe,int * status)3899 static int ForceCopy( AstFrameSet *this, int iframe, int *status ) {
3900 /*
3901 *  Name:
3902 *     ForceCopy
3903 
3904 *  Purpose:
3905 *     Force a copy to be made of a Frame, if necessary.
3906 
3907 *  Type:
3908 *     Private function.
3909 
3910 *  Synopsis:
3911 *     #include "frameset.h"
3912 *     int ForceCopy( AstFrameSet *this, int iframe, int *status )
3913 
3914 *  Class Membership:
3915 *     FrameSet member function.
3916 
3917 *  Description:
3918 *     This function examines a Frame within a FrameSet, identified by its
3919 *     Frame index. If the same Frame is found to be referenced a second time
3920 *     within the FrameSet, then the original reference is replaced with an
3921 *     independent copy of the Frame.
3922 *
3923 *     This process supports the preservation of FrameSet integrity in cases
3924 *     where the same Frame is referenced more than once. After using this
3925 *     function, the nominated Frame's attributes may be modified without
3926 *     danger of affecting other parts of the FrameSet.
3927 
3928 *  Parameters:
3929 *     this
3930 *        Pointer to the FrameSet.
3931 *     iframe
3932 *        The index of the Frame to be examined.
3933 *     status
3934 *        Pointer to the inherited status variable.
3935 
3936 *  Returned Value:
3937 *     One if a copy of the nominated Frame was made, otherwise zero.
3938 
3939 *  Notes:
3940 *     - Using this function a second time on the same Frame will have no
3941 *     effect, since the first usage will make the Frame independent of any
3942 *     other Frames within the FrameSet.
3943 *     - A value of zero will be returned if this function is invoked with
3944 *     the global error status set, or if it should fail for any reason.
3945 */
3946 
3947 /* Local Variables: */
3948    astDECLARE_GLOBALS           /* Declare the thread specific global data */
3949    AstFrame *frame;             /* Pointer to Frame */
3950    AstFrame *tmp;               /* Temporary Frame pointer */
3951    int ifr;                     /* Loop counter for Frames */
3952    int result;                  /* Value to return */
3953 
3954 /* Initialise. */
3955    result = 0;
3956 
3957 /* Check the global error status. */
3958    if ( !astOK ) return result;
3959 
3960 /* Get a pointer to the structure holding thread-specific global data. */
3961    astGET_GLOBALS(this);
3962 
3963 /* Validate and translate the Frame index supplied. */
3964    iframe = astValidateFrameIndex( this, iframe, integrity_method );
3965 
3966 /* If OK, obtain the corresponding Frame pointer (don't clone it). */
3967    if ( astOK ) {
3968       frame = this->frame[ iframe - 1 ];
3969 
3970 /* Loop to inspect each Frame in the FrameSet. */
3971       for ( ifr = 1; ifr <= this->nframe; ifr++ ) {
3972 
3973 /* If the same Frame is referenced anywhere else, then make a copy of it. */
3974          if ( ( ifr != iframe ) && ( this->frame[ ifr - 1 ] == frame ) ) {
3975             tmp = astCopy( frame );
3976 
3977 /* If successful, replace the original reference to the Frame with a pointer
3978    to this copy and annul the original pointer. */
3979             if ( astOK ) {
3980                this->frame[ iframe - 1 ] = tmp;
3981                frame = astAnnul( frame );
3982 
3983 /* Set the returned result. */
3984                if ( astOK ) result = 1;
3985             }
3986 
3987 /* Quit looping once a copy has been made. */
3988             break;
3989          }
3990       }
3991    }
3992 
3993 /* Return the result. */
3994    return result;
3995 }
3996 
Format(AstFrame * this_frame,int axis,double value,int * status)3997 static const char *Format( AstFrame *this_frame, int axis, double value, int *status ) {
3998 /*
3999 *  Name:
4000 *     Format
4001 
4002 *  Purpose:
4003 *     Format a coordinate value for a FrameSet axis.
4004 
4005 *  Type:
4006 *     Private function.
4007 
4008 *  Synopsis:
4009 *     #include "frameset.h"
4010 *     const char *Format( AstFrame *this, int axis, double value, int *status )
4011 
4012 *  Class Membership:
4013 *     FrameSet member function (over-rides the astFormat method
4014 *     inherited from the Frame class).
4015 
4016 *  Description:
4017 *     This function returns a pointer to a string containing the
4018 *     formatted (character) version of a coordinate value for a
4019 *     FrameSet axis. The formatting applied is that specified by a
4020 *     previous invocation of the astSetFormat method. A suitable
4021 *     default format is applied if necessary.
4022 
4023 *  Parameters:
4024 *     this
4025 *        Pointer to the FrameSet.
4026 *     axis
4027 *        The number of the axis (zero-based) for which formatting is
4028 *        to be performed.
4029 *     value
4030 *        The coordinate value to be formatted.
4031 *     status
4032 *        Pointer to the inherited status variable.
4033 
4034 *  Returned Value:
4035 *     A pointer to a null-terminated string containing the formatted
4036 *     value.
4037 
4038 *  Notes:
4039 *     - The returned string pointer may point at memory allocated
4040 *     within the FrameSet object, or at static memory. The contents of
4041 *     the string may be over-written or the pointer may become invalid
4042 *     following a further invocation of the same function or deletion
4043 *     of the FrameSet. A copy of the string should therefore be made
4044 *     if necessary.
4045 *     - A NULL pointer will be returned if this function is invoked
4046 *     with the global error status set, or if it should fail for any
4047 *     reason.
4048 */
4049 
4050 /* Local Variables: */
4051    AstFrame *fr;                 /* Pointer to current Frame */
4052    AstFrameSet *this;            /* Pointer to the FrameSet structure */
4053    const char *result;           /* Pointer value to return */
4054 
4055 /* Check the global error status. */
4056    if ( !astOK ) return NULL;
4057 
4058 /* Obtain a pointer to the FrameSet structure. */
4059    this = (AstFrameSet *) this_frame;
4060 
4061 /* Validate the axis index. */
4062    (void) astValidateAxis( this, axis, 1, "astFormat" );
4063 
4064 /* Obtain a pointer to the FrameSet's current Frame and invoke the
4065    astFormat method for this Frame. Annul the Frame pointer
4066    afterwards. */
4067    fr = astGetFrame( this, AST__CURRENT );
4068    result = astFormat( fr, axis, value );
4069    fr = astAnnul( fr );
4070 
4071 /* If an error occurred, clear the result value. */
4072    if ( !astOK ) result = NULL;
4073 
4074 /* Return the result. */
4075    return result;
4076 }
4077 
Gap(AstFrame * this_frame,int axis,double gap,int * ntick,int * status)4078 static double Gap( AstFrame *this_frame, int axis, double gap, int *ntick, int *status ) {
4079 /*
4080 *  Name:
4081 *     Gap
4082 
4083 *  Purpose:
4084 *     Find a "nice" gap for tabulating FrameSet axis values.
4085 
4086 *  Type:
4087 *     Private function.
4088 
4089 *  Synopsis:
4090 *     #include "frameset.h"
4091 *     double Gap( AstFrame *this, int axis, double gap, int *ntick, int *status )
4092 
4093 *  Class Membership:
4094 *     FrameSet member function (over-rides the protected astGap method
4095 *     inherited from the Frame class).
4096 
4097 *  Description:
4098 *     This function returns a gap size which produces a nicely spaced
4099 *     series of formatted values for a FrameSet axis, the returned gap
4100 *     size being as close as possible to the supplied target gap
4101 *     size. It also returns a convenient number of divisions into
4102 *     which the gap can be divided.
4103 
4104 *  Parameters:
4105 *     this
4106 *        Pointer to the FrameSet.
4107 *     axis
4108 *        The number of the axis (zero-based) for which a gap is to be found.
4109 *     gap
4110 *        The target gap size.
4111 *     ntick
4112 *        Address of an int in which to return a convenient number of
4113 *        divisions into which the gap can be divided.
4114 *     status
4115 *        Pointer to the inherited status variable.
4116 
4117 *  Returned Value:
4118 *     The nice gap size.
4119 
4120 *  Notes:
4121 *     - A value of zero is returned if the target gap size is zero.
4122 *     - A negative gap size is returned if the supplied gap size is negative.
4123 *     - A value of zero will be returned if this function is invoked
4124 *     with the global error status set, or if it should fail for any
4125 *     reason.
4126 */
4127 
4128 /* Local Variables: */
4129    AstFrame *fr;                 /* Pointer to current Frame */
4130    AstFrameSet *this;            /* Pointer to the FrameSet structure */
4131    double result;                /* Gap value to return */
4132 
4133 /* Check the global error status. */
4134    if ( !astOK ) return 0.0;
4135 
4136 /* Obtain a pointer to the FrameSet structure. */
4137    this = (AstFrameSet *) this_frame;
4138 
4139 /* Validate the axis index. */
4140    (void) astValidateAxis( this, axis, 1, "astGap" );
4141 
4142 /* Obtain a pointer to the FrameSet's current Frame and invoke this
4143    Frame's astGap method to obtain the required gap value. Annul the
4144    Frame pointer afterwards. */
4145    fr = astGetFrame( this, AST__CURRENT );
4146    result = astGap( fr, axis, gap, ntick );
4147    fr = astAnnul( fr );
4148 
4149 /* If an error occurred, clear the result. */
4150    if ( !astOK ) result = 0.0;
4151 
4152 /* Return the result. */
4153    return result;
4154 }
4155 
GetObjSize(AstObject * this_object,int * status)4156 static int GetObjSize( AstObject *this_object, int *status ) {
4157 /*
4158 *  Name:
4159 *     GetObjSize
4160 
4161 *  Purpose:
4162 *     Return the in-memory size of an Object.
4163 
4164 *  Type:
4165 *     Private function.
4166 
4167 *  Synopsis:
4168 *     #include "frameset.h"
4169 *     int GetObjSize( AstObject *this, int *status )
4170 
4171 *  Class Membership:
4172 *     FrameSet member function (over-rides the astGetObjSize protected
4173 *     method inherited from the parent class).
4174 
4175 *  Description:
4176 *     This function returns the in-memory size of the supplied FrameSet,
4177 *     in bytes.
4178 
4179 *  Parameters:
4180 *     this
4181 *        Pointer to the FrameSet.
4182 *     status
4183 *        Pointer to the inherited status variable.
4184 
4185 *  Returned Value:
4186 *     The Object size, in bytes.
4187 
4188 *  Notes:
4189 *     - A value of zero will be returned if this function is invoked
4190 *     with the global status set, or if it should fail for any reason.
4191 */
4192 
4193 /* Local Variables: */
4194    AstFrameSet *this;         /* Pointer to FrameSet structure */
4195    int result;                /* Result value to return */
4196    int iframe;                /* Loop counter for Frames */
4197    int inode;                 /* Loop counter for nodes */
4198 
4199 /* Initialise. */
4200    result = 0;
4201 
4202 /* Check the global error status. */
4203    if ( !astOK ) return result;
4204 
4205 /* Obtain a pointers to the FrameSet structure. */
4206    this = (AstFrameSet *) this_object;
4207 
4208 /* Invoke the GetObjSize method inherited from the parent class, and then
4209    add on any components of the class structure defined by thsi class
4210    which are stored in dynamically allocated memory. */
4211    result = (*parent_getobjsize)( this_object, status );
4212 
4213    for ( iframe = 0; iframe < this->nframe; iframe++ ) {
4214       result += astGetObjSize( this->frame[ iframe ] );
4215    }
4216 
4217    for ( inode = 0; inode < this->nnode - 1; inode++ ) {
4218       result += astGetObjSize( this->map[ inode ] );
4219    }
4220 
4221    result += astTSizeOf( this->frame );
4222    result += astTSizeOf( this->varfrm );
4223    result += astTSizeOf( this->node );
4224    result += astTSizeOf( this->map );
4225    result += astTSizeOf( this->link );
4226    result += astTSizeOf( this->invert );
4227 
4228 /* If an error occurred, clear the result value. */
4229    if ( !astOK ) result = 0;
4230 
4231 /* Return the result, */
4232    return result;
4233 }
4234 
GetAttrib(AstObject * this_object,const char * attrib,int * status)4235 static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) {
4236 /*
4237 *  Name:
4238 *     GetAttrib
4239 
4240 *  Purpose:
4241 *     Get the value of a specified attribute for a FrameSet.
4242 
4243 *  Type:
4244 *     Private function.
4245 
4246 *  Synopsis:
4247 *     #include "frameset.h"
4248 *     const char *GetAttrib( AstObject *this, const char *attrib, int *status )
4249 
4250 *  Class Membership:
4251 *     FrameSet member function (over-rides the protected astGetAttrib
4252 *     method inherited from the Frame class).
4253 
4254 *  Description:
4255 *     This function returns a pointer to the value of a specified
4256 *     attribute for a FrameSet, formatted as a character string.
4257 
4258 *  Parameters:
4259 *     this
4260 *        Pointer to the FrameSet.
4261 *     attrib
4262 *        Pointer to a null-terminated string containing the name of
4263 *        the attribute whose value is required. This name should be in
4264 *        lower case, with all white space removed.
4265 *     status
4266 *        Pointer to the inherited status variable.
4267 
4268 *  Returned Value:
4269 *     - Pointer to a null-terminated string containing the attribute
4270 *     value.
4271 
4272 *  Notes:
4273 *     - The returned string pointer may point at memory allocated
4274 *     within the FrameSet, or at static memory. The contents of the
4275 *     string may be over-written or the pointer may become invalid
4276 *     following a further invocation of the same function or any
4277 *     modification of the FrameSet. A copy of the string should
4278 *     therefore be made if necessary.
4279 *     - A NULL pointer will be returned if this function is invoked
4280 *     with the global error status set, or if it should fail for any
4281 *     reason.
4282 */
4283 
4284 /* Local Variables: */
4285    astDECLARE_GLOBALS            /* Declare the thread specific global data */
4286    AstFrame *fr;                 /* Pointer to current Frame */
4287    AstFrameSet *this;            /* Pointer to the FrameSet structure */
4288    const char *result;           /* Pointer value to return */
4289    int base;                     /* Base attribute value */
4290    int current;                  /* Current attribute value */
4291    int invert;                   /* Invert attribute value */
4292    int nframe;                   /* Nframe attribute value */
4293    int nin;                      /* Nin attribute value */
4294    int nobject;                  /* Nobject attribute value */
4295    int nout;                     /* Nout attribute value */
4296    int ref_count;                /* RefCount attribute value */
4297    int report;                   /* Report attribute value */
4298    int tranforward;              /* TranForward attribute value */
4299    int traninverse;              /* TranInverse attribute value */
4300 
4301 /* Initialise. */
4302    result = NULL;
4303 
4304 /* Check the global error status. */
4305    if ( !astOK ) return result;
4306 
4307 /* Get a pointer to the structure holding thread-specific global data. */
4308    astGET_GLOBALS(this_object);
4309 
4310 /* Obtain a pointer to the FrameSet structure. */
4311    this = (AstFrameSet *) this_object;
4312 
4313 /* Compare "attrib" with each recognised attribute name in turn,
4314    obtaining the value of the required attribute. If necessary, write
4315    the value into "getattrib_buff" as a null-terminated string in an appropriate
4316    format.  Set "result" to point at the result string. */
4317 
4318 /* We first handle attributes that apply to the FrameSet as a whole
4319    (rather than to the current Frame). */
4320 
4321 /* AllVariants. */
4322 /* ------------ */
4323    if ( !strcmp( attrib, "allvariants" ) ) {
4324       result = astGetAllVariants( this );
4325 
4326 /* Base. */
4327 /* ----- */
4328    } else if ( !strcmp( attrib, "base" ) ) {
4329       base = astGetBase( this );
4330       if ( astOK ) {
4331          (void) sprintf( getattrib_buff, "%d", base );
4332          result = getattrib_buff;
4333       }
4334 
4335 /* Class. */
4336 /* ------ */
4337    } else if ( !strcmp( attrib, "class" ) ) {
4338       result = astGetClass( this );
4339 
4340 /* Current. */
4341 /* -------- */
4342    } else if ( !strcmp( attrib, "current" ) ) {
4343       current = astGetCurrent( this );
4344       if ( astOK ) {
4345          (void) sprintf( getattrib_buff, "%d", current );
4346          result = getattrib_buff;
4347       }
4348 
4349 /* ID. */
4350 /* --- */
4351    } else if ( !strcmp( attrib, "id" ) ) {
4352       result = astGetID( this );
4353 
4354 /* Ident. */
4355 /* ------ */
4356    } else if ( !strcmp( attrib, "ident" ) ) {
4357       result = astGetIdent( this );
4358 
4359 /* Invert. */
4360 /* ------- */
4361    } else if ( !strcmp( attrib, "invert" ) ) {
4362       invert = astGetInvert( this );
4363       if ( astOK ) {
4364          (void) sprintf( getattrib_buff, "%d", invert );
4365          result = getattrib_buff;
4366       }
4367 
4368 /* Nframe. */
4369 /* ------- */
4370    } else if ( !strcmp( attrib, "nframe" ) ) {
4371       nframe = astGetNframe( this );
4372       if ( astOK ) {
4373          (void) sprintf( getattrib_buff, "%d", nframe );
4374          result = getattrib_buff;
4375       }
4376 
4377 /* Nin. */
4378 /* ---- */
4379    } else if ( !strcmp( attrib, "nin" ) ) {
4380       nin = astGetNin( this );
4381       if ( astOK ) {
4382          (void) sprintf( getattrib_buff, "%d", nin );
4383          result = getattrib_buff;
4384       }
4385 
4386 /* Nobject. */
4387 /* -------- */
4388    } else if ( !strcmp( attrib, "nobject" ) ) {
4389       nobject = astGetNobject( this );
4390       if ( astOK ) {
4391          (void) sprintf( getattrib_buff, "%d", nobject );
4392          result = getattrib_buff;
4393       }
4394 
4395 /* Nout. */
4396 /* ----- */
4397    } else if ( !strcmp( attrib, "nout" ) ) {
4398       nout = astGetNout( this );
4399       if ( astOK ) {
4400          (void) sprintf( getattrib_buff, "%d", nout );
4401          result = getattrib_buff;
4402       }
4403 
4404 /* RefCount. */
4405 /* --------- */
4406    } else if ( !strcmp( attrib, "refcount" ) ) {
4407       ref_count = astGetRefCount( this );
4408       if ( astOK ) {
4409          (void) sprintf( getattrib_buff, "%d", ref_count );
4410          result = getattrib_buff;
4411       }
4412 
4413 /* Report. */
4414 /* ------- */
4415    } else if ( !strcmp( attrib, "report" ) ) {
4416       report = astGetReport( this );
4417       if ( astOK ) {
4418          (void) sprintf( getattrib_buff, "%d", report );
4419          result = getattrib_buff;
4420       }
4421 
4422 /* TranForward. */
4423 /* ------------ */
4424    } else if ( !strcmp( attrib, "tranforward" ) ) {
4425       tranforward = astGetTranForward( this );
4426       if ( astOK ) {
4427          (void) sprintf( getattrib_buff, "%d", tranforward );
4428          result = getattrib_buff;
4429       }
4430 
4431 /* TranInverse. */
4432 /* ------------ */
4433    } else if ( !strcmp( attrib, "traninverse" ) ) {
4434       traninverse = astGetTranInverse( this );
4435       if ( astOK ) {
4436          (void) sprintf( getattrib_buff, "%d", traninverse );
4437          result = getattrib_buff;
4438       }
4439 
4440 /* Variant. */
4441 /* -------- */
4442    } else if ( !strcmp( attrib, "variant" ) ) {
4443       result = astGetVariant( this );
4444 
4445 /* Pass unrecognised attributes on to the FrameSet's current Frame for
4446    further interpretation. */
4447    } else {
4448 
4449 /* Obtain a pointer to the current Frame and invoke its astGetAttrib
4450    method. Annul the Frame pointer afterwards. */
4451       fr = astGetFrame( this, AST__CURRENT );
4452       result = astGetAttrib( fr, attrib );
4453       fr = astAnnul( fr );
4454    }
4455 
4456 /* If an error occurred, clear the result value. */
4457    if ( !astOK ) result = NULL;
4458 
4459 /* Return the result. */
4460    return result;
4461 }
4462 
GetAxis(AstFrame * this_frame,int axis,int * status)4463 static AstAxis *GetAxis( AstFrame *this_frame, int axis, int *status ) {
4464 /*
4465 *  Name:
4466 *     GetAxis
4467 
4468 *  Purpose:
4469 *     Obtain a pointer to a specified Axis from a FrameSet.
4470 
4471 *  Type:
4472 *     Private function.
4473 
4474 *  Synopsis:
4475 *     #include "frameset.h"
4476 *     AstAxis *GetAxis( AstFrame *this, int axis, int *status )
4477 
4478 *  Class Membership:
4479 *     FrameSet member function (over-rides the astGetAxis method
4480 *     inherited from the Frame class).
4481 
4482 *  Description:
4483 *     This function returns a pointer to the Axis object associated
4484 *     with one of the axes of the current Frame of a FrameSet. This
4485 *     object describes the quantity which is represented along that
4486 *     axis.
4487 
4488 *  Parameters:
4489 *     this
4490 *        Pointer to the FrameSet.
4491 *     axis
4492 *        The number of the axis (zero-based) for which an Axis pointer
4493 *        is required.
4494 *     status
4495 *        Pointer to the inherited status variable.
4496 
4497 *  Returned Value:
4498 *     A pointer to the requested Axis object.
4499 
4500 *  Notes:
4501 *     - The reference count of the requested Axis object will be
4502 *     incremented by one to reflect the additional pointer returned by
4503 *     this function.
4504 *     - A NULL pointer will be returned if this function is invoked
4505 *     with the global error status set, or if it should fail for any
4506 *     reason.
4507 */
4508 
4509 /* Local Variables: */
4510    AstAxis *result;              /* Pointer to Axis */
4511    AstFrame *fr;                 /* Pointer to current Frame */
4512    AstFrameSet *this;            /* Pointer to the FrameSet structure */
4513 
4514 /* Check the global error status. */
4515    if ( !astOK ) return NULL;
4516 
4517 /* Obtain a pointer to the FrameSet structure. */
4518    this = (AstFrameSet *) this_frame;
4519 
4520 /* Validate the axis index. */
4521    (void) astValidateAxis( this, axis, 1, "astGetAxis" );
4522 
4523 /* Obtain a pointer to the FrameSet's current Frame and invoke this
4524    Frame's astGetAxis method to obtain the required Axis
4525    pointer. Annul the Frame pointer afterwards. */
4526    fr = astGetFrame( this, AST__CURRENT );
4527    result = astGetAxis( fr, axis );
4528    fr = astAnnul( fr );
4529 
4530 /* If an error occurred, annul the result. */
4531    if ( !astOK ) result = astAnnul( result );
4532 
4533 /* Return the result. */
4534    return result;
4535 }
4536 
GetBase(AstFrameSet * this,int * status)4537 static int GetBase( AstFrameSet *this, int *status ) {
4538 /*
4539 *+
4540 *  Name:
4541 *     astGetBase
4542 
4543 *  Purpose:
4544 *     Obtain the value of the Base attribute for a FrameSet.
4545 
4546 *  Type:
4547 *     Protected virtual function.
4548 
4549 *  Synopsis:
4550 *     #include "frameset.h"
4551 *     int astGetBase( AstFrameSet *this )
4552 
4553 *  Class Membership:
4554 *     FrameSet method.
4555 
4556 *  Description:
4557 *     This function returns the value of the Base attribute for a
4558 *     FrameSet. This value is an index that identifies the base Frame
4559 *     in the FrameSet.
4560 
4561 *  Parameters:
4562 *     this
4563 *        Pointer to the FrameSet.
4564 
4565 *  Returned Value:
4566 *     The Base attribute value.
4567 
4568 *  Notes:
4569 *     - A value of zero will be returned if this function is invoked
4570 *     with the global status set, or if it should fail for any reason.
4571 *-
4572 */
4573 
4574 /* Local Variables: */
4575    int invert;                   /* FrameSet is inverted? */
4576    int result;                   /* Value to return */
4577 
4578 /* Initialise */
4579    result = 0;
4580 
4581 /* Check the global error status. */
4582    if ( !astOK ) return result;
4583 
4584 /* Determine if the FrameSet has been inverted. */
4585    invert = astGetInvert( this );
4586 
4587 /* If it has not been inverted, return the base Frame index, otherwise
4588    return the index of the current Frame instead. Provide defaults if
4589    necessary. */
4590    if ( astOK ) {
4591       if ( !invert ) {
4592          result = ( this->base != -INT_MAX ) ? this->base : 1;
4593       } else {
4594          result = ( this->current != -INT_MAX ) ? this->current :
4595                                                   astGetNframe( this );
4596       }
4597    }
4598 
4599 /* If an error occurred, clear the result. */
4600    if ( !astOK ) result = 0;
4601 
4602 /* Return the result. */
4603    return result;
4604 }
4605 
GetCurrent(AstFrameSet * this,int * status)4606 static int GetCurrent( AstFrameSet *this, int *status ) {
4607 /*
4608 *+
4609 *  Name:
4610 *     astGetCurrent
4611 
4612 *  Purpose:
4613 *     Obtain the value of the Current attribute for a FrameSet.
4614 
4615 *  Type:
4616 *     Protected function.
4617 
4618 *  Synopsis:
4619 *     #include "frameset.h"
4620 *     int astGetCurrent( AstFrameSet *this )
4621 
4622 *  Class Membership:
4623 *     FrameSet method.
4624 
4625 *  Description:
4626 *     This function returns the value of the Current attribute for a
4627 *     FrameSet.  This attribute is an index that identifies the
4628 *     current Frame in a FrameSet.
4629 
4630 *  Parameters:
4631 *     this
4632 *        Pointer to the FrameSet.
4633 
4634 *  Returned Value:
4635 *     Value of the Current attribute.
4636 
4637 *  Notes:
4638 *     - A value of zero will be returned if this function is invoked
4639 *     with the global status set, or if it should fail for any reason.
4640 *-
4641 */
4642 
4643 /* Local Variables: */
4644    int invert;                   /* FrameSet is inverted? */
4645    int result;                   /* Value to return */
4646 
4647 /* Initialise */
4648    result = 0;
4649 
4650 /* Check the global error status. */
4651    if ( !astOK ) return result;
4652 
4653 /* Determine if the FrameSet has been inverted. */
4654    invert = astGetInvert( this );
4655 
4656 /* If it has not been inverted, return the current Frame index,
4657    otherwise return the index of the base Frame instead. Provide
4658    defaults if necessary. */
4659    if ( astOK ) {
4660       if ( !invert ) {
4661          result = ( this->current != -INT_MAX ) ? this->current :
4662                                                   astGetNframe( this );
4663       } else {
4664          result = ( this->base != -INT_MAX ) ? this->base : 1;
4665       }
4666    }
4667 
4668 /* If an error occurred, clear the result. */
4669    if ( !astOK ) result = 0;
4670 
4671 /* Return the result. */
4672    return result;
4673 }
4674 
GetFrame(AstFrameSet * this,int iframe,int * status)4675 static AstFrame *GetFrame( AstFrameSet *this, int iframe, int *status ) {
4676 /*
4677 *++
4678 *  Name:
4679 c     astGetFrame
4680 f     AST_GETFRAME
4681 
4682 *  Purpose:
4683 *     Obtain a pointer to a specified Frame in a FrameSet.
4684 
4685 *  Type:
4686 *     Public virtual function.
4687 
4688 *  Synopsis:
4689 c     #include "frameset.h"
4690 c     AstFrame *astGetFrame( AstFrameSet *this, int iframe )
4691 f     RESULT = AST_GETFRAME( THIS, IFRAME, STATUS )
4692 
4693 *  Class Membership:
4694 *     FrameSet method.
4695 
4696 *  Description:
4697 *     This function returns a pointer to a specified Frame in a
4698 *     FrameSet.
4699 
4700 *  Parameters:
4701 c     this
4702 f     THIS = INTEGER (Given)
4703 *        Pointer to the FrameSet.
4704 c     iframe
4705 f     IFRAME = INTEGER (Given)
4706 *        The index of the required Frame within the FrameSet.  This
4707 *        value should lie in the range from 1 to the number of Frames
4708 *        in the FrameSet (as given by its Nframe attribute).
4709 f     STATUS = INTEGER (Given and Returned)
4710 f        The global status.
4711 
4712 *  Returned Value:
4713 c     astGetFrame()
4714 f     AST_GETFRAME = INTEGER
4715 *        A pointer to the requested Frame.
4716 
4717 *  Notes:
4718 *     - A value of AST__BASE or AST__CURRENT may be given for the
4719 c     "iframe" parameter to specify the base Frame or the current
4720 f     IFRAME argument to specify the base Frame or the current
4721 *     Frame respectively.
4722 *     - This function increments the RefCount attribute of the
4723 *     selected Frame by one.
4724 *     - A null Object pointer (AST__NULL) will be returned if this
4725 c     function is invoked with the AST error status set, or if it
4726 f     function is invoked with STATUS set to an error value, or if it
4727 *     should fail for any reason.
4728 *--
4729 */
4730 
4731 /* Local Variables: */
4732    AstFrame *result;             /* Pointer value to return */
4733 
4734 /* Initialise. */
4735    result = NULL;
4736 
4737 /* Check the global error status. */
4738    if ( !astOK ) return result;
4739 
4740 /* Validate and translate the Frame index supplied. */
4741    iframe = astValidateFrameIndex( this, iframe, "astGetFrame" );
4742 
4743 /* If OK, clone a pointer to the requested Frame. */
4744    if ( astOK ) result = astClone( this->frame[ iframe - 1 ] );
4745 
4746 /* Return the result. */
4747    return result;
4748 }
4749 
GetIsLinear(AstMapping * this_mapping,int * status)4750 static int GetIsLinear( AstMapping *this_mapping, int *status ){
4751 /*
4752 *  Name:
4753 *     GetIsLinear
4754 
4755 *  Purpose:
4756 *     Return the value of the IsLinear attribute for a FrameSet.
4757 
4758 *  Type:
4759 *     Private function.
4760 
4761 *  Synopsis:
4762 *     #include "mapping.h"
4763 *     void GetIsLinear( AstMapping *this, int *status )
4764 
4765 *  Class Membership:
4766 *     FrameSet member function (over-rides the protected astGetIsLinear
4767 *     method inherited from the Mapping class).
4768 
4769 *  Description:
4770 *     This function returns the value of the IsLinear attribute for a
4771 *     FrameSet, which is the IsLinear value of he base->current Mapping.
4772 
4773 *  Parameters:
4774 *     this
4775 *        Pointer to the Frame.
4776 *     status
4777 *        Pointer to the inherited status variable.
4778 */
4779 /* Local Variables: */
4780    AstMapping *map;
4781    int result;
4782 
4783 /* Check global status */
4784    if( !astOK ) return 0;
4785 
4786 /* Get the Mapping. */
4787    map = astGetMapping( (AstFrameSet *) this_mapping, AST__BASE,
4788                         AST__CURRENT );
4789 
4790 /* Get its IsLinear attribute value. */
4791    result = astGetIsLinear( map );
4792 
4793 /* Free the Mapping. */
4794    map = astAnnul( map );
4795 
4796 /* Return the result. */
4797    return result;
4798 }
4799 
GetMapping(AstFrameSet * this,int iframe1,int iframe2,int * status)4800 static AstMapping *GetMapping( AstFrameSet *this, int iframe1, int iframe2, int *status ) {
4801 /*
4802 *++
4803 *  Name:
4804 c     astGetMapping
4805 f     AST_GETMAPPING
4806 
4807 *  Purpose:
4808 *     Obtain a Mapping that converts between two Frames in a FrameSet.
4809 
4810 *  Type:
4811 *     Public virtual function.
4812 
4813 *  Synopsis:
4814 c     #include "frameset.h"
4815 c     AstMapping *astGetMapping( AstFrameSet *this, int iframe1, int iframe2 )
4816 f     RESULT = AST_GETMAPPING( THIS, IFRAME1, IFRAME2, STATUS )
4817 
4818 *  Class Membership:
4819 *     FrameSet method.
4820 
4821 *  Description:
4822 *     This function returns a pointer to a Mapping that will convert
4823 *     coordinates between the coordinate systems represented by two
4824 *     Frames in a FrameSet.
4825 
4826 *  Parameters:
4827 c     this
4828 f     THIS = INTEGER (Given)
4829 *        Pointer to the FrameSet.
4830 c     iframe1
4831 f     IFRAME1 = INTEGER (Given)
4832 *        The index of the first Frame in the FrameSet. This Frame describes
4833 *        the coordinate system for the "input" end of the Mapping.
4834 c     iframe2
4835 f     IFRAME2 = INTEGER (Given)
4836 *        The index of the second Frame in the FrameSet. This Frame
4837 *        describes the coordinate system for the "output" end of the
4838 *        Mapping.
4839 f     STATUS = INTEGER (Given and Returned)
4840 f        The global status.
4841 
4842 *  Returned Value:
4843 c     astGetMapping()
4844 f     AST_GETMAPPING = INTEGER
4845 *        Pointer to a Mapping whose forward transformation converts
4846 *        coordinates from the first coordinate system to the second
4847 *        one, and whose inverse transformation converts coordinates in
4848 *        the opposite direction.
4849 
4850 *  Notes:
4851 *     - The returned Mapping will include the clipping effect of any
4852 *     Regions which occur on the path between the two supplied Frames
4853 *     (this includes the two supplied Frames themselves).
4854 c     - The values given for the "iframe1" and "iframe2" parameters
4855 f     - The values given for the IFRAME1 and IFRAME2 arguments
4856 *     should lie in the range from 1 to the number of Frames in the
4857 *     FrameSet (as given by its Nframe attribute). A value of
4858 *     AST__BASE or AST__CURRENT may also be given to identify the
4859 *     FrameSet's base Frame or current Frame respectively.  It is
4860 c     permissible for both these parameters to have the same value, in
4861 f     permissible for both these arguments to have the same value, in
4862 *     which case a unit Mapping (UnitMap) is returned.
4863 *     - It should always be possible to generate the Mapping
4864 *     requested, but this does necessarily guarantee that it will be
4865 *     able to perform the required coordinate conversion. If
4866 *     necessary, the TranForward and TranInverse attributes of the
4867 *     returned Mapping should be inspected to determine if the
4868 *     required transformation is available.
4869 *     - A null Object pointer (AST__NULL) will be returned if this
4870 c     function is invoked with the AST error status set, or if it
4871 f     function is invoked with STATUS set to an error value, or if it
4872 *     should fail for any reason.
4873 *--
4874 */
4875 
4876 /* Local Variables: */
4877    AstFrame *fr;                 /* Temporary pointer to Frame */
4878    AstFrame **frames;            /* Pointer to array of Frames */
4879    AstMapping **path;            /* Pointer to array of conversion Mappings */
4880    AstMapping *copy;             /* Pointer to copy of Mapping */
4881    AstMapping *result;           /* Result pointer to be returned */
4882    AstMapping *tmp;              /* Temporary pointer for joining Mappings */
4883    int *forward;                 /* Pointer to array of Mapping directions */
4884    int ipath;                    /* Loop counter for conversion path steps */
4885    int iframe;                   /* Frame index */
4886    int inode;                    /* Node index */
4887    int npath;                    /* Number of steps in conversion path */
4888 
4889 /* Initialise. */
4890    result = NULL;
4891 
4892 /* Check the global error status. */
4893    if ( !astOK ) return result;
4894 
4895 /* Validate and translate the Frame indices supplied. */
4896    iframe1 = astValidateFrameIndex( this, iframe1, "astGetMapping" );
4897    iframe2 = astValidateFrameIndex( this, iframe2, "astGetMapping" );
4898 
4899 /* Allocate memory to hold an array of Mapping pointers and associated
4900    direction flags - a maximum of one element for each Mapping and one
4901    for each Frame in the FrameSet. */
4902    path = astMalloc( sizeof( AstMapping * ) * (size_t) ( this->nnode - 1 +
4903                                                          this->nframe ) );
4904    forward = astMalloc( sizeof( int ) * (size_t) ( this->nnode - 1 +
4905                                                    this->nframe ) );
4906 
4907 /* Allocate memory to hold a list of the Frame pointers (if any) associated
4908    with each node. */
4909    frames = astMalloc( sizeof( AstFrame * )  * (size_t) ( this->nnode ) );
4910 
4911 /* If OK, set up an array of Frame pointers indexed by node index. If a
4912    node has no associated Frame store a NULL pointer. This is needed so
4913    that we can find Frame pointers quickly within the Span function. Note,
4914    we simply copy the pointers rather than cloning them, so they do not
4915    need to be annulled when finished with. */
4916    if ( astOK ) {
4917       for( inode = 0; inode < this->nnode; inode++ ) frames[ inode ] = NULL;
4918       for( iframe = 0; iframe < this->nframe; iframe++ ) {
4919          frames[ this->node[ iframe ] ] = this->frame[ iframe ];
4920       }
4921 
4922 /* Obtain the Mapping pointers and direction flags needed to convert
4923    coordinates between the nodes associated with the two specified
4924    Frames. */
4925       npath = Span( this, frames, this->node[ iframe1 - 1 ],
4926                     this->node[ iframe2 - 1 ], -1, path, forward, status ) - 1;
4927 
4928 /* If this failed, it indicates a corrupt FrameSet object, so report
4929    an error. */
4930       if ( npath < 0 ) {
4931          astError( AST__FRSIN, "astGetMapping(%s): Invalid or corrupt "
4932                    "%s - could not find conversion path between Frames "
4933                    "%d and %d.", status, astGetClass( this ), astGetClass( this ),
4934                    iframe1, iframe2 );
4935 
4936 /* If the conversion path is of zero length (i.e. the two Frames are
4937    the same) then we will return a Mapping which is equivalent to the
4938    Frame. Most classes of Frame are equivalent to a UnitMap. However, we do
4939    not hard-wire this equivalence since some classes of Frame (e.g. Regions
4940    or CmpFrames containing Regions) do not correspond to a UnitMap. Instead
4941    we use the astIsUnitFrame method on the Frame to determine if the
4942    Frame is equivalent to a UnitMap.Is os, create a suitable UnitMap. If
4943    not, return the Frame itself (a form of Mapping). */
4944       } else if ( npath == 0 ) {
4945          fr = astGetFrame( this, iframe1 );
4946          if( astIsUnitFrame( fr ) ){
4947             result = (AstMapping *) astUnitMap( astGetNaxes( fr ), "", status );
4948          } else {
4949             result = (AstMapping *) astClone( fr );
4950          }
4951          fr = astAnnul( fr );
4952 
4953 /* If the conversion path involves at least one non-trivial Mapping,
4954    make a copy of the first Mapping, inverting the copy if
4955    necessary. */
4956       } else {
4957          result = astCopy( path[ 0 ] );
4958          if ( !forward[ 0 ] ) astInvert( result );
4959 
4960 /* Now loop to concatenate any further Mappings. First make a copy of
4961    each additional Mapping and invert the copy if necessary. */
4962          for ( ipath = 1; ipath < npath; ipath++ ) {
4963             copy = astCopy( path[ ipath ] );
4964             if ( !forward[ ipath ] ) astInvert( copy );
4965 
4966 /* Concatenate the copy with the result so far, then annul the pointer
4967    to the copy and save the pointer to the new result. */
4968             tmp = (AstMapping *) astCmpMap( result, copy, 1, "", status );
4969             result = astAnnul( result );
4970             copy = astAnnul( copy );
4971             result = tmp;
4972          }
4973       }
4974    }
4975 
4976 /* Free the memory allocated for the conversion path information. */
4977    path = astFree( path );
4978    forward = astFree( forward );
4979    frames = astFree( frames );
4980 
4981 /* If an error occurred, annul the returned Mapping. */
4982    if ( !astOK ) result = astAnnul( result );
4983 
4984 /* Return the result. */
4985    return result;
4986 }
4987 
GetNaxes(AstFrame * this_frame,int * status)4988 static int GetNaxes( AstFrame *this_frame, int *status ) {
4989 /*
4990 *  Name:
4991 *     GetNaxes
4992 
4993 *  Purpose:
4994 *     Determine how many axes a FrameSet has.
4995 
4996 *  Type:
4997 *     Private function.
4998 
4999 *  Synopsis:
5000 *     #include "frameset.h"
5001 *     int GetNaxes( AstFrame *this, int *status )
5002 
5003 *  Class Membership:
5004 *     FrameSet member function (over-rides the astGetNaxes method
5005 *     inherited from the Frame class).
5006 
5007 *  Description:
5008 *     This function returns the number of axes for a FrameSet. This is equal
5009 *     to the number of axes in its current Frame.
5010 
5011 *  Parameters:
5012 *     this
5013 *        Pointer to the FrameSet.
5014 *     status
5015 *        Pointer to the inherited status variable.
5016 
5017 *  Returned Value:
5018 *     The number of FrameSet axes (zero or more).
5019 
5020 *  Notes:
5021 *     - A value of zero will be returned if this function is invoked
5022 *     with the global error status set, or if it should fail for any
5023 *     reason.
5024 */
5025 
5026 /* Local Variables: */
5027    AstFrame *fr;                 /* Pointer to current Frame */
5028    AstFrameSet *this;            /* Pointer to the FrameSet structure */
5029    int result;                   /* Result to be returned */
5030 
5031 /* Check the global error status. */
5032    if ( !astOK ) return 0;
5033 
5034 /* Obtain a pointer to the FrameSet structure. */
5035    this = (AstFrameSet *) this_frame;
5036 
5037 /* Obtain a pointer to the FrameSet's current Frame. */
5038    fr = astGetFrame( this, AST__CURRENT );
5039 
5040 /* Obtain the number of axes in this Frame. */
5041    result = astGetNaxes( fr );
5042 
5043 /* Annul the current Frame pointer. */
5044    fr = astAnnul( fr );
5045 
5046 /* If an error occurred, clear the result value. */
5047    if ( !astOK ) result = 0;
5048 
5049 /* Return the result. */
5050    return result;
5051 }
5052 
GetNframe(AstFrameSet * this,int * status)5053 static int GetNframe( AstFrameSet *this, int *status ) {
5054 /*
5055 *+
5056 *  Name:
5057 *     astGetNframe
5058 
5059 *  Purpose:
5060 *     Determine the number of Frames in a FrameSet.
5061 
5062 *  Type:
5063 *     Protected virtual function.
5064 
5065 *  Synopsis:
5066 *     #include "frameset.h"
5067 *     int astGetNframe( AstFrameSet *this )
5068 
5069 *  Class Membership:
5070 *     FrameSet method.
5071 
5072 *  Description:
5073 *     This function returns the number of Frames in a FrameSet.
5074 
5075 *  Parameters:
5076 *     this
5077 *        Pointer to the FrameSet.
5078 
5079 *  Returned Value:
5080 *     The number of Frames in the FrameSet (always 1 or more).
5081 
5082 *  Notes:
5083 *     - A value of zero will be returned if this function is invoked
5084 *     with the global status set, or if it should fail for any reason.
5085 *-
5086 */
5087 
5088 /* Check the global error status. */
5089    if ( !astOK ) return 0;
5090 
5091 /* Return the Frame count. */
5092    return this->nframe;
5093 }
5094 
GetNin(AstMapping * this_mapping,int * status)5095 static int GetNin( AstMapping *this_mapping, int *status ) {
5096 /*
5097 *  Name:
5098 *     GetNin
5099 
5100 *  Purpose:
5101 *     Get the number of input coordinates for a FrameSet.
5102 
5103 *  Type:
5104 *     Private function.
5105 
5106 *  Synopsis:
5107 *     #include "frameset.h"
5108 *     int GetNin( AstMapping *this, int *status )
5109 
5110 *  Class Membership:
5111 *     FrameSet member function (over-rides the astGetNin method
5112 *     inherited from the Frame class).
5113 
5114 *  Description:
5115 *     This function returns the number of input coordinate values
5116 *     required per point by a FrameSet when used to transform a set of
5117 *     points (i.e. the number of dimensions of the space in which the
5118 *     input points reside).
5119 *
5120 *     The value returned is equal to the number of axes in the
5121 *     FrameSet's base Frame.
5122 
5123 *  Parameters:
5124 *     this
5125 *        Pointer to the FrameSet.
5126 *     status
5127 *        Pointer to the inherited status variable.
5128 
5129 *  Returned Value:
5130 *     Number of coordinate values required.
5131 
5132 *  Notes:
5133 *     - A value of zero will be returned if this function is invoked
5134 *     with the global error status set, or if it should fail for any
5135 *     reason.
5136 */
5137 
5138 /* Local Variables: */
5139    AstFrame *fr;                 /* Pointer to base Frame */
5140    AstFrameSet *this;            /* Pointer to the FrameSet structure */
5141    int result;                   /* Result to be returned */
5142 
5143 /* Check the global error status. */
5144    if ( !astOK ) return 0;
5145 
5146 /* Obtain a pointer to the FrameSet structure. */
5147    this = (AstFrameSet *) this_mapping;
5148 
5149 /* Obtain a pointer to the FrameSet's base Frame. */
5150    fr = astGetFrame( this, AST__BASE );
5151 
5152 /* Obtain the number of axes in this Frame. */
5153    result = astGetNaxes( fr );
5154 
5155 /* Annul the base Frame pointer. */
5156    fr = astAnnul( fr );
5157 
5158 /* If an error occurred, clear the result value. */
5159    if ( !astOK ) result = 0;
5160 
5161 /* Return the result. */
5162    return result;
5163 }
5164 
GetNout(AstMapping * this_mapping,int * status)5165 static int GetNout( AstMapping *this_mapping, int *status ) {
5166 /*
5167 *  Name:
5168 *     GetNout
5169 
5170 *  Purpose:
5171 *     Get the number of output coordinates for a FrameSet.
5172 
5173 *  Type:
5174 *     Private function.
5175 
5176 *  Synopsis:
5177 *     #include "frameset.h"
5178 *     int GetNout( AstMapping *this, int *status )
5179 
5180 *  Class Membership:
5181 *     FrameSet member function (over-rides the astGetNout method
5182 *     inherited from the Frame class).
5183 
5184 *  Description:
5185 *     This function returns the number of output coordinate values
5186 *     generated per point by a FrameSet when used to transform a set
5187 *     of points (i.e. the number of dimensions of the space in which
5188 *     the output points reside).
5189 *
5190 *     The value returned is equal to the number of axes in the
5191 *     FrameSet's current Frame.
5192 
5193 *  Parameters:
5194 *     this
5195 *        Pointer to the FrameSet.
5196 *     status
5197 *        Pointer to the inherited status variable.
5198 
5199 *  Returned Value:
5200 *     Number of coordinate values generated.
5201 
5202 *  Notes:
5203 *     - A value of zero will be returned if this function is invoked
5204 *     with the global error status set, or if it should fail for any
5205 *     reason.
5206 */
5207 
5208 /* Check the global error status. */
5209    if ( !astOK ) return 0;
5210 
5211 /* Return the number of axes in the FrameSet's current Frame. */
5212    return GetNaxes( (AstFrame *) this_mapping, status );
5213 }
5214 
GetPerm(AstFrame * this_frame,int * status)5215 static const int *GetPerm( AstFrame *this_frame, int *status ) {
5216 /*
5217 *  Name:
5218 *     GetPerm
5219 
5220 *  Purpose:
5221 *     Access the axis permutation array for the current Frame of a FrameSet.
5222 
5223 *  Type:
5224 *     Private function.
5225 
5226 *  Synopsis:
5227 *     #include "frameset.h"
5228 *     const int *GetPerm( AstFrame *this, int *status )
5229 
5230 *  Class Membership:
5231 *     FrameSet member function (over-rides the astGetPerm protected
5232 *     method inherited from the Frame class).
5233 
5234 *  Description:
5235 *     This function returns a pointer to the axis permutation array
5236 *     for the current Frame of a FrameSet. This array constitutes a
5237 *     lookup-table that converts between an axis number supplied
5238 *     externally and the corresponding index in the Frame's internal
5239 *     axis arrays.
5240 
5241 *  Parameters:
5242 *     this
5243 *        Pointer to the FrameSet.
5244 *     status
5245 *        Pointer to the inherited status variable.
5246 
5247 *  Returned Value:
5248 *     Pointer to the current Frame's axis permutation array (a
5249 *     constant array of int).  Each element of this contains the
5250 *     (zero-based) internal axis index to be used in place of the
5251 *     external index which is used to address the permutation
5252 *     array. If the current Frame has zero axes, this pointer will be
5253 *     NULL.
5254 
5255 *  Notes:
5256 *     - The pointer returned by this function gives direct access to
5257 *     data internal to the Frame object. It remains valid only so long
5258 *     as the Frame exists. The permutation array contents may be
5259 *     modified by other functions which operate on the Frame and this
5260 *     may render the returned pointer invalid.
5261 *     - A NULL pointer will be returned if this function is invoked
5262 *     with the global error status set, or if it should fail for any
5263 *     reason.
5264 */
5265 
5266 /* Local Variables: */
5267    AstFrame *fr;                 /* Pointer to current Frame */
5268    AstFrameSet *this;            /* Pointer to FrameSet structure */
5269    const int *result;            /* Result pointer value */
5270 
5271 /* Check the global error status. */
5272    if ( !astOK ) return NULL;
5273 
5274 /* Obtain a pointer to the FrameSet structure. */
5275    this = (AstFrameSet *) this_frame;
5276 
5277 /* Obtain a pointer to the FrameSet's current Frame and then obtain a
5278    pointer to its axis permutation array. Annul the Frame pointer
5279    afterwards. */
5280    fr = astGetFrame( this, AST__CURRENT );
5281    result = astGetPerm( fr );
5282    fr = astAnnul( fr );
5283 
5284 /* If an error occurred, clear the result value. */
5285    if ( !astOK ) result = NULL;
5286 
5287 /* Return the result. */
5288    return result;
5289 }
5290 
GetTranForward(AstMapping * this_mapping,int * status)5291 static int GetTranForward( AstMapping *this_mapping, int *status ) {
5292 /*
5293 *  Name:
5294 *     GetTranForward
5295 
5296 *  Purpose:
5297 *     Determine if a FrameSet defines a forward coordinate transformation.
5298 
5299 *  Type:
5300 *     Private function.
5301 
5302 *  Synopsis:
5303 *     #include "frameset.h"
5304 *     int GetTranForward( AstMapping *this )
5305 
5306 *  Class Membership:
5307 *     Frameset member function (over-rides the astGetTranForward
5308 *     protected method inherited from the Frame class).
5309 
5310 *  Description:
5311 *     This function returns a value indicating whether a FrameSet is
5312 *     able to perform a coordinate transformation in the "forward"
5313 *     direction.
5314 
5315 *  Parameters:
5316 *     this
5317 *        Pointer to the FrameSet.
5318 
5319 *  Returned Value:
5320 *     Zero if the forward coordinate transformation is not defined, or
5321 *     1 if it is.
5322 
5323 *  Notes:
5324 *     - A value of zero will be returned if this function is invoked
5325 *     with the global error status set, or if it should fail for any
5326 *     reason.
5327 */
5328 
5329 /* Local Variables: */
5330    AstFrameSet *this;            /* Pointer to the FrameSet structure */
5331    AstMapping *map;              /* Pointer to base->current Mapping */
5332    int result;                   /* Result to be returned */
5333 
5334 /* Check the global error status. */
5335    if ( !astOK ) return 0;
5336 
5337 /* Obtain a pointer to the FrameSet structure. */
5338    this = (AstFrameSet *) this_mapping;
5339 
5340 /* Obtain the Mapping between the base and current Frames in the
5341    FrameSet (note this takes account of whether the FrameSet has been
5342    inverted). */
5343    map = astGetMapping( this, AST__BASE, AST__CURRENT );
5344 
5345 /* Determine whether the required transformation is defined. */
5346    result = astGetTranForward( map );
5347 
5348 /* Annul the Mapping pointer. */
5349    map = astAnnul( map );
5350 
5351 /* If an error occurred, clear the returned result. */
5352    if ( !astOK ) result = 0;
5353 
5354 /* Return the result. */
5355    return result;
5356 }
5357 
GetTranInverse(AstMapping * this_mapping,int * status)5358 static int GetTranInverse( AstMapping *this_mapping, int *status ) {
5359 /*
5360 *  Name:
5361 *     GetTranInverse
5362 
5363 *  Purpose:
5364 *     Determine if a FrameSet defines an inverse coordinate transformation.
5365 
5366 *  Type:
5367 *     Private function.
5368 
5369 *  Synopsis:
5370 *     #include "frameset.h"
5371 *     int GetTranInverse( AstMapping *this )
5372 
5373 *  Class Membership:
5374 *     Frameset member function (over-rides the astGetTranInverse
5375 *     protected method inherited from the Frame class).
5376 
5377 *  Description:
5378 *     This function returns a value indicating whether a FrameSet is
5379 *     able to perform a coordinate transformation in the "inverse"
5380 *     direction.
5381 
5382 *  Parameters:
5383 *     this
5384 *        Pointer to the FrameSet.
5385 
5386 *  Returned Value:
5387 *     Zero if the inverse coordinate transformation is not defined, or
5388 *     1 if it is.
5389 
5390 *  Notes:
5391 *     - A value of zero will be returned if this function is invoked
5392 *     with the global error status set, or if it should fail for any
5393 *     reason.
5394 */
5395 
5396 /* Local Variables: */
5397    AstFrameSet *this;            /* Pointer to the FrameSet structure */
5398    AstMapping *map;              /* Pointer to base->current Mapping */
5399    int result;                   /* Result to be returned */
5400 
5401 /* Check the global error status. */
5402    if ( !astOK ) return 0;
5403 
5404 /* Obtain a pointer to the FrameSet structure. */
5405    this = (AstFrameSet *) this_mapping;
5406 
5407 /* Obtain the Mapping between the base and current Frames in the
5408    FrameSet (note this takes account of whether the FrameSet has been
5409    inverted). */
5410    map = astGetMapping( this, AST__BASE, AST__CURRENT );
5411 
5412 /* Determine whether the required transformation is defined. */
5413    result = astGetTranInverse( map );
5414 
5415 /* Annul the Mapping pointer. */
5416    map = astAnnul( map );
5417 
5418 /* If an error occurred, clear the returned result. */
5419    if ( !astOK ) result = 0;
5420 
5421 /* Return the result. */
5422    return result;
5423 }
5424 
GetUseDefs(AstObject * this_object,int * status)5425 static int GetUseDefs( AstObject *this_object, int *status ) {
5426 /*
5427 *  Name:
5428 *     GetUseDefs
5429 
5430 *  Purpose:
5431 *     Get the value of the UseDefs attribute for a FrameSet.
5432 
5433 *  Type:
5434 *     Private function.
5435 
5436 *  Synopsis:
5437 *     #include "frameset.h"
5438 *     int GetUseDefs( AstObject *this_object, int *status ) {
5439 
5440 *  Class Membership:
5441 *     FrameSet member function (over-rides the protected astGetUseDefs
5442 *     method inherited from the Frame class).
5443 
5444 *  Description:
5445 *     This function returns the value of the UseDefs attribute for a FrameSet,
5446 *     supplying a suitable default.
5447 
5448 *  Parameters:
5449 *     this
5450 *        Pointer to the FrameSet.
5451 *     status
5452 *        Pointer to the inherited status variable.
5453 
5454 *  Returned Value:
5455 *     - The USeDefs value.
5456 */
5457 
5458 /* Local Variables: */
5459    AstFrame *fr;                 /* Pointer to current Frame */
5460    AstFrameSet *this;            /* Pointer to the FrameSet structure */
5461    int result;                   /* Value to return */
5462 
5463 /* Initialise. */
5464    result = 0;
5465 
5466 /* Check the global error status. */
5467    if ( !astOK ) return result;
5468 
5469 /* Obtain a pointer to the FrameSet structure. */
5470    this = (AstFrameSet *) this_object;
5471 
5472 /* If the UseDefs value for the FrameSet has been set explicitly, use the
5473    Get method inherited from the parent Frame class to get its value> */
5474    if( astTestUseDefs( this ) ) {
5475       result = (*parent_getusedefs)( this_object, status );
5476 
5477 /* Otherwise, supply a default value equal to the UseDefs value of the
5478    current Frame. */
5479    } else {
5480       fr = astGetFrame( this, AST__CURRENT );
5481       result = astGetUseDefs( fr );
5482       fr = astAnnul( fr );
5483    }
5484 
5485 /* Return the result. */
5486    return result;
5487 }
5488 
GetVarFrm(AstFrameSet * this,int iframe,int * status)5489 static int GetVarFrm( AstFrameSet *this, int iframe, int *status ) {
5490 /*
5491 *  Name:
5492 *     GetVarFrm
5493 
5494 *  Purpose:
5495 *     Get the index of the variants Frame for a nominated Frame.
5496 
5497 *  Type:
5498 *     Private function.
5499 
5500 *  Synopsis:
5501 *     #include "frameset.h"
5502 *     int GetVarFrm( AstFrameSet *this, int iframe, int *status ) {
5503 
5504 *  Class Membership:
5505 *     Private function.
5506 
5507 *  Description:
5508 *     This function returns the index of the variants Frame associated
5509 *     with a nominated mirror Frame. See astMirrorVariants.
5510 
5511 *  Parameters:
5512 *     this
5513 *        Pointer to the FrameSet.
5514 *     iframe
5515 *        The one-based index of the nominated Frame that may potentially be
5516 *        a mirror for the variant Mappings in another Frame.
5517 *     status
5518 *        Pointer to the inherited status variable.
5519 
5520 *  Returned Value:
5521 *     The one-based Frame index of the Frame that defines the variant
5522 *     Mappings associated with Frame "iframe". This will be the same as
5523 *     "iframe" unless the nominated Frame is a mirror for another Frame.
5524 */
5525 
5526 /* Local Variables: */
5527    int result;                   /* Value to return */
5528 
5529 /* Initialise. */
5530    result = AST__NOFRAME;
5531 
5532 /* Check the global error status. */
5533    if ( !astOK ) return result;
5534 
5535 /* Initialise the returned value. */
5536    result = iframe;
5537 
5538 /* If the nominated Frame is mirroring another Frame, return the index of
5539    the mirrored Frame. Walk up the chain until we reach a Frame which is
5540    not a mirror for another Frame. */
5541    while( this->varfrm[ result - 1 ] > 0 ) {
5542       if( this->varfrm[ result - 1 ] == result ) {
5543          astError( AST__INTER, "GetVarFrm(FrameSet): FrameSet is corrupt "
5544                    "(internal programming error).", status );
5545          break;
5546       } else {
5547          result = this->varfrm[ result - 1 ];
5548       }
5549    }
5550 
5551 /* Return the result. */
5552    return result;
5553 }
5554 
GetVariant(AstFrameSet * this,int * status)5555 static const char *GetVariant( AstFrameSet *this, int *status ) {
5556 /*
5557 *+
5558 *  Name:
5559 *     astGetVariant
5560 
5561 *  Purpose:
5562 *     Obtain the value of the Variant attribute for a FrameSet.
5563 
5564 *  Type:
5565 *     Protected virtual function.
5566 
5567 *  Synopsis:
5568 *     #include "frameset.h"
5569 *     const char *astGetVariant( AstFrameSet *this )
5570 
5571 *  Class Membership:
5572 *     FrameSet method.
5573 
5574 *  Description:
5575 *     This function returns the value of the Variant attribute for a
5576 *     FrameSet.
5577 
5578 *  Parameters:
5579 *     this
5580 *        Pointer to the FrameSet.
5581 
5582 *  Returned Value:
5583 *     The Variant attribute value.
5584 
5585 *  Notes:
5586 *     - A NULL value will be returned if this function is invoked
5587 *     with the global status set, or if it should fail for any reason.
5588 *-
5589 */
5590 
5591 /* Local Variables: */
5592    AstFrame *frm;
5593    AstFrame *vfs;
5594    const char *result;
5595    int icur;
5596    int iuse;
5597 
5598 /* Initialise */
5599    result = NULL;
5600 
5601 /* Check the global error status. */
5602    if ( !astOK ) return result;
5603 
5604 /* Get the one-based index of the current Frame. */
5605    icur = astGetCurrent( this );
5606 
5607 /* The current Frame may mirror the variant Mappings in another Frame,
5608    rather than defining any variant Mappings itself. Get the one-based
5609    index of the Frame that defines the variant Mappings to use. */
5610    iuse = GetVarFrm( this, icur, status );
5611 
5612 /* Get a pointer to the Variants FrameSet in the used Frame. */
5613    frm = astGetFrame( this, iuse );
5614    vfs = astGetFrameVariants( frm );
5615 
5616 /* If the current Frame has no Variants FrameSet, return the Domain name
5617    of the current Frame. */
5618    if( !vfs ) {
5619       result = astGetDomain( this );
5620 
5621 /* Otherwise, return the Domain name of the current Frame in the Variants
5622    FrameSet. Then annul the Variants FrameSet pointer. */
5623    } else {
5624       result = astGetDomain( vfs );
5625       vfs = astAnnul( vfs );
5626    }
5627 
5628 /* Annul the current Frame pointer. */
5629    frm = astAnnul( frm );
5630 
5631 /* If an error occurred, clear the result. */
5632    if ( !astOK ) result = NULL;
5633 
5634 /* Return the result. */
5635    return result;
5636 }
5637 
astInitFrameSetVtab_(AstFrameSetVtab * vtab,const char * name,int * status)5638 void astInitFrameSetVtab_(  AstFrameSetVtab *vtab, const char *name, int *status ) {
5639 /*
5640 *+
5641 *  Name:
5642 *     astInitFrameSetVtab
5643 
5644 *  Purpose:
5645 *     Initialise a virtual function table for a FrameSet.
5646 
5647 *  Type:
5648 *     Protected function.
5649 
5650 *  Synopsis:
5651 *     #include "frameset.h"
5652 *     void astInitFrameSetVtab( AstFrameSetVtab *vtab, const char *name )
5653 
5654 *  Class Membership:
5655 *     FrameSet vtab initialiser.
5656 
5657 *  Description:
5658 *     This function initialises the component of a virtual function
5659 *     table which is used by the FrameSet class.
5660 
5661 *  Parameters:
5662 *     vtab
5663 *        Pointer to the virtual function table. The components used by
5664 *        all ancestral classes will be initialised if they have not already
5665 *        been initialised.
5666 *     name
5667 *        Pointer to a constant null-terminated character string which contains
5668 *        the name of the class to which the virtual function table belongs (it
5669 *        is this pointer value that will subsequently be returned by the Object
5670 *        astClass function).
5671 *-
5672 */
5673 
5674 /* Local Variables: */
5675    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
5676    AstFrameVtab *frame;          /* Pointer to Frame component of Vtab */
5677    AstMappingVtab *mapping;      /* Pointer to Mapping component of Vtab */
5678    AstObjectVtab *object;        /* Pointer to Object component of Vtab */
5679 
5680 /* Check the local error status. */
5681    if ( !astOK ) return;
5682 
5683 /* Get a pointer to the thread specific global data structure. */
5684    astGET_GLOBALS(NULL);
5685 
5686 /* Initialize the component of the virtual function table used by the
5687    parent class. */
5688    astInitFrameVtab( (AstFrameVtab *) vtab, name );
5689 
5690 /* Store a unique "magic" value in the virtual function table. This
5691    will be used (by astIsAFrameSet) to determine if an object belongs
5692    to this class.  We can conveniently use the address of the (static)
5693    class_check variable to generate this unique value. */
5694    vtab->id.check = &class_check;
5695    vtab->id.parent = &(((AstFrameVtab *) vtab)->id);
5696 
5697 /* Initialise member function pointers. */
5698 /* ------------------------------------ */
5699 /* Store pointers to the member functions (implemented here) that
5700    provide virtual methods for this class. */
5701    vtab->AddFrame = AddFrame;
5702    vtab->AddVariant = AddVariant;
5703    vtab->ClearBase = ClearBase;
5704    vtab->ClearCurrent = ClearCurrent;
5705    vtab->GetBase = GetBase;
5706    vtab->GetCurrent = GetCurrent;
5707    vtab->GetFrame = GetFrame;
5708    vtab->GetMapping = GetMapping;
5709    vtab->GetNframe = GetNframe;
5710    vtab->GetAllVariants = GetAllVariants;
5711    vtab->MirrorVariants = MirrorVariants;
5712    vtab->RemapFrame = RemapFrame;
5713    vtab->RemoveFrame = RemoveFrame;
5714    vtab->SetBase = SetBase;
5715    vtab->SetCurrent = SetCurrent;
5716    vtab->TestBase = TestBase;
5717    vtab->TestCurrent = TestCurrent;
5718    vtab->ValidateFrameIndex = ValidateFrameIndex;
5719 
5720    vtab->ClearVariant = ClearVariant;
5721    vtab->GetVariant = GetVariant;
5722    vtab->SetVariant = SetVariant;
5723    vtab->TestVariant = TestVariant;
5724 
5725 /* Save the inherited pointers to methods that will be extended, and
5726    replace them with pointers to the new member functions. */
5727    object = (AstObjectVtab *) vtab;
5728 
5729    parent_clear = object->Clear;
5730    parent_getobjsize = object->GetObjSize;
5731    object->GetObjSize = GetObjSize;
5732    object->Clear = Clear;
5733 
5734    parent_vset = object->VSet;
5735    object->VSet = VSet;
5736 
5737    parent_getusedefs = object->GetUseDefs;
5738    object->GetUseDefs = GetUseDefs;
5739 
5740 #if defined(THREAD_SAFE)
5741    parent_managelock = object->ManageLock;
5742    object->ManageLock = ManageLock;
5743 #endif
5744 
5745 /* Store replacement pointers for methods which will be over-ridden by
5746    new member functions implemented here. */
5747    mapping = (AstMappingVtab *) vtab;
5748    frame = (AstFrameVtab *) vtab;
5749 
5750    object->ClearAttrib = ClearAttrib;
5751    object->GetAttrib = GetAttrib;
5752    object->SetAttrib = SetAttrib;
5753    object->TestAttrib = TestAttrib;
5754 
5755    object->GetUseDefs = GetUseDefs;
5756    object->Equal = Equal;
5757    object->Cast = Cast;
5758 
5759    mapping->GetIsLinear = GetIsLinear;
5760    mapping->GetNin = GetNin;
5761    mapping->GetNout = GetNout;
5762    mapping->GetTranForward = GetTranForward;
5763    mapping->GetTranInverse = GetTranInverse;
5764    mapping->Rate = Rate;
5765    mapping->ReportPoints = ReportPoints;
5766    mapping->RemoveRegions = RemoveRegions;
5767    mapping->Simplify = Simplify;
5768    mapping->Transform = Transform;
5769    mapping->MapSplit = MapSplit;
5770 
5771    frame->Abbrev = Abbrev;
5772    frame->Angle = Angle;
5773    frame->AxAngle = AxAngle;
5774    frame->AxDistance = AxDistance;
5775    frame->AxOffset = AxOffset;
5776    frame->CheckPerm = CheckPerm;
5777    frame->ClearDigits = ClearDigits;
5778    frame->ClearDirection = ClearDirection;
5779    frame->ClearDomain = ClearDomain;
5780    frame->ClearFormat = ClearFormat;
5781    frame->ClearLabel = ClearLabel;
5782    frame->ClearMatchEnd = ClearMatchEnd;
5783    frame->ClearMaxAxes = ClearMaxAxes;
5784    frame->ClearMinAxes = ClearMinAxes;
5785    frame->ClearPermute = ClearPermute;
5786    frame->ClearPreserveAxes = ClearPreserveAxes;
5787    frame->ClearSymbol = ClearSymbol;
5788    frame->ClearTitle = ClearTitle;
5789    frame->ClearUnit = ClearUnit;
5790    frame->Convert = Convert;
5791    frame->ConvertX = ConvertX;
5792    frame->Distance = Distance;
5793    frame->Fields = Fields;
5794    frame->FindFrame = FindFrame;
5795    frame->Format = Format;
5796    frame->FrameGrid = FrameGrid;
5797    frame->Gap = Gap;
5798    frame->GetAxis = GetAxis;
5799    frame->GetDigits = GetDigits;
5800    frame->GetDirection = GetDirection;
5801    frame->GetDomain = GetDomain;
5802    frame->GetFormat = GetFormat;
5803    frame->GetLabel = GetLabel;
5804    frame->GetMatchEnd = GetMatchEnd;
5805    frame->GetMaxAxes = GetMaxAxes;
5806    frame->GetMinAxes = GetMinAxes;
5807    frame->GetNaxes = GetNaxes;
5808    frame->GetPerm = GetPerm;
5809    frame->GetPermute = GetPermute;
5810    frame->GetPreserveAxes = GetPreserveAxes;
5811    frame->GetSymbol = GetSymbol;
5812    frame->GetTitle = GetTitle;
5813    frame->GetUnit = GetUnit;
5814    frame->Intersect = Intersect;
5815    frame->IsUnitFrame = IsUnitFrame;
5816    frame->LineContains = LineContains;
5817    frame->LineCrossing = LineCrossing;
5818    frame->LineDef = LineDef;
5819    frame->LineOffset = LineOffset;
5820    frame->Match = Match;
5821    frame->MatchAxes = MatchAxes;
5822    frame->MatchAxesX = MatchAxesX;
5823    frame->Norm = Norm;
5824    frame->NormBox = NormBox;
5825    frame->Offset = Offset;
5826    frame->Offset2 = Offset2;
5827    frame->Overlay = Overlay;
5828    frame->PermAxes = PermAxes;
5829    frame->PickAxes = PickAxes;
5830    frame->PrimaryFrame = PrimaryFrame;
5831    frame->Resolve = Resolve;
5832    frame->ResolvePoints = ResolvePoints;
5833    frame->SetAxis = SetAxis;
5834    frame->SetDigits = SetDigits;
5835    frame->SetDirection = SetDirection;
5836    frame->SetDomain = SetDomain;
5837    frame->SetFormat = SetFormat;
5838    frame->SetLabel = SetLabel;
5839    frame->SetMatchEnd = SetMatchEnd;
5840    frame->SetMaxAxes = SetMaxAxes;
5841    frame->SetMinAxes = SetMinAxes;
5842    frame->SetPermute = SetPermute;
5843    frame->SetPreserveAxes = SetPreserveAxes;
5844    frame->SetSymbol = SetSymbol;
5845    frame->SetTitle = SetTitle;
5846    frame->SetUnit = SetUnit;
5847    frame->SubFrame = SubFrame;
5848    frame->SystemCode = SystemCode;
5849    frame->SystemString = SystemString;
5850    frame->TestDigits = TestDigits;
5851    frame->TestDirection = TestDirection;
5852    frame->TestDomain = TestDomain;
5853    frame->TestFormat = TestFormat;
5854    frame->TestLabel = TestLabel;
5855    frame->TestMatchEnd = TestMatchEnd;
5856    frame->TestMaxAxes = TestMaxAxes;
5857    frame->TestMinAxes = TestMinAxes;
5858    frame->TestPermute = TestPermute;
5859    frame->TestPreserveAxes = TestPreserveAxes;
5860    frame->TestSymbol = TestSymbol;
5861    frame->TestTitle = TestTitle;
5862    frame->TestUnit = TestUnit;
5863    frame->Unformat = Unformat;
5864    frame->ValidateAxis = ValidateAxis;
5865    frame->ValidateAxisSelection = ValidateAxisSelection;
5866    frame->ValidateSystem = ValidateSystem;
5867 
5868    frame->GetActiveUnit = GetActiveUnit;
5869    frame->SetActiveUnit = SetActiveUnit;
5870    frame->TestActiveUnit = TestActiveUnit;
5871 
5872    frame->GetTop = GetTop;
5873    frame->SetTop = SetTop;
5874    frame->TestTop = TestTop;
5875    frame->ClearTop = ClearTop;
5876 
5877    frame->GetBottom = GetBottom;
5878    frame->SetBottom = SetBottom;
5879    frame->TestBottom = TestBottom;
5880    frame->ClearBottom = ClearBottom;
5881 
5882    frame->GetEpoch = GetEpoch;
5883    frame->SetEpoch = SetEpoch;
5884    frame->TestEpoch = TestEpoch;
5885    frame->ClearEpoch = ClearEpoch;
5886 
5887    frame->GetSystem = GetSystem;
5888    frame->SetSystem = SetSystem;
5889    frame->TestSystem = TestSystem;
5890    frame->ClearSystem = ClearSystem;
5891 
5892    frame->GetAlignSystem = GetAlignSystem;
5893    frame->SetAlignSystem = SetAlignSystem;
5894    frame->TestAlignSystem = TestAlignSystem;
5895    frame->ClearAlignSystem = ClearAlignSystem;
5896 
5897    frame->ClearObsLat = ClearObsLat;
5898    frame->TestObsLat = TestObsLat;
5899    frame->GetObsLat = GetObsLat;
5900    frame->SetObsLat = SetObsLat;
5901 
5902    frame->ClearObsAlt = ClearObsAlt;
5903    frame->TestObsAlt = TestObsAlt;
5904    frame->GetObsAlt = GetObsAlt;
5905    frame->SetObsAlt = SetObsAlt;
5906 
5907    frame->ClearObsLon = ClearObsLon;
5908    frame->TestObsLon = TestObsLon;
5909    frame->GetObsLon = GetObsLon;
5910    frame->SetObsLon = SetObsLon;
5911 
5912 /* Declare the copy constructor, destructor and class dump
5913    functions. */
5914    astSetDelete( vtab, Delete );
5915    astSetCopy( vtab, Copy );
5916    astSetDump( vtab, Dump, "FrameSet",
5917                "Set of inter-related coordinate systems" );
5918 
5919 /* If we have just initialised the vtab for the current class, indicate
5920    that the vtab is now initialised, and store a pointer to the class
5921    identifier in the base "object" level of the vtab. */
5922    if( vtab == &class_vtab ) {
5923       class_init = 1;
5924       astSetVtabClassIdentifier( vtab, &(vtab->id) );
5925    }
5926 }
5927 
Intersect(AstFrame * this_frame,const double a1[2],const double a2[2],const double b1[2],const double b2[2],double cross[2],int * status)5928 static void Intersect( AstFrame *this_frame, const double a1[2],
5929                        const double a2[2], const double b1[2],
5930                        const double b2[2], double cross[2],
5931                        int *status ) {
5932 /*
5933 *  Name:
5934 *     Intersect
5935 
5936 *  Purpose:
5937 *     Find the point of intersection between two geodesic curves.
5938 
5939 *  Type:
5940 *     Private function.
5941 
5942 *  Synopsis:
5943 *     #include "frameset.h"
5944 *     void Intersect( AstFrame *this_frame, const double a1[2],
5945 *                      const double a2[2], const double b1[2],
5946 *                      const double b2[2], double cross[2],
5947 *                      int *status )
5948 
5949 *  Class Membership:
5950 *     FrameSet member function (over-rides the astIntersect method
5951 *     inherited from the Frame class).
5952 
5953 *  Description:
5954 *     This function finds the coordinate values at the point of
5955 *     intersection between two geodesic curves. Each curve is specified
5956 *     by two points on the curve.
5957 
5958 *  Parameters:
5959 *     this
5960 *        Pointer to the SkyFrame.
5961 *     a1
5962 *        An array of double, with one element for each Frame axis.
5963 *        This should contain the coordinates of a point on the first
5964 *        geodesic curve.
5965 *     a2
5966 *        An array of double, with one element for each Frame axis.
5967 *        This should contain the coordinates of a second point on the
5968 *        first geodesic curve.
5969 *     b1
5970 *        An array of double, with one element for each Frame axis.
5971 *        This should contain the coordinates of a point on the second
5972 *        geodesic curve.
5973 *     b2
5974 *        An array of double, with one element for each Frame axis.
5975 *        This should contain the coordinates of a second point on
5976 *        the second geodesic curve.
5977 *     cross
5978 *        An array of double, with one element for each Frame axis
5979 *        in which the coordinates of the required intersection
5980 *        point will be returned. These will be AST__BAD if the curves do
5981 *        not intersect.
5982 *     status
5983 *        Pointer to the inherited status variable.
5984 
5985 *  Notes:
5986 *     - The geodesic curve used by this function is the path of
5987 *     shortest distance between two points, as defined by the
5988 *     astDistance function.
5989 *     - This function will return "bad" coordinate values (AST__BAD)
5990 *     if any of the input coordinates has this value.
5991 *     - For SkyFrames each curve will be a great circle, and in general
5992 *     each pair of curves will intersect at two diametrically opposite
5993 *     points on the sky. The returned position is the one which is
5994 *     closest to point "a1".
5995 */
5996 
5997 /* Local Variables: */
5998    AstFrame *fr;                 /* Pointer to current Frame */
5999    AstFrameSet *this;            /* Pointer to the FrameSet structure */
6000 
6001 /* Check the global error status. */
6002    if ( !astOK ) return;
6003 
6004 /* Obtain a pointer to the FrameSet structure. */
6005    this = (AstFrameSet *) this_frame;
6006 
6007 /* Obtain a pointer to the FrameSet's current Frame and invoke the
6008    astIntersect method for this Frame. Annul the Frame pointer
6009    afterwards. */
6010    fr = astGetFrame( this, AST__CURRENT );
6011    astIntersect( fr, a1, a2, b1, b2, cross );
6012    fr = astAnnul( fr );
6013 
6014 }
6015 
IsUnitFrame(AstFrame * this_frame,int * status)6016 static int IsUnitFrame( AstFrame *this_frame, int *status ){
6017 /*
6018 *  Name:
6019 *     IsUnitFrame
6020 
6021 *  Purpose:
6022 *     Is this Frame equivalent to a UnitMap?
6023 
6024 *  Type:
6025 *     Private function.
6026 
6027 *  Synopsis:
6028 *     #include "frameset.h"
6029 *     int IsUnitFrame( AstFrame *this, int *status )
6030 
6031 *  Class Membership:
6032 *     FrameSet member function (over-rides the protected astIsUnitFrame
6033 *     method inherited from the Frame class).
6034 
6035 *  Description:
6036 *     This function returns a flag indicating if the supplied Frame is
6037 *     equivalent to a UnitMap when treated as a Mapping (note, the Frame
6038 *     class inherits from Mapping and therefore every Frame is also a Mapping).
6039 
6040 *  Parameters:
6041 *     this
6042 *        Pointer to the Frame.
6043 *     status
6044 *        Pointer to the inherited status variable.
6045 
6046 *  Returned Value:
6047 *     A non-zero value is returned if the supplied Frame is equivalent to
6048 *     a UnitMap when treated as a Mapping.
6049 
6050 *-
6051 */
6052 
6053 /* Local Variables: */
6054    AstFrame *fr;                 /* Pointer to FrameSet's current Frame */
6055    AstFrameSet *this;            /* Pointer to the FrameSet structure */
6056    int result;                   /* Result to be returned */
6057 
6058 /* Initialise the returned value. */
6059    result = 0;
6060 
6061 /* Check the global error status. */
6062    if ( !astOK ) return result;
6063 
6064 /* Obtain a pointer to the FrameSet structure. */
6065    this = (AstFrameSet *) this_frame;
6066 
6067 /* Obtain a pointer to the FrameSet's current Frame. */
6068    fr = astGetFrame( this, AST__CURRENT );
6069 
6070 /* Invoke the astIsUnitFrame method for this Frame. */
6071    result = astIsUnitFrame( fr );
6072 
6073 /* Annul the Frame pointer. */
6074    fr = astAnnul( fr );
6075 
6076 /* If an error occurred, clean up by clearing the returned result. */
6077    if ( !astOK ) result = 0;
6078 
6079 /* Return the result. */
6080    return result;
6081 }
6082 
LineContains(AstFrame * this_frame,AstLineDef * l,int def,double * point,int * status)6083 static int LineContains( AstFrame *this_frame, AstLineDef *l, int def, double *point, int *status ) {
6084 /*
6085 *  Name:
6086 *     LineContains
6087 
6088 *  Purpose:
6089 *     Determine if a line contains a point.
6090 
6091 *  Type:
6092 *     Private function.
6093 
6094 *  Synopsis:
6095 *     #include "frameset.h"
6096 *     int LineContains( AstFrame *this, AstLineDef *l, int def, double *point, int *status )
6097 
6098 *  Class Membership:
6099 *     FrameSet member function (over-rides the protected astLineContains
6100 *     method inherited from the Frame class).
6101 
6102 *  Description:
6103 *     This function determines if the supplied point is on the supplied
6104 *     line within the supplied Frame.
6105 
6106 *  Parameters:
6107 *     this
6108 *        Pointer to the Frame.
6109 *     l
6110 *        Pointer to the structure defining the line.
6111 *     def
6112 *        Should be set non-zero if the "point" array was created by a
6113 *        call to astLineCrossing (in which case it may contain extra
6114 *        information following the axis values),and zero otherwise.
6115 *     point
6116 *        Point to an array containing the axis values of the point to be
6117 *        tested, possibly followed by extra cached information (see "def").
6118 *     status
6119 *        Pointer to the inherited status variable.
6120 
6121 *  Returned Value:
6122 *     A non-zero value is returned if the line contains the point.
6123 
6124 *  Notes:
6125 *     - The pointer supplied for "l" should have been created using the
6126 *     astLineDef method. These structures contained cached information about
6127 *     the lines which improve the efficiency of this method when many
6128 *     repeated calls are made. An error will be reported if the structure
6129 *     does not refer to the Frame specified by "this".
6130 *     - Zero will be returned if this function is invoked with the global
6131 *     error status set, or if it should fail for any reason.
6132 */
6133 
6134 /* Local Variables: */
6135    AstFrame *fr;                 /* Pointer to current Frame */
6136    int result;                   /* Returned value */
6137 
6138 /* Initialise */
6139    result =0;
6140 
6141 /* Obtain a pointer to the FrameSet's current Frame and then invoke the
6142    method. Annul the Frame pointer afterwards. */
6143    fr = astGetFrame( (AstFrameSet *) this_frame, AST__CURRENT );
6144    result = astLineContains( fr, l, def, point );
6145    fr = astAnnul( fr );
6146 
6147 /* Return the result. */
6148    return result;
6149 }
6150 
LineCrossing(AstFrame * this_frame,AstLineDef * l1,AstLineDef * l2,double ** cross,int * status)6151 static int LineCrossing( AstFrame *this_frame, AstLineDef *l1, AstLineDef *l2,
6152                          double **cross, int *status ) {
6153 /*
6154 *  Name:
6155 *     LineCrossing
6156 
6157 *  Purpose:
6158 *     Determine if two lines cross.
6159 
6160 *  Type:
6161 *     Private function.
6162 
6163 *  Synopsis:
6164 *     #include "frameset.h"
6165 *     int LineCrossing( AstFrame *this, AstLineDef *l1, AstLineDef *l2,
6166 *                       double **cross, int *status )
6167 
6168 *  Class Membership:
6169 *     FrameSet member function (over-rides the protected astLineCrossing
6170 *     method inherited from the Frame class).
6171 
6172 *  Description:
6173 *     This function determines if the two suplied line segments cross,
6174 *     and if so returns the axis values at the point where they cross.
6175 *     A flag is also returned indicating if the crossing point occurs
6176 *     within the length of both line segments, or outside one or both of
6177 *     the line segments.
6178 
6179 *  Parameters:
6180 *     this
6181 *        Pointer to the Frame.
6182 *     l1
6183 *        Pointer to the structure defining the first line.
6184 *     l2
6185 *        Pointer to the structure defining the second line.
6186 *     cross
6187 *        Pointer to a location at which to put a pointer to a dynamically
6188 *        alocated array containing the axis values at the crossing. If
6189 *        NULL is supplied no such array is returned. Otherwise, the returned
6190 *        array should be freed using astFree when no longer needed. If the
6191 *        lines are parallel (i.e. do not cross) then AST__BAD is returned for
6192 *        all axis values. Note usable axis values are returned even if the
6193 *        lines cross outside the segment defined by the start and end points
6194 *        of the lines. The order of axes in the returned array will take
6195 *        account of the current axis permutation array if appropriate. Note,
6196 *        sub-classes such as SkyFrame may append extra values to the end
6197 *        of the basic frame axis values. A NULL pointer is returned if an
6198 *        error occurs.
6199 *     status
6200 *        Pointer to the inherited status variable.
6201 
6202 *  Returned Value:
6203 *     A non-zero value is returned if the lines cross at a point which is
6204 *     within the [start,end) segment of both lines. If the crossing point
6205 *     is outside this segment on either line, or if the lines are parallel,
6206 *     zero is returned. Note, the start point is considered to be inside
6207 *     the length of the segment, but the end point is outside.
6208 
6209 *  Notes:
6210 *     - The pointers supplied for "l1" and "l2" should have been created
6211 *     using the astLineDef method. These structures contained cached
6212 *     information about the lines which improve the efficiency of this method
6213 *     when many repeated calls are made. An error will be reported if
6214 *     either structure does not refer to the Frame specified by "this".
6215 *     - Zero will be returned if this function is invoked with the global
6216 *     error status set, or if it should fail for any reason.
6217 */
6218 
6219 /* Local Variables: */
6220    AstFrame *fr;                 /* Pointer to current Frame */
6221    int result;                   /* Returned value */
6222 
6223 /* Initialise */
6224    result =0;
6225 
6226 /* Obtain a pointer to the FrameSet's current Frame and then invoke the
6227    method. Annul the Frame pointer afterwards. */
6228    fr = astGetFrame( (AstFrameSet *) this_frame, AST__CURRENT );
6229    result = astLineCrossing( fr, l1, l2, cross );
6230    fr = astAnnul( fr );
6231 
6232 /* Return the result. */
6233    return result;
6234 }
6235 
LineDef(AstFrame * this_frame,const double start[2],const double end[2],int * status)6236 static AstLineDef *LineDef( AstFrame *this_frame, const double start[2],
6237                             const double end[2], int *status ) {
6238 /*
6239 *  Name:
6240 *     LineDef
6241 
6242 *  Purpose:
6243 *     Creates a structure describing a line segment in a 2D Frame.
6244 
6245 *  Type:
6246 *     Private function.
6247 
6248 *  Synopsis:
6249 *     #include "frameset.h"
6250 *     AstLineDef *LineDef( AstFrame *this, const double start[2],
6251 *                             const double end[2], int *status )
6252 
6253 *  Class Membership:
6254 *     FrameSet member function (over-rides the protected astLineDef
6255 *     method inherited from the Frame class).
6256 
6257 *  Description:
6258 *     This function creates a structure containing information describing a
6259 *     given line segment within the supplied 2D Frame. This may include
6260 *     information which allows other methods such as astLineCrossing to
6261 *     function more efficiently. Thus the returned structure acts as a
6262 *     cache to store intermediate values used by these other methods.
6263 
6264 *  Parameters:
6265 *     this
6266 *        Pointer to the Frame. Must have 2 axes.
6267 *     start
6268 *        An array of 2 doubles marking the start of the line segment.
6269 *     end
6270 *        An array of 2 doubles marking the end of the line segment.
6271 *     status
6272 *        Pointer to the inherited status variable.
6273 
6274 *  Returned Value:
6275 *     Pointer to the memory structure containing the description of the
6276 *     line. This structure should be freed using astFree when no longer
6277 *     needed. A NULL pointer is returned (without error) if any of the
6278 *     supplied axis values are AST__BAD.
6279 
6280 *  Notes:
6281 *     - A null pointer will be returned if this function is invoked
6282 *     with the global error status set, or if it should fail for any
6283 *     reason.
6284 */
6285 
6286 /* Local Variables: */
6287    AstFrame *fr;                 /* Pointer to current Frame */
6288    AstLineDef *result;           /* Returned value */
6289 
6290 /* Initialise */
6291    result = NULL;
6292 
6293 /* Obtain a pointer to the FrameSet's current Frame and then invoke the
6294    method. Annul the Frame pointer afterwards. */
6295    fr = astGetFrame( (AstFrameSet *) this_frame, AST__CURRENT );
6296    result = astLineDef( fr, start, end );
6297    fr = astAnnul( fr );
6298 
6299 /* Return the result. */
6300    return result;
6301 }
6302 
LineOffset(AstFrame * this_frame,AstLineDef * line,double par,double prp,double point[2],int * status)6303 static void LineOffset( AstFrame *this_frame, AstLineDef *line, double par,
6304                         double prp, double point[2], int *status ){
6305 /*
6306 *  Name:
6307 *     LineOffset
6308 
6309 *  Purpose:
6310 *     Find a position close to a line.
6311 
6312 *  Type:
6313 *     Private function.
6314 
6315 *  Synopsis:
6316 *     #include "frame.h"
6317 *     void LineOffset( AstFrame *this, AstLineDef *line, double par,
6318 *                      double prp, double point[2], int *status )
6319 
6320 *  Class Membership:
6321 *     FrameSet member function (over-rides the protected astLineOffset
6322 *     method inherited from the Frame class).
6323 
6324 *  Description:
6325 *     This function returns a position formed by moving a given distance along
6326 *     the supplied line, and then a given distance away from the supplied line.
6327 
6328 *  Parameters:
6329 *     this
6330 *        Pointer to the Frame.
6331 *     line
6332 *        Pointer to the structure defining the line.
6333 *     par
6334 *        The distance to move along the line from the start towards the end.
6335 *     prp
6336 *        The distance to move at right angles to the line. Positive
6337 *        values result in movement to the left of the line, as seen from
6338 *        the observer, when moving from start towards the end.
6339 *     status
6340 *        Pointer to the inherited status variable.
6341 
6342 *  Notes:
6343 *     - The pointer supplied for "line" should have been created using the
6344 *     astLineDef method. This structure contains cached information about the
6345 *     line which improves the efficiency of this method when many repeated
6346 *     calls are made. An error will be reported if the structure does not
6347 *     refer to the Frame specified by "this".
6348 */
6349 
6350 
6351 /* Local Variables: */
6352    AstFrame *fr;                 /* Pointer to current Frame */
6353 
6354 /* Obtain a pointer to the FrameSet's current Frame and then invoke the
6355    method. Annul the Frame pointer afterwards. */
6356    fr = astGetFrame( (AstFrameSet *) this_frame, AST__CURRENT );
6357    astLineOffset( fr, line, par, prp, point );
6358    fr = astAnnul( fr );
6359 }
6360 
GetAllVariants(AstFrameSet * this,int * status)6361 static const char *GetAllVariants( AstFrameSet *this, int *status ) {
6362 /*
6363 *  Name:
6364 *     GetAllVariants
6365 
6366 *  Purpose:
6367 *     Get a pointer to a list of the variant Mappings for the current Frame.
6368 
6369 *  Type:
6370 *     Private function.
6371 
6372 *  Synopsis:
6373 *     #include "frameset.h"
6374 *     const char *getAllVariants( AstFrameSet *this )
6375 
6376 *  Class Membership:
6377 *     FrameSet member function.
6378 
6379 *  Description:
6380 *     This function returns a space separated list of names for all the
6381 *     variant Mappings associated with the current Frame. See attribute
6382 *     "Variant". If the current Frame has no variant Mappings, the return
6383 *     value contains just the Domain name of the current Frame in the
6384 *     supplied FrameSet.
6385 
6386 *  Parameters:
6387 *     this
6388 *        Pointer to the Frame.
6389 
6390 *  Returned Value:
6391 *     A pointer to a null-terminated string containing the list.
6392 
6393 *  Notes:
6394 *     - The returned string pointer may point at memory allocated
6395 *     within the FrameSet, or at static memory. The contents of the
6396 *     string may be over-written or the pointer may become invalid
6397 *     following a further invocation of the same function or any
6398 *     modification of the Frame. A copy of the string should
6399 *     therefore be made if necessary.
6400 *     - A NULL pointer will be returned if this function is invoked
6401 *     with the global error status set, or if it should fail for any
6402 *     reason.
6403 */
6404 
6405 /* Local Variables: */
6406    astDECLARE_GLOBALS
6407    AstFrame *frm;
6408    AstFrame *vfrm;
6409    AstFrameSet *vfs;
6410    const char *dom;
6411    const char *result;
6412    int ifrm;
6413    int nc;
6414    int icur;
6415    int nfrm;
6416 
6417 /* Check the global error status. */
6418    if ( !astOK ) return NULL;
6419 
6420 /* Get a pointer to the structure holding thread-specific global data. */
6421    astGET_GLOBALS( this );
6422 
6423 /* Get the one-based index of the Frame that defines the available
6424    variant Mappings. */
6425    icur = GetVarFrm( this, astGetCurrent( this ), status );
6426 
6427 /* Get the variants FrameSet from the Frame selected above. */
6428    frm = astGetFrame( this, icur );
6429    vfs = astGetFrameVariants( frm );
6430 
6431 /* If the Frame does not have a variants FrameSet, just return the DOmain
6432    name from the current Frame. */
6433    if( !vfs ) {
6434       result = astGetDomain( this );
6435 
6436 /* If a variants FrameSet was found, form a space sperated list of the
6437    Domain names in the FrameSet, stored in the static "getallvariants_buff"
6438    string. */
6439    } else if( astOK ){
6440       nc = 0;
6441 
6442       nfrm = astGetNframe( vfs );
6443       for( ifrm = 0; ifrm < nfrm; ifrm++ ) {
6444          vfrm = astGetFrame( vfs, ifrm + 1 );
6445          dom = astGetDomain( vfrm );
6446          if( astOK ){
6447             if( ( nc + strlen(dom) + 1 ) < GETALLVARIANTS_BUFF_LEN ) {
6448                nc += sprintf( getallvariants_buff + nc, "%s ", dom  );
6449             } else {
6450                astError( AST__INTER, "astGetAllVariants(%s): Buffer "
6451                          "overflow - too many variants.", status,
6452                          astGetClass(this) );
6453             }
6454          }
6455          vfrm = astAnnul( vfrm );
6456       }
6457 
6458 /* Remove the final space. */
6459       getallvariants_buff[ nc - 1 ] = 0;
6460 
6461 /* Return a pointer to the buffer. */
6462       result = getallvariants_buff;
6463 
6464 /* Annul the pointer to the variants FrameSet. */
6465       vfs = astAnnul( vfs );
6466    }
6467 
6468 /* Free the pointer to the current Frame. */
6469    frm = astAnnul( frm );
6470 
6471 /* If an error occurred, clear the result value. */
6472    if ( !astOK ) result = NULL;
6473 
6474 /* Return the result. */
6475    return result;
6476 }
6477 
6478 #if defined(THREAD_SAFE)
ManageLock(AstObject * this_object,int mode,int extra,AstObject ** fail,int * status)6479 static int ManageLock( AstObject *this_object, int mode, int extra,
6480                        AstObject **fail, int *status ) {
6481 /*
6482 *  Name:
6483 *     ManageLock
6484 
6485 *  Purpose:
6486 *     Manage the thread lock on an Object.
6487 
6488 *  Type:
6489 *     Private function.
6490 
6491 *  Synopsis:
6492 *     #include "object.h"
6493 *     AstObject *ManageLock( AstObject *this, int mode, int extra,
6494 *                            AstObject **fail, int *status )
6495 
6496 *  Class Membership:
6497 *     FrameSet member function (over-rides the astManageLock protected
6498 *     method inherited from the parent class).
6499 
6500 *  Description:
6501 *     This function manages the thread lock on the supplied Object. The
6502 *     lock can be locked, unlocked or checked by this function as
6503 *     deteremined by parameter "mode". See astLock for details of the way
6504 *     these locks are used.
6505 
6506 *  Parameters:
6507 *     this
6508 *        Pointer to the Object.
6509 *     mode
6510 *        An integer flag indicating what the function should do:
6511 *
6512 *        AST__LOCK: Lock the Object for exclusive use by the calling
6513 *        thread. The "extra" value indicates what should be done if the
6514 *        Object is already locked (wait or report an error - see astLock).
6515 *
6516 *        AST__UNLOCK: Unlock the Object for use by other threads.
6517 *
6518 *        AST__CHECKLOCK: Check that the object is locked for use by the
6519 *        calling thread (report an error if not).
6520 *     extra
6521 *        Extra mode-specific information.
6522 *     fail
6523 *        If a non-zero function value is returned, a pointer to the
6524 *        Object that caused the failure is returned at "*fail". This may
6525 *        be "this" or it may be an Object contained within "this". Note,
6526 *        the Object's reference count is not incremented, and so the
6527 *        returned pointer should not be annulled. A NULL pointer is
6528 *        returned if this function returns a value of zero.
6529 *     status
6530 *        Pointer to the inherited status variable.
6531 
6532 *  Returned Value:
6533 *    A local status value:
6534 *        0 - Success
6535 *        1 - Could not lock or unlock the object because it was already
6536 *            locked by another thread.
6537 *        2 - Failed to lock a POSIX mutex
6538 *        3 - Failed to unlock a POSIX mutex
6539 *        4 - Bad "mode" value supplied.
6540 
6541 *  Notes:
6542 *     - This function attempts to execute even if an error has already
6543 *     occurred.
6544 */
6545 
6546 /* Local Variables: */
6547    AstFrameSet *this;    /* Pointer to FrameSet structure */
6548    int i;                /* Loop count */
6549    int result;           /* Returned status value */
6550 
6551 /* Initialise */
6552    result = 0;
6553 
6554 /* Check the supplied pointer is not NULL. */
6555    if( !this_object ) return result;
6556 
6557 /* Obtain a pointers to the FrameSet structure. */
6558    this = (AstFrameSet *) this_object;
6559 
6560 /* Invoke the ManageLock method inherited from the parent class. */
6561    if( !result ) result = (*parent_managelock)( this_object, mode, extra,
6562                                                 fail, status );
6563 
6564 /* Invoke the astManageLock method on any Objects contained within
6565    the supplied Object. */
6566    for( i = 0; i < this->nframe; i++ ) {
6567       if( !result ) result = astManageLock( this->frame[ i ], mode,
6568                                             extra, fail );
6569    }
6570 
6571    for ( i = 0; i < this->nnode - 1; i++ ) {
6572       if( !result ) result = astManageLock( this->map[ i ], mode, extra,
6573                                             fail );
6574    }
6575 
6576    return result;
6577 
6578 }
6579 #endif
6580 
MapSplit(AstMapping * this_map,int nin,const int * in,AstMapping ** map,int * status)6581 static int *MapSplit( AstMapping *this_map, int nin, const int *in, AstMapping **map, int *status ){
6582 /*
6583 *  Name:
6584 *     MapSplit
6585 
6586 *  Purpose:
6587 *     Create a Mapping representing a subset of the inputs of an existing
6588 *     FrameSet.
6589 
6590 *  Type:
6591 *     Private function.
6592 
6593 *  Synopsis:
6594 *     #include "frameset.h"
6595 *     int *MapSplit( AstMapping *this, int nin, const int *in, AstMapping **map, int *status )
6596 
6597 *  Class Membership:
6598 *     FrameSet method (over-rides the protected astMapSplit method
6599 *     inherited from the Mapping class).
6600 
6601 *  Description:
6602 *     This function creates a new Mapping by picking specified inputs from
6603 *     an existing FrameSet. This is only possible if the specified inputs
6604 *     correspond to some subset of the FrameSet outputs. That is, there
6605 *     must exist a subset of the FrameSet outputs for which each output
6606 *     depends only on the selected FrameSet inputs, and not on any of the
6607 *     inputs which have not been selected. If this condition is not met
6608 *     by the supplied FrameSet, then a NULL Mapping is returned.
6609 
6610 *  Parameters:
6611 *     this
6612 *        Pointer to the FrameSet to be split (the FrameSet is not actually
6613 *        modified by this function).
6614 *     nin
6615 *        The number of inputs to pick from "this".
6616 *     in
6617 *        Pointer to an array of indices (zero based) for the inputs which
6618 *        are to be picked. This array should have "nin" elements. If "Nin"
6619 *        is the number of inputs of the supplied FrameSet, then each element
6620 *        should have a value in the range zero to Nin-1.
6621 *     map
6622 *        Address of a location at which to return a pointer to the new
6623 *        Mapping. This Mapping will have "nin" inputs (the number of
6624 *        outputs may be different to "nin"). A NULL pointer will be
6625 *        returned if the supplied FrameSet has no subset of outputs which
6626 *        depend only on the selected inputs.
6627 *     status
6628 *        Pointer to the inherited status variable.
6629 
6630 *  Returned Value:
6631 *     A pointer to a dynamically allocated array of ints. The number of
6632 *     elements in this array will equal the number of outputs for the
6633 *     returned Mapping. Each element will hold the index of the
6634 *     corresponding output in the supplied FrameSet. The array should be
6635 *     freed using astFree when no longer needed. A NULL pointer will
6636 *     be returned if no output Mapping can be created.
6637 
6638 *  Notes:
6639 *     - If this function is invoked with the global error status set,
6640 *     or if it should fail for any reason, then NULL values will be
6641 *     returned as the function value and for the "map" pointer.
6642 */
6643 
6644 /* Local Variables: */
6645    AstMapping *bcmap;   /* Base->current Mapping */
6646    int *result;         /* Returned pointer */
6647 
6648 /* Initialise */
6649    result = NULL;
6650    *map = NULL;
6651 
6652 /* Check the global error status. */
6653    if ( !astOK ) return result;
6654 
6655 /* Get the Mapping from base to current Frame and try to split it. */
6656    bcmap = astGetMapping( (AstFrameSet *) this_map, AST__BASE, AST__CURRENT );
6657    result = astMapSplit( bcmap, nin, in, map );
6658    bcmap = astAnnul( bcmap );
6659 
6660 /* Free returned resources if an error has occurred. */
6661    if( !astOK ) {
6662       result = astFree( result );
6663       *map = astAnnul( *map );
6664    }
6665 
6666 /* Return the list of output indices. */
6667    return result;
6668 }
6669 
Match(AstFrame * this_frame,AstFrame * target,int matchsub,int ** template_axes,int ** target_axes,AstMapping ** map,AstFrame ** result,int * status)6670 static int Match( AstFrame *this_frame, AstFrame *target, int matchsub,
6671                   int **template_axes, int **target_axes,
6672                   AstMapping **map, AstFrame **result, int *status ) {
6673 /*
6674 *  Name:
6675 *     Match
6676 
6677 *  Purpose:
6678 *     Determine if conversion is possible between two coordinate systems.
6679 
6680 *  Type:
6681 *     Private function.
6682 
6683 *  Synopsis:
6684 *     #include "frameset.h"
6685 *     int Match( AstFrame *template, AstFrame *target, int matchsub,
6686 *                int **template_axes, int **target_axes,
6687 *                AstMapping **map, AstFrame **result, int *status )
6688 
6689 *  Class Membership:
6690 *     FrameSet member function (over-rides the protected astMatch
6691 *     method inherited from the Frame class).
6692 
6693 *  Description:
6694 *     This function matches the current Frame of a "template" FrameSet
6695 *     to a "target" frame and determines whether it is possible to
6696 *     convert coordinates between them.  If it is, a Mapping that
6697 *     performs the transformation is returned along with a new Frame
6698 *     that describes the coordinate system that results when this
6699 *     Mapping is applied to the current Frame of the target
6700 *     FrameSet. In addition, information is returned to allow the axes
6701 *     in this "result" Frame to be associated with the corresponding
6702 *     axes in the target and template Frames from which they are
6703 *     derived.
6704 
6705 *  Parameters:
6706 *     template
6707 *        Pointer to the template FrameSet, whose current Frame
6708 *        describes the coordinate system (or set of possible
6709 *        coordinate systems) into which we wish to convert our
6710 *        coordinates.
6711 *     target
6712 *        Pointer to the target Frame. This describes the coordinate
6713 *        system in which we already have coordinates.
6714 *     matchsub
6715 *        If zero then a match only occurs if the template is of the same
6716 *        class as the target, or of a more specialised class. If non-zero
6717 *        then a match can occur even if this is not the case (i.e. if the
6718 *        target is of a more specialised class than the template). In
6719 *        this latter case, the target is cast down to the class of the
6720 *        template. NOTE, this argument is handled by the global method
6721 *        wrapper function "astMatch_", rather than by the class-specific
6722 *        implementations of this method.
6723 *     template_axes
6724 *        Address of a location where a pointer to int will be returned
6725 *        if the requested coordinate conversion is possible. This
6726 *        pointer will point at a dynamically allocated array of
6727 *        integers with one element for each axis of the "result" Frame
6728 *        (see below). It must be freed by the caller (using astFree)
6729 *        when no longer required.
6730 *
6731 *        For each axis in the result Frame, the corresponding element
6732 *        of this array will return the index of the axis in the
6733 *        template FrameSet's current Frame from which it is
6734 *        derived. If it is not derived from any template FrameSet
6735 *        axis, a value of -1 will be returned instead.
6736 *     target_axes
6737 *        Address of a location where a pointer to int will be returned
6738 *        if the requested coordinate conversion is possible. This
6739 *        pointer will point at a dynamically allocated array of
6740 *        integers with one element for each axis of the "result" Frame
6741 *        (see below). It must be freed by the caller (using astFree)
6742 *        when no longer required.
6743 *
6744 *        For each axis in the result Frame, the corresponding element
6745 *        of this array will return the index of the target Frame axis
6746 *        from which it is derived. If it is not derived from any
6747 *        target Frame axis, a value of -1 will be returned instead.
6748 *     map
6749 *        Address of a location where a pointer to a new Mapping will
6750 *        be returned if the requested coordinate conversion is
6751 *        possible. If returned, the forward transformation of this
6752 *        Mapping may be used to convert coordinates between the target
6753 *        Frame and the result Frame (see below) and the inverse
6754 *        transformation will convert in the opposite direction.
6755 *     result
6756 *        Address of a location where a pointer to a new Frame will be
6757 *        returned if the requested coordinate conversion is
6758 *        possible. If returned, this Frame describes the coordinate
6759 *        system that results from applying the returned Mapping
6760 *        (above) to the "target" coordinate system. In general, this
6761 *        Frame will combine attributes from (and will therefore be
6762 *        more specific than) both the target Frame and the current
6763 *        Frame of the template FrameSet. In particular, when the
6764 *        template allows the possibility of transformaing to any one
6765 *        of a set of alternative coordinate systems, the "result"
6766 *        Frame will indicate which of the alternatives was used.
6767 *     status
6768 *        Pointer to the inherited status variable.
6769 
6770 *  Returned Value:
6771 *     A non-zero value is returned if the requested coordinate
6772 *     conversion is possible. Otherwise zero is returned (this will
6773 *     not in itself result in an error condition).
6774 
6775 *  Notes:
6776 *     - A value of zero will be returned if this function is invoked
6777 *     with the global error status set, or if it should fail for any
6778 *     reason.
6779 */
6780 
6781 /* Local Variables: */
6782    AstFrame *fr;                 /* Pointer to FrameSet's current Frame */
6783    AstFrameSet *this;            /* Pointer to the FrameSet structure */
6784    int match;                    /* Result to be returned */
6785 
6786 /* Initialise the returned values. */
6787    *template_axes = NULL;
6788    *target_axes = NULL;
6789    *map = NULL;
6790    *result = NULL;
6791    match = 0;
6792 
6793 /* Check the global error status. */
6794    if ( !astOK ) return match;
6795 
6796 /* Obtain a pointer to the FrameSet structure. */
6797    this = (AstFrameSet *) this_frame;
6798 
6799 /* Obtain a pointer to the FrameSet's current Frame. */
6800    fr = astGetFrame( this, AST__CURRENT );
6801 
6802 /* Invoke the astMatch method for this Frame. */
6803    match =astMatch( fr, target, matchsub, template_axes, target_axes,
6804                     map, result );
6805 
6806 /* Annul the Frame pointer. */
6807    fr = astAnnul( fr );
6808 
6809 /* If an error occurred, clean up by freeing any allocated memory,
6810    annulling returned objects and clearing the returned result. */
6811    if ( !astOK ) {
6812       *template_axes = astFree( *template_axes );
6813       *target_axes = astFree( *target_axes );
6814       *map = astAnnul( *map );
6815       *result = astAnnul( *result );
6816       match = 0;
6817    }
6818 
6819 /* Return the result. */
6820    return match;
6821 }
6822 
MatchAxes(AstFrame * frm1_frame,AstFrame * frm2,int * axes,int * status)6823 static void MatchAxes( AstFrame *frm1_frame, AstFrame *frm2, int *axes,
6824                        int *status ) {
6825 /*
6826 *  Name:
6827 *     MatchAxes
6828 
6829 *  Purpose:
6830 *     Find any corresponding axes in two Frames.
6831 
6832 *  Type:
6833 *     Private function.
6834 
6835 *  Synopsis:
6836 *     #include "frameset.h"
6837 *     void MatchAxes( AstFrame *frm1, AstFrame *frm2, int *axes )
6838 *                     int *status )
6839 
6840 *  Class Membership:
6841 *     FrameSet member function (over-rides the protected astMatchAxes
6842 *     method inherited from the Frame class).
6843 
6844 *  Description:
6845 *     This function looks for corresponding axes within two supplied
6846 *     Frames. An array of integers is returned that contains an element
6847 *     for each axis in the second supplied Frame. An element in this array
6848 *     will be set to zero if the associated axis within the second Frame
6849 *     has no corresponding axis within the first Frame. Otherwise, it
6850 *     will be set to the index (a non-zero positive integer) of the
6851 *     corresponding axis within the first supplied Frame.
6852 
6853 *  Parameters:
6854 *     frm1
6855 *        Pointer to the first Frame.
6856 *     frm2
6857 *        Pointer to the second Frame.
6858 *     axes
6859 *        Pointer to an
6860 *        integer array in which to return the indices of the axes (within
6861 *        the second Frame) that correspond to each axis within the first
6862 *        Frame. Axis indices start at 1. A value of zero will be stored
6863 *        in the returned array for each axis in the first Frame that has
6864 *        no corresponding axis in the second Frame.
6865 *
6866 *        The number of elements in this array must be greater than or
6867 *        equal to the number of axes in the first Frame.
6868 *     status
6869 *        Pointer to inherited status value.
6870 
6871 *  Notes:
6872 *     -  Corresponding axes are identified by the fact that a Mapping
6873 *     can be found between them using astFindFrame or astConvert. Thus,
6874 *     "corresponding axes" are not necessarily identical. For instance,
6875 *     SkyFrame axes in two Frames will match even if they describe
6876 *     different celestial coordinate systems
6877 */
6878 
6879 /* Local Variables: */
6880    AstFrame *frm1;
6881 
6882 /* Check the global error status. */
6883    if ( !astOK ) return;
6884 
6885 /* Get a pointer to the current Frame in the FrameSet. */
6886    frm1 = astGetFrame( (AstFrameSet *) frm1_frame, AST__CURRENT );
6887 
6888 /* Invoke the astMatchAxesX on the second Frame. */
6889    astMatchAxesX( frm2, frm1, axes );
6890 
6891 /* Free resources */
6892    frm1 = astAnnul( frm1 );
6893 }
6894 
MatchAxesX(AstFrame * frm2_frame,AstFrame * frm1,int * axes,int * status)6895 static void MatchAxesX( AstFrame *frm2_frame, AstFrame *frm1, int *axes,
6896                         int *status ) {
6897 /*
6898 *  Name:
6899 *     MatchAxesX
6900 
6901 *  Purpose:
6902 *     Find any corresponding axes in two Frames.
6903 
6904 *  Type:
6905 *     Private function.
6906 
6907 *  Synopsis:
6908 *     #include "frameset.h"
6909 *     void MatchAxesX( AstFrame *frm2, AstFrame *frm1, int *axes )
6910 *                      int *status )
6911 
6912 *  Class Membership:
6913 *     FrameSet member function (over-rides the protected astMatchAxesX
6914 *     method inherited from the Frame class).
6915 
6916 *     This function looks for corresponding axes within two supplied
6917 *     Frames. An array of integers is returned that contains an element
6918 *     for each axis in the second supplied Frame. An element in this array
6919 *     will be set to zero if the associated axis within the second Frame
6920 *     has no corresponding axis within the first Frame. Otherwise, it
6921 *     will be set to the index (a non-zero positive integer) of the
6922 *     corresponding axis within the first supplied Frame.
6923 
6924 *  Parameters:
6925 *     frm2
6926 *        Pointer to the second Frame.
6927 *     frm1
6928 *        Pointer to the first Frame.
6929 *     axes
6930 *        Pointer to an integer array in which to return the indices of
6931 *        the axes (within the first Frame) that correspond to each axis
6932 *        within the second Frame. Axis indices start at 1. A value of zero
6933 *        will be stored in the returned array for each axis in the second
6934 *        Frame that has no corresponding axis in the first Frame.
6935 *
6936 *        The number of elements in this array must be greater than or
6937 *        equal to the number of axes in the second Frame.
6938 *     status
6939 *        Pointer to inherited status value.
6940 
6941 *  Notes:
6942 *     -  Corresponding axes are identified by the fact that a Mapping
6943 *     can be found between them using astFindFrame or astConvert. Thus,
6944 *     "corresponding axes" are not necessarily identical. For instance,
6945 *     SkyFrame axes in two Frames will match even if they describe
6946 *     different celestial coordinate systems
6947 */
6948 
6949 /* Local Variables: */
6950    AstFrame *frm2;
6951 
6952 /* Check the global error status. */
6953    if ( !astOK ) return;
6954 
6955 /* Get a pointer to the current Frame in the FrameSet. */
6956    frm2 = astGetFrame( (AstFrameSet *) frm2_frame, AST__CURRENT );
6957 
6958 /* Invoke the astMatchAxesX on the current Frame. */
6959    astMatchAxesX( frm2, frm1, axes );
6960 
6961 /* Free resources */
6962    frm2 = astAnnul( frm2 );
6963 }
6964 
MirrorVariants(AstFrameSet * this,int iframe,int * status)6965 static void MirrorVariants( AstFrameSet *this, int iframe, int *status ) {
6966 /*
6967 *++
6968 *  Name:
6969 c     astMirrorVariants
6970 f     AST_MIRRORVARIANTS
6971 
6972 *  Purpose:
6973 *     Make the current Frame mirror the variant Mappings in another Frame.
6974 
6975 *  Type:
6976 *     Public virtual function.
6977 
6978 *  Synopsis:
6979 c     #include "frameset.h"
6980 c     void astMirrorVariants( AstFrameSet *this, int iframe, int *status )
6981 f     CALL AST_MIRRORVARIANTS( THIS, IFRAME, STATUS )
6982 
6983 *  Class Membership:
6984 *     FrameSet method.
6985 
6986 *  Description:
6987 c     This function
6988 f     This routine
6989 *     indicates that all access to the Variant attribute of the current
6990 *     Frame should should be forwarded to some other nominated Frame in
6991 *     the FrameSet. For instance, if a value is set subsequently for the
6992 *     Variant attribute of the current Frame, the current Frame will be left
6993 *     unchanged and the setting is instead applied to the nominated Frame.
6994 *     Likewise, if the value of the Variant attribute is requested, the
6995 *     value returned is the value stored for the nominated Frame rather
6996 *     than the current Frame itself.
6997 *
6998 *     This provides a mechanism for propagating the effects of variant
6999 *     Mappings around a FrameSet. If a new Frame is added to a FrameSet
7000 *     by connecting it to an pre-existing Frame that has two or more variant
7001 *     Mappings, then it may be appropriate to set the new Frame so that it
7002 *     mirrors the variants Mappings of the pre-existing Frame. If this is
7003 *     done, then it will be possible to select a specific variant Mapping
7004 *     using either the pre-existing Frame or the new Frame.
7005 
7006 *  Parameters:
7007 c     this
7008 f     THIS = INTEGER (Given)
7009 *        Pointer to the FrameSet.
7010 c     iframe
7011 f     IFRAME = INTEGER (Given)
7012 *        The index of the Frame within the FrameSet which is to be
7013 *        mirrored by the current Frame. This value should lie in the range
7014 *        from 1 to the number of Frames in the FrameSet (as given by its
7015 *        Nframe attribute). If AST__NOFRAME is supplied (or the current
7016 *        Frame is specified), then any mirroring established by a previous
7017 *        call to this
7018 c        function
7019 f        routine
7020 *        is disabled.
7021 f     STATUS = INTEGER (Given and Returned)
7022 f        The global status.
7023 
7024 *  Notes:
7025 *     - Mirrors can be chained. That is, if Frame B is set to be a mirror
7026 *     of Frame A, and Frame C is set to be a mirror of Frame B, then
7027 *     Frame C will act as a mirror of Frame A.
7028 *     - Variant Mappings cannot be added to the current Frame if it is
7029 *     mirroring another Frame. So calls to the
7030 c     astAddVariant function
7031 f     AST_ADDVARIANT routine
7032 *     will cause an error to be reported if the current Frame is
7033 *     mirroring another Frame.
7034 *     - A value of AST__BASE may be given for the
7035 c     "iframe" parameter
7036 f     IFRAME argument
7037 *     to specify the base Frame.
7038 *     - Any variant Mappings explicitly added to the current Frame using
7039 c     astAddVariant
7040 f     AST_ADDVARIANT
7041 *     will be ignored if the current Frame is mirroring another Frame.
7042 
7043 *--
7044 */
7045 
7046 /* Local Variables: */
7047    int icur;
7048 
7049 /* Check the global error status. */
7050    if ( !astOK ) return;
7051 
7052 /* Get the current Frame index. */
7053    icur = astGetCurrent( this );
7054 
7055 /* If AST__NOFRAME, disable any mirroring. */
7056    if( iframe == AST__NOFRAME ) {
7057       this->varfrm[ icur - 1 ] = 0;
7058 
7059 /* Otherwise, validate and translate the Frame index supplied. */
7060    } else {
7061       iframe = astValidateFrameIndex( this, iframe, "astMirrorVariants" );
7062 
7063 /* If the current Frame has been specified, disable any mirroring. */
7064       if( iframe == icur ) {
7065          this->varfrm[ icur - 1 ] = 0;
7066 
7067 /* Otherwise, store the one-based variants frame index. */
7068       } else {
7069          this->varfrm[ icur - 1 ] = iframe;
7070       }
7071    }
7072 }
7073 
Norm(AstFrame * this_frame,double value[],int * status)7074 static void Norm( AstFrame *this_frame, double value[], int *status ) {
7075 /*
7076 *  Name:
7077 *     Norm
7078 
7079 *  Purpose:
7080 *     Normalise a set of FrameSet coordinates.
7081 
7082 *  Type:
7083 *     Private function.
7084 
7085 *  Synopsis:
7086 *     #include "frameset.h"
7087 *     void Norm( AstAxis *this, double value[], int *status )
7088 
7089 *  Class Membership:
7090 *     FrameSet member function (over-rides the astNorm method
7091 *     inherited from the Frame class).
7092 
7093 *  Description:
7094 *     This function converts a set of coordinate values for the
7095 *     current Frame of a FrameSet, which might potentially be
7096 *     unsuitable for display to a user (for instance, may lie outside
7097 *     the expected range of values) into a set of acceptable
7098 *     alternative values suitable for display.
7099 *
7100 *     Typically, for Frames whose axes represent cyclic values (such
7101 *     as angles or positions on the sky), this function wraps an
7102 *     arbitrary set of coordinates, so that they lie within the first
7103 *     cycle (say zero to 2*pi or -pi/2 to +pi/2). For Frames with
7104 *     ordinary linear axes, without constraints, this function will
7105 *     typically return the original coordinate values unchanged.
7106 
7107 *  Parameters:
7108 *     this
7109 *        Pointer to the FrameSet.
7110 *     value
7111 *        An array of double, with one element for each FrameSet axis.
7112 *        This should contain the initial set of coordinate values,
7113 *        which will be modified in place.
7114 *     status
7115 *        Pointer to the inherited status variable.
7116 */
7117 
7118 /* Local Variables: */
7119    AstFrame *fr;                 /* Pointer to the current Frame */
7120    AstFrameSet *this;            /* Pointer to the FrameSet structure */
7121 
7122 /* Check the global error status. */
7123    if ( !astOK ) return;
7124 
7125 /* Obtain a pointer to the FrameSet structure. */
7126    this = (AstFrameSet *) this_frame;
7127 
7128 /* Obtain a pointer to the FrameSet's current Frame and invoke this
7129    Frame's astNorm method to obtain the new values. Annul the Frame
7130    pointer afterwards. */
7131    fr = astGetFrame( this, AST__CURRENT );
7132    astNorm( fr, value );
7133    fr = astAnnul( fr );
7134 }
7135 
NormBox(AstFrame * this_frame,double lbnd[],double ubnd[],AstMapping * reg,int * status)7136 static void NormBox( AstFrame *this_frame, double lbnd[], double ubnd[],
7137                      AstMapping *reg, int *status ) {
7138 /*
7139 *  Name:
7140 *     NormBox
7141 
7142 *  Purpose:
7143 *     Extend a box to include effect of any singularities in the Frame.
7144 
7145 *  Type:
7146 *     Private function.
7147 
7148 *  Synopsis:
7149 *     #include "frameset.h"
7150 *     void astNormBox( AstFrame *this, double lbnd[], double ubnd[],
7151 *                      AstMapping *reg, int *status )
7152 
7153 *  Class Membership:
7154 *     FrameSet member function (over-rides the astNormBox method inherited
7155 *     from the Frame class).
7156 
7157 *  Description:
7158 *     This function modifies a supplied box to include the effect of any
7159 *     singularities in the co-ordinate system represented by the Frame.
7160 *     For a normal Cartesian coordinate system, the box will be returned
7161 *     unchanged. Other classes of Frame may do other things. For instance,
7162 *     a SkyFrame will check to see if the box contains either the north
7163 *     or south pole and extend the box appropriately.
7164 
7165 *  Parameters:
7166 *     this
7167 *        Pointer to the Frame.
7168 *     lbnd
7169 *        An array of double, with one element for each Frame axis
7170 *        (Naxes attribute). Initially, this should contain a set of
7171 *        lower axis bounds for the box. They will be modified on exit
7172 *        to include the effect of any singularities within the box.
7173 *     ubnd
7174 *        An array of double, with one element for each Frame axis
7175 *        (Naxes attribute). Initially, this should contain a set of
7176 *        upper axis bounds for the box. They will be modified on exit
7177 *        to include the effect of any singularities within the box.
7178 *     reg
7179 *        A Mapping which should be used to test if any singular points are
7180 *        inside or outside the box. The Mapping should leave an input
7181 *        position unchanged if the point is inside the box, and should
7182 *        set all bad if the point is outside the box.
7183 *     status
7184 *        Pointer to the inherited status variable.
7185 */
7186 
7187 /* Local Variables: */
7188    AstFrame *fr;                 /* Pointer to the current Frame */
7189    AstFrameSet *this;            /* Pointer to the FrameSet structure */
7190 
7191 /* Check the global error status. */
7192    if ( !astOK ) return;
7193 
7194 /* Obtain a pointer to the FrameSet structure. */
7195    this = (AstFrameSet *) this_frame;
7196 
7197 /* Obtain a pointer to the FrameSet's current Frame and invoke this
7198    Frame's astNormBox method to obtain the new values. Annul the Frame
7199    pointer afterwards. */
7200    fr = astGetFrame( this, AST__CURRENT );
7201    astNormBox( fr, lbnd, ubnd, reg );
7202    fr = astAnnul( fr );
7203 }
7204 
Offset(AstFrame * this_frame,const double point1[],const double point2[],double offset,double point3[],int * status)7205 static void Offset( AstFrame *this_frame, const double point1[],
7206                     const double point2[], double offset, double point3[], int *status ) {
7207 /*
7208 *  Name:
7209 *     Offset
7210 
7211 *  Purpose:
7212 *     Calculate an offset along a geodesic curve.
7213 
7214 *  Type:
7215 *     Public virtual function.
7216 
7217 *  Synopsis:
7218 *     #include "frameset.h"
7219 *     void Offset( AstFrame *this,
7220 *                  const double point1[], const double point2[],
7221 *                  double offset, double point3[], int *status )
7222 
7223 *  Class Membership:
7224 *     FrameSet member function (over-rides the protected astOffset
7225 *     method inherited from the Frame class).
7226 
7227 *  Description:
7228 *     This function finds the FrameSet coordinate values of a point
7229 *     which is offset a specified distance along the geodesic curve
7230 *     between two other points.
7231 
7232 *  Parameters:
7233 *     this
7234 *        Pointer to the FrameSet.
7235 *     point1
7236 *        An array of double, with one element for each FrameSet axis.
7237 *        This should contain the coordinates of the point marking the
7238 *        start of the geodesic curve.
7239 *     point2
7240 *        An array of double, with one element for each FrameSet axis
7241 *        This should contain the coordinates of the point marking the
7242 *        end of the geodesic curve.
7243 *     offset
7244 *        The required offset from the first point along the geodesic
7245 *        curve. If this is positive, it will be towards the second
7246 *        point. If it is negative, it will be in the opposite
7247 *        direction. This offset need not imply a position lying
7248 *        between the two points given, as the curve will be
7249 *        extrapolated if necessary.
7250 *     point3
7251 *        An array of double, with one element for each FrameSet axis
7252 *        in which the coordinates of the required point will be
7253 *        returned.
7254 *     status
7255 *        Pointer to the inherited status variable.
7256 
7257 *  Notes:
7258 *     - The geodesic curve used by this function is the path of
7259 *     shortest distance between two points, as defined by the
7260 *     astDistance function.
7261 *     - This function will return "bad" coordinate values (AST__BAD)
7262 *     if any of the input coordinates has this value.
7263 *     - "Bad" coordinate values will also be returned if the two
7264 *     points supplied are coincident (or otherwise fail to uniquely
7265 *     specify a geodesic curve) but the requested offset is non-zero.
7266 */
7267 
7268 /* Local Variables: */
7269    AstFrame *fr;                 /* Pointer to current Frame */
7270    AstFrameSet *this;            /* Pointer to the FrameSet structure */
7271 
7272 /* Check the global error status. */
7273    if ( !astOK ) return;
7274 
7275 /* Obtain a pointer to the FrameSet structure. */
7276    this = (AstFrameSet *) this_frame;
7277 
7278 /* Obtain a pointer to the FrameSet's current Frame and invoke this
7279    Frame's astOffset method. Annul the Frame pointer afterwards. */
7280    fr = astGetFrame( this, AST__CURRENT );
7281    astOffset( fr, point1, point2, offset, point3 );
7282    fr = astAnnul( fr );
7283 }
7284 
Offset2(AstFrame * this_frame,const double point1[2],double angle,double offset,double point2[2],int * status)7285 static double Offset2( AstFrame *this_frame, const double point1[2],
7286                        double angle, double offset, double point2[2], int *status ){
7287 /*
7288 *  Name:
7289 *     Offset2
7290 
7291 *  Purpose:
7292 *     Calculate an offset along a geodesic curve in a 2D Frame.
7293 
7294 *  Type:
7295 *     Private function.
7296 
7297 *  Synopsis:
7298 *     #include "frameset.h"
7299 *     double Offset2( AstFrame *this, const double point1[2], double angle,
7300 *                     double offset, double point2[2], int *status );
7301 
7302 *  Class Membership:
7303 *     FrameSet member function (over-rides the protected astOffset2
7304 *     method inherited from the Frame class).
7305 
7306 *  Description:
7307 *     This function finds the Frame coordinate values of a point which
7308 *     is offset a specified distance along the geodesic curve at a
7309 *     given angle from a specified starting point. It can only be
7310 *     used with 2-dimensional Frames.
7311 *
7312 *     For example, in a basic Frame, this offset will be along the
7313 *     straight line joining two points. For a more specialised Frame
7314 *     describing a sky coordinate system, however, it would be along
7315 *     the great circle passing through two sky positions.
7316 
7317 *  Parameters:
7318 *     this
7319 *        Pointer to the Frame.
7320 *     point1
7321 *        An array of double, with one element for each Frame axis
7322 *        (Naxes attribute). This should contain the coordinates of the
7323 *        point marking the start of the geodesic curve.
7324 *     angle
7325 *        The angle (in radians) from the positive direction of the second
7326 *        axis, to the direction of the required position, as seen from
7327 *        the starting position. Positive rotation is in the sense of
7328 *        rotation from the positive direction of axis 2 to the positive
7329 *        direction of axis 1.
7330 *     offset
7331 *        The required offset from the first point along the geodesic
7332 *        curve. If this is positive, it will be in the direction of the
7333 *        given angle. If it is negative, it will be in the opposite
7334 *        direction.
7335 *     point2
7336 *        An array of double, with one element for each Frame axis
7337 *        in which the coordinates of the required point will be returned.
7338 *     status
7339 *        Pointer to the inherited status variable.
7340 
7341 *  Returned Value:
7342 *     The direction of the geodesic curve at the end point. That is, the
7343 *     angle (in radians) between the positive direction of the second
7344 *     axis and the continuation of the geodesic curve at the requested
7345 *     end point. Positive rotation is in the sense of rotation from
7346 *     the positive direction of axis 2 to the positive direction of axis 1.
7347 
7348 *  Notes:
7349 *     - The geodesic curve used by this function is the path of
7350 *     shortest distance between two points, as defined by the
7351 *     astDistance function.
7352 *     - An error will be reported if the Frame is not 2-dimensional.
7353 *     - This function will return "bad" coordinate values (AST__BAD)
7354 *     if any of the input coordinates has this value.
7355 */
7356 
7357 /* Local Variables: */
7358    AstFrame *fr;                 /* Pointer to current Frame */
7359    AstFrameSet *this;            /* Pointer to the FrameSet structure */
7360    double result;                /* Value to return */
7361 
7362 /* Check the global error status. */
7363    if ( !astOK ) return AST__BAD;
7364 
7365 /* Obtain a pointer to the FrameSet structure. */
7366    this = (AstFrameSet *) this_frame;
7367 
7368 /* Obtain a pointer to the FrameSet's current Frame and invoke the
7369    astOffset2 method for this Frame. Annul the Frame pointer afterwards. */
7370    fr = astGetFrame( this, AST__CURRENT );
7371    result = astOffset2( fr, point1, angle, offset, point2 );
7372    fr = astAnnul( fr );
7373 
7374 /* If an error occurred, clear the result value. */
7375    if ( !astOK ) result = AST__BAD;
7376 
7377 /* Return the result. */
7378    return result;
7379 }
7380 
Overlay(AstFrame * template_frame,const int * template_axes,AstFrame * result,int * status)7381 static void Overlay( AstFrame *template_frame, const int *template_axes,
7382                      AstFrame *result, int *status ) {
7383 /*
7384 *  Name:
7385 *     Overlay
7386 
7387 *  Purpose:
7388 *     Overlay the attributes of a template FrameSet on to another Frame.
7389 
7390 *  Type:
7391 *     Private function.
7392 
7393 *  Synopsis:
7394 *     #include "frameset.h"
7395 *     void Overlay( AstFrame *template, const int *template_axes,
7396 *                   AstFrame *result, int *status )
7397 
7398 *  Class Membership:
7399 *     FrameSet member function (over-rides the protected astOverlay
7400 *     method inherited from the Frame class).
7401 
7402 *  Description:
7403 *     This function overlays attributes from the current Frame of a
7404 *     FrameSet on to another Frame, so as to over-ride selected
7405 *     attributes of that second Frame. Normally only those attributes
7406 *     which have been specifically set in the template will be
7407 *     transferred. This implements a form of defaulting, in which a
7408 *     Frame acquires attributes from the template, but retains its
7409 *     original attributes (as the default) if new values have not
7410 *     previously been explicitly set in the template.
7411 
7412 *  Parameters:
7413 *     template
7414 *        Pointer to the template FrameSet, for whose current Frame
7415 *        values should have been explicitly set for any attribute
7416 *        which is to be transferred.
7417 *     template_axes
7418 *        Pointer to an array of int, with one element for each axis of
7419 *        the "result" Frame (see below). For each axis in the result
7420 *        frame, the corresponding element of this array should contain
7421 *        the (zero-based) index of the axis in the current Frame of
7422 *        the template FrameSet to which it corresponds. This array is
7423 *        used to establish from which template Frame axis any
7424 *        axis-dependent attributes should be obtained.
7425 *
7426 *        If any axis in the result Frame is not associated with a
7427 *        template Frame axis, the corresponding element of this array
7428 *        should be set to -1.
7429 *
7430 *        If a NULL pointer is supplied, the template and result axis
7431 *        indicies are assumed to be identical.
7432 *     result
7433 *        Pointer to the Frame which is to receive the new attribute values.
7434 *     status
7435 *        Pointer to the inherited status variable.
7436 */
7437 
7438 /* Local Variables: */
7439    AstFrame *fr;                 /* Pointer to current Frame */
7440    AstFrameSet *template;        /* Pointer to the FrameSet structure */
7441 
7442 /* Check the global error status. */
7443    if ( !astOK ) return;
7444 
7445 /* Obtain a pointer to the FrameSet structure. */
7446    template = (AstFrameSet *) template_frame;
7447 
7448 /* Obtain a pointer to the current Frame and invoke its astOverlay
7449    method to overlay its attributes. Annul the Frame pointer
7450    afterwards. */
7451    fr = astGetFrame( template, AST__CURRENT );
7452    astOverlay( fr, template_axes, result );
7453    fr = astAnnul( fr );
7454 }
7455 
PermAxes(AstFrame * this_frame,const int perm[],int * status)7456 static void PermAxes( AstFrame *this_frame, const int perm[], int *status ) {
7457 /*
7458 *  Name:
7459 *     PermAxes
7460 
7461 *  Purpose:
7462 *     Permute the order of a FrameSet's axes.
7463 
7464 *  Type:
7465 *     Private function.
7466 
7467 *  Synopsis:
7468 *     #include "frameset.h"
7469 *     void PermAxes( AstFrame *this, const int perm[], int *status )
7470 
7471 *  Class Membership:
7472 *     FrameSet member function (over-rides the astPermAxes method
7473 *     inherited from the Frame class).
7474 
7475 *  Description:
7476 *     This function permutes the order in which the axes in the
7477 *     current Frame of a FrameSet occur.
7478 
7479 *  Parameters:
7480 *     this
7481 *        Pointer to the FrameSet.
7482 *     perm
7483 *        An array of int (with one element for each axis of the
7484 *        FrameSet's current Frame) which lists the axes in their new
7485 *        order. Each element of this array should be a (zero-based)
7486 *        axis index identifying the axes according to their old
7487 *        (un-permuted) order.
7488 *     status
7489 *        Pointer to the inherited status variable.
7490 
7491 *  Notes:
7492 *     - Only genuine permutations of the axis order are permitted, so
7493 *     each axis must be referenced exactly once in the "perm" array.
7494 *     - If more than one axis permutation is applied to the same Frame
7495 *     in a FrameSet, the effects are cumulative.
7496 */
7497 
7498 /* Local Variables: */
7499    AstFrame *fr;                 /* Pointer to current Frame */
7500    AstFrameSet *this;            /* Pointer to the FrameSet structure */
7501    AstPermMap *map;              /* Pointer to axis permutation Mapping */
7502    int *invperm;                 /* Pointer to inverse permutation array */
7503    int axis;                     /* Loop counter for axes */
7504    int naxes;                    /* Number of FrameSet axes */
7505 
7506 /* Check the global error status. */
7507    if ( !astOK ) return;
7508 
7509 /* Obtain a pointer to the FrameSet structure. */
7510    this = (AstFrameSet *) this_frame;
7511 
7512 /* Validate the permutation array, to check that it describes a
7513    genuine permutation. */
7514    astCheckPerm( this, perm, "astPermAxes" );
7515 
7516 /* Obtain a pointer to the FrameSet's current Frame and invoke this
7517    Frame's astPermAxes method to permute its axes. Annul the Frame
7518    pointer afterwards. */
7519    fr = astGetFrame( this, AST__CURRENT );
7520    astPermAxes( fr, perm );
7521    fr = astAnnul( fr );
7522 
7523 /* Obtain the number of axes in the FrameSet's current Frame and allocate
7524    memory to hold an inverse permutation array. */
7525    naxes =  astGetNaxes( this );
7526    invperm = astMalloc( sizeof( int ) * (size_t) naxes );
7527 
7528 /* Fill the inverse permutation array with values that will invert the
7529    axis permutation supplied. */
7530    if ( astOK ) {
7531       for ( axis = 0; axis < naxes; axis++ ) invperm[ perm[ axis ] ] = axis;
7532 
7533 /* Create a PermMap that will permute coordinate values in the same way as
7534    the current Frame's axes have been permuted. */
7535       map = astPermMap( naxes, invperm, naxes, perm, NULL, "", status );
7536 
7537 /* Modify the Frame's relationship to the rest of the Frames in the
7538    FrameSet so that the correct coordinate values remain associated
7539    with the permuted axes. */
7540       astRemapFrame( this, AST__CURRENT, map );
7541 
7542 /* Annul the PermMap and free the inverse permutation array. */
7543       map = astAnnul( map );
7544    }
7545    invperm = astFree( invperm );
7546 }
7547 
PickAxes(AstFrame * this_frame,int naxes,const int axes[],AstMapping ** map,int * status)7548 static AstFrame *PickAxes( AstFrame *this_frame, int naxes, const int axes[],
7549                            AstMapping **map, int *status ) {
7550 /*
7551 *  Name:
7552 *     PickAxes
7553 
7554 *  Purpose:
7555 *     Create a new Frame by picking axes from a FrameSet.
7556 
7557 *  Type:
7558 *     Private function.
7559 
7560 *  Synopsis:
7561 *     #include "frameset.h"
7562 *     AstFrame *PickAxes( AstFrame *this, int naxes, const int axes[],
7563 *                         AstMapping **map, int *status )
7564 
7565 *  Class Membership:
7566 *     FrameSet member function (over-rides the astPickAxes protected
7567 *     method inherited from the Frame class).
7568 
7569 *  Description:
7570 *     This function creates a new Frame whose axes are copies of axes
7571 *     picked from the current Frame of an existing FrameSet. Other
7572 *     Frame attributes are also copied from this current Frame to the
7573 *     new Frame. Zero or more of the original axes may be picked in
7574 *     any order, but each can be used only once. Additional axes (with
7575 *     default characteristics) may be included in the new Frame if
7576 *     required.
7577 *
7578 *     Optionally, a Mapping that converts between the original Frame's
7579 *     axes and those of the new Frame may also be returned.
7580 
7581 *  Parameters:
7582 *     this
7583 *        Pointer to the FrameSet.
7584 *     naxes
7585 *        The number of axes required in the new Frame.
7586 *     axes
7587 *        Pointer to an array of int with naxes elements. This should
7588 *        contain (zero based) axis indices specifying the axes which
7589 *        are to be included in the new Frame, in the order
7590 *        required. Each axis index may occur only once.
7591 *
7592 *        If additional (default) axes are also to be included, the
7593 *        corresponding elements of this array should be set to -1.
7594 *     map
7595 *        Address of a location to receive a pointer to a new
7596 *        Mapping. This will be a PermMap (or a UnitMap as a special
7597 *        case) that describes the axis permutation that has taken
7598 *        place between the current Frame of the FrameSet and the new
7599 *        Frame.  The forward transformation will convert from the
7600 *        original FrameSet's axes to the new one's, and vice versa.
7601 *
7602 *        If this Mapping is not required, a NULL value may be supplied
7603 *        for this parameter.
7604 *     status
7605 *        Pointer to the inherited status variable.
7606 
7607 *  Returned Value:
7608 *     Pointer to the new Frame.
7609 
7610 *  Notes:
7611 *     - The class of object returned may differ from that of the
7612 *     original current Frame, depending on which axes are
7613 *     selected. For example, if a single axis is picked from a
7614 *     SkyFrame (which always has two axes), the resulting Frame cannot
7615 *     be a valid SkyFrame, so will revert to the parent class (Frame)
7616 *     instead.
7617 *     - The new Frame contains a deep copy of all the data selected
7618 *     from the original current Frame. Modifying the new Frame will
7619 *     therefore not affect the FrameSet or the Frames it contains.
7620 *     - A NULL pointer will be returned if this function is invoked
7621 *     with the global error status set, or if it should fail for any
7622 *     reason.
7623 */
7624 
7625 /* Local Variables: */
7626    AstFrame *fr;                 /* Pointer to current Frame */
7627    AstFrame *frame;              /* Pointer to Frame to be returned */
7628    AstFrameSet *this;            /* Pointer to FrameSet structure */
7629 
7630 /* Initialise the returned pointers. */
7631    if ( map ) *map = NULL;
7632    frame = NULL;
7633 
7634 /* Check the global error status. */
7635    if ( !astOK ) return frame;
7636 
7637 /* Obtain a pointer to the FrameSet structure. */
7638    this = (AstFrameSet *) this_frame;
7639 
7640 /* Check that a valid set of axes is being selected . */
7641    astValidateAxisSelection( this, naxes, axes, "astPickAxes" );
7642 
7643 /* Obtain a pointer to the FrameSet's current Frame and use its
7644    astPickAxes method to obtain the required new Frame and
7645    Mapping. Annul the current Frame pointer afterwards. */
7646    fr = astGetFrame( this, AST__CURRENT );
7647    frame = astPickAxes( fr, naxes, axes, map );
7648    fr = astAnnul( fr );
7649 
7650 /* If an error occurred, annul the Mapping pointer (if requested) and
7651    the new Frame pointer. */
7652    if ( !astOK ) {
7653       if ( map ) *map = astAnnul( *map );
7654       frame = astAnnul( frame );
7655    }
7656 
7657 /* Return the pointer to the new Frame. */
7658    return frame;
7659 }
7660 
PrimaryFrame(AstFrame * this_frame,int axis1,AstFrame ** frame,int * axis2,int * status)7661 static void PrimaryFrame( AstFrame *this_frame, int axis1,
7662                           AstFrame **frame, int *axis2, int *status ) {
7663 /*
7664 *  Name:
7665 *     PrimaryFrame
7666 
7667 *  Purpose:
7668 *     Uniquely identify a primary Frame and one of its axes.
7669 
7670 *  Type:
7671 *     Private function.
7672 
7673 *  Synopsis:
7674 *     #include "frameset.h"
7675 *     void PrimaryFrame( AstFrame *this, int axis1, AstFrame **frame,
7676 *                        int *axis2, int *status )
7677 
7678 *  Class Membership:
7679 *     FrameSet member function (over-rides the protected
7680 *     astPrimaryFrame method inherited from the Frame class).
7681 
7682 *  Description:
7683 *     This function returns information about the underlying (primary)
7684 *     Frame corresponding to a specified axis of the current Frame of
7685 *     a FrameSet, when this current Frame may be a compound Frame
7686 *     composed of more than one simpler one.
7687 
7688 *  Parameters:
7689 *     this
7690 *        Pointer to the FrameSet.
7691 *     axis1
7692 *        An axis index (zero-based) identifying the axis of the
7693 *        FrameSet's current Frame for which information is required.
7694 *     frame
7695 *        Address of a location to receive a pointer to the underlying
7696 *        (primary) frame to which the requested axis belongs
7697 *        (i.e. this will not be a compound Frame).
7698 *     axis2
7699 *        Pointer to an int which is to receive the axis index within
7700 *        "frame" which identifies the axis being referred to, using
7701 *        the axis order that applied when the primary Frame was
7702 *        originally constructed (i.e. this function undoes all
7703 *        subsequent axis pemutations and the effects of combining
7704 *        Frames, in order to reveal the original underlying axis
7705 *        order).
7706 *     status
7707 *        Pointer to the inherited status variable.
7708 
7709 *  Notes:
7710 *     - This protected method is provided so that class
7711 *     implementations can distinguish the axes of Frames from one
7712 *     another (e.g. can distinguish a longitude axis as being
7713 *     different from a latitide axis) even after their order has been
7714 *     permuted and they have been combined with axes from other
7715 *     Frames.
7716 *     - The reference count of the primary Frame will be incremented
7717 *     by one to reflect the new pointer returned.
7718 */
7719 
7720 /* Local Variables: */
7721    AstFrame *fr;                 /* Pointer to current Frame */
7722    AstFrameSet *this;            /* Pointer to the FrameSet structure */
7723 
7724 /* Initialise the returned values. */
7725    *frame = NULL;
7726    *axis2 = 0;
7727 
7728 /* Check the global error status. */
7729    if ( !astOK ) return;
7730 
7731 /* Obtain a pointer to the FrameSet structure. */
7732    this = (AstFrameSet *) this_frame;
7733 
7734 /* Validate the axis index supplied. */
7735    (void) astValidateAxis( this, axis1, 1, "astPrimaryFrame" );
7736 
7737 /* Obtain a pointer to the FrameSet's current Frame and invoke its
7738    astPrimaryFrame method. Annul the Frame pointer afterwards. */
7739    fr = astGetFrame( this, AST__CURRENT );
7740    astPrimaryFrame( fr, axis1, frame, axis2 );
7741    fr = astAnnul( fr );
7742 
7743 /* If an error occurred, annul the returned object and clear the
7744    returned axis value. */
7745    if ( !astOK ) {
7746       *frame = astAnnul( *frame );
7747       *axis2 = 0;
7748    }
7749 }
7750 
Rate(AstMapping * this_mapping,double * at,int ax1,int ax2,int * status)7751 static double Rate( AstMapping *this_mapping, double *at, int ax1, int ax2, int *status ){
7752 /*
7753 *  Name:
7754 *     Rate
7755 
7756 *  Purpose:
7757 *     Calculate the rate of change of a Mapping output.
7758 
7759 *  Type:
7760 *     Private function.
7761 
7762 *  Synopsis:
7763 *     #include "frameset.h"
7764 *     result = Rate( AstMapping *this, double *at, int ax1, int ax2, int *status )
7765 
7766 *  Class Membership:
7767 *     FrameSet member function (over-rides the astRate method
7768 *     inherited from the Frame class).
7769 
7770 *     This function evaluates the rate of change of a specified output of
7771 *     the supplied Mapping with respect to a specified input, at a
7772 *     specified input position.
7773 *
7774 *     The result is estimated by interpolating the function using a
7775 *     fourth order polynomial in the neighbourhood of the specified
7776 *     position. The size of the neighbourhood used is chosen to minimise
7777 *     the RMS residual per unit length between the interpolating
7778 *     polynomial and the supplied Mapping function.
7779 
7780 *  Parameters:
7781 *     this
7782 *        Pointer to the Mapping to be applied.
7783 *     at
7784 *        The address of an array holding the axis values at the position
7785 *        at which the rate of change is to be evaluated. The number of
7786 *        elements in this array should equal the number of inputs to the
7787 *        Mapping.
7788 *     ax1
7789 *        The index of the Mapping output for which the rate of change is to
7790 *        be found (output numbering starts at 0 for the first output).
7791 *     ax2
7792 *        The index of the Mapping input which is to be varied in order to
7793 *        find the rate of change (input numbering starts at 0 for the first
7794 *        input).
7795 *     status
7796 *        Pointer to the inherited status variable.
7797 
7798 *  Returned Value:
7799 *     astRate()
7800 *        The rate of change of Mapping output "ax1" with respect to input
7801 *        "ax2", evaluated at "at", or AST__BAD if the value cannot be
7802 *        calculated.
7803 
7804 *  Notes:
7805 *     - A value of AST__BAD will be returned if this function is invoked
7806 *     with the global error status set, or if it should fail for any
7807 *     reason.
7808 *-
7809 */
7810 
7811 /* Local Variables: */
7812    AstFrameSet *this;            /* Pointer to the FrameSet structure */
7813    AstMapping *map;              /* Pointer to the base->current Mapping */
7814    double result;                /* Returned rate of change */
7815 
7816 /* Check the global error status. */
7817    if ( !astOK ) return AST__BAD;
7818 
7819 /* Obtain a pointer to the FrameSet structure. */
7820    this = (AstFrameSet *) this_mapping;
7821 
7822 /* Obtain the Mapping between the base and current Frames in the
7823    FrameSet (note this takes account of whether the FrameSet has been
7824    inverted). */
7825    map = astGetMapping( this, AST__BASE, AST__CURRENT );
7826 
7827 /* Invoke the astRate method on the Mapping. */
7828    result = astRate( map, at, ax1, ax2 );
7829 
7830 /* Annul the Mapping pointer. */
7831    map = astAnnul( map );
7832 
7833 /* Return a pointer to the output PointSet. */
7834    return result;
7835 }
7836 
RecordIntegrity(AstFrameSet * this,int * status)7837 static void RecordIntegrity( AstFrameSet *this, int *status ) {
7838 /*
7839 *+
7840 *  Name:
7841 *     RecordIntegrity
7842 
7843 *  Purpose:
7844 *     Record the current integrity state of a FrameSet.
7845 
7846 *  Type:
7847 *     Private function.
7848 
7849 *  Synopsis:
7850 *     #include "frameset.h"
7851 *     void RecordIntegrity( AstFrameSet *this, int *status )
7852 
7853 *  Class Membership:
7854 *     FrameSet member function.
7855 
7856 *  Description:
7857 *     This function makes a record of the current integrity state of a
7858 *     FrameSet by taking a copy of its current Frame (it stores a
7859 *     pointer to this copy in a static variable). If the current Frame
7860 *     is subsequently modified, the RestoreIntegrity function can then
7861 *     attempt to restore the FrameSet's integrity to this recorded
7862 *     state by appropriately remapping its current Frame.
7863 
7864 *  Parameters:
7865 *     this
7866 *        Pointer to the FrameSet.
7867 *-
7868 *     status
7869 *        Pointer to the inherited status variable.
7870 */
7871 
7872 /* Local Variables: */
7873    astDECLARE_GLOBALS            /* Declare the thread specific global data */
7874    AstFrame *current;            /* Pointer to current Frame */
7875 
7876 /* Get a pointer to the structure holding thread-specific global data. */
7877    astGET_GLOBALS(this);
7878 
7879 /* Initialise the record of the FrameSet's integrity. */
7880    integrity_frame = NULL;
7881    integrity_lost = 0;
7882 
7883 /* Check the global error status. */
7884    if ( !astOK ) return;
7885 
7886 /* Obtain a pointer to the FrameSet's current Frame. */
7887    current = astGetFrame( this, AST__CURRENT );
7888 
7889 /* Make a copy of this Frame, storing its pointer. */
7890    integrity_frame = astCopy( current );
7891 
7892 /* Annul the current Frame pointer. */
7893    current = astAnnul( current );
7894 }
7895 
RemapFrame(AstFrameSet * this,int iframe,AstMapping * map,int * status)7896 static void RemapFrame( AstFrameSet *this, int iframe, AstMapping *map, int *status ) {
7897 /*
7898 *++
7899 *  Name:
7900 c     astRemapFrame
7901 f     AST_REMAPFRAME
7902 
7903 *  Purpose:
7904 *     Modify a Frame's relationship to other Frames in a FrameSet.
7905 
7906 *  Type:
7907 *     Public virtual function.
7908 
7909 *  Synopsis:
7910 c     #include "frameset.h"
7911 c     void astRemapFrame( AstFrameSet *this, int iframe, AstMapping *map )
7912 f     CALL AST_REMAPFRAME( THIS, IFRAME, MAP, STATUS )
7913 
7914 *  Class Membership:
7915 *     FrameSet method.
7916 
7917 *  Description:
7918 c     This function modifies the relationship (i.e. Mapping) between a
7919 f     This routine modifies the relationship (i.e. Mapping) between a
7920 *     specified Frame in a FrameSet and the other Frames in that
7921 *     FrameSet.
7922 *
7923 *     Typically, this might be required if the FrameSet has been used
7924 *     to calibrate (say) an image, and that image is re-binned. The
7925 *     Frame describing the image will then have undergone a coordinate
7926 *     transformation, and this should be communicated to the associated
7927 c     FrameSet using this function.
7928 f     FrameSet using this routine.
7929 
7930 *  Parameters:
7931 c     this
7932 f     THIS = INTEGER (Given)
7933 *        Pointer to the FrameSet.
7934 c     iframe
7935 f     IFRAME = INTEGER (Given)
7936 *        The index within the FrameSet of the Frame to be modified.
7937 *        This value should lie in the range from 1 to the number of
7938 *        Frames in the FrameSet (as given by its Nframe attribute).
7939 c     map
7940 f     MAP = INTEGER (Given)
7941 *        Pointer to a Mapping whose forward transformation converts
7942 *        coordinate values from the original coordinate system
7943 *        described by the Frame to the new one, and whose inverse
7944 *        transformation converts in the opposite direction.
7945 f     STATUS = INTEGER (Given and Returned)
7946 f        The global status.
7947 
7948 *  Notes:
7949 *     - A value of AST__BASE or AST__CURRENT may be given for the
7950 c     "iframe" parameter to specify the base Frame or the current
7951 f     IFRAME argument to specify the base Frame or the current
7952 *     Frame respectively.
7953 *     - The relationship between the selected Frame and any other
7954 c     Frame within the FrameSet will be modified by this function,
7955 f     Frame within the FrameSet will be modified by this routine,
7956 *     but the relationship between all other Frames in the FrameSet
7957 *     remains unchanged.
7958 *     - The number of input coordinate values accepted by the Mapping
7959 *     (its Nin attribute) and the number of output coordinate values
7960 *     generated (its Nout attribute) must be equal and must match the
7961 *     number of axes in the Frame being modified.
7962 *     - If a simple change of axis order is required, then the
7963 c     astPermAxes function may provide a more straightforward method
7964 f     AST_PERMAXES routine may provide a more straightforward method
7965 *     of making the required changes to the FrameSet.
7966 c     - This function cannot be used to change the number of Frame
7967 f     - This routine cannot be used to change the number of Frame
7968 *     axes. To achieve this, a new Frame must be added to the FrameSet
7969 c     (astAddFrame) and the original one removed if necessary
7970 c     (astRemoveFrame).
7971 f     (AST_ADDFRAME) and the original one removed if necessary
7972 f     (AST_REMOVEFRAME).
7973 *     - Any variant Mappings associated with the remapped Frame (except
7974 *     for the current variant) will be lost as a consequence of calling this
7975 *     method (see attribute "Variant").
7976 *--
7977 */
7978 
7979 /* Local Variables: */
7980    AstFrame *fr;                 /* Pointer to Frame */
7981    int icur;                     /* Index of original current Frame */
7982    int naxes;                    /* Number of Frame axes */
7983    int nin;                      /* Number of Mapping input coordinates */
7984    int nout;                     /* Number of Mapping output coordinates */
7985    int varfrm;                   /* The index of the variants frame */
7986 
7987 /* Check the global error status. */
7988    if ( !astOK ) return;
7989 
7990 /* Validate and translate the Frame index supplied. */
7991    iframe = astValidateFrameIndex( this, iframe, "astRemapFrame" );
7992 
7993 /* Variant Mappings from a source node to a destination node are stored
7994    within the Frame object associated with the destination node. But
7995    remapping a Frame causes the Frame to be dissociated from its original
7996    node, and associated with a new node, leaving the original node
7997    without any Frame in which to store its variant mappings. So we are
7998    forced to remove the variant Mappings if the Frame is remapped. We do
7999    this by clearing the Variant attribute before the Frame is remapped.
8000    This will leave the current variant as the sole Mapping between the
8001    original source and destination nodes. However, if the Frame being
8002    remapped is just a mirror for another Frame, then we do not need to
8003    do this since the Frame being mirrored is not itself being remapped
8004    and so can retain its variant mappings. So we temporarily prevent the
8005    remapped Frame from acting as a mirror before we clear the Variant
8006    attribute. */
8007    icur = astGetCurrent( this );
8008    astSetCurrent( this, iframe );
8009 
8010    varfrm = this->varfrm[ iframe - 1 ];
8011    this->varfrm[ iframe - 1 ] = 0;
8012 
8013    astClearVariant( this );
8014 
8015    this->varfrm[ iframe - 1 ] = varfrm;
8016    astSetCurrent( this, icur );
8017 
8018 /* Obtain the number of input and output coordinates per point for the
8019    Mapping supplied. */
8020    nin = astGetNin( map );
8021    nout = astGetNout( map );
8022 
8023 /* Obtain a pointer to the specified Frame and determine how many axes
8024    it has. Annul the Frame pointer afterwards. */
8025    fr = astGetFrame( this, iframe );
8026    naxes = astGetNaxes( fr );
8027    fr = astAnnul( fr );
8028 
8029 /* Check that the number of input coordinates matches the number of
8030    Frame axes and report an error if necessary. */
8031    if ( astOK ) {
8032       if ( nin != naxes ) {
8033          astError( AST__NCPIN, "astRemapFrame(%s): Bad number of %s input "
8034                    "coordinate values (%d).", status, astGetClass( this ),
8035                    astGetClass( map ), nin );
8036          astError( AST__NCPIN, "The %s given should accept %d coordinate "
8037                    "value%s for each input point.", status, astGetClass( map ), naxes,
8038                    ( naxes == 1 ) ? "" : "s" );
8039 
8040 /* Similarly, check that the number of output coordinates matches the
8041    number of Frame axes. */
8042       } else if ( nout != naxes ) {
8043          astError( AST__NCPIN, "astRemapFrame(%s): Bad number of %s output "
8044                    "coordinate values (%d).", status, astGetClass( this ),
8045                    astGetClass( map ), nout );
8046          astError( AST__NCPIN, "The %s given should generate %d "
8047                    "coordinate value%s for each output point.", status,
8048                    astGetClass( map ), naxes, ( naxes == 1 ) ? "" : "s" );
8049       }
8050    }
8051 
8052 /* If there is more than one Frame present in the FrameSet, extend the
8053    FrameSet arrays to hold a new node. */
8054    if ( astOK && ( this->nframe > 1 ) ) {
8055       this->map = astGrow( this->map, this->nnode, sizeof( AstMapping * ) );
8056       this->link = astGrow( this->link, this->nnode, sizeof( int ) );
8057       this->invert = astGrow( this->invert, this->nnode, sizeof( int ) );
8058 
8059 /* Clone and store a pointer to the Mapping. */
8060       if ( astOK ) {
8061          this->map[ this->nnode - 1 ] = astClone( map );
8062 
8063 /* Add a new "link" element showing that the new node is derived from
8064    that of the old Frame and store the current value of the Invert
8065    attribute for the Mapping. */
8066          this->link[ this->nnode - 1 ] = this->node[ iframe - 1 ];
8067          this->invert[ this->nnode - 1 ] = astGetInvert( map );
8068 
8069 /* Increment the node count and associate the modified Frame with the
8070    new node. */
8071          if ( astOK ) {
8072             this->nnode++;
8073             this->node[ iframe - 1 ] = this->nnode - 1;
8074 
8075 /* Tidy the resulting set of nodes, because the node originally
8076    referenced by the Frame may no longer be needed. This also
8077    simplifies any compound Mapping which may result if this node is
8078    removed. */
8079             TidyNodes( this, status );
8080          }
8081       }
8082    }
8083 }
8084 
RemoveFrame(AstFrameSet * this,int iframe,int * status)8085 static void RemoveFrame( AstFrameSet *this, int iframe, int *status ) {
8086 /*
8087 *++
8088 *  Name:
8089 c     astRemoveFrame
8090 f     AST_REMOVEFRAME
8091 
8092 *  Purpose:
8093 *     Remove a Frame from a FrameSet.
8094 
8095 *  Type:
8096 *     Public virtual function.
8097 
8098 *  Synopsis:
8099 c     #include "frameset.h"
8100 c     void astRemoveFrame( AstFrameSet *this, int iframe )
8101 f     CALL AST_REMOVEFRAME( THIS, IFRAME, STATUS )
8102 
8103 *  Class Membership:
8104 *     FrameSet method.
8105 
8106 *  Description:
8107 c     This function removes a Frame from a FrameSet. All other Frames
8108 f     This routine removes a Frame from a FrameSet. All other Frames
8109 *     in the FrameSet have their indices re-numbered from one (if
8110 *     necessary), but are otherwise unchanged.
8111 
8112 *  Parameters:
8113 c     this
8114 f     THIS = INTEGER (Given)
8115 *        Pointer to the FrameSet.
8116 c     iframe
8117 f     IFRAME = INTEGER (Given)
8118 *        The index within the FrameSet of the Frame to be removed.
8119 *        This value should lie in the range from 1 to the number of
8120 *        Frames in the FrameSet (as given by its Nframe attribute).
8121 f     STATUS = INTEGER (Given and Returned)
8122 f        The global status.
8123 
8124 *  Notes:
8125 *     - Removing a Frame from a FrameSet does not affect the
8126 *     relationship between other Frames in the FrameSet, even if they
8127 *     originally depended on the Frame being removed.
8128 *     - The number of Frames in a FrameSet cannot be reduced to zero.
8129 *     An error will result if an attempt is made to remove the only
8130 *     remaining Frame.
8131 *     - A value of AST__BASE or AST__CURRENT may be given for the
8132 c     "iframe" parameter to specify the base Frame or the current
8133 f     IFRAME argument to specify the base Frame or the current
8134 *     Frame respectively.
8135 *     - If a FrameSet's base or current Frame is removed, the Base or
8136 *     Current attribute (respectively) of the FrameSet will have its
8137 *     value cleared, so that another Frame will then assume its role
8138 *     by default.
8139 *     - If any other Frame is removed, the base and current Frames
8140 *     will remain the same. To ensure this, the Base and/or Current
8141 *     attributes of the FrameSet will be changed, if necessary, to
8142 *     reflect any change in the indices of these Frames.
8143 *--
8144 */
8145 
8146 /* Local Variables: */
8147    int ifr;                      /* Loop counter for Frames */
8148    int ii;                       /* Base/current Frame index */
8149 
8150 /* Check the global error status. */
8151    if ( !astOK ) return;
8152 
8153 /* Validate and translate the Frame index supplied. */
8154    iframe = astValidateFrameIndex( this, iframe, "astRemoveFrame" );
8155    if ( astOK ) {
8156 
8157 /* Reject any attempt to remove the final Frame from the FrameSet. */
8158       if ( this->nframe == 1 ) {
8159          astError( AST__REMIN, "astRemoveFrame(%s): Invalid attempt to "
8160                    "remove the only Frame in a %s.", status, astGetClass( this ),
8161                    astGetClass( this ) );
8162 
8163 /* If OK, annul the pointer to the selected Frame. */
8164       } else {
8165          this->frame[ iframe - 1 ] = astAnnul( this->frame[ iframe - 1 ] );
8166 
8167 /* Ensure that the variant Mappings in the Frame being removed are not
8168    mirrored by any other Frames in the FrameSet. */
8169          RemoveMirrors( this, iframe, status );
8170 
8171 /* Any Frames that are mirroring variants in Frames higher than the
8172    removed Frame need to have their mirror frame indicies decremented. */
8173          for ( ifr = 1; ifr <= this->nframe; ifr++ ) {
8174             if( this->varfrm[ ifr - 1 ] > iframe ) this->varfrm[ ifr - 1 ]--;
8175          }
8176 
8177 /* Loop to move all subsequent Frame pointers down in the FrameSet's
8178    "frame" array to close the resulting gap. Also move the associated
8179    "node" and "varfrm" array contents in the same way. */
8180          for ( ifr = iframe; ifr < this->nframe; ifr++ ) {
8181             this->frame[ ifr - 1 ] = this->frame[ ifr ];
8182             this->node[ ifr - 1 ] = this->node[ ifr ];
8183             this->varfrm[ ifr - 1 ] = this->varfrm[ ifr ];
8184          }
8185          this->frame[ this->nframe - 1 ] = NULL;
8186          this->node[ this->nframe - 1 ] = -1;
8187          this->varfrm[ this->nframe - 1 ] = 0;
8188 
8189 /* Decrement the Frame count. */
8190          this->nframe--;
8191 
8192 /* Tidy the nodes in the FrameSet. */
8193          TidyNodes( this, status );
8194 
8195 /* If the Base attribute is set and the removed Frame was the base
8196    Frame, then clear the attribute value so that a new base Frame will
8197    be selected by default. */
8198          if ( astTestBase( this ) ) {
8199             ii = astGetBase( this );
8200             if ( iframe == ii ) {
8201                astClearBase( this );
8202 
8203 /* If the index of the removed Frame is smaller than the base Frame
8204    index, then decrement the Base attribute so that the same base
8205    Frame will be used in future. */
8206             } else if ( iframe < ii ) {
8207                astSetBase( this, ii - 1 );
8208             }
8209          }
8210 
8211 /* Repeat the above procedure for the current Frame. */
8212          if ( astTestCurrent( this ) ) {
8213             ii = astGetCurrent( this );
8214             if ( iframe == ii ) {
8215                astClearCurrent( this );
8216             } else if ( iframe < ii ) {
8217                astSetCurrent( this, ii - 1 );
8218             }
8219          }
8220       }
8221    }
8222 }
8223 
RemoveMirrors(AstFrameSet * this,int iframe,int * status)8224 static void RemoveMirrors( AstFrameSet *this, int iframe, int *status ) {
8225 /*
8226 *  Name:
8227 *     RemoveMirrors
8228 
8229 *  Purpose:
8230 *     Ensure no other Frames act as mirrors for a specified Frame.
8231 
8232 *  Type:
8233 *     Private function.
8234 
8235 *  Synopsis:
8236 *     #include "frameset.h"
8237 *     void RemoveMirrors( AstFrameSet *this, int iframe, int *status )
8238 
8239 *  Class Membership:
8240 *     Private function.
8241 
8242 *  Description:
8243 *     This function searchs the FrameSet for Frames that are currently
8244 *     acting as mirrors for the variant Mappings in the Frame with index
8245 *     "iframe", and disables mirroring in any found Frames. It should be
8246 *     used when "iframe" has its variant Mappings removed.
8247 
8248 *  Parameters:
8249 *     this
8250 *        Pointer to the FrameSet.
8251 *     iframe
8252 *        One-based index of a Frame that has had its variant Mappings
8253 *        removed.
8254 *     status
8255 *        Pointer to the inherited status variable.
8256 
8257 */
8258 
8259 /* Local Variables: */
8260    int *frmlist;
8261    int ifr;
8262    int nfrm;
8263 
8264 /* Check the global error status. */
8265    if ( !astOK ) return;
8266 
8267 /* Iniitalise a list to hold the indices of the FRames that mirror
8268    "iframe". */
8269    nfrm = 0;
8270    frmlist = NULL;
8271 
8272 /* Check each Frame in the FrameSet. */
8273    for( ifr = 1; ifr <= this->nframe; ifr++ ) {
8274 
8275 /* Get the index of the Frame that defines the variant Mappings to use
8276    with Frame "ifr". If this is "iframe", then add "ifr" to the list of
8277    Frames that need to be "de-mirrored". We cannot "de-mirror" the Frame
8278    immediately as doing so may break a chain of mirrors, resulting in the
8279    Frames higher up the chain no longer being associated with "iframe". */
8280       if( GetVarFrm( this, ifr, status ) == iframe ) {
8281          frmlist = astGrow( frmlist, nfrm + 1, sizeof( *frmlist ) );
8282          if( astOK ) frmlist[ nfrm++ ] = ifr;
8283       }
8284    }
8285 
8286 /* Loop round all the Frames found above that mirror "iframe". */
8287    for( ifr = 0; ifr < nfrm; ifr++ ) {
8288 
8289 /* Indicate that the Frame no longer mirrors any other Frame. */
8290       this->varfrm[ frmlist[ ifr ] - 1 ] = 0;
8291    }
8292 
8293 /* Free the list. */
8294    frmlist = astFree( frmlist );
8295 }
8296 
RemoveRegions(AstMapping * this_mapping,int * status)8297 static AstMapping *RemoveRegions( AstMapping *this_mapping, int *status ) {
8298 /*
8299 *  Name:
8300 *     RemoveRegions
8301 
8302 *  Purpose:
8303 *     Remove any Regions from a Mapping.
8304 
8305 *  Type:
8306 *     Private function.
8307 
8308 *  Synopsis:
8309 *     #include "frameset.h"
8310 *     AstMapping *RemoveRegions( AstMapping *this, int *status )
8311 
8312 *  Class Membership:
8313 *     FrameSet method (over-rides the astRemoveRegions method inherited
8314 *     from the Mapping class).
8315 
8316 *  Description:
8317 *     This function searches the supplied Mapping (which may be a
8318 *     compound Mapping such as a FrameSet) for any component Mappings
8319 *     that are instances of the AST Region class. It then creates a new
8320 *     Mapping from which all Regions have been removed. If a Region
8321 *     cannot simply be removed (for instance, if it is a component of a
8322 *     parallel FrameSet), then it is replaced with an equivalent UnitMap
8323 *     in the returned Mapping.
8324 *
8325 *     The implementation provided by the FrameSet class invokes the
8326 *     astRemoveRegions method on all the component Frames and Mappings,
8327 *     and joins the results together into a new FrameSet.
8328 
8329 *  Parameters:
8330 *     this
8331 *        Pointer to the original Region.
8332 *     status
8333 *        Pointer to the inherited status variable.
8334 
8335 *  Returned Value:
8336 *     A pointer to the modified mapping.
8337 
8338 *  Notes:
8339 *     - A NULL pointer value will be returned if this function is
8340 *     invoked with the AST error status set, or if it should fail for
8341 *     any reason.
8342 */
8343 
8344 /* Local Variables: */
8345    AstFrame **newfrms;           /* Array of new Frames */
8346    AstFrameSet *new;             /* Pointer to new FrameSet */
8347    AstFrameSet *this;            /* Pointer to FrameSet structure */
8348    AstMapping **newmaps;         /* Array of new Mappings */
8349    AstMapping *result;           /* Result pointer to return */
8350    int changed;                  /* Has any mapping been changed? */
8351    int i;                        /* Loop count */
8352    int nax;                      /* Number of Frame axes */
8353 
8354 /* Initialise. */
8355    result = NULL;
8356 
8357 /* Check the global error status. */
8358    if ( !astOK ) return result;
8359 
8360 /* Get a pointer to the FrameSet. */
8361    this = (AstFrameSet *) this_mapping;
8362 
8363 /* Allocate arrays to hold the modified Mapping and Frame pointers. */
8364    newmaps = astMalloc( sizeof( AstMapping *)*( this->nnode - 1 ) );
8365    newfrms = astMalloc( sizeof( AstFrame *)*( this->nframe ) );
8366    if( astOK ) {
8367 
8368 /* Invoke the astRemoveRegions method on all the component Mappings. */
8369       changed = 0;
8370       for( i = 0; i < this->nnode - 1; i++ ) {
8371          newmaps[ i ] = astRemoveRegions( this->map[ i ] );
8372 
8373 /* Note if any Mapping was changed. */
8374          if( newmaps[ i ] != this->map[ i ] ) {
8375             changed = 1;
8376 
8377 /* The implementation of the astRemoveRegions method provided by the
8378    Region class returns a Frame rather than a UnitMap. But we need
8379    Mappings here, not Frames. So if the new Mapping is a Frame, replace
8380    it with an equivalent UnitMap. */
8381             if( astIsAFrame( newmaps[ i ] ) ) {
8382                nax = astGetNin( newmaps[ i ] );
8383                (void) astAnnul( newmaps[ i ] );
8384                newmaps[ i ] = (AstMapping *) astUnitMap( nax, " ", status );
8385             }
8386          }
8387       }
8388 
8389 /* Invoke the astRemoveRegions method on all the component Frames. */
8390       for( i = 0; i < this->nframe; i++ ) {
8391          newfrms[ i ] = astRemoveRegions( this->frame[ i ] );
8392 
8393 /* Note if any Frame was changed. */
8394          if( newfrms[ i ] != this->frame[ i ] ) changed = 1;
8395       }
8396 
8397 /* If no component was modified, just return a clone of the supplied
8398    pointer. */
8399       if( ! changed ) {
8400          result = astClone( this );
8401 
8402 /* Otherwise, we need to create a new FrameSet to return. We take a deep
8403    copy of the supplied FrameSet and then modify the Mappings and Frames
8404    so that we retain any extra information in the supplied FrameSet. */
8405       } else {
8406          new = astCopy( this );
8407 
8408          for( i = 0; i < this->nnode - 1; i++ ) {
8409             (void) astAnnul( new->map[ i ] );
8410             new->map[ i ] = astClone( newmaps[ i ] );
8411          }
8412 
8413          for( i = 0; i < this->nframe; i++ ) {
8414             (void) astAnnul( new->frame[ i ] );
8415             new->frame[ i ] = astClone( newfrms[ i ] );
8416          }
8417 
8418          result = (AstMapping *) new;
8419       }
8420 
8421 /* Free resources. */
8422       for( i = 0; i < this->nnode - 1; i++ ) {
8423          newmaps[ i ] = astAnnul( newmaps[ i ] );
8424       }
8425 
8426       for( i = 0; i < this->nframe; i++ ) {
8427          newfrms[ i ] = astAnnul( newfrms[ i ] );
8428       }
8429 
8430    }
8431 
8432    newfrms = astFree( newfrms );
8433    newmaps = astFree( newmaps );
8434 
8435 /* Annul the returned Mapping if an error has occurred. */
8436    if( !astOK ) result = astAnnul( result );
8437 
8438 /* Return the result. */
8439    return result;
8440 }
8441 
ReportPoints(AstMapping * this_mapping,int forward,AstPointSet * in_points,AstPointSet * out_points,int * status)8442 static void ReportPoints( AstMapping *this_mapping, int forward,
8443                           AstPointSet *in_points, AstPointSet *out_points, int *status ) {
8444 /*
8445 *  Name:
8446 *     ReportPoints
8447 
8448 *  Purpose:
8449 *     Report the effect of transforming a set of points using a FrameSet.
8450 
8451 *  Type:
8452 *     Private function.
8453 
8454 *  Synopsis:
8455 *     #include "mapping.h"
8456 *     void ReportPoints( AstMapping *this, int forward,
8457 *                        AstPointSet *in_points, AstPointSet *out_points, int *status )
8458 
8459 *  Class Membership:
8460 *     FrameSet member function (over-rides the protected astReportPoints
8461 *     method inherited from the Frame class).
8462 
8463 *  Description:
8464 *     This function reports the coordinates of a set of points before
8465 *     and after being transformed by a FrameSet, by writing them to
8466 *     standard output.
8467 
8468 *  Parameters:
8469 *     this
8470 *        Pointer to the FrameSet.
8471 *     forward
8472 *        A non-zero value indicates that the FrameSet's forward
8473 *        coordinate transformation has been applied, while a zero
8474 *        value indicates the inverse transformation.
8475 *     in_points
8476 *        Pointer to a PointSet which is associated with the
8477 *        coordinates of a set of points before the FrameSet was
8478 *        applied.
8479 *     out_points
8480 *        Pointer to a PointSet which is associated with the
8481 *        coordinates of the same set of points after the FrameSet has
8482 *        been applied.
8483 *     status
8484 *        Pointer to the inherited status variable.
8485 */
8486 
8487 /* Local Variables: */
8488    AstFrame *base_frame;         /* Pointer to current Frame */
8489    AstFrame *current_frame;      /* Pointer to base Frame */
8490    AstFrameSet *this;            /* Pointer to the FrameSet structure */
8491    double **ptr_in;              /* Pointer to array of input data pointers */
8492    double **ptr_out;             /* Pointer to array of output data pointers */
8493    int coord;                    /* Loop counter for coordinates */
8494    int ncoord_in;                /* Number of input coordinates per point */
8495    int ncoord_out;               /* Number of output coordinates per point */
8496    int npoint;                   /* Number of points to report */
8497    int npoint_in;                /* Number of input points */
8498    int npoint_out;               /* Number of output points */
8499    int point;                    /* Loop counter for points */
8500 
8501 /* Check the global error status. */
8502    if ( !astOK ) return;
8503 
8504 /* Obtain a pointer to the FrameSet structure. */
8505    this = (AstFrameSet *) this_mapping;
8506 
8507 /* Obtain the numbers of points and coordinates associated with each
8508    PointSet. */
8509    npoint_in = astGetNpoint( in_points );
8510    npoint_out = astGetNpoint( out_points );
8511    ncoord_in = astGetNcoord( in_points );
8512    ncoord_out = astGetNcoord( out_points );
8513 
8514 /* Obtain the pointers that give access to the coordinate data
8515    associated with each PointSet. */
8516    ptr_in = astGetPoints( in_points );
8517    ptr_out = astGetPoints( out_points );
8518 
8519 /* In the event that both PointSets don't contain equal numbers of
8520    points (this shouldn't actually happen), simply use the minimum
8521    number. */
8522    npoint = ( npoint_in < npoint_out ) ? npoint_in : npoint_out;
8523 
8524 /* Obtain pointers to the FrameSet's base and current Frames. */
8525    base_frame = astGetFrame( this, AST__BASE );
8526    current_frame = astGetFrame( this, AST__CURRENT );
8527 
8528 /* Loop to report the effect of the transformation on each point in
8529    turn. */
8530    if ( astOK ) {
8531       for ( point = 0; point < npoint; point++ ) {
8532 
8533 /* Report the input coordinates (in parentheses and separated by
8534    commas). Format each value for display using the appropriate
8535    Frame's astFormat method. */
8536          printf( "(" );
8537          for ( coord = 0; coord < ncoord_in; coord++ ) {
8538             printf( "%s%s", coord ? ", " : "",
8539                     astFormat( forward ? base_frame : current_frame,
8540                                coord, ptr_in[ coord ][ point ] ) );
8541          }
8542 
8543 /* Similarly report the output coordinates, this time formatting
8544    values using the other Frame's astFormat method. */
8545          printf( ") --> (" );
8546          for ( coord = 0; coord < ncoord_out; coord++ ) {
8547             printf( "%s%s", coord ? ", " : "",
8548                     astFormat( forward ? current_frame : base_frame,
8549                                coord, ptr_out[ coord ][ point ] ) );
8550          }
8551          printf( ")\n" );
8552       }
8553    }
8554 
8555 /* Annul the Frame pointers. */
8556    base_frame = astAnnul( base_frame );
8557    current_frame = astAnnul( current_frame );
8558 }
8559 
Resolve(AstFrame * this_frame,const double point1[],const double point2[],const double point3[],double point4[],double * d1,double * d2,int * status)8560 static void Resolve( AstFrame *this_frame, const double point1[],
8561                      const double point2[], const double point3[],
8562                      double point4[], double *d1, double *d2, int *status ){
8563 /*
8564 *  Name:
8565 *     Resolve
8566 
8567 *  Purpose:
8568 *     Resolve a vector into two orthogonal components
8569 
8570 *  Type:
8571 *     Private function.
8572 
8573 *  Synopsis:
8574 *     #include "frameset.h"
8575 *     void Resolve( AstFrame *this, const double point1[],
8576 *                   const double point2[], const double point3[],
8577 *                   double point4[], double *d1, double *d2, int *status );
8578 
8579 *  Class Membership:
8580 *     FrameSet member function (over-rides the protected astResolve
8581 *     method inherited from the Frame class).
8582 
8583 *  Description:
8584 *     This function resolves a vector into two perpendicular components.
8585 *     The vector from point 1 to point 2 is used as the basis vector.
8586 *     The vector from point 1 to point 3 is resolved into components
8587 *     parallel and perpendicular to this basis vector. The lengths of the
8588 *     two components are returned, together with the position of closest
8589 *     aproach of the basis vector to point 3.
8590 
8591 *  Parameters:
8592 *     this
8593 *        Pointer to the Frame.
8594 *     point1
8595 *        An array of double, with one element for each Frame axis
8596 *        (Naxes attribute). This marks the start of the basis vector,
8597 *        and of the vector to be resolved.
8598 *     point2
8599 *        An array of double, with one element for each Frame axis
8600 *        (Naxes attribute). This marks the end of the basis vector.
8601 *     point3
8602 *        An array of double, with one element for each Frame axis
8603 *        (Naxes attribute). This marks the end of the vector to be
8604 *        resolved.
8605 *     point4
8606 *        An array of double, with one element for each Frame axis
8607 *        in which the coordinates of the point of closest approach of the
8608 *        basis vector to point 3 will be returned.
8609 *     d1
8610 *        The address of a location at which to return the distance from
8611 *        point 1 to point 4 (that is, the length of the component parallel
8612 *        to the basis vector). Positive values are in the same sense as
8613 *        movement from point 1 to point 2.
8614 *     d2
8615 *        The address of a location at which to return the distance from
8616 *        point 4 to point 3 (that is, the length of the component
8617 *        perpendicular to the basis vector). The value is always positive.
8618 *     status
8619 *        Pointer to the inherited status variable.
8620 
8621 *  Notes:
8622 *     - Each vector used in this function is the path of
8623 *     shortest distance between two points, as defined by the
8624 *     astDistance function.
8625 *     - This function will return "bad" coordinate values (AST__BAD)
8626 *     if any of the input coordinates has this value, or if the required
8627 *     output values are undefined.
8628 */
8629 
8630 /* Local Variables: */
8631    AstFrame *fr;                 /* Pointer to current Frame */
8632    AstFrameSet *this;            /* Pointer to the FrameSet structure */
8633 
8634 /* Check the global error status. */
8635    if ( !astOK ) return;
8636 
8637 /* Obtain a pointer to the FrameSet structure. */
8638    this = (AstFrameSet *) this_frame;
8639 
8640 /* Obtain a pointer to the FrameSet's current Frame and invoke this
8641    Frame's astResolve method. Annul the Frame pointer afterwards. */
8642    fr = astGetFrame( this, AST__CURRENT );
8643    astResolve( fr, point1, point2, point3, point4, d1, d2 );
8644    fr = astAnnul( fr );
8645 
8646 }
8647 
ResolvePoints(AstFrame * this_frame,const double point1[],const double point2[],AstPointSet * in,AstPointSet * out,int * status)8648 static AstPointSet *ResolvePoints( AstFrame *this_frame, const double point1[],
8649                                    const double point2[], AstPointSet *in,
8650                                    AstPointSet *out, int *status ) {
8651 /*
8652 *  Name:
8653 *     ResolvePoints
8654 
8655 *  Purpose:
8656 *     Resolve a set of vectors into orthogonal components
8657 
8658 *  Type:
8659 *     Private function.
8660 
8661 *  Synopsis:
8662 *     #include "frameset.h"
8663 *     AstPointSet *astResolvePoints( AstFrame *this, const double point1[],
8664 *                                    const double point2[], AstPointSet *in,
8665 *                                    AstPointSet *out )
8666 
8667 *  Class Membership:
8668 *     FrameSet member function (over-rides the astResolvePoints method
8669 *     inherited from the Frame class).
8670 
8671 *  Description:
8672 *     This function takes a Frame and a set of vectors encapsulated
8673 *     in a PointSet, and resolves each one into two orthogonal components,
8674 *     returning these two components in another PointSet.
8675 *
8676 *     This is exactly the same as the public astResolve method, except
8677 *     that this method allows many vectors to be processed in a single call,
8678 *     thus reducing the computational cost of overheads of many
8679 *     individual calls to astResolve.
8680 
8681 *  Parameters:
8682 *     this
8683 *        Pointer to the Frame.
8684 *     point1
8685 *        An array of double, with one element for each Frame axis
8686 *        (Naxes attribute). This marks the start of the basis vector,
8687 *        and of the vectors to be resolved.
8688 *     point2
8689 *        An array of double, with one element for each Frame axis
8690 *        (Naxes attribute). This marks the end of the basis vector.
8691 *     in
8692 *        Pointer to the PointSet holding the ends of the vectors to be
8693 *        resolved.
8694 *     out
8695 *        Pointer to a PointSet which will hold the length of the two
8696 *        resolved components. A NULL value may also be given, in which
8697 *        case a new PointSet will be created by this function.
8698 
8699 *  Returned Value:
8700 *     Pointer to the output (possibly new) PointSet. The first axis will
8701 *     hold the lengths of the vector components parallel to the basis vector.
8702 *     These values will be signed (positive values are in the same sense as
8703 *     movement from point 1 to point 2. The second axis will hold the lengths
8704 *     of the vector components perpendicular to the basis vector. These
8705 *     values will always be positive.
8706 
8707 *  Notes:
8708 *     - The number of coordinate values per point in the input
8709 *     PointSet must match the number of axes in the supplied Frame.
8710 *     - If an output PointSet is supplied, it must have space for
8711 *     sufficient number of points and 2 coordinate values per point.
8712 *     - A null pointer will be returned if this function is invoked
8713 *     with the global error status set, or if it should fail for any
8714 *     reason.
8715 */
8716 
8717 /* Local Variables: */
8718    AstPointSet *result;          /* Pointer to output PointSet */
8719    AstFrameSet *this;            /* Pointer to FrameSet structure */
8720    AstFrame *fr;                 /* Pointer to current Frame */
8721 
8722 /* Initialise. */
8723    result = NULL;
8724 
8725 /* Check the global error status. */
8726    if ( !astOK ) return result;
8727 
8728 /* Obtain a pointer to the FrameSet structure. */
8729    this = (AstFrameSet *) this_frame;
8730 
8731 /* Obtain a pointer to the FrameSet's current Frame and invoke this
8732    Frame's astResolvePoints method. Annul the Frame pointer afterwards. */
8733    fr = astGetFrame( this, AST__CURRENT );
8734    result = astResolvePoints( this, point1, point2, in, out );
8735    fr = astAnnul( fr );
8736 
8737 /* Return a pointer to the output PointSet. */
8738    return result;
8739 
8740 }
8741 
RestoreIntegrity(AstFrameSet * this,int * status)8742 static void RestoreIntegrity( AstFrameSet *this, int *status ) {
8743 /*
8744 *+
8745 *  Name:
8746 *     RestoreIntegrity
8747 
8748 *  Purpose:
8749 *     Restore a previous integrity state for a FrameSet.
8750 
8751 *  Type:
8752 *     Private function.
8753 
8754 *  Synopsis:
8755 *     #include "frameset.h"
8756 *     void RestoreIntegrity( AstFrameSet *this )
8757 
8758 *  Class Membership:
8759 *     FrameSet member function.
8760 
8761 *  Description:
8762 *     This function restores a FrameSet to a previous integrity state,
8763 *     as recorded (in static variables) by a previous invocation of
8764 *     the RecordIntegrity function. It does this by appropriately
8765 *     remapping the FrameSet's current Frame, if this appears
8766 *     necessary.
8767 
8768 *  Parameters:
8769 *     this
8770 *        Pointer to the FrameSet.
8771 
8772 *  Notes:
8773 *     - The previous record of the FrameSet's integrity state (as
8774 *     recorded by RecordIntegrity) is deleted by this function, even
8775 *     if it is invoked with the global error status set.
8776 *     - An error will result if the previous integrity state cannot be
8777 *     restored.
8778 *-
8779 */
8780 
8781 /* Local Variables: */
8782    astDECLARE_GLOBALS            /* Declare the thread specific global data */
8783    AstFrame *current;            /* Pointer to current Frame */
8784    AstFrameSet *cvt;             /* Pointer to conversion FrameSet */
8785    AstMapping *map;              /* Pointer to conversion Mapping */
8786    int flags;                    /* Flags associated with current frame */
8787 
8788 /* Get a pointer to the structure holding thread-specific global data. */
8789    astGET_GLOBALS(this);
8790 
8791 /* Check that a previous record of the FrameSet's integrity state has
8792    been made. Do not modify the FrameSet if it appears that the
8793    previous integrity state has not been lost (i.e. that the current
8794    Frame has not been modified), nor if there is only one Frame
8795    present. Check the global error status. */
8796    if ( integrity_frame && integrity_lost && ( astGetNframe( this ) > 1 ) &&
8797         astOK ) {
8798 
8799 /* Obtain a pointer to the current Frame. */
8800       current = astGetFrame( this, AST__CURRENT );
8801 
8802 /* Since we need to obtain a conversion between the recorded copy of
8803    this Frame and the current one, we must match their Domain
8804    attributes (otherwise conversion cannot be performed). Do this by
8805    changing the recorded copy as necessary. */
8806       if ( astTestDomain( current ) ) {
8807          astSetDomain( integrity_frame, astGetDomain( current ) );
8808       } else {
8809          astClearDomain( integrity_frame );
8810       }
8811 
8812 /* Temporarily set both Frames AST__INTFLAG flag to indicate that the
8813    following call to astConvert is part of the process of restoring a
8814    FrameSet's integrity. Some classes of Frame (e.g. DSBSpecFrames) may
8815    choose to return a different Mapping in this case. */
8816       astSetFrameFlags( integrity_frame, astGetFrameFlags( integrity_frame )
8817                                          | AST__INTFLAG );
8818       flags = astGetFrameFlags( current );
8819       astSetFrameFlags( current, flags | AST__INTFLAG );
8820 
8821 /* Obtain the required conversion FrameSet, restore the original frame
8822    flags and annul the current Frame pointer. */
8823       cvt = astConvert( integrity_frame, current, "" );
8824       astSetFrameFlags( current, flags );
8825       current = astAnnul( current );
8826 
8827 /* If no conversion could be found, then the FrameSet's integrity
8828    state cannot be restored, so report an error. */
8829       if ( !cvt ) {
8830          if( astOK ) {
8831             astError( AST__ILOST, "%s(%s): Cannot maintain %s integrity.", status,
8832                       integrity_method, astGetClass( this ),
8833                       astGetClass( this ) );
8834          }
8835 
8836 /* Otherwise, obtain a pointer to the conversion Mapping. */
8837       } else {
8838          map = astGetMapping( cvt, AST__BASE, AST__CURRENT );
8839 
8840 /* If the Mapping is not a UnitMap (i.e. a null Mapping), then use it
8841    to remap the FrameSet's current Frame. */
8842          if ( strcmp( astGetClass( map ), "UnitMap" ) ) {
8843             astRemapFrame( this, AST__CURRENT, map );
8844          }
8845 
8846 /* Annul the conversion Mapping and Frameset pointers. */
8847          map = astAnnul( map );
8848          cvt = astAnnul( cvt );
8849       }
8850    }
8851 
8852 /* Delete the recorded integrity information by annulling the original
8853    copy of the current Frame (thus deleting it) and resetting the
8854    associated modification flag. */
8855    if ( integrity_frame ) integrity_frame = astAnnul( integrity_frame );
8856    integrity_lost = 0;
8857 }
8858 
SetAttrib(AstObject * this_object,const char * setting,int * status)8859 static void SetAttrib( AstObject *this_object, const char *setting, int *status ) {
8860 /*
8861 *  Name:
8862 *     SetAttrib
8863 
8864 *  Purpose:
8865 *     Set an attribute value for a FrameSet.
8866 
8867 *  Type:
8868 *     Private function.
8869 
8870 *  Synopsis:
8871 *     #include "frameset.h"
8872 *     void SetAttrib( AstObject *this, const char *setting, int *status )
8873 
8874 *  Class Membership:
8875 *     FrameSet member function (extends the astSetAttrib method
8876 *     inherited from the Frame class).
8877 
8878 *  Description:
8879 *     This function assigns an attribute value for a FrameSet, the
8880 *     attribute and its value being specified by means of a string of
8881 *     the form:
8882 *
8883 *        "attribute= value "
8884 *
8885 *     Here, "attribute" specifies the attribute name and should be in
8886 *     lower case with no white space present. The value to the right
8887 *     of the "=" should be a suitable textual representation of the
8888 *     value to be assigned and this will be interpreted according to
8889 *     the attribute's data type.  White space surrounding the value is
8890 *     only significant for string attributes.
8891 
8892 *  Parameters:
8893 *     this
8894 *        Pointer to the FrameSet.
8895 *     setting
8896 *        Pointer to a null terminated string specifying the new
8897 *        attribute value.
8898 *     status
8899 *        Pointer to the inherited status variable.
8900 
8901 *  Attributes:
8902 *     The set of attribute values is not fixed and is determined by
8903 *     the current Frame. In addition, the FrameSet class defines the
8904 *     following attributes:
8905 *
8906 *        Base (integer)
8907 *        Current (integer)
8908 
8909 *  Notes:
8910 *     - This protected method is intended to be invoked by the Object
8911 *     astSet method and makes additional attributes accessible to it.
8912 *     - All attribute settings passed to this function are simply
8913 *     passed on to the corresponding method for the FrameSet's current
8914 *     Frame.
8915 */
8916 
8917 /* Local Variables: */
8918    astDECLARE_GLOBALS            /* Declare the thread specific global data */
8919    AstFrame *fr;                 /* Pointer to current Frame */
8920    AstFrameSet *this;            /* Pointer to the FrameSet structure */
8921    int base;                     /* Base attribute value */
8922    int base_off;                 /* Offset of Base value string */
8923    int current;                  /* Current attribute value */
8924    int current_off;              /* Offset of Current value string */
8925    int id;                       /* Offset of ID string */
8926    int invert;                   /* Invert attribute value */
8927    int len;                      /* Length of setting string */
8928    int nc;                       /* Number of characters read by astSscanf */
8929    int report;                   /* Report attribute value */
8930    int variant;                  /* Offset of Variant string */
8931 
8932 /* Check the global error status. */
8933    if ( !astOK ) return;
8934 
8935 /* Get a pointer to the structure holding thread-specific global data. */
8936    astGET_GLOBALS(this_object);
8937 
8938 /* Obtain a pointer to the FrameSet structure. */
8939    this = (AstFrameSet *) this_object;
8940 
8941 /* Obtain the length of the setting string. */
8942    len = strlen( setting );
8943 
8944 /* Test for each recognised attribute in turn, using "astSscanf" to parse the
8945    setting string and extract the attribute value (or an offset to it in the
8946    case of string values). In each case, use the value set in "nc" to check
8947    that the entire string was matched. Once a value has been obtained, use the
8948    appropriate method to set it. */
8949 
8950 /* We first handle attributes that apply to the FrameSet as a whole
8951    (rather than to the current Frame). */
8952 
8953 /* Base. */
8954 /* ----- */
8955 /* Read as an integer. */
8956    if ( nc = 0,
8957         ( 1 == astSscanf( setting, "base= %d %n", &base, &nc ) )
8958           && ( nc >= len ) ) {
8959       astSetBase( this, base );
8960 
8961 /* Also allow a string. */
8962    } else if ( nc = 0,
8963                ( 0 == astSscanf( setting, "base= %n%*s %n", &base_off, &nc ) )
8964                  && ( nc >= len ) ) {
8965 
8966 /* Check for "AST__CURRENT" or "Current". */
8967       if ( astChrMatch( "AST__CURRENT", setting + base_off ) ||
8968            astChrMatch( "Current", setting + base_off ) ) {
8969          astSetBase( this, AST__CURRENT );
8970 
8971 /* Check for "AST__BASE" or "Base" (possible, although not very
8972    useful). */
8973       } else if ( astChrMatch( "AST__BASE", setting + base_off ) ||
8974                   astChrMatch( "Base", setting + base_off ) ) {
8975 
8976 /* Report an error if the value wasn't recognised. */
8977       } else {
8978          astError( AST__ATTIN, "astSetAttrib(%s): Invalid index value for "
8979                    "Base Frame \"%s\".", status,
8980                    astGetClass( this ),  setting + base_off );
8981       }
8982 
8983 /* Current. */
8984 /* -------- */
8985 /* Since this determines the choice of current Frame, we must restore
8986    the integrity state of the FrameSet before changing this attribute
8987    and record the new integrity state afterwards. */
8988 
8989 /* Read as an integer. */
8990    } else if ( nc = 0,
8991                ( 1 == astSscanf( setting, "current= %d %n", &current, &nc ) )
8992                  && ( nc >= len ) ) {
8993       RestoreIntegrity( this, status );
8994       astSetCurrent( this, current );
8995       RecordIntegrity( this, status );
8996 
8997 /* Also allow a string. */
8998    } else if ( nc = 0,
8999                ( 0 == astSscanf( setting, "current= %n%*s %n",
9000                               &current_off, &nc ) )
9001                  && ( nc >= len ) ) {
9002 
9003 /* Check for "AST__BASE" or "Base". */
9004       if ( astChrMatch( "AST__BASE", setting + current_off ) ||
9005            astChrMatch( "Base", setting + current_off ) ) {
9006          RestoreIntegrity( this, status );
9007          astSetCurrent( this, AST__BASE );
9008          RecordIntegrity( this, status );
9009 
9010 /* Check for "AST__CURRENT" or "Current" (possible, although not very
9011    useful). */
9012       } else if ( astChrMatch( "AST__CURRENT", setting + current_off ) ||
9013                   astChrMatch( "Current", setting + current_off ) ) {
9014 
9015 /* Report an error if the value wasn't recognised. */
9016       } else {
9017          astError( AST__ATTIN, "astSetAttrib(%s): Invalid index value for "
9018                    "Current Frame \"%s\".", status,
9019                    astGetClass( this ),  setting + current_off );
9020       }
9021 
9022 /* ID. */
9023 /* --- */
9024    } else if ( nc = 0, ( 0 == astSscanf( setting, "id=%n%*[^\n]%n", &id, &nc ) )
9025                        && ( nc >= len ) ) {
9026       astSetID( this, setting + id );
9027 
9028 /* Ident. */
9029 /* ------ */
9030    } else if ( nc = 0, ( 0 == astSscanf( setting, "ident=%n%*[^\n]%n", &id, &nc ) )
9031                        && ( nc >= len ) ) {
9032       astSetIdent( this, setting + id );
9033 
9034 /* Invert. */
9035 /* ------- */
9036 /* Since this affects the choice of current Frame, we must restore the
9037    integrity state of the FrameSet before changing this attribute and
9038    record the new integrity state afterwards. */
9039    } else if ( nc = 0,
9040         ( 1 == astSscanf( setting, "invert= %d %n", &invert, &nc ) )
9041         && ( nc >= len ) ) {
9042       RestoreIntegrity( this, status );
9043       astSetInvert( this, invert );
9044       RecordIntegrity( this, status );
9045 
9046 /* Report. */
9047 /* ------- */
9048    } else if ( nc = 0,
9049         ( 1 == astSscanf( setting, "report= %d %n", &report, &nc ) )
9050         && ( nc >= len ) ) {
9051       astSetReport( this, report );
9052 
9053 /* Variant. */
9054 /* -------- */
9055    } else if ( nc = 0,
9056                ( 0 == astSscanf( setting, "variant=%n%*[^\n]%n", &variant, &nc ) )
9057                && ( nc >= len ) ) {
9058       astSetVariant( this, setting + variant );
9059 
9060 /* Define a macro to see if the setting string matches any of the
9061    read-only attributes of this class. */
9062 #define MATCH(attrib) \
9063         ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \
9064                   ( nc >= len ) )
9065 
9066 /* If the attribute was not recognised, use this macro to report an error
9067    if a read-only attribute has been specified. */
9068    } else if ( MATCH( "allvariants" ) ||
9069                MATCH( "class" ) ||
9070                MATCH( "nframe" ) ||
9071                MATCH( "nin" ) ||
9072                MATCH( "nobject" ) ||
9073                MATCH( "nout" ) ||
9074                MATCH( "refcount" ) ||
9075                MATCH( "tranforward" ) ||
9076                MATCH( "traninverse" ) ) {
9077       astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status,
9078                 setting, astGetClass( this ) );
9079       astError( AST__NOWRT, "This is a read-only attribute." , status);
9080 
9081 /* Pass unrecognised settings on to the FrameSet's current Frame for
9082    further interpretation. */
9083    } else {
9084 
9085 /* Force a copy to be made of the current Frame, if needed, to make it
9086    independent of other Frames within the FrameSet. */
9087       (void) ForceCopy( this, AST__CURRENT, status );
9088 
9089 /* Obtain a pointer to the current Frame and invoke its astSetAttrib
9090    method. Annul the Frame pointer afterwards. */
9091       fr = astGetFrame( this, AST__CURRENT );
9092       astSetAttrib( fr, setting );
9093       fr = astAnnul( fr );
9094 
9095 /* Note that the current Frame has been modified. */
9096       integrity_lost = 1;
9097    }
9098 
9099 /* Undefine macros local to this function. */
9100 #undef MATCH
9101 }
9102 
SetAxis(AstFrame * this_frame,int axis,AstAxis * newaxis,int * status)9103 static void SetAxis( AstFrame *this_frame, int axis, AstAxis *newaxis, int *status ) {
9104 /*
9105 *  Name:
9106 *     SetAxis
9107 
9108 *  Purpose:
9109 *     Set a new Axis for a FrameSet.
9110 
9111 *  Type:
9112 *     Private function.
9113 
9114 *  Synopsis:
9115 *     #include "frameset.h"
9116 *     void SetAxis( AstFrame *this, int axis, AstAxis *newaxis, int *status )
9117 
9118 *  Class Membership:
9119 *     FrameSet member function (over-rides the astSetAxis method
9120 *     inherited from the Frame class).
9121 
9122 *  Description:
9123 *     This function allows a new Axis object to be associated with one
9124 *     of the axes of the current Frame in a FrameSet, replacing the
9125 *     previous one. Each Axis object contains a description of the
9126 *     quantity represented along one of the Frame's axes, so this
9127 *     function allows this description to be exchanged for another
9128 *     one.
9129 
9130 *  Parameters:
9131 *     this
9132 *        Pointer to the FrameSet.
9133 *     axis
9134 *        The index (zero-based) of the axis whose associated Axis
9135 *        object is to be replaced.
9136 *     newaxis
9137 *        Pointer to the new Axis object.
9138 *     status
9139 *        Pointer to the inherited status variable.
9140 */
9141 
9142 /* Local Variables: */
9143    AstFrame *fr;                 /* Pointer to current Frame */
9144    AstFrameSet *this;            /* Pointer to the FrameSet structure */
9145 
9146 /* Check the global error status. */
9147    if ( !astOK ) return;
9148 
9149 /* Obtain a pointer to the FrameSet structure. */
9150    this = (AstFrameSet *) this_frame;
9151 
9152 /* Validate the axis index supplied. */
9153    (void) astValidateAxis( this, axis, 1, "astSetAxis" );
9154 
9155 /* Obtain a pointer to the FrameSet's current Frame and invoke this
9156    Frame's astSetAxis method to assign the new Axis object. Annul the
9157    Frame pointer afterwards. */
9158    fr = astGetFrame( this, AST__CURRENT );
9159    astSetAxis( fr, axis, newaxis );
9160    fr = astAnnul( fr );
9161 }
9162 
SetBase(AstFrameSet * this,int iframe,int * status)9163 static void SetBase( AstFrameSet *this, int iframe, int *status ) {
9164 /*
9165 *+
9166 *  Name:
9167 *     astSetBase
9168 
9169 *  Purpose:
9170 *     Set a value for the Base attribute of a FrameSet.
9171 
9172 *  Type:
9173 *     Protected virtual function.
9174 
9175 *  Synopsis:
9176 *     #include "frameset.h"
9177 *     void astSetBase( AstFrameSet *this, int iframe )
9178 
9179 *  Class Membership:
9180 *     FrameSet method.
9181 
9182 *  Description:
9183 *     This function sets a value for the Base attribute of a FrameSet. This
9184 *     value is an index that identifies the base Frame for the FrameSet.
9185 
9186 *  Parameters:
9187 *     this
9188 *        Pointer to the FrameSet.
9189 *     iframe
9190 *        Value to be set for the Base attribute.
9191 
9192 *  Notes:
9193 *     - A value of AST__BASE or AST__CURRENT may be given for the
9194 *     "iframe" parameter to identify the base Frame or the current
9195 *     Frame respectively.
9196 *-
9197 */
9198 
9199 /* Local Variables: */
9200    int invert;                    /* FrameSet is inverted? */
9201 
9202 /* Check the global error status. */
9203    if ( !astOK ) return;
9204 
9205 /* Validate and translate the Frame index supplied. */
9206    iframe = astValidateFrameIndex( this, iframe, "astSetBase" );
9207 
9208 /* Determine if the FrameSet has been inverted. */
9209    invert = astGetInvert( this );
9210 
9211 /* If it has not been inverted, set the base Frame index, otherwise
9212    set the current Frame index instead. */
9213    if ( astOK ) *( invert ? &this->current : &this->base ) = iframe;
9214 }
9215 
SetCurrent(AstFrameSet * this,int iframe,int * status)9216 static void SetCurrent( AstFrameSet *this, int iframe, int *status ) {
9217 /*
9218 *+
9219 *  Name:
9220 *     astSetCurrent
9221 
9222 *  Purpose:
9223 *     Set a value for the Current attribute of a FrameSet.
9224 
9225 *  Type:
9226 *     Protected function.
9227 
9228 *  Synopsis:
9229 *     #include "frameset.h"
9230 *     int astSetCurrent( AstFrameSet *this, int iframe )
9231 
9232 *  Class Membership:
9233 *     FrameSet method.
9234 
9235 *  Description:
9236 *     This function sets a value for the Current attribute of a
9237 *     FrameSet. This attribute is an index that identifies the current
9238 *     Frame for the FrameSet.
9239 
9240 *  Parameters:
9241 *     this
9242 *        Pointer to the FrameSet.
9243 *     iframe
9244 *        Value to be set for the Current attribute.
9245 
9246 *  Notes:
9247 *     - A value of AST__BASE or AST__CURRENT may be given for the
9248 *     "iframe" parameter to identify the base Frame or the current
9249 *     Frame respectively.
9250 *-
9251 */
9252 
9253 /* Local Variables: */
9254    int invert;                   /* FrameSet is inverted? */
9255 
9256 /* Check the global error status. */
9257    if ( !astOK ) return;
9258 
9259 /* Validate and translate the Frame index supplied. */
9260    iframe = astValidateFrameIndex( this, iframe, "astSetCurrent" );
9261 
9262 /* Determine if the FrameSet has been inverted. */
9263    invert = astGetInvert( this );
9264 
9265 /* If it has not been inverted, set the current frame index, otherwise
9266    set the base Frame index instead. */
9267    if ( astOK ) *( invert ? &this->base : &this->current ) = iframe;
9268 }
9269 
SetVariant(AstFrameSet * this,const char * variant,int * status)9270 static void SetVariant( AstFrameSet *this, const char *variant, int *status ) {
9271 /*
9272 *+
9273 *  Name:
9274 *     astSetVariant
9275 
9276 *  Purpose:
9277 *     Set a value for the Variant attribute of a FrameSet.
9278 
9279 *  Type:
9280 *     Protected virtual function.
9281 
9282 *  Synopsis:
9283 *     #include "frameset.h"
9284 *     void astSetVariant( AstFrameSet *this,  const char *variant )
9285 
9286 *  Class Membership:
9287 *     FrameSet method.
9288 
9289 *  Description:
9290 *     This function sets a value for the Variant attribute of a FrameSet.
9291 
9292 *  Parameters:
9293 *     this
9294 *        Pointer to the FrameSet.
9295 *     variant
9296 *        Value to be set for the Variant attribute.
9297 
9298 *  Notes:
9299 *     - An error will be reported if the supplied variant name cannot be
9300 *     found in the Variants FrameSet associated with the current Frame.
9301 
9302 *-
9303 */
9304 
9305 /* Local Variables: */
9306    AstCmpMap *map6;
9307    AstCmpMap *map5;
9308    AstCmpMap *map4;
9309    AstFrame *frm;
9310    AstFrame *vfrm;
9311    AstFrameSet *tfs;
9312    AstFrameSet *vfs;
9313    AstMapping *map0;
9314    AstMapping *map2;
9315    AstMapping *map3;
9316    AstMapping *map1;
9317    char *myvar;
9318    const char *dom;
9319    int icur;
9320    int ifrm;
9321    int inode;
9322    int inv0;
9323    int inv;
9324    int nfrm;
9325 
9326 /* Check the global error status. */
9327    if ( !astOK ) return;
9328 
9329 /* Get a copy of the supplied string and clean it. */
9330    myvar = astStore( NULL, variant, strlen( variant ) + 1 );
9331    astRemoveLeadingBlanks( myvar );
9332    astChrCase( NULL, myvar, 1, 0 );
9333    if( astOK ) {
9334       myvar[ astChrLen( myvar ) ] = 0;
9335 
9336 /* Get the one-based index of the Frame that defines the available
9337    variant Mappings. */
9338       icur = GetVarFrm( this, astGetCurrent( this ), status );
9339 
9340 /* Get the variants FrameSet from the Frame selected above. */
9341       frm = astGetFrame( this, icur );
9342       vfs = astGetFrameVariants( frm );
9343 
9344 /* If there is no variants FrameSet in the Frame, the only allowed value
9345    for "Variant" is the Domain name of the current Frame. */
9346       if( ! vfs ) {
9347          dom = astGetDomain( this );
9348          if( astOK && strcmp( myvar, dom ) ) {
9349             astError( AST__ATTIN, "astSetVariant(%s): Unknown Frame "
9350                       "variant '%s' requested.", status, astGetClass( this ),
9351                       myvar );
9352          }
9353 
9354 /* If there is a variants FrameSet in the Frame... */
9355       } else {
9356 
9357 /* Find the index of the Frame in the Variants FrameSet that has a Domain
9358    equal to myvar. */
9359          nfrm = astGetNframe( vfs );
9360          for( ifrm = 0; ifrm < nfrm; ifrm++ ) {
9361             vfrm = astGetFrame( vfs, ifrm + 1 );
9362             dom = astGetDomain( vfrm );
9363             vfrm = astAnnul( vfrm );
9364             if( !astOK || !strcmp( myvar, dom ) ) break;
9365          }
9366 
9367 /* Report an error if no such Frame found. */
9368          if( ifrm == nfrm && astOK ) {
9369             astError( AST__ATTIN, "astSetVariant(%s): Unknown Frame "
9370                       "variant '%s' requested - available variants are "
9371                       "'%s'.", status, astGetClass(this), myvar,
9372                       astGetAllVariants(this) );
9373 
9374 /* Otherwise, get a Mapping from the current Frame in "this" to the
9375    currently selected Variant Frame. We cannot assume that they are the
9376    same as attributes of the current Frame (e.g. System) may have been
9377    changed since the variant was added. If the required Frame is already
9378    the current Frame, there is nothing more to do since the required
9379    variant is already selected. */
9380          } else if( ifrm + 1 != astGetCurrent( vfs ) ){
9381             vfrm = astGetFrame( vfs, AST__CURRENT );
9382             dom = astGetDomain( frm );
9383             if( dom ) dom = astStore( NULL, dom, strlen( dom ) + 1 );
9384             astSetDomain( frm, astGetDomain( vfrm ) );
9385             tfs = astConvert( frm, vfrm, "" );
9386             astSetDomain( frm, dom );
9387             if( tfs ) {
9388                map1 = astGetMapping( tfs, AST__BASE, AST__CURRENT );
9389                tfs = astAnnul( tfs );
9390                vfrm = astAnnul( vfrm );
9391 
9392 /* Get the Mapping from the original Variant Frame to the requested variant
9393    Frame. */
9394                map2 = astGetMapping( vfs, AST__CURRENT, ifrm + 1 );
9395 
9396 /* Get a Mapping from the new variant Frame to the current Frame in "this". */
9397                vfrm = astGetFrame( vfs, ifrm + 1 );
9398                astSetDomain( frm, astGetDomain( vfrm ) );
9399                tfs = astConvert( vfrm, frm, "" );
9400                astSetDomain( frm, dom );
9401                if( tfs ) {
9402                   map3 = astGetMapping( tfs, AST__BASE, AST__CURRENT );
9403                   tfs = astAnnul( tfs );
9404 
9405 /* Concatentate the three Mappings, to get the Mapping from the old
9406    variant Frame to the new variant Frame. */
9407                   map4 = astCmpMap( map1, map2, 1, " ", status );
9408                   map5 = astCmpMap( map4, map3, 1, " ", status );
9409 
9410 /* Now we modify the Mapping in the FrameSet. First get the index of the node
9411    with which the Frame is associated. */
9412                   inode = this->node[ icur - 1 ];
9413 
9414 /* Get the Mapping that generates the node values, and its Invert flag. */
9415                   map0 = this->map[ inode - 1 ];
9416                   inv0 = this->invert[ inode - 1 ];
9417 
9418 /* Temporarily reset the invert flag in the Mapping to account for any
9419    changes made to the Mapping via other pointers. */
9420                   inv = astGetInvert( map0 );
9421                   astSetInvert( map0, inv0 );
9422 
9423 /* Concatentate with "map5" to get the Mapping form the the parent node
9424    to the new variant of the current node. */
9425                   map6 = astCmpMap( map0, map5, 1, " ", status );
9426 
9427 /* Simplify it and use it to replace the Mapping in the FrameSet structure. */
9428                   this->map[ inode - 1 ] = astSimplify( map6 );
9429                   this->invert[ inode - 1 ] = astGetInvert( this->map[ inode - 1 ] );
9430 
9431 /* Re-instate the original Invert flag and free the old Mapping pointer. */
9432                   astSetInvert( map0, inv );
9433                   map0 = astAnnul( map0 );
9434 
9435 /* Make the variant Frame the current Frame within the Variants FrameSet. */
9436                   astSetCurrent( vfs, ifrm + 1 );
9437 
9438 /* Free resources. */
9439                   map6 = astAnnul( map6 );
9440                   map5 = astAnnul( map5 );
9441                   map4 = astAnnul( map4 );
9442                   map3 = astAnnul( map3 );
9443 
9444 /* Report an error if a Mapping cannot be found from the new variant Frame
9445    to the current Frame in "this". */
9446                } else if( astOK ) {
9447                   astError( AST__INTER, "astSetVariant(%s): Cannot convert "
9448                             "from a %s with Domain '%s' to a %s with Domain "
9449                             "'%s' (internal programming error).", status,
9450                             astGetClass( this ), astGetClass( vfrm ),
9451                             astGetDomain( vfrm ), astGetClass( frm ),
9452                             astGetDomain( frm ) );
9453                }
9454 
9455 /* Free resources. */
9456                map2 = astAnnul( map2 );
9457                map1 = astAnnul( map1 );
9458 
9459 /* Report an error if a Mapping cannot be found from the current Frame in
9460    "this" to the current Variant Frame. */
9461             } else if( astOK ) {
9462                astError( AST__INTER, "astSetVariant(%s): Cannot convert "
9463                          "from a %s with Domain '%s' to a %s with Domain "
9464                          "'%s' (internal programming error).", status,
9465                          astGetClass( this ), astGetClass( frm ),
9466                          astGetDomain( frm ), astGetClass( vfrm ),
9467                          astGetDomain( vfrm ) );
9468             }
9469 
9470 /* Free resources. */
9471             vfrm = astAnnul( vfrm );
9472             dom = astFree( (void *) dom );
9473          }
9474 
9475 /* Annul the pointer to the Variants FrameSet. */
9476          vfs = astAnnul( vfs );
9477       }
9478 
9479 /* Annul the pointer to the current Frame in "this". */
9480       frm = astAnnul( frm );
9481    }
9482 
9483 /* Free the memory holding the cleaned variant name. */
9484    myvar = astFree( myvar );
9485 }
9486 
Simplify(AstMapping * this_mapping,int * status)9487 static AstMapping *Simplify( AstMapping *this_mapping, int *status ) {
9488 /*
9489 *  Name:
9490 *     Simplify
9491 
9492 *  Purpose:
9493 *     Simplify the Mappings in a FrameSet.
9494 
9495 *  Type:
9496 *     Private function.
9497 
9498 *  Synopsis:
9499 *     #include "frameset.h"
9500 *     AstMapping *Simplify( AstMapping *this, int *status )
9501 
9502 *  Class Membership:
9503 *     FrameSet method (over-rides the astSimplify method inherited
9504 *     from the Frame class).
9505 
9506 *  Description:
9507 *     This function simplifies the Mappings in a FrameSet to eliminate
9508 *     redundant computational steps, or to merge separate steps which
9509 *     can be performed more efficiently in a single operation.
9510 
9511 *  Parameters:
9512 *     this
9513 *        Pointer to the original FrameSet.
9514 *     status
9515 *        Pointer to the inherited status variable.
9516 
9517 *  Returned Value:
9518 *     A new pointer to the (possibly simplified) FrameSet. If
9519 *     simplification was not possible, this will be a cloned pointer
9520 *     to the original FrameSet.
9521 
9522 *  Notes:
9523 *     - A NULL pointer value will be returned if this function is
9524 *     invoked with the AST error status set, or if it should fail for
9525 *     any reason.
9526 */
9527 
9528 /* Local Variables: */
9529    AstFrameSet *new;             /* Pointer to new (simpler?) FrameSet */
9530    AstFrameSet *this;            /* Pointer to original FrameSet structure */
9531    AstMapping *map;              /* Pointer to Mapping */
9532    AstMapping *result;           /* Result pointer to return */
9533    AstMapping *tmp;              /* Temporary Mapping pointer */
9534    int inode;                    /* Loop counter for FrameSet nodes */
9535    int inv;                      /* Mapping Invert attribute value */
9536    int invert;                   /* Invert flag value */
9537    int set;                      /* Invert attribute set? */
9538    int simpler;                  /* Simplification achieved? */
9539 
9540 /* Initialise. */
9541    result = NULL;
9542 
9543 /* Check the global error status. */
9544    if ( !astOK ) return result;
9545 
9546 /* Obtain a pointer to the FrameSet structure. */
9547    this = (AstFrameSet *) this_mapping;
9548 
9549 /* Make a copy of the FrameSet, since we may alter it (this is a deep
9550    copy, which is a minor limitation of the current implementation). */
9551    new = astCopy( this );
9552 
9553 /* Loop to examine each of the Mappings between the Frames in the
9554    copy. */
9555    simpler = 0;
9556    for ( inode = 1; astOK && ( inode < new->nnode ); inode++ ) {
9557 
9558 /* Obtain the Mapping pointer and associated invert flag. */
9559       map = new->map[ inode - 1 ];
9560       invert = new->invert[ inode - 1 ];
9561 
9562 /* Determine if the Mapping's Invert attribute is set, and obtain its
9563    value. */
9564       set = astTestInvert( map );
9565       inv = astGetInvert( map );
9566 
9567 /* If necessary, set the required value for the Invert attribute. */
9568       if ( inv != invert ) astSetInvert( map, invert );
9569 
9570 /* Simplify the Mapping. */
9571       tmp = astSimplify( map );
9572 
9573 /* If necessary, restore the original state of the Mapping's Invert
9574    attribute. */
9575       if ( inv != invert ) {
9576          if ( set ) {
9577             astSetInvert( map, inv );
9578          } else {
9579             astClearInvert( map );
9580          }
9581       }
9582 
9583 /* Test if simplification was performed. */
9584       if ( astOK ) {
9585          if ( tmp != map ) {
9586 
9587 /* If so, annul the original Mapping pointer and substitute the new
9588    one. Also set a new invert flag to accompany it. */
9589             (void) astAnnul( new->map[ inode - 1 ] );
9590             new->map[ inode - 1 ] = astClone( tmp );
9591             new->invert[ inode - 1 ] = astGetInvert( tmp );
9592 
9593 /* Note if any Mapping within the FrameSet is simplified. */
9594             simpler = 1;
9595          }
9596       }
9597 
9598 /* Annul the pointer to the simplified Mapping. */
9599       tmp = astAnnul( tmp );
9600    }
9601 
9602 /* If simplification was possible, clone a pointer to the new
9603    FrameSet. Otherwise clone a pointer to the original one. */
9604    if ( astOK ) result = astClone( simpler ? new : this );
9605 
9606 /* Annul the new FrameSet pointer. */
9607    new = astAnnul( new );
9608 
9609 /* If an error occurred, annul the returned pointer. */
9610    if ( !astOK ) result = astAnnul( result );
9611 
9612 /* Return the result. */
9613    return result;
9614 }
9615 
Span(AstFrameSet * this,AstFrame ** frames,int inode1,int inode2,int avoid,AstMapping ** map,int * forward,int * status)9616 static int Span( AstFrameSet *this, AstFrame **frames, int inode1, int inode2,
9617                  int avoid, AstMapping **map, int *forward, int *status ) {
9618 /*
9619 *  Name:
9620 *     Span
9621 
9622 *  Purpose:
9623 *     Find a path between two nodes in a FrameSet.
9624 
9625 *  Type:
9626 *     Private function.
9627 
9628 *  Synopsis:
9629 *     #include "frameset.h"
9630 *     int Span( AstFrameSet *this, AstFrame **frames, int inode1, int inode2,
9631 *               int avoid, AstMapping **map, int *forward, int *status )
9632 
9633 *  Class Membership:
9634 *     FrameSet member function.
9635 
9636 *  Description:
9637 *     This function searches a FrameSet to identify a path between two
9638 *     specified nodes. It returns an array of pointers to each Mapping
9639 *     in the path, along with direction information, so that an
9640 *     overall Mapping between the two nodes can be constructed.
9641 
9642 *  Parameters:
9643 *     this
9644 *        Pointer to the FrameSet.
9645 *     frames
9646 *        Pointer to an array of Frame pointers, indexed by node index.
9647 *        Nodes which have no associated Frame will have a NULL pointer
9648 *        stored in this array.
9649 *     inode1
9650 *        Zero based index of the starting node.
9651 *     inode2
9652 *        Zero based index of the ending node.
9653 *     avoid
9654 *        Zero based index which identifies a node which is to be
9655 *        avoided (i.e. the initial step in the path should not be via
9656 *        this node). This value is required because the function
9657 *        invokes itself recursively; it provides a mechanism to
9658 *        prevent searches proceeding back down paths that have already
9659 *        been searched. External callers should provide a value of -1,
9660 *        which indicates that all possible paths should initially be
9661 *        explored.
9662 *     map
9663 *        Pointer to the start of an array that will be filled with a
9664 *        series of pointers to Mappings which must be applied in turn
9665 *        in order to transform between the two Frames. External
9666 *        callers should ensure that this array contains at least as many
9667 *        elements as there are Mappings and Frames in the FrameSet (one less
9668 *        than the number of nodes plus the number of Frames).
9669 *
9670 *        Note that the pointers are simply copies of addresses from
9671 *        the FrameSet's "map" array. They are not cloned, so should
9672 *        not be annulled by the caller.
9673 *     forward
9674 *        Pointer to the start of an array of int that will be filled
9675 *        with boolean flags (0 or 1) to indicate whether the forward
9676 *        (as opposed to the inverse) transformation should be used for
9677 *        each Mapping returned in order to effect the transformation
9678 *        between the starting and ending nodes. This array should be the
9679 *        same size as the "map" array.
9680 *     status
9681 *        Pointer to the inherited status variable.
9682 
9683 *  Returned Value:
9684 *     The function returns one more than the number of Mappings
9685 *     required to perform the transformation, or zero if it was not
9686 *     possible to find a path between the two nodes.
9687 
9688 *  Notes:
9689 *     - If a node has an associated Frame, the Frame usually represents a
9690 *     UnitMap and so can be ignored. The exception is if the Frame is
9691 *     actually a Region (or a CmpFrame containing a Region), in which case
9692 *     it represents a Mapping which returns bad values if the input position
9693 *     is outside the region. This form of Mapping should not be ignored, and
9694 *     so the returned list of Mappings includes the effect of any Frames
9695 *     along the path which are not equivalent to a UnitMap. This
9696 *     equivalence is determined by invoking the astSimplify method on the
9697 *     Frame.
9698 *     - A value of zero will be returned if this function is invoked
9699 *     with the global status set, or if it should fail for any reason.
9700 *     - On the assumption that the FrameSet has been consistently
9701 *     constructed, there should be exactly one path between any pair
9702 *     of its nodes.  It should not, therefore, ever fail to find a
9703 *     path except when invoked recursively to explore a subset of the
9704 *     FrameSet's nodes (this should not be visible to an external
9705 *     caller).  Failure to find a path does not in itself result in an
9706 *     error condition.
9707 */
9708 
9709 /* Local Variables: */
9710    AstFrame *frame;          /* Pointer to Frame associated with inode1 */
9711    int fwd;                  /* Forward Mapping identified? */
9712    int inode;                /* Loop counter for nodes */
9713    int inv;                  /* Inverse Mapping identified? */
9714    int invert;               /* Original Mapping Invert value */
9715    int nextra;               /* No. of extra Mappings to add to path */
9716    int result;               /* Count of mappings (to be returned) */
9717 
9718 /* Check the global error status. */
9719    if ( !astOK ) return 0;
9720 
9721 /* See if the two nodes are the same. */
9722    result = ( inode1 == inode2 );
9723 
9724 /* If so, we need to consider the Mapping represented by any Frame
9725    associated with the node. Most classes of Frames are equivalent to a
9726    UnitMap and so can be ignored. But some (e.g. the Region class) are not
9727    equivalent to a UnitMap and so needs to be included in the returned
9728    Mapping list. */
9729    if( result ) {
9730       result = 1;
9731 
9732 /* If inode1 is associated with a Frame, which is not equivalent to a
9733    UnitMap, add the Frame as the first Mapping into the returned list. The
9734    "forward" value is irrelevant since the forward and inverse transformations
9735    of Frames are the same. */
9736       frame = frames[ inode1 ];
9737       if( frame ) {
9738          if( !astIsUnitFrame( frame ) ) {
9739             result++;
9740             *map = (AstMapping *) frame;
9741             *forward = 1;
9742          }
9743       }
9744 
9745 /* If the nodes are different, we now attempt to find the next step in
9746    the path between them. Loop through all available nodes looking for
9747    the next one to transform to (i.e. one that is directly related by
9748    a Mapping to our starting node). */
9749    } else {
9750       for ( inode = 0; inode < this->nnode; inode++ ) {
9751 
9752 /* Do not consider node "avoid". This prevents us re-tracing our steps
9753    backwards when this function is invoked recursively. */
9754          if ( inode != avoid ) {
9755 
9756 /* Test if inode is derived from inode1 (if so, the Mapping associated
9757    with inode will convert from inode1 to inode when applied in the
9758    forward direction). */
9759             fwd = ( inode > 0 ) && ( this->link[ inode - 1 ] == inode1 );
9760 
9761 /* Test if inode1 is derived from inode (if so, the Mapping associated
9762    with inode1 will convert from inode1 to inode when applied in the
9763    inverse direction). */
9764             inv = ( inode1 > 0 ) && ( this->link[ inode1 - 1 ] == inode );
9765 
9766 /* If the nodes are directly related, we try to find a path from inode to
9767    inode2 without going back through inode1. */
9768             if ( fwd || inv ) {
9769 
9770 /* If node1 is associated with a Frame, we need to include the Frame
9771    as a Mapping in the returned list unless the Frame is equivalent to a
9772    UnitMap. Note the number of slots to be reserved for node1 when we call
9773    Span recursively below. */
9774                nextra = 1;
9775                frame = frames[ inode1 ];
9776                if( frame && !astIsUnitFrame( frame ) ) nextra = 2;
9777 
9778 /* Invoke this function recursively to try and find a path from inode
9779    to inode2 without going back through inode1. If this is possible, a
9780    non-zero result will be returned. Store the returned Mappings and
9781    direction information in the arrays supplied, but leave extra space to
9782    insert information about the Mapping between nodes inode1 and inode. */
9783                result = Span( this, frames, inode, inode2, inode1,
9784                               map + nextra, forward + nextra, status );
9785 
9786 /* If a path was found, increment the Mapping count to account for the
9787    one that transforms between nodes inode1 and inode and insert
9788    information for this Mapping into the output arrays. */
9789                if ( result ) {
9790                   result++;
9791                   nextra--;
9792                   map[ nextra ] = this->map[ ( fwd ? inode : inode1 ) - 1 ];
9793                   forward[ nextra ] = fwd;
9794 
9795 /* Obtain the original value of the Invert attribute for the Mapping
9796    between nodes inode1 and inode (recorded when the Mapping was first
9797    added to the FrameSet). Test if this value has now changed. If so,
9798    some external code has inverted the Mapping via another pointer, so
9799    invert the returned direction information to compensate for
9800    this. */
9801                   invert = this->invert[ ( fwd ? inode : inode1 ) - 1 ];
9802                   if ( invert != astGetInvert( map[ nextra ] ) ) {
9803                      forward[ nextra ] = !forward[ nextra ];
9804                   }
9805 
9806 /* If inode1 is associated with a non-unit Frame Mapping, add the Frame
9807    Mapping in as the first Mapping in the returned list. The "forward" value
9808    is irrelevant since the forward and inverse transformations of Frames
9809    are the same. */
9810                   if( nextra ) {
9811                      result++;
9812                      *map = (AstMapping *) frame;
9813                      *forward = 1;
9814                   }
9815 
9816 /* Quit searching once a path has been found. */
9817                   break;
9818 	       }
9819 	    }
9820          }
9821       }
9822    }
9823 
9824 /* Return the result, which is one more than the number of mappings
9825    found (i.e. steps in the path), or zero if no path was found (this
9826    should only occur when invoked recursively to explore an
9827    unsuccessful sub-path). */
9828    return result;
9829 }
9830 
SubFrame(AstFrame * this_frame,AstFrame * template,int result_naxes,const int * target_axes,const int * template_axes,AstMapping ** map,AstFrame ** result,int * status)9831 static int SubFrame( AstFrame *this_frame, AstFrame *template,
9832                      int result_naxes,
9833                      const int *target_axes, const int *template_axes,
9834                      AstMapping **map, AstFrame **result, int *status ) {
9835 /*
9836 *  Name:
9837 *     SubFrame
9838 
9839 *  Purpose:
9840 *     Select axes from a FrameSet and convert to the new coordinate system.
9841 
9842 *  Type:
9843 *     Private function.
9844 
9845 *  Synopsis:
9846 *     #include "frameset.h"
9847 *     int SubFrame( AstFrame *target, AstFrame *template, int result_naxes,
9848 *                   const int *target_axes, const int *template_axes,
9849 *                   AstMapping **map, AstFrame **result, int *status )
9850 
9851 *  Class Membership:
9852 *     FrameSet member function (over-rides the protected astSubFrame
9853 *     method inherited from the Frame class).
9854 
9855 *  Description:
9856 *     This function selects a requested sub-set (or super-set) of the
9857 *     axes from the current Frame of a "target" FrameSet and creates a
9858 *     new Frame with copies of the selected axes assembled in the
9859 *     requested order. It then optionally overlays the attributes of a
9860 *     "template" Frame on to the result. It returns both the resulting
9861 *     Frame and a Mapping that describes how to convert between the
9862 *     coordinate systems described by the current Frame of the target
9863 *     FrameSet and the result Frame. If necessary, this Mapping takes
9864 *     account of any differences in the Frames' attributes due to the
9865 *     influence of the template.
9866 
9867 *  Parameters:
9868 *     target
9869 *        Pointer to the target FrameSet, from whose current Frame the
9870 *        axes are to be selected.
9871 *     template
9872 *        Pointer to the template Frame, from which new attributes for
9873 *        the result Frame are to be obtained. Optionally, this may be
9874 *        NULL, in which case no overlaying of template attributes will
9875 *        be performed.
9876 *     result_naxes
9877 *        Number of axes to be selected from the target FrameSet. This
9878 *        number may be greater than or less than the number of axes in
9879 *        the FrameSet's current Frame (or equal).
9880 *     target_axes
9881 *        Pointer to an array of int with result_naxes elements, giving
9882 *        a list of the (zero-based) axis indices of the axes to be
9883 *        selected from the current Frame of the target FrameSet. The
9884 *        order in which these are given determines the order in which
9885 *        the axes appear in the result Frame. If any of the values in
9886 *        this array is set to -1, the corresponding result axis will
9887 *        not be derived from the target FrameSet, but will be assigned
9888 *        default attributes instead.
9889 *     template_axes
9890 *        Pointer to an array of int with result_naxes elements. This
9891 *        should contain a list of the template axes (given as
9892 *        zero-based axis indices) with which the axes of the result
9893 *        Frame are to be associated. This array determines which axes
9894 *        are used when overlaying axis-dependent attributes of the
9895 *        template on to the result. If any element of this array is
9896 *        set to -1, the corresponding result axis will not receive any
9897 *        template attributes.
9898 *
9899 *        If the template argument is given as NULL, this array is not
9900 *        used and a NULL pointer may also be supplied here.
9901 *     map
9902 *        Address of a location to receive a pointer to the returned
9903 *        Mapping.  The forward transformation of this Mapping will
9904 *        describe how to convert coordinates from the coordinate
9905 *        system described by the current Frame of the target FrameSet
9906 *        to that described by the result Frame. The inverse
9907 *        transformation will convert in the opposite direction.
9908 *     result
9909 *        Address of a location to receive a pointer to the result Frame.
9910 *     status
9911 *        Pointer to the inherited status variable.
9912 
9913 *  Returned Value:
9914 *     A non-zero value is returned if coordinate conversion is
9915 *     possible between the current Frame of the target FrameSet and
9916 *     the result Frame. Otherwise zero is returned and *map and
9917 *     *result are returned as NULL (but this will not in itself result
9918 *     in an error condition). In general, coordinate conversion should
9919 *     always be possible if no template Frame is supplied but may not
9920 *     always be possible otherwise.
9921 
9922 *  Notes:
9923 *     - A value of zero will be returned if this function is invoked
9924 *     with the global error status set, or if it should fail for any
9925 *     reason.
9926 */
9927 
9928 /* Local Variables: */
9929    AstFrame *fr;                 /* Pointer to FrameSet's current Frame */
9930    AstFrameSet *this;            /* Pointer to the FrameSet structure */
9931    int match;                    /* Result to be returned */
9932 
9933 /* Initialise. */
9934    *map = NULL;
9935    *result = NULL;
9936    match = 0;
9937 
9938 /* Check the global error status. */
9939    if ( !astOK ) return match;
9940 
9941 /* Obtain a pointer to the FrameSet structure. */
9942    this = (AstFrameSet *) this_frame;
9943 
9944 /* Obtain a pointer to the FrameSet's current Frame. */
9945    fr = astGetFrame( this, AST__CURRENT );
9946 
9947 /* Invoke the astSubFrame method for this Frame. */
9948    match = astSubFrame( fr, template, result_naxes, target_axes, template_axes,
9949                         map, result );
9950 
9951 /* Annul the Frame pointer. */
9952    fr = astAnnul( fr );
9953 
9954 /* If an error occurred, clean up by annulling any returned objects and clear
9955    the returned result. */
9956    if ( !astOK ) {
9957       *map = astAnnul( *map );
9958       *result = astAnnul( *result );
9959       match = 0;
9960    }
9961 
9962 /* Return the result. */
9963    return match;
9964 }
9965 
SystemCode(AstFrame * this_frame,const char * system,int * status)9966 static AstSystemType SystemCode( AstFrame *this_frame, const char *system, int *status ) {
9967 /*
9968 *  Name:
9969 *     SystemCode
9970 
9971 *  Purpose:
9972 *     Convert a string into a coordinate system type code.
9973 
9974 *  Type:
9975 *     Private function.
9976 
9977 *  Synopsis:
9978 *     #include "frameset.h"
9979 *     AstSystemType SystemCode( AstFrame *this, const char *system, int *status )
9980 
9981 *  Class Membership:
9982 *     FrameSet member function (over-rides the protected astSystemCode
9983 *     method inherited from the Frame class).
9984 
9985 *  Description:
9986 *     This function converts a string used for the external description of
9987 *     a coordinate system into a Frame coordinate system type code (System
9988 *     attribute value). It is the inverse of the astSystemString function.
9989 
9990 *  Parameters:
9991 *     this
9992 *        Pointer to the Frame.
9993 *     system
9994 *        Pointer to a constant null-terminated string containing the
9995 *        external description of the coordinate system.
9996 *     status
9997 *        Pointer to the inherited status variable.
9998 
9999 *  Returned Value:
10000 *     The System type code.
10001 
10002 *  Notes:
10003 *     - A value of AST__BADSYSTEM is returned if the coordinate system
10004 *     description was not recognised. This does not produce an error.
10005 *     - A value of AST__BADSYSTEM is also returned if this function
10006 *     is invoked with the global error status set or if it should fail
10007 *     for any reason.
10008 */
10009 
10010 /* Local Variables: */
10011    AstSystemType result;      /* Result value to return */
10012    AstFrame *fr;              /* Pointer to FrameSet's current Frame */
10013    AstFrameSet *this;         /* Pointer to the FrameSet structure */
10014 
10015 /* Initialise. */
10016    result = AST__BADSYSTEM;
10017 
10018 /* Check the global error status. */
10019    if ( !astOK ) return result;
10020 
10021 /* Obtain a pointer to the FrameSet structure. */
10022    this = (AstFrameSet *) this_frame;
10023 
10024 /* Obtain a pointer to the FrameSet's current Frame and invoke the
10025    astSystemCode method for this Frame. Annul the Frame pointer afterwards. */
10026    fr = astGetFrame( this, AST__CURRENT );
10027    result = astSystemCode( fr, system );
10028    fr = astAnnul( fr );
10029 
10030 /* If an error occurred, clear the result value. */
10031    if ( !astOK ) result = AST__BADSYSTEM;
10032 
10033 /* Return the result. */
10034    return result;
10035 }
10036 
SystemString(AstFrame * this_frame,AstSystemType system,int * status)10037 static const char *SystemString( AstFrame *this_frame, AstSystemType system, int *status ) {
10038 /*
10039 *  Name:
10040 *     SystemString
10041 
10042 *  Purpose:
10043 *     Convert a coordinate system type code into a string.
10044 
10045 *  Type:
10046 *     Private function.
10047 
10048 *  Synopsis:
10049 *     #include "frameset.h"
10050 *     const char *SystemString( AstFrame *this, AstSystemType system, int *status )
10051 
10052 *  Class Membership:
10053 *     FrameSet member function (over-rides the protected astSystemString
10054 *     method inherited from the Frame class).
10055 
10056 *  Description:
10057 *     This function converts a Frame coordinate system type code
10058 *     (System attribute value) into a string suitable for use as an
10059 *     external representation of the coordinate system type.
10060 
10061 *  Parameters:
10062 *     this
10063 *        Pointer to the Frame.
10064 *     system
10065 *        The coordinate system type code.
10066 *     status
10067 *        Pointer to the inherited status variable.
10068 
10069 *  Returned Value:
10070 *     Pointer to a constant null-terminated string containing the
10071 *     textual equivalent of the type code supplied.
10072 
10073 *  Notes:
10074 *     - A NULL pointer value is returned if the coordinate system
10075 *     code was not recognised. This does not produce an error.
10076 *     - A NULL pointer value is also returned if this function is
10077 *     invoked with the global error status set or if it should fail
10078 *     for any reason.
10079 */
10080 
10081 /* Local Variables: */
10082    AstFrame *fr;                 /* Pointer to FrameSet's current Frame */
10083    AstFrameSet *this;            /* Pointer to the FrameSet structure */
10084    const char *result;           /* Pointer value to return */
10085 
10086 /* Initialise. */
10087    result = NULL;
10088 
10089 /* Check the global error status. */
10090    if ( !astOK ) return result;
10091 
10092 /* Obtain a pointer to the FrameSet structure. */
10093    this = (AstFrameSet *) this_frame;
10094 
10095 /* Obtain a pointer to the FrameSet's current Frame and invoke the
10096    astSystemString method for this Frame. Annul the Frame pointer
10097    afterwards. */
10098    fr = astGetFrame( this, AST__CURRENT );
10099    result = astSystemString( fr, system );
10100    fr = astAnnul( fr );
10101 
10102 /* If an error occurred, clear the result value. */
10103    if ( !astOK ) result = NULL;
10104 
10105 /* Return the result pointer. */
10106    return result;
10107 
10108 }
10109 
TestAttrib(AstObject * this_object,const char * attrib,int * status)10110 static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) {
10111 /*
10112 *  Name:
10113 *     TestAttrib
10114 
10115 *  Purpose:
10116 *     Test if a specified attribute value is set for a FrameSet.
10117 
10118 *  Type:
10119 *     Private function.
10120 
10121 *  Synopsis:
10122 *     #include "frameset.h"
10123 *     int TestAttrib( AstObject *this, const char *attrib, int *status )
10124 
10125 *  Class Membership:
10126 *     FrameSet member function (over-rides the astTestAttrib protected
10127 *     method inherited from the Frame class).
10128 
10129 *  Description:
10130 *     This function returns a boolean result (0 or 1) to indicate whether
10131 *     a value has been set for one of a FrameSet's attributes.
10132 
10133 *  Parameters:
10134 *     this
10135 *        Pointer to the FrameSet.
10136 *     attrib
10137 *        Pointer to a null terminated string specifying the attribute
10138 *        name.  This should be in lower case with no surrounding white
10139 *        space.
10140 *     status
10141 *        Pointer to the inherited status variable.
10142 
10143 *  Returned Value:
10144 *     One if a value has been set, otherwise zero.
10145 
10146 *  Notes:
10147 *     - A value of zero will be returned if this function is invoked
10148 *     with the global status set, or if it should fail for any reason.
10149 */
10150 
10151 /* Local Variables: */
10152    AstFrame *fr;                 /* Pointer to current Frame */
10153    AstFrameSet *this;            /* Pointer to the FrameSet structure */
10154    int result;                   /* Result value to return */
10155 
10156 /* Initialise. */
10157    result = 0;
10158 
10159 /* Check the global error status. */
10160    if ( !astOK ) return result;
10161 
10162 /* Obtain a pointer to the FrameSet structure. */
10163    this = (AstFrameSet *) this_object;
10164 
10165 /* Check the attribute name and test the appropriate attribute. */
10166 
10167 /* We first handle attributes that apply to the FrameSet as a whole
10168    (rather than to the current Frame). */
10169 
10170 /* Base. */
10171 /* ----- */
10172    if ( !strcmp( attrib, "base" ) ) {
10173       result = astTestBase( this );
10174 
10175 /* Current. */
10176 /* -------- */
10177    } else if ( !strcmp( attrib, "current" ) ) {
10178       result = astTestCurrent( this );
10179 
10180 /* ID. */
10181 /* --- */
10182    } else if ( !strcmp( attrib, "id" ) ) {
10183       result = astTestID( this );
10184 
10185 /* Ident. */
10186 /* ------ */
10187    } else if ( !strcmp( attrib, "ident" ) ) {
10188       result = astTestIdent( this );
10189 
10190 /* Invert. */
10191 /* ------- */
10192    } else if ( !strcmp( attrib, "invert" ) ) {
10193       result = astTestInvert( this );
10194 
10195 /* Report. */
10196 /* ------- */
10197    } else if ( !strcmp( attrib, "report" ) ) {
10198       result = astTestReport( this );
10199 
10200 /* Variant. */
10201 /* -------- */
10202    } else if ( !strcmp( attrib, "variant" ) ) {
10203       result = astTestVariant( this );
10204 
10205 /* If the name is not recognised, test if it matches any of the
10206    read-only attributes of this class. If it does, then return
10207    zero. */
10208    } else if ( !strcmp( attrib, "allvariants" ) ||
10209                !strcmp( attrib, "class" ) ||
10210                !strcmp( attrib, "nframe" ) ||
10211                !strcmp( attrib, "nin" ) ||
10212                !strcmp( attrib, "nobject" ) ||
10213                !strcmp( attrib, "nout" ) ||
10214                !strcmp( attrib, "refcount" ) ||
10215                !strcmp( attrib, "tranforward" ) ||
10216                !strcmp( attrib, "traninverse" ) ) {
10217       result = 0;
10218 
10219 /* Pass unrecognised attributes on to the FrameSet's current Frame for
10220    further interpretation. */
10221    } else {
10222 
10223 /* Obtain a pointer to the current Frame and invoke its astTestAttrib
10224    method. Annul the Frame pointer afterwards. */
10225       fr = astGetFrame( this, AST__CURRENT );
10226       result = astTestAttrib( fr, attrib );
10227       fr = astAnnul( fr );
10228    }
10229 
10230 /* If an error occurred, clear the result value. */
10231    if ( !astOK ) result = 0;
10232 
10233 /* Return the result, */
10234    return result;
10235 }
10236 
TestBase(AstFrameSet * this,int * status)10237 static int TestBase( AstFrameSet *this, int *status ) {
10238 /*
10239 *+
10240 *  Name:
10241 *     astTestBase
10242 
10243 *  Purpose:
10244 *     Determine if a value has been set for the Base attribute of a FrameSet.
10245 
10246 *  Type:
10247 *     Protected virtual function.
10248 
10249 *  Synopsis:
10250 *     #include "frameset.h"
10251 *     int astTestBase( AstFrameSet *this )
10252 
10253 *  Class Membership:
10254 *     FrameSet method.
10255 
10256 *  Description:
10257 *     This function returns a boolean result to indicate if a value
10258 *     has been set for the Base attribute of a FrameSet. This
10259 *     attribute is an index that identifies the base Frame in the
10260 *     FrameSet.
10261 
10262 *  Parameters:
10263 *     this
10264 *        Pointer to the FrameSet.
10265 
10266 *  Returned Value:
10267 *     Zero or 1, depending on whether a value has been set.
10268 
10269 *  Notes:
10270 *     - A value of zero will be returned if this function is invoked
10271 *     with the global status set, or if it should fail for any reason.
10272 *-
10273 */
10274 
10275 /* Local Variables: */
10276    int invert;                   /* FrameSet is inverted? */
10277    int result;                   /* Value to return */
10278 
10279 /* Initialise. */
10280    result = 0;
10281 
10282 /* Check the global error status. */
10283    if ( !astOK ) return result;
10284 
10285 /* Determine if the FrameSet has been inverted. */
10286    invert = astGetInvert( this );
10287 
10288 /* If it has not been inverted, test the base Frame index, otherwise
10289    test the index of the current Frame instead. */
10290    if ( astOK ) {
10291       if ( !invert ) {
10292          result = ( this->base != -INT_MAX );
10293       } else {
10294          result = ( this->current != -INT_MAX );
10295       }
10296    }
10297 
10298 /* Return the result. */
10299    return result;
10300 }
10301 
TestCurrent(AstFrameSet * this,int * status)10302 static int TestCurrent( AstFrameSet *this, int *status ) {
10303 /*
10304 *+
10305 *  Name:
10306 *     astTestCurrent
10307 
10308 *  Purpose:
10309 *     Test if a value has been set for the Current attribute of a FrameSet.
10310 
10311 *  Type:
10312 *     Protected function.
10313 
10314 *  Synopsis:
10315 *     #include "frameset.h"
10316 *     int astTestCurrent( AstFrameSet *this )
10317 
10318 *  Class Membership:
10319 *     FrameSet method.
10320 
10321 *  Description:
10322 *     This function returns a boolean result to indicate whether a
10323 *     value has been set for the Current attribute of a FrameSet.
10324 *     This attribute is an index that identifies the current Frame in
10325 *     a FrameSet.
10326 
10327 *  Parameters:
10328 *     this
10329 *        Pointer to the FrameSet.
10330 
10331 *  Returned Value:
10332 *     Zero or 1, depending on whether a value has been set.
10333 
10334 *  Notes:
10335 *     - A value of zero will be returned if this function is invoked
10336 *     with the global status set, or if it should fail for any reason.
10337 *-
10338 */
10339 
10340 /* Local Variables: */
10341    int invert;                   /* FrameSet is inverted? */
10342    int result;                   /* Value to return */
10343 
10344 /* Initialise. */
10345    result = 0;
10346 
10347 /* Check the global error status. */
10348    if ( !astOK ) return result;
10349 
10350 /* Determine if the FrameSet has been inverted. */
10351    invert = astGetInvert( this );
10352 
10353 /* If it has not been inverted, test the current Frame index,
10354    otherwise test the index of the base Frame instead. */
10355    if ( astOK ) {
10356       if ( !invert ) {
10357          result = ( this->current != -INT_MAX );
10358       } else {
10359          result = ( this->base != -INT_MAX );
10360       }
10361    }
10362 
10363 /* Return the result. */
10364    return result;
10365 }
10366 
TestVariant(AstFrameSet * this,int * status)10367 static int TestVariant( AstFrameSet *this, int *status ) {
10368 /*
10369 *+
10370 *  Name:
10371 *     astTestVariant
10372 
10373 *  Purpose:
10374 *     Determine if a value has been set for the Variant attribute of a FrameSet.
10375 
10376 *  Type:
10377 *     Protected virtual function.
10378 
10379 *  Synopsis:
10380 *     #include "frameset.h"
10381 *     int astTestVariant( AstFrameSet *this )
10382 
10383 *  Class Membership:
10384 *     FrameSet method.
10385 
10386 *  Description:
10387 *     This function returns a boolean result to indicate if a value
10388 *     has been set for the Variant attribute of a FrameSet.
10389 
10390 *  Parameters:
10391 *     this
10392 *        Pointer to the FrameSet.
10393 
10394 *  Returned Value:
10395 *     Zero or 1, depending on whether a value has been set.
10396 
10397 *  Notes:
10398 *     - A value of zero will be returned if this function is invoked
10399 *     with the global status set, or if it should fail for any reason.
10400 *-
10401 */
10402 
10403 /* Local Variables: */
10404    AstFrame *frm;
10405    AstFrameSet *vfs;
10406    int result;
10407    int icur;
10408 
10409 /* Initialise. */
10410    result = 0;
10411 
10412 /* Check the global error status. */
10413    if ( !astOK ) return result;
10414 
10415 /* Get the one-based index of the Frame to use. */
10416    icur = GetVarFrm( this, astGetCurrent( this ), status );
10417 
10418 /* Get a pointer to the Variants FrameSet in the current Frame. */
10419    frm = astGetFrame( this, icur );
10420    vfs = astGetFrameVariants( frm );
10421 
10422 /* If it is null, return zero, otherwise 1. */
10423    result = vfs ? 1 : 0;
10424 
10425 /* Annul pointers. */
10426    if( vfs ) vfs = astAnnul( vfs );
10427    frm = astAnnul( frm );
10428 
10429 /* Return the result. */
10430    return result;
10431 }
10432 
TidyNodes(AstFrameSet * this,int * status)10433 static void TidyNodes( AstFrameSet *this, int *status ) {
10434 /*
10435 *  Name:
10436 *     TidyNodes
10437 
10438 *  Purpose:
10439 *     Tidy the nodes in a FrameSet.
10440 
10441 *  Type:
10442 *     Private function.
10443 
10444 *  Synopsis:
10445 *     #include "frameset.h"
10446 *     void TidyNodes( AstFrameSet *this, int *status )
10447 
10448 *  Class Membership:
10449 *     FrameSet member function.
10450 
10451 *  Description:
10452 *     This function tidies the nodes in a FrameSet, removing any that
10453 *     are unnecessary or represent dead-ends. It should be used after
10454 *     any changes have been made to a FrameSet that may have reduced
10455 *     the number of references to any of its nodes (either by Frames
10456 *     or by other nodes).
10457 
10458 *  Parameters:
10459 *     this
10460 *        Pointer to the FrameSet.
10461 *     status
10462 *        Pointer to the inherited status variable.
10463 */
10464 
10465 /* Local Variables: */
10466    AstMapping *newmap;           /* Pointer to simplified Mapping */
10467    AstMapping *tmpmap;           /* Pointer to new compound Mapping */
10468    int ifr;                      /* Loop counter for Frames */
10469    int inode;                    /* Loop counter for nodes */
10470    int last_link[ 2 ];           /* Last nodes to reference via "link" array */
10471    int link_ref;                 /* Number of "link" array references */
10472    int needed;                   /* Node still required? */
10473    int next;                     /* Node which references the removed one */
10474    int remove;                   /* Node to be removed */
10475    int suspect;                  /* Loop counter for testing nodes */
10476 
10477 /* Check the global error status. */
10478    if ( !astOK ) return;
10479 
10480 /* Loop to search for unnecessary nodes until no more are found. */
10481    needed = 0;
10482    while ( !needed ) {
10483 
10484 /* Inspect each node (including node zero, which does not actually
10485    have a Mapping associated with it) to see how many times it is
10486    referenced. */
10487       for ( suspect = 0; suspect < this->nnode; suspect++ ) {
10488          link_ref = 0;
10489 
10490 /* Test for at least one reference from within the "node" array which
10491    associates Frames with particular nodes. */
10492          for ( ifr = 1; ifr <= this->nframe; ifr++ ) {
10493             if ( ( needed = ( this->node[ ifr - 1 ] == suspect ) ) ) break;
10494          }
10495 
10496 /* If no references were found above, look for references in the
10497    "link" array that inter-connects all the nodes. */
10498          if ( !needed ) {
10499             for ( inode = 1; inode < this->nnode; inode ++ ) {
10500                if ( this->link[ inode - 1 ] == suspect ) {
10501 
10502 /* Node zero must be retained if it has more than two links
10503    referencing it, while other nodes only require more than one. */
10504                   if ( ( needed = ( link_ref >= ( suspect ? 1 : 2 ) ) ) ) break;
10505 
10506 /* Remember (up to) the first two nodes which reference the current one. */
10507                   last_link[ link_ref++ ] = inode;
10508                }
10509             }
10510          }
10511 
10512 /* If there were insufficient references to retain this node, we must
10513    now decide why it should be removed. */
10514          if ( !needed ) {
10515 
10516 /* If there is no Frame associated with a node and there are less than
10517    two links to it (for node zero), or less then one link (for other
10518    nodes), then the there is no route to anything else via this node.
10519    It is a dead-end. */
10520             if ( link_ref < ( suspect ? 1 : 2 ) ) {
10521 
10522 /* To tidy up, we remove the affected node or, for node zero, the
10523    remaining one that references it. Annul the Mapping associated with
10524    the node being removed. */
10525                remove = suspect ? suspect : last_link[ 0 ];
10526                this->map[ remove - 1 ] = astAnnul( this->map[ remove - 1 ] );
10527 
10528 /* If an unnecessary node is not a dead-end, then it is a redundant
10529    node which simply joins two Mappings. */
10530             } else {
10531 
10532 /* To tidy up, we remove the affected node or, for node zero, the
10533    first one that references it. */
10534                remove = suspect ? suspect : last_link[ 0 ];
10535 
10536 /* We then produce a compound Mapping which spans the gap by
10537    concatenating the Mappings associated with the node being removed
10538    and the remaining one which references it. For node zero, the first
10539    of these Mappings must be inverted because there are no out-going
10540    Mappings from node zero. */
10541                next = suspect ? last_link[ 0 ] : last_link[ 1 ];
10542                tmpmap = CombineMaps( this->map[ remove - 1 ],
10543                                      this->invert[ remove - 1 ] != !suspect,
10544                                      this->map[ next - 1 ],
10545                                      this->invert[ next - 1 ], 1, status );
10546 
10547 /* Simplify this compound Mapping. */
10548                newmap = astSimplify( tmpmap );
10549                tmpmap = astAnnul( tmpmap );
10550 
10551 /* Annul the individual Mapping pointers. */
10552                this->map[ remove - 1 ] = astAnnul( this->map[ remove - 1 ] );
10553                this->map[ next - 1 ] = astAnnul( this->map[ next - 1 ] );
10554 
10555 /* Install the new compound Mapping and its Invert flag. */
10556                this->map[ next - 1 ] = newmap;
10557                this->invert[ next - 1 ] = astGetInvert( newmap );
10558 
10559 /* Transfer the "link" value from the removed node to the one which
10560    takes its place. */
10561                this->link[ next - 1 ] = this->link[ remove - 1 ];
10562             }
10563 
10564 /* Loop to move all subsequent node data down in the "map", "invert"
10565    and "link" arrays to close the gap where a node has been
10566    removed. */
10567             for ( inode = remove; inode < this->nnode - 1; inode ++ ) {
10568                this->map [ inode - 1 ] = this->map[ inode ];
10569                this->link [ inode - 1 ] = this->link[ inode ];
10570                this->invert[ inode - 1 ] = this->invert[ inode ];
10571             }
10572             this->map[ this->nnode - 2 ] = NULL;
10573             this->link[ this->nnode - 2 ] = -1;
10574             this->invert[ this->nnode - 2 ] = -1;
10575 
10576 /* Decrement the node count. */
10577             this->nnode--;
10578 
10579 /* Loop to adjust each entry in the "node" array for the change in
10580    node numbering, re-directing references to the removed node towards
10581    the new node zero. */
10582             for ( ifr = 1; ifr <= this->nframe; ifr++ ) {
10583                if ( this->node[ ifr - 1 ] > remove ) {
10584                   this->node[ ifr - 1 ]--;
10585                } else if ( this->node[ ifr - 1 ] == remove ) {
10586                   this->node[ ifr - 1 ] = 0;
10587                }
10588             }
10589 
10590 /* Similarly adjust each entry in the "link" array. */
10591             for ( inode = 1; inode < this->nnode; inode++ ) {
10592                if ( this->link[ inode - 1 ] > remove ) {
10593                   this->link[ inode - 1 ]--;
10594                } else if ( this->link[ inode - 1 ] == remove ) {
10595                   this->link[ inode - 1 ] = 0;
10596                }
10597             }
10598 
10599 /* Once a node has been removed, other nodes (perhaps already tested)
10600    may no longer be needed, so quit the testing loop and start testing
10601    again with node zero. The process terminates when no more
10602    unnecessary nodes can be found. */
10603             break;
10604          }
10605       }
10606    }
10607 }
10608 
Transform(AstMapping * this_mapping,AstPointSet * in,int forward,AstPointSet * out,int * status)10609 static AstPointSet *Transform( AstMapping *this_mapping, AstPointSet *in,
10610                                int forward, AstPointSet *out, int *status ) {
10611 /*
10612 *  Name:
10613 *     Transform
10614 
10615 *  Purpose:
10616 *     Transform a set of points.
10617 
10618 *  Type:
10619 *     Private function.
10620 
10621 *  Synopsis:
10622 *     #include "frameset.h"
10623 *     AstPointSet *Transform( AstMapping *this, AstPointSet *in,
10624 *                             int forward, AstPointSet *out, int *status )
10625 
10626 *  Class Membership:
10627 *     FrameSet member function (over-rides the astTransform method
10628 *     inherited from the Frame class).
10629 
10630 *  Description:
10631 *     This function takes a FrameSet and a set of points encapsulated
10632 *     in a PointSet, and applies either the forward or inverse
10633 *     coordinate transformation (if defined by the FrameSet) to the
10634 *     points. The forward transformation converts between the
10635 *     FrameSet's base Frame and its current Frame, while the inverse
10636 *     transformation converts in the opposite direction.
10637 
10638 *  Parameters:
10639 *     this
10640 *        Pointer to the FrameSet.
10641 *     in
10642 *        Pointer to the PointSet holding the input coordinate data.
10643 *     forward
10644 *        A non-zero value indicates that the forward coordinate transformation
10645 *        should be applied, while a zero value requests the inverse
10646 *        transformation.
10647 *     out
10648 *        Pointer to a PointSet which will hold the transformed (output)
10649 *        coordinate values. A NULL value may also be given, in which case a
10650 *        new PointSet will be created by this function.
10651 *     status
10652 *        Pointer to the inherited status variable.
10653 
10654 *  Returned Value:
10655 *     Pointer to the output (possibly new) PointSet.
10656 
10657 *  Notes:
10658 *     - An error will result if the FrameSet supplied does not define
10659 *     the requested coordinate transformation (either forward or
10660 *     inverse).
10661 *     - The number of coordinate values per point in the input
10662 *     PointSet must match the number of input coordinates for the
10663 *     FrameSet being applied (or number of output coordinates if the
10664 *     inverse transformation is requested).  This will be equal to the
10665 *     number of axes in the FrameSet's base Frame (or the current
10666 *     Frame for the inverse transformation).
10667 *     - If an output PointSet is supplied, it must have space for
10668 *     sufficient number of points and coordinate values per point to
10669 *     accommodate the result (e.g. the number of FrameSet output
10670 *     coordinates, or number of input coordinates if the inverse
10671 *     transformation is requested). Any excess space will be ignored.
10672 *     - A null pointer will be returned if this function is invoked
10673 *     with the global error status set, or if it should fail for any
10674 *     reason.
10675 */
10676 
10677 /* Local Variables: */
10678    AstFrameSet *this;            /* Pointer to the FrameSet structure */
10679    AstMapping *map;              /* Pointer to the base->current Mapping */
10680    AstPointSet *result;          /* Pointer value to return */
10681 
10682 /* Check the global error status. */
10683    if ( !astOK ) return NULL;
10684 
10685 /* Obtain a pointer to the FrameSet structure. */
10686    this = (AstFrameSet *) this_mapping;
10687 
10688 /* Obtain the Mapping between the base and current Frames in the
10689    FrameSet (note this takes account of whether the FrameSet has been
10690    inverted). */
10691    map = astGetMapping( this, AST__BASE, AST__CURRENT );
10692 
10693 /* Apply the Mapping to the input PointSet. */
10694    result = astTransform( map, in, forward, out );
10695 
10696 /* Annul the Mapping pointer. */
10697    map = astAnnul( map );
10698 
10699 /* If an error has occurred and a new PointSet may have been created, then
10700    clean up by annulling it. In any case, ensure that a NULL result is
10701    returned.*/
10702    if ( !astOK ) {
10703       if ( !out ) result = astAnnul( result );
10704       result = NULL;
10705    }
10706 
10707 /* Return a pointer to the output PointSet. */
10708    return result;
10709 }
10710 
Unformat(AstFrame * this_frame,int axis,const char * string,double * value,int * status)10711 static int Unformat( AstFrame *this_frame, int axis, const char *string,
10712                      double *value, int *status ) {
10713 /*
10714 *  Name:
10715 *     Unformat
10716 
10717 *  Purpose:
10718 *     Read a formatted coordinate value for a FrameSet axis.
10719 
10720 *  Type:
10721 *     Private function.
10722 
10723 *  Synopsis:
10724 *     #include "frameset.h"
10725 *     int Unformat( AstFrame *this, int axis, const char *string,
10726 *                   double *value, int *status )
10727 
10728 *  Class Membership:
10729 *     FrameSet member function (over-rides the public astUnformat
10730 *     method inherited from the Frame class).
10731 
10732 *  Description:
10733 *     This function reads a formatted coordinate value for a FrameSet
10734 *     axis (supplied as a string) and returns the equivalent numerical
10735 *     value as a double. It also returns the number of characters read
10736 *     from the string.
10737 
10738 *  Parameters:
10739 *     this
10740 *        Pointer to the FrameSet.
10741 *     axis
10742 *        The number of the FrameSet axis for which the coordinate
10743 *        value is to be read (axis numbering starts at zero for the
10744 *        first axis).
10745 *     string
10746 *        Pointer to a constant null-terminated string containing the
10747 *        formatted coordinate value.
10748 *     value
10749 *        Pointer to a double in which the coordinate value read will be
10750 *        returned.
10751 *     status
10752 *        Pointer to the inherited status variable.
10753 
10754 *  Returned Value:
10755 *     The number of characters read from the string to obtain the
10756 *     coordinate value.
10757 
10758 *  Notes:
10759 *     - Any white space at the beginning of the string will be
10760 *     skipped, as also will any trailing white space following the
10761 *     coordinate value read. The function's return value will reflect
10762 *     this.
10763 *     - A function value of zero (and no coordinate value) will be
10764 *     returned, without error, if the string supplied does not contain
10765 *     a suitably formatted value.
10766 *     - The string "<bad>" is recognised as a special case and will
10767 *     generate the value AST__BAD, without error. The test for this
10768 *     string is case-insensitive and permits embedded white space.
10769 *     - A function result of zero will be returned and no coordinate
10770 *     value will be returned via the "value" pointer if this function
10771 *     is invoked with the global error status set, or if it should
10772 *     fail for any reason.
10773 */
10774 
10775 /* Local Variables: */
10776    AstFrame *fr;                 /* Pointer to current Frame */
10777    AstFrameSet *this;            /* Pointer to the FrameSet structure */
10778    double coord;                 /* Coordinate value read */
10779    int nc;                       /* Number of characters read */
10780 
10781 /* Initialise. */
10782    nc = 0;
10783 
10784 /* Check the global error status. */
10785    if ( !astOK ) return nc;
10786 
10787 /* Obtain a pointer to the FrameSet structure. */
10788    this = (AstFrameSet *) this_frame;
10789 
10790 /* Validate the axis index. */
10791    (void) astValidateAxis( this, axis, 1, "astUnformat" );
10792 
10793 /* Obtain a pointer to the FrameSet's current Frame and invoke the
10794    astUnformat method for this Frame. Annul the Frame pointer
10795    afterwards. */
10796    fr = astGetFrame( this, AST__CURRENT );
10797    nc = astUnformat( fr, axis, string, &coord );
10798    fr = astAnnul( fr );
10799 
10800 /* If an error occurred, clear the number of characters read. */
10801    if ( !astOK ) {
10802       nc = 0;
10803 
10804 /* Otherwise, if characters were read, return the coordinate value. */
10805    } else if ( nc ) {
10806       *value = coord;
10807    }
10808 
10809 /* Return the number of characters read. */
10810    return nc;
10811 }
10812 
ValidateAxis(AstFrame * this_frame,int axis,int fwd,const char * method,int * status)10813 static int ValidateAxis( AstFrame *this_frame, int axis, int fwd,
10814                          const char *method, int *status ) {
10815 /*
10816 *  Name:
10817 *     ValidateAxis
10818 
10819 *  Purpose:
10820 *     Validate and permute a FrameSet's axis index.
10821 
10822 *  Type:
10823 *     Private function.
10824 
10825 *  Synopsis:
10826 *     #include "frameset.h"
10827 *     int ValidateAxis( AstFrame *this, int axis, int fwd, const char *method,
10828 *                       int *status )
10829 
10830 *  Class Membership:
10831 *     FrameSet member function (over-rides the protected
10832 *     astValidateAxis method inherited from the Frame class).
10833 
10834 *  Description:
10835 *     This function checks the validity of an index (zero-based) which
10836 *     is to be used to address one of the coordinate axes of the
10837 *     current Frame in a FrameSet. If the index is valid, it is
10838 *     permuted using the axis permutation array associated with the
10839 *     FrameSet's current Frame and the (zero-based) permuted axis
10840 *     index is returned.  This gives the index the axis had when the
10841 *     Frame was first created. If the axis index supplied is not
10842 *     valid, an error is reported and the global error status is set.
10843 
10844 *  Parameters:
10845 *     this
10846 *        Pointer to the FrameSet.
10847 *     axis
10848 *        The axis index (zero-based) to be checked. To be valid, it
10849 *        must lie between zero and (naxes-1) inclusive, where "naxes"
10850 *        is the number of coordinate axes associated with the
10851 *        FrameSet's current Frame.
10852 *     fwd
10853 *        If non-zero, the suppplied axis index is assumed to be an
10854 *        "external" axis index, and the corresponding "internal" axis index
10855 *        is returned as the function value. Otherwise, the suppplied axis
10856 *        index is assumed to be an "internal" axis index, and the
10857 *        corresponding "external" axis index is returned as the function
10858 *        value.
10859 *     method
10860 *        Pointer to a constant null-terminated character string
10861 *        containing the name of the method that invoked this function
10862 *        to validate an axis index. This method name is used solely
10863 *        for constructing error messages.
10864 *     status
10865 *        Pointer to the inherited status variable.
10866 
10867 *  Returned Value:
10868 *     The permuted axis index - either "internal" or "external" as
10869 *     specified by "fwd".
10870 
10871 *  Notes:
10872 *     - A value of zero will be returned if this function is invoked
10873 *     with the global error status set, or if it should fail for any
10874 *     reason.
10875 */
10876 
10877 /* Local Variables: */
10878    AstFrame *fr;                 /* Pointer to current Frame */
10879    AstFrameSet *this;            /* Pointer to the FrameSet structure */
10880    int naxes;                    /* Number of FrameSet axes */
10881    int result;                   /* Permuted axis index */
10882 
10883 /* Initialise. */
10884    result = 0;
10885 
10886 /* Check the global error status. */
10887    if ( !astOK ) return result;
10888 
10889 /* Obtain a pointer to the FrameSet structure. */
10890    this = (AstFrameSet *) this_frame;
10891 
10892 /* Determine the number of FrameSet axes. */
10893    naxes = astGetNaxes( this );
10894    if ( astOK ) {
10895 
10896 /* If the FrameSet has no axes, report an error (convert to 1-based
10897    axis numbering for the benefit of the public interface). */
10898       if ( naxes == 0 ) {
10899          astError( AST__AXIIN, "%s(%s): Invalid attempt to use an axis index "
10900                    "(%d) for a %s which has no axes.", status, method,
10901                    astGetClass( this ), axis + 1, astGetClass( this ) );
10902 
10903 /* Otherwise, check the axis index for validity and report an error if
10904    it is not valid (again, convert to 1-based axis numbering). */
10905       } else if ( ( axis < 0 ) || ( axis >= naxes ) ) {
10906          astError( AST__AXIIN, "%s(%s): Axis index (%d) invalid - it should "
10907                    "be in the range 1 to %d.", status, method, astGetClass( this ),
10908                    axis + 1, naxes );
10909 
10910 /* If the axis index was valid, obtain a pointer to the FrameSet's
10911    current Frame and invoke this Frame's astValidateAxis method to
10912    obtain the permuted axis index. Annul the Frame pointer
10913    afterwards. */
10914       } else {
10915          fr = astGetFrame( this, AST__CURRENT );
10916          result = astValidateAxis( fr, axis, fwd, "astValidateAxis" );
10917          fr = astAnnul( fr );
10918       }
10919    }
10920 
10921 /* If an error occurred, clear the result value. */
10922    if ( !astOK ) result = 0;
10923 
10924 /* Return the result. */
10925    return result;
10926 }
10927 
ValidateAxisSelection(AstFrame * this_frame,int naxes,const int * axes,const char * method,int * status)10928 static void ValidateAxisSelection( AstFrame *this_frame, int naxes,
10929                                    const int *axes, const char *method, int *status ) {
10930 /*
10931 *  Name:
10932 *     ValidateAxisSelection
10933 
10934 *  Purpose:
10935 *     Check that a set of axes selected from a Frame is valid.
10936 
10937 *  Type:
10938 *     Private function.
10939 
10940 *  Synopsis:
10941 *     #include "frameset.h"
10942 *     void ValidateAxisSelection( AstFrame *this, int naxes,
10943 *                                 const int *axes, const char *method, int *status )
10944 
10945 *  Class Membership:
10946 *     FrameSet member function (over-rides the protected astValidateAxisSelection
10947 *     method inherited from the Frame class).
10948 
10949 *  Description:
10950 *     This function checks the validity of an array of (zero-based)
10951 *     axis indices that specify a set of axes to be selected from a
10952 *     Frame. To be valid, no axis should be selected more than
10953 *     once. In assessing this, any axis indices that do not refer to
10954 *     valid Frame axes (e.g. are set to -1) are ignored.
10955 *
10956 *     If the axis selection is valid, this function returns without further
10957 *     action. Otherwise, an error is reported and the global error status is
10958 *     set.
10959 
10960 *  Parameters:
10961 *     this
10962 *        Pointer to the Frame.
10963 *     naxes
10964 *        The number of axes to be selected (may be zero).
10965 *     axes
10966 *        Pointer to an array of int with naxes elements that contains the
10967 *        (zero based) axis indices to be checked.
10968 *     method
10969 *        Pointer to a constant null-terminated character string
10970 *        containing the name of the method that invoked this function
10971 *        to validate an axis selection. This method name is used
10972 *        solely for constructing error messages.
10973 *     status
10974 *        Pointer to the inherited status variable.
10975 */
10976 
10977 /* Local Variables: */
10978    AstFrame *fr;                 /* Pointer to current Frame */
10979    AstFrameSet *this;            /* Pointer to the FrameSet structure */
10980 
10981 /* Check the global error status. */
10982    if ( !astOK ) return;
10983 
10984 /* Obtain a pointer to the FrameSet structure. */
10985    this = (AstFrameSet *) this_frame;
10986 
10987 /* Obtain a pointer to the FrameSet's current Frame and invoke this
10988    Frame's astValidateAxisSelection method. Annul the Frame pointer
10989    afterwards. */
10990    fr = astGetFrame( this, AST__CURRENT );
10991    astValidateAxisSelection( fr, naxes, axes, method );
10992    fr = astAnnul( fr );
10993 
10994 }
10995 
ValidateFrameIndex(AstFrameSet * this,int iframe,const char * method,int * status)10996 static int ValidateFrameIndex( AstFrameSet *this, int iframe,
10997                                const char *method, int *status ) {
10998 /*
10999 *+
11000 *  Name:
11001 *     astValidateFrameIndex
11002 
11003 *  Purpose:
11004 *     Validate a FrameSet Frame index number.
11005 
11006 *  Type:
11007 *     Protected virtual function.
11008 
11009 *  Synopsis:
11010 *     #include "frameset.h"
11011 *     int astValidateFrameIndex( AstFrameSet *this, int iframe,
11012 *                                const char *method )
11013 
11014 *  Class Membership:
11015 *     FrameSet method.
11016 
11017 *  Description:
11018 *     This function checks a (one-based) FrameSet Frame index for
11019 *     validity. If it is not valid, an error is reported. Otherwise,
11020 *     the function returns the Frame index value, having translated
11021 *     the special values AST__CURRENT and AST__BASE into valid Frame
11022 *     indices if necessary.
11023 
11024 *  Parameters:
11025 *     this
11026 *        Pointer to the FrameSet.
11027 *     iframe
11028 *        The Frame index. To be valid this should lie in the range 1
11029 *        to the number of Frames in the FrameSet.  In addition, the
11030 *        values AST__CURRENT and AST__BASE may be given to indicate
11031 *        the "current" and "base" Frames. These values will be
11032 *        translated into the acceptable range.
11033 *     method
11034 *        Pointer to a constant null-terminated character string
11035 *        containing the name of the method that invoked this function
11036 *        to validate a Frame index. This method name is used solely
11037 *        for constructing error messages.
11038 
11039 *  Returned Value:
11040 *     The validated (one-based) Frame index.
11041 
11042 *  Notes:
11043 *     - A value of zero will be returned if this function is invoked
11044 *     with the global status set, or if it should fail for any reason
11045 *     (e.g. if the Frame index is invalid).
11046 *-
11047 */
11048 
11049 /* Local Variables: */
11050    int nframe;                   /* Number of Frames */
11051    int result;                   /* Returned index value */
11052 
11053 /* Initialise. */
11054    result = 0;
11055 
11056 /* Check the global error status. */
11057    if ( !astOK ) return result;
11058 
11059 /* Check if the base or current Frame was specified and retrieve the
11060    required Frame index from the FrameSet. */
11061    if ( iframe == AST__BASE ) {
11062       result = astGetBase( this );
11063    } else if ( iframe == AST__CURRENT ) {
11064       result = astGetCurrent( this );
11065 
11066 /* Otherwise, determine how many Frames there are in the FrameSet. */
11067    } else {
11068       nframe = astGetNframe( this );
11069       if ( astOK ) {
11070 
11071 /* Check that the supplied index is within range and report an error
11072    if it is not. */
11073          if ( ( iframe < 1 ) || ( iframe > nframe ) ) {
11074             astError( AST__FRMIN, "%s(%s): Invalid Frame index (%d) given.", status,
11075                       method, astGetClass( this ), iframe );
11076             astError( AST__FRMIN, "This value should be in the range 1 to "
11077                       "%d (or AST__CURRENT or AST__BASE).", status, nframe );
11078 
11079 /* If OK, return the validated index value. */
11080          } else {
11081             result = iframe;
11082          }
11083       }
11084    }
11085 
11086 /* Return the result. */
11087    return result;
11088 }
11089 
ValidateSystem(AstFrame * this_frame,AstSystemType system,const char * method,int * status)11090 static int ValidateSystem( AstFrame *this_frame, AstSystemType system, const char *method, int *status ) {
11091 /*
11092 *  Name:
11093 *     ValidateSystem
11094 
11095 *  Purpose:
11096 *     Validate a value for a Frame's System attribute.
11097 
11098 *  Type:
11099 *     Private function.
11100 
11101 *  Synopsis:
11102 *     #include "frameset.h"
11103 *     int ValidateSystem( AstFrame *this, AstSystemType system,
11104 *                         const char *method, int *status )
11105 
11106 *  Class Membership:
11107 *     FrameSet member function (over-rides the protected astValidateSystem
11108 *     method inherited from the Frame class).
11109 
11110 *  Description:
11111 *     This function checks the validity of the supplied system value.
11112 *     If the value is valid, it is returned unchanged. Otherwise, an
11113 *     error is reported and a value of AST__BADSYSTEM is returned.
11114 
11115 *  Parameters:
11116 *     this
11117 *        Pointer to the Frame.
11118 *     system
11119 *        The system value to be checked.
11120 *     method
11121 *        Pointer to a constant null-terminated character string
11122 *        containing the name of the method that invoked this function
11123 *        to validate an axis index. This method name is used solely
11124 *        for constructing error messages.
11125 *     status
11126 *        Pointer to the inherited status variable.
11127 
11128 *  Returned Value:
11129 *     The validated system value.
11130 
11131 *  Notes:
11132 *     - A value of AST_BADSYSTEM will be returned if this function is invoked
11133 *     with the global error status set, or if it should fail for any
11134 *     reason.
11135 *-
11136 */
11137 
11138 /* Local Variables: */
11139    AstSystemType result;      /* Validated system value */
11140    AstFrame *fr;              /* Pointer to FrameSet's current Frame */
11141    AstFrameSet *this;         /* Pointer to the FrameSet structure */
11142 
11143 /* Initialise. */
11144    result = AST__BADSYSTEM;
11145 
11146 /* Check the global error status. */
11147    if ( !astOK ) return result;
11148 
11149 /* Obtain a pointer to the FrameSet structure. */
11150    this = (AstFrameSet *) this_frame;
11151 
11152 /* Obtain a pointer to the FrameSet's current Frame and invoke the
11153    astValidateSystem method for this Frame. Annul the Frame pointer
11154    afterwards. */
11155    fr = astGetFrame( this, AST__CURRENT );
11156    result = astValidateSystem( this, system, method );
11157    fr = astAnnul( fr );
11158 
11159 /* If an error occurred, clear the result value. */
11160    if ( !astOK ) result = AST__BADSYSTEM;
11161 
11162 /* Return the result. */
11163    return result;
11164 }
11165 
VSet(AstObject * this_object,const char * settings,char ** text,va_list args,int * status)11166 static void VSet( AstObject *this_object, const char *settings,
11167                   char **text, va_list args, int *status ) {
11168 /*
11169 *  Name:
11170 *     VSet
11171 
11172 *  Purpose:
11173 *     Set values for a FrameSet's attributes.
11174 
11175 *  Type:
11176 *     Private function.
11177 
11178 *  Synopsis:
11179 *     #include "frameset.h"
11180 *     void VSet( AstObject *this, const char *settings, char **text,
11181 *                va_list args, int *status )
11182 
11183 *  Class Membership:
11184 *     FrameSet member function (over-rides the protected astVSet
11185 *     method inherited from the Object class).
11186 
11187 *  Description:
11188 *     This function assigns a set of attribute values for a FrameSet,
11189 *     the attributes and their values being specified by means of a
11190 *     string containing a comma-separated list of the form:
11191 *
11192 *        "attribute1 = value1, attribute2 = value2, ... "
11193 *
11194 *     Here, "attribute" specifies an attribute name and the value to
11195 *     the right of each "=" sign should be a suitable textual
11196 *     representation of the value to be assigned to that
11197 *     attribute. This will be interpreted according to the attribute's
11198 *     data type.
11199 *
11200 *     The string supplied may also contain "printf"-style format
11201 *     specifiers identified by a "%" sign in the usual way. If
11202 *     present, these will be substituted by values supplied as
11203 *     optional arguments (as a va_list variable argument list), using
11204 *     the normal "printf" rules, before the string is used.
11205 
11206 *  Parameters:
11207 *     this
11208 *        Pointer to the FrameSet.
11209 *     settings
11210 *        Pointer to a null-terminated string containing a
11211 *        comma-separated list of attribute settings.
11212 *     text
11213 *        Pointer to a location at which to return a pointer to dynamic
11214 *        memory holding a copy of the expanded setting string. This memory
11215 *        should be freed using astFree when no longer needed. If a NULL
11216 *        pointer is supplied, no string is created.
11217 *     args
11218 *        The variable argument list which contains values to be
11219 *        substituted for any "printf"-style format specifiers that
11220 *        appear in the "settings" string.
11221 *     status
11222 *        Pointer to the inherited status variable.
11223 
11224 *  Notes:
11225 *     - This function preserves the integrity of the FrameSet (if
11226 *     possible) by appropriately remapping its current Frame to take
11227 *     account of its changed attribute values.
11228 */
11229 
11230 /* Local Variables: */
11231    astDECLARE_GLOBALS            /* Declare the thread specific global data */
11232    AstFrame *save_frame;         /* Saved pointer to integrity Frame */
11233    AstFrameSet *this;            /* Pointer to FrameSet structure */
11234    char *fulltext;               /* Pointer to expanded text string */
11235    const char *save_method;      /* Saved pointer to method name */
11236    int len;                      /* Length of settings string */
11237    int ok;                       /* Status OK? */
11238    int save_lost;                /* Saved integrity modified flag */
11239 
11240 /* Initialise */
11241    if( text ) *text = NULL;
11242 
11243 /* Check the global error status. */
11244    if ( !astOK ) return;
11245 
11246 /* Get a pointer to the structure holding thread-specific global data. */
11247    astGET_GLOBALS(this_object);
11248 
11249 /* Obtain the length of the "settings" string and test it is not
11250    zero. If it is, there is nothing more to do. */
11251    len = (int) strlen( settings );
11252    if ( len != 0 ) {
11253 
11254 /* Obtain a pointer to the FrameSet structure. */
11255       this = (AstFrameSet *) this_object;
11256 
11257 /* This function may be invoked recursively (because astConvert,
11258    below, constructs a FrameSet and may require that its attributes be
11259    set). To allow this, we first save any existing FrameSet integrity
11260    information in local variables. */
11261       save_frame = integrity_frame;
11262       save_lost = integrity_lost;
11263       save_method = integrity_method;
11264 
11265 /* Set the name of the method being used (for use in error
11266    messages). */
11267       integrity_method = "astSet";
11268 
11269 /* Record the initial integrity state of the FrameSet. */
11270       RecordIntegrity( this, status );
11271 
11272 /* Invoke the parent astVSet method to set the FrameSet's attribute
11273    values and note if this succeeds. */
11274       (*parent_vset)( this_object, settings, &fulltext, args, status );
11275       ok = astOK;
11276 
11277 /* Restore the FrameSet's integrity. */
11278       RestoreIntegrity( this, status );
11279 
11280 /* If integrity could not be restored, then add contextual error
11281    information. */
11282       if ( !astOK && ok ) {
11283 
11284 /* Display the message. */
11285          astError( astStatus, "Unable to accommodate the attribute setting "
11286                                "\"%s\".", status, fulltext );
11287       }
11288 
11289 /* Restore any saved FrameSet integrity information. */
11290       integrity_frame = save_frame;
11291       integrity_lost = save_lost;
11292       integrity_method = save_method;
11293 
11294 /* If the full text of the setting string is not needed, free it.
11295    Otherwise return it. */
11296       if( text ) {
11297          *text = fulltext;
11298       } else {
11299          fulltext = astFree( fulltext );
11300       }
11301    }
11302 }
11303 
11304 /* FrameSet Attributes. */
11305 /* -------------------- */
11306 /*
11307 *att++
11308 *  Name:
11309 *     AllVariants
11310 
11311 *  Purpose:
11312 *     A list of the variant Mappings associated with the current Frame.
11313 
11314 *  Type:
11315 *     Public attribute.
11316 
11317 *  Synopsis:
11318 *     String, read-only.
11319 
11320 *  Description:
11321 *     This attrbute gives a space separated list of the names of all the
11322 *     variant Mappings associated with the current Frame (see attribute
11323 *     "Variant"). If the current Frame has no variant Mappings, then the
11324 *     list will hold a single entry equal to the Domain name of the
11325 *     current Frame.
11326 
11327 *  Applicability:
11328 *     FrameSet
11329 *        All FrameSets have this attribute.
11330 *att--
11331 */
11332 
11333 /*
11334 *att++
11335 *  Name:
11336 *     Base
11337 
11338 *  Purpose:
11339 *     FrameSet base Frame index.
11340 
11341 *  Type:
11342 *     Public attribute.
11343 
11344 *  Synopsis:
11345 *     Integer.
11346 
11347 *  Description:
11348 *     This attribute gives the index of the Frame which is to be
11349 *     regarded as the "base" Frame within a FrameSet. The default is
11350 *     the first Frame added to the FrameSet when it is created (this
11351 *     Frame always has an index of 1).
11352 
11353 *  Applicability:
11354 *     FrameSet
11355 *        All FrameSets have this attribute.
11356 
11357 *  Notes:
11358 *     - Inverting a FrameSet (inverting the boolean sense of its
11359 c     Invert attribute, with the astInvert function for example) will
11360 f     Invert attribute, with the AST_INVERT routine for example) will
11361 *     interchange the values of its Base and Current attributes.
11362 *att--
11363 */
11364 
11365 /*
11366 *att++
11367 *  Name:
11368 *     Current
11369 
11370 *  Purpose:
11371 *     FrameSet current Frame index.
11372 
11373 *  Type:
11374 *     Public attribute.
11375 
11376 *  Synopsis:
11377 *     Integer.
11378 
11379 *  Description:
11380 *     This attribute gives the index of the Frame which is to be
11381 *     regarded as the "current" Frame within a FrameSet. The default
11382 *     is the most recent Frame added to the FrameSet (this Frame
11383 *     always has an index equal to the FrameSet's Nframe attribute).
11384 
11385 *  Applicability:
11386 *     FrameSet
11387 *        All FrameSets have this attribute.
11388 
11389 *  Notes:
11390 *     - Inverting a FrameSet (inverting the boolean sense of its
11391 c     Invert attribute, with the astInvert function for example) will
11392 f     Invert attribute, with the AST_INVERT routine for example) will
11393 *     interchange the values of its Base and Current attributes.
11394 *att--
11395 */
11396 
11397 /*
11398 *att++
11399 *  Name:
11400 *     Nframe
11401 
11402 *  Purpose:
11403 *     Number of Frames in a FrameSet.
11404 
11405 *  Type:
11406 *     Public attribute.
11407 
11408 *  Synopsis:
11409 *     Integer, read-only.
11410 
11411 *  Description:
11412 *     This attrbute gives the number of Frames in a FrameSet. This
11413 *     value will change as Frames are added or removed, but will
11414 *     always be at least one.
11415 
11416 *  Applicability:
11417 *     FrameSet
11418 *        All FrameSets have this attribute.
11419 *att--
11420 */
11421 
11422 /*
11423 *att++
11424 *  Name:
11425 *     Variant
11426 
11427 *  Purpose:
11428 *     Indicates which variant of the current Frame is to be used.
11429 
11430 *  Type:
11431 *     Public attribute.
11432 
11433 *  Synopsis:
11434 *     String.
11435 
11436 *  Description:
11437 *     This attribute can be used to change the Mapping that connects the
11438 *     current Frame to the other Frames in the FrameSet. By default, each
11439 *     Frame in a FrameSet is connected to the other Frames by a single
11440 *     Mapping that can only be changed by using the
11441 c     astRemapFrame
11442 f     AST_REMAPFRAME
11443 *     method. However, it is also possible to associate multiple Mappings
11444 *     with a Frame, each Mapping having an identifying name. If this is
11445 *     done, the "Variant" attribute can be set to indicate the name of
11446 *     the Mapping that is to be used with the current Frame.
11447 *
11448 *     A possible (if unlikely) use-case is to create a FrameSet that can
11449 *     be used to describe the WCS of an image formed by co-adding images
11450 *     of two different parts of the sky. In such an image, each pixel contains
11451 *     flux from two points on the sky.and so the WCS for the image should
11452 *     ideally contain one pixel Frame and two SkyFrames - one describing
11453 *     each of the two co-added images. There is nothing to prevent a
11454 *     FrameSet containing two explicit SkyFrames, but the problem then arises
11455 *     of how to distinguish between them. The two primary characteristics of
11456 *     a Frame that distinguishes it from other Frames ar eits class and its
11457 *     Domain attribute value. The class of a Frame cannot be changed, but we
11458 *     could in principle use two different Domain values to distinguish the
11459 *     two SkyFrames. However, in practice it is not uncommon for application
11460 *     software to assume that SkyFrames will have the default Domain value
11461 *     of "SKY". That is, instead of searching for Frames that have a class
11462 *     of "SkyFrame", such software searches for Frames that have a Domain
11463 *     of "SKY". To alleviate this problem, it is possible to add a single
11464 *     SkyFrame to the FrameSet, but specifying two alternate Mappings to
11465 *     use with the SkyFrame. Setting the "Variant" attribute to the name
11466 *     of one or the other of these alternate Mappings will cause the
11467 *     SkyFrame to be remapped within the FrameSet so that it uses the
11468 *     specified Mapping. The same facility can be used with any class of
11469 *     Frame, not just SkyFrames.
11470 *
11471 *     To use this facility, the Frame should first be added to the
11472 *     FrameSet in the usual manner using the
11473 c     astAddFrame method. By default, the Mapping supplied to astAddFrame
11474 f     AST_ADDFRAME method. By default, the Mapping supplied to AST_ADDVARIANT
11475 *     is assigned a name equal to the Domain name of the Frame. To assign a
11476 *     different name to it, the
11477 c     astAddVariant
11478 f     AST_ADDVARIANT
11479 *     method should then be called specifying the required name and a NULL
11480 *     Mapping. The
11481 c     astAddFrame
11482 f     AST_ADDFRAME
11483 *     method should then be called repeatedly to add each required extra
11484 *     Mapping to the current Frame, supplying a unique name for each one.
11485 *
11486 *     Each Frame in a FrameSet can have its own set of variant Mappings.
11487 *     To control the Mappings in use with a specific Frame, you need first
11488 *     to make it the current Frame in the FrameSet.
11489 *
11490 *     The
11491 c     astMirrorVariants function
11492 f     AST_MIRRORVARIANTS routine
11493 *     allows the effects of variant Mappings associated with a nominated
11494 *     Frame to be propagated to other Frames in the FrameSet.
11495 *
11496 *     Once this has been done, setting a new value for the "Variant"
11497 *     attribute of a FrameSet will cause the current Frame in the
11498 *     FrameSet to be remapped to use the specified variant Mapping. An
11499 *     error will be reported if the current Frame has no variant Mapping
11500 *     with the supplied name.
11501 *
11502 *     Getting the value of the "Variant" attribute will return the name
11503 *     of the variant Mapping currently in use with the current Frame. If
11504 *     the Frame has no variant Mappings, the value will default to the
11505 *     Domain name of the current Frame.
11506 *
11507 *     Clearing the "Variant" attribute will have the effect of removing
11508 *     all variant Mappings (except for the currently selected Mapping) from
11509 *     the current Frame.
11510 *
11511 *     Testing the "Variant" attribute will return
11512 c     a non-zero value
11513 f     .TRUE.
11514 *     if the current Frame contains any variant Mappings, and
11515 c     zero
11516 f     .FALSE.
11517 *     otherwise.
11518 *
11519 *     A complete list of the names associated with all the available
11520 *     variant Mappings in the current Frame can be obtained from the
11521 *     AllVariants attribute.
11522 *
11523 *     If a Frame with variant Mappings is remapped using the
11524 c     astRemapFrame
11525 f     AST_REMAPFRAME
11526 *     method, the currently selected variant Mapping is used by
11527 c     astRemapFrame
11528 f     AST_REMAPFRAME
11529 *     and the other variant Mappings are removed from the Frame.
11530 
11531 *  Applicability:
11532 *     FrameSet
11533 *        All FrameSets have this attribute.
11534 *att--
11535 */
11536 
11537 /* Access to attributes of the current Frame. */
11538 /* ------------------------------------------ */
11539 /* Use the macros defined at the start of this file to implement
11540    private member functions that give access to the attributes of the
11541    current Frame of a FrameSet and its axes. These functions over-ride
11542    the attribute access methods inherited from the Frame class. */
11543 
11544 /* Clear, Get, Set and Test axis-independent Frame attributes. */
11545 MAKE_CLEAR(Digits)
MAKE_CLEAR(Domain)11546 MAKE_CLEAR(Domain)
11547 MAKE_CLEAR(MatchEnd)
11548 MAKE_CLEAR(MaxAxes)
11549 MAKE_CLEAR(MinAxes)
11550 MAKE_CLEAR(Permute)
11551 MAKE_CLEAR(PreserveAxes)
11552 MAKE_CLEAR(Title)
11553 
11554 MAKE_GET(Digits,int)
11555 MAKE_GET(Domain,const char *)
11556 MAKE_GET(MatchEnd,int)
11557 MAKE_GET(MaxAxes,int)
11558 MAKE_GET(MinAxes,int)
11559 MAKE_GET(Permute,int)
11560 MAKE_GET(PreserveAxes,int)
11561 MAKE_GET(Title,const char *)
11562 MAKE_SET(Digits,int)
11563 MAKE_SET(Domain,const char *)
11564 MAKE_SET(MatchEnd,int)
11565 MAKE_SET(MaxAxes,int)
11566 MAKE_SET(MinAxes,int)
11567 MAKE_SET(Permute,int)
11568 MAKE_SET(PreserveAxes,int)
11569 MAKE_SET(Title,const char *)
11570 MAKE_TEST(Digits)
11571 MAKE_TEST(Domain)
11572 MAKE_TEST(MatchEnd)
11573 MAKE_TEST(MaxAxes)
11574 MAKE_TEST(MinAxes)
11575 MAKE_TEST(Permute)
11576 MAKE_TEST(PreserveAxes)
11577 MAKE_TEST(Title)
11578 
11579 MAKE_GET(ActiveUnit,int)
11580 MAKE_SET(ActiveUnit,int)
11581 MAKE_TEST(ActiveUnit)
11582 
11583 MAKE_GET(System,AstSystemType)
11584 MAKE_SET(System,AstSystemType)
11585 MAKE_TEST(System)
11586 MAKE_CLEAR(System)
11587 
11588 MAKE_GET(AlignSystem,AstSystemType)
11589 MAKE_SET(AlignSystem,AstSystemType)
11590 MAKE_TEST(AlignSystem)
11591 MAKE_CLEAR(AlignSystem)
11592 
11593 MAKE_GET(Epoch,double)
11594 MAKE_SET(Epoch,double)
11595 MAKE_TEST(Epoch)
11596 MAKE_CLEAR(Epoch)
11597 
11598 MAKE_GET(ObsLon,double)
11599 MAKE_SET(ObsLon,double)
11600 MAKE_TEST(ObsLon)
11601 MAKE_CLEAR(ObsLon)
11602 
11603 MAKE_GET(ObsLat,double)
11604 MAKE_SET(ObsLat,double)
11605 MAKE_TEST(ObsLat)
11606 MAKE_CLEAR(ObsLat)
11607 
11608 MAKE_GET(ObsAlt,double)
11609 MAKE_SET(ObsAlt,double)
11610 MAKE_TEST(ObsAlt)
11611 MAKE_CLEAR(ObsAlt)
11612 
11613 /* Clear, Get, Set and Test axis-dependent Frame attributes. */
11614 MAKE_CLEAR_AXIS(Direction)
11615 MAKE_CLEAR_AXIS(Format)
11616 MAKE_CLEAR_AXIS(Label)
11617 MAKE_CLEAR_AXIS(Symbol)
11618 MAKE_CLEAR_AXIS(Unit)
11619 MAKE_GET_AXIS(Direction,int)
11620 MAKE_GET_AXIS(Format,const char *)
11621 MAKE_GET_AXIS(Label,const char *)
11622 MAKE_GET_AXIS(Symbol,const char *)
11623 MAKE_GET_AXIS(Unit,const char *)
11624 MAKE_SET_AXIS(Direction,int)
11625 MAKE_SET_AXIS(Format,const char *)
11626 MAKE_SET_AXIS(Label,const char *)
11627 MAKE_SET_AXIS(Symbol,const char *)
11628 MAKE_SET_AXIS(Unit,const char *)
11629 MAKE_TEST_AXIS(Direction)
11630 MAKE_TEST_AXIS(Format)
11631 MAKE_TEST_AXIS(Label)
11632 MAKE_TEST_AXIS(Symbol)
11633 MAKE_TEST_AXIS(Unit)
11634 
11635 MAKE_GET_AXIS(Bottom,double)
11636 MAKE_SET_AXIS(Bottom,double)
11637 MAKE_TEST_AXIS(Bottom)
11638 MAKE_CLEAR_AXIS(Bottom)
11639 
11640 MAKE_GET_AXIS(Top,double)
11641 MAKE_SET_AXIS(Top,double)
11642 MAKE_TEST_AXIS(Top)
11643 MAKE_CLEAR_AXIS(Top)
11644 
11645 /* Copy constructor. */
11646 /* ----------------- */
11647 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
11648 /*
11649 *  Name:
11650 *     Copy
11651 
11652 *  Purpose:
11653 *     Copy constructor for FrameSet objects.
11654 
11655 *  Type:
11656 *     Private function.
11657 
11658 *  Synopsis:
11659 *     void Copy( const AstObject *objin, AstObject *objout, int *status )
11660 
11661 *  Description:
11662 *     This function implements the copy constructor for FrameSet objects.
11663 
11664 *  Parameters:
11665 *     objin
11666 *        Pointer to the object to be copied.
11667 *     objout
11668 *        Pointer to the object being constructed.
11669 *     status
11670 *        Pointer to the inherited status variable.
11671 
11672 *  Notes:
11673 *     -  This constructor makes a deep copy.
11674 */
11675 
11676 /* Local Variables: */
11677    AstFrameSet *in;              /* Pointer to input FrameSet */
11678    AstFrameSet *out;             /* Pointer to output FrameSet */
11679    int iframe;                   /* Loop counter for Frames */
11680    int inode;                    /* Loop counter for nodes */
11681 
11682 /* Check the global error status. */
11683    if ( !astOK ) return;
11684 
11685 /* Obtain pointers to the input and output FrameSets. */
11686    in = (AstFrameSet *) objin;
11687    out = (AstFrameSet *) objout;
11688 
11689 /* For safety, first clear any references to the input memory from
11690    the output FrameSet. */
11691    out->frame = NULL;
11692    out->varfrm = NULL;
11693    out->node = NULL;
11694    out->map = NULL;
11695    out->link = NULL;
11696    out->invert = NULL;
11697 
11698 /* Allocate memory in the output FrameSet to store the Frame and node
11699    information and copy scalar information across. */
11700    out->frame = astMalloc( sizeof( AstFrame * ) * (size_t) in->nframe );
11701    out->varfrm = astStore( NULL, in->varfrm, sizeof( int ) *
11702                                          (size_t) in->nframe );
11703    out->node = astStore( NULL, in->node, sizeof( int ) *
11704                                          (size_t) in->nframe );
11705    out->map = astMalloc( sizeof( AstMapping * ) * (size_t) ( in->nnode - 1 ) );
11706    out->link = astStore( NULL, in->link, sizeof( int ) *
11707                                          (size_t) ( in->nnode - 1 ) );
11708    out->invert = astStore( NULL, in->invert, sizeof( int ) *
11709                                          (size_t) ( in->nnode - 1 ) );
11710 
11711 /* If OK, make copies of each input Frame and Mapping and store the
11712    resulting pointers in the output FrameSet. */
11713    if ( astOK ) {
11714       for ( iframe = 0; iframe < in->nframe; iframe++ ) {
11715          out->frame[ iframe ] = astCopy( in->frame[ iframe ] );
11716       }
11717       for ( inode = 0; inode < in->nnode - 1; inode++ ) {
11718          out->map[ inode ] = astCopy( in->map[ inode ] );
11719       }
11720 
11721 /* If an error occurred while copying any of these objects, clean up
11722    by looping through the arrays of pointers again and annulling them
11723    all. */
11724       if ( !astOK ) {
11725          for ( iframe = 0; iframe < in->nframe; iframe++ ) {
11726             out->frame[ iframe ] = astAnnul( out->frame[ iframe ] );
11727          }
11728          for ( inode = 0; inode < in->nnode - 1; inode++ ) {
11729             out->map[ inode ] = astAnnul( out->map[ inode ] );
11730          }
11731       }
11732    }
11733 
11734 /* If an error occurred, clean up by freeing all memory allocated above. */
11735    if ( !astOK ) {
11736       out->frame = astFree( out->frame );
11737       out->varfrm = astFree( out->varfrm );
11738       out->node = astFree( out->node );
11739       out->map = astFree( out->map );
11740       out->link = astFree( out->link );
11741       out->invert = astFree( out->invert );
11742    }
11743 }
11744 
11745 /* Destructor. */
11746 /* ----------- */
Delete(AstObject * obj,int * status)11747 static void Delete( AstObject *obj, int *status ) {
11748 /*
11749 *  Name:
11750 *     Delete
11751 
11752 *  Purpose:
11753 *     Destructor for FrameSet objects.
11754 
11755 *  Type:
11756 *     Private function.
11757 
11758 *  Synopsis:
11759 *     void Delete( AstObject *obj, int *status )
11760 
11761 *  Description:
11762 *     This function implements the destructor for FrameSet objects.
11763 
11764 *  Parameters:
11765 *     obj
11766 *        Pointer to the object to be deleted.
11767 *     status
11768 *        Pointer to the inherited status variable.
11769 
11770 *  Notes:
11771 *     This function attempts to execute even if the global error status is
11772 *     set.
11773 */
11774 
11775 /* Local Variables: */
11776    AstFrameSet *this;               /* Pointer to FrameSet */
11777    int iframe;                      /* Loop counter for Frames */
11778    int inode;                       /* Loop counter for nodes */
11779 
11780 /* Obtain a pointer to the FrameSet structure. */
11781    this = (AstFrameSet *) obj;
11782 
11783 /* Annul all Frame pointers and clear the node numbers associated with
11784    them. */
11785    for ( iframe = 0; iframe < this->nframe; iframe++ ) {
11786       this->frame[ iframe ] = astAnnul( this->frame[ iframe ] );
11787       this->node[ iframe ] = 0;
11788    }
11789 
11790 /* Annul all Mapping pointers and clear the links between pairs of
11791    nodes and the associated Mapping Invert information. */
11792    for ( inode = 0; inode < this->nnode - 1; inode++ ) {
11793       this->map[ inode ] = astAnnul( this->map[ inode ] );
11794       this->link[ inode ] = 0;
11795       this->invert[ inode ] = 0;
11796    }
11797 
11798 /* Free all allocated memory. */
11799    this->frame = astFree( this->frame );
11800    this->varfrm = astFree( this->varfrm );
11801    this->node = astFree( this->node );
11802    this->map = astFree( this->map );
11803    this->link = astFree( this->link );
11804    this->invert = astFree( this->invert );
11805 }
11806 
11807 /* Dump function. */
11808 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)11809 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
11810 /*
11811 *  Name:
11812 *     Dump
11813 
11814 *  Purpose:
11815 *     Dump function for FrameSet objects.
11816 
11817 *  Type:
11818 *     Private function.
11819 
11820 *  Synopsis:
11821 *     void Dump( AstObject *this, AstChannel *channel, int *status )
11822 
11823 *  Description:
11824 *     This function implements the Dump function which writes out data
11825 *     for the FrameSet class to an output Channel.
11826 
11827 *  Parameters:
11828 *     this
11829 *        Pointer to the FrameSet whose data are being written.
11830 *     channel
11831 *        Pointer to the Channel to which the data are being written.
11832 *     status
11833 *        Pointer to the inherited status variable.
11834 */
11835 
11836 /* Local Constants: */
11837 #define COMMENT_LEN 150          /* Maximum length of a comment string */
11838 #define KEY_LEN 50               /* Maximum length of a keyword */
11839 
11840 /* Local Variables: */
11841    AstFrameSet *this;            /* Pointer to the FrameSet structure */
11842    char comment[ COMMENT_LEN + 1 ]; /* Buffer for comment string */
11843    char key[ KEY_LEN + 1 ];      /* Buffer for keyword string */
11844    int ifr;                      /* Loop counter for Frames */
11845    int inode;                    /* Loop counter for nodes */
11846    int invert;                   /* Invert attribute value */
11847    int ival;                     /* Integer value */
11848    int set;                      /* Attribute value set? */
11849 
11850 /* Check the global error status. */
11851    if ( !astOK ) return;
11852 
11853 /* Obtain a pointer to the FrameSet structure. */
11854    this = (AstFrameSet *) this_object;
11855 
11856 /* Determine if the FrameSet is inverted. This is required so that the
11857    effects of inversion can be un-done to obtain information about the
11858    "true" Base and Current Frames. (The values written are "internal"
11859    values that are not affected by the Invert setting.) */
11860    invert = astGetInvert( this );
11861 
11862 /* Write out values representing the instance variables for the
11863    FrameSet class.  Accompany these with appropriate comment strings,
11864    possibly depending on the values being written.*/
11865 
11866 /* In the case of attributes, we first use the appropriate (private)
11867    Test...  member function to see if they are set. If so, we then use
11868    the (private) Get... function to obtain the value to be written
11869    out.
11870 
11871    For attributes which are not set, we use the astGet... method to
11872    obtain the value instead. This will supply a default value
11873    (possibly provided by a derived class which over-rides this method)
11874    which is more useful to a human reader as it corresponds to the
11875    actual default attribute value.  Since "set" will be zero, these
11876    values are for information only and will not be read back. */
11877 
11878 /* Nframe. */
11879 /* ------- */
11880    set = ( this->nframe != 0 );
11881    ival = set ? this->nframe : astGetNframe( this );
11882    astWriteInt( channel, "Nframe", set, 1, ival,
11883                 "Number of Frames in FrameSet" );
11884 
11885 /* Base. */
11886 /* ----- */
11887    set = ( this->base != -INT_MAX );
11888    ival = set ? this->base : ( !invert ? astGetBase( this ) :
11889                                          astGetCurrent( this ) );
11890    astWriteInt( channel, "Base", set, 1, ival, "Index of base Frame" );
11891 
11892 /* Current. */
11893 /* -------- */
11894    set = ( this->current != -INT_MAX );
11895    ival = set ? this->current : ( !invert ? astGetCurrent( this ) :
11896                                             astGetBase( this ) );
11897    astWriteInt( channel, "Currnt", set, 1, ival, "Index of current Frame" );
11898 
11899 /* Number of nodes. */
11900 /* ---------------- */
11901    ival = this->nnode;
11902    set = ( ival != this->nframe );
11903    astWriteInt( channel, "Nnode", set, 0, ival,
11904                 "Number of nodes in FrameSet" );
11905 
11906 /* Node index for each Frame. */
11907 /* -------------------------- */
11908 /* There is a node value for each Frame in the FrameSet. */
11909    for ( ifr = 1; ifr <= this->nframe; ifr++ ) {
11910 
11911 /* Convert node numbering to start at 1 for the external
11912    representation. Regard a node number as "set" if it differs from
11913    the Frame number. */
11914       ival = this->node[ ifr - 1 ] + 1;
11915       set = ( ival != ifr );
11916 
11917 /* Create a suitable keyword and comment. */
11918       (void) sprintf( key, "Nod%d", ifr );
11919       (void) sprintf( comment,
11920                       "Frame %d is associated with node %d", ifr, ival );
11921 
11922 /* Write out the value. */
11923       astWriteInt( channel, key, set, 0, ival, comment );
11924    }
11925 
11926 /* Index of variants Frame for each Frame. */
11927 /* --------------------------------------- */
11928    for ( ifr = 1; ifr <= this->nframe; ifr++ ) {
11929 
11930 /* Retain the one-based Frame index values in varfrm. Regard a number as
11931    "set" if it is greater than zero. */
11932       ival = this->varfrm[ ifr - 1 ];
11933       set = ( ival > 0 );
11934 
11935 /* Create a suitable keyword and comment. */
11936       (void) sprintf( key, "VFr%d", ifr );
11937       (void) sprintf( comment,
11938                       "Frame %d inherits variants from Frame %d", ifr, ival );
11939 
11940 /* Write out the value. */
11941       astWriteInt( channel, key, set, 0, ival, comment );
11942    }
11943 
11944 /* Links between nodes. */
11945 /* -------------------- */
11946 /* Each node in the FrameSet (except the first) has a link to another
11947    node from which it is derived. */
11948    for ( inode = 1; inode < this->nnode; inode++ ) {
11949 
11950 /* Convert node numbering to start at 1 (as above). */
11951       ival = this->link[ inode - 1 ] + 1;
11952       (void) sprintf( key, "Lnk%d", inode + 1 );
11953       (void) sprintf( comment,
11954                       "Node %d is derived from node %d", inode + 1, ival );
11955       astWriteInt( channel, key, 1, 0, ival, comment );
11956 
11957 /* Inversion flags. */
11958 /* ---------------- */
11959 /* Each node with a link has a value which the Invert attribute of the
11960    associated Mapping should have when the transformation from the
11961    parent node to the node in question is required. */
11962       ival = this->invert[ inode - 1 ];
11963 
11964 /* Regard the value as set only if the Mapping's inverse
11965    transformation is required. */
11966       set = ( ival != 0 );
11967       (void) sprintf( key, "Inv%d", inode + 1 );
11968       astWriteInt( channel, key, set, 0, ival,
11969                    ival ? "The inverse mapping is used" :
11970                           "The forward mapping is used" );
11971    }
11972 
11973 /* Frame objects. */
11974 /* -------------- */
11975 /* Output an Object description for each Frame in the FrameSet. */
11976    for ( ifr = 1; ifr <= this->nframe; ifr++ ) {
11977       (void) sprintf( key, "Frm%d", ifr );
11978       (void) sprintf( comment, "Frame number %d", ifr );
11979       astWriteObject( channel, key, 1, 1, this->frame[ ifr - 1 ],
11980                       comment );
11981    }
11982 
11983 /* Mapping objects. */
11984 /* ---------------- */
11985 /* Output an Object description for each Mapping in the FrameSet. */
11986    for ( inode = 1; inode < this->nnode; inode++ ) {
11987       (void) sprintf( key, "Map%d", inode + 1 );
11988       (void) sprintf( comment, "Mapping between nodes %d and %d",
11989                       this->link[ inode - 1 ] + 1, inode + 1 );
11990       astWriteObject( channel, key, 1, 1, this->map[ inode - 1 ], comment );
11991    }
11992 
11993 /* Undefine macros local to this function. */
11994 #undef COMMENT_LEN
11995 #undef KEY_LEN
11996 }
11997 
11998 /* Standard class functions. */
11999 /* ========================= */
12000 /* Implement the astIsAFrameSet and astCheckFrameSet functions using
12001    the macros defined for this purpose in the "object.h" header
12002    file. */
astMAKE_ISA(FrameSet,Frame)12003 astMAKE_ISA(FrameSet,Frame)
12004 astMAKE_CHECK(FrameSet)
12005 
12006 AstFrameSet *astFrameSet_( void *frame_void, const char *options, int *status, ...) {
12007 /*
12008 *+
12009 *  Name:
12010 *     astFrameSet
12011 
12012 *  Purpose:
12013 *     Create a FrameSet.
12014 
12015 *  Type:
12016 *     Protected function.
12017 
12018 *  Synopsis:
12019 *     #include "frameset.h"
12020 *     AstFrameSet *astFrameSet( AstFrame *frame, const char *options, int *status, ... )
12021 
12022 *  Class Membership:
12023 *     FrameSet constructor.
12024 
12025 *  Description:
12026 *     This function creates a new FrameSet and optionally initialises
12027 *     its attributes.
12028 
12029 *  Parameters:
12030 *     frame
12031 *        Pointer to the initial Frame. If this is not a FrameSet, the
12032 *        new FrameSet will be initialised to contain this Frame alone.
12033 *
12034 *        If it is a FrameSet, the new FrameSet will be initialised to
12035 *        contain the same Frames (and Mappings) and to have the same
12036 *        attribute values as the one supplied. This is similar to
12037 *        making a copy, except that the Frames (and Mappings)
12038 *        contained in the original FrameSet are not themselves copied,
12039 *        but are shared by both FrameSets.
12040 *     options
12041 *        Pointer to a null terminated string containing an optional
12042 *        comma-separated list of attribute assignments to be used for
12043 *        initialising the new FrameSet. The syntax used is the same as
12044 *        for the astSet method and may include "printf" format
12045 *        specifiers identified by "%" symbols in the normal way.
12046 *     status
12047 *        Pointer to the inherited status variable.
12048 *     ...
12049 *        If the "options" string contains "%" format specifiers, then
12050 *        an optional list of arguments may follow it in order to
12051 *        supply values to be substituted for these specifiers. The
12052 *        rules for supplying these are identical to those for the
12053 *        astSet method (and for the C "printf" function).
12054 
12055 *  Returned Value:
12056 *     A pointer to the new FrameSet.
12057 
12058 *  Notes:
12059 *     - A NULL pointer will be returned if this function is invoked
12060 *     with the global error status set, or if it should fail for any
12061 *     reason.
12062 *-
12063 
12064 *  Implementation Notes:
12065 *     - This function implements the basic FrameSet constructor which
12066 *     is available via the protected interface to the FrameSet class.
12067 *     A public interface is provided by the astFrameSetId_ function.
12068 *     - Because this function has a variable argument list, it is
12069 *     invoked by a macro that evaluates to a function pointer (not a
12070 *     function invocation) and no checking or casting of arguments is
12071 *     performed before the function is invoked. Because of this, the
12072 *     "frame" parameter is of type (void *) and is converted and
12073 *     validated within the function itself.
12074 */
12075 
12076 /* Local Variables: */
12077    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
12078    AstFrame *frame;              /* Pointer to Frame structure */
12079    AstFrameSet *new;             /* Pointer to new FrameSet */
12080    va_list args;                 /* Variable argument list */
12081 
12082 /* Initialise. */
12083    new = NULL;
12084 
12085 /* Get a pointer to the thread specific global data structure. */
12086    astGET_GLOBALS(NULL);
12087 
12088 /* Check the global status. */
12089    if ( !astOK ) return new;
12090 
12091 /* Obtain and validate a pointer to the Frame structure provided. */
12092    frame = astCheckFrame( frame_void );
12093    if ( astOK ) {
12094 
12095 /* Initialise the FrameSet, allocating memory and initialising the
12096    virtual function table as well if necessary. */
12097       new = astInitFrameSet( NULL, sizeof( AstFrameSet ), !class_init,
12098                              &class_vtab, "FrameSet", frame );
12099 
12100 /* If successful, note that the virtual function table has been
12101    initialised. */
12102       if ( astOK ) {
12103          class_init = 1;
12104 
12105 /* Obtain the variable argument list and pass it along with the
12106    options string to the astVSet method to initialise the new
12107    FrameSet's attributes. */
12108          va_start( args, status );
12109          astVSet( new, options, NULL, args );
12110          va_end( args );
12111 
12112 /* If an error occurred, clean up by deleting the new object. */
12113          if ( !astOK ) new = astDelete( new );
12114       }
12115    }
12116 
12117 /* Return a pointer to the new FrameSet. */
12118    return new;
12119 }
12120 
astInitFrameSet_(void * mem,size_t size,int init,AstFrameSetVtab * vtab,const char * name,AstFrame * frame,int * status)12121 AstFrameSet *astInitFrameSet_( void *mem, size_t size, int init,
12122                                AstFrameSetVtab *vtab, const char *name,
12123                                AstFrame *frame, int *status ) {
12124 /*
12125 *+
12126 *  Name:
12127 *     astInitFrameSet
12128 
12129 *  Purpose:
12130 *     Initialise a FrameSet.
12131 
12132 *  Type:
12133 *     Protected function.
12134 
12135 *  Synopsis:
12136 *     #include "frameset.h"
12137 *     AstFrameSet *astInitFrameSet( void *mem, size_t size, int init,
12138 *                                   AstFrameSetVtab *vtab, const char *name,
12139 *                                   AstFrame *frame )
12140 
12141 *  Class Membership:
12142 *     FrameSet initialiser.
12143 
12144 *  Description:
12145 *     This function is provided for use by class implementations to
12146 *     initialise a new FrameSet object. It allocates memory (if
12147 *     necessary) to accommodate the FrameSet plus any additional data
12148 *     associated with the derived class.  It then initialises a
12149 *     FrameSet structure at the start of this memory. If the "init"
12150 *     flag is set, it also initialises the contents of a virtual
12151 *     function table for a FrameSet at the start of the memory passed
12152 *     via the "vtab" parameter.
12153 
12154 *  Parameters:
12155 *     mem
12156 *        A pointer to the memory in which the FrameSet is to be
12157 *        created. This must be of sufficient size to accommodate the
12158 *        FrameSet data (sizeof(FrameSet)) plus any data used by the
12159 *        derived class. If a value of NULL is given, this function
12160 *        will allocate the memory itself using the "size" parameter to
12161 *        determine its size.
12162 *     size
12163 *        The amount of memory used by the FrameSet (plus derived class
12164 *        data).  This will be used to allocate memory if a value of
12165 *        NULL is given for the "mem" parameter. This value is also
12166 *        stored in the FrameSet structure, so a valid value must be
12167 *        supplied even if not required for allocating memory.
12168 *     init
12169 *        A logical flag indicating if the FrameSet's virtual function
12170 *        table is to be initialised. If this value is non-zero, the
12171 *        virtual function table will be initialised by this function.
12172 *     vtab
12173 *        Pointer to the start of the virtual function table to be
12174 *        associated with the new FrameSet.
12175 *     name
12176 *        Pointer to a constant null-terminated character string which
12177 *        contains the name of the class to which the new object
12178 *        belongs (it is this pointer value that will subsequently be
12179 *        returned by the astGetClass method).
12180 *     frame
12181 *        Pointer to the initial Frame (or FrameSet).
12182 
12183 *  Returned Value:
12184 *     A pointer to the new FrameSet.
12185 
12186 *  Notes:
12187 *     - A null pointer will be returned if this function is invoked
12188 *     with the global error status set, or if it should fail for any
12189 *     reason.
12190 *-
12191 */
12192 
12193 /* Local Variables: */
12194    AstFrameSet *new;                /* Pointer to new FrameSet */
12195    AstFrameSet *old;                /* Pointer to original FrameSet */
12196    int iframe;                      /* Loop counter for Frames */
12197    int inode;                       /* Loop counter for nodes */
12198 
12199 /* Check the global status. */
12200    if ( !astOK ) return NULL;
12201 
12202 /* If necessary, initialise the virtual function table. */
12203    if ( init ) astInitFrameSetVtab( vtab, name );
12204 
12205 /* Initialise a Frame structure (the parent class) as the first
12206    component within the FrameSet structure, allocating memory if
12207    necessary. Give this Frame zero axes, as all axis information for
12208    the FrameSet will be derived from the Frames it contains. */
12209    new = (AstFrameSet *) astInitFrame( mem, size, 0,
12210                                        (AstFrameVtab *) vtab, name, 0 );
12211 
12212    if ( astOK ) {
12213 
12214 /* Initialise the FrameSet data. */
12215 /* ----------------------------- */
12216 
12217 /* Normal Frame supplied. */
12218 /* ---------------------- */
12219 /* Check that the Frame supplied is not a FrameSet (initialising using
12220    a FrameSet is a special case which is handled below).  If not, we
12221    initialise the new FrameSet to refer to a single Frame. */
12222       if ( !astIsAFrameSet( frame ) && astOK ) {
12223 
12224 /* Allocate memory for the arrays of Frame information. */
12225          new->frame = astMalloc( sizeof( AstFrame * ) );
12226          new->node = astMalloc( sizeof( int ) );
12227          new->varfrm = astMalloc( sizeof( int ) );
12228 
12229 /* The node arrays are not required until at least two Frames are
12230    present. */
12231          new->map = NULL;
12232          new->link = NULL;
12233          new->invert = NULL;
12234 
12235 /* If OK, initialise these arrays, thus adding the Frame to the
12236    FrameSet. */
12237          if ( astOK ) {
12238             new->frame[ 0 ] = astClone( frame );
12239             new->node[ 0 ] = 0;
12240             new->varfrm[ 0 ] = 0;
12241             new->nframe = 1;
12242             new->nnode = 1;
12243 
12244 /* Initialise the FrameSet attributes to their undefined states. */
12245             new->base = -INT_MAX;
12246             new->current = -INT_MAX;
12247          }
12248 
12249 /* FrameSet supplied. */
12250 /* ------------------ */
12251 /* If a FrameSet was supplied, we will initialise the new FrameSet to
12252    refer to the same Frame and Mapping information (this is similar to
12253    making a copy, except that we clone all the pointers, instead of
12254    copying the Objects they refer to). */
12255       } else if ( astOK ) {
12256 
12257 /* Obtain a pointer to the original FrameSet structure. */
12258          old = (AstFrameSet *) frame;
12259 
12260 /* Allocate memory in the new FrameSet to store the Frame and node
12261    information and copy any scalar information across. */
12262          new->frame = astMalloc( sizeof( AstFrame * ) * (size_t) old->nframe );
12263          new->node = astStore( NULL, old->node,
12264                                sizeof( int ) * (size_t) old->nframe );
12265          new->varfrm = astStore( NULL, old->varfrm,
12266                                sizeof( int ) * (size_t) old->nframe );
12267          new->map = astMalloc( sizeof( AstMapping * ) *
12268                                (size_t) ( old->nnode - 1 ) );
12269          new->link = astStore( NULL, old->link,
12270                                sizeof( int ) * (size_t) ( old->nnode - 1 ) );
12271          new->invert = astStore( NULL, old->invert,
12272                                  sizeof( int ) * (size_t) ( old->nnode - 1 ) );
12273 
12274 /* If OK, clone the pointer to each Frame and Mapping referenced by
12275    the original FrameSet and store the resulting pointers in the new
12276    FrameSet. */
12277          if ( astOK ) {
12278             for ( iframe = 0; iframe < old->nframe; iframe++ ) {
12279                new->frame[ iframe ] = astClone( old->frame[ iframe ] );
12280             }
12281             for ( inode = 0; inode < old->nnode - 1; inode++ ) {
12282                new->map[ inode ] = astClone( old->map[ inode ] );
12283             }
12284 
12285 /* If an error occurred while cloning any of these pointers, clean up
12286    by looping through the arrays of cloned pointers again and
12287    annulling them all. */
12288             if ( !astOK ) {
12289                for ( iframe = 0; iframe < old->nframe; iframe++ ) {
12290                   new->frame[ iframe ] = astAnnul( new->frame[ iframe ] );
12291                }
12292                for ( inode = 0; inode < old->nnode - 1; inode++ ) {
12293                   new->map[ inode ] = astAnnul( new->map[ inode ] );
12294                }
12295             }
12296          }
12297 
12298 /* If an error occurred, clean up by freeing all memory allocated
12299    above. */
12300          if ( !astOK ) {
12301             new->frame = astFree( new->frame );
12302             new->node = astFree( new->node );
12303             new->varfrm = astFree( new->varfrm );
12304             new->map = astFree( new->map );
12305             new->link = astFree( new->link );
12306             new->invert = astFree( new->invert );
12307          }
12308 
12309 /* Copy the Frame and node counts across. */
12310          new->nframe = old->nframe;
12311          new->nnode = old->nnode;
12312 
12313 /* Copy the other FrameSet attributes across. */
12314          new->base = old->base;
12315          new->current = old->current;
12316 
12317 /* Transfer any other inherited attribute values that relate to the
12318    FrameSet itself (rather than the enclosed Frames). */
12319         if ( astTestInvert( old ) ) astSetInvert( new, astGetInvert( old ) );
12320       }
12321 
12322 /* If an error occurred, clean up by deleting the new object. */
12323       if ( !astOK ) new = astDelete( new );
12324    }
12325 
12326 /* Return a pointer to the new object. */
12327    return new;
12328 
12329 /* Undefine macros local to this function. */
12330 #undef TRANSFER
12331 }
12332 
astLoadFrameSet_(void * mem,size_t size,AstFrameSetVtab * vtab,const char * name,AstChannel * channel,int * status)12333 AstFrameSet *astLoadFrameSet_( void *mem, size_t size,
12334                                AstFrameSetVtab *vtab, const char *name,
12335                                AstChannel *channel, int *status ) {
12336 /*
12337 *+
12338 *  Name:
12339 *     astLoadFrameSet
12340 
12341 *  Purpose:
12342 *     Load a FrameSet.
12343 
12344 *  Type:
12345 *     Protected function.
12346 
12347 *  Synopsis:
12348 *     #include "frameset.h"
12349 *     AstFrameSet *astLoadFrameSet( void *mem, size_t size,
12350 *                                   AstFrameSetVtab *vtab, const char *name,
12351 *                                   AstChannel *channel )
12352 
12353 *  Class Membership:
12354 *     FrameSet loader.
12355 
12356 *  Description:
12357 *     This function is provided to load a new FrameSet using data read
12358 *     from a Channel. It first loads the data used by the parent class
12359 *     (which allocates memory if necessary) and then initialises a
12360 *     FrameSet structure in this memory, using data read from the
12361 *     input Channel.
12362 
12363 *  Parameters:
12364 *     mem
12365 *        A pointer to the memory into which the FrameSet is to be
12366 *        loaded.  This must be of sufficient size to accommodate the
12367 *        FrameSet data (sizeof(FrameSet)) plus any data used by
12368 *        derived classes. If a value of NULL is given, this function
12369 *        will allocate the memory itself using the "size" parameter to
12370 *        determine its size.
12371 *     size
12372 *        The amount of memory used by the FrameSet (plus derived class
12373 *        data).  This will be used to allocate memory if a value of
12374 *        NULL is given for the "mem" parameter. This value is also
12375 *        stored in the FrameSet structure, so a valid value must be
12376 *        supplied even if not required for allocating memory.
12377 *
12378 *        If the "vtab" parameter is NULL, the "size" value is ignored
12379 *        and sizeof(AstFrameSet) is used instead.
12380 *     vtab
12381 *        Pointer to the start of the virtual function table to be
12382 *        associated with the new FrameSet. If this is NULL, a pointer
12383 *        to the (static) virtual function table for the FrameSet class
12384 *        is used instead.
12385 *     name
12386 *        Pointer to a constant null-terminated character string which
12387 *        contains the name of the class to which the new object
12388 *        belongs (it is this pointer value that will subsequently be
12389 *        returned by the astGetClass method).
12390 *
12391 *        If the "vtab" parameter is NULL, the "name" value is ignored
12392 *        and a pointer to the string "FrameSet" is used instead.
12393 
12394 *  Returned Value:
12395 *     A pointer to the new FrameSet.
12396 
12397 *  Notes:
12398 *     - A null pointer will be returned if this function is invoked
12399 *     with the global error status set, or if it should fail for any
12400 *     reason.
12401 *-
12402 */
12403 
12404 /* Local Constants: */
12405    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
12406 #define KEY_LEN 50               /* Maximum length of a keyword */
12407 
12408 /* Local Variables: */
12409    AstFrameSet *new;             /* Pointer to the new FrameSet */
12410    char key[ KEY_LEN + 1 ];      /* Buffer for keyword string */
12411    int ifr;                      /* Get a pointer to the thread specific global data structure. */
12412 
12413 /* Loop counter for Frames */
12414    int inode;                    /* Loop counter for nodes */
12415 
12416    astGET_GLOBALS(channel);
12417 
12418 /* Initialise. */
12419    new = NULL;
12420 
12421 /* Check the global error status. */
12422    if ( !astOK ) return new;
12423 
12424 /* If a NULL virtual function table has been supplied, then this is
12425    the first loader to be invoked for this FrameSet. In this case the
12426    FrameSet belongs to this class, so supply appropriate values to be
12427    passed to the parent class loader (and its parent, etc.). */
12428    if ( !vtab ) {
12429       size = sizeof( AstFrameSet );
12430       vtab = &class_vtab;
12431       name = "FrameSet";
12432 
12433 /* If required, initialise the virtual function table for this class. */
12434       if ( !class_init ) {
12435          astInitFrameSetVtab( vtab, name );
12436          class_init = 1;
12437       }
12438    }
12439 
12440 /* Invoke the parent class loader to load data for all the ancestral
12441    classes of the current one, returning a pointer to the resulting
12442    partly-built FrameSet. */
12443    new = astLoadFrame( mem, size, (AstFrameVtab *) vtab, name,
12444                        channel );
12445 
12446    if ( astOK ) {
12447 
12448 /* Read input data. */
12449 /* ================ */
12450 /* Request the input Channel to read all the input data appropriate to
12451    this class into the internal "values list". */
12452       astReadClassData( channel, "FrameSet" );
12453 
12454 /* Now read each individual data item from this list and use it to
12455    initialise the appropriate instance variable(s) for this class. */
12456 
12457 /* In the case of attributes, we first read the "raw" input value,
12458    supplying the "unset" value as the default. If a "set" value is
12459    obtained, we then use the appropriate (private) Set... member
12460    function to validate and set the value properly. */
12461 
12462 /* Nframe. */
12463 /* ------- */
12464       new->nframe = astReadInt( channel, "nframe", 1 );
12465       if ( new->nframe < 0 ) new->nframe = 1;
12466 
12467 /* Number of nodes. */
12468 /* ---------------- */
12469       new->nnode = astReadInt( channel, "nnode", new->nframe );
12470       if ( new->nnode < 1 ) new->nnode = 1;
12471 
12472 /* Allocate memory to hold Frame and node information. */
12473       new->frame = astMalloc( sizeof( AstFrame *) * (size_t) new->nframe );
12474       new->node = astMalloc( sizeof( int ) * (size_t) new->nframe );
12475       new->varfrm = astMalloc( sizeof( int ) * (size_t) new->nframe );
12476       new->link = astMalloc( sizeof( int ) * (size_t) ( new->nnode - 1 ) );
12477       new->invert = astMalloc( sizeof( int ) * (size_t) ( new->nnode - 1 ) );
12478       new->map = astMalloc( sizeof( AstMapping * ) *
12479                             (size_t) ( new->nnode - 1 ) );
12480 
12481 /* If an error occurs, ensure that all allocated memory is freed. */
12482       if ( !astOK ) {
12483          new->frame = astFree( new->frame );
12484          new->node = astFree( new->node );
12485          new->varfrm = astFree( new->varfrm );
12486          new->link = astFree( new->link );
12487          new->invert = astFree( new->invert );
12488          new->map = astFree( new->map );
12489 
12490 /* Otherwise, initialise the arrays which will hold Object pointers. */
12491       } else {
12492          for ( ifr = 1; ifr <= new->nframe; ifr++ ) {
12493             new->frame[ ifr - 1 ] = NULL;
12494          }
12495          for ( inode = 1; inode < new->nnode; inode++ ) {
12496             new->map[ inode - 1 ] = NULL;
12497          }
12498 
12499 /* Read Frame data... */
12500          for ( ifr = 1; ifr <= new->nframe; ifr++ ) {
12501 
12502 /* Frame objects. */
12503 /* -------------- */
12504 /* Create the required keyword and then read the Frame. */
12505             (void) sprintf( key, "frm%d", ifr );
12506             new->frame[ ifr - 1 ] = astReadObject( channel, key, NULL );
12507 
12508 /* Node index for each Frame. */
12509 /* -------------------------- */
12510             (void) sprintf( key, "nod%d", ifr );
12511             new->node[ ifr - 1 ] = astReadInt( channel, key, ifr ) - 1;
12512 
12513 /* Index of variants Frame. */
12514 /* ------------------------ */
12515             (void) sprintf( key, "vfr%d", ifr );
12516             new->varfrm[ ifr - 1 ] = astReadInt( channel, key, 0 );
12517          }
12518 
12519 /* Read node data... */
12520          for ( inode = 1; inode < new->nnode; inode++ ) {
12521 
12522 /* Links between nodes. */
12523 /* -------------------- */
12524             (void) sprintf( key, "lnk%d", inode + 1 );
12525             new->link[ inode - 1 ] = astReadInt( channel, key, 0 ) - 1;
12526 
12527 /* Inversion flags. */
12528 /* ---------------- */
12529             (void) sprintf( key, "inv%d", inode + 1 );
12530             new->invert[ inode - 1 ] = astReadInt( channel, key, 0 );
12531 
12532 /* Mapping objects. */
12533 /* ---------------- */
12534             (void) sprintf( key, "map%d", inode + 1 );
12535             new->map[ inode - 1 ] = astReadObject( channel, key, NULL );
12536          }
12537 
12538 /* Read remaining data... */
12539 
12540 /* Base. */
12541 /* ----- */
12542          new->base = astReadInt( channel, "base", -INT_MAX );
12543          if ( new->base < 1 ) new->base = -INT_MAX;
12544 
12545 /* Current. */
12546 /* -------- */
12547          new->current = astReadInt( channel, "currnt", -INT_MAX );
12548          if ( new->base < 1 ) new->base = -INT_MAX;
12549       }
12550 
12551 /* If an error occurred, clean up by deleting the new FrameSet. */
12552       if ( !astOK ) new = astDelete( new );
12553    }
12554 
12555 /* Return the new FrameSet pointer. */
12556    return new;
12557 
12558 /* Undefine macros local to this function. */
12559 #undef KEY_LEN
12560 }
12561 
12562 /* Virtual function interfaces. */
12563 /* ============================ */
12564 /* These provide the external interface to the virtual functions defined by
12565    this class. Each simply checks the global error status and then locates and
12566    executes the appropriate member function, using the function pointer stored
12567    in the object's virtual function table (this pointer is located using the
12568    astMEMBER macro defined in "object.h").
12569 
12570    Note that the member function may not be the one defined here, as it may
12571    have been over-ridden by a derived class. However, it should still have the
12572    same interface. */
astAddFrame_(AstFrameSet * this,int iframe,AstMapping * map,AstFrame * frame,int * status)12573 void astAddFrame_( AstFrameSet *this, int iframe, AstMapping *map,
12574                    AstFrame *frame, int *status ) {
12575    if ( !astOK ) return;
12576    (**astMEMBER(this,FrameSet,AddFrame))( this, iframe, map, frame, status );
12577 }
astClearBase_(AstFrameSet * this,int * status)12578 void astClearBase_( AstFrameSet *this, int *status ) {
12579    if ( !astOK ) return;
12580    (**astMEMBER(this,FrameSet,ClearBase))( this, status );
12581 }
astClearCurrent_(AstFrameSet * this,int * status)12582 void astClearCurrent_( AstFrameSet *this, int *status ) {
12583    if ( !astOK ) return;
12584    (**astMEMBER(this,FrameSet,ClearCurrent))( this, status );
12585 }
astClearVariant_(AstFrameSet * this,int * status)12586 void astClearVariant_( AstFrameSet *this, int *status ) {
12587    if ( !astOK ) return;
12588    (**astMEMBER(this,FrameSet,ClearVariant))( this, status );
12589 }
astGetBase_(AstFrameSet * this,int * status)12590 int astGetBase_( AstFrameSet *this, int *status ) {
12591    if ( !astOK ) return 0;
12592    return (**astMEMBER(this,FrameSet,GetBase))( this, status );
12593 }
astGetCurrent_(AstFrameSet * this,int * status)12594 int astGetCurrent_( AstFrameSet *this, int *status ) {
12595    if ( !astOK ) return 0;
12596    return (**astMEMBER(this,FrameSet,GetCurrent))( this, status );
12597 }
astGetVariant_(AstFrameSet * this,int * status)12598 const char *astGetVariant_( AstFrameSet *this, int *status ) {
12599    if ( !astOK ) return NULL;
12600    return (**astMEMBER(this,FrameSet,GetVariant))( this, status );
12601 }
astGetFrame_(AstFrameSet * this,int iframe,int * status)12602 AstFrame *astGetFrame_( AstFrameSet *this, int iframe, int *status ) {
12603    if ( !astOK ) return NULL;
12604    return (**astMEMBER(this,FrameSet,GetFrame))( this, iframe, status );
12605 }
astGetMapping_(AstFrameSet * this,int iframe1,int iframe2,int * status)12606 AstMapping *astGetMapping_( AstFrameSet *this, int iframe1, int iframe2, int *status ) {
12607    if ( !astOK ) return NULL;
12608    return (**astMEMBER(this,FrameSet,GetMapping))( this, iframe1, iframe2, status );
12609 }
astGetNframe_(AstFrameSet * this,int * status)12610 int astGetNframe_( AstFrameSet *this, int *status ) {
12611    if ( !astOK ) return 0;
12612    return (**astMEMBER(this,FrameSet,GetNframe))( this, status );
12613 }
astRemapFrame_(AstFrameSet * this,int iframe,AstMapping * map,int * status)12614 void astRemapFrame_( AstFrameSet *this, int iframe, AstMapping *map, int *status ) {
12615    if ( !astOK ) return;
12616    (**astMEMBER(this,FrameSet,RemapFrame))( this, iframe, map, status );
12617 }
astAddVariant_(AstFrameSet * this,AstMapping * map,const char * name,int * status)12618 void astAddVariant_( AstFrameSet *this, AstMapping *map, const char *name, int *status ) {
12619    if ( !astOK ) return;
12620    (**astMEMBER(this,FrameSet,AddVariant))( this, map, name, status );
12621 }
astMirrorVariants_(AstFrameSet * this,int iframe,int * status)12622 void astMirrorVariants_( AstFrameSet *this, int iframe, int *status ) {
12623    if ( !astOK ) return;
12624    (**astMEMBER(this,FrameSet,MirrorVariants))( this, iframe, status );
12625 }
astRemoveFrame_(AstFrameSet * this,int iframe,int * status)12626 void astRemoveFrame_( AstFrameSet *this, int iframe, int *status ) {
12627    if ( !astOK ) return;
12628    (**astMEMBER(this,FrameSet,RemoveFrame))( this, iframe, status );
12629 }
astSetBase_(AstFrameSet * this,int ibase,int * status)12630 void astSetBase_( AstFrameSet *this, int ibase, int *status ) {
12631    if ( !astOK ) return;
12632    (**astMEMBER(this,FrameSet,SetBase))( this, ibase, status );
12633 }
astSetCurrent_(AstFrameSet * this,int icurrent,int * status)12634 void astSetCurrent_( AstFrameSet *this, int icurrent, int *status ) {
12635    if ( !astOK ) return;
12636    (**astMEMBER(this,FrameSet,SetCurrent))( this, icurrent, status );
12637 }
astSetVariant_(AstFrameSet * this,const char * variant,int * status)12638 void astSetVariant_( AstFrameSet *this, const char *variant, int *status ) {
12639    if ( !astOK ) return;
12640    (**astMEMBER(this,FrameSet,SetVariant))( this, variant, status );
12641 }
astTestBase_(AstFrameSet * this,int * status)12642 int astTestBase_( AstFrameSet *this, int *status ) {
12643    if ( !astOK ) return 0;
12644    return (**astMEMBER(this,FrameSet,TestBase))( this, status );
12645 }
astTestCurrent_(AstFrameSet * this,int * status)12646 int astTestCurrent_( AstFrameSet *this, int *status ) {
12647    if ( !astOK ) return 0;
12648    return (**astMEMBER(this,FrameSet,TestCurrent))( this, status );
12649 }
astTestVariant_(AstFrameSet * this,int * status)12650 int astTestVariant_( AstFrameSet *this, int *status ) {
12651    if ( !astOK ) return 0;
12652    return (**astMEMBER(this,FrameSet,TestVariant))( this, status );
12653 }
astValidateFrameIndex_(AstFrameSet * this,int iframe,const char * method,int * status)12654 int astValidateFrameIndex_( AstFrameSet *this, int iframe,
12655                             const char *method, int *status ) {
12656    if ( !astOK ) return 0;
12657    return (**astMEMBER(this,FrameSet,ValidateFrameIndex))( this, iframe,
12658                                                            method, status );
12659 }
astGetAllVariants_(AstFrameSet * this,int * status)12660 const char *astGetAllVariants_( AstFrameSet *this, int *status ) {
12661    if ( !astOK ) return NULL;
12662    return (**astMEMBER(this,FrameSet,GetAllVariants))( this, status );
12663 }
12664 
12665 /* Special public interface functions. */
12666 /* =================================== */
12667 /* These provide the public interface to certain special functions
12668    whose public interface cannot be handled using macros (such as
12669    astINVOKE) alone. In general, they are named after the
12670    corresponding protected version of the function, but with "Id"
12671    appended to the name. */
12672 
12673 /* Public Interface Function Prototypes. */
12674 /* ------------------------------------- */
12675 /* The following functions have public prototypes only (i.e. no
12676    protected prototypes), so we must provide local prototypes for use
12677    within this module. */
12678 AstFrameSet *astFrameSetId_( void *, const char *, ... );
12679 
12680 /* Special interface function implementations. */
12681 /* ------------------------------------------- */
astFrameSetId_(void * frame_void,const char * options,...)12682 AstFrameSet *astFrameSetId_( void *frame_void, const char *options, ... ) {
12683 /*
12684 *++
12685 *  Name:
12686 c     astFrameSet
12687 f     AST_FRAMESET
12688 
12689 *  Purpose:
12690 *     Create a FrameSet.
12691 
12692 *  Type:
12693 *     Public function.
12694 
12695 *  Synopsis:
12696 c     #include "frameset.h"
12697 c     AstFrameSet *astFrameSet( AstFrame *frame, const char *options, ... )
12698 f     RESULT = AST_FRAMESET( FRAME, OPTIONS, STATUS )
12699 
12700 *  Class Membership:
12701 *     FrameSet constructor.
12702 
12703 *  Description:
12704 *     This function creates a new FrameSet and optionally initialises
12705 *     its attributes.
12706 *
12707 *     A FrameSet consists of a set of one or more Frames (which
12708 *     describe coordinate systems), connected together by Mappings
12709 *     (which describe how the coordinate systems are inter-related). A
12710 *     FrameSet makes it possible to obtain a Mapping between any pair
12711 *     of these Frames (i.e. to convert between any of the coordinate
12712 *     systems which it describes).  The individual Frames are
12713 *     identified within the FrameSet by an integer index, with Frames
12714 *     being numbered consecutively from one as they are added to the
12715 *     FrameSet.
12716 *
12717 *     Every FrameSet has a "base" Frame and a "current" Frame (which
12718 *     are allowed to be the same). Any of the Frames may be nominated
12719 *     to hold these positions, and the choice is determined by the
12720 *     values of the FrameSet's Base and Current attributes, which hold
12721 *     the indices of the relevant Frames.  By default, the first Frame
12722 *     added to a FrameSet is its base Frame, and the last one added is
12723 *     its current Frame.
12724 *
12725 *     The base Frame describes the "native" coordinate system of
12726 *     whatever the FrameSet is used to calibrate (e.g. the pixel
12727 *     coordinates of an image) and the current Frame describes the
12728 *     "apparent" coordinate system in which it should be viewed
12729 *     (e.g. displayed, etc.). Any further Frames represent a library
12730 *     of alternative coordinate systems, which may be selected by
12731 *     making them current.
12732 *
12733 *     When a FrameSet is used in a context that requires a Frame,
12734 *     (e.g. obtaining its Title value, or number of axes), the current
12735 *     Frame is used. A FrameSet may therefore be used in place of its
12736 *     current Frame in most situations.
12737 *
12738 *     When a FrameSet is used in a context that requires a Mapping,
12739 *     the Mapping used is the one between its base Frame and its
12740 *     current Frame. Thus, a FrameSet may be used to convert "native"
12741 *     coordinates into "apparent" ones, and vice versa. Like any
12742 c     Mapping, a FrameSet may also be inverted (see astInvert), which
12743 f     Mapping, a FrameSet may also be inverted (see AST_INVERT), which
12744 *     has the effect of interchanging its base and current Frames and
12745 *     hence of reversing the Mapping between them.
12746 *
12747 *     Regions may be added into a FrameSet (since a Region is a type of
12748 *     Frame), either explicitly or as components within CmpFrames. In this
12749 *     case the Mapping between a pair of Frames within a FrameSet will
12750 *     include the effects of the clipping produced by any Regions included
12751 *     in the path between the Frames.
12752 
12753 *  Parameters:
12754 c     frame
12755 f     FRAME = INTEGER (Given)
12756 *        Pointer to the first Frame to be inserted into the
12757 *        FrameSet. This initially becomes both the base and the
12758 *        current Frame. (Further Frames may be added using the
12759 c        astAddFrame function.)
12760 f        AST_ADDFRAME routine.)
12761 c     options
12762 f     OPTIONS = CHARACTER * ( * ) (Given)
12763 c        Pointer to a null-terminated string containing an optional
12764 c        comma-separated list of attribute assignments to be used for
12765 c        initialising the new FrameSet. The syntax used is identical to
12766 c        that for the astSet function and may include "printf" format
12767 c        specifiers identified by "%" symbols in the normal way.
12768 c        If no initialisation is required, a zero-length string may be
12769 c        supplied.
12770 f        A character string containing an optional comma-separated
12771 f        list of attribute assignments to be used for initialising the
12772 f        new FrameSet. The syntax used is identical to that for the
12773 f        AST_SET routine. If no initialisation is required, a blank
12774 f        value may be supplied.
12775 c     ...
12776 c        If the "options" string contains "%" format specifiers, then
12777 c        an optional list of additional arguments may follow it in
12778 c        order to supply values to be substituted for these
12779 c        specifiers. The rules for supplying these are identical to
12780 c        those for the astSet function (and for the C "printf"
12781 c        function).
12782 f     STATUS = INTEGER (Given and Returned)
12783 f        The global status.
12784 
12785 *  Returned Value:
12786 c     astFrameSet()
12787 f     AST_FRAMESET
12788 *        A pointer to the new FrameSet.
12789 
12790 *  Notes:
12791 c     - If a pointer to an existing FrameSet is given for the "frame"
12792 c     parameter, then the new FrameSet will (as a special case) be
12793 f     - If a pointer to an existing FrameSet is given for the FRAME
12794 f     argument, then the new FrameSet will (as a special case) be
12795 *     initialised to contain the same Frames and Mappings, and to have
12796 *     the same attribute values, as the one supplied. This process is
12797 c     similar to making a copy of a FrameSet (see astCopy), except
12798 f     similar to making a copy of a FrameSet (see AST_COPY), except
12799 *     that the Frames and Mappings contained in the original are not
12800 *     themselves copied, but are shared by both FrameSets.
12801 *     - A null Object pointer (AST__NULL) will be returned if this
12802 c     function is invoked with the AST error status set, or if it
12803 f     function is invoked with STATUS set to an error value, or if it
12804 *     should fail for any reason.
12805 *--
12806 
12807 *  Implementation Notes:
12808 *     - This function implements the external (public) interface to
12809 *     the astFrameSet constructor function. It returns an ID value
12810 *     (instead of a true C pointer) to external users, and must be
12811 *     provided because astFrameSet_ has a variable argument list which
12812 *     cannot be encapsulated in a macro (where this conversion would
12813 *     otherwise occur).
12814 *     - Because no checking or casting of arguments is performed
12815 *     before the function is invoked, the "frame" parameter is of type
12816 *     (void *) and is converted from an ID value to a pointer and
12817 *     validated within the function itself.
12818 *     - The variable argument list also prevents this function from
12819 *     invoking astFrameSet_ directly, so it must be a
12820 *     re-implementation of it in all respects, except for the
12821 *     conversions between IDs and pointers on input/output of Objects.
12822 */
12823 
12824 /* Local Variables: */
12825    astDECLARE_GLOBALS            /* Pointer to thread-specific global data */
12826    AstFrame *frame;              /* Pointer to Frame structure */
12827    AstFrameSet *new;             /* Pointer to new FrameSet */
12828    va_list args;                 /* Variable argument list */
12829 
12830    int *status;
12831 
12832 /* Initialise. */
12833    new = NULL;
12834 
12835 /* Get a pointer to the thread specific global data structure. */
12836    astGET_GLOBALS(NULL);
12837 
12838 /* Pointer to inherited status value */
12839 
12840 /* Get a pointer to the inherited status value. */
12841    status = astGetStatusPtr;
12842 
12843 /* Check the global status. */
12844    if ( !astOK ) return new;
12845 
12846 /* Obtain the Frame pointer from the ID supplied and validate the
12847    pointer to ensure it identifies a valid Frame. */
12848    frame = astVerifyFrame( astMakePointer( frame_void ) );
12849    if ( astOK ) {
12850 
12851 /* Initialise the FrameSet, allocating memory and initialising the
12852    virtual function table as well if necessary. */
12853       new = astInitFrameSet( NULL, sizeof( AstFrameSet ), !class_init,
12854                              &class_vtab, "FrameSet", frame );
12855 
12856 /* If successful, note that the virtual function table has been
12857    initialised. */
12858       if ( astOK ) {
12859          class_init = 1;
12860 
12861 /* Obtain the variable argument list and pass it along with the
12862    options string to the astVSet method to initialise the new
12863    FrameSet's attributes. */
12864          va_start( args, options );
12865          astVSet( new, options, NULL, args );
12866          va_end( args );
12867 
12868 /* If an error occurred, clean up by deleting the new object. */
12869          if ( !astOK ) new = astDelete( new );
12870       }
12871    }
12872 
12873 /* Return an ID value for the new FrameSet. */
12874    return astMakeId( new );
12875 }
12876 
12877 
12878 
12879