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", ¤t, &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 ¤t_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