1 /*
2 *class++
3 * Name:
4 * WcsMap
5
6 * Purpose:
7 * Implement a FITS-WCS sky projection.
8
9 * Constructor Function:
10 c astWcsMap
11 f AST_WCSMAP
12
13 * Description:
14 * This class is used to represent sky coordinate projections as
15 * described in the FITS world coordinate system (FITS-WCS) paper II
16 * "Representations of Celestial Coordinates in FITS" by M. Calabretta
17 * and E.W. Griesen. This paper defines a set of functions, or sky
18 * projections, which transform longitude-latitude pairs representing
19 * spherical celestial coordinates into corresponding pairs of Cartesian
20 * coordinates (and vice versa).
21 *
22 * A WcsMap is a specialised form of Mapping which implements these
23 * sky projections and applies them to a specified pair of coordinates.
24 * All the projections in the FITS-WCS paper are supported, plus the now
25 * deprecated "TAN with polynomial correction terms" projection which
26 * is refered to here by the code "TPN". Using the FITS-WCS terminology,
27 * the transformation is between "native spherical" and "projection
28 * plane" coordinates (also called "intermediate world coordinates".
29 * These coordinates may, optionally, be embedded in a space with more
30 * than two dimensions, the remaining coordinates being copied unchanged.
31 * Note, however, that for consistency with other AST facilities, a
32 * WcsMap handles coordinates that represent angles in radians (rather
33 * than the degrees used by FITS-WCS).
34 *
35 * The type of FITS-WCS projection to be used and the coordinates
36 * (axes) to which it applies are specified when a WcsMap is first
37 * created. The projection type may subsequently be determined
38 * using the WcsType attribute and the coordinates on which it acts
39 * may be determined using the WcsAxis(lonlat) attribute.
40 *
41 * Each WcsMap also allows up to 100 "projection parameters" to be
42 * associated with each axis. These specify the precise form of the
43 * projection, and are accessed using PVi_m attribute, where "i" is
44 * the integer axis index (starting at 1), and m is an integer
45 * "parameter index" in the range 0 to 99. The number of projection
46 * parameters required by each projection, and their meanings, are
47 * dependent upon the projection type (most projections either do not
48 * use any projection parameters, or use parameters 1 and 2 associated
49 * with the latitude axis). Before creating a WcsMap you should consult
50 * the FITS-WCS paper for details of which projection parameters are
51 * required, and which have defaults. When creating the WcsMap, you must
52 * explicitly set values for all those required projection parameters
53 * which do not have defaults defined in this paper.
54
55 * Inheritance:
56 * The WcsMap class inherits from the Mapping class.
57
58 * Attributes:
59 * In addition to those attributes common to all Mappings, every
60 * WcsMap also has the following attributes:
61 *
62 * - NatLat: Native latitude of the reference point of a FITS-WCS projection
63 * - NatLon: Native longitude of the reference point of a FITS-WCS projection
64 * - PVi_m: FITS-WCS projection parameters
65 * - PVMax: Maximum number of FITS-WCS projection parameters
66 * - WcsAxis(lonlat): FITS-WCS projection axes
67 * - WcsType: FITS-WCS projection type
68
69 * Functions:
70 c The WcsMap class does not define any new functions beyond those
71 f The WcsMap class does not define any new routines beyond those
72 * which are applicable to all Mappings.
73
74 * Copyright:
75 * Copyright (C) 1997-2006 Council for the Central Laboratory of the
76 * Research Councils
77
78 * Licence:
79 * This program is free software: you can redistribute it and/or
80 * modify it under the terms of the GNU Lesser General Public
81 * License as published by the Free Software Foundation, either
82 * version 3 of the License, or (at your option) any later
83 * version.
84 *
85 * This program is distributed in the hope that it will be useful,
86 * but WITHOUT ANY WARRANTY; without even the implied warranty of
87 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88 * GNU Lesser General Public License for more details.
89 *
90 * You should have received a copy of the GNU Lesser General
91 * License along with this program. If not, see
92 * <http://www.gnu.org/licenses/>.
93
94 * Authors:
95 * DSB: D.S. Berry (Starlink)
96 * RFWS: R.F. Warren-Smith (Starlink)
97
98 * History:
99 * 15-FEB-1996 (DSB):
100 * Original version.
101 * 23-MAR-1996 (DSB):
102 * Added support for PointSets with more than 2 axes.
103 * 14-NOV-1996 (DSB):
104 * Added I/O facilities, external interface, attributes, etc.
105 * 16-JAN-1997 (DSB):
106 * Allowed WCSBAD as a projection type in astWcsMap.
107 * 24-APR-1997 (RFWS):
108 * Tidied prologues.
109 * 26-SEP-1997 (DSB):
110 * o Long descriptions of projections changed to include a textual
111 * description as well as the three letter acronym.
112 * o Added protected function astPrjDesc.
113 * o String values now used instead of integers to represent
114 * "choice" attributes externally (eg WcsType).
115 * 8-APR-1998 (DSB):
116 * Modified MapMerge so that a WcsMap can merge with its own
117 * inverse when astSimplify is used.
118 * 20-APR-1998 (DSB):
119 * Modified MapMerge to avoid the possibility of returning an
120 * empty mappings list.
121 * 4-SEP-1998 (DSB):
122 * Changed MapMerge to allow WcsMaps to swap with PermMaps in
123 * order to bring mergable WcsMaps closer together.
124 * 5-MAY-1999 (DSB):
125 * More corrections to MapMerge: Cleared up errors in the use of the
126 * supplied invert flags, and corrected logic for deciding which
127 * neighbouring Mapping to swap with.
128 * 12-JUL-1999 (DSB):
129 * - Report an error if too many or two few projection parameters are
130 * supplied in a WcsMap.
131 * - Corrected MapMerge to prevent unset projection parameters
132 * being copied to any new WcsMaps.
133 * - Correct handling of invert flags in WcsPerm.
134 * 16-JUL-1999 (DSB):
135 * Fixed memory leak in MapMerge.
136 * 11-FEB-2000 (DSB):
137 * Added PVj_m attributes. Attributes ProjP(0) to ProjP(9) are now
138 * aliases for PV(axlat)_0 to PV(axlat)_9. Renamed GLS projection
139 * as SFL (GLS retained as alias for SFL).
140 * 10-AUG-2000 (DSB):
141 * MapMerge no longer simplifies a CAR projection. Previously they
142 * were replaced by a UnitMap, but this removed the cylic nature of
143 * the mapping (i.e. 2.PI == 0 ).
144 * 6-OCT-2000 (DSB):
145 * Ignore leading and trailing spaces in astWCsPrjType (some
146 * CTYPE FITS keywords have appeared with trailing white space).
147 * 26-SEP-2001 (DSB):
148 * Changed names of all functions and structure to avoid name clashes
149 * with wcslib.
150 * 10-OCT-2002 (DSB):
151 * Added astIsZenithal.
152 * 22-OCT-2002 (DSB):
153 * - GetPV now returns the FITS default value instead of AST__BAD
154 * if a defaultable latitude projection parameter has not been set.
155 * - A number of changes needed to support WcsLib v2.9.
156 * - Added AST__TPN projection.
157 * 8-JAN-2003 (DSB):
158 * Changed private InitVtab method to protected astInitWcsMapVtab
159 * method.
160 * 4-JUN-2003 (DSB):
161 * - Added attribute "NatLon".
162 * - Changed to allow a user-specified fiducial point to be stored
163 * in projection parameter PVi_1 and PVi_2 for the longitude axis.
164 * - Changed "PVj_m" to "PVi_m" for consistency with FITS-WCS paper II.
165 * 18-AUG-2003 (DSB):
166 * In function Map, assign zero longitude to output positions which
167 * are very close to a pole.
168 * 23-SEP-2003 (DSB):
169 * - Changed so that the NatLat and NatLon attributes refer to the
170 * fixed values for the projections defined in FITS-WCS paper II, rather
171 * than the user-defined values stored in projection parameter PVi_1 and
172 * PVi_2 for the longitude axis.
173 * 11-FEB-2004 (DSB):
174 * Corrected axis numbering when reporting missing keywords in
175 * Transform.
176 * 23-APR-2004 (DSB):
177 * Changes to simplification algorithm.
178 * 1-SEP-2004 (DSB):
179 * CopyPV rewritten to avoid assumption that the input and output
180 * WcsMaps have the same number of axes and that the lon/lat axes have
181 * the same indices.
182 * 7-DEC-2005 (DSB):
183 * Free memory allocated by calls to astReadString.
184 * 14-FEB-2006 (DSB):
185 * Override astGetObjSize.
186 * 15-FEB-2006 (DSB):
187 * Use dynamic rather than static memory for the parameter arrays in
188 * the AstPrjPrm structure.Override astGetObjSize. This is to
189 * reduce the in-memory size of a WcsMap.
190 * 10-MAY-2006 (DSB):
191 * Override astEqual.
192 * 10-AUG-2006 (DSB):
193 * Correct astLoadWcsMap to take acount of the different number of
194 * PVi_m values that can be associated with each axis.
195 * 4-JAN-2007 (DSB):
196 * Correct astLoadWcsMap to load the projection parameter with
197 * highest index correctly.
198 * 23-FEB-2007 (DSB):
199 * Added HPX projection.
200 * 1-MAR-2011 (DSB):
201 * In function Map, do not allow valid longitude range to include both
202 * the high limit and the low limt (since they are both the same point on
203 * the sky).
204 * 7-MAR-2011 (DSB):
205 * In function Map, only do the longitude check if the projection
206 * is not cyclic.
207 * 24-MAY-2011 (DSB):
208 * Added protected FITSProj and TPNTan attributes (they should be
209 * removed when the PolyMap class has an iterative inverse).
210 * 6-MAR-2014 (DSB):
211 * Revert the change made on 18-AUG-2003 since setting the
212 * longitude arbitrarily to zero for points close to the pole
213 * causes significant round trip errors when doing pixel->sky->pixel
214 * transformation for points very close to the pole, if the pixel
215 * size is very small. The longitude at the pole is indeterminate,
216 * but whatever random numerical value is returned by atan2 is
217 * no less useful (and no more useful) than a fixed value of zero.
218 * 12-JUN-2014 (DSB):
219 * Added XPH projection.
220 *class--
221 */
222
223 /* Module Macros. */
224 /* ============== */
225 /* Set the name of the class we are implementing. This indicates to
226 the header files that define class interfaces that they should make
227 "protected" symbols available. */
228 #define astCLASS WcsMap
229
230 /* Macros which return the maximum and minimum of two values. */
231 #define MAX(aa,bb) ((aa)>(bb)?(aa):(bb))
232 #define MIN(aa,bb) ((aa)<(bb)?(aa):(bb))
233
234 /* Macros to check for equality of floating point values. We cannot
235 compare bad values directory because of the danger of floating point
236 exceptions, so bad values are dealt with explicitly. */
237 #define EQUAL(aa,bb) (((aa)==AST__BAD)?(((bb)==AST__BAD)?1:0):(((bb)==AST__BAD)?0:(fabs((aa)-(bb))<=1.0E5*MAX((fabs(aa)+fabs(bb))*DBL_EPSILON,DBL_MIN))))
238
239 /*
240 *
241 * Name:
242 * MAKE_CLEAR
243
244 * Purpose:
245 * Implement a method to clear a single value in a multi-valued attribute.
246
247 * Type:
248 * Private macro.
249
250 * Synopsis:
251 * #include "wcsmap.h"
252 * MAKE_CLEAR(attr,component,assign,nval)
253
254 * Class Membership:
255 * Defined by the WcsMap class.
256
257 * Description:
258 * This macro expands to an implementation of a private member function of
259 * the form:
260 *
261 * static void Clear<Attribute>( AstWcsMap *this, int axis )
262 *
263 * and an external interface function of the form:
264 *
265 * void astClear<Attribute>_( AstWcsMap *this, int axis )
266 *
267 * which implement a method for clearing a single value in a specified
268 * multi-valued attribute for an axis of a WcsMap.
269
270 * Parameters:
271 * attr
272 * The name of the attribute to be cleared, as it appears in the function
273 * name (e.g. Label in "astClearLabelAt").
274 * component
275 * The name of the class structure component that holds the attribute
276 * value.
277 * assign
278 * An expression that evaluates to the value to assign to the component
279 * to clear its value. The variable "axis" can be used to refer to
280 * the zero-based index of the attribute component being cleared.
281 * nval
282 * Specifies the number of values in the multi-valued attribute. The
283 * "axis" values supplied to the created function should be in the
284 * range zero to (nval - 1).
285
286 * Notes:
287 * - To avoid problems with some compilers, you should not leave any white
288 * space around the macro arguments.
289 *
290 */
291
292 /* Define the macro. */
293 #define MAKE_CLEAR(attr,component,assign,nval) \
294 \
295 /* Private member function. */ \
296 /* ------------------------ */ \
297 static void Clear##attr( AstWcsMap *this, int axis, int *status ) { \
298 \
299 /* Check the global error status. */ \
300 if ( !astOK ) return; \
301 \
302 /* Validate the axis index. */ \
303 if( axis < 0 || axis >= nval ){ \
304 astError( AST__AXIIN, "%s(%s): Index (%d) is invalid for attribute " \
305 #attr " - it should be in the range 1 to %d.", status, \
306 "astClear" #attr, astGetClass( this ), \
307 axis + 1, nval ); \
308 \
309 /* Assign the "clear" value. */ \
310 } else { \
311 this->component[ axis ] = (assign); \
312 } \
313 } \
314 \
315 /* External interface. */ \
316 /* ------------------- */ \
317 void astClear##attr##_( AstWcsMap *this, int axis, int *status ) { \
318 \
319 /* Check the global error status. */ \
320 if ( !astOK ) return; \
321 \
322 /* Invoke the required method via the virtual function table. */ \
323 (**astMEMBER(this,WcsMap,Clear##attr))( this, axis, status ); \
324 }
325
326
327 /*
328 *
329 * Name:
330 * MAKE_GET
331
332 * Purpose:
333 * Implement a method to get a single value in a multi-valued attribute.
334
335 * Type:
336 * Private macro.
337
338 * Synopsis:
339 * #include "wcsmap.h"
340 * MAKE_GET(attr,type,bad_value,assign,nval)
341
342 * Class Membership:
343 * Defined by the WcsMap class.
344
345 * Description:
346 * This macro expands to an implementation of a private member function of
347 * the form:
348 *
349 * static <Type> Get<Attribute>( AstWcsMap *this, int axis )
350 *
351 * and an external interface function of the form:
352 *
353 * <Type> astGet<Attribute>_( AstWcsMap *this, int axis )
354 *
355 * which implement a method for getting a single value from a specified
356 * multi-valued attribute for an axis of a WcsMap.
357
358 * Parameters:
359 * attr
360 * The name of the attribute whose value is to be obtained, as it
361 * appears in the function name (e.g. Label in "astGetLabel").
362 * type
363 * The C type of the attribute.
364 * bad_value
365 * A constant value to return if the global error status is set, or if
366 * the function fails.
367 * assign
368 * An expression that evaluates to the value to be returned. This can
369 * use the string "axis" to represent the zero-based value index.
370 * nval
371 * Specifies the number of values in the multi-valued attribute. The
372 * "axis" values supplied to the created function should be in the
373 * range zero to (nval - 1).
374
375 * Notes:
376 * - To avoid problems with some compilers, you should not leave any white
377 * space around the macro arguments.
378 *
379 */
380
381 /* Define the macro. */
382 #define MAKE_GET(attr,type,bad_value,assign,nval) \
383 \
384 /* Private member function. */ \
385 /* ------------------------ */ \
386 static type Get##attr( AstWcsMap *this, int axis, int *status ) { \
387 type result; /* Result to be returned */ \
388 \
389 /* Initialise */ \
390 result = (bad_value); \
391 \
392 /* Check the global error status. */ \
393 if ( !astOK ) return result; \
394 \
395 /* Validate the axis index. */ \
396 if( axis < 0 || axis >= nval ){ \
397 astError( AST__AXIIN, "%s(%s): Index (%d) is invalid for attribute " \
398 #attr " - it should be in the range 1 to %d.", status, \
399 "astGet" #attr, astGetClass( this ), \
400 axis + 1, nval ); \
401 \
402 /* Assign the result value. */ \
403 } else { \
404 result = (assign); \
405 } \
406 \
407 /* Check for errors and clear the result if necessary. */ \
408 if ( !astOK ) result = (bad_value); \
409 \
410 /* Return the result. */ \
411 return result; \
412 } \
413 /* External interface. */ \
414 /* ------------------- */ \
415 type astGet##attr##_( AstWcsMap *this, int axis, int *status ) { \
416 \
417 /* Check the global error status. */ \
418 if ( !astOK ) return (bad_value); \
419 \
420 /* Invoke the required method via the virtual function table. */ \
421 return (**astMEMBER(this,WcsMap,Get##attr))( this, axis, status ); \
422 }
423
424 /*
425 *
426 * Name:
427 * MAKE_SET
428
429 * Purpose:
430 * Implement a method to set a single value in a multi-valued attribute
431 * for a WcsMap.
432
433 * Type:
434 * Private macro.
435
436 * Synopsis:
437 * #include "wcsmap.h"
438 * MAKE_SET(attr,type,component,assign,nval)
439
440 * Class Membership:
441 * Defined by the WcsMap class.
442
443 * Description:
444 * This macro expands to an implementation of a private member function of
445 * the form:
446 *
447 * static void Set<Attribute>( AstWcsMap *this, int axis, <Type> value )
448 *
449 * and an external interface function of the form:
450 *
451 * void astSet<Attribute>_( AstWcsMap *this, int axis, <Type> value )
452 *
453 * which implement a method for setting a single value in a specified
454 * multi-valued attribute for a WcsMap.
455
456 * Parameters:
457 * attr
458 * The name of the attribute to be set, as it appears in the function
459 * name (e.g. Label in "astSetLabelAt").
460 * type
461 * The C type of the attribute.
462 * component
463 * The name of the class structure component that holds the attribute
464 * value.
465 * assign
466 * An expression that evaluates to the value to be assigned to the
467 * component.
468 * nval
469 * Specifies the number of values in the multi-valued attribute. The
470 * "axis" values supplied to the created function should be in the
471 * range zero to (nval - 1).
472
473 * Notes:
474 * - To avoid problems with some compilers, you should not leave any white
475 * space around the macro arguments.
476 *-
477 */
478
479 /* Define the macro. */
480 #define MAKE_SET(attr,type,component,assign,nval) \
481 \
482 /* Private member function. */ \
483 /* ------------------------ */ \
484 static void Set##attr( AstWcsMap *this, int axis, type value, int *status ) { \
485 \
486 /* Check the global error status. */ \
487 if ( !astOK ) return; \
488 \
489 /* Validate the axis index. */ \
490 if( axis < 0 || axis >= nval ){ \
491 astError( AST__AXIIN, "%s(%s): Index (%d) is invalid for attribute " \
492 #attr " - it should be in the range 1 to %d.", status, \
493 "astSet" #attr, astGetClass( this ), \
494 axis + 1, nval ); \
495 \
496 /* Store the new value in the structure component. */ \
497 } else { \
498 this->component[ axis ] = (assign); \
499 } \
500 } \
501 \
502 /* External interface. */ \
503 /* ------------------- */ \
504 void astSet##attr##_( AstWcsMap *this, int axis, type value, int *status ) { \
505 \
506 /* Check the global error status. */ \
507 if ( !astOK ) return; \
508 \
509 /* Invoke the required method via the virtual function table. */ \
510 (**astMEMBER(this,WcsMap,Set##attr))( this, axis, value, status ); \
511 }
512
513 /*
514 *
515 * Name:
516 * MAKE_TEST
517
518 * Purpose:
519 * Implement a method to test if a single value has been set in a
520 * multi-valued attribute for a class.
521
522 * Type:
523 * Private macro.
524
525 * Synopsis:
526 * #include "wcsmap.h"
527 * MAKE_TEST(attr,assign,nval)
528
529 * Class Membership:
530 * Defined by the WcsMap class.
531
532 * Description:
533 * This macro expands to an implementation of a private member function of
534 * the form:
535 *
536 * static int Test<Attribute>( AstWcsMap *this, int axis )
537 *
538 * and an external interface function of the form:
539 *
540 * int astTest<Attribute>_( AstWcsMap *this, int axis )
541 *
542 * which implement a method for testing if a single value in a specified
543 * multi-valued attribute has been set for a class.
544
545 * Parameters:
546 * attr
547 * The name of the attribute to be tested, as it appears in the function
548 * name (e.g. Label in "astTestLabelAt").
549 * assign
550 * An expression that evaluates to 0 or 1, to be used as the returned
551 * value. This can use the string "axis" to represent the zero-based
552 * index of the value within the attribute.
553 * nval
554 * Specifies the number of values in the multi-valued attribute. The
555 * "axis" values supplied to the created function should be in the
556 * range zero to (nval - 1).
557
558 * Notes:
559 * - To avoid problems with some compilers, you should not leave any white
560 * space around the macro arguments.
561 *-
562 */
563
564 /* Define the macro. */
565 #define MAKE_TEST(attr,assign,nval) \
566 \
567 /* Private member function. */ \
568 /* ------------------------ */ \
569 static int Test##attr( AstWcsMap *this, int axis, int *status ) { \
570 int result; /* Value to return */ \
571 \
572 /* Initialise */ \
573 result = 0; \
574 \
575 /* Check the global error status. */ \
576 if ( !astOK ) return result; \
577 \
578 \
579 /* Validate the axis index. */ \
580 if( axis < 0 || axis >= nval ){ \
581 astError( AST__AXIIN, "%s(%s): Index (%d) is invalid for attribute " \
582 #attr " - it should be in the range 1 to %d.", status, \
583 "astTest" #attr, astGetClass( this ), \
584 axis + 1, nval ); \
585 \
586 /* Assign the result value. */ \
587 } else { \
588 result = (assign); \
589 } \
590 \
591 /* Check for errors and clear the result if necessary. */ \
592 if ( !astOK ) result = 0; \
593 \
594 /* Return the result. */ \
595 return result; \
596 } \
597 /* External interface. */ \
598 /* ------------------- */ \
599 int astTest##attr##_( AstWcsMap *this, int axis, int *status ) { \
600 \
601 /* Check the global error status. */ \
602 if ( !astOK ) return 0; \
603 \
604 /* Invoke the required method via the virtual function table. */ \
605 return (**astMEMBER(this,WcsMap,Test##attr))( this, axis, status ); \
606 }
607
608
609 /* Include files. */
610 /* ============== */
611 /* Interface definitions. */
612 /* ---------------------- */
613
614 #include "globals.h" /* Thread-safe global data access */
615 #include "error.h" /* Error reporting facilities */
616 #include "memory.h" /* Memory allocation facilities */
617 #include "globals.h" /* Thread-safe global data access */
618 #include "object.h" /* Base Object class */
619 #include "pointset.h" /* Sets of points/coordinates */
620 #include "mapping.h" /* Coordinate mappings (parent class) */
621 #include "unitmap.h" /* Unit mappings */
622 #include "permmap.h" /* Axis permutation mappings */
623 #include "wcsmap.h" /* Interface definition for this class */
624 #include "pal.h" /* SLALIB function prototypes */
625 #include "channel.h" /* I/O channels */
626 #include "proj.h" /* WCSLIB projections and WCSLIB_MXPAR */
627
628 /* Error code definitions. */
629 /* ----------------------- */
630 #include "ast_err.h" /* AST error codes */
631
632 /* C header files. */
633 /* --------------- */
634 #include <ctype.h>
635 #include <math.h>
636 #include <stdio.h>
637 #include <stdlib.h>
638 #include <string.h>
639 #include <limits.h>
640
641 /* Local Type Definitions. */
642 /* ----------------------- */
643 /* This structure is used to hold information describing a WCSLIB
644 projection. */
645 typedef struct PrjData {
646 int prj; /* WCSLIB projection identifier value */
647 int mxpar; /* Max index for a lat axis projection param */
648 int mxpar2; /* Max index for a lon axis projection param */
649 char desc[60]; /* Long projection description */
650 char ctype[5]; /* FITS CTYPE identifying string */
651 int (* WcsFwd)(double, double, struct AstPrjPrm *, double *, double *);
652 /* Pointer to forward projection function */
653 int (* WcsRev)(double, double, struct AstPrjPrm *, double *, double *);
654 /* Pointer to reverse projection function */
655 double theta0; /* Default native latitude of fiducial point */
656 } PrjData;
657
658 /* Module Variables. */
659 /* ================= */
660
661 /* Address of this static variable is used as a unique identifier for
662 member of this class. */
663 static int class_check;
664
665 /* Pointers to parent class methods which are extended by this class. */
666 static int (* parent_getobjsize)( AstObject *, int * );
667 static AstPointSet *(* parent_transform)( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
668 static const char *(* parent_getattrib)( AstObject *, const char *, int * );
669 static int (* parent_testattrib)( AstObject *, const char *, int * );
670 static void (* parent_clearattrib)( AstObject *, const char *, int * );
671 static void (* parent_setattrib)( AstObject *, const char *, int * );
672 static int *(* parent_mapsplit)( AstMapping *, int, const int *, AstMapping **, int * );
673
674 /* The following array of PrjData structured describes each of the WCSLIB
675 projections. The last entry in the list should be for the AST__WCSBAD
676 projection. This marks the end of the list. */
677 static PrjData PrjInfo[] = {
678 { AST__AZP, 2, 4, "zenithal perspective", "-AZP", astAZPfwd, astAZPrev, AST__DPIBY2 },
679 { AST__SZP, 3, 4, "slant zenithal perspective", "-SZP", astSZPfwd, astSZPrev, AST__DPIBY2 },
680 { AST__TAN, 0, 4, "gnomonic", "-TAN", astTANfwd, astTANrev, AST__DPIBY2 },
681 { AST__STG, 0, 4, "stereographic", "-STG", astSTGfwd, astSTGrev, AST__DPIBY2 },
682 { AST__SIN, 2, 4, "orthographic", "-SIN", astSINfwd, astSINrev, AST__DPIBY2 },
683 { AST__ARC, 0, 4, "zenithal equidistant", "-ARC", astARCfwd, astARCrev, AST__DPIBY2 },
684 { AST__ZPN, WCSLIB_MXPAR, 4, "zenithal polynomial", "-ZPN", astZPNfwd, astZPNrev, AST__DPIBY2 },
685 { AST__ZEA, 0, 4, "zenithal equal area", "-ZEA", astZEAfwd, astZEArev, AST__DPIBY2 },
686 { AST__AIR, 1, 4, "Airy", "-AIR", astAIRfwd, astAIRrev, AST__DPIBY2 },
687 { AST__CYP, 2, 4, "cylindrical perspective", "-CYP", astCYPfwd, astCYPrev, 0.0 },
688 { AST__CEA, 1, 4, "cylindrical equal area", "-CEA", astCEAfwd, astCEArev, 0.0 },
689 { AST__CAR, 0, 4, "Cartesian", "-CAR", astCARfwd, astCARrev, 0.0 },
690 { AST__MER, 0, 4, "Mercator", "-MER", astMERfwd, astMERrev, 0.0 },
691 { AST__SFL, 0, 4, "Sanson-Flamsteed", "-SFL", astSFLfwd, astSFLrev, 0.0 },
692 { AST__PAR, 0, 4, "parabolic", "-PAR", astPARfwd, astPARrev, 0.0 },
693 { AST__MOL, 0, 4, "Mollweide", "-MOL", astMOLfwd, astMOLrev, 0.0 },
694 { AST__AIT, 0, 4, "Hammer-Aitoff", "-AIT", astAITfwd, astAITrev, 0.0 },
695 { AST__COP, 2, 4, "conical perspective", "-COP", astCOPfwd, astCOPrev, AST__BAD },
696 { AST__COE, 2, 4, "conical equal area", "-COE", astCOEfwd, astCOErev, AST__BAD },
697 { AST__COD, 2, 4, "conical equidistant", "-COD", astCODfwd, astCODrev, AST__BAD },
698 { AST__COO, 2, 4, "conical orthomorphic", "-COO", astCOOfwd, astCOOrev, AST__BAD },
699 { AST__BON, 1, 4, "Bonne's equal area", "-BON", astBONfwd, astBONrev, 0.0 },
700 { AST__PCO, 0, 4, "polyconic", "-PCO", astPCOfwd, astPCOrev, 0.0 },
701 { AST__TSC, 0, 4, "tangential spherical cube", "-TSC", astTSCfwd, astTSCrev, 0.0 },
702 { AST__CSC, 0, 4, "cobe quadrilateralized spherical cube", "-CSC", astCSCfwd, astCSCrev, 0.0 },
703 { AST__QSC, 0, 4, "quadrilateralized spherical cube", "-QSC", astQSCfwd, astQSCrev, 0.0 },
704 { AST__NCP, 2, 4, "AIPS north celestial pole", "-NCP", NULL, NULL, 0.0 },
705 { AST__GLS, 0, 4, "sinusoidal", "-GLS", astSFLfwd, astSFLrev, 0.0 },
706 { AST__HPX, 2, 4, "HEALPix", "-HPX", astHPXfwd, astHPXrev, 0.0 },
707 { AST__XPH, 0, 4, "polar HEALPix", "-XPH", astXPHfwd, astXPHrev, AST__DPIBY2 },
708 { AST__TPN, WCSLIB_MXPAR, WCSLIB_MXPAR, "gnomonic polynomial", "-TPN", astTPNfwd, astTPNrev, AST__DPIBY2 },
709 { AST__WCSBAD, 0, 4, "<null>", " ", NULL, NULL, 0.0 } };
710
711 /* Define macros for accessing each item of thread specific global data. */
712 #ifdef THREAD_SAFE
713
714 /* Define how to initialise thread-specific globals. */
715 #define GLOBAL_inits \
716 globals->Class_Init = 0; \
717 globals->GetAttrib_Buff[ 0 ] = 0;
718
719 /* Create the function that initialises global data for this module. */
720 astMAKE_INITGLOBALS(WcsMap)
721
722 /* Define macros for accessing each item of thread specific global data. */
723 #define class_init astGLOBAL(WcsMap,Class_Init)
724 #define class_vtab astGLOBAL(WcsMap,Class_Vtab)
725 #define getattrib_buff astGLOBAL(WcsMap,GetAttrib_Buff)
726
727
728
729 /* If thread safety is not needed, declare and initialise globals at static
730 variables. */
731 #else
732
733 static char getattrib_buff[ 101 ];
734
735
736 /* Define the class virtual function table and its initialisation flag
737 as static variables. */
738 static AstWcsMapVtab class_vtab; /* Virtual function table */
739 static int class_init = 0; /* Virtual function table initialised? */
740
741 #endif
742
743 /* External Interface Function Prototypes. */
744 /* ======================================= */
745 /* The following functions have public prototypes only (i.e. no
746 protected prototypes), so we must provide local prototypes for use
747 within this module. */
748 AstWcsMap *astWcsMapId_( int, int, int, int, const char *options, ... );
749
750 /* Prototypes for Private Member Functions. */
751 /* ======================================== */
752 static int GetObjSize( AstObject *, int * );
753 static double GetPV( AstWcsMap *, int, int, int * );
754 static int TestPV( AstWcsMap *, int, int, int * );
755 static void ClearPV( AstWcsMap *, int, int, int * );
756 static void SetPV( AstWcsMap *, int, int, double, int * );
757
758 static int GetPVMax( AstWcsMap *, int, int * );
759 static int GetWcsType( AstWcsMap *, int * );
760 static double GetNatLat( AstWcsMap *, int * );
761 static double GetNatLon( AstWcsMap *, int * );
762 static int GetWcsAxis( AstWcsMap *, int, int * );
763
764 static int GetFITSProj( AstWcsMap *, int * );
765 static int TestFITSProj( AstWcsMap *, int * );
766 static void ClearFITSProj( AstWcsMap *, int * );
767 static void SetFITSProj( AstWcsMap *, int, int * );
768
769 static int GetTPNTan( AstWcsMap *, int * );
770 static int TestTPNTan( AstWcsMap *, int * );
771 static void ClearTPNTan( AstWcsMap *, int * );
772 static void SetTPNTan( AstWcsMap *, int, int * );
773
774 static AstPointSet *Transform( AstMapping *, AstPointSet *, int, AstPointSet *, int * );
775 static const PrjData *FindPrjData( int, int * );
776 static const char *GetAttrib( AstObject *, const char *, int * );
777 static int CanMerge( AstMapping *, int, AstMapping *, int, int * );
778 static int CanSwap( AstMapping *, AstMapping *, int, int, int *, int * );
779 static int Equal( AstObject *, AstObject *, int * );
780 static int GetNP( AstWcsMap *, int, int * );
781 static int IsZenithal( AstWcsMap *, int * );
782 static int LongRange( const PrjData *, struct AstPrjPrm *, double *, double *, int * );
783 static int Map( AstWcsMap *, int, int, double *, double *, double *, double *, int * );
784 static int MapMerge( AstMapping *, int, int, int *, AstMapping ***, int **, int * );
785 static int TestAttrib( AstObject *, const char *, int * );
786 static void ClearAttrib( AstObject *, const char *, int * );
787 static void Copy( const AstObject *, AstObject *, int * );
788 static void CopyPV( AstWcsMap *, AstWcsMap *, int * );
789 static void Delete( AstObject *obj, int * );
790 static void Dump( AstObject *, AstChannel *, int * );
791 static void FreePV( AstWcsMap *, int * );
792 static void InitPrjPrm( AstWcsMap *, int * );
793 static void PermGet( AstPermMap *, int **, int **, double **, int * );
794 static void SetAttrib( AstObject *, const char *, int * );
795 static void WcsPerm( AstMapping **, int *, int, int * );
796 static int *MapSplit( AstMapping *, int, const int *, AstMapping **, int * );
797
798 /* Member functions. */
799 /* ================= */
CanMerge(AstMapping * map1,int inv1,AstMapping * map2,int inv2,int * status)800 static int CanMerge( AstMapping *map1, int inv1, AstMapping *map2, int inv2, int *status ){
801 /*
802 *
803 * Name:
804 * CanMerge
805
806 * Purpose:
807 * Checks if two WcsMaps can be merged.
808
809 * Type:
810 * Private function.
811
812 * Synopsis:
813 * #include "wcsmap.h"
814 * int CanMerge( AstMapping *map1, int inv1, AstMapping *map2, int inv2, int *status )
815
816 * Class Membership:
817 * WcsMap internal utility function.
818
819 * Description:
820 * This function checks the two supplied Mappings to see if they are
821 * two WcsMaps which can be merged. This is only possible if they
822 * form an inverse pair.
823
824 * Parameters:
825 * map1
826 * A pointer to the first mapping.
827 * map2
828 * A pointer to the second mapping.
829 * inv1
830 * The invert flag to use with the first mapping.
831 * inv2
832 * The invert flag to use with the second mapping.
833 * status
834 * Pointer to the inherited status variable.
835
836 * Returned Value:
837 * 1 if the WcsMaps can be merged, zero otherwise.
838
839 */
840
841 /* Local Variables: */
842 AstWcsMap *wcs1; /* Pointer to first WcsMap */
843 AstWcsMap *wcs2; /* Pointer to second WcsMap */
844 int m; /* Projection parameter index */
845 int ret; /* Can the Mappings be merged? */
846 int i; /* Axis index */
847
848 /* Initialise the returned value. */
849 ret = 0;
850
851 /* Check the global error status. */
852 if ( !astOK ) return ret;
853
854 /* Both Mappings must be WcsMaps to merge. */
855 if( !strcmp( "WcsMap", astGetClass( map1 ) ) &&
856 !strcmp( "WcsMap", astGetClass( map2 ) ) ) {
857
858 /* Get pointers to the WcsMaps. */
859 wcs1 = (AstWcsMap *) map1;
860 wcs2 = (AstWcsMap *) map2;
861
862 /* Check that the two WcsMaps performs the same sort of projection, and
863 have the same number of axes. */
864 if( astGetWcsType( wcs1 ) == astGetWcsType( wcs2 ) &&
865 astGetNin( wcs1 ) == astGetNin( wcs2 ) ) {
866
867 /* Check that the Mappings are applied in opposite senses. */
868 if( inv1 != inv2 ) {
869
870 /* Check that the latitude and longitude axes have the same indices in
871 both WcsMaps. */
872 if( astGetWcsAxis( wcs1, 0 ) == astGetWcsAxis( wcs2, 0 ) &&
873 astGetWcsAxis( wcs1, 1 ) == astGetWcsAxis( wcs2, 1 ) ){
874
875 /* We nopw check the projection parameters are equal. Assume they are for
876 the moment. */
877 ret = 1;
878
879 /* Check the parameters for each axis in turn. */
880 for( i = 0; i < astGetNin( wcs1 ); i++ ){
881
882 /* If the two WcsMaps have a different number of parameters for this axes,
883 they cannot merge. */
884 if( GetNP( wcs1, i, status ) != GetNP( wcs1, i, status ) ){
885 ret = 0;
886 break;
887
888 /* Otherwise, check each parameter value in turn. If any are found which
889 are not equal, the WcsMaps cannot merge. */
890 } else {
891 for( m = 0; m < GetNP( wcs1, i, status ); m++ ){
892 if( !EQUAL( astGetPV( wcs1, i, m ),
893 astGetPV( wcs2, i, m ) ) ){
894 ret = 0;
895 break;
896 }
897 }
898 if( !ret ) break;
899 }
900 }
901 }
902 }
903 }
904 }
905
906 /* Return the answer. */
907 return ret;
908 }
909
CanSwap(AstMapping * map1,AstMapping * map2,int inv1,int inv2,int * simpler,int * status)910 static int CanSwap( AstMapping *map1, AstMapping *map2, int inv1, int inv2,
911 int *simpler, int *status ){
912 /*
913 * Name:
914
915 * CanSwap
916
917 * Purpose:
918 * Determine if two Mappings could be swapped.
919
920 * Type:
921 * Private function.
922
923 * Synopsis:
924 * #include "wcsmap.h"
925 * int CanSwap( AstMapping *map1, AstMapping *map2, int inv1, int inv2,
926 * int *simpler )
927
928 * Class Membership:
929 * WcsMap member function
930
931 * Description:
932 * This function returns a flag indicating if the pair of supplied
933 * Mappings could be replaced by an equivalent pair of Mappings from the
934 * same classes as the supplied pair, but in reversed order. Each pair
935 * of Mappings is considered to be compunded in series. The supplied
936 * Mapings are not changed in any way.
937
938 * Parameters:
939 * map1
940 * The Mapping to be applied first.
941 * map2
942 * The Mapping to be applied second.
943 * inv1
944 * The invert flag to use with map1. A value of zero causes the forward
945 * mapping to be used, and a non-zero value causes the inverse
946 * mapping to be used.
947 * inv2
948 * The invert flag to use with map2.
949 * simpler
950 * Addresss of a location at which to return a flag indicating if
951 * the swapped Mappings would be intrinsically simpler than the
952 * original Mappings.
953
954 * Returned Value:
955 * 1 if the Mappings could be swapped, 0 otherwise.
956
957 * Notes:
958 * - One of the supplied pair of Mappings must be a WcsMap.
959 * - A value of 0 is returned if the two Mappings could be merged into
960 * a single Mapping.
961 * - A value of 0 is returned if an error has already occurred, or if
962 * this function should fail for any reason.
963 */
964
965 /* Local Variables: */
966 AstMapping *nowcs; /* Pointer to non-WcsMap Mapping */
967 AstWcsMap *wcs; /* Pointer to WcsMap Mapping */
968 const char *class1; /* Pointer to map1 class string */
969 const char *class2; /* Pointer to map2 class string */
970 const char *nowcs_class; /* Pointer to non-WcsMap class string */
971 double *consts; /* Pointer to constants array */
972 int *inperm; /* Pointer to input axis permutation array */
973 int *outperm; /* Pointer to output axis permutation array */
974 int i; /* Loop count */
975 int invert[ 2 ]; /* Original invert flags */
976 int latax; /* Index of latitude axis in WcsMap */
977 int lonax; /* Index of longitude axis in WcsMap */
978 int nin; /* No. of input coordinates for the PermMap */
979 int nout; /* No. of output coordinates for the PermMap */
980 int ret; /* Returned flag */
981
982 /* Check the global error status. */
983 if ( !astOK ) return 0;
984
985 /* Initialise */
986 ret = 0;
987 *simpler = 0;
988
989 /* Temporarily set the Invert attributes of both Mappings to the supplied
990 values. */
991 invert[ 0 ] = astGetInvert( map1 );
992 astSetInvert( map1, inv1 );
993
994 invert[ 1 ] = astGetInvert( map2 );
995 astSetInvert( map2, inv2 );
996
997 /* Get the classes of the two mappings. */
998 class1 = astGetClass( map1 );
999 class2 = astGetClass( map2 );
1000 if( astOK ){
1001
1002 /* Get a pointer to the non-WcsMap Mapping. */
1003 if( !strcmp( class1, "WcsMap" ) ){
1004 wcs = (AstWcsMap *) map1;
1005 nowcs = map2;
1006 nowcs_class = class2;
1007 } else {
1008 nowcs = map1;
1009 wcs = (AstWcsMap *) map2;
1010 nowcs_class = class1;
1011 }
1012
1013 /* If it is a PermMap, the Mappings can be swapped so long as:
1014 1) all links between input and output axes in the PermMap are
1015 bi-directional. This does not preclude the existence of unconnected axes,
1016 which do not have links (bi-directional or otherwise).
1017 2) The PermMap passesd though both the longitude and latitude axes of
1018 the WcsMap */
1019 if( !strcmp( nowcs_class, "PermMap" ) ){
1020
1021 /* Get the number of input and output coordinates. */
1022 nin = astGetNin( nowcs );
1023 nout = astGetNout( nowcs );
1024
1025 /* We need to know the axis permutation arrays and constants array for
1026 the PermMap. */
1027 PermGet( (AstPermMap *) nowcs, &outperm, &inperm, &consts, status );
1028 if( astOK ) {
1029
1030 /* Indicate we can swap with the PermMap. */
1031 ret = 1;
1032
1033 /* Check each output axis. If any links between axes are found which are
1034 not bi-directional, indicate that we cannot swap with the PermMap. */
1035 for( i = 0; i < nout; i++ ){
1036 if( outperm[ i ] >= 0 && outperm[ i ] < nin ) {
1037 if( inperm[ outperm[ i ] ] != i ) {
1038 ret = 0;
1039 break;
1040 }
1041 }
1042 }
1043
1044 /* Check each input axis. If any links between axes are found which are
1045 not bi-directional, indicate that we cannot swap with the PermMap. */
1046 for( i = 0; i < nin; i++ ){
1047 if( inperm[ i ] >= 0 && inperm[ i ] < nout ) {
1048 if( outperm[ inperm[ i ] ] != i ) {
1049 ret = 0;
1050 break;
1051 }
1052 }
1053 }
1054
1055 /* Check that the longitude and latitude axes both have bi-directional
1056 links in the PermMap, or are both unassigned. */
1057 if( ret ) {
1058
1059 /* Get the indices of the longitude and latitude axes in the WcsMap */
1060 lonax = astGetWcsAxis( wcs, 0 );
1061 latax = astGetWcsAxis( wcs, 1 );
1062
1063 /* If the WcsMap is applied first... */
1064 if( wcs == (AstWcsMap *) map1 ) {
1065 if( inperm[ lonax] < 0 && inperm[ latax ] < 0 ) {
1066 ret = 1;
1067 } else if( inperm[ lonax ] < 0 || inperm[ lonax ] >= nout ||
1068 inperm[ latax ] < 0 || inperm[ latax ] >= nout ) {
1069 ret = 0;
1070 }
1071
1072 /* If the WcsMap is applied second ... */
1073 } else {
1074 if( outperm[ lonax ] < 0 && outperm[ latax ] < 0 ) {
1075 ret = 1;
1076 } else if( outperm[ lonax ] < 0 || outperm[ lonax ] >= nin ||
1077 outperm[ latax ] < 0 || outperm[ latax ] >= nin ) {
1078 ret = 0;
1079 }
1080 }
1081 }
1082
1083 /* If we can swap with the PermMap, the swapped Mappings may be
1084 intrinsically simpler than the original mappings. */
1085 if( ret ) {
1086
1087 /* If the PermMap precedes the WcsMap, this will be the case if the PermMap
1088 has more outputs than inputs. If the WcsMap precedes the PermMap, this
1089 will be the case if the PermMap has more inputs than outputs. */
1090 *simpler = ( nowcs == map1 ) ? nout > nin : nin > nout;
1091 }
1092
1093 /* Free the axis permutation and constants arrays. */
1094 outperm = (int *) astFree( (void *) outperm );
1095 inperm = (int *) astFree( (void *) inperm );
1096 consts = (double *) astFree( (void *) consts );
1097 }
1098 }
1099 }
1100
1101 /* Re-instate the original settings of the Invert attributes for the
1102 supplied MatrixMaps. */
1103 astSetInvert( map1, invert[ 0 ] );
1104 astSetInvert( map2, invert[ 1 ] );
1105
1106 /* Return the answer. */
1107 return astOK ? ret : 0;
1108 }
1109
ClearAttrib(AstObject * this_object,const char * attrib,int * status)1110 static void ClearAttrib( AstObject *this_object, const char *attrib, int *status ) {
1111 /*
1112 * Name:
1113 * ClearAttrib
1114
1115 * Purpose:
1116 * Clear an attribute value for a WcsMap.
1117
1118 * Type:
1119 * Private function.
1120
1121 * Synopsis:
1122 * #include "wcsmap.h"
1123 * void ClearAttrib( AstObject *this, const char *attrib, int *status )
1124
1125 * Class Membership:
1126 * WcsMap member function (over-rides the astClearAttrib protected
1127 * method inherited from the Mapping class).
1128
1129 * Description:
1130 * This function clears the value of a specified attribute for a
1131 * WcsMap, so that the default value will subsequently be used.
1132
1133 * Parameters:
1134 * this
1135 * Pointer to the WcsMap.
1136 * attrib
1137 * Pointer to a null terminated string specifying the attribute
1138 * name. This should be in lower case with no surrounding white
1139 * space.
1140 * status
1141 * Pointer to the inherited status variable.
1142 */
1143
1144 /* Local Variables: */
1145 AstWcsMap *this; /* Pointer to the WcsMap structure */
1146 int i; /* Axis index */
1147 int len; /* Length of the attribute name */
1148 int m; /* Projection parameter index */
1149 int nc; /* No. of characters read by astSscanf */
1150
1151 /* Check the global error status. */
1152 if ( !astOK ) return;
1153
1154 /* Obtain a pointer to the WcsMap structure. */
1155 this = (AstWcsMap *) this_object;
1156
1157 /* Obtain the length of the attrib string. */
1158 len = strlen( attrib );
1159
1160 /* Check the attribute name and clear the appropriate attribute. */
1161
1162 /* ProjP. */
1163 /* ------ */
1164 if ( nc = 0, ( 1 == astSscanf( attrib, "prpjp(%d)%n", &m, &nc ) )
1165 && ( nc >= len ) ) {
1166 astClearPV( this, astGetWcsAxis( this, 1 ), m );
1167
1168 /* PV. */
1169 /* ------ */
1170 } else if ( nc = 0, ( 2 == astSscanf( attrib, "pv%d_%d%n", &i, &m, &nc ) )
1171 && ( nc >= len ) ) {
1172 astClearPV( this, i - 1, m );
1173
1174 /* If the name was not recognised, test if it matches any of the
1175 read-only attributes of this class. If it does, then report an
1176 error. */
1177 } else if ( ( nc = 0, ( 1 == astSscanf( attrib, "wcsaxis(%d)%n", &i, &nc ) )
1178 && ( nc >= len ) ) ||
1179 !strcmp( attrib, "wcstype" ) ||
1180 !strcmp( attrib, "natlat" ) ||
1181 !strcmp( attrib, "natlon" ) ){
1182 astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" "
1183 "value for a %s.", status, attrib, astGetClass( this ) );
1184 astError( AST__NOWRT, "This is a read-only attribute." , status);
1185
1186 /* If the attribute is still not recognised, pass it on to the parent
1187 method for further interpretation. */
1188 } else {
1189 (*parent_clearattrib)( this_object, attrib, status );
1190 }
1191 }
1192
ClearPV(AstWcsMap * this,int i,int m,int * status)1193 static void ClearPV( AstWcsMap *this, int i, int m, int *status ) {
1194 /*
1195 *+
1196 * Name:
1197 * astClearPV
1198
1199 * Purpose:
1200 * Clear a PVi_m attribute.
1201
1202 * Type:
1203 * Protected function.
1204
1205 * Synopsis:
1206 * #include "wcsmap.h"
1207 * void astClearPV( AstWcsMap *this, int i, int m )
1208
1209 * Class Membership:
1210 * WcsMap protected function
1211
1212 * Description:
1213 * This function clears a specified member of the PV attribute array, by
1214 * resetting its value to AST__BAD.
1215
1216 * Parameters:
1217 * this
1218 * A pointer to the WcsMap.
1219 * i
1220 * Zero based axis index.
1221 * m
1222 * Zero based parameter index.
1223
1224 *-
1225 */
1226 /* Local Variables; */
1227 int npar;
1228 int mxpar;
1229
1230 /* Check the global error status. */
1231 if ( !astOK ) return;
1232
1233 /* Validate the axis index. */
1234 if( i < 0 || i >= astGetNin( this ) ){
1235 astError( AST__AXIIN, "astClearPV(%s): Axis index (%d) is invalid in "
1236 "attribute PV%d_%d - it should be in the range 1 to %d.",
1237 status, astGetClass( this ), i + 1, i + 1, m,
1238 astGetNin( this ) );
1239
1240 } else {
1241
1242 /* Find the maximum number of parameters allowed for the axis. */
1243 mxpar = astGetPVMax( this, i );
1244
1245 /* Ignore unused parameters. */
1246 if( m < 0 || m > mxpar ){
1247
1248 /* See if the parameter is currently set. Is so, set its value to
1249 AST__BAD. */
1250 } else if( this->np && this->p ){
1251 npar = this->np[ i ];
1252 if( m < npar && this->p[ i ] ) this->p[ i ][ m ] = AST__BAD;
1253 }
1254
1255 /* Re-initialize the values stored in the "AstPrjPrm" structure. */
1256 InitPrjPrm( this, status );
1257 }
1258 }
1259
ClearTPNTan(AstWcsMap * this,int * status)1260 static void ClearTPNTan( AstWcsMap *this, int *status ) {
1261 /*
1262 *+
1263 * Name:
1264 * astClearTPNTan
1265
1266 * Purpose:
1267 * Clear the TPNTan attribute.
1268
1269 * Type:
1270 * Protected function.
1271
1272 * Synopsis:
1273 * #include "wcsmap.h"
1274 * void ClearTPNTan( AstWcsMap *this, int *status )
1275
1276 * Class Membership:
1277 * WcsMap protected function
1278
1279 * Description:
1280 * This function clears the TPNTan attribute, ensuring the projection
1281 * parameters used by WCSLIB are adjusted accordingly.
1282
1283 * Parameters:
1284 * this
1285 * A pointer to the WcsMap.
1286
1287 *-
1288 */
1289
1290 /* Check the global error status. */
1291 if ( !astOK ) return;
1292
1293 /* Clear the value. */
1294 this->tpn_tan = -INT_MAX;
1295
1296 /* Re-initialize the values stored in the "AstPrjPrm" structure. */
1297 InitPrjPrm( this, status );
1298 }
1299
CopyPV(AstWcsMap * in,AstWcsMap * out,int * status)1300 static void CopyPV( AstWcsMap *in, AstWcsMap *out, int *status ) {
1301 /*
1302 * Name:
1303 * CopyPV
1304
1305 * Purpose:
1306 * Copy projection parameter information from one WcsMap to another.
1307
1308 * Type:
1309 * Private function.
1310
1311 * Synopsis:
1312 * void CopyPV( AstWcsMap *in, AstWcsMap *out )
1313
1314 * Description:
1315 * This function copies projection parameter information from one
1316 * WcsMap to another.
1317
1318 * Parameters:
1319 * in
1320 * Pointer to the input WcsMap.
1321 * out
1322 * Pointer to the output WcsMap.
1323
1324 */
1325
1326
1327 /* Local Variables: */
1328 int i; /* Axis index */
1329 int latax_in; /* Index of input latitude axis */
1330 int latax_out; /* Index of output latitude axis */
1331 int lonax_in; /* Index of input longitude axis */
1332 int lonax_out; /* Index of output longitude axis */
1333 int nax_out; /* No. of axis in the output WcsMap */
1334
1335 /* Check the global error status. */
1336 if ( !astOK ) return;
1337
1338 /* Nullify the pointers stored in the output WcsMap since these may
1339 currently be pointing at good data. Otherwise, the good data could be
1340 freed by accident if the output object is deleted due to an error
1341 occuring in this function. */
1342 out->np = NULL;
1343 out->p = NULL;
1344
1345 /* Do nothing more if either of the input pointers are null (i.e. if there
1346 are no projection parameters. */
1347 if( in->np && in->p ){
1348
1349 /* Store the number of axes in the input and output WcsMaps */
1350 nax_out = astGetNin( out );
1351
1352 /* Allocate memory for the array holding the number of projection parameters
1353 associated with each axis. */
1354 out->np = (int *) astMalloc( sizeof( int )*nax_out );
1355
1356 /* Allocate memory for the array of pointers which identify the arrays
1357 holding the parameter values. */
1358 out->p = (double **) astMalloc( sizeof( double *)*nax_out );
1359
1360 /* Check pointers can be used */
1361 if( astOK ) {
1362
1363 /* Initialise the above arrays. */
1364 for( i = 0; i < nax_out; i++ ) {
1365 (out->np)[ i ] = 0;
1366 (out->p)[ i ] = NULL;
1367 }
1368
1369 /* Copy the longitude and latitude values from in to out (other axes do
1370 not have projection parameters). */
1371 lonax_in = astGetWcsAxis( in, 0 );
1372 latax_in = astGetWcsAxis( in, 1 );
1373 lonax_out = astGetWcsAxis( out, 0 );
1374 latax_out = astGetWcsAxis( out, 1 );
1375
1376 (out->np)[ lonax_out ] = (in->np)[ lonax_in ];
1377 (out->p)[ lonax_out ] = (double *) astStore( NULL,
1378 (void *) (in->p)[ lonax_in ],
1379 sizeof(double)*(in->np)[ lonax_in ] );
1380
1381 (out->np)[ latax_out ] = (in->np)[ latax_in ];
1382 (out->p)[ latax_out ] = (double *) astStore( NULL,
1383 (void *) (in->p)[ latax_in ],
1384 sizeof(double)*(in->np)[ latax_in ] );
1385 }
1386
1387 /* If an error has occurred, free the output arrays. */
1388 if( !astOK ) FreePV( out, status );
1389
1390 }
1391
1392 /* Re-initialize the values stored in the "AstPrjPrm" structure. */
1393 InitPrjPrm( out, status );
1394
1395 }
1396
Equal(AstObject * this_object,AstObject * that_object,int * status)1397 static int Equal( AstObject *this_object, AstObject *that_object, int *status ) {
1398 /*
1399 * Name:
1400 * Equal
1401
1402 * Purpose:
1403 * Test if two WcsMaps are equivalent.
1404
1405 * Type:
1406 * Private function.
1407
1408 * Synopsis:
1409 * #include "wcsmap.h"
1410 * int Equal( AstObject *this, AstObject *that, int *status )
1411
1412 * Class Membership:
1413 * WcsMap member function (over-rides the astEqual protected
1414 * method inherited from the astMapping class).
1415
1416 * Description:
1417 * This function returns a boolean result (0 or 1) to indicate whether
1418 * two WcsMaps are equivalent.
1419
1420 * Parameters:
1421 * this
1422 * Pointer to the first Object (a WcsMap).
1423 * that
1424 * Pointer to the second Object.
1425 * status
1426 * Pointer to the inherited status variable.
1427
1428 * Returned Value:
1429 * One if the WcsMaps are equivalent, zero otherwise.
1430
1431 * Notes:
1432 * - A value of zero will be returned if this function is invoked
1433 * with the global status set, or if it should fail for any reason.
1434 */
1435
1436 /* Local Variables: */
1437 AstWcsMap *that;
1438 AstWcsMap *this;
1439 int i, j;
1440 int nin;
1441 int nout;
1442 int result;
1443
1444 /* Initialise. */
1445 result = 0;
1446
1447 /* Check the global error status. */
1448 if ( !astOK ) return result;
1449
1450 /* Obtain pointers to the two WcsMap structures. */
1451 this = (AstWcsMap *) this_object;
1452 that = (AstWcsMap *) that_object;
1453
1454 /* Check the second object is a WcsMap. We know the first is a
1455 WcsMap since we have arrived at this implementation of the virtual
1456 function. */
1457 if( astIsAWcsMap( that ) ) {
1458
1459 /* Get the number of inputs and outputs and check they are the same for both. */
1460 nin = astGetNin( this );
1461 nout = astGetNout( this );
1462 if( astGetNin( that ) == nin && astGetNout( that ) == nout ) {
1463
1464 /* If the Invert flags for the two WcsMaps differ, it may still be possible
1465 for them to be equivalent. First compare the WcsMaps if their Invert
1466 flags are the same. In this case all the attributes of the two WcsMaps
1467 must be identical. */
1468 if( astGetInvert( this ) == astGetInvert( that ) ) {
1469
1470 if( this->type == that->type &&
1471 this->wcsaxis[ 0 ] == that->wcsaxis[ 0 ] &&
1472 this->wcsaxis[ 1 ] == that->wcsaxis[ 1 ] ) {
1473
1474 result = 1;
1475
1476 if( this->np && that->np ){
1477
1478 for( i = 0; i < nout && result; i++ ) {
1479
1480 if( (this->np)[ i ] != (that->np)[ i ] ) {
1481 result = 0;
1482
1483 } else if( (this->p)[ i ] && !(this->p)[ i ] ) {
1484 result = 0;
1485
1486 } else if( !(this->p)[ i ] && (this->p)[ i ] ) {
1487 result = 0;
1488
1489 } else if( (this->p)[ i ] && (this->p)[ i ] ) {
1490
1491 for( j = 0; j < (this->np)[ i ]; j++ ) {
1492 if( !astEQUAL( (this->p)[ i ][ j ],
1493 (that->p)[ i ][ j ] ) ) {
1494 result = 0;
1495 break;
1496 }
1497 }
1498 }
1499 }
1500 }
1501
1502 } else if( this->np || that->np ){
1503 result = 0;
1504 }
1505
1506 /* If the Invert flags for the two WcsMaps differ, the attributes of the two
1507 WcsMaps must be inversely related to each other. */
1508 } else {
1509
1510 /* In the specific case of a WcsMap, Invert flags must be equal. */
1511 result = 0;
1512
1513 }
1514 }
1515 }
1516
1517 /* If an error occurred, clear the result value. */
1518 if ( !astOK ) result = 0;
1519
1520 /* Return the result, */
1521 return result;
1522 }
1523
FindPrjData(int type,int * status)1524 static const PrjData *FindPrjData( int type, int *status ){
1525 /*
1526 *+
1527 * Name:
1528 * FindPrjData
1529
1530 * Purpose:
1531 * Get information about a WCSLIB projection given a projection type.
1532
1533 * Type:
1534 * Private function.
1535
1536 * Synopsis:
1537 * #include "wcsmap.h"
1538 * const PrjData *FindPrjData( int type, int *status )
1539
1540 * Class Membership:
1541 * WcsMap member function
1542
1543 * Description:
1544 * This function returns a pointer to an PrjData structure describing
1545 * the WCSLIB projection with the supplied type.
1546
1547 * Parameters:
1548 * type
1549 * The projection type.
1550 * status
1551 * Pointer to the inherited status variable.
1552
1553 * Returned Value:
1554 * A pointer to the "const" PrjData structure describing the projection.
1555
1556 * Notes:
1557 * - The returned pointer points to an element in a static array and
1558 * should not be freed.
1559 * - This function attempts to execute even if an error has already
1560 * occurred. A description of a "null" projection will be returned if
1561 * this function subsequently fails (for instance if the projection is
1562 * not recognised).
1563 *-
1564 */
1565
1566 const PrjData *data;
1567 data = PrjInfo;
1568 while( data->prj != AST__WCSBAD && data->prj != type ) data++;
1569 return data;
1570 }
1571
FreePV(AstWcsMap * this,int * status)1572 static void FreePV( AstWcsMap *this, int *status ) {
1573 /*
1574 *
1575 * Name:
1576 * FreePV
1577
1578 * Purpose:
1579 * Free memory used to hold projection parameters
1580
1581 * Type:
1582 * Private function.
1583
1584 * Synopsis:
1585 * #include "wcsmap.h"
1586 * FreePV( AstWcsMap *this, int *status )
1587
1588 * Class Membership:
1589 * WcsMap private function
1590
1591 * Description:
1592 * This function frees all the dynamic memory used to store projection
1593 * parameter information in the supplied WcsMap.
1594
1595 * Parameters:
1596 * this
1597 * A pointer to the WcsMap.
1598 * status
1599 * Pointer to the inherited status variable.
1600
1601 * Notes:
1602 * This function attempts to execute even if an error has already occurred.
1603
1604 *
1605 */
1606 int i; /* Axis index */
1607
1608 if( this->np ) this->np = (int *) astFree( (void *) this->np );
1609 if( this->p ){
1610 for( i = 0; i < astGetNin( this ); i++ ){
1611 this->p[ i ] = (double *) astFree( (void *) this->p[ i ] );
1612 }
1613 this->p = (double **) astFree( (void *) this->p );
1614 }
1615
1616 /* Re-initialize the values stored in the "AstPrjPrm" structure. */
1617 InitPrjPrm( this, status );
1618
1619
1620 }
1621
GetObjSize(AstObject * this_object,int * status)1622 static int GetObjSize( AstObject *this_object, int *status ) {
1623 /*
1624 * Name:
1625 * GetObjSize
1626
1627 * Purpose:
1628 * Return the in-memory size of an Object.
1629
1630 * Type:
1631 * Private function.
1632
1633 * Synopsis:
1634 * #include "wcsmap.h"
1635 * int GetObjSize( AstObject *this, int *status )
1636
1637 * Class Membership:
1638 * WcsMap member function (over-rides the astGetObjSize protected
1639 * method inherited from the parent class).
1640
1641 * Description:
1642 * This function returns the in-memory size of the supplied WcsMap,
1643 * in bytes.
1644
1645 * Parameters:
1646 * this
1647 * Pointer to the WcsMap.
1648 * status
1649 * Pointer to the inherited status variable.
1650
1651 * Returned Value:
1652 * The Object size, in bytes.
1653
1654 * Notes:
1655 * - A value of zero will be returned if this function is invoked
1656 * with the global status set, or if it should fail for any reason.
1657 */
1658
1659 /* Local Variables: */
1660 AstWcsMap *this; /* Pointer to WcsMap structure */
1661 int result; /* Result value to return */
1662 int i; /* Axis index */
1663
1664 /* Initialise. */
1665 result = 0;
1666
1667 /* Check the global error status. */
1668 if ( !astOK ) return result;
1669
1670 /* Obtain a pointers to the WcsMap structure. */
1671 this = (AstWcsMap *) this_object;
1672
1673 /* Invoke the GetObjSize method inherited from the parent class, and then
1674 add on any components of the class structure defined by thsi class
1675 which are stored in dynamically allocated memory. */
1676 result = (*parent_getobjsize)( this_object, status );
1677
1678 result += astTSizeOf( this->np );
1679 if( this->p ){
1680 for( i = 0; i < astGetNin( this ); i++ ){
1681 result += astTSizeOf( (void *) this->p[ i ] );
1682 }
1683 result += astTSizeOf( this->p );
1684 }
1685
1686 result += astTSizeOf( this->params.p );
1687 result += astTSizeOf( this->params.p2 );
1688
1689 /* If an error occurred, clear the result value. */
1690 if ( !astOK ) result = 0;
1691
1692 /* Return the result, */
1693 return result;
1694 }
1695
GetAttrib(AstObject * this_object,const char * attrib,int * status)1696 static const char *GetAttrib( AstObject *this_object, const char *attrib, int *status ) {
1697 /*
1698 * Name:
1699 * GetAttrib
1700
1701 * Purpose:
1702 * Get the value of a specified attribute for a WcsMap.
1703
1704 * Type:
1705 * Private function.
1706
1707 * Synopsis:
1708 * #include "wcsmap.h"
1709 * const char *GetAttrib( AstObject *this, const char *attrib, int *status )
1710
1711 * Class Membership:
1712 * WcsMap member function (over-rides the protected astGetAttrib
1713 * method inherited from the Mapping class).
1714
1715 * Description:
1716 * This function returns a pointer to the value of a specified
1717 * attribute for a WcsMap, formatted as a character string.
1718
1719 * Parameters:
1720 * this
1721 * Pointer to the WcsMap.
1722 * attrib
1723 * Pointer to a null-terminated string containing the name of
1724 * the attribute whose value is required. This name should be in
1725 * lower case, with all white space removed.
1726 * status
1727 * Pointer to the inherited status variable.
1728
1729 * Returned Value:
1730 * - Pointer to a null-terminated string containing the attribute
1731 * value.
1732
1733 * Notes:
1734 * - The returned string pointer may point at memory allocated
1735 * within the WcsMap, or at static memory. The contents of the
1736 * string may be over-written or the pointer may become invalid
1737 * following a further invocation of the same function or any
1738 * modification of the WcsMap. A copy of the string should
1739 * therefore be made if necessary.
1740 * - A NULL pointer will be returned if this function is invoked
1741 * with the global error status set, or if it should fail for any
1742 * reason.
1743 */
1744
1745 /* Local Variables: */
1746 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
1747 AstWcsMap *this; /* Pointer to the WcsMap structure */
1748 const char *result; /* Pointer value to return */
1749 double dval; /* Floating point attribute value */
1750 int i; /* Axis index */
1751 int ival; /* Integer attribute value */
1752 int len; /* Length of attribute string */
1753 int m; /* Projection parameter index */
1754 int nc; /* No. of characters read by astSscanf */
1755
1756 /* Initialise. */
1757 result = NULL;
1758
1759 /* Check the global error status. */
1760 if ( !astOK ) return result;
1761
1762 /* Get a pointer to the thread specific global data structure. */
1763 astGET_GLOBALS(this_object);
1764
1765 /* Obtain a pointer to the WcsMap structure. */
1766 this = (AstWcsMap *) this_object;
1767
1768 /* Obtain the length of the attrib string. */
1769 len = strlen( attrib );
1770
1771 /* Compare "attrib" with each recognised attribute name in turn,
1772 obtaining the value of the required attribute. If necessary, write
1773 the value into "getattrib_buff" as a null-terminated string in an appropriate
1774 format. Set "result" to point at the result string. */
1775
1776 /* ProjP. */
1777 /* ------ */
1778 if ( nc = 0, ( 1 == astSscanf( attrib, "projp(%d)%n", &m, &nc ) )
1779 && ( nc >= len ) ) {
1780 dval = astGetPV( this, astGetWcsAxis( this, 1 ), m );
1781 if ( astOK ) {
1782 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
1783 result = getattrib_buff;
1784 }
1785
1786 /* PV. */
1787 /* --- */
1788 } else if ( nc = 0, ( 2 == astSscanf( attrib, "pv%d_%d%n", &i, &m, &nc ) )
1789 && ( nc >= len ) ) {
1790 dval = astGetPV( this, i - 1, m );
1791 if ( astOK ) {
1792 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
1793 result = getattrib_buff;
1794 }
1795
1796 /* WcsType */
1797 /* ======= */
1798 } else if ( !strcmp( attrib, "wcstype" ) ) {
1799 ival = astGetWcsType( this );
1800 if ( astOK ) {
1801 (void) sprintf( getattrib_buff, "%d", ival );
1802 result = getattrib_buff;
1803 }
1804
1805 /* PVMax */
1806 /* ===== */
1807 } else if ( nc = 0, ( 1 == astSscanf( attrib, "pvmax(%d)%n", &i, &nc ) )
1808 && ( nc >= len ) ) {
1809 ival = astGetPVMax( this, i - 1 );
1810 if ( astOK ) {
1811 (void) sprintf( getattrib_buff, "%d", ival );
1812 result = getattrib_buff;
1813 }
1814
1815 /* NatLat */
1816 /* ====== */
1817 } else if ( !strcmp( attrib, "natlat" ) ) {
1818 dval = astGetNatLat( this );
1819 if ( astOK ) {
1820 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
1821 result = getattrib_buff;
1822 }
1823
1824 /* NatLon */
1825 /* ====== */
1826 } else if ( !strcmp( attrib, "natlon" ) ) {
1827 dval = astGetNatLon( this );
1828 if ( astOK ) {
1829 (void) sprintf( getattrib_buff, "%.*g", DBL_DIG, dval );
1830 result = getattrib_buff;
1831 }
1832
1833
1834 /* WcsAxis */
1835 /* ======= */
1836 } else if ( nc = 0, ( 1 == astSscanf( attrib, "wcsaxis(%d)%n", &i, &nc ) )
1837 && ( nc >= len ) ) {
1838 ival = astGetWcsAxis( this, i - 1 ) + 1;
1839 if ( astOK ) {
1840 (void) sprintf( getattrib_buff, "%d", ival );
1841 result = getattrib_buff;
1842 }
1843
1844 /* If the attribute name was not recognised, pass it on to the parent
1845 method for further interpretation. */
1846 } else {
1847 result = (*parent_getattrib)( this_object, attrib, status );
1848 }
1849
1850 /* Return the result. */
1851 return result;
1852 }
1853
GetNatLat(AstWcsMap * this,int * status)1854 static double GetNatLat( AstWcsMap *this, int *status ) {
1855 /*
1856 *+
1857 * Name:
1858 * GetNatLat
1859
1860 * Purpose:
1861 * Get the value of the NatLat attribute.
1862
1863 * Type:
1864 * Protected function.
1865
1866 * Synopsis:
1867 * #include "wcsmap.h"
1868 * double GetNatLat( AstWcsMap *this, int *status )
1869
1870 * Class Membership:
1871 * WcsMap protected function
1872
1873 * Description:
1874 * This function returns the value of the NatLat attribute. This is
1875 * fixed value for most projection types , defined in the FITS-WCS paper
1876 * II. For instance, all zenithal projections have NatLat = PI/2 (90
1877 * degrees). For some prjections (e.g. conics), the value is defined
1878 * by a projection parameter.
1879
1880 * Parameters:
1881 * this
1882 * A pointer to the WcsMap.
1883 * status
1884 * Pointer to the inherited status variable.
1885
1886 * Returned Value:
1887 * The attribute value, in radians.
1888
1889 *-
1890 */
1891 double ret; /* Returned value */
1892
1893 /* The native latitude of the reference point of the projection is
1894 constant for most projection, but for some (the conics) it is
1895 specified by projection one on the latitude axis. */
1896 ret = FindPrjData( this->type, status )->theta0;
1897 if( ret == AST__BAD ){
1898 ret = astGetPV( this, astGetWcsAxis( this, 1 ), 1 );
1899 if( ret != AST__BAD ) ret *= AST__DD2R;
1900 }
1901
1902 /* Return the result. */
1903 return ret;
1904 }
1905
GetNatLon(AstWcsMap * this,int * status)1906 static double GetNatLon( AstWcsMap *this, int *status ) {
1907 /*
1908 *+
1909 * Name:
1910 * GetNatLon
1911
1912 * Purpose:
1913 * Get the value of the NatLon attribute.
1914
1915 * Type:
1916 * Protected function.
1917
1918 * Synopsis:
1919 * #include "wcsmap.h"
1920 * double GetNatLon( AstWcsMap *this, int *status )
1921
1922 * Class Membership:
1923 * WcsMap protected function
1924
1925 * Description:
1926 * This function returns the value of the NatLon attribute. This is
1927 * fixed value of zero for all projection types.
1928
1929 * Parameters:
1930 * this
1931 * A pointer to the WcsMap.
1932 * status
1933 * Pointer to the inherited status variable.
1934
1935 * Returned Value:
1936 * The attribute value, in radians.
1937
1938 *-
1939 */
1940 return 0.0;
1941 }
1942
GetNP(AstWcsMap * this,int i,int * status)1943 static int GetNP( AstWcsMap *this, int i, int *status ) {
1944 /*
1945 *+
1946 * Name:
1947 * GetNP
1948
1949 * Purpose:
1950 * Get the number of projection parameters for a specified axis.
1951
1952 * Type:
1953 * Protected function.
1954
1955 * Synopsis:
1956 * #include "wcsmap.h"
1957 * int GetNP( AstWcsMap *this, int i, int *status )
1958
1959 * Class Membership:
1960 * WcsMap protected function
1961
1962 * Description:
1963 * This function returns the current number of projection parameters
1964 * associated with the speified axis. Some of these may be unset (i.e.
1965 * equal to AST__BAD). The returned number is the size of the array
1966 * holding the projection parameters.
1967
1968 * Parameters:
1969 * this
1970 * A pointer to the WcsMap.
1971 * i
1972 * Zero based axis index.
1973 * status
1974 * Pointer to the inherited status variable.
1975
1976 * Returned Value:
1977 * The number of projection parameters for the specified axis.
1978
1979 *-
1980 */
1981 double ret;
1982
1983 /* Initialise */
1984 ret = 0;
1985
1986 /* Check the global error status. */
1987 if ( !astOK ) return ret;
1988
1989 /* Validate the axis index, and get the count. */
1990 if( i >= 0 && this->np && i < astGetNin( this ) ) ret = this->np[ i ];
1991
1992 return ret;
1993
1994 }
1995
GetPV(AstWcsMap * this,int i,int m,int * status)1996 static double GetPV( AstWcsMap *this, int i, int m, int *status ) {
1997 /*
1998 *+
1999 * Name:
2000 * astGetPV
2001
2002 * Purpose:
2003 * Get the value of a PVi_m attribute.
2004
2005 * Type:
2006 * Protected function.
2007
2008 * Synopsis:
2009 * #include "wcsmap.h"
2010 * double astGetPV( AstWcsMap *this, int i, int m )
2011
2012 * Class Membership:
2013 * WcsMap protected function
2014
2015 * Description:
2016 * This function returns the current value of a specified member of the
2017 * PV attribute array. A value of AST__BAD is returned if no value has
2018 * been set for the parameter.
2019
2020 * Parameters:
2021 * this
2022 * A pointer to the WcsMap.
2023 * i
2024 * Zero based axis index.
2025 * m
2026 * Zero based parameter index.
2027
2028 * Returned Value:
2029 * The value of the requested attribute, of AST__BAD if not set.
2030
2031 *-
2032 */
2033
2034 /* Local Variables: */
2035 double ret;
2036 int npar;
2037 int mxpar;
2038
2039 /* Initialise */
2040 ret = AST__BAD;
2041
2042 /* Check the global error status. */
2043 if ( !astOK ) return ret;
2044
2045 /* Validate the axis index. */
2046 if( i < 0 || i >= astGetNin( this ) ){
2047 astError( AST__AXIIN, "astGetPV(%s): Axis index (%d) is invalid in "
2048 "attribute PV%d_%d - it should be in the range 1 to %d.",
2049 status, astGetClass( this ), i + 1, i + 1, m, astGetNin( this ) );
2050
2051 /* Find the maximum number of parameters allowed for the axis. */
2052 } else {
2053 mxpar = astGetPVMax( this, i );
2054
2055 /* Validate the parameter index. */
2056 if( m < 0 || m > mxpar ){
2057 astError( AST__AXIIN, "astGetPV(%s): Parameter index (%d) is invalid "
2058 "in attribute PV%d_%d for a \"%s\" projection - it should be "
2059 "in the range 0 to %d.", status, astGetClass( this ), m, i + 1, m,
2060 FindPrjData( this->type, status )->ctype, mxpar );
2061
2062 /* For latitude parameters use the values in the "params" structure which will
2063 have been defaulted. */
2064 } else if( i == astGetWcsAxis( this, 1 ) ) {
2065 ret = (this->params).p[ m ];
2066
2067 /* For other axes, see if the arrays stored in the WcsMap structure extend as
2068 far as the requested parameter. If so, return the required attribute value.
2069 Otherwise the AST__BAD value initialised above is retained. */
2070 } else if( this->np && this->p ){
2071 npar = this->np[ i ];
2072 if( m < npar && this->p[ i ] ) ret = this->p[ i ][ m ];
2073 }
2074
2075 /* FITS-WCS paper II gives defaults for the first 3 longitude axis
2076 parameters. The AST-specific TPN projection does not use this
2077 convention since it needs all projection parameters to specify
2078 correction terms. */
2079 if( ret == AST__BAD && i == astGetWcsAxis( this, 0 ) &&
2080 astGetWcsType( this ) != AST__TPN ) {
2081
2082 /* Parameter zero has a default of zero. */
2083 if( m == 0 ) {
2084 ret = 0.0;
2085
2086 /* Parameter one has a default equal to the native longitude of the
2087 reference point of the projection, in degrees. */
2088 } else if( m == 1 ) {
2089 ret = astGetNatLon( this )*AST__DR2D;
2090
2091 /* Parameter two has a default equal to the native latitude of the
2092 reference point of the projection (in degrees). This is constant for
2093 most projection, but for some (the conics) it is specified by
2094 projection one on the latitude axis. */
2095 } else if( m == 2 ) {
2096 ret = astGetNatLat( this )*AST__DR2D;
2097 }
2098 }
2099 }
2100
2101 return ret;
2102
2103 }
2104
GetPVMax(AstWcsMap * this,int i,int * status)2105 static int GetPVMax( AstWcsMap *this, int i, int *status ) {
2106 /*
2107 *+
2108 * Name:
2109 * astGetPVMax
2110
2111 * Purpose:
2112 * Get the maximum projection parameter index for a WcsMap.
2113
2114 * Type:
2115 * Protected function.
2116
2117 * Synopsis:
2118 * #include "wcsmap.h"
2119 * int astGetPVMax( AstWcsMap *this, int i )
2120
2121 * Class Membership:
2122 * WcsMap protected function
2123
2124 * Description:
2125 * This function returns the largest legal projection parameter index
2126 * for a specified axis of the given WcsMap (i.e. the largest value of
2127 * "m" in the attribute "PVi_m").
2128
2129 * Parameters:
2130 * this
2131 * A pointer to the WcsMap.
2132 * i
2133 * Zero based axis index.
2134
2135 * Returned Value:
2136 * The largest legal projection parameter index, or -1 if no
2137 * projection parameters are allowed on the specified axis.
2138
2139 *-
2140 */
2141
2142 /* Local Variables: */
2143 int mxpar;
2144
2145 /* Initialise */
2146 mxpar = 0;
2147
2148 /* Check the global error status. */
2149 if ( !astOK ) return -1;
2150
2151 /* Validate the axis index. */
2152 if( i < 0 || i >= astGetNin( this ) ){
2153 astError( AST__AXIIN, "astGetPVMax(%s): Axis index (%d) is invalid in "
2154 "attribute PVMax(%d) - it should be in the range 1 to %d.",
2155 status, astGetClass( this ), i + 1, i + 1, astGetNin( this ) );
2156
2157 /* Find the maximum number of parameters allowed for the axis. */
2158 } else if( i == astGetWcsAxis( this, 0 ) ) {
2159 mxpar = astSizeOf( this->params.p2 )/sizeof( double );
2160
2161 } else if( i == astGetWcsAxis( this, 1 ) ) {
2162 mxpar = astSizeOf( this->params.p )/sizeof( double );
2163
2164 }
2165
2166 /* The mxpar variable holds the max number of parameters. Return the the
2167 largest legal parameter index (one less than the max number of
2168 parameters). */
2169 return mxpar - 1;
2170 }
2171
InitPrjPrm(AstWcsMap * this,int * status)2172 static void InitPrjPrm( AstWcsMap *this, int *status ) {
2173 /*
2174 * Name:
2175 * InitPrjPrm
2176
2177 * Purpose:
2178 * Initialise the WcsLib PrjPrm structure, assigning default values for
2179 * missing parameters.
2180
2181 * Type:
2182 * Private function.
2183
2184 * Synopsis:
2185 * void InitPrjPrm( AstWcsMap *this, int *status )
2186
2187 * Description:
2188 * This function initializes the projection parameter information
2189 * stored within the WcsLib AstPrjPrm structure associated with the
2190 * supplied WcsMap. Default values are assigned to any unspecified
2191 * parameter values. AST__BAD values are assigned if any parameters
2192 * have not been supplied for which there is no default.
2193
2194 * Parameters:
2195 * this
2196 * The WcsMap.
2197 * status
2198 * Pointer to the inherited status variable.
2199
2200 */
2201
2202
2203 /* Local Variables: */
2204 struct AstPrjPrm *params; /* The AstPrjPrm structure from the WcsMap */
2205 int i; /* Loop index */
2206 int latax; /* Index of latitude axis */
2207 int lonax; /* Index of longitude axis */
2208 int npar; /* No. of parameters supplied */
2209 int plen; /* Length of params array */
2210 int plen2; /* Length of latitude params array */
2211 int type; /* Projection type */
2212
2213 /* Check the global error status. */
2214 if ( !astOK ) return;
2215
2216 /* Get a pointer to the AstPrjPrm structure*/
2217 params = &(this->params);
2218
2219 /* Tell the routines within the WcsLib "proj.c" module to re-calculate
2220 intermediate values. */
2221 params->flag = 0;
2222 params->r0 = 0;
2223
2224 /* If this is a TPN projection, indicate whether or not the
2225 transformation should include the TAN projection or just the
2226 polynomial transformation. */
2227 if( this->type == AST__TPN ) params->n = astGetTPNTan( this );
2228
2229 /* Find the max number of projection parameters associated with each
2230 axis.*/
2231 plen2 = astSizeOf( params->p2 )/sizeof( double );
2232 plen = astSizeOf( params->p )/sizeof( double );
2233
2234 /* Initially set all parameter to AST__BAD. */
2235 for( i = 0; i < plen; i++ ) (params->p)[i] = AST__BAD;
2236 for( i = 0; i < plen2; i++ ) (params->p2)[i] = AST__BAD;
2237
2238 /* If the WcsMap contains any projection parameter values... */
2239 if( this->np && this->p ){
2240
2241 /* Get the index of the latitude axis. Currently, all projection
2242 parameters are associated with the latitude axis (except for
2243 the TPN projection, which is a hang-over from a earlier draft of the
2244 FITS-WCS paper). */
2245 latax = astGetWcsAxis( this, 1 );
2246
2247 /* Find the number of projection parameters in the WcsMap for the
2248 latitude axis. */
2249 npar = (this->np)[ latax ];
2250 if( npar > plen ) {
2251 astError( AST__INTER, "InitPrjPrm(WcsMap): Too many projection "
2252 "parameters on the latitude axis (%d > %d) (internal "
2253 "AST programming error).", status, npar, plen );
2254 }
2255
2256 /* Copy the parameters to the AstPrjPrm structure. Do not copy more than
2257 can be stored in the AstPrjPrm structure. */
2258 for( i = 0; i < npar && i < plen; i++ ) {
2259 (params->p)[ i ] = (this->p)[ latax ][ i ];
2260 }
2261
2262 /* Do the same for the longitude axis (for the benefit of the TPN projection). */
2263 lonax = astGetWcsAxis( this, 0 );
2264 npar = (this->np)[ lonax ];
2265
2266 if( npar > plen2 ) {
2267 astError( AST__INTER, "InitPrjPrm(WcsMap): Too many projection "
2268 "parameters on the longitude axis (%d > %d) (internal "
2269 "AST programming error).", status, npar, plen2 );
2270 }
2271
2272 for( i = 0; i < npar && i < plen2; i++ ) {
2273 (params->p2)[ i ] = (this->p)[ lonax ][ i ];
2274 }
2275
2276 }
2277
2278 /* Get the projection type. */
2279 type = astGetWcsType( this );
2280
2281 /* First supply default values for any missing projection parameters which
2282 do not default to zero. */
2283 if( type == AST__SZP ){
2284 if( (params->p)[ 3 ] == AST__BAD ) (params->p)[ 3 ] = 90.0;
2285
2286 } else if( type == AST__AIR ){
2287 if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 90.0;
2288
2289 } else if( type == AST__CYP ){
2290 if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 1.0;
2291 if( (params->p)[ 2 ] == AST__BAD ) (params->p)[ 2 ] = 1.0;
2292
2293 } else if( type == AST__CEA ){
2294 if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 1.0;
2295
2296 } else if( type == AST__TPN ){
2297 if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 1.0;
2298 if( (params->p2)[ 1 ] == AST__BAD ) (params->p2)[ 1 ] = 1.0;
2299
2300 } else if( type == AST__HPX ){
2301 if( (params->p)[ 1 ] == AST__BAD ) (params->p)[ 1 ] = 4.0;
2302 if( (params->p)[ 2 ] == AST__BAD ) (params->p)[ 2 ] = 3.0;
2303
2304 }
2305
2306 /* Now use a default value of zero for any remaining unspecified values,
2307 except for un-defaultable projection parameters. */
2308 for( i = 0; i < plen; i++ ){
2309
2310 /* Retain any AST__BAD value for these undefaultable parameters. */
2311 if( i == 1 && ( type == AST__BON ||
2312 type == AST__COP || type == AST__COE ||
2313 type == AST__COD || type == AST__COO ) ){
2314
2315 /* Use a default of zero for all other parameters. */
2316 } else {
2317 if( (params->p)[ i ] == AST__BAD ) (params->p)[ i ] = 0.0;
2318 }
2319 }
2320
2321 /* Do the same for the latitude projection parameters (if any) */
2322 for( i = 0; i < plen2; i++ ){
2323 if( i == 1 && ( type == AST__BON ||
2324 type == AST__COP || type == AST__COE ||
2325 type == AST__COD || type == AST__COO ) ){
2326 } else {
2327 if( (params->p2)[ i ] == AST__BAD ) (params->p2)[ i ] = 0.0;
2328 }
2329 }
2330 }
2331
astInitWcsMapVtab_(AstWcsMapVtab * vtab,const char * name,int * status)2332 void astInitWcsMapVtab_( AstWcsMapVtab *vtab, const char *name, int *status ) {
2333 /*
2334 *+
2335 * Name:
2336 * astInitWcsMapVtab
2337
2338 * Purpose:
2339 * Initialise a virtual function table for a WcsMap.
2340
2341 * Type:
2342 * Protected function.
2343
2344 * Synopsis:
2345 * #include "wcsmap.h"
2346 * void astInitWcsMapVtab( AstWcsMapVtab *vtab, const char *name )
2347
2348 * Class Membership:
2349 * WcsMap vtab initialiser.
2350
2351 * Description:
2352 * This function initialises the component of a virtual function
2353 * table which is used by the WcsMap class.
2354
2355 * Parameters:
2356 * vtab
2357 * Pointer to the virtual function table. The components used by
2358 * all ancestral classes will be initialised if they have not already
2359 * been initialised.
2360 * name
2361 * Pointer to a constant null-terminated character string which contains
2362 * the name of the class to which the virtual function table belongs (it
2363 * is this pointer value that will subsequently be returned by the Object
2364 * astClass function).
2365 *-
2366 */
2367
2368 /* Local Variables: */
2369 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
2370 AstObjectVtab *object; /* Pointer to Object component of Vtab */
2371 AstMappingVtab *mapping; /* Pointer to Mapping component of Vtab */
2372
2373 /* Check the local error status. */
2374 if ( !astOK ) return;
2375
2376 /* Get a pointer to the thread specific global data structure. */
2377 astGET_GLOBALS(NULL);
2378
2379 /* Initialize the component of the virtual function table used by the
2380 parent class. */
2381 astInitMappingVtab( (AstMappingVtab *) vtab, name );
2382
2383 /* Store a unique "magic" value in the virtual function table. This
2384 will be used (by astIsAWcsMap) to determine if an object belongs
2385 to this class. We can conveniently use the address of the (static)
2386 class_check variable to generate this unique value. */
2387 vtab->id.check = &class_check;
2388 vtab->id.parent = &(((AstMappingVtab *) vtab)->id);
2389
2390 /* Initialise member function pointers. */
2391 /* ------------------------------------ */
2392 /* Store pointers to the member functions (implemented here) that provide
2393 virtual methods for this class. */
2394 vtab->ClearPV = ClearPV;
2395 vtab->GetNatLat = GetNatLat;
2396 vtab->GetNatLon = GetNatLon;
2397 vtab->GetPV = GetPV;
2398 vtab->GetWcsAxis = GetWcsAxis;
2399 vtab->GetPVMax = GetPVMax;
2400 vtab->GetWcsType = GetWcsType;
2401 vtab->SetPV = SetPV;
2402 vtab->TestPV = TestPV;
2403 vtab->IsZenithal = IsZenithal;
2404
2405 vtab->ClearFITSProj = ClearFITSProj;
2406 vtab->TestFITSProj = TestFITSProj;
2407 vtab->GetFITSProj = GetFITSProj;
2408 vtab->SetFITSProj = SetFITSProj;
2409
2410 vtab->ClearTPNTan = ClearTPNTan;
2411 vtab->TestTPNTan = TestTPNTan;
2412 vtab->GetTPNTan = GetTPNTan;
2413 vtab->SetTPNTan = SetTPNTan;
2414
2415 /* Save the inherited pointers to methods that will be extended, and
2416 replace them with pointers to the new member functions. */
2417 object = (AstObjectVtab *) vtab;
2418 mapping = (AstMappingVtab *) vtab;
2419 parent_getobjsize = object->GetObjSize;
2420 object->GetObjSize = GetObjSize;
2421
2422 parent_clearattrib = object->ClearAttrib;
2423 object->ClearAttrib = ClearAttrib;
2424 parent_getattrib = object->GetAttrib;
2425 object->GetAttrib = GetAttrib;
2426 parent_setattrib = object->SetAttrib;
2427 object->SetAttrib = SetAttrib;
2428 parent_testattrib = object->TestAttrib;
2429 object->TestAttrib = TestAttrib;
2430
2431 parent_transform = mapping->Transform;
2432 mapping->Transform = Transform;
2433
2434 parent_mapsplit = mapping->MapSplit;
2435 mapping->MapSplit = MapSplit;
2436
2437 /* Store replacement pointers for methods which will be over-ridden by
2438 new member functions implemented here. */
2439 object->Equal = Equal;
2440 mapping->MapMerge = MapMerge;
2441
2442 /* Declare the destructor and copy constructor. */
2443 astSetDelete( (AstObjectVtab *) vtab, Delete );
2444 astSetCopy( (AstObjectVtab *) vtab, Copy );
2445
2446 /* Declare the class dump function. */
2447 astSetDump( vtab, Dump, "WcsMap", "FITS-WCS sky projection" );
2448
2449 /* If we have just initialised the vtab for the current class, indicate
2450 that the vtab is now initialised, and store a pointer to the class
2451 identifier in the base "object" level of the vtab. */
2452 if( vtab == &class_vtab ) {
2453 class_init = 1;
2454 astSetVtabClassIdentifier( vtab, &(vtab->id) );
2455 }
2456 }
2457
IsZenithal(AstWcsMap * this,int * status)2458 static int IsZenithal( AstWcsMap *this, int *status ){
2459 /*
2460 *+
2461 * Name:
2462 * IsZenithal
2463
2464 * Purpose:
2465 * Determine if this WcsMap represents a zenithal projection.
2466
2467 * Type:
2468 * Protected function.
2469
2470 * Synopsis:
2471 * #include "wcsmap.h"
2472 * int IsZenithal( AstWcsMap *this, int *status )
2473
2474 * Class Membership:
2475 * WcsMap protected function
2476
2477 * Description:
2478 * This function returns a flag indicating if this WcsMap is a zenithal
2479 * projection. Some projections which are classed as zenithal in the
2480 * Calabretta and Greisen paper are only genuinely zenithal if the
2481 * projection parameters have certain values. These projections are
2482 * not considered to be zenithal unless the projection parameters have
2483 * appropriate values.
2484
2485 * Parameters:
2486 * this
2487 * The WcsMap.
2488 * status
2489 * Pointer to the inherited status variable.
2490
2491 * Returned Value:
2492 * A non-zero value if the WcsMap represents a zenithal projection.
2493
2494 *-
2495 */
2496
2497 /* Local Variables: */
2498 double p1; /* PVi_1 */
2499 double p2; /* PVi_2 */
2500 double p3; /* PVi_3 */
2501 int latax; /* Index of latitude axis */
2502 int ret; /* Returned flag */
2503 int type; /* Projection type */
2504
2505 /* Initialise the returned value. */
2506 ret = 0;
2507
2508 /* Check the global error status. */
2509 if ( !astOK ) return ret;
2510
2511 /* Get the projection type. */
2512 type = astGetWcsType( this );
2513
2514 /* Get the index of the latitude axis. */
2515 latax = astGetWcsAxis( this, 1 );
2516
2517 /* The following are always zenithal... */
2518 if( type == AST__TAN || type == AST__STG || type == AST__ARC ||
2519 type == AST__ZPN || type == AST__ZEA || type == AST__AIR ||
2520 type == AST__TPN ) {
2521 ret = 1;
2522
2523 /* The following are sometimes zenithal... */
2524 } else if( type == AST__AZP ) {
2525 p2 = astGetPV( this, latax, 2 );
2526 if( p2 == AST__BAD || p2 == 0.0 ) ret = 1;
2527
2528 } else if( type == AST__SIN ) {
2529 p1 = astGetPV( this, latax, 1 );
2530 p2 = astGetPV( this, latax, 2 );
2531 if( p1 == AST__BAD ) p1 = 0.0;
2532 if( p2 == AST__BAD ) p2 = 0.0;
2533 if( p1 == 0.0 && p2 == 0.0 ) ret = 1;
2534
2535 } else if( type == AST__SZP ) {
2536 p3 = astGetPV( this, latax, 2 );
2537 if( p3 == AST__BAD ) p3 = 90.0;
2538 if( p3 == 90.0 || p3 == -90.0 ) ret = 1;
2539
2540 }
2541
2542 return ret;
2543 }
2544
LongRange(const PrjData * prjdata,struct AstPrjPrm * params,double * high,double * low,int * status)2545 static int LongRange( const PrjData *prjdata, struct AstPrjPrm *params,
2546 double *high, double *low, int *status ){
2547 /*
2548 *
2549 * Name:
2550 * LongRange
2551
2552 * Purpose:
2553 * See if primary range of longitude produced by a WCSLIB mapping is
2554 * [0,360] or [-180,+180].
2555
2556 * Type:
2557 * Private function.
2558
2559 * Synopsis:
2560 * #include "wcsmap.h"
2561 * void LongRange( const PrjData *prjdata, struct AstPrjPrm *params,
2562 * double *high, double *low, int *status )
2563
2564 * Class Membership:
2565 * WcsMap internal utility function.
2566
2567 * Description:
2568 * This function uses the WCSLIB library to transform the supplied input
2569 * positions.
2570
2571 * Parameters:
2572 * prjdata
2573 * A pointer to information about the mapping.
2574 * params
2575 * Pointer to a WCSLIB "AstPrjPrm" structure containing the projection
2576 * parameters, etc.
2577 * high
2578 * A pointer to a location at which is returned the upper bound of
2579 * the primary longitude range.
2580 * low
2581 * A pointer to a location at which is returned the lower bound of
2582 * the primary longitude range.
2583 * status
2584 * Pointer to the inherited status variable.
2585
2586 * Returned Value:
2587 * A flag indicating if the sky->xy transformation is cyclic (i.e.
2588 * [a,0] gets mapped to the same (x,y) position as [a+2.PI,0]).
2589 */
2590
2591
2592 /* Local Variables: */
2593 int point; /* Loop counter for points */
2594 static double xx[ 4 ] = { -1.0E-6, 0.0, 1.0E-6, 0.0 };
2595 static double yy[ 4 ] = { 0.0, 1.0E-6, 0.0, -1.0E-6 };
2596 double aa;
2597 double bb;
2598 double xxx[ 2 ];
2599 double yyy[ 2 ];
2600 int cyclic;
2601
2602 /* Initialise the returned values. */
2603 *high = 180.0;
2604 *low = -180.0;
2605
2606 /* Check the global error status. */
2607 if ( !astOK ) return 0;
2608
2609 /* Project each of the points. If any longitude value is found which is
2610 greater than 180 degrees, return [0,360] as the longitude range. */
2611 for( point = 0; point < 4; point++ ){
2612 if( !prjdata->WcsRev( xx[ point ], yy[ point ], params, &aa, &bb ) ){
2613 if( aa > 180.0 ){
2614 *high = 360.0;
2615 *low = 0.0;
2616 break;
2617 }
2618 }
2619 }
2620
2621 /* See if the projection is cyclic. Transform the sky positions [90,bb] and
2622 [450,bb] into cartesian positions and see if they are the same. */
2623 prjdata->WcsFwd( 90.0, bb, params, xxx, yyy );
2624 prjdata->WcsFwd( 450.0, bb, params, xxx + 1, yyy + 1 );
2625 cyclic = ( fabs( xxx[ 0 ] - xxx[ 1 ] ) < 1.0E-10 &&
2626 fabs( yyy[ 0 ] - yyy[ 1 ] ) < 1.0E-10 );
2627
2628 /* Return. */
2629 return cyclic;
2630
2631 }
2632
Map(AstWcsMap * this,int forward,int npoint,double * in0,double * in1,double * out0,double * out1,int * status)2633 static int Map( AstWcsMap *this, int forward, int npoint, double *in0,
2634 double *in1, double *out0, double *out1, int *status ){
2635 /*
2636 *
2637 * Name:
2638 * Map
2639
2640 * Purpose:
2641 * Transform a set of points using a function from the WCSLIB library.
2642
2643 * Type:
2644 * Private function.
2645
2646 * Synopsis:
2647 * #include "wcsmap.h"
2648 * int Map( AstWcsMap *this, int forward, int npoint, double *in0,
2649 * double *in1, double *out0, double *out1 )
2650
2651 * Class Membership:
2652 * WcsMap internal utility function.
2653
2654 * Description:
2655 * This function uses the WCSLIB library to transform the supplied input
2656 * positions.
2657
2658 * Parameters:
2659 * this
2660 * Pointer to the WcsMap.
2661 * forward
2662 * A non-zero value indicates that the forward projection from
2663 * (long,lat) to (x,y) is required, while a zero value requests the
2664 * reverse transformation.
2665 * npoint
2666 * The number of points to transform (i.e. the size of the
2667 * in0, in1, out0 and out1 arrays).
2668 * in0
2669 * A pointer to the input coordinate data for the 0th axis (i.e.
2670 * longitude or X depending on "forward").
2671 * in1
2672 * A pointer to the input coordinate data for the 1st axis (i.e.
2673 * latitude or Y depending on "forward").
2674 * out0
2675 * A pointer to the returned output coordinate data for the 0th axis
2676 * (i.e. X or longitude depending on "forward").
2677 * out1
2678 * A pointer to the returned output coordinate data for the 1st axis
2679 * (i.e. Y or latitude depending on "forward").
2680
2681 * Returned Value:
2682 * The status value: 0 - Success
2683 * 1 - Unrecognised projection type
2684 * 2 - Invalid projection parameters values.
2685 * 4 - Error existed on entry
2686 * 100 - 399: Longitude axis projection parameter
2687 * (status-100) not supplied.
2688 * 400 - 699: Latitude axis projection parameter
2689 * (status-400) not supplied.
2690
2691
2692 * Notes:
2693 * - This function does not report any errors. Reporting of suitable
2694 * error messages is the responsibility of the calling function.
2695 * - The value 4 will be returned if this function is invoked with the
2696 * global error status set.
2697 *
2698 */
2699
2700 /* Local Variables: */
2701 const PrjData *prjdata; /* Information about the projection */
2702 double factor; /* Factor that scales input into radians. */
2703 double latitude; /* Latitude value in degrees */
2704 double longhi; /* Upper longitude limit in degrees */
2705 double longitude; /* Longitude value in degrees */
2706 double longlo; /* Lower longitude limit in degrees */
2707 double x; /* X Cartesian coordinate in degrees */
2708 double y; /* Y Cartesian coordinate in degrees */
2709 int cyclic; /* Is sky->xy transformation cyclic? */
2710 int i; /* Loop count */
2711 int plen; /* Length of proj par array */
2712 int point; /* Loop counter for points */
2713 int type; /* Projection type */
2714 int wcs_status; /* Status from WCSLIB functions */
2715 struct AstPrjPrm *params; /* Pointer to structure holding WCSLIB info */
2716
2717 /* Check the global error status. */
2718 if ( !astOK ) return 4;
2719
2720 /* Initialise variables to avoid compiler warnings. */
2721 longlo = AST__BAD;
2722 longhi = AST__BAD;
2723
2724 /* Store the projection type. */
2725 type = astGetWcsType( this );
2726
2727 /* Get information about the projection. */
2728 prjdata = FindPrjData( type, status );
2729
2730 /* Return if there are no WcsLib mapping functons associated with the
2731 projection. */
2732 if( ( !prjdata->WcsFwd && forward ) ||
2733 ( !prjdata->WcsRev && !forward ) ) return 1;
2734
2735 /* Check that all necessary projection parameters have been supplied, or
2736 can be defaulted. */
2737 params = &(this->params);
2738 plen = astSizeOf( params->p )/sizeof( double );
2739 for( i = 0; i < plen; i++ ) {
2740 if( ( params->p)[ i ] == AST__BAD ) return 400+i;
2741 }
2742
2743 /* If we are doing a reverse mapping, get the acceptable range of longitude
2744 values. */
2745 cyclic = forward ? 0 : LongRange( prjdata, params, &longhi, &longlo,
2746 status );
2747
2748 /* The WcsMap input and output values are normally in radians, but if
2749 the TPNTan attribute has been reset then they are in degrees. The
2750 WCSLIB projection functions always expect and return degrees. Get
2751 the factor that scales the WcsMap input into radians. */
2752 factor = astGetTPNTan( this ) ? 1.0 : AST__DD2R;
2753
2754 /* Loop to apply the projection to each point in turn, checking for
2755 (and propagating) bad values in the process. */
2756 for ( point = 0; point < npoint; point++ ) {
2757 if ( in0[ point ] == AST__BAD ||
2758 in1[ point ] == AST__BAD ){
2759 out0[ point ] = AST__BAD;
2760 out1[ point ] = AST__BAD;
2761 } else {
2762
2763 /* First deal with forward projection calls */
2764 if ( forward ){
2765
2766 /* The input coordinates are assumed to be longitude and latitude, in
2767 radians or degrees (as specified by the TPNTan attribute). Convert them
2768 to degrees ensuring that the longitude value is in the range [-180,180]
2769 and the latitude is in the range [-90,90] (as required by the WCSLIB
2770 library). Any point with a latitude outside the range [-90,90] is
2771 converted to the equivalent point on the complementary meridian. */
2772 latitude = AST__DR2D*palDrange( factor*in1[ point ] );
2773 if ( latitude > 90.0 ){
2774 latitude = 180.0 - latitude;
2775 longitude = AST__DR2D*palDrange( AST__DPI + factor*in0[ point ] );
2776
2777 } else if ( latitude < -90.0 ){
2778 latitude = -180.0 - latitude;
2779 longitude = AST__DR2D*palDrange( AST__DPI + factor*in0[ point ] );
2780
2781 } else {
2782 longitude = AST__DR2D*palDrange( factor*in0[ point ] );
2783 }
2784
2785 /* Call the relevant WCSLIB forward projection function. */
2786 wcs_status = prjdata->WcsFwd( longitude, latitude, params, &x, &y );
2787
2788 /* Store the returned Cartesian coordinates, converting them from degrees
2789 to radians. If the position could not be projected, use the value
2790 AST__BAD. Abort for any other bad status. */
2791 if( wcs_status == 0 ){
2792 out0[ point ] = (AST__DD2R/factor)*x;
2793 out1[ point ] = (AST__DD2R/factor)*y;
2794
2795 } else if( wcs_status == 1 ){
2796 return 2;
2797
2798 } else if( wcs_status == 2 ){
2799 out0[ point ] = AST__BAD;
2800 out1[ point ] = AST__BAD;
2801
2802 } else {
2803 return wcs_status;
2804 }
2805
2806 /* Now deal with reverse projection calls */
2807 } else {
2808
2809 /* Convert the supplied Cartesian coordinates from radians to degrees. */
2810 x = (AST__DR2D*factor)*in0[ point ];
2811 y = (AST__DR2D*factor)*in1[ point ];
2812
2813 /* Call the relevant WCSLIB reverse projection function. */
2814 wcs_status = prjdata->WcsRev( x, y, params, &longitude, &latitude );
2815
2816 /* Store the returned longitude and latitude, converting them from degrees
2817 to radians. Many projections (ARC, AIT, ZPN, etc) are not cyclic (i.e.
2818 [long,lat]=[0,0] does not get mapped to the same place as
2819 [long,lat]=[360,0] ). Only accept values in the primary longitude or
2820 latitude ranges. This avoids (x,y) points outside the physical domain
2821 of the mapping being assigned valid (long,lat) values. */
2822 if( wcs_status == 0 ){
2823 if( ( cyclic || ( longitude < longhi &&
2824 longitude >= longlo ) ) &&
2825 fabs( latitude ) <= 90.0 ){
2826
2827 out0[ point ] = (AST__DD2R/factor)*longitude;
2828 out1[ point ] = (AST__DD2R/factor)*latitude;
2829
2830 } else {
2831 out0[ point ] = AST__BAD;
2832 out1[ point ] = AST__BAD;
2833 }
2834
2835 /* Abort if projection parameters were unusable. */
2836 } else if( wcs_status == 1 ){
2837 return 2;
2838
2839 /* If the position could not be projected, use the value AST__BAD. */
2840 } else if( wcs_status == 2 ){
2841 out0[ point ] = AST__BAD;
2842 out1[ point ] = AST__BAD;
2843
2844 /* Abort if projection parameters were not supplied. */
2845 } else {
2846 return wcs_status;
2847 }
2848
2849 }
2850
2851 }
2852
2853 }
2854
2855 return 0;
2856 }
2857
MapMerge(AstMapping * this,int where,int series,int * nmap,AstMapping *** map_list,int ** invert_list,int * status)2858 static int MapMerge( AstMapping *this, int where, int series, int *nmap,
2859 AstMapping ***map_list, int **invert_list, int *status ) {
2860 /*
2861 * Name:
2862 * MapMerge
2863
2864 * Purpose:
2865 * Simplify a sequence of Mappings containing a WcsMap.
2866
2867 * Type:
2868 * Private function.
2869
2870 * Synopsis:
2871 * #include "wcsmap.h"
2872 * int MapMerge( AstMapping *this, int where, int series, int *nmap,
2873 * AstMapping ***map_list, int **invert_list, int *status )
2874
2875 * Class Membership:
2876 * WcsMap method (over-rides the protected astMapMerge method
2877 * inherited from the Mapping class).
2878
2879 * Description:
2880 * This function attempts to simplify a sequence of Mappings by
2881 * merging a nominated WcsMap in the sequence with its neighbours,
2882 * so as to shorten the sequence if possible.
2883 *
2884 * In many cases, simplification will not be possible and the
2885 * function will return -1 to indicate this, without further
2886 * action.
2887 *
2888 * In most cases of interest, however, this function will either
2889 * attempt to replace the nominated WcsMap with a Mapping which it
2890 * considers simpler, or to merge it with the Mappings which
2891 * immediately precede it or follow it in the sequence (both will
2892 * normally be considered). This is sufficient to ensure the
2893 * eventual simplification of most Mapping sequences by repeated
2894 * application of this function.
2895 *
2896 * In some cases, the function may attempt more elaborate
2897 * simplification, involving any number of other Mappings in the
2898 * sequence. It is not restricted in the type or scope of
2899 * simplification it may perform, but will normally only attempt
2900 * elaborate simplification in cases where a more straightforward
2901 * approach is not adequate.
2902
2903 * Parameters:
2904 * this
2905 * Pointer to the nominated WcsMap which is to be merged with
2906 * its neighbours. This should be a cloned copy of the WcsMap
2907 * pointer contained in the array element "(*map_list)[where]"
2908 * (see below). This pointer will not be annulled, and the
2909 * WcsMap it identifies will not be modified by this function.
2910 * where
2911 * Index in the "*map_list" array (below) at which the pointer
2912 * to the nominated WcsMap resides.
2913 * series
2914 * A non-zero value indicates that the sequence of Mappings to
2915 * be simplified will be applied in series (i.e. one after the
2916 * other), whereas a zero value indicates that they will be
2917 * applied in parallel (i.e. on successive sub-sets of the
2918 * input/output coordinates).
2919 * nmap
2920 * Address of an int which counts the number of Mappings in the
2921 * sequence. On entry this should be set to the initial number
2922 * of Mappings. On exit it will be updated to record the number
2923 * of Mappings remaining after simplification.
2924 * map_list
2925 * Address of a pointer to a dynamically allocated array of
2926 * Mapping pointers (produced, for example, by the astMapList
2927 * method) which identifies the sequence of Mappings. On entry,
2928 * the initial sequence of Mappings to be simplified should be
2929 * supplied.
2930 *
2931 * On exit, the contents of this array will be modified to
2932 * reflect any simplification carried out. Any form of
2933 * simplification may be performed. This may involve any of: (a)
2934 * removing Mappings by annulling any of the pointers supplied,
2935 * (b) replacing them with pointers to new Mappings, (c)
2936 * inserting additional Mappings and (d) changing their order.
2937 *
2938 * The intention is to reduce the number of Mappings in the
2939 * sequence, if possible, and any reduction will be reflected in
2940 * the value of "*nmap" returned. However, simplifications which
2941 * do not reduce the length of the sequence (but improve its
2942 * execution time, for example) may also be performed, and the
2943 * sequence might conceivably increase in length (but normally
2944 * only in order to split up a Mapping into pieces that can be
2945 * more easily merged with their neighbours on subsequent
2946 * invocations of this function).
2947 *
2948 * If Mappings are removed from the sequence, any gaps that
2949 * remain will be closed up, by moving subsequent Mapping
2950 * pointers along in the array, so that vacated elements occur
2951 * at the end. If the sequence increases in length, the array
2952 * will be extended (and its pointer updated) if necessary to
2953 * accommodate any new elements.
2954 *
2955 * Note that any (or all) of the Mapping pointers supplied in
2956 * this array may be annulled by this function, but the Mappings
2957 * to which they refer are not modified in any way (although
2958 * they may, of course, be deleted if the annulled pointer is
2959 * the final one).
2960 * invert_list
2961 * Address of a pointer to a dynamically allocated array which,
2962 * on entry, should contain values to be assigned to the Invert
2963 * attributes of the Mappings identified in the "*map_list"
2964 * array before they are applied (this array might have been
2965 * produced, for example, by the astMapList method). These
2966 * values will be used by this function instead of the actual
2967 * Invert attributes of the Mappings supplied, which are
2968 * ignored.
2969 *
2970 * On exit, the contents of this array will be updated to
2971 * correspond with the possibly modified contents of the
2972 * "*map_list" array. If the Mapping sequence increases in
2973 * length, the "*invert_list" array will be extended (and its
2974 * pointer updated) if necessary to accommodate any new
2975 * elements.
2976 * status
2977 * Pointer to the inherited status variable.
2978
2979 * Returned Value:
2980 * If simplification was possible, the function returns the index
2981 * in the "map_list" array of the first element which was
2982 * modified. Otherwise, it returns -1 (and makes no changes to the
2983 * arrays supplied).
2984
2985 * Notes:
2986 * - A value of -1 will be returned if this function is invoked
2987 * with the global error status set, or if it should fail for any
2988 * reason.
2989 */
2990
2991 /* Local Variables: */
2992 AstMapping *mc[2]; /* Copies of supplied Mappings to swap */
2993 AstMapping *smc0; /* Simplied Mapping */
2994 AstMapping *smc1; /* Simplied Mapping */
2995 const char *nclass; /* Pointer to neighbouring Mapping class */
2996 const char *class1; /* Pointer to first Mapping class string */
2997 const char *class2; /* Pointer to second Mapping class string */
2998 int do1; /* Would a backward swap make a simplification? */
2999 int do2; /* Would a forward swap make a simplification? */
3000 int i1; /* Lower index of the two WcsMaps being merged */
3001 int i2; /* Upper index of the two WcsMaps being merged */
3002 int i; /* Mapping index */
3003 int ic[2]; /* Copies of supplied invert flags to swap */
3004 int merge; /* Can WcsMap merge with a neighbour? */
3005 int nin; /* Number of coordinates for WcsMap */
3006 int nstep1; /* No. of Mappings backwards to next mergable Mapping */
3007 int nstep2; /* No. of Mappings forward to next mergable Mapping */
3008 int result; /* Result value to return */
3009 int swaphi; /* Can WcsMap be swapped with higher neighbour? */
3010 int swaplo; /* Can WcsMap be swapped with lower neighbour? */
3011 int type; /* Projection type */
3012
3013 /* Initialise. */
3014 result = -1;
3015
3016 /* Check the global error status. */
3017 if ( !astOK ) return result;
3018
3019 /* Initialise variables to avoid "used of uninitialised variable"
3020 messages from dumb compilers. */
3021 i1 = 0;
3022 i2 = 0;
3023
3024 /* Get the number of axes for the WcsMap. */
3025 nin = astGetNin( ( *map_list )[ where ] );
3026
3027 /* First of all, see if the WcsMap can be replaced by a simpler Mapping,
3028 without reference to the neighbouring Mappings in the list. */
3029 /* ======================================================================*/
3030 /* WcsMaps with map type of AST__WCSBAD are equivalent to a UnitMap. */
3031 type = astGetWcsType( this );
3032 if( type == AST__WCSBAD ){
3033
3034 /* Annul the WcsMap pointer in the list and replace it with a UnitMap
3035 pointer, and indicate that the forward transformation of the returned
3036 UnitMap should be used. */
3037 (void) astAnnul( ( *map_list )[ where ] );
3038 ( *map_list )[ where ] = (AstMapping *) astUnitMap( nin, "", status );
3039 ( *invert_list )[ where ] = 0;
3040
3041 /* Return the index of the first modified element. */
3042 result = where;
3043
3044 /* If the WcsMap itself could not be simplified, see if it can be merged
3045 with the Mappings on either side of it in the list. This can only be
3046 done in series for a WcsMap. */
3047 /* ===================================================================== */
3048 } else if( series && *nmap > 1 ) {
3049
3050 /* Store the classes of the neighbouring Mappings in the list. */
3051 class1 = ( where > 0 ) ? astGetClass( ( *map_list )[ where - 1 ] ) : NULL;
3052 class2 = ( where < *nmap - 1 ) ? astGetClass( ( *map_list )[ where + 1 ] ) : NULL;
3053
3054 /* A WcsMap can only combine with its own inverse. Set a flag indicating
3055 that we have not yet found a neighbour with which the WcsMap can be
3056 merged. */
3057 merge = 0;
3058
3059 /* First check the lower neighbour (if any). */
3060 if( where > 0 ) {
3061 i1 = where - 1;
3062 i2 = where;
3063 merge = CanMerge( ( *map_list )[ i1 ], (* invert_list)[ i1 ],
3064 ( *map_list )[ i2 ], (* invert_list)[ i2 ], status );
3065 }
3066
3067 /* If the WcsMap can not be merged with its lower neighbour, check its
3068 upper neighbour (if any) in the same way. */
3069 if( !merge && where < *nmap - 1 ) {
3070 i1 = where;
3071 i2 = where + 1;
3072 merge = CanMerge( ( *map_list )[ i1 ], (* invert_list)[ i1 ],
3073 ( *map_list )[ i2 ], (* invert_list)[ i2 ], status );
3074 }
3075
3076 /* If either neighbour has passed these checks, it is the inverse of the
3077 WcsMap being checked. The pair of WcsMaps can be replaced by a single
3078 UnitMap. */
3079 if( merge ) {
3080
3081 /* Annul the two WcsMaps. */
3082 (void) astAnnul( ( *map_list )[ i1 ] );
3083 (void) astAnnul( ( *map_list )[ i2 ] );
3084
3085 /* Create a UnitMap, and store a pointer for it in place of the first
3086 WcsMap. */
3087 ( *map_list )[ i1 ] = (AstMapping *) astUnitMap( nin, "", status );
3088 ( *invert_list )[ i1 ] = 0;
3089
3090 /* Shuffle down the remaining Mappings to fill the hole left by the
3091 second WcsMap. */
3092 for ( i = i2 + 1; i < *nmap; i++ ) {
3093 ( *map_list )[ i - 1 ] = ( *map_list )[ i ];
3094 ( *invert_list )[ i - 1 ] = ( *invert_list )[ i ];
3095 }
3096
3097 /* Clear the vacated element at the end. */
3098 ( *map_list )[ *nmap - 1 ] = NULL;
3099 ( *invert_list )[ *nmap - 1 ] = 0;
3100
3101 /* Decrement the Mapping count and return the index of the first
3102 modified element. */
3103 (*nmap)--;
3104 result = i1;
3105
3106 /* If the WcsMap could not merge directly with either of its neighbours,
3107 we consider whether it would be worthwhile to swap the WcsMap with
3108 either of its neighbours. This can only be done for certain PermMaps,
3109 and will usually require both Mappings to be modified (unless they are
3110 commutative). The advantage of swapping the order of the Mappings is that
3111 it may result in the WcsMap being adjacent to a Mapping with which it can
3112 merge directly on the next invocation of this function, thus reducing the
3113 number of Mappings in the list. */
3114 } else {
3115
3116 /* Set a flag if we could swap the WcsMap with its higher neighbour. "do2"
3117 is returned if swapping the Mappings would simplify either of the
3118 Mappings. */
3119 if( where + 1 < *nmap ){
3120 swaphi = CanSwap( ( *map_list )[ where ],
3121 ( *map_list )[ where + 1 ],
3122 ( *invert_list )[ where ],
3123 ( *invert_list )[ where + 1 ], &do2, status );
3124 } else {
3125 do2 = 0;
3126 swaphi = 0;
3127 }
3128
3129 /* If so, step through each of the Mappings which follow the WcsMap,
3130 looking for a Mapping with which the WcsMap could merge directly. Stop
3131 when such a Mapping is found, or if a Mapping is found with which the
3132 WcsMap could definitely not swap. Note the number of Mappings which
3133 separate the WcsMap from the Mapping with which it could merge (if
3134 any). */
3135 nstep2 = -1;
3136 if( swaphi ){
3137 for( i2 = where + 1; i2 < *nmap; i2++ ){
3138
3139 /* See if we can merge with this Mapping. If so, note the number of steps
3140 between the two Mappings and leave the loop. */
3141 if( CanMerge( ( *map_list )[ i2 ], ( *invert_list )[ i2 ],
3142 ( *map_list )[ where ], ( *invert_list )[ where ], status ) ) {
3143 nstep2 = i2 - where - 1;
3144 break;
3145 }
3146
3147 /* If there is no chance that we can swap with this Mapping, leave the loop
3148 with -1 for the number of steps to indicate that no merging is possible.
3149 WcsMaps can swap only with some PermMaps. */
3150 nclass = astGetClass( ( *map_list )[ i2 ] );
3151 if( strcmp( nclass, "PermMap" ) ) {
3152 break;
3153 }
3154
3155 }
3156
3157 }
3158
3159 /* Do the same working forward from the WcsMap towards the start of the map
3160 list. */
3161 if( where > 0 ){
3162 swaplo = CanSwap( ( *map_list )[ where - 1 ],
3163 ( *map_list )[ where ],
3164 ( *invert_list )[ where - 1 ],
3165 ( *invert_list )[ where ], &do1, status );
3166 } else {
3167 do1 = 0;
3168 swaplo = 0;
3169 }
3170
3171 nstep1 = -1;
3172 if( swaplo ){
3173 for( i1 = where - 1; i1 >= 0; i1-- ){
3174
3175 if( CanMerge( ( *map_list )[ i1 ], ( *invert_list )[ i1 ],
3176 ( *map_list )[ where ], ( *invert_list )[ where ], status ) ) {
3177 nstep1 = where - 1 - i1;
3178 break;
3179 }
3180
3181 nclass = astGetClass( ( *map_list )[ i1 ] );
3182 if( strcmp( nclass, "PermMap" ) ) {
3183 break;
3184 }
3185
3186 }
3187
3188 }
3189
3190 /* Choose which neighbour to swap with so that the WcsMap moves towards the
3191 nearest Mapping with which it can merge. */
3192 if( do1 || (
3193 nstep1 != -1 && ( nstep2 == -1 || nstep2 > nstep1 ) ) ){
3194 nclass = class1;
3195 i1 = where - 1;
3196 i2 = where;
3197 } else if( do2 || nstep2 != -1 ){
3198 nclass = class2;
3199 i1 = where;
3200 i2 = where + 1;
3201 } else {
3202 nclass = NULL;
3203 }
3204
3205 /* If there is a target Mapping in the list with which the WcsMap could
3206 merge, replace the supplied Mappings with swapped Mappings to bring a
3207 WcsMap closer to the target Mapping. */
3208 if( nclass ){
3209
3210 WcsPerm( (*map_list) + i1, (*invert_list) + i1, where - i1, status );
3211
3212 /* Store the index of the first modified Mapping. */
3213 result = i1;
3214
3215 /* If there is no Mapping available for merging, it may still be
3216 advantageous to swap with a neighbour because the swapped Mapping may
3217 be simpler than the original Mappings. */
3218 } else if( swaphi || swaplo ) {
3219
3220 /* Choose a neightbour to swap with. If both are suitable for swapping,
3221 swap with the lower. */
3222 if( swaplo ){
3223 nclass = class1;
3224 i1 = where - 1;
3225 i2 = where;
3226 } else {
3227 nclass = class2;
3228 i1 = where;
3229 i2 = where + 1;
3230 }
3231
3232 /* Take copies of the Mapping and Invert flag arrays so we do not change
3233 the supplied values. */
3234 mc[ 0 ] = (AstMapping *) astCopy( ( (*map_list) + i1 )[0] );
3235 mc[ 1 ] = (AstMapping *) astCopy( ( (*map_list) + i1 )[1] );
3236 ic[ 0 ] = ( (*invert_list) + i1 )[0];
3237 ic[ 1 ] = ( (*invert_list) + i1 )[1];
3238
3239 /* Swap these Mappings. */
3240 WcsPerm( mc, ic, where - i1, status );
3241
3242 /* If neither of the swapped Mappings can be simplified further, then there
3243 is no point in swapping the Mappings, so just annul the map copies. */
3244 smc0 = astSimplify( mc[0] );
3245 smc1 = astSimplify( mc[1] );
3246
3247 if( astGetClass( smc0 ) == astGetClass( mc[0] ) &&
3248 astGetClass( smc1 ) == astGetClass( mc[1] ) ) {
3249
3250 mc[ 0 ] = (AstMapping *) astAnnul( mc[ 0 ] );
3251 mc[ 1 ] = (AstMapping *) astAnnul( mc[ 1 ] );
3252
3253 /* If one or both of the swapped Mappings could be simplified, then annul
3254 the supplied Mappings and return the swapped mappings, storing the index
3255 of the first modified Mapping. */
3256 } else {
3257 (void ) astAnnul( ( (*map_list) + i1 )[0] );
3258 (void ) astAnnul( ( (*map_list) + i1 )[1] );
3259
3260 ( (*map_list) + i1 )[0] = mc[ 0 ];
3261 ( (*map_list) + i1 )[1] = mc[ 1 ];
3262
3263 ( (*invert_list) + i1 )[0] = ic[ 0 ];
3264 ( (*invert_list) + i1 )[1] = ic[ 1 ];
3265
3266 result = i1;
3267
3268 }
3269
3270 /* Annul the simplied Mappings */
3271 smc0 = astAnnul( smc0 );
3272 smc1 = astAnnul( smc1 );
3273
3274 }
3275 }
3276 }
3277
3278 /* Return the result. */
3279 return result;
3280 }
3281
MapSplit(AstMapping * this_map,int nin,const int * in,AstMapping ** map,int * status)3282 static int *MapSplit( AstMapping *this_map, int nin, const int *in, AstMapping **map, int *status ){
3283 /*
3284 * Name:
3285 * MapSplit
3286
3287 * Purpose:
3288 * Create a Mapping representing a subset of the inputs of an existing
3289 * WcsMap.
3290
3291 * Type:
3292 * Private function.
3293
3294 * Synopsis:
3295 * #include "wcsmap.h"
3296 * int *MapSplit( AstMapping *this, int nin, const int *in, AstMapping **map, int *status )
3297
3298 * Class Membership:
3299 * WcsMap method (over-rides the protected astMapSplit method
3300 * inherited from the Mapping class).
3301
3302 * Description:
3303 * This function creates a new Mapping by picking specified inputs from
3304 * an existing WcsMap. This is only possible if the specified inputs
3305 * correspond to some subset of the WcsMap outputs. That is, there
3306 * must exist a subset of the WcsMap outputs for which each output
3307 * depends only on the selected WcsMap inputs, and not on any of the
3308 * inputs which have not been selected. If this condition is not met
3309 * by the supplied WcsMap, then a NULL Mapping is returned.
3310
3311 * Parameters:
3312 * this
3313 * Pointer to the WcsMap to be split (the WcsMap is not actually
3314 * modified by this function).
3315 * nin
3316 * The number of inputs to pick from "this".
3317 * in
3318 * Pointer to an array of indices (zero based) for the inputs which
3319 * are to be picked. This array should have "nin" elements. If "Nin"
3320 * is the number of inputs of the supplied WcsMap, then each element
3321 * should have a value in the range zero to Nin-1.
3322 * map
3323 * Address of a location at which to return a pointer to the new
3324 * Mapping. This Mapping will have "nin" inputs (the number of
3325 * outputs may be different to "nin"). A NULL pointer will be
3326 * returned if the supplied WcsMap has no subset of outputs which
3327 * depend only on the selected inputs.
3328 * status
3329 * Pointer to the inherited status variable.
3330
3331 * Returned Value:
3332 * A pointer to a dynamically allocated array of ints. The number of
3333 * elements in this array will equal the number of outputs for the
3334 * returned Mapping. Each element will hold the index of the
3335 * corresponding output in the supplied WcsMap. The array should be
3336 * freed using astFree when no longer needed. A NULL pointer will
3337 * be returned if no output Mapping can be created.
3338
3339 * Notes:
3340 * - If this function is invoked with the global error status set,
3341 * or if it should fail for any reason, then NULL values will be
3342 * returned as the function value and for the "map" pointer.
3343 */
3344
3345 /* Local Variables: */
3346 AstWcsMap *newwcs; /* Pointer to returned WcsMap */
3347 AstWcsMap *this; /* Pointer to WcsMap structure */
3348 int *result; /* Pointer to returned array */
3349 int *inperm; /* Input axis permutation array */
3350 int *outperm; /* Output axis permutation array */
3351 int i; /* Loop count */
3352 int iin; /* Mapping input index */
3353 int ilat; /* Index of latitude axis in new WcsMap */
3354 int ilatlon; /* Index of last lat or lon axis */
3355 int ilon; /* Index of longitude axis in new WcsMap */
3356 int latax; /* Index of latitude axis in supplied WcsMap */
3357 int lonax; /* Index of longitude axis in supplied WcsMap */
3358 int mnin; /* No. of Mapping inputs */
3359 int ok; /* Are input indices OK? */
3360
3361 /* Initialise */
3362 result = NULL;
3363 *map = NULL;
3364
3365 /* Check the global error status. */
3366 if ( !astOK ) return result;
3367
3368 /* Invoke the parent astMapSplit method to see if it can do the job. */
3369 result = (*parent_mapsplit)( this_map, nin, in, map, status );
3370
3371 /* If not, we provide a special implementation here. */
3372 if( !result ) {
3373
3374 /* Get a pointer to the WcsMap structure. */
3375 this = (AstWcsMap *) this_map;
3376
3377 /* Prevent compiler warnings. */
3378 ilatlon = -1;
3379
3380 /* Allocate memory for the returned array. */
3381 result = astMalloc( sizeof( int )*(size_t) nin );
3382 if( astOK ) {
3383
3384 /* Get the indices of the longitude and latitude axes in the WcsMap */
3385 lonax = astGetWcsAxis( this, 0 );
3386 latax = astGetWcsAxis( this, 1 );
3387
3388 /* See if the selected axes include the longitude and/or latitude axis.
3389 At the same time check the axis indices are ok, and set up the output
3390 axis array. */
3391 ilat = -1;
3392 ilon = -1;
3393 mnin = astGetNin( this );
3394 ok = 1;
3395 for( i = 0; i < nin; i++ ) {
3396 iin = in[ i ];
3397 if( iin < 0 || iin >= mnin ) {
3398 ok = 0;
3399 break;
3400 } else if( iin == lonax ) {
3401 ilon = i;
3402 ilatlon = i;
3403 } else if( iin == latax ) {
3404 ilat = i;
3405 ilatlon = i;
3406 }
3407 result[ i ] = iin;
3408 }
3409
3410 /* If any of the input indices were invalid, free the returned array. */
3411 if( !ok ) {
3412 result = astFree( result );
3413
3414 /* If both longitude and latitude axes are selected, then the returned Mapping
3415 is a WcsMap. Create one based on the supplied WcsMap. */
3416 } else if( ilat != -1 && ilon != -1 ) {
3417 newwcs = astWcsMap( nin, astGetWcsType( this ), ilon + 1, ilat + 1,
3418 "", status );
3419 CopyPV( this, newwcs, status );
3420 astSetInvert( newwcs, astGetInvert( this ) );
3421 *map = (AstMapping *) newwcs;
3422
3423 /* If neither the longitude nor the latitude axis has been selected, then
3424 the returned Mapping is a UnitMap. */
3425 } else if( ilat == -1 && ilon == -1 ) {
3426 *map = (AstMapping *) astUnitMap( nin, "", status );
3427
3428 /* If only one of the latitude and longitude axes was selected we remove
3429 it from the returned Mapping (a PermMap) and list of outputs */
3430 } else if( nin > 1 ) {
3431
3432 for( i = ilatlon; i < nin - 1; i++ ) {
3433 result[ i ] = result[ i + 1 ];
3434 }
3435 result[ i ] = -1;
3436
3437 inperm = astMalloc( sizeof( int )*(size_t) nin );
3438 outperm = astMalloc( sizeof( int )*(size_t) ( nin - 1 ) );
3439 if( outperm ) {
3440 for( i = 0; i < ilatlon; i++ ) {
3441 inperm[ i ] = i;
3442 outperm[ i ] = i;
3443 }
3444 inperm[ ilatlon ] = INT_MAX;
3445 for( i = ilatlon + 1; i < nin; i++ ) {
3446 inperm[ i ] = i - 1;
3447 outperm[ i - 1 ] = i;
3448 }
3449
3450 *map = (AstMapping *) astPermMap( nin, inperm, nin - 1, outperm, NULL, " ", status );
3451
3452 }
3453 inperm = astFree( inperm );
3454 outperm = astFree( outperm );
3455
3456 } else {
3457 result = astFree( result );
3458 }
3459 }
3460 }
3461
3462 /* Free returned resources if an error has occurred. */
3463 if( !astOK ) {
3464 result = astFree( result );
3465 *map = astAnnul( *map );
3466 }
3467
3468 /* Return the list of output indices. */
3469 return result;
3470 }
3471
PermGet(AstPermMap * map,int ** outperm,int ** inperm,double ** consts,int * status)3472 static void PermGet( AstPermMap *map, int **outperm, int **inperm,
3473 double **consts, int *status ){
3474 /*
3475 * Name:
3476 * PermGet
3477
3478 * Purpose:
3479 * Get the axis permutation and constants array for a PermMap.
3480
3481 * Type:
3482 * Private function.
3483
3484 * Synopsis:
3485 * #include "wcsmap.h"
3486 * void PermGet( AstPermMap *map, int **outperm, int **inperm,
3487 * double **const, int *status )
3488
3489 * Class Membership:
3490 * WcsMap member function
3491
3492 * Description:
3493 * This function returns axis permutation and constants arrays which can
3494 * be used to create a PermMap which is equivalent to the supplied PermMap.
3495
3496 * Parameters:
3497 * map
3498 * The PermMap.
3499 * outperm
3500 * An address at which to return a popinter to an array of ints
3501 * holding the output axis permutation array. The array should be
3502 * released using astFree when no longer needed.
3503 * inperm
3504 * An address at which to return a popinter to an array of ints
3505 * holding the input axis permutation array. The array should be
3506 * released using astFree when no longer needed.
3507 * consts
3508 * An address at which to return a popinter to an array of doubles
3509 * holding the constants array. The array should be released using
3510 * astFree when no longer needed.
3511 * status
3512 * Pointer to the inherited status variable.
3513
3514 * Notes:
3515 * - NULL pointers are returned if an error has already occurred, or if
3516 * this function should fail for any reason.
3517 */
3518
3519 /* Local Variables: */
3520 AstPointSet *pset1; /* PointSet holding input positions for PermMap */
3521 AstPointSet *pset2; /* PointSet holding output positions for PermMap */
3522 double **ptr1; /* Pointer to pset1 data */
3523 double **ptr2; /* Pointer to pset2 data */
3524 double *cnst; /* Pointer to constants array */
3525 double cn; /* Potential new constant value */
3526 double ip; /* Potential output axis index */
3527 double op; /* Potential input axis index */
3528 int *inprm; /* Pointer to input axis permutation array */
3529 int *outprm; /* Pointer to output axis permutation array */
3530 int i; /* Axis count */
3531 int nc; /* Number of constants stored so far */
3532 int nin; /* No. of input coordinates for the PermMap */
3533 int nout; /* No. of output coordinates for the PermMap */
3534
3535 /* Initialise. */
3536 if( outperm ) *outperm = NULL;
3537 if( inperm ) *inperm = NULL;
3538 if( consts ) *consts = NULL;
3539
3540 /* Check the global error status and the supplied pointers. */
3541 if ( !astOK || !outperm || !inperm || !consts ) return;
3542
3543 /* Initialise variables to avoid "used of uninitialised variable"
3544 messages from dumb compilers. */
3545 nc = 0;
3546
3547 /* Get the number of input and output axes for the supplied PermMap. */
3548 nin = astGetNin( map );
3549 nout = astGetNout( map );
3550
3551 /* Allocate the memory for the returned arrays. */
3552 outprm = (int *) astMalloc( sizeof( int )* (size_t) nout );
3553 inprm = (int *) astMalloc( sizeof( int )* (size_t) nin );
3554 cnst = (double *) astMalloc( sizeof( double )* (size_t) ( nout + nin ) );
3555
3556 /* Returned the pointers to these arrays.*/
3557 *outperm = outprm;
3558 *inperm = inprm;
3559 *consts = cnst;
3560
3561 /* Create two PointSets, each holding two points, which can be used for
3562 input and output positions with the PermMap. */
3563 pset1 = astPointSet( 2, nin, "", status );
3564 pset2 = astPointSet( 2, nout, "", status );
3565
3566 /* Set up the two input positions to be [0,1,2...] and [-1,-1,-1,...]. The
3567 first position is used to enumerate the axes, and the second is used to
3568 check for constant axis values. */
3569 ptr1 = astGetPoints( pset1 );
3570 if( astOK ){
3571 for( i = 0; i < nin; i++ ){
3572 ptr1[ i ][ 0 ] = ( double ) i;
3573 ptr1[ i ][ 1 ] = -1.0;
3574 }
3575 }
3576
3577 /* Use the PermMap to transform these positions in the forward direction. */
3578 (void) astTransform( map, pset1, 1, pset2 );
3579
3580 /* Look at the mapped positions to determine the output axis permutation
3581 array. */
3582 ptr2 = astGetPoints( pset2 );
3583 if( astOK ){
3584
3585 /* No constant axis valeus found yet. */
3586 nc = 0;
3587
3588 /* Do each output axis. */
3589 for( i = 0; i < nout; i++ ){
3590
3591 /* If the output axis value is copied from an input axis value, the index
3592 of the appropriate input axis will be in the mapped first position. */
3593 op = ptr2[ i ][ 0 ];
3594
3595 /* If the output axis value is assigned a constant value, the result of
3596 mapping the two different input axis values will be the same. */
3597 cn = ptr2[ i ][ 1 ];
3598 if( op == cn ) {
3599
3600 /* We have found another constant. Store it in the constants array, and
3601 store the index of the constant in the output axis permutation array. */
3602 cnst[ nc ] = cn;
3603 outprm[ i ] = -( nc + 1 );
3604 nc++;
3605
3606 /* If the output axis values are different, then the output axis value
3607 must be copied from the input axis value. */
3608 } else {
3609 outprm[ i ] = (int) ( op + 0.5 );
3610 }
3611 }
3612 }
3613
3614 /* Now do the same thing to determine the input permutation array. */
3615 if( astOK ){
3616 for( i = 0; i < nout; i++ ){
3617 ptr2[ i ][ 0 ] = ( double ) i;
3618 ptr2[ i ][ 1 ] = -1.0;
3619 }
3620 }
3621
3622 (void) astTransform( map, pset2, 0, pset1 );
3623
3624 if( astOK ){
3625
3626 for( i = 0; i < nin; i++ ){
3627
3628 ip = ptr1[ i ][ 0 ];
3629 cn = ptr1[ i ][ 1 ];
3630 if( ip == cn ) {
3631
3632 cnst[ nc ] = cn;
3633 inprm[ i ] = -( nc + 1 );
3634 nc++;
3635
3636 } else {
3637 inprm[ i ] = (int) ( ip + 0.5 );
3638 }
3639 }
3640 }
3641
3642 /* Annul the PointSets. */
3643 pset1 = astAnnul( pset1 );
3644 pset2 = astAnnul( pset2 );
3645
3646 /* If an error has occurred, attempt to free the returned arrays. */
3647 if( !astOK ) {
3648 *outperm = (int *) astFree( (void *) *outperm );
3649 *inperm = (int *) astFree( (void *) *inperm );
3650 *consts = (double *) astFree( (void *) *consts );
3651 }
3652
3653 /* Return. */
3654 return;
3655 }
3656
SetAttrib(AstObject * this_object,const char * setting,int * status)3657 static void SetAttrib( AstObject *this_object, const char *setting, int *status ) {
3658 /*
3659 * Name:
3660 * SetAttrib
3661
3662 * Purpose:
3663 * Set an attribute value for a WcsMap.
3664
3665 * Type:
3666 * Private function.
3667
3668 * Synopsis:
3669 * #include "wcsmap.h"
3670 * void SetAttrib( AstObject *this, const char *setting )
3671
3672 * Class Membership:
3673 * WcsMap member function (over-rides the astSetAttrib protected
3674 * method inherited from the Mapping class).
3675
3676 * Description:
3677 * This function assigns an attribute value for a WcsMap, the
3678 * attribute and its value being specified by means of a string of
3679 * the form:
3680 *
3681 * "attribute= value "
3682 *
3683 * Here, "attribute" specifies the attribute name and should be in
3684 * lower case with no white space present. The value to the right
3685 * of the "=" should be a suitable textual representation of the
3686 * value to be assigned and this will be interpreted according to
3687 * the attribute's data type. White space surrounding the value is
3688 * only significant for string attributes.
3689
3690 * Parameters:
3691 * this
3692 * Pointer to the WcsMap.
3693 * setting
3694 * Pointer to a null-terminated string specifying the new attribute
3695 * value.
3696 */
3697
3698 /* Local Variables: */
3699 AstWcsMap *this; /* Pointer to the WcsMap structure */
3700 double dval; /* Attribute value */
3701 int len; /* Length of setting string */
3702 int nc; /* Number of characters read by astSscanf */
3703 int i; /* Axis index */
3704 int m; /* Projection parameter number */
3705
3706 /* Check the global error status. */
3707 if ( !astOK ) return;
3708
3709 /* Obtain a pointer to the WcsMap structure. */
3710 this = (AstWcsMap *) this_object;
3711
3712 /* Obtain the length of the setting string. */
3713 len = (int) strlen( setting );
3714
3715 /* Test for each recognised attribute in turn, using "astSscanf" to parse
3716 the setting string and extract the attribute value (or an offset to
3717 it in the case of string values). In each case, use the value set
3718 in "nc" to check that the entire string was matched. Once a value
3719 has been obtained, use the appropriate method to set it. */
3720
3721 /* ProjP(i). */
3722 /* --------- */
3723 if ( nc = 0, ( 2 == astSscanf( setting, "projp(%d)= %lg %n", &m, &dval, &nc ) )
3724 && ( nc >= len ) ) {
3725 astSetPV( this, astGetWcsAxis( this, 1 ), m, dval );
3726
3727 /* PV. */
3728 /* --- */
3729 } else if ( nc = 0, ( 3 == astSscanf( setting, "pv%d_%d= %lg %n", &i, &m, &dval, &nc ) )
3730 && ( nc >= len ) ) {
3731 astSetPV( this, i - 1, m, dval );
3732
3733 /* Define macros to see if the setting string matches any of the
3734 read-only attributes of this class. */
3735 #define MATCH(attrib) \
3736 ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \
3737 ( nc >= len ) )
3738
3739 #define MATCH2(attrib) \
3740 ( nc = 0, ( 1 == astSscanf( setting, attrib "(%d)=%*[^\n]%n", &i, &nc ) ) && \
3741 ( nc >= len ) )
3742
3743 /* If the attribute was not recognised, use this macro to report an error
3744 if a read-only attribute has been specified. */
3745 } else if ( MATCH( "wcstype" ) ||
3746 MATCH( "natlat" ) ||
3747 MATCH( "natlon" ) ||
3748 MATCH2( "wcsaxis" ) ) {
3749 astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status,
3750 setting, astGetClass( this ) );
3751 astError( AST__NOWRT, "This is a read-only attribute." , status);
3752
3753 /* If the attribute is still not recognised, pass it on to the parent
3754 method for further interpretation. */
3755 } else {
3756 (*parent_setattrib)( this_object, setting, status );
3757 }
3758
3759 /* Undefine macros local to this function. */
3760 #undef MATCH
3761 #undef MATCH2
3762 }
3763
SetPV(AstWcsMap * this,int i,int m,double val,int * status)3764 static void SetPV( AstWcsMap *this, int i, int m, double val, int *status ) {
3765 /*
3766 *+
3767 * Name:
3768 * astSetPV
3769
3770 * Purpose:
3771 * Set the value of a PVi_m attribute.
3772
3773 * Type:
3774 * Protected function.
3775
3776 * Synopsis:
3777 * #include "wcsmap.h"
3778 * void astSetPV( AstWcsMap *this, int i, int m, double val )
3779
3780 * Class Membership:
3781 * WcsMap protected function
3782
3783 * Description:
3784 * This function stores a value for the specified member of the PV
3785 * attribute array.
3786
3787 * Parameters:
3788 * this
3789 * A pointer to the WcsMap.
3790 * i
3791 * Zero based axis index.
3792 * m
3793 * Zero based parameter index.
3794
3795 *-
3796 */
3797 /* Local Variables: */
3798 int naxis; /* No. of axes in WcsMap */
3799 int mm; /* Loop count */
3800 int mxpar; /* Max number of parameters allowed for the axis */
3801
3802 /* Check the global error status. */
3803 if ( !astOK ) return;
3804
3805 /* Find the number of axes in the WcsMap. */
3806 naxis = astGetNin( this );
3807
3808 /* Validate the axis index. */
3809 if( i < 0 || i >= naxis ){
3810 astError( AST__AXIIN, "astSetPV(%s): Axis index (%d) is invalid in "
3811 "attribute PV%d_%d - it should be in the range 1 to %d.",
3812 status, astGetClass( this ), i + 1, i + 1, m, naxis );
3813
3814 /* Validate the parameter index. */
3815 } else {
3816 mxpar = astGetPVMax( this, i );
3817 if( m < 0 || m > mxpar ){
3818 astError( AST__AXIIN, "astSetPV(%s): Parameter index (%d) is invalid "
3819 "in attribute PV%d_%d for a \"%s\" projection - it should be "
3820 "in the range 0 to %d.", status, astGetClass( this ), m, i + 1, m,
3821 FindPrjData( this->type, status )->ctype, mxpar );
3822
3823 /* If the dynamic arrays used to hold the parameters have not yet been
3824 created, create them now, and store pointers to them in the WcsMap
3825 structure. */
3826 } else {
3827 if( !this->np || !this->p ) {
3828 this->np = (int *) astMalloc( sizeof(int)*naxis );
3829 this->p = (double **) astMalloc( sizeof(double *)*naxis );
3830 if( astOK ) {
3831 for( mm = 0; mm < naxis; mm++ ) {
3832 this->np[ mm ] = 0;
3833 this->p[ mm ] = NULL;
3834 }
3835 }
3836
3837 /* Release the dynamic arrays if an error has occurred. */
3838 if( !astOK ) FreePV( this, status );
3839
3840 }
3841 }
3842
3843 /* Check we can use the arrays. */
3844 if( astOK ) {
3845
3846 /* Ensure the dynamic array used to hold parameter values for the
3847 specified axis is big enough to hold the specified parameter. */
3848 this->p[ i ] = (double *) astGrow( (void *) this->p[ i ],
3849 m + 1, sizeof(double) );
3850
3851 /* Check we can use this array. */
3852 if( astOK ) {
3853
3854 /* Store the supplied value in the relevant element of this array. */
3855 this->p[ i ][ m ] = val;
3856
3857 /* If the array was extended to hold this parameter... */
3858 if( this->np[ i ] <= m ) {
3859
3860 /* Fill any other new elements in this array with AST__BAD */
3861 for( mm = this->np[ i ]; mm < m; mm++ ) this->p[ i ][ mm ] = AST__BAD;
3862
3863 /* Remember the new array size. */
3864 this->np[ i ] = m + 1;
3865 }
3866 }
3867 }
3868 }
3869
3870 /* Re-initialize the values stored in the "AstPrjPrm" structure. */
3871 InitPrjPrm( this, status );
3872 }
3873
SetTPNTan(AstWcsMap * this,int val,int * status)3874 static void SetTPNTan( AstWcsMap *this, int val, int *status ) {
3875 /*
3876 *+
3877 * Name:
3878 * astSetTPNTan
3879
3880 * Purpose:
3881 * Set the value of a TPNTan attribute.
3882
3883 * Type:
3884 * Protected function.
3885
3886 * Synopsis:
3887 * #include "wcsmap.h"
3888 * void astSetTPNTan( AstWcsMap *this, int val )
3889
3890 * Class Membership:
3891 * WcsMap protected function
3892
3893 * Description:
3894 * This function stores a value for the TPNTan attribute and updates
3895 * the projection parameters used by WCSLIB accordingly.
3896
3897 * Parameters:
3898 * this
3899 * A pointer to the WcsMap.
3900 * val
3901 * New attribute value.
3902
3903 *-
3904 */
3905
3906 /* Check the global error status. */
3907 if ( !astOK ) return;
3908
3909 /* Store the new value. */
3910 this->tpn_tan = ( val != 0 );
3911
3912 /* Re-initialize the values stored in the "AstPrjPrm" structure. */
3913 InitPrjPrm( this, status );
3914 }
3915
TestAttrib(AstObject * this_object,const char * attrib,int * status)3916 static int TestAttrib( AstObject *this_object, const char *attrib, int *status ) {
3917 /*
3918 * Name:
3919 * TestAttrib
3920
3921 * Purpose:
3922 * Test if a specified attribute value is set for a WcsMap.
3923
3924 * Type:
3925 * Private function.
3926
3927 * Synopsis:
3928 * #include "wcsmap.h"
3929 * int TestAttrib( AstObject *this, const char *attrib, int *status )
3930
3931 * Class Membership:
3932 * WcsMap member function (over-rides the astTestAttrib protected
3933 * method inherited from the Mapping class).
3934
3935 * Description:
3936 * This function returns a boolean result (0 or 1) to indicate whether
3937 * a value has been set for one of a WcsMap's attributes.
3938
3939 * Parameters:
3940 * this
3941 * Pointer to the WcsMap.
3942 * attrib
3943 * Pointer to a null-terminated string specifying the attribute
3944 * name. This should be in lower case with no surrounding white
3945 * space.
3946 * status
3947 * Pointer to the inherited status variable.
3948
3949 * Returned Value:
3950 * One if a value has been set, otherwise zero.
3951
3952 * Notes:
3953 * - A value of zero will be returned if this function is invoked
3954 * with the global status set, or if it should fail for any reason.
3955 */
3956
3957 /* Local Variables: */
3958 AstWcsMap *this; /* Pointer to the WcsMap structure */
3959 int i; /* Axis index */
3960 int m; /* Projection parameter index */
3961 int len; /* Length os supplied string */
3962 int nc; /* No. of characters read by astSscanf */
3963 int result; /* Result value to return */
3964
3965 /* Initialise. */
3966 result = 0;
3967
3968 /* Check the global error status. */
3969 if ( !astOK ) return result;
3970
3971 /* Obtain a pointer to the WcsMap structure. */
3972 this = (AstWcsMap *) this_object;
3973
3974 /* Obtain the length of the attrib string. */
3975 len = strlen( attrib );
3976
3977 /* Check the attribute name and test the appropriate attribute. */
3978
3979
3980 /* ProjP(i). */
3981 /* --------- */
3982 if ( nc = 0, ( 1 == astSscanf( attrib, "projp(%d)%n", &m, &nc ) )
3983 && ( nc >= len ) ) {
3984 result = astTestPV( this, astGetWcsAxis( this, 1 ), m );
3985
3986 /* PV. */
3987 /* --- */
3988 } else if ( nc = 0, ( 2 == astSscanf( attrib, "pv%d_%d%n", &i, &m, &nc ) )
3989 && ( nc >= len ) ) {
3990 result = astTestPV( this, i - 1, m );
3991
3992 /* If the name is not recognised, test if it matches any of the
3993 read-only attributes of this class. If it does, then return
3994 zero. */
3995 } else if ( !strcmp( attrib, "wcstype" ) ||
3996 !strcmp( attrib, "natlat" ) ||
3997 !strcmp( attrib, "natlon" ) ||
3998 ( nc = 0, ( 1 == astSscanf( attrib, "wcsaxis(%d)%n", &i, &nc ) )
3999 && ( nc >= len ) ) ) {
4000 result = 0;
4001
4002 /* If the attribute is still not recognised, pass it on to the parent
4003 method for further interpretation. */
4004 } else {
4005 result = (*parent_testattrib)( this_object, attrib, status );
4006 }
4007
4008 /* Return the result, */
4009 return result;
4010 }
4011
TestPV(AstWcsMap * this,int i,int m,int * status)4012 static int TestPV( AstWcsMap *this, int i, int m, int *status ) {
4013 /*
4014 *+
4015 * Name:
4016 * astTestPV
4017
4018 * Purpose:
4019 * Test a PVi_m attribute.
4020
4021 * Type:
4022 * Protected function.
4023
4024 * Synopsis:
4025 * #include "wcsmap.h"
4026 * int astTestPV( AstWcsMap *this, int i, int m )
4027
4028 * Class Membership:
4029 * WcsMap protected function
4030
4031 * Description:
4032 * This function returns 1 if a specified member of the PV attribute
4033 * array is currently set, and 0 otherwise.
4034
4035 * Parameters:
4036 * this
4037 * A pointer to the WcsMap.
4038 * i
4039 * Zero based axis index.
4040 * m
4041 * Zero based parameter index.
4042
4043 * Returned Value:
4044 * 1 if the attribute is set, 0 otherwise.
4045
4046 *-
4047 */
4048 /* Local Variables: */
4049 int ret;
4050 int npar;
4051 int mxpar;
4052
4053 /* Initialise */
4054 ret = 0;
4055
4056 /* Check the global error status. */
4057 if ( !astOK ) return ret;
4058
4059 /* Validate the axis index. */
4060 if( i < 0 || i >= astGetNin( this ) ){
4061 astError( AST__AXIIN, "astTestPV(%s): Axis index (%d) is invalid in "
4062 "attribute PV%d_%d - it should be in the range 1 to %d.",
4063 status, astGetClass( this ), i + 1, i + 1, m, astGetNin( this ) );
4064
4065 /* Find the maximum number of parameters allowed for the axis. */
4066 } else {
4067 mxpar = astGetPVMax( this, i );
4068
4069 /* Ignore unused parameters. */
4070 if( m < 0 || m > mxpar ){
4071
4072 /* See if the parameter is currently set. */
4073 } else if( this->np && this->p ){
4074 npar = this->np[ i ];
4075 if( m < npar && this->p[ i ] ){
4076 ret = ( this->p[ i ][ m ] != AST__BAD );
4077 }
4078 }
4079 }
4080
4081 return ret;
4082 }
4083
Transform(AstMapping * this,AstPointSet * in,int forward,AstPointSet * out,int * status)4084 static AstPointSet *Transform( AstMapping *this, AstPointSet *in,
4085 int forward, AstPointSet *out, int *status ) {
4086 /*
4087 *+
4088 * Name:
4089 * Transform
4090
4091 * Purpose:
4092 * Apply a WcsMap to a set of points.
4093
4094 * Type:
4095 * Private function.
4096
4097 * Synopsis:
4098 * #include "wcsmap.h"
4099 * AstPointSet *Transform( AstMapping *this, AstPointSet *in,
4100 * int forward, AstPointSet *out, int *status )
4101
4102 * Class Membership:
4103 * WcsMap member function (over-rides the astTransform method inherited
4104 * from the Mapping class).
4105
4106 * Description:
4107 * This function takes a WcsMap and a set of points encapsulated in a
4108 * PointSet and transforms the points using the requested projection.
4109
4110 * Parameters:
4111 * this
4112 * Pointer to the WcsMap.
4113 * in
4114 * Pointer to the PointSet holding the input coordinate data.
4115 * forward
4116 * A non-zero value indicates that the forward coordinate transformation
4117 * should be applied, while a zero value requests the inverse
4118 * transformation.
4119 * out
4120 * Pointer to a PointSet which will hold the transformed (output)
4121 * coordinate values. A NULL value may also be given, in which case a
4122 * new PointSet will be created by this function.
4123 * status
4124 * Pointer to the inherited status variable.
4125
4126 * Returned Value:
4127 * Pointer to the output (possibly new) PointSet.
4128
4129 * Notes:
4130 * - Assuming the WcsMap has not been inverted, the forward mapping
4131 * transforms spherical (longitude,latitude) pairs into Cartesian (x,y)
4132 * pairs. Longitude and latitude values are given and returned in radians,
4133 * and no restrictions are imposed on their ranges. X and Y values are
4134 * also given and returned in radians, with no restrictions imposed on
4135 * their ranges.
4136 * - A null pointer will be returned if this function is invoked with the
4137 * global error status set, or if it should fail for any reason.
4138 * - The number of coordinate values per point in the input PointSet must
4139 * match the number of coordinates for the WcsMap being applied.
4140 * - If an output PointSet is supplied, it must have space for sufficient
4141 * number of points and coordinate values per point to accommodate the
4142 * result. Any excess space will be ignored.
4143 *-
4144 */
4145
4146 /* Local Variables: */
4147 AstPointSet *result; /* Pointer to output PointSet */
4148 AstWcsMap *map; /* Pointer to WcsMap to be applied */
4149 double **ptr_in; /* Pointer to input coordinate data */
4150 double **ptr_out; /* Pointer to output coordinate data */
4151 int i; /* Axis count */
4152 int latax; /* Latitude axis index */
4153 int lonax; /* Longitude axis index */
4154 int npoint; /* Number of points */
4155 int status_value; /* Status from Map function */
4156
4157 /* Check the global error status. */
4158 if ( !astOK ) return NULL;
4159
4160 /* Obtain a pointer to the WcsMap. */
4161 map = (AstWcsMap *) this;
4162
4163 /* Apply the parent mapping using the stored pointer to the Transform member
4164 function inherited from the parent Mapping class. This function validates
4165 all arguments and generates an output PointSet if necessary, but does not
4166 actually transform any coordinate values. */
4167 result = (*parent_transform)( this, in, forward, out, status );
4168
4169 /* We will now extend the parent astTransform method by performing the
4170 calculations needed to generate the output coordinate values. */
4171
4172 /* Determine the numbers of points from the input PointSet and obtain pointers
4173 for accessing the input and output coordinate values. */
4174 npoint = astGetNpoint( in );
4175 ptr_in = astGetPoints( in );
4176 ptr_out = astGetPoints( result );
4177
4178 /* If a genuine FITS-WCS projection is being performed... */
4179 if( astGetWcsType( map ) != AST__WCSBAD ){
4180
4181 /* Determine whether to apply the forward or inverse mapping, according to the
4182 direction specified and whether the mapping has been inverted. */
4183 if ( astGetInvert( map ) ) forward = !forward;
4184
4185 /* Do the coordinate transformation. */
4186 lonax = astGetWcsAxis( map, 0 );
4187 latax = astGetWcsAxis( map, 1 );
4188 status_value = Map( map, forward, npoint, ptr_in[ lonax ], ptr_in[ latax ],
4189 ptr_out[ lonax ], ptr_out[ latax ], status );
4190
4191 /* Report an error if the projection type was unrecognised. */
4192 if ( status_value == 1 ) {
4193 astError( AST__WCSTY, "astTransform(%s): The %s specifies an "
4194 "illegal projection type ('%s').", status, astClass( this ),
4195 astClass( this ), FindPrjData( map->type, status )->desc );
4196
4197 /* Report an error if the projection parameters were invalid. */
4198 } else if ( status_value == 2 ) {
4199 astError( AST__WCSPA, "astTransform(%s): The %s projection "
4200 "parameter values in this %s are unusable.", status,
4201 astClass( this ), FindPrjData( map->type, status )->desc,
4202 astClass( this ) );
4203
4204 /* Report an error if required projection parameters were not supplied. */
4205 } else if ( status_value >= 400 ) {
4206 astError( AST__WCSPA, "astTransform(%s): Required projection "
4207 "parameter PV%d_%d was not supplied for a %s "
4208 "projection.", status, astClass( this ), latax+1, status_value - 400,
4209 FindPrjData( map->type, status )->desc );
4210
4211 } else if ( status_value >= 100 ) {
4212 astError( AST__WCSPA, "astTransform(%s): Required projection "
4213 "parameter PV%d_%d was not supplied for a %s "
4214 "projection.", status, astClass( this ), lonax+1, status_value - 100,
4215 FindPrjData( map->type, status )->desc );
4216 }
4217
4218 /* Copy the remaining axes (i.e. all axes except the longitude and latitude
4219 axes) from the input to the output. */
4220 for( i = 0; i < astGetNcoord( in ); i++ ){
4221 if( ( i != lonax && i != latax ) ){
4222 (void) memcpy( ptr_out[ i ], ptr_in[ i ], sizeof( double )*
4223 (size_t) npoint );
4224 }
4225
4226 }
4227
4228 /* If there is no FITS-WCS projection, just copy all the axes from input to
4229 output. */
4230 } else {
4231 for( i = 0; i < astGetNcoord( in ); i++ ){
4232 (void) memcpy( ptr_out[ i ], ptr_in[ i ], sizeof( double )*
4233 (size_t) npoint );
4234 }
4235 }
4236
4237 /* If an error has occurred, attempt to delete the results PointSet. */
4238 if ( !astOK ) result = astDelete( result );
4239
4240 /* Return a pointer to the output PointSet. */
4241 return result;
4242
4243 }
4244
astWcsPrjType_(const char * ctype,int * status)4245 int astWcsPrjType_( const char *ctype, int *status ){
4246 /*
4247 *+
4248 * Name:
4249 * astWcsPrjType
4250
4251 * Purpose:
4252 * Get the integer identifier for a WCSLIB projection given by a FITS
4253 * CTYPE keyword value.
4254
4255 * Type:
4256 * Protected function.
4257
4258 * Synopsis:
4259 * #include "wcsmap.h"
4260 * int astWcsPrjType( const char *ctype )
4261
4262 * Class Membership:
4263 * WcsMap protected function
4264
4265 * Description:
4266 * This function returns the integer identifier for the WCSLIB projection
4267 * specified by the supplied FITS CTYPE keyword value. The returned
4268 * value can be passed to astWcsMap to create a WcsMap which implements
4269 * the corresponding projection.
4270
4271 * Parameters:
4272 * ctype
4273 * A pointer to the last 4 characters of a FITS CTYPE1 (etc) keyword.
4274
4275 * Returned Value:
4276 * The integer identifier associated with the projection.
4277
4278 * Notes:
4279 * - A value of AST__WCSBAD is returned if the projection type is
4280 * unknown, but no error is reported.
4281 *-
4282 */
4283
4284 PrjData *data;
4285 char buffer[81];
4286 const char *a;
4287 char *b;
4288
4289 /* Remove leading and trailing blanks from the supplied string. */
4290 a = ctype;
4291 b = buffer;
4292 while( *a && (b - buffer) < 80 ){
4293 if( !isspace( (int) *a ) ) {
4294 *(b++) = *a;
4295 }
4296 a++;
4297 }
4298 *b = 0;
4299
4300 /* Search for the projection in the list of available projectons. */
4301 data = PrjInfo;
4302 while( data->prj != AST__WCSBAD && strcmp( data->ctype, buffer ) ) data ++;
4303
4304 return data->prj;
4305 }
4306
astWcsPrjName_(int type,int * status)4307 const char *astWcsPrjName_( int type, int *status ){
4308 /*
4309 *+
4310 * Name:
4311 * astWcsPrjName
4312
4313 * Purpose:
4314 * Get the name of a projection given its integer identifier.
4315
4316 * Type:
4317 * Protected function.
4318
4319 * Synopsis:
4320 * #include "wcsmap.h"
4321 * const char *astWcsPrjName( int type )
4322
4323 * Class Membership:
4324 * WcsMap protected function
4325
4326 * Description:
4327 * This function returns a string holding 4 characters which can be
4328 * used as the last 4 characters of a FITS CTYPE keyword value
4329 * describing the WCSLIB projection specified by the supplied type.
4330
4331 * Parameters:
4332 * type
4333 * The projection type.
4334
4335 * Returned Value:
4336 * A pointer to a null-terminated const character string holding the
4337 * last 4 CTYPE characters describing the projection.
4338
4339 * Notes:
4340 * - This function attempts to execute even if an error has already
4341 * occurred.
4342 *-
4343 */
4344
4345 PrjData *data;
4346 data = PrjInfo;
4347 while( data->prj != AST__WCSBAD && data->prj != type ) data ++;
4348 return data->ctype;
4349 }
4350
astWcsPrjDesc_(int type,int * status)4351 const char *astWcsPrjDesc_( int type, int *status ){
4352 /*
4353 *+
4354 * Name:
4355 * astWcsPrjDesc
4356
4357 * Purpose:
4358 * Get a textual description of a projection given its integer
4359 * identifier.
4360
4361 * Type:
4362 * Protected function.
4363
4364 * Synopsis:
4365 * #include "wcsmap.h"
4366 * const char *astWcsPrjDesc( int type )
4367
4368 * Class Membership:
4369 * WcsMap protected function
4370
4371 * Description:
4372 * This function returns a pointer to a string string holding a
4373 * textual description of the specified projection type.
4374
4375 * Parameters:
4376 * type
4377 * The projection type.
4378
4379 * Returned Value:
4380 * A pointer to a null-terminated const character string holding the
4381 * projection description.
4382
4383 * Notes:
4384 * - This function attempts to execute even if an error has already
4385 * occurred.
4386 *-
4387 */
4388
4389 PrjData *data;
4390 data = PrjInfo;
4391 while( data->prj != AST__WCSBAD && data->prj != type ) data ++;
4392 return data->desc;
4393 }
4394
WcsPerm(AstMapping ** maps,int * inverts,int iwm,int * status)4395 static void WcsPerm( AstMapping **maps, int *inverts, int iwm, int *status ){
4396 /*
4397 * Name:
4398 * WcsPerm
4399
4400 * Purpose:
4401 * Swap a WcsMap and a PermMap.
4402
4403 * Type:
4404 * Private function.
4405
4406 * Synopsis:
4407 * #include "wcsmap.h"
4408 * void WcsPerm( AstMapping **maps, int *inverts, int iwm, int *status )
4409
4410 * Class Membership:
4411 * WcsMap member function
4412
4413 * Description:
4414 * A list of two Mappings is supplied containing a WcsMap and a
4415 * PermMap. These Mappings are annulled, and replaced with
4416 * another pair of Mappings consisting of a WcsMap and a PermMap
4417 * in the opposite order. These Mappings are chosen so that their
4418 * combined effect is the same as the original pair of Mappings.
4419
4420 * Parameters:
4421 * maps
4422 * A pointer to an array of two Mapping pointers.
4423 * inverts
4424 * A pointer to an array of two invert flags.
4425 * iwm
4426 * The index within "maps" of the WcsMap.
4427 * status
4428 * Pointer to the inherited status variable.
4429
4430 * Notes:
4431 * - All links between input and output axes in the PermMap must
4432 * be bi-directional, but there can be unconnected axes, and there
4433 * need not be the same number of input and output axes. Both
4434 * longitude and latitude axes must be passed by the PermMap.
4435
4436 */
4437
4438 /* Local Variables: */
4439 AstPermMap *pm; /* Pointer to the supplied PermMap */
4440 AstPermMap *newpm; /* Pointer to the returned PermMap */
4441 AstMapping *newwm; /* Pointer to the returned WcsMap */
4442 AstWcsMap *wm; /* Pointer to the supplied WcsMap */
4443 double *consts; /* Pointer to constants array */
4444 int *inperm; /* Pointer to input axis permutation array */
4445 int *outperm; /* Pointer to output axis permutation array */
4446 int latax; /* Index of latitude axis */
4447 int lonax; /* Index of longitude axis */
4448 int npin; /* No. of input axes in supplied PermMap */
4449 int npout; /* No. of output axes in supplied PermMap */
4450 int old_pinv; /* Invert value for the supplied PermMap */
4451 int old_winv; /* Invert value for the supplied WcsMap */
4452 int type; /* Projection type */
4453 int done; /* Have Mappings been swapped? */
4454 int i; /* AXis index */
4455 double *p; /* Pointer to input position */
4456 double *q; /* Pointer to output position */
4457
4458 /* Check the global error status. */
4459 if ( !astOK ) return;
4460
4461 /* Initialise variables to avoid "used of uninitialised variable"
4462 messages from dumb compilers. */
4463 newpm = NULL;
4464 newwm = NULL;
4465
4466 /* Store pointers to the supplied WcsMap and the PermMap. */
4467 wm = (AstWcsMap *) maps[ iwm ];
4468 pm = (AstPermMap *) maps[ 1 - iwm ];
4469
4470 /* Temporarily set the Invert attribute of the supplied PermMap to the
4471 supplied values. */
4472 old_pinv = astGetInvert( pm );
4473 astSetInvert( pm, inverts[ 1 - iwm ] );
4474 old_winv = astGetInvert( wm );
4475 astSetInvert( wm, inverts[ iwm ] );
4476
4477 /* Get the projection type of the supplied WcsMap and the indices of the
4478 longitude and latitude axes. */
4479 type = astGetWcsType( wm );
4480 lonax = astGetWcsAxis( wm, 0 );
4481 latax = astGetWcsAxis( wm, 1 );
4482
4483 /* Get the axis permutation and constants arrays representing the
4484 PermMap. Note, no constants are used more than once in the returned
4485 arrays (i.e. duplicate constants are returned in "consts" if more than
4486 one axis uses a given constant). */
4487 PermGet( pm, &outperm, &inperm, &consts, status );
4488
4489 if( astOK ) {
4490
4491 /* Get the number of input and output axes in the PermMap. */
4492 npin = astGetNin( pm );
4493 npout = astGetNout( pm );
4494
4495 /* If the lon and lat axes of the WcsMap are unassigned, we return a
4496 UnitMap instead of a WcsMap.
4497 ================================================================ */
4498 done = 0;
4499
4500 /* If the PermMap comes after the WcsMap... */
4501 if( iwm == 0 ) {
4502 if( inperm[ lonax ] < 0 && inperm[ latax ] < 0 ) {
4503 done = 1;
4504
4505 /* Transform the constant values, using AST__BAD for other axes. */
4506 p = (double *) astMalloc( sizeof( double )*(size_t) npin );
4507 q = (double *) astMalloc( sizeof( double )*(size_t) npin );
4508 if( astOK ) {
4509 for( i = 0; i < npin; i++ ) {
4510 if( inperm[ i ] < 0 ) {
4511 p[ i ] = consts[ -inperm[ i ] - 1 ];
4512 } else {
4513 p[ i ] = AST__BAD;
4514 }
4515 }
4516
4517 /* Transform this position using the inverse WcsMap. */
4518 astTranN( wm, 1, npin, 1, p, 0, npin, 1, q );
4519
4520 /* The new PermMap has the same axis permutations as the original, but it
4521 has different constants. */
4522 for( i = 0; i < npin; i++ ) {
4523 if( inperm[ i ] < 0 ) {
4524 consts[ -inperm[ i ] - 1 ] = q[ i ];
4525 }
4526 }
4527
4528 newpm = astPermMap( npin, inperm, npout, outperm, consts, "", status );
4529
4530 /* Use a UnitMap instead of the WcsMap. */
4531 newwm = (AstMapping *) astUnitMap( npout, "", status );
4532
4533 }
4534
4535 /* Free memory */
4536 p = astFree( p );
4537 q = astFree( q );
4538
4539 }
4540
4541 /* If the WcsMap comes after the PermMap... */
4542 } else {
4543 if( outperm[ lonax ] < 0 && outperm[ latax ] < 0 ) {
4544 done = 1;
4545
4546 /* Transform the constant values, using AST__BAD for other axes. */
4547 p = (double *) astMalloc( sizeof( double )*(size_t) npout );
4548 q = (double *) astMalloc( sizeof( double )*(size_t) npout );
4549 if( astOK ) {
4550 for( i = 0; i < npout; i++ ) {
4551 if( outperm[ i ] < 0 ) {
4552 p[ i ] = consts[ -outperm[ i ] - 1 ];
4553 } else {
4554 p[ i ] = AST__BAD;
4555 }
4556 }
4557
4558 /* Transform this position using the forward WcsMap. */
4559 astTranN( wm, 1, npout, 1, p, 1, npout, 1, q );
4560
4561 /* The new PermMap has the same axis permutations as the original, but it
4562 has different constants. */
4563 for( i = 0; i < npout; i++ ) {
4564 if( outperm[ i ] < 0 ) {
4565 consts[ -outperm[ i ] - 1 ] = q[ i ];
4566 }
4567 }
4568
4569 newpm = astPermMap( npin, inperm, npout, outperm, consts, "", status );
4570
4571 /* Use a UnitMap instead ofhte WcsMap. */
4572 newwm = (AstMapping *) astUnitMap( npin, "", status );
4573
4574 }
4575
4576 /* Free memory */
4577 p = astFree( p );
4578 q = astFree( q );
4579
4580 }
4581 }
4582
4583 /* If the lon and lat axes of the WcsMap are both assigned, we return a
4584 WcsMap.
4585 ================================================================ */
4586 if( !done ) {
4587
4588 /* Create the new WcsMap with permuted longitude and latitude axes. Note,
4589 the private interface to astWcsMap uses 1-based axis indices. */
4590 if( iwm == 0 ) {
4591 newwm = (AstMapping *) astWcsMap( npout, type, inperm[ lonax ] + 1,
4592 inperm[ latax ] + 1, "", status );
4593 } else {
4594 newwm = (AstMapping *) astWcsMap( npin, type, outperm[ lonax ] + 1,
4595 outperm[ latax ] + 1, "", status );
4596 }
4597
4598 /* Copy any projection parameters which have been set. */
4599 CopyPV( wm, (AstWcsMap *) newwm, status );
4600
4601 /* Set the invert flag. */
4602 astSetInvert( newwm, inverts[ iwm ] );
4603
4604 /* The returned PermMap is a clone of the supplied PermMap */
4605 newpm = astClone( pm );
4606 }
4607
4608 /* Free the axis permutation and constants arrays. */
4609 outperm = (int *) astFree( (void *) outperm );
4610 inperm = (int *) astFree( (void *) inperm );
4611 consts = (double *) astFree( (void *) consts );
4612 }
4613
4614 /* Re-instate the original value of the Invert attributes. */
4615 astSetInvert( pm, old_pinv );
4616 astSetInvert( wm, old_winv );
4617
4618 /* Annul the supplied pointers */
4619 pm = astAnnul( pm );
4620 wm = astAnnul( wm );
4621
4622 /* Store the returned Mappings. */
4623 maps[ iwm ] = (AstMapping *) newpm;
4624 inverts[ iwm ] = astGetInvert( newpm );
4625 maps[ 1 - iwm ] = newwm;
4626 inverts[ 1 - iwm ] = astGetInvert( newwm );
4627
4628 /* Return. */
4629 return;
4630 }
4631
4632 /* Functions which access class attributes. */
4633 /* ---------------------------------------- */
4634 /* Implement member functions to access the attributes associated with
4635 this class using the macros defined for this purpose in the
4636 "object.h" file. For a description of each attribute, see the class
4637 interface (in the associated .h file). */
4638
4639
4640 /*
4641 *att+
4642 * Name:
4643 * FITSProj
4644
4645 * Purpose:
4646 * Is this WcsMap used as a FITS-WCS projection?
4647
4648 * Type:
4649 * Protected attribute.
4650
4651 * Synopsis:
4652 * Integer (boolean).
4653
4654 * Description:
4655 * This attribute controls how a WcsMap is used when creating a set
4656 * of FITS headers. If the WcsMap is contained within a FrameSet
4657 * that is to be converted into a set of FITS headers using the
4658 c astWrite funtion,
4659 f AST_WRITE routine,
4660 * the WcsMap will be used to define the projection code appeneded to
4661 * the FITS "CTYPEi" keywords if, and only if, the FITSProj attribute
4662 * is set non-zero in the WcsMap. In order for the conversion to be
4663 * successful, the compoound Mapping connecting the base and current
4664 * Frames in the FrameSet must contained one (and only one) WcsMap
4665 * that has a non-zero value for its FITSProj attribute.
4666 *
4667 * The default value is one.
4668
4669 * Applicability:
4670 * WcsMap
4671 * All Frames have this attribute.
4672 *att-
4673 */
4674 astMAKE_CLEAR(WcsMap,FITSProj,fits_proj,-INT_MAX)
4675 astMAKE_GET(WcsMap,FITSProj,int,1,( ( this->fits_proj != -INT_MAX ) ?
4676 this->fits_proj : 1 ))
4677 astMAKE_SET(WcsMap,FITSProj,int,fits_proj,( value != 0 ))
4678 astMAKE_TEST(WcsMap,FITSProj,( this->fits_proj != -INT_MAX ))
4679
4680 /*
4681 *att+
4682 * Name:
4683 * TPNTan
4684
4685 * Purpose:
4686 * Should the TPN projection include a TAN projection?
4687
4688 * Type:
4689 * Protected attribute.
4690
4691 * Synopsis:
4692 * Integer (boolean).
4693
4694 * Description:
4695 * This attribute controls how a WcsMap with a AST__TPN projection
4696 * type behaves. If the attribute value is non-zero (the default),
4697 * the complete projection is performed as described in the draft
4698 * version of FITS-WCS paper II. If it is zero, then the TAN
4699 * projection from (psi,theta) to (xi,eta) is replaced by a unit
4700 * transformation, so that the WcsMap implements the polynomial
4701 * transformation only, without any preceding TAN projection.
4702 *
4703 * In addition if the TPNTan value is zero, then the WcsMap
4704 * assumes that the input and output values are in degrees rather
4705 * than radians.
4706
4707 * Applicability:
4708 * WcsMap
4709 * All Frames have this attribute.
4710 *att-
4711 */
4712 astMAKE_GET(WcsMap,TPNTan,int,1,( ( this->tpn_tan != -INT_MAX ) ?
4713 this->tpn_tan : 1 ))
4714 astMAKE_TEST(WcsMap,TPNTan,( this->tpn_tan != -INT_MAX ))
4715
4716 /* ProjP. */
4717 /* ------ */
4718 /*
4719 *att++
4720 * Name:
4721 * ProjP(m)
4722
4723 * Purpose:
4724 * FITS-WCS projection parameters.
4725
4726 * Type:
4727 * Public attribute.
4728
4729 * Synopsis:
4730 * Floating point.
4731
4732 * Description:
4733 * This attribute provides aliases for the PV attributes, which
4734 * specifies the projection parameter values to be used by a WcsMap
4735 * when implementing a FITS-WCS sky projection. ProjP is retained for
4736 * compatibility with previous versions of FITS-WCS and AST. New
4737 * applications should use the PV attibute instead.
4738 *
4739 * Attributes ProjP(0) to ProjP(9) correspond to attributes PV<axlat>_0
4740 * to PV<axlat>_9, where <axlat> is replaced by the index of the
4741 * latitude axis (given by attribute WcsAxis(2)). See PV for further
4742 * details.
4743
4744 * Applicability:
4745 * WcsMap
4746 * All WcsMaps have this attribute.
4747
4748 *att--
4749 */
4750
4751 /* PV. */
4752 /* --- */
4753 /*
4754 *att++
4755 * Name:
4756 * PVi_m
4757
4758 * Purpose:
4759 * FITS-WCS projection parameters.
4760
4761 * Type:
4762 * Public attribute.
4763
4764 * Synopsis:
4765 * Floating point.
4766
4767 * Description:
4768 * This attribute specifies the projection parameter values to be
4769 * used by a WcsMap when implementing a FITS-WCS sky projection.
4770 * Each PV attribute name should include two integers, i and m,
4771 * separated by an underscore. The axis index is specified
4772 * by i, and should be in the range 1 to 99. The parameter number
4773 * is specified by m, and should be in the range 0 to 99. For
4774 * example, "PV2_1=45.0" would specify a value for projection
4775 * parameter 1 of axis 2 in a WcsMap.
4776 *
4777 * These projection parameters correspond exactly to the values
4778 * stored using the FITS-WCS keywords "PV1_1", "PV1_2", etc. This
4779 * means that projection parameters which correspond to angles must
4780 * be given in degrees (despite the fact that the angular
4781 * coordinates and other attributes used by a WcsMap are in
4782 * radians).
4783 *
4784 * The set of projection parameters used by a WcsMap depends on the
4785 * type of projection, which is determined by its WcsType
4786 * parameter. Most projections either do not require projection
4787 * parameters, or use parameters 1 and 2 associated with the latitude
4788 * axis. You should consult the FITS-WCS paper for details.
4789 *
4790 * Some projection parameters have default values (as defined in
4791 * the FITS-WCS paper) which apply if no explicit value is given.
4792 * You may omit setting a value for these "optional" parameters and the
4793 * default will apply. Some projection parameters, however, have no
4794 * default and a value must be explicitly supplied. This is most
4795 * conveniently
4796 c done using the "options" argument of astWcsMap (q.v.) when a WcsMap
4797 f done using the OPTIONS argument of AST_WCSMAP (q.v.) when a WcsMap
4798 * is first created. An error will result when a WcsMap is used to
4799 * transform coordinates if any of its required projection
4800 * parameters has not been set and lacks a default value.
4801
4802 * A "get" operation for a parameter which has not been assigned a value
4803 * will return the default value defined in the FITS-WCS paper, or
4804 * AST__BAD if the paper indicates that the parameter has no default.
4805 * A default value of zero is returned for parameters which are not
4806 * accessed by the projection.
4807 *
4808 * Note, the FITS-WCS paper reserves parameters 1 and 2 on the longitude
4809 * axis to hold the native longitude and latitude of the fiducial
4810 * point of the projection, in degrees. The default values for these
4811 * parameters are determined by the projection type. The AST-specific
4812 * TPN projection does not use this convention - all projection
4813 * parameters for both axes are used to represent polynomical correction
4814 * terms, and the native longitude and latitude at the fiducial point may
4815 * not be changed from the default values of zero and 90 degrees.
4816
4817 * Applicability:
4818 * WcsMap
4819 * All WcsMaps have this attribute.
4820
4821 * Notes:
4822 * - If the projection parameter values given for a WcsMap do not
4823 * satisfy all the required constraints (as defined in the FITS-WCS
4824 * paper), then an error will result when the WcsMap is used to
4825 * transform coordinates.
4826 *att--
4827 */
4828
4829 /* PVMax. */
4830 /* ------ */
4831 /*
4832 *att++
4833 * Name:
4834 * PVMax(i)
4835
4836 * Purpose:
4837 * Maximum number of FITS-WCS projection parameters.
4838
4839 * Type:
4840 * Public attribute.
4841
4842 * Synopsis:
4843 * Integer, read-only.
4844
4845 * Description:
4846 * This attribute specifies the largest legal index for a PV projection
4847 * parameter attached to a specified axis of the WcsMap (i.e. the
4848 * largest legal value for "m" when accessing the "PVi_m" attribute).
4849 * The axis index is specified by i, and should be in the range 1 to 99.
4850 * The value for each axis is determined by the projection type specified
4851 * when the WcsMap
4852 c is first created using astWcsMap and cannot subsequently be
4853 f is first created using AST_WCSMAP and cannot subsequently be
4854 * changed.
4855
4856 * Applicability:
4857 * WcsMap
4858 * All WcsMaps have this attribute.
4859 *att--
4860 */
4861
4862 /* WcsType. */
4863 /* -------- */
4864 /*
4865 *att++
4866 * Name:
4867 * WcsType
4868
4869 * Purpose:
4870 * FITS-WCS projection type.
4871
4872 * Type:
4873 * Public attribute.
4874
4875 * Synopsis:
4876 * Integer, read-only.
4877
4878 * Description:
4879 * This attribute specifies which type of FITS-WCS projection will
4880 * be performed by a WcsMap. The value is specified when a WcsMap
4881 c is first created using astWcsMap and cannot subsequently be
4882 f is first created using AST_WCSMAP and cannot subsequently be
4883 * changed.
4884 *
4885 c The values used are represented by macros with names of
4886 f The values used are represented by symbolic constants with names of
4887 * the form "AST__XXX", where "XXX" is the (upper case) 3-character
4888 * code used by the FITS-WCS "CTYPEi" keyword to identify the
4889 * projection. For example, possible values are AST__TAN (for the
4890 * tangent plane or gnomonic projection) and AST__AIT (for the
4891 * Hammer-Aitoff projection). AST__TPN is an exception in that it
4892 * is not part of the FITS-WCS standard (it represents a TAN
4893 * projection with polynomial correction terms as defined in an early
4894 * draft of the FITS-WCS paper).
4895
4896 * Applicability:
4897 * WcsMap
4898 * All WcsMaps have this attribute.
4899
4900 * Notes:
4901 * - For a list of available projections, see the FITS-WCS paper.
4902 *att--
4903 */
4904
4905 /* Type of FITS-WCS projection. Read only. */
4906 astMAKE_GET(WcsMap,WcsType,int,AST__WCSBAD,this->type)
4907
4908 /* NatLat. */
4909 /* ------- */
4910 /*
4911 *att++
4912 * Name:
4913 * NatLat
4914
4915 * Purpose:
4916 * Native latitude of the reference point of a FITS-WCS projection.
4917
4918 * Type:
4919 * Public attribute.
4920
4921 * Synopsis:
4922 * Floating point, read-only.
4923
4924 * Description:
4925 * This attribute gives the latitude of the reference point of the
4926 * FITS-WCS projection implemented by a WcsMap. The value is in
4927 * radians in the "native spherical" coordinate system. This value is
4928 * fixed for most projections, for instance it is PI/2 (90 degrees)
4929 * for all zenithal projections. For some projections (e.g. the conics)
4930 * the value is not fixed, but is specified by parameter one on the
4931 * latitude axis.
4932 *
4933 * FITS-WCS paper II introduces the concept of a "fiducial point"
4934 * which is logical distinct from the projection reference point.
4935 * It is easy to confuse the use of these two points. The fiducial
4936 * point is the point which has celestial coordinates given by the
4937 * CRVAL FITS keywords. The native spherical coordinates for this point
4938 * default to the values of the NatLat and NatLon, but these defaults
4939 * mey be over-ridden by values stored in the PVi_j keywords. Put
4940 * another way, the CRVAL keywords will by default give the celestial
4941 * coordinates of the projection reference point, but may refer to
4942 * some other point if alternative native longitude and latitude values
4943 * are provided through the PVi_j keywords.
4944 *
4945 * The NatLat attribute is read-only.
4946
4947 * Applicability:
4948 * WcsMap
4949 * All WcsMaps have this attribute.
4950
4951 * Notes:
4952 * - A default value of AST__BAD is used if no latitude value is available.
4953 *att--
4954 */
4955
4956 /*
4957 *att++
4958 * Name:
4959 * NatLon
4960
4961 * Purpose:
4962 * Native longitude of the reference point of a FITS-WCS projection.
4963
4964 * Type:
4965 * Public attribute.
4966
4967 * Synopsis:
4968 * Floating point, read-only.
4969
4970 * Description:
4971 * This attribute gives the longitude of the reference point of the
4972 * FITS-WCS projection implemented by a WcsMap. The value is in
4973 * radians in the "native spherical" coordinate system, and will
4974 * usually be zero. See the description of attribute NatLat for further
4975 * information.
4976 *
4977 * The NatLon attribute is read-only.
4978
4979 * Applicability:
4980 * WcsMap
4981 * All WcsMaps have this attribute.
4982
4983 * Notes:
4984 *att--
4985 */
4986
4987 /* WcsAxis. */
4988 /* -------- */
4989 /*
4990 *att++
4991 * Name:
4992 * WcsAxis(lonlat)
4993
4994 * Purpose:
4995 * FITS-WCS projection axes.
4996
4997 * Type:
4998 * Public attribute.
4999
5000 * Synopsis:
5001 * Integer, read-only.
5002
5003 * Description:
5004 * This attribute gives the indices of the longitude and latitude
5005 * coordinates of the FITS-WCS projection within the coordinate
5006 * space used by a WcsMap. These indices are defined when the
5007 c WcsMap is first created using astWcsMap and cannot
5008 f WcsMap is first created using AST_WCSMAP and cannot
5009 * subsequently be altered.
5010 *
5011 * If "lonlat" is 1, the index of the longitude axis is
5012 * returned. Otherwise, if it is 2, the index of the latitude axis
5013 * is returned.
5014
5015 * Applicability:
5016 * WcsMap
5017 * All WcsMaps have this attribute.
5018 *att--
5019 */
5020
5021 /* Index of the latitude or longitude axis. */
5022 MAKE_GET(WcsAxis,int,0,this->wcsaxis[ axis ],2)
5023
5024 /* Copy constructor. */
5025 /* ----------------- */
Copy(const AstObject * objin,AstObject * objout,int * status)5026 static void Copy( const AstObject *objin, AstObject *objout, int *status ) {
5027 /*
5028 * Name:
5029 * Copy
5030
5031 * Purpose:
5032 * Copy constructor for WcsMap objects.
5033
5034 * Type:
5035 * Private function.
5036
5037 * Synopsis:
5038 * void Copy( const AstObject *objin, AstObject *objout, int *status )
5039
5040 * Description:
5041 * This function implements the copy constructor for WcsMap objects.
5042
5043 * Parameters:
5044 * objin
5045 * Pointer to the object to be copied.
5046 * objout
5047 * Pointer to the object being constructed.
5048 * status
5049 * Pointer to the inherited status variable.
5050
5051 * Returned Value:
5052 * void
5053
5054 * Notes:
5055 * - This constructor makes a deep copy, including a copy of the
5056 * projection parameter values associated with the input WcsMap.
5057 */
5058
5059
5060 /* Local Variables: */
5061 AstWcsMap *in; /* Pointer to input WcsMap */
5062 AstWcsMap *out; /* Pointer to output WcsMap */
5063
5064 /* Check the global error status. */
5065 if ( !astOK ) return;
5066
5067 /* Obtain pointers to the input and output WcsMaps. */
5068 in = (AstWcsMap *) objin;
5069 out = (AstWcsMap *) objout;
5070
5071 /* Allocate memory to hold the projection parameters within the AstPrjPrm
5072 structure used by WCSLIB. */
5073 (out->params).p = astMalloc( astSizeOf( (in->params).p ) );
5074 (out->params).p2 = astMalloc( astSizeOf( (in->params).p2 ) );
5075
5076 /* Copy the projection parameter information. */
5077 CopyPV( in, out, status );
5078
5079 return;
5080
5081 }
5082
5083 /* Destructor. */
5084 /* ----------- */
Delete(AstObject * obj,int * status)5085 static void Delete( AstObject *obj, int *status ) {
5086 /*
5087 * Name:
5088 * Delete
5089
5090 * Purpose:
5091 * Destructor for WcsMap objects.
5092
5093 * Type:
5094 * Private function.
5095
5096 * Synopsis:
5097 * void Delete( AstObject *obj, int *status )
5098
5099 * Description:
5100 * This function implements the destructor for WcsMap objects.
5101
5102 * Parameters:
5103 * obj
5104 * Pointer to the object to be deleted.
5105 * status
5106 * Pointer to the inherited status variable.
5107
5108 * Returned Value:
5109 * void
5110
5111 * Notes:
5112 * This function attempts to execute even if the global error status is
5113 * set.
5114 */
5115
5116 /* Local Variables: */
5117 AstWcsMap *this; /* Pointer to WcsMap */
5118
5119 /* Obtain a pointer to the WcsMap structure. */
5120 this = (AstWcsMap *) obj;
5121
5122 /* Free the arrays used to store projection parameters. */
5123 FreePV( this, status );
5124
5125 /* Free memory used to hold the projection parameters within the AstPrjPrm
5126 structure used by WCSLIB. */
5127 this->params.p = astFree( this->params.p );
5128 this->params.p2 = astFree( this->params.p2 );
5129
5130 }
5131
5132 /* Dump function. */
5133 /* -------------- */
Dump(AstObject * this_object,AstChannel * channel,int * status)5134 static void Dump( AstObject *this_object, AstChannel *channel, int *status ) {
5135 /*
5136 * Name:
5137 * Dump
5138
5139 * Purpose:
5140 * Dump function for WcsMap objects.
5141
5142 * Type:
5143 * Private function.
5144
5145 * Synopsis:
5146 * void Dump( AstObject *this, AstChannel *channel, int *status )
5147
5148 * Description:
5149 * This function implements the Dump function which writes out data
5150 * for the WcsMap class to an output Channel.
5151
5152 * Parameters:
5153 * this
5154 * Pointer to the WcsMap whose data are being written.
5155 * channel
5156 * Pointer to the Channel to which the data are being written.
5157 * status
5158 * Pointer to the inherited status variable.
5159 */
5160
5161 #define COMMENT_LEN 150 /* Maximum length of a keyword comment */
5162 #define KEY_LEN 50 /* Maximum length of a keyword */
5163
5164 /* Local Variables: */
5165 AstWcsMap *this; /* Pointer to the WcsMap structure */
5166 char *comment; /* Pointer to comment string */
5167 char buff[ KEY_LEN + 1 ]; /* Buffer for keyword string */
5168 char comment_buff[ COMMENT_LEN + 1 ]; /* Buffer for keyword comment */
5169 const PrjData *prjdata; /* Information about the projection */
5170 double dval; /* Double precision value */
5171 int axis; /* Zero based axis index */
5172 int i; /* Axis index */
5173 int m; /* Parameter index */
5174 int ival; /* Integer value */
5175 int set; /* Attribute value set? */
5176
5177 /* Check the global error status. */
5178 if ( !astOK ) return;
5179
5180 /* Obtain a pointer to the WcsMap structure. */
5181 this = (AstWcsMap *) this_object;
5182
5183 /* Write out values representing the instance variables for the
5184 WcsMap class. Accompany these with appropriate comment strings,
5185 possibly depending on the values being written.*/
5186
5187 /* In the case of attributes, we first use the appropriate (private)
5188 Test... member function to see if they are set. If so, we then use
5189 the (private) Get... function to obtain the value to be written
5190 out. Note, all read-only attributes are considered to be set.
5191
5192 For attributes which are not set, we use the astGet... method to
5193 obtain the value instead. This will supply a default value
5194 (possibly provided by a derived class which over-rides this method)
5195 which is more useful to a human reader as it corresponds to the
5196 actual default attribute value. Since "set" will be zero, these
5197 values are for information only and will not be read back. */
5198
5199 /* WcsType. */
5200 /* -------- */
5201 ival = GetWcsType( this, status );
5202 prjdata = FindPrjData( ival, status );
5203 (void) sprintf( comment_buff, "%s projection", prjdata->desc );
5204 comment_buff[ 0 ] = toupper( comment_buff[ 0 ] );
5205 astWriteString( channel, "Type", 1, 1, prjdata->ctype + 1, comment_buff );
5206
5207 /* FITSProj */
5208 /* -------- */
5209 set = TestFITSProj( this, status );
5210 ival = set ? GetFITSProj( this, status ) : astGetFITSProj( this );
5211 astWriteInt( channel, "FitsPrj", set, 0, ival,
5212 ival ? "Defines the FITS-WCS projection" :
5213 "Does not define the FITS-WCS projection" );
5214
5215 /* TPNTan */
5216 /* ------ */
5217 set = TestTPNTan( this, status );
5218 ival = set ? GetTPNTan( this, status ) : astGetTPNTan( this );
5219 astWriteInt( channel, "TpnTan", set, 0, ival,
5220 ival ? "Include TAN projection in TPN mapping" :
5221 "Exclude TAN projection from TPN mapping" );
5222
5223 /* PVi_m. */
5224 /* ------ */
5225 for( i = 0; i < astGetNin( this ); i++ ){
5226 if( this->np ) {
5227 for( m = 0; m < this->np[ i ]; m++ ){
5228 set = TestPV( this, i, m, status );
5229 if( set ) {
5230 dval = set ? GetPV( this, i, m, status ) : astGetPV( this, i, m );
5231 (void) sprintf( buff, "PV%d_%d", i + 1, m );
5232 (void) sprintf( comment_buff, "Projection parameter %d for axis %d", m, i + 1 );
5233 astWriteDouble( channel, buff, set, 0, dval, comment_buff );
5234 }
5235 }
5236 }
5237 }
5238
5239 /* WcsAxis(axis). */
5240 /* -------------- */
5241 for( axis = 0; axis < 2; axis++ ){
5242 ival = GetWcsAxis( this, axis, status );
5243 (void) sprintf( buff, "WcsAx%d", axis + 1 );
5244 if( axis == 0 ) {
5245 comment = "Index of celestial longitude axis";
5246 } else {
5247 comment = "Index of celestial latitude axis";
5248 }
5249 astWriteInt( channel, buff, (axis!=ival), 0, ival + 1, comment );
5250 }
5251
5252 /* Note, the "params" component of the AstWcsMap structure is not written out
5253 because it can be re-generated from the other components. */
5254
5255 /* Return. */
5256 return;
5257
5258 /* Undefine macros local to this function. */
5259 #undef COMMENT_LEN
5260 #undef KEY_LEN
5261 }
5262
5263 /* Standard class functions. */
5264 /* ========================= */
5265 /* Implement the astIsAWcsMap and astCheckWcsMap functions using the macros
5266 defined for this purpose in the "object.h" header file. */
astMAKE_ISA(WcsMap,Mapping)5267 astMAKE_ISA(WcsMap,Mapping)
5268 astMAKE_CHECK(WcsMap)
5269
5270 AstWcsMap *astWcsMap_( int ncoord, int type, int lonax, int latax,
5271 const char *options, int *status, ...){
5272 /*
5273 *++
5274 * Name:
5275 c astWcsMap
5276 f AST_WCSMAP
5277
5278 * Purpose:
5279 * Create a WcsMap.
5280
5281 * Type:
5282 * Public function.
5283
5284 * Synopsis:
5285 c #include "wcsmap.h"
5286 c AstWcsMap *astWcsMap( int ncoord, int type, int lonax, int latax,
5287 c const char *options, ... )
5288 f RESULT = AST_WCSMAP( NCOORD, TYPE, LONAX, LATAX, OPTIONS, STATUS )
5289
5290 * Class Membership:
5291 * WcsMap constructor.
5292
5293 * Description:
5294 * This function creates a new WcsMap and optionally initialises its
5295 * attributes.
5296 *
5297 * A WcsMap is used to represent sky coordinate projections as
5298 * described in the (draft) FITS world coordinate system (FITS-WCS)
5299 * paper by E.W. Griesen and M. Calabretta (A & A, in preparation).
5300 * This paper defines a set of functions, or sky projections, which
5301 * transform longitude-latitude pairs representing spherical
5302 * celestial coordinates into corresponding pairs of Cartesian
5303 * coordinates (and vice versa).
5304 *
5305 * A WcsMap is a specialised form of Mapping which implements these
5306 * sky projections and applies them to a specified pair of coordinates.
5307 * All the projections in the FITS-WCS paper are supported, plus the now
5308 * deprecated "TAN with polynomial correction terms" projection which
5309 * is refered to here by the code "TPN". Using the FITS-WCS terminology,
5310 * the transformation is between "native spherical" and "projection
5311 * plane" coordinates. These coordinates may, optionally, be embedded in
5312 * a space with more than two dimensions, the remaining coordinates being
5313 * copied unchanged. Note, however, that for consistency with other AST
5314 * facilities, a WcsMap handles coordinates that represent angles
5315 * in radians (rather than the degrees used by FITS-WCS).
5316 *
5317 * The type of FITS-WCS projection to be used and the coordinates
5318 * (axes) to which it applies are specified when a WcsMap is first
5319 * created. The projection type may subsequently be determined
5320 * using the WcsType attribute and the coordinates on which it acts
5321 * may be determined using the WcsAxis(lonlat) attribute.
5322 *
5323 * Each WcsMap also allows up to 100 "projection parameters" to be
5324 * associated with each axis. These specify the precise form of the
5325 * projection, and are accessed using PVi_m attribute, where "i" is
5326 * the integer axis index (starting at 1), and m is an integer
5327 * "parameter index" in the range 0 to 99. The number of projection
5328 * parameters required by each projection, and their meanings, are
5329 * dependent upon the projection type (most projections either do not
5330 * use any projection parameters, or use parameters 1 and 2 associated
5331 * with the latitude axis). Before creating a WcsMap you should consult
5332 * the FITS-WCS paper for details of which projection parameters are
5333 * required, and which have defaults. When creating the WcsMap, you must
5334 * explicitly set values for all those required projection parameters
5335 * which do not have defaults defined in this paper.
5336
5337 * Parameters:
5338 c ncoord
5339 f NCOORD = INTEGER (Given)
5340 * The number of coordinate values for each point to be
5341 * transformed (i.e. the number of dimensions of the space in
5342 * which the points will reside). This must be at least 2. The
5343 * same number is applicable to both input and output points.
5344 c type
5345 f TYPE = INTEGER (Given)
5346 * The type of FITS-WCS projection to apply. This should be
5347 c given using a macro value such as AST__TAN (for a tangent
5348 f given as a symbolic value such as AST__TAN (for a tangent
5349 * plane projection), where the characters following the double
5350 * underscore give the projection type code (in upper case) as
5351 * used in the FITS-WCS "CTYPEi" keyword. You should consult the
5352 * FITS-WCS paper for a list of the available projections. The
5353 * additional code of AST__TPN can be supplied which represents a
5354 * TAN projection with polynomial correction terms as defined in an
5355 * early draft of the FITS-WCS paper.
5356 c lonax
5357 f LONAX = INTEGER (Given)
5358 * The index of the longitude axis. This should lie in the range
5359 c 1 to "ncoord".
5360 f 1 to NCOORD.
5361 c latax
5362 f LATAX = INTEGER (Given)
5363 * The index of the latitude axis. This should lie in the range
5364 c 1 to "ncoord" and be distinct from "lonax".
5365 f 1 to NCOORD and be distinct from LONAX.
5366 c options
5367 f OPTIONS = CHARACTER * ( * ) (Given)
5368 c Pointer to a null-terminated string containing an optional
5369 c comma-separated list of attribute assignments to be used for
5370 c initialising the new WcsMap. The syntax used is identical to
5371 c that for the astSet function and may include "printf" format
5372 c specifiers identified by "%" symbols in the normal way.
5373 f A character string containing an optional comma-separated
5374 f list of attribute assignments to be used for initialising the
5375 f new WcsMap. The syntax used is identical to that for the
5376 f AST_SET routine.
5377 *
5378 * If the sky projection to be implemented requires projection
5379 * parameter values to be set, then this should normally be done
5380 * here via the PVi_m attribute (see the "Examples"
5381 * section). Setting values for these parameters is mandatory if
5382 * they do not have default values (as defined in the FITS-WCS
5383 * paper).
5384 c ...
5385 c If the "options" string contains "%" format specifiers, then
5386 c an optional list of additional arguments may follow it in
5387 c order to supply values to be substituted for these
5388 c specifiers. The rules for supplying these are identical to
5389 c those for the astSet function (and for the C "printf"
5390 c function).
5391 f STATUS = INTEGER (Given and Returned)
5392 f The global status.
5393
5394 * Returned Value:
5395 c astWcsMap()
5396 f AST_WCSMAP = INTEGER
5397 * A pointer to the new WcsMap.
5398
5399 * Examples:
5400 c wcsmap = astWcsMap( 2, AST__MER, 1, 2, "" );
5401 f WCSMAP = AST_WCSMAP( 2, AST__MER, 1, 2, ' ', STATUS )
5402 * Creates a WcsMap that implements a FITS-WCS Mercator
5403 * projection on pairs of coordinates, with coordinates 1 and 2
5404 * representing the longitude and latitude respectively. Note
5405 * that the FITS-WCS Mercator projection does not require any
5406 * projection parameters.
5407 c wcsmap = astWcsMap( 3, AST__COE, 2, 3, "PV3_1=40.0" );
5408 f WCSMAP = AST_WCSMAP( 3, AST__COE, 2, 3, 'PV3_1=40.0', STATUS )
5409 * Creates a WcsMap that implements a FITS-WCS conical equal
5410 * area projection. The WcsMap acts on points in a 3-dimensional
5411 * space; coordinates 2 and 3 represent longitude and latitude
5412 * respectively, while the values of coordinate 1 are copied
5413 * unchanged. Projection parameter 1 associatyed with the latitude
5414 * axis (corresponding to FITS keyword "PV3_1") is required and has
5415 * no default, so is set explicitly to 40.0 degrees. Projection
5416 * parameter 2 (corresponding to FITS keyword "PV3_2") is required
5417 * but has a default of zero, so need not be specified.
5418
5419 * Notes:
5420 * - The forward transformation of a WcsMap converts between
5421 * FITS-WCS "native spherical" and "relative physical" coordinates,
5422 * while the inverse transformation converts in the opposite
5423 * direction. This arrangement may be reversed, if required, by
5424 c using astInvert or by setting the Invert attribute to a non-zero
5425 f using AST_INVERT or by setting the Invert attribute to a non-zero
5426 * value.
5427 * - If any set of coordinates cannot be transformed (for example,
5428 * many projections do not cover the entire celestial sphere), then
5429 * a WcsMap will yield coordinate values of AST__BAD.
5430 * - The validity of any projection parameters given via the PVi_m
5431 c parameter in the "options" string is not checked by this
5432 f parameter in the OPTIONS string is not checked by this
5433 * function. However, their validity is checked when the resulting
5434 * WcsMap is used to transform coordinates, and an error will
5435 * result if the projection parameters do not satisfy all the
5436 * required constraints (as defined in the FITS-WCS paper).
5437 * - A null Object pointer (AST__NULL) will be returned if this
5438 c function is invoked with the AST error status set, or if it
5439 f function is invoked with STATUS set to an error value, or if it
5440 * should fail for any reason.
5441
5442 * Status Handling:
5443 * The protected interface to this function includes an extra
5444 * parameter at the end of the parameter list descirbed above. This
5445 * parameter is a pointer to the integer inherited status
5446 * variable: "int *status".
5447
5448 *--
5449 */
5450
5451 /* Local Variables: */
5452 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
5453 AstWcsMap *new; /* Pointer to new WcsMap */
5454 va_list args; /* Variable argument list */
5455
5456 /* Check the global status. */
5457 if ( !astOK ) return NULL;
5458
5459 /* Get a pointer to the thread specific global data structure. */
5460 astGET_GLOBALS(NULL);
5461
5462 /* Initialise the WcsMap, allocating memory and initialising the
5463 virtual function table as well if necessary. */
5464 new = astInitWcsMap( NULL, sizeof( AstWcsMap ), !class_init, &class_vtab,
5465 "WcsMap", ncoord, type, lonax - 1, latax - 1 );
5466
5467 /* If successful, note that the virtual function table has been
5468 initialised. */
5469 if ( astOK ) {
5470 class_init = 1;
5471
5472 /* Obtain the variable argument list and pass it along with the options string
5473 to the astVSet method to initialise the new WcsMap's attributes. */
5474 va_start( args, status );
5475 astVSet( new, options, NULL, args );
5476 va_end( args );
5477
5478 /* If an error occurred, clean up by deleting the new object. */
5479 if ( !astOK ) new = astDelete( new );
5480 }
5481
5482 /* Return a pointer to the new WcsMap. */
5483 return new;
5484 }
5485
astWcsMapId_(int ncoord,int type,int lonax,int latax,const char * options,...)5486 AstWcsMap *astWcsMapId_( int ncoord, int type, int lonax, int latax,
5487 const char *options, ... ){
5488 /*
5489 * Name:
5490 * astWcsMapId_
5491
5492 * Purpose:
5493 * Create a WcsMap.
5494
5495 * Type:
5496 * Private function.
5497
5498 * Synopsis:
5499 * #include "wcsmap.h"
5500 * AstWcsMap *astWcsMap_( int ncoord, int type, int lonax, int latax,
5501 * const char *options, ... )
5502
5503 * Class Membership:
5504 * WcsMap constructor.
5505
5506 * Description:
5507 * This function implements the external (public) interface to the
5508 * astWcsMap constructor function. It returns an ID value (instead
5509 * of a true C pointer) to external users, and must be provided
5510 * because astWcsMap_ has a variable argument list which cannot be
5511 * encapsulated in a macro (where this conversion would otherwise
5512 * occur).
5513 *
5514 * The variable argument list also prevents this function from
5515 * invoking astWcsMap_ directly, so it must be a re-implementation
5516 * of it in all respects, except for the final conversion of the
5517 * result to an ID value.
5518
5519 * Parameters:
5520 * As for astWcsMap_.
5521
5522 * Returned Value:
5523 * The ID value associated with the new WcsMap.
5524 */
5525
5526 /* Local Variables: */
5527 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
5528 AstWcsMap *new; /* Pointer to new WcsMap */
5529 va_list args; /* Variable argument list */
5530 int *status; /* Pointer to inherited status value */
5531
5532 /* Get a pointer to the inherited status value. */
5533 status = astGetStatusPtr;
5534
5535 /* Get a pointer to the thread specific global data structure. */
5536 astGET_GLOBALS(NULL);
5537
5538 /* Check the global status. */
5539 if ( !astOK ) return NULL;
5540
5541 /* Initialise the WcsMap, allocating memory and initialising the
5542 virtual function table as well if necessary. */
5543 new = astInitWcsMap( NULL, sizeof( AstWcsMap ), !class_init, &class_vtab,
5544 "WcsMap", ncoord, type, lonax - 1, latax - 1 );
5545
5546 /* If successful, note that the virtual function table has been
5547 initialised. */
5548 if ( astOK ) {
5549 class_init = 1;
5550
5551 /* Obtain the variable argument list and pass it along with the options string
5552 to the astVSet method to initialise the new WcsMap's attributes. */
5553 va_start( args, options );
5554 astVSet( new, options, NULL, args );
5555 va_end( args );
5556
5557 /* If an error occurred, clean up by deleting the new object. */
5558 if ( !astOK ) new = astDelete( new );
5559 }
5560
5561 /* Return an ID value for the new WcsMap. */
5562 return astMakeId( new );
5563 }
5564
astInitWcsMap_(void * mem,size_t size,int init,AstWcsMapVtab * vtab,const char * name,int ncin,int type,int lonax,int latax,int * status)5565 AstWcsMap *astInitWcsMap_( void *mem, size_t size, int init,
5566 AstWcsMapVtab *vtab, const char *name,
5567 int ncin, int type, int lonax, int latax, int *status ) {
5568 /*
5569 *+
5570 * Name:
5571 * astInitWcsMap
5572
5573 * Purpose:
5574 * Initialise a WcsMap.
5575
5576 * Type:
5577 * Protected function.
5578
5579 * Synopsis:
5580 * #include "wcsmap.h"
5581 * AstWcsMap *astInitWcsMap( void *mem, size_t size, int init,
5582 * AstWcsMapVtab *vtab, const char *name,
5583 * int ncin, int type, int lonax, int latax )
5584
5585 * Class Membership:
5586 * WcsMap initialiser.
5587
5588 * Description:
5589 * This function is provided for use by class implementations to initialise
5590 * a new WcsMap object. It allocates memory (if necessary) to accommodate
5591 * the WcsMap plus any additional data associated with the derived class.
5592 * It then initialises a WcsMap structure at the start of this memory. If
5593 * the "init" flag is set, it also initialises the contents of a virtual
5594 * function table for a WcsMap at the start of the memory passed via the
5595 * "vtab" parameter.
5596
5597 * Parameters:
5598 * mem
5599 * A pointer to the memory in which the WcsMap is to be initialised.
5600 * This must be of sufficient size to accommodate the WcsMap data
5601 * (sizeof(WcsMap)) plus any data used by the derived class. If a value
5602 * of NULL is given, this function will allocate the memory itself using
5603 * the "size" parameter to determine its size.
5604 * size
5605 * The amount of memory used by the WcsMap (plus derived class data).
5606 * This will be used to allocate memory if a value of NULL is given for
5607 * the "mem" parameter. This value is also stored in the WcsMap
5608 * structure, so a valid value must be supplied even if not required for
5609 * allocating memory.
5610 * init
5611 * A logical flag indicating if the WcsMap's virtual function table is
5612 * to be initialised. If this value is non-zero, the virtual function
5613 * table will be initialised by this function.
5614 * vtab
5615 * Pointer to the start of the virtual function table to be associated
5616 * with the new WcsMap.
5617 * name
5618 * Pointer to a constant null-terminated character string which contains
5619 * the name of the class to which the new object belongs (it is this
5620 * pointer value that will subsequently be returned by the astGetClass
5621 * method).
5622 * ncin
5623 * The number of coordinate values per point.
5624 * type
5625 * The type of projection to use, choosen from the list available
5626 * in the FITS celestial coordinates system. These are specified by
5627 * symbolic values such as AST__TAN (specifying a tangent plane
5628 * projection), where the characters following the double underscore
5629 * gives the FITS projection type (in upper case) as used in the FITS
5630 * "CTYPEn" keyword.
5631 * lonax
5632 * The index of the longitude axis. The first axis has index 0.
5633 * latax
5634 * The index of the latitude axis. The first axis has index 0.
5635
5636 * Returned Value:
5637 * A pointer to the new WcsMap.
5638
5639 * Notes:
5640 * - A null pointer will be returned if this function is invoked with the
5641 * global error status set, or if it should fail for any reason.
5642 *-
5643 */
5644
5645 /* Local Variables: */
5646 const PrjData *prjdata; /* Information about the projection */
5647 AstWcsMap *new; /* Pointer to new WcsMap */
5648
5649 /* Check the global status. */
5650 if ( !astOK ) return NULL;
5651
5652 /* If necessary, initialise the virtual function table. */
5653 if ( init ) astInitWcsMapVtab( vtab, name );
5654
5655 /* Initialise. */
5656 new = NULL;
5657
5658 /* If a genuine FITS-WCS projection has been specified, check the initialisation
5659 value(s) for validity, reporting an error if necessary. Prefix the error
5660 report with the name of the function and the class of object being
5661 processed. First check that at least two dimensions are to be mapped. */
5662 if( type != AST__WCSBAD ){
5663 if ( ncin < 2 ){
5664 astError( AST__WCSNC, "astInitWcsMap(%s): Too few axes (%d) "
5665 "specified. Must be at least 2.", status, name, ncin );
5666
5667 /* Report an error if either the longitude or latitude axes are out of
5668 bounds. */
5669 } else if ( lonax < 0 || lonax >= ncin ){
5670 astError( AST__WCSAX, "astInitWcsMap(%s): Specified longitude axis (%d) "
5671 "does not exist within a %d dimensional coordinate system. ", status,
5672 name, lonax + 1, ncin );
5673
5674 } else if ( latax < 0 || latax >= ncin ){
5675 astError( AST__WCSAX, "astInitWcsMap(%s): Specified latitude axis (%d) "
5676 "does not exist within a %d dimensional coordinate system. ", status,
5677 name, latax + 1, ncin );
5678
5679 /* Report an error if the longitude or latitude axes are the same. */
5680 } else if ( lonax == latax ){
5681 astError( AST__WCSAX, "astInitWcsMap(%s): The same axis (%d) has been "
5682 "given for both the longitude and the latitude axis.", status, name,
5683 lonax + 1 );
5684
5685 /* Report an error if projection type is unknown. */
5686 } else if ( type < 1 || type >= AST__WCSBAD ){
5687 astError( AST__WCSTY, "astInitWcsMap(%s): Projection type %d is "
5688 "undefined. Projection types must be in the range 1 to %d.", status,
5689 name, type, AST__WCSBAD - 1 );
5690 }
5691 }
5692
5693 /* Get a description of the requeste dprojection type. */
5694 prjdata = FindPrjData( type, status );
5695
5696 /* If all the above checks have been passed succesfully... */
5697 if( astOK ){
5698
5699 /* Initialise a Mapping structure (the parent class) as the first component
5700 within the WcsMap structure, allocating memory if necessary. Specify that
5701 the Mapping should be defined in both the forward and inverse directions. */
5702 new = (AstWcsMap *) astInitMapping( mem, size, 0,
5703 (AstMappingVtab *) vtab, name,
5704 ncin, ncin, 1, 1 );
5705
5706 if ( astOK ) {
5707
5708 /* Initialise the WcsMap data. */
5709 /* ---------------------------- */
5710 /* Store the projection type. */
5711 new->type = type;
5712
5713 /* Store the "use as FITS-WCS projection" flag. */
5714 new->fits_proj = -INT_MAX;
5715
5716 /* Store the "include TAN component in TPN Mapping" flag. */
5717 new->tpn_tan = -INT_MAX;
5718
5719 /* Store the axes associated with longitude and latitude. */
5720 new->wcsaxis[0] = lonax;
5721 new->wcsaxis[1] = latax;
5722
5723 /* Store NULL pointers for the arrays holding projection parameters. */
5724 new->p = NULL;
5725 new->np = NULL;
5726
5727 /* Allocate memory of the right size to hold the maximum number of
5728 projection parameters needed by the projection. */
5729 new->params.p = astMalloc( sizeof( double ) * (prjdata->mxpar + 1) );
5730 new->params.p2 = astMalloc( sizeof( double ) * (prjdata->mxpar2 + 1) );
5731
5732 /* Initialise the "AstPrjPrm" structure (defined in proj.h). */
5733 InitPrjPrm( new, status );
5734
5735 /* If an error occurred, clean up by deleting the new WcsMap. */
5736 if ( !astOK ) new = astDelete( new );
5737 }
5738 }
5739
5740 /* Return a pointer to the new WcsMap. */
5741 return new;
5742 }
5743
astLoadWcsMap_(void * mem,size_t size,AstWcsMapVtab * vtab,const char * name,AstChannel * channel,int * status)5744 AstWcsMap *astLoadWcsMap_( void *mem, size_t size,
5745 AstWcsMapVtab *vtab, const char *name,
5746 AstChannel *channel, int *status ) {
5747 /*
5748 *+
5749 * Name:
5750 * astLoadWcsMap
5751
5752 * Purpose:
5753 * Load a WcsMap.
5754
5755 * Type:
5756 * Protected function.
5757
5758 * Synopsis:
5759 * #include "wcsmap.h"
5760 * AstWcsMap *astLoadWcsMap( void *mem, size_t size,
5761 * AstWcsMapVtab *vtab, const char *name,
5762 * AstChannel *channel )
5763
5764 * Class Membership:
5765 * WcsMap loader.
5766
5767 * Description:
5768 * This function is provided to load a new WcsMap using data read
5769 * from a Channel. It first loads the data used by the parent class
5770 * (which allocates memory if necessary) and then initialises a
5771 * WcsMap structure in this memory, using data read from the input
5772 * Channel.
5773 *
5774 * If the "init" flag is set, it also initialises the contents of a
5775 * virtual function table for a WcsMap at the start of the memory
5776 * passed via the "vtab" parameter.
5777
5778
5779 * Parameters:
5780 * mem
5781 * A pointer to the memory into which the WcsMap is to be
5782 * loaded. This must be of sufficient size to accommodate the
5783 * WcsMap data (sizeof(WcsMap)) plus any data used by derived
5784 * classes. If a value of NULL is given, this function will
5785 * allocate the memory itself using the "size" parameter to
5786 * determine its size.
5787 * size
5788 * The amount of memory used by the WcsMap (plus derived class
5789 * data). This will be used to allocate memory if a value of
5790 * NULL is given for the "mem" parameter. This value is also
5791 * stored in the WcsMap structure, so a valid value must be
5792 * supplied even if not required for allocating memory.
5793 *
5794 * If the "vtab" parameter is NULL, the "size" value is ignored
5795 * and sizeof(AstWcsMap) is used instead.
5796 * vtab
5797 * Pointer to the start of the virtual function table to be
5798 * associated with the new WcsMap. If this is NULL, a pointer
5799 * to the (static) virtual function table for the WcsMap class
5800 * is used instead.
5801 * name
5802 * Pointer to a constant null-terminated character string which
5803 * contains the name of the class to which the new object
5804 * belongs (it is this pointer value that will subsequently be
5805 * returned by the astGetClass method).
5806 *
5807 * If the "vtab" parameter is NULL, the "name" value is ignored
5808 * and a pointer to the string "WcsMap" is used instead.
5809
5810 * Returned Value:
5811 * A pointer to the new WcsMap.
5812
5813 * Notes:
5814 * - A null pointer will be returned if this function is invoked
5815 * with the global error status set, or if it should fail for any
5816 * reason.
5817 *-
5818 */
5819
5820 #define KEY_LEN 50 /* Maximum length of a keyword */
5821
5822 astDECLARE_GLOBALS /* Pointer to thread-specific global data */
5823 /* Local Variables: */
5824 const PrjData *prjdata; /* Information about the projection */
5825 AstWcsMap *new; /* Pointer to the new WcsMap */
5826 char *text; /* Textual form of an integer value */
5827 char buff[ KEY_LEN + 1 ]; /* Buffer for keyword string */
5828 double pv; /* Projection parameter */
5829 int axis; /* Axis index */
5830 int i; /* Axis index */
5831 int m; /* Parameter index */
5832 int mxpar; /* Maximum number of PVi_m values */
5833
5834 /* Get a pointer to the thread specific global data structure. */
5835 astGET_GLOBALS(channel);
5836
5837 /* Initialise. */
5838 new = NULL;
5839
5840 /* Check the global error status. */
5841 if ( !astOK ) return new;
5842
5843 /* If a NULL virtual function table has been supplied, then this is
5844 the first loader to be invoked for this WcsMap. In this case the
5845 WcsMap belongs to this class, so supply appropriate values to be
5846 passed to the parent class loader (and its parent, etc.). */
5847 if ( !vtab ) {
5848 size = sizeof( AstWcsMap );
5849 vtab = &class_vtab;
5850 name = "WcsMap";
5851
5852 /* If required, initialise the virtual function table for this class. */
5853 if ( !class_init ) {
5854 astInitWcsMapVtab( vtab, name );
5855 class_init = 1;
5856 }
5857 }
5858
5859 /* Invoke the parent class loader to load data for all the ancestral
5860 classes of the current one, returning a pointer to the resulting
5861 partly-built WcsMap. */
5862 new = astLoadMapping( mem, size, (AstMappingVtab *) vtab, name,
5863 channel );
5864
5865 if ( astOK ) {
5866
5867 /* Read input data. */
5868 /* ================ */
5869 /* Request the input Channel to read all the input data appropriate to
5870 this class into the internal "values list". */
5871 astReadClassData( channel, "WcsMap" );
5872
5873 /* Now read each individual data item from this list and use it to
5874 initialise the appropriate instance variable(s) for this class. */
5875
5876 /* In the case of attributes, we first read the "raw" input value,
5877 supplying the "unset" value as the default. If a "set" value is
5878 obtained, we then use the appropriate (private) Set... member
5879 function to validate and set the value properly. Note, this is only
5880 done for read/write attributes, not read-only ones. */
5881
5882 /* FITSProj */
5883 /* -------- */
5884 new->fits_proj = astReadInt( channel, "fitsprj", -INT_MAX );
5885 if ( TestFITSProj( new, status ) ) {
5886 SetFITSProj( new, new->fits_proj, status );
5887 }
5888
5889 /* TPNTan */
5890 /* -------- */
5891 new->tpn_tan = astReadInt( channel, "tpntan", -INT_MAX );
5892 if ( TestTPNTan( new, status ) ) {
5893 SetTPNTan( new, new->tpn_tan, status );
5894 }
5895
5896 /* WcsType */
5897 /* ------- */
5898 text = astReadString( channel, "type", " " );
5899 if( strcmp( text, " " ) ){
5900 char tmp[ 10 ];
5901 (void) sprintf( tmp, "-%.8s", text );
5902 new->type = astWcsPrjType( tmp );
5903 } else {
5904 new->type = AST__WCSBAD;
5905 }
5906 text = astFree( text );
5907 prjdata = FindPrjData( new->type, status );
5908
5909 /* WcsAxis(axis). */
5910 /* -------------- */
5911 for( axis = 0; axis < 2; axis++ ){
5912 (void) sprintf( buff, "wcsax%d", axis + 1 );
5913 new->wcsaxis[ axis ] = astReadInt( channel, buff, axis + 1 ) - 1;
5914 }
5915
5916 /* Initialise the pointers to the projection parameter information. */
5917 new->p = NULL;
5918 new->np = NULL;
5919 new->params.p = astMalloc( sizeof( double ) * (prjdata->mxpar + 1) );
5920 new->params.p2 = astMalloc( sizeof( double ) * (prjdata->mxpar2 + 1) );
5921
5922 /* Initialise the structure used by WCSLIB to hold intermediate values,
5923 so that the values will be re-calculated on the first invocation of a
5924 mapping function. */
5925 InitPrjPrm( new, status );
5926
5927 /* ProjP(m). */
5928 /* --------- */
5929 for( m = 0; m < AST__WCSMX; m++ ){
5930 (void) sprintf( buff, "projp%d", m );
5931 pv = astReadDouble( channel, buff, AST__BAD );
5932 if( pv != AST__BAD ) SetPV( new, new->wcsaxis[ 1 ], m, pv, status );
5933 }
5934
5935 /* PVi_m. */
5936 /* -------*/
5937 for( i = 0; i < astGetNin( new ); i++ ){
5938
5939 if( i == new->wcsaxis[ 0 ] ) {
5940 mxpar = prjdata->mxpar2;
5941 } else if( i == new->wcsaxis[ 1 ] ) {
5942 mxpar = prjdata->mxpar;
5943 } else {
5944 mxpar = 0;
5945 }
5946
5947 for( m = 0; m <= mxpar; m++ ){
5948 (void) sprintf( buff, "pv%d_%d", i + 1, m );
5949 pv = astReadDouble( channel, buff, AST__BAD );
5950 if( pv != AST__BAD ) SetPV( new, i, m, pv, status );
5951 }
5952 }
5953
5954 /* If an error occurred, clean up by deleting the new WcsMap. */
5955 if ( !astOK ) new = astDelete( new );
5956 }
5957
5958 /* Return the new WcsMap pointer. */
5959 return new;
5960
5961 /* Undefine macros local to this function. */
5962 #undef KEY_LEN
5963 }
5964
5965 /* Virtual function interfaces. */
5966 /* ============================ */
5967 /* These provide the external interface to the virtual functions defined by
5968 this class. Each simply checks the global error status and then locates and
5969 executes the appropriate member function, using the function pointer stored
5970 in the object's virtual function table (this pointer is located using the
5971 astMEMBER macro defined in "object.h").
5972
5973 Note that the member function may not be the one defined here, as it may
5974 have been over-ridden by a derived class. However, it should still have the
5975 same interface. */
5976
astClearPV_(AstWcsMap * this,int i,int m,int * status)5977 void astClearPV_( AstWcsMap *this, int i, int m, int *status ) {
5978 if ( !astOK ) return;
5979 (**astMEMBER(this,WcsMap,ClearPV))( this, i, m, status );
5980 }
5981
astClearTPNTan_(AstWcsMap * this,int * status)5982 void astClearTPNTan_( AstWcsMap *this, int *status ) {
5983 if ( !astOK ) return;
5984 (**astMEMBER(this,WcsMap,ClearTPNTan))( this, status );
5985 }
5986
astGetPV_(AstWcsMap * this,int i,int m,int * status)5987 double astGetPV_( AstWcsMap *this, int i, int m, int *status ) {
5988 if ( !astOK ) return AST__BAD;
5989 return (**astMEMBER(this,WcsMap,GetPV))( this, i, m, status );
5990 }
5991
astSetPV_(AstWcsMap * this,int i,int m,double val,int * status)5992 void astSetPV_( AstWcsMap *this, int i, int m, double val, int *status ) {
5993 if ( !astOK ) return;
5994 (**astMEMBER(this,WcsMap,SetPV))( this, i, m, val, status );
5995 }
5996
astSetTPNTan_(AstWcsMap * this,int val,int * status)5997 void astSetTPNTan_( AstWcsMap *this, int val, int *status ) {
5998 if ( !astOK ) return;
5999 (**astMEMBER(this,WcsMap,SetTPNTan))( this, val, status );
6000 }
6001
astTestPV_(AstWcsMap * this,int i,int m,int * status)6002 int astTestPV_( AstWcsMap *this, int i, int m, int *status ) {
6003 if ( !astOK ) return 0;
6004 return (**astMEMBER(this,WcsMap,TestPV))( this, i, m, status );
6005 }
6006
astIsZenithal_(AstWcsMap * this,int * status)6007 int astIsZenithal_( AstWcsMap *this, int *status ) {
6008 if ( !astOK ) return 0;
6009 return (**astMEMBER(this,WcsMap,IsZenithal))( this, status );
6010 }
6011
astGetNatLat_(AstWcsMap * this,int * status)6012 double astGetNatLat_( AstWcsMap *this, int *status ) {
6013 if ( !astOK ) return AST__BAD;
6014 return (**astMEMBER(this,WcsMap,GetNatLat))( this, status );
6015 }
6016
astGetNatLon_(AstWcsMap * this,int * status)6017 double astGetNatLon_( AstWcsMap *this, int *status ) {
6018 if ( !astOK ) return AST__BAD;
6019 return (**astMEMBER(this,WcsMap,GetNatLon))( this, status );
6020 }
6021
astGetPVMax_(AstWcsMap * this,int i,int * status)6022 int astGetPVMax_( AstWcsMap *this, int i, int *status ) {
6023 if ( !astOK ) return -1;
6024 return (**astMEMBER(this,WcsMap,GetPVMax))( this, i, status );
6025 }
6026
6027
6028
6029
6030
6031
6032
6033