casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
MVAngle.h
Go to the documentation of this file.
00001 //# MVAngle.h: Class to handle angle type conversions and I/O
00002 //# Copyright (C) 1996,1997,1998,1999,2000,2001
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 //# $Id: MVAngle.h 21051 2011-04-20 11:46:29Z gervandiepen $
00027 
00028 #ifndef CASA_MVANGLE_H
00029 #define CASA_MVANGLE_H
00030 
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <casa/Quanta/Quantum.h>
00035 #include <casa/iosfwd.h>
00036 
00037 namespace casa { //# NAMESPACE CASA - BEGIN
00038 
00039 //# Forward Declarations
00040 class String;
00041 class MUString;
00042 
00043 //# Constants (SUN compiler does not accept non-simple default arguments)
00044 
00045 // <summary>
00046 // Class to handle angle type conversions and I/O
00047 // </summary>
00048 
00049 // <use visibility=export>
00050 
00051 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tMeasure" demos="">
00052 // </reviewed>
00053 
00054 // <prerequisite>
00055 // <li> <linkto class=Quantum>Quantum</linkto>
00056 // </prerequisite>
00057 //
00058 // <etymology>
00059 // From Measure, Value and Angle
00060 // </etymology>
00061 //
00062 // <synopsis>
00063 // An MVAngle is a simple Double, to be used for angle conversions and I/O.
00064 // It can be constructed from a Double (in which case radians are assumed),
00065 // or from a Quantity (<src>Quantum<Double></src>). Quantities must be in
00066 // either angle or time units.<br>
00067 // It has an automatic conversion to Double, so all standard mathematical
00068 // operations can operate on it.<br>
00069 // The class has a number of special member operations:
00070 // <ul>
00071 //  <li> <src>MVAngle operator()</src> will normalise the angle between
00072 //      -180 and +180(inclusive) degrees and return the value 
00073 //  <li> <src>MVAngle operator(Double)</src> will normalise the angle 
00074 //      using the value specified (and return the value)
00075 //      in fractions of a circle (this was chosen rather than radians to make
00076 //      for easier and more precise programming) as a lower bound. I.e.
00077 //      (-0.5) will normalise between -180 and +180 degrees, (0.) between
00078 //      0 and 360 degrees, (-0.25) between -90 and +270 degrees,
00079 //      (5.) between 1800 and 2160 dgrees.
00080 //   <li> <src>MVAngle operator(MVAngle)</src> will normalise (and
00081 //      return the normalised value) to within 180 degrees of the
00082 //      argument value. This is useful for making a range of angles
00083 //      contiguous.
00084 //   <li> <src>MVAngle binorm(Double)</src> will normalise the angle in
00085 //      steps of 180 degrees. 
00086 //      using the value specified (and return the value)
00087 //      in fractions of 180 degrees (this was chosen rather than radians to make
00088 //      for easier and more precise programming) as a lower bound. I.e.
00089 //      (-0.5) will normalise between -90 and +90 degrees, (0.) between
00090 //      0 and 180 degrees, (10.) between 1800 and 1980 dgrees.
00091 //   <li> <src>Double radian()</src> will return value in radians
00092 //   <li> <src>Double degree()</src> will return value in degrees
00093 //   <li> <src>Double circle()</src> will return value in fraction of circles
00094 //   <li> <src>MVAngle coAngle()</src> will return 90-angle (or rather 
00095 //              pi/2 - angle), with (0) normalisation.
00096 //   <li> <src>Quantity get()</src> will return radians
00097 //   <li> <src>Quantity get(Unit)</src> will return in specified units 
00098 //              (angle or time)
00099 // </ul>
00100 // Output formatting is done with the <src><<</src> statement, with the
00101 // following rules:
00102 // <ul>
00103 //   <li> standard output is done in the following format:
00104 //      <src>+ddd.mm.ss.tt</src> with a floating sign. The number of
00105 //      digits presented will be based on the precision attached to the
00106 //      current stream
00107 //   <li> output can be formatted by using either the <src>setFormat()</src>
00108 //      method for global angle format setting, or the output of
00109 //      <src>MVAngle::Format()</src> data for a once off change (see later).
00110 //      Formats have a first argument which
00111 //      determines the type (default, if not given, MVAngle::ANGLE, other
00112 //      possibility MVAngle::TIME (as hh:mm:ss.tt..),
00113 //      the second the number of digits wanted (default stream precision),
00114 //      with a value:
00115 //      <ul>
00116 //        <li> <3 : ddd.. only
00117 //        <li> <5 : ddd.mm.
00118 //        <li> <7 : ddd.mm.ss
00119 //        <li> >6 : with precision-6 t's added
00120 //      </ul> 
00121 //      comparable for time. <note role=tip> The added periods are to enable input
00122 //      checking of the format. Look at the 'clean' types to bypass them.
00123 //      </note>
00124 //      The output format can be modified with modifiers (specify as
00125 //      MVAngle::ANGLE | MVAngle::MOD (or + MVAngle::MOD)). 
00126 //      <note role=caution>
00127 //       For overloading/casting problems with some compilers, the
00128 //      use of modifiers necessitates either the presence of a precision
00129 //      (i.e. <src>(A|B, prec)</src>), or an explicit cast:
00130 //      <src>((MVAngle::formatTypes)(A|B))</src>, or make use of
00131 //      the provided <src>ANGLE[_CLEAN][_NO_D[M]]</src> and
00132 //      <src>TIME[_CLEAN][_NO_H[M]].</src>
00133 //      </note>
00134 //      The modifiers can be:
00135 //      <ul>
00136 //       <li> <src>MVAngle::CLEAN</src> to suppress leading or trailing
00137 //              periods (or colons for TIME). + and leading zeroes in degree
00138 //              field for angle representation will be replaced with a space.
00139 //              Note that he result can not be
00140 //              read automatically.
00141 //       <li> <src>MVAngle::NO_D</src> (or <src>NO_H</src>) to suppress
00142 //              the output of degrees (or hours): useful for offsets
00143 //       <li> <src>MVAngle::NO_DM</src> (or <src>NO_HM</src>), to
00144 //              suppress the degrees and minutes.
00145 //       <li> <src>MVAngle::DIG2</src> to allow only 2 digits for degrees,
00146 //              or -12 - +12 range for hours
00147 //       <li> <src>MVAngle::LOCAL</src> to indicate local time to FITS
00148 //              formatting only
00149 //        <li> <src>MVAngle::FITS</src> to produce, if
00150 //              LOCAL set, the time zone (note that if local set
00151 //              here, as opposed to in MVTime) the angle is supposed
00152 //              to be in local time already).
00153 //      </ul>
00154 //      Output in formats like <src>20'</src> can be done via the standard
00155 //      Quantum output (e.g. <src> stream << angle.get("'") </src>).
00156 //   <li> Available formats:
00157 //      <ul>
00158 //        <li> MVAngle::ANGLE in +ddd.mm.ss.ttt format
00159 //        <li> MVAngle::TIME in hh:mm:ss.ttt format
00160 //        <li> MVAngle::[ANGLE|TIME]_CLEAN format without superfluous periods
00161 //        <li> MVAngle::[ANGLE|TIME][_CLEAN]_NO_[D|H][M] in format with
00162 //              leading zero fields left empty.
00163 //        <li> MVAngle::CLEAN modifier for suppressing superfluous periods
00164 //        <li> MVAngle::NO_[D|H][M] modifier to suppress first field(s)
00165 //        <li> MVAngle::DIG2 modifier to output in +dd.mm.ss.ttt format or
00166 //              in time format in range -12 to +12h
00167 //      </ul>
00168 // </ul>
00169 // The default formatting can be overwritten by a 
00170 // <src> MVAngle::setFormat(); </src> statement; which returns an 
00171 // MVAngle::Format
00172 // structure, that can be used in a subsequent one to reset to previous.
00173 // The format set holds for all MVAngle output on all streams.<br>
00174 // Temporary formats (i.e. for one MVAngle output only), can be set by
00175 // outputting a format (i.e. <src> stream << MVAngle::Format() << ... </src>).
00176 // <note role=caution> A setFormat() will also reset any lingering temporary format.
00177 // A setFormat(getFormat()) will reset without changing. Problems could
00178 // arise in parallel processors. </note>
00179 // Input can be read if the values are in any of the above (non-clean) output
00180 // formats. <br>
00181 // For other formatting practice, the output can be written to a String with
00182 // the string() member function.<br>
00183 // Note that using a temporary format is inherently thread-unsafe because
00184 // the format is kept in a static variable. Another thread may overwrite
00185 // the format just set. The only thread-safe way to format an MVTime is using
00186 // a <src>print</src> or <src>string</src> that accepts a Format object.
00187 //
00188 // Strings and input can be converted to an MVAngle (or Quantity) by
00189 // <src>Bool read(Quantity &out, const String &in)</src> and
00190 // <src> istream >> MVAngle &</src>. In the latter case the actual
00191 // reading is done by the String read, which reads between white-spaces.<br>
00192 // The following input formats (note no blanks allowed) are supported
00193 // (+stands for an optional + or -; v for an unsigned integer; dv for a
00194 // floating number. [] indicate optional values. Separating codes are
00195 // case insensitive):
00196 // <ul>
00197 //   <li> +[v].[v].[dv]    -- value in deg, arcmin, arcsec
00198 //   <li> +[v]D[v[M[dv]]]  -- value in deg, arcmin, arcsec
00199 //   <li> +[v]:[v[:[dv]]]  -- value in h, min, s
00200 //   <li> +[v]H[v[M[dv]]]  -- value in h, min, s
00201 //   <li> +[v]{D|H|:}[dv]  -- value in deg (or h), arcmin (or min)
00202 //   <li> +dv[unit string] -- value in time or angle units. rad default
00203 // </ul>
00204 // Examples of valid strings:
00205 // <srcblock>
00206 //      5::2.59         5h + 0min + 2.59 s
00207 //      5..2.59         5deg + 0arcmin + 2.59arcsec
00208 //      5.259           5.259 rad
00209 //      5..259          5deg + 259arcsec
00210 //      5.259a          5.259 * pi * 2 *365.25 rad (normalised)
00211 // </srcblock>
00212 // <note role=caution> In general the input will be read as a Quantity.
00213 // Reading of Quantities will always try to read special formats (like 
00214 // MVAngle, MVTime) first. In
00215 // that case problems could arise converting strings like 5d, 5::, 5hm, 5dm.
00216 // In 'angle' mode they could have meant to be
00217 // 5d0m, 5:0:, 5h0m, 5d0m, but they could have
00218 // meant: days, min, hectometre, decimetre. In the same vain 5d2 could have
00219 // meant 5d2m or 5 d<sup>2</sup>.
00220 // To try to guess the general use, the following interpretation is made:
00221 // <ul>
00222 //   <li> 5d, 5:: == 5deg, 5h0m; make float (like 5.d) to make it days/min
00223 //   <li> 5dm, 5hm == decimetre, hectometre; use 5d0m 5h0m for
00224 //              angle
00225 //   <li> 5d2, 5h2, 5:2 == 5d2m, 5h2m, 5:2:; use float 5 or explicit () for
00226 //              other interpretation 
00227 // </ul>
00228 // </note>
00229 // </synopsis>
00230 //
00231 // <example>
00232 // See synopsis
00233 // </example>
00234 //
00235 // <motivation>
00236 // To be able to format angle-like values in user-required ways.
00237 // </motivation>
00238 //
00239 // <todo asof="1997/09/16">
00240 //   <li> Use AipsrcData once moved to aips from trial
00241 // </todo>
00242 
00243 class MVAngle {
00244 
00245  public:
00246 
00247   //# Enumerations
00248   // Format types
00249   enum formatTypes {
00250     ANGLE,
00251     TIME,
00252     CLEAN                       = 4,
00253     NO_D                        = 8,
00254     NO_DM                       = NO_D+16,
00255     DIG2                        = 1024,
00256     FITS                        = TIME+2048,
00257     LOCAL                       = 4096,
00258     NO_H                        = NO_D,
00259     NO_HM                       = NO_DM,
00260     ANGLE_CLEAN                 = ANGLE + CLEAN,
00261     ANGLE_NO_D                  = ANGLE + NO_D,
00262     ANGLE_NO_DM                 = ANGLE + NO_DM,
00263     ANGLE_CLEAN_NO_D            = ANGLE + CLEAN + NO_D,
00264     ANGLE_CLEAN_NO_DM           = ANGLE + CLEAN + NO_DM,
00265     TIME_CLEAN                  = TIME + CLEAN,
00266     TIME_NO_H                   = TIME + NO_H,
00267     TIME_NO_HM                  = TIME + NO_HM,
00268     TIME_CLEAN_NO_H             = TIME + CLEAN + NO_H,
00269     TIME_CLEAN_NO_HM            = TIME + CLEAN + NO_HM ,
00270     MOD_MASK                    = NO_DM + CLEAN + DIG2 + LOCAL};
00271   
00272   //# Local structure
00273   // Format structure
00274   class Format {
00275   public:
00276     friend class MVAngle;
00277     Format(MVAngle::formatTypes intyp = MVAngle::ANGLE,
00278            uInt inprec = 0) :
00279       typ(intyp), prec(inprec) {;};
00280     Format(uInt inprec) :
00281       typ(MVAngle::ANGLE), prec(inprec) {;};
00282     // Construct from type and precision (present due to overlaoding problems)
00283     Format(uInt intyp, uInt inprec) :
00284       typ((MVAngle::formatTypes) intyp), prec(inprec) {;};
00285     Format(const Format &other) :
00286       typ(other.typ), prec(other.prec) {;};
00287   private:
00288     MVAngle::formatTypes typ;
00289     uInt prec;
00290   };
00291   
00292   //# Friends
00293   // Output an angle
00294   friend ostream &operator<<(ostream &os, const MVAngle &meas);
00295   // Input an angle
00296   friend istream &operator>>(istream &is, MVAngle &meas);
00297   // Set a temporary format
00298   friend ostream &operator<<(ostream &os, const MVAngle::Format &form);
00299   
00300   //# Constructors
00301   // Default constructor: generate a zero value
00302   MVAngle();
00303   // Copy constructor
00304   MVAngle(const MVAngle &other);
00305   // Copy assignment
00306   MVAngle &operator=(const MVAngle &other);
00307   // Constructor from Double
00308   MVAngle(Double d);
00309   // Constructor from Quantum : value can be an angle or time
00310   // <thrown>
00311   //   <li> AipsError if not a time or angle
00312   // </thrown>
00313   MVAngle(const Quantity &other);
00314   
00315   // Destructor
00316   ~MVAngle();
00317   
00318   //# Operators
00319   // Conversion operator
00320   operator Double() const;
00321   // Normalisation between -180 and +180 degrees (-pi and +pi)
00322   const MVAngle &operator()();
00323   // Normalisation between 2pi*norm and 2pi*norm + 2pi
00324   const MVAngle &operator()(Double norm);
00325   // Normalisation between norm-pi and norm+pi
00326   const MVAngle &operator()(const MVAngle &norm);
00327   
00328   //# General member functions
00329   // Normalisation between pi*norm and pi*norm + pi
00330   const MVAngle &binorm(Double norm);
00331   // Check if String unit
00332   static Bool unitString(UnitVal &uv, String &us, MUString &in);
00333   // Make res angle Quantity from string in angle/time-like format. In the
00334   // case of String input, also quantities are recognised. chk checks eos
00335   // <group> 
00336   static Bool read(Quantity &res, const String &in);
00337   static Bool read(Quantity &res, MUString &in);
00338   static Bool read(Quantity &res, const String &in, Bool chk);
00339   static Bool read(Quantity &res, MUString &in, Bool chk);
00340   // </group>
00341   // Make co-angle (e.g. zenith distance from elevation)
00342   MVAngle coAngle() const;
00343   // Get value in given unit
00344   // <group>
00345   Double radian() const;
00346   Double degree() const;
00347   Double circle() const;
00348   Quantity get() const;
00349   Quantity get(const Unit &inunit) const;
00350   // </group>
00351   // Output data
00352   // <note role=warning>
00353   // The first function below is thread-unsafe because it uses the result of
00354   // the setFormat function which changes a static class member.
00355   // The other functions are thread-safe because the format is directly given.
00356   // </note>
00357   // <group>
00358   String string() const;
00359   String string(MVAngle::formatTypes intyp, uInt inprec = 0) const;
00360   String string(uInt intyp, uInt inprec) const;
00361   String string(uInt inprec) const;
00362   String string(const MVAngle::Format &form) const;
00363   void print(ostream &oss, const MVAngle::Format &form) const;
00364   void print(ostream &oss, const MVAngle::Format &form, Bool loc) const;
00365   // </group>
00366   // Set default format
00367   // <note role=warning>
00368   // It is thread-unsafe to print using the setFormat functions because they
00369   // change a static class member. The only thred-safe way to print a time is
00370   // to use the print function above. 
00371   // </note>
00372   // <group>
00373   static Format setFormat(MVAngle::formatTypes intyp, 
00374                           uInt inprec = 0);
00375   static Format setFormat(uInt intyp, uInt inprec);
00376   static Format setFormat(uInt inprec = 0);
00377   static Format setFormat(const Format &form);
00378   // </group>
00379   // Get default format
00380   static Format getFormat();
00381   // Get code belonging to string. 0 if not known
00382   static MVAngle::formatTypes  giveMe(const String &in);
00383   // Get time zone offset (in days)
00384   static Double timeZone();
00385   
00386  private:
00387   //# Data
00388   // Value
00389   Double val;
00390   // Default format
00391   static MVAngle::Format defaultFormat;
00392   // Temporary format
00393   // <group>
00394   static MVAngle::Format interimFormat;
00395   static Bool interimSet;
00396   // </group>
00397   
00398   //# Member functions
00399 };
00400 
00401 // Global functions
00402 // <summary> Global output/input functions </summary>
00403 // Output/Input
00404 // <group name=output>
00405 ostream &operator<<(ostream &os, const MVAngle &meas);
00406 istream &operator>>(istream &is, MVAngle &meas);
00407 // Set a temporary format (thread-unsafe).
00408 ostream &operator<<(ostream &os, const MVAngle::Format &form);
00409 // </group>
00410 
00411 
00412 } //# NAMESPACE CASA - END
00413 
00414 #endif