casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
DirectionCoordinate.h
Go to the documentation of this file.
00001 //# DirectionCoordinate.h: Interconvert pixel positions and directions (e.g. RA/DEC)
00002 //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003,2004
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //#
00027 //# $Id: 
00028 
00029 
00030 #ifndef COORDINATES_DIRECTIONCOORDINATE_H
00031 #define COORDINATES_DIRECTIONCOORDINATE_H
00032 
00033 #include <casa/aips.h>
00034 #include <coordinates/Coordinates/Coordinate.h>
00035 #include <coordinates/Coordinates/Projection.h>
00036 #include <casa/Arrays/Vector.h>
00037 #include <measures/Measures/MDirection.h>
00038 #include <measures/Measures/MeasConvert.h>
00039 #include <casa/Quanta/RotMatrix.h>
00040 #include <wcslib/wcs.h>
00041 
00042 class celprm;
00043 class prjprm;
00044 class wcsprm;
00045 
00046 namespace casa { //# NAMESPACE CASA - BEGIN
00047 
00048 class MVDirection;
00049 class MVAngle;
00050 class LogIO;
00051 template<class T> class Quantum;
00052 
00053 
00054 // <summary>
00055 // Interconvert pixel positions and directions (e.g. RA/DEC).
00056 // </summary>
00057 
00058 // <use visibility=export>
00059 
00060 // <reviewed reviewer="Peter Barnes" date="1999/12/24" tests="tDirectionCoordinate"> 
00061 // </reviewed>
00062 
00063 
00064 // <prerequisite>
00065 //   <li> Knowledge of astronomical coordinate conversions in general. Probably the
00066 //        best documents are the papers by Mark Calabretta and Eric Greisen.
00067 //        The initial draft from 1996 can be found at
00068 //        http://www.atnf.csiro.au/~mcalabre.  It is this draft that the
00069 //        Coordinate classes are based upon.  Since then, this paper has evolved
00070 //        into three which can be found at the above address, and will be published in the
00071 //        Astronomy and Astrophysics Supplement Series (probably in 2000).
00072 //        The design has changed since the initial draft.  When these papers
00073 //        are finalized, and the IAU has ratified the new standards, WCSLIB
00074 //        (Mark Calabretta's implementation of these conventions) will be
00075 //        revised for the new designs.  At that time, the Coordinate classes
00076 //        may also be revised.
00077 //   <li> <linkto class=Coordinate>Coordinate</linkto> defines the fundamental
00078 //        interface to coordinate conversions.
00079 //   <li> <linkto class=MDirection>MDirection</linkto> defines the types of
00080 //        directions (J2000 etc.) which are defined. The measures machinery
00081 //        also implements "astronomical" conversions which are outside the
00082 //        scope of these coordinates (for example, <src>J2000</src> to
00083 //        <src>B1950</src>).
00084 //   <li> <linkto class=Projection>Projection</linkto> defines the types of
00085 //        celestial projections which are available.
00086 // </prerequisite>
00087 //
00088 // <synopsis>
00089 // This class implements pixel to world coordinate conversions. This class
00090 // implements geometric conversions (e.g. SIN projection) via the WCS library
00091 // and also provides an interface to astronomical conversions (RA/DEC <--> l,b)
00092 // via the <linkto module=Measures>Measures</linkto> module.
00093 // </synopsis>
00094 //
00095 //
00096 // <note role=caution>
00097 // All absolute pixels coordinates are zero relative.
00098 // </note>
00099 //
00100 // <example>
00101 // Let's make a DirectionCoordinate --- used to represent a direction,
00102 // usually an RA/DEC, but it could also be, e.g., an AZ/EL pair.
00103 // <srcblock>
00104 //    Matrix<Double> xform(2,2);                                    // 1
00105 //    xform = 0.0; xform.diagonal() = 1.0;                          // 2
00106 //    DirectionCoordinate radec(MDirection::J2000,                  // 3 
00107 //                            Projection(Projection::SIN),          // 4 
00108 //                            135*C::pi/180.0, 60*C::pi/180.0,      // 5
00109 //                            -1*C::pi/180.0, 1*C::pi/180,          // 6
00110 //                            xform,                                // 7
00111 //                            128, 128);                            // 8   
00112 // </srcblock>
00113 // <ul>
00114 //    <li> <i>1-2:</i>Here we set up a diagonal transformation matrix.      
00115 //         Normally this matrix should be diagonal, however if you wanted
00116 //         to introduce a rotation or skew, you would do it through this
00117 //         matrix.
00118 //    <li> <i>3:</i>This defines the astronomical type of the world
00119 //         coordinate. Most of the time it will probably be J2000   
00120 //         or B1950, but many other possibilities are possible as listed
00121 //         in the <linkto class=MDirection>MDirection</linkto> class
00122 //         header.
00123 //    <li> <i>4:</i>The <linkto class=Projection>Projection</linkto> class
00124 //         defines the "geometry" that is used to map <src>xy<-->world</src>. SIN
00125 //         is the most common projection for radio interferometers. Note that
00126 //         SIN can optionally take parameters as defined in Calabretta and Greisen.
00127 //         If not provided, they default to 0.0, which is the "old" SIN
00128 //         convention.
00129 //    <li> <i>5:</i>Set the reference position to RA=135, DEC=60 degrees.
00130 //         Note that the native units of a Direction is radians.
00131 //    <li> <i>6:</i> Set the increments to -1 degree in RA, and +1 degree
00132 //         in DEC.
00133 //    <li> <i>7:</i> Set the previously defined transformation matrix.
00134 //    <li> <i>8:</i> Set the zero-relative reference pixel. Note that it does
00135 //         not have to be incremental. At the reference pixel, the world 
00136 //         coordinate has the reference value.
00137 // </ul>
00138 // 
00139 // In this example is is more convenient to change the units to degrees. This can
00140 // be accomplished as follows:
00141 // <srcblock>
00142 //    Vector<String> units(2); units = "deg";                       //  9
00143 //    radec.setWorldAxisUnits(units);                               // 10
00144 // </srcblock>
00145 // The increment and reference value are updated appropriately.  
00146 // 
00147 // Set up a couple of vectors to use the world and pixel coordinate values.  
00148 // <srcblock>
00149 //    Vector<Double> world(2), pixel(2);                            // 11
00150 //    pixel = 138.0;                                                // 12
00151 // </srcblock>
00152 // We use 138 as an arbitrary pixel position which is near the reference pixel
00153 // so we can tell if the answers look foolish or not.
00154 // We can actually perform a transformation like this as follows. If
00155 // it succeeds we print the value of the world coordinate.
00156 // <srcblock>
00157 //    Bool ok = radec.toWorld(world, pixel);                        // 13
00158 //    if (!ok) {                                                    // 14 
00159 //      cout << "Error: " << radec.errorMessage() << endl;          // 15
00160 //      return 1;                                                   // 16
00161 //    }                                                             // 17
00162 //    cout << world << " <--- " << pixel << endl;         // 18
00163 // </srcblock>
00164 // There is an overloaded "toWorld" function that produces an MDirection
00165 // in case you want to, e.g., find out what the position in B1950 coordinates
00166 // would be.
00167 //                              
00168 // The reverse transformation takes place similarly:
00169 // <srcblock>
00170 //    ok = radec.toPixel(pixel, world);                             // 19   
00171 // </srcblock>
00172 // </example>
00173 //
00174 // <example>
00175 // We could also have made the above DirectionCoordinate using the Quantum-based
00176 // constructor, which is a little more elegant if you want to use degrees.
00177 //
00178 //    Matrix<Double> xform(2,2);                
00179 //    xform = 0.0; xform.diagonal() = 1.0;                 
00180 //    Quantum<Double> refLon(135.0, "deg");
00181 //    Quantum<Double> refLat(60.0, "deg");
00182 //    Quantum<Double> incLon(-1.0, "deg");
00183 //    Quantum<Double> incLat(1.0, "deg");
00184 //    DirectionCoordinate radec(MDirection::J2000,         
00185 //                            Projection(Projection::SIN), 
00186 //                            refLon, refLat,
00187 //                            incLon, incLat,
00188 //                            xform,      
00189 //                            128, 128);  
00190 //
00191 // But note that the constructor will have converted the native units
00192 // of the DirectionCoordinate to radians.  So the Double-based toWorld and
00193 // toPixel functions will be in terms of radians.   If you want the native
00194 // units to be degrees, then again you can use 
00195 //
00196 // <srcblock>
00197 //    Vector<String> units(2); units = "deg";         
00198 //    radec.setWorldAxisUnits(units);                 
00199 // </srcblock>
00200 // and thereafter degrees are the native units.
00201 // </example>
00202 //
00203 // <motivation>
00204 // Directions in the sky are fundamental to astronomy.
00205 // </motivation>
00206 //
00207 //
00208 // <thrown>
00209 //   <li>  AipsError
00210 // </thrown>
00211 //
00212 // <todo asof="2000/01/01">
00213 //   <li> Nothing
00214 // </todo>
00215 
00216 
00217 class DirectionCoordinate : public Coordinate
00218 {
00219 public:
00220     // The default constructor creates a J2000 DirectionCoordinate with a
00221     // CARtesion projection with longitude,latitude 0,0 at pixel 0,0 and an
00222     // increment of +1 radian per pixel on both axes.
00223     DirectionCoordinate();
00224 
00225     // Define the DirectionCoordinate transformation. <src>refLong</src> and 
00226     // <src>refLat</src> will normally the the RA/DEC of the pixel described by 
00227     // <src>refX/refY</src>. <src>incLat/incLong</src>
00228     // are the increments per pixel (RA is usually negative), and the <src>xform</src>
00229     // matrix is usually the unit diagonal matrix unless you have a rotation or
00230     // some other linear transformation between the pixel and world axes.
00231     // 
00232     // Note that the units are radians initially. You can change it to degrees
00233     // or something else with the <src>setWorldAxisUnits</src> method later if you want.
00234     // 
00235     // longPole and latPole are defined by Calabretta and Greisen (these
00236     // are reference points not at the native pole).  In general
00237     // you can leave these out and the default values will cause them
00238     // to be computed appropriately.  However, when reading from FITS
00239     // the LONPOLE and LATPOLE keywords are passed along here.
00240     DirectionCoordinate(MDirection::Types directionType,
00241                         const Projection &projection,
00242                         Double refLong, Double refLat,
00243                         Double incLong, Double incLat,
00244                         const Matrix<Double> &xform,
00245                         Double refX, Double refY,
00246                         Double longPole=999.0, Double latPole=999.0);
00247 
00248     // Create DirectionCoordinate with Quantum-based interface. 
00249     // Parameters are the same as above.
00250     // Regardless of the units of the quanta, the initial units
00251     // of the DirectionCoordinate will be converted radians.
00252     // You can change it to degrees or something else with the 
00253     // setWorldAxisUnits method later if you want.
00254     //
00255     // longPole and latPole are defined by Calabretta and Greisen (these
00256     // are reference points not at the native pole).  In general
00257     // you can leave these out and the default values will cause them
00258     // to be computed appropriately.  However, when reading from FITS
00259     // the LONPOLE and LATPOLE keywords are passed along here.
00260     // To get the default the 999.0 value should be used (units
00261     // are irrelevant in that case)
00262     DirectionCoordinate(MDirection::Types directionType,
00263                         const Projection &projection,
00264                         const Quantum<Double>& refLong, 
00265                         const Quantum<Double>& refLat,
00266                         const Quantum<Double>& incLong, 
00267                         const Quantum<Double>& incLat,
00268                         const Matrix<Double> &xform,
00269                         Double refX, Double refY,
00270                         const Quantum<Double>& longPole=Quantum<Double>(999.0,Unit("rad")),
00271                         const Quantum<Double>& latPole=Quantum<Double>(999.0,Unit("rad")));
00272 
00273     // Constructor from WCS structure; must hold ONLY a celestial wcs structure
00274     // Specify whether the absolute pixel coordinates in the wcs structure
00275     // are 0- or 1-relative.  The coordinate is always constructed with 0-relative
00276     // pixel coordinates
00277     DirectionCoordinate(MDirection::Types directionType,
00278                         const ::wcsprm& wcs, Bool oneRel=True);
00279 
00280     // Copy constructor (copy semantics)
00281     DirectionCoordinate(const DirectionCoordinate &other);
00282 
00283     // Assignment (copy semantics).
00284     DirectionCoordinate &operator=(const DirectionCoordinate &other);
00285 
00286     // Destructor
00287     virtual ~DirectionCoordinate();
00288 
00289     // Return Coordinate::DIRECTION
00290     virtual Coordinate::Type type() const;
00291 
00292     // Always returns the String "Direction".
00293     virtual String showType() const;
00294 
00295     // Always returns 2.
00296     // <group>
00297     virtual uInt nPixelAxes() const;
00298     virtual uInt nWorldAxes() const;
00299     // </group>
00300 
00301 
00302     // Set extra conversion type.  Whenever a conversion from pixel to world is done,
00303     // the world value is then further converted to this MDirection::Types value.
00304     // For example, your DirectionCoordinate may be defined in J2000.
00305     // You can use this to get the world values out in say GALACTIC.
00306     // Similarly, whenever you convert from world to pixel, the world
00307     // value is assumed to be that appropriate to the conversionDirectionType.
00308     // It is first converted to the MDirection::Types with which the
00309     // DirectionCoordinate was constructed and from there to pixel.
00310     // If you don't call this function, or you set the same type
00311     // for which the DirectionCoordinate was constructed, no extra
00312     // conversions occur.   Some conversions will fail.  These are the
00313     // ones that require extra frame information (epoch, position) such
00314     // as to AZEL from J2000 etc.  This will be added later.
00315     //
00316     // In the mixed pixel/world conversion routine <src>toMix</src>
00317     // the implementation is only partial.  See the comments for this
00318     // function below.
00319     // <group>
00320     void setReferenceConversion (MDirection::Types type);
00321     void getReferenceConversion (MDirection::Types& type) const
00322        {type=conversionType_p;};
00323     // </group>
00324 
00325     // Convert a pixel position to a world position or vice versa. Returns True
00326     // if the conversion succeeds, otherwise it returns False and method
00327     // errorMessage returns an error message.   The output 
00328     // vectors are appropriately resized.
00329     // <group>
00330     virtual Bool toWorld(Vector<Double> &world, 
00331                          const Vector<Double> &pixel) const;
00332     virtual Bool toPixel(Vector<Double> &pixel, 
00333                          const Vector<Double> &world) const;
00334     // </group>
00335 
00336     // Mixed pixel/world coordinate conversion.
00337     // <src>worldIn</src> and <src>worldAxes</src> are of length 
00338     // nWorldAxes. 
00339     // <src>pixelIn</src> and <src>pixelAxes</src> are of length nPixelAxes.
00340     // <src>worldAxes(i)=True</src> specifies you have given a world
00341     // value in <src>worldIn(i)</src> to convert to pixel.
00342     // <src>pixelAxes(i)=True</src> specifies you have given a pixel 
00343     // value in <src>pixelIn(i)</src> to convert to world.
00344     // You cannot specify the same axis via <src>worldAxes</src>
00345     // and <src>pixelAxes</src>.
00346     // Values in <src>pixelIn</src> are converted to world and
00347     // put into <src>worldOut</src> in the appropriate world axis
00348     // location.  Values in <src>worldIn</src> are copied to
00349     // <src>worldOut</src>.   
00350     // Values in <src>worldIn</src> are converted to pixel and
00351     // put into <src>pixelOut</src> in the appropriate pixel axis
00352     // location.  Values in <src>pixelIn</src> are copied to
00353     // <src>pixelOut</src>.  
00354     //
00355     // <src>worldMin</src> and <src>worldMax</src> specify the range of the world
00356     // coordinate (in the world axis units of that world axis
00357     // in the CoordinateSystem) being solved for in a mixed calculation
00358     // for each world axis.    Some mixed solutions can be degenerate, whereupon you
00359     // you must say which one you want.  Use functions <src>setWorldMixRanges</src>
00360     // and <src>worldMixMin, worldMixMax</src> to set these ranges,
00361     // If you don't know, use the defaults (function <src>setDefaultWorldMixRanges</src>.
00362     // Removed axes are handled (for example, a removed pixel
00363     // axis with remaining corresponding world axis will
00364     // correctly be converted to world using the replacement
00365     // value).
00366     // Returns True if the conversion succeeds, otherwise it returns False and
00367     // <src>errorMessage()</src> contains an error message. The output vectors
00368     // are resized.
00369     //
00370     // If you actually request a pure pixel to world or world to pixel
00371     // via <src>toMix</src>, then the functions <src>toWorld</src> or <src>toPixel</src>
00372     // will be invoked directly (see above) and the extra conversion layer
00373     // invoked through function <src>setReferenceConversion</src> will be active.  
00374     // However, if you request a true mixed pixel/world conversion,
00375     // the extra conversion layer is not activated (because of the nature of mixed
00376     // conversions).  This situation may change in the future
00377     // with a partial implementation added.
00378     virtual Bool toMix(Vector<Double>& worldOut,
00379                        Vector<Double>& pixelOut,
00380                        const Vector<Double>& worldIn,
00381                        const Vector<Double>& pixelIn,
00382                        const Vector<Bool>& worldAxes,
00383                        const Vector<Bool>& pixelAxes,
00384                        const Vector<Double>& worldMin,
00385                        const Vector<Double>& worldMax) const; 
00386 
00387     // Compute and retrieve the world min and max ranges, for use in function <src>toMix</src>, 
00388     // for  a lattice of the given shape (for this coordinate).   Using these
00389     // ranges in <src>toMix</src> should speed it up and help avoid ambiguity.
00390     // If the shape is negative, that indicates that the shape is unknown
00391     // for that axis.  The default range is used for that axis.  This situation
00392     // arises in a CoordinateSystem for which a pixel, but not a world axis
00393     // has been removed.
00394     // The output vectors are resized.  Returns False if fails (and
00395     // then <src>setDefaultWorldMixRanges</src> generates the ranges)
00396     // with a reason in <src>errorMessage()</src>.
00397     // The <src>setDefaultWorldMixRanges</src> function
00398     // just gives you [-90->90], [-180,180] (in appropriate units) 
00399     // <group>
00400     virtual Bool setWorldMixRanges (const IPosition& shape);
00401     virtual void setDefaultWorldMixRanges ();
00402     // </group>
00403 
00404     // Non-virtual function.  When <src>which</src> is T, use the 
00405     // world value as the center for the mix world range.
00406     void setWorldMixRanges (const Vector<Bool>& which,
00407                             const Vector<Double>& world);
00408 
00409     // A convenient way to turn the world vector into an MDirection or MVDirection 
00410     // for further processing in the Measures system.  
00411     //
00412     // We could improve the performance of this if it would be useful, however I
00413     // expect that normally you would just call this once to get a template
00414     // MDirection, and then call the vector versions. 
00415     // <group>
00416     Bool toWorld(MDirection &world, const Vector<Double> &pixel) const;
00417     Bool toPixel(Vector<Double> &pixel, const MDirection &world) const;
00418     Bool toWorld(MVDirection &world, const Vector<Double> &pixel) const;
00419     Bool toPixel(Vector<Double> &pixel, const MVDirection &world) const;
00420      //</group>
00421 
00422     // Batch up a lot of transformations. The first (most rapidly varying) axis
00423     // of the matrices contain the coordinates. Returns False if any conversion
00424     // failed  and  <src>errorMessage()</src> will hold a message.
00425     // The <src>failures</src> array is the length of the number of conversions
00426     // (True for failure, False for success)
00427     // <group>
00428     virtual Bool toWorldMany(Matrix<Double> &world,
00429                              const Matrix<Double> &pixel,
00430                              Vector<Bool> &failures) const;
00431     virtual Bool toPixelMany(Matrix<Double> &pixel,
00432                              const Matrix<Double> &world,
00433                              Vector<Bool> &failures) const;
00434     // </group>
00435   
00436 
00437     // Make absolute world coordinates relative and vice-versa (relative to
00438     // the reference value).  Note that these functions are independent 
00439     // of the MDirection::Types  (set either at construction or by function
00440     // <src>setReferenceConversion</src>).  The vectors must be
00441     // of length <src>nWorldAxes</src> or memory access errors will occur
00442     //<group>
00443     virtual void makeWorldRelative (Vector<Double>& world) const;
00444     virtual void makeWorldRelative (MDirection& world) const;
00445     virtual void makeWorldAbsolute (Vector<Double>& world) const;
00446     virtual void makeWorldAbsolute (MDirection& world) const;
00447     //</group>
00448 
00449     // Make absolute coordinates relative and vice versa with respect
00450     // to the given reference value.  Add the other functions in this grouping
00451     // as needed.
00452     //<group>
00453     virtual void makeWorldAbsoluteRef (Vector<Double>& world,
00454                                        const Vector<Double>& refVal) const;
00455     //</group>
00456 
00457     // Recover the requested attribute.
00458     // <group>
00459     MDirection::Types directionType(Bool showConversion=False) const;    
00460     Projection projection() const;
00461     virtual Vector<String> worldAxisNames() const;
00462     virtual Vector<String> worldAxisUnits() const;
00463     virtual Vector<Double> referenceValue() const;
00464     virtual Vector<Double> increment() const;
00465     virtual Matrix<Double> linearTransform() const;
00466     virtual Vector<Double> referencePixel() const;
00467     // </group>
00468 
00469     // Set the value of the requested attribute.  Note that these just
00470     // change the internal values, they do not cause any recomputation.
00471     // <group>
00472     virtual Bool setWorldAxisNames(const Vector<String> &names);
00473     virtual Bool setReferencePixel(const Vector<Double> &refPix);
00474     virtual Bool setLinearTransform(const Matrix<Double> &xform);
00475     virtual Bool setIncrement(const Vector<Double> &inc);
00476     virtual Bool setReferenceValue(const Vector<Double> &refval);
00477     // </group>
00478 
00479     // Change the world axis units.  Adjust the increment and
00480     // reference value by the ratio of the old and new units. 
00481     // The units must be compatible with
00482     // angle. The units are initially "rad" (radians).
00483     virtual Bool setWorldAxisUnits(const Vector<String> &units);
00484 
00485     // Return canonical axis names for the given MDirection type,
00486     // giving FITS names if desired.
00487     // BEG think this should be in the MDirection class, but WNB
00488     // disagrees. Leave it here for now.
00489     static Vector<String> axisNames(MDirection::Types type, 
00490                                     Bool FITSName = False);
00491 
00492     // Comparison function. Any private Double data members are compared    
00493     // with the specified fractional tolerance.  Don't compare on the specified     
00494     // axes in the Coordinate.  If the comparison returns False,  method
00495     // errorMessage returns a message about why.
00496      // <group>
00497     virtual Bool near(const Coordinate& other, 
00498                       Double tol=1e-6) const;
00499     virtual Bool near(const Coordinate& other, 
00500                       const Vector<Int>& excludeAxes,
00501                       Double tol=1e-6) const;
00502     // </group>
00503 
00504 
00505     // Format a DirectionCoordinate coordinate world value nicely through the
00506     // common format interface.  See <linkto class=Coordinate>Coordinate</linkto>
00507     // for basics.
00508     //
00509     // Formatting types that are allowed are SCIENTIFIC, FIXED, MIXED, and TIME
00510     // If you ask for format type Coordinate::DEFAULT then the
00511     // selected format depends upon what the value of the enum 
00512     // MDirection::GlobalTypes is for this DirectionCoordinate.
00513     // For example, if it is GRADEC or GHADEC you would
00514     // get Coordinate::TIME style formatting (DD:MM:SS.SS), otherwise
00515     // you would get Coordinate::FIXED formatting by default.
00516     //
00517     // <src>axis</src> says which axis in this Coordinate we are formatting.  
00518     // We have to know this because we may format Longitude and Latitude differently.  
00519     // For Coordinate::TIME style formatting, precision
00520     // refers to the places after the decimal in the SS field.
00521     //
00522     // If you leave <src>units</src> empty, then it makes up a nice unit for you.
00523     //<group>
00524     virtual void getPrecision (Int& precision, 
00525                                Coordinate::formatType& format,
00526                                Bool showAsAbsolute, 
00527                                Int defPrecScientific,
00528                                Int defPrecFixed,
00529                                Int defPrecTime) const;
00530     virtual String format(String& units,
00531                           Coordinate::formatType format, 
00532                           Double worldValue, 
00533                           uInt axis, 
00534                           Bool isAbsolute,
00535                           Bool showAsAbsolute,
00536                           Int precision=-1, Bool usePrecForMixed=False) const;
00537     //</group>
00538 
00539     // Fix cylindrical coordinates to put the longitude in [-180,180] range.
00540     // If False returned, it failed an an error is in <src>errorMessage</src>
00541     // This fix is not done automatically internally because of the dependence
00542     // on the image shape.  It should be called for any foreign image
00543     // (such as FITS) that is imported
00544     Bool cylindricalFix (Int shapeLong, Int shapeLat);
00545 
00546     // Find the Coordinate for when we Fourier Transform ourselves.  This pointer
00547     // must be deleted by the caller. Axes specifies which axes of the Coordinate
00548     // you wish to transform.   Shape specifies the shape of the image
00549     // associated with all the axes of the Coordinate.   Currently the
00550     // output reference pixel is always shape/2. If the pointer returned is 0, 
00551     // it failed with a message in <src>errorMessage</src>
00552     virtual Coordinate* makeFourierCoordinate (const Vector<Bool>& axes,
00553                                                const Vector<Int>& shape) const;
00554 
00555     // Save the DirectionCoordinate into the supplied record using the supplied field name.
00556     // The field must not exist, otherwise <src>False</src> is returned.
00557     virtual Bool save(RecordInterface &container,
00558                     const String &fieldName) const;
00559 
00560     // Recover the DirectionCoordinate from a record.
00561     // A null pointer means that the restoration did not succeed.
00562     static DirectionCoordinate *restore(const RecordInterface &container,
00563                                    const String &fieldName);
00564 
00565     // Make a copy of the DirectionCoordinate using new. The caller 
00566     // is responsible for calling delete.
00567     virtual Coordinate *clone() const;
00568 
00569     // Fish out the ref and non-native poles (refLong, refLat, longPole, latPole)
00570     // Not for general use.  Units are degrees.
00571     Vector<Double> longLatPoles() const;
00572 
00573     // get the pixel area.
00574     Quantity getPixelArea() const;
00575 
00576     // Convert this coordinate to another reference frame by rotating it
00577     // about the reference pixel so the the axes of the new reference frame
00578     // are aligned along the cardinal directions (left-right, up-down).
00579     // The reference pixel remains the same and the conversion is
00580     // exact for the reference pixel and in general becomes less accurate
00581     // as distance from reference pixel increases. The latitude like and
00582     // the longitude like pixel increments are preserved.  Conversions for which require extra
00583     // information such as epoch and position are not supported. The <src>angle</src>
00584     // parameter is the angle through which this coordinate had to be rotated clockwise
00585     // to produce the new coordinate.
00586 
00587     DirectionCoordinate convert(
00588         Quantity& angle, MDirection::Types directionType
00589     ) const;
00590 
00591 private:
00592     // Direction type
00593     MDirection::Types type_p, conversionType_p;
00594 
00595     // Projection parameters
00596     Projection projection_p;
00597 
00598     // WCS structure.  This is mutable because the wcs functions
00599     // that do toPixel and toWorld (which have const signature)
00600     // require a non const wcs structure.  so either all of these
00601     // virtual functions lose their const or we use mutable...
00602     mutable ::wcsprm wcs_p;
00603 
00604     // WCS computes in degrees - use this to convert back and forth between
00605     // current DirectionCoordinate units and degrees or radians
00606     Vector<Double> to_degrees_p;           // From current units to degrees
00607     Vector<Double> to_radians_p;           // From current units to radians
00608 
00609     // Axis names.
00610     Vector<String> names_p;
00611 
00612     // Current units.
00613     Vector<String> units_p;
00614 
00615     // Rotation matrix used to handle relative coordinates
00616     RotMatrix rot_p;
00617 
00618     // Conversion machines.  
00619     // "To"   handles type_p -> conversionType_p
00620     // "From" handles conversionType_p -> type_p;
00621     mutable MDirection::Convert* pConversionMachineTo_p;
00622     mutable MDirection::Convert* pConversionMachineFrom_p;
00623 
00624     // Interconvert between the current units and wcs units (degrees)
00625     // <group>
00626     void toCurrent(Vector<Double>& degrees) const;
00627     void fromCurrent(Vector<Double>& current) const;
00628     // </group>
00629 
00630     // Check formatting types.
00631     void checkFormat(Coordinate::formatType& format,
00632                      Bool absolute) const;
00633 
00634     // Format a latitude.
00635     String formatLatitude (String& units, MVAngle& mVA,
00636                            Bool absolute, 
00637                            Coordinate::formatType form,
00638                            Int prec) const;
00639     // Format a longitude.
00640     String formatLongitude (String& units, MVAngle& mVA,
00641                             MDirection::GlobalTypes gtype,
00642                             Bool absolute, 
00643                             Coordinate::formatType form,
00644                             Int prec) const;
00645 
00646     // Mixed pixel/world coordinate conversion.  Vector in must
00647     // be length nWorldAxes (2).  Specify whether longitude
00648     // (in(0)) or latitude (in(1)) is the world coordinate . It is
00649     // assumed that the other value is the pixel coordinate.
00650     Bool toMix2(Vector<Double>& out, const Vector<Double>& in,
00651                 const Vector<Double>& minWorld, const Vector<Double>& maxWorld,
00652                 Bool longIsWorld) const;
00653 
00654     // Initialize unit conversion vectors and units
00655     void initializeFactors ();
00656 
00657     // Helper functions interfacing to WCS.
00658     // <group>
00659     void makeDirectionCoordinate(MDirection::Types directionType,
00660                                  const Projection& proj, Double refLong, Double refLat,
00661                                  Double incLong, Double incLat,
00662                                  const Matrix<Double> &xform,
00663                                  Double refX, Double refY, 
00664                                  Double longPole, Double latPole);
00665 //
00666     void makeWCS(::wcsprm& wcs,  const Matrix<Double>& xform,
00667                  const Projection& proj, MDirection::Types directionType,
00668                  Double refPixLong, Double refPixLat,
00669                  Double refLong, Double refLat,
00670                  Double incLong, Double incLat,
00671                  Double longPole, Double latPole);
00672     // </group>
00673 
00674     // Normalize each row of the PC matrix such that increment() will return the actual
00675     // angular increment and any scale factors are removed from the PC matrix
00676     // (modifies wcs_p.pc _and_ wcs_p.cdelt _and_ wcs_p.altlin,
00677     // executes set_wcs() and hence wcsset() on the struct)
00678     // See Greisen & Calabretta, A&A 395, 1061-1075 (2002), equation (4) 
00679     void normalizePCMatrix();
00680 
00681     Double putLongInPiRange (Double lon, const String& unit) const;
00682 
00683     // Set up conversion machine
00684     void makeConversionMachines();
00685 
00686     // Convert from type_p -> conversionType_p
00687     // <group>
00688     virtual void convertTo (Vector<Double>& world) const;
00689     virtual void convertFrom (Vector<Double>& world) const;
00690     // </group>
00691 
00692     // Copy private data
00693     void copy (const DirectionCoordinate& other);
00694     
00695     // Set up the offset coordinate rotation matrix.  Units
00696     // of long and lat are current world units
00697     // <group>
00698     void setRotationMatrix ();
00699     void setRotationMatrix (RotMatrix& rot, Double lon, Double lat) const;
00700     // </group>
00701     
00702     // Return unit conversion vector for converting to current units
00703     const Vector<Double> toCurrentFactors () const;
00704 };
00705 
00706 } //# NAMESPACE CASA - END
00707 
00708 
00709 #endif
00710