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