casa
$Rev:20696$
|
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