1 /*
2 *class++
3 * Name:
4 * Frame
5
6 * Purpose:
7 * Coordinate system description.
8
9 * Constructor Function:
10 c astFrame
11 f AST_FRAME
12
13 * Description:
14 * This class is used to represent coordinate systems. It does this
15 * in rather the same way that a frame around a graph describes the
16 * coordinate space in which data are plotted. Consequently, a
17 * Frame has a Title (string) attribute, which describes the
18 * coordinate space, and contains axes which in turn hold
19 * information such as Label and Units strings which are used for
20 * labelling (e.g.) graphical output. In general, however, the
21 * number of axes is not restricted to two.
22 *
23 * Functions are available for converting Frame coordinate values
24 * into a form suitable for display, and also for calculating
25 * distances and offsets between positions within the Frame.
26 *
27 * Frames may also contain knowledge of how to transform to and
28 * from related coordinate systems.
29
30 * Inheritance:
31 * The Frame class inherits from the Mapping class.
32
33 * Attributes:
34 * In addition to those attributes common to all Mappings, every
35 * Frame also has the following attributes (if the Frame has only one
36 * axis, the axis specifier can be omited from the following attribute
37 * names):
38 *
39 * - AlignSystem: Coordinate system used to align Frames
40 * - Bottom(axis): Lowest axis value to display
41 * - Digits/Digits(axis): Number of digits of precision
42 * - Direction(axis): Display axis in conventional direction?
43 * - Domain: Coordinate system domain
44 * - Dut1: Difference between the UT1 and UTC timescale
45 * - Epoch: Epoch of observation
46 * - Format(axis): Format specification for axis values
47 * - Label(axis): Axis label
48 * - MatchEnd: Match trailing axes?
49 * - MaxAxes: Maximum number of Frame axes to match
50 * - MinAxes: Minimum number of Frame axes to match
51 * - Naxes: Number of Frame axes
52 * - NormUnit(axis): Normalised axis physical units
53 * - ObsAlt: Geodetic altitude of observer
54 * - ObsLat: Geodetic latitude of observer
55 * - ObsLon: Geodetic longitude of observer
56 * - Permute: Permute axis order?
57 * - PreserveAxes: Preserve axes?
58 * - Symbol(axis): Axis symbol
59 * - System: Coordinate system used to describe the domain
60 * - Title: Frame title
61 * - Top(axis): Highest axis value to display
62 * - Unit(axis): Axis physical units
63
64 * Functions:
65 c In addition to those functions applicable to all Mappings, the
66 c following functions may also be applied to all Frames:
67 f In addition to those routines applicable to all Mappings, the
68 f following routines may also be applied to all Frames:
69 *
70 c - astAngle: Calculate the angle subtended by two points at a third point
71 c - astAxAngle: Find the angle from an axis, to a line through two points
72 c - astAxDistance: Calculate the distance between two axis values
73 c - astAxOffset: Calculate an offset along an axis
74 c - astConvert: Determine how to convert between two coordinate systems
75 c - astDistance: Calculate the distance between two points in a Frame
76 c - astFindFrame: Find a coordinate system with specified characteristics
77 c - astFormat: Format a coordinate value for a Frame axis
78 c - astGetActiveUnit: Determines how the Unit attribute will be used
79 c - astIntersect: Find the intersection between two geodesic curves
80 c - astMatchAxes: Find any corresponding axes in two Frames
81 c - astNorm: Normalise a set of Frame coordinates
82 c - astOffset: Calculate an offset along a geodesic curve
83 c - astOffset2: Calculate an offset along a geodesic curve in a 2D Frame
84 c - astPermAxes: Permute the order of a Frame's axes
85 c - astPickAxes: Create a new Frame by picking axes from an existing one
86 c - astResolve: Resolve a vector into two orthogonal components
87 c - astSetActiveUnit: Specify how the Unit attribute should be used
88 c - astUnformat: Read a formatted coordinate value for a Frame axis
89 f - AST_ANGLE: Find the angle subtended by two points at a third point
90 f - AST_AXANGLE: Find the angle from an axis, to a line through two points
91 f - AST_AXDISTANCE: Calculate the distance between two axis values
92 f - AST_AXOFFSET: Calculate an offset along an axis
93 f - AST_CONVERT: Determine how to convert between two coordinate systems
94 f - AST_DISTANCE: Calculate the distance between two points in a Frame
95 f - AST_FINDFRAME: Find a coordinate system with specified characteristics
96 f - AST_FORMAT: Format a coordinate value for a Frame axis
97 f - AST_GETACTIVEUNIT: Determines how the Unit attribute will be used
98 f - AST_INTERSECT: Find the intersection between two geodesic curves
99 f - AST_MATCHAXES: Find any corresponding axes in two Frames
100 f - AST_NORM: Normalise a set of Frame coordinates
101 f - AST_OFFSET: Calculate an offset along a geodesic curve
102 f - AST_OFFSET2: Calculate an offset along a geodesic curve in a 2D Frame
103 f - AST_PERMAXES: Permute the order of a Frame's axes
104 f - AST_PICKAXES: Create a new Frame by picking axes from an existing one
105 f - AST_RESOLVE: Resolve a vector into two orthogonal components
106 f - AST_SETACTIVEUNIT: Specify how the Unit attribute should be used
107 f - AST_UNFORMAT: Read a formatted coordinate value for a Frame axis
108
109 * Notes:
110 * - When used as a Mapping, a Frame implements a unit (null)
111 * transformation in both the forward and inverse directions
112 * (equivalent to a UnitMap). The Nin and Nout attribute values are
113 * both equal to the number of Frame axes.
114
115 * Copyright:
116 * Copyright (C) 1997-2006 Council for the Central Laboratory of the
117 * Research Councils
118
119 * Licence:
120 * This program is free software: you can redistribute it and/or
121 * modify it under the terms of the GNU Lesser General Public
122 * License as published by the Free Software Foundation, either
123 * version 3 of the License, or (at your option) any later
124 * version.
125 *
126 * This program is distributed in the hope that it will be useful,
127 * but WITHOUT ANY WARRANTY; without even the implied warranty of
128 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
129 * GNU Lesser General Public License for more details.
130 *
131 * You should have received a copy of the GNU Lesser General
132 * License along with this program. If not, see
133 * <http://www.gnu.org/licenses/>.
134
135 * Authors:
136 * RFWS: R.F. Warren-Smith (Starlink)
137 * DSB: B.S. Berry (Starlink)
138
139 * History:
140 * 1-MAR-1996 (RFWS):
141 * Original version.
142 * 4-JUN-1996 (RFWS):
143 * Added the CleanDomain function to fold all Domain strings to
144 * upper case and remove white space.
145 * 12-JUL-1996 (RFWS):
146 * Over-ride the astReportPoints method to provide
147 * Frame-specific formatting.
148 * 11-SEP-1996 (RFWS):
149 * Added astGap (written by DSB).
150 * 10-JUN-1997 (RFWS):
151 * Re-implemented astConvert and astFindFrame.
152 * 1-SEP-1997 (RFWS):
153 * Added missing return statement in astAbbrev_.
154 * 14-NOV-1997 (RFWS):
155 * Fixed wrong amount of memory allocated in ValidateAxisSelection.
156 * 20-NOV-1997 (RFWS):
157 * Updated astConvert prologue.
158 * 22-DEC-1997 (RFWS):
159 * Updated astConvert prologue again.
160 * 15-FEB-1998 (RFWS):
161 * Added astUnformat.
162 * 2-MAR-1999 (RFWS);
163 * Fixed missing STATUS arguments in examples for AST_FINDFRAME
164 * prologue.
165 * 18-JUL-1999 (RFWS):
166 * Fixed memory leak in ConvertX.
167 * 21-JUN-2001 (DSB):
168 * Added methods astAngle and astOffset2.
169 * 29-AUG-2001 (DSB):
170 * Added methods astAxDistance and astAxOffset.
171 * 4-SEP-2001 (DSB):
172 * Added method astResolve.
173 * 9-SEP-2001 (DSB):
174 * Added method astBear.
175 * 21-SEP-2001 (DSB):
176 * Replaced astBear with astAxAngle.
177 * 10-OCT-2002 (DSB):
178 * Added Top and Bottom.
179 * 15-NOV-2002 (DSB):
180 * Moved the System and Epoch attributes from the SkyFrame class to
181 * this class. Added virtual method astValidateSystem, astSystemString,
182 * astSystemCode. Added attribute AlignSystem.
183 * 17-DEC-2002 (DSB):
184 * Added the GetActiveUnit, TestActiveUnit and SetActiveUnit functions.
185 * 8-JAN-2003 (DSB):
186 * Changed private InitVtab method to protected astInitFrameVtab
187 * method.
188 * 15-SEP-2003 (DSB):
189 * Allow Frame attribute names to include an axis specifier within
190 * GetAttrib, SetAttrib, TestAttrib and ClearAttrib (eg "Domain(1)"
191 * is now accepted as equivalent to "Domain").
192 * 24-JAN-2004 (DSB):
193 * o Added astFields.
194 * o Added argument "fmt" to Abbrev.
195 * 24-MAR-2004 (DSB):
196 * Add protected function astIsUnitFrame.
197 * 7-SEP-2004 (DSB):
198 * Modified SetUnit to exclude any trailing spaces
199 * 8-SEP-2004 (DSB):
200 * - Added astResolvePoints.
201 * - Override astEqual.
202 * 29-NOV-2004 (DSB):
203 * - Set/Get/Test/ClearAttrib: Allow axis specifier to be omitted from
204 * axis attribute names if the Frame only has one axis.
205 * 2-FEB-2005 (DSB):
206 * - Avoid using astStore to allocate more storage than is supplied
207 * in the "data" pointer. This can cause access violations since
208 * astStore will then read beyond the end of the "data" area.
209 * 17-FEB-2005 (DSB):
210 * - Change use of ActiveUnit flag so that both target and template
211 * Frames must have active units in order for the Mapping to take
212 * account of differences in units. Previously, the test was based
213 * on the template Frame alone.
214 * 23-MAR-2005 (DSB):
215 * - GetActiveUnit: Always return zero if the Frame contains any
216 * SkyAxes.
217 * 5-APR-2005 (DSB):
218 * Correct error checking in Clear/Get/Set/TestAttrib.
219 * 12-MAY-2005 (DSB):
220 * Added astNormBox method.
221 * 16-JUN-2005 (DSB):
222 * Added documentation for the TimeFrame class.
223 * 12-AUG-2005 (DSB):
224 * Added ObsLat and ObsLon attributes.
225 * 1-MAR-2006 (DSB):
226 * Replace astSetPermMap within DEBUG blocks by astBeginPM/astEndPM.
227 * 15-MAY-2006 (DSB):
228 * Remove unused global variable parent_equal.
229 * 26-JUN-2006 (DSB):
230 * Document the use of the Direction attribute by the Plot class.
231 * 30-JUN-2006 (DSB):
232 * Allow astAbbrev to have a null "str1" value.
233 * 16-AUG-2006 (DSB):
234 * Correct "Class Applicability" to "Applicability".
235 * 5-OCT-2006 (DSB):
236 * Increase the number of digits used when formating a ObsLon or
237 * ObsLat value in GetAttrib.
238 * 14-OCT-2006 (DSB):
239 * - Add Dut1 attribute
240 * 26-JAN-2007 (DSB):
241 * Fix bug in NewUnit that causes segvio when changing axis symbols
242 * to accomodate changes in units.
243 * 17-MAY-2007 (DSB):
244 * Added read-only attribute NormUnit.
245 * 21-MAY-2007 (DSB):
246 * Use rather than ignore the value returned by astTestAxisDigits in
247 * TestAttrib.
248 * 25-JUN-2007 (DSB):
249 * Documentation typos.
250 * 26-NOV-2007 (DSB):
251 * In Clear/Get/Set/TestAttrib, include any appropriate axis index in
252 * the attribute name when attempting to get the attribute value from
253 * the primary frame
254 * 17-NOV-2008 (DSB):
255 * Correct parent class in invocation of astMAKE_ISA.
256 * 14-JAN-2009 (DSB):
257 * Added astIntersect.
258 * 18-MAR-2009 (DSB):
259 * Fixed bug in LineCrossing.
260 * 18-JUN-2000 (DSB):
261 * Added ObsAlt attribute.
262 * 28-SEP-2009 (DSB):
263 * Added astMatchAxes method.
264 * 22-MAR-2011 (DSB):
265 * Add astFrameGrid method.
266 * 29-APR-2011 (DSB):
267 * Prevent astFindFrame from matching a subclass template against a
268 * superclass target.
269 * 11-APR-2012 (DSB):
270 * Change astValidateAxis so that it can permute in either direction.
271 * 29-APR-2013 (DSB):
272 * Added protected methods astSetFrameVariants and astGetFrameVariants.
273 * 1-MAY-2013 (DSB):
274 * Override the astDoNotSimplify method to indicate that Frames should
275 * always be simplified. This is mainly because the STC class uses the
276 * Ident attribute with Frames, and preventing such frames from
277 * simplifying (which is what the parent astDoNotSimplify method does)
278 * causes the STC tester in the ast_tester directory to fail.
279 *class--
280 */
281
282 /* Module Macros. */
283 /* ============== */
284 /* Set the name of the class we are implementing. This indicates to
285 the header files that define class interfaces that they should make
286 "protected" symbols available. */
287 #define astCLASS Frame
288
289 /* Define numerical constants for use in this module. */
290 #define LABEL_BUFF_LEN 100 /* Max length of default axis Label string */
291 #define SYMBOL_BUFF_LEN 50 /* Max length of default axis Symbol string */
292 #define TITLE_BUFF_LEN 100 /* Max length of default title string */
293 #define GETATTRIB_BUFF_LEN 50 /* Max length of string returned by GetAttrib */
294 #define ASTFMTDECIMALYR_BUFF_LEN 50 /* Max length of string returned by GetAttrib */
295 #define ASTFORMATID_MAX_STRINGS 50 /* Number of string values buffer by astFormatID*/
296
297
298 /* Define the first and last acceptable System values. */
299 #define FIRST_SYSTEM AST__CART
300 #define LAST_SYSTEM AST__CART
301
302 /* Define macros to implement methods for accessing axis attributes. */
303 /*
304 * Name:
305 * MAKE_CLEAR
306
307 * Purpose:
308 * Implement a method to clear an attribute value for a Frame axis.
309
310 * Type:
311 * Private macro.
312
313 * Synopsis:
314 * #include "frame.h"
315 * MAKE_CLEAR(attribute)
316
317 * Class Membership:
318 * Defined by the Frame class.
319
320 * Description:
321 * This macro expands to an implementation of a private member function of
322 * the form:
323 *
324 * static void Clear<Attribute>( AstFrame *this, int axis )
325 *
326 * and an external interface function of the form:
327 *
328 * void astClear<Attribute>_( AstFrame *this, int axis )
329 *
330 * which implement a method for clearing an attribute value for a specified
331 * axis of a Frame.
332
333 * Parameters:
334 * attribute
335 * The name of the attribute to be cleared, as it appears in the
336 * function name (e.g. Label in "astClearLabel").
337
338 * Notes:
339 * - This macro assumes the existence of a method of the form:
340 *
341 * void astClearAxis<Attribute>( AstAxis *this )
342 *
343 * which clears the required attribute for an Axis object.
344 * - To avoid problems with some compilers, you should not leave any white
345 * space around the macro arguments.
346 */
347
348 /* Define the macro. */
349 #define MAKE_CLEAR(attribute) \
350 \
351 /* Private member function. */ \
352 /* ------------------------ */ \
353 static void Clear##attribute( AstFrame *this, int axis, int *status ) { \
354 AstAxis *ax; /* Pointer to Axis object */ \
355 \
356 /* Check the global error status. */ \
357 if ( !astOK ) return; \
358 \
359 /* Validate the axis index and obtain a pointer to the required Axis. */ \
360 (void) astValidateAxis( this, axis, 1, "astClear" #attribute ); \
361 ax = astGetAxis( this, axis ); \
362 \
363 /* Clear the Axis attribute. */ \
364 astClearAxis##attribute( ax ); \
365 \
366 /* Annul the Axis pointer. */ \
367 ax = astAnnul( ax ); \
368 } \
369 \
370 /* External interface. */ \
371 /* ------------------- */ \
372 void astClear##attribute##_( AstFrame *this, int axis, int *status ) { \
373 \
374 /* Check the global error status. */ \
375 if ( !astOK ) return; \
376 \
377 /* Invoke the required method via the virtual function table. */ \
378 (**astMEMBER(this,Frame,Clear##attribute))( this, axis, status ); \
379 }
380
381 /*
382 * Name:
383 * MAKE_GET
384
385 * Purpose:
386 * Implement a method to get an attribute value for a Frame axis.
387
388 * Type:
389 * Private macro.
390
391 * Synopsis:
392 # #include "frame.h"
393 * MAKE_GET(attribute,type,bad_value,default,assign_default)
394
395 * Class Membership:
396 * Defined by the Frame class.
397
398 * Description:
399 * This macro expands to an implementation of a private member function of
400 * the form:
401 *
402 * static <Type> Get<Attribute>( AstFrame *this, int axis )
403 *
404 * and an external interface function of the form:
405 *
406 * Type astGet<Attribute>_( AstFrame *this, int axis )
407 *
408 * which implement a method for getting an attribute value for a specified
409 * axis of a Frame.
410
411 * Parameters:
412 * attribute
413 * The name of the attribute whose value is to be obtained, as
414 * it appears in the function name (e.g. Label in
415 * "astGetLabel").
416 * type
417 * The C type of the attribute.
418 * bad_value
419 * A constant value to return if the global error status is set, or if
420 * the function fails.
421 * default
422 * A boolean (int) constant that indicates whether a new default value
423 * should be returned by the method if the requested attribute has not
424 * been set for the axis. If this value is zero, the axis default will
425 * be used instead.
426 * assign_default
427 * An expression that evaluates to the new default value to be assigned.
428 * This value is ignored if "default" is zero, but a valid (e.g.
429 * constant) value should nevertheless be supplied.
430
431 * Notes:
432 * - This macro assumes the existence of a method of the form:
433 *
434 * <Type> astGetAxis<Attribute>( AstAxis *this )
435 *
436 * which gets the required attribute for an Axis object.
437 * - To avoid problems with some compilers, you should not leave any white
438 * space around the macro arguments.
439 */
440
441 /* Define the macro. */
442 #define MAKE_GET(attribute,type,bad_value,default,assign_default) \
443 \
444 /* Private member function. */ \
445 /* ------------------------ */ \
446 static type Get##attribute( AstFrame *this, int axis, int *status ) { \
447 AstAxis *ax; /* Pointer to Axis object */ \
448 int digits_set; /* Axis Digits attribute set? */ \
449 int old_axis; /* Original (un-permuted) axis index */ \
450 type result; /* Result to be returned */ \
451 \
452 /* Initialise. */ \
453 result = (bad_value); \
454 \
455 /* Check the global error status. */ \
456 if ( !astOK ) return result; \
457 \
458 /* Validate and permute the axis index and obtain a pointer to the required \
459 Axis. */ \
460 old_axis = axis; \
461 axis = astValidateAxis( this, axis, 1, "astGet" #attribute ); \
462 ax = astGetAxis( this, old_axis ); \
463 \
464 /* Since the Axis is "managed" by the enclosing Frame, we next test if any \
465 Axis attributes which may affect the result are undefined (i.e. have not \
466 been explicitly set). If so, we over-ride them, giving them temporary \
467 values dictated by the Frame. Only the Digits attribute is relevant \
468 here. */ \
469 digits_set = astTestAxisDigits( ax ); \
470 if ( !digits_set ) astSetAxisDigits( ax, astGetDigits( this ) ); \
471 \
472 /* If the default value is to be over-ridden, test if the Axis attribute has \
473 been set. Then, if required, obtain the attribute value from the Axis. */ \
474 if ( !(default) || astTestAxis##attribute( ax ) ) { \
475 result = astGetAxis##attribute( ax ); \
476 \
477 /* If required, assign the new default value. */ \
478 } else { \
479 result = (assign_default); \
480 } \
481 \
482 /* Clear Axis attributes which were temporarily over-ridden above and annul \
483 the Axis pointer. */ \
484 if ( !digits_set ) astClearAxisDigits( ax ); \
485 ax = astAnnul( ax ); \
486 \
487 /* If an error occurred, clear the result value. */ \
488 if ( !astOK ) result = (bad_value); \
489 \
490 /* Return the result. */ \
491 return result; \
492 } \
493 \
494 /* External interface. */ \
495 /* ------------------- */ \
496 type astGet##attribute##_( AstFrame *this, int axis, int *status ) { \
497 \
498 /* Check the global error status. */ \
499 if ( !astOK ) return (bad_value); \
500 \
501 /* Invoke the required method via the virtual function table. */ \
502 return (**astMEMBER(this,Frame,Get##attribute))( this, axis, status ); \
503 }
504
505 /*
506 * Name:
507 * MAKE_SET
508
509 * Purpose:
510 * Implement a method to set an attribute value for a Frame axis.
511
512 * Type:
513 * Private macro.
514
515 * Synopsis:
516 * #include "frame.h"
517 * MAKE_SET(attribute,type)
518
519 * Class Membership:
520 * Defined by the Frame class.
521
522 * Description:
523 * This macro expands to an implementation of a private member function of
524 * the form:
525 *
526 * static void Set<Attribute>( AstFrame *this, int axis, <Type> value )
527 *
528 * and an external interface function of the form:
529 *
530 * void astSet<Attribute>_( AstFrame *this, int axis, <Type> value )
531 *
532 * which implement a method for setting an attribute value for a specified
533 * axis of a Frame.
534
535 * Parameters:
536 * attribute
537 * The name of the attribute to be set, as it appears in the
538 * function name (e.g. Label in "astSetLabel").
539 * type
540 * The C type of the attribute.
541
542 * Notes:
543 * - This macro assumes the existence of a method of the form:
544 *
545 * void astSetAxis<Attribute>( AstAxis *this, <Type> value )
546 *
547 * which sets the required attribute for an Axis object.
548 * - To avoid problems with some compilers, you should not leave any white
549 * space around the macro arguments.
550 */
551
552 /* Define the macro. */
553 #define MAKE_SET(attribute,type) \
554 \
555 /* Private member function. */ \
556 /* ------------------------ */ \
557 static void Set##attribute( AstFrame *this, int axis, type value, int *status ) { \
558 AstAxis *ax; /* Pointer to Axis object */ \
559 \
560 /* Check the global error status. */ \
561 if ( !astOK ) return; \
562 \
563 /* Validate the axis index and obtain a pointer to the required Axis. */ \
564 (void) astValidateAxis( this, axis, 1, "astSet" #attribute ); \
565 ax = astGetAxis( this, axis ); \
566 \
567 /* Set the Axis attribute value. */ \
568 astSetAxis##attribute( ax, value ); \
569 \
570 /* Annul the Axis pointer. */ \
571 ax = astAnnul( ax ); \
572 } \
573 \
574 /* External interface. */ \
575 /* ------------------- */ \
576 void astSet##attribute##_( AstFrame *this, int axis, type value, int *status ) { \
577 \
578 /* Check the global error status. */ \
579 if ( !astOK ) return; \
580 \
581 /* Invoke the required method via the virtual function table. */ \
582 (**astMEMBER(this,Frame,Set##attribute))( this, axis, value, status ); \
583 }
584
585 /*
586 * Name:
587 * MAKE_TEST
588
589 * Purpose:
590 * Implement a method to test if an attribute has been set for a Frame axis.
591
592 * Type:
593 * Private macro.
594
595 * Synopsis:
596 * #include "frame.h"
597 * MAKE_TEST(attribute)
598
599 * Class Membership:
600 * Defined by the Frame class.
601
602 * Description:
603 * This macro expands to an implementation of a private member function of
604 * the form:
605 *
606 * static int Test<Attribute>( AstFrame *this, int axis )
607 *
608 * and an external interface function of the form:
609 *
610 * int astTest<Attribute>_( AstFrame *this, int axis )
611 *
612 * which implement a method for testing if an attribute has been set for a
613 * specified axis of a Frame.
614
615 * Parameters:
616 * attribute
617 * The name of the attribute to be tested, as it appears in the
618 * function name (e.g. Label in "astTestLabel").
619
620 * Notes:
621 * - This macro assumes the existence of a method of the form:
622 *
623 * void astTestAxis<Attribute>( AstAxis *this )
624 *
625 * which tests the required attribute for an Axis object.
626 * - To avoid problems with some compilers, you should not leave any white
627 * space around the macro arguments.
628 */
629
630 /* Define the macro. */
631 #define MAKE_TEST(attribute) \
632 \
633 /* Private member function. */ \
634 /* ------------------------ */ \
635 static int Test##attribute( AstFrame *this, int axis, int *status ) { \
636 AstAxis *ax; /* Pointer to Axis object */ \
637 int result; /* Value to be returned */ \
638 \
639 /* Check the global error status. */ \
640 if ( !astOK ) return 0; \
641 \
642 /* Validate the axis index and obtain a pointer to the required Axis. */ \
643 (void) astValidateAxis( this, axis, 1, "astTest" #attribute ); \
644 ax = astGetAxis( this, axis ); \
645 \
646 /* Test if the attribute has been set. */ \
647 result = astTestAxis##attribute( ax ); \
648 \
649 /* Annul the Axis pointer. */ \
650 ax = astAnnul( ax ); \
651 \
652 /* If an error occurred, clear the result value. */ \
653 if ( !astOK ) result = 0; \
654 \
655 /* Return the result. */ \
656 return result; \
657 } \
658 \
659 /* External interface. */ \
660 /* ------------------- */ \
661 int astTest##attribute##_( AstFrame *this, int axis, int *status ) { \
662 \
663 /* Check the global error status. */ \
664 if ( !astOK ) return 0; \
665 \
666 /* Invoke the required method via the virtual function table. */ \
667 return (**astMEMBER(this,Frame,Test##attribute))( this, axis, status ); \
668 }
669
670 /* Header files. */
671 /* ============= */
672 /* Interface definitions. */
673 /* ---------------------- */
674
675 #include "globals.h" /* Thread-safe global data access */
676 #include "error.h" /* Error reporting facilities */
677 #include "memory.h" /* Memory allocation facilities */
678 #include "object.h" /* Base Object class */
679 #include "mapping.h" /* Coordinate mappings (parent class) */
680 #include "pointset.h" /* Sets of points */
681 #include "unitmap.h" /* Unit Mapping */
682 #include "permmap.h" /* Coordinate permutation Mapping */
683 #include "cmpmap.h" /* Compound Mappings */
684 #include "axis.h" /* Coordinate Axis */
685 #include "skyaxis.h" /* Sky coordinate axes */
686 #include "skyframe.h" /* Celestial coordinate frames */
687 #include "channel.h" /* I/O channels */
688 #include "frame.h" /* Interface definition for this class */
689 #include "frameset.h" /* Collections of Frames */
690 #include "cmpframe.h" /* Compound Frames */
691 #include "pal.h" /* SLALIB library interface */
692 #include "unit.h" /* Units identification and mapping */
693 #include "globals.h" /* Thread-safe global data access */
694
695 /* Error code definitions. */
696 /* ----------------------- */
697 #include "ast_err.h" /* AST error codes */
698
699 /* C header files. */
700 /* --------------- */
701 #include <ctype.h>
702 #include <limits.h>
703 #include <math.h>
704 #include <stddef.h>
705 #include <stdio.h>
706 #include <string.h>
707
708 /* Module Variables. */
709 /* ================= */
710
711 /* Address of this static variable is used as a unique identifier for
712 member of this class. */
713 static int class_check;
714
715 /* Pointers to parent class methods which are extended by this class. */
716 static const char *(* parent_getattrib)( AstObject *, const char *, int * );
717 static int (* parent_testattrib)( AstObject *, const char *, int * );
718 static void (* parent_clearattrib)( AstObject *, const char *, int * );
719 static void (* parent_setattrib)( AstObject *, const char *, int * );
720 static void (* parent_cleanattribs)( AstObject *, int * );
721 static int (* parent_getobjsize)( AstObject *, int * );
722
723 #if defined(THREAD_SAFE)
724 static int (* parent_managelock)( AstObject *, int, int, AstObject **, int * );
725 #endif
726
727 /* Define a variable to hold a SkyFrame which will be used for formatting
728 and unformatting ObsLat and ObsLon values. */
729 static AstSkyFrame *skyframe;
730
731 /* Define macros for accessing each item of thread specific global data. */
732 #ifdef THREAD_SAFE
733
734 /* Define how to initialise thread-specific globals. */
735 #define GLOBAL_inits \
736 globals->Class_Init = 0; \
737 globals->GetAttrib_Buff[ 0 ] = 0; \
738 globals->AstFormatID_Init = 0; \
739 globals->AstFormatID_Istr = 0; \
740 globals->Label_Buff[ 0 ] = 0; \
741 globals->Symbol_Buff[ 0 ] = 0; \
742 globals->Title_Buff[ 0 ] = 0; \
743 globals->AstFmtDecimalYr_Buff[ 0 ] = 0;
744
745 /* Create the function that initialises global data for this module. */
746 astMAKE_INITGLOBALS(Frame)
747
748 #define class_init astGLOBAL(Frame,Class_Init)
749 #define class_vtab astGLOBAL(Frame,Class_Vtab)
750 #define getattrib_buff astGLOBAL(Frame,GetAttrib_Buff)
751 #define astformatid_strings astGLOBAL(Frame,AstFormatID_Strings)
752 #define astformatid_istr astGLOBAL(Frame,AstFormatID_Istr)
753 #define astformatid_init astGLOBAL(Frame,AstFormatID_Init)
754 #define label_buff astGLOBAL(Frame,Label_Buff)
755 #define symbol_buff astGLOBAL(Frame,Symbol_Buff)
756 #define title_buff astGLOBAL(Frame,Title_Buff)
757 #define astfmtdecimalyr_buff astGLOBAL(Frame,AstFmtDecimalYr_Buff)
758
759
760
761 /* If thread safety is not needed, declare and initialise globals at static
762 variables. */
763 #else
764
765 /* Buffer returned by GetAttrib. */
766 static char getattrib_buff[ GETATTRIB_BUFF_LEN + 1 ];
767
768 /* Strings returned by astFormatID */
769 static char *astformatid_strings[ ASTFORMATID_MAX_STRINGS ];
770
771 /* Offset of next string in "AstFormatID_Strings" */
772 static int astformatid_istr;
773
774 /* "AstFormatID_Strings" array initialised? */
775 static int astformatid_init;
776
777 /* Default Label string buffer */
778 static char label_buff[ LABEL_BUFF_LEN + 1 ];
779
780 /* Default Symbol buffer */
781 static char symbol_buff[ SYMBOL_BUFF_LEN + 1 ];
782
783 /* Default Title string buffer */
784 static char title_buff[ TITLE_BUFF_LEN + 1 ];
785
786 /* Buffer for result string */
787 static char astfmtdecimalyr_buff[ ASTFMTDECIMALYR_BUFF_LEN + 1 ];
788
789
790 /* Define the class virtual function table and its initialisation flag
791 as static variables. */
792 static AstFrameVtab class_vtab; /* Virtual function table */
793 static int class_init = 0; /* Virtual function table initialised? */
794
795 #endif
796
797
798 /* Prototypes for Private Member Functions. */
799 /* ======================================== */
800 static AstAxis *GetAxis( AstFrame *, int, int * );
801 static AstFrame *PickAxes( AstFrame *, int, const int[], AstMapping **, int * );
802 static AstFrameSet *Convert( AstFrame *, AstFrame *, const char *, int * );
803 static AstFrameSet *ConvertX( AstFrame *, AstFrame *, const char *, int * );
804 static AstFrameSet *FindFrame( AstFrame *, AstFrame *, const char *, int * );
805 static void MatchAxes( AstFrame *, AstFrame *, int *, int * );
806 static void MatchAxesX( AstFrame *, AstFrame *, int *, int * );
807 static AstLineDef *LineDef( AstFrame *, const double[2], const double[2], int * );
808 static AstPointSet *FrameGrid( AstFrame *, int, const double *, const double *, int * );
809 static AstPointSet *ResolvePoints( AstFrame *, const double [], const double [], AstPointSet *, AstPointSet *, int * );
810 static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
811 static char *CleanDomain( char *, int * );
812 static const char *Abbrev( AstFrame *, int, const char *, const char *, const char *, int * );
813 static const char *Format( AstFrame *, int, double, int * );
814 static const char *GetAttrib( AstObject *, const char *, int * );
815 static const char *GetDefaultLabel( int, int * );
816 static const char *GetDefaultSymbol( AstFrame *, int, int * );
817 static const char *GetDefaultTitle( AstFrame *, int * );
818 static const char *GetDomain( AstFrame *, int * );
819 static const char *GetFormat( AstFrame *, int, int * );
820 static const char *GetLabel( AstFrame *, int, int * );
821 static const char *GetNormUnit( AstFrame *, int, int * );
822 static const char *GetSymbol( AstFrame *, int, int * );
823 static const char *GetTitle( AstFrame *, int * );
824 static const char *GetUnit( AstFrame *, int, int * );
825 static const int *GetPerm( AstFrame *, int * );
826 static double Angle( AstFrame *, const double[], const double[], const double[], int * );
827 static double AxAngle( AstFrame *, const double[], const double[], int, int * );
828 static double AxDistance( AstFrame *, int, double, double, int * );
829 static double AxOffset( AstFrame *, int, double, double, int * );
830 static double Distance( AstFrame *, const double[], const double[], int * );
831 static double Gap( AstFrame *, int, double, int *, int * );
832 static double Offset2( AstFrame *, const double[2], double, double, double[2], int * );
833 static int AxIn( AstFrame *, int, double, double, double, int, int * );
834 static int ConsistentMaxAxes( AstFrame *, int, int * );
835 static int ConsistentMinAxes( AstFrame *, int, int * );
836 static int DefaultMaxAxes( AstFrame *, int * );
837 static int DefaultMinAxes( AstFrame *, int * );
838 static int DoNotSimplify( AstMapping *, int * );
839 static int Equal( AstObject *, AstObject *, int * );
840 static int Fields( AstFrame *, int, const char *, const char *, int, char **, int *, double *, int * );
841 static int GetDigits( AstFrame *, int * );
842 static int GetDirection( AstFrame *, int, int * );
843 static int GetIsLinear( AstMapping *, int * );
844 static int GetIsSimple( AstMapping *, int * );
845 static int LineContains( AstFrame *, AstLineDef *, int, double *, int * );
846 static int LineCrossing( AstFrame *, AstLineDef *, AstLineDef *, double **, int * );
847 static int GetObjSize( AstObject *, int * );
848 static void CleanAttribs( AstObject *, int * );
849 static void LineOffset( AstFrame *, AstLineDef *, double, double, double[2], int * );
850
851 static double GetTop( AstFrame *, int, int * );
852 static int TestTop( AstFrame *, int, int * );
853 static void ClearTop( AstFrame *, int, int * );
854 static void SetTop( AstFrame *, int, double, int * );
855
856 static double GetBottom( AstFrame *, int, int * );
857 static int TestBottom( AstFrame *, int, int * );
858 static void ClearBottom( AstFrame *, int, int * );
859 static void SetBottom( AstFrame *, int, double, int * );
860
861 static AstSystemType GetSystem( AstFrame *, int * );
862 static int TestSystem( AstFrame *, int * );
863 static void ClearSystem( AstFrame *, int * );
864 static void SetSystem( AstFrame *, AstSystemType, int * );
865
866 static AstSystemType GetAlignSystem( AstFrame *, int * );
867 static int TestAlignSystem( AstFrame *, int * );
868 static void ClearAlignSystem( AstFrame *, int * );
869 static void SetAlignSystem( AstFrame *, AstSystemType, int * );
870
871 static double GetEpoch( AstFrame *, int * );
872 static int TestEpoch( AstFrame *, int * );
873 static void ClearEpoch( AstFrame *, int * );
874 static void SetEpoch( AstFrame *, double, int * );
875
876 static double GetObsLat( AstFrame *, int * );
877 static int TestObsLat( AstFrame *, int * );
878 static void ClearObsLat( AstFrame *, int * );
879 static void SetObsLat( AstFrame *, double, int * );
880
881 static double GetObsLon( AstFrame *, int * );
882 static int TestObsLon( AstFrame *, int * );
883 static void ClearObsLon( AstFrame *, int * );
884 static void SetObsLon( AstFrame *, double, int * );
885
886 static double GetObsAlt( AstFrame *, int * );
887 static int TestObsAlt( AstFrame *, int * );
888 static void ClearObsAlt( AstFrame *, int * );
889 static void SetObsAlt( AstFrame *, double, int * );
890
891 static double GetDut1( AstFrame *, int * );
892 static int TestDut1( AstFrame *, int * );
893 static void ClearDut1( AstFrame *, int * );
894 static void SetDut1( AstFrame *, double, int * );
895
896 static int GetActiveUnit( AstFrame *, int * );
897 static int TestActiveUnit( AstFrame *, int * );
898 static void SetActiveUnit( AstFrame *, int, int * );
899
900 static AstFrameSet *GetFrameVariants( AstFrame *, int * );
901 static void SetFrameVariants( AstFrame *, AstFrameSet *, int * );
902
903 static int GetFrameFlags( AstFrame *, int * );
904 static int *MapSplit( AstMapping *, int, const int *, AstMapping **, int * );
905 static int GetMatchEnd( AstFrame *, int * );
906 static int GetMaxAxes( AstFrame *, int * );
907 static int GetMinAxes( AstFrame *, int * );
908 static int GetNaxes( AstFrame *, int * );
909 static int GetNin( AstMapping *, int * );
910 static int GetNout( AstMapping *, int * );
911 static int GetPermute( AstFrame *, int * );
912 static int GetPreserveAxes( AstFrame *, int * );
913 static int Match( AstFrame *, AstFrame *, int, int **, int **, AstMapping **, AstFrame **, int * );
914 static int SubFrame( AstFrame *, AstFrame *, int, const int *, const int *, AstMapping **, AstFrame **, int * );
915 static int TestAttrib( AstObject *, const char *, 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 IsUnitFrame( AstFrame *, int * );
930 static int Unformat( AstFrame *, int, const char *, double *, int * );
931 static int ValidateAxis( AstFrame *, int, int, const char *, int * );
932 static AstSystemType ValidateSystem( AstFrame *, AstSystemType, const char *, int * );
933 static AstSystemType SystemCode( AstFrame *, const char *, int * );
934 static const char *SystemString( AstFrame *, AstSystemType, int * );
935 static void AddUnderscores( char *, int * );
936 static void CheckPerm( AstFrame *, const int *, const char *, int * );
937 static void ClearAttrib( AstObject *, const char *, int * );
938 static void ClearDigits( AstFrame *, int * );
939 static void ClearDirection( AstFrame *, int, int * );
940 static void ClearDomain( AstFrame *, int * );
941 static void ClearFormat( AstFrame *, int, int * );
942 static void ClearLabel( AstFrame *, int, int * );
943 static void ClearMatchEnd( AstFrame *, int * );
944 static void ClearMaxAxes( AstFrame *, int * );
945 static void ClearMinAxes( AstFrame *, int * );
946 static void ClearPermute( AstFrame *, int * );
947 static void ClearPreserveAxes( AstFrame *, int * );
948 static void ClearSymbol( AstFrame *, int, int * );
949 static void ClearTitle( AstFrame *, int * );
950 static void ClearUnit( AstFrame *, int, int * );
951 static void Copy( const AstObject *, AstObject *, int * );
952 static void Delete( AstObject *, int * );
953 static void Dump( AstObject *, AstChannel *, int * );
954 static void Intersect( AstFrame *, const double[2], const double[2], const double[2], const double[2], double[2], int * );
955 static void Norm( AstFrame *, double[], int * );
956 static void NormBox( AstFrame *, double[], double[], AstMapping *, int * );
957 static void Offset( AstFrame *, const double[], const double[], double, double[], int * );
958 static void Overlay( AstFrame *, const int *, AstFrame *, int * );
959 static void PermAxes( AstFrame *, const int[], int * );
960 static void PrimaryFrame( AstFrame *, int, AstFrame **, int *, int * );
961 static void ReportPoints( AstMapping *, int, AstPointSet *, AstPointSet *, int * );
962 static void Resolve( AstFrame *, const double [], const double [], const double [], double [], double *, double *, int * );
963 static void SetAttrib( AstObject *, const char *, int * );
964 static void SetAxis( AstFrame *, int, AstAxis *, int * );
965 static void SetDigits( AstFrame *, int, int * );
966 static void SetDirection( AstFrame *, int, int, int * );
967 static void SetDomain( AstFrame *, const char *, int * );
968 static void SetFormat( AstFrame *, int, const char *, int * );
969 static void SetFrameFlags( AstFrame *, int, int * );
970 static void SetLabel( AstFrame *, int, const char *, int * );
971 static void SetMatchEnd( AstFrame *, int, int * );
972 static void SetMaxAxes( AstFrame *, int, int * );
973 static void SetMinAxes( AstFrame *, int, int * );
974 static void SetPermute( AstFrame *, int, int * );
975 static void SetPreserveAxes( AstFrame *, int, int * );
976 static void SetSymbol( AstFrame *, int, const char *, int * );
977 static void SetTitle( AstFrame *, const char *, int * );
978 static void SetUnit( AstFrame *, int, const char *, int * );
979 static void NewUnit( AstAxis *, const char *, const char *, const char *, const char *, int * );
980 static void ValidateAxisSelection( AstFrame *, int, const int *, const char *, int * );
981
982 #if defined(THREAD_SAFE)
983 static int ManageLock( AstObject *, int, int, AstObject **, int * );
984 #endif
985
986 /* Member functions. */
987 /* ================= */
Abbrev(AstFrame * this,int axis,const char * fmt,const char * str1,const char * str2,int * status)988 static const char *Abbrev( AstFrame *this, int axis, const char *fmt,
989 const char *str1, const char *str2, int *status ) {
990 /*
991 *+
992 * Name:
993 * astAbbrev
994
995 * Purpose:
996 * Abbreviate a formatted Frame axis value by skipping leading fields.
997
998 * Type:
999 * Protected virtual function.
1000
1001 * Synopsis:
1002 * #include "frame.h"
1003 * const char *astAbbrev( AstFrame *this, int axis, const char *fmt,
1004 * const char *str1, const char *str2 )
1005
1006 * Class Membership:
1007 * Frame method.
1008
1009 * Description:
1010 * This function compares two Frame axis values that have been
1011 * formatted (using astFormat) and determines if they have any
1012 * redundant leading fields (i.e. leading fields in common which
1013 * can be suppressed when tabulating the values or plotting them on
1014 * the axis of a graph).
1015
1016 * Parameters:
1017 * this
1018 * Pointer to the Frame.
1019 * axis
1020 * The number of the Frame axis for which the values have been
1021 * formatted (axis numbering starts at zero for the first axis).
1022 * fmt
1023 * Pointer to a constant null-terminated string containing the
1024 * format specification used to format the two values.
1025 * str1
1026 * Pointer to a constant null-terminated string containing the
1027 * first formatted value. If this is null, the returned pointer
1028 * points to the start of the final field in str2.
1029 * str2
1030 * Pointer to a constant null-terminated string containing the
1031 * second formatted value.
1032
1033 * Returned Value:
1034 * A pointer into the "str2" string which locates the first
1035 * character in the first field that differs between the two
1036 * formatted values.
1037 *
1038 * If the two values have no leading fields in common, the returned
1039 * value will point at the start of string "str2". If the two
1040 * values are equal, it will point at the terminating null at the
1041 * end of this string.
1042
1043 * Notes:
1044 * - This function assumes that the format specification used was
1045 * the same when both values were formatted and that they both
1046 * apply to the same Frame axis.
1047 * - A pointer to the start of "str2" will be returned if this
1048 * function is invoked with the global error status set, or if it
1049 * should fail for any reason.
1050 *-
1051 */
1052
1053 /* Local Variables: */
1054 AstAxis *ax; /* Pointer to Axis object */
1055 const char *result; /* Result pointer to return */
1056
1057 /* Initialise. */
1058 result = str2;
1059
1060 /* Check the global error status. */
1061 if ( !astOK ) return result;
1062
1063 /* Validate the axis index and obtain a pointer to the required
1064 Axis. */
1065 (void) astValidateAxis( this, axis, 1, "astAbbrev" );
1066 ax = astGetAxis( this, axis );
1067
1068 /* Invoke the Axis astAxisAbbrev method to perform the processing. */
1069 result = astAxisAbbrev( ax, fmt, str1, str2 );
1070
1071 /* Annul the Axis pointer. */
1072 ax = astAnnul( ax );
1073
1074 /* If an error occurred, clear the returned value. */
1075 if ( !astOK ) result = str2;
1076
1077 /* Return the result. */
1078 return result;
1079 }
1080
AddUnderscores(char * string,int * status)1081 static void AddUnderscores( char *string, int *status ) {
1082 /*
1083 * Name:
1084 * AddUnderscores
1085
1086 * Purpose:
1087 * Add underscores to a string in place of white space.
1088
1089 * Type:
1090 * Private function.
1091
1092 * Synopsis:
1093 * #include "frame.h"
1094 * void AddUnderscores( char *string, int *status )
1095
1096 * Class Membership:
1097 * Frame member function.
1098
1099 * Description:
1100 * This function changes all white space characters in a string into
1101 * the underscore character '_'.
1102
1103 * Parameters:
1104 * this
1105 * Pointer to the Frame.
1106 * string
1107 * Pointer to the null terminated string to be processed.
1108 * status
1109 * Pointer to the inherited status variable.
1110 */
1111
1112 /* Local Variables. */
1113 int i; /* Loop counter for characters */
1114
1115 /* Inspect each character in the string. */
1116 for ( i = 0; string[ i ]; i++ ) {
1117
1118 /* If it is a white space character, replace it with an underscore. */
1119 if ( isspace( string[ i ] ) ) string[ i ] = '_';
1120 }
1121 }
1122
Angle(AstFrame * this,const double a[],const double b[],const double c[],int * status)1123 static double Angle( AstFrame *this, const double a[],
1124 const double b[], const double c[], int *status ) {
1125 /*
1126 *++
1127 * Name:
1128 c astAngle
1129 f AST_ANGLE
1130
1131 * Purpose:
1132 * Calculate the angle subtended by two points at a third point.
1133
1134 * Type:
1135 * Public virtual function.
1136
1137 * Synopsis:
1138 c #include "frame.h"
1139 c double astAngle( AstFrame *this, const double a[], const double b[],
1140 c const double c[] )
1141 f RESULT = AST_ANGLE( THIS, A, B, C, STATUS )
1142
1143 * Class Membership:
1144 * Frame method.
1145
1146 * Description:
1147 c This function
1148 f This routine
1149 * finds the angle at point B between the line joining points A and B,
1150 * and the line joining points C and B. These lines will in fact be
1151 * geodesic curves appropriate to the Frame in use. For instance, in
1152 * SkyFrame, they will be great circles.
1153
1154 * Parameters:
1155 c this
1156 f THIS = INTEGER (Given)
1157 * Pointer to the Frame.
1158 c a
1159 f A( * ) = DOUBLE PRECISION (Given)
1160 c An array of double, with one element for each Frame axis
1161 f An array with one element for each Frame axis
1162 * (Naxes attribute) containing the coordinates of the first point.
1163 c b
1164 f B( * ) = DOUBLE PRECISION (Given)
1165 c An array of double, with one element for each Frame axis
1166 f An array with one element for each Frame axis
1167 * (Naxes attribute) containing the coordinates of the second point.
1168 c c
1169 f C( * ) = DOUBLE PRECISION (Given)
1170 c An array of double, with one element for each Frame axis
1171 f An array with one element for each Frame axis
1172 * (Naxes attribute) containing the coordinates of the third point.
1173 f STATUS = INTEGER (Given and Returned)
1174 f The global status.
1175
1176 * Returned Value:
1177 c astAngle
1178 f AST_ANGLE = DOUBLE PRECISION
1179 * The angle in radians, from the line AB to the line CB. If the
1180 * Frame is 2-dimensional, it will be in the range $\pm \pi$,
1181 * and positive rotation is in the same sense as rotation from
1182 * the positive direction of axis 2 to the positive direction of
1183 * axis 1. If the Frame has more than 2 axes, a positive value will
1184 * always be returned in the range zero to $\pi$.
1185
1186 * Notes:
1187 * - A value of AST__BAD will also be returned if points A and B are
1188 * co-incident, or if points B and C are co-incident.
1189 * - A value of AST__BAD will also be returned if this function is
1190 c invoked with the AST error status set, or if it should fail for
1191 f invoked with STATUS set to an error value, or if it should fail for
1192 * any reason.
1193 *--
1194 */
1195
1196 /* Local Variables: */
1197 double *ab; /* Pointer to vector AB */
1198 double *cb; /* Pointer to vector CB */
1199 double cos; /* cosine of required angle */
1200 double anga; /* Angle from +ve Y to the line BA */
1201 double angc; /* Angle from +ve Y to the line BC */
1202 double result; /* Result value to return */
1203 double sla; /* Squared length of vector AB */
1204 double slc; /* Squared length of vector CB */
1205 double sp; /* Scalar product of AB and CB */
1206 int axis; /* Axis index */
1207 int naxes; /* Number of Frame axes */
1208 int ok; /* Supplied points OK? */
1209
1210 /* Initialise. */
1211 result = AST__BAD;
1212
1213 /* Check the global error status. */
1214 if ( !astOK ) return result;
1215
1216 /* Assume everything is ok */
1217 ok = 1;
1218
1219 /* Obtain the number of Frame axes. */
1220 naxes = astGetNaxes( this );
1221
1222 /* Obtain workspace. */
1223 ab = (double *) astMalloc( sizeof(double)*naxes );
1224 cb = (double *) astMalloc( sizeof(double)*naxes );
1225
1226 /* Check all positions are good, and form the vectors from b to a, and
1227 from b to c. Also find the squared length of each vector. */
1228 if( astOK ) {
1229 sla = 0.0;
1230 slc = 0.0;
1231 for( axis = 0; axis < naxes; axis++ ) {
1232 if( a[ axis ] == AST__BAD || b[ axis ] == AST__BAD ||
1233 c[ axis ] == AST__BAD ) {
1234 ok = 0;
1235 break;
1236 } else {
1237 ab[ axis ] = a[ axis ] - b[ axis ];
1238 cb[ axis ] = c[ axis ] - b[ axis ];
1239 sla += ( ab[ axis ] )*( ab[ axis ] );
1240 slc += ( cb[ axis ] )*( cb[ axis ] );
1241 }
1242 }
1243
1244 /* Check that neither of the vectors have zero length. */
1245 if( sla == 0 || slc == 0 ) ok = 0;
1246
1247 /* Only proceed if these checks were passed. */
1248 if ( ok ) {
1249
1250 /* Deal first with 2-dimensional Frames. */
1251 if( naxes == 2 ) {
1252
1253 /* Find the angle from +ve Y to the line BA. */
1254 anga = atan2( ab[ 0 ], ab[ 1 ] );
1255
1256 /* Find the angle from +ve Y to the line BC. */
1257 angc = atan2( cb[ 0 ], cb[ 1 ] );
1258
1259 /* Find the difference, folded into the range +/- PI. */
1260 result = palDrange( angc - anga );
1261
1262 /* Now deal with Frames with more than 2 axes. */
1263 } else {
1264
1265 /* Form the scalar product of the two vectors. */
1266 sp = 0.0;
1267 for( axis = 0; axis < naxes; axis++ ) {
1268 sp += ab[ axis ]*cb[ axis ];
1269 }
1270
1271 /* Derive the required angle from the normalized scalar product. */
1272 cos = sp/sqrt( sla*slc );
1273 if( cos > 1.0 ) {
1274 cos = 1.0;
1275 } else if( cos < -1.0 ) {
1276 cos = -1.0;
1277 }
1278 result =acos( cos );
1279 }
1280 }
1281 }
1282
1283 /* Free the work space. */
1284 ab = (double *) astFree( (void *) ab );
1285 cb = (double *) astFree( (void *) cb );
1286
1287 /* Return the result. */
1288 return result;
1289 }
1290
AxAngle(AstFrame * this,const double a[],const double b[],int axis,int * status)1291 static double AxAngle( AstFrame *this, const double a[], const double b[], int axis, int *status ) {
1292 /*
1293 *++
1294 * Name:
1295 c astAxAngle
1296 f AST_AXANGLE
1297
1298 * Purpose:
1299 * Returns the angle from an axis, to a line through two points.
1300
1301 * Type:
1302 * Public virtual function.
1303
1304 * Synopsis:
1305 c #include "frame.h"
1306 c double astAxAngle( AstFrame *this, const double a[], const double b[], int axis )
1307 f RESULT = AST_AXANGLE( THIS, A, B, AXIS, STATUS )
1308
1309 * Class Membership:
1310 * Frame method.
1311
1312 * Description:
1313 c This function
1314 f This routine
1315 * finds the angle, as seen from point A, between the positive
1316 * direction of a specified axis, and the geodesic curve joining point
1317 * A to point B.
1318
1319 * Parameters:
1320 c this
1321 f THIS = INTEGER (Given)
1322 * Pointer to the Frame.
1323 c a
1324 f A( * ) = DOUBLE PRECISION (Given)
1325 c An array of double, with one element for each Frame axis
1326 f An array with one element for each Frame axis
1327 * (Naxes attribute) containing the coordinates of the first point.
1328 c b
1329 f B( * ) = DOUBLE PRECISION (Given)
1330 c An array of double, with one element for each Frame axis
1331 f An array with one element for each Frame axis
1332 * (Naxes attribute) containing the coordinates of the second point.
1333 c axis
1334 f AXIS = INTEGER (Given)
1335 * The number of the Frame axis from which the angle is to be
1336 * measured (axis numbering starts at 1 for the first axis).
1337 f STATUS = INTEGER (Given and Returned)
1338 f The global status.
1339
1340 * Returned Value:
1341 c astAxAngle
1342 f AST_AXANGLE = DOUBLE PRECISION
1343 * The angle in radians, from the positive direction of the
1344 * specified axis, to the line AB. If the Frame is 2-dimensional,
1345 * it will be in the range [-PI/2,+PI/2], and positive rotation is in
1346 * the same sense as rotation from the positive direction of axis 2
1347 * to the positive direction of axis 1. If the Frame has more than 2
1348 * axes, a positive value will always be returned in the range zero
1349 * to PI.
1350
1351 * Notes:
1352 c - The geodesic curve used by this function is the path of
1353 f - The geodesic curve used by this routine is the path of
1354 * shortest distance between two points, as defined by the
1355 c astDistance function.
1356 f AST_DISTANCE function.
1357 * - This function will return "bad" coordinate values (AST__BAD)
1358 * if any of the input coordinates has this value, or if the require
1359 * position angle is undefined.
1360 *--
1361 */
1362
1363 /* Local Variables: */
1364 double *aa; /* Pointer to third point */
1365 double ab; /* Absolute value of component */
1366 double mxab; /* Largest absolute value of component */
1367 double result; /* The returned value */
1368 int iaxis; /* Axis index */
1369 int naxes; /* Number of Frame axes */
1370 int ok; /* Are values ok to use? */
1371
1372 /* Initialise. */
1373 result = AST__BAD;
1374
1375 /* Check the global error status. */
1376 if ( !astOK ) return result;
1377
1378 /* Validate the axis index. */
1379 (void) astValidateAxis( this, axis - 1, 1, "astAxAngle" );
1380
1381 /* Obtain the number of Frame axes. */
1382 naxes = astGetNaxes( this );
1383
1384 /* Obtain workspace. */
1385 aa = (double *) astMalloc( sizeof(double)*naxes );
1386
1387 /* Create a position which is offset slightly from point A in the
1388 positive direction of the specified axis. Also get the largest absolute
1389 value of any component of the vector AB. */
1390 if( astOK ) {
1391 ok = 1;
1392 mxab = 0.0;
1393
1394 for( iaxis = 0; iaxis < naxes; iaxis++ ) {
1395 if( a[ iaxis ] != AST__BAD && b[ iaxis ] != AST__BAD ) {
1396 aa[ iaxis ] = a[ iaxis ];
1397 ab = fabs( a[ iaxis ] - b[ iaxis ] );
1398 if( ab > mxab ) mxab = ab;
1399 } else {
1400 ok = 0;
1401 break;
1402 }
1403 }
1404
1405 if( ok ) {
1406
1407 if( a[ axis - 1 ] != 0.0 ) {
1408 aa[ axis - 1 ] += 10000.0*DBL_EPSILON*fabs( a[ axis - 1 ] );
1409
1410 } else if( b[ axis - 1 ] != 0.0 ) {
1411 aa[ axis - 1 ] = 10000.0*DBL_EPSILON*fabs( b[ iaxis - 1 ] );
1412
1413 } else if( mxab != 0.0 ) {
1414 aa[ axis - 1 ] = 10000.0*DBL_EPSILON*mxab;
1415
1416 } else {
1417 aa[ axis - 1 ] = 1.0;
1418 }
1419
1420 /* Use astAngle to get the required angle. */
1421 result = astAngle( this, aa, a, b );
1422 }
1423 }
1424
1425 /* Free the workspace. */
1426 aa = (double *) astFree( (void *) aa );
1427
1428 /* Return the result. */
1429 return result;
1430
1431 }
1432
AxDistance(AstFrame * this,int axis,double v1,double v2,int * status)1433 static double AxDistance( AstFrame *this, int axis, double v1, double v2, int *status ) {
1434 /*
1435 *++
1436 * Name:
1437 c astAxDistance
1438 f AST_AXDISTANCE
1439
1440 * Purpose:
1441 * Find the distance between two axis values.
1442
1443 * Type:
1444 * Public virtual function.
1445
1446 * Synopsis:
1447 c #include "frame.h"
1448 c double astAxDistance( AstFrame *this, int axis, double v1, double v2 )
1449 f RESULT = AST_AXDISTANCE( THIS, AXIS, V1, V2, STATUS )
1450
1451 * Class Membership:
1452 * Frame method.
1453
1454 * Description:
1455 c This function returns a signed value representing the axis increment
1456 f This routine returns a signed value representing the axis increment
1457 * from axis value v1 to axis value v2.
1458 *
1459 * For a simple Frame, this is a trivial operation returning the
1460 * difference between the two axis values. But for other derived classes
1461 * of Frame (such as a SkyFrame) this is not the case.
1462
1463 * Parameters:
1464 c this
1465 f THIS = INTEGER (Given)
1466 * Pointer to the Frame.
1467 c axis
1468 f AXIS = INTEGER (Given)
1469 * The index of the axis to which the supplied values refer. The
1470 * first axis has index 1.
1471 c v1
1472 f V1 = DOUBLE PRECISION (Given)
1473 * The first axis value.
1474 c v2
1475 f V2 = DOUBLE PRECISION (Given)
1476 * The second axis value.
1477 f STATUS = INTEGER (Given and Returned)
1478 f The global status.
1479
1480 * Returned Value:
1481 c astAxDistance
1482 f AST_AXDISTANCE = DOUBLE PRECISION
1483 * The distance from the first to the second axis value.
1484
1485 * Notes:
1486 * - This function will return a "bad" result value (AST__BAD) if
1487 * any of the input values has this value.
1488 * - A "bad" value will also be returned if this function is
1489 c invoked with the AST error status set, or if it should fail for
1490 f invoked with STATUS set to an error value, or if it should fail for
1491 * any reason.
1492 *--
1493
1494 * Implementation Deficiencies;
1495 * - The protected interface for this function uses 1-based axis
1496 * numbering (like the public interface), rather than the more usual
1497 * zero-based system used by all other protected interfaces. There is
1498 * no real reason for this, and it should be changed at some time.
1499
1500 */
1501
1502 /* Local Variables: */
1503 AstAxis *ax; /* Pointer to Axis object */
1504 double result; /* The returned answer */
1505
1506 /* Initialise. */
1507 result = AST__BAD;
1508
1509 /* Check the global error status. */
1510 if ( !astOK ) return result;
1511
1512 /* Validate the axis index and obtain a pointer to the required Axis. */
1513 (void) astValidateAxis( this, axis - 1, 1, "astAxDistance" );
1514 ax = astGetAxis( this, axis - 1 );
1515
1516 /* Use the AxisDistance method associated with the Axis. */
1517 if( astOK ) result = astAxisDistance( ax, v1, v2 );
1518
1519 /* Annul the Axis pointer. */
1520 ax = astAnnul( ax );
1521
1522 /* Return the result. */
1523 return result;
1524
1525 }
1526
AxIn(AstFrame * this,int axis,double lo,double hi,double val,int closed,int * status)1527 static int AxIn( AstFrame *this, int axis, double lo, double hi, double val,
1528 int closed, int *status ){
1529 /*
1530 *+
1531 * Name:
1532 * astAxIn
1533
1534 * Purpose:
1535 * Test if an axis value lies within a given interval.
1536
1537 * Type:
1538 * Protected virtual function.
1539
1540 * Synopsis:
1541 * #include "frame.h"
1542 * int astAxIn( AstFrame *this, int axis, double lo, double hi, double val,
1543 * int closed )
1544
1545 * Class Membership:
1546 * Frame member function.
1547
1548 * Description:
1549 * This function returns non-zero if a given axis values lies within a
1550 * given axis interval.
1551
1552 * Parameters:
1553 * this
1554 * Pointer to the Frame.
1555 * axis
1556 * The index of the axis. The first axis has index 0.
1557 * lo
1558 * The lower axis limit of the interval.
1559 * hi
1560 * The upper axis limit of the interval.
1561 * val
1562 * The axis value to be tested.
1563 * closed
1564 * If non-zero, then the lo and hi axis values are themselves
1565 * considered to be within the interval. Otherwise they are outside.
1566
1567 * Returned Value:
1568 * Non-zero if the test value is inside the interval.
1569
1570 * Applicability:
1571 * Frame
1572 * Uses simple Euclidean test
1573 * SkyFrame
1574 * All angles which are numerically between "lo" and "hi" are within
1575 * the interval. Angle outside this range are also within the interval
1576 * if they can be brought into the range by addition or subtraction
1577 * of a multiple of 2.PI.
1578 *-
1579 */
1580
1581 /* Local Variables: */
1582 AstAxis *ax; /* Pointer to Axis object */
1583 int result; /* Returned value */
1584
1585 /* For speed, omit the astOK check and axis validation (since this is
1586 protected code, AST should get it right). Obtain a pointer to the
1587 required Axis. */
1588 ax = astGetAxis( this, axis );
1589
1590 /* Use the AxisIn method associated with the Axis. */
1591 result = ax ? astAxisIn( ax, lo, hi, val, closed ) : 0;
1592
1593 /* Annul the Axis pointer. */
1594 ax = astAnnul( ax );
1595
1596 /* Return the result. */
1597 return result;
1598 }
1599
AxOffset(AstFrame * this,int axis,double v1,double dist,int * status)1600 static double AxOffset( AstFrame *this, int axis, double v1, double dist, int *status ) {
1601 /*
1602 *++
1603 * Name:
1604 c astAxOffset
1605 f AST_AXOFFSET
1606
1607 * Purpose:
1608 * Add an increment onto a supplied axis value.
1609
1610 * Type:
1611 * Public virtual function.
1612
1613 * Synopsis:
1614 c #include "frame.h"
1615 c double astAxOffset( AstFrame *this, int axis, double v1, double dist )
1616 f RESULT = AST_AXOFFSET( THIS, AXIS, V1, DIST, STATUS )
1617
1618 * Class Membership:
1619 * Frame method.
1620
1621 * Description:
1622 c This function returns an axis value formed by adding a signed axis
1623 f This routine returns an axis value formed by adding a signed axis
1624 * increment onto a supplied axis value.
1625 *
1626 * For a simple Frame, this is a trivial operation returning the
1627 * sum of the two supplied values. But for other derived classes
1628 * of Frame (such as a SkyFrame) this is not the case.
1629
1630 * Parameters:
1631 c this
1632 f THIS = INTEGER (Given)
1633 * Pointer to the Frame.
1634 c axis
1635 f AXIS = INTEGER (Given)
1636 * The index of the axis to which the supplied values refer. The
1637 * first axis has index 1.
1638 c v1
1639 f V1 = DOUBLE PRECISION (Given)
1640 * The original axis value.
1641 c dist
1642 f DIST = DOUBLE PRECISION (Given)
1643 * The axis increment to add to the original axis value.
1644 f STATUS = INTEGER (Given and Returned)
1645 f The global status.
1646
1647 * Returned Value:
1648 c astAxOffset
1649 f AST_AXOFFSET = DOUBLE PRECISION
1650 * The incremented axis value.
1651
1652 * Notes:
1653 * - This function will return a "bad" result value (AST__BAD) if
1654 * any of the input values has this value.
1655 * - A "bad" value will also be returned if this function is
1656 c invoked with the AST error status set, or if it should fail for
1657 f invoked with STATUS set to an error value, or if it should fail for
1658 * any reason.
1659 *--
1660 */
1661
1662 /* Local Variables: */
1663 AstAxis *ax; /* Pointer to Axis object */
1664 double result; /* The returned answer */
1665
1666 /* Initialise. */
1667 result = AST__BAD;
1668
1669 /* Check the global error status. */
1670 if ( !astOK ) return result;
1671
1672 /* Validate the axis index and obtain a pointer to the required Axis. */
1673 (void) astValidateAxis( this, axis - 1, 1, "astAxOffset" );
1674 ax = astGetAxis( this, axis - 1 );
1675
1676 /* Use the AxisOffset method associated with the Axis. */
1677 if( astOK ) result = astAxisOffset( ax, v1, dist );
1678
1679 /* Annul the Axis pointer. */
1680 ax = astAnnul( ax );
1681
1682 /* Return the result. */
1683 return result;
1684
1685 }
1686
CheckPerm(AstFrame * this,const int * perm,const char * method,int * status)1687 static void CheckPerm( AstFrame *this, const int *perm, const char *method, int *status ) {
1688 /*
1689 *+
1690 * Name:
1691 * astCheckPerm
1692
1693 * Purpose:
1694 * Check that an array contains a valid permutation.
1695
1696 * Type:
1697 * Protected virtual function.
1698
1699 * Synopsis:
1700 * #include "frame.h"
1701 * void astCheckPerm( AstFrame *this, const int *perm, const char *method )
1702
1703 * Class Membership:
1704 * Frame method.
1705
1706 * Description:
1707 * This function checks the validity of a permutation array that
1708 * will be used to permute the order of a Frame's axes. If the
1709 * permutation specified by the array is not valid, an error is
1710 * reported and the global error status is set. Otherwise, the
1711 * function returns without further action.
1712
1713 * Parameters:
1714 * this
1715 * Pointer to the Frame.
1716 * perm
1717 * Pointer to an array of integers with the same number of
1718 * elements as there are axes in the Frame. For each axis, the
1719 * corresponding integer gives the (zero based) axis index to be
1720 * used to identify the information for that axis (using the
1721 * un-permuted axis numbering). To be valid, the integers in
1722 * this array should therefore all lie in the range zero to
1723 * (naxes-1) inclusive, where "naxes" is the number of Frame
1724 * axes, and each value should occur exactly once.
1725 * method
1726 * Pointer to a constant null-terminated character string
1727 * containing the name of the method that invoked this function
1728 * to validate a permutation array. This method name is used
1729 * solely for constructing error messages.
1730
1731 * Notes:
1732 * - Error messages issued by this function refer to the external
1733 * (public) numbering system used for axes (which is one-based),
1734 * whereas zero-based axis indices are used internally.
1735 *-
1736 */
1737
1738 /* Local Variables: */
1739 int *there; /* Pointer to temporary array */
1740 int axis; /* Loop counter for axes */
1741 int naxes; /* Number of Frame axes */
1742 int valid; /* Permutation array is valid? */
1743
1744 /* Check the global error status. */
1745 if ( !astOK ) return;
1746
1747 /* Initialise. */
1748 valid = 1;
1749
1750 /* Obtain the number of Frame axes and allocate a temporary array of integers
1751 with the same number of elements. */
1752 naxes = astGetNaxes( this );
1753 there = astMalloc( sizeof( int ) * (size_t) naxes );
1754 if ( astOK ) {
1755
1756 /* Initialise the temporary array to zero. */
1757 for ( axis = 0; axis < naxes; axis++ ) there[ axis ] = 0;
1758
1759 /* Scan the permutation array, checking that each permuted axis index it
1760 contains is within the correct range. Note an error and quit checking
1761 if an invalid value is found. */
1762 for ( axis = 0; axis < naxes; axis++ ) {
1763 if ( ( perm[ axis ] < 0 ) || ( perm[ axis ] >= naxes ) ) {
1764 valid = 0;
1765 break;
1766
1767 /* Use the temporary array to count how many times each valid axis index
1768 occurs. */
1769 } else {
1770 there[ perm[ axis ] ]++;
1771 }
1772 }
1773
1774 /* If all the axis indices were within range, check to ensure that each value
1775 occurred only once. */
1776 if ( valid ) {
1777 for ( axis = 0; axis < naxes; axis++ ) {
1778
1779 /* Note an error and quit checking if any value did not occur exactly once. */
1780 if ( there[ axis ] != 1 ) {
1781 valid = 0;
1782 break;
1783 }
1784 }
1785 }
1786 }
1787
1788 /* Free the temporary array. */
1789 there = astFree( there );
1790
1791 /* If an invalid permutation was detected and no other error has
1792 occurred, then report an error (note we convert to one-based axis
1793 numbering in the error message). */
1794 if ( !valid && astOK ) {
1795 astError( AST__PRMIN, "%s(%s): Invalid axis permutation array.", status,
1796 method, astGetClass( this ) );
1797 astError( AST__PRMIN, "Each axis index should lie in the range 1 to %d "
1798 "and should occur only once.", status, naxes );
1799 }
1800 }
1801
CleanAttribs(AstObject * this_object,int * status)1802 static void CleanAttribs( AstObject *this_object, int *status ) {
1803 /*
1804 * Name:
1805 * CleanAttribs
1806
1807 * Purpose:
1808 * Clear any invalid set attribute values.
1809
1810 * Type:
1811 * Private function.
1812
1813 * Synopsis:
1814 * #include "frame.h"
1815 * void CleanAttribs( AstObject *this_object, int *status )
1816
1817 * Class Membership:
1818 * Frame member function (over-rides the protected astCleanAttribs
1819 * method inherited from the Object class).
1820
1821 * Description:
1822 * This function clears any attributes that are currently set to
1823 * invalid values in thr supplied object.
1824
1825 * Parameters:
1826 * this
1827 * Pointer to the Object to be cleaned.
1828
1829 */
1830
1831 /* Local Variables; */
1832 AstAxis *ax;
1833 AstFrame *this;
1834 int i;
1835 int nax;
1836 int reporting;
1837
1838 /* Check inherited status */
1839 if( !astOK ) return;
1840
1841 /* Get a pointer to the Frame structure. */
1842 this = (AstFrame *) this_object;
1843
1844 /* Defer error reporting, as required by the astCLEAN_ATTRIB macro. */
1845 reporting = astReporting( 0 );
1846
1847 /* Clean attributes in any Objects contained within "this". */
1848 nax = astGetNaxes( this );
1849 for( i = 0; i < nax; i++ ) {
1850 ax = astGetAxis( this, i );
1851 astCleanAttribs( ax );
1852 ax = astAnnul( ax );
1853 }
1854
1855 /* Clean attributes of this class. */
1856 astCLEAN_ATTRIB(System)
1857 astCLEAN_ATTRIB(AlignSystem)
1858
1859 /* Re-establish error reporting. */
1860 astReporting( reporting );
1861
1862 /* Invoke the method inherited form the parent to clean attributes
1863 defined by the parent class. */
1864 (*parent_cleanattribs)( this_object, status );
1865 }
1866
CleanDomain(char * domain,int * status)1867 static char *CleanDomain( char *domain, int *status ) {
1868 /*
1869 * Name:
1870 * CleanDomain
1871
1872 * Purpose:
1873 * Clean a Domain string and convert to upper case.
1874
1875 * Type:
1876 * Private function.
1877
1878 * Synopsis:
1879 * #include "frame.h"
1880 * char *CleanDomain( char *domain, int *status )
1881
1882 * Class Membership:
1883 * Frame member function.
1884
1885 * Description:
1886 * This function removes all white space from a string and converts
1887 * other characters to upper case. It is intended for cleaning up
1888 * values supplied for the Domain attribute of a Frame.
1889
1890 * Parameters:
1891 * domain
1892 * Pointer to the null terminated Domain string to be modified.
1893 * status
1894 * Pointer to the inherited status variable.
1895
1896 * Returned Value:
1897 * The pointer value "domain" is always returned (even under error
1898 * conditions).
1899 */
1900
1901 /* Local Variables: */
1902 int i; /* Loop counter for characters */
1903 int j; /* Good character count */
1904
1905 /* Check the global error status. */
1906 if ( !astOK ) return domain;
1907
1908 /* Eliminate white space characters and convert the rest to upper
1909 case. */
1910 for ( i = j = 0; domain[ i ]; i++ ) {
1911 if ( !isspace( domain[ i ] ) ) domain[ j++ ] = toupper( domain[ i ] );
1912 }
1913 domain[ j ] = '\0';
1914
1915 /* Return the string pointer. */
1916 return domain;
1917 }
1918
ClearAttrib(AstObject * this_object,const char * attrib,int * status)1919 static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) {
1920 /*
1921 * Name:
1922 * ClearAttrib
1923
1924 * Purpose:
1925 * Clear an attribute value for a Frame.
1926
1927 * Type:
1928 * Private function.
1929
1930 * Synopsis:
1931 * #include "frame.h"
1932 * void ClearAttrib( AstObject *this, const char *attrib, int *status )
1933
1934 * Class Membership:
1935 * Frame member function (over-rides the astClearAttrib protected
1936 * method inherited from the Mapping class).
1937
1938 * Description:
1939 * This function clears the value of a specified attribute for a
1940 * Frame, so that the default value will subsequently be used.
1941
1942 * Parameters:
1943 * this
1944 * Pointer to the Frame.
1945 * attrib
1946 * Pointer to a null terminated string specifying the attribute
1947 * name. This should be in lower case with no surrounding white
1948 * space.
1949 * status
1950 * Pointer to the inherited status variable.
1951
1952 * Notes:
1953 * - This function uses one-based axis numbering so that it is
1954 * suitable for external (public) use.
1955 */
1956
1957 /* Local Variables: */
1958 AstAxis *ax; /* Pointer to Axis */
1959 AstFrame *pfrm; /* Pointer to primary Frame containing axis */
1960 AstFrame *this; /* Pointer to the Frame structure */
1961 char pfrm_attrib[ 100 ]; /* Primary Frame attribute */
1962 char *axis_attrib; /* Pointer to axis attribute name */
1963 const char *old_attrib; /* Pointer to supplied attribute name string */
1964 int axis; /* Frame axis number */
1965 int axis_nc; /* No. characters in axis attribute name */
1966 int free_axis_attrib; /* Should axis_attrib be freed? */
1967 int has_axis; /* Does attrib name include axis specifier? */
1968 int len; /* Length of attrib string */
1969 int nc; /* No. characters read by astSscanf */
1970 int oldrep; /* Original error reporting state */
1971 int paxis; /* Axis index within primary frame */
1972 int used; /* Could the setting string be used? */
1973
1974 /* Check the global error status. */
1975 if ( !astOK ) return;
1976
1977 /* Obtain a pointer to the Frame structure. */
1978 this = (AstFrame *) this_object;
1979
1980 /* Set a flag indicating if the attribute name includes an axis
1981 specifier. */
1982 has_axis = ( strchr( attrib, '(' ) != NULL );
1983
1984 /* A flag indicating that we do not need to free the axis_attrib memory. */
1985 free_axis_attrib = 0;
1986
1987 /* Initialise things to avoid compiler warnings. */
1988 axis_attrib = NULL;
1989 old_attrib = NULL;
1990
1991 /* Jump back to here if we are trying the same attribute but with an explicit
1992 axis "(1)" added to the end of the name. */
1993 L1:
1994
1995 /* Obtain the length of the "attrib" string. */
1996 len = strlen( attrib );
1997
1998 /* Check the attribute name and clear the appropriate attribute. */
1999
2000 /* Digits. */
2001 /* ------- */
2002 if ( !strcmp( attrib, "digits" ) ) {
2003 astClearDigits( this );
2004
2005 /* Digits(axis). */
2006 /* ------------- */
2007 } else if ( nc = 0,
2008 ( 1 == astSscanf( attrib, "digits(%d)%n", &axis, &nc ) )
2009 && ( nc >= len ) ) {
2010
2011 /* There is no function to clear the Digits attribute for an axis
2012 directly, so obtain a pointer to the Axis and use this to clear the
2013 attribute. */
2014 (void) astValidateAxis( this, axis - 1, 1, "astClearDigits(axis)" );
2015 ax = astGetAxis( this, axis - 1 );
2016 astClearAxisDigits( ax );
2017 ax = astAnnul( ax );
2018
2019 /* Direction(axis). */
2020 /* ---------------- */
2021 } else if ( nc = 0,
2022 ( 1 == astSscanf( attrib, "direction(%d)%n", &axis, &nc ) )
2023 && ( nc >= len ) ) {
2024 astClearDirection( this, axis - 1 );
2025
2026 /* Epoch. */
2027 /* ------ */
2028 } else if ( !strcmp( attrib, "epoch" ) ) {
2029 astClearEpoch( this );
2030
2031 /* Top(axis). */
2032 /* ---------- */
2033 } else if ( nc = 0,
2034 ( 1 == astSscanf( attrib, "top(%d)%n", &axis, &nc ) )
2035 && ( nc >= len ) ) {
2036 astClearTop( this, axis - 1 );
2037
2038 /* Bottom(axis). */
2039 /* ------------- */
2040 } else if ( nc = 0,
2041 ( 1 == astSscanf( attrib, "bottom(%d)%n", &axis, &nc ) )
2042 && ( nc >= len ) ) {
2043 astClearBottom( this, axis - 1 );
2044
2045 /* Domain. */
2046 /* ------- */
2047 } else if ( !strcmp( attrib, "domain" ) ) {
2048 astClearDomain( this );
2049
2050 /* Format(axis). */
2051 /* ------------- */
2052 } else if ( nc = 0,
2053 ( 1 == astSscanf( attrib, "format(%d)%n", &axis, &nc ) )
2054 && ( nc >= len ) ) {
2055 astClearFormat( this, axis - 1 );
2056
2057 /* Label(axis). */
2058 /* ------------ */
2059 } else if ( nc = 0,
2060 ( 1 == astSscanf( attrib, "label(%d)%n", &axis, &nc ) )
2061 && ( nc >= len ) ) {
2062 astClearLabel( this, axis - 1 );
2063
2064 /* MatchEnd. */
2065 /* --------- */
2066 } else if ( !strcmp( attrib, "matchend" ) ) {
2067 astClearMatchEnd( this );
2068
2069 /* MaxAxes. */
2070 /* -------- */
2071 } else if ( !strcmp( attrib, "maxaxes" ) ) {
2072 astClearMaxAxes( this );
2073
2074 /* MinAxes. */
2075 /* -------- */
2076 } else if ( !strcmp( attrib, "minaxes" ) ) {
2077 astClearMinAxes( this );
2078
2079 /* Permute. */
2080 /* -------- */
2081 } else if ( !strcmp( attrib, "permute" ) ) {
2082 astClearPermute( this );
2083
2084 /* PreserveAxes. */
2085 /* ------------- */
2086 } else if ( !strcmp( attrib, "preserveaxes" ) ) {
2087 astClearPreserveAxes( this );
2088
2089 /* Symbol(axis). */
2090 /* ------------- */
2091 } else if ( nc = 0,
2092 ( 1 == astSscanf( attrib, "symbol(%d)%n", &axis, &nc ) )
2093 && ( nc >= len ) ) {
2094 astClearSymbol( this, axis - 1 );
2095
2096 /* System. */
2097 /* ------- */
2098 } else if ( !strcmp( attrib, "system" ) ) {
2099 astClearSystem( this );
2100
2101 /* AlignSystem. */
2102 /* ------------ */
2103 } else if ( !strcmp( attrib, "alignsystem" ) ) {
2104 astClearAlignSystem( this );
2105
2106 /* Title. */
2107 /* ------ */
2108 } else if ( !strcmp( attrib, "title" ) ) {
2109 astClearTitle( this );
2110
2111 /* Unit(axis). */
2112 /* ----------- */
2113 } else if ( nc = 0,
2114 ( 1 == astSscanf( attrib, "unit(%d)%n", &axis, &nc ) )
2115 && ( nc >= len ) ) {
2116 astClearUnit( this, axis - 1 );
2117
2118 /* ObsLat. */
2119 /* ------- */
2120 } else if ( !strcmp( attrib, "obslat" ) ) {
2121 astClearObsLat( this );
2122
2123 /* ObsLon. */
2124 /* ------- */
2125 } else if ( !strcmp( attrib, "obslon" ) ) {
2126 astClearObsLon( this );
2127
2128 /* ObsAlt. */
2129 /* ------- */
2130 } else if ( !strcmp( attrib, "obsalt" ) ) {
2131 astClearObsAlt( this );
2132
2133 /* Dut1 */
2134 /* --- */
2135 } else if ( !strcmp( attrib, "dut1" ) ) {
2136 astClearDut1( this );
2137
2138 /* Read-only attributes. */
2139 /* --------------------- */
2140 /* Test if the attribute name matches any of the read-only attributes
2141 of this class. If it does, then report an error. */
2142 } else if ( !strcmp( attrib, "naxes" ) ||
2143 !strncmp( attrib, "normunit", 8 ) ) {
2144 astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" "
2145 "value for a %s.", status, attrib, astGetClass( this ) );
2146 astError( AST__NOWRT, "This is a read-only attribute." , status);
2147
2148 /* Other axis attributes. */
2149 /* ---------------------- */
2150 /* If the attribute was not identified above, but appears to refer to
2151 a Frame axis, then it may refer to an Axis object of a derived type
2152 (which has additional attributes not recognised here). */
2153 } else if( !free_axis_attrib && ( nc = 0,
2154 ( 1 == astSscanf( attrib, "%*[^()]%n(%d)%n",
2155 &axis_nc, &axis, &nc ) )
2156 && ( nc >= len ) ) ) {
2157
2158 /* Validate the axis index and extract the attribute name. */
2159 (void) astValidateAxis( this, axis - 1, 1, "astClear" );
2160 axis_attrib = astString( attrib, axis_nc );
2161
2162 /* Obtain a pointer to the Axis object. */
2163 ax = astGetAxis( this, axis - 1 );
2164 if( astOK ) {
2165
2166 /* Assume that we will be able to use the attribute name. */
2167 used = 1;
2168
2169 /* Temporarily switch off error reporting so that if the following attempt
2170 to access the axis attribute fails, we can try to interpret the
2171 attribute name as an attribute of the primary Frame containing the
2172 specified axis. Any errors reported in this context will simply be
2173 ignored, in particularly they are not deferred for later delivery. */
2174 oldrep = astReporting( 0 );
2175
2176 /* Use the Axis astClearAttrib method to clear the attribute value. */
2177 astClearAttrib( ax, axis_attrib );
2178
2179 /* If the above call failed with a status of AST__BADAT, indicating that
2180 the attribute name was not recognised, clear the status so that we can
2181 try to interpret the attribute name as an attribute of the primary Frame
2182 containing the specified axis. */
2183 if( astStatus == AST__BADAT ) {
2184 astClearStatus;
2185
2186 /* Find the primary Frame containing the specified axis. */
2187 astPrimaryFrame( this, axis - 1, &pfrm, &paxis );
2188
2189 /* Only attempt to use the primary Frame if it is not the same as "this"
2190 - otherwise we could end up in an infinite loop. */
2191 if( pfrm != this ) {
2192
2193 /* astPrimaryFrame returns the original - unpermuted - axis index within
2194 the primary Frame. So we need to take into account any axis permutation
2195 which has been applied to the primary Frame when forming the attribute name
2196 to use below. Find the permuted (external) axis index which corresponds to
2197 the internal (unpermuted) axis index "paxis". */
2198 paxis = astValidateAxis( pfrm, paxis, 0, "astClear" );
2199
2200 /* Modify the attribute name to refer to the axis numbering of the
2201 primary frame. */
2202 sprintf( pfrm_attrib, "%s(%d)", axis_attrib, paxis + 1 );
2203
2204 /* Attempt to clear the attribute as an attribute of the primary Frame. */
2205 astClearAttrib( pfrm, pfrm_attrib );
2206
2207 /* If this failed, clear the status and indicate that we have not managed to
2208 use the attribute name. */
2209 if( !astOK ) {
2210 astClearStatus;
2211 used = 0;
2212 }
2213
2214 } else {
2215 used = 0;
2216 }
2217
2218 /* If not found attempt to clear the attribute value in the Axis, omitting
2219 the axis index. */
2220 if( ! used ) {
2221 astClearAttrib( pfrm, axis_attrib );
2222 if( !astOK ) {
2223 astClearStatus;
2224 } else {
2225 used = 1;
2226 }
2227 }
2228
2229 /* Annul the primary Frame pointer. */
2230 pfrm = astAnnul( pfrm );
2231 }
2232
2233 /* Re-instate the original error reporting state. */
2234 astReporting( oldrep );
2235
2236 /* If we could not use the attribute name, attempt to clear the axis
2237 attribute again, this time retaining the error report. This is done
2238 to ensure the user gets an appropriate error message. */
2239 if( !used ) astClearAttrib( ax, axis_attrib );
2240 }
2241
2242 /* Annul the Axis pointer and free the memory holding the attribute
2243 name. */
2244 ax = astAnnul( ax );
2245 axis_attrib = astFree( axis_attrib );
2246
2247 /* Not recognised. */
2248 /* --------------- */
2249 /* If the attribute is still not recognised, and the Frame has only 1 axis,
2250 and the attribute name does not already include an axis specifier, try
2251 again after appending "(1)" to the end of the attribute name. */
2252 } else if( !has_axis && astGetNaxes( this ) == 1 ) {
2253
2254 /* Take a copy of the supplied name, allowing 3 extra characters for the
2255 axis specifier "(1)". */
2256 axis_attrib = astMalloc( len + 4 );
2257 if( axis_attrib ) memcpy( axis_attrib, attrib, len );
2258
2259 /* Indicate we should free the axis_attrib memory. */
2260 free_axis_attrib = 1;
2261
2262 /* Add in the axis specifier. */
2263 strcpy( axis_attrib + len, "(1)" );
2264
2265 /* Use the new attribute name instead of the supplied name. */
2266 old_attrib = attrib;
2267 attrib = axis_attrib;
2268
2269 /* Indicate the attribute name now has an axis specifier. */
2270 has_axis = 1;
2271
2272 /* Jump back to try interpreting the new attribute name. */
2273 goto L1;
2274
2275 /* Not recognised. */
2276 /* --------------- */
2277 /* If the attribute name is still not recognised, pass it on to the parent
2278 method for further interpretation. First re-instate the original attrib
2279 name string if it was changed above. */
2280 } else {
2281 if( free_axis_attrib ) {
2282 attrib = old_attrib;
2283 axis_attrib = astFree( axis_attrib );
2284 }
2285 (*parent_clearattrib)( this_object, attrib, status );
2286 }
2287 }
2288
ClearUnit(AstFrame * this,int axis,int * status)2289 static void ClearUnit( AstFrame *this, int axis, int *status ) {
2290 /*
2291 * Name:
2292 * ClearUnit
2293
2294 * Purpose:
2295 * Clear the Unit attribute of a Frame.
2296
2297 * Type:
2298 * Protected virtual function.
2299
2300 * Synopsis:
2301 * #include "frame.h"
2302 * void ClearUnit( AstFrame *this, int axis, int *status )
2303
2304 * Class Membership:
2305 * Frame method.
2306
2307 * Description:
2308 * This function clears the Unit value for an axis of a Frame.
2309
2310 * Parameters:
2311 * this
2312 * Pointer to the Frame.
2313 * axis
2314 * The number of the axis (zero-based) for which the Unit value is to
2315 * be cleared.
2316 * unit
2317 * The new value to be set.
2318 * status
2319 * Pointer to the inherited status variable.
2320
2321 * Returned Value:
2322 * void.
2323 */
2324
2325 /* Local Variables: */
2326 AstAxis *ax; /* Pointer to Axis object */
2327 const char *units; /* Pointer to units string */
2328 char *old_units; /* Pointer to copy of original units */
2329
2330 /* Check the global error status. */
2331 if ( !astOK ) return;
2332
2333 /* Validate the axis index. */
2334 (void) astValidateAxis( this, axis, 1, "astSetUnit" );
2335
2336 /* Do nothing more if the attribute is already cleared. */
2337 if( astTestUnit( this, axis ) ) {
2338
2339 /* Obtain a pointer to the required Axis. */
2340 ax = astGetAxis( this, axis );
2341
2342 /* Save a copy of the old units. */
2343 units = astGetAxisUnit( ax );
2344 old_units = astStore( NULL, units, strlen( units ) + 1 );
2345
2346 /* Clear the Axis Unit attribute value, and then get a pointer to the
2347 new default Units string. */
2348 astClearAxisUnit( ax );
2349 units = astGetUnit( this, axis );
2350
2351 /* The new unit may require the Label and/or Symbol to be changed, but
2352 only if the Frames ActiveUnit flag is set. */
2353 if( astGetActiveUnit( this ) ) NewUnit( ax, old_units, units,
2354 "astSetUnit", astGetClass( this ), status );
2355
2356 /* Free resources. */
2357 old_units = astFree( old_units );
2358
2359 /* Annul the Axis pointer. */
2360 ax = astAnnul( ax );
2361 }
2362 }
2363
ConsistentMaxAxes(AstFrame * this,int value,int * status)2364 static int ConsistentMaxAxes( AstFrame *this, int value, int *status ) {
2365 /*
2366 * Name:
2367 * ConsistentMaxAxes
2368
2369 * Purpose:
2370 * Ensure a consistent value when setting the MaxAxes attribute.
2371
2372 * Type:
2373 * Private function.
2374
2375 * Synopsis:
2376 * #include "frame.h"
2377 * int ConsistentMaxAxes( AstFrame *this, int value, int *status )
2378
2379 * Class Membership:
2380 * Frame member function.
2381
2382 * Description:
2383 * This function accepts a value which is to be set for a Frame's MaxAxes
2384 * attribute and returns an appropriately adjusted value to be assigned
2385 * to the Frame structure's max_axes component. If necessary, the Frame's
2386 * MinAxes attribute is adjusted to remain consistent with the new MaxAxes
2387 * value (but note that the MaxAxes value itself is not assigned by this
2388 * function).
2389
2390 * Parameters:
2391 * this
2392 * Pointer to the Frame.
2393 * value
2394 * The new value being set for the MaxAxes attribute.
2395 * status
2396 * Pointer to the inherited status variable.
2397
2398 * Returned Value:
2399 * The value to be assigned to the max_axes component.
2400
2401 * Notes:
2402 * - A value of -INT_MAX will be returned if this function is
2403 * invoked with the global error status set, or if it should fail
2404 * for any reason.
2405 */
2406
2407 /* Local Variables: */
2408 int result; /* Result to be returned */
2409
2410 /* Check the global error status. */
2411 if ( !astOK ) return -INT_MAX;
2412
2413 /* Ensure that the result value isn't negative. */
2414 result = ( value >= 0 ) ? value : 0;
2415
2416 /* Check if the MinAxes attribute is set. If not, its default value will be
2417 consistent with the MaxAxes value (the DefaultMinAxes function ensures
2418 this). Otherwise, obtain its value to check for consistency. */
2419 if ( astTestMinAxes( this ) ) {
2420
2421 /* If necessary, set a new MinAxes value to prevent it exceeding the MaxAxes
2422 value about to be returned. */
2423 if ( astGetMinAxes( this ) > result ) astSetMinAxes( this, result );
2424 }
2425
2426 /* If an error occurred, clear the result value. */
2427 if ( !astOK ) result = -INT_MAX;
2428
2429 /* Return the result. */
2430 return result;
2431 }
2432
ConsistentMinAxes(AstFrame * this,int value,int * status)2433 static int ConsistentMinAxes( AstFrame *this, int value, int *status ) {
2434 /*
2435 * Name:
2436 * ConsistentMinAxes
2437
2438 * Purpose:
2439 * Ensure a consistent value when setting the MinAxes attribute.
2440
2441 * Type:
2442 * Private function.
2443
2444 * Synopsis:
2445 * #include "frame.h"
2446 * int ConsistentMinAxes( AstFrame *this, int value, int *status )
2447
2448 * Class Membership:
2449 * Frame member function.
2450
2451 * Description:
2452 * This function accepts a value which is to be set for a Frame's MinAxes
2453 * attribute and returns an appropriately adjusted value to be assigned
2454 * to the Frame structure's min_axes component. If necessary, the Frame's
2455 * MaxAxes attribute is adjusted to remain consistent with the new MinAxes
2456 * value (but note that the MinAxes value itself is not assigned by this
2457 * function).
2458
2459 * Parameters:
2460 * this
2461 * Pointer to the Frame.
2462 * value
2463 * The new value being set for the MinAxes attribute.
2464 * status
2465 * Pointer to the inherited status variable.
2466
2467 * Returned Value:
2468 * The value to be assigned to the min_axes component.
2469
2470 * Notes:
2471 * - A value of -INT_MAX will be returned if this function is
2472 * invoked with the global error status set, or if it should fail
2473 * for any reason.
2474 */
2475
2476 /* Local Variables: */
2477 int result; /* Result to be returned */
2478
2479 /* Check the global error status. */
2480 if ( !astOK ) return -INT_MAX;
2481
2482 /* Ensure that the result value isn't negative. */
2483 result = ( value >= 0 ) ? value : 0;
2484
2485 /* Check if the MaxAxes attribute is set. If not, its default value will be
2486 consistent with the MinAxes value (the DefaultMaxAxes function ensures
2487 this). Otherwise, obtain its value to check for consistency. */
2488 if ( astTestMaxAxes( this ) ) {
2489
2490 /* If necessary, set a new MaxAxes value to prevent it being less than the
2491 MinAxes value about to be returned. */
2492 if ( astGetMaxAxes( this ) < result ) astSetMaxAxes( this, result );
2493 }
2494
2495 /* If an error occurred, clear the result value. */
2496 if ( !astOK ) result = -INT_MAX;
2497
2498 /* Return the result. */
2499 return result;
2500 }
2501
Convert(AstFrame * from,AstFrame * to,const char * domainlist,int * status)2502 static AstFrameSet *Convert( AstFrame *from, AstFrame *to,
2503 const char *domainlist, int *status ) {
2504 /*
2505 *++
2506 * Name:
2507 c astConvert
2508 f AST_CONVERT
2509
2510 * Purpose:
2511 * Determine how to convert between two coordinate systems.
2512
2513 * Type:
2514 * Public virtual function.
2515
2516 * Synopsis:
2517 c #include "frame.h"
2518 c AstFrameSet *astConvert( AstFrame *from, AstFrame *to,
2519 c const char *domainlist )
2520 f RESULT = AST_CONVERT( FROM, TO, DOMAINLIST, STATUS )
2521
2522 * Class Membership:
2523 * Frame method.
2524
2525 * Description:
2526 * This function compares two Frames and determines whether it is
2527 * possible to convert between the coordinate systems which they
2528 * represent. If conversion is possible, it returns a FrameSet
2529 * which describes the conversion and which may be used (as a
2530 * Mapping) to transform coordinate values in either direction.
2531 *
2532 * The same function may also be used to determine how to convert
2533 * between two FrameSets (or between a Frame and a FrameSet, or
2534 * vice versa). This mode is intended for use when (for example)
2535 * two images have been calibrated by attaching a FrameSet to each.
2536 c astConvert might then be used to search for a
2537 f AST_CONVERT might then be used to search for a
2538 * celestial coordinate system that both images have in common, and
2539 * the result could then be used to convert between the pixel
2540 * coordinates of both images -- having effectively used their
2541 * celestial coordinate systems to align them.
2542 *
2543 * When using FrameSets, there may be more than one possible
2544 * intermediate coordinate system in which to perform the
2545 * conversion (for instance, two FrameSets might both have
2546 * celestial coordinates, detector coordinates, pixel coordinates,
2547 * etc.). A comma-separated list of coordinate system domains may
2548 * therefore be given which defines a priority order to use when
2549 * selecting the intermediate coordinate system. The path used for
2550 * conversion must go via an intermediate coordinate system whose
2551 * Domain attribute matches one of the domains given. If conversion
2552 * cannot be achieved using the first domain, the next one is
2553 * considered, and so on, until success is achieved.
2554
2555 * Parameters:
2556 c from
2557 f FROM = INTEGER (Given)
2558 * Pointer to a Frame which represents the "source" coordinate
2559 * system. This is the coordinate system in which you already
2560 * have coordinates available.
2561 *
2562 * If a FrameSet is given, its current Frame (as determined by
2563 * its Current attribute) is taken to describe the source
2564 * coordinate system. Note that the Base attribute of this
2565 * FrameSet may be modified by this function to indicate which
2566 * intermediate coordinate system was used (see under
2567 * "FrameSets" in the "Applicability" section for details).
2568 c to
2569 f TO = INTEGER (Given)
2570 * Pointer to a Frame which represents the "destination"
2571 * coordinate system. This is the coordinate system into which
2572 * you wish to convert your coordinates.
2573 *
2574 * If a FrameSet is given, its current Frame (as determined by
2575 * its Current attribute) is taken to describe the destination
2576 * coordinate system. Note that the Base attribute of this
2577 * FrameSet may be modified by this function to indicate which
2578 * intermediate coordinate system was used (see under
2579 * "FrameSets" in the "Applicability" section for details).
2580 c domainlist
2581 f DOMAINLIST = CHARACTER * ( * ) (Given)
2582 c Pointer to a null-terminated character string containing a
2583 f A character string containing a
2584 * comma-separated list of Frame domains. This may be used to
2585 * define a priority order for the different intermediate
2586 * coordinate systems that might be used to perform the
2587 * conversion.
2588 *
2589 * The function will first try to obtain a conversion by making
2590 * use only of an intermediate coordinate system whose Domain
2591 * attribute matches the first domain in this list. If this
2592 * fails, the second domain in the list will be used, and so on,
2593 * until conversion is achieved. A blank domain (e.g. two
2594 * consecutive commas) indicates that all coordinate systems
2595 * should be considered, regardless of their domains.
2596 *
2597 * This list is case-insensitive and all white space is ignored.
2598 * If you do not wish to restrict the domain in this way,
2599 c you should supply an empty string. This is normally
2600 f you should supply a blank string. This is normally
2601 * appropriate if either of the source or destination coordinate
2602 * systems are described by Frames (rather than FrameSets),
2603 * since there is then usually only one possible choice of
2604 * intermediate coordinate system.
2605 f STATUS = INTEGER (Given and Returned)
2606 f The global status.
2607
2608 * Returned Value:
2609 c astConvert()
2610 f AST_CONVERT = INTEGER
2611 * If the requested coordinate conversion is possible, the
2612 * function returns a pointer to a FrameSet which describes the
2613 * conversion. Otherwise, a null Object pointer (AST__NULL) is
2614 * returned without error.
2615 *
2616 * If a FrameSet is returned, it will contain two Frames. Frame
2617 * number 1 (its base Frame) will describe the source coordinate
2618 c system, corresponding to the "from" parameter. Frame number 2
2619 f system, corresponding to the FROM argument. Frame number 2
2620 * (its current Frame) will describe the destination coordinate
2621 c system, corresponding to the "to" parameter. The Mapping
2622 f system, corresponding to the TO argument. The Mapping
2623 * which inter-relates these two Frames will perform the
2624 * required conversion between their respective coordinate
2625 * systems.
2626 *
2627 * Note that a FrameSet may be used both as a Mapping and as a
2628 * Frame. If the result is used as a Mapping (e.g. with
2629 c astTran2), then it provides a means of converting coordinates
2630 f AST_TRAN2), then it provides a means of converting coordinates
2631 * from the source to the destination coordinate system (or
2632 * vice versa if its inverse transformation is selected). If it
2633 * is used as a Frame, its attributes will describe the
2634 * destination coordinate system.
2635
2636 * Applicability:
2637 * DSBSpecFrame
2638 * If the AlignSideBand attribute is non-zero, alignment occurs in the
2639 * upper sideband expressed within the spectral system and standard of
2640 * rest given by attributes AlignSystem and AlignStdOfRest. If
2641 * AlignSideBand is zero, the two DSBSpecFrames are aligned as if
2642 * they were simple SpecFrames (i.e. the SideBand is ignored).
2643 * Frame
2644 * This function applies to all Frames. Alignment occurs within the
2645 * coordinate system given by attribute AlignSystem.
2646 * FrameSet
2647 c If either of the "from" or "to" parameters is a pointer to a
2648 f If either of the FROM or TO arguments is a pointer to a
2649 c FrameSet, then astConvert will attempt to convert from the
2650 f FrameSet, then AST_CONVERT will attempt to convert from the
2651 c coordinate system described by the current Frame of the "from"
2652 f coordinate system described by the current Frame of the FROM
2653 c FrameSet to that described by the current Frame of the "to"
2654 f FrameSet to that described by the current Frame of the TO
2655 * FrameSet.
2656 *
2657 * To achieve this, it will consider all of the Frames within
2658 * each FrameSet as a possible way of reaching an intermediate
2659 * coordinate system that can be used for the conversion. There
2660 * is then the possibility that more than one conversion path
2661 * may exist and, unless the choice is sufficiently restricted
2662 c by the "domainlist" string, the sequence in which the Frames
2663 f by the DOMAINLIST string, the sequence in which the Frames
2664 * are considered can be important. In this case, the search
2665 * for a conversion path proceeds as follows:
2666 c - Each field in the "domainlist" string is considered in turn.
2667 f - Each field in the DOMAINLIST string is considered in turn.
2668 * - The Frames within each FrameSet are considered in a
2669 * specific order: (1) the base Frame is always considered
2670 * first, (2) after this come all the other Frames in
2671 * Frame-index order (but omitting the base and current Frames),
2672 * (3) the current Frame is always considered last. However, if
2673 * either FrameSet's Invert attribute is set to a non-zero value
2674 * (so that the FrameSet is inverted), then its Frames are
2675 * considered in reverse order. (Note that this still means that
2676 * the base Frame is considered first and the current Frame
2677 * last, because the Invert value will also cause these Frames
2678 * to swap places.)
2679 * - All source Frames are first considered (in the appropriate
2680 * order) for conversion to the first destination Frame. If no
2681 * suitable intermediate coordinate system emerges, they are
2682 * then considered again for conversion to the second
2683 * destination Frame (in the appropriate order), and so on.
2684 * - Generally, the first suitable intermediate coordinate
2685 * system found is used. However, the overall Mapping between
2686 * the source and destination coordinate systems is also
2687 * examined. Preference is given to cases where both the
2688 * forward and inverse transformations are defined (as indicated
2689 * by the TranForward and TranInverse attributes). If only one
2690 * transformation is defined, the forward one is preferred.
2691 * - If the domain of the intermediate coordinate system matches
2692 c the current "domainlist" field, the conversion path is
2693 f the current DOMAINLIST field, the conversion path is
2694 c accepted. Otherwise, the next "domainlist" field is considered
2695 f accepted. Otherwise, the next DOMAINLIST field is considered
2696 * and the process repeated.
2697 *
2698 * If conversion is possible, the Base attributes of the two
2699 * FrameSets will be modified on exit to identify the Frames
2700 * used to access the intermediate coordinate system which was
2701 * finally accepted.
2702 *
2703 * Note that it is possible to force a particular Frame within a
2704 * FrameSet to be used as the basis for the intermediate
2705 * coordinate system, if it is suitable, by (a) focussing
2706 * attention on
2707 c it by specifying its domain in the "domainlist" string, or (b)
2708 f it by specifying its domain in the DOMAINLIST string, or (b)
2709 * making it the base Frame, since this is always considered
2710 * first.
2711 * SpecFrame
2712 * Alignment occurs within the spectral system and standard of rest
2713 * given by attributes AlignSystem and AlignStdOfRest.
2714 * TimeFrame
2715 * Alignment occurs within the time system and time scale given by
2716 * attributes AlignSystem and AlignTimeScale.
2717
2718 * Examples:
2719 c cvt = astConvert( a, b, "" );
2720 f CVT = AST_CONVERT( A, B, ' ', STATUS )
2721 * Attempts to convert between the coordinate systems represented
2722 c by "a" and "b" (assumed to be Frames). If successful, a FrameSet
2723 f by A and B (assumed to be Frames). If successful, a FrameSet
2724 c is returned via the "cvt" pointer which may be used to apply the
2725 f is returned via the CVT pointer which may be used to apply the
2726 c conversion to sets of coordinates (e.g. using astTran2).
2727 f conversion to sets of coordinates (e.g. using AST_TRAN2).
2728 c cvt = astConvert( astSkyFrame(""), astSkyFrame("Equinox=2005"), "" );
2729 f CVT = AST_CONVERT( AST_SKYFRAME( ' ', STATUS ), AST_SKYFRAME( 'Equinox=2005', STATUS ), ' ', STATUS )
2730 * Creates a FrameSet which describes precession in the default
2731 * FK5 celestial coordinate system between equinoxes J2000 (also
2732 c the default) and J2005. The returned "cvt" pointer may then
2733 f the default) and J2005. The returned CVT pointer may then
2734 c be passed to astTran2 to apply this precession correction to
2735 f be passed to AST_TRAN2 to apply this precession correction to
2736 * any number of coordinate values given in radians.
2737 *
2738 * Note that the returned FrameSet also contains information
2739 * about how to format coordinate values. This means that
2740 * setting its Report attribute to 1 is a simple way to obtain
2741 * printed output (formatted in sexagesimal notation) to show
2742 * the coordinate values before and after conversion.
2743 c cvt = astConvert( a, b, "sky,detector," );
2744 f CVT = AST_CONVERT( A, B, 'SKY,DETECTOR,', STATUS )
2745 * Attempts to convert between the coordinate systems
2746 c represented by the current Frames of "a" and "b"
2747 f represented by the current Frames of A and B
2748 * (now assumed to be FrameSets), via the intermediate "SKY"
2749 * coordinate system. This, by default, is the Domain
2750 * associated with a celestial coordinate system represented by
2751 * a SkyFrame.
2752 *
2753 * If this fails (for example, because either FrameSet lacks
2754 * celestial coordinate information), then the user-defined
2755 * "DETECTOR" coordinate system is used instead. If this also
2756 * fails, then all other possible ways of achieving conversion
2757 * are considered before giving up.
2758 *
2759 c The returned pointer "cvt" indicates whether conversion was
2760 f The returned pointer CVT indicates whether conversion was
2761 * possible and will have the value AST__NULL if it was not. If
2762 c conversion was possible, "cvt" will point at a new FrameSet
2763 f conversion was possible, CVT will point at a new FrameSet
2764 * describing the conversion.
2765 *
2766 * The Base attributes of the two FrameSets
2767 c will be set by astConvert to indicate which of their Frames was
2768 f will be set by AST_CONVERT to indicate which of their Frames was
2769 * used for the intermediate coordinate system. This means that
2770 * you can subsequently determine which coordinate system was
2771 * used by enquiring the Domain attribute of either base Frame.
2772
2773 * Notes:
2774 * - The Mapping represented by the returned FrameSet results in
2775 * alignment taking place in the coordinate system specified by the
2776 c AlignSystem attribute of the "to" Frame. See the description of the
2777 f AlignSystem attribute of the TO Frame. See the description of the
2778 * AlignSystem attribute for further details.
2779 * - When aligning (say) two images, which have been calibrated by
2780 * attaching FrameSets to them, it is usually necessary to convert
2781 * between the base Frames (representing "native" pixel
2782 * coordinates) of both FrameSets. This may be achieved by
2783 * inverting the FrameSets (e.g. using astInvert) so as to
2784 * interchange their base and current Frames before using
2785 * astConvert.
2786 * - A null Object pointer (AST__NULL) will be returned if this
2787 c function is invoked with the AST error status set, or if it
2788 f function is invoked with STATUS set to an error value, or if it
2789 * should fail for any reason.
2790 *--
2791
2792 * Implementation Notes:
2793 * This function is simply a wrap-up for the protected astConvertX
2794 * method which performs the required processing but swaps the order
2795 * of the first two arguments. This is a trick to allow the
2796 * astConvert method to be over-ridden by derived classes on the
2797 * basis of the class of either of the first two arguments.
2798 */
2799
2800 /* Check the global error status. */
2801 if ( !astOK ) return NULL;
2802
2803 /* Invoke the "astConvertX" method with the first two arguments
2804 swapped. */
2805 return astConvertX( to, from, domainlist );
2806 }
2807
ConvertX(AstFrame * to,AstFrame * from,const char * domainlist,int * status)2808 static AstFrameSet *ConvertX( AstFrame *to, AstFrame *from,
2809 const char *domainlist, int *status ) {
2810 /*
2811 *+
2812 * Name:
2813 * astConvertX
2814
2815 * Purpose:
2816 * Determine how to convert between two coordinate systems.
2817
2818 * Type:
2819 * Protected virtual function.
2820
2821 * Synopsis:
2822 * #include "frame.h"
2823 * AstFrameSet *astConvertX( AstFrame *to, AstFrame *from,
2824 * const char *domainlist )
2825
2826 * Class Membership:
2827 * Frame method.
2828
2829 * Description:
2830 * This function performs the processing for the public astConvert
2831 * method and has exactly the same interface except that the order
2832 * of the first two arguments is swapped. This is a trick to allow
2833 * the astConvert method to be over-ridden by derived classes on
2834 * the basis of the class of either of its first two arguments.
2835 *
2836 * See the astConvert method for details of the interface.
2837 *-
2838
2839 * Implementation Deficiencies:
2840 * - This function's job is basically to negotiate with two Frames
2841 * to try and find a mutually agreeable coordinate system for
2842 * conversion. Ideally, it should be able to juggle the number of
2843 * axes, etc. to do this. At present, however, the implementation
2844 * is much simpler. This is adequate for the Frame classes which
2845 * exist at the time of writing, but the implementation may need
2846 * beefing up in future.
2847 * - One likely problem is with attributes which default in both
2848 * the source and destination Frames. This means they also default
2849 * in the common coordinate system. If these default values were to
2850 * differ when matching different target Frames, however, we would
2851 * be in trouble, because the common coordinate system would not
2852 * then be remaining constant. The longer-term solution to this is
2853 * probably to provide some mechanism to "fix" all attribute values
2854 * for a Frame, by taking any attributes that are un-set and
2855 * explicitly setting a firm value (equal to the default) so they
2856 * cannot then change.
2857 */
2858
2859 /* Local Variables: */
2860 AstFrameSet *result; /* Pointer to Mapping to be returned */
2861 AstFrame *ftmp; /* Pointer to returned Frame */
2862 AstMapping **map1_address; /* Location of first Mapping pointer */
2863 AstMapping **map2_address; /* Location of second Mapping pointer */
2864 AstMapping *common0; /* Initial common coordinate system */
2865 AstMapping *common1; /* Improved common coordinate system */
2866 AstMapping *common2; /* Final common coordinate system */
2867 AstMapping *frame1; /* Pointer to Frame for first match */
2868 AstMapping *frame2; /* Pointer to Frame for second match */
2869 AstMapping *from_map; /* Pointer to "from" Mapping */
2870 AstMapping *map; /* Pointer to conversion Mapping */
2871 AstMapping *result_map; /* Pointer to result Mapping */
2872 AstMapping *tmp; /* Temporary Mapping pointer */
2873 AstMapping *to_map; /* Pointer to "to" Mapping */
2874 char *domain; /* Pointer to result domain */
2875 char *domain_end; /* Pointer to null at end of domain */
2876 char *domainlist_copy; /* Pointer to copy of domainlist */
2877 int *axes1; /* Pointer to axis assignments */
2878 int *axes2; /* Pointer to axis assignments */
2879 int best_score; /* Score assigned to best match */
2880 int icom; /* Common coordinate system loop counter */
2881 int match1; /* First match succeeded? */
2882 int match2; /* Second match succeeded? */
2883 int match; /* Overall match found? */
2884 int perfect; /* Perfect match found? */
2885 int score; /* Score assigned to match */
2886
2887 /* Initialise. */
2888 result = NULL;
2889
2890 /* Check the global error status. */
2891 if ( !astOK ) return result;
2892
2893 /* Further initialisation. */
2894 result_map = NULL;
2895
2896 /* Make a temporary copy of the domains list. */
2897 domainlist_copy = astStore( NULL, domainlist,
2898 strlen( domainlist ) + (size_t) 1 );
2899 if ( astOK ) {
2900
2901 /* Loop to inspect each comma-separated field in the domains list
2902 until an error occurs, all the domains are used up, or a match is
2903 found. */
2904 domain = domainlist_copy;
2905 match = 0;
2906 while ( astOK && domain && !match ) {
2907
2908 /* Change the comma at the end of each field to a null to terminate
2909 the domain. Then convert the domain to upper case and eliminate
2910 white space. */
2911 if ( ( domain_end = strchr( domain, ',' ) ) ) *domain_end = '\0';
2912 CleanDomain( domain, status );
2913
2914 /* For any given domain, we will ignore imperfect matches in favour of
2915 better ones by assigning a score to each match. Initialise the best
2916 score value for the current domain. */
2917 best_score = -1;
2918
2919 /* Loop to consider both the "to" and "from" Frames in turn as the
2920 basis of a possible common coordinate system. Quit looping early if
2921 an error occurs or a perfect match is found. */
2922 perfect = 0;
2923 for ( icom = 0; astOK && !perfect && ( icom <= 1 ); icom++ ) {
2924
2925 /* Make a copy of the Frame representing the initial guess at a common
2926 coordinate system. We will use this to probe the other
2927 Frame. Ensure that axes are not preserved (so that we convert to
2928 the common axis number/order). */
2929 common0 = astCopy( icom ? from : to );
2930 astSetPreserveAxes( common0, 0 );
2931
2932 /* Also, if the current domain is not blank, set the Domain attribute (so
2933 we will only find coordinate systems which match the current
2934 "domainlist" field). */
2935 if ( *domain ) astSetDomain( common0, domain );
2936
2937 /* Obtain a pointer to the other Frame. */
2938 frame1 = astClone( icom ? to : from );
2939
2940 /* Set the address at which to store the resulting Mapping pointer. */
2941 map1_address = icom ? &to_map : &from_map;
2942
2943 /* See if conversion from "frame1" to the common coordinate system is
2944 possible. If successful, this results in a new approximation
2945 ("common1") to the possible common coordinate system. */
2946 match1 = astMatch( common0, frame1, 1, &axes1, &axes2,
2947 map1_address, &ftmp );
2948 common1 = (AstMapping *) ftmp;
2949
2950 /* If successful, free memory allocated for the axis association
2951 arrays, which are not needed. */
2952 if ( astOK && match1 ) {
2953 axes1 = astFree( axes1 );
2954 axes2 = astFree( axes2 );
2955
2956 /* Using the improved approximation to the common coordinate system,
2957 now test if conversion from the alternative Frame "frame2" is
2958 possible. */
2959 frame2 = astClone( icom ? from : to );
2960 map2_address = icom ? &from_map : &to_map;
2961 astSetPreserveAxes( common1, 0 );
2962 match2 = astMatch( common1, frame2, 1, &axes1, &axes2,
2963 map2_address, &ftmp );
2964 common2 = (AstMapping *) ftmp;
2965
2966 /* If successful, free memory allocated for the axis association
2967 arrays, which are not needed. */
2968 if ( astOK && match2 ) {
2969 axes1 = astFree( axes1 );
2970 axes2 = astFree( axes2 );
2971
2972 /* Invert the "to" Mapping and concatenate the two Mappings to
2973 describe the conversion between the "from" and "to" Frames. Then
2974 simplify the result. */
2975 astInvert( to_map );
2976 tmp = (AstMapping *) astCmpMap( from_map, to_map, 1, "", status );
2977 map = astSimplify( tmp );
2978 tmp = astAnnul( tmp );
2979
2980 /* Assign a score that favours Mappings with both transformations
2981 available over those with only one, and Mappings with only a
2982 forward transformation over those with only an inverse
2983 transformation. */
2984 score = ( astGetTranForward( map ) ? 2 : 0 ) +
2985 ( astGetTranInverse( map ) ? 1 : 0 );
2986
2987 /* If the new score is better than the previous one (or is the first
2988 one), note that we have a possible match. */
2989 if ( astOK && ( score > best_score ) ) {
2990 match = 1;
2991
2992 /* Update the best score and note if it indicates a perfect match (in
2993 which case we can stop searching at this point). */
2994 best_score = score;
2995 perfect = ( best_score >= 3 );
2996
2997 /* Annul any previous result Mapping pointer and replace it with this
2998 better one. */
2999 if ( result_map ) result_map = astAnnul( result_map );
3000 result_map = astClone( map );
3001 }
3002
3003 /* Annul pointers to all the intermediate Objects. */
3004 map = astAnnul( map );
3005 common2 = astAnnul( common2 );
3006 *map2_address = astAnnul( *map2_address );
3007 }
3008 frame2 = astAnnul( frame2 );
3009 common1 = astAnnul( common1 );
3010 *map1_address = astAnnul( *map1_address );
3011 }
3012 frame1 = astAnnul( frame1 );
3013 common0 = astAnnul( common0 );
3014 }
3015
3016 /* Go on to consider the next field in the domains list. */
3017 domain = domain_end ? domain_end + 1 : NULL;
3018 }
3019 }
3020
3021 /* Free the domain list copy. */
3022 domainlist_copy = astFree( domainlist_copy );
3023
3024 /* If returning a result, build the result FrameSet. Then annul the
3025 result Mapping pointer. */
3026 if ( result_map ) {
3027 result = astFrameSet( from, "", status );
3028 astAddFrame( result, AST__BASE, result_map, to );
3029 result_map = astAnnul( result_map );
3030 }
3031
3032 /* If an error occurred, annul the result FrameSet pointer. */
3033 if ( !astOK ) result = astAnnul( result );
3034
3035 /* Return the result. */
3036 return result;
3037 }
3038
DefaultMaxAxes(AstFrame * this,int * status)3039 static int DefaultMaxAxes( AstFrame *this, int *status ) {
3040 /*
3041 * Name:
3042 * DefaultMaxAxes
3043
3044 * Purpose:
3045 * Obtain the MaxAxes attribute from a Frame structure, with defaulting.
3046
3047 * Type:
3048 * Private function.
3049
3050 * Synopsis:
3051 * #include "frame.h"
3052 * int DefaultMaxAxes( AstFrame *this, int *status )
3053
3054 * Class Membership:
3055 * Frame member function.
3056
3057 * Description:
3058 * This function inspects the max_axes component of a Frame structure and
3059 * derives a value for the MaxAxes attribute. If the component's value
3060 * indicates that the attribute has not been set, a suitable default is
3061 * returned which is consistent with the state of the Frames's MinAxes
3062 * attribute.
3063
3064 * Parameters:
3065 * this
3066 * Pointer to the Frame.
3067 * status
3068 * Pointer to the inherited status variable.
3069
3070 * Returned Value:
3071 * The value to be used for the MaxAxes attribute.
3072 */
3073
3074 /* Local Variables. */
3075 int result; /* Result to be returned */
3076 int min_axes; /* Value of MinAxes attribute */
3077
3078 /* Check the global error status. */
3079 if ( !astOK ) return 0;
3080
3081 /* If the Frame's max_axes component is set, return its value. */
3082 if ( this->max_axes != -INT_MAX ) {
3083 result = this->max_axes;
3084
3085 /* Otherwise, the preferred default value is the number of Frame axes. */
3086 } else {
3087 result = astGetNaxes( this );
3088
3089 /* Before returning this value, check if the MinAxes attribute is set. If it
3090 is, obtain its value. */
3091 if ( astTestMinAxes( this ) ) {
3092 min_axes = astGetMinAxes( this );
3093
3094 /* If necessary, increase the MaxAxes default value so that it is not less than
3095 MinAxes. */
3096 if ( result < min_axes ) result = min_axes;
3097 }
3098 }
3099
3100 /* If an error occurred, clear the result value. */
3101 if ( !astOK ) result = 0;
3102
3103 /* Return the result. */
3104 return result;
3105 }
3106
DefaultMinAxes(AstFrame * this,int * status)3107 static int DefaultMinAxes( AstFrame *this, int *status ) {
3108 /*
3109 * Name:
3110 * DefaultMinAxes
3111
3112 * Purpose:
3113 * Obtain the MinAxes attribute from a Frame structure, with defaulting.
3114
3115 * Type:
3116 * Private function.
3117
3118 * Synopsis:
3119 * #include "frame.h"
3120 * int DefaultMinAxes( AstFrame *this, int *status )
3121
3122 * Class Membership:
3123 * Frame member function.
3124
3125 * Description:
3126 * This function inspects the min_axes component of a Frame structure and
3127 * derives a value for the MinAxes attribute. If the component's value
3128 * indicates that the attribute has not been set, a suitable default is
3129 * returned which is consistent with the state of the Frames's MaxAxes
3130 * attribute.
3131
3132 * Parameters:
3133 * this
3134 * Pointer to the Frame.
3135 * status
3136 * Pointer to the inherited status variable.
3137
3138 * Returned Value:
3139 * The value to be used for the MinAxes attribute.
3140 */
3141
3142 /* Local Variables: */
3143 int result; /* Result to be returned */
3144 int max_axes; /* Value of MaxAxes attribute */
3145
3146 /* Check the global error status. */
3147 if ( !astOK ) return 0;
3148
3149 /* If the Frame's min_axes component is set, return its value. */
3150 if ( this->min_axes != -INT_MAX ) {
3151 result = this->min_axes;
3152
3153 /* Otherwise, the preferred default value is the number of Frame axes. */
3154 } else {
3155 result = astGetNaxes( this );
3156
3157 /* Before returning this value, check if the MaxAxes attribute is set. If it
3158 is, obtain its value. */
3159 if ( astTestMaxAxes( this ) ) {
3160 max_axes = astGetMaxAxes( this );
3161
3162 /* If necessary, reduce the MinAxes default value so that it does not exceed
3163 MaxAxes. */
3164 if ( result > max_axes ) result = max_axes;
3165 }
3166 }
3167
3168 /* If an error occurred, clear the result value. */
3169 if ( !astOK ) result = 0;
3170
3171 /* Return the result. */
3172 return result;
3173 }
3174
Distance(AstFrame * this,const double point1[],const double point2[],int * status)3175 static double Distance( AstFrame *this,
3176 const double point1[], const double point2[], int *status ) {
3177 /*
3178 *++
3179 * Name:
3180 c astDistance
3181 f AST_DISTANCE
3182
3183 * Purpose:
3184 * Calculate the distance between two points in a Frame.
3185
3186 * Type:
3187 * Public virtual function.
3188
3189 * Synopsis:
3190 c #include "frame.h"
3191 c double astDistance( AstFrame *this,
3192 c const double point1[], const double point2[] )
3193 f RESULT = AST_DISTANCE( THIS, POINT1, POINT2, STATUS )
3194
3195 * Class Membership:
3196 * Frame method.
3197
3198 * Description:
3199 * This function finds the distance between two points whose Frame
3200 * coordinates are given. The distance calculated is that along
3201 * the geodesic curve that joins the two points.
3202 *
3203 * For example, in a basic Frame, the distance calculated will be
3204 * the Cartesian distance along the straight line joining the two
3205 * points. For a more specialised Frame describing a sky coordinate
3206 * system, however, it would be the distance along the great circle
3207 * passing through two sky positions.
3208
3209 * Parameters:
3210 c this
3211 f THIS = INTEGER (Given)
3212 * Pointer to the Frame.
3213 c point1
3214 f POINT1( * ) = DOUBLE PRECISION (Given)
3215 c An array of double, with one element for each Frame axis
3216 f An array with one element for each Frame axis
3217 * (Naxes attribute) containing the coordinates of the first point.
3218 c point2
3219 f POINT2( * ) = DOUBLE PRECISION (Given)
3220 c An array of double, with one element for each Frame axis
3221 f An array with one element for each Frame axis
3222 * containing the coordinates of the second point.
3223 f STATUS = INTEGER (Given and Returned)
3224 f The global status.
3225
3226 * Returned Value:
3227 c astDistance
3228 f AST_DISTANCE = DOUBLE PRECISION
3229 * The distance between the two points.
3230
3231 * Notes:
3232 * - This function will return a "bad" result value (AST__BAD) if
3233 * any of the input coordinates has this value.
3234 * - A "bad" value will also be returned if this function is
3235 c invoked with the AST error status set, or if it should fail for
3236 f invoked with STATUS set to an error value, or if it should fail for
3237 * any reason.
3238 *--
3239 */
3240
3241 /* Local Variables: */
3242 double delta; /* Separation along an axis */
3243 double result; /* Result value to return */
3244 int axis; /* Loop counter for axes */
3245 int naxes; /* Number of Frame axes */
3246
3247 /* Initialise. */
3248 result = AST__BAD;
3249
3250 /* Check the global error status. */
3251 if ( !astOK ) return result;
3252
3253 /* Obtain the number of Frame axes. */
3254 naxes = astGetNaxes( this );
3255 if ( astOK ) {
3256
3257 /* Loop to determine the Cartesian distance between the points. */
3258 result = 0.0;
3259 for ( axis = 0; axis < naxes; axis++ ) {
3260
3261 /* If any of the coordinates supplied is bad, set the distance to be
3262 bad and quit looping. */
3263 if ( ( point1[ axis ] == AST__BAD ) ||
3264 ( point2[ axis ] == AST__BAD ) ) {
3265 result = AST__BAD;
3266 break;
3267
3268 /* Otherwise, accumulate the sum of squared separations along each
3269 axis. */
3270 } else {
3271 delta = point1[ axis ] - point2[ axis ];
3272 result += ( delta * delta );
3273 }
3274 }
3275
3276 /* Take the square root to find the distance (if valid). */
3277 if ( result != AST__BAD ) result = sqrt( result );
3278 }
3279
3280 /* Return the result. */
3281 return result;
3282 }
3283
DoNotSimplify(AstMapping * this,int * status)3284 static int DoNotSimplify( AstMapping *this, int *status ) {
3285 /*
3286 * Name:
3287 * DoNotSimplify
3288
3289 * Purpose:
3290 * Check if a Mapping is appropriate for simplification.
3291
3292 * Type:
3293 * Private function.
3294
3295 * Synopsis:
3296 * #include "object.h"
3297 * int DoNotSImplify( AstMapping *this );
3298
3299 * Class Membership:
3300 * CmpMap member function (over-rides the astDoNotSimplify protected
3301 * method inherited from the parent class).
3302
3303 * Description:
3304 * This function returns a flag indivating if the supplied Mapping is
3305 * appropriate for simplification.
3306
3307 * Parameters:
3308 * this
3309 * Pointer to the Mapping.
3310 * status
3311 * Pointer to the inherited status variable.
3312
3313 * Returned Value:
3314 * Non-zero if the supplied Mapping is not appropriate for
3315 * simplification, and zero otherwise.
3316
3317 * Notes:
3318 * - A value of 0 will be returned if this function is invoked
3319 * with the global error status set, or if it should fail for any
3320 * reason.
3321
3322 */
3323
3324 /* Unlike basic Mappings, Frames that have a set value for the Ident
3325 can be simplified. So always return zero. */
3326 return 0;
3327 }
3328
Equal(AstObject * this_object,AstObject * that_object,int * status)3329 static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
3330 /*
3331 * Name:
3332 * Equal
3333
3334 * Purpose:
3335 * Test if two Frames are equivalent.
3336
3337 * Type:
3338 * Private function.
3339
3340 * Synopsis:
3341 * #include "frame.h"
3342 * int Equal( AstObject *this, AstObject *that, int *status )
3343
3344 * Class Membership:
3345 * Frame member function (over-rides the astEqual protected
3346 * method inherited from the Mapping class).
3347
3348 * Description:
3349 * This function returns a boolean result (0 or 1) to indicate whether
3350 * two Frames are equivalent.
3351
3352 * Parameters:
3353 * this
3354 * Pointer to the first Frame.
3355 * that
3356 * Pointer to the second Frame.
3357 * status
3358 * Pointer to the inherited status variable.
3359
3360 * Returned Value:
3361 * One if the Frames are equivalent, zero otherwise.
3362
3363 * Notes:
3364 * - The two Frames are considered equivalent if the Mapping between
3365 * them is a UnitMap.
3366 * - A value of zero will be returned if this function is invoked
3367 * with the global status set, or if it should fail for any reason.
3368 */
3369
3370 /* Local Variables: */
3371 AstFrame *that; /* Pointer to the second Frame structure */
3372 AstFrame *this; /* Pointer to the first Frame structure */
3373 AstFrameSet *fs; /* FrameSet connecting the two Frames */
3374 AstMapping *map1; /* Mapping connecting the two Frames */
3375 AstMapping *map2; /* Simplified mapping connecting two Frames */
3376 int result; /* Result value to return */
3377
3378 /* Initialise. */
3379 result = 0;
3380
3381 /* Check the global error status. */
3382 if ( !astOK ) return result;
3383
3384 /* Checks that the second object is of the same class as the first . */
3385 if( !strcmp( astGetClass( this_object ), astGetClass( that_object ) ) ){
3386
3387 /* Obtain pointers to the two Frame structures. */
3388 this = (AstFrame *) this_object;
3389 that = (AstFrame *) that_object;
3390
3391 /* Get the Mapping between them, and see if it is a UnitMap. */
3392 fs = astConvert( that, this, "" );
3393 if( fs ) {
3394 map1 = astGetMapping( fs, AST__BASE, AST__CURRENT );
3395 map2 = astSimplify( map1 );
3396 result = astIsAUnitMap( map2 );
3397 map1 = astAnnul( map1 );
3398 map2 = astAnnul( map2 );
3399 fs = astAnnul( fs );
3400 }
3401 }
3402
3403 /* If an error occurred, clear the result value. */
3404 if ( !astOK ) result = 0;
3405
3406 /* Return the result, */
3407 return result;
3408 }
3409
Fields(AstFrame * this,int axis,const char * fmt,const char * str,int maxfld,char ** fields,int * nc,double * val,int * status)3410 static int Fields( AstFrame *this, int axis, const char *fmt,
3411 const char *str, int maxfld, char **fields,
3412 int *nc, double *val, int *status ) {
3413 /*
3414 *+
3415 * Name:
3416 * astFields
3417
3418 * Purpose:
3419 * Identify numerical fields within a formatted Axis value.
3420
3421 * Type:
3422 * Protected virtual function.
3423
3424 * Synopsis:
3425 * #include "frame.h"
3426 * int astFields( AstFrame *this, int axis, const char *fmt,
3427 * const char *str, int maxfld, char **fields,
3428 * int *nc, double *val )
3429
3430 * Class Membership:
3431 * Frame method.
3432
3433 * Description:
3434 * This function identifies the numerical fields within a Frame axis
3435 * value that has been formatted using astAxisFormat. It assumes that
3436 * the value was formatted using the supplied format string. It also
3437 * returns the equivalent floating point value.
3438
3439 * Parameters:
3440 * this
3441 * Pointer to the Frame.
3442 * axis
3443 * The number of the Frame axis for which the values have been
3444 * formatted (axis numbering starts at zero for the first axis).
3445 * fmt
3446 * Pointer to a constant null-terminated string containing the
3447 * format used when creating "str".
3448 * str
3449 * Pointer to a constant null-terminated string containing the
3450 * formatted value.
3451 * maxfld
3452 * The maximum number of fields to identify within "str".
3453 * fields
3454 * A pointer to an array of at least "maxfld" character pointers.
3455 * Each element is returned holding a pointer to the start of the
3456 * corresponding field in "str" (in the order in which they occur
3457 * within "str"), or NULL if no corresponding field can be found.
3458 * nc
3459 * A pointer to an array of at least "maxfld" integers. Each
3460 * element is returned holding the number of characters in the
3461 * corresponding field, or zero if no corresponding field can be
3462 * found.
3463 * val
3464 * Pointer to a location at which to store the value
3465 * equivalent to the returned field values. If this is NULL,
3466 * it is ignored.
3467
3468 * Returned Value:
3469 * The number of fields succesfully identified and returned.
3470
3471 * Notes:
3472 * - Leading and trailing spaces are ignored.
3473 * - If the formatted value is not consistent with the supplied format
3474 * string, then a value of zero will be returned, "fields" will be
3475 * returned holding NULLs, "nc" will be returned holding zeros, and
3476 * "val" is returned holding VAL__BAD.
3477 * - Fields are counted from the start of the formatted string. If the
3478 * string contains more than "maxfld" fields, then trailing fields are
3479 * ignored.
3480 * - If this function is invoked with the global error status set, or
3481 * if it should fail for any reason, then a value of zero will be returned
3482 * as the function value, and "fields", "nc" and "val" will be returned
3483 * holding their supplied values
3484 *-
3485 */
3486
3487 /* Local Variables: */
3488 AstAxis *ax; /* Pointer to Axis object */
3489 int result; /* Result field count to return */
3490
3491 /* Initialise. */
3492 result = 0;
3493
3494 /* Check the global error status. */
3495 if ( !astOK ) return result;
3496
3497 /* Validate the axis index and obtain a pointer to the required
3498 Axis. */
3499 (void) astValidateAxis( this, axis, 1, "astFields" );
3500 ax = astGetAxis( this, axis );
3501
3502 /* Invoke the Axis astAxisFields method to perform the processing. */
3503 result = astAxisFields( ax, fmt, str, maxfld, fields, nc, val );
3504
3505 /* Annul the Axis pointer. */
3506 ax = astAnnul( ax );
3507
3508 /* If an error occurred, clear the returned value. */
3509 if ( !astOK ) result = 0;
3510
3511 /* Return the result. */
3512 return result;
3513 }
3514
FindFrame(AstFrame * target,AstFrame * template,const char * domainlist,int * status)3515 static AstFrameSet *FindFrame( AstFrame *target, AstFrame *template,
3516 const char *domainlist, int *status ) {
3517 /*
3518 *++
3519 * Name:
3520 c astFindFrame
3521 f AST_FINDFRAME
3522
3523 * Purpose:
3524 * Find a coordinate system with specified characteristics.
3525
3526 * Type:
3527 * Public virtual function.
3528
3529 * Synopsis:
3530 c #include "frame.h"
3531 c AstFrameSet *astFindFrame( AstFrame *target, AstFrame *template,
3532 c const char *domainlist )
3533 f RESULT = AST_FINDFRAME( TARGET, TEMPLATE, DOMAINLIST, STATUS )
3534
3535 * Class Membership:
3536 * Frame method.
3537
3538 * Description:
3539 * This function uses a "template" Frame to search another Frame
3540 * (or FrameSet) to identify a coordinate system which has a
3541 * specified set of characteristics. If a suitable coordinate
3542 * system can be found, the function returns a pointer to a
3543 * FrameSet which describes the required coordinate system and how
3544 * to convert coordinates to and from it.
3545 *
3546 * This function is provided to help answer general questions about
3547 * coordinate systems, such as typically arise when coordinate
3548 * information is imported into a program as part of an initially
3549 * unknown dataset. For example:
3550 * - Is there a wavelength scale?
3551 * - Is there a 2-dimensional coordinate system?
3552 * - Is there a celestial coordinate system?
3553 * - Can I plot the data in ecliptic coordinates?
3554 *
3555 * You can also use this function as a means of reconciling a
3556 * user's preference for a particular coordinate system (for
3557 * example, what type of axes to draw) with what is actually
3558 * possible given the coordinate information available.
3559 *
3560 * To perform a search, you supply a "target" Frame (or FrameSet)
3561 * which represents the set of coordinate systems to be searched.
3562 * If a basic Frame is given as the target, this set of coordinate
3563 * systems consists of the one described by this Frame, plus all
3564 * other "virtual" coordinate systems which can potentially be
3565 * reached from it by applying built-in conversions (for example,
3566 * any of the celestial coordinate conversions known to the AST
3567 * library would constitute a "built-in" conversion). If a FrameSet
3568 * is given as the target, the set of coordinate systems to be
3569 * searched consists of the union of those represented by all the
3570 * individual Frames within it.
3571 *
3572 * To select from this large set of possible coordinate systems,
3573 * you supply a "template" Frame which is an instance of the type
3574 * of Frame you are looking for. Effectively, you then ask the
3575 * function to "find a coordinate system that looks like this".
3576 *
3577 * You can make your request more or less specific by setting
3578 * attribute values for the template Frame. If a particular
3579 * attribute is set in the template, then the function will only
3580 * find coordinate systems which have exactly the same value for
3581 * that attribute. If you leave a template attribute un-set,
3582 * however, then the function has discretion about the value the
3583 * attribute should have in any coordinate system it finds. The
3584 * attribute will then take its value from one of the actual
3585 * (rather than virtual) coordinate systems in the target. If the
3586 * target is a FrameSet, its Current attribute will be modified to
3587 * indicate which of its Frames was used for this purpose.
3588 *
3589 * The result of this process is a coordinate system represented by
3590 * a hybrid Frame which acquires some attributes from the template
3591 * (but only if they were set) and the remainder from the
3592 * target. This represents the "best compromise" between what you
3593 * asked for and what was available. A Mapping is then generated
3594 * which converts from the target coordinate system to this hybrid
3595 * one, and the returned FrameSet encapsulates all of this
3596 * information.
3597
3598 * Parameters:
3599 c target
3600 f TARGET = INTEGER (Given)
3601 * Pointer to the target Frame (or FrameSet).
3602 *
3603 * Note that if a FrameSet is supplied (and a suitable
3604 * coordinate system is found), then its Current attribute will
3605 * be modified to indicate which Frame was used to obtain
3606 * attribute values which were not specified by the template.
3607 * This Frame will, in some sense, represent the "closest"
3608 * non-virtual coordinate system to the one you requested.
3609 c template
3610 f TEMPLATE = INTEGER (Given)
3611 * Pointer to the template Frame, which should be an instance of
3612 * the type of Frame you wish to find. If you wanted to find a
3613 * Frame describing a celestial coordinate system, for example,
3614 * then you might use a SkyFrame here. See the "Examples"
3615 * section for more ideas.
3616 c domainlist
3617 f DOMAINLIST = CHARACTER * ( * ) (Given)
3618 c Pointer to a null-terminated character string containing a
3619 f A character string containing a
3620 * comma-separated list of Frame domains. This may be used to
3621 * establish a priority order for the different types of
3622 * coordinate system that might be found.
3623 *
3624 * The function will first try to find a suitable coordinate
3625 * system whose Domain attribute equals the first domain in this
3626 * list. If this fails, the second domain in the list will be
3627 * used, and so on, until a result is obtained. A blank domain
3628 * (e.g. two consecutive commas) indicates that any coordinate
3629 * system is acceptable (subject to the template) regardless of
3630 * its domain.
3631 *
3632 * This list is case-insensitive and all white space is ignored.
3633 * If you do not wish to restrict the domain in this way,
3634 c you should supply an empty string.
3635 f you should supply a blank string.
3636 f STATUS = INTEGER (Given and Returned)
3637 f The global status.
3638
3639 * Returned Value:
3640 c astFindFrame()
3641 f AST_FINDFRAME = INTEGER
3642 * If the search is successful, the function returns a pointer
3643 * to a FrameSet which contains the Frame found and a
3644 * description of how to convert to (and from) the coordinate
3645 * system it represents. Otherwise, a null Object pointer
3646 * (AST__NULL) is returned without error.
3647 *
3648 * If a FrameSet is returned, it will contain two Frames. Frame
3649 * number 1 (its base Frame) represents the target coordinate
3650 * system and will be the same as the (base Frame of the)
3651 * target. Frame number 2 (its current Frame) will be a Frame
3652 * representing the coordinate system which the function
3653 * found. The Mapping which inter-relates these two Frames will
3654 * describe how to convert between their respective coordinate
3655 * systems.
3656 *
3657 * Note that a FrameSet may be used both as a Mapping and as a
3658 * Frame. If the result is used as a Mapping (e.g. with
3659 * astTran2), then it provides a means of converting coordinates
3660 * from the target coordinate system into the new coordinate
3661 * system that was found (and vice versa if its inverse
3662 * transformation is selected). If it is used as a Frame, its
3663 * attributes will describe the new coordinate system.
3664
3665 * Applicability:
3666 * Frame
3667 * This function applies to all Frames.
3668 * FrameSet
3669 * If the target is a FrameSet, the possibility exists that
3670 * several of the Frames within it might be matched by the
3671 * template. Unless the choice is sufficiently restricted by
3672 c the "domainlist" string, the sequence in which Frames are
3673 f the DOMAINLIST string, the sequence in which Frames are
3674 * searched can then become important. In this case, the search
3675 * proceeds as follows:
3676 c - Each field in the "domainlist" string is considered in turn.
3677 f - Each field in the DOMAINLIST string is considered in turn.
3678 * - An attempt is made to match the template to each of the
3679 * target's Frames in the order: (1) the current Frame, (2) the
3680 * base Frame, (3) each remaining Frame in the order of being
3681 * added to the target FrameSet.
3682 * - Generally, the first match found is used. However, the
3683 * Mapping between the target coordinate system and the
3684 * resulting Frame is also examined. Preference is given to
3685 * cases where both the forward and inverse transformations are
3686 * defined (as indicated by the TranForward and TranInverse
3687 * attributes). If only one transformation is defined, the
3688 * forward one is preferred.
3689 * - If a match is found and the domain of the resulting Frame also
3690 c matches the current "domainlist" field, it is
3691 f matches the current DOMAINLIST field, it is
3692 c accepted. Otherwise, the next "domainlist" field is considered
3693 f accepted. Otherwise, the next DOMAINLIST field is considered
3694 * and the process repeated.
3695 *
3696 * If a suitable coordinate system is found, the Current
3697 * attribute of the target FrameSet will be modified on exit to
3698 * identify the Frame whose match with the target was eventually
3699 * accepted.
3700
3701 * Examples:
3702 c result = astFindFrame( target, astFrame( 3, "" ), "" );
3703 f RESULT = AST_FINDFRAME( TARGET, AST_FRAME( 3, ' ', STATUS ), ' ', STATUS )
3704 * Searches for a 3-dimensional coordinate system in the target
3705 * Frame (or FrameSet). No attributes have been set in the
3706 c template Frame (created by astFrame), so no restriction has
3707 f template Frame (created by AST_FRAME), so no restriction has
3708 * been placed on the required coordinate system, other than
3709 * that it should have 3 dimensions. The first suitable Frame
3710 c found will be returned as part of the "result" FrameSet.
3711 f found will be returned as part of the RESULT FrameSet.
3712 c result = astFindFrame( target, astSkyFrame( "" ), "" );
3713 f RESULT = AST_FINDFRAME( TARGET, AST_SKYFRAME( ' ', STATUS ), ' ', STATUS )
3714 * Searches for a celestial coordinate system in the target
3715 * Frame (or FrameSet). The type of celestial coordinate system
3716 c is unspecified, so astFindFrame will return the first one
3717 f is unspecified, so AST_FINDFRAME will return the first one
3718 c found as part of the "result" FrameSet. If the target is
3719 f found as part of the RESULT FrameSet. If the target is
3720 * a FrameSet, then its Current attribute will be updated to
3721 * identify the Frame that was used.
3722 *
3723 * If no celestial coordinate system can be found, a value of
3724 * AST__NULL will be returned without error.
3725 c result = astFindFrame( target, astSkyFrame( "MaxAxes=100" ), "" );
3726 f RESULT = AST_FINDFRAME( TARGET, AST_SKYFRAME( 'MaxAxes=100', STATUS ), ' ', STATUS )
3727 * This is like the last example, except that in the event of the
3728 * target being a CmpFrame, the component Frames encapsulated by the
3729 * CmpFrame will be searched for a SkyFrame. If found, the returned
3730 * Mapping will included a PermMap which selects the required axes
3731 * from the target CmpFrame.
3732 *
3733 * This is acomplished by setting the MaxAxes attribute of the
3734 * template SkyFrame to a large number (larger than or equal to the
3735 * number of axes in the target CmpFrame). This allows the SkyFrame
3736 * to be used as a match for Frames containing from 2 to 100 axes.
3737 c result = astFindFrame( target, astSkyFrame( "System=FK5" ), "" );
3738 f RESULT = AST_FINDFRAME( TARGET, AST_SKYFRAME( 'System=FK5', STATUS ), ' ', STATUS )
3739 * Searches for an equatorial (FK5) coordinate system in the
3740 * target. The Equinox value for the coordinate system has not
3741 * been specified, so will be obtained from the target. If the
3742 * target is a FrameSet, its Current attribute will be updated
3743 * to indicate which SkyFrame was used to obtain this value.
3744 c result = astFindFrame( target, astFrame( 2, "" ), "sky,pixel," );
3745 f RESULT = AST_FINDFRAME( TARGET, AST_FRAME( 2, ' ', STATUS ), 'SKY,PIXEL,', STATUS )
3746 * Searches for a 2-dimensional coordinate system in the
3747 * target. Initially, a search is made for a suitable coordinate
3748 * system whose Domain attribute has the value "SKY". If this
3749 * search fails, a search is then made for one with the domain
3750 * "PIXEL". If this also fails, then any 2-dimensional
3751 c coordinate system is returned as part of the "result"
3752 f coordinate system is returned as part of the RESULT
3753 * FrameSet.
3754 *
3755 * Only if no 2-dimensional coordinate systems can be reached by
3756 * applying built-in conversions to any of the Frames in the
3757 * target will a value of AST__NULL be returned.
3758 c result = astFindFrame( target, astFrame( 1, "Domain=WAVELENGTH" ), "" );
3759 f RESULT = AST_FINDFRAME( TARGET, AST_FRAME( 1, 'Domain=WAVELENGTH', STATUS ), ' ', STATUS )
3760 * Searches for any 1-dimensional coordinate system in the
3761 * target which has the domain "WAVELENGTH".
3762 c result = astFindFrame( target, astFrame( 1, "" ), "wavelength" );
3763 f RESULT = AST_FINDFRAME( TARGET, AST_FRAME( 1, ' ', STATUS ), 'WAVELENGTH', STATUS )
3764 * This example has exactly the same effect as that above. It
3765 * illustrates the equivalence of the template's Domain attribute
3766 c and the fields in the "domainlist" string.
3767 f and the fields in the DOMAINLIST string.
3768 c result = astFindFrame( target, astFrame( 1, "MaxAxes=3" ), "" );
3769 f RESULT = AST_FINDFRAME( TARGET, AST_FRAME( 1, 'MaxAxes=3', STATUS ), ' ', STATUS )
3770 * This is a more advanced example which will search for any
3771 * coordinate system in the target having 1, 2 or 3
3772 c dimensions. The Frame returned (as part of the "result"
3773 f dimensions. The Frame returned (as part of the RESULT
3774 * FrameSet) will always be 1-dimensional, but will be related
3775 * to the coordinate system that was found by a suitable Mapping
3776 * (e.g. a PermMap) which simply extracts the first axis.
3777 *
3778 * If we had wanted a Frame representing the actual (1, 2 or
3779 * 3-dimensional) coordinate system found, we could set the
3780 * PreserveAxes attribute to a non-zero value in the template.
3781 c result = astFindFrame( target, astSkyFrame( "Permute=0" ), "" );
3782 f RESULT = AST_FINDFRAME( TARGET, AST_SKYFRAME( 'Permute=0', STATUS ), ' ', STATUS )
3783 * Searches for any celestial coordinate system in the target,
3784 * but only finds one if its axes are in the conventional
3785 * (longitude,latitude) order and have not been permuted
3786 c (e.g. with astPermAxes).
3787 f (e.g. with AST_PERMAXES).
3788
3789 * Notes:
3790 * - The Mapping represented by the returned FrameSet results in
3791 * alignment taking place in the coordinate system specified by the
3792 c AlignSystem attribute of the "template" Frame. See the description
3793 f AlignSystem attribute of the TEMPLATE Frame. See the description
3794 * of the AlignSystem attribute for further details.
3795 * - Beware of setting the Domain attribute of the template and then
3796 c using a "domainlist" string which does not include the template's domain
3797 f using a DOMAINLIST string which does not include the template's domain
3798 * (or a blank field). If you do so, no coordinate system will be
3799 * found.
3800 * - A null Object pointer (AST__NULL) will be returned if this
3801 c function is invoked with the AST error status set, or if it
3802 f function is invoked with STATUS set to an error value, or if it
3803 * should fail for any reason.
3804
3805 * More on Using Templates:
3806 * A Frame (describing a coordinate system) will be found by this
3807 * function if (a) it is "matched" by the template you supply, and
3808 c (b) the value of its Domain attribute appears in the "domainlist"
3809 f (b) the value of its Domain attribute appears in the DOMAINLIST
3810 * string (except that a blank field in this string permits any
3811 * domain). A successful match by the template depends on a number
3812 * of criteria, as outlined below:
3813 * - In general, a template will only match another Frame which
3814 * belongs to the same class as the template, or to a derived (more
3815 * specialised) class. For example, a SkyFrame template will match
3816 * any other SkyFrame, but will not match a basic
3817 * Frame. Conversely, a basic Frame template will match any class
3818 * of Frame.
3819 * - The exception to this is that a Frame of any class can be used to
3820 * match a CmpFrame, if that CmpFrame contains a Frame of the same
3821 * class as the template. Note however, the MaxAxes and MinAxes
3822 * attributes of the template must be set to suitable values to allow
3823 * it to match the CmpFrame. That is, the MinAxes attribute must be
3824 * less than or equal to the number of axes in the target, and the MaxAxes
3825 * attribute must be greater than or equal to the number of axes in
3826 * the target.
3827 * - If using a CmpFrame as a template frame, the MinAxes and MaxAxes
3828 * for the template are determined by the MinAxes and MaxAxes values of
3829 * the component Frames within the template. So if you want a template
3830 * CmpFrame to be able to match Frames with different numbers of axes,
3831 * then you must set the MaxAxes and/or MinAxes attributes in the component
3832 * template Frames, before combining them together into the template
3833 * CmpFrame.
3834 * - If a template has a value set for any of its main attributes, then
3835 * it will only match Frames which have an identical value for that
3836 * attribute (or which can be transformed, using a built-in
3837 * conversion, so that they have the required value for that
3838 * attribute). If any attribute in the template is un-set, however,
3839 * then Frames are matched regardless of the value they may have
3840 * for that attribute. You may therefore make a template more or
3841 * less specific by choosing the attributes for which you set
3842 * values. This requirement does not apply to 'descriptive' attributes
3843 * such as titles, labels, symbols, etc.
3844 * - An important application of this principle involves the Domain
3845 * attribute. Setting the Domain attribute of the template has the
3846 * effect of restricting the search to a particular type of Frame
3847 * (with the domain you specify). Conversely, if the Domain
3848 * attribute is not set in the template, then the domain of the
3849 * Frame found is not relevant, so all Frames are searched. Note
3850 * that the
3851 c "domainlist" string provides an alternative way of restricting the
3852 f DOMAINLIST string provides an alternative way of restricting the
3853 * search in the same manner, but is a more convenient interface if
3854 * you wish to search automatically for another domain if the first
3855 * search fails.
3856 * - Normally, a template will only match a Frame which has the
3857 * same number of axes as itself. However, for some classes of
3858 * template, this default behaviour may be changed by means of the
3859 * MinAxes, MaxAxes and MatchEnd attributes. In addition, the
3860 * behaviour of a template may be influenced by its Permute and
3861 * PreserveAxes attributes, which control whether it matches Frames
3862 * whose axes have been permuted, and whether this permutation is
3863 * retained in the Frame which is returned (as opposed to returning
3864 * the axes in the order specified in the template, which is the
3865 * default behaviour). You should consult the descriptions of these
3866 * attributes for details of this more advanced use of templates.
3867 *--
3868 */
3869
3870 /* Local Variables: */
3871 AstFrame *frame; /* Pointer to result Frame */
3872 AstFrameSet *result; /* Pointer to result FrameSet */
3873 AstMapping *map; /* Pointer to result Mapping */
3874 AstMapping *tmp; /* Temporary Mapping pointer */
3875 char *domain_copy; /* Pointer to copy of result domain */
3876 char *domainlist_copy; /* Pointer to copy of domains list */
3877 const char *domain; /* Pointer to result Domain value */
3878 int *target_axes; /* Pointer to target axis assignments */
3879 int *template_axes; /* Pointer to template axis assignments */
3880 int i; /* Loop counter for characters */
3881 int j; /* Character index */
3882 int match; /* Template matched target? */
3883
3884 /* Initialise. */
3885 result = NULL;
3886
3887 /* Check the global error status. */
3888 if ( !astOK ) return result;
3889
3890 /* Allocate space to store a copy of the domains list, with added
3891 commas. */
3892 domainlist_copy = astMalloc( strlen( domainlist ) + (size_t) 3 );
3893 if ( astOK ) {
3894
3895 /* Make a copy of the domains list, with an extra comma added at each
3896 end. Also remove all white space and convert to upper case. */
3897 domainlist_copy[ 0 ] = ',';
3898 for ( i = 0, j = 1; domainlist[ i ]; i++ ) {
3899 if ( !isspace( domainlist[ i ] ) ) {
3900 domainlist_copy[ j++ ] = toupper( domainlist[ i ] );
3901 }
3902 }
3903 domainlist_copy[ j++ ] = ',';
3904 domainlist_copy[ j ] = '\0';
3905
3906 /* Invoke the protected astMatch method associated with the template
3907 Frame. This matches the template to the target and returns
3908 information about how to convert between the target and the Frame
3909 it found (if any). */
3910 match = astMatch( template, target, 0,
3911 &template_axes, &target_axes, &map, &frame );
3912
3913 /* If successful, obtain a pointer to the Domain string of the result
3914 Frame. Allocate space for a copy of this string, with added
3915 commas. */
3916 if ( match && astOK ) {
3917 domain = astGetDomain( frame );
3918 if ( astOK ) {
3919 domain_copy = astMalloc( strlen( domain ) + (size_t) 3 );
3920 if ( astOK ) {
3921
3922 /* Make a copy of the domain, adding an extra comma at each end. */
3923 domain_copy[ 0 ] = ',';
3924 for ( i = 0, j = 1; domain[ i ]; i++ ) {
3925 domain_copy[ j++ ] = domain[ i ];
3926 }
3927 domain_copy[ j++ ] = ',';
3928 domain_copy[ j ] = '\0';
3929
3930 /* Test if the domain appears in the domains list (with added
3931 commas). If not, test if a blank domain (which permits the result
3932 Frame to have any Domain) appears instead. */
3933 if ( strstr( domainlist_copy, domain_copy ) ||
3934 strstr( domainlist_copy, ",," ) ) {
3935
3936 /* If the result Frame is acceptable, simplify the result Mapping. */
3937 tmp = astSimplify( map );
3938 map = astAnnul( map );
3939 map = tmp;
3940
3941 /* Build the result FrameSet. */
3942 result = astFrameSet( target, "", status );
3943 astAddFrame( result, AST__BASE, map, frame );
3944 }
3945 }
3946
3947 /* Free the copy of the result domain. */
3948 domain_copy = astFree( domain_copy );
3949 }
3950
3951 /* Free space and annul pointers allocated by astMatch. */
3952 template_axes = astFree( template_axes );
3953 target_axes = astFree( target_axes );
3954 map = astAnnul( map );
3955 frame = astAnnul( frame );
3956 }
3957 }
3958
3959 /* Free the copy of the domains list. */
3960 domainlist_copy = astFree( domainlist_copy );
3961
3962 /* If an error occurred, annul any result pointer. */
3963 if ( !astOK && result ) result = astAnnul( result );
3964
3965 /* Return the result. */
3966 return result;
3967 }
3968
astFmtDecimalYr_(double year,int digits,int * status)3969 const char *astFmtDecimalYr_( double year, int digits, int *status ) {
3970 /*
3971 *+
3972 * Name:
3973 * astFmtDecimalYr
3974
3975 * Purpose:
3976 * Format an epoch expressed in years as a decimal string.
3977
3978 * Type:
3979 * Protected function.
3980
3981 * Synopsis:
3982 * #include "frame.h"
3983 * const char *astFmtDecimalYr( double year, int digits )
3984
3985 * Class Membership:
3986 * Frame member function.
3987
3988 * Description:
3989 * This function formats an epoch expressed in years as a decimal string
3990 * and returns a pointer to the result. It is intended for formatting
3991 * Frame Epoch values, etc, for display.
3992
3993 * Parameters:
3994 * year
3995 * The epoch to be formatted.
3996 * digits
3997 * The number of digits of precision required.
3998
3999 * Returned Value:
4000 * Pointer to a null terminated string containing the formatted value.
4001
4002 * Notes:
4003 * - The result string is stored in static memory and may be
4004 * over-written by a subsequent invocation of this function.
4005 * - A NULL pointer is returned if this function is invoked with
4006 * the global error status set or if it should fail for any reason.
4007 *-
4008 */
4009
4010 /* Local Variables: */
4011 astDECLARE_GLOBALS /* Declare the thread specific global data */
4012 int nc; /* Number of characters in buffer */
4013
4014 /* Check the global error status. */
4015 if ( !astOK ) return NULL;
4016
4017 /* Get a pointer to the structure holding thread-specific global data. */
4018 astGET_GLOBALS(NULL);
4019
4020 /* Limit the precision to what is meaningful. */
4021 digits = ( digits > DBL_DIG ) ? DBL_DIG : digits;
4022
4023 /* Format the year value. Use "g" format to avoid buffer overflow and
4024 to get useful diagnostic output if a silly value is given. */
4025 nc = sprintf( astfmtdecimalyr_buff, "%#.*g", digits, year );
4026
4027 /* Loop to remove redundant zeros from the end of the result. */
4028 while ( astfmtdecimalyr_buff[ --nc ] == '0' ) astfmtdecimalyr_buff[ nc ] = '\0';
4029
4030 /* If the last character is now a decimal point, put back one zero. */
4031 if ( astfmtdecimalyr_buff[ nc ] == '.' ) {
4032 astfmtdecimalyr_buff[ ++nc ] = '0';
4033 astfmtdecimalyr_buff[ ++nc ] = '\0';
4034 }
4035
4036 /* Return the result. */
4037 return astfmtdecimalyr_buff;
4038 }
4039
Format(AstFrame * this,int axis,double value,int * status)4040 static const char *Format( AstFrame *this, int axis, double value, int *status ) {
4041 /*
4042 *+
4043 * Name:
4044 * astFormat
4045
4046 * Purpose:
4047 * Format a coordinate value for a Frame axis.
4048
4049 * Type:
4050 * Protected virtual function.
4051
4052 * Synopsis:
4053 * #include "frame.h"
4054 * const char *astFormat( AstFrame *this, int axis, double value )
4055
4056 * Class Membership:
4057 * Frame method.
4058
4059 * Description:
4060 * This function returns a pointer to a string containing the
4061 * formatted (character) version of a coordinate value for a Frame
4062 * axis. The formatting applied is determined by the Frame's
4063 * attributes and, in particular, by any Format attribute string
4064 * that has been set for the axis. A suitable default format will
4065 * be applied if necessary.
4066
4067 * Parameters:
4068 * this
4069 * Pointer to the Frame.
4070 * axis
4071 * The number of the Frame axis for which formatting is to be
4072 * performed (axis numbering starts at zero for the first axis).
4073 * value
4074 * The coordinate value to be formatted.
4075
4076 * Returned Value:
4077 * A pointer to a null-terminated string containing the formatted
4078 * value.
4079
4080 * Notes:
4081 * - The returned string pointer may point at memory allocated
4082 * within the Frame, or at static memory. The contents of the
4083 * string may be over-written or the pointer may become invalid
4084 * following a further invocation of the same function or any
4085 * modification of the Frame. A copy of the string should
4086 * therefore be made if necessary.
4087 * - A NULL pointer will be returned if this function is invoked
4088 * with the global error status set, or if it should fail for any
4089 * reason.
4090 *-
4091
4092 * Implementation Notes:
4093 * - This function implements the basic astFormat method available
4094 * via the protected interface to the Frame class. The public
4095 * interface to this method is provided by the astFormatId_
4096 * function.
4097 */
4098
4099 /* Local Variables: */
4100 AstAxis *ax; /* Pointer to Axis object */
4101 const char *result; /* Pointer value to return */
4102 int digits_set; /* Axis Digits attribute set? */
4103
4104 /* Check the global error status. */
4105 if ( !astOK ) return NULL;
4106
4107 /* Validate the axis index and obtain a pointer to the required Axis. */
4108 (void) astValidateAxis( this, axis, 1, "astFormat" );
4109 ax = astGetAxis( this, axis );
4110
4111 /* Test if any Axis attributes which may affect the result are undefined (i.e.
4112 have not been explicitly set). If so, we over-ride them, giving them
4113 temporary values dictated by the Frame. Only the Digits attribute is
4114 relevant here. */
4115 digits_set = astTestAxisDigits( ax );
4116 if ( !digits_set ) astSetAxisDigits( ax, astGetDigits( this ) );
4117
4118 /* Format the value. */
4119 result = astAxisFormat( ax, value );
4120
4121 /* Clear any Axis attributes that were temporarily over-ridden. */
4122 if ( !digits_set ) astClearAxisDigits( ax );
4123
4124 /* Annul the Axis pointer. */
4125 ax = astAnnul( ax );
4126
4127 /* If an error occurred, clear the result value. */
4128 if ( !astOK ) result = NULL;
4129
4130 /* Return the result. */
4131 return result;
4132 }
4133
FrameGrid(AstFrame * this,int size,const double * lbnd,const double * ubnd,int * status)4134 static AstPointSet *FrameGrid( AstFrame *this, int size, const double *lbnd,
4135 const double *ubnd, int *status ){
4136 /*
4137 *+
4138 * Name:
4139 * astFrameGrid
4140
4141 * Purpose:
4142 * Return a grid of points covering a rectangular area of a Frame.
4143
4144 * Type:
4145 * Protected virtual function.
4146
4147 * Synopsis:
4148 * #include "frame.h"
4149 * AstPointSet *astFrameGrid( AstFrame *this_frame, int size,
4150 * const double *lbnd, const double *ubnd )
4151
4152 * Class Membership:
4153 * Frame method.
4154
4155 * Description:
4156 * This function returns a PointSet containing positions spread
4157 * approximately evenly throughtout a specified rectangular area of
4158 * the Frame.
4159
4160 * Parameters:
4161 * this
4162 * Pointer to the Frame.
4163 * size
4164 * The preferred number of points in the returned PointSet. The
4165 * actual number of points in the returned PointSet may be
4166 * different, but an attempt is made to stick reasonably closely to
4167 * the supplied value.
4168 * lbnd
4169 * Pointer to an array holding the lower bound of the rectangular
4170 * area on each Frame axis. The array should have one element for
4171 * each Frame axis.
4172 * ubnd
4173 * Pointer to an array holding the upper bound of the rectangular
4174 * area on each Frame axis. The array should have one element for
4175 * each Frame axis.
4176
4177 * Returned Value:
4178 * A pointer to a new PointSet holding the grid of points.
4179
4180 * Notes:
4181 * - A NULL pointer is returned if an error occurs.
4182 *-
4183 */
4184
4185 /* Local Variables: */
4186 AstPointSet *result;
4187 const char *unit;
4188 double **ptr;
4189 double *gmean;
4190 double *step;
4191 int *maxi;
4192 int *nsame;
4193 int *ntick;
4194 int *pi;
4195 int bad;
4196 int iax;
4197 int ipp;
4198 int jax;
4199 int naxes;
4200 int np;
4201 int ntick0;
4202
4203 /* Initialise. */
4204 result = NULL;
4205
4206 /* Check the global error status. */
4207 if ( !astOK ) return result;
4208
4209 /* Get the number of axes in the Frame. */
4210 naxes = astGetNaxes( this );
4211
4212 /* Allocate an array to hold the number of ticks along each axis. */
4213 ntick = astMalloc( sizeof(int)*naxes );
4214
4215 /* Allocate an array to hold the geometric mean of the lengths of the
4216 axes that have the same units as the current axis. */
4217 gmean = astMalloc( naxes*sizeof(double) );
4218
4219 /* Allocate an array to hold the number of axes that share the same unit. */
4220 nsame = astMalloc( naxes*sizeof(int) );
4221 if( astOK ) {
4222
4223 /* For each axis, find the total number of axes in the Frame that have
4224 the same unit string. Also, find the product of the lengths of these
4225 axes. */
4226 bad = 0;
4227 for( iax = 0; iax < naxes; iax++ ) {
4228 nsame[ iax ] = 1;
4229
4230 if( ubnd[ iax ] == AST__BAD &&
4231 lbnd[ iax ] == AST__BAD ) {
4232 bad = 1;
4233 break;
4234 }
4235
4236 gmean[ iax ] = ubnd[ iax ] - lbnd[ iax ];
4237 unit = astGetUnit( this, iax );
4238 for( jax = 0; jax < naxes; jax++ ) {
4239 if( jax != iax ) {
4240 if( astOK && !strcmp( unit, astGetUnit( this, jax ) ) ) {
4241 nsame[ iax ]++;
4242 gmean[ iax ] *= ubnd[ jax ] - lbnd[ jax ];
4243 }
4244 }
4245 }
4246 }
4247
4248 /* Do nothing if any bad bounds were supplied, or if the size is less
4249 than 1. */
4250 if( !bad && size >= 1 ) {
4251
4252 /* Get the nominal number of ticks per axis. */
4253 ntick0 = pow( size, 1.0/(double)naxes );
4254 if( ntick0 < 2 ) ntick0 = 2;
4255
4256 /* Convert the dimension products into geometric means. */
4257 for( iax = 0; iax < naxes; iax++ ) {
4258 gmean[ iax ] = pow( fabs(gmean[ iax ]), 1.0/(double)nsame[ iax ] );
4259 }
4260
4261 /* The number of ticks to use on each axis is equal to the nominal number
4262 multiplied by the ratio of the axis length to the geometric mean of the
4263 axis lengths that sahare the same unit string. This gives more ticks
4264 on the longer axes within any group of common-unit axes, whilst
4265 retaining the overall number of ticks (roughly). Also find the total
4266 number of points. */
4267 np = 1;
4268 for( iax = 0; iax < naxes; iax++ ) {
4269 ntick[ iax ] = ntick0*( ubnd[ iax ] - lbnd[ iax ] )/gmean[ iax ];
4270 if( ntick[ iax ] < 2 ) ntick[ iax ] = 2;
4271 np *= ntick[ iax ];
4272 }
4273
4274 /* Create a PointSet large enough to hold this many points. */
4275 result = astPointSet( np, naxes, " ", status );
4276 ptr = astGetPoints( result );
4277
4278 /* Allocate memory to hold the max indices on each axis. */
4279 maxi = astMalloc( sizeof( int )*(size_t) naxes );
4280
4281 /* Allocate memory to hold the indices of the current position.*/
4282 pi = astMalloc( sizeof( int )*(size_t) naxes );
4283
4284 /* Allocate memory to hold the step size for each axis. */
4285 step = astMalloc( sizeof( double )*(size_t) naxes );
4286 if( astOK ) {
4287
4288 /* For every axis, set up the step size, initialise the current position to
4289 the lower bound, and store a modified upper limit which includes some
4290 safety marging to allow for rounding errors. */
4291 for( iax = 0; iax < naxes; iax++ ) {
4292 step[ iax ] = ( ubnd[ iax ] - lbnd[ iax ] )/( ntick[ iax ] - 1 );
4293 pi[ iax ] = 0;
4294 maxi[ iax ] = ntick[ iax ] - 1;
4295 }
4296
4297 /* Initialise the index of the next position to store. */
4298 ipp = 0;
4299
4300 /* Loop round adding points to the array until the whole volume has been
4301 done. */
4302 iax = 0;
4303 while( iax < naxes ) {
4304
4305 /* Add the current point to the supplied array, and increment the index of
4306 the next point to add. */
4307 for( iax = 0; iax < naxes; iax++ ) {
4308 ptr[ iax ][ ipp ] = lbnd[ iax ] + pi[ iax ]*step[ iax ];
4309 }
4310 ipp++;
4311
4312 /* We now move the current position on to the next sample */
4313 iax = 0;
4314 while( iax < naxes ) {
4315 pi[ iax ]++;
4316 if( pi[ iax ] > maxi[ iax ] ) {
4317 pi[ iax ] = 0;
4318 iax++;
4319 } else {
4320 break;
4321 }
4322 }
4323 }
4324 }
4325
4326 /* Free resources. */
4327 maxi = astFree( maxi );
4328 pi = astFree( pi );
4329 step = astFree( step );
4330
4331 /* Report error if supplied values were bad. */
4332 } else if( astOK ) {
4333 if( bad ) {
4334 astError( AST__ATTIN, "astFrameGrid(%s): One of more of the "
4335 "supplied bounds is AST__BAD (programming error).",
4336 status, astGetClass( this ) );
4337 } else if( size < 1 ) {
4338 astError( AST__ATTIN, "astFrameGrid(%s): The supplied grid "
4339 "size (%d) is invalid (programming error).",
4340 status, astGetClass( this ), size );
4341 }
4342 }
4343 }
4344
4345 /* Free resources. */
4346 ntick = astFree( ntick );
4347 nsame = astFree( nsame );
4348 gmean = astFree( gmean );
4349
4350 /* Annul the returned PointSet if an error has occurred. */
4351 if( !astOK ) result = astAnnul( result );
4352
4353 /* Return the PointSet holding the grid. */
4354 return result;
4355 }
4356
Gap(AstFrame * this,int axis,double gap,int * ntick,int * status)4357 static double Gap( AstFrame *this, int axis, double gap, int *ntick, int *status ) {
4358 /*
4359 *+
4360 * Name:
4361 * astGap
4362
4363 * Purpose:
4364 * Find a "nice" gap for tabulating Frame axis values.
4365
4366 * Type:
4367 * Protected virtual function.
4368
4369 * Synopsis:
4370 * #include "frame.h"
4371 * double astGap( AstFrame *this, int axis, double gap, int *ntick )
4372
4373 * Class Membership:
4374 * Frame method.
4375
4376 * Description:
4377 * This function returns a gap size which produces a nicely spaced
4378 * series of formatted values for a Frame axis, the returned gap
4379 * size being as close as possible to the supplied target gap
4380 * size. It also returns a convenient number of divisions into
4381 * which the gap can be divided.
4382
4383 * Parameters:
4384 * this
4385 * Pointer to the Frame.
4386 * axis
4387 * The number of the axis (zero-based) for which a gap is to be found.
4388 * gap
4389 * The target gap size.
4390 * ntick
4391 * Address of an int in which to return a convenient number of
4392 * divisions into which the gap can be divided.
4393
4394 * Returned Value:
4395 * The nice gap size.
4396
4397 * Notes:
4398 * - A value of zero is returned if the target gap size is zero.
4399 * - A negative gap size is returned if the supplied gap size is negative.
4400 * - A value of zero will be returned if this function is invoked
4401 * with the global error status set, or if it should fail for any
4402 * reason.
4403 *-
4404 */
4405
4406 /* Local Variables: */
4407 AstAxis *ax; /* Pointer to Axis object */
4408 double result; /* The nice gap value */
4409
4410 /* Check the global error status. */
4411 if ( !astOK ) return 0.0;
4412
4413 /* Validate the axis index and obtain a pointer to the required
4414 Axis. */
4415 (void) astValidateAxis( this, axis, 1, "astGap" );
4416 ax = astGetAxis( this, axis );
4417
4418 /* Find the gap. */
4419 result = astAxisGap( ax, gap, ntick );
4420
4421 /* Annul the Axis pointer. */
4422 ax = astAnnul( ax );
4423
4424 /* If an error occurred, clear the result value. */
4425 if ( !astOK ) result = 0.0;
4426
4427 /* Return the result. */
4428 return result;
4429 }
4430
GetActiveUnit(AstFrame * this,int * status)4431 static int GetActiveUnit( AstFrame *this, int *status ){
4432 /*
4433 *++
4434 * Name:
4435 c astGetActiveUnit
4436 f AST_GETACTIVEUNIT
4437
4438 * Purpose:
4439 * Determines how the Unit attribute will be used.
4440
4441 * Type:
4442 * Public virtual function.
4443
4444 * Synopsis:
4445 c #include "frame.h"
4446 c int astGetActiveUnit( AstFrame *this )
4447 f RESULT = AST_GETACTIVEUNIT( THIS, STATUS )
4448
4449 * Class Membership:
4450 * Frame method.
4451
4452 * Description:
4453 c This function
4454 f This routine
4455 * returns the current value of the ActiveUnit flag for a Frame. See
4456 c the description of the astSetActiveUnit function
4457 f the description of the AST_SETACTIVEUNIT routine
4458 * for a description of the ActiveUnit flag.
4459
4460 * Parameters:
4461 c this
4462 f THIS = INTEGER (Given)
4463 * Pointer to the Frame.
4464 f STATUS = INTEGER (Given and Returned)
4465 f The global status.
4466
4467 * Returned Value:
4468 c astGetActiveUnit
4469 f AST_GETACTIVEUNIT = LOGICAL
4470 * The current value of the ActiveUnit flag.
4471
4472 * Notes:
4473 c - A zero value will be returned if this function is
4474 c invoked with the AST error status set, or if it should fail for
4475 f - A value of .FALSE. will be returned if this function is
4476 f invoked with STATUS set to an error value, or if it should fail for
4477 * any reason.
4478 *--
4479 */
4480
4481 /* Local Variables: */
4482 AstAxis *ax; /* Pointer to axis structure */
4483 int i; /* Index of axis in Frame */
4484 int has_skyaxis; /* Does Frame contain any SkyAxes? */
4485 int nax; /* Number of axes in Frame */
4486 int result; /* The returned value */
4487
4488 /* Initialise. */
4489 result = 0;
4490
4491 /* Check the global error status. */
4492 if ( !astOK ) return result;
4493
4494 /* See if the Frame contains a SkyAxis. */
4495 has_skyaxis = 0;
4496 nax = astGetNaxes( this );
4497 for( i = 0; i < nax; i++ ) {
4498 ax = astGetAxis( this, i );
4499 if( astIsASkyAxis( ax ) ) has_skyaxis = 1;
4500 ax = astAnnul( ax );
4501 }
4502
4503 /* If the Frame contains a SkyAxis the ActiveUnit flag is always zero. */
4504 if( !has_skyaxis ) {
4505
4506 /* Otherwise, get the value from the Frame. If it has not yet been assigned a
4507 value return the value zero. */
4508 result = this->active_unit;
4509 if( result == -INT_MAX ) result = 0;
4510 }
4511
4512 /* Return the result. */
4513 return result;
4514 }
4515
GetAttrib(AstObject * this_object,const char * attrib,int * status)4516 static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) {
4517 /*
4518 * Name:
4519 * GetAttrib
4520
4521 * Purpose:
4522 * Get the value of a specified attribute for a Frame.
4523
4524 * Type:
4525 * Private function.
4526
4527 * Synopsis:
4528 * #include "frame.h"
4529 * const char *GetAttrib( AstObject *this, const char *attrib, int *status )
4530
4531 * Class Membership:
4532 * Frame member function (over-rides the protected astGetAttrib
4533 * method inherited from the Mapping class).
4534
4535 * Description:
4536 * This function returns a pointer to the value of a specified
4537 * attribute for a Frame, formatted as a character string.
4538
4539 * Parameters:
4540 * this
4541 * Pointer to the Frame.
4542 * attrib
4543 * Pointer to a null-terminated string containing the name of
4544 * the attribute whose value is required. This name should be in
4545 * lower case, with all white space removed.
4546 * status
4547 * Pointer to the inherited status variable.
4548
4549 * Returned Value:
4550 * - Pointer to a null-terminated string containing the attribute
4551 * value.
4552
4553 * Notes:
4554 * - This function uses one-based axis numbering so that it is
4555 * suitable for external (public) use.
4556 * - The returned string pointer may point at memory allocated
4557 * within the Frame, or at static memory. The contents of the
4558 * string may be over-written or the pointer may become invalid
4559 * following a further invocation of the same function or any
4560 * modification of the Frame. A copy of the string should
4561 * therefore be made if necessary.
4562 * - A NULL pointer will be returned if this function is invoked
4563 * with the global error status set, or if it should fail for any
4564 * reason.
4565 */
4566
4567 /* Local Variables: */
4568 astDECLARE_GLOBALS /* Declare the thread specific global data */
4569 AstAxis *ax; /* Pointer to Axis */
4570 AstFrame *pfrm; /* Pointer to primary Frame containing axis */
4571 AstFrame *this; /* Pointer to the Frame structure */
4572 AstSystemType system; /* System code */
4573 char pfrm_attrib[ 100 ]; /* Primary Frame attribute */
4574 char *axis_attrib; /* Pointer to axis attribute name */
4575 const char *old_attrib; /* Pointer to supplied attribute name string */
4576 const char *result; /* Pointer value to return */
4577 double dval; /* Double attibute value */
4578 double epoch; /* Epoch attribute value (as MJD) */
4579 int axis; /* Frame axis number */
4580 int axis_nc; /* No. characters in axis attribute name */
4581 int digits; /* Digits attribute value */
4582 int direction; /* Direction attribute value */
4583 int free_axis_attrib; /* Should axis_attrib be freed? */
4584 int has_axis; /* Does attrib name include axis specifier? */
4585 int len; /* Length of attrib string */
4586 int match_end; /* MatchEnd attribute value */
4587 int max_axes; /* MaxAxes attribute value */
4588 int min_axes; /* MinAxes attribute value */
4589 int naxes; /* Naxes attribute value */
4590 int nc; /* No. characters read by astSscanf */
4591 int oldrep; /* Original error reporting state */
4592 int paxis; /* Axis index within primary frame */
4593 int permute; /* Permute attribute value */
4594 int preserve_axes; /* PreserveAxes attribute value */
4595 int used; /* Could the setting string be used? */
4596
4597 /* Initialise. */
4598 result = NULL;
4599
4600 /* Check the global error status. */
4601 if ( !astOK ) return result;
4602
4603 /* Get a pointer to the structure holding thread-specific global data. */
4604 astGET_GLOBALS(this_object);
4605
4606 /* Obtain a pointer to the Frame structure. */
4607 this = (AstFrame *) this_object;
4608
4609 /* Set a flag indicating if the attribute name includes an axis
4610 specifier. */
4611 has_axis = ( strchr( attrib, '(' ) != NULL );
4612
4613 /* A flag indicating that we do not need to free the axis_attrib memory. */
4614 free_axis_attrib = 0;
4615
4616 /* Initialise things to avoid compiler warnings. */
4617 axis_attrib = NULL;
4618 old_attrib = NULL;
4619
4620 /* Jump back to here if we are trying the same attribute but with an explicit
4621 axis "(1)" added to the end of the name. */
4622 L1:
4623
4624 /* Obtain the length of the attrib string. */
4625 len = strlen( attrib );
4626
4627 /* Save the number of axes in the Frame for later use. */
4628 naxes = astGetNaxes( this );
4629
4630 /* Compare "attrib" with each recognised attribute name in turn,
4631 obtaining the value of the required attribute. If necessary, write
4632 the value into "getattrib_buff" as a null-terminated string in an appropriate
4633 format. Set "result" to point at the result string. */
4634
4635 /* Digits. */
4636 /* ------- */
4637 if ( !strcmp( attrib, "digits" ) ) {
4638 digits = astGetDigits( this );
4639 if ( astOK ) {
4640 (void) sprintf( getattrib_buff, "%d", digits );
4641 result = getattrib_buff;
4642 }
4643
4644 /* Digits(axis). */
4645 /* ------------- */
4646 } else if ( nc = 0,
4647 ( 1 == astSscanf( attrib, "digits(%d)%n", &axis, &nc ) )
4648 && ( nc >= len ) ) {
4649
4650 /* There is no function to obtain the Digits attribute value for an
4651 axis directly, so obtain a pointer to the Axis and use this to
4652 obtain the value. Use the Frame's Digits attribute instead if the
4653 Axis attribute value is not set. */
4654 (void) astValidateAxis( this, axis - 1, 1, "astGetDigits(axis)" );
4655 ax = astGetAxis( this, axis - 1 );
4656 if ( astTestAxisDigits( ax ) ) {
4657 digits = astGetAxisDigits( ax );
4658 } else {
4659 digits = astGetDigits( this );
4660 }
4661 ax = astAnnul( ax );
4662 if ( astOK ) {
4663 (void) sprintf( getattrib_buff, "%d", digits );
4664 result = getattrib_buff;
4665 }
4666
4667
4668 /* Direction(axis). */
4669 /* ---------------- */
4670 } else if ( nc = 0,
4671 ( 1 == astSscanf( attrib, "direction(%d)%n", &axis, &nc ) )
4672 && ( nc >= len ) ) {
4673 direction = astGetDirection( this, axis - 1 );
4674 if ( astOK ) {
4675 (void) sprintf( getattrib_buff, "%d", direction );
4676 result = getattrib_buff;
4677 }
4678
4679 /* Epoch. */
4680 /* ------ */
4681 } else if ( !strcmp( attrib, "epoch" ) ) {
4682 epoch = astGetEpoch( this );
4683 if ( astOK ) {
4684
4685 /* Format the Epoch as decimal years. Use a Besselian epoch if it will
4686 be less than 1984.0, otherwise use a Julian epoch. */
4687 result = astFmtDecimalYr( ( epoch < palEpj2d( 1984.0 ) ) ?
4688 palEpb( epoch ) : palEpj( epoch ), DBL_DIG );
4689 }
4690
4691 /* Top(axis). */
4692 /* ---------- */
4693 } else if ( nc = 0,
4694 ( 1 == astSscanf( attrib, "top(%d)%n", &axis, &nc ) )
4695 && ( nc >= len ) ) {
4696 dval = astGetTop( this, axis -1 );
4697 if ( astOK ) {
4698 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
4699 result = getattrib_buff;
4700 }
4701
4702 /* Bottom(axis). */
4703 /* ---------- */
4704 } else if ( nc = 0,
4705 ( 1 == astSscanf( attrib, "bottom(%d)%n", &axis, &nc ) )
4706 && ( nc >= len ) ) {
4707 dval = astGetBottom( this, axis -1 );
4708 if ( astOK ) {
4709 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
4710 result = getattrib_buff;
4711 }
4712
4713 /* Domain. */
4714 /* ------- */
4715 } else if ( !strcmp( attrib, "domain" ) ) {
4716 result = astGetDomain( this );
4717
4718 /* Format(axis). */
4719 /* ------------- */
4720 } else if ( nc = 0,
4721 ( 1 == astSscanf( attrib, "format(%d)%n", &axis, &nc ) )
4722 && ( nc >= len ) ) {
4723 result = astGetFormat( this, axis - 1 );
4724
4725 /* Label(axis). */
4726 /* ------------ */
4727 } else if ( nc = 0,
4728 ( 1 == astSscanf( attrib, "label(%d)%n", &axis, &nc ) )
4729 && ( nc >= len ) ) {
4730 result = astGetLabel( this, axis - 1 );
4731
4732 /* MatchEnd. */
4733 /* --------- */
4734 } else if ( !strcmp( attrib, "matchend" ) ) {
4735 match_end = astGetMatchEnd( this );
4736 if ( astOK ) {
4737 (void) sprintf( getattrib_buff, "%d", match_end );
4738 result = getattrib_buff;
4739 }
4740
4741 /* MaxAxes. */
4742 /* -------- */
4743 } else if ( !strcmp( attrib, "maxaxes" ) ) {
4744 max_axes = astGetMaxAxes( this );
4745 if ( astOK ) {
4746 (void) sprintf( getattrib_buff, "%d", max_axes );
4747 result = getattrib_buff;
4748 }
4749
4750 /* MinAxes. */
4751 /* -------- */
4752 } else if ( !strcmp( attrib, "minaxes" ) ) {
4753 min_axes = astGetMinAxes( this );
4754 if ( astOK ) {
4755 (void) sprintf( getattrib_buff, "%d", min_axes );
4756 result = getattrib_buff;
4757 }
4758
4759 /* Naxes. */
4760 /* -----_ */
4761 } else if ( !strcmp( attrib, "naxes" ) ) {
4762 (void) sprintf( getattrib_buff, "%d", naxes );
4763 result = getattrib_buff;
4764
4765 /* Permute. */
4766 /* -------- */
4767 } else if ( !strcmp( attrib, "permute" ) ) {
4768 permute = astGetPermute( this );
4769 if ( astOK ) {
4770 (void) sprintf( getattrib_buff, "%d", permute );
4771 result = getattrib_buff;
4772 }
4773
4774 /* PreserveAxes. */
4775 /* ------------- */
4776 } else if ( !strcmp( attrib, "preserveaxes" ) ) {
4777 preserve_axes = astGetPreserveAxes( this );
4778 if ( astOK ) {
4779 (void) sprintf( getattrib_buff, "%d", preserve_axes );
4780 result = getattrib_buff;
4781 }
4782
4783 /* Symbol(axis). */
4784 /* ------------- */
4785 } else if ( nc = 0,
4786 ( 1 == astSscanf( attrib, "symbol(%d)%n", &axis, &nc ) )
4787 && ( nc >= len ) ) {
4788 result = astGetSymbol( this, axis - 1 );
4789
4790 /* AlignSystem. */
4791 /* ------------ */
4792 /* Obtain the AlignSystem code and convert to a string. */
4793 } else if ( !strcmp( attrib, "alignsystem" ) ) {
4794 system = astGetAlignSystem( this );
4795 if ( astOK ) {
4796 result = astSystemString( this, system );
4797
4798 /* Report an error if the value was not recognised. */
4799 if ( !result ) {
4800 astError( AST__SCSIN,
4801 "astGetAttrib(%s): Corrupt %s contains invalid "
4802 "AlignSystem identification code (%d).", status,
4803 astGetClass( this ), astGetClass( this ), (int) system );
4804 }
4805 }
4806
4807 /* System. */
4808 /* ------- */
4809 /* Obtain the System code and convert to a string. */
4810 } else if ( !strcmp( attrib, "system" ) ) {
4811 system = astGetSystem( this );
4812 if ( astOK ) {
4813 result = astSystemString( this, system );
4814
4815 /* Report an error if the value was not recognised. */
4816 if ( !result ) {
4817 astError( AST__SCSIN,
4818 "astGetAttrib(%s): Corrupt %s contains invalid "
4819 "System identification code (%d).", status,
4820 astGetClass( this ), astGetClass( this ), (int) system );
4821 }
4822 }
4823
4824 /* Title. */
4825 /* ------ */
4826 } else if ( !strcmp( attrib, "title" ) ) {
4827 result = astGetTitle( this );
4828
4829 /* Unit(axis). */
4830 /* ----------- */
4831 } else if ( nc = 0,
4832 ( 1 == astSscanf( attrib, "unit(%d)%n", &axis, &nc ) )
4833 && ( nc >= len ) ) {
4834 result = astGetUnit( this, axis - 1 );
4835
4836 /* NormUnit(axis). */
4837 /* --------------- */
4838 } else if ( nc = 0,
4839 ( 1 == astSscanf( attrib, "normunit(%d)%n", &axis, &nc ) )
4840 && ( nc >= len ) ) {
4841 result = astGetNormUnit( this, axis - 1 );
4842
4843 /* ObsLat. */
4844 /* ------- */
4845 } else if ( !strcmp( attrib, "obslat" ) ) {
4846 dval = astGetObsLat( this );
4847 if ( astOK ) {
4848
4849 /* If not already created, create an FK5 J2000 SkyFrame which will be used
4850 for formatting and unformatting ObsLon and ObsLat values. */
4851 if( !skyframe ) {
4852 astBeginPM;
4853 skyframe = astSkyFrame("system=FK5,equinox=J2000,format(2)=dms.2", status );
4854 astEndPM;
4855 }
4856
4857 /* Display absolute value preceded by "N" or "S" as appropriate. */
4858 if( dval < 0 ) {
4859 (void) sprintf( getattrib_buff, "S%s", astFormat( skyframe, 1, -dval ) );
4860 } else {
4861 (void) sprintf( getattrib_buff, "N%s", astFormat( skyframe, 1, dval ) );
4862 }
4863 result = getattrib_buff;
4864 }
4865
4866 /* ObsLon. */
4867 /* ------- */
4868 } else if ( !strcmp( attrib, "obslon" ) ) {
4869 dval = astGetObsLon( this );
4870 if ( astOK ) {
4871
4872 /* Put into range +/- PI. */
4873 dval = palDrange( dval );
4874
4875 /* If not already created, create an FK5 J2000 SkyFrame which will be used
4876 for formatting and unformatting ObsLon and ObsLat values. */
4877 if( !skyframe ) {
4878 astBeginPM;
4879 skyframe = astSkyFrame( "system=FK5,equinox=J2000,format(2)=dms.2", status );
4880 astEndPM;
4881 }
4882
4883 /* Display absolute value preceded by "E" or "W" as appropriate. */
4884 if( dval < 0 ) {
4885 (void) sprintf( getattrib_buff, "W%s", astFormat( skyframe, 1, -dval ) );
4886 } else {
4887 (void) sprintf( getattrib_buff, "E%s", astFormat( skyframe, 1, dval ) );
4888 }
4889 result = getattrib_buff;
4890
4891 }
4892
4893 /* ObsAlt. */
4894 /* ------- */
4895 } else if ( !strcmp( attrib, "obsalt" ) ) {
4896 dval = astGetObsAlt( this );
4897 if ( astOK ) {
4898 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
4899 result = getattrib_buff;
4900 }
4901
4902 /* Dut1. */
4903 /* ---- */
4904 } else if ( !strcmp( attrib, "dut1" ) ) {
4905 dval = astGetDut1( this );
4906 if ( astOK ) {
4907 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
4908 result = getattrib_buff;
4909 }
4910
4911 /* Other axis attributes. */
4912 /* ---------------------- */
4913 /* If the attribute was not identified above, but appears to refer to
4914 a Frame axis, then it may refer to an Axis object of a derived type
4915 (which has additional attributes not recognised here). */
4916 } else if ( !free_axis_attrib && ( nc = 0,
4917 ( 1 == astSscanf( attrib, "%*[^()]%n(%d)%n",
4918 &axis_nc, &axis, &nc ) )
4919 && ( nc >= len ) ) ) {
4920
4921 /* Validate the axis index and extract the attribute name. */
4922 (void) astValidateAxis( this, axis - 1, 1, "astGet" );
4923 axis_attrib = astString( attrib, axis_nc );
4924
4925 /* Obtain a pointer to the Axis object. */
4926 ax = astGetAxis( this, axis - 1 );
4927 if( astOK ) {
4928
4929 /* Assume that we will be able to use the attribute name. */
4930 used = 1;
4931
4932 /* Temporarily switch off error reporting so that if the following attempt
4933 to access the axis attribute fails, we can try to interpret the
4934 attribute name as an attribute of the primary Frame containing the
4935 specified axis. Any errors reported in this context will simply be
4936 ignored, in particularly they are not deferred for later delivery. */
4937 oldrep = astReporting( 0 );
4938
4939 /* Use the Axis astGetAttrib method to obtain the result. */
4940 result = astGetAttrib( ax, axis_attrib );
4941
4942 /* If the above call failed with a status of AST__BADAT, indicating that
4943 the attribute name was not recognised, clear the status so that we can
4944 try to interpret the attribute name as an attribute of the primary Frame
4945 containing the specified axis. */
4946 if( astStatus == AST__BADAT ) {
4947 astClearStatus;
4948
4949 /* Find the primary Frame containing the specified axis. */
4950 astPrimaryFrame( this, axis - 1, &pfrm, &paxis );
4951
4952 /* Only attempt to use the primary Frame if it is not the same as "this"
4953 - otherwise we could end up in an infinite loop. */
4954 if( pfrm != this ) {
4955
4956 /* astPrimaryFrame returns the original - unpermuted - axis index within
4957 the primary Frame. So we need to take into account any axis permutation
4958 which has been applied to the primary Frame when forming the attribute name
4959 to use below. Find the permuted (external) axis index which corresponds to
4960 the internal (unpermuted) axis index "paxis". */
4961 paxis = astValidateAxis( pfrm, paxis, 0, "astGet" );
4962
4963 /* Modify the attribute name to refer to the axis numbering of the
4964 primary frame. */
4965 sprintf( pfrm_attrib, "%s(%d)", axis_attrib, paxis + 1 );
4966
4967 /* Attempt to use the Axis astGetAttrib method to obtain the result. */
4968 result = astGetAttrib( pfrm, pfrm_attrib );
4969
4970 /* If this failed, clear the status and indicate that we have not managed to
4971 use the attribute name. */
4972 if( !astOK ) {
4973 astClearStatus;
4974 used = 0;
4975 }
4976
4977 } else {
4978 used = 0;
4979 }
4980
4981 /* If not found attempt to get the attribute value from the Axis, omitting
4982 the axis index. */
4983 if( ! used ) {
4984 result = astGetAttrib( pfrm, axis_attrib );
4985 if( !astOK ) {
4986 astClearStatus;
4987 } else {
4988 used = 1;
4989 }
4990 }
4991
4992 /* Annul the primary Frame pointer. */
4993 pfrm = astAnnul( pfrm );
4994 }
4995
4996 /* Re-instate the original error reporting state. */
4997 astReporting( oldrep );
4998
4999 /* If we could not use the attribute name, attempt to get the axis
5000 attribute again, this time retaining the error report. This is done
5001 to ensure the user gets an appropriate error message. */
5002 if( !used ) result = astGetAttrib( ax, axis_attrib );
5003 }
5004
5005 /* Annul the Axis pointer and free the memory holding the attribute
5006 name. */
5007 ax = astAnnul( ax );
5008 axis_attrib = astFree( axis_attrib );
5009
5010 /* Not recognised. */
5011 /* --------------- */
5012 /* If the attribute is still not recognised, and the Frame has only 1 axis,
5013 and the attribute name does not already include an axis specifier, try
5014 again after appending "(1)" to the end of the attribute name. */
5015 } else if( !has_axis && naxes == 1 ) {
5016
5017 /* Take a copy of the supplied name, allowing 3 extra characters for the
5018 axis specifier "(1)". */
5019 axis_attrib = astMalloc( len + 4 );
5020 if( axis_attrib ) memcpy( axis_attrib, attrib, len );
5021
5022 /* Indicate we should free the axis_attrib memory. */
5023 free_axis_attrib = 1;
5024
5025 /* Add in the axis specifier. */
5026 strcpy( axis_attrib + len, "(1)" );
5027
5028 /* Use the new attribute name instead of the supplied name. */
5029 old_attrib = attrib;
5030 attrib = axis_attrib;
5031
5032 /* Indicate the attribute name now has an axis specifier. */
5033 has_axis = 1;
5034
5035 /* Jump back to try interpreting the new attribute name. */
5036 goto L1;
5037
5038 /* Not recognised. */
5039 /* --------------- */
5040 /* If the attribute name is still not recognised, pass it on to the parent
5041 method for further interpretation. First re-instate the original attrib
5042 name string if it was changed above. */
5043 } else {
5044 if( free_axis_attrib ) {
5045 attrib = old_attrib;
5046 axis_attrib = astFree( axis_attrib );
5047 }
5048 result = (*parent_getattrib)( this_object, attrib, status );
5049 }
5050
5051 /* Return the result. */
5052 return result;
5053 }
5054
GetAxis(AstFrame * this,int axis,int * status)5055 static AstAxis *GetAxis( AstFrame *this, int axis, int *status ) {
5056 /*
5057 *+
5058 * Name:
5059 * astGetAxis
5060
5061 * Purpose:
5062 * Obtain a pointer to a specified Axis from a Frame.
5063
5064 * Type:
5065 * Protected virtual function.
5066
5067 * Synopsis:
5068 * #include "frame.h"
5069 * AstAxis *astGetAxis( AstFrame *this, int axis )
5070
5071 * Class Membership:
5072 * Frame method.
5073
5074 * Description:
5075 * This function returns a pointer to the Axis object associated
5076 * with one of the axes of a Frame. This object describes the
5077 * quantity which is represented along that axis.
5078
5079 * Parameters:
5080 * this
5081 * Pointer to the Frame.
5082 * axis
5083 * The number of the axis (zero-based) for which an Axis pointer is
5084 * required.
5085
5086 * Returned Value:
5087 * A pointer to the requested Axis object.
5088
5089 * Notes:
5090 * - The reference count of the requested Axis object will be
5091 * incremented by one to reflect the additional pointer returned by
5092 * this function.
5093 * - A NULL pointer will be returned if this function is invoked
5094 * with the global error status set, or if it should fail for any
5095 * reason.
5096 *-
5097 */
5098
5099 /* Local Variables: */
5100 AstAxis *result; /* Pointer to Axis */
5101
5102 /* Check the global error status. */
5103 if ( !astOK ) return NULL;
5104
5105 /* Initialise. */
5106 result = NULL;
5107
5108 /* Validate and permute the axis index. */
5109 axis = astValidateAxis( this, axis, 1, "astGetAxis" );
5110
5111 /* If OK, clone the required Axis pointer. */
5112 if ( astOK ) result = astClone( this->axis[ axis ] );
5113
5114 /* Return the result. */
5115 return result;
5116 }
5117
GetDefaultLabel(int axis,int * status)5118 static const char *GetDefaultLabel( int axis, int *status ) {
5119 /*
5120 * Name:
5121 * GetDefaultLabel
5122
5123 * Purpose:
5124 * Return a pointer to a default axis Label string.
5125
5126 * Type:
5127 * Private function.
5128
5129 * Synopsis:
5130 * #include "frame.h"
5131 * const char *GetDefaultLabel( int axis, int *status )
5132
5133 * Class Membership:
5134 * Frame member function
5135
5136 * Description:
5137 * This function returns a pointer to a string holding a default axis
5138 * Label value.
5139
5140 * Parameters:
5141 * axis
5142 * Zero based axis index.
5143 * status
5144 * Pointer to the inherited status variable.
5145
5146 * Returned Value:
5147 * - Pointer to a static null-terminated string containing the attribute
5148 * value.
5149
5150 */
5151
5152 /* Local Variables: */
5153 astDECLARE_GLOBALS /* Declare the thread specific global data */
5154
5155 /* Get a pointer to the structure holding thread-specific global data. */
5156 astGET_GLOBALS(NULL);
5157
5158 /* Format the axis index, putting the string in a global buffer. */
5159 (void) sprintf( label_buff, "Axis %d", axis + 1 );
5160
5161 /* Return a pointer to the global buffer. */
5162 return label_buff;
5163 }
5164
GetDefaultSymbol(AstFrame * this,int axis,int * status)5165 static const char *GetDefaultSymbol( AstFrame *this, int axis, int *status ) {
5166 /*
5167 * Name:
5168 * GetDefaultSymbol
5169
5170 * Purpose:
5171 * Return a pointer to a default axis Symbol string.
5172
5173 * Type:
5174 * Private function.
5175
5176 * Synopsis:
5177 * #include "frame.h"
5178 * const char *GetDefaultSymbol( AstFrame *this, int axis, int *status )
5179
5180 * Class Membership:
5181 * Frame member function
5182
5183 * Description:
5184 * This function returns a pointer to a string holding a default axis
5185 * Symbol value.
5186
5187 * Parameters:
5188 * this
5189 * Pointer to the Frame.
5190 * axis
5191 * Zero based axis index.
5192 * status
5193 * Pointer to the inherited status variable.
5194
5195 * Returned Value:
5196 * - Pointer to a static null-terminated string containing the attribute
5197 * value.
5198
5199 */
5200
5201 /* Local Variables: */
5202 astDECLARE_GLOBALS /* Declare the thread specific global data */
5203
5204 /* Get a pointer to the structure holding thread-specific global data. */
5205 astGET_GLOBALS(this);
5206
5207 /* Note we use "sprintf" once to determine how many characters are
5208 produced by the "%d" format string and then limit the number of
5209 characters used from the Domain string in the second invocation of
5210 "sprintf" so that the total length of the default Symbol string
5211 does not exceed SYMBOL_BUFF_LEN characters. */
5212 (void) sprintf( symbol_buff, "%.*s%d",
5213 SYMBOL_BUFF_LEN - sprintf( symbol_buff, "%d", axis + 1 ),
5214 astTestDomain( this ) ? astGetDomain( this ) : "x",
5215 axis + 1 );
5216
5217 /* Use the AddUnderscores function to replace any white space in the Symbol
5218 string with underscore characters. */
5219 AddUnderscores( symbol_buff, status );
5220
5221 /* Return a pointer to the global buffer. */
5222 return symbol_buff;
5223 }
5224
GetDefaultTitle(AstFrame * this,int * status)5225 static const char *GetDefaultTitle( AstFrame *this, int *status ) {
5226 /*
5227 * Name:
5228 * GetDefaultTitle
5229
5230 * Purpose:
5231 * Return a pointer to a default Title string.
5232
5233 * Type:
5234 * Private function.
5235
5236 * Synopsis:
5237 * #include "frame.h"
5238 * const char *GetDefaultTitle( AstFrame *this, int *status )
5239
5240 * Class Membership:
5241 * Frame member function
5242
5243 * Description:
5244 * This function returns a pointer to a string holding a default Title value.
5245
5246 * Parameters:
5247 * this
5248 * Pointer to the Frame.
5249 * status
5250 * Pointer to the inherited status variable.
5251
5252 * Returned Value:
5253 * - Pointer to a static null-terminated string containing the attribute
5254 * value.
5255
5256 */
5257
5258 /* Local Variables: */
5259 astDECLARE_GLOBALS /* Declare the thread specific global data */
5260
5261 /* Get a pointer to the structure holding thread-specific global data. */
5262 astGET_GLOBALS(this);
5263
5264 /* Create the Title value and put it in the global buffer. */
5265 (void) sprintf( title_buff, "%d-d coordinate system", astGetNaxes( this ) );
5266
5267 /* Return a pointer to the global buffer. */
5268 return title_buff;
5269 }
5270
GetFrameFlags(AstFrame * this,int * status)5271 static int GetFrameFlags( AstFrame *this, int *status ){
5272 /*
5273 *+
5274 * Name:
5275 * astGetFrameFlags
5276
5277 * Purpose:
5278 * Return the bit mask of flags associated with a Frame.
5279
5280 * Type:
5281 * Protected function.
5282
5283 * Synopsis:
5284 * #include "frame.h"
5285 * int *astGetFrameFlags( astFrame *this )
5286
5287 * Class Membership:
5288 * Frame virtual function.
5289
5290 * Description:
5291 * This function returns a bit mask holding the current set of flags
5292 * associated with a Frame. See astSetFrameFlags for details of these
5293 * flags.
5294
5295 * Parameters:
5296 * this
5297 * The Frame.
5298
5299 * Returned Value:
5300 * The bit mask.
5301
5302 * Notes:
5303 * - Zero is returned if this function is invoked with
5304 * the global error status set or if it should fail for any reason.
5305 *-
5306 */
5307
5308 /* Check the global error status. */
5309 if ( !astOK ) return 0;
5310
5311 /* Return the result. */
5312 return this->flags;
5313 }
5314
GetIsLinear(AstMapping * this_mapping,int * status)5315 static int GetIsLinear( AstMapping *this_mapping, int *status ){
5316 /*
5317 * Name:
5318 * GetIsLinear
5319
5320 * Purpose:
5321 * Return the value of the IsLinear attribute for a Frame.
5322
5323 * Type:
5324 * Private function.
5325
5326 * Synopsis:
5327 * #include "mapping.h"
5328 * void GetIsLinear( AstMapping *this, int *status )
5329
5330 * Class Membership:
5331 * Frame member function (over-rides the protected astGetIsLinear
5332 * method inherited from the Mapping class).
5333
5334 * Description:
5335 * This function returns the value of the IsLinear attribute for a
5336 * Frame, which is always one because a Frame is treated like a UnitMap.
5337
5338 * Parameters:
5339 * this
5340 * Pointer to the Frame.
5341 * status
5342 * Pointer to the inherited status variable.
5343 */
5344 return 1;
5345 }
5346
GetIsSimple(AstMapping * this_mapping,int * status)5347 static int GetIsSimple( AstMapping *this_mapping, int *status ){
5348 /*
5349 * Name:
5350 * GetIsSimple
5351
5352 * Purpose:
5353 * Return the value of the IsSimple attribute for a Frame.
5354
5355 * Type:
5356 * Private function.
5357
5358 * Synopsis:
5359 * #include "mapping.h"
5360 * void GetIsSimple( AstMapping *this, int *status )
5361
5362 * Class Membership:
5363 * Frame member function (over-rides the protected astGetIsSimple
5364 * method inherited from the Mapping class).
5365
5366 * Description:
5367 * This function returns the value of the IsSimple attribute for a
5368 * Frame, which is always zero because Frames are not immutable (unlike
5369 * non-Frame Mappings).
5370
5371 * Parameters:
5372 * this
5373 * Pointer to the Frame.
5374 * status
5375 * Pointer to the inherited status variable.
5376 */
5377 return 0;
5378 }
5379
GetNaxes(AstFrame * this,int * status)5380 static int GetNaxes( AstFrame *this, int *status ) {
5381 /*
5382 *+
5383 * Name:
5384 * astGetNaxes
5385
5386 * Purpose:
5387 * Determine how many axes a Frame has.
5388
5389 * Type:
5390 * Protected virtual function.
5391
5392 * Synopsis:
5393 * #include "frame.h"
5394 * int astGetNaxes( AstFrame *this )
5395
5396 * Class Membership:
5397 * Frame method.
5398
5399 * Description:
5400 * This function returns the number of axes for a Frame.
5401
5402 * Parameters:
5403 * this
5404 * Pointer to the Frame.
5405
5406 * Returned Value:
5407 * The number of Frame axes.
5408
5409 * Notes:
5410 * - A value of zero will be returned if this function is invoked
5411 * with the global error status set, or if it should fail for any
5412 * reason.
5413 *-
5414 */
5415
5416 /* Check the global error status. */
5417 if ( !astOK ) return 0;
5418
5419 /* Return the number of Frame axes. */
5420 return this->naxes;
5421 }
5422
GetNin(AstMapping * this_mapping,int * status)5423 static int GetNin( AstMapping *this_mapping, int *status ) {
5424 /*
5425 * Name:
5426 * GetNin
5427
5428 * Purpose:
5429 * Get the number of input coordinates for a Frame.
5430
5431 * Type:
5432 * Private function.
5433
5434 * Synopsis:
5435 * #include "frame.h"
5436 * int GetNin( AstMapping *this, int *status )
5437
5438 * Class Membership:
5439 * Frame member function (over-rides the astGetNin method inherited
5440 * from the Mapping class).
5441
5442 * Description:
5443 * This function returns the number of input coordinate values
5444 * required per point by a Frame, when used as a Mapping (i.e. the
5445 * number of dimensions of the space in which input points reside).
5446
5447 * Parameters:
5448 * this
5449 * Pointer to the Frame.
5450 * status
5451 * Pointer to the inherited status variable.
5452
5453 * Returned Value:
5454 * Number of coordinate values required.
5455
5456 * Notes:
5457 * - A value of zero will be returned if this function is invoked
5458 * with the global error status set, or if it should fail for any
5459 * reason.
5460 */
5461
5462 /* Local Variables: */
5463 AstFrame *this; /* Pointer to Frame structure */
5464 int result; /* Result value to return */
5465
5466 /* Initialise. */
5467 result = 0;
5468
5469 /* Check the global error status. */
5470 if ( !astOK ) return result;
5471
5472 /* Obtain a pointer to the Frame structure. */
5473 this = (AstFrame *) this_mapping;
5474
5475 /* Return the number of Frame axes. */
5476 result = astGetNaxes( this );
5477
5478 /* Return the result. */
5479 return result;
5480 }
5481
GetNout(AstMapping * this_mapping,int * status)5482 static int GetNout( AstMapping *this_mapping, int *status ) {
5483 /*
5484 * Name:
5485 * GetNout
5486
5487 * Purpose:
5488 * Get the number of output coordinates for a Frame.
5489
5490 * Type:
5491 * Private function.
5492
5493 * Synopsis:
5494 * #include "frame.h"
5495 * int GetNout( AstMapping *this, int *status )
5496
5497 * Class Membership:
5498 * Frame member function (over-rides the astGetNout method
5499 * inherited from the Mapping class).
5500
5501 * Description:
5502 * This function returns the number of output coordinate values
5503 * generated per point by a Frame, when used as a Mapping (i.e. the
5504 * number of dimensions of the space in which output points
5505 * reside).
5506
5507 * Parameters:
5508 * this
5509 * Pointer to the Frame.
5510 * status
5511 * Pointer to the inherited status variable.
5512
5513 * Returned Value:
5514 * Number of coordinate values generated.
5515
5516 * Notes:
5517 * - A value of zero will be returned if this function is invoked
5518 * with the global error status set, or if it should fail for any
5519 * reason.
5520 */
5521
5522 /* Local Variables: */
5523 AstFrame *this; /* Pointer to Frame structure */
5524 int result; /* Result value to return */
5525
5526 /* Initialise. */
5527 result = 0;
5528
5529 /* Check the global error status. */
5530 if ( !astOK ) return result;
5531
5532 /* Obtain a pointer to the Frame structure. */
5533 this = (AstFrame *) this_mapping;
5534
5535 /* Return the number of Frame axes. */
5536 result = astGetNaxes( this );
5537
5538 /* Return the result. */
5539 return result;
5540 }
5541
GetObjSize(AstObject * this_object,int * status)5542 static int GetObjSize( AstObject *this_object, int *status ) {
5543 /*
5544 * Name:
5545 * GetObjSize
5546
5547 * Purpose:
5548 * Return the in-memory size of an Object.
5549
5550 * Type:
5551 * Private function.
5552
5553 * Synopsis:
5554 * #include "frame.h"
5555 * int GetObjSize( AstObject *this, int *status )
5556
5557 * Class Membership:
5558 * Frame member function (over-rides the astGetObjSize protected
5559 * method inherited from the parent class).
5560
5561 * Description:
5562 * This function returns the in-memory size of the supplied Frame,
5563 * in bytes.
5564
5565 * Parameters:
5566 * this
5567 * Pointer to the Frame.
5568 * status
5569 * Pointer to the inherited status variable.
5570
5571 * Returned Value:
5572 * The Object size, in bytes.
5573
5574 * Notes:
5575 * - A value of zero will be returned if this function is invoked
5576 * with the global status set, or if it should fail for any reason.
5577 */
5578
5579 /* Local Variables: */
5580 AstFrame *this; /* Pointer to Frame structure */
5581 int axis; /* Axis index */
5582 int result; /* Result value to return */
5583
5584 /* Initialise. */
5585 result = 0;
5586
5587 /* Check the global error status. */
5588 if ( !astOK ) return result;
5589
5590 /* Obtain a pointers to the FrameSet structure. */
5591 this = (AstFrame *) this_object;
5592
5593 /* Invoke the GetObjSize method inherited from the parent class, and then
5594 add on any components of the class structure defined by this class
5595 which are stored in dynamically allocated memory. */
5596 result = (*parent_getobjsize)( this_object, status );
5597 result += astGetObjSize( this->variants );
5598 result += astTSizeOf( this->domain );
5599 result += astTSizeOf( this->title );
5600 result += astTSizeOf( this->axis );
5601 result += astTSizeOf( this->perm );
5602
5603 for ( axis = 0; axis < this->naxes; axis++ ) {
5604 result += astGetObjSize( this->axis[ axis ] );
5605 }
5606
5607 /* If an error occurred, clear the result value. */
5608 if ( !astOK ) result = 0;
5609
5610 /* Return the result, */
5611 return result;
5612 }
5613
GetPerm(AstFrame * this,int * status)5614 static const int *GetPerm( AstFrame *this, int *status ) {
5615 /*
5616 *+
5617 * Name:
5618 * astGetPerm
5619
5620 * Purpose:
5621 * Access the axis permutation array for a Frame.
5622
5623 * Type:
5624 * Protected virtual function.
5625
5626 * Synopsis:
5627 * #include "frame.h"
5628 * const int *astGetPerm( AstFrame *this )
5629
5630 * Class Membership:
5631 * Frame method.
5632
5633 * Description:
5634 * This function returns a pointer to the axis permutation array
5635 * for a Frame. This array constitutes a lookup-table that converts
5636 * between an axis number supplied externally and the corresponding
5637 * index in the Frame's internal axis arrays.
5638
5639 * Parameters:
5640 * this
5641 * Pointer to the Frame.
5642
5643 * Returned Value:
5644 * Pointer to the Frame's axis permutation array (a constant array
5645 * of int). Each element of this contains the (zero-based)
5646 * internal axis index to be used in place of the external index
5647 * which is used to address the permutation array. If the Frame has
5648 * zero axes, this pointer will be NULL.
5649
5650 * Notes:
5651 * - This protected method is provided to assist class
5652 * implementations which need to implement axis-dependent
5653 * extensions to Frame methods, and which therefore need to know
5654 * how a Frames's external axis index is converted for internal
5655 * use.
5656 * - The pointer returned by this function gives direct access to
5657 * data internal to the Frame object. It remains valid only so long
5658 * as the Frame exists. The permutation array contents may be
5659 * modified by other functions which operate on the Frame and this
5660 * may render the returned pointer invalid.
5661 * - A NULL pointer will be returned if this function is invoked
5662 * with the global error status set, or if it should fail for any
5663 * reason.
5664 *-
5665 */
5666
5667 /* Check the global error status. */
5668 if ( !astOK ) return NULL;
5669
5670 /* Return a pointer to the axis permutation array. */
5671 return this->perm;
5672 }
5673
GetFrameVariants(AstFrame * this,int * status)5674 static AstFrameSet *GetFrameVariants( AstFrame *this, int *status ){
5675 /*
5676 *+
5677 * Name:
5678 * astGetFrameVariants
5679
5680 * Purpose:
5681 * Returns the FrameSet holding the available Frame variants.
5682
5683 * Type:
5684 * Protected virtual function.
5685
5686 * Synopsis:
5687 * #include "frame.h"
5688 * AstFrameSet *astGetFrameVariants( AstFrame *this )
5689
5690 * Class Membership:
5691 * Frame method.
5692
5693 * Description:
5694 * This function returns a pointer to any FrameSet previously stored
5695 * in the Frame using method astSetVariants.
5696
5697 * Parameters:
5698 * this
5699 * Pointer to the Frame.
5700
5701 * Returned Value:
5702 * astGetFrameVariants
5703 * A pointer to the FrameSet. It should be annulled using astAnnul
5704 * when no longer needed. NULL will be returned if no FrameSet is
5705 * stored in the Frame.
5706
5707 * Notes:
5708 * - A NULL value will be returned if this function is invoked with the
5709 * AST error status set, or if it should fail for any reason.
5710 *-
5711 */
5712
5713 /* Local Variables: */
5714 AstFrameSet *result;
5715
5716 /* Initialise. */
5717 result = NULL;
5718
5719 /* Check the global error status. */
5720 if ( !astOK ) return result;
5721
5722 /* Get a clone of any FrameSet pointer. */
5723 if( this->variants ) result = astClone( this->variants );
5724
5725 /* Return the result. */
5726 return result;
5727 }
5728
astInitFrameVtab_(AstFrameVtab * vtab,const char * name,int * status)5729 void astInitFrameVtab_( AstFrameVtab *vtab, const char *name, int *status ) {
5730 /*
5731 *+
5732 * Name:
5733 * astInitFrameVtab
5734
5735 * Purpose:
5736 * Initialise a virtual function table for a Frame.
5737
5738 * Type:
5739 * Protected function.
5740
5741 * Synopsis:
5742 * #include "frame.h"
5743 * void astInitFrameVtab( AstFrameVtab *vtab, const char *name )
5744
5745 * Class Membership:
5746 * Frame vtab initialiser.
5747
5748 * Description:
5749 * This function initialises the component of a virtual function
5750 * table which is used by the Frame class.
5751
5752 * Parameters:
5753 * vtab
5754 * Pointer to the virtual function table. The components used by
5755 * all ancestral classes will be initialised if they have not already
5756 * been initialised.
5757 * name
5758 * Pointer to a constant null-terminated character string which contains
5759 * the name of the class to which the virtual function table belongs (it
5760 * is this pointer value that will subsequently be returned by the Object
5761 * astClass function).
5762 *-
5763 */
5764
5765 /* Local Variables: */
5766 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
5767 AstObjectVtab *object; /* Pointer to Object component of Vtab */
5768 AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */
5769
5770 /* Check the local error status. */
5771 if ( !astOK ) return;
5772
5773 /* Get a pointer to the thread specific global data structure. */
5774 astGET_GLOBALS(NULL);
5775
5776 /* Initialize the component of the virtual function table used by the
5777 parent class. */
5778 astInitMappingVtab( (AstMappingVtab *) vtab, name );
5779
5780 /* Store a unique "magic" value in the virtual function table. This
5781 will be used (by astIsAFrame ) to determine if an object belongs
5782 to this class. We can conveniently use the address of the (static)
5783 class_check variable to generate this unique value. */
5784 vtab->id.check = &class_check;
5785 vtab->id.parent = &(((AstMappingVtab *) vtab)->id);
5786
5787 /* Initialise member function pointers. */
5788 /* ------------------------------------ */
5789 /* Store pointers to the member functions (implemented here) that provide
5790 virtual methods for this class. */
5791 vtab->Abbrev = Abbrev;
5792 vtab->CheckPerm = CheckPerm;
5793 vtab->ClearDigits = ClearDigits;
5794 vtab->ClearDirection = ClearDirection;
5795 vtab->ClearDomain = ClearDomain;
5796 vtab->ClearFormat = ClearFormat;
5797 vtab->ClearLabel = ClearLabel;
5798 vtab->ClearMatchEnd = ClearMatchEnd;
5799 vtab->ClearMaxAxes = ClearMaxAxes;
5800 vtab->ClearMinAxes = ClearMinAxes;
5801 vtab->ClearPermute = ClearPermute;
5802 vtab->ClearPreserveAxes = ClearPreserveAxes;
5803 vtab->ClearSymbol = ClearSymbol;
5804 vtab->ClearTitle = ClearTitle;
5805 vtab->ClearUnit = ClearUnit;
5806 vtab->Convert = Convert;
5807 vtab->ConvertX = ConvertX;
5808 vtab->Angle = Angle;
5809 vtab->Distance = Distance;
5810 vtab->Fields = Fields;
5811 vtab->FindFrame = FindFrame;
5812 vtab->MatchAxes = MatchAxes;
5813 vtab->MatchAxesX = MatchAxesX;
5814 vtab->Format = Format;
5815 vtab->Gap = Gap;
5816 vtab->GetAxis = GetAxis;
5817 vtab->GetDigits = GetDigits;
5818 vtab->GetDirection = GetDirection;
5819 vtab->GetDomain = GetDomain;
5820 vtab->GetFormat = GetFormat;
5821 vtab->GetLabel = GetLabel;
5822 vtab->GetMatchEnd = GetMatchEnd;
5823 vtab->GetMaxAxes = GetMaxAxes;
5824 vtab->GetMinAxes = GetMinAxes;
5825 vtab->GetNaxes = GetNaxes;
5826 vtab->GetPerm = GetPerm;
5827 vtab->GetPermute = GetPermute;
5828 vtab->GetPreserveAxes = GetPreserveAxes;
5829 vtab->GetSymbol = GetSymbol;
5830 vtab->GetTitle = GetTitle;
5831 vtab->GetUnit = GetUnit;
5832 vtab->GetNormUnit = GetNormUnit;
5833 vtab->Intersect = Intersect;
5834 vtab->IsUnitFrame = IsUnitFrame;
5835 vtab->Match = Match;
5836 vtab->Norm = Norm;
5837 vtab->NormBox = NormBox;
5838 vtab->AxDistance = AxDistance;
5839 vtab->AxOffset = AxOffset;
5840 vtab->AxIn = AxIn;
5841 vtab->AxAngle = AxAngle;
5842 vtab->FrameGrid = FrameGrid;
5843 vtab->Offset = Offset;
5844 vtab->Offset2 = Offset2;
5845 vtab->Resolve = Resolve;
5846 vtab->ResolvePoints = ResolvePoints;
5847 vtab->LineDef = LineDef;
5848 vtab->LineContains = LineContains;
5849 vtab->LineCrossing = LineCrossing;
5850 vtab->LineOffset = LineOffset;
5851 vtab->Overlay = Overlay;
5852 vtab->PermAxes = PermAxes;
5853 vtab->PickAxes = PickAxes;
5854 vtab->PrimaryFrame = PrimaryFrame;
5855 vtab->SetAxis = SetAxis;
5856 vtab->SetDigits = SetDigits;
5857 vtab->SetDirection = SetDirection;
5858 vtab->SetDomain = SetDomain;
5859 vtab->SetFormat = SetFormat;
5860 vtab->SetLabel = SetLabel;
5861 vtab->SetMatchEnd = SetMatchEnd;
5862 vtab->SetMaxAxes = SetMaxAxes;
5863 vtab->SetMinAxes = SetMinAxes;
5864 vtab->SetPermute = SetPermute;
5865 vtab->SetPreserveAxes = SetPreserveAxes;
5866 vtab->SetSymbol = SetSymbol;
5867 vtab->SetTitle = SetTitle;
5868 vtab->SetUnit = SetUnit;
5869 vtab->SubFrame = SubFrame;
5870 vtab->TestDigits = TestDigits;
5871 vtab->TestDirection = TestDirection;
5872 vtab->TestDomain = TestDomain;
5873 vtab->TestFormat = TestFormat;
5874 vtab->TestLabel = TestLabel;
5875 vtab->TestMatchEnd = TestMatchEnd;
5876 vtab->TestMaxAxes = TestMaxAxes;
5877 vtab->TestMinAxes = TestMinAxes;
5878 vtab->TestPermute = TestPermute;
5879 vtab->TestPreserveAxes = TestPreserveAxes;
5880 vtab->TestSymbol = TestSymbol;
5881 vtab->TestTitle = TestTitle;
5882 vtab->TestUnit = TestUnit;
5883 vtab->Unformat = Unformat;
5884 vtab->ValidateAxis = ValidateAxis;
5885 vtab->ValidateAxisSelection = ValidateAxisSelection;
5886 vtab->ValidateSystem = ValidateSystem;
5887 vtab->SystemString = SystemString;
5888 vtab->SystemCode = SystemCode;
5889
5890 vtab->GetFrameFlags = GetFrameFlags;
5891 vtab->SetFrameFlags = SetFrameFlags;
5892
5893 vtab->TestActiveUnit = TestActiveUnit;
5894 vtab->GetActiveUnit = GetActiveUnit;
5895 vtab->SetActiveUnit = SetActiveUnit;
5896
5897 vtab->GetFrameVariants = GetFrameVariants;
5898 vtab->SetFrameVariants = SetFrameVariants;
5899
5900 vtab->ClearSystem = ClearSystem;
5901 vtab->GetSystem = GetSystem;
5902 vtab->SetSystem = SetSystem;
5903 vtab->TestSystem = TestSystem;
5904
5905 vtab->ClearAlignSystem = ClearAlignSystem;
5906 vtab->GetAlignSystem = GetAlignSystem;
5907 vtab->SetAlignSystem = SetAlignSystem;
5908 vtab->TestAlignSystem = TestAlignSystem;
5909
5910 vtab->ClearTop = ClearTop;
5911 vtab->GetTop = GetTop;
5912 vtab->SetTop = SetTop;
5913 vtab->TestTop = TestTop;
5914
5915 vtab->ClearBottom = ClearBottom;
5916 vtab->GetBottom = GetBottom;
5917 vtab->SetBottom = SetBottom;
5918 vtab->TestBottom = TestBottom;
5919
5920 vtab->ClearEpoch = ClearEpoch;
5921 vtab->GetEpoch = GetEpoch;
5922 vtab->SetEpoch = SetEpoch;
5923 vtab->TestEpoch = TestEpoch;
5924
5925 vtab->ClearObsLat = ClearObsLat;
5926 vtab->TestObsLat = TestObsLat;
5927 vtab->GetObsLat = GetObsLat;
5928 vtab->SetObsLat = SetObsLat;
5929
5930 vtab->ClearObsLon = ClearObsLon;
5931 vtab->TestObsLon = TestObsLon;
5932 vtab->GetObsLon = GetObsLon;
5933 vtab->SetObsLon = SetObsLon;
5934
5935 vtab->ClearObsAlt = ClearObsAlt;
5936 vtab->TestObsAlt = TestObsAlt;
5937 vtab->GetObsAlt = GetObsAlt;
5938 vtab->SetObsAlt = SetObsAlt;
5939
5940 vtab->ClearDut1 = ClearDut1;
5941 vtab->GetDut1 = GetDut1;
5942 vtab->SetDut1 = SetDut1;
5943 vtab->TestDut1 = TestDut1;
5944
5945 /* Save the inherited pointers to methods that will be extended, and
5946 replace them with pointers to the new member functions. */
5947 object = (AstObjectVtab *) vtab;
5948
5949 parent_getobjsize = object->GetObjSize;
5950 object->GetObjSize = GetObjSize;
5951 parent_clearattrib = object->ClearAttrib;
5952 object->ClearAttrib = ClearAttrib;
5953 parent_getattrib = object->GetAttrib;
5954 object->GetAttrib = GetAttrib;
5955 parent_setattrib = object->SetAttrib;
5956 object->SetAttrib = SetAttrib;
5957 parent_testattrib = object->TestAttrib;
5958 object->TestAttrib = TestAttrib;
5959
5960 parent_cleanattribs = object->CleanAttribs;
5961 object->CleanAttribs = CleanAttribs;
5962
5963 #if defined(THREAD_SAFE)
5964 parent_managelock = object->ManageLock;
5965 object->ManageLock = ManageLock;
5966 #endif
5967
5968 /* Store replacement pointers for methods which will be over-ridden by
5969 new member functions implemented here. */
5970 mapping = (AstMappingVtab *) vtab;
5971
5972 object->Equal = Equal;
5973 mapping->GetIsLinear = GetIsLinear;
5974 mapping->GetIsSimple = GetIsSimple;
5975 mapping->GetNin = GetNin;
5976 mapping->GetNout = GetNout;
5977 mapping->ReportPoints = ReportPoints;
5978 mapping->Transform = Transform;
5979 mapping->MapSplit = MapSplit;
5980 mapping->DoNotSimplify = DoNotSimplify;
5981
5982 /* Declare the copy constructor, destructor and class dump
5983 function. */
5984 astSetCopy( vtab, Copy );
5985 astSetDelete( vtab, Delete );
5986 astSetDump( vtab, Dump, "Frame", "Coordinate system description" );
5987
5988 /* If we have just initialised the vtab for the current class, indicate
5989 that the vtab is now initialised, and store a pointer to the class
5990 identifier in the base "object" level of the vtab. */
5991 if( vtab == &class_vtab ) {
5992 class_init = 1;
5993 astSetVtabClassIdentifier( vtab, &(vtab->id) );
5994 }
5995 }
5996
Intersect(AstFrame * this,const double a1[2],const double a2[2],const double b1[2],const double b2[2],double cross[2],int * status)5997 static void Intersect( AstFrame *this, const double a1[2],
5998 const double a2[2], const double b1[2],
5999 const double b2[2], double cross[2],
6000 int *status ) {
6001 /*
6002 *++
6003 * Name:
6004 c astIntersect
6005 f AST_INTERSECT
6006
6007 * Purpose:
6008 * Find the point of intersection between two geodesic curves.
6009
6010 * Type:
6011 * Public virtual function.
6012
6013 * Synopsis:
6014 c #include "frame.h"
6015 c void astIntersect( AstFrame *this, const double a1[2],
6016 c const double a2[2], const double b1[2],
6017 c const double b2[2], double cross[2] )
6018 f CALL AST_INTERSECT( THIS, A1, A2, B1, B2, CROSS, STATUS )
6019
6020 * Class Membership:
6021 * Frame method.
6022
6023 * Description:
6024 c This function
6025 f This routine
6026 * finds the coordinate values at the point of intersection between
6027 * two geodesic curves. Each curve is specified by two points on
6028 * the curve. It can only be used with 2-dimensional Frames.
6029 *
6030 * For example, in a basic Frame, it will find the point of
6031 * intersection between two straight lines. But for a SkyFrame it
6032 * will find an intersection of two great circles.
6033
6034 * Parameters:
6035 c this
6036 f THIS = INTEGER (Given)
6037 * Pointer to the Frame.
6038 c a1
6039 f A1( 2 ) = DOUBLE PRECISION (Given)
6040 c An array of double, with one element for each Frame axis
6041 f An array with one element for each Frame axis
6042 * (Naxes attribute). This should contain the coordinates of the
6043 * first point on the first geodesic curve.
6044 c a2
6045 f A2( 2 ) = DOUBLE PRECISION (Given)
6046 c An array of double, with one element for each Frame axis
6047 f An array with one element for each Frame axis
6048 * (Naxes attribute). This should contain the coordinates of a
6049 * second point on the first geodesic curve. It should not be
6050 * co-incident with the first point.
6051 c b1
6052 f B1( 2 ) = DOUBLE PRECISION (Given)
6053 c An array of double, with one element for each Frame axis
6054 f An array with one element for each Frame axis
6055 * (Naxes attribute). This should contain the coordinates of the
6056 * first point on the second geodesic curve.
6057 c b2
6058 f B2( 2 ) = DOUBLE PRECISION (Given)
6059 c An array of double, with one element for each Frame axis
6060 f An array with one element for each Frame axis
6061 * (Naxes attribute). This should contain the coordinates of a
6062 * second point on the second geodesic curve. It should not be
6063 * co-incident with the first point.
6064 c cross
6065 f CROSS( 2 ) = DOUBLE PRECISION (Returned)
6066 c An array of double, with one element for each Frame axis
6067 f An array with one element for each Frame axis
6068 * in which the coordinates of the required intersection will
6069 * be returned.
6070 f STATUS = INTEGER (Given and Returned)
6071 f The global status.
6072
6073 * Notes:
6074 * - For SkyFrames each curve will be a great circle, and in general
6075 * each pair of curves will intersect at two diametrically opposite
6076 * points on the sky. The returned position is the one which is
6077 * closest to point
6078 c "a1".
6079 f A1.
6080 * - This function will return "bad" coordinate values (AST__BAD)
6081 * if any of the input coordinates has this value, or if the two
6082 * points defining either geodesic are co-incident, or if the two
6083 * curves do not intersect.
6084 c - The geodesic curve used by this function is the path of
6085 f - The geodesic curve used by this routine is the path of
6086 * shortest distance between two points, as defined by the
6087 c astDistance function.
6088 f AST_DISTANCE function.
6089 * - An error will be reported if the Frame is not 2-dimensional.
6090 *--
6091 */
6092
6093 /* Local Variables: */
6094 double ca; /* Y axis intercept of line a */
6095 double cb; /* Y axis intercept of line b */
6096 double dxa; /* X range spanned by line a */
6097 double dxb; /* X range spanned by line b */
6098 double ma; /* Gradient of line a */
6099 double mb; /* Gradient of line b */
6100 int naxes; /* Number of Frame axes */
6101
6102 /* Check the global error status. */
6103 if ( !astOK ) return;
6104
6105 /* Initialize bad values. */
6106 cross[ 0 ] = AST__BAD;
6107 cross[ 1 ] = AST__BAD;
6108
6109 /* Determine the number of Frame axes. */
6110 naxes = astGetNaxes( this );
6111
6112 /* Report an error if the Frame is not 2 dimensional. */
6113 if( naxes != 2 && astOK ) {
6114 astError( AST__NAXIN, "astIntersect(%s): Invalid number of Frame axes (%d)."
6115 " astIntersect can only be used with 2 dimensonal Frames.", status,
6116 astGetClass( this ), naxes );
6117 }
6118
6119 /* Check that all supplied values are OK. */
6120 if ( ( a1[ 0 ] != AST__BAD ) && ( a1[ 1 ] != AST__BAD ) &&
6121 ( a2[ 0 ] != AST__BAD ) && ( a2[ 1 ] != AST__BAD ) &&
6122 ( b1[ 0 ] != AST__BAD ) && ( b1[ 1 ] != AST__BAD ) &&
6123 ( b2[ 0 ] != AST__BAD ) && ( b2[ 1 ] != AST__BAD ) ) {
6124
6125 /* Find the x increments spanned by the two lines. */
6126
6127 /* Check the first line is not vertical. */
6128 dxa = a2[ 0 ] - a1[ 0 ];
6129 dxb = b2[ 0 ] - b1[ 0 ];
6130 if( dxa != 0.0 ) {
6131
6132 /* Find the gradient and Y axis intercept of the first line. */
6133 ma = ( a2[ 1 ] - a1[ 1 ] )/dxa;
6134 ca = a1[ 1 ] - a1[ 0 ]*ma;
6135
6136 /* Check the second line is not vertical. */
6137 if( dxb != 0.0 ) {
6138
6139 /* Find the gradient and Y axis intercept of the second line. */
6140 mb = ( b2[ 1 ] - b1[ 1 ] )/dxb;
6141 cb = b1[ 1 ] - b1[ 0 ]*mb;
6142
6143 /* Check the lines are not parallel. */
6144 if( ma != mb ) {
6145
6146 /* Find the intersection of the two lines. */
6147 cross[ 0 ] = ( cb -ca )/( ma - mb );
6148 cross[ 1 ] = ( ( ma + mb )*cross[ 0 ] + ca + cb )/2;
6149 }
6150
6151 /* If the second line is vertical but the first is not. */
6152 } else if( b1[ 1 ] != b2[ 1 ] ){
6153 cross[ 0 ] = b1[ 0 ];
6154 cross[ 1 ] = ma*b1[ 0 ] + ca;
6155 }
6156
6157 /* First line is vertical but second is not. */
6158 } else if( dxb != 0.0 && a1[ 1 ] != a2[ 1 ] ){
6159
6160 /* Find the gradient and Y axis intercept of the second line. */
6161 mb = ( b2[ 1 ] - b1[ 1 ] )/dxb;
6162 cb = b1[ 1 ] - b1[ 0 ]*mb;
6163
6164 /* Find the intercection. */
6165 cross[ 0 ] = a1[ 0 ];
6166 cross[ 1 ] = mb*a1[ 0 ] + cb;
6167 }
6168 }
6169 }
6170
IsUnitFrame(AstFrame * this,int * status)6171 static int IsUnitFrame( AstFrame *this, int *status ){
6172 /*
6173 *+
6174 * Name:
6175 * astIsUnitFrame
6176
6177 * Purpose:
6178 * Is this Frame equivalent to a UnitMap?
6179
6180 * Type:
6181 * Protected virtual function.
6182
6183 * Synopsis:
6184 * #include "frame.h"
6185 * int astIsUnitFrame( AstFrame *this )
6186
6187 * Class Membership:
6188 * Frame method.
6189
6190 * Description:
6191 * This function returns a flag indicating if the supplied Frame is
6192 * equivalent to a UnitMap when treated as a Mapping (note, the Frame
6193 * class inherits from Mapping and therefore every Frame is also a Mapping).
6194
6195 * Parameters:
6196 * this
6197 * Pointer to the Frame.
6198
6199 * Returned Value:
6200 * A non-zero value is returned if the supplied Frame is equivalent to
6201 * a UnitMap when treated as a Mapping.
6202
6203 *-
6204 */
6205
6206 /* Check the local error status. */
6207 if( !astOK ) return 0;
6208
6209 /* The base Frame class is always equivalent to a UnitMap. */
6210 return 1;
6211 }
6212
LineContains(AstFrame * this,AstLineDef * l,int def,double * point,int * status)6213 static int LineContains( AstFrame *this, AstLineDef *l, int def, double *point, int *status ) {
6214 /*
6215 *+
6216 * Name:
6217 * astLineContains
6218
6219 * Purpose:
6220 * Determine if a line contains a point.
6221
6222 * Type:
6223 * Protected virtual function.
6224
6225 * Synopsis:
6226 * #include "frame.h"
6227 * int astLineContains( AstFrame *this, AstLineDef *l, int def, double *point )
6228
6229 * Class Membership:
6230 * Frame method.
6231
6232 * Description:
6233 * This function determines if the supplied point is on the supplied
6234 * line within the supplied Frame. The start point of the line is
6235 * considered to be within the line, but the end point is not. The tests
6236 * are that the point of closest approach of the line to the point should
6237 * be between the start and end, and that the distance from the point to
6238 * the point of closest aproach should be less than 1.0E-7 of the length
6239 * of the line.
6240
6241 * Parameters:
6242 * this
6243 * Pointer to the Frame.
6244 * l
6245 * Pointer to the structure defining the line.
6246 * def
6247 * Should be set non-zero if the "point" array was created by a
6248 * call to astLineCrossing (in which case it may contain extra
6249 * information following the axis values),and zero otherwise.
6250 * point
6251 * Point to an array containing the axis values of the point to be
6252 * tested, possibly followed by extra cached information (see "def").
6253
6254 * Returned Value:
6255 * A non-zero value is returned if the line contains the point.
6256
6257 * Notes:
6258 * - The pointer supplied for "l" should have been created using the
6259 * astLineDef method. These structures contained cached information about
6260 * the lines which improve the efficiency of this method when many
6261 * repeated calls are made. An error will be reported if the structure
6262 * does not refer to the Frame specified by "this".
6263 * - Zero will be returned if this function is invoked with the global
6264 * error status set, or if it should fail for any reason.
6265 *-
6266 */
6267
6268 /* Local Variables: */
6269 int result;
6270 double dx, dy, p;
6271
6272 /* Initialise. */
6273 result = 0;
6274
6275 /* Check the global error status. */
6276 if ( !astOK ) return result;
6277
6278 /* Check that the line refers to the supplied Frame. */
6279 if( l->frame != this ) {
6280 astError( AST__INTER, "astLineContains(%s): The supplied line does "
6281 "not relate to the supplied %s (AST internal programming "
6282 "error).", status, astGetClass( this ), astGetClass( this ) );
6283
6284 /* If the point is good, find the offsets from the start of the line. */
6285 } else if( point[ 0 ] != AST__BAD && point[ 1 ] != AST__BAD ) {
6286 dx = point[ 0 ] - l->start[ 0 ];
6287 dy = point[ 1 ] - l->start[ 1 ];
6288
6289 /* Check the nearest point on the line is between the start and end.
6290 Exclude the end point. */
6291 p = dx*l->dir[ 0 ] + dy*l->dir[ 1 ];
6292 if( p >= 0.0 && p < l->length ) {
6293
6294 /* Check the distance from the point to the nearest point on the line is not
6295 further than 1.0E-7 of the length of the line. */
6296 if( fabs( dx*l->q[ 0 ] + dy*l->q[ 1 ] ) <= 1.0E-7*l->length ) {
6297 result = 1;
6298 }
6299 }
6300 }
6301
6302 /* Return zero if an error occurred. */
6303 if( !astOK ) result = 0;
6304
6305 /* Return a pointer to the output structure. */
6306 return result;
6307 }
6308
LineCrossing(AstFrame * this,AstLineDef * l1,AstLineDef * l2,double ** cross,int * status)6309 static int LineCrossing( AstFrame *this, AstLineDef *l1, AstLineDef *l2,
6310 double **cross, int *status ) {
6311 /*
6312 *+
6313 * Name:
6314 * astLineCrossing
6315
6316 * Purpose:
6317 * Determine if two lines cross.
6318
6319 * Type:
6320 * Protected virtual function.
6321
6322 * Synopsis:
6323 * #include "frame.h"
6324 * int astLineCrossing( AstFrame *this, AstLineDef *l1, AstLineDef *l2,
6325 * double **cross )
6326
6327 * Class Membership:
6328 * Frame method.
6329
6330 * Description:
6331 * This function determines if the two suplied line segments cross,
6332 * and if so returns the axis values at the point where they cross.
6333 * A flag is also returned indicating if the crossing point occurs
6334 * within the length of both line segments, or outside one or both of
6335 * the line segments.
6336
6337 * Parameters:
6338 * this
6339 * Pointer to the Frame.
6340 * l1
6341 * Pointer to the structure defining the first line.
6342 * l2
6343 * Pointer to the structure defining the second line.
6344 * cross
6345 * Pointer to a location at which to put a pointer to a dynamically
6346 * alocated array containing the axis values at the crossing. If
6347 * NULL is supplied no such array is returned. Otherwise, the returned
6348 * array should be freed using astFree when no longer needed. If the
6349 * lines are parallel (i.e. do not cross) then AST__BAD is returned for
6350 * all axis values. Note usable axis values are returned even if the
6351 * lines cross outside the segment defined by the start and end points
6352 * of the lines. The order of axes in the returned array will take
6353 * account of the current axis permutation array if appropriate. Note,
6354 * sub-classes such as SkyFrame may append extra values to the end
6355 * of the basic frame axis values. A NULL pointer is returned if an
6356 * error occurs.
6357
6358 * Returned Value:
6359 * A non-zero value is returned if the lines cross at a point which is
6360 * within the [start,end) segment of the lines that are flagged as
6361 * finite (if a line is marked as infinite any crossing is assumed to
6362 * be within the bounds of the line). If the crossing point is outside
6363 * this segment on either (inifinte) line, or if the lines are parallel,
6364 * zero is returned. Note, the start point is considered to be inside
6365 * the length of the segment, but the end point is outside.
6366
6367 * Notes:
6368 * - The pointers supplied for "l1" and "l2" should have been created
6369 * using the astLineDef method. These structures contained cached
6370 * information about the lines which improve the efficiency of this method
6371 * when many repeated calls are made. An error will be reported if
6372 * either structure does not refer to the Frame specified by "this".
6373 * - Zero will be returned if this function is invoked with the global
6374 * error status set, or if it should fail for any reason.
6375 *-
6376 */
6377
6378 /* Local Variables: */
6379 double *crossing; /* Returned array */
6380 double den; /* Denominator */
6381 double dx; /* Offset in start X values */
6382 double dy; /* Offset in start Y values */
6383 double t1; /* Distance from start of line 1 to crossing */
6384 double t2; /* Distance from start of line 2 to crossing */
6385 int result; /* Returned value */
6386
6387 /* Check the global error status. */
6388 if ( !astOK ) return 0;
6389
6390 /* Initialise. */
6391 result = 0;
6392 crossing = astMalloc( sizeof(double)*2 );
6393
6394 /* Check that both lines refer to the supplied Frame. */
6395 if( l1->frame != this ) {
6396 astError( AST__INTER, "astLineCrossing(%s): First supplied line does "
6397 "not relate to the supplied %s (AST internal programming "
6398 "error).", status, astGetClass( this ), astGetClass( this ) );
6399
6400 } else if( l2->frame != this ) {
6401 astError( AST__INTER, "astLineCrossing(%s): Second supplied line does "
6402 "not relate to the supplied %s (AST internal programming "
6403 "error).", status, astGetClass( this ), astGetClass( this ) );
6404
6405 } else if( crossing ){
6406
6407 /* Each of the lines can be represented as "p = start + t.v" where start is
6408 the start position, v is the unit vector pointing from start to end,
6409 and t is the scalar distance from the start position. So to find the
6410 intersection put "start1 + t1.v1 = start2 + t2.v2" and solve for t1
6411 and t2. */
6412 den = (l1->dir[ 0 ])*(l2->dir[ 1 ]) - (l2->dir[ 0 ])*(l1->dir[ 1 ]);
6413 if( den != 0.0 ) {
6414 dx = l2->start[ 0 ] - l1->start[ 0 ];
6415 dy = l2->start[ 1 ] - l1->start[ 1 ];
6416 t1 = ( l2->dir[ 1 ]*dx - l2->dir[ 0 ]*dy )/den;
6417 t2 = ( l1->dir[ 1 ]*dx - l1->dir[ 0 ]*dy )/den;
6418
6419 /* Store the crossing point, using the smaller t value to redue error. */
6420 if( fabs( t1 ) < fabs( t2 ) ) {
6421 crossing[ 0 ] = l1->start[ 0 ] + t1*l1->dir[ 0 ];
6422 crossing[ 1 ] = l1->start[ 1 ] + t1*l1->dir[ 1 ];
6423 } else {
6424 crossing[ 0 ] = l2->start[ 0 ] + t2*l2->dir[ 0 ];
6425 crossing[ 1 ] = l2->start[ 1 ] + t2*l2->dir[ 1 ];
6426 }
6427
6428 /* See if the intersection is within the length of both lines (excluding
6429 the end points). If a line is flagged as infinite, set the "t" parameter
6430 to zero to make it look like the crossing is within the line. */
6431 if( l1->infinite ) t1 = 0.0;
6432 if( l2->infinite ) t2 = 0.0;
6433
6434 if( t1 >= 0.0 && t1 < l1->length &&
6435 t2 >= 0.0 && t2 < l2->length ) result = 1;
6436
6437 } else {
6438 crossing[ 0 ] = AST__BAD;
6439 crossing[ 1 ] = AST__BAD;
6440 }
6441 }
6442
6443 /* Return zero if an error occurred. */
6444 if( !astOK ) {
6445 crossing = astFree( crossing );
6446 result = 0;
6447 }
6448
6449 /* Return the crossing pointer. */
6450 if( cross ) {
6451 *cross = crossing;
6452 } else if( crossing ){
6453 crossing = astFree( crossing );
6454 }
6455
6456 /* Return a pointer to the output structure. */
6457 return result;
6458 }
6459
LineDef(AstFrame * this,const double start[2],const double end[2],int * status)6460 static AstLineDef *LineDef( AstFrame *this, const double start[2],
6461 const double end[2], int *status ) {
6462 /*
6463 *+
6464 * Name:
6465 * astLineDef
6466
6467 * Purpose:
6468 * Creates a structure describing a line segment in a 2D Frame.
6469
6470 * Type:
6471 * Protected virtual function.
6472
6473 * Synopsis:
6474 * #include "frame.h"
6475 * AstLineDef *astLineDef( AstFrame *this, const double start[2],
6476 * const double end[2] )
6477
6478 * Class Membership:
6479 * Frame method.
6480
6481 * Description:
6482 * This function creates a structure containing information describing a
6483 * given line segment within the supplied 2D Frame. This may include
6484 * information which allows other methods such as astLineCrossing to
6485 * function more efficiently. Thus the returned structure acts as a
6486 * cache to store intermediate values used by these other methods.
6487
6488 * Parameters:
6489 * this
6490 * Pointer to the Frame. Must have 2 axes.
6491 * start
6492 * An array of 2 doubles marking the start of the line segment.
6493 * end
6494 * An array of 2 doubles marking the end of the line segment.
6495
6496 * Returned Value:
6497 * Pointer to the memory structure containing the description of the
6498 * line. This structure should be freed using astFree when no longer
6499 * needed. A NULL pointer is returned (without error) if any of the
6500 * supplied axis values are AST__BAD.
6501
6502 * Notes:
6503 * - A null pointer will be returned if this function is invoked
6504 * with the global error status set, or if it should fail for any
6505 * reason.
6506 *-
6507 */
6508
6509 /* Local Variables: */
6510 AstLineDef *result; /* Pointer to output structure */
6511
6512 /* Initialise. */
6513 result = NULL;
6514
6515 /* Check the global error status. */
6516 if ( !astOK ) return result;
6517
6518 /* Check the Frame has 2 axes. */
6519 if( astGetNaxes( this ) != 2 ) {
6520 astError( AST__INTER, "astLineDef(%s): The supplied %s is not 2 "
6521 "dimensional (internal AST proramming error).", status,
6522 astGetClass( this ), astGetClass( this ) );
6523 }
6524
6525 /* Check the axis values are good */
6526 if( start[ 0 ] != AST__BAD && start[ 1 ] != AST__BAD &&
6527 end[ 0 ] != AST__BAD && end[ 1 ] != AST__BAD ) {
6528
6529 /* Allocate memory for the returned structure. */
6530 result = astMalloc( sizeof( AstLineDef ) );
6531 if( result ) {
6532
6533 /* Store the supplied axis values in the returned structure. */
6534 result->start[ 0 ] = start[ 0 ];
6535 result->start[ 1 ] = start[ 1 ];
6536 result->end[ 0 ] = end[ 0 ];
6537 result->end[ 1 ] = end[ 1 ];
6538
6539 /* Store the length of the line segment. */
6540 result->length = astDistance( this, start, end );
6541
6542 /* Store a unit vector pointing from the start to the end. */
6543 if( result->length > 0.0 ) {
6544 result->dir[ 0 ] = ( end[ 0 ] - start[ 0 ] )/result->length;
6545 result->dir[ 1 ] = ( end[ 1 ] - start[ 1 ] )/result->length;
6546 } else {
6547 result->dir[ 0 ] = 1.0;
6548 result->dir[ 1 ] = 0.0;
6549 }
6550
6551 /* Store a unit vector perpendicular to the line, such that the vector
6552 points to the left, as vewied from the observer, when moving from the
6553 start to the end of the line. */
6554 result->q[ 0 ] = -result->dir[ 1 ];
6555 result->q[ 1 ] = result->dir[ 0 ];
6556
6557 /* Store a pointer to the defining Frame. */
6558 result->frame = this;
6559
6560 /* Indicate that the line is considered to be terminated at the start and
6561 end points. */
6562 result->infinite = 0;
6563 }
6564 }
6565
6566 /* Free the returned pointer if an error occurred. */
6567 if( !astOK ) result = astFree( result );
6568
6569 /* Return a pointer to the output structure. */
6570 return result;
6571 }
6572
LineOffset(AstFrame * this,AstLineDef * line,double par,double prp,double point[2],int * status)6573 static void LineOffset( AstFrame *this, AstLineDef *line, double par,
6574 double prp, double point[2], int *status ){
6575 /*
6576 *+
6577 * Name:
6578 * astLineOffset
6579
6580 * Purpose:
6581 * Find a position close to a line.
6582
6583 * Type:
6584 * Protected virtual function.
6585
6586 * Synopsis:
6587 * #include "frame.h"
6588 * void LineOffset( AstFrame *this, AstLineDef *line, double par,
6589 * double prp, double point[2] )
6590
6591 * Class Membership:
6592 * Frame method.
6593
6594 * Description:
6595 * This function returns a position formed by moving a given distance along
6596 * the supplied line, and then a given distance away from the supplied line.
6597
6598 * Parameters:
6599 * this
6600 * Pointer to the Frame.
6601 * line
6602 * Pointer to the structure defining the line.
6603 * par
6604 * The distance to move along the line from the start towards the end.
6605 * prp
6606 * The distance to move at right angles to the line. Positive
6607 * values result in movement to the left of the line, as seen from
6608 * the observer, when moving from start towards the end.
6609
6610 * Notes:
6611 * - The pointer supplied for "line" should have been created using the
6612 * astLineDef method. This structure contains cached information about the
6613 * line which improves the efficiency of this method when many repeated
6614 * calls are made. An error will be reported if the structure does not
6615 * refer to the Frame specified by "this".
6616 *-
6617 */
6618
6619 /* Check the global error status. */
6620 if ( !astOK ) return;
6621
6622 /* Check that the line refers to the supplied Frame. */
6623 if( line->frame != this ) {
6624 astError( AST__INTER, "astLineOffset(%s): The supplied line does "
6625 "not relate to the supplied %s (AST internal programming "
6626 "error).", status, astGetClass( this ), astGetClass( this ) );
6627
6628 /* This implementation uses simple flat geometry. */
6629 } else {
6630 point[ 0 ] = line->start[ 0 ] + par*line->dir[ 0 ] + prp*line->q[ 0 ];
6631 point[ 1 ] = line->start[ 1 ] + par*line->dir[ 1 ] + prp*line->q[ 1 ];
6632 }
6633 }
6634
6635 #if defined(THREAD_SAFE)
ManageLock(AstObject * this_object,int mode,int extra,AstObject ** fail,int * status)6636 static int ManageLock( AstObject *this_object, int mode, int extra,
6637 AstObject **fail, int *status ) {
6638 /*
6639 * Name:
6640 * ManageLock
6641
6642 * Purpose:
6643 * Manage the thread lock on an Object.
6644
6645 * Type:
6646 * Private function.
6647
6648 * Synopsis:
6649 * #include "object.h"
6650 * AstObject *ManageLock( AstObject *this, int mode, int extra,
6651 * AstObject **fail, int *status )
6652
6653 * Class Membership:
6654 * CmpMap member function (over-rides the astManageLock protected
6655 * method inherited from the parent class).
6656
6657 * Description:
6658 * This function manages the thread lock on the supplied Object. The
6659 * lock can be locked, unlocked or checked by this function as
6660 * deteremined by parameter "mode". See astLock for details of the way
6661 * these locks are used.
6662
6663 * Parameters:
6664 * this
6665 * Pointer to the Object.
6666 * mode
6667 * An integer flag indicating what the function should do:
6668 *
6669 * AST__LOCK: Lock the Object for exclusive use by the calling
6670 * thread. The "extra" value indicates what should be done if the
6671 * Object is already locked (wait or report an error - see astLock).
6672 *
6673 * AST__UNLOCK: Unlock the Object for use by other threads.
6674 *
6675 * AST__CHECKLOCK: Check that the object is locked for use by the
6676 * calling thread (report an error if not).
6677 * extra
6678 * Extra mode-specific information.
6679 * fail
6680 * If a non-zero function value is returned, a pointer to the
6681 * Object that caused the failure is returned at "*fail". This may
6682 * be "this" or it may be an Object contained within "this". Note,
6683 * the Object's reference count is not incremented, and so the
6684 * returned pointer should not be annulled. A NULL pointer is
6685 * returned if this function returns a value of zero.
6686 * status
6687 * Pointer to the inherited status variable.
6688
6689 * Returned Value:
6690 * A local status value:
6691 * 0 - Success
6692 * 1 - Could not lock or unlock the object because it was already
6693 * locked by another thread.
6694 * 2 - Failed to lock a POSIX mutex
6695 * 3 - Failed to unlock a POSIX mutex
6696 * 4 - Bad "mode" value supplied.
6697
6698 * Notes:
6699 * - This function attempts to execute even if an error has already
6700 * occurred.
6701 */
6702
6703 /* Local Variables: */
6704 AstFrame *this; /* Pointer to Frame structure */
6705 int i; /* Loop count */
6706 int result; /* Returned status value */
6707
6708 /* Initialise */
6709 result = 0;
6710
6711 /* Check the supplied pointer is not NULL. */
6712 if( !this_object ) return result;
6713
6714 /* Obtain a pointers to the Frame structure. */
6715 this = (AstFrame *) this_object;
6716
6717 /* Invoke the ManageLock method inherited from the parent class. */
6718 if( !result ) result = (*parent_managelock)( this_object, mode, extra,
6719 fail, status );
6720
6721 /* Invoke the astManageLock method on any Objects contained within
6722 the supplied Object. */
6723 for( i = 0; i < this->naxes; i++ ) {
6724 if( !result ) result = astManageLock( this->axis[ i ], mode, extra,
6725 fail );
6726 }
6727 if( this->variants && !result ) result = astManageLock( this->variants, mode,
6728 extra, fail );
6729
6730 return result;
6731
6732 }
6733 #endif
6734
MapSplit(AstMapping * this_map,int nin,const int * in,AstMapping ** map,int * status)6735 static int *MapSplit( AstMapping *this_map, int nin, const int *in, AstMapping **map, int *status ){
6736 /*
6737 * Name:
6738 * MapSplit
6739
6740 * Purpose:
6741 * Create a Mapping representing a subset of the inputs of an existing
6742 * Frame.
6743
6744 * Type:
6745 * Private function.
6746
6747 * Synopsis:
6748 * #include "frame.h"
6749 * int *MapSplit( AstMapping *this, int nin, const int *in, AstMapping **map, int *status )
6750
6751 * Class Membership:
6752 * Frame method (over-rides the protected astMapSplit method
6753 * inherited from the Mapping class).
6754
6755 * Description:
6756 * This function creates a new Mapping by picking specified inputs from
6757 * an existing Frame. This is only possible if the specified inputs
6758 * correspond to some subset of the Frame outputs. That is, there
6759 * must exist a subset of the Frame outputs for which each output
6760 * depends only on the selected Frame inputs, and not on any of the
6761 * inputs which have not been selected. If this condition is not met
6762 * by the supplied Frame, then a NULL Mapping is returned.
6763
6764 * Parameters:
6765 * this
6766 * Pointer to the Frame to be split (the Frame is not actually
6767 * modified by this function).
6768 * nin
6769 * The number of inputs to pick from "this".
6770 * in
6771 * Pointer to an array of indices (zero based) for the inputs which
6772 * are to be picked. This array should have "nin" elements. If "Nin"
6773 * is the number of inputs of the supplied Frame, then each element
6774 * should have a value in the range zero to Nin-1.
6775 * map
6776 * Address of a location at which to return a pointer to the new
6777 * Mapping. This Mapping will have "nin" inputs (the number of
6778 * outputs may be different to "nin"). A NULL pointer will be
6779 * returned if the supplied Frame has no subset of outputs which
6780 * depend only on the selected inputs.
6781 * status
6782 * Pointer to the inherited status variable.
6783
6784 * Returned Value:
6785 * A pointer to a dynamically allocated array of ints. The number of
6786 * elements in this array will equal the number of outputs for the
6787 * returned Mapping. Each element will hold the index of the
6788 * corresponding output in the supplied Frame. The array should be
6789 * freed using astFree when no longer needed. A NULL pointer will
6790 * be returned if no output Mapping can be created.
6791
6792 * Notes:
6793 * - If this function is invoked with the global error status set,
6794 * or if it should fail for any reason, then NULL values will be
6795 * returned as the function value and for the "map" pointer.
6796 */
6797
6798 /* Local Variables: */
6799 int *result; /* Returned pointer */
6800
6801 /* Initialise */
6802 result = NULL;
6803 *map = NULL;
6804
6805 /* Check the global error status. */
6806 if ( !astOK ) return result;
6807
6808 /* Pick the selected axes from the Frame. */
6809 *map = (AstMapping *) astPickAxes( (AstFrame *) this_map, nin, in, NULL );
6810
6811 /* Return a copy of the supplied axis array.*/
6812 result = astStore( NULL, in, sizeof( int )*(size_t) nin );
6813
6814 /* Free returned resources if an error has occurred. */
6815 if( !astOK ) {
6816 result = astFree( result );
6817 *map = astAnnul( *map );
6818 }
6819
6820 /* Return the list of output indices. */
6821 return result;
6822 }
6823
Match(AstFrame * template,AstFrame * target,int matchsub,int ** template_axes,int ** target_axes,AstMapping ** map,AstFrame ** result,int * status)6824 static int Match( AstFrame *template, AstFrame *target, int matchsub,
6825 int **template_axes, int **target_axes,
6826 AstMapping **map, AstFrame **result, int *status ) {
6827 /*
6828 *+
6829 * Name:
6830 * astMatch
6831
6832 * Purpose:
6833 * Determine if conversion is possible between two coordinate systems.
6834
6835 * Type:
6836 * Protected virtual function.
6837
6838 * Synopsis:
6839 * #include "frame.h"
6840 * int astMatch( AstFrame *template, AstFrame *target, int matchsub,
6841 * int **template_axes, int **target_axes,
6842 * AstMapping **map, AstFrame **result )
6843
6844 * Class Membership:
6845 * Frame method.
6846
6847 * Description:
6848 * This function matches a "template" frame to a "target" frame and
6849 * determines whether it is possible to convert coordinates between
6850 * them. If it is, a mapping that performs the transformation is
6851 * returned along with a new Frame that describes the coordinate
6852 * system that results when this mapping is applied to the "target"
6853 * coordinate system. In addition, information is returned to allow
6854 * the axes in this "result" Frame to be associated with the
6855 * corresponding axes in the "target" and "template" Frames from
6856 * which they are derived.
6857
6858 * Parameters:
6859 * template
6860 * Pointer to the template Frame. This describes the coordinate
6861 * system (or set of possible coordinate systems) into which we
6862 * wish to convert our coordinates.
6863 * target
6864 * Pointer to the target Frame. This describes the coordinate
6865 * system in which we already have coordinates.
6866 * matchsub
6867 * If zero then a match only occurs if the template is of the same
6868 * class as the target, or of a more specialised class. If non-zero
6869 * then a match can occur even if this is not the case (i.e. if the
6870 * target is of a more specialised class than the template). In
6871 * this latter case, the target is cast down to the class of the
6872 * template. NOTE, this argument is handled by the global method
6873 * wrapper function "astMatch_", rather than by the class-specific
6874 * implementations of this method.
6875 * template_axes
6876 * Address of a location where a pointer to int will be returned
6877 * if the requested coordinate conversion is possible. This
6878 * pointer will point at a dynamically allocated array of
6879 * integers with one element for each axis of the "result" Frame
6880 * (see below). It must be freed by the caller (using astFree)
6881 * when no longer required.
6882 *
6883 * For each axis in the result Frame, the corresponding element
6884 * of this array will return the (zero-based) index of the
6885 * template Frame axis from which it is derived. If it is not
6886 * derived from any template frame axis, a value of -1 will be
6887 * returned instead.
6888 * target_axes
6889 * Address of a location where a pointer to int will be returned
6890 * if the requested coordinate conversion is possible. This
6891 * pointer will point at a dynamically allocated array of
6892 * integers with one element for each axis of the "result" Frame
6893 * (see below). It must be freed by the caller (using astFree)
6894 * when no longer required.
6895 *
6896 * For each axis in the result Frame, the corresponding element
6897 * of this array will return the (zero-based) index of the
6898 * target Frame axis from which it is derived. If it is not
6899 * derived from any target Frame axis, a value of -1 will be
6900 * returned instead.
6901 * map
6902 * Address of a location where a pointer to a new Mapping will
6903 * be returned if the requested coordinate conversion is
6904 * possible. If returned, the forward transformation of this
6905 * Mapping may be used to convert coordinates between the
6906 * "target" Frame and the "result" Frame (see below) and the
6907 * inverse transformation will convert in the opposite
6908 * direction.
6909 * result
6910 * Address of a location where a pointer to a new Frame will be
6911 * returned if the requested coordinate conversion is
6912 * possible. If returned, this Frame describes the coordinate
6913 * system that results from applying the returned Mapping
6914 * (above) to the "target" coordinate system. In general, this
6915 * Frame will combine attributes from (and will therefore be
6916 * more specific than) both the target and the template
6917 * Frames. In particular, when the template allows the
6918 * possibility of transformaing to any one of a set of
6919 * alternative coordinate systems, the "result" Frame will
6920 * indicate which of the alternatives was used.
6921
6922 * Returned Value:
6923 * A non-zero value is returned if the requested coordinate
6924 * conversion is possible. Otherwise zero is returned (this will
6925 * not in itself result in an error condition).
6926
6927 * Notes:
6928 * - By default, the "result" frame will have its number of axes
6929 * and axis order determined by the "template" Frame. However, if
6930 * the PreserveAxes attribute of the template frame is non-zero,
6931 * then the axis count and axis order of the "target" frame will be
6932 * used instead.
6933 * - The template_axes and target_axes arrays are provided so that
6934 * if the caller needs to permute the target and/or template axes
6935 * before invoking this function, it is possible to deduce how the
6936 * result axes should be permuted so as to correspond with the
6937 * original template/target axis order.
6938 * - For result axes that do not correspond with a template and/or
6939 * target axis (where a value of -1 is returned in the
6940 * template_axes and/or target_axes arrays), the caller has no
6941 * clear way of knowing where these axes should appear in any
6942 * permuted order. In this case, the relative position of these
6943 * axes within the result Frame (with respect to axes that do have
6944 * template/target axis associations) will be used to convey this
6945 * information. Such axes should be taken to be associated either
6946 * with the next preceding or following axis (depending on the
6947 * AST__MATCHEND flag of the template frame) which does have an
6948 * association.
6949 * - If the result Frame has zero axes, then NULL pointer values
6950 * will be returned for *template_axes and *target_axes.
6951 * - A value of zero will be returned if this function is invoked
6952 * with the global error status set, or if it should fail for any
6953 * reason.
6954 *-
6955
6956 * Implementation Notes:
6957 * This implementation addresses the matching of a Frame class
6958 * object to other types of Frames (i.e. the target may be from a
6959 * derived class). A Frame will match any other type of Frame with
6960 * an acceptable number of axes but will not distinguish axis order
6961 * (i.e. it will match the axes in whatever order they are
6962 * given). If the template Frame has a value set for its Domain
6963 * attribute, then it will only match another Frame with the same
6964 * Domain.
6965 */
6966
6967 /* Local Variables: */
6968 char *template_domain; /* Pointer to copy of template domain */
6969 const char *ptr; /* Pointer to domain string */
6970 const char *target_domain; /* Pointer to target domain string */
6971 int match; /* Template matches target? */
6972 int match_end; /* Match final axes of target? */
6973 int max_axes; /* Maximum acceptable number of axes */
6974 int min_axes; /* Minimum acceptable nu,ber of axes */
6975 int preserve_axes; /* Preserve target axes? */
6976 int result_axis; /* Loop counter for result axes */
6977 int result_naxes; /* Number of result axes */
6978 int target_naxes; /* Number of target axes */
6979 int template_naxes; /* Number of template axes */
6980
6981 /* Initialise the returned values. */
6982 *template_axes = NULL;
6983 *target_axes = NULL;
6984 *map = NULL;
6985 *result = NULL;
6986 match = 0;
6987
6988 /* Check the global error status. */
6989 if ( !astOK ) return match;
6990
6991 /* The first requirement for a match is that the target object is a Frame. This
6992 is already known to be true, as it forms part of the argument validation
6993 for this function. */
6994
6995 /* The second requirement is that the number of target axes is acceptable.
6996 Obtain the number of target axes and the minimum and maximum number of axes
6997 that the template will match. */
6998 target_naxes = astGetNaxes( target );
6999 min_axes = astGetMinAxes( template );
7000 max_axes = astGetMaxAxes( template );
7001
7002 /* Test if the number of target axes is acceptable. */
7003 if ( astOK ) {
7004 match = ( ( target_naxes >= min_axes ) && ( target_naxes <= max_axes ) );
7005 }
7006
7007 /* The third requirement is that if the template has its Domain
7008 attribute defined, then the target must also have the same Domain
7009 (although it need not be set - the default will do). First check if
7010 the template has a domain. */
7011 if ( astOK && match ) {
7012 if ( astTestDomain( template ) ) {
7013
7014 /* Obtain a pointer to the template domain. Then allocate memory and
7015 make a copy of it (this is necessary as we will next inquire the
7016 domain of the target and may over-write the buffer holding the
7017 template's domain). */
7018 ptr = astGetDomain( template );
7019 if ( astOK ) {
7020 template_domain = astStore( NULL, ptr,
7021 strlen( ptr ) + (size_t) 1 );
7022
7023 /* Obtain a pointer to the target domain. */
7024 target_domain = astGetDomain( target );
7025
7026 /* Compare the domain strings for equality. Then free the memory
7027 allocated above. */
7028 match = astOK && !strcmp( template_domain, target_domain );
7029 template_domain = astFree( template_domain );
7030 }
7031 }
7032 }
7033
7034 /* If the template matches, obtain the values of the template's PreserveAxes
7035 and MatchEnd attributes and determine the number of template axes. */
7036 if ( astOK && match ) {
7037 preserve_axes = astGetPreserveAxes( template );
7038 match_end = astGetMatchEnd( template );
7039 template_naxes = astGetNaxes( template );
7040
7041 /* If the PreserveAxes attribute is non-zero, the target axes should be
7042 preserved, so the number of result axes equals the number of target axes.
7043 Otherwise the number of template axes is used. */
7044 result_naxes = preserve_axes ? target_naxes : template_naxes;
7045
7046 /* Allocate memory for the arrays of axis associations to be returned. */
7047 *template_axes = astMalloc( sizeof( int ) * (size_t) result_naxes );
7048 *target_axes = astMalloc( sizeof( int ) * (size_t) result_naxes );
7049 if ( astOK ) {
7050
7051 /* Loop through each of the result axes. */
7052 for ( result_axis = 0; result_axis < result_naxes; result_axis++ ) {
7053
7054 /* Set up the axis associations. By default, associate the first result axis
7055 with the first template/target axis. */
7056 (*template_axes)[ result_axis ] = result_axis;
7057 (*target_axes)[ result_axis ] = result_axis;
7058
7059 /* However, if the MatchEnd attribute is non-zero, associate the last result
7060 axis with the last template/target axis (this only makes a difference if
7061 there is a difference in the number of axes). */
7062 if ( match_end ) {
7063 (*template_axes)[ result_axis ] +=
7064 template_naxes - result_naxes;
7065 (*target_axes)[ result_axis ] += target_naxes - result_naxes;
7066 }
7067
7068 /* If any of the associations would be with a template/target axis that doesn't
7069 exist, then use an axis index of -1 for the association instead. */
7070 if ( ( (*template_axes)[ result_axis ] < 0 ) ||
7071 ( (*template_axes)[ result_axis ] >= template_naxes ) ) {
7072 (*template_axes)[ result_axis ] = -1;
7073 }
7074 if ( ( (*target_axes)[ result_axis ] < 0 ) ||
7075 ( (*target_axes)[ result_axis ] >= target_naxes ) ) {
7076 (*target_axes)[ result_axis ] = -1;
7077 }
7078 }
7079
7080 /* Use the target's astSubFrame method to select the required axes from it,
7081 overlaying the template's attributes on to the resulting Frame. This process
7082 also generates the required Mapping between the target and result Frames. */
7083 match = astSubFrame( target, template,
7084 result_naxes, *target_axes, *template_axes,
7085 map, result );
7086 }
7087 }
7088
7089 /* If an error occurred, free any allocated memory and reset the result. */
7090 if ( !astOK || !match ) {
7091 *template_axes = astFree( *template_axes );
7092 *target_axes = astFree( *target_axes );
7093 match = 0;
7094 }
7095
7096 /* Return the result. */
7097 return match;
7098 }
7099
MatchAxes(AstFrame * frm1,AstFrame * frm2,int * axes,int * status)7100 static void MatchAxes( AstFrame *frm1, AstFrame *frm2, int *axes,
7101 int *status ) {
7102 /*
7103 *++
7104 * Name:
7105 c astMatchAxes
7106 f AST_MATCHAXES
7107
7108 * Purpose:
7109 * Find any corresponding axes in two Frames.
7110
7111 * Type:
7112 * Public virtual function.
7113
7114 * Synopsis:
7115 c #include "frame.h"
7116 c void astMatchAxes( AstFrame *frm1, AstFrame *frm2, int *axes )
7117 f CALL AST_MATCHAXES( FRM1, FRM2, AXES, STATUS )
7118
7119 * Class Membership:
7120 * Frame method.
7121
7122 * Description:
7123 * This function looks for corresponding axes within two supplied
7124 * Frames. An array of integers is returned that contains an element
7125 * for each axis in the second supplied Frame. An element in this array
7126 * will be set to zero if the associated axis within the second Frame
7127 * has no corresponding axis within the first Frame. Otherwise, it
7128 * will be set to the index (a non-zero positive integer) of the
7129 * corresponding axis within the first supplied Frame.
7130
7131 * Parameters:
7132 c frm1
7133 f FRM1 = INTEGER (Given)
7134 * Pointer to the first Frame.
7135 c frm2
7136 f FRM2 = INTEGER (Given)
7137 * Pointer to the second Frame.
7138 c axes
7139 f AXES = INTEGER( * ) (Returned)
7140 c Pointer to an
7141 f An
7142 * integer array in which to return the indices of the axes (within
7143 * the first Frame) that correspond to each axis within the second
7144 * Frame. Axis indices start at 1. A value of zero will be stored
7145 * in the returned array for each axis in the second Frame that has
7146 * no corresponding axis in the first Frame.
7147 *
7148 * The number of elements in this array must be greater than or
7149 * equal to the number of axes in the second Frame.
7150 f STATUS = INTEGER (Given and Returned)
7151 f The global status.
7152
7153 * Applicability:
7154 * Frame
7155 * This function applies to all Frames.
7156
7157 * Notes:
7158 * - Corresponding axes are identified by the fact that a Mapping can
7159 * be found between them using
7160 c astFindFrame or astConvert.
7161 f AST_FINDFRAME or AST_CONVERT.
7162 * Thus, "corresponding axes" are not necessarily identical. For
7163 * instance, SkyFrame axes in two Frames will match even if they
7164 * describe different celestial coordinate systems
7165 *--
7166
7167 * Implementation Notes:
7168 * This function is simply a wrap-up for the protected astMatchAxesX
7169 * method which performs the required processing but swaps the order
7170 * of the first two arguments. This is a trick to allow the
7171 * astMatchAxes method to be over-ridden by derived classes on the
7172 * basis of the class of either of the first two arguments.
7173 *
7174 * In practice, each class that represents an encapsulated Frame (e.g.
7175 * FrameSet, Region, etc) should over-ride this method, extracting a
7176 * Frame from the supplied "frm1" pointer, and then invoking
7177 * astMatchAxesX.
7178
7179 */
7180
7181 /* Check the global error status. */
7182 if ( !astOK ) return;
7183
7184 /* Invoke the "astMatchAxesX" method with the first two arguments
7185 swapped. */
7186 astMatchAxesX( frm2, frm1, axes );
7187 }
7188
MatchAxesX(AstFrame * frm2,AstFrame * frm1,int * axes,int * status)7189 static void MatchAxesX( AstFrame *frm2, AstFrame *frm1, int *axes,
7190 int *status ) {
7191 /*
7192 *+
7193 * Name:
7194 * astMatchAxesX
7195
7196 * Purpose:
7197 * Find any corresponding axes in two Frames.
7198
7199 * Type:
7200 * Protected virtual function.
7201
7202 * Synopsis:
7203 * #include "frame.h"
7204 * void astMatchAxesX( AstFrame *frm2, AstFrame *frm1, int *axes )
7205
7206 * Class Membership:
7207 * Frame method.
7208
7209 * Description:
7210 * This function performs the processing for the public astMatchAxes
7211 * method and has exactly the same interface except that the order
7212 * of the first two arguments is swapped. This is a trick to allow
7213 * the astMatchAxes method to be over-ridden by derived classes on
7214 * the basis of the class of either of its first two arguments.
7215 *
7216 * See the astMatchAxes method for details of the interface.
7217 *-
7218 */
7219
7220 /* Local Variables: */
7221 AstFrame *pfrm;
7222 AstFrame *resfrm;
7223 AstMapping *resmap;
7224 int *frm1_axes;
7225 int *pfrm_axes;
7226 int ifirst;
7227 int max_axes;
7228 int min_axes;
7229 int nax2;
7230 int pax;
7231 int preserve_axes;
7232
7233 /* Check the global error status. */
7234 if ( !astOK ) return;
7235
7236 /* Temporarily ensure that the PreserveAxes attribute is non-zero in
7237 the second supplied Frame. This means thte result Frame returned by
7238 astMatch below will have the axis count and order of the target Frame
7239 (i.e. "pfrm"). */
7240 if( astTestPreserveAxes( frm1 ) ) {
7241 preserve_axes = astGetPreserveAxes( frm1 ) ? 1 : 0;
7242 } else {
7243 preserve_axes = -1;
7244 }
7245 astSetPreserveAxes( frm1, 1 );
7246
7247 /* Temporarily ensure that the MaxAxes and MinAxes attributes in the
7248 second supplied Frame are set so the Frame can be used as a template
7249 in astMatch for matching any number of axes. */
7250 if( astTestMaxAxes( frm1 ) ) {
7251 max_axes = astGetMaxAxes( frm1 );
7252 } else {
7253 max_axes = -1;
7254 }
7255 astSetMaxAxes( frm1, 10000 );
7256
7257 if( astTestMinAxes( frm1 ) ) {
7258 min_axes = astGetMinAxes( frm1 );
7259 } else {
7260 min_axes = -1;
7261 }
7262 astSetMinAxes( frm1, 1 );
7263
7264 /* Get the number of axes in the frm2 Frame. */
7265 nax2 = astGetNaxes( frm2 );
7266
7267 /* Loop round the axes in the frm2 Frame. */
7268 for( ifirst = 0; ifirst < nax2; ifirst++ ) {
7269
7270 /* Identify the primary Frame defining the current axis in the frm2
7271 Frame. */
7272 astPrimaryFrame( frm2, ifirst, &pfrm, &pax );
7273
7274 /* Attempt to find a sub-frame within the frm1 Frame that corresponds to
7275 this primary Frame. */
7276 if( astMatch( frm1, pfrm, 1, &frm1_axes, &pfrm_axes, &resmap, &resfrm ) ) {
7277
7278 /* Store the one-based index within "frm1" of the corresponding axis. */
7279 axes[ ifirst ] = frm1_axes[ pax ] + 1;
7280
7281 /* Free resources */
7282 frm1_axes = astFree( frm1_axes );
7283 pfrm_axes = astFree( pfrm_axes );
7284 resmap = astAnnul( resmap );
7285 resfrm = astAnnul( resfrm );
7286
7287 /* If no corresponding axis was found store zero in the returned array. */
7288 } else {
7289 axes[ ifirst ] = 0;
7290 }
7291
7292 /* Free resouces. */
7293 pfrm = astAnnul( pfrm );
7294 }
7295
7296 /* Re-instate the original attribute values in the frm1 Frame. */
7297 if( preserve_axes == -1 ) {
7298 astClearPreserveAxes( frm1 );
7299 } else {
7300 astSetPreserveAxes( frm1, preserve_axes );
7301 }
7302
7303 if( max_axes == -1 ) {
7304 astClearMaxAxes( frm1 );
7305 } else {
7306 astSetMaxAxes( frm1, max_axes );
7307 }
7308
7309 if( min_axes == -1 ) {
7310 astClearMinAxes( frm1 );
7311 } else {
7312 astSetMinAxes( frm1, min_axes );
7313 }
7314 }
7315
NewUnit(AstAxis * ax,const char * old_units,const char * new_units,const char * method,const char * class,int * status)7316 static void NewUnit( AstAxis *ax, const char *old_units, const char *new_units,
7317 const char *method, const char *class, int *status ) {
7318 /*
7319 * Name:
7320 * NewUnit
7321
7322 * Purpose:
7323 * Modify an Axis Label and Symbol to reflect a new Unit value.
7324
7325 * Type:
7326 * Private function.
7327
7328 * Synopsis:
7329 * #include "frame.h"
7330 * void NewUnit( AstAxis *ax, const char *old_units, const char *new_units,
7331 * const char *method, const char *class )
7332
7333 * Class Membership:
7334 * Frame method.
7335
7336 * Description:
7337 * This function modifies the Label and Symbol attributes of an Axis
7338 * to reflect a new Unit value. This function should only be called if
7339 * the ActiveUnit flag of the parent Frame is non-zero (this is not
7340 * checked within this function).
7341 *
7342 * If the axis has a set label, then we may be able to modify it to
7343 * correctly describe the axis in the supplied new units. For instance,
7344 * if the original units were "Hz", the original label was "frequency",
7345 * and the new units are "log(Hz)", then the label is modified to become
7346 * "log( frequency )".
7347 *
7348 * The Axis Format attribute is cleared if the supplied units are
7349 * different to the old units (because any set format is probably not
7350 * going to be appropriate for a new system of units.
7351
7352 * Parameters:
7353 * ax
7354 * Pointer to the Axis.
7355 * old_units
7356 * The original units value.
7357 * new_units
7358 * The new units value.
7359 * method
7360 * Pointer to a constant null-terminated character string
7361 * containing the name of the method that invoked this function
7362 * to validate an axis selection. This method name is used
7363 * solely for constructing error messages.
7364 * class
7365 * Pointer to a constant null-terminated character string
7366 * containing the name of the class upon which this function
7367 * was invoked. This is used solely for constructing error messages.
7368
7369 * Returned Value:
7370 * void.
7371 */
7372
7373 /* Local Variables: */
7374 AstMapping *map; /* Pointer to units Mapping */
7375 char *new_lab; /* Pointer to new axis label */
7376 char *new_sym; /* Pointer to new axis symbol */
7377
7378 /* Check the global error status. */
7379 if ( !astOK ) return;
7380
7381 /* Check that the axis label is set. We relay on sub-classes to return
7382 appropriate default labels if the label is not set. */
7383 if( astTestAxisLabel( ax ) ) {
7384
7385 /* See if it is possible to map the old units into the new units.
7386 If it is, then a Mapping is returned together with an appropriately
7387 modified label. */
7388 map = astUnitMapper( old_units, new_units, astGetAxisLabel( ax ),
7389 &new_lab );
7390
7391 /* If succesfull, annul the Mapping (which we do not need), and store the
7392 modified label in the Axis, finally freeing the memory used to hold
7393 the modified label. */
7394 if( map ) {
7395 map = astAnnul( map );
7396 if( new_lab ) {
7397 astSetAxisLabel( ax, new_lab );
7398 new_lab = astFree( new_lab );
7399 }
7400 }
7401 }
7402
7403 /* Do the same for the axis symbol. */
7404 if( astTestAxisSymbol( ax ) ) {
7405 map = astUnitMapper( old_units, new_units, astGetAxisSymbol( ax ),
7406 &new_sym );
7407 if( map ) {
7408 map = astAnnul( map );
7409 if( new_sym ) {
7410 astSetAxisSymbol( ax, new_sym );
7411 new_sym = astFree( new_sym );
7412 }
7413 }
7414 }
7415
7416 /* If succesful, clear the axis format if the new and old units are
7417 different. */
7418 if( astOK ) {
7419 if( strcmp( old_units, new_units ) ) astClearAxisFormat( ax );
7420 }
7421
7422 }
7423
Norm(AstFrame * this,double value[],int * status)7424 static void Norm( AstFrame *this, double value[], int *status ) {
7425 /*
7426 *++
7427 * Name:
7428 c astNorm
7429 f AST_NORM
7430
7431 * Purpose:
7432 * Normalise a set of Frame coordinates.
7433
7434 * Type:
7435 * Public virtual function.
7436
7437 * Synopsis:
7438 c #include "frame.h"
7439 c void astNorm( AstFrame *this, double value[] )
7440 f CALL AST_NORM( THIS, VALUE, STATUS )
7441
7442 * Class Membership:
7443 * Frame method.
7444
7445 * Description:
7446 c This function normalises a set of Frame coordinate values which
7447 f This routine normalises a set of Frame coordinate values which
7448 * might be unsuitable for display (e.g. may lie outside the
7449 * expected range) into a set of acceptable values suitable for
7450 * display.
7451
7452 * Parameters:
7453 c this
7454 f THIS = INTEGER (Given)
7455 * Pointer to the Frame.
7456 c value
7457 f VALUE( * ) = DOUBLE PRECISION (Given and Returned)
7458 c An array of double, with one element for each Frame axis
7459 f An array with one element for each Frame axis
7460 * (Naxes attribute). Initially, this should contain a set of
7461 * coordinate values representing a point in the space which the
7462 * Frame describes. If these values lie outside the expected
7463 * range for the Frame, they will be replaced with more
7464 * acceptable (normalised) values. Otherwise, they will be
7465 * returned unchanged.
7466 f STATUS = INTEGER (Given and Returned)
7467 f The global status.
7468
7469 * Notes:
7470 * - For some classes of Frame, whose coordinate values are not
7471 * constrained, this function will never modify the values
7472 * supplied. However, for Frames whose axes represent cyclic
7473 * quantities (such as angles or positions on the sky), coordinates
7474 * will typically be wrapped into an appropriate standard range,
7475 * such as zero to 2*pi.
7476 * - The NormMap class is a Mapping which can be used to normalise a
7477 * set of points using the
7478 c astNorm function
7479 f AST_NORM routine
7480 * of a specified Frame.
7481 * - It is intended to be possible to put any set of coordinates
7482 * into a form suitable for display by using this function to
7483 * normalise them, followed by appropriate formatting
7484 c (using astFormat).
7485 f (using AST_FORMAT).
7486 *--
7487 */
7488
7489 /* Local Variables: */
7490 AstAxis *ax; /* Pointer to Axis object */
7491 int axis; /* Loop counter for axes */
7492 int naxes; /* Number of Frame axes */
7493
7494 /* Check the global error status. */
7495 if ( !astOK ) return;
7496
7497 /* Obtain the number of Frame axes. */
7498 naxes = astGetNaxes( this );
7499
7500 /* Loop to process the coordinate for each axis in turn. */
7501 for ( axis = 0; axis < naxes; axis++ ) {
7502
7503 /* Obtain a pointer to the relevant Frame Axis. */
7504 ax = astGetAxis( this, axis );
7505
7506 /* Normalise the coordinate for this axis. */
7507 astAxisNorm( ax, value + axis );
7508
7509 /* Annul the pointer to the Axis. */
7510 ax = astAnnul( ax );
7511
7512 /* Quit looping if an error occurs. */
7513 if ( !astOK ) break;
7514 }
7515 }
7516
NormBox(AstFrame * this,double lbnd[],double ubnd[],AstMapping * reg,int * status)7517 static void NormBox( AstFrame *this, double lbnd[], double ubnd[],
7518 AstMapping *reg, int *status ) {
7519 /*
7520 *+
7521 * Name:
7522 * astNormBox
7523
7524 * Purpose:
7525 * Extend a box to include effect of any singularities in the Frame.
7526
7527 * Type:
7528 * Protected virtual function.
7529
7530 * Synopsis:
7531 * #include "frame.h"
7532 * void astNormBox( AstFrame *this, double lbnd[], double ubnd[],
7533 * AstMapping *reg )
7534
7535 * Class Membership:
7536 * Frame method.
7537
7538 * Description:
7539 * This function modifies a supplied box to include the effect of any
7540 * singularities in the co-ordinate system represented by the Frame.
7541 * For a normal Cartesian coordinate system, the box will be returned
7542 * unchanged. Other classes of Frame may do other things. For instance,
7543 * a SkyFrame will check to see if the box contains either the north
7544 * or south pole and extend the box appropriately.
7545
7546 * Parameters:
7547 * this
7548 * Pointer to the Frame.
7549 * lbnd
7550 * An array of double, with one element for each Frame axis
7551 * (Naxes attribute). Initially, this should contain a set of
7552 * lower axis bounds for the box. They will be modified on exit
7553 * to include the effect of any singularities within the box.
7554 * ubnd
7555 * An array of double, with one element for each Frame axis
7556 * (Naxes attribute). Initially, this should contain a set of
7557 * upper axis bounds for the box. They will be modified on exit
7558 * to include the effect of any singularities within the box.
7559 * reg
7560 * A Mapping which should be used to test if any singular points are
7561 * inside or outside the box. The Mapping should leave an input
7562 * position unchanged if the point is inside the box, and should
7563 * set all bad if the point is outside the box.
7564 *-
7565 */
7566
7567 /* This base class returns the box limits unchanged. */
7568 }
7569
Offset2(AstFrame * this,const double point1[2],double angle,double offset,double point2[2],int * status)7570 static double Offset2( AstFrame *this, const double point1[2], double angle,
7571 double offset, double point2[2], int *status ){
7572 /*
7573 *++
7574 * Name:
7575 c astOffset2
7576 f AST_OFFSET2
7577
7578 * Purpose:
7579 * Calculate an offset along a geodesic curve in a 2D Frame.
7580
7581 * Type:
7582 * Public virtual function.
7583
7584 * Synopsis:
7585 c #include "frame.h"
7586 c double astOffset2( AstFrame *this, const double point1[2], double angle,
7587 c double offset, double point2[2] );
7588 f RESULT = AST_OFFSET2( THIS, POINT1, ANGLE, OFFSET, POINT2, STATUS )
7589
7590 * Class Membership:
7591 * Frame method.
7592
7593 * Description:
7594 c This function finds the Frame coordinate values of a point which
7595 f This routine finds the Frame coordinate values of a point which
7596 * is offset a specified distance along the geodesic curve at a
7597 * given angle from a specified starting point. It can only be
7598 * used with 2-dimensional Frames.
7599 *
7600 * For example, in a basic Frame, this offset will be along the
7601 * straight line joining two points. For a more specialised Frame
7602 * describing a sky coordinate system, however, it would be along
7603 * the great circle passing through two sky positions.
7604
7605 * Parameters:
7606 c this
7607 f THIS = INTEGER (Given)
7608 * Pointer to the Frame.
7609 c point1
7610 f POINT1( * ) = DOUBLE PRECISION (Given)
7611 c An array of double, with one element for each Frame axis
7612 f An array with one element for each Frame axis
7613 * (Naxes attribute). This should contain the coordinates of the
7614 * point marking the start of the geodesic curve.
7615 c angle
7616 f ANGLE = DOUBLE PRECISION (Given)
7617 * The angle (in radians) from the positive direction of the second
7618 * axis, to the direction of the required position, as seen from
7619 * the starting position. Positive rotation is in the sense of
7620 * rotation from the positive direction of axis 2 to the positive
7621 * direction of axis 1.
7622 c offset
7623 f OFFSET = DOUBLE PRECISION
7624 * The required offset from the first point along the geodesic
7625 * curve. If this is positive, it will be in the direction of the
7626 * given angle. If it is negative, it will be in the opposite
7627 * direction.
7628 c point2
7629 f POINT2( * ) = DOUBLE PRECISION (Returned)
7630 c An array of double, with one element for each Frame axis
7631 f An array with one element for each Frame axis
7632 * in which the coordinates of the required point will be returned.
7633 f STATUS = INTEGER (Given and Returned)
7634 f The global status.
7635
7636 * Returned Value:
7637 c astOffset2
7638 f AST_OFFSET2 = DOUBLE PRECISION
7639 * The direction of the geodesic curve at the end point. That is, the
7640 * angle (in radians) between the positive direction of the second
7641 * axis and the continuation of the geodesic curve at the requested
7642 * end point. Positive rotation is in the sense of rotation from
7643 * the positive direction of axis 2 to the positive direction of axis
7644 * 1.
7645
7646 * Notes:
7647 c - The geodesic curve used by this function is the path of
7648 f - The geodesic curve used by this routine is the path of
7649 * shortest distance between two points, as defined by the
7650 c astDistance function.
7651 f AST_DISTANCE function.
7652 * - An error will be reported if the Frame is not 2-dimensional.
7653 * - This function will return "bad" coordinate values (AST__BAD)
7654 * if any of the input coordinates has this value.
7655 *--
7656 */
7657
7658 /* Local Variables: */
7659 int naxes; /* Number of Frame axes */
7660 double result; /* Returned value */
7661
7662 /* Check the global error status. */
7663 result = AST__BAD;
7664 if ( !astOK ) return result;
7665
7666 /* Initialize bad values. */
7667 point2[ 0 ] = AST__BAD;
7668 point2[ 1 ] = AST__BAD;
7669
7670 /* Determine the number of Frame axes. */
7671 naxes = astGetNaxes( this );
7672
7673 /* Report an error if the Frame is not 2 dimensional. */
7674 if( naxes != 2 && astOK ) {
7675 astError( AST__NAXIN, "astOffset2(%s): Invalid number of Frame axes (%d)."
7676 " astOffset2 can only be used with 2 dimensonal Frames.", status,
7677 astGetClass( this ), naxes );
7678 }
7679
7680 /* Check the supplied values. */
7681 if ( astOK && point1[ 0 ] != AST__BAD && point1[ 1 ] != AST__BAD &&
7682 angle != AST__BAD && offset != AST__BAD ) {
7683
7684 /* Store the results. */
7685 point2[ 0 ] = point1[ 0 ] + sin( angle )*offset;
7686 point2[ 1 ] = point1[ 1 ] + cos( angle )*offset;
7687
7688 /* The position angle of the curve does not vary in cartesian coordinates */
7689 result = angle;
7690
7691 }
7692
7693 /* Return the result. */
7694 return result;
7695
7696 }
7697
Offset(AstFrame * this,const double point1[],const double point2[],double offset,double point3[],int * status)7698 static void Offset( AstFrame *this, const double point1[],
7699 const double point2[], double offset, double point3[], int *status ) {
7700 /*
7701 *++
7702 * Name:
7703 c astOffset
7704 f AST_OFFSET
7705
7706 * Purpose:
7707 * Calculate an offset along a geodesic curve.
7708
7709 * Type:
7710 * Public virtual function.
7711
7712 * Synopsis:
7713 c #include "frame.h"
7714 c void astOffset( AstFrame *this,
7715 c const double point1[], const double point2[],
7716 c double offset, double point3[] )
7717 f CALL AST_OFFSET( THIS, POINT1, POINT2, OFFSET, POINT3, STATUS )
7718
7719 * Class Membership:
7720 * Frame method.
7721
7722 * Description:
7723 c This function finds the Frame coordinate values of a point which
7724 f This routine finds the Frame coordinate values of a point which
7725 * is offset a specified distance along the geodesic curve between
7726 * two other points.
7727 *
7728 * For example, in a basic Frame, this offset will be along the
7729 * straight line joining two points. For a more specialised Frame
7730 * describing a sky coordinate system, however, it would be along
7731 * the great circle passing through two sky positions.
7732
7733 * Parameters:
7734 c this
7735 f THIS = INTEGER (Given)
7736 * Pointer to the Frame.
7737 c point1
7738 f POINT1( * ) = DOUBLE PRECISION (Given)
7739 c An array of double, with one element for each Frame axis
7740 f An array with one element for each Frame axis
7741 * (Naxes attribute). This should contain the coordinates of the
7742 * point marking the start of the geodesic curve.
7743 c point2
7744 f POINT2( * ) = DOUBLE PRECISION (Given)
7745 c An array of double, with one element for each Frame axis
7746 f An array with one element for each Frame axis.
7747 * This should contain the coordinates of the point marking the
7748 * end of the geodesic curve.
7749 c offset
7750 f OFFSET = DOUBLE PRECISION
7751 * The required offset from the first point along the geodesic
7752 * curve. If this is positive, it will be towards the second
7753 * point. If it is negative, it will be in the opposite
7754 * direction. This offset need not imply a position lying
7755 * between the two points given, as the curve will be
7756 * extrapolated if necessary.
7757 c point3
7758 f POINT3( * ) = DOUBLE PRECISION (Returned)
7759 c An array of double, with one element for each Frame axis
7760 f An array with one element for each Frame axis
7761 * in which the coordinates of the required point will be returned.
7762 f STATUS = INTEGER (Given and Returned)
7763 f The global status.
7764
7765 * Notes:
7766 c - The geodesic curve used by this function is the path of
7767 f - The geodesic curve used by this routine is the path of
7768 * shortest distance between two points, as defined by the
7769 c astDistance function.
7770 f AST_DISTANCE function.
7771 * - This function will return "bad" coordinate values (AST__BAD)
7772 * if any of the input coordinates has this value.
7773 * - "Bad" coordinate values will also be returned if the two
7774 * points supplied are coincident (or otherwise fail to uniquely
7775 * specify a geodesic curve) but the requested offset is non-zero.
7776 *--
7777 */
7778
7779 /* Local Variables: */
7780 double delta; /* Displacement along axis */
7781 double dist; /* Distance between points */
7782 double fract; /* Fraction of distance required */
7783 int axis; /* Loop counter for axes */
7784 int naxes; /* Number of Frame axes */
7785
7786 /* Check the global error status. */
7787 if ( !astOK ) return;
7788
7789 /* Determine the number of Frame axes. */
7790 naxes = astGetNaxes( this );
7791 if ( astOK ) {
7792
7793 /* Loop to determine the Cartesian distance between points 1 and 2. */
7794 dist = 0.0;
7795 for ( axis = 0; axis < naxes; axis++ ) {
7796
7797 /* If any of the coordinates supplied is bad, set the distance to be
7798 bad and quit looping. */
7799 if ( ( point1[ axis ] == AST__BAD ) ||
7800 ( point2[ axis ] == AST__BAD ) ) {
7801 dist = AST__BAD;
7802 break;
7803
7804 /* Otherwise, accumulate the sum of squared displacements along each
7805 axis. */
7806 } else {
7807 delta = point1[ axis ] - point2[ axis ];
7808 dist += ( delta * delta );
7809 }
7810 }
7811
7812 /* Take the square root to find the distance (if valid). */
7813 if ( dist != AST__BAD ) dist = sqrt( dist );
7814
7815 /* If the distance between the points cannot be found, or the distance
7816 is zero but the required offset is non-zero, then set the result
7817 coordinates to be bad. */
7818 if ( ( dist == AST__BAD ) ||
7819 ( ( dist == 0.0 ) && ( offset != 0.0 ) ) ) {
7820 for ( axis = 0; axis < naxes; axis++ ) {
7821 point3[ axis ] = AST__BAD;
7822 }
7823
7824 /* Otherwise, calculate what fraction of the distance between the
7825 points we need to move, and apply this fraction of the displacement
7826 along each axis. */
7827 } else {
7828 fract = ( dist == 0.0 ) ? 0.0 : offset / dist;
7829 for ( axis = 0; axis < naxes; axis++ ) {
7830 point3[ axis ] = point1[ axis ] +
7831 fract * ( point2[ axis ] - point1[ axis ] );
7832 }
7833 }
7834 }
7835 }
7836
Overlay(AstFrame * template,const int * template_axes,AstFrame * result,int * status)7837 static void Overlay( AstFrame *template, const int *template_axes,
7838 AstFrame *result, int *status ) {
7839 /*
7840 *+
7841 * Name:
7842 * astOverlay
7843
7844 * Purpose:
7845 * Overlay the attributes of a template Frame on to another Frame.
7846
7847 * Type:
7848 * Protected virtual function.
7849
7850 * Synopsis:
7851 * #include "frame.h"
7852 * void astOverlay( AstFrame *template, const int *template_axes,
7853 * AstFrame *result )
7854
7855 * Class Membership:
7856 * Frame method.
7857
7858 * Description:
7859 * This function overlays attributes of one Frame (the "template") on to
7860 * another Frame, so as to over-ride selected attributes of that second
7861 * Frame. Normally only those attributes which have been specifically set
7862 * in the template will be transferred. This implements a form of
7863 * defaulting, in which a Frame acquires attributes from the template, but
7864 * retains its original attributes (as the default) if new values have not
7865 * previously been explicitly set in the template.
7866
7867 * Parameters:
7868 * template
7869 * Pointer to the template Frame, for which values should have been
7870 * explicitly set for any attribute which is to be transferred.
7871 * template_axes
7872 * Pointer to an array of int, with one element for each axis of the
7873 * "result" Frame (see below). For each axis in the result frame, the
7874 * corresponding element of this array should contain the (zero-based)
7875 * index of the template axis to which it corresponds. This array is used
7876 * to establish from which template axis any axis-dependent attributes
7877 * should be obtained.
7878 *
7879 * If any axis in the result Frame is not associated with a template
7880 * axis, the corresponding element of this array should be set to -1.
7881 *
7882 * If a NULL pointer is supplied, the template and result axis
7883 * indicies are assumed to be identical.
7884 * result
7885 * Pointer to the Frame which is to receive the new attribute values.
7886 *-
7887 */
7888
7889 /* Local Variables: */
7890 AstAxis *result_ax; /* Pointer to result Axis object */
7891 AstAxis *template_ax; /* Pointer to template Axis object */
7892 AstSystemType sys; /* System value */
7893 int result_axis; /* Loop counter for result Frame axes */
7894 int result_naxes; /* Number of result Frame axes */
7895 int template_axis; /* Index of template Frame axis */
7896 int template_naxes; /* Number of template Frame axes */
7897
7898 /* Check the global error status. */
7899 if ( !astOK ) return;
7900
7901 /* Define a macro that tests whether an attribute is set in the template and,
7902 if so, transfers its value to the target. */
7903 #define OVERLAY(attribute) \
7904 if ( astTest##attribute( template ) ) { \
7905 astSet##attribute( result, astGet##attribute( template ) ); \
7906 }
7907
7908 /* Use the macro to transfer each Frame attribute in turn. */
7909 OVERLAY(Dut1);
7910 OVERLAY(Digits);
7911 OVERLAY(Domain);
7912 OVERLAY(Epoch);
7913 OVERLAY(Title);
7914 OVERLAY(ObsLat)
7915 OVERLAY(ObsLon)
7916 OVERLAY(ObsAlt)
7917
7918 /* Transfer the ActiveUnit flag. */
7919 astSetActiveUnit( result, astGetActiveUnit( template ) );
7920
7921 /* Only overlay the System and AlignSystem attribute if the values are
7922 valid for the result class. */
7923 if( astTestSystem( template ) ) {
7924 sys = astGetSystem( template );
7925 if( astValidateSystem( result, sys, "astOverlay" ) ) {
7926 astSetSystem( result, sys );
7927 }
7928 }
7929
7930 if( astTestAlignSystem( template ) ) {
7931 sys = astGetAlignSystem( template );
7932 if( astValidateSystem( result, sys, "astOverlay" ) ) {
7933 astSetAlignSystem( result, sys );
7934 }
7935 }
7936
7937 /* Now transfer attributes associated with individual axes. Obtain the number
7938 of axes in the template and result Frames. */
7939 template_naxes = astGetNaxes( template );
7940 result_naxes = astGetNaxes( result );
7941 if ( astOK ) {
7942
7943 /* Loop through all the axes in the result Frame and determine to which
7944 template axis each one corresponds. Check that the resulting axis index is
7945 valid. If not, then the axis will not receive new attributes. */
7946 for ( result_axis = 0; result_axis < result_naxes; result_axis++ ) {
7947 template_axis = template_axes ? template_axes[ result_axis ] : result_axis;
7948 if ( ( template_axis >= 0 ) && ( template_axis < template_naxes ) ) {
7949
7950 /* Obtain pointers to the relevant Axis objects of each Frame and use the
7951 astAxisOverlay method of the template Axis to overlay attributes on to
7952 the result Axis. Annul the Axis pointers afterwards. */
7953 template_ax = astGetAxis( template, template_axis );
7954 result_ax = astGetAxis( result, result_axis );
7955 astAxisOverlay( template_ax, result_ax );
7956 template_ax = astAnnul( template_ax );
7957 result_ax = astAnnul( result_ax );
7958
7959 /* Quit looping if an error occurs. */
7960 if ( !astOK ) break;
7961 }
7962 }
7963 }
7964
7965 /* Undefine macros local to this function. */
7966 #undef OVERLAY
7967 }
7968
PermAxes(AstFrame * this,const int perm[],int * status)7969 static void PermAxes( AstFrame *this, const int perm[], int *status ) {
7970 /*
7971 *+
7972 * Name:
7973 * astPermAxes
7974
7975 * Purpose:
7976 * Permute the order of a Frame's axes.
7977
7978 * Type:
7979 * Protected virtual function.
7980
7981 * Synopsis:
7982 * #include "frame.h"
7983 * void astPermAxes( AstFrame *this, const int perm[] )
7984
7985 * Class Membership:
7986 * Frame method.
7987
7988 * Description:
7989 * This function permutes the order in which a Frame's axes occur.
7990
7991 * Parameters:
7992 * this
7993 * Pointer to the Frame.
7994 * perm
7995 * An array of int (with one element for each axis of the Frame)
7996 * which lists the axes in their new order. Each element of this
7997 * array should be a (zero-based) axis index identifying the
7998 * axes according to their old (un-permuted) order.
7999
8000 * Notes:
8001 * - Only genuine permutations of the axis order are permitted, so
8002 * each axis must be referenced exactly once in the "perm" array.
8003 * - If more than one axis permutation is applied to a Frame, the
8004 * effects are cumulative.
8005 *-
8006
8007 * Implementation Notes:
8008 * - This function implements the basic astPermAxes method which is
8009 * available via the protected interface to the Frame class. A
8010 * public interface to this method is provided by the
8011 * astPermAxesId_ function.
8012 */
8013
8014 /* Local Variables: */
8015 int *old; /* Pointer to copy of old permutation array */
8016 int axis; /* Loop counter for Frame axes */
8017 int naxes; /* Number of Frame axes */
8018
8019 /* Check the global error status. */
8020 if ( !astOK ) return;
8021
8022 /* Validate the permutation array, to check that it describes a genuine
8023 permutation. */
8024 astCheckPerm( this, perm, "astPermAxes" );
8025
8026 /* Obtain the number of Frame axes. */
8027 naxes = astGetNaxes( this );
8028
8029 /* Allocate memory and use it to store a copy of the old permutation array for
8030 the Frame. */
8031 old = astStore( NULL, this->perm, sizeof( int ) * (size_t) naxes );
8032
8033 /* Apply the new axis permutation cumulatively to the old one and store the
8034 result in the Frame. */
8035 if ( astOK ) {
8036 for ( axis = 0; axis < naxes; axis++ ) {
8037 this->perm[ axis ] = old[ perm[ axis ] ];
8038 }
8039 }
8040
8041 /* Free the temporary copy of the old array. */
8042 old = astFree( old );
8043 }
8044
PickAxes(AstFrame * this,int naxes,const int axes[],AstMapping ** map,int * status)8045 static AstFrame *PickAxes( AstFrame *this, int naxes, const int axes[],
8046 AstMapping **map, int *status ) {
8047 /*
8048 *+
8049 * Name:
8050 * astPickAxes
8051
8052 * Purpose:
8053 * Create a new Frame by picking axes from an existing one.
8054
8055 * Type:
8056 * Protected virtual function.
8057
8058 * Synopsis:
8059 * #include "frame.h"
8060 * AstFrame *PickAxes( AstFrame *this, int naxes, const int axes[],
8061 * AstMapping **map )
8062
8063 * Class Membership:
8064 * Frame method.
8065
8066 * Description:
8067 * This function creates a new Frame whose axes are copies of axes
8068 * picked from an existing Frame. Other Frame attributes are also
8069 * copied to the new Frame. Zero or more of the original axes may
8070 * be picked in any order, but each can be used only
8071 * once. Additional axes (with default characteristics) may be
8072 * included in the new Frame if required.
8073 *
8074 * Optionally, a Mapping that converts between the original Frame's
8075 * axes and those of the new Frame may also be returned.
8076
8077 * Parameters:
8078 * this
8079 * Pointer to the original Frame.
8080 * naxes
8081 * The number of axes required in the new Frame.
8082 * axes
8083 * Pointer to an array of int with naxes elements. This should
8084 * contain (zero based) axis indices specifying the axes which
8085 * are to be included in the new Frame, in the order
8086 * required. Each axis index may occur only once.
8087 *
8088 * If additional (default) axes are also to be included, the
8089 * corresponding elements of this array should be set to -1.
8090 * map
8091 * Address of a location to receive a pointer to a new
8092 * Mapping. This will be a PermMap (or a UnitMap as a special
8093 * case) that describes the axis permutation that has taken
8094 * place between the original and new Frames. The forward
8095 * transformation will convert from the original Frame's axes to
8096 * the new one's, and vice versa.
8097 *
8098 * If this Mapping is not required, a NULL value may be supplied
8099 * for this parameter.
8100
8101 * Returned Value:
8102 * Pointer to the new Frame.
8103
8104 * Notes:
8105 * - The class of object returned may differ from that of the
8106 * original Frame, depending on which axes are selected. For
8107 * example, if a single axis is picked from a SkyFrame (which
8108 * always has two axes), the resulting Frame cannot be a valid
8109 * SkyFrame, so will revert to the parent class (Frame) instead.
8110 * - The new Frame contains a deep copy of all the data selected
8111 * from the original Frame. Modifying the new Frame will therefore
8112 * not affect the original one.
8113 * - A NULL pointer will be returned if this function is invoked
8114 * with the global error status set, or if it should fail for any
8115 * reason.
8116 *-
8117
8118 * Implementation Notes:
8119 * - This function implements the basic astPickAxes method
8120 * available via the protected interface to the Frame class. The
8121 * public interface to this method is provided by the
8122 * astPickAxesId_ function.
8123 */
8124
8125 /* Local Variables: */
8126 AstFrame *frame; /* Pointer to Frame to be returned */
8127 AstMapping *mapping; /* Pointer to Mapping to be returned */
8128
8129 /* Check the global error status. */
8130 if ( !astOK ) return NULL;
8131
8132 /* Initialise the returned pointers. */
8133 frame = NULL;
8134 if ( map ) *map = NULL;
8135
8136 /* Check that a valid set of axes is being selected . */
8137 astValidateAxisSelection( this, naxes, axes, "astPickAxes" );
8138
8139 /* Create the required new Frame by selecting the axes. This also returns a
8140 Mapping which transforms between the original Frame and the new one. */
8141 astSubFrame( this, NULL, naxes, axes, NULL, &mapping, &frame );
8142 if ( astOK ) {
8143
8144 /* Return the Mapping pointer if required. */
8145 if ( map ) {
8146 *map = mapping;
8147
8148 /* Otherwise annul the Mapping. If an error occurs, also annul the Frame. */
8149 } else {
8150 mapping = astAnnul( mapping );
8151 if ( !astOK ) frame = astAnnul( frame );
8152 }
8153 }
8154
8155 /* Return the pointer to the new Frame. */
8156 return frame;
8157 }
8158
PrimaryFrame(AstFrame * this,int axis1,AstFrame ** frame,int * axis2,int * status)8159 static void PrimaryFrame( AstFrame *this, int axis1,
8160 AstFrame **frame, int *axis2, int *status ) {
8161 /*
8162 *+
8163 * Name:
8164 * astPrimaryFrame
8165
8166 * Purpose:
8167 * Uniquely identify a primary Frame and one of its axes.
8168
8169 * Type:
8170 * Protected virtual function.
8171
8172 * Synopsis:
8173 * #include "frame.h"
8174 * void astPrimaryFrame( AstFrame *this, int axis1, AstFrame **frame,
8175 * int *axis2 )
8176
8177 * Class Membership:
8178 * Frame method.
8179
8180 * Description:
8181 * This function returns information about the underlying (primary) Frame
8182 * corresponding to a specified axis, when given what may be a compound
8183 * Frame composed of more than one simpler one.
8184
8185 * Parameters:
8186 * this
8187 * Pointer to the Frame.
8188 * axis1
8189 * An axis index (zero-based) identifying the Frame axis for which
8190 * information is required.
8191 * frame
8192 * Address of a location to receive a pointer to the underlying (primary)
8193 * frame to which the requested axis belongs (i.e. this will not be a
8194 * compound Frame).
8195 * axis2
8196 * Pointer to an int which is to receive the (zero-based) axis
8197 * index within "frame" which identifies the axis being referred
8198 * to, using the axis order that applied when the primary Frame
8199 * was originally constructed (i.e. this function undoes all
8200 * subsequent axis pemutations and the effects of combining
8201 * Frames, in order to reveal the original underlying axis
8202 * order).
8203
8204 * Notes:
8205 * - This protected method is provided so that class implementations can
8206 * distinguish the axes of frames from one another (e.g. can distinguish
8207 * a longitude axis as being different from a latitide axis) even after
8208 * their order has been permuted and they have been combined with axes from
8209 * other Frames.
8210 * - The reference count of the primary Frame will be incremented by one to
8211 * reflect the new pointer returned.
8212 *-
8213 */
8214
8215 /* Check the global error status. */
8216 if ( !astOK ) return;
8217
8218 /* Initialise the returned values. */
8219 *frame = NULL;
8220 *axis2 = 0;
8221
8222 /* Validate and permute the axis index supplied. */
8223 axis1 = astValidateAxis( this, axis1, 1, "astPrimaryFrame" );
8224
8225 /* Since "this" is a primary Frame (i.e. is not compound), simply clone a
8226 pointer to it. */
8227 if ( astOK ) *frame = astClone( this );
8228
8229 /* Return the permuted axis index, which refers to the original axis order. */
8230 if ( astOK ) *axis2 = axis1;
8231 }
8232
astReadDateTime_(const char * value,int * status)8233 double astReadDateTime_( const char *value, int *status ) {
8234 /*
8235 *+
8236 * Name:
8237 * astReadDateTime
8238
8239 * Purpose:
8240 * Read a date/time string.
8241
8242 * Type:
8243 * Private function.
8244
8245 * Synopsis:
8246 * #include "frame.h"
8247 * double astReadDateTime( const char *value )
8248
8249 * Class Membership:
8250 * Frame member function.
8251
8252 * Description:
8253 * This function reads a date/time string in a variety of formats and
8254 * returns the resulting time as a Modified Julian Date. If the string
8255 * cannot be interpreted as a date/time or contains invalid values, an
8256 * error is reported.
8257
8258 * Parameters:
8259 * value
8260 * Pointer to a null terminated string containing the value to be read.
8261
8262 * Returned Value:
8263 * The time as a Modified Julian date.
8264
8265 * Date/Time Formats:
8266 * The date/time formats supported by this function are listed below. These
8267 * are interpreted in a case-insensitive manner and the function is
8268 * generally flexible about the presence of additional white space and the
8269 * use of alternative field delimiters.
8270 *
8271 * Besselian Epoch
8272 * Expressed in decimal years, with or without decimal places
8273 * ("B1950" or "B1976.13", for example).
8274 * Julian Epoch
8275 * Expressed in decimal years, with or without decimal places
8276 * ("J2000" or "J2100.9", for example).
8277 * Year
8278 * Decimal years, with or without decimal places ("1996.8" for example).
8279 * Such values are interpreted as a Besselian epoch (see above) if less
8280 * than 1984.0 and as a Julian epoch otherwise.
8281 * Julian Date
8282 * With or without decimal places ("JD 2454321.9" for example).
8283 * Modified Julian Date
8284 * With or without decimal places ("MJD 54321.4" for example).
8285 * Gregorian Calendar Date
8286 * With the month expressed as an integer or 3-character
8287 * abbreviation, and with optional decimal places to represent a
8288 * fraction of a day ("1996-10-2" or "1996-Oct-2.6" for
8289 * example). If no fractional part of a day is given, the time
8290 * refers to the start of the day (zero hours).
8291 * Gregorian Date and Time
8292 * Any calendar date (as above) but with a fraction of a day expressed
8293 * as hours, minutes and seconds ("1996-Oct-2 12:13:56.985" for example).
8294 * The date and time can be separated by a space or by a "T" (as used
8295 * by ISO8601).
8296
8297 * Notes:
8298 * - The date/time value is interpreted as a calendar date and time, not
8299 * linked to any particular time system. Thus, interpretation of hours,
8300 * minutes and seconds is done in the obvious manner assuming 86400 seconds
8301 * in a day. No allowance for is made, for instance, for leap seconds or for
8302 * the varying length of a second in some time systems.
8303 * - A value of AST__BAD is returned if this function is invoked with the
8304 * global error status set or if it should fail for any reason.
8305 *-
8306 */
8307
8308 /* Local Vaiables: */
8309 char cmonth[ 4 ]; /* Buffer for name of month */
8310 char sep1[ 2 ]; /* Year/month separator string */
8311 char sep2[ 2 ]; /* Month/day separator string */
8312 char sep3[ 2 ]; /* Hour/minute separator string */
8313 char sep4[ 2 ]; /* Minute/second separator string */
8314 char *cc; /* Pointer to copy of remaining text */
8315 const char *v; /* Pointer into value string */
8316 const char *p; /* Pointer to date/time separator */
8317 double day; /* Day number plus fraction of whole day */
8318 double epoch; /* Epoch stored as decimal years */
8319 double hms; /* Hours, min & sec as fraction of a day */
8320 double jd; /* Julian Date */
8321 double mjd; /* Modified Julian Date */
8322 double result; /* Result to be returned */
8323 double sec; /* Seconds and fractions of a second */
8324 int hour; /* Number of hours */
8325 int iday; /* Number of whole days */
8326 int l; /* Length of string remaining */
8327 int len; /* Length of string */
8328 int match; /* Date/time string has correct form? */
8329 int minute; /* Number of minutes */
8330 int month; /* Number of months */
8331 int nc; /* Number of characters read from string */
8332 int stat; /* Status return from SLALIB functions */
8333 int year; /* Number of years */
8334
8335 /* Check the global error status. */
8336 if ( !astOK ) return AST__BAD;
8337
8338 /* Initialise. */
8339 result = AST__BAD;
8340
8341 /* Obtain the length of the input string. */
8342 len = (int) strlen( value );
8343
8344 /* Attempt to read the string using each recognised format in turn. */
8345
8346 /* Besselian epoch in decimal years (e.g. "B1950.0"). */
8347 /* ================================================== */
8348 if ( nc = 0,
8349 ( 1 == astSscanf( value, " %*1[Bb] %lf %n", &epoch, &nc ) )
8350 && ( nc >= len ) ) {
8351
8352 /* Convert to Modified Julian Date. */
8353 result = palEpb2d( epoch );
8354
8355 /* Julian epoch in decimal years (e.g. "J2000.0"). */
8356 /* =============================================== */
8357 } else if ( nc = 0,
8358 ( 1 == astSscanf( value, " %*1[Jj] %lf %n", &epoch, &nc ) )
8359 && ( nc >= len ) ) {
8360
8361 /* Convert to Modified Julian Date. */
8362 result = palEpj2d( epoch );
8363
8364 /* Decimal years (e.g. "1976.2"). */
8365 /* ============================== */
8366 } else if ( nc = 0,
8367 ( 1 == astSscanf( value, " %lf %n", &epoch, &nc ) )
8368 && ( nc >= len ) ) {
8369
8370 /* Convert to Modified Julian Date, treating the epoch as Julian or Besselian
8371 depending on whether it is 1984.0 or later. */
8372 result = ( epoch < 1984.0 ) ? palEpb2d( epoch ) : palEpj2d( epoch );
8373
8374 /* Modified Julian Date (e.g. "MJD 54321.0"). */
8375 /* ============================================ */
8376 } else if ( nc = 0,
8377 ( 1 == astSscanf( value, " %*1[Mm] %*1[Jj] %*1[Dd] %lf %n",
8378 &mjd, &nc ) ) && ( nc >= len ) ) {
8379
8380 /* Use the result directly. */
8381 result = mjd;
8382
8383 /* Julian Date (e.g. "JD 2454321.5"). */
8384 /* ==================================== */
8385 } else if ( nc = 0,
8386 ( 1 == astSscanf( value, " %*1[Jj] %*1[Dd] %lf %n",
8387 &jd, &nc ) ) && ( nc >= len ) ) {
8388
8389 /* Convert to Modified Julian Date. */
8390 result = jd - 2400000.5;
8391
8392 /* Gregorian calendar date (e.g. "1996-10-2" or "1996-Oct-2"). */
8393 /* =========================================================== */
8394 /* This format also allows day fractions expressed as decimal days, e.g:
8395
8396 "1996-Oct-2.5001"
8397
8398 or as hours, minutes and seconds, e.g:
8399
8400 "1996-Oct-2 12:14:30.52"
8401
8402 Various alternative field delimiters are also allowed. */
8403 } else {
8404
8405 /* Note that the method used to parse this format relies heavily on
8406 conditional execution controlled by "&&" and "||" operators. Initialise
8407 the variables used. */
8408 v = value;
8409 l = len;
8410 *cmonth = '\0';
8411 year = month = iday = hour = minute = 0;
8412 day = sec = 0.0;
8413
8414 /* Identify the year and month. */
8415 /* ---------------------------- */
8416 /* Try to match an initial " 1996 - 10 -" or " 1996 10 " or similar. */
8417 match =
8418 ( nc = 0, ( 4 == astSscanf( v, " %d %1[:/-] %2d %1[:/-]%n",
8419 &year, sep1, &month, sep2, &nc ) ) );
8420 match = match ||
8421 ( nc = 0, ( 4 == astSscanf( v, " %d%1[ ] %2d%1[ ]%n",
8422 &year, sep1, &month, sep2, &nc ) ) );
8423
8424 /* If that failed, allow " 1996 - Oct -" or " 1996 Oct " or similar. */
8425 match = match ||
8426 ( nc = 0, ( 4 == astSscanf( v,
8427 " %d %1[:/-] %3[ABCDEFGHIJKLMNOPQRSTUVWXYZ"
8428 "abcdefghijklmnopqrstuvwxyz] %1[:/-]%n",
8429 &year, sep1, cmonth, sep2, &nc ) ) );
8430 match = match ||
8431 ( nc = 0, ( 4 == astSscanf( v,
8432 " %d%1[ ] %3[ABCDEFGHIJKLMNOPQRSTUVWXYZ"
8433 "abcdefghijklmnopqrstuvwxyz]%1[ ]%n",
8434 &year, sep1, cmonth, sep2, &nc ) ) );
8435
8436 /* Alternative field separators are permitted above, but ensure that
8437 they are both the same. */
8438 match = match && ( *sep1 == *sep2 );
8439
8440 /* Identify the day and fraction of day. */
8441 /*-------------------------------------- */
8442 /* If the above matched correctly, modify the string pointer "v" to
8443 the next character to be interpreted and decrement the remaining
8444 string length. */
8445 if ( match ) {
8446 v += nc;
8447 l -= nc;
8448
8449 /* ISO8601 format uses the litter T as a delimiter between the date and time.
8450 If there is a T in the remaining string, take a copy and change the T to
8451 a space. */
8452 p = strchr( v, 'T' );
8453 if( p ) {
8454 cc = astStore( NULL, v, l + 1 );
8455 cc[ p - v ] = ' ';
8456 v = cc;
8457 } else {
8458 cc = NULL;
8459 }
8460
8461 /* We now try to match the following characters but without reading
8462 any values. This is done to ensure the string has the correct form
8463 (e.g. exclude "-" signs and exponents in numbers, which are
8464 otherwise hard to detect). */
8465
8466 /* Try to match " 12.3456 " or similar. */
8467 match =
8468 ( nc = 0, ( 0 == astSscanf( v, " %*2[0123456789].%*[0123456789] %n",
8469 &nc ) )
8470 && ( nc == l ) );
8471
8472 /* If that failed, then try to match " 12. " or similar. */
8473 match = match ||
8474 ( nc = 0, ( 0 == astSscanf( v, " %*2[0123456789]. %n", &nc ) )
8475 && ( nc == l ) );
8476
8477 /* If that also failed, then try to match just " 12 " or similar. */
8478 match = match ||
8479 ( nc = 0, ( 0 == astSscanf( v, " %*2[0123456789] %n", &nc ) )
8480 && ( nc == l ) );
8481
8482 /* If any of the above patterns matched, now read the data (the day number)
8483 as a double value. */
8484 if ( match ) {
8485 match = ( nc = 0, ( 1 == astSscanf( v, " %lf %n", &day, &nc ) )
8486 && ( nc == l ) );
8487
8488 /* If none of the above matched, then look to see if the day fraction has been
8489 given in hours, minutes and seconds by trying to match " 12 03 : 45 :" or
8490 " 12 13 45 " or similar. */
8491 } else {
8492 match =
8493 ( nc = 0, ( 5 == astSscanf( v,
8494 " %2d%*1[ ] %2d %1[:/-] %2d %1[:/-]%n",
8495 &iday, &hour, sep3, &minute, sep4,
8496 &nc ) ) );
8497 match = match ||
8498 ( nc = 0, ( 5 == astSscanf( v, " %2d%*1[ ] %2d%1[ ] %2d%1[ ]%n",
8499 &iday, &hour, sep3, &minute, sep4,
8500 &nc ) ) );
8501
8502 /* Alternative field separators are permitted above, but ensure that
8503 they are both the same. */
8504 match = match && ( *sep3 == *sep4 );
8505
8506 /* If the day number was read as an integer, convert it to double. */
8507 if ( match ) day = (double) iday;
8508
8509 /* If no match, see if we can get a match without a trailing seconds field. */
8510 if( !match ) {
8511 match =
8512 ( nc = 0, ( 4 == astSscanf( v,
8513 " %2d%*1[ ] %2d %1[:/-] %2d %n",
8514 &iday, &hour, sep3, &minute, &nc ) &&
8515 ( nc == l ) ) );
8516 match = match ||
8517 ( nc = 0, ( 4 == astSscanf( v, " %2d%*1[ ] %2d%1[ ] %2d %n",
8518 &iday, &hour, sep3, &minute, &nc ) &&
8519 ( nc == l ) ) );
8520
8521 /* If the day number was read as an integer, convert it to double. */
8522 if ( match ) day = (double) iday;
8523
8524 /* Otherwise, identify the seconds field. */
8525 /* -------------------------------------- */
8526 /* If hours and minutes fields have been matched, now look for the
8527 final seconds (and fractions of seconds) field. This is similar to
8528 the day/fraction field (see earlier) in that we first check that it
8529 has the correct form before reading its value. */
8530
8531 /* Adjust the string pointer and remaining string length. */
8532 } else {
8533 v += nc;
8534 l -= nc;
8535
8536 /* Try to match " 12.3456 " or similar. */
8537 match =
8538 ( nc = 0, ( 0 == astSscanf( v,
8539 " %*2[0123456789].%*[0123456789] %n",
8540 &nc ) )
8541 && ( nc == l ) );
8542
8543 /* If that failed, then try to match " 12. " or similar. */
8544 match = match ||
8545 ( nc = 0, ( 0 == astSscanf( v, " %*2[0123456789]. %n", &nc ) )
8546 && ( nc == l ) );
8547
8548 /* If that also failed, then try to match just " 12 " or similar. */
8549 match = match ||
8550 ( nc = 0, ( 0 == astSscanf( v, " %*2[0123456789] %n", &nc ) )
8551 && ( nc == l ) );
8552
8553 /* If any of the above patterns matched, now read the data (the number of
8554 seconds) as a double value. */
8555 if ( match ) {
8556 match = ( nc = 0, ( 1 == astSscanf( v, " %lf %n", &sec, &nc ) )
8557 && ( nc == l ) );
8558 }
8559 }
8560 }
8561
8562 /* Free resources */
8563 if( cc ) cc = astFree( cc );
8564
8565 }
8566
8567 /* Interpret the values that were read. */
8568 /* ------------------------------------ */
8569 /* We execute this if all of the above text matching was successful,
8570 transferred the required number of data values, and consumed the
8571 entire input string. */
8572 if ( match ) {
8573
8574 /* See if the month was given as a character string (e.g. "Oct") instead of
8575 a number. If so, define local variables for use in converting it. */
8576 if ( *cmonth ) {
8577 char lcmonth[ 4 ]; /* Lower case copy of month string */
8578 const char *ptr; /* Pointer result from look up */
8579 const char *table = /* Month look up table */
8580 "jan feb mar apr may jun jul aug sep oct nov dec";
8581 int i; /* Loop counter for characters */
8582
8583 /* Convert the month string to lower case. */
8584 for ( i = 0; cmonth[ i ]; i++ ) {
8585 lcmonth[ i ] = tolower( cmonth[ i ] );
8586 }
8587 lcmonth[ i ] = '\0';
8588
8589 /* Look the month up in the table of months and generate the required month
8590 number. */
8591 if ( ( ptr = strstr( table, lcmonth ) ) ) {
8592 month = 1 + ( ptr - table ) / 4;
8593
8594 /* If the lookup failed, report an error. */
8595 } else {
8596 astError( AST__DTERR, "Month value \"%s\" is invalid.", status,
8597 cmonth );
8598 }
8599 }
8600
8601 /* If OK, extract the integral day number and convert years, months and days
8602 to a Modified Julian Date. */
8603 if ( astOK ) {
8604 iday = (int) day;
8605 palCaldj( year, month, iday, &mjd, &stat );
8606
8607 /* Examine the return status from the conversion and report an appropriate
8608 error if necessary. */
8609 switch ( stat ) {
8610 case 1:
8611 astError( AST__DTERR, "Year value (%d) is invalid.", status, year );
8612 break;
8613 case 2:
8614 astError( AST__DTERR, "Month value (%d) is invalid.", status, month );
8615 break;
8616 case 3:
8617 astError( AST__DTERR, "Day value (%.*g) is invalid.", status, DBL_DIG,
8618 day );
8619 break;
8620
8621 /* If conversion to MJD was successful, add any fractional part of a day to the
8622 result. */
8623 default:
8624 mjd += ( day - (double) iday );
8625
8626 /* Convert hours, minutes and seconds to a fraction of a day (this will give
8627 zero if none of these quantities was supplied). */
8628 palDtf2d( hour, minute, sec, &hms, &stat );
8629
8630 /* Examine the return status from the conversion and report an appropriate
8631 error if necessary. */
8632 switch ( stat ) {
8633 case 1:
8634 astError( AST__DTERR, "Hour value (%d) is invalid.", status, hour );
8635 break;
8636 case 2:
8637 astError( AST__DTERR, "Minute value (%d) is invalid.", status,
8638 minute );
8639 break;
8640 case 3:
8641 astError( AST__DTERR, "Seconds value (%.*g) is invalid.", status,
8642 DBL_DIG, sec );
8643 break;
8644
8645 /* Add the fraction of a day derived from hours, minutes and seconds fields to
8646 the result. */
8647 default:
8648 mjd += hms;
8649 break;
8650 }
8651 break;
8652 }
8653
8654 /* Return the result, if no error occurred. */
8655 if ( astOK ) result = mjd;
8656 }
8657
8658 /* If none of the supported date/time formats matched, then report an error. */
8659 } else {
8660 astError( AST__DTERR, "Date/time does not have the correct form." , status);
8661 }
8662 }
8663
8664 /* Return the result. */
8665 return result;
8666 }
8667
ReportPoints(AstMapping * this_mapping,int forward,AstPointSet * in_points,AstPointSet * out_points,int * status)8668 static void ReportPoints( AstMapping *this_mapping, int forward,
8669 AstPointSet *in_points, AstPointSet *out_points, int *status ) {
8670 /*
8671 * Name:
8672 * ReportPoints
8673
8674 * Purpose:
8675 * Report the effect of transforming a set of points using a Frame.
8676
8677 * Type:
8678 * Private function.
8679
8680 * Synopsis:
8681 * #include "mapping.h"
8682 * void ReportPoints( AstMapping *this, int forward,
8683 * AstPointSet *in_points, AstPointSet *out_points, int *status )
8684
8685 * Class Membership:
8686 * Frame member function (over-rides the protected astReportPoints
8687 * method inherited from the Mapping class).
8688
8689 * Description:
8690 * This function reports the coordinates of a set of points before
8691 * and after being transformed by a Frame, by writing them to
8692 * standard output.
8693
8694 * Parameters:
8695 * this
8696 * Pointer to the Frame.
8697 * forward
8698 * A non-zero value indicates that the Frame's forward
8699 * coordinate transformation has been applied, while a zero
8700 * value indicates the inverse transformation.
8701 * in_points
8702 * Pointer to a PointSet which is associated with the
8703 * coordinates of a set of points before the Frame was applied.
8704 * out_points
8705 * Pointer to a PointSet which is associated with the
8706 * coordinates of the same set of points after the Frame has
8707 * been applied.
8708 * status
8709 * Pointer to the inherited status variable.
8710 */
8711
8712 /* Local Variables: */
8713 AstFrame *this; /* Pointer to the Frame structure */
8714 double **ptr_in; /* Pointer to array of input data pointers */
8715 double **ptr_out; /* Pointer to array of output data pointers */
8716 int coord; /* Loop counter for coordinates */
8717 int ncoord_in; /* Number of input coordinates per point */
8718 int ncoord_out; /* Number of output coordinates per point */
8719 int npoint; /* Number of points to report */
8720 int npoint_in; /* Number of input points */
8721 int npoint_out; /* Number of output points */
8722 int point; /* Loop counter for points */
8723
8724 /* Check the global error status. */
8725 if ( !astOK ) return;
8726
8727 /* Obtain a pointer to the Frame structure. */
8728 this = (AstFrame *) this_mapping;
8729
8730 /* Obtain the numbers of points and coordinates associated with each
8731 PointSet. */
8732 npoint_in = astGetNpoint( in_points );
8733 npoint_out = astGetNpoint( out_points );
8734 ncoord_in = astGetNcoord( in_points );
8735 ncoord_out = astGetNcoord( out_points );
8736
8737 /* Obtain the pointers that give access to the coordinate data
8738 associated with each PointSet. */
8739 ptr_in = astGetPoints( in_points );
8740 ptr_out = astGetPoints( out_points );
8741
8742 /* In the event that both PointSets don't contain equal numbers of
8743 points (this shouldn't actually happen), simply use the minimum
8744 number. */
8745 npoint = ( npoint_in < npoint_out ) ? npoint_in : npoint_out;
8746
8747 /* Loop to report the effect of the transformation on each point in
8748 turn. */
8749 for ( point = 0; point < npoint; point++ ) {
8750
8751 /* Report the input coordinates (in parentheses and separated by
8752 commas). Format each value for display using the Frame's astFormat
8753 method. */
8754 printf( "(" );
8755 for ( coord = 0; coord < ncoord_in; coord++ ) {
8756 printf( "%s%s", coord ? ", " : "",
8757 astFormat( this, coord, ptr_in[ coord ][ point ] ) );
8758 }
8759
8760 /* Similarly report the output coordinates. */
8761 printf( ") --> (" );
8762 for ( coord = 0; coord < ncoord_out; coord++ ) {
8763 printf( "%s%s", coord ? ", " : "",
8764 astFormat( this, coord, ptr_out[ coord ][ point ] ) );
8765 }
8766 printf( ")\n" );
8767 }
8768 }
8769
Resolve(AstFrame * this,const double point1[],const double point2[],const double point3[],double point4[],double * d1,double * d2,int * status)8770 static void Resolve( AstFrame *this, const double point1[],
8771 const double point2[], const double point3[],
8772 double point4[], double *d1, double *d2, int *status ){
8773 /*
8774 *++
8775 * Name:
8776 c astResolve
8777 f AST_RESOLVE
8778
8779 * Purpose:
8780 * Resolve a vector into two orthogonal components
8781
8782 * Type:
8783 * Public virtual function.
8784
8785 * Synopsis:
8786 c #include "frame.h"
8787 c void astResolve( AstFrame *this, const double point1[],
8788 c const double point2[], const double point3[],
8789 c double point4[], double *d1, double *d2 );
8790 f CALL AST_RESOLVE( THIS, POINT1, POINT2, POINT3, POINT4, D1, D2,
8791 f STATUS )
8792
8793 * Class Membership:
8794 * Frame method.
8795
8796 * Description:
8797 c This function resolves a vector into two perpendicular components.
8798 f This routine resolves a vector into two perpendicular components.
8799 * The vector from point 1 to point 2 is used as the basis vector.
8800 * The vector from point 1 to point 3 is resolved into components
8801 * parallel and perpendicular to this basis vector. The lengths of the
8802 * two components are returned, together with the position of closest
8803 * aproach of the basis vector to point 3.
8804
8805 * Parameters:
8806 c this
8807 f THIS = INTEGER (Given)
8808 * Pointer to the Frame.
8809 c point1
8810 f POINT1( * ) = DOUBLE PRECISION (Given)
8811 c An array of double, with one element for each Frame axis
8812 f An array with one element for each Frame axis
8813 * (Naxes attribute). This marks the start of the basis vector,
8814 * and of the vector to be resolved.
8815 c point2
8816 f POINT2( * ) = DOUBLE PRECISION (Given)
8817 c An array of double, with one element for each Frame axis
8818 f An array with one element for each Frame axis
8819 * (Naxes attribute). This marks the end of the basis vector.
8820 c point3
8821 f POINT3( * ) = DOUBLE PRECISION (Given)
8822 c An array of double, with one element for each Frame axis
8823 f An array with one element for each Frame axis
8824 * (Naxes attribute). This marks the end of the vector to be
8825 * resolved.
8826 c point4
8827 f POINT4( * ) = DOUBLE PRECISION (Returned)
8828 c An array of double, with one element for each Frame axis
8829 f An array with one element for each Frame axis
8830 * in which the coordinates of the point of closest approach of the
8831 * basis vector to point 3 will be returned.
8832 c d1
8833 f D1 = DOUBLE PRECISION (Returned)
8834 c The address of a location at which to return the distance from
8835 f The distance from
8836 * point 1 to point 4 (that is, the length of the component parallel
8837 * to the basis vector). Positive values are in the same sense as
8838 * movement from point 1 to point 2.
8839 c d2
8840 f D2 = DOUBLE PRECISION (Returned)
8841 c The address of a location at which to return the distance from
8842 f The distance from
8843 * point 4 to point 3 (that is, the length of the component
8844 * perpendicular to the basis vector). The value is always positive.
8845 f STATUS = INTEGER (Given and Returned)
8846 f The global status.
8847
8848 * Notes:
8849 c - Each vector used in this function is the path of
8850 f - Each vector used in this routine is the path of
8851 * shortest distance between two points, as defined by the
8852 c astDistance function.
8853 f AST_DISTANCE function.
8854 * - This function will return "bad" coordinate values (AST__BAD)
8855 * if any of the input coordinates has this value, or if the required
8856 * output values are undefined.
8857 *--
8858 */
8859
8860 /* Local Variables: */
8861 double bv; /* Length of basis vector */
8862 double c; /* Component length */
8863 double dp; /* Dot product */
8864 int axis; /* Loop counter for axes */
8865 int naxes; /* Number of Frame axes */
8866 int ok; /* OK to proceed? */
8867
8868 /* Check the global error status. */
8869 *d1 = AST__BAD;
8870 *d2 = AST__BAD;
8871 if ( !astOK ) return;
8872
8873 /* Determine the number of Frame axes. */
8874 naxes = astGetNaxes( this );
8875
8876 /* Initialize bad values, and check if the supplied vectors are good. */
8877 ok = 1;
8878 for( axis = 0; axis < naxes; axis++ ){
8879 point4[ axis ] = AST__BAD;
8880 if( point1[ axis ] == AST__BAD ||
8881 point2[ axis ] == AST__BAD ||
8882 point3[ axis ] == AST__BAD ) ok = 0;
8883 }
8884
8885 /* Check the supplied values. */
8886 if ( ok ) {
8887
8888 /* Find the dot product of the basis vector with the vector joining point 1
8889 and point 3. At the same time form the squared length of the basis
8890 vector. */
8891 dp = 0.0;
8892 bv = 0.0;
8893 for( axis = 0; axis < naxes; axis++ ){
8894 c = point2[ axis ] - point1[ axis ];
8895 dp += c * ( point3[ axis ] - point1[ axis ] );
8896 bv += c * c;
8897 }
8898
8899 /* Check the basis vector does not have zero length, and convert the
8900 squared length into a length. */
8901 if( bv > 0.0 ) {
8902 bv = sqrt( bv );
8903
8904 /* The dot product is the required distance d1 multiplied by the length
8905 of the basis vector. Form the distance d1. */
8906 *d1 = dp/bv;
8907
8908 /* Offset away from point 1 towards point 2 by a distance of d1. */
8909 for( axis = 0; axis < naxes; axis++ ){
8910 point4[ axis ] = point1[ axis ] +
8911 (*d1/bv)*( point2[ axis ] - point1[ axis ] );
8912 }
8913
8914 /* Finally, form the required length d2. */
8915 *d2 = 0.0;
8916 for( axis = 0; axis < naxes; axis++ ){
8917 c = ( point3[ axis ] - point4[ axis ] );
8918 *d2 += c*c;
8919 }
8920 *d2 = sqrt( *d2 );
8921
8922 }
8923 }
8924
8925 return;
8926
8927 }
8928
ResolvePoints(AstFrame * this,const double point1[],const double point2[],AstPointSet * in,AstPointSet * out,int * status)8929 static AstPointSet *ResolvePoints( AstFrame *this, const double point1[],
8930 const double point2[], AstPointSet *in,
8931 AstPointSet *out, int *status ) {
8932 /*
8933 *+
8934 * Name:
8935 * astResolvePoints
8936
8937 * Purpose:
8938 * Resolve a set of vectors into orthogonal components
8939
8940 * Type:
8941 * Protected virtual function.
8942
8943 * Synopsis:
8944 * #include "frame.h"
8945 * AstPointSet *astResolvePoints( AstFrame *this, const double point1[],
8946 * const double point2[], AstPointSet *in,
8947 * AstPointSet *out )
8948
8949 * Class Membership:
8950 * Frame method.
8951
8952 * Description:
8953 * This function takes a Frame and a set of vectors encapsulated
8954 * in a PointSet, and resolves each one into two orthogonal components,
8955 * returning these two components in another PointSet.
8956 *
8957 * This is exactly the same as the public astResolve method, except
8958 * that this method allows many vectors to be processed in a single call,
8959 * thus reducing the computational cost of overheads of many
8960 * individual calls to astResolve.
8961
8962 * Parameters:
8963 * this
8964 * Pointer to the Frame.
8965 * point1
8966 * An array of double, with one element for each Frame axis
8967 * (Naxes attribute). This marks the start of the basis vector,
8968 * and of the vectors to be resolved.
8969 * point2
8970 * An array of double, with one element for each Frame axis
8971 * (Naxes attribute). This marks the end of the basis vector.
8972 * in
8973 * Pointer to the PointSet holding the ends of the vectors to be
8974 * resolved.
8975 * out
8976 * Pointer to a PointSet which will hold the length of the two
8977 * resolved components. A NULL value may also be given, in which
8978 * case a new PointSet will be created by this function.
8979
8980 * Returned Value:
8981 * Pointer to the output (possibly new) PointSet. The first axis will
8982 * hold the lengths of the vector components parallel to the basis vector.
8983 * These values will be signed (positive values are in the same sense as
8984 * movement from point 1 to point 2. The second axis will hold the lengths
8985 * of the vector components perpendicular to the basis vector. These
8986 * values will be signed only if the Frame is 2-dimensional, in which
8987 * case a positive value indicates that rotation from the basis vector
8988 * to the tested vector is in the same sense as rotation from the first
8989 * to the second axis of the Frame.
8990
8991 * Notes:
8992 * - The number of coordinate values per point in the input
8993 * PointSet must match the number of axes in the supplied Frame.
8994 * - If an output PointSet is supplied, it must have space for
8995 * sufficient number of points and 2 coordinate values per point.
8996 * - A null pointer will be returned if this function is invoked
8997 * with the global error status set, or if it should fail for any
8998 * reason.
8999 * - We assume flat geometry throughout this function. Other classes,
9000 * (e.g. SkyFrame) will override this method using more appropriate
9001 * geometry.
9002 *-
9003 */
9004
9005 /* Local Variables: */
9006 AstPointSet *result; /* Pointer to output PointSet */
9007 double **ptr_in; /* Pointers to input axis values */
9008 double **ptr_out; /* Pointers to returned axis values */
9009 double *basisv; /* Pointer to array holding basis vector */
9010 double *d1; /* Pointer to next parallel component value */
9011 double *d2; /* Pointer to next perpendicular component value */
9012 double *ip; /* Pointer to next input axis value */
9013 double bv; /* Length of basis vector */
9014 double c; /* Constant value */
9015 double d; /* Component length */
9016 double dp; /* Dot product */
9017 double x1; /* First axis of basis vector */
9018 double x2; /* First axis of test vector */
9019 double y1; /* Second axis of basis vector */
9020 double y2; /* Second axis of test vector */
9021 int axis; /* Loop counter for axes */
9022 int ipoint; /* Index of next point */
9023 int nax; /* Number of Frame axes */
9024 int ncoord_in; /* Number of input PointSet coordinates */
9025 int ncoord_out; /* Number of coordinates in output PointSet */
9026 int npoint; /* Number of points to transform */
9027 int npoint_out; /* Number of points in output PointSet */
9028 int ok; /* OK to proceed? */
9029
9030 /* Initialise. */
9031 result = NULL;
9032
9033 /* Check the global error status. */
9034 if ( !astOK ) return result;
9035
9036 /* Obtain the number of axes in the Frame. */
9037 nax = astGetNaxes( this );
9038
9039 /* Obtain the number of input vectors to resolve and the number of coordinate
9040 values per vector. */
9041 npoint = astGetNpoint( in );
9042 ncoord_in = astGetNcoord( in );
9043
9044 /* If OK, check that the number of input coordinates matches the number
9045 required by the Frame. Report an error if these numbers do not match. */
9046 if ( astOK && ( ncoord_in != nax ) ) {
9047 astError( AST__NCPIN, "astResolvePoints(%s): Bad number of coordinate "
9048 "values (%d) in input %s.", status, astGetClass( this ), ncoord_in,
9049 astGetClass( in ) );
9050 astError( AST__NCPIN, "The %s given requires %d coordinate value(s) for "
9051 "each input point.", status, astGetClass( this ), nax );
9052 }
9053
9054 /* If still OK, and a non-NULL pointer has been given for the output PointSet,
9055 then obtain the number of points and number of coordinates per point for
9056 this PointSet. */
9057 if ( astOK && out ) {
9058 npoint_out = astGetNpoint( out );
9059 ncoord_out = astGetNcoord( out );
9060
9061 /* Check that the dimensions of this PointSet are adequate to accommodate the
9062 output coordinate values and report an error if they are not. */
9063 if ( astOK ) {
9064 if ( npoint_out < npoint ) {
9065 astError( AST__NOPTS, "astResolvePoints(%s): Too few points (%d) in "
9066 "output %s.", status, astGetClass( this ), npoint_out,
9067 astGetClass( out ) );
9068 astError( AST__NOPTS, "The %s needs space to hold %d transformed "
9069 "point(s).", status, astGetClass( this ), npoint );
9070 } else if ( ncoord_out < 2 ) {
9071 astError( AST__NOCTS, "astResolvePoints(%s): Too few coordinate "
9072 "values per point (%d) in output %s.", status,
9073 astGetClass( this ), ncoord_out, astGetClass( out ) );
9074 astError( AST__NOCTS, "The %s supplied needs space to store 2 "
9075 "coordinate value(s) per transformed point.", status,
9076 astGetClass( this ) );
9077 }
9078 }
9079 }
9080
9081 /* If all the validation stages are passed successfully, and a NULL output
9082 pointer was given, then create a new PointSet to encapsulate the output
9083 coordinate data. */
9084 if ( astOK ) {
9085 if ( !out ) {
9086 result = astPointSet( npoint, 2, "", status );
9087
9088 /* Otherwise, use the PointSet supplied. */
9089 } else {
9090 result = out;
9091 }
9092 }
9093
9094 /* Get pointers to the input and output axis values */
9095 ptr_in = astGetPoints( in );
9096 ptr_out = astGetPoints( result );
9097
9098 /* Store points to the first two axis arrays in the returned PointSet. */
9099 d1 = ptr_out[ 0 ];
9100 d2 = ptr_out[ 1 ];
9101
9102 /* Allocate work space. */
9103 basisv = astMalloc( sizeof( double )*(size_t) nax );
9104
9105 /* If the Frame has only one axis, then the supplied basic vector is
9106 irrelevant - the returned perpendicular distances are always zero and
9107 the returned parallel distances are just the distances from point1
9108 to each input point. */
9109 if( nax < 2 && basisv ) {
9110 ip = ptr_in[ 0 ];
9111 for( ipoint = 0; ipoint < npoint; ipoint++, d1++, d2++, ip++ ) {
9112 *d1 = astAxDistance( this, 1, point1[0], *ip );
9113 *d2 = 0.0;
9114 }
9115
9116 /* Now deal with Frames which have 2 or more axes */
9117 } else if( basisv ){
9118
9119 /* Check if the supplied positions defining the basis vector are good.
9120 Store the basis vector, and get its squared length. */
9121 ok = 1;
9122 bv = 0.0;
9123 for( axis = 0; axis < nax; axis++ ){
9124 if( point1[ axis ] == AST__BAD ||
9125 point2[ axis ] == AST__BAD ) {
9126 ok = 0;
9127 break;
9128 } else {
9129 basisv[ axis ] = point2[ axis ] - point1[ axis ];
9130 bv += basisv[ axis ]*basisv[ axis ];
9131 }
9132 }
9133
9134 /* Check the basis vector does not have zero length, and convert the
9135 squared length into a length. */
9136 if( ok && bv > 0.0 ) {
9137 bv = sqrt( bv );
9138 } else {
9139 ok = 0;
9140 }
9141
9142 /* Store points to the first two axis arrays in the returned PointSet. */
9143 d1 = ptr_out[ 0 ];
9144 d2 = ptr_out[ 1 ];
9145
9146 /* Check supplied values can be used */
9147 if( ok ) {
9148
9149 /* Loop round each supplied vector. */
9150 for( ipoint = 0; ipoint < npoint; ipoint++, d1++, d2++ ) {
9151
9152 /* Find the dot product of the basis vector with the vector joining point 1
9153 and the end of the current vector. */
9154 ok = 1;
9155 dp = 0.0;
9156 for( axis = 0; axis < nax; axis++ ){
9157 d = ptr_in[ axis ][ ipoint ] - point1[ axis ];
9158 if( d != AST__BAD ) {
9159 dp += basisv[ axis ] * d;
9160 } else {
9161 ok = 0;
9162 break;
9163 }
9164 }
9165
9166 /* If this input position is good... */
9167 if( ok ) {
9168
9169 /* The dot product is the required parallel component length multiplied by the
9170 length of the basis vector. Form the distance d1. */
9171 *d1 = dp/bv;
9172
9173 /* Offset away from point 1 towards point 2 by a distance of d1, and form the
9174 required length d2. */
9175 c = *d1/bv;
9176 if( nax > 2 ) {
9177 *d2 = 0.0;
9178 for( axis = 0; axis < nax; axis++ ){
9179 d = ptr_in[ axis ][ ipoint ] -
9180 ( point1[ axis ] + c*basisv[ axis ] );
9181 *d2 += d*d;
9182 }
9183 *d2 = sqrt( *d2 );
9184
9185 /* If the Frame is 2 dimensional, we can give a sign the the perpendicular
9186 component. */
9187 } else {
9188 x1 = c*basisv[ 0 ];
9189 y1 = c*basisv[ 1 ];
9190 x2 = ptr_in[ 0 ][ ipoint ] - ( point1[ 0 ] + x1 );
9191 y2 = ptr_in[ 1 ][ ipoint ] - ( point1[ 1 ] + y1 );
9192 *d2 = sqrt( x2*x2 + y2*y2 );
9193 if( x1*y2 - x2*y1 < 0.0 ) *d2 = -(*d2);
9194 }
9195
9196 /* If this input vector is bad, put bad values in the output */
9197 } else {
9198 *d1 = AST__BAD;
9199 *d2 = AST__BAD;
9200 }
9201 }
9202
9203 /* If supplied values cannot be used, fill the returned PointSet with bad
9204 values */
9205 } else {
9206 for( ipoint = 0; ipoint < npoint; ipoint++, d1++, d2++ ) {
9207 *d1 = AST__BAD;
9208 *d2 = AST__BAD;
9209 }
9210 }
9211 }
9212
9213 /* Free resources */
9214 basisv = astFree( basisv );
9215
9216 /* Annul the returned PointSet if an error occurred. */
9217 if( !astOK ) result = astAnnul( result );
9218
9219 /* Return a pointer to the output PointSet. */
9220 return result;
9221 }
9222
SetActiveUnit(AstFrame * this,int value,int * status)9223 static void SetActiveUnit( AstFrame *this, int value, int *status ){
9224 /*
9225 *++
9226 * Name:
9227 c astSetActiveUnit
9228 f AST_SETACTIVEUNIT
9229
9230 * Purpose:
9231 * Specify how the Unit attribute should be used.
9232
9233 * Type:
9234 * Public virtual function.
9235
9236 * Synopsis:
9237 c #include "frame.h"
9238 c void astSetActiveUnit( AstFrame *this, int value )
9239 f CALL AST_SETACTIVEUNIT( THIS, VALUE, STATUS )
9240
9241 * Class Membership:
9242 * Frame method.
9243
9244 * Description:
9245 c This function
9246 f This routine
9247 * sets the current value of the ActiveUnit flag for a Frame, which
9248 * controls how the Frame behaves when it is used (by
9249 c astFindFrame or astConvert)
9250 f AST_FINDFRAME or AST_CONVERT)
9251 * to match another Frame. If the ActiveUnit flag is set in both
9252 * template and target Frames then the returned Mapping takes into account
9253 * any differences in axis units. The default value for simple Frames is
9254 * zero, which preserves the behaviour of versions of AST prior to
9255 * version 2.0.
9256 *
9257 * If the ActiveUnit flag of either Frame is
9258 c zero,
9259 f .FALSE.,
9260 * then the Mapping will ignore any difference in the Unit attributes of
9261 * corresponding template and target axes. In this mode, the Unit
9262 * attributes are purely descriptive commentary for the benefit of
9263 * human readers and do not influence the Mappings between Frames.
9264 * This is the behaviour which all Frames had in older version of AST,
9265 * prior to the introduction of this attribute.
9266 *
9267 * If the ActiveUnit flag of both Frames is
9268 c non-zero,
9269 f .TRUE.,
9270 * then the Mapping from template to target will take account of any
9271 * difference in the axis Unit attributes, where-ever possible. For
9272 * instance, if corresponding target and template axes have Unit strings of
9273 * "km" and "m", then the FrameSet class will use a ZoomMap to connect
9274 * them which introduces a scaling of 1000. If no Mapping can be found
9275 * between the corresponding units string, then an error is reported.
9276 * In this mode, it is assumed that values of the Unit attribute conform
9277 * to the syntax for units strings described in the FITS WCS Paper I
9278 * "Representations of world coordinates in FITS" (Greisen & Calabretta).
9279 * Particularly, any of the named unit symbols, functions, operators or
9280 * standard multiplier prefixes listed within that paper can be used within
9281 * a units string. A units string may contain symbols for unit which are
9282 * not listed in the FITS paper, but transformation to any other units
9283 * will then not be possible (except to units which depend only on the
9284 * same unknown units - thus "flops" can be transformed to "Mflops"
9285 * even though "flops" is not a standard FITS unit symbol).
9286 *
9287 * A range of common non-standard variations of unit names and multiplier
9288 * prefixes are also allowed, such as adding an "s" to the end of Angstrom,
9289 * using a lower case "a" at the start of "angstrom", "micron" instead of
9290 * "um", "sec" instead of "s", etc.
9291 *
9292 c If the ActiveUnit flag is non-zero, setting a new Unit value for an
9293 f If the ActiveUnit flag is .TRUE., setting a new Unit value for an
9294 * axis may also change its Label and Symbol attributes. For instance, if
9295 * an axis has Unit "Hz" and Label "frequency", then changing its Unit to
9296 * "log(Hz)" will change its Label to "log( frequency )". In addition,
9297 * the Axis Format attribute will be cleared when-ever a new value
9298 * is assigned to the Unit attribute.
9299 *
9300 c Note, if a non-zero value is set for the ActiveUnit flag, then changing a
9301 f Note, if a .TRUE. value is set for the ActiveUnit flag, then changing a
9302 * Unit value for the current Frame within a FrameSet will result in the
9303 * Frame being re-mapped (that is, the Mappings which define the
9304 * relationships between Frames within the FrameSet will be modified to
9305 * take into account the change in Units).
9306
9307 * Parameters:
9308 c this
9309 f THIS = INTEGER (Given)
9310 * Pointer to the Frame.
9311 c value
9312 f VALUE = LOGICAL (Given)
9313 * The new value to use.
9314 f STATUS = INTEGER (Given and Returned)
9315 f The global status.
9316
9317 * Applicability:
9318 * SkyFrame
9319 c The ActiveUnit flag for a SkyFrame is always 0 (any value
9320 c supplied using this function is ignored).
9321 f The ActiveUnit flag for a SkyFrame is always .FALSE. (any value
9322 f supplied using this routine is ignored).
9323 * SpecFrame
9324 c The ActiveUnit flag for a SpecFrame is always 1 (any value
9325 c supplied using this function is ignored).
9326 f The ActiveUnit flag for a SpecFrame is always .TRUE. (any value
9327 f supplied using this routine is ignored).
9328 * FluxFrame
9329 c The ActiveUnit flag for a FluxFrame is always 1 (any value
9330 c supplied using this function is ignored).
9331 f The ActiveUnit flag for a FluxFrame is always .TRUE. (any value
9332 f supplied using this routine is ignored).
9333 * CmpFrame
9334 c The default ActiveUnit flag for a CmpFrame is 1 if both of the
9335 c component Frames are using active units, and zero otherwise. When
9336 f The default ActiveUnit flag for a CmpFrame is .TRUE. if both of the
9337 f component Frames are using active units, and .FALSE. otherwise. When
9338 * a new value is set for the ActiveUnit flag, the flag value
9339 * is propagated to the component Frames. This change will be
9340 * reflected through all references to the component Frames, not
9341 * just those encapsulated within the CmpFrame.
9342 * Region:
9343 * Regions always use active units if possible.
9344
9345 * Notes:
9346 * - The ActiveUnit flag resembles a Frame attribute, except that it
9347 * cannot be tested or cleared, and it cannot be accessed using the
9348 c generic astGet<X> and astSet<X> functions.
9349 f generic AST_GET<X> and AST_SET<X> routines.
9350 c - The astGetActiveUnit function can be used to retrieve the current
9351 f - The AST_GETACTIVEUNIT routine can be used to retrieve the current
9352 * value of the ActiveUnit flag.
9353
9354 *--
9355 */
9356
9357 /* Check the global error status. */
9358 if ( !astOK ) return;
9359
9360 /* Store a value of 1 for the Frame component if the supplied value is
9361 non-zero. */
9362 this->active_unit = ( value ) ? 1 : 0;
9363 }
9364
SetAttrib(AstObject * this_object,const char * setting,int * status)9365 static void SetAttrib( AstObject *this_object, const char *setting, int *status ) {
9366 /*
9367 * Name:
9368 * SetAttrib
9369
9370 * Purpose:
9371 * Set an attribute value for a Frame.
9372
9373 * Type:
9374 * Private function.
9375
9376 * Synopsis:
9377 * #include "frame.h"
9378 * void SetAttrib( AstObject *this, const char *setting, int *status )
9379
9380 * Class Membership:
9381 * Frame member function (over-rides the astSetAttrib method inherited
9382 * from the Mapping class).
9383
9384 * Description:
9385 * This function assigns an attribute value for a Frame, the
9386 * attribute and its value being specified by means of a string of
9387 * the form:
9388 *
9389 * "attribute= value "
9390 *
9391 * Here, "attribute" specifies the attribute name and should be in
9392 * lower case with no white space present. The value to the right
9393 * of the "=" should be a suitable textual representation of the
9394 * value to be assigned and this will be interpreted according to
9395 * the attribute's data type. White space surrounding the value is
9396 * only significant for string attributes.
9397
9398 * Parameters:
9399 * this
9400 * Pointer to the Frame.
9401 * setting
9402 * Pointer to a null terminated string specifying the new attribute
9403 * value.
9404 * status
9405 * Pointer to the inherited status variable.
9406
9407 * Notes:
9408 * - This function uses one-based axis numbering so that it is
9409 * suitable for external (public) use.
9410 */
9411
9412 /* Local Vaiables: */
9413 AstAxis *ax; /* Pointer to Axis */
9414 AstFrame *pfrm; /* Pointer to primary Frame containing axis */
9415 AstFrame *this; /* Pointer to the Frame structure */
9416 AstSystemType system_code; /* System code */
9417 char pfrm_attrib[ 100 ]; /* Primary Frame attribute */
9418 char *pfrm_setting; /* Primary Frame attribute */
9419 char *axis_setting; /* Pointer to axis attribute setting string */
9420 const char *equals; /* Pointer to equals sign */
9421 const char *old_setting; /* Pointer to supplied setting string */
9422 const char *op; /* Pointer to opening parenthesis */
9423 double dval; /* Double attibute value */
9424 double mjd; /* Epoch as a Modified Julian Date */
9425 int axis; /* Index for the Frame axis */
9426 int axis_nc; /* No. characters in axis attribute name */
9427 int axis_value; /* Offset of value to be assigned to axis */
9428 int digits; /* Number of digits of precision */
9429 int direction; /* Axis direction flag */
9430 int domain; /* Offset of Domain string */
9431 int epoch; /* Offset of Epoch string */
9432 int format; /* Offset of axis Format string */
9433 int free_axis_setting; /* Should axis_setting be freed? */
9434 int has_axis; /* Does setting include an axis specifier? */
9435 int ival; /* Integer attribute value */
9436 int label; /* Offset of axis Label string */
9437 int len; /* Length of setting string */
9438 int match_end; /* Match final axes of target? */
9439 int max_axes; /* Maximum number of axes matched */
9440 int min_axes; /* Minimum number of axes matched */
9441 int nc; /* Number of characters read by astSscanf */
9442 int off2; /* Modified offset of attribute value */
9443 int off; /* Offset of attribute value */
9444 int oldrep; /* Original error reporting state */
9445 int paxis; /* Axis index within primary frame */
9446 int permute; /* Permute axes in order to match? */
9447 int preserve_axes; /* Preserve matched target axes? */
9448 int sign; /* Sign of longitude value */
9449 int symbol; /* Offset of axis Symbol string */
9450 int system; /* Offset of System string */
9451 int title; /* Offset of Title string */
9452 int unit; /* Offset of axis Unit string */
9453 int used; /* Could the setting string be used? */
9454
9455 /* Check the global error status. */
9456 if ( !astOK ) return;
9457
9458 /* Obtain a pointer to the Frame structure. */
9459 this = (AstFrame *) this_object;
9460
9461 /* Find the offset to the first equal sign in the setting string. */
9462 equals = strchr( setting, '=' );
9463
9464 /* Set a flag indicating if the attribute name includes an axis
9465 specifier. */
9466 op = strchr( setting, '(' );
9467 has_axis = ( !op || op > equals ) ? 0 : 1;
9468
9469 /* A flag indicating that we do not need to free the axis_setting memory. */
9470 free_axis_setting = 0;
9471
9472 /* Initialise things to avoid compiler warnings. */
9473 axis_setting = NULL;
9474 old_setting = NULL;
9475
9476 /* Jump back to here if we are trying the same attribute setting but with
9477 an explicit axis "(1)" added to the attribute name. */
9478 L1:
9479
9480 /* Obtain the length of the setting string. */
9481 len = strlen( setting );
9482
9483 /* Test for each recognised attribute in turn, using "astSscanf" to parse the
9484 setting string and extract the attribute value (or an offset to it in the
9485 case of string values). In each case, use the value set in "nc" to check
9486 that the entire string was matched. Once a value has been obtained, use the
9487 appropriate method to set it. */
9488
9489 /* Digits. */
9490 /* ------- */
9491 if ( nc = 0,
9492 ( 1 == astSscanf( setting, "digits= %d %n", &digits, &nc ) )
9493 && ( nc >= len ) ) {
9494 astSetDigits( this, digits );
9495
9496 /* Digits(axis). */
9497 /* ------------- */
9498 } else if ( nc = 0,
9499 ( 2 == astSscanf( setting, "digits(%d)= %d %n",
9500 &axis, &digits, &nc ) )
9501 && ( nc >= len ) ) {
9502
9503 /* There is no function to set the Digits attribute value for an axis
9504 directly, so obtain a pointer to the Axis and use this to set the
9505 attribute. */
9506 (void) astValidateAxis( this, axis - 1, 1, "astSetDigits(axis)" );
9507 ax = astGetAxis( this, axis - 1 );
9508 astSetAxisDigits( ax, digits );
9509 ax = astAnnul( ax );
9510
9511 /* Direction(axis). */
9512 /* ---------------- */
9513 } else if ( nc = 0,
9514 ( 2 == astSscanf( setting, "direction(%d)= %d %n",
9515 &axis, &direction, &nc ) )
9516 && ( nc >= len ) ) {
9517 astSetDirection( this, axis - 1, direction );
9518
9519 /* Epoch. */
9520 /* ------ */
9521 } else if ( nc = 0,
9522 ( 0 == astSscanf( setting, "epoch=%n%*[^\n]%n", &epoch, &nc ) )
9523 && ( nc >= len ) ) {
9524
9525 /* Convert the Epoch value to a Modified Julian Date before use. */
9526 mjd = astReadDateTime( setting + epoch );
9527 if ( astOK ) {
9528 astSetEpoch( this, mjd );
9529
9530 /* Report contextual information if the conversion failed. */
9531 } else {
9532 astError( AST__ATTIN, "astSetAttrib(%s): Invalid epoch value "
9533 "\"%s\" given for coordinate system.", status,
9534 astGetClass( this ), setting + epoch );
9535 }
9536
9537 /* Top(axis). */
9538 /* ---------- */
9539 } else if ( nc = 0,
9540 ( 2 == astSscanf( setting, "top(%d)= %lg %n",
9541 &axis, &dval, &nc ) )
9542 && ( nc >= len ) ) {
9543 astSetTop( this, axis - 1, dval );
9544
9545 /* Bottom(axis). */
9546 /* ------------- */
9547 } else if ( nc = 0,
9548 ( 2 == astSscanf( setting, "bottom(%d)= %lg %n",
9549 &axis, &dval, &nc ) )
9550 && ( nc >= len ) ) {
9551 astSetBottom( this, axis - 1, dval );
9552
9553 /* Domain. */
9554 /* ------- */
9555 } else if ( nc = 0,
9556 ( 0 == astSscanf( setting, "domain=%n%*[^\n]%n", &domain, &nc ) )
9557 && ( nc >= len ) ) {
9558 astSetDomain( this, setting + domain );
9559
9560 /* Format(axis). */
9561 /* ------------- */
9562 } else if ( nc = 0,
9563 ( 1 == astSscanf( setting, "format(%d)=%n%*[^\n]%n",
9564 &axis, &format, &nc ) )
9565 && ( nc >= len ) ) {
9566 astSetFormat( this, axis - 1, setting + format );
9567
9568 /* Label(axis). */
9569 /* ------------ */
9570 } else if ( nc = 0,
9571 ( 1 == astSscanf( setting, "label(%d)=%n%*[^\n]%n",
9572 &axis, &label, &nc ) )
9573 && ( nc >= len ) ) {
9574 astSetLabel( this, axis - 1, setting + label );
9575
9576 /* MatchEnd. */
9577 /* --------- */
9578 } else if ( nc = 0,
9579 ( 1 == astSscanf( setting, "matchend= %d %n", &match_end, &nc ) )
9580 && ( nc >= len ) ) {
9581 astSetMatchEnd( this, match_end );
9582
9583 /* MaxAxes. */
9584 /* -------- */
9585 } else if ( nc = 0,
9586 ( 1 == astSscanf( setting, "maxaxes= %d %n", &max_axes, &nc ) )
9587 && ( nc >= len ) ) {
9588 astSetMaxAxes( this, max_axes );
9589
9590 /* MinAxes. */
9591 /* -------- */
9592 } else if ( nc = 0,
9593 ( 1 == astSscanf( setting, "minaxes= %d %n", &min_axes, &nc ) )
9594 && ( nc >= len ) ) {
9595 astSetMinAxes( this, min_axes );
9596
9597 /* Permute. */
9598 /* -------- */
9599 } else if ( nc = 0,
9600 ( 1 == astSscanf( setting, "permute= %d %n", &permute, &nc ) )
9601 && ( nc >= len ) ) {
9602 astSetPermute( this, permute );
9603
9604 /* PreserveAxes. */
9605 /* ------------- */
9606 } else if ( nc = 0,
9607 ( 1 == astSscanf( setting, "preserveaxes= %d %n",
9608 &preserve_axes, &nc ) )
9609 && ( nc >= len ) ) {
9610 astSetPreserveAxes( this, preserve_axes );
9611
9612 /* Symbol(axis). */
9613 /* ------------- */
9614 } else if ( nc = 0,
9615 ( 1 == astSscanf( setting, "symbol(%d)=%n%*[^\n]%n",
9616 &axis, &symbol, &nc ) )
9617 && ( nc >= len ) ) {
9618 astSetSymbol( this, axis - 1, setting + symbol );
9619
9620 /* AlignSystem. */
9621 /* ------------ */
9622 } else if ( nc = 0,
9623 ( 0 == astSscanf( setting, "alignsystem= %n%*s %n", &system, &nc ) )
9624 && ( nc >= len ) ) {
9625
9626 /* Convert the string to a System code before use. */
9627 system_code = astSystemCode( this, system + setting );
9628 if ( system_code != AST__BADSYSTEM ) {
9629 astSetAlignSystem( this, system_code );
9630
9631 /* Report an error if the string value wasn't recognised. */
9632 } else {
9633 astError( AST__ATTIN,
9634 "astSetAttrib(%s): Invalid AlignSystem description \"%s\".", status,
9635 astGetClass( this ), system + setting );
9636 }
9637
9638 /* System. */
9639 /* ------- */
9640 } else if ( nc = 0,
9641 ( 0 == astSscanf( setting, "system= %n%*s %n", &system, &nc ) )
9642 && ( nc >= len ) ) {
9643
9644 /* Convert the string to a System code before use. */
9645 system_code = astSystemCode( this, system + setting );
9646 if ( system_code != AST__BADSYSTEM ) {
9647 astSetSystem( this, system_code );
9648
9649 /* Report an error if the string value wasn't recognised. */
9650 } else {
9651 astError( AST__ATTIN,
9652 "astSetAttrib(%s): Invalid System description \"%s\".", status,
9653 astGetClass( this ), system + setting );
9654 }
9655
9656 /* Title. */
9657 /* ------ */
9658 } else if ( nc = 0,
9659 ( 0 == astSscanf( setting, "title=%n%*[^\n]%n", &title, &nc ) )
9660 && ( nc >= len ) ) {
9661 astSetTitle( this, setting + title );
9662
9663 /* Unit(axis). */
9664 /* ----------- */
9665 } else if ( nc = 0,
9666 ( 1 == astSscanf( setting, "unit(%d)=%n%*[^\n]%n",
9667 &axis, &unit, &nc ) )
9668 & ( nc >= len ) ) {
9669 astSetUnit( this, axis - 1, setting + unit );
9670
9671 /* ObsLat. */
9672 /* ------- */
9673 } else if ( nc = 0,
9674 ( 0 == astSscanf( setting, "obslat=%n%*s %n", &off, &nc ) )
9675 && ( nc >= 7 ) ) {
9676
9677 /* If the first character in the value string is "N" or "S", remember the
9678 sign of the value and skip over the sign character. Default is north
9679 (+ve). */
9680 off2 = off;
9681 if( setting[ off ] == 'N' || setting[ off ] == 'n' ) {
9682 off2++;
9683 sign = +1;
9684 } else if( setting[ off ] == 'S' || setting[ off ] == 's' ) {
9685 off2++;
9686 sign = -1;
9687 } else {
9688 sign = +1;
9689 }
9690
9691 /* If not already created, create an FK5 J2000 SkyFrame which will be used
9692 for formatting and unformatting ObsLon and ObsLat values. */
9693 if( !skyframe ) {
9694 astBeginPM;
9695 skyframe = astSkyFrame( "system=FK5,equinox=J2000,format(2)=dms.2", status );
9696 astEndPM;
9697 }
9698
9699 /* Convert the string to a radians value before use. */
9700 ival = astUnformat( skyframe, 1, setting + off2, &dval );
9701 if ( ival == astChrLen( setting ) - off2 ) {
9702 astSetObsLat( this, dval*sign );
9703
9704 /* Report an error if the string value wasn't recognised. */
9705 } else {
9706 astError( AST__ATTIN, "astSetAttrib(%s): Invalid value for "
9707 "ObsLat (observers latitude) \"%s\".", status, astGetClass( this ),
9708 setting + off );
9709 }
9710
9711 /* ObsLon. */
9712 /* ------- */
9713 } else if ( nc = 0,
9714 ( 0 == astSscanf( setting, "obslon=%n%*s %n", &off, &nc ) )
9715 && ( nc >= 7 ) ) {
9716
9717 /* If the first character in the value string is "E" or "W", remember the
9718 sign of the value and skip over the sign character. Default is east
9719 (+ve). */
9720 off2 = off;
9721 if( setting[ off ] == 'E' || setting[ off ] == 'e' ) {
9722 off2++;
9723 sign = +1;
9724 } else if( setting[ off ] == 'W' || setting[ off ] == 'w' ) {
9725 off2++;
9726 sign = -1;
9727 } else {
9728 sign = +1;
9729 }
9730
9731 /* If not already created, create an FK5 J2000 SkyFrame which will be used
9732 for formatting and unformatting ObsLon and ObsLat values. */
9733 if( !skyframe ) {
9734 astBeginPM;
9735 skyframe = astSkyFrame( "system=FK5,equinox=J2000,format(2)=dms.2", status );
9736 astEndPM;
9737 }
9738
9739 /* Convert the string to a radians value before use. */
9740 ival = astUnformat( skyframe, 1, setting + off2, &dval );
9741 if ( ival == astChrLen( setting ) - off2 ) {
9742 astSetObsLon( this, dval*sign );
9743
9744 /* Report an error if the string value wasn't recognised. */
9745 } else {
9746 astError( AST__ATTIN, "astSetAttrib(%s): Invalid value for "
9747 "ObsLon (observers longitude) \"%s\".", status, astGetClass( this ),
9748 setting + off );
9749 }
9750
9751 /* ObsAlt. */
9752 /* ------- */
9753 } else if ( nc = 0,
9754 ( 1 == astSscanf( setting, "obsalt= %lg %n", &dval, &nc ) )
9755 && ( nc >= len ) ) {
9756 astSetObsAlt( this, dval );
9757
9758 /* Dut1. */
9759 /* ---- */
9760 } else if ( nc = 0,
9761 ( 1 == astSscanf( setting, "dut1= %lg %n", &dval, &nc ) )
9762 && ( nc >= len ) ) {
9763 astSetDut1( this, dval );
9764
9765
9766 /* Read-only attributes. */
9767 /* --------------------- */
9768 /* Define a macro to see if the setting string matches any of the
9769 read-only attributes of this class. */
9770 #define MATCH(attrib) \
9771 ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \
9772 ( nc >= len ) )
9773
9774 /* Use this macro to report an error if a read-only attribute has been
9775 specified. */
9776 } else if ( MATCH( "naxes" ) ||
9777 !strncmp( setting, "normunit", 8 ) ) {
9778 astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status,
9779 setting, astGetClass( this ) );
9780 astError( AST__NOWRT, "This is a read-only attribute." , status);
9781
9782 /* Other axis attributes. */
9783 /* ---------------------- */
9784 /* If the attribute was not identified above, but appears to refer to
9785 a Frame axis, then it may refer to an Axis object of a derived type
9786 (which has additional attributes not recognised here). */
9787 } else if ( !free_axis_setting && ( nc = 0,
9788 ( 1 == astSscanf( setting, "%*[^()]%n(%d)%n=%*[^\n]%n",
9789 &axis_nc, &axis, &axis_value, &nc ) )
9790 && ( nc >= len ) ) ) {
9791
9792 /* Validate the axis index and copy the attribute setting string. */
9793 (void) astValidateAxis( this, axis - 1, 1, "astSet" );
9794 axis_setting = astString( setting, len );
9795 if ( astOK ) {
9796
9797 /* Over-write the axis index in the copy with the value to be
9798 assigned. */
9799 (void) strcpy( axis_setting + axis_nc, setting + axis_value );
9800
9801 /* Obtain a pointer to the Axis object. */
9802 ax = astGetAxis( this, axis - 1 );
9803 if( astOK ) {
9804
9805 /* Assume that we will be able to use the setting. */
9806 used = 1;
9807
9808 /* Temporarily switch off error reporting so that if the following attempt
9809 to access the axis attribute fails, we can try to interpret the
9810 attribute name as an attribute of the primary Frame containing the
9811 specified axis. Any errors reported in this context will simply be
9812 ignored, in particularly they are not deferred for later delivery. */
9813 oldrep = astReporting( 0 );
9814
9815 /* Use the Axis astSetAttrib method
9816 to set the value. */
9817 astSetAttrib( ax, axis_setting );
9818
9819 /* If the above call failed with a status of AST__BADAT, indicating that
9820 the attribute name was not recognised, clear the status so that we can
9821 try to interpret the attribute name as an attribute of the primary Frame
9822 containing the specified axis. */
9823 if( astStatus == AST__BADAT ) {
9824 astClearStatus;
9825
9826 /* Find the primary Frame containing the specified axis. */
9827 astPrimaryFrame( this, axis - 1, &pfrm, &paxis );
9828
9829 /* Only attempt to use the primary Frame if it is not the same as "this"
9830 - otherwise we could end up in an infinite loop. */
9831 if( pfrm != this ) {
9832
9833 /* astPrimaryFrame returns the original - unpermuted - axis index within
9834 the primary Frame. So we need to take into account any axis permutation
9835 which has been applied to the primary Frame when forming the attribute name
9836 to use below. Find the permuted (external) axis index which corresponds to
9837 the internal (unpermuted) axis index "paxis". */
9838 paxis = astValidateAxis( pfrm, paxis, 0, "astSet" );
9839
9840 /* Modify the attribute name to refer to the axis numbering of the
9841 primary frame. */
9842 sprintf( pfrm_attrib, "%.*s(%d)", axis_nc, setting, paxis + 1 );
9843
9844 /* Create a setting string in which the attribute name refers to the axis
9845 numbering of the primary frame. */
9846 pfrm_setting = NULL;
9847 nc = 0;
9848 pfrm_setting = astAppendString( pfrm_setting, &nc, pfrm_attrib );
9849 pfrm_setting = astAppendString( pfrm_setting, &nc, setting + axis_value );
9850
9851 /* Attempt to set the attribute within the primary Frame. */
9852 astSetAttrib( pfrm, pfrm_setting );
9853
9854 /* Free the memory. */
9855 pfrm_setting = astFree( pfrm_setting );
9856
9857 /* If this failed, clear the status and indicate that we have not managed to
9858 use the attribute setting. */
9859 if( !astOK ) {
9860 astClearStatus;
9861 used = 0;
9862 }
9863
9864 } else {
9865 used = 0;
9866 }
9867
9868 /* If not found attempt to set the attribute value in the Axis, omitting
9869 the axis index. */
9870 if( ! used ) {
9871 astSetAttrib( pfrm, axis_setting );
9872 if( !astOK ) {
9873 astClearStatus;
9874 } else {
9875 used = 1;
9876 }
9877 }
9878
9879 /* Free the setting string, and annul the primary Frame pointer. */
9880 pfrm = astAnnul( pfrm );
9881 }
9882
9883 /* Re-instate the original error reporting state. */
9884 astReporting( oldrep );
9885
9886 /* If we could not use the setting, attempt to set the axis attribute again,
9887 this time retaining the error report. This is done to ensure the user
9888 gets an appropriate error message. */
9889 if( !used ) astSetAttrib( ax, axis_setting );
9890 }
9891
9892 /* Annul the Axis pointer and free the memory holding the attribute
9893 setting. */
9894 ax = astAnnul( ax );
9895 }
9896 axis_setting = astFree( axis_setting );
9897
9898 /* Not recognised. */
9899 /* --------------- */
9900 /* If the attribute is still not recognised, and the Frame has only 1 axis,
9901 and the attribute name does not already include an axis specifier, try
9902 again after appending "(1)" to the end of the attribute name. */
9903 } else if( !has_axis && astGetNaxes( this ) == 1 && equals ) {
9904
9905 /* Take a copy of the supplied setting, allowing 3 extra characters for the
9906 axis specifier "(1)". */
9907 axis_setting = astMalloc( len + 4 );
9908 if( axis_setting ) memcpy( axis_setting, setting, len );
9909
9910 /* Indicate we should free the axis_setting memory. */
9911 free_axis_setting = 1;
9912
9913 /* Add in the axis specifier. */
9914 strcpy( axis_setting + ( equals - setting ), "(1)" );
9915
9916 /* Add in the equals sign and attribute value. */
9917 strcpy( axis_setting + ( equals - setting ) + 3, equals );
9918
9919 /* Use the new setting instead of the supplied setting. */
9920 old_setting = setting;
9921 setting = axis_setting;
9922
9923 /* Indicate the setting now has an axis specifier. */
9924 has_axis = 1;
9925
9926 /* Jump back to try interpreting the new setting string. */
9927 goto L1;
9928
9929 /* Not recognised. */
9930 /* --------------- */
9931 /* If the attribute is still not recognised, pass it on to the parent
9932 method for further interpretation. First re-instate the original setting
9933 string if it was changed above. */
9934 } else {
9935 if( free_axis_setting ) {
9936 setting = old_setting;
9937 axis_setting = astFree( axis_setting );
9938 free_axis_setting = 0;
9939 }
9940 (*parent_setattrib)( this_object, setting, status );
9941 }
9942
9943 if( free_axis_setting ) axis_setting = astFree( axis_setting );
9944
9945 /* Undefine macros local to this function. */
9946 #undef MATCH
9947 }
9948
SetAxis(AstFrame * this,int axis,AstAxis * newaxis,int * status)9949 static void SetAxis( AstFrame *this, int axis, AstAxis *newaxis, int *status ) {
9950 /*
9951 *+
9952 * Name:
9953 * astSetAxis
9954
9955 * Purpose:
9956 * Set a new Axis for a Frame.
9957
9958 * Type:
9959 * Protected virtual function.
9960
9961 * Synopsis:
9962 * #include "frame.h"
9963 * void astSetAxis( AstFrame *this, int axis, AstAxis *newaxis )
9964
9965 * Class Membership:
9966 * Frame method.
9967
9968 * Description:
9969 * This function allows a new Axis object to be associated with one
9970 * of the axes of a Frame, replacing the previous one. Each Axis
9971 * object contains a description of the quantity represented along
9972 * one of the Frame's axes, so this function allows this
9973 * description to be exchanged for another one.
9974
9975 * Parameters:
9976 * this
9977 * Pointer to the Frame.
9978 * axis
9979 * The index (zero-based) of the axis whose associated Axis object is to
9980 * be replaced.
9981 * newaxis
9982 * Pointer to the new Axis object.
9983 *-
9984 */
9985
9986 /* Check the global error status. */
9987 if ( !astOK ) return;
9988
9989 /* Validate and permute the axis index supplied. */
9990 axis = astValidateAxis( this, axis, 1, "astSetAxis" );
9991
9992 /* If OK, annul the Frame's pointer to the old Axis object and clone a pointer
9993 to the new one to replace it. */
9994 if ( astOK ) {
9995 this->axis[ axis ] = astAnnul( this->axis[ axis ] );
9996 this->axis[ axis ] = astClone( newaxis );
9997 }
9998 }
9999
SetFrameFlags(AstFrame * this,int flags,int * status)10000 static void SetFrameFlags( AstFrame *this, int flags, int *status ){
10001 /*
10002 *+
10003 * Name:
10004 * astSetFrameFlags
10005
10006 * Purpose:
10007 * Store a new bit mask of flags in a Frame.
10008
10009 * Type:
10010 * Protected function.
10011
10012 * Synopsis:
10013 * #include "frame.h"
10014 * void astSetFrameFlags( astFrame *this, int flags )
10015
10016 * Class Membership:
10017 * Frame member function.
10018
10019 * Description:
10020 * This function stores a new set of flags in a Frame. The flags can
10021 * be retrieved using astGetFrameFlags.
10022
10023 * Parameters:
10024 * this
10025 * The Frame.
10026 * flags
10027 * A bit mask holding the flags. Currently, the following bits are
10028 * used:
10029 *
10030 * 0 - Used to indicate if the Frame is currently involved in an
10031 * attempt to restore the integrity of a FrameSet following
10032 * changes to the attribute values of the Frame.
10033
10034 *-
10035 */
10036
10037 /* Check the global error status. */
10038 if ( !astOK ) return;
10039
10040 /* Assign the new bit mask. */
10041 this->flags = flags;
10042 }
10043
SetFrameVariants(AstFrame * this,AstFrameSet * variants,int * status)10044 static void SetFrameVariants( AstFrame *this, AstFrameSet *variants, int *status ){
10045 /*
10046 *+
10047 * Name:
10048 * astSetFrameVariants
10049
10050 * Purpose:
10051 * Store a FrameSet holding alternative Frame properties.
10052
10053 * Type:
10054 * Protected virtual function.
10055
10056 * Synopsis:
10057 * #include "frame.h"
10058 * void astSetVariants( AstFrame *this, AstFrameSet *variants )
10059
10060 * Class Membership:
10061 * Frame method.
10062
10063 * Description:
10064 * This function adds sets of alternative Frame properties to a Frame.
10065
10066 * Parameters:
10067 * this
10068 * Pointer to the Frame.
10069 * variants
10070 * Pointer to a FrameSet in which each Frame is of the same class
10071 * and dimensionality as "this" and all Frames have unique Domain
10072 * names.
10073
10074 * Notes:
10075 * - A clone of the supplied FrameSet pointer is stored in the Frame.
10076 *-
10077 */
10078
10079 /* Check the global error status. */
10080 if ( !astOK ) return;
10081
10082 /* Annul any variants FrameSet already stored in the Frame. */
10083 if( this->variants ) this->variants = astAnnul( this->variants );
10084
10085 /* Store a clone of ht esupplied FrameSet pointer. */
10086 if( variants ) this->variants = astClone( variants );
10087
10088 }
10089
SetUnit(AstFrame * this,int axis,const char * unit,int * status)10090 static void SetUnit( AstFrame *this, int axis, const char *unit, int *status ) {
10091 /*
10092 * Name:
10093 * SetUnit
10094
10095 * Purpose:
10096 * Set a value for the Unit attribute of a Frame.
10097
10098 * Type:
10099 * Protected virtual function.
10100
10101 * Synopsis:
10102 * #include "frame.h"
10103 * void SetUnit( AstFrame *this, int axis, const char *unit, int *status )
10104
10105 * Class Membership:
10106 * Frame method.
10107
10108 * Description:
10109 * This function sets the Unit value for a Frame.
10110
10111 * Parameters:
10112 * this
10113 * Pointer to the Frame.
10114 * axis
10115 * The number of the axis (zero-based) for which the Unit value is to
10116 * be set.
10117 * unit
10118 * The new value to be set.
10119 * status
10120 * Pointer to the inherited status variable.
10121
10122 * Returned Value:
10123 * void.
10124 */
10125
10126 /* Local Variables: */
10127 AstAxis *ax; /* Pointer to Axis object */
10128 char *c; /* Copy of supplied string */
10129 const char *oldunit; /* Pointer to old units string */
10130 int l; /* Used length of supplied string */
10131
10132 /* Check the global error status. */
10133 if ( !astOK ) return;
10134
10135 /* Get a copy of the supplied string which excludes trailing spaces. */
10136 l = astChrLen( unit );
10137 c = astStore( NULL, unit, (size_t) (l + 1) );
10138 if( astOK ) {
10139 c[ l ] = 0;
10140
10141 /* Validate the axis index and obtain a pointer to the required Axis. */
10142 (void) astValidateAxis( this, axis, 1, "astSetUnit" );
10143 ax = astGetAxis( this, axis );
10144
10145 /* The new unit may require the Label and/or Symbol to be changed, but
10146 only if the Frames ActiveUnit flag is set. */
10147 if( astGetActiveUnit( this ) ) {
10148
10149 /* Get the existing Axis unit, using the astGetUnit method (rather than
10150 astGetAxisUnit) in order to get any default value in the case where
10151 the Unit attribute is not set. */
10152 oldunit = astGetUnit( this, axis );
10153
10154 /* Assign the new Unit value. This modifies labels and/or Symbols if
10155 necessary. */
10156 NewUnit( ax, oldunit, c, "astSetUnit", astGetClass( this ), status );
10157 }
10158
10159 /* Set the Axis Unit attribute value. */
10160 astSetAxisUnit( ax, c );
10161
10162 /* Annul the Axis pointer. */
10163 ax = astAnnul( ax );
10164 }
10165
10166 /* Free the string copy */
10167 c = astFree( c );
10168
10169 }
10170
SubFrame(AstFrame * target,AstFrame * template,int result_naxes,const int * target_axes,const int * template_axes,AstMapping ** map,AstFrame ** result,int * status)10171 static int SubFrame( AstFrame *target, AstFrame *template,
10172 int result_naxes, const int *target_axes,
10173 const int *template_axes, AstMapping **map,
10174 AstFrame **result, int *status ) {
10175 /*
10176 *+
10177 * Name:
10178 * astSubFrame
10179
10180 * Purpose:
10181 * Select axes from a Frame and convert to the new coordinate system.
10182
10183 * Type:
10184 * Protected virtual function.
10185
10186 * Synopsis:
10187 * #include "frame.h"
10188 * int astSubFrame( AstFrame *target, AstFrame *template,
10189 * int result_naxes, const int *target_axes,
10190 * const int *template_axes, AstMapping **map,
10191 * AstFrame **result )
10192
10193 * Class Membership:
10194 * Frame method.
10195
10196 * Description:
10197 * This function selects a requested sub-set (or super-set) of the axes from
10198 * a "target" Frame and creates a new Frame with copies of the selected
10199 * axes assembled in the requested order. It then optionally overlays the
10200 * attributes of a "template" Frame on to the result. It returns both the
10201 * resulting Frame and a Mapping that describes how to convert between the
10202 * coordinate systems described by the target and result Frames. If
10203 * necessary, this Mapping takes account of any differences in the Frames'
10204 * attributes due to the influence of the template.
10205
10206 * Parameters:
10207 * target
10208 * Pointer to the target Frame, from which axes are to be selected.
10209 * template
10210 * Pointer to the template Frame, from which new attributes for the
10211 * result Frame are to be obtained. Optionally, this may be NULL, in
10212 * which case no overlaying of template attributes will be performed.
10213 * result_naxes
10214 * Number of axes to be selected from the target Frame. This number may
10215 * be greater than or less than the number of axes in this Frame (or
10216 * equal).
10217 * target_axes
10218 * Pointer to an array of int with result_naxes elements, giving a list
10219 * of the (zero-based) axis indices of the axes to be selected from the
10220 * target Frame. The order in which these are given determines the order
10221 * in which the axes appear in the result Frame. If any of the values in
10222 * this array is set to -1, the corresponding result axis will not be
10223 * derived from the target Frame, but will be assigned default attributes
10224 * instead.
10225 * template_axes
10226 * Pointer to an array of int with result_naxes elements. This should
10227 * contain a list of the template axes (given as zero-based axis indices)
10228 * with which the axes of the result Frame are to be associated. This
10229 * array determines which axes are used when overlaying axis-dependent
10230 * attributes of the template on to the result. If any element of this
10231 * array is set to -1, the corresponding result axis will not receive any
10232 * template attributes.
10233 *
10234 * If the template argument is given as NULL, this array is not used and
10235 * a NULL pointer may also be supplied here.
10236 * map
10237 * Address of a location to receive a pointer to the returned Mapping.
10238 * The forward transformation of this Mapping will describe how to
10239 * convert coordinates from the coordinate system described by the target
10240 * Frame to that described by the result Frame. The inverse
10241 * transformation will convert in the opposite direction.
10242 * result
10243 * Address of a location to receive a pointer to the result Frame.
10244
10245 * Returned Value:
10246 * A non-zero value is returned if coordinate conversion is
10247 * possible between the target and the result Frame. Otherwise zero
10248 * is returned and *map and *result are returned as NULL (but this
10249 * will not in itself result in an error condition). In general,
10250 * coordinate conversion should always be possible if no template
10251 * Frame is supplied but may not always be possible otherwise.
10252
10253 * Notes:
10254 * - A value of zero will be returned if this function is invoked
10255 * with the global error status set, or if it should fail for any
10256 * reason.
10257
10258 * Implementation Deficiencies:
10259 * - Any axis selection is currently permitted. Probably this
10260 * should be restricted so that each axis can only be selected
10261 * once. The astValidateAxisSelection method will do this but
10262 * currently there are bugs in the CmpFrame class that cause axis
10263 * selections which will not pass this test. Install the validation
10264 * when these are fixed.
10265 *-
10266
10267 * Implementation Notes:
10268 * - This implementation addresses the selection of axes from a
10269 * Frame class object. This simply results in another object of the
10270 * same class and a Mapping which describes an axis permutation (or
10271 * a unit Mapping as a special case). Changes of Frame attributes
10272 * have no significance for coordinate values in this class, so do
10273 * not affect the Mapping returned.
10274 */
10275
10276 /* Local Variables: */
10277 AstAxis *newaxis; /* Pointer to new Axis object */
10278 AstFrame *tempframe; /* Pointer to temporary Frame */
10279 AstMapping *aumap; /* A units Mapping for a single axis */
10280 AstMapping *numap; /* The new total units Mapping */
10281 AstMapping *umap; /* The total units Mapping */
10282 int *inperm; /* Pointer to permutation array */
10283 int *outperm; /* Pointer to permutation array */
10284 int match; /* Coordinate conversion possible? */
10285 int result_axis; /* Result Frame axis index */
10286 int target_axis; /* Target Frame axis index */
10287 int target_naxes; /* Number of target Frame axes */
10288 int unit; /* Unit Mapping appropriate? */
10289 int uunit; /* Is the "umap" Mapping a UnitMap? */
10290
10291 /* Initialise the returned values. */
10292 *map = NULL;
10293 *result = NULL;
10294 match = 0;
10295
10296 /* Check the global error status. */
10297 if ( !astOK ) return match;
10298
10299 /* Obtain the number of target Frame axes. */
10300 target_naxes = astGetNaxes( target );
10301
10302 /* Ensure we do not attempt to use a negative number of result axes. */
10303 if ( result_naxes < 0 ) result_naxes = 0;
10304
10305 /* Create a temporary new Frame with the required number of axes. This will
10306 have a default Axis object associated with each of its axes. We will
10307 replace these where necessary with copies of the actual Axis objects we
10308 require. */
10309 tempframe = astFrame( result_naxes, "", status );
10310
10311 /* Allocate memory to store two permutation arrays. These will be used to
10312 construct the Mapping that relates the target and result Frames. */
10313 inperm = astMalloc( sizeof( int ) * (size_t) target_naxes );
10314 outperm = astMalloc( sizeof( int ) * (size_t) result_naxes );
10315 if ( astOK ) {
10316
10317 /* Initialise the array that associates each target axis with the corresponding
10318 result axis (filling it with the value -1 initially signifies no
10319 associations). */
10320 for ( target_axis = 0; target_axis < target_naxes; target_axis++ ) {
10321 inperm[ target_axis ] = -1;
10322 }
10323
10324 /* Loop through each axis in the result Frame and obtain the index of the axis
10325 in the target Frame from which it is to be derived. */
10326 for ( result_axis = 0; result_axis < result_naxes; result_axis++ ) {
10327 target_axis = target_axes[ result_axis ];
10328
10329 /* Check if the resulting axis index is valid. If not, this result axis is not
10330 to be derived from any target axis, and it will therefore be left with its
10331 default attributes. Make an entry in the appropriate permutation array to
10332 indicate that this result axis is unassociated. */
10333 if ( ( target_axis < 0 ) || ( target_axis >= target_naxes ) ) {
10334 outperm[ result_axis ] = -1;
10335
10336 /* Otherwise, obtain a pointer to the target Axis object and modify the
10337 temporary Frame so that its axis is associated with the same Axis object.
10338 Annul the Axis pointer afterwards. */
10339 } else {
10340 newaxis = astGetAxis( target, target_axis );
10341 astSetAxis( tempframe, result_axis, newaxis );
10342 newaxis = astAnnul( newaxis );
10343
10344 /* Update both permutation arrays to record the association between the target
10345 and result axes. */
10346 outperm[ result_axis ] = target_axis;
10347 inperm[ target_axis ] = result_axis;
10348 }
10349
10350 /* Quit looping if an error occurs. */
10351 if ( !astOK ) break;
10352 }
10353
10354 /* So far, we have only modified pointers in the temporary Frame to refer to
10355 the target Frame's Axis objects. Since we will next modify these objects'
10356 attributes, we must make a deep copy of the entire temporary Frame so that
10357 we do not modify the target's axes. This copy now becomes our result Frame.
10358 Annul the temporary one. */
10359 if ( astOK ) {
10360 *result = astCopy( tempframe );
10361 tempframe = astAnnul( tempframe );
10362
10363 /* Invoke the target "astOverlay" method to overlay any remaining
10364 attributes from the target Frame which are not associated with
10365 individual axes (e.g. the Frame's Title and Domain). */
10366 astOverlay( target, target_axes, *result );
10367
10368 /* If a template Frame was supplied, also invoke its astOverlay method to
10369 overlay its attributes on the result Frame. (Note that in this particular
10370 case this has no effect other than transferring attributes. In general,
10371 however, i.e. in derived classes, this process is vital to determining the
10372 mapping below, whose main purpose is to convert between the target and
10373 result Frames. These will have different attributes as a result of the
10374 influence that the template has here.) */
10375 if ( template ) astOverlay( template, template_axes, *result );
10376
10377 /* We will next generate the Mapping that relates the target and result
10378 Frames. If appropriate this should be a unit Mapping (UnitMap), so test if
10379 the number of axes in both Frames is equal. */
10380 unit = ( target_naxes == result_naxes );
10381
10382 /* If so, check the contents of one of the permutation arrays to see if all
10383 result axes are associated with the corresponding target axis (the converse
10384 then also follows). If not, note this fact and quit checking. */
10385 if ( unit ) {
10386 for ( result_axis = 0; result_axis < result_naxes;
10387 result_axis++ ) {
10388 if ( outperm[ result_axis ] != result_axis ) {
10389 unit = 0;
10390 break;
10391 }
10392 }
10393 }
10394
10395 /* If a unit Mapping is appropriate, then construct it. */
10396 if ( unit ) {
10397 *map = (AstMapping *) astUnitMap( result_naxes, "", status );
10398
10399 /* Otherwise, construct a Mapping describing the axis permutation we have
10400 produced. */
10401 } else {
10402 *map = (AstMapping *) astPermMap( target_naxes, inperm,
10403 result_naxes, outperm, NULL,
10404 "", status );
10405 }
10406
10407 /* Note that coordinate conversion is possible. */
10408 match = 1;
10409
10410 /* If the ActiveUnit flag in both template and result Frame is non-zero, we
10411 now modify the Mapping to take account of any differences in the Units
10412 attributes of the target and results Frames. */
10413 if( template && astGetActiveUnit( template ) &&
10414 astGetActiveUnit( *result ) ) {
10415
10416 /* Loop round the axes of the results Frame, accumulating a parallel CmpMap
10417 ("umap") in which each Mapping is the 1-D Mapping which transforms the
10418 Units of the corresponding target axis into the Units of the results
10419 axis. */
10420 umap = NULL;
10421 uunit = 1;
10422 for( result_axis = 0; result_axis < result_naxes; result_axis++ ) {
10423
10424 /* Find the index of the corresponding target axis. */
10425 if( unit ) {
10426 target_axis = result_axis;
10427 } else {
10428 target_axis = outperm[ result_axis ];
10429 }
10430
10431 /* Get the Unit string for both axes, and attempt to find a Mapping which
10432 transforms values in the target units into the corresponding value in the
10433 results units. If this results axis does not have a corresponding
10434 target axis, then indicate that no units mapping can be found. */
10435 if( target_axis > -1 ) {
10436 aumap = astUnitMapper( astGetUnit( target, target_axis ),
10437 astGetUnit( *result, result_axis ),
10438 NULL, NULL );
10439 } else {
10440 aumap = NULL;
10441 }
10442
10443 /* If no Mapping could be found, annull the Mapping and leave the loop.
10444 Otherwise, see if the Mapping is a UnitMap. If not, set a flag to indicate
10445 that we have at least one non-unit map. */
10446 if( !aumap ) {
10447 if( umap ) umap = astAnnul( umap );
10448 match = 0;
10449 break;
10450 } else {
10451 if( !astIsAUnitMap( aumap ) ) uunit = 0;
10452 }
10453
10454 /* Add this Mapping into the parallel CmpMap. */
10455 if( umap ) {
10456 numap = (AstMapping *) astCmpMap( umap, aumap, 0, "", status );
10457 umap = astAnnul( umap );
10458 aumap = astAnnul( aumap );
10459 umap = numap;
10460 } else {
10461 umap = aumap;
10462 }
10463 }
10464
10465 /* If the resulting CmpMap is not just a UnitMap, add it in series with
10466 the current results mapping, and then simplify it. */
10467 if( !uunit && umap ) {
10468 numap = (AstMapping *) astCmpMap( *map, umap, 1, "", status );
10469 (void) astAnnul( *map );
10470 *map = numap;
10471 }
10472
10473 /* Annul the CmpMap containing the units Mappings. */
10474 if( umap ) umap = astAnnul( umap );
10475
10476 /* If the units could not bve matched annul the returned mapping. */
10477 if( !match && *map ) *map = astAnnul( *map );
10478 }
10479 }
10480 }
10481
10482 /* Free the memory used for the permutation arrays. */
10483 inperm = astFree( inperm );
10484 outperm = astFree( outperm );
10485
10486 /* If an error occurred, annul the returned objects and reset the returned
10487 value. */
10488 if ( !astOK ) {
10489 *map = astAnnul( *map );
10490 *result = astAnnul( *result );
10491 match = 0;
10492 }
10493
10494 /* Return the result. */
10495 return match;
10496 }
10497
SystemCode(AstFrame * this,const char * system,int * status)10498 static AstSystemType SystemCode( AstFrame *this, const char *system, int *status ) {
10499 /*
10500 *+
10501 * Name:
10502 * astSystemCode
10503
10504 * Purpose:
10505 * Convert a string into a coordinate system type code.
10506
10507 * Type:
10508 * Protected virtual function.
10509
10510 * Synopsis:
10511 * #include "frame.h"
10512 * AstSystemType SystemCode( AstFrame *this, const char *system )
10513
10514 * Class Membership:
10515 * Frame method.
10516
10517 * Description:
10518 * This function converts a string used for the external description of
10519 * a coordinate system into a Frame coordinate system type code (System
10520 * attribute value). It is the inverse of the astSystemString function.
10521
10522 * Parameters:
10523 * this
10524 * Pointer to the Frame.
10525 * system
10526 * Pointer to a constant null-terminated string containing the
10527 * external description of the coordinate system.
10528
10529 * Returned Value:
10530 * The System type code.
10531
10532 * Notes:
10533 * - A value of AST__BADSYSTEM is returned if the coordinate system
10534 * description was not recognised. This does not produce an error.
10535 * - A value of AST__BADSYSTEM is also returned if this function
10536 * is invoked with the global error status set or if it should fail
10537 * for any reason.
10538 *-
10539 */
10540
10541 /* Local Variables: */
10542 AstSystemType result; /* Result value to return */
10543
10544 /* Initialise. */
10545 result = AST__BADSYSTEM;
10546
10547 /* Check the global error status. */
10548 if ( !astOK ) return result;
10549
10550 /* Match the "system" string against each possibility and assign the
10551 result. The basic Frame class only supports a single system
10552 "Cartesian". */
10553 if ( astChrMatch( "Cartesian", system ) ) {
10554 result = AST__CART;
10555 }
10556
10557 /* Return the result. */
10558 return result;
10559 }
10560
SystemString(AstFrame * this,AstSystemType system,int * status)10561 static const char *SystemString( AstFrame *this, AstSystemType system, int *status ) {
10562 /*
10563 *+
10564 * Name:
10565 * astSystemString
10566
10567 * Purpose:
10568 * Convert a coordinate system type code into a string.
10569
10570 * Type:
10571 * Protected virtual function.
10572
10573 * Synopsis:
10574 * #include "frame.h"
10575 * const char *astSystemString( AstFrame *this, AstSystemType system )
10576
10577 * Class Membership:
10578 * Frame method.
10579
10580 * Description:
10581 * This function converts a Frame coordinate system type code
10582 * (System attribute value) into a string suitable for use as an
10583 * external representation of the coordinate system type.
10584
10585 * Parameters:
10586 * this
10587 * Pointer to the Frame.
10588 * system
10589 * The coordinate system type code.
10590
10591 * Returned Value:
10592 * Pointer to a constant null-terminated string containing the
10593 * textual equivalent of the type code supplied.
10594
10595 * Notes:
10596 * - A NULL pointer value is returned if the coordinate system
10597 * code was not recognised. This does not produce an error.
10598 * - A NULL pointer value is also returned if this function is
10599 * invoked with the global error status set or if it should fail
10600 * for any reason.
10601 *-
10602 */
10603
10604 /* Local Variables: */
10605 const char *result; /* Pointer value to return */
10606
10607 /* Initialise. */
10608 result = NULL;
10609
10610 /* Check the global error status. */
10611 if ( !astOK ) return result;
10612
10613 /* Match the "system" value against each possibility and convert to a
10614 string pointer. (Where possible, return the same string as would be
10615 used in the FITS WCS representation of the coordinate system). A basic
10616 Frame only allows a single System value, "Cartesian". */
10617 switch ( system ) {
10618 case AST__CART:
10619 result = "Cartesian";
10620 break;
10621 }
10622
10623 /* Return the result pointer. */
10624 return result;
10625
10626 }
10627
TestActiveUnit(AstFrame * this,int * status)10628 static int TestActiveUnit( AstFrame *this, int *status ){
10629 /*
10630 *+
10631 * Name:
10632 * astTestActiveUnit
10633
10634 * Purpose:
10635 * Determines if the ActiveUnit flag is set.
10636
10637 * Type:
10638 * Protected virtual function.
10639
10640 * Synopsis:
10641 * #include "frame.h"
10642 * int astTestActiveUnit( AstFrame *this )
10643
10644 * Class Membership:
10645 * Frame method.
10646
10647 * Description:
10648 * This function tests the current value of the ActiveUnit flag for a
10649 * Frame. See the description of the astSetActiveUnit function for a
10650 * description of the ActiveUnit flag.
10651
10652 * Parameters:
10653 * this
10654 * Pointer to the Frame.
10655
10656 * Returned Value:
10657 * Non-zero if the flag has been set. Zero otherwise.
10658
10659 * Notes:
10660 * - A zero value will be returned if this function is
10661 * invoked with the AST error status set, or if it should fail for
10662 * any reason.
10663 *--
10664 */
10665
10666 /* Local Variables: */
10667 int result; /* The returned value */
10668
10669 /* Initialise. */
10670 result = 0;
10671
10672 /* Check the global error status. */
10673 if ( !astOK ) return result;
10674
10675 /* Return the result. */
10676 return ( this->active_unit != -INT_MAX );
10677 }
10678
TestAttrib(AstObject * this_object,const char * attrib,int * status)10679 static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) {
10680 /*
10681 * Name:
10682 * TestAttrib
10683
10684 * Purpose:
10685 * Test if a specified attribute value is set for a Frame.
10686
10687 * Type:
10688 * Private function.
10689
10690 * Synopsis:
10691 * #include "frame.h"
10692 * int TestAttrib( AstObject *this, const char *attrib, int *status )
10693
10694 * Class Membership:
10695 * Frame member function (over-rides the astTestAttrib protected
10696 * method inherited from the Mapping class).
10697
10698 * Description:
10699 * This function returns a boolean result (0 or 1) to indicate whether
10700 * a value has been set for one of a Frame's attributes.
10701
10702 * Parameters:
10703 * this
10704 * Pointer to the Frame.
10705 * attrib
10706 * Pointer to a null terminated string specifying the attribute
10707 * name. This should be in lower case with no surrounding white
10708 * space.
10709 * status
10710 * Pointer to the inherited status variable.
10711
10712 * Returned Value:
10713 * One if a value has been set, otherwise zero.
10714
10715 * Notes:
10716 * - This function uses one-based axis numbering so that it is
10717 * suitable for external (public) use.
10718 * - A value of zero will be returned if this function is invoked
10719 * with the global status set, or if it should fail for any reason.
10720 */
10721
10722 /* Local Variables: */
10723 AstAxis *ax; /* Pointer to Axis */
10724 AstFrame *pfrm; /* Pointer to primary Frame containing axis */
10725 AstFrame *this; /* Pointer to the Frame structure */
10726 char pfrm_attrib[ 100 ]; /* Primary Frame attribute */
10727 char *axis_attrib; /* Pointer to axis attribute name */
10728 const char *old_attrib; /* Pointer to supplied attribute name string */
10729 int axis; /* Frame axis number */
10730 int axis_nc; /* No. characters in axis attribute name */
10731 int free_axis_attrib; /* Should axis_attrib be freed? */
10732 int has_axis; /* Does attrib name include axis specifier? */
10733 int len; /* Length of attrib string */
10734 int nc; /* No. characters read by astSscanf */
10735 int oldrep; /* Original error reporting state */
10736 int paxis; /* Axis index within primary frame */
10737 int result; /* Result value to return */
10738 int used; /* Could the setting string be used? */
10739
10740 /* Initialise. */
10741 result = 0;
10742
10743 /* Check the global error status. */
10744 if ( !astOK ) return result;
10745
10746 /* Obtain a pointer to the Frame structure. */
10747 this = (AstFrame *) this_object;
10748
10749 /* Set a flag indicating if the attribute name includes an axis
10750 specifier. */
10751 has_axis = ( strchr( attrib, '(' ) != NULL );
10752
10753 /* A flag indicating that we do not need to free the axis_attrib memory. */
10754 free_axis_attrib = 0;
10755
10756 /* Initialise things to avoid compiler warnings. */
10757 axis_attrib = NULL;
10758 old_attrib = NULL;
10759
10760 /* Jump back to here if we are trying the same attribute but with an explicit
10761 axis "(1)" added to the end of the name. */
10762 L1:
10763
10764 /* Obtain the length of the attrib string. */
10765 len = strlen( attrib );
10766
10767 /* Check the attribute name and test the appropriate attribute. */
10768
10769 /* Digits. */
10770 /* ------- */
10771 if ( !strcmp( attrib, "digits" ) ) {
10772 result = astTestDigits( this );
10773
10774 /* Digits(axis). */
10775 /* ------------- */
10776 } else if ( nc = 0,
10777 ( 1 == astSscanf( attrib, "digits(%d)%n", &axis, &nc ) )
10778 && ( nc >= len ) ) {
10779
10780 /* There is no function to test the Digits attribute for an axis
10781 directly, so obtain a pointer to the Axis and use this to test the
10782 attribute. */
10783 (void) astValidateAxis( this, axis - 1, 1, "astTestDigits(axis)" );
10784 ax = astGetAxis( this, axis - 1 );
10785 result = astTestAxisDigits( ax );
10786 ax = astAnnul( ax );
10787
10788 /* Direction(axis). */
10789 /* ---------------- */
10790 } else if ( nc = 0,
10791 ( 1 == astSscanf( attrib, "direction(%d)%n", &axis, &nc ) )
10792 && ( nc >= len ) ) {
10793 result = astTestDirection( this, axis - 1 );
10794
10795 /* Epoch. */
10796 /* ------ */
10797 } else if ( !strcmp( attrib, "epoch" ) ) {
10798 result = astTestEpoch( this );
10799
10800 /* Bottom(axis). */
10801 /* ------------- */
10802 } else if ( nc = 0,
10803 ( 1 == astSscanf( attrib, "bottom(%d)%n", &axis, &nc ) )
10804 && ( nc >= len ) ) {
10805 result = astTestBottom( this, axis - 1 );
10806
10807 /* Top(axis). */
10808 /* ---------- */
10809 } else if ( nc = 0,
10810 ( 1 == astSscanf( attrib, "top(%d)%n", &axis, &nc ) )
10811 && ( nc >= len ) ) {
10812 result = astTestTop( this, axis - 1 );
10813
10814 /* Domain. */
10815 /* ------- */
10816 } else if ( !strcmp( attrib, "domain" ) ) {
10817 result = astTestDomain( this );
10818
10819 /* Format(axis). */
10820 /* ------------- */
10821 } else if ( nc = 0,
10822 ( 1 == astSscanf( attrib, "format(%d)%n", &axis, &nc ) )
10823 && ( nc >= len ) ) {
10824 result = astTestFormat( this, axis - 1 );
10825
10826 /* Label(axis). */
10827 /* ------------ */
10828 } else if ( nc = 0,
10829 ( 1 == astSscanf( attrib, "label(%d)%n", &axis, &nc ) )
10830 && ( nc >= len ) ) {
10831 result = astTestLabel( this, axis - 1 );
10832
10833 /* MatchEnd. */
10834 /* --------- */
10835 } else if ( !strcmp( attrib, "matchend" ) ) {
10836 result = astTestMatchEnd( this );
10837
10838 /* MaxAxes. */
10839 /* -------- */
10840 } else if ( !strcmp( attrib, "maxaxes" ) ) {
10841 result = astTestMaxAxes( this );
10842
10843 /* MinAxes. */
10844 /* -------- */
10845 } else if ( !strcmp( attrib, "minaxes" ) ) {
10846 result = astTestMinAxes( this );
10847
10848 /* Permute. */
10849 /* -------- */
10850 } else if ( !strcmp( attrib, "permute" ) ) {
10851 result = astTestPermute( this );
10852
10853 /* PreserveAxes. */
10854 /* ------------- */
10855 } else if ( !strcmp( attrib, "preserveaxes" ) ) {
10856 result = astTestPreserveAxes( this );
10857
10858 /* Symbol(axis). */
10859 /* ------------- */
10860 } else if ( nc = 0,
10861 ( 1 == astSscanf( attrib, "symbol(%d)%n", &axis, &nc ) )
10862 && ( nc >= len ) ) {
10863 result = astTestSymbol( this, axis - 1 );
10864
10865 /* AlignSystem. */
10866 /* ------------ */
10867 } else if ( !strcmp( attrib, "alignsystem" ) ) {
10868 result = astTestAlignSystem( this );
10869
10870 /* System. */
10871 /* ------- */
10872 } else if ( !strcmp( attrib, "system" ) ) {
10873 result = astTestSystem( this );
10874
10875 /* Title. */
10876 /* ------ */
10877 } else if ( !strcmp( attrib, "title" ) ) {
10878 result = astTestTitle( this );
10879
10880 /* Unit(axis). */
10881 /* ----------- */
10882 } else if ( nc = 0,
10883 ( 1 == astSscanf( attrib, "unit(%d)%n", &axis, &nc ) )
10884 && ( nc >= len ) ) {
10885 result = astTestUnit( this, axis - 1 );
10886
10887 /* ObsLat. */
10888 /* ------- */
10889 } else if ( !strcmp( attrib, "obslat" ) ) {
10890 result = astTestObsLat( this );
10891
10892 /* ObsLon. */
10893 /* ------- */
10894 } else if ( !strcmp( attrib, "obslon" ) ) {
10895 result = astTestObsLon( this );
10896
10897 /* ObsAlt. */
10898 /* ------- */
10899 } else if ( !strcmp( attrib, "obsalt" ) ) {
10900 result = astTestObsAlt( this );
10901
10902 /* Dut1. */
10903 /* ---- */
10904 } else if ( !strcmp( attrib, "dut1" ) ) {
10905 result = astTestDut1( this );
10906
10907 /* Read-only attributes. */
10908 /* --------------------- */
10909 /* Test if the attribute name matches any of the read-only attributes
10910 of this class. If it does, then return zero. */
10911 } else if ( !strcmp( attrib, "naxes" ) ||
10912 !strncmp( attrib, "normunit", 8 ) ) {
10913 result = 0;
10914
10915 /* Other axis attributes. */
10916 /* ---------------------- */
10917 /* If the attribute was not identified above, but appears to refer to
10918 a Frame axis, then it may refer to an Axis object of a derived type
10919 (which has additional attributes not recognised here). */
10920 } else if ( !free_axis_attrib && ( nc = 0,
10921 ( 1 == astSscanf( attrib, "%*[^()]%n(%d)%n",
10922 &axis_nc, &axis, &nc ) )
10923 && ( nc >= len ) ) ) {
10924
10925 /* Validate the axis index and extract the attribute name. */
10926 (void) astValidateAxis( this, axis - 1, 1, "astTest" );
10927 axis_attrib = astString( attrib, axis_nc );
10928
10929 /* Obtain a pointer to the Axis object. */
10930 ax = astGetAxis( this, axis - 1 );
10931 if( astOK ) {
10932
10933 /* Assume that we will be able to use the attribute name. */
10934 used = 1;
10935
10936 /* Temporarily switch off error reporting so that if the following attempt
10937 to access the axis attribute fails, we can try to interpret the
10938 attribute name as an attribute of the primary Frame containing the
10939 specified axis. Any errors reported in this context will simply be
10940 ignored, in particularly they are not deferred for later delivery. */
10941 oldrep = astReporting( 0 );
10942
10943 /* Use the Axis astTestAttrib method to test the attribute value. */
10944 result = astTestAttrib( ax, axis_attrib );
10945
10946 /* If the above call failed with a status of AST__BADAT, indicating that
10947 the attribute name was not recognised, clear the status so that we can
10948 try to interpret the attribute name as an attribute of the primary Frame
10949 containing the specified axis. */
10950 if( astStatus == AST__BADAT ) {
10951 astClearStatus;
10952
10953 /* Find the primary Frame containing the specified axis. */
10954 astPrimaryFrame( this, axis - 1, &pfrm, &paxis );
10955
10956 /* Only attempt to use the primary Frame if it is not the same as "this"
10957 - otherwise we could end up in an infinite loop. */
10958 if( pfrm != this ) {
10959
10960 /* astPrimaryFrame returns the original - unpermuted - axis index within
10961 the primary Frame. So we need to take into account any axis permutation
10962 which has been applied to the primary Frame when forming the attribute name
10963 to use below. Find the permuted (external) axis index which corresponds to
10964 the internal (unpermuted) axis index "paxis". */
10965 paxis = astValidateAxis( pfrm, paxis, 0, "astTest" );
10966
10967 /* Modify the attribute name to refer to the axis numbering of the
10968 primary frame. */
10969 sprintf( pfrm_attrib, "%s(%d)", axis_attrib, paxis + 1 );
10970
10971 /* Attempt to test the attribute as an attribute of the primary Frame. */
10972 result = astTestAttrib( pfrm, pfrm_attrib );
10973
10974 /* If this failed, clear the status and indicate that we have not managed to
10975 use the attribute name. */
10976 if( !astOK ) {
10977 astClearStatus;
10978 used = 0;
10979 }
10980
10981 } else {
10982 used = 0;
10983 }
10984
10985 /* If not found attempt to test the attribute value in the Axis, omitting
10986 the axis index. */
10987 if( ! used ) {
10988 result = astTestAttrib( pfrm, axis_attrib );
10989 if( !astOK ) {
10990 astClearStatus;
10991 } else {
10992 used = 1;
10993 }
10994 }
10995
10996 /* Annul the primary Frame pointer. */
10997 pfrm = astAnnul( pfrm );
10998 }
10999
11000 /* Re-instate the original error reporting state. */
11001 astReporting( oldrep );
11002
11003 /* If we could not use the attribute name, attempt to test the axis
11004 attribute again, this time retaining the error report. This is done
11005 to ensure the user gets an appropriate error message. */
11006 if( !used ) result = astTestAttrib( ax, axis_attrib );
11007 }
11008
11009 /* Annul the Axis pointer and free the memory holding the attribute
11010 name. */
11011 ax = astAnnul( ax );
11012 axis_attrib = astFree( axis_attrib );
11013
11014 /* Not recognised. */
11015 /* --------------- */
11016 /* If the attribute is still not recognised, and the Frame has only 1 axis,
11017 and the attribute name does not already include an axis specifier, try
11018 again after appending "(1)" to the end of the attribute name. */
11019 } else if( !has_axis && astGetNaxes( this ) == 1 ) {
11020
11021 /* Take a copy of the supplied name, allowing 3 extra characters for the
11022 axis specifier "(1)". */
11023 axis_attrib = astMalloc( len + 4 );
11024 if( axis_attrib ) memcpy( axis_attrib, attrib, len );
11025
11026 /* Indicate we should free the axis_attrib memory. */
11027 free_axis_attrib = 1;
11028
11029 /* Add in the axis specifier. */
11030 strcpy( axis_attrib + len, "(1)" );
11031
11032 /* Use the new attribute name instead of the supplied name. */
11033 old_attrib = attrib;
11034 attrib = axis_attrib;
11035
11036 /* Indicate the attribute name now has an axis specifier. */
11037 has_axis = 1;
11038
11039 /* Jump back to try interpreting the new attribute name. */
11040 goto L1;
11041
11042 /* Not recognised. */
11043 /* --------------- */
11044 /* If the attribute name is still not recognised, pass it on to the parent
11045 method for further interpretation. First re-instate the original attrib
11046 name string if it was changed above. */
11047 } else {
11048 if( free_axis_attrib ) {
11049 attrib = old_attrib;
11050 axis_attrib = astFree( axis_attrib );
11051 }
11052 result = (*parent_testattrib)( this_object, attrib, status );
11053 }
11054
11055 /* Return the result, */
11056 return result;
11057 }
11058
Transform(AstMapping * this_mapping,AstPointSet * in,int forward,AstPointSet * out,int * status)11059 static AstPointSet *Transform( AstMapping *this_mapping, AstPointSet *in,
11060 int forward, AstPointSet *out, int *status ) {
11061 /*
11062 * Name:
11063 * Transform
11064
11065 * Purpose:
11066 * Use a Frame to transform a set of points.
11067
11068 * Type:
11069 * Private function.
11070
11071 * Synopsis:
11072 * #include "frame.h"
11073 * AstPointSet *Transform( AstMapping *this, AstPointSet *in,
11074 * int forward, AstPointSet *out, int *status )
11075
11076 * Class Membership:
11077 * Frame member function (over-rides the astTransform method inherited
11078 * from the Mapping class).
11079
11080 * Description:
11081 * This function takes a Frame and a set of points encapsulated in a
11082 * PointSet and transforms the points so as to perform the identity
11083 * transformation (i.e. simply copies the coordinate values).
11084
11085 * Parameters:
11086 * this
11087 * Pointer to the Frame.
11088 * in
11089 * Pointer to the PointSet holding the input coordinate data.
11090 * forward
11091 * A non-zero value indicates that the forward coordinate transformation
11092 * should be applied, while a zero value requests the inverse
11093 * transformation. In this case, both transformations are equivalent.
11094 * out
11095 * Pointer to a PointSet which will hold the transformed (output)
11096 * coordinate values. A NULL value may also be given, in which case a
11097 * new PointSet will be created by this function.
11098 * status
11099 * Pointer to the inherited status variable.
11100
11101 * Returned Value:
11102 * Pointer to the output (possibly new) PointSet.
11103
11104 * Notes:
11105 * - A null pointer will be returned if this function is invoked with the
11106 * global error status set, or if it should fail for any reason.
11107 * - The number of coordinate values per point in the input PointSet must
11108 * match the number of coordinates for the Frame being applied. This number
11109 * will be equal to the number of Frame axes.
11110 * - If an output PointSet is supplied, it must have space for sufficient
11111 * number of points and coordinate values per point to accommodate the
11112 * result. Any excess space will be ignored.
11113 */
11114
11115 /* Local Variables: */
11116 AstFrame *this; /* Pointer to the Frame structure */
11117 AstPointSet *result; /* Pointer value to be returned */
11118 AstUnitMap *unitmap; /* Pointer to temporary UnitMap */
11119
11120 /* Check the global error status. */
11121 if ( !astOK ) return NULL;
11122
11123 /* Obtain a pointer to the Frame structure. */
11124 this = (AstFrame *) this_mapping;
11125
11126 /* Create a unit Mapping with one coordinate for each Frame axis. */
11127 unitmap = astUnitMap( astGetNaxes( this ), "", status );
11128
11129 /* Use the Mapping to transform (i.e. copy) the coordinate values. */
11130 result = astTransform( unitmap, in, forward, out );
11131
11132 /* Annul the Mapping. */
11133 unitmap = astAnnul( unitmap );
11134
11135 /* If an error occurred and a new PointSet may have been created, then annul
11136 the result. In any case, ensure that a NULL pointer is returned. */
11137 if ( !astOK ) {
11138 if ( !out ) result = astAnnul( result );
11139 result = NULL;
11140 }
11141
11142 /* Return the result pointer. */
11143 return result;
11144 }
11145
Unformat(AstFrame * this,int axis,const char * string,double * value,int * status)11146 static int Unformat( AstFrame *this, int axis, const char *string,
11147 double *value, int *status ) {
11148 /*
11149 *+
11150 * Name:
11151 * astUnformat
11152
11153 * Purpose:
11154 * Read a formatted coordinate value for a Frame axis.
11155
11156 * Type:
11157 * Protected virtual function.
11158
11159 * Synopsis:
11160 * #include "frame.h"
11161 * int astUnformat( AstFrame *this, int axis, const char *string,
11162 * double *value )
11163
11164 * Class Membership:
11165 * Frame method.
11166
11167 * Description:
11168 * This function reads a formatted coordinate value for a Frame
11169 * axis (supplied as a string) and returns the equivalent numerical
11170 * value as a double. It also returns the number of characters read
11171 * from the string.
11172
11173 * Parameters:
11174 * this
11175 * Pointer to the Frame.
11176 * axis
11177 * The number of the Frame axis for which the coordinate value
11178 * is to be read (axis numbering starts at zero for the first
11179 * axis).
11180 * string
11181 * Pointer to a constant null-terminated string containing the
11182 * formatted coordinate value.
11183 * value
11184 * Pointer to a double in which the coordinate value read will be
11185 * returned.
11186
11187 * Returned Value:
11188 * The number of characters read from the string to obtain the
11189 * coordinate value.
11190
11191 * Notes:
11192 * - Any white space at the beginning of the string will be
11193 * skipped, as also will any trailing white space following the
11194 * coordinate value read. The function's return value will reflect
11195 * this.
11196 * - A function value of zero (and no coordinate value) will be
11197 * returned, without error, if the string supplied does not contain
11198 * a suitably formatted value.
11199 * - The string "<bad>" is recognised as a special case and will
11200 * generate the value AST__BAD, without error. The test for this
11201 * string is case-insensitive and permits embedded white space.
11202 * - A function result of zero will be returned and no coordinate
11203 * value will be returned via the "value" pointer if this function
11204 * is invoked with the global error status set, or if it should
11205 * fail for any reason.
11206 *-
11207
11208 * Implementation Notes:
11209 * - This function implements the basic astUnformat method
11210 * available via the protected interface to the Frame class. The
11211 * public interface to this method is provided by the
11212 * astUnformatId_ function.
11213 */
11214
11215 /* Local Variables: */
11216 AstAxis *ax; /* Pointer to Axis object */
11217 const char *label; /* Pointer to axis label string */
11218 double coord; /* Coordinate value read */
11219 int digits_set; /* Axis Digits attribute set? */
11220 int nc; /* Number of characters read */
11221 int status_value; /* AST error status */
11222
11223 /* Initialise. */
11224 nc = 0;
11225
11226 /* Check the global error status. */
11227 if ( !astOK ) return nc;
11228
11229 /* Validate the axis index and obtain a pointer to the required Axis. */
11230 (void) astValidateAxis( this, axis, 1, "astUnformat" );
11231 ax = astGetAxis( this, axis );
11232
11233 /* Test if any Axis attributes which may affect the result are
11234 undefined (i.e. have not been explicitly set). If so, we over-ride
11235 them, giving them temporary values dictated by the Frame. Only the
11236 Digits attribute is potentially relevant here. */
11237 digits_set = astTestAxisDigits( ax );
11238 if ( !digits_set ) astSetAxisDigits( ax, astGetDigits( this ) );
11239
11240 /* Read the coordinate value. */
11241 if ( astOK ) {
11242 nc = astAxisUnformat( ax, string, &coord );
11243
11244 /* If an error occurred, save and temporarily clear the global error
11245 status while the axis Label string is obtained. Then restore the
11246 original error status value afterwards. */
11247 if ( !astOK ) {
11248 status_value = astStatus;
11249 astClearStatus;
11250 label = astGetLabel( this, axis );
11251 astSetStatus( status_value );
11252
11253 /* Report a contextual error message containing the axis label. */
11254 astError( status_value, "%s(%s): Unable to read \"%s\" value.", status,
11255 "astUnformat", astGetClass( this ), label );
11256 }
11257 }
11258
11259 /* Clear any Axis attributes that were temporarily over-ridden. */
11260 if ( !digits_set ) astClearAxisDigits( ax );
11261
11262 /* Annul the Axis pointer. */
11263 ax = astAnnul( ax );
11264
11265 /* If an error occurred, clear the count of characters read. */
11266 if ( !astOK ) {
11267 nc = 0;
11268
11269 /* Otherwise, if characters were read, return the coordinate value. */
11270 } else if ( nc ) {
11271 *value = coord;
11272 }
11273
11274 /* Return the number of characters read. */
11275 return nc;
11276 }
11277
ValidateAxis(AstFrame * this,int axis,int fwd,const char * method,int * status)11278 static int ValidateAxis( AstFrame *this, int axis, int fwd, const char *method,
11279 int *status ) {
11280 /*
11281 *+
11282 * Name:
11283 * astValidateAxis
11284
11285 * Purpose:
11286 * Validate and permute a Frame's axis index.
11287
11288 * Type:
11289 * Protected virtual function.
11290
11291 * Synopsis:
11292 * #include "frame.h"
11293 * int astValidateAxis( AstFrame *this, int axis, int fwd,
11294 * const char *method )
11295
11296 * Class Membership:
11297 * Frame method.
11298
11299 * Description:
11300 * This function checks the validity of an index (zero-based) which
11301 * is to be used to address one of the coordinate axes of a
11302 * Frame. If the index is valid, it is permuted using the axis
11303 * permutation array associated with the Frame and the (zero-based)
11304 * permuted axis index is returned. This gives the location of the
11305 * required axis information within the Frame's internal arrays. If
11306 * the axis index supplied is not valid, an error is reported and
11307 * the global error status is set.
11308
11309 * Parameters:
11310 * this
11311 * Pointer to the Frame.
11312 * axis
11313 * The axis index (zero-based) to be checked. To be valid, it
11314 * must lie between zero and (naxes-1) inclusive, where "naxes"
11315 * is the number of coordinate axes associated with the Frame.
11316 * fwd
11317 * If non-zero, the suppplied axis index is assumed to be an
11318 * "external" axis index, and the corresponding "internal" axis index
11319 * is returned as the function value. Otherwise, the suppplied axis
11320 * index is assumed to be an "internal" axis index, and the
11321 * corresponding "external" axis index is returned as the function
11322 * value.
11323 * method
11324 * Pointer to a constant null-terminated character string
11325 * containing the name of the method that invoked this function
11326 * to validate an axis index. This method name is used solely
11327 * for constructing error messages.
11328
11329 * Returned Value:
11330 * The permuted axis index - either "internal" or "external" as
11331 * specified by "fwd".
11332
11333 * Notes:
11334 * - A value of zero will be returned if this function is invoked
11335 * with the global error status set, or if it should fail for any
11336 * reason.
11337 * - Error messages issued by this function refer to the public
11338 * numbering system used for axes which is one-based (zero-based axis
11339 * indices are used internally).
11340 *-
11341 */
11342
11343 /* Local Variables: */
11344 const int *perm; /* Pointer to axis permutation array */
11345 int naxes; /* Number of Frame axes */
11346 int result; /* Permuted axis index */
11347
11348 /* Initialise. */
11349 result = 0;
11350
11351 /* Determine the number of Frame axes. */
11352 naxes = astGetNaxes( this );
11353 if ( astOK ) {
11354
11355 /* If the Frame has no axes, report an error (note we convert to
11356 one-based axis numbering in the error message). */
11357 if ( naxes == 0 ) {
11358 astError( AST__AXIIN, "%s(%s): Invalid attempt to use an axis index "
11359 "(%d) for a %s which has no axes.", status, method,
11360 astGetClass( this ), axis + 1, astGetClass( this ) );
11361
11362 /* Otherwise, check the axis index for validity and report an error if
11363 it is not valid (again, use one-based axis numbering). */
11364 } else if ( ( axis < 0 ) || ( axis >= naxes ) ) {
11365 astError( AST__AXIIN, "%s(%s): Axis index (%d) invalid - it should "
11366 "be in the range 1 to %d.", status, method, astGetClass( this ),
11367 axis + 1, naxes );
11368
11369 /* If the axis index was valid, obtain the axis permutation array and
11370 use this to generate the permuted axis value. */
11371 } else {
11372 perm = astGetPerm( this );
11373 if( perm ) {
11374
11375 /* External to internal is a simple look-up. */
11376 if( fwd ) {
11377 result = perm[ axis ];
11378
11379 /* Internal to external requires a search through the permutation array. */
11380 } else {
11381 for( result = 0; result < naxes; result++ ) {
11382 if( perm[ result ] == axis ) break;
11383 }
11384 }
11385 }
11386 }
11387 }
11388
11389 /* Return the result. */
11390 return result;
11391 }
11392
ValidateAxisSelection(AstFrame * this,int naxes,const int * axes,const char * method,int * status)11393 static void ValidateAxisSelection( AstFrame *this, int naxes, const int *axes,
11394 const char *method, int *status ) {
11395 /*
11396 *+
11397 * Name:
11398 * astValidateAxisSelection
11399
11400 * Purpose:
11401 * Check that a set of axes selected from a Frame is valid.
11402
11403 * Type:
11404 * Protected virtual function.
11405
11406 * Synopsis:
11407 * #include "frame.h"
11408 * void astValidateAxisSelection( AstFrame *this, int naxes,
11409 * const int *axes, const char *method )
11410
11411 * Class Membership:
11412 * Frame method.
11413
11414 * Description:
11415 * This function checks the validity of an array of (zero-based)
11416 * axis indices that specify a set of axes to be selected from a
11417 * Frame. To be valid, no axis should be selected more than
11418 * once. In assessing this, any axis indices that do not refer to
11419 * valid Frame axes (e.g. are set to -1) are ignored.
11420 *
11421 * If the axis selection is valid, this function returns without further
11422 * action. Otherwise, an error is reported and the global error status is
11423 * set.
11424
11425 * Parameters:
11426 * this
11427 * Pointer to the Frame.
11428 * naxes
11429 * The number of axes to be selected (may be zero).
11430 * axes
11431 * Pointer to an array of int with naxes elements that contains the
11432 * (zero based) axis indices to be checked.
11433 * method
11434 * Pointer to a constant null-terminated character string
11435 * containing the name of the method that invoked this function
11436 * to validate an axis selection. This method name is used
11437 * solely for constructing error messages.
11438 *-
11439 */
11440
11441 /* Local Variables: */
11442 int *count; /* Pointer to temporary array of counts */
11443 int axis; /* Loop counter for selected axes */
11444 int frame_axis; /* Loop counter for Frame axes */
11445 int frame_naxes; /* Number of Frame axes */
11446 int valid; /* Axis selection valid? */
11447
11448 /* Check the global error status. */
11449 if ( !astOK ) return;
11450
11451 /* Check to see if no axes have been selected. If so, there is nothing to
11452 do. */
11453 if ( naxes ) {
11454
11455 /* Initialise. */
11456 valid = 1;
11457
11458 /* Obtain the number of Frame axes and allocate an array of int with
11459 one element for each Frame axis. This will store a count of the
11460 number of times each axis is selected. */
11461 frame_naxes = astGetNaxes( this );
11462 count = astMalloc( sizeof( int ) * (size_t) frame_naxes );
11463 if ( astOK ) {
11464
11465 /* Initialise the array of counts to zero. */
11466 for ( frame_axis = 0; frame_axis < frame_naxes; frame_axis++ ) {
11467 count[ frame_axis ] = 0;
11468 }
11469
11470 /* Loop through each selected axis. */
11471 for ( axis = 0; axis < naxes; axis++ ) {
11472 frame_axis = axes[ axis ];
11473
11474 /* Check if the selected axis index is valid for the Frame. If so, increment
11475 the selection count for that Frame axis. */
11476 if ( ( frame_axis >= 0 ) && ( frame_axis < frame_naxes ) ) {
11477 count[ frame_axis ]++;
11478 }
11479 }
11480
11481 /* Loop through the count array and check that no Frame axis was selected
11482 more than once. If it was, clear the "valid" flag and quit checking. */
11483 for ( frame_axis = 0; frame_axis < frame_naxes; frame_axis++ ) {
11484 if ( count[ frame_axis ] > 1 ) {
11485 valid = 0;
11486 break;
11487 }
11488 }
11489 }
11490
11491 /* Free the temporary count array. */
11492 count = astFree( count );
11493
11494 /* If no error has occurred, but the axis selection is not valid, then report
11495 an error. */
11496 if ( astOK && !valid ) {
11497 astError( AST__SELIN, "%s(%s): Invalid axis selection - each axis "
11498 "may be selected only once.", status, method, astGetClass( this ) );
11499 }
11500 }
11501 }
11502
ValidateSystem(AstFrame * this,AstSystemType system,const char * method,int * status)11503 static int ValidateSystem( AstFrame *this, AstSystemType system, const char *method, int *status ) {
11504 /*
11505 *+
11506 * Name:
11507 * astValidateSystem
11508
11509 * Purpose:
11510 * Validate a value for a Frame's System attribute.
11511
11512 * Type:
11513 * Protected virtual function.
11514
11515 * Synopsis:
11516 * #include "frame.h"
11517 * int astValidateSystem( AstFrame *this, AstSystemType system,
11518 * const char *method )
11519
11520 * Class Membership:
11521 * Frame method.
11522
11523 * Description:
11524 * This function checks the validity of the supplied system value.
11525 * If the value is valid, it is returned unchanged. Otherwise, an
11526 * error is reported and a value of AST__BADSYSTEM is returned.
11527
11528 * Parameters:
11529 * this
11530 * Pointer to the Frame.
11531 * system
11532 * The system value to be checked.
11533 * method
11534 * Pointer to a constant null-terminated character string
11535 * containing the name of the method that invoked this function
11536 * to validate an axis index. This method name is used solely
11537 * for constructing error messages.
11538
11539 * Returned Value:
11540 * The validated system value.
11541
11542 * Notes:
11543 * - A value of AST_BADSYSTEM will be returned if this function is invoked
11544 * with the global error status set, or if it should fail for any
11545 * reason.
11546 *-
11547 */
11548
11549 /* Local Variables: */
11550 AstSystemType result; /* Validated system value */
11551
11552 /* Initialise. */
11553 result = AST__BADSYSTEM;
11554
11555 /* Check the global error status. */
11556 if ( !astOK ) return result;
11557
11558 /* If the value is out of bounds, report an error. */
11559 if ( system < FIRST_SYSTEM || system > LAST_SYSTEM ) {
11560 astError( AST__AXIIN, "%s(%s): Bad value (%d) given for the System "
11561 "or AlignSystem attribute of a %s.", status, method,
11562 astGetClass( this ), (int) system, astGetClass( this ) );
11563
11564 /* Otherwise, return the supplied value. */
11565 } else {
11566 result = system;
11567 }
11568
11569 /* Return the result. */
11570 return result;
11571 }
11572
11573 /* Functions which access class attributes. */
11574 /* ---------------------------------------- */
11575 /* Implement member functions to access the attributes associated with
11576 the axes of a Frame using the private macros defined for this
11577 purpose at the start of this file. */
11578
11579 /*
11580 *att++
11581 * Name:
11582 * Naxes
11583
11584 * Purpose:
11585 * Number of Frame axes.
11586
11587 * Type:
11588 * Public attribute.
11589
11590 * Synopsis:
11591 * Integer, read-only.
11592
11593 * Description:
11594 * This is a read-only attribute giving the number of axes in a
11595 * Frame (i.e. the number of dimensions of the coordinate space
11596 * which the Frame describes). This value is determined when the
11597 * Frame is created.
11598
11599 * Applicability:
11600 * Frame
11601 * All Frames have this attribute.
11602 * FrameSet
11603 * The Naxes attribute of a FrameSet is the same as that of its
11604 * current Frame (as specified by the Current attribute).
11605 * CmpFrame
11606 * The Naxes attribute of a CmpFrame is equal to the sum of the
11607 * Naxes values of its two component Frames.
11608 *att--
11609 */
11610
11611
11612 /*
11613 *att++
11614 * Name:
11615 * Direction(axis)
11616
11617 * Purpose:
11618 * Display axis in conventional direction?
11619
11620 * Type:
11621 * Public attribute.
11622
11623 * Synopsis:
11624 * Integer (boolean).
11625
11626 * Description:
11627 * This attribute is a boolean value which suggests how the axes of
11628 * a Frame should be displayed (e.g.) in graphical output. By
11629 * default, it has the value one, indicating that they should be
11630 * shown in the conventional sense (increasing left to right for an
11631 * abscissa, and bottom to top for an ordinate). If set to zero,
11632 * this attribute indicates that the direction should be reversed,
11633 * as would often be done for an astronomical magnitude or a right
11634 * ascension axis.
11635
11636 * Applicability:
11637 * Frame
11638 * The default Direction value supplied by the Frame class is 1,
11639 * indicating that all axes should be displayed in the
11640 * conventional direction.
11641 * SkyFrame
11642 * The SkyFrame class re-defines the default Direction value to
11643 * suggest that certain axes (e.g. right ascension) should be
11644 * plotted in reverse when appropriate.
11645 * FrameSet
11646 * The Direction attribute of a FrameSet axis is the same as
11647 * that of its current Frame (as specified by the Current
11648 * attribute).
11649 * Plot
11650 * The Direction attribute of the base Frame in a Plot is set to
11651 * indicate the sense of the two graphics axes, as implied by the
11652 * graphics bounding box supplied when the Plot was created.
11653
11654 * Notes:
11655 * - When specifying this attribute by name, it should be
11656 * subscripted with the number of the Frame axis to which it
11657 * applies.
11658 * - The Direction attribute does not directly affect the behaviour
11659 * of the AST library. Instead, it serves as a hint to applications
11660 * programs about the orientation in which they may wish to display
11661 * any data associated with the Frame. Applications are free to
11662 * ignore this hint if they wish.
11663 *att--
11664 */
11665 /* This simply provides an interface to the Axis methods for accessing
11666 the Direction flag. */
11667 MAKE_CLEAR(Direction)
11668 MAKE_GET(Direction,int,0,0,0)
MAKE_SET(Direction,int)11669 MAKE_SET(Direction,int)
11670 MAKE_TEST(Direction)
11671
11672 /*
11673 *att++
11674 * Name:
11675 * Dut1
11676
11677 * Purpose:
11678 * The UT1-UTC correction.
11679
11680 * Type:
11681 * Public attribute.
11682
11683 * Synopsis:
11684 * Floating point.
11685
11686 * Description:
11687 * This attribute is used when calculating the Local Apparent Sidereal
11688 * Time corresponding to SkyFrame's Epoch value (used when converting
11689 * positions to or from the "AzEl" system). It should be set to the
11690 * difference, in seconds, between the UT1 and UTC timescales at the
11691 * moment in time represented by the SkyFrame's Epoch attribute. The
11692 * value to use is unpredictable and depends on changes in the earth's
11693 * rotation speed. Values for UT1-UTC can be obtained from the
11694 * International Earth Rotation and Reference Systems Service
11695 * (IERS) at http://www.iers.org/.
11696 *
11697 * Currently, the correction is always less than 1 second. This is
11698 * ensured by the occasional introduction of leap seconds into the UTC
11699 * timescale. Therefore no great error will usually result if no value
11700 * is assigned to this attribute (in which case a default value of
11701 * zero is used). However, it is possible that a decision may be taken
11702 * at some time in the future to abandon the introduction of leap
11703 * seconds, in which case the DUT correction could grow to significant
11704 * sizes.
11705
11706 * Applicability:
11707 * Frame
11708 * All Frames have this attribute.
11709
11710 *att--
11711 */
11712 /* The UT1-UTC correction, in seconds. Has a value of AST__BAD when not set
11713 yielding a default value of 0.0. */
11714 astMAKE_CLEAR(Frame,Dut1,dut1,AST__BAD)
11715 astMAKE_GET(Frame,Dut1,double,0.0,(this->dut1 == AST__BAD ? 0.0 : this->dut1))
11716 astMAKE_SET(Frame,Dut1,double,dut1,value)
11717 astMAKE_TEST(Frame,Dut1,( this->dut1 != AST__BAD ))
11718
11719
11720
11721 /*
11722 *att++
11723 * Name:
11724 * Epoch
11725
11726 * Purpose:
11727 * Epoch of observation.
11728
11729 * Type:
11730 * Public attribute.
11731
11732 * Synopsis:
11733 * Floating point.
11734
11735 * Description:
11736 * This attribute is used to qualify the coordinate systems described by
11737 * a Frame, by giving the moment in time when the coordinates are known
11738 * to be correct. Often, this will be the date of observation, and is
11739 * important in cases where coordinates systems move with respect to each
11740 * other over the course of time.
11741 *
11742 * The Epoch attribute is stored as a Modified Julian Date, but
11743 * when setting its value it may be given in a variety of
11744 * formats. See the "Input Formats" section (below) for details.
11745 * Strictly, the Epoch value should be supplied in the TDB timescale,
11746 * but for some purposes (for instance, for converting sky positions
11747 * between different types of equatorial system) the timescale is not
11748 * significant, and UTC may be used.
11749
11750 * Input Formats:
11751 * The formats accepted when setting an Epoch value are listed
11752 * below. They are all case-insensitive and are generally tolerant
11753 * of extra white space and alternative field delimiters:
11754 *
11755 * - Besselian Epoch: Expressed in decimal years, with or without
11756 * decimal places ("B1950" or "B1976.13" for example).
11757 *
11758 * - Julian Epoch: Expressed in decimal years, with or without
11759 * decimal places ("J2000" or "J2100.9" for example).
11760 *
11761 * - Year: Decimal years, with or without decimal places ("1996.8"
11762 * for example). Such values are interpreted as a Besselian epoch
11763 * (see above) if less than 1984.0 and as a Julian epoch otherwise.
11764 *
11765 * - Julian Date: With or without decimal places ("JD 2454321.9" for
11766 * example).
11767 *
11768 * - Modified Julian Date: With or without decimal places
11769 * ("MJD 54321.4" for example).
11770 *
11771 * - Gregorian Calendar Date: With the month expressed either as an
11772 * integer or a 3-character abbreviation, and with optional decimal
11773 * places to represent a fraction of a day ("1996-10-2" or
11774 * "1996-Oct-2.6" for example). If no fractional part of a day is
11775 * given, the time refers to the start of the day (zero hours).
11776 *
11777 * - Gregorian Date and Time: Any calendar date (as above) but with
11778 * a fraction of a day expressed as hours, minutes and seconds
11779 * ("1996-Oct-2 12:13:56.985" for example). The date and time can be
11780 * separated by a space or by a "T" (as used by ISO8601 format).
11781
11782 * Output Format:
11783 * When enquiring Epoch values, the format used is the "Year"
11784 * format described under "Input Formats". This is a value in
11785 * decimal years which will be a Besselian epoch if less than
11786 * 1984.0 and a Julian epoch otherwise. By omitting any character
11787 * prefix, this format allows the Epoch value to be obtained as
11788 * either a character string or a floating point value.
11789
11790 * Applicability:
11791 * Frame
11792 * All Frames have this attribute. The basic Frame class provides
11793 * a default of J2000.0 (Julian) but makes no use of the Epoch value.
11794 * This is because the Frame class does not distinguish between
11795 * different Cartesian coordinate systems (see the System attribute).
11796 * CmpFrame
11797 * The default Epoch value for a CmpFrame is selected as follows;
11798 * if the Epoch attribute has been set in the first component Frame
11799 * then the Epoch value from the first component Frame is used as
11800 * the default for the CmpFrame. Otherwise, if the Epoch attribute has
11801 * been set in the second component Frame then the Epoch value from the
11802 * second component Frame is used as the default for the CmpFrame.
11803 * Otherwise, the default Epoch value from the first component
11804 * Frame is used as the default for the CmpFrame. When the Epoch
11805 * attribute of a CmpFrame is set or cleared, it is also set or
11806 * cleared in the two component Frames.
11807 * FrameSet
11808 * The Epoch attribute of a FrameSet is the same as that of its current
11809 * Frame (as specified by the Current attribute).
11810 * SkyFrame
11811 * The coordinates of sources within a SkyFrame can changed with time
11812 * for various reasons, including: (i) changing aberration of light
11813 * caused by the observer's velocity (e.g. due to the Earth's motion
11814 * around the Sun), (ii) changing gravitational deflection by the Sun
11815 * due to changes in the observer's position with time, (iii) fictitious
11816 * motion due to rotation of non-inertial coordinate systems (e.g. the
11817 * old FK4 system), and (iv) proper motion of the source itself (although
11818 * this last effect is not handled by the SkyFrame class because it
11819 * affects individual sources rather than the coordinate system as
11820 * a whole).
11821 *
11822 * The default Epoch value in a SkyFrame is B1950.0 (Besselian) for the
11823 * old FK4-based coordinate systems (see the System attribute) and
11824 * J2000.0 (Julian) for all others.
11825 *
11826 * Care must be taken to distinguish the Epoch value, which relates to
11827 * motion (or apparent motion) of the source, from the superficially
11828 * similar Equinox value. The latter is used to qualify a coordinate
11829 * system which is itself in motion in a (notionally) predictable way
11830 * as a result of being referred to a slowly moving reference plane
11831 * (e.g. the equator).
11832 *
11833 * See the description of the System attribute for details of which
11834 * qualifying attributes apply to each celestial coordinate system.
11835 * TimeFrame
11836 * A TimeFrame describes a general time axis and so cannot be completely
11837 * characterised by a single Epoch value. For this reason the TimeFrame
11838 * class makes no use of the Epoch attribute. However, user code can
11839 * still make use of the attribute if necessary to represent a "typical"
11840 * time spanned by the TimeFrame. The default Epoch value for a TimeFrame
11841 * will be the TDB equivalent of the current value of the TimeFrame's
11842 * TimeOrigin attribute. If no value has been set for TimeOrigin,
11843 * then the default Epoch value is J2000.0.
11844
11845
11846 The coordinates of sources within a SkyFrame can changed with time
11847 *att--
11848 */
11849 /* Clear the Epoch value by setting it to AST__BAD. */
11850 astMAKE_CLEAR(Frame,Epoch,epoch,AST__BAD)
11851
11852 /* Provide a default value of J2000.0 setting. */
11853 astMAKE_GET(Frame,Epoch,double,AST__BAD,(
11854 ( this->epoch != AST__BAD ) ? this->epoch : palEpj2d( 2000.0 )))
11855
11856 /* Allow any Epoch value to be set. */
11857 astMAKE_SET(Frame,Epoch,double,epoch,value)
11858
11859 /* An Epoch value is set if it is not equal to AST__BAD. */
11860 astMAKE_TEST(Frame,Epoch,( this->epoch != AST__BAD ))
11861
11862 /*
11863 *att++
11864 * Name:
11865 * Top(axis)
11866
11867 * Purpose:
11868 * Highest axis value to display
11869
11870 * Type:
11871 * Public attribute.
11872
11873 * Synopsis:
11874 * Floating point.
11875
11876 * Description:
11877 * This attribute gives the highest axis value to be displayed (for
11878 c instance, by the astGrid method).
11879 f instance, by the AST_GRID method).
11880
11881 * Applicability:
11882 * Frame
11883 * The default supplied by the Frame class is to display all axis
11884 * values, without any limit.
11885 * SkyFrame
11886 * The SkyFrame class re-defines the default Top value to +90 degrees
11887 * for latitude axes, and 180 degrees for co-latitude axes. The
11888 * default for longitude axes is to display all axis values.
11889
11890 * Notes:
11891 * - When specifying this attribute by name, it should be
11892 * subscripted with the number of the Frame axis to which it
11893 * applies.
11894 *att--
11895 */
11896 /* This simply provides an interface to the Axis methods for accessing
11897 the Top value. */
11898 MAKE_CLEAR(Top)
11899 MAKE_GET(Top,double,DBL_MAX,0,DBL_MAX)
11900 MAKE_SET(Top,double)
11901 MAKE_TEST(Top)
11902
11903 /*
11904 *att++
11905 * Name:
11906 * Bottom(axis)
11907
11908 * Purpose:
11909 * Lowest axis value to display
11910
11911 * Type:
11912 * Public attribute.
11913
11914 * Synopsis:
11915 * Floating point.
11916
11917 * Description:
11918 * This attribute gives the lowest axis value to be displayed (for
11919 c instance, by the astGrid method).
11920 f instance, by the AST_GRID method).
11921
11922 * Applicability:
11923 * Frame
11924 * The default supplied by the Frame class is to display all axis
11925 * values, without any limit.
11926 * SkyFrame
11927 * The SkyFrame class re-defines the default Bottom value to -90 degrees
11928 * for latitude axes, and 0 degrees for co-latitude axes. The
11929 * default for longitude axes is to display all axis values.
11930
11931 * Notes:
11932 * - When specifying this attribute by name, it should be
11933 * subscripted with the number of the Frame axis to which it
11934 * applies.
11935 *att--
11936 */
11937 /* This simply provides an interface to the Axis methods for accessing
11938 the Bottom value. */
11939 MAKE_CLEAR(Bottom)
11940 MAKE_GET(Bottom,double,-DBL_MAX,0,-DBL_MAX)
11941 MAKE_SET(Bottom,double)
11942 MAKE_TEST(Bottom)
11943
11944 /*
11945 *att++
11946 * Name:
11947 * Format(axis)
11948
11949 * Purpose:
11950 * Format specification for axis values.
11951
11952 * Type:
11953 * Public attribute.
11954
11955 * Synopsis:
11956 * String.
11957
11958 * Description:
11959 * This attribute specifies the format to be used when displaying
11960 * coordinate values associated with a particular Frame axis
11961 * (i.e. to convert values from binary to character form). It is
11962 c interpreted by the astFormat function and determines the
11963 f interpreted by the AST_FORMAT function and determines the
11964 * formatting which it applies.
11965 *
11966 * If no Format value is set for a Frame axis, a default value is
11967 * supplied instead. This is based on the value of the Digits, or
11968 * Digits(axis), attribute and is chosen so that it displays the
11969 * requested number of digits of precision.
11970
11971 * Applicability:
11972 * Frame
11973 * The Frame class interprets this attribute as a format
11974 * specification string to be passed to the C "printf" function
11975 * (e.g. "%1.7G") in order to format a single coordinate value
11976 * (supplied as a double precision number).
11977 c
11978 c When supplying a value for this attribute, beware that the
11979 c "%" character may be interpreted directly as a format
11980 c specification by some printf-like functions (such as
11981 c astSet). You may need to double it (i.e. use "%%") to avoid
11982 c this.
11983 * SkyFrame
11984 * The SkyFrame class re-defines the syntax and default value of
11985 * the Format string to allow the formatting of sexagesimal
11986 * values as appropriate for the particular celestial coordinate
11987 * system being represented. The syntax of SkyFrame Format
11988 * strings is described (below) in the "SkyFrame Formats"
11989 * section.
11990 * FrameSet
11991 * The Format attribute of a FrameSet axis is the same as that
11992 * of its current Frame (as specified by the Current
11993 * attribute). Note that the syntax of the Format string is also
11994 * determined by the current Frame.
11995 * TimeFrame
11996 * The TimeFrame class extends the syntax of the Format string to
11997 * allow the formatting of TimeFrame axis values as Gregorian calendar
11998 * dates and times. The syntax of TimeFrame Format strings is described
11999 * (below) in the "TimeFrame Formats" section.
12000
12001 * SkyFrame Formats:
12002 * The Format string supplied for a SkyFrame should contain zero or
12003 * more of the following characters. These may occur in any order,
12004 * but the following is recommended for clarity:
12005 *
12006 * - "+": Indicates that a plus sign should be prefixed to positive
12007 * values. By default, no plus sign is used.
12008 *
12009 * - "z": Indicates that leading zeros should be prefixed to the
12010 * value so that the first field is of constant width, as would be
12011 * required in a fixed-width table (leading zeros are always
12012 * prefixed to any fields that follow). By default, no leading
12013 * zeros are added.
12014 *
12015 * - "i": Use the standard ISO field separator (a colon) between
12016 * fields. This is the default behaviour.
12017 *
12018 * - "b": Use a blank to separate fields.
12019 *
12020 * - "l": Use a letter ("h"/"d", "m" or "s" as appropriate) to
12021 * separate fields.
12022 *
12023 * - "g": Use a letter and symbols to separate fields ("h"/"d", "m" or "s",
12024 * etc, as appropriate), but include escape sequences in the formatted
12025 * value so that the Plot class will draw the separators as small
12026 * super-scripts.
12027 c The default escape sequences are optimised for the pgplot graphics
12028 c package, but new escape sequences may be specified using function
12029 c astSetSkyDelim.
12030 *
12031 * - "d": Include a degrees field. Expressing the angle purely in
12032 * degrees is also the default if none of "h", "m", "s" or "t" are
12033 * given.
12034 *
12035 * - "h": Express the angle as a time and include an hours field
12036 * (where 24 hours correspond to 360 degrees). Expressing the angle
12037 * purely in hours is also the default if "t" is given without
12038 * either "m" or "s".
12039 *
12040 * - "m": Include a minutes field. By default this is not included.
12041 *
12042 * - "s": Include a seconds field. By default this is not included.
12043 * This request is ignored if "d" or "h" is given, unless a minutes
12044 * field is also included.
12045 *
12046 * - "t": Express the angle as a time (where 24 hours correspond to
12047 * 360 degrees). This option is ignored if either "d" or "h" is
12048 * given and is intended for use where the value is to be expressed
12049 * purely in minutes and/or seconds of time (with no hours
12050 * field). If "t" is given without "d", "h", "m" or "s" being
12051 * present, then it is equivalent to "h".
12052 *
12053 * - ".": Indicates that decimal places are to be given for the
12054 * final field in the formatted string (whichever field this
12055 * is). The "." should be followed immediately by an unsigned
12056 * integer which gives the number of decimal places required, or by an
12057 * asterisk. If an asterisk is supplied, a default number of decimal
12058 * places is used which is based on the value of the Digits
12059 * attribute.
12060 *
12061 * All of the above format specifiers are case-insensitive. If
12062 * several characters make conflicting requests (e.g. if both "i"
12063 * and "b" appear), then the character occurring last takes
12064 * precedence, except that "d" and "h" always override "t".
12065 *
12066 * If the format string starts with a percentage sign (%), then the
12067 * whole format string is assumed to conform to the syntax defined by
12068 * the Frame class, and the axis values is formated as a decimal
12069 * radians value.
12070
12071 * TimeFrame Formats:
12072 * The Format string supplied for a TimeFrame should either use the
12073 * syntax defined by the base Frame class (i.e. a C "printf" format
12074 * string), or the extended "iso" syntax described below (the default
12075 * value is inherited from the Frame class):
12076 *
12077 * - C "printf" syntax: If the Format string is a C "printf" format
12078 * description such as "%1.7G", the TimeFrame axis value will be
12079 * formatted without change as a floating point value using this format.
12080 * The formatted string will thus represent an offset from the zero point
12081 * specified by the TimeFrame's TimeOrigin attribute, measured in
12082 * units given by the TimeFrame's Unit attribute.
12083 *
12084 * - "iso" syntax: This is used to format a TimeFrame axis value as a
12085 * Gregorian date followed by an optional time of day. If the Format
12086 * value commences with the string "iso" then the TimeFrame axis value
12087 * will be converted to an absolute MJD, including the addition of the
12088 * current TimeOrigin value, and then formatted as a Gregorian date
12089 * using the format "yyyy-mm-dd". Optionally, the Format value may
12090 * include an integer precision following the "iso" specification (e.g.
12091 * "iso.2"), in which case the time of day will be appended to the
12092 * formatted date (if no time of day is included, the date field is
12093 * rounded to the nearest day). The integer value in the Format string
12094 * indicates the number of decimal places to use in the seconds field. For
12095 * instance, a Format value of "iso.0" produces a time of day of the form
12096 * "hh:mm:ss", and a Format value of "iso.2" produces a time of day of the
12097 * form "hh:mm:ss.ss". The date and time fields will be separated by a
12098 * space unless 'T' is appended to the end of string, in which case
12099 * the letter T (upper case) will be used as the separator. The value of
12100 * the Digits attribute is ignored when using this "iso" format.
12101
12102 * Notes:
12103 * - When specifying this attribute by name, it should be
12104 * subscripted with the number of the Frame axis to which it
12105 * applies.
12106 *att--
12107 */
12108 /* This simply provides an interface to the Axis methods for accessing
12109 the Format string. */
12110 MAKE_CLEAR(Format)
12111 MAKE_GET(Format,const char *,NULL,0,0)
12112 MAKE_SET(Format,const char *)
12113 MAKE_TEST(Format)
12114
12115 /*
12116 *att++
12117 * Name:
12118 * Label(axis)
12119
12120 * Purpose:
12121 * Axis label.
12122
12123 * Type:
12124 * Public attribute.
12125
12126 * Synopsis:
12127 * String.
12128
12129 * Description:
12130 * This attribute specifies a label to be attached to each axis of
12131 * a Frame when it is represented (e.g.) in graphical output.
12132 *
12133 * If a Label value has not been set for a Frame axis, then a
12134 * suitable default is supplied.
12135
12136 * Applicability:
12137 * Frame
12138 * The default supplied by the Frame class is the string "Axis
12139 * <n>", where <n> is 1, 2, etc. for each successive axis.
12140 * SkyFrame
12141 * The SkyFrame class re-defines the default Label value
12142 * (e.g. to "Right ascension" or "Galactic latitude") as
12143 * appropriate for the particular celestial coordinate system
12144 * being represented.
12145 * TimeFrame
12146 * The TimeFrame class re-defines the default Label value as
12147 * appropriate for the particular time system being represented.
12148 * FrameSet
12149 * The Label attribute of a FrameSet axis is the same as that of
12150 * its current Frame (as specified by the Current attribute).
12151
12152 * Notes:
12153 * - Axis labels are intended purely for interpretation by human
12154 * readers and not by software.
12155 * - When specifying this attribute by name, it should be
12156 * subscripted with the number of the Frame axis to which it
12157 * applies.
12158 *att--
12159 */
12160 /* This provides an interface to the Axis methods for accessing the
12161 Label string, but provides an alternative default Label based on
12162 the axis number. This default string is written to the static
12163 "label_buff" buffer and a pointer to this is returned if
12164 required. */
12165 MAKE_CLEAR(Label)
12166 MAKE_GET(Label,const char *,NULL,1,GetDefaultLabel( axis, status ))
12167 MAKE_SET(Label,const char *)
12168 MAKE_TEST(Label)
12169
12170 /*
12171 *att++
12172 * Name:
12173 * Symbol(axis)
12174
12175 * Purpose:
12176 * Axis symbol.
12177
12178 * Type:
12179 * Public attribute.
12180
12181 * Synopsis:
12182 * String.
12183
12184 * Description:
12185 * This attribute specifies a short-form symbol to be used to
12186 * represent coordinate values for a particular axis of a
12187 * Frame. This might be used (e.g.) in algebraic expressions where
12188 * a full description of the axis would be inappropriate. Examples
12189 * include "RA" and "Dec" (for Right Ascension and Declination).
12190 *
12191 * If a Symbol value has not been set for a Frame axis, then a
12192 * suitable default is supplied.
12193
12194 * Applicability:
12195 * Frame
12196 * The default Symbol value supplied by the Frame class is the
12197 * string "<Domain><n>", where <n> is 1, 2, etc. for successive
12198 * axes, and <Domain> is the value of the Frame's Domain
12199 * attribute (truncated if necessary so that the final string
12200 * does not exceed 15 characters). If no Domain value has been
12201 * set, "x" is used as the <Domain> value in constructing this
12202 * default string.
12203 * SkyFrame
12204 * The SkyFrame class re-defines the default Symbol value
12205 * (e.g. to "RA" or "Dec") as appropriate for the particular
12206 * celestial coordinate system being represented.
12207 * TimeFrame
12208 * The TimeFrame class re-defines the default Symbol value as
12209 * appropriate for the particular time system being represented.
12210 * FrameSet
12211 * The Symbol attribute of a FrameSet axis is the same as that
12212 * of its current Frame (as specified by the Current attribute).
12213
12214 * Notes:
12215 * - When specifying this attribute by name, it should be
12216 * subscripted with the number of the Frame axis to which it
12217 * applies.
12218 *att--
12219 */
12220 /* This provides an interface to the Axis methods for accessing the
12221 Symbol string, but provides an alternative default Symbol based on
12222 the axis number and the Frame's Domain (if defined, otherwise "x"
12223 is used). This default string is written to the static
12224 "symbol_buff" buffer and a pointer to this is returned if
12225 required. */
12226 MAKE_CLEAR(Symbol)
12227 MAKE_GET(Symbol,const char *,NULL,1,GetDefaultSymbol( this, axis, status ) )
12228 MAKE_SET(Symbol,const char *)
12229 MAKE_TEST(Symbol)
12230
12231 /*
12232 *att++
12233 * Name:
12234 * Unit(axis)
12235
12236 * Purpose:
12237 * Axis physical units.
12238
12239 * Type:
12240 * Public attribute.
12241
12242 * Synopsis:
12243 * String.
12244
12245 * Description:
12246 * This attribute contains a textual representation of the physical
12247 * units used to represent coordinate values on a particular axis
12248 c of a Frame. The astSetActiveUnit function controls how the Unit values
12249 f of a Frame. The AST_SETACTIVEUNIT routine controls how the Unit values
12250 * are used.
12251
12252 * Applicability:
12253 * Frame
12254 * The default supplied by the Frame class is an empty string.
12255 * SkyFrame
12256 * The SkyFrame class re-defines the default Unit value (e.g. to
12257 * "hh:mm:ss.sss") to describe the character string returned by
12258 c the astFormat function when formatting coordinate values.
12259 f the AST_FORMAT function when formatting coordinate values.
12260 * SpecFrame
12261 * The SpecFrame class re-defines the default Unit value so that it
12262 * is appropriate for the current System value. See the System
12263 * attribute for details. An error will be reported if an attempt
12264 * is made to use an inappropriate Unit.
12265 * TimeFrame
12266 * The TimeFrame class re-defines the default Unit value so that it
12267 * is appropriate for the current System value. See the System
12268 * attribute for details. An error will be reported if an attempt
12269 * is made to use an inappropriate Unit (e.g. "km").
12270 * FrameSet
12271 * The Unit attribute of a FrameSet axis is the same as that of
12272 * its current Frame (as specified by the Current attribute).
12273
12274 * Notes:
12275 * - When specifying this attribute by name, it should be
12276 * subscripted with the number of the Frame axis to which it
12277 * applies.
12278 *att--
12279 */
12280 /* This simply provides an interface to the Axis methods for accessing
12281 the Unit string. */
12282 MAKE_GET(Unit,const char *,NULL,0,0)
12283 MAKE_TEST(Unit)
12284
12285 /*
12286 *att++
12287 * Name:
12288 * NormUnit(axis)
12289
12290 * Purpose:
12291 * Normalised Axis physical units.
12292
12293 * Type:
12294 * Public attribute.
12295
12296 * Synopsis:
12297 * String, read-only.
12298
12299 * Description:
12300 * The value of this read-only attribute is derived from the current
12301 * value of the Unit attribute. It will represent an equivalent system
12302 * of units to the Unit attribute, but will potentially be simplified.
12303 * For instance, if Unit is set to "s*(m/s)", the NormUnit value will
12304 * be "m". If no simplification can be performed, the value of the
12305 * NormUnit attribute will equal that of the Unit attribute.
12306
12307 * Applicability:
12308 * Frame
12309 * All Frames have this attribute.
12310
12311 * Notes:
12312 * - When specifying this attribute by name, it should be
12313 * subscripted with the number of the Frame axis to which it
12314 * applies.
12315 *att--
12316 */
12317 /* This simply provides an interface to the Axis methods for accessing
12318 the Unit string. */
12319 MAKE_GET(NormUnit,const char *,NULL,0,0)
12320
12321 /* Implement member functions to access the attributes associated with
12322 the Frame as a whole using the macros defined for this purpose in
12323 the "object.h" file. */
12324
12325 /*
12326 *att++
12327 * Name:
12328 * Digits/Digits(axis)
12329
12330 * Purpose:
12331 * Number of digits of precision.
12332
12333 * Type:
12334 * Public attribute.
12335
12336 * Synopsis:
12337 * Integer.
12338
12339 * Description:
12340 * This attribute specifies how many digits of precision are
12341 * required by default when a coordinate value is formatted for a
12342 c Frame axis (e.g. using astFormat). Its value may be set either
12343 f Frame axis (e.g. using AST_FORMAT). Its value may be set either
12344 * for a Frame as a whole, or (by subscripting the attribute name
12345 * with the number of an axis) for each axis individually. Any
12346 * value set for an individual axis will over-ride the value for
12347 * the Frame as a whole.
12348 *
12349 * Note that the Digits value acts only as a means of determining a
12350 * default Format string. Its effects are over-ridden if a Format
12351 * string is set explicitly for an axis. However, if the Format
12352 * attribute specifies the precision using the string ".*", then
12353 * the Digits attribute is used to determine the number of decimal
12354 * places to produce.
12355
12356 * Applicability:
12357 * Frame
12358 * The default Digits value supplied by the Frame class is 7. If
12359 * a value less than 1 is supplied, then 1 is used instead.
12360 * FrameSet
12361 * The Digits attribute of a FrameSet (or one of its axes) is
12362 * the same as that of its current Frame (as specified by the
12363 * Current attribute).
12364 * Plot
12365 * The default Digits value used by the Plot class when drawing
12366 * annotated axis labels is the smallest value which results in all
12367 * adjacent labels being distinct.
12368 * TimeFrame
12369 * The Digits attribute is ignored when a TimeFrame formats a value
12370 * as a date and time string (see the Format attribute).
12371 *att--
12372 */
12373 /* Clear the Digits value by setting it to -INT_MAX. */
12374 astMAKE_CLEAR(Frame,Digits,digits,-INT_MAX)
12375
12376 /* Supply a default of 7 digits if no value has been set. */
12377 astMAKE_GET(Frame,Digits,int,0,( ( this->digits != -INT_MAX ) ? this->digits :
12378 7 ))
12379
12380 /* Constrain the Digits value being set to be at least 1. */
12381 astMAKE_SET(Frame,Digits,int,digits,( value > 1 ? value : 1 ))
12382
12383 /* The Digits value is set if it is not -INT_MAX. */
12384 astMAKE_TEST(Frame,Digits,( this->digits != -INT_MAX ))
12385
12386 /*
12387 *att++
12388 * Name:
12389 * MatchEnd
12390
12391 * Purpose:
12392 * Match trailing axes?
12393
12394 * Type:
12395 * Public attribute.
12396
12397 * Synopsis:
12398 * Integer (boolean).
12399
12400 * Description:
12401 * This attribute is a boolean value which controls how a Frame
12402 c behaves when it is used (by astFindFrame) as a template to match
12403 f behaves when it is used (by AST_FINDFRAME) as a template to match
12404 * another (target) Frame. It applies only in the case where a
12405 * match occurs between template and target Frames with different
12406 * numbers of axes.
12407 *
12408 * If the MatchEnd value of the template Frame is zero, then the
12409 * axes which occur first in the target Frame will be matched and
12410 * any trailing axes (in either the target or template) will be
12411 * disregarded. If it is non-zero, the final axes in each Frame
12412 * will be matched and any un-matched leading axes will be
12413 * disregarded instead.
12414
12415 * Applicability:
12416 * Frame
12417 * The default MatchEnd value for a Frame is zero, so that
12418 * trailing axes are disregarded.
12419 * FrameSet
12420 * The MatchEnd attribute of a FrameSet is the same as that of
12421 * its current Frame (as specified by the Current attribute).
12422 *att--
12423 */
12424 /* Clear the MatchEnd value by setting it to -INT_MAX. */
12425 astMAKE_CLEAR(Frame,MatchEnd,match_end,-INT_MAX)
12426
12427 /* Supply a default of 0 if no MatchEnd value has been set. */
12428 astMAKE_GET(Frame,MatchEnd,int,0,( ( this->match_end != -INT_MAX ) ?
12429 this->match_end : 0 ))
12430
12431 /* Set a MatchEnd value of 1 if any non-zero value is supplied. */
12432 astMAKE_SET(Frame,MatchEnd,int,match_end,( value != 0 ))
12433
12434 /* The MatchEnd value is set if it is not -INT_MAX. */
12435 astMAKE_TEST(Frame,MatchEnd,( this->match_end != -INT_MAX ))
12436
12437 /*
12438 *att++
12439 * Name:
12440 * MaxAxes
12441
12442 * Purpose:
12443 * Maximum number of Frame axes to match.
12444
12445 * Type:
12446 * Public attribute.
12447
12448 * Synopsis:
12449 * Integer.
12450
12451 * Description:
12452 * This attribute controls how a Frame behaves when it is used (by
12453 c astFindFrame) as a template to match another (target) Frame. It
12454 f AST_FINDFRAME) as a template to match another (target) Frame. It
12455 * specifies the maximum number of axes that the target Frame may
12456 * have in order to match the template.
12457 *
12458 * Normally, this value will equal the number of Frame axes, so
12459 * that a template Frame will only match another Frame with the
12460 * same number of axes as itself. By setting a different value,
12461 * however, the matching process may be used to identify Frames
12462 * with specified numbers of axes.
12463
12464 * Applicability:
12465 * Frame
12466 * The default MaxAxes value for a Frame is equal to the number
12467 * of Frame axes (Naxes attribute).
12468 * CmpFrame
12469 * The MaxAxes attribute of a CmpFrame defaults to a large number
12470 * (1000000) which is much larger than any likely number of axes in
12471 * a Frame. Combined with the MinAxes default of zero (for a
12472 * CmpFrame), this means that the default behaviour for a CmpFrame
12473 * is to match any target Frame that consists of a subset of the
12474 * axes in the template CmpFrame. To change this so that a CmpFrame
12475 * will only match Frames that have the same number of axes, you
12476 * should set the CmpFrame MaxAxes and MinAxes attributes to the
12477 * number of axes in the CmpFrame.
12478 * FrameSet
12479 * The MaxAxes attribute of a FrameSet is the same as that of
12480 * its current Frame (as specified by the Current attribute).
12481
12482 * Notes:
12483 * - When setting a MaxAxes value, the value of the MinAxes
12484 * attribute may also be silently changed so that it remains
12485 * consistent with (i.e. does not exceed) the new value. The
12486 * default MaxAxes value may also be reduced to remain consistent
12487 * with the MinAxes value.
12488 * - If a template Frame is used to match a target with a different
12489 * number of axes, the MatchEnd attribute of the template is used
12490 * to determine how the individual axes of each Frame should match.
12491 *att--
12492 */
12493 /* Clear the MaxAxes value by setting it to -INT_MAX. */
12494 astMAKE_CLEAR(Frame,MaxAxes,max_axes,-INT_MAX)
12495
12496 /* Use the DefaultMaxAxes and ConsistentMaxAxes functions (defined earlier) for
12497 the Get and Set operations to ensure that MinAxes and MaxAxes values remain
12498 consistent. */
12499 astMAKE_GET(Frame,MaxAxes,int,0,DefaultMaxAxes( this, status ))
12500 astMAKE_SET(Frame,MaxAxes,int,max_axes,ConsistentMaxAxes( this, value, status ))
12501
12502 /* The MaxAxes value is set if it is not -INT_MAX. */
12503 astMAKE_TEST(Frame,MaxAxes,( this->max_axes != -INT_MAX ))
12504
12505 /*
12506 *att++
12507 * Name:
12508 * MinAxes
12509
12510 * Purpose:
12511 * Minimum number of Frame axes to match.
12512
12513 * Type:
12514 * Public attribute.
12515
12516 * Synopsis:
12517 * Integer.
12518
12519 * Description:
12520 * This attribute controls how a Frame behaves when it is used (by
12521 c astFindFrame) as a template to match another (target) Frame. It
12522 f AST_FINDFRAME) as a template to match another (target) Frame. It
12523 * specifies the minimum number of axes that the target Frame may
12524 * have in order to match the template.
12525 *
12526 * Normally, this value will equal the number of Frame axes, so
12527 * that a template Frame will only match another Frame with the
12528 * same number of axes as itself. By setting a different value,
12529 * however, the matching process may be used to identify Frames
12530 * with specified numbers of axes.
12531
12532 * Applicability:
12533 * Frame
12534 * The default MinAxes value for a Frame is equal to the number
12535 * of Frame axes (Naxes attribute).
12536 * CmpFrame
12537 * The MinAxes attribute of a CmpFrame defaults to zero. Combined
12538 * with the MaxAxes default of 1000000 (for a CmpFrame), this means
12539 * that the default behaviour for a CmpFrame is to match any target
12540 * Frame that consists of a subset of the axes in the template
12541 * CmpFrame. To change this so that a CmpFrame will only match Frames
12542 * that have the same number of axes, you should set the CmpFrame
12543 * MinAxes and MaxAxes attributes to the number of axes in the CmpFrame.
12544 * FrameSet
12545 * The MinAxes attribute of a FrameSet is the same as that of
12546 * its current Frame (as specified by the Current attribute).
12547
12548 * Notes:
12549 * - When setting a MinAxes value, the value of the MaxAxes
12550 * attribute may also be silently changed so that it remains
12551 * consistent with (i.e. is not less than) the new value. The
12552 * default MinAxes value may also be reduced to remain consistent
12553 * with the MaxAxes value.
12554 * - If a template Frame is used to match a target with a different
12555 * number of axes, the MatchEnd attribute of the template is used
12556 * to determine how the individual axes of each Frame should match.
12557 *att--
12558 */
12559 /* Clear the MinAxes value by setting it to -INT_MAX. */
12560 astMAKE_CLEAR(Frame,MinAxes,min_axes,-INT_MAX)
12561
12562 /* Use the DefaultMinAxes and ConsistentMinAxes functions (defined earlier) for
12563 the Get and Set operations to ensure that MinAxes and MaxAxes values remain
12564 consistent. */
12565 astMAKE_GET(Frame,MinAxes,int,0,DefaultMinAxes( this, status ))
12566 astMAKE_SET(Frame,MinAxes,int,min_axes,ConsistentMinAxes( this, value, status ))
12567
12568 /* The MinAxes value is set if it is not -INT_MAX. */
12569 astMAKE_TEST(Frame,MinAxes,( this->min_axes != -INT_MAX ))
12570
12571 /*
12572 *att++
12573 * Name:
12574 * Domain
12575
12576 * Purpose:
12577 * Coordinate system domain.
12578
12579 * Type:
12580 * Public attribute.
12581
12582 * Synopsis:
12583 * String.
12584
12585 * Description:
12586 * This attribute contains a string which identifies the physical
12587 * domain of the coordinate system that a Frame describes.
12588 *
12589 * The Domain attribute also controls how a Frame behaves when it is
12590 c used (by astFindFrame) as a template to match another (target)
12591 f used (by AST_FINDFRAME) as a template to match another (target)
12592 * Frame. It does this by specifying the Domain that the target
12593 * Frame should have in order to match the template. If the Domain
12594 * value in the template Frame is set, then only targets with the
12595 * same Domain value will be matched. If the template's Domain
12596 * value is not set, however, then the target's Domain will be
12597 * ignored.
12598
12599 * Applicability:
12600 * Frame
12601 * The default Domain value supplied by the Frame class is an
12602 * empty string.
12603 * SkyFrame
12604 * The SkyFrame class re-defines the default Domain value to be
12605 * "SKY".
12606 * CmpFrame
12607 * The CmpFrame class re-defines the default Domain value to be
12608 * of the form "<dom1>-<dom2>", where <dom1> and <dom2> are the
12609 * Domains of the two component Frames. If both these Domains are
12610 * blank, then the string "CMP" is used as the default Domain name.
12611 * FrameSet
12612 * The Domain attribute of a FrameSet is the same as that of its
12613 * current Frame (as specified by the Current attribute).
12614 * SpecFrame
12615 * The SpecFrame class re-defines the default Domain value to be
12616 * "SPECTRUM".
12617 * DSBSpecFrame
12618 * The DSBSpecFrame class re-defines the default Domain value to be
12619 * "DSBSPECTRUM".
12620 * FluxFrame
12621 * The FluxFrame class re-defines the default Domain value to be
12622 * "FLUX".
12623 * SpecFluxFrame
12624 * The FluxFrame class re-defines the default Domain value to be
12625 * "SPECTRUM-FLUX".
12626 * TimeFrame
12627 * The TimeFrame class re-defines the default Domain value to be
12628 * "TIME".
12629
12630 * Notes:
12631 * - All Domain values are converted to upper case and white space
12632 * is removed before use.
12633 *att--
12634 */
12635 /* Clear the Domain value by freeing the allocated memory and
12636 assigning a NULL pointer. */
12637 astMAKE_CLEAR(Frame,Domain,domain,astFree( this->domain ))
12638
12639 /* If the Domain value is not set, supply a default in the form of a
12640 pointer to the constant string "". */
12641 astMAKE_GET(Frame,Domain,const char *,NULL,( this->domain ? this->domain :
12642 "" ))
12643
12644 /* Set a Domain value by freeing any previously allocated memory,
12645 allocating new memory, storing the string, removing white space,
12646 converting to upper case and saving the pointer to the cleaned
12647 copy. */
12648 astMAKE_SET(Frame,Domain,const char *,domain,CleanDomain(
12649 astStore( this->domain,
12650 value, strlen( value ) + (size_t) 1 ), status ))
12651
12652 /* The Domain value is set if the pointer to it is not NULL. */
12653 astMAKE_TEST(Frame,Domain,( this->domain != NULL ))
12654
12655 /*
12656 *att++
12657 * Name:
12658 * Permute
12659
12660 * Purpose:
12661 * Permute axis order?
12662
12663 * Type:
12664 * Public attribute.
12665
12666 * Synopsis:
12667 * String.
12668
12669 * Description:
12670 * This attribute is a boolean value which controls how a Frame
12671 c behaves when it is used (by astFindFrame) as a template to match
12672 f behaves when it is used (by AST_FINDFRAME) as a template to match
12673 * another (target) Frame. It specifies whether the axis order of
12674 * the target Frame may be permuted in order to obtain a match.
12675 *
12676 * If the template's Permute value is zero, it will match a target
12677 * only if it can do so without changing the order of its
12678 * axes. Otherwise, it will attempt to permute the target's axes as
12679 * necessary.
12680 *
12681 * The default value is 1, so that axis permutation will be attempted.
12682
12683 * Applicability:
12684 * Frame
12685 * All Frames have this attribute. However, the Frame class
12686 * effectively ignores this attribute and behaves as if it has
12687 * the value 1. This is because the axes of a basic Frame are
12688 * not distinguishable and will always match any other Frame
12689 * whatever their order.
12690 * SkyFrame
12691 * Unlike a basic Frame, the SkyFrame class makes use of this
12692 * attribute.
12693 * FrameSet
12694 * The Permute attribute of a FrameSet is the same as that of
12695 * its current Frame (as specified by the Current attribute).
12696 *att--
12697 */
12698 /* Clear the Permute value by setting it to -INT_MAX. */
12699 astMAKE_CLEAR(Frame,Permute,permute,-INT_MAX)
12700
12701 /* Supply a default of 1 if no Permute value has been set. */
12702 astMAKE_GET(Frame,Permute,int,0,( ( this->permute != -INT_MAX ) ?
12703 this->permute : 1 ))
12704
12705 /* Set a Permute value of 1 if any non-zero value is supplied. */
12706 astMAKE_SET(Frame,Permute,int,permute,( value != 0 ))
12707
12708 /* The Permute value is set if it is not -INT_MAX. */
12709 astMAKE_TEST(Frame,Permute,( this->permute != -INT_MAX ))
12710
12711 /*
12712 *att++
12713 * Name:
12714 * PreserveAxes
12715
12716 * Purpose:
12717 * Preserve axes?
12718
12719 * Type:
12720 * Public attribute.
12721
12722 * Synopsis:
12723 * Integer (boolean).
12724
12725 * Description:
12726 * This attribute controls how a Frame behaves when it is used (by
12727 c astFindFrame) as a template to match another (target) Frame. It
12728 f AST_FINDFRAME) as a template to match another (target) Frame. It
12729 * determines which axes appear (and in what order) in the "result"
12730 * Frame produced.
12731 *
12732 * If PreserveAxes is zero in the template Frame, then the result
12733 * Frame will have the same number (and order) of axes as the
12734 * template. If it is non-zero, however, the axes of the target
12735 * Frame will be preserved, so that the result Frame will have the
12736 * same number (and order) of axes as the target.
12737 *
12738 * The default value is zero, so that target axes are not preserved
12739 * and the result Frame resembles the template.
12740
12741 * Applicability:
12742 * Frame
12743 * All Frames have this attribute.
12744 * FrameSet
12745 * The PreserveAxes attribute of a FrameSet is the same as that
12746 * of its current Frame (as specified by the Current attribute).
12747 *att--
12748 */
12749 /* Clear the PreserveAxes value by setting it to -INT_MAX. */
12750 astMAKE_CLEAR(Frame,PreserveAxes,preserve_axes,-INT_MAX)
12751
12752 /* Supply a default of 0 if no PreserveAxes value has been set. */
12753 astMAKE_GET(Frame,PreserveAxes,int,0,( ( this->preserve_axes != -INT_MAX ) ?
12754 this->preserve_axes : 0 ))
12755
12756 /* Set a PreserveAxes value of 1 if any non-zero value is supplied. */
12757 astMAKE_SET(Frame,PreserveAxes,int,preserve_axes,( value != 0 ))
12758
12759 /* The PreserveAxes value is set if it is not -INT_MAX. */
12760 astMAKE_TEST(Frame,PreserveAxes,( this->preserve_axes != -INT_MAX ))
12761
12762 /*
12763 *att++
12764 * Name:
12765 * AlignSystem
12766
12767 * Purpose:
12768 * Coordinate system in which to align the Frame.
12769
12770 * Type:
12771 * Public attribute.
12772
12773 * Synopsis:
12774 * String.
12775
12776 * Description:
12777 * This attribute controls how a Frame behaves when it is used (by
12778 c astFindFrame or astConvert) as a template to match another (target)
12779 f AST_FINDFRAME or AST_CONVERT) as a template to match another (target)
12780 * Frame. It identifies the coordinate system in which the two Frames
12781 * will be aligned by the match.
12782 *
12783 * The values which may be assigned to this attribute, and its default
12784 * value, depend on the class of Frame and are described in the
12785 * "Applicability" section below. In general, the AlignSystem attribute
12786 * will accept any of the values which may be assigned to the System
12787 * attribute.
12788 *
12789 c The Mapping returned by AST_FINDFRAME or AST_CONVERT will use the
12790 f The Mapping returned by astFindFrame or astConvert will use the
12791 * coordinate system specified by the AlignSystem attribute as an
12792 * intermediate coordinate system. The total returned Mapping will first
12793 * map positions from the first Frame into this intermediate coordinate
12794 * system, using the attributes of the first Frame. It will then map
12795 * these positions from the intermediate coordinate system into the
12796 * second Frame, using the attributes of the second Frame.
12797
12798 * Applicability:
12799 * Frame
12800 * The AlignSystem attribute for a basic Frame always equals "Cartesian",
12801 * and may not be altered.
12802 * CmpFrame
12803 * The AlignSystem attribute for a CmpFrame always equals "Compound",
12804 * and may not be altered.
12805 * FrameSet
12806 * The AlignSystem attribute of a FrameSet is the same as that of its
12807 * current Frame (as specified by the Current attribute).
12808 * SkyFrame
12809 * The default AlignSystem attribute for a SkyFrame is "ICRS".
12810 * SpecFrame
12811 * The default AlignSystem attribute for a SpecFrame is "Wave"
12812 * (wavelength).
12813 * TimeFrame
12814 * The default AlignSystem attribute for a TimeFrame is "MJD".
12815 *att--
12816 */
12817 /* Clear the AlignSystem value by setting it to AST__BADSYSTEM. */
12818 astMAKE_CLEAR(Frame,AlignSystem,alignsystem,AST__BADSYSTEM)
12819
12820 /* Provide a default AlignSystem of AST__CART. */
12821 astMAKE_GET(Frame,AlignSystem,AstSystemType,AST__BADSYSTEM,(
12822 ( this->alignsystem == AST__BADSYSTEM ) ? AST__CART : this->alignsystem ) )
12823
12824 /* Validate the AlignSystem value being set and retain the original if the
12825 supplied value is not recognized. */
12826 astMAKE_SET(Frame,AlignSystem,AstSystemType,alignsystem,(
12827 (astValidateSystem( this, value, "astSetAlignSystem" ) != AST__BADSYSTEM) ?
12828 value : this->alignsystem ))
12829
12830 /* The AlignSystem value is set if it is not AST__BADSYSTEM. */
12831 astMAKE_TEST(Frame,AlignSystem,( this->alignsystem != AST__BADSYSTEM ))
12832
12833 /*
12834 *att++
12835 * Name:
12836 * System
12837
12838 * Purpose:
12839 * Coordinate system used to describe positions within the domain
12840
12841 * Type:
12842 * Public attribute.
12843
12844 * Synopsis:
12845 * String.
12846
12847 * Description:
12848 * In general it is possible for positions within a given physical
12849 * domain to be described using one of several different coordinate
12850 * systems. For instance, the SkyFrame class can use galactic
12851 * coordinates, equatorial coordinates, etc, to describe positions on
12852 * the sky. As another example, the SpecFrame class can use frequency,
12853 * wavelength, velocity, etc, to describe a position within an
12854 * electromagnetic spectrum. The System attribute identifies the particular
12855 * coordinate system represented by a Frame. Each class of Frame
12856 * defines a set of acceptable values for this attribute, as listed
12857 * below (all are case insensitive). Where more than one alternative
12858 * System value is shown, the first of will be returned when an
12859 * enquiry is made.
12860
12861 * Applicability:
12862 * Frame
12863 * The System attribute for a basic Frame always equals "Cartesian",
12864 * and may not be altered.
12865 * CmpFrame
12866 * The System attribute for a CmpFrame always equals "Compound",
12867 * and may not be altered. In addition, the CmpFrame class allows
12868 * the System attribute to be referenced for a component Frame by
12869 * including the index of an axis within the required component
12870 * Frame. For instance, "System(3)" refers to the System attribute
12871 * of the component Frame which includes axis 3 of the CmpFrame.
12872 * FrameSet
12873 * The System attribute of a FrameSet is the same as that of its
12874 * current Frame (as specified by the Current attribute).
12875 * SkyFrame
12876 * The SkyFrame class supports the following System values and
12877 * associated celestial coordinate systems:
12878 *
12879 * - "AZEL": Horizon coordinates. The longitude axis is azimuth
12880 * such that geographic north has an azimuth of zero and geographic
12881 * east has an azimuth of +PI/2 radians. The zenith has elevation
12882 * +PI/2. When converting to and from other celestial coordinate
12883 * systems, no corrections are applied for atmospheric refraction
12884 * or polar motion (however, a correction for diurnal aberattion is
12885 * applied). Note, unlike most other
12886 * celestial coordinate systems, this system is right handed. Also,
12887 * unlike other SkyFrame systems, the AzEl system is sensitive to
12888 * the timescale in which the Epoch value is supplied. This is
12889 * because of the gross diurnal rotation which this system undergoes,
12890 * causing a small change in time to translate to a large rotation.
12891 * When converting to or from an AzEl system, the Epoch value for
12892 * both source and destination SkyFrames should be supplied in the
12893 * TDB timescale. The difference between TDB and TT is between 1
12894 * and 2 milliseconds, and so a TT value can usually be supplied in
12895 * place of a TDB value. The TT timescale is related to TAI via
12896 * TT = TAI + 32.184 seconds.
12897 *
12898 * - "ECLIPTIC": Ecliptic coordinates (IAU 1980), referred to the
12899 * ecliptic and mean equinox specified by the qualifying Equinox
12900 * value.
12901 *
12902 * - "FK4": The old FK4 (barycentric) equatorial coordinate system,
12903 * which should be qualified by an Equinox value. The underlying
12904 * model on which this is based is non-inertial and rotates slowly
12905 * with time, so for accurate work FK4 coordinate systems should
12906 * also be qualified by an Epoch value.
12907 *
12908 * - "FK4-NO-E" or "FK4_NO_E": The old FK4 (barycentric) equatorial
12909 * system but without the "E-terms of aberration" (e.g. some radio
12910 * catalogues). This coordinate system should also be qualified by
12911 * both an Equinox and an Epoch value.
12912 *
12913 * - "FK5" or "EQUATORIAL": The modern FK5 (barycentric) equatorial
12914 * coordinate system. This should be qualified by an Equinox value.
12915 *
12916 * - "GALACTIC": Galactic coordinates (IAU 1958).
12917 *
12918 * - "GAPPT", "GEOCENTRIC" or "APPARENT": The geocentric apparent
12919 * equatorial coordinate system, which gives the apparent positions
12920 * of sources relative to the true plane of the Earth's equator and
12921 * the equinox (the coordinate origin) at a time specified by the
12922 * qualifying Epoch value. (Note that no Equinox is needed to
12923 * qualify this coordinate system because no model "mean equinox"
12924 * is involved.) These coordinates give the apparent right
12925 * ascension and declination of a source for a specified date of
12926 * observation, and therefore form an approximate basis for
12927 * pointing a telescope. Note, however, that they are applicable to
12928 * a fictitious observer at the Earth's centre, and therefore
12929 * ignore such effects as atmospheric refraction and the (normally
12930 * much smaller) aberration of light due to the rotational velocity
12931 * of the Earth's surface. Geocentric apparent coordinates are
12932 * derived from the standard FK5 (J2000.0) barycentric coordinates
12933 * by taking account of the gravitational deflection of light by
12934 * the Sun (usually small), the aberration of light caused by the
12935 * motion of the Earth's centre with respect to the barycentre
12936 * (larger), and the precession and nutation of the Earth's spin
12937 * axis (normally larger still).
12938 *
12939 * - "HELIOECLIPTIC": Ecliptic coordinates (IAU 1980), referred to the
12940 * ecliptic and mean equinox of J2000.0, in which an offset is added to
12941 * the longitude value which results in the centre of the sun being at
12942 * zero longitude at the date given by the Epoch attribute. Attempts to
12943 * set a value for the Equinox attribute will be ignored, since this
12944 * system is always referred to J2000.0.
12945 *
12946 * - "ICRS": The Internation Celestial Reference System, realised
12947 * through the Hipparcos catalogue. Whilst not an equatorial system
12948 * by definition, the ICRS is very close to the FK5 (J2000) system
12949 * and is usually treated as an equatorial system. The distinction
12950 * between ICRS and FK5 (J2000) only becomes important when accuracies
12951 * of 50 milli-arcseconds or better are required. ICRS need not be
12952 * qualified by an Equinox value.
12953 *
12954 * - "J2000": An equatorial coordinate system based on the mean
12955 * dynamical equator and equinox of the J2000 epoch. The dynamical
12956 * equator and equinox differ slightly from those used by the FK5
12957 * model, and so a "J2000" SkyFrame will differ slightly from an
12958 * "FK5(Equinox=J2000)" SkyFrame. The J2000 System need not be
12959 * qualified by an Equinox value
12960 *
12961 * - "SUPERGALACTIC": De Vaucouleurs Supergalactic coordinates.
12962 *
12963 * - "UNKNOWN": Any other general spherical coordinate system. No
12964 * Mapping can be created between a pair of SkyFrames if either of the
12965 * SkyFrames has System set to "Unknown".
12966 *
12967 * Currently, the default System value is "ICRS". However, this
12968 * default may change in future as new astrometric standards
12969 * evolve. The intention is to track the most modern appropriate
12970 * standard. For this reason, you should use the default only if
12971 * this is what you intend (and can tolerate any associated slight
12972 * change in future). If you intend to use the ICRS system
12973 * indefinitely, then you should specify it explicitly.
12974 * SpecFrame
12975 * The SpecFrame class supports the following System values and
12976 * associated spectral coordinate systems (the default is "WAVE" -
12977 * wavelength). They are all defined in FITS-WCS paper III:
12978 *
12979 * - "FREQ": Frequency (GHz)
12980 * - "ENER" or "ENERGY": Energy (J)
12981 * - "WAVN" or "WAVENUM": Wave-number (1/m)
12982 * - "WAVE" or "WAVELEN": Vacuum wave-length (Angstrom)
12983 * - "AWAV" or "AIRWAVE": Wave-length in air (Angstrom)
12984 * - "VRAD" or "VRADIO": Radio velocity (km/s)
12985 * - "VOPT" or "VOPTICAL": Optical velocity (km/s)
12986 * - "ZOPT" or "REDSHIFT": Redshift (dimensionless)
12987 * - "BETA": Beta factor (dimensionless)
12988 * - "VELO" or "VREL": Apparent radial ("relativistic") velocity (km/s)
12989 *
12990 * The default value for the Unit attribute for each system is shown
12991 * in parentheses. Note that the default value for the ActiveUnit flag
12992 c is non-zero
12993 f is .TRUE.
12994 * for a SpecFrame, meaning that changes to the Unit attribute for
12995 * a SpecFrame will result in the SpecFrame being re-mapped within
12996 * its enclosing FrameSet in order to reflect the change in units
12997 c (see astSetActiveUnit function for further information).
12998 f (see AST_SETACTIVEUNIT routine for further information).
12999 * TimeFrame
13000 * The TimeFrame class supports the following System values and
13001 * associated coordinate systems (the default is "MJD"):
13002 *
13003 * - "MJD": Modified Julian Date (d)
13004 * - "JD": Julian Date (d)
13005 * - "JEPOCH": Julian epoch (yr)
13006 * - "BEPOCH": Besselian (yr)
13007 *
13008 * The default value for the Unit attribute for each system is shown
13009 * in parentheses. Strictly, these systems should not allow changes
13010 * to be made to the units. For instance, the usual definition of
13011 * "MJD" and "JD" include the statement that the values will be in
13012 * units of days. However, AST does allow the use of other units
13013 * with all the above supported systems (except BEPOCH), on the
13014 * understanding that conversion to the "correct" units involves
13015 * nothing more than a simple scaling (1 yr = 365.25 d, 1 d = 24 h,
13016 * 1 h = 60 min, 1 min = 60 s). Besselian epoch values are defined
13017 * in terms of tropical years of 365.2422 days, rather than the
13018 * usual Julian year of 365.25 days. Therefore, to avoid any
13019 * confusion, the Unit attribute is automatically cleared to "yr" when
13020 * a System value of BEPOCH System is selected, and an error is
13021 * reported if any attempt is subsequently made to change the Unit
13022 * attribute.
13023 *
13024 * Note that the default value for the ActiveUnit flag
13025 c is non-zero
13026 f is .TRUE.
13027 * for a TimeFrame, meaning that changes to the Unit attribute for
13028 * a TimeFrame will result in the TimeFrame being re-mapped within
13029 * its enclosing FrameSet in order to reflect the change in units
13030 c (see astSetActiveUnit function for further information).
13031 f (see AST_SETACTIVEUNIT routine for further information).
13032 * FluxFrame
13033 * The FluxFrame class supports the following System values and
13034 * associated systems for measuring observed value:
13035 *
13036 * - "FLXDN": Flux per unit frequency (W/m^2/Hz)
13037 * - "FLXDNW": Flux per unit wavelength (W/m^2/Angstrom)
13038 * - "SFCBR": Surface brightness in frequency units (W/m^2/Hz/arcmin**2)
13039 * - "SFCBRW": Surface brightness in wavelength units (W/m^2/Angstrom/arcmin**2)
13040 *
13041 * The above lists specified the default units for each System. If an
13042 * explicit value is set for the Unit attribute but no value is set
13043 * for System, then the default System value is determined by the Unit
13044 * string (if the units are not appropriate for describing any of the
13045 * supported Systems then an error will be reported when an attempt is
13046 * made to access the System value). If no value has been specified for
13047 * either Unit or System, then System=FLXDN and Unit=W/m^2/Hz are
13048 * used.
13049 *att--
13050 */
13051 /* Clear the System value by setting it to AST__BADSYSTEM. */
13052 astMAKE_CLEAR(Frame,System,system,AST__BADSYSTEM)
13053
13054 /* Provide a default coordinate system of AST__CART. */
13055 astMAKE_GET(Frame,System,AstSystemType,AST__BADSYSTEM,(
13056 ( this->system == AST__BADSYSTEM ) ? AST__CART : this->system ) )
13057
13058 /* Validate the System value being set and retain the original if the
13059 supplied value is not recognized. */
13060 astMAKE_SET(Frame,System,AstSystemType,system,(
13061 (astValidateSystem( this, value, "astSetSystem" ) != AST__BADSYSTEM) ?
13062 value : this->system ))
13063
13064 /* The System value is set if it is not AST__BADSYSTEM. */
13065 astMAKE_TEST(Frame,System,( this->system != AST__BADSYSTEM ))
13066
13067 /*
13068 *att++
13069 * Name:
13070 * Title
13071
13072 * Purpose:
13073 * Frame title.
13074
13075 * Type:
13076 * Public attribute.
13077
13078 * Synopsis:
13079 * String.
13080
13081 * Description:
13082 * This attribute holds a string which is used as a title in (e.g.)
13083 * graphical output to describe the coordinate system which a Frame
13084 * represents. Examples might be "Detector Coordinates" or
13085 * "Galactic Coordinates".
13086 *
13087 * If a Title value has not been set for a Frame, then a suitable
13088 * default is supplied, depending on the class of the Frame.
13089
13090 * Applicability:
13091 * Frame
13092 * The default supplied by the Frame class is "<n>-d coordinate
13093 * system", where <n> is the number of Frame axes (Naxes
13094 * attribute).
13095 * CmpFrame
13096 * The CmpFrame class re-defines the default Title value to be
13097 * "<n>-d compound coordinate system", where <n> is the number
13098 * of CmpFrame axes (Naxes attribute).
13099 * FrameSet
13100 * The Title attribute of a FrameSet is the same as that of its
13101 * current Frame (as specified by the Current attribute).
13102
13103 * Notes:
13104 * - A Frame's Title is intended purely for interpretation by human
13105 * readers and not by software.
13106 *att--
13107 */
13108 /* Clear the Title value by freeing the allocated memory and assigning
13109 a NULL pointer. */
13110 astMAKE_CLEAR(Frame,Title,title,astFree( this->title ))
13111
13112 /* If the Title value is not set, write a default based on the number of Frame
13113 axes into the static "title_buff" buffer, and return a pointer to this
13114 buffer. */
13115 astMAKE_GET(Frame,Title,const char *,NULL,( this->title ?
13116 this->title : GetDefaultTitle( this, status ) ))
13117
13118 /* Set a Title value by freeing any previously allocated memory, allocating
13119 new memory, storing the string and saving the pointer to the copy. */
13120 astMAKE_SET(Frame,Title,const char *,title,astStore( this->title, value,
13121 strlen( value ) + (size_t) 1 ))
13122
13123 /* The Title value is set if the pointer to it is not NULL. */
13124 astMAKE_TEST(Frame,Title,( this->title != NULL ))
13125
13126 /*
13127 *att++
13128 * Name:
13129 * ObsLat
13130
13131 * Purpose:
13132 * The geodetic latitude of the observer
13133
13134 * Type:
13135 * Public attribute.
13136
13137 * Synopsis:
13138 * String.
13139
13140 * Description:
13141 * This attribute specifies the geodetic latitude of the observer, in
13142 * degrees, relative to the IAU 1976 reference ellipsoid. The basic Frame
13143 * class makes no use of this attribute, but specialised subclasses of
13144 * Frame may use it. For instance, the SpecFrame, SkyFrame and TimeFrame
13145 * classes use it. The default value is zero.
13146 *
13147 * The value is stored internally in radians, but is converted to and
13148 * from a degrees string for access. Some example input formats are:
13149 * "22:19:23.2", "22 19 23.2", "22:19.387", "22.32311", "N22.32311",
13150 * "-45.6", "S45.6". As indicated, the sign of the latitude can
13151 * optionally be indicated using characters "N" and "S" in place of the
13152 * usual "+" and "-". When converting the stored value to a string, the
13153 * format "[s]dd:mm:ss.ss" is used, when "[s]" is "N" or "S".
13154
13155 * Applicability:
13156 * Frame
13157 * All Frames have this attribute.
13158 * SpecFrame
13159 * Together with the ObsLon, Epoch, RefRA and RefDec attributes,
13160 * it defines the Doppler shift introduced by the observers diurnal
13161 * motion around the earths axis, which is needed when converting to
13162 * or from the topocentric standard of rest. The maximum velocity
13163 * error which can be caused by an incorrect value is 0.5 km/s. The
13164 * default value for the attribute is zero.
13165 * TimeFrame
13166 * Together with the ObsLon attribute, it is used when converting
13167 * between certain time scales (TDB, TCB, LMST, LAST)
13168
13169 *att--
13170 */
13171 /* The geodetic latitude of the observer (radians). Clear the ObsLat value by
13172 setting it to AST__BAD, returning zero as the default value. Any value is
13173 acceptable. */
13174 astMAKE_CLEAR(Frame,ObsLat,obslat,AST__BAD)
13175 astMAKE_GET(Frame,ObsLat,double,0.0,((this->obslat!=AST__BAD)?this->obslat:0.0))
13176 astMAKE_SET(Frame,ObsLat,double,obslat,value)
13177 astMAKE_TEST(Frame,ObsLat,(this->obslat!=AST__BAD))
13178
13179
13180 /*
13181 *att++
13182 * Name:
13183 * ObsAlt
13184
13185 * Purpose:
13186 * The geodetic altitude of the observer
13187
13188 * Type:
13189 * Public attribute.
13190
13191 * Synopsis:
13192 * String.
13193
13194 * Description:
13195 * This attribute specifies the geodetic altitude of the observer, in
13196 * metres, relative to the IAU 1976 reference ellipsoid. The basic Frame
13197 * class makes no use of this attribute, but specialised subclasses of
13198 * Frame may use it. For instance, the SpecFrame, SkyFrame and TimeFrame
13199 * classes use it. The default value is zero.
13200
13201 * Applicability:
13202 * Frame
13203 * All Frames have this attribute.
13204 * SpecFrame
13205 * Together with the ObsLon, Epoch, RefRA and RefDec attributes,
13206 * it defines the Doppler shift introduced by the observers diurnal
13207 * motion around the earths axis, which is needed when converting to
13208 * or from the topocentric standard of rest. The maximum velocity
13209 * error which can be caused by an incorrect value is 0.5 km/s. The
13210 * default value for the attribute is zero.
13211 * TimeFrame
13212 * Together with the ObsLon attribute, it is used when converting
13213 * between certain time scales (TDB, TCB, LMST, LAST)
13214
13215 *att--
13216 */
13217 /* The geodetic altitude of the observer (metres). Clear the ObsAlt value by
13218 setting it to AST__BAD, returning zero as the default value. Any value is
13219 acceptable. */
13220 astMAKE_CLEAR(Frame,ObsAlt,obsalt,AST__BAD)
13221 astMAKE_GET(Frame,ObsAlt,double,0.0,((this->obsalt!=AST__BAD)?this->obsalt:0.0))
13222 astMAKE_SET(Frame,ObsAlt,double,obsalt,value)
13223 astMAKE_TEST(Frame,ObsAlt,(this->obsalt!=AST__BAD))
13224
13225
13226 /*
13227 *att++
13228 * Name:
13229 * ObsLon
13230
13231 * Purpose:
13232 * The geodetic longitude of the observer
13233
13234 * Type:
13235 * Public attribute.
13236
13237 * Synopsis:
13238 * String.
13239
13240 * Description:
13241 * This attribute specifies the geodetic (or equivalently, geocentric)
13242 * longitude of the observer, in degrees, measured positive eastwards.
13243 * See also attribute ObsLat. The basic Frame class makes no use of this
13244 * attribute, but specialised subclasses of Frame may use it. For instance,
13245 * the SpecFrame, SkyFrame and TimeFrame classes use it. The default value
13246 * is zero.
13247 *
13248 * The value is stored internally in radians, but is converted to and
13249 * from a degrees string for access. Some example input formats are:
13250 * "155:19:23.2", "155 19 23.2", "155:19.387", "155.32311", "E155.32311",
13251 * "-204.67689", "W204.67689". As indicated, the sign of the longitude can
13252 * optionally be indicated using characters "E" and "W" in place of the
13253 * usual "+" and "-". When converting the stored value to a string, the
13254 * format "[s]ddd:mm:ss.ss" is used, when "[s]" is "E" or "W" and the
13255 * numerical value is chosen to be less than 180 degrees.
13256
13257 * Applicability:
13258 * Frame
13259 * All Frames have this attribute.
13260 * SpecFrame
13261 * Together with the ObsLon, Epoch, RefRA and RefDec attributes,
13262 * it defines the Doppler shift introduced by the observers diurnal
13263 * motion around the earths axis, which is needed when converting to
13264 * or from the topocentric standard of rest. The maximum velocity
13265 * error which can be caused by an incorrect value is 0.5 km/s. The
13266 * default value for the attribute is zero.
13267 * TimeFrame
13268 * Together with the ObsLon attribute, it is used when converting
13269 * between certain time scales (TDB, TCB, LMST, LAST)
13270
13271 *att--
13272 */
13273 /* The geodetic longitude of the observer (radians). Clear the ObsLon value by
13274 setting it to AST__BAD, returning zero as the default value. Any value is
13275 acceptable. */
13276 astMAKE_CLEAR(Frame,ObsLon,obslon,AST__BAD)
13277 astMAKE_GET(Frame,ObsLon,double,0.0,((this->obslon!=AST__BAD)?this->obslon:0.0))
13278 astMAKE_SET(Frame,ObsLon,double,obslon,value)
13279 astMAKE_TEST(Frame,ObsLon,(this->obslon!=AST__BAD))
13280
13281
13282 /* Copy constructor. */
13283 /* ----------------- */
13284 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
13285 /*
13286 * Name:
13287 * Copy
13288
13289 * Purpose:
13290 * Copy constructor for Frame objects.
13291
13292 * Type:
13293 * Private function.
13294
13295 * Synopsis:
13296 * void Copy( const AstObject *objin, AstObject *objout, int *status )
13297
13298 * Description:
13299 * This function implements the copy constructor for Frame objects.
13300
13301 * Parameters:
13302 * objin
13303 * Pointer to the object to be copied.
13304 * objout
13305 * Pointer to the object being constructed.
13306 * status
13307 * Pointer to the inherited status variable.
13308
13309 * Notes:
13310 * - This constructor makes a deep copy.
13311 */
13312
13313 /* Local Variables: */
13314 AstFrame *in; /* Pointer to input Frame */
13315 AstFrame *out; /* Pointer to output Frame */
13316 int axis; /* Loop counter for axes */
13317
13318 /* Check the global error status. */
13319 if ( !astOK ) return;
13320
13321 /* Obtain pointers to the input and output Frames. */
13322 in = (AstFrame *) objin;
13323 out = (AstFrame *) objout;
13324
13325 /* For safety, first clear any references to the input memory from
13326 the output Frame. */
13327 out->axis = NULL;
13328 out->domain = NULL;
13329 out->perm = NULL;
13330 out->title = NULL;
13331 out->variants = NULL;
13332
13333 /* If necessary, allocate memory in the output Frame and store a copy of the
13334 input Title and Domain strings. */
13335 if ( in->title ) out->title = astStore( NULL, in->title,
13336 strlen( in->title ) + (size_t) 1 );
13337 if ( in->domain ) out->domain = astStore( NULL, in->domain,
13338 strlen( in->domain ) +
13339 (size_t) 1 );
13340
13341 /* Allocate memory to hold the output Frame's Axis object pointers and its axis
13342 permutation array. */
13343 out->axis = astMalloc( sizeof( AstAxis * ) * (size_t) in->naxes );
13344 out->perm = astMalloc( sizeof( int ) * (size_t) in->naxes );
13345
13346 /* Make a copy of each of the input Frame's Axis objects, storing the pointer
13347 to each new Axis in the memory just allocated. Also copy the axis
13348 permutation array. */
13349 if ( astOK ) {
13350 for ( axis = 0; axis < in->naxes; axis++ ) {
13351 out->axis[ axis ] = astCopy( in->axis[ axis ] );
13352 out->perm[ axis ] = in->perm[ axis ];
13353 }
13354
13355 /* If an error occurred while copying the Axis objects, then loop through the
13356 resulting array of pointers and make sure that all of them are properly
13357 annulled. */
13358 if ( !astOK ) {
13359 for ( axis = 0; axis < in->naxes; axis++ ) {
13360 out->axis[ axis ] = astAnnul( out->axis[ axis ] );
13361 }
13362 }
13363 }
13364
13365 /* Other remaining objects */
13366 if( in->variants ) out->variants = astCopy( in->variants );
13367
13368 /* If an error occurred, free any allocated memory. */
13369 if ( !astOK ) {
13370 out->axis = astFree( out->axis );
13371 out->domain = astFree( out->domain );
13372 out->perm = astFree( out->perm );
13373 out->title = astFree( out->title );
13374 }
13375 }
13376
13377 /* Destructor. */
13378 /* ----------- */
Delete(AstObject * obj,int * status)13379 static void Delete( AstObject *obj, int *status ) {
13380 /*
13381 * Name:
13382 * Delete
13383
13384 * Purpose:
13385 * Destructor for Frame objects.
13386
13387 * Type:
13388 * Private function.
13389
13390 * Synopsis:
13391 * void Delete( AstObject *obj, int *status )
13392
13393 * Description:
13394 * This function implements the destructor for Frame objects.
13395
13396 * Parameters:
13397 * obj
13398 * Pointer to the object to be deleted.
13399 * status
13400 * Pointer to the inherited status variable.
13401
13402 * Notes:
13403 * This function attempts to execute even if the global error status is
13404 * set.
13405 */
13406
13407 /* Local Variables: */
13408 AstFrame *this; /* Pointer to Frame */
13409 int axis; /* Loop counter for Frame axes */
13410
13411 /* Obtain a pointer to the Frame structure. */
13412 this = (AstFrame *) obj;
13413
13414 /* Free the memory used for the Title and Domain strings if necessary. */
13415 this->title = astFree( this->title );
13416 this->domain = astFree( this->domain );
13417
13418 /* If memory has been allocated to store pointers to the Frame's Axis objects,
13419 annul each of these pointers and then free the memory. */
13420 if ( this->axis ) {
13421 for ( axis = 0; axis < this->naxes; axis++ ) {
13422 this->axis[ axis ] = astAnnul( this->axis[ axis ] );
13423 }
13424 this->axis = astFree( this->axis );
13425 }
13426
13427 /* Free memory used for the axis permutation array if necessary. */
13428 this->perm = astFree( this->perm );
13429
13430 /* Other objects. */
13431 if( this->variants ) this->variants = astAnnul( this->variants );
13432 }
13433
13434 /* Dump function. */
13435 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)13436 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
13437 /*
13438 * Name:
13439 * Dump
13440
13441 * Purpose:
13442 * Dump function for Frame objects.
13443
13444 * Type:
13445 * Private function.
13446
13447 * Synopsis:
13448 * void Dump( AstObject *this, AstChannel *channel, int *status )
13449
13450 * Description:
13451 * This function implements the Dump function which writes out data
13452 * for the Frame class to an output Channel.
13453
13454 * Parameters:
13455 * this
13456 * Pointer to the Frame whose data are being written.
13457 * channel
13458 * Pointer to the Channel to which the data are being written.
13459 * status
13460 * Pointer to the inherited status variable.
13461 */
13462
13463 /* Local Constants: */
13464 #define COMMENT_LEN 150 /* Maximum length of a comment string */
13465 #define KEY_LEN 50 /* Maximum length of a keyword */
13466
13467 /* Local Variables: */
13468 AstAxis *ax; /* Pointer to Axis */
13469 AstFrame *cfrm; /* Pointer to FrameSet's current Frame */
13470 AstFrame *this; /* Pointer to the Frame structure */
13471 AstSystemType system; /* System code */
13472 char comment[ COMMENT_LEN + 1 ]; /* Buffer for comment strings */
13473 char key[ KEY_LEN + 1 ]; /* Buffer for keywords */
13474 const char *sval; /* Pointer to string value */
13475 const char *lab; /* Pointer to unit label */
13476 const int *perm; /* Pointer to axis permutation array */
13477 double dval; /* Double attibute value */
13478 int *invperm; /* Pointer to inverse permutation array */
13479 int axis; /* Loop counter for Frame axes */
13480 int bessyr; /* Format as Besselian years (else Julian) */
13481 int digits_set; /* Digits set explicitly for any axis? */
13482 int full; /* Full attribute value */
13483 int full_set; /* Full attribute set? */
13484 int helpful; /* Helpful to show value even if not set? */
13485 int isFrame; /* Is this a simple Frame? */
13486 int ival; /* Integer value */
13487 int naxes; /* Number of Frame axes */
13488 int set; /* Attribute value set? */
13489
13490 /* Check the global error status. */
13491 if ( !astOK ) return;
13492
13493 /* Obtain a pointer to the Frame structure. */
13494 this = (AstFrame *) this_object;
13495
13496 /* Determine the number of Frame axes and a pointer to the Frame's
13497 axis permutation array (using methods, to allow for any over-ride
13498 by a derived class). */
13499 naxes = astGetNaxes( this );
13500 perm = astGetPerm( this );
13501
13502 /* Some default attribute values are not helpful for a simple Frame. Note
13503 if this is a simple Frame, or if it is a FrameSet with a simple Frame
13504 as its current Frame., or if it is a CmpFrame. */
13505 if( !strcmp( astGetClass( this ), "Frame" ) ) {
13506 isFrame = 1;
13507 } else if( astIsAFrameSet( this ) ) {
13508 cfrm = astGetFrame( (AstFrameSet *) this, AST__CURRENT );
13509 isFrame = !strcmp( astGetClass( cfrm ), "Frame" );
13510 cfrm = astAnnul( cfrm );
13511 } else if( astIsACmpFrame( this ) ) {
13512 isFrame = 1;
13513 } else {
13514 isFrame = 0;
13515 }
13516
13517 /* Allocate memory to hold an inverse axis permutation array and
13518 generate this array from the forward permutation values. This will
13519 be used to determine which axis should be enquired about (using
13520 possibly over-ridden methods) to obtain data to correspond with a
13521 particular internal value (i.e. instance variable) relating to an
13522 axis. This step is needed so that the effect of any axis
13523 permutation can be un-done before values are written out, as output
13524 values are written by this function in un-permuted order. */
13525 invperm = astMalloc( sizeof( int ) * (size_t) naxes );
13526 if ( astOK ) {
13527 for ( axis = 0; axis < naxes; axis++ ) invperm[ perm[ axis ] ] = axis;
13528
13529 /* Write out values representing the instance variables for the Frame
13530 class. Accompany these with appropriate comment strings, possibly
13531 depending on the values being written.*/
13532
13533 /* In the case of attributes, we first use the appropriate (private)
13534 Test... member function to see if they are set. If so, we then use
13535 the (private) Get... function to obtain the value to be written
13536 out.
13537
13538 For attributes which are not set, we use the astGet... method to
13539 obtain the value instead. This will supply a default value
13540 (possibly provided by a derived class which over-rides this method)
13541 which is more useful to a human reader as it corresponds to the
13542 actual default attribute value. Since "set" will be zero, these
13543 values are for information only and will not be read back. */
13544
13545 /* Title. */
13546 /* ------ */
13547 set = TestTitle( this, status );
13548 sval = set ? GetTitle( this, status ) : astGetTitle( this );
13549 astWriteString( channel, "Title", set, 1, sval,
13550 "Title of coordinate system" );
13551
13552 /* Naxes. */
13553 /* ------ */
13554 set = ( this->naxes != 0 );
13555 ival = set ? this->naxes : naxes;
13556 astWriteInt( channel, "Naxes", set, 1, ival,
13557 "Number of coordinate axes" );
13558
13559 /* Domain. */
13560 /* ------- */
13561 set = TestDomain( this, status );
13562 sval = set ? GetDomain( this, status ) : astGetDomain( this );
13563
13564 /* Don't show an un-set Domain value if it is blank. */
13565 helpful = ( sval && *sval );
13566 astWriteString( channel, "Domain", set, helpful, sval,
13567 "Coordinate system domain" );
13568
13569 /* Epoch. */
13570 /* ------ */
13571 set = TestEpoch( this, status );
13572 dval = set ? GetEpoch( this, status ) : astGetEpoch( this );
13573
13574 /* Convert MJD to Besselian or Julian years, depending on the value. */
13575 bessyr = ( dval < palEpj2d( 1984.0 ) );
13576 dval = bessyr ? palEpb( dval ) : palEpj( dval );
13577 astWriteDouble( channel, "Epoch", set, !isFrame, dval,
13578 bessyr ? "Besselian epoch of observation" :
13579 "Julian epoch of observation" );
13580
13581 /* Label. */
13582 /* ------ */
13583 /* This, and some other, attributes are stored internally by the
13584 Frame's Axis objects, but are "re-packaged" by the Frame class to
13585 appear as Frame attributes. We treat them here like Frame
13586 attributes that are "un-set". There is a Label value for each Frame
13587 axis. */
13588 for ( axis = 0; axis < naxes; axis++ ) {
13589
13590 /* The inverse axis permutation array is used to obtain the axis index
13591 for astGetLabel. This reverses the effect of the Frame's axis
13592 permutation array and yields a default value appropriate to the
13593 axis with internal index "axis". */
13594 sval = astGetLabel( this, invperm[ axis ] );
13595
13596 /* Create keyword and comment strings appropriate to each axis
13597 (converting to 1-based axis numbering) and write out the Label
13598 values. */
13599 (void) sprintf( key, "Lbl%d", axis + 1 );
13600 (void) sprintf( comment, "Label for axis %d", axis + 1 );
13601 astWriteString( channel, key, 0, 1, sval, comment );
13602 }
13603
13604 /* Symbol. */
13605 /* ------- */
13606 /* There is a Symbol value for each Frame axis. These are handled in
13607 the same way as the Label values. */
13608 for ( axis = 0; axis < naxes; axis++ ) {
13609 sval = astGetSymbol( this, invperm[ axis ] );
13610 (void) sprintf( key, "Sym%d", axis + 1 );
13611 (void) sprintf( comment, "Symbol for axis %d", axis + 1 );
13612 astWriteString( channel, key, 0, 0, sval, comment );
13613 }
13614
13615 /* System. */
13616 /* ------- */
13617 set = TestSystem( this, status );
13618 system = set ? GetSystem( this, status ) : astGetSystem( this );
13619
13620 /* If set, convert explicitly to a string for the external representation. */
13621 if ( set ) {
13622 if ( astOK ) {
13623 sval = astSystemString( this, system );
13624
13625 /* Report an error if the System value was not recognised. */
13626 if ( !sval ) {
13627 astError( AST__SCSIN,
13628 "astWrite(%s): Corrupt %s contains invalid "
13629 "System identification code (%d).", status,
13630 astGetClass( channel ), astGetClass( this ),
13631 (int) system );
13632 }
13633 }
13634
13635 /* If not set, use astGetAttrib which returns a string value using
13636 (possibly over-ridden) methods. */
13637 } else {
13638 sval = astGetAttrib( this_object, "system" );
13639 }
13640
13641 /* Write out the value. */
13642 astWriteString( channel, "System", set, !isFrame, sval,
13643 "Coordinate system type" );
13644
13645 /* AlignSystem. */
13646 /* ------------ */
13647 set = TestAlignSystem( this, status );
13648 system = set ? GetAlignSystem( this, status ) : astGetAlignSystem( this );
13649
13650 /* If set, convert explicitly to a string for the external representation. */
13651 if ( set ) {
13652 if ( astOK ) {
13653 sval = astSystemString( this, system );
13654
13655 /* Report an error if the AlignSystem value was not recognised. */
13656 if ( !sval ) {
13657 astError( AST__SCSIN,
13658 "astWrite(%s): Corrupt %s contains invalid "
13659 "AlignSystem identification code (%d).", status,
13660 astGetClass( channel ), astGetClass( this ),
13661 (int) system );
13662 }
13663 }
13664
13665 /* If not set, use astGetAttrib which returns a string value using
13666 (possibly over-ridden) methods. */
13667 } else {
13668 sval = astGetAttrib( this_object, "alignsystem" );
13669 }
13670
13671 /* Write out the value. */
13672 astWriteString( channel, "AlSys", set, 0, sval,
13673 "Alignment coordinate system" );
13674
13675 /* Unit. */
13676 /* ----- */
13677 /* There is a Unit value for each axis. */
13678 for ( axis = 0; axis < naxes; axis++ ) {
13679 sval = astGetUnit( this, invperm[ axis ] );
13680
13681 /* Get any label associated with the unit string. */
13682 lab = astUnitLabel( sval );
13683
13684 /* Construct a comment including the above label (but only if it is not
13685 the same as the unit string) . */
13686 if( lab && strcmp( lab, sval ) ) {
13687 (void) sprintf( comment, "Units for axis %d (%s)", axis + 1, lab );
13688 } else {
13689 (void) sprintf( comment, "Units for axis %d", axis + 1 );
13690 }
13691
13692 /* Show the Unit value if it is not blank. */
13693 helpful = ( sval && *sval );
13694 (void) sprintf( key, "Uni%d", axis + 1 );
13695 astWriteString( channel, key, 0, helpful, sval, comment );
13696 }
13697
13698 /* Digits. */
13699 /* ------- */
13700 /* There is a Digits value for each axis... */
13701 digits_set = 0;
13702 for ( axis = 0; axis < naxes; axis++ ) {
13703
13704 /* Obtain the axis Digits value, using the Frame's Digits value as a
13705 default. */
13706 ax = astGetAxis( this, invperm[ axis ] );
13707 set = astTestAxisDigits( ax );
13708 ival = set ? astGetAxisDigits( ax ) : astGetDigits( this );
13709 ax = astAnnul( ax );
13710
13711 /* Show the value if it is set for the axis (i.e. if it differs from
13712 the default for the whole Frame) and note if any such value is
13713 set. */
13714 helpful = set;
13715 if ( set ) digits_set = 1;
13716 (void) sprintf( key, "Dig%d", axis + 1 );
13717 (void) sprintf( comment, "Individual precision for axis %d",
13718 axis + 1 );
13719 astWriteInt( channel, key, 0, helpful, ival, comment );
13720 }
13721
13722 /* There is also a Digits value for the Frame as a whole... */
13723 set = TestDigits( this, status );
13724
13725 /* Show the value (even if not set) if an explicit Digits value has
13726 been set for any axis (above). */
13727 helpful = digits_set;
13728 ival = set ? GetDigits( this, status ) : astGetDigits( this );
13729 astWriteInt( channel, "Digits", set, helpful, ival,
13730 "Default formatting precision" );
13731
13732 /* Format. */
13733 /* ------- */
13734 /* There is a Format value for each axis. */
13735 for ( axis = 0; axis < naxes; axis++ ) {
13736 sval = astGetFormat( this, invperm[ axis ] );
13737
13738 /* Show the Format value if the Digits value is set for an individual
13739 axis. */
13740 ax = astGetAxis( this, invperm[ axis ] );
13741 helpful = astTestAxisDigits( ax );
13742 ax = astAnnul( ax );
13743 (void) sprintf( key, "Fmt%d", axis + 1 );
13744 (void) sprintf( comment, "Format specifier for axis %d", axis + 1 );
13745 astWriteString( channel, key, 0, helpful, sval, comment );
13746 }
13747
13748 /* Direction. */
13749 /* ---------- */
13750 /* There is a Direction value for each axis. */
13751 for ( axis = 0; axis < naxes; axis++ ) {
13752 ival = astGetDirection( this, invperm[ axis ] );
13753
13754 /* Show the value if it is zero. */
13755 helpful = ( ival == 0 );
13756 (void) sprintf( key, "Dir%d", axis + 1 );
13757 (void) sprintf( comment,
13758 ival ? "Plot axis %d in conventional direction" :
13759 "Plot axis %d in reverse direction",
13760 axis + 1 );
13761 astWriteInt( channel, key, 0, helpful, ival, comment );
13762 }
13763
13764 /* Bottom. */
13765 /* ------- */
13766 /* There is a Bottom value for each axis. */
13767 for ( axis = 0; axis < naxes; axis++ ) {
13768 dval = astGetBottom( this, invperm[ axis ] );
13769
13770 /* Show the value if it is zero. */
13771 helpful = ( dval != -DBL_MAX );
13772 (void) sprintf( key, "Bot%d", axis + 1 );
13773 astWriteDouble( channel, key, 0, helpful, dval, "Lowest legal axis value");
13774 }
13775
13776 /* Top. */
13777 /* ------- */
13778 /* There is a Top value for each axis. */
13779 for ( axis = 0; axis < naxes; axis++ ) {
13780 dval = astGetTop( this, invperm[ axis ] );
13781
13782 /* Show the value if it is zero. */
13783 helpful = ( dval != DBL_MAX );
13784 (void) sprintf( key, "Top%d", axis + 1 );
13785 astWriteDouble( channel, key, 0, helpful, dval, "Highest legal axis value");
13786 }
13787
13788 /* PreserveAxes. */
13789 /* ------------- */
13790 set = TestPreserveAxes( this, status );
13791 ival = set ? GetPreserveAxes( this, status ) : astGetPreserveAxes( this );
13792 astWriteInt( channel, "Presrv", set, 0, ival,
13793 ival ? "Preserve target axes" :
13794 "Don't preserve target axes" );
13795
13796 /* Permute. */
13797 /* -------- */
13798 set = TestPermute( this, status );
13799 ival = set ? GetPermute( this, status ) : astGetPermute( this );
13800 astWriteInt( channel, "Permut", set, 0, ival,
13801 ival ? "Axes may be permuted to match" :
13802 "Axes may not be permuted match" );
13803
13804 /* MinAxes. */
13805 /* -------- */
13806 set = TestMinAxes( this, status );
13807 ival = set ? GetMinAxes( this, status ) : astGetMinAxes( this );
13808 astWriteInt( channel, "MinAx", set, 0, ival,
13809 "Minimum number of axes to match" );
13810
13811 /* MaxAxes. */
13812 /* -------- */
13813 set = TestMaxAxes( this, status );
13814 ival = set ? GetMaxAxes( this, status ) : astGetMaxAxes( this );
13815 astWriteInt( channel, "MaxAx", set, 0, ival,
13816 "Maximum number of axes to match" );
13817
13818 /* MatchEnd. */
13819 /* --------- */
13820 set = TestMatchEnd( this, status );
13821 ival = set ? GetMatchEnd( this, status ) : astGetMatchEnd( this );
13822 astWriteInt( channel, "MchEnd", set, 0, ival,
13823 ival ? "Match final target axes" :
13824 "Match initial target axes" );
13825
13826 /* ObsLat. */
13827 /* ------- */
13828 set = TestObsLat( this, status );
13829 dval = set ? GetObsLat( this, status ) : astGetObsLat( this );
13830 astWriteDouble( channel, "ObsLat", set, 0, dval, "Observers geodetic latitude (rads)" );
13831
13832 /* ObsLon. */
13833 /* ------- */
13834 set = TestObsLon( this, status );
13835 dval = set ? GetObsLon( this, status ) : astGetObsLon( this );
13836 astWriteDouble( channel, "ObsLon", set, 0, dval, "Observers geodetic longitude (rads)" );
13837
13838 /* ObsAlt. */
13839 /* ------- */
13840 set = TestObsAlt( this, status );
13841 dval = set ? GetObsAlt( this, status ) : astGetObsAlt( this );
13842 astWriteDouble( channel, "ObsAlt", set, 0, dval, "Observers geodetic altitude (metres)" );
13843
13844 /* Dut1*/
13845 /* ---- */
13846 set = TestDut1( this, status );
13847 dval = set ? GetDut1( this, status ) : astGetDut1( this );
13848 astWriteDouble( channel, "Dut1", set, 0, dval, "UT1-UTC in seconds" );
13849
13850
13851 /* ActiveUnit. */
13852 /* ----------- */
13853 if( astTestActiveUnit( this ) ) {
13854 ival = astGetActiveUnit( this );
13855 astWriteInt( channel, "ActUnt", 1, 0, ival,
13856 ival ? "Unit strings affects alignment" :
13857 "Unit strings do not affect alignment" );
13858 }
13859
13860 /* Axis permutation array. */
13861 /* ----------------------- */
13862 /* Write out the axis permutation array value for each axis,
13863 converting to 1-based axis numbering. */
13864 for ( axis = 0; axis < this->naxes; axis++ ) {
13865 set = ( this->perm[ axis ] != axis );
13866 ival = this->perm[ axis ] + 1;
13867
13868 /* Create a keyword and comment appropriate to the axis. */
13869 (void) sprintf( key, "Prm%d", axis + 1 );
13870 if ( set ) {
13871 (void) sprintf( comment,
13872 "Axis %d permuted to use internal axis %d",
13873 axis + 1, ival );
13874 } else {
13875 (void) sprintf( comment, "Axis %d not permuted", axis + 1 );
13876 }
13877 astWriteInt( channel, key, set, 0, ival, comment );
13878 }
13879
13880 /* Axis Objects. */
13881 /* ------------- */
13882 /* Temporarily set the Channel's Full attribute to -1 (unless it is +1
13883 to start with), remembering the original setting. This prevents any
13884 unnecessary "un-set" Axis values being output that would otherwise
13885 simply duplicate the Frame's attributes which have already been
13886 written. "Set" Axis values are still written, however (and all
13887 values are written if Full is set to 1). */
13888 full_set = astTestFull( channel );
13889 full = astGetFull( channel );
13890 if ( full <= 0 ) astSetFull( channel, -1 );
13891
13892 /* Handle each axis in turn. */
13893 for ( axis = 0; axis < this->naxes; axis++ ) {
13894
13895 /* Create a keyword and comment appropriate to the axis (converting to
13896 1-based axis numbering). */
13897 (void) sprintf( key, "Ax%d", axis + 1 );
13898 (void) sprintf( comment, "Axis number %d", axis + 1 );
13899
13900 /* Write out the axis Object description. */
13901 astWriteObject( channel, key, 1, 0, this->axis[ axis ], comment );
13902 }
13903
13904 /* Restore the Channel's original Full attribute setting. */
13905 if ( full_set ) {
13906 astSetFull( channel, full );
13907 } else {
13908 astClearFull( channel );
13909 }
13910
13911 /* Free the inverse axis permutation array. */
13912 invperm = astFree( invperm );
13913
13914 /* Variants */
13915 /* ------- */
13916 if( this->variants ) astWriteObject( channel, "Vrnts", 1, 0,
13917 this->variants, "Variant Frames" );
13918 }
13919
13920 /* Undefine macros local to this function. */
13921 #undef COMMENT_LEN
13922 #undef KEY_LEN
13923 }
13924
13925 /* Standard class functions. */
13926 /* ========================= */
13927 /* Implement the astIsAFrame and astCheckFrame functions using the macros
13928 defined for this purpose in the "object.h" header file. */
astMAKE_ISA(Frame,Mapping)13929 astMAKE_ISA(Frame,Mapping)
13930 astMAKE_CHECK(Frame)
13931
13932 AstFrame *astFrame_( int naxes, const char *options, int *status, ...) {
13933 /*
13934 *+
13935 * Name:
13936 * astFrame
13937
13938 * Purpose:
13939 * Create a Frame.
13940
13941 * Type:
13942 * Protected function.
13943
13944 * Synopsis:
13945 * #include "frame.h"
13946 * AstFrame *astFrame( int naxes, const char *options, int *status, ... )
13947
13948 * Class Membership:
13949 * Frame constructor.
13950
13951 * Description:
13952 * This function creates a new Frame and optionally initialises its
13953 * attributes.
13954
13955 * Parameters:
13956 * naxes
13957 * The number of Frame axes.
13958 * options
13959 * Pointer to a null terminated string containing an optional
13960 * comma-separated list of attribute assignments to be used for
13961 * initialising the new Frame. The syntax used is the same as
13962 * for the astSet method and may include "printf" format
13963 * specifiers identified by "%" symbols in the normal way.
13964 * status
13965 * Pointer to the inherited status variable.
13966 * ...
13967 * If the "options" string contains "%" format specifiers, then
13968 * an optional list of arguments may follow it in order to
13969 * supply values to be substituted for these specifiers. The
13970 * rules for supplying these are identical to those for the
13971 * astSet method (and for the C "printf" function).
13972
13973 * Returned Value:
13974 * A pointer to the new Frame.
13975
13976 * Notes:
13977 * - A NULL pointer will be returned if this function is invoked
13978 * with the global error status set, or if it should fail for any
13979 * reason.
13980 *-
13981
13982 * Implementation Notes:
13983 * - This function implements the basic Frame constructor which is
13984 * available via the protected interface to the Frame class. A
13985 * public interface is provided by the astFrameId_ function.
13986 */
13987
13988 /* Local Variables: */
13989 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
13990 AstFrame *new; /* Pointer to new Frame */
13991 va_list args; /* Variable argument list */
13992
13993 /* Get a pointer to the thread specific global data structure. */
13994 astGET_GLOBALS(NULL);
13995
13996 /* Check the global error status. */
13997 if ( !astOK ) return NULL;
13998
13999 /* Initialise the Frame, allocating memory and initialising the virtual
14000 function table as well if necessary. */
14001 new = astInitFrame( NULL, sizeof( AstFrame ), !class_init, &class_vtab,
14002 "Frame", naxes );
14003
14004 /* If successful, note that the virtual function table has been initialised. */
14005 if ( astOK ) {
14006 class_init = 1;
14007
14008 /* Obtain the variable argument list and pass it along with the options string
14009 to the astVSet method to initialise the new Frame's attributes. */
14010 va_start( args, status );
14011 astVSet( new, options, NULL, args );
14012 va_end( args );
14013
14014 /* If an error occurred, clean up by deleting the new object. */
14015 if ( !astOK ) new = astDelete( new );
14016 }
14017
14018 /* Return a pointer to the new Frame. */
14019 return new;
14020 }
14021
astInitFrame_(void * mem,size_t size,int init,AstFrameVtab * vtab,const char * name,int naxes,int * status)14022 AstFrame *astInitFrame_( void *mem, size_t size, int init,
14023 AstFrameVtab *vtab, const char *name,
14024 int naxes, int *status ) {
14025 /*
14026 *+
14027 * Name:
14028 * astInitFrame
14029
14030 * Purpose:
14031 * Initialise a Frame.
14032
14033 * Type:
14034 * Protected function.
14035
14036 * Synopsis:
14037 * #include "frame.h"
14038 * AstFrame *astInitFrame( void *mem, size_t size, int init,
14039 * AstFrameVtab *vtab, const char *name,
14040 * int naxes )
14041
14042 * Class Membership:
14043 * Frame initialiser.
14044
14045 * Description:
14046 * This function is provided for use by class implementations to initialise
14047 * a new Frame object. It allocates memory (if necessary) to accommodate
14048 * the Frame plus any additional data associated with the derived class.
14049 * It then initialises a Frame structure at the start of this memory. If
14050 * the "init" flag is set, it also initialises the contents of a virtual
14051 * function table for a Frame at the start of the memory passed via the
14052 * "vtab" parameter.
14053
14054 * Parameters:
14055 * mem
14056 * A pointer to the memory in which the Frame is to be created. This
14057 * must be of sufficient size to accommodate the Frame data
14058 * (sizeof(Frame)) plus any data used by the derived class. If a value
14059 * of NULL is given, this function will allocate the memory itself using
14060 * the "size" parameter to determine its size.
14061 * size
14062 * The amount of memory used by the Frame (plus derived class data).
14063 * This will be used to allocate memory if a value of NULL is given for
14064 * the "mem" parameter. This value is also stored in the Frame
14065 * structure, so a valid value must be supplied even if not required for
14066 * allocating memory.
14067 * init
14068 * A logical flag indicating if the Frame's virtual function table is
14069 * to be initialised. If this value is non-zero, the virtual function
14070 * table will be initialised by this function.
14071 * vtab
14072 * Pointer to the start of the virtual function table to be associated
14073 * with the new Frame.
14074 * name
14075 * Pointer to a constant null-terminated character string which contains
14076 * the name of the class to which the new object belongs (it is this
14077 * pointer value that will subsequently be returned by the astGetClass
14078 * method).
14079 * naxes
14080 * The number of Frame axes.
14081
14082 * Returned Value:
14083 * A pointer to the new Frame.
14084
14085 * Notes:
14086 * - A null pointer will be returned if this function is invoked with the
14087 * global error status set, or if it should fail for any reason.
14088 *-
14089 */
14090
14091 /* Local Variables: */
14092 AstFrame *new; /* Pointer to new Frame */
14093 int axis; /* Loop counter for Frame axes */
14094
14095 /* Check the global status. */
14096 if ( !astOK ) return NULL;
14097
14098 /* If necessary, initialise the virtual function table. */
14099 if ( init ) astInitFrameVtab( vtab, name );
14100
14101 /* Initialise. */
14102 new = NULL;
14103
14104 /* Check the number of axes for validity, reporting an error if necessary. */
14105 if ( naxes < 0 ) {
14106 astError( AST__NAXIN, "astInitFrame(%s): Number of axes (%d) is "
14107 "invalid - this number should not be negative.", status, name, naxes );
14108
14109 /* Initialise a Mapping structure (the parent class) as the first
14110 component within the Frame structure, allocating memory if
14111 necessary. Set the number of input/output coordinates to zero (the
14112 astGetNin and astGetNout methods are over-ridden by the Frame class
14113 to provide values for these that are equal to the number of Frame
14114 axes). */
14115 } else {
14116 new = (AstFrame *) astInitMapping( mem, size, 0,
14117 (AstMappingVtab *) vtab, name,
14118 0, 0, 1, 1 );
14119
14120 if ( astOK ) {
14121
14122 /* Initialise the Frame data. */
14123 /* ----------------------------- */
14124 /* Set the number of Frame axes. */
14125 new->naxes = naxes;
14126
14127 /* Initialise all attributes to their "undefined" values. */
14128 new->digits = -INT_MAX;
14129 new->domain = NULL;
14130 new->epoch = AST__BAD;
14131 new->match_end = -INT_MAX;
14132 new->max_axes = -INT_MAX;
14133 new->min_axes = -INT_MAX;
14134 new->permute = -INT_MAX;
14135 new->preserve_axes = -INT_MAX;
14136 new->title = NULL;
14137 new->system = AST__BADSYSTEM;
14138 new->alignsystem = AST__BADSYSTEM;
14139 new->active_unit = -INT_MAX;
14140 new->obsalt = AST__BAD;
14141 new->obslat = AST__BAD;
14142 new->obslon = AST__BAD;
14143 new->dut1 = AST__BAD;
14144 new->flags = 0;
14145 new->variants = NULL;
14146
14147 /* Allocate memory to store pointers to the Frame's Axis objects and to store
14148 its axis permutation array. */
14149 new->axis = astMalloc( sizeof( AstAxis * ) * (size_t) naxes );
14150 new->perm = astMalloc( sizeof( int ) * (size_t) naxes );
14151
14152 /* Create a new Axis object to describe each axis of the Frame and store the
14153 resulting pointers in the memory allocated above. Also initialise the
14154 axis permutation array so that the axes appear in their natural order. */
14155 if ( astOK ) {
14156 for ( axis = 0; axis < naxes; axis++ ) {
14157 new->axis[ axis ] = astAxis( "", status );
14158 new->perm[ axis ] = axis;
14159 }
14160
14161 /* If an error occurred while creating the Axis objects, scan through the array
14162 of pointers to them again to ensure that they are all correctly annulled. */
14163 if ( !astOK ) {
14164 for ( axis = 0; axis < naxes; axis++ ) {
14165 new->axis[ axis ] = astAnnul( new->axis[ axis ] );
14166 }
14167 }
14168 }
14169
14170 /* If an error occurred, clean up by deleting the new object. */
14171 if ( !astOK ) new = astDelete( new );
14172 }
14173 }
14174
14175 /* Return a pointer to the new object. */
14176 return new;
14177 }
14178
astLoadFrame_(void * mem,size_t size,AstFrameVtab * vtab,const char * name,AstChannel * channel,int * status)14179 AstFrame *astLoadFrame_( void *mem, size_t size,
14180 AstFrameVtab *vtab, const char *name,
14181 AstChannel *channel, int *status ) {
14182 /*
14183 *+
14184 * Name:
14185 * astLoadFrame
14186
14187 * Purpose:
14188 * Load a Frame.
14189
14190 * Type:
14191 * Protected function.
14192
14193 * Synopsis:
14194 * #include "frame.h"
14195 * AstFrame *astLoadFrame( void *mem, size_t size,
14196 * AstFrameVtab *vtab, const char *name,
14197 * AstChannel *channel )
14198
14199 * Class Membership:
14200 * Frame loader.
14201
14202 * Description:
14203 * This function is provided to load a new Frame using data read
14204 * from a Channel. It first loads the data used by the parent class
14205 * (which allocates memory if necessary) and then initialises a
14206 * Frame structure in this memory, using data read from the input
14207 * Channel.
14208 *
14209 * If the "init" flag is set, it also initialises the contents of a
14210 * virtual function table for a Frame at the start of the memory
14211 * passed via the "vtab" parameter.
14212
14213
14214 * Parameters:
14215 * mem
14216 * A pointer to the memory into which the Frame is to be loaded.
14217 * This must be of sufficient size to accommodate the Frame data
14218 * (sizeof(Frame)) plus any data used by derived classes. If a
14219 * value of NULL is given, this function will allocate the
14220 * memory itself using the "size" parameter to determine its
14221 * size.
14222 * size
14223 * The amount of memory used by the Frame (plus derived class
14224 * data). This will be used to allocate memory if a value of
14225 * NULL is given for the "mem" parameter. This value is also
14226 * stored in the Frame structure, so a valid value must be
14227 * supplied even if not required for allocating memory.
14228 *
14229 * If the "vtab" parameter is NULL, the "size" value is ignored
14230 * and sizeof(AstFrame) is used instead.
14231 * vtab
14232 * Pointer to the start of the virtual function table to be
14233 * associated with the new Frame. If this is NULL, a pointer to
14234 * the (static) virtual function table for the Frame class is
14235 * used instead.
14236 * name
14237 * Pointer to a constant null-terminated character string which
14238 * contains the name of the class to which the new object
14239 * belongs (it is this pointer value that will subsequently be
14240 * returned by the astGetClass method).
14241 *
14242 * If the "vtab" parameter is NULL, the "name" value is ignored
14243 * and a pointer to the string "Frame" is used instead.
14244
14245 * Returned Value:
14246 * A pointer to the new Frame.
14247
14248 * Notes:
14249 * - A null pointer will be returned if this function is invoked
14250 * with the global error status set, or if it should fail for any
14251 * reason.
14252 *-
14253 */
14254
14255 /* Local Constants: */
14256 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
14257 #define KEY_LEN 50 /* Maximum length of a keyword */
14258
14259 /* Local Variables: */
14260 AstFrame *new; /* Pointer to the new Frame */
14261 char *sval; /* Pointer to string value */
14262 char key[ KEY_LEN + 1 ]; /* Buffer for keywords */
14263 double dval; /* DOuble attribute value */
14264 int axis; /* Loop counter for axes */
14265 int ival; /* Integer value */
14266
14267 /* Get a pointer to the thread specific global data structure. */
14268 astGET_GLOBALS(channel);
14269
14270 /* Initialise. */
14271 new = NULL;
14272
14273 /* Check the global error status. */
14274 if ( !astOK ) return new;
14275
14276 /* If a NULL virtual function table has been supplied, then this is
14277 the first loader to be invoked for this Frame. In this case the
14278 Frame belongs to this class, so supply appropriate values to be
14279 passed to the parent class loader (and its parent, etc.). */
14280 if ( !vtab ) {
14281 size = sizeof( AstFrame );
14282 vtab = &class_vtab;
14283 name = "Frame";
14284
14285 /* If required, initialise the virtual function table for this class. */
14286 if ( !class_init ) {
14287 astInitFrameVtab( vtab, name );
14288 class_init = 1;
14289 }
14290 }
14291
14292 /* Invoke the parent class loader to load data for all the ancestral
14293 classes of the current one, returning a pointer to the resulting
14294 partly-built Frame. */
14295 new = astLoadMapping( mem, size, (AstMappingVtab *) vtab, name,
14296 channel );
14297
14298 if ( astOK ) {
14299
14300 /* Assign values for transient components that are not included in the
14301 Frame dump */
14302 new->flags = 0;
14303
14304 /* Read input data. */
14305 /* ================ */
14306 /* Request the input Channel to read all the input data appropriate to
14307 this class into the internal "values list". */
14308 astReadClassData( channel, "Frame" );
14309
14310 /* Now read each individual data item from this list and use it to
14311 initialise the appropriate instance variable(s) for this class. */
14312
14313 /* In the case of attributes, we first read the "raw" input value,
14314 supplying the "unset" value as the default. If a "set" value is
14315 obtained, we then use the appropriate (private) Set... member
14316 function to validate and set the value properly. */
14317
14318 /* Naxes. */
14319 /* ------ */
14320 /* Obtain the number of Frame axes and allocate memory for the arrays
14321 which hold axis information. */
14322 new->naxes = astReadInt( channel, "naxes", 0 );
14323 if ( new->naxes < 0 ) new->naxes = 0;
14324 new->perm = astMalloc( sizeof( int ) * (size_t) new->naxes );
14325 new->axis = astMalloc( sizeof( AstAxis * ) * (size_t) new->naxes );
14326
14327 /* If an error occurred, ensure that any allocated memory is freed. */
14328 if ( !astOK ) {
14329 new->perm = astFree( new->perm );
14330 new->axis = astFree( new->axis );
14331
14332 /* Otherwise, initialise the array of Axis pointers. */
14333 } else {
14334 for ( axis = 0; axis < new->naxes; axis++ ) new->axis[ axis ] = NULL;
14335
14336 /* Now obtain those input values which are required for each axis... */
14337 for ( axis = 0; axis < new->naxes; axis++ ) {
14338
14339 /* Axis object. */
14340 /* ------------ */
14341 /* This must be read first, so that it can hold the other axis values
14342 obtained below. */
14343
14344 /* Create a keyword appropriate to this axis. */
14345 (void) sprintf( key, "ax%d", axis + 1 );
14346
14347 /* Read the Axis object. If none was read, provide a default Axis
14348 instead. */
14349 new->axis[ axis ] = astReadObject( channel, key, NULL );
14350 if ( !new->axis[ axis ] ) new->axis[ axis ] = astAxis( "", status );
14351
14352 /* Label. */
14353 /* ------ */
14354 /* Read the Label string for each axis. If a value is obtained, use
14355 it to set the Label attribute for the axis. Free the memory holding
14356 the string when no longer needed. */
14357 (void) sprintf( key, "lbl%d", axis + 1 );
14358 sval = astReadString( channel, key, NULL );
14359 if ( sval ) {
14360 astSetAxisLabel( new->axis[ axis ], sval );
14361 sval = astFree( sval );
14362 }
14363
14364 /* Symbol. */
14365 /* ------- */
14366 (void) sprintf( key, "sym%d", axis + 1 );
14367 sval = astReadString( channel, key, NULL );
14368 if ( sval ) {
14369 astSetAxisSymbol( new->axis[ axis ], sval );
14370 sval = astFree( sval );
14371 }
14372
14373 /* Format. */
14374 /* ------- */
14375 (void) sprintf( key, "fmt%d", axis + 1 );
14376 sval = astReadString( channel, key, NULL );
14377 if ( sval ) {
14378 astSetAxisFormat( new->axis[ axis ], sval );
14379 sval = astFree( sval );
14380 }
14381
14382 /* Unit. */
14383 /* ----- */
14384 (void) sprintf( key, "uni%d", axis + 1 );
14385 sval = astReadString( channel, key, NULL );
14386 if ( sval ) {
14387 astSetAxisUnit( new->axis[ axis ], sval );
14388 sval = astFree( sval );
14389 }
14390
14391 /* Direction. */
14392 /* ---------- */
14393 (void) sprintf( key, "dir%d", axis + 1 );
14394 ival = astReadInt( channel, key, -INT_MAX );
14395 if ( ival != -INT_MAX ) {
14396 astSetAxisDirection( new->axis[ axis ], ival );
14397 }
14398
14399 /* Top. */
14400 /*----- */
14401 (void) sprintf( key, "top%d", axis + 1 );
14402 dval = astReadDouble( channel, key, AST__BAD );
14403 if ( dval != AST__BAD ) {
14404 astSetAxisTop( new->axis[ axis ], dval );
14405 }
14406
14407 /* Bottom. */
14408 /*----- -- */
14409 (void) sprintf( key, "bot%d", axis + 1 );
14410 dval = astReadDouble( channel, key, AST__BAD );
14411 if ( dval != AST__BAD ) {
14412 astSetAxisBottom( new->axis[ axis ], dval );
14413 }
14414
14415 /* Digits. */
14416 /* ------- */
14417 (void) sprintf( key, "dig%d", axis + 1 );
14418 ival = astReadInt( channel, key, -INT_MAX );
14419 if ( ival != -INT_MAX ) {
14420 astSetAxisDigits( new->axis[ axis ], ival );
14421 }
14422
14423 /* Axis permutation array. */
14424 /* ----------------------- */
14425 /* Convert from 1-based to zero-based axis numbering at this
14426 point. The default is the "un-permuted" value. */
14427 sprintf( key, "prm%d", axis + 1 );
14428 new->perm[ axis ] = astReadInt( channel, key, axis + 1 ) - 1;
14429
14430 /* Quit looping if an error occurs. */
14431 if ( !astOK ) break;
14432 }
14433
14434 /* The remaining values are not associated with particular axes... */
14435
14436 /* Title. */
14437 /* ------ */
14438 new->title = astReadString( channel, "title", NULL );
14439
14440 /* Domain. */
14441 /* ------- */
14442 new->domain = astReadString( channel, "domain", NULL );
14443
14444 /* Epoch. */
14445 /* ------ */
14446 /* Interpret this as Besselian or Julian depending on its value. */
14447 new->epoch = astReadDouble( channel, "epoch", AST__BAD );
14448 if ( TestEpoch( new, status ) ) {
14449 SetEpoch( new, ( new->epoch < 1984.0 ) ? palEpb2d( new->epoch ) :
14450 palEpj2d( new->epoch ), status );
14451 }
14452
14453 /* Digits. */
14454 /* ------- */
14455 /* This is the value that applies to the Frame as a whole. */
14456 new->digits = astReadInt( channel, "digits", -INT_MAX );
14457 if ( TestDigits( new, status ) ) SetDigits( new, new->digits, status );
14458
14459 /* PreserveAxes. */
14460 /* ------------- */
14461 new->preserve_axes = astReadInt( channel, "presrv", -INT_MAX );
14462 if ( TestPreserveAxes( new, status ) ) {
14463 SetPreserveAxes( new, new->preserve_axes, status );
14464 }
14465
14466 /* Permute. */
14467 /* -------- */
14468 new->permute = astReadInt( channel, "permut", -INT_MAX );
14469 if ( TestPermute( new, status ) ) SetPermute( new, new->permute, status );
14470
14471 /* MinAxes. */
14472 /* -------- */
14473 new->min_axes = astReadInt( channel, "minax", -INT_MAX );
14474 if ( TestMinAxes( new, status ) ) SetMinAxes( new, new->min_axes, status );
14475
14476 /* MaxAxes. */
14477 /* -------- */
14478 new->max_axes = astReadInt( channel, "maxax", -INT_MAX );
14479 if ( TestMaxAxes( new, status ) ) SetMaxAxes( new, new->max_axes, status );
14480
14481 /* MatchEnd. */
14482 /* --------- */
14483 new->match_end = astReadInt( channel, "mchend", -INT_MAX );
14484 if ( TestMatchEnd( new, status ) ) SetMatchEnd( new, new->match_end, status );
14485
14486 /* ObsLat. */
14487 /* ------- */
14488 new->obslat = astReadDouble( channel, "obslat", AST__BAD );
14489 if ( TestObsLat( new, status ) ) SetObsLat( new, new->obslat, status );
14490
14491 /* ObsLon. */
14492 /* ------- */
14493 new->obslon = astReadDouble( channel, "obslon", AST__BAD );
14494 if ( TestObsLon( new, status ) ) SetObsLon( new, new->obslon, status );
14495
14496 /* ObsAlt. */
14497 /* ------- */
14498 new->obsalt = astReadDouble( channel, "obsalt", AST__BAD );
14499 if ( TestObsAlt( new, status ) ) SetObsAlt( new, new->obsalt, status );
14500
14501 /* Dut1. */
14502 /* ---- */
14503 new->dut1 = astReadDouble( channel, "dut1", AST__BAD );
14504 if ( TestDut1( new, status ) ) SetDut1( new, new->dut1, status );
14505
14506 /* ActiveUnit. */
14507 /* ----------- */
14508 new->active_unit = astReadInt( channel, "actunt", -INT_MAX );
14509 if ( TestActiveUnit( new, status ) ) SetActiveUnit( new, new->active_unit, status );
14510
14511 /* System. */
14512 /* ------- */
14513 /* Set the default and read the external representation as a string. */
14514 new->system = AST__BADSYSTEM;
14515 sval = astReadString( channel, "system", NULL );
14516
14517 /* If a value was read, convert from a string to a System code. */
14518 if ( sval ) {
14519 if ( astOK ) {
14520 new->system = astSystemCode( new, sval );
14521
14522 /* Report an error if the value wasn't recognised. */
14523 if ( new->system == AST__BADSYSTEM ) {
14524 astError( AST__ATTIN,
14525 "astRead(%s): Invalid System description "
14526 "\"%s\".", status, astGetClass( channel ), sval );
14527 }
14528 }
14529
14530 /* Free the string value. */
14531 sval = astFree( sval );
14532 }
14533
14534 /* AlignSystem. */
14535 /* ------------ */
14536 /* Set the default and read the external representation as a string. */
14537 new->alignsystem = AST__BADSYSTEM;
14538 sval = astReadString( channel, "alsys", NULL );
14539
14540 /* If a value was read, convert from a string to a System code. */
14541 if ( sval ) {
14542 if ( astOK ) {
14543 new->alignsystem = astSystemCode( new, sval );
14544
14545 /* Report an error if the value wasn't recognised. */
14546 if ( new->alignsystem == AST__BADSYSTEM ) {
14547 astError( AST__ATTIN,
14548 "astRead(%s): Invalid AlignSystem description "
14549 "\"%s\".", status, astGetClass( channel ), sval );
14550 }
14551 }
14552
14553 /* Free the string value. */
14554 sval = astFree( sval );
14555 }
14556
14557 /* Variants. */
14558 /* -------- */
14559 new->variants = astReadObject( channel, "vrnts", NULL );
14560 }
14561
14562 /* If an error occurred, clean up by deleting the new Frame. */
14563 if ( !astOK ) new = astDelete( new );
14564 }
14565
14566 /* Return the new Frame pointer. */
14567 return new;
14568
14569 /* Undefine macros local to this function. */
14570 #undef KEY_LEN
14571 }
14572
14573 /* Virtual function interfaces. */
14574 /* ============================ */
14575 /* These provide the external interface to the virtual functions defined by
14576 this class. Each simply checks the global error status and then locates and
14577 executes the appropriate member function, using the function pointer stored
14578 in the object's virtual function table (this pointer is located using the
14579 astMEMBER macro defined in "object.h").
14580
14581 Note that the member function may not be the one defined here, as it may
14582 have been over-ridden by a derived class. However, it should still have the
14583 same interface. */
astAbbrev_(AstFrame * this,int axis,const char * fmt,const char * str1,const char * str2,int * status)14584 const char *astAbbrev_( AstFrame *this, int axis, const char *fmt,
14585 const char *str1, const char *str2, int *status ) {
14586 if ( !astOK ) return str2;
14587 return (**astMEMBER(this,Frame,Abbrev))( this, axis, fmt, str1, str2, status );
14588 }
astFields_(AstFrame * this,int axis,const char * fmt,const char * str,int maxfld,char ** fields,int * nc,double * val,int * status)14589 int astFields_( AstFrame *this, int axis, const char *fmt,
14590 const char *str, int maxfld, char **fields,
14591 int *nc, double *val, int *status ) {
14592 if ( !astOK ) return 0;
14593 return (**astMEMBER(this,Frame,Fields))( this, axis, fmt, str, maxfld, fields, nc, val, status );
14594 }
astCheckPerm_(AstFrame * this,const int * perm,const char * method,int * status)14595 void astCheckPerm_( AstFrame *this, const int *perm, const char *method, int *status ) {
14596 if ( !astOK ) return;
14597 (**astMEMBER(this,Frame,CheckPerm))( this, perm, method, status );
14598 }
14599
astResolvePoints_(AstFrame * this,const double point1[],const double point2[],AstPointSet * in,AstPointSet * out,int * status)14600 AstPointSet *astResolvePoints_( AstFrame *this, const double point1[],
14601 const double point2[], AstPointSet *in,
14602 AstPointSet *out, int *status ) {
14603 if ( !astOK ) return NULL;
14604 return (**astMEMBER(this,Frame,ResolvePoints))( this, point1, point2, in, out, status );
14605 }
astLineDef_(AstFrame * this,const double start[2],const double end[2],int * status)14606 AstLineDef *astLineDef_( AstFrame *this, const double start[2],
14607 const double end[2], int *status ) {
14608 if ( !astOK ) return NULL;
14609 return (**astMEMBER(this,Frame,LineDef))( this, start, end, status );
14610 }
astLineCrossing_(AstFrame * this,AstLineDef * l1,AstLineDef * l2,double ** cross,int * status)14611 int astLineCrossing_( AstFrame *this, AstLineDef *l1, AstLineDef *l2,
14612 double **cross, int *status ) {
14613 if ( !astOK ) return 0;
14614 return (**astMEMBER(this,Frame,LineCrossing))( this, l1, l2, cross, status );
14615 }
astLineOffset_(AstFrame * this,AstLineDef * line,double par,double prp,double point[2],int * status)14616 void astLineOffset_( AstFrame *this, AstLineDef *line, double par, double prp,
14617 double point[2], int *status ){
14618 if ( !astOK ) return;
14619 (**astMEMBER(this,Frame,LineOffset))( this, line, par, prp, point, status );
14620 }
astLineContains_(AstFrame * this,AstLineDef * l,int def,double * point,int * status)14621 int astLineContains_( AstFrame *this, AstLineDef *l, int def, double *point, int *status ) {
14622 if ( !astOK ) return 0;
14623 return (**astMEMBER(this,Frame,LineContains))( this, l, def, point, status );
14624 }
astConvert_(AstFrame * from,AstFrame * to,const char * domainlist,int * status)14625 AstFrameSet *astConvert_( AstFrame *from, AstFrame *to,
14626 const char *domainlist, int *status ) {
14627 if ( !astOK ) return NULL;
14628 return (**astMEMBER(from,Frame,Convert))( from, to, domainlist, status );
14629 }
astConvertX_(AstFrame * to,AstFrame * from,const char * domainlist,int * status)14630 AstFrameSet *astConvertX_( AstFrame *to, AstFrame *from,
14631 const char *domainlist, int *status ) {
14632 if ( !astOK ) return NULL;
14633 return (**astMEMBER(to,Frame,ConvertX))( to, from, domainlist, status );
14634 }
astAngle_(AstFrame * this,const double a[],const double b[],const double c[],int * status)14635 double astAngle_( AstFrame *this, const double a[], const double b[],
14636 const double c[], int *status ) {
14637 if ( !astOK ) return AST__BAD;
14638 return (**astMEMBER(this,Frame,Angle))( this, a, b, c, status );
14639 }
astGetActiveUnit_(AstFrame * this,int * status)14640 int astGetActiveUnit_( AstFrame *this, int *status ) {
14641 if ( !astOK ) return 0;
14642 return (**astMEMBER(this,Frame,GetActiveUnit))( this, status );
14643 }
astTestActiveUnit_(AstFrame * this,int * status)14644 int astTestActiveUnit_( AstFrame *this, int *status ) {
14645 if ( !astOK ) return 0;
14646 return (**astMEMBER(this,Frame,TestActiveUnit))( this, status );
14647 }
astSetActiveUnit_(AstFrame * this,int value,int * status)14648 void astSetActiveUnit_( AstFrame *this, int value, int *status ) {
14649 if ( !astOK ) return;
14650 (**astMEMBER(this,Frame,SetActiveUnit))( this, value, status );
14651 }
astDistance_(AstFrame * this,const double point1[],const double point2[],int * status)14652 double astDistance_( AstFrame *this,
14653 const double point1[], const double point2[], int *status ) {
14654 if ( !astOK ) return AST__BAD;
14655 return (**astMEMBER(this,Frame,Distance))( this, point1, point2, status );
14656 }
astFindFrame_(AstFrame * target,AstFrame * template,const char * domainlist,int * status)14657 AstFrameSet *astFindFrame_( AstFrame *target, AstFrame *template,
14658 const char *domainlist, int *status ) {
14659 if ( !astOK ) return NULL;
14660 return (**astMEMBER(target,Frame,FindFrame))( target, template, domainlist, status );
14661 }
astMatchAxes_(AstFrame * frm1,AstFrame * frm2,int * axes,int * status)14662 void astMatchAxes_( AstFrame *frm1, AstFrame *frm2, int *axes, int *status ) {
14663 if ( !astOK ) return;
14664 (**astMEMBER(frm1,Frame,MatchAxes))( frm1, frm2, axes, status );
14665 }
astMatchAxesX_(AstFrame * frm2,AstFrame * frm1,int * axes,int * status)14666 void astMatchAxesX_( AstFrame *frm2, AstFrame *frm1, int *axes, int *status ) {
14667 if ( !astOK ) return;
14668 (**astMEMBER(frm2,Frame,MatchAxesX))( frm2, frm1, axes, status );
14669 }
astFormat_(AstFrame * this,int axis,double value,int * status)14670 const char *astFormat_( AstFrame *this, int axis, double value, int *status ) {
14671 if ( !astOK ) return NULL;
14672 return (**astMEMBER(this,Frame,Format))( this, axis, value, status );
14673 }
astGap_(AstFrame * this,int axis,double gap,int * ntick,int * status)14674 double astGap_( AstFrame *this, int axis, double gap, int *ntick, int *status ) {
14675 if ( !astOK ) return 0.0;
14676 return (**astMEMBER(this,Frame,Gap))( this, axis, gap, ntick, status );
14677 }
astGetAxis_(AstFrame * this,int axis,int * status)14678 AstAxis *astGetAxis_( AstFrame *this, int axis, int *status ) {
14679 if ( !astOK ) return NULL;
14680 return (**astMEMBER(this,Frame,GetAxis))( this, axis, status );
14681 }
astGetNaxes_(AstFrame * this,int * status)14682 int astGetNaxes_( AstFrame *this, int *status ) {
14683 if ( !astOK ) return 0;
14684 return (**astMEMBER(this,Frame,GetNaxes))( this, status );
14685 }
astGetPerm_(AstFrame * this,int * status)14686 const int *astGetPerm_( AstFrame *this, int *status ) {
14687 if ( !astOK ) return NULL;
14688 return (**astMEMBER(this,Frame,GetPerm))( this, status );
14689 }
astGetFrameVariants_(AstFrame * this,int * status)14690 AstFrameSet *astGetFrameVariants_( AstFrame *this, int *status ) {
14691 if ( !astOK ) return NULL;
14692 return (**astMEMBER(this,Frame,GetFrameVariants))( this, status );
14693 }
astSetFrameVariants_(AstFrame * this,AstFrameSet * variants,int * status)14694 void astSetFrameVariants_( AstFrame *this, AstFrameSet *variants, int *status ) {
14695 if ( !astOK ) return;
14696 (**astMEMBER(this,Frame,SetFrameVariants))( this, variants, status );
14697 }
14698
14699
astMatch_(AstFrame * this,AstFrame * target,int matchsub,int ** template_axes,int ** target_axes,AstMapping ** map,AstFrame ** result,int * status)14700 int astMatch_( AstFrame *this, AstFrame *target, int matchsub,
14701 int **template_axes, int **target_axes,
14702 AstMapping **map, AstFrame **result, int *status ) {
14703
14704 AstFrame *super_this;
14705 const char *dom;
14706 int match;
14707
14708 if ( !astOK ) return 0;
14709
14710 match = (**astMEMBER(this,Frame,Match))( this, target, matchsub,
14711 template_axes, target_axes,
14712 map, result, status );
14713
14714 /* If the template ("this") could not be used to probe the target, it may
14715 be because the template class is a more specialised form of the target
14716 class. E.g. a SkyFrame cannot directly be used to probe a Frame, but a
14717 Frame *can* be used to probe a SkyFrame. This means (for instance),
14718 that a basic Frame with Domain FRED cannot be aligned (using astConvert)
14719 with a CmpFrame with Domain FRED. This sort of alignment is often
14720 useful, so we try now to use the supplied template to probe a modified
14721 form of the target that has been cast into the same class as the
14722 template. This is only possible if the template class is a sub-class of
14723 the target class. Attempt to do the cast. */
14724 if( ! match && matchsub ) {
14725 super_this = (AstFrame *) astCast( this, target );
14726
14727 /* If the cast was possible, fix the template Domain since the parent
14728 class may provide a different default Domain, and then invoke the Match
14729 method appropriate to the new template class (i.e. the target class). */
14730 if( super_this ) {
14731 if( astTestDomain( target ) ) {
14732 dom = astGetDomain( this );
14733 if( astChrLen( dom ) > 0 ) astSetDomain( super_this, dom );
14734 }
14735 match = (**astMEMBER(super_this,Frame,Match))( super_this, target,
14736 matchsub, template_axes,
14737 target_axes, map,
14738 result, status );
14739 super_this = astAnnul( super_this );
14740 }
14741 }
14742
14743 return match;
14744 }
14745
14746
astIsUnitFrame_(AstFrame * this,int * status)14747 int astIsUnitFrame_( AstFrame *this, int *status ){
14748 if ( !astOK ) return 0;
14749 return (**astMEMBER(this,Frame,IsUnitFrame))( this, status );
14750 }
astNorm_(AstFrame * this,double value[],int * status)14751 void astNorm_( AstFrame *this, double value[], int *status ) {
14752 if ( !astOK ) return;
14753 (**astMEMBER(this,Frame,Norm))( this, value, status );
14754 }
astNormBox_(AstFrame * this,double lbnd[],double ubnd[],AstMapping * reg,int * status)14755 void astNormBox_( AstFrame *this, double lbnd[], double ubnd[], AstMapping *reg, int *status ) {
14756 if ( !astOK ) return;
14757 (**astMEMBER(this,Frame,NormBox))( this, lbnd, ubnd, reg, status );
14758 }
astAxDistance_(AstFrame * this,int axis,double v1,double v2,int * status)14759 double astAxDistance_( AstFrame *this, int axis, double v1, double v2, int *status ) {
14760 if ( !astOK ) return AST__BAD;
14761 return (**astMEMBER(this,Frame,AxDistance))( this, axis, v1, v2, status );
14762 }
astAxOffset_(AstFrame * this,int axis,double v1,double dist,int * status)14763 double astAxOffset_( AstFrame *this, int axis, double v1, double dist, int *status ) {
14764 if ( !astOK ) return AST__BAD;
14765 return (**astMEMBER(this,Frame,AxOffset))( this, axis, v1, dist, status );
14766 }
14767
14768
astFrameGrid_(AstFrame * this,int size,const double * lbnd,const double * ubnd,int * status)14769 AstPointSet *astFrameGrid_( AstFrame *this, int size, const double *lbnd,
14770 const double *ubnd, int *status ){
14771 if ( !astOK ) return NULL;
14772 return (**astMEMBER(this,Frame,FrameGrid))( this, size, lbnd, ubnd, status );
14773 }
14774
14775
astOffset_(AstFrame * this,const double point1[],const double point2[],double offset,double point3[],int * status)14776 void astOffset_( AstFrame *this, const double point1[], const double point2[],
14777 double offset, double point3[], int *status ) {
14778 if ( !astOK ) return;
14779 (**astMEMBER(this,Frame,Offset))( this, point1, point2, offset, point3, status );
14780 }
astAxAngle_(AstFrame * this,const double a[2],const double b[2],int axis,int * status)14781 double astAxAngle_( AstFrame *this, const double a[2], const double b[2],
14782 int axis, int *status ) {
14783 if ( !astOK ) return AST__BAD;
14784 return (**astMEMBER(this,Frame,AxAngle))( this, a, b, axis, status );
14785 }
astOffset2_(AstFrame * this,const double point1[2],double angle,double offset,double point2[2],int * status)14786 double astOffset2_( AstFrame *this, const double point1[2], double angle,
14787 double offset, double point2[2], int *status ) {
14788 if ( !astOK ) return AST__BAD;
14789 return (**astMEMBER(this,Frame,Offset2))( this, point1, angle, offset, point2, status );
14790 }
astIntersect_(AstFrame * this,const double a1[2],const double a2[2],const double b1[2],const double b2[2],double cross[2],int * status)14791 void astIntersect_( AstFrame *this, const double a1[2],
14792 const double a2[2], const double b1[2],
14793 const double b2[2], double cross[2],
14794 int *status ) {
14795 if ( !astOK ) return;
14796 (**astMEMBER(this,Frame,Intersect))( this, a1, a2, b1, b2, cross, status );
14797 }
astOverlay_(AstFrame * template,const int * template_axes,AstFrame * result,int * status)14798 void astOverlay_( AstFrame *template, const int *template_axes,
14799 AstFrame *result, int *status ) {
14800 if ( !astOK ) return;
14801 (**astMEMBER(template,Frame,Overlay))( template, template_axes, result, status );
14802 }
astPermAxes_(AstFrame * this,const int perm[],int * status)14803 void astPermAxes_( AstFrame *this, const int perm[], int *status ) {
14804 if ( !astOK ) return;
14805 (**astMEMBER(this,Frame,PermAxes))( this, perm, status );
14806 }
astPickAxes_(AstFrame * this,int naxes,const int axes[],AstMapping ** map,int * status)14807 AstFrame *astPickAxes_( AstFrame *this, int naxes, const int axes[],
14808 AstMapping **map, int *status ) {
14809 if ( !astOK ) return NULL;
14810 return (**astMEMBER(this,Frame,PickAxes))( this, naxes, axes, map, status );
14811 }
astPrimaryFrame_(AstFrame * this,int axis1,AstFrame ** frame,int * axis2,int * status)14812 void astPrimaryFrame_( AstFrame *this, int axis1,
14813 AstFrame **frame, int *axis2, int *status ) {
14814 if ( !astOK ) return;
14815 (**astMEMBER(this,Frame,PrimaryFrame))( this, axis1, frame, axis2, status );
14816 }
astResolve_(AstFrame * this,const double point1[],const double point2[],const double point3[],double point4[],double * d1,double * d2,int * status)14817 void astResolve_( AstFrame *this, const double point1[], const double point2[],
14818 const double point3[], double point4[], double *d1,
14819 double *d2, int *status ) {
14820 if ( !astOK ) return;
14821 (**astMEMBER(this,Frame,Resolve))( this, point1, point2, point3, point4, d1, d2, status );
14822 }
astSetAxis_(AstFrame * this,int axis,AstAxis * newaxis,int * status)14823 void astSetAxis_( AstFrame *this, int axis, AstAxis *newaxis, int *status ) {
14824 if ( !astOK ) return;
14825 (**astMEMBER(this,Frame,SetAxis))( this, axis, newaxis, status );
14826 }
astSetUnit_(AstFrame * this,int axis,const char * value,int * status)14827 void astSetUnit_( AstFrame *this, int axis, const char *value, int *status ) {
14828 if ( !astOK ) return;
14829 (**astMEMBER(this,Frame,SetUnit))( this, axis, value, status );
14830 }
astClearUnit_(AstFrame * this,int axis,int * status)14831 void astClearUnit_( AstFrame *this, int axis, int *status ) {
14832 if ( !astOK ) return;
14833 (**astMEMBER(this,Frame,ClearUnit))( this, axis, status );
14834 }
astSubFrame_(AstFrame * target,AstFrame * template,int result_naxes,const int * target_axes,const int * template_axes,AstMapping ** map,AstFrame ** result,int * status)14835 int astSubFrame_( AstFrame *target, AstFrame *template, int result_naxes,
14836 const int *target_axes, const int *template_axes,
14837 AstMapping **map, AstFrame **result, int *status ) {
14838 if ( !astOK ) return 0;
14839 return (**astMEMBER(target,Frame,SubFrame))( target, template, result_naxes,
14840 target_axes, template_axes,
14841 map, result, status );
14842 }
astUnformat_(AstFrame * this,int axis,const char * string,double * value,int * status)14843 int astUnformat_( AstFrame *this, int axis, const char *string,
14844 double *value, int *status ) {
14845 if ( !astOK ) return 0;
14846 return (**astMEMBER(this,Frame,Unformat))( this, axis, string, value, status );
14847 }
astValidateAxis_(AstFrame * this,int axis,int fwd,const char * method,int * status)14848 int astValidateAxis_( AstFrame *this, int axis, int fwd, const char *method, int *status ) {
14849 if ( !astOK ) return 0;
14850 return (**astMEMBER(this,Frame,ValidateAxis))( this, axis, fwd, method, status );
14851 }
astValidateAxisSelection_(AstFrame * this,int naxes,const int * axes,const char * method,int * status)14852 void astValidateAxisSelection_( AstFrame *this, int naxes, const int *axes,
14853 const char *method, int *status ) {
14854 if ( !astOK ) return;
14855 (**astMEMBER(this,Frame,ValidateAxisSelection))( this, naxes, axes,
14856 method, status );
14857 }
astValidateSystem_(AstFrame * this,AstSystemType system,const char * method,int * status)14858 AstSystemType astValidateSystem_( AstFrame *this, AstSystemType system, const char *method, int *status ) {
14859 if ( !astOK ) return AST__BADSYSTEM;
14860 return (**astMEMBER(this,Frame,ValidateSystem))( this, system, method, status );
14861 }
astSystemCode_(AstFrame * this,const char * system,int * status)14862 AstSystemType astSystemCode_( AstFrame *this, const char *system, int *status ) {
14863 if ( !astOK ) return AST__BADSYSTEM;
14864 return (**astMEMBER(this,Frame,SystemCode))( this, system, status );
14865 }
astSystemString_(AstFrame * this,AstSystemType system,int * status)14866 const char *astSystemString_( AstFrame *this, AstSystemType system, int *status ) {
14867 if ( !astOK ) return NULL;
14868 return (**astMEMBER(this,Frame,SystemString))( this, system, status );
14869 }
astAxIn_(AstFrame * this,int axis,double lo,double hi,double val,int closed,int * status)14870 int astAxIn_( AstFrame *this, int axis, double lo, double hi, double val,
14871 int closed, int *status ) {
14872 if ( !astOK ) return 0;
14873 return (**astMEMBER(this,Frame,AxIn))( this, axis, lo, hi, val, closed, status );
14874 }
astGetFrameFlags_(AstFrame * this,int * status)14875 int astGetFrameFlags_( AstFrame *this, int *status ) {
14876 if ( !astOK ) return 0;
14877 return (**astMEMBER(this,Frame,GetFrameFlags))( this, status );
14878 }
astSetFrameFlags_(AstFrame * this,int value,int * status)14879 void astSetFrameFlags_( AstFrame *this, int value, int *status ) {
14880 if ( !astOK ) return;
14881 (**astMEMBER(this,Frame,SetFrameFlags))( this, value, status );
14882 }
14883
14884
14885 /* Special public interface functions. */
14886 /* =================================== */
14887 /* These provide the public interface to certain special functions
14888 whose public interface cannot be handled using macros (such as
14889 astINVOKE) alone. In general, they are named after the
14890 corresponding protected version of the function, but with "Id"
14891 appended to the name. */
14892
14893 /* Public Interface Function Prototypes. */
14894 /* ------------------------------------- */
14895 /* The following functions have public prototypes only (i.e. no
14896 protected prototypes), so we must provide local prototypes for use
14897 within this module. */
14898 AstFrame *PickAxesId_( AstFrame *, int, const int[], AstMapping **, int * );
14899 AstFrame *astFrameId_( int, const char *, ... );
14900 const char *astFormatId_( AstFrame *, int, double, int * );
14901 int astUnformatId_( AstFrame *, int, const char *, double *, int * );
14902 void astPermAxesId_( AstFrame *, const int[], int * );
14903
14904 /* Special interface function implementations. */
14905 /* ------------------------------------------- */
astFormatId_(AstFrame * this,int axis,double value,int * status)14906 const char *astFormatId_( AstFrame *this, int axis, double value, int *status ) {
14907 /*
14908 *++
14909 * Name:
14910 c astFormat
14911 f AST_FORMAT
14912
14913 * Purpose:
14914 * Format a coordinate value for a Frame axis.
14915
14916 * Type:
14917 * Public virtual function.
14918
14919 * Synopsis:
14920 c #include "frame.h"
14921 c const char *astFormat( AstFrame *this, int axis, double value )
14922 f RESULT = AST_FORMAT( THIS, AXIS, VALUE, STATUS )
14923
14924 * Class Membership:
14925 * Frame method.
14926
14927 * Description:
14928 c This function returns a pointer to a string containing the
14929 f This function returns a character string containing the
14930 * formatted (character) version of a coordinate value for a Frame
14931 * axis. The formatting applied is determined by the Frame's
14932 * attributes and, in particular, by any Format attribute string
14933 * that has been set for the axis. A suitable default format (based
14934 * on the Digits attribute value) will be applied if necessary.
14935
14936 * Parameters:
14937 c this
14938 f THIS = INTEGER (given)
14939 * Pointer to the Frame.
14940 c axis
14941 f AXIS = INTEGER (Given)
14942 * The number of the Frame axis for which formatting is to be
14943 * performed (axis numbering starts at 1 for the first axis).
14944 c value
14945 f VALUE = DOUBLE PRECISION (Given)
14946 * The coordinate value to be formatted.
14947 f STATUS = INTEGER (Given and Returned)
14948 f The global status.
14949
14950 * Returned Value:
14951 c astFormat()
14952 c A pointer to a null-terminated string containing the formatted
14953 c value.
14954 f AST_FORMAT = CHARACTER * ( AST__SZCHR )
14955 f The formatted value.
14956
14957 * Notes:
14958 c - The returned pointer is guaranteed to remain valid and the
14959 c string to which it points will not be over-written for a total
14960 c of 50 successive invocations of this function. After this, the
14961 c memory containing the string may be re-used, so a copy of the
14962 c string should be made if it is needed for longer than this.
14963 c - A formatted value may be converted back into a numerical (double)
14964 c value using astUnformat.
14965 f - A formatted value may be converted back into a numerical
14966 f (double precision) value using AST_UNFORMAT.
14967 c - A NULL pointer will be returned if this function is invoked
14968 c with the AST error status set, or if it should fail for any
14969 c reason.
14970 f - A blank string will be returned if this function is invoked
14971 f with STATUS set to an error value, or if it should fail for any
14972 f reason.
14973 *--
14974
14975 * Implementation Notes:
14976 * This function implements the public interface for the astFormat
14977 * method. It is identical to astFormat_ except that:
14978 *
14979 * - The axis index is decremented by 1 before use. This allows the
14980 * public interface to use 1-based axis numbers (whereas internally
14981 * axis numbers are zero-based).
14982 *
14983 * - The returned string value is buffered in dynamically allocated
14984 * memory so that it will remain valid for a guaranteed number of
14985 * function invocations.
14986 */
14987
14988 /* Local Variables: */
14989 astDECLARE_GLOBALS /* Thread-specific global data */
14990 const char *fvalue; /* Pointer to formatted value */
14991 const char *result; /* Pointer value to return */
14992 int i; /* Loop counter for initialisation */
14993
14994 /* Initialise. */
14995 result = NULL;
14996
14997 /* Check the global error status. */
14998 if ( !astOK ) return result;
14999
15000 /* Get a pointer to Thread-specific global data. */
15001 astGET_GLOBALS(this);
15002
15003 /* If the "astformatid_strings" array has not been initialised, fill it with NULL
15004 pointers. */
15005 if ( !astformatid_init ) {
15006 astformatid_init = 1;
15007 for ( i = 0; i < ASTFORMATID_MAX_STRINGS; i++ ) astformatid_strings[ i ] = NULL;
15008 }
15009
15010 /* Invoke the normal astFormat_ function to obtain a pointer to the
15011 required formatted value, adjusting the axis index to become
15012 zero-based. */
15013 fvalue = astFormat( this, axis - 1, value );
15014
15015 /* If OK, store a copy of the resulting string in dynamically allocated memory,
15016 putting a pointer to the copy into the next element of the "astformatid_strings"
15017 array. (This process also de-allocates any previously allocated memory pointed
15018 at by this "astformatid_strings" element, so the earlier string is effectively
15019 replaced by the new one.) */
15020 if ( astOK ) {
15021 astBeginPM;
15022 astformatid_strings[ astformatid_istr ] = astStore( astformatid_strings[ astformatid_istr ], fvalue,
15023 strlen( fvalue ) + (size_t) 1 );
15024 astEndPM;
15025
15026 /* If OK, return a pointer to the copy and increment "astformatid_istr" to use
15027 the next element of "astformatid_strings" on the next invocation. Recycle
15028 "astformatid_istr" to zero when all elements have been used. */
15029 if ( astOK ) {
15030 result = astformatid_strings[ astformatid_istr++ ];
15031 if ( astformatid_istr == ( ASTFORMATID_MAX_STRINGS - 1 ) ) astformatid_istr = 0;
15032 }
15033 }
15034
15035 /* Return the result. */
15036 return result;
15037
15038 }
15039
astFrameId_(int naxes,const char * options,...)15040 AstFrame *astFrameId_( int naxes, const char *options, ... ) {
15041 /*
15042 *++
15043 * Name:
15044 c astFrame
15045 f AST_FRAME
15046
15047 * Purpose:
15048 * Create a Frame.
15049
15050 * Type:
15051 * Public function.
15052
15053 * Synopsis:
15054 c #include "frame.h"
15055 c AstFrame *astFrame( int naxes, const char *options, ... )
15056 f RESULT = AST_FRAME( NAXES, OPTIONS, STATUS )
15057
15058 * Class Membership:
15059 * Frame constructor.
15060
15061 * Description:
15062 * This function creates a new Frame and optionally initialises its
15063 * attributes.
15064 *
15065 * A Frame is used to represent a coordinate system. It does this
15066 * in rather the same way that a frame around a graph describes the
15067 * coordinate space in which data are plotted. Consequently, a
15068 * Frame has a Title (string) attribute, which describes the
15069 * coordinate space, and contains axes which in turn hold
15070 * information such as Label and Units strings which are used for
15071 * labelling (e.g.) graphical output. In general, however, the
15072 * number of axes is not restricted to two.
15073 *
15074 * Functions are available for converting Frame coordinate values
15075 * into a form suitable for display, and also for calculating
15076 * distances and offsets between positions within the Frame.
15077 *
15078 * Frames may also contain knowledge of how to transform to and
15079 * from related coordinate systems.
15080
15081 * Parameters:
15082 c naxes
15083 f NAXES = INTEGER (Given)
15084 * The number of Frame axes (i.e. the number of dimensions of
15085 * the coordinate space which the Frame describes).
15086 c options
15087 f OPTIONS = CHARACTER * ( * ) (Given)
15088 c Pointer to a null-terminated string containing an optional
15089 c comma-separated list of attribute assignments to be used for
15090 c initialising the new Frame. The syntax used is identical to
15091 c that for the astSet function and may include "printf" format
15092 c specifiers identified by "%" symbols in the normal way.
15093 c If no initialisation is required, a zero-length string may be
15094 c supplied.
15095 f A character string containing an optional comma-separated
15096 f list of attribute assignments to be used for initialising the
15097 f new Frame. The syntax used is identical to that for the
15098 f AST_SET routine. If no initialisation is required, a blank
15099 f value may be supplied.
15100 c ...
15101 c If the "options" string contains "%" format specifiers, then
15102 c an optional list of additional arguments may follow it in
15103 c order to supply values to be substituted for these
15104 c specifiers. The rules for supplying these are identical to
15105 c those for the astSet function (and for the C "printf"
15106 c function).
15107 f STATUS = INTEGER (Given and Returned)
15108 f The global status.
15109
15110 * Returned Value:
15111 c astFrame()
15112 f AST_FRAME = INTEGER
15113 * A pointer to the new Frame.
15114
15115 * Examples:
15116 c frame = astFrame( 2, "Title=Energy Spectrum: Plot %d", n );
15117 c Creates a new 2-dimensional Frame and initialises its Title
15118 c attribute to the string "Energy Spectrum: Plot <n>", where
15119 c <n> takes the value of the int variable "n".
15120 c frame = astFrame( 2, "Label(1)=Energy, Label(2)=Response" );
15121 c Creates a new 2-dimensional Frame and initialises its axis
15122 c Label attributes to suitable string values.
15123 f FRAME = AST_FRAME( 2, 'Title=Energy Spectrum', STATUS );
15124 f Creates a new 2-dimensional Frame and initialises its Title
15125 f attribute to the string "Energy Spectrum".
15126 f FRAME = AST_FRAME( 2, 'Label(1)=Energy, Label(2)=Response', STATUS );
15127 f Creates a new 2-dimensional Frame and initialises its axis
15128 f Label attributes to suitable string values.
15129
15130 * Notes:
15131 * - A null Object pointer (AST__NULL) will be returned if this
15132 c function is invoked with the AST error status set, or if it
15133 f function is invoked with STATUS set to an error value, or if it
15134 * should fail for any reason.
15135 *--
15136
15137 * Implementation Notes:
15138 * - This function implements the external (public) interface to
15139 * the astFrame constructor function. It returns an ID value
15140 * (instead of a true C pointer) to external users, and must be
15141 * provided because astFrame_ has a variable argument list which
15142 * cannot be encapsulated in a macro (where this conversion would
15143 * otherwise occur).
15144 * - The variable argument list also prevents this function from
15145 * invoking astFrame_ directly, so it must be a re-implementation
15146 * of it in all respects, except for the final conversion of the
15147 * result to an ID value.
15148 */
15149
15150 /* Local Variables: */
15151 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
15152 AstFrame *new; /* Pointer to new Frame */
15153 va_list args; /* Variable argument list */
15154
15155 int *status; /* Pointer to inherited status value */
15156
15157 /* Get a pointer to the inherited status value. */
15158 status = astGetStatusPtr;
15159
15160 /* Get a pointer to the thread specific global data structure. */
15161 astGET_GLOBALS(NULL);
15162
15163 /* Check the global error status. */
15164 if ( !astOK ) return NULL;
15165
15166 /* Initialise the Frame, allocating memory and initialising the virtual
15167 function table as well if necessary. */
15168 new = astInitFrame( NULL, sizeof( AstFrame ), !class_init, &class_vtab,
15169 "Frame", naxes );
15170
15171 /* If successful, note that the virtual function table has been initialised. */
15172 if ( astOK ) {
15173 class_init = 1;
15174
15175 /* Obtain the variable argument list and pass it along with the options string
15176 to the astVSet method to initialise the new Frame's attributes. */
15177 va_start( args, options );
15178 astVSet( new, options, NULL, args );
15179 va_end( args );
15180
15181 /* If an error occurred, clean up by deleting the new object. */
15182 if ( !astOK ) new = astDelete( new );
15183 }
15184
15185 /* Return an ID value for the new Frame. */
15186 return astMakeId( new );
15187 }
15188
astPermAxesId_(AstFrame * this,const int perm[],int * status)15189 void astPermAxesId_( AstFrame *this, const int perm[], int *status ) {
15190 /*
15191 *++
15192 * Name:
15193 c astPermAxes
15194 f AST_PERMAXES
15195
15196 * Purpose:
15197 * Permute the axis order in a Frame.
15198
15199 * Type:
15200 * Public virtual function.
15201
15202 * Synopsis:
15203 c #include "frame.h"
15204 c void astPermAxes( AstFrame *this, const int perm[] )
15205 f CALL AST_PERMAXES( THIS, PERM, STATUS )
15206
15207 * Class Membership:
15208 * Frame method.
15209
15210 * Description:
15211 c This function permutes the order in which a Frame's axes occur.
15212 f This routine permutes the order in which a Frame's axes occur.
15213
15214 * Parameters:
15215 c this
15216 f THIS = INTEGER (Given)
15217 * Pointer to the Frame.
15218 c perm
15219 f PERM( * ) = INTEGER (Given)
15220 * An array with one element for each axis of the Frame (Naxes
15221 * attribute). This should list the axes in their new order,
15222 * using the original axis numbering (which starts at 1 for the
15223 * first axis).
15224 f STATUS = INTEGER (Given and Returned)
15225 f The global status.
15226
15227 * Notes:
15228 * - Only genuine permutations of the axis order are permitted, so
15229 c each axis must be referenced exactly once in the "perm" array.
15230 f each axis must be referenced exactly once in the PERM array.
15231 * - If successive axis permutations are applied to a Frame, then
15232 * the effects are cumulative.
15233 *--
15234
15235 * Implementation Notes:
15236 * This function implements the public interface for the
15237 * astPermAxes method. It is identical to astPermAxes_ except that
15238 * the axis numbers in the "perm" array are decremented by 1 before
15239 * use. This is to allow the public interface to use one-based axis
15240 * numbering (internally, zero-based axis numbering is used).
15241 */
15242
15243 /* Local Variables: */
15244 int *perm1; /* Pointer to modified perm array */
15245 int axis; /* Loop counter for Frame axes */
15246 int naxes; /* Number of Frame axes */
15247
15248 /* Check the global error status. */
15249 if ( !astOK ) return;
15250
15251 /* Obtain the number of Frame axes. */
15252 naxes = astGetNaxes( this );
15253
15254 /* Allocate an array to hold a modified version of the "perm"
15255 array. */
15256 perm1 = astMalloc( sizeof( int ) * (size_t) naxes );
15257 if ( astOK ) {
15258
15259 /* Make a modified copy of the "perm" array by subtracting one from
15260 each element. This allows the public interface to use one-based
15261 axis numbering, whereas all internal code is zero-based. */
15262 for ( axis = 0; axis < naxes; axis++ ) perm1[ axis ] = perm[ axis ] - 1;
15263
15264 /* Invoke the normal astPermAxes_ function to permute the Frame's axes. */
15265 astPermAxes( this, perm1 );
15266 }
15267
15268 /* Free the temporary array. */
15269 perm1 = astFree( perm1 );
15270 }
15271
astPickAxesId_(AstFrame * this,int naxes,const int axes[],AstMapping ** map,int * status)15272 AstFrame *astPickAxesId_( AstFrame *this, int naxes, const int axes[],
15273 AstMapping **map, int *status ) {
15274 /*
15275 *++
15276 * Name:
15277 c astPickAxes
15278 f AST_PICKAXES
15279
15280 * Purpose:
15281 * Create a new Frame by picking axes from an existing one.
15282
15283 * Type:
15284 * Public virtual function.
15285
15286 * Synopsis:
15287 c #include "frame.h"
15288 c AstFrame *astPickAxes( AstFrame *this, int naxes, const int axes[],
15289 c AstMapping **map )
15290 f RESULT = AST_PICKAXES( THIS, NAXES, AXES, MAP, STATUS )
15291
15292 * Class Membership:
15293 * Frame method.
15294
15295 * Description:
15296 * This function creates a new Frame whose axes are copied from an
15297 * existing Frame along with other Frame attributes, such as its
15298 * Title. Any number (zero or more) of the original Frame's axes
15299 * may be copied, in any order, and additional axes with default
15300 * attributes may also be included in the new Frame.
15301 *
15302 c Optionally, a Mapping that converts between the coordinate
15303 f A Mapping that converts between the coordinate
15304 * systems described by the two Frames will also be returned.
15305
15306 * Parameters:
15307 c this
15308 f THIS = INTEGER (Given)
15309 * Pointer to the original Frame.
15310 c naxes
15311 f NAXES = INTEGER (Given)
15312 * The number of axes required in the new Frame.
15313 c axes
15314 f AXES( NAXES ) = INTEGER (Given)
15315 c An array, with "naxes" elements, which lists the axes to be
15316 f An array which lists the axes to be
15317 * copied. These should be given in the order required in the
15318 * new Frame, using the axis numbering in the original Frame
15319 * (which starts at 1 for the first axis). Axes may be selected
15320 * in any order, but each may only be used once. If additional
15321 * (default) axes are also to be included, the corresponding
15322 * elements of this array should be set to zero.
15323 c map
15324 f MAP = INTEGER (Returned)
15325 c Address of a location in which to return a pointer to a new
15326 f A pointer to a new
15327 * Mapping. This will be a PermMap (or a UnitMap as a special
15328 * case) that describes the axis permutation that has taken
15329 * place between the original and new Frames. The Mapping's
15330 * forward transformation will convert coordinates from the
15331 * original Frame into the new one, and vice versa.
15332 c
15333 c If this Mapping is not required, a NULL value may be supplied
15334 c for this parameter.
15335 f STATUS = INTEGER (Given and Returned)
15336 f The global status.
15337
15338 * Returned Value:
15339 c astPickAxes()
15340 f AST_PICKAXES = INTEGER
15341 * A pointer to the new Frame.
15342
15343 * Applicability:
15344 * Frame
15345 * This function applies to all Frames. The class of Frame returned
15346 * may differ from that of the original Frame, depending on which
15347 * axes are selected. For example, if a single axis is picked from a
15348 * SkyFrame (which must always have two axes) then the resulting
15349 * Frame cannot be a valid SkyFrame, so will revert to the parent
15350 * class (Frame) instead.
15351 * FrameSet
15352 * Using this function on a FrameSet is identical to using it on
15353 * the current Frame in the FrameSet. The returned Frame will not
15354 * be a FrameSet.
15355 * Region
15356 * If this function is used on a Region, an attempt is made to
15357 * retain the bounds information on the selected axes. If
15358 * succesful, the returned Frame will be a Region of some class.
15359 * Otherwise, the returned Frame is obtained by calling this
15360 * function on the Frame represented by the supplied Region (the
15361 * returned Frame will then not be a Region). In order to be
15362 * succesful, the selected axes in the Region must be independent
15363 * of the others. For instance, a Box can be split in this way but
15364 * a Circle cannot. Another requirement for success is that no
15365 * default axes are added (that is, the
15366 c "axes"
15367 f AXES
15368 * array must not contain any zero values.
15369
15370 * Notes:
15371 c - The new Frame will contain a "deep" copy (c.f. astCopy) of all
15372 f - The new Frame will contain a "deep" copy (c.f. AST_COPY) of all
15373 * the data selected from the original Frame. Modifying any aspect
15374 * of the new Frame will therefore not affect the original one.
15375 * - A null Object pointer (AST__NULL) will be returned if this
15376 c function is invoked with the AST error status set, or if it
15377 f function is invoked with STATUS set to an error value, or if it
15378 * should fail for any reason.
15379 *--
15380
15381 * Implementation Notes:
15382 * This function implements the public interface for the
15383 * astPickAxes method. It is identical to astPickAxes_ except for
15384 * the following:
15385 *
15386 * - The axis numbers in the "axes" array are decremented by 1 before
15387 * use. This is to allow the public interface to use one-based axis
15388 * numbering (internally, zero-based axis numbering is used).
15389 *
15390 * - An ID value is returned via the "map" parameter (if used)
15391 * instead of a true C pointer. This is required because this
15392 * conversion cannot be performed by the macro that invokes the
15393 * function.
15394 */
15395
15396 /* Local Variables: */
15397 AstFrame *result; /* Pointer to result Frame */
15398 int *axes1; /* Pointer to modified axes array */
15399 int axis; /* Loop counter for axes */
15400
15401 /* Initialise. */
15402 result = NULL;
15403
15404 /* Check the global error status. */
15405 if ( !astOK ) return result;
15406
15407 /* Allocate an array to hold a modified version of the "axes" array
15408 (check that "naxes" is valid first - if not, this error will be
15409 reported by astPickAxes_ below). */
15410 axes1 = ( naxes >= 0 ) ? astMalloc( sizeof( int ) * (size_t) naxes ) :
15411 NULL;
15412 if ( astOK ) {
15413
15414 /* Make a modified copy of the "axes" array by subtracting one from
15415 each element. This allows the public interface to use one-based
15416 axis numbering, whereas all internal code is zero-based. */
15417 for ( axis = 0; axis < naxes; axis++ ) axes1[ axis ] = axes[ axis ] - 1;
15418
15419 /* Invoke the normal astPickAxes_ function to select the required axes. */
15420 result = astPickAxes( this, naxes, axes1, map );
15421 }
15422
15423 /* Free the temporary array. */
15424 axes1 = astFree( axes1 );
15425
15426 /* If required, return an ID value for the Mapping. */
15427 if ( map ) *map = astMakeId( *map );
15428
15429 /* Return the result. */
15430 return result;
15431 }
15432
astUnformatId_(AstFrame * this,int axis,const char * string,double * value,int * status)15433 int astUnformatId_( AstFrame *this, int axis, const char *string,
15434 double *value, int *status ) {
15435 /*
15436 *++
15437 * Name:
15438 c astUnformat
15439 f AST_UNFORMAT
15440
15441 * Purpose:
15442 * Read a formatted coordinate value for a Frame axis.
15443
15444 * Type:
15445 * Public virtual function.
15446
15447 * Synopsis:
15448 c #include "frame.h"
15449 c int astUnformat( AstFrame *this, int axis, const char *string,
15450 c double *value )
15451 f RESULT = AST_UNFORMAT( THIS, AXIS, STRING, VALUE, STATUS )
15452
15453 * Class Membership:
15454 * Frame method.
15455
15456 * Description:
15457 c This function reads a formatted coordinate value (given as a
15458 c character string) for a Frame axis and returns the equivalent
15459 c numerical (double) value. It also returns the number of
15460 c characters read from the string.
15461 f This function reads a formatted coordinate value (given as a
15462 f character string) for a Frame axis and returns the equivalent
15463 f numerical (double precision) value. It also returns the number
15464 f of characters read from the string.
15465 *
15466 c The principle use of this function is in decoding user-supplied
15467 c input which contains formatted coordinate values. Free-format
15468 c input is supported as far as possible. If input is ambiguous, it
15469 c is interpreted with reference to the Frame's attributes (in
15470 c particular, the Format string associated with the Frame's
15471 c axis). This function is, in essence, the inverse of astFormat.
15472 f The principle use of this function is in decoding user-supplied
15473 f input which contains formatted coordinate values. Free-format
15474 f input is supported as far as possible. If input is ambiguous, it
15475 f is interpreted with reference to the Frame's attributes (in
15476 f particular, the Format string associated with the Frame's
15477 f axis). This function is, in essence, the inverse of AST_FORMAT.
15478
15479 * Parameters:
15480 c this
15481 f THIS = INTEGER (Given)
15482 * Pointer to the Frame.
15483 c axis
15484 f AXIS = INTEGER (Given)
15485 * The number of the Frame axis for which a coordinate value is to
15486 * be read (axis numbering starts at 1 for the first axis).
15487 c string
15488 f STRING = CHARACTER * ( * ) (Given)
15489 c Pointer to a null-terminated character string containing the
15490 c formatted coordinate value.
15491 f A character string containing the formatted coordinate value.
15492 * This string may contain additional information following the
15493 * value to be read, in which case reading stops at the first
15494 * character which cannot be interpreted as part of the value.
15495 * Any white space before or after the value is discarded.
15496 c value
15497 f VALUE = DOUBLE PRECISION (Returned)
15498 c Pointer to a double in which the coordinate value read will be
15499 c returned.
15500 f The coordinate value read.
15501 f STATUS = INTEGER (Given and Returned)
15502 f The global status.
15503
15504 * Returned Value:
15505 c astUnformat()
15506 f AST_UNFORMAT = INTEGER
15507 * The number of characters read from the string in order to
15508 * obtain the coordinate value. This will include any white
15509 * space which occurs before or after the value.
15510
15511 * Applicability:
15512 * Frame
15513 * This function applies to all Frames. See the "Frame Input
15514 * Format" section below for details of the input formats
15515 * accepted by a basic Frame.
15516 * SkyFrame
15517 * The SkyFrame class re-defines the input format to be suitable
15518 * for representing angles and times, with the resulting
15519 * coordinate value returned in radians. See the "SkyFrame
15520 * Input Format" section below for details of the formats
15521 * accepted.
15522 * FrameSet
15523 * The input formats accepted by a FrameSet are determined by
15524 * its current Frame (as specified by the Current attribute).
15525
15526 * Frame Input Format
15527 * The input format accepted for a basic Frame axis is as follows:
15528 * - An optional sign, followed by:
15529 * - A sequence of one or more digits possibly containing a decimal point,
15530 * followed by:
15531 * - An optional exponent field.
15532 * - The exponent field, if present, consists of "E" or "e"
15533 * followed by a possibly signed integer.
15534 *
15535 * Examples of acceptable Frame input formats include:
15536 * - 99
15537 * - 1.25
15538 * - -1.6
15539 * - 1E8
15540 * - -.99e-17
15541 * - <bad>
15542
15543 * SkyFrame Input Format
15544 * The input format accepted for a SkyFrame axis is as follows:
15545 * - An optional sign, followed by between one and three fields
15546 * representing either degrees, arc-minutes, arc-seconds or hours,
15547 * minutes, seconds (e.g. "-12 42 03").
15548 * - Each field should consist of a sequence of one or more digits,
15549 * which may include leading zeros. At most one field may contain a
15550 * decimal point, in which case it is taken to be the final field
15551 * (e.g. decimal degrees might be given as "124.707", while degrees
15552 * and decimal arc-minutes might be given as "-13 33.8").
15553 * - The first field given may take any value, allowing angles and
15554 * times outside the conventional ranges to be
15555 * represented. However, subsequent fields must have values of less
15556 * than 60 (e.g. "720 45 31" is valid, whereas "11 45 61" is not).
15557 * - Fields may be separated by white space or by ":" (colon), but
15558 * the choice of separator must be used consistently throughout the
15559 * value. Additional white space may be present around fields and
15560 * separators (e.g. "- 2: 04 : 7.1").
15561 * - The following field identification characters may be used as
15562 * separators to replace either of those above (or may be appended
15563 * to the final field), in order to identify the field to which
15564 * they are appended: "d"---degrees; "h"---hours; "m"---minutes of
15565 * arc or time; "s"---seconds of arc or time; "'" (single
15566 * quote)---minutes of arc; """ (double quote)---seconds of arc.
15567 * Either lower or upper case may be used. Fields must be given in
15568 * order of decreasing significance (e.g. "-11D 3' 14.4"" or
15569 * "22h14m11.2s").
15570 * - The presence of any of the field identification characters
15571 * "d", "'" (single quote) or """ (double quote) indicates that the
15572 * value is to be interpreted as an angle. Conversely, the presence
15573 * of "h" indicates that it is to be interpreted as a time (with 24
15574 * hours corresponding to 360 degrees). Incompatible angle/time
15575 * identification characters may not be mixed (e.g. "10h14'3"" is
15576 * not valid). The remaining field identification characters and
15577 * separators do not specify a preference for an angle or a time
15578 * and may be used with either.
15579 c - If no preference for an angle or a time is expressed anywhere
15580 c within the value, it is interpreted as an angle if the Format
15581 c attribute string associated with the SkyFrame axis generates an
15582 c angle and as a time otherwise. This ensures that values produced
15583 c by astFormat are correctly interpreted by astUnformat.
15584 f - If no preference for an angle or a time is expressed anywhere
15585 f within the value, it is interpreted as an angle if the Format
15586 f attribute string associated with the SkyFrame axis generates an
15587 f angle and as a time otherwise. This ensures that values produced
15588 f by AST_FORMAT are correctly interpreted by AST_UNFORMAT.
15589 * - Fields may be omitted, in which case they default to zero. The
15590 * remaining fields may be identified by using appropriate field
15591 * identification characters (see above) and/or by adding extra
15592 * colon separators (e.g. "-05m13s" is equivalent to "-:05:13"). If
15593 * a field is not identified explicitly, it is assumed that
15594 * adjacent fields have been given, after taking account of any
15595 * extra separator characters (e.g. "14:25.4s" specifies minutes
15596 * and seconds, while "14::25.4s" specifies degrees and seconds).
15597 c - If fields are omitted in such a way that the remaining ones
15598 c cannot be identified uniquely (e.g. "01:02"), then the first
15599 c field (either given explicitly or implied by an extra leading
15600 c colon separator) is taken to be the most significant field that
15601 c astFormat would produce when formatting a value (using the
15602 c Format attribute associated with the SkyFrame axis). By
15603 c default, this means that the first field will normally be
15604 c interpreted as degrees or hours. However, if this does not
15605 c result in consistent field identification, then the last field
15606 c (either given explicitly or implied by an extra trailing colon
15607 c separator) is taken to to be the least significant field that
15608 c astFormat would produce.
15609 f - If fields are omitted in such a way that the remaining ones
15610 f cannot be identified uniquely (e.g. "01:02"), then the first
15611 f field (either given explicitly or implied by an extra leading
15612 f colon separator) is taken to be the most significant field that
15613 f AST_FORMAT would produce when formatting a value (using the
15614 f Format attribute associated with the SkyFrame axis). By
15615 f default, this means that the first field will normally be
15616 f interpreted as degrees or hours. However, if this does not
15617 f result in consistent field identification, then the last field
15618 f (either given explicitly or implied by an extra trailing colon
15619 f separator) is taken to to be the least significant field that
15620 f AST_FORMAT would produce.
15621 *
15622 c This final convention is intended to ensure that values formatted
15623 c by astFormat which contain less than three fields will be
15624 c correctly interpreted if read back using astUnformat, even if
15625 c they do not contain field identification characters.
15626 f This final convention is intended to ensure that values formatted
15627 f by AST_FORMAT which contain less than three fields will be
15628 f correctly interpreted if read back using AST_UNFORMAT, even if
15629 f they do not contain field identification characters.
15630 *
15631 * Examples of acceptable SkyFrame input formats (with
15632 * interpretation in parentheses) include:
15633 * - -14d 13m 22.2s (-14d 13' 22.2")
15634 * - + 12:34:56.7 (12d 34' 56.7" or 12h 34m 56.7s)
15635 * - 001 : 02 : 03.4 (1d 02' 03.4" or 1h 02m 03.4s)
15636 * - 22h 30 (22h 30m 00s)
15637 * - 136::10" (136d 00' 10" or 136h 00m 10s)
15638 * - -14M 27S (-0d 14' 27" or -0h 14m 27s)
15639 * - -:14: (-0d 14' 00" or -0h 14m 00s)
15640 * - -::4.1 (-0d 00' 04.1" or -0h 00m 04.1s)
15641 * - .9" (0d 00' 00.9")
15642 * - d12m (0d 12' 00")
15643 * - H 12:22.3s (0h 12m 22.3s)
15644 * - <bad> (AST__BAD)
15645 *
15646 * Where alternative interpretations are shown, the choice of angle or
15647 * time depends on the associated Format(axis) attribute.
15648
15649 * Notes:
15650 * - A function value of zero (and no coordinate value) will be
15651 * returned, without error, if the string supplied does not contain
15652 * a suitably formatted value.
15653 c - Beware that it is possible for a formatting error part-way
15654 c through an input string to terminate input before it has been
15655 c completely read, but to yield a coordinate value that appears
15656 c valid. For example, if a user types "1.5r6" instead of "1.5e6",
15657 c the "r" will terminate input, giving an incorrect coordinate
15658 c value of 1.5. It is therefore most important to check the return
15659 c value of this function to ensure that the correct number of
15660 c characters have been read.
15661 f - Beware that it is possible for a formatting error part-way
15662 f through an input string to terminate input before it has been
15663 f completely read, but to yield a coordinate value that appears
15664 f valid. For example, if a user types "1.5R6" instead of "1.5E6",
15665 f the "R" will terminate input, giving an incorrect coordinate
15666 f value of 1.5. It is therefore most important to check the return
15667 f value of this function to ensure that the correct number of
15668 f characters have been read.
15669 * - An error will result if a value is read which appears to have
15670 * the correct format, but which cannot be converted into a valid
15671 * coordinate value (for instance, because the value of one or more
15672 * of its fields is invalid).
15673 * - The string "<bad>" is recognised as a special case and will
15674 * yield the coordinate value AST__BAD without error. The test for
15675 * this string is case-insensitive and also permits embedded white
15676 * space.
15677 c - A function result of zero will be returned and no coordinate
15678 c value will be returned via the "value" pointer if this function
15679 c is invoked with the AST error status set, or if it should fail
15680 c for any reason.
15681 f - A function result of zero will be returned and no coordinate
15682 f value will be returned via the VALUE argument if this function
15683 f is invoked with the AST error status set, or if it should fail
15684 f for any reason.
15685 *--
15686
15687 * Implementation Notes:
15688 * This function implements the public interface for the
15689 * astUnformat method. It is identical to astUnformat_ except that:
15690 *
15691 * - The axis index is decremented by 1 before use. This allows the
15692 * public interface to use 1-based axis numbers (whereas internally
15693 * axis numbers are zero-based).
15694 */
15695
15696 /* Invoke the normal astUnformat_ function, adjusting the axis index
15697 to become zero-based. */
15698 return astUnformat( this, axis - 1, string, value );
15699 }
15700
15701
15702
15703
15704
15705
15706
15707
15708
15709
15710
15711
15712
15713