//# MVAngle.h: Class to handle angle type conversions and I/O //# Copyright (C) 1996,1997,1998,1999,2000,2001 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #ifndef CASA_MVANGLE_H #define CASA_MVANGLE_H //# Includes #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN //# Forward Declarations class String; class MUString; //# Constants (SUN compiler does not accept non-simple default arguments) // // Class to handle angle type conversions and I/O // // // // // //
  • Quantum // // // // From Measure, Value and Angle // // // // An MVAngle is a simple Double, to be used for angle conversions and I/O. // It can be constructed from a Double (in which case radians are assumed), // or from a Quantity (Quantum). Quantities must be in // either angle or time units.
    // It has an automatic conversion to Double, so all standard mathematical // operations can operate on it.
    // The class has a number of special member operations: //
      //
    • MVAngle operator() will normalise the angle between // -180 and +180(inclusive) degrees and return the value //
    • MVAngle operator(Double) will normalise the angle // using the value specified (and return the value) // in fractions of a circle (this was chosen rather than radians to make // for easier and more precise programming) as a lower bound. I.e. // (-0.5) will normalise between -180 and +180 degrees, (0.) between // 0 and 360 degrees, (-0.25) between -90 and +270 degrees, // (5.) between 1800 and 2160 dgrees. //
    • MVAngle operator(MVAngle) will normalise (and // return the normalised value) to within 180 degrees of the // argument value. This is useful for making a range of angles // contiguous. //
    • MVAngle binorm(Double) will normalise the angle in // steps of 180 degrees. // using the value specified (and return the value) // in fractions of 180 degrees (this was chosen rather than radians to make // for easier and more precise programming) as a lower bound. I.e. // (-0.5) will normalise between -90 and +90 degrees, (0.) between // 0 and 180 degrees, (10.) between 1800 and 1980 dgrees. //
    • Double radian() will return value in radians //
    • Double degree() will return value in degrees //
    • Double circle() will return value in fraction of circles //
    • MVAngle coAngle() will return 90-angle (or rather // pi/2 - angle), with (0) normalisation. //
    • Quantity get() will return radians //
    • Quantity get(Unit) will return in specified units // (angle or time) //
    // Output formatting is done with the << statement, with the // following rules: //
      //
    • standard output is done in the following format: // +ddd.mm.ss.tt with a floating sign. The number of // digits presented will be based on the precision attached to the // current stream //
    • output can be formatted by using either the setFormat() // method for global angle format setting, or the output of // MVAngle::Format() data for a once off change (see later). // Formats have a first argument which // determines the type (default, if not given, MVAngle::ANGLE, other // possibility MVAngle::TIME (as hh:mm:ss.tt..), // the second the number of digits wanted (default stream precision), // with a value: //
        //
      • <3 : ddd.. only //
      • <5 : ddd.mm. //
      • <7 : ddd.mm.ss //
      • >6 : with precision-6 t's added //
      // comparable for time. The added periods are to enable input // checking of the format. Look at the 'clean' types to bypass them. // // The output format can be modified with modifiers (specify as // MVAngle::ANGLE | MVAngle::MOD (or + MVAngle::MOD)). // // For overloading/casting problems with some compilers, the // use of modifiers necessitates either the presence of a precision // (i.e. (A|B, prec)), or an explicit cast: // ((MVAngle::formatTypes)(A|B)), or make use of // the provided ANGLE[_CLEAN][_NO_D[M]] and // TIME[_CLEAN][_NO_H[M]]. // // // The modifiers can be: //
        //
      • MVAngle::CLEAN to suppress leading or trailing // periods (or colons for TIME), + and leading zeroes in degree // field for angle representation will be replaced with a space. // Note that the result can not be read automatically. //
      • MVAngle::NO_D (or NO_H) to suppress // the output of degrees (or hours): useful for offsets //
      • MVAngle::NO_DM (or NO_HM), to // suppress the degrees and minutes. //
      • MVAngle::DIG2 to allow only 2 digits for degrees, // or -12 - +12 range for hours //
      • MVAngle::LOCAL to indicate local time to FITS // formatting only //
      • MVAngle::FITS to produce, if // LOCAL set, the time zone (note that if local set // here, as opposed to in MVTime) the angle is supposed // to be in local time already). //
      • MVAngle::ALPHA to use d (or h) and m instead of // periods or colons. //
      // Output in formats like 20' can be done via the standard // Quantum output (e.g. stream << angle.get("'") ). //
    • Available formats: //
        //
      • MVAngle::ANGLE in +ddd.mm.ss.ttt format //
      • MVAngle::TIME in hh:mm:ss.ttt format //
      • MVAngle::[ANGLE|TIME]_CLEAN format without superfluous periods //
      • MVAngle::[ANGLE|TIME][_CLEAN]_NO_[D|H][M] in format with // leading zero fields left empty. //
      • MVAngle::CLEAN modifier for suppressing superfluous periods //
      • MVAngle::NO_[D|H][M] modifier to suppress first field(s) //
      • MVAngle::DIG2 modifier to output in +dd.mm.ss.ttt format or // in time format in range -12 to +12h //
      //
    // The default formatting can be overwritten by a // MVAngle::setFormat(); statement; which returns an // MVAngle::Format // structure, that can be used in a subsequent one to reset to previous. // The format set holds for all MVAngle output on all streams.
    // Temporary formats (i.e. for one MVAngle output only), can be set by // outputting a format (i.e. stream << MVAngle::Format() << ... ). // A setFormat() will also reset any lingering temporary format. // A setFormat(getFormat()) will reset without changing. Problems could // arise in parallel processors. // Input can be read if the values are in any of the above (non-clean) output // formats.
    // For other formatting practice, the output can be written to a String with // the string() member function.
    // Note that using a temporary format is inherently thread-unsafe because // the format is kept in a static variable. Another thread may overwrite // the format just set. The only thread-safe way to format an MVTime is using // a print or string that accepts a Format object. // // Strings and input can be converted to an MVAngle (or Quantity) by // Bool read(Quantity &out, const String &in) and // istream >> MVAngle &. In the latter case the actual // reading is done by the String read, which reads between white-spaces.
    // The following input formats (note no blanks allowed) are supported // (+stands for an optional + or -; v for an unsigned integer; dv for a // floating number. [] indicate optional values. Separating codes are // case insensitive): //
      //
    • +[v].[v].[dv] -- value in deg, arcmin, arcsec //
    • +[v]D[v[M[dv]]] -- value in deg, arcmin, arcsec //
    • +[v]:[v[:[dv]]] -- value in h, min, s //
    • +[v]H[v[M[dv]]] -- value in h, min, s //
    • +[v]{D|H|:}[dv] -- value in deg (or h), arcmin (or min) //
    • +dv[unit string] -- value in time or angle units. rad default //
    // Examples of valid strings: // // 5::2.59 5h + 0min + 2.59 s // 5..2.59 5deg + 0arcmin + 2.59arcsec // 5.259 5.259 rad // 5..259 5deg + 259arcsec // 5.259a 5.259 * pi * 2 *365.25 rad (normalised) // // In general the input will be read as a Quantity. // Reading of Quantities will always try to read special formats (like // MVAngle, MVTime) first. In // that case problems could arise converting strings like 5d, 5::, 5hm, 5dm. // In 'angle' mode they could have meant to be // 5d0m, 5:0:, 5h0m, 5d0m, but they could have // meant: days, min, hectometre, decimetre. In the same vain 5d2 could have // meant 5d2m or 5 d2. // To try to guess the general use, the following interpretation is made: //
      //
    • 5d, 5:: == 5deg, 5h0m; make float (like 5.d) to make it days/min //
    • 5dm, 5hm == decimetre, hectometre; use 5d0m 5h0m for // angle //
    • 5d2, 5h2, 5:2 == 5d2m, 5h2m, 5:2:; use float 5 or explicit () for // other interpretation //
    //
    //
    // // // See synopsis // // // // To be able to format angle-like values in user-required ways. // // // //
  • Use AipsrcData once moved to aips from trial // class MVAngle { public: //# Enumerations (should mimic those in MVTime) // Format types enum formatTypes { ANGLE, TIME, CLEAN = 4, NO_D = 8, NO_DM = NO_D+16, DIG2 = 1024, FITS = TIME+2048, LOCAL = 4096, USE_SPACE = 8192, //# Only for MVTIme compatibility ALPHA = 16384, NO_H = NO_D, NO_HM = NO_DM, ANGLE_CLEAN = ANGLE + CLEAN, ANGLE_NO_D = ANGLE + NO_D, ANGLE_NO_DM = ANGLE + NO_DM, ANGLE_CLEAN_NO_D = ANGLE + CLEAN + NO_D, ANGLE_CLEAN_NO_DM = ANGLE + CLEAN + NO_DM, TIME_CLEAN = TIME + CLEAN, TIME_NO_H = TIME + NO_H, TIME_NO_HM = TIME + NO_HM, TIME_CLEAN_NO_H = TIME + CLEAN + NO_H, TIME_CLEAN_NO_HM = TIME + CLEAN + NO_HM , MOD_MASK = CLEAN + NO_DM + DIG2 + LOCAL + USE_SPACE + ALPHA}; //# Local structure // Format structure class Format { public: friend class MVAngle; Format(MVAngle::formatTypes intyp = MVAngle::ANGLE, uInt inprec = 0) : typ(intyp), prec(inprec) {;}; Format(uInt inprec) : typ(MVAngle::ANGLE), prec(inprec) {;}; // Construct from type and precision (present due to overlaoding problems) Format(uInt intyp, uInt inprec) : typ((MVAngle::formatTypes) intyp), prec(inprec) {;}; private: MVAngle::formatTypes typ; uInt prec; }; //# Friends // Output an angle friend ostream &operator<<(ostream &os, const MVAngle &meas); // Input an angle friend istream &operator>>(istream &is, MVAngle &meas); // Set a temporary format friend ostream &operator<<(ostream &os, const MVAngle::Format &form); //# Constructors // Default constructor: generate a zero value MVAngle(); // Copy constructor MVAngle(const MVAngle &other); // Copy assignment MVAngle &operator=(const MVAngle &other); // Constructor from Double MVAngle(Double d); // Constructor from Quantum : value can be an angle or time // //
  • AipsError if not a time or angle // MVAngle(const Quantity &other); // Destructor ~MVAngle(); //# Operators // Conversion operator operator Double() const; // Normalisation between -180 and +180 degrees (-pi and +pi) const MVAngle &operator()(); // Normalisation between 2pi*norm and 2pi*norm + 2pi const MVAngle &operator()(Double norm); // Normalisation between norm-pi and norm+pi const MVAngle &operator()(const MVAngle &norm); //# General member functions // Normalisation between pi*norm and pi*norm + pi const MVAngle &binorm(Double norm); // Check if String unit static Bool unitString(UnitVal &uv, String &us, MUString &in); // Make res angle Quantity from string in angle/time-like format. In the // case of String input, also quantities are recognised. // chk=True means that the entire string should be consumed. // throwExcp=True means that an exception is thrown in case of an error. // static Bool read(Quantity &res, const String &in, Bool chk=True); static Bool read(Quantity &res, MUString &in, Bool chk=True); static Bool read(Quantity &res, const String &in, Bool chk, Bool throwExcp); static Bool read(Quantity &res, MUString &in, Bool chk, Bool throwExcp); // // Handle a read error. An exception is thrown if indicated so. // Otherwise in.pop() is called and False is returned. static Bool handleReadError(MUString& in, Bool throwExcp); // Make co-angle (e.g. zenith distance from elevation) MVAngle coAngle() const; // Get value in given unit // Double radian() const; Double degree() const; Double circle() const; Quantity get() const; Quantity get(const Unit &inunit) const; // // Output data // // The first function below is thread-unsafe because it uses the result of // the setFormat function which changes a static class member. // The other functions are thread-safe because the format is directly given. // // String string() const; String string(MVAngle::formatTypes intyp, uInt inprec = 0) const; String string(uInt intyp, uInt inprec) const; String string(uInt inprec) const; String string(const MVAngle::Format &form) const; void print(ostream &oss, const MVAngle::Format &form) const; void print(ostream &oss, const MVAngle::Format &form, Bool loc) const; // // Set default format // // It is thread-unsafe to print using the setFormat functions because they // change a static class member. The only thred-safe way to print a time is // to use the print function above. // // static Format setFormat(MVAngle::formatTypes intyp, uInt inprec = 0); static Format setFormat(uInt intyp, uInt inprec); static Format setFormat(uInt inprec = 0); static Format setFormat(const Format &form); // // Get default format static Format getFormat(); // Get code belonging to string. 0 if not known static MVAngle::formatTypes giveMe(const String &in); // Get time zone offset (in days) static Double timeZone(); private: //# Data // Value Double val; // Default format static MVAngle::Format defaultFormat; // Temporary format // static MVAngle::Format interimFormat; static Bool interimSet; // //# Member functions }; // Global functions // Global output/input functions // Output/Input // ostream &operator<<(ostream &os, const MVAngle &meas); istream &operator>>(istream &is, MVAngle &meas); // Set a temporary format (thread-unsafe). ostream &operator<<(ostream &os, const MVAngle::Format &form); // } //# NAMESPACE CASACORE - END #endif