source: trunk/src/Utils/position_related.cc @ 950

Last change on this file since 950 was 950, checked in by MatthewWhiting, 12 years ago

Fixing a problem with the precision of RA & DEC for high-precision data (eg from VLBA). I needed to change ra & dec to double (rather than float), and have done the same
for most of the other parameters. This will need checking! Also made a few improvements to the decToDMS function. Seems to work now.

File size: 7.1 KB
RevLine 
[643]1// -----------------------------------------------------------------------
2// position_related.cc: General utility functions related to WCS positions
3// -----------------------------------------------------------------------
4// Copyright (C) 2006, Matthew Whiting, ATNF
5//
6// This program is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2 of the License, or (at your
9// option) any later version.
10//
11// Duchamp is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14// for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with Duchamp; if not, write to the Free Software Foundation,
18// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19//
20// Correspondence concerning Duchamp may be directed to:
21//    Internet email: Matthew.Whiting [at] atnf.csiro.au
22//    Postal address: Dr. Matthew Whiting
23//                    Australia Telescope National Facility, CSIRO
24//                    PO Box 76
25//                    Epping NSW 1710
26//                    AUSTRALIA
27// -----------------------------------------------------------------------
[3]28#include <iostream>
29#include <sstream>
30#include <iomanip>
31#include <string>
[643]32#include <stdlib.h>
[3]33#include <math.h>
[393]34#include <duchamp/Utils/utils.hh>
[3]35
36using std::setw;
37using std::setfill;
38using std::setprecision;
39
[232]40std::string getIAUNameEQ(double ra, double dec, float equinox)
[3]41{
42  /**
[232]43   * std::string getIAUNameEQ(double, double, float)
[3]44   *  both ra and dec are assumed to be in degrees.
[925]45   *  returns name of the form J123456-654321 for equinox = 2000,
[3]46   *   and B1234-4321 otherwise
47   */
48
[925]49  std::string rastr=decToDMS(ra,"RA",0);
50  rastr.erase(rastr.begin()+2);
51  rastr.erase(rastr.begin()+4);
52  if(equinox==2000.)
53    rastr.erase(rastr.begin()+6,rastr.end());
54  else
55    rastr.erase(rastr.begin()+4,rastr.end());
56  std::string decstr=decToDMS(dec,"DEC",0);
57  decstr.erase(decstr.begin()+3);
58  decstr.erase(decstr.begin()+5);
59  if(equinox==2000.)
60    decstr.erase(decstr.begin()+7,decstr.end());
61  else
62    decstr.erase(decstr.begin()+5,decstr.end());
63   
64  std::stringstream ss;
65  if(equinox==2000.) ss<<"J";
66  else ss<<"B";
67  ss<<rastr<<decstr;
[3]68  return ss.str();
[925]69
[3]70}
71
[232]72std::string getIAUNameGAL(double lon, double lat)
[3]73{
74  /**
[232]75   * std::string getIAUNameGAL(double, double)
[3]76   *  both ra and dec are assumed to be in degrees.
[112]77   *  returns name of the form G321.123+01.234
[3]78   */
79
80  std::stringstream ss(std::stringstream::out);
81  ss.setf(std::ios::showpoint);
82  ss.setf(std::ios::fixed);
83  ss<<"G";
[926]84  double goodlon=lon;
[930]85  if(lon<0.) goodlon += 360.;
[926]86  ss<<setw(7)<<setfill('0')<<setprecision(3)<<goodlon;
[3]87  ss.setf(std::ios::showpos);
88  ss.setf(std::ios::internal);
[112]89  ss<<setw(7)<<setfill('0')<<setprecision(3)<<lat;
[3]90  ss.unsetf(std::ios::internal);
91  ss.unsetf(std::ios::showpos);
92  ss.unsetf(std::ios::showpoint);
93  ss.unsetf(std::ios::fixed);
94  return ss.str();
95}
96
[907]97std::string decToDMS(const double dec, const std::string type, int decPrecision)
[3]98{
99  /**
[324]100   *Converts a decimal angle (in degrees) to a format reflecting the axis type:
101   *  RA   (right ascension):     hh:mm:ss.ss, with dec modulo 360. (24hrs)
102   *  DEC  (declination):        sdd:mm:ss.ss  (with sign, either + or -)
103   *  GLON (galactic longitude): ddd:mm:ss.ss, with dec made modulo 360.
104   *  GLAT (galactic latitude):  sdd:mm:ss.ss  (with sign, either + or -)
[38]105   *    Any other type defaults to RA, and prints warning.
[324]106   *
107   * \param dec Decimal value of the angle, in degrees.
108   * \param type String indicating desired type of output. Options RA, DEC,
109   *              GLON, GLAT
110   * \return String with angle in desired format.
[3]111   */
112
[950]113  double dec_abs,degD,minD,minDint,sec;
[3]114  int deg,min;
[950]115  const double minPerHour=60.;
116  const double degPerHour=15.;
[38]117  double thisDec = dec;
[232]118  std::string sign="";
[38]119  int degSize = 2; // number of figures in the degrees part of the output.
[3]120
[907]121  int precision=std::max(0,decPrecision);
122  if(type=="RA") precision++;
123
[38]124  if((type=="RA")||(type=="GLON")){
[324]125    if(type=="GLON")  degSize = 3; // longitude has three figures in degrees.
[38]126    // Make these modulo 360.;
127    while (thisDec < 0.) { thisDec += 360.; }
128    while (thisDec >= 360.) { thisDec -= 360.; }
[950]129    if(type=="RA") thisDec /= degPerHour;  // Convert to hours.
[38]130  }
131  else if((type=="DEC")||(type=="GLAT")){
132    if(thisDec<0.) sign = "-";
133    else sign = "+";
134  }
135  else { // UNKNOWN TYPE -- DEFAULT TO RA.
[201]136    std::cerr << "WARNING <decToDMS> : Unknown axis type ("
137              << type << "). Defaulting to using RA.\n";
[38]138    while (thisDec < 0.) { thisDec += 360.; }
139    while (thisDec >= 360.) { thisDec -= 360.; }
[950]140    thisDec /= degPerHour;
[38]141  }
142 
143  dec_abs = fabs(thisDec);
[950]144  minD = modf(dec_abs, &degD) * minPerHour;
145  sec = modf(minD, &minDint) * minPerHour;
146  deg = int(degD);
147  min = int(minDint);
148
149  if(fabs(sec-minPerHour)<pow(10,-precision)){ // to prevent rounding errors stuffing things up
150    std::cerr << "!\n";
[3]151    sec=0.;
152    min++;
[925]153    if(min==60){
154      min=0;
155      deg++;
156    }
[3]157  }
[950]158
[3]159  std::stringstream ss(std::stringstream::out);
160  ss.setf(std::ios::showpoint);
161  ss.setf(std::ios::fixed);
[38]162  ss << sign;
163  ss << setw(degSize)<<setfill('0')<<deg<<":";
[3]164  ss<<setw(2)<<setfill('0')<<min<<":";
[907]165  if(precision>0)
166    ss<<setw(precision+3)<<setprecision(precision)<<sec;
167  else {
168    ss << setw(2) << int(sec);
169  }
[950]170
[3]171  return ss.str();
172}
173
[38]174
[232]175double dmsToDec(std::string dms)
[3]176{
177  /**
178   *  double dmsToDec(string)
[232]179   *   Converts a std::string in the format +12:23:34.45 to a decimal angle in degrees.
[3]180   *   Assumes the angle given is in degrees, so if passing RA as the argument,
181   *   need to multiply by 15 to get the result in degrees rather than hours.
182   *   The sign of the angle is preserved, if present.
183   */
184
185
186  bool isNeg = false;
187  if(dms[0]=='-') isNeg = true;
188
189  std::stringstream ss;
190  ss.str(dms);
[232]191  std::string deg,min,sec;
[3]192  getline(ss,deg,':');
193  getline(ss,min,':');
194  getline(ss,sec);
195  char *end;
196  double d = strtod(deg.c_str(),&end);
197  double m = strtod(min.c_str(),&end);
198  double s = strtod(sec.c_str(),&end); 
199
200  double dec = fabs(d) + m/60. + s/3600.;
201  if(isNeg) dec = dec * -1.;
202
203  return dec;
204
205}
[213]206
207const long double degToRadian=M_PI/180.;
[3]208 
209double angularSeparation(double &ra1, double &dec1, double &ra2, double &dec2)
210{
211  /**
212   * double angularSeparation(double &,double &,double &,double &);
213   *  Enter ra & dec for two positions.
214   *    (all positions in degrees)
215   *  Returns the angular separation in degrees.
216   */
217
[213]218  long double dra = (ra1-ra2)*degToRadian;
219  long double d1 = dec1*degToRadian;
220  long double d2 = dec2*degToRadian;
221  long double angsep;
222  if((fabs(ra1-ra2) < 1./3600.)&&(fabs(dec1-dec2)<1./3600.))
223    return sqrt(dra*dra + (d1-d2)*(d1-d2)) / degToRadian;
224  else {
225    if(fabs(ra1-ra2) < 1./3600.)
226      angsep = cos(d1)*cos(d2) - dra*dra*cos(d1)*cos(d2)/2. + sin(d1)*sin(d2);
227    else
228      angsep = cos(dra)*cos(d1)*cos(d2) + sin(d1)*sin(d2);
229    double dangsep = acos(angsep) / degToRadian;
230    return dangsep;
231  }
[3]232
233}
Note: See TracBrowser for help on using the repository browser.