source: tags/release-1.1.12/src/Utils/position_related.cc

Last change on this file was 743, checked in by MatthewWhiting, 14 years ago

Need to deal with the possiblity of RA being negative (which was corrupting the IAU names)

File size: 6.9 KB
Line 
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// -----------------------------------------------------------------------
28#include <iostream>
29#include <sstream>
30#include <iomanip>
31#include <string>
32#include <stdlib.h>
33#include <math.h>
34#include <duchamp/Utils/utils.hh>
35
36using std::setw;
37using std::setfill;
38using std::setprecision;
39
40std::string getIAUNameEQ(double ra, double dec, float equinox)
41{
42  /**
43   * std::string getIAUNameEQ(double, double, float)
44   *  both ra and dec are assumed to be in degrees.
45   *  returns name of the form J1234-4321 for equinox = 2000,
46   *   and B1234-4321 otherwise
47   */
48
49  double raHrs = fmod(ra+360.,360.) / 15.;   // need to account for ra possibly being negative...
50  int h = int(raHrs);
51  int m = (int)(fmod(raHrs,1.)*60.);
52  int s = (int)(fmod(raHrs,1./60.)*3600.);
53  std::stringstream ss(std::stringstream::out);
54  ss.setf(std::ios::showpoint);
55  ss.setf(std::ios::fixed);
56  if(equinox==2000.) ss << "J";
57  else ss << "B";
58  ss<<setw(2)<<setfill('0')<<h;
59  ss<<setw(2)<<setfill('0')<<m;
60  ss<<setw(2)<<setfill('0')<<s;
61  int sign = int( dec / fabs(dec) );
62  double d = dec / sign;
63  h = int(d);
64  m = (int)(fmod(d,1.)*60.);
65  s = (int)(fmod(d,1./60.)*3600.);
66  if(sign==1) ss<<"+"; else ss<<"-";
67  ss<<setw(2)<<setfill('0')<<h;
68  ss.unsetf(std::ios::showpos);
69  ss<<setw(2)<<setfill('0')<<m;
70  ss<<setw(2)<<setfill('0')<<s;
71  return ss.str();
72}
73
74std::string getIAUNameGAL(double lon, double lat)
75{
76  /**
77   * std::string getIAUNameGAL(double, double)
78   *  both ra and dec are assumed to be in degrees.
79   *  returns name of the form G321.123+01.234
80   */
81
82  std::stringstream ss(std::stringstream::out);
83  ss.setf(std::ios::showpoint);
84  ss.setf(std::ios::fixed);
85  ss<<"G";
86  ss<<setw(7)<<setfill('0')<<setprecision(3)<<lon;
87  ss.setf(std::ios::showpos);
88  ss.setf(std::ios::internal);
89  ss<<setw(7)<<setfill('0')<<setprecision(3)<<lat;
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
97std::string decToDMS(const double dec, const std::string type)
98{
99  /**
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 -)
105   *    Any other type defaults to RA, and prints warning.
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.
111   */
112
113  double dec_abs,sec;
114  int deg,min;
115  const double onemin=1./60.;
116  double thisDec = dec;
117  std::string sign="";
118  int degSize = 2; // number of figures in the degrees part of the output.
119
120  if((type=="RA")||(type=="GLON")){
121    if(type=="GLON")  degSize = 3; // longitude has three figures in degrees.
122    // Make these modulo 360.;
123    while (thisDec < 0.) { thisDec += 360.; }
124    while (thisDec >= 360.) { thisDec -= 360.; }
125    if(type=="RA") thisDec /= 15.;  // Convert to hours.
126  }
127  else if((type=="DEC")||(type=="GLAT")){
128    if(thisDec<0.) sign = "-";
129    else sign = "+";
130  }
131  else { // UNKNOWN TYPE -- DEFAULT TO RA.
132    std::cerr << "WARNING <decToDMS> : Unknown axis type ("
133              << type << "). Defaulting to using RA.\n";
134    while (thisDec < 0.) { thisDec += 360.; }
135    while (thisDec >= 360.) { thisDec -= 360.; }
136    thisDec /= 15.;
137  }
138 
139  dec_abs = fabs(thisDec);
140  deg = int(dec_abs);
141  min = int(fmod(dec_abs,1.)*60.);
142  sec = fmod(dec_abs,onemin)*3600.;
143  if(fabs(sec-60.)<1.e-10){ // to prevent rounding errors stuffing things up
144    sec=0.;
145    min++;
146  }
147  std::stringstream ss(std::stringstream::out);
148  ss.setf(std::ios::showpoint);
149  ss.setf(std::ios::fixed);
150  ss << sign;
151  ss << setw(degSize)<<setfill('0')<<deg<<":";
152  ss<<setw(2)<<setfill('0')<<min<<":";
153  ss<<setw(5)<<setprecision(2)<<sec;
154  return ss.str();
155}
156
157
158double dmsToDec(std::string dms)
159{
160  /**
161   *  double dmsToDec(string)
162   *   Converts a std::string in the format +12:23:34.45 to a decimal angle in degrees.
163   *   Assumes the angle given is in degrees, so if passing RA as the argument,
164   *   need to multiply by 15 to get the result in degrees rather than hours.
165   *   The sign of the angle is preserved, if present.
166   */
167
168
169  bool isNeg = false;
170  if(dms[0]=='-') isNeg = true;
171
172  std::stringstream ss;
173  ss.str(dms);
174  std::string deg,min,sec;
175  getline(ss,deg,':');
176  getline(ss,min,':');
177  getline(ss,sec);
178  char *end;
179  double d = strtod(deg.c_str(),&end);
180  double m = strtod(min.c_str(),&end);
181  double s = strtod(sec.c_str(),&end); 
182
183  double dec = fabs(d) + m/60. + s/3600.;
184  if(isNeg) dec = dec * -1.;
185
186  return dec;
187
188}
189
190const long double degToRadian=M_PI/180.;
191 
192double angularSeparation(double &ra1, double &dec1, double &ra2, double &dec2)
193{
194  /**
195   * double angularSeparation(double &,double &,double &,double &);
196   *  Enter ra & dec for two positions.
197   *    (all positions in degrees)
198   *  Returns the angular separation in degrees.
199   */
200
201  long double dra = (ra1-ra2)*degToRadian;
202  long double d1 = dec1*degToRadian;
203  long double d2 = dec2*degToRadian;
204  long double angsep;
205  if((fabs(ra1-ra2) < 1./3600.)&&(fabs(dec1-dec2)<1./3600.))
206    return sqrt(dra*dra + (d1-d2)*(d1-d2)) / degToRadian;
207  else {
208    if(fabs(ra1-ra2) < 1./3600.)
209      angsep = cos(d1)*cos(d2) - dra*dra*cos(d1)*cos(d2)/2. + sin(d1)*sin(d2);
210    else
211      angsep = cos(dra)*cos(d1)*cos(d2) + sin(d1)*sin(d2);
212    double dangsep = acos(angsep) / degToRadian;
213    return dangsep;
214  }
215
216}
Note: See TracBrowser for help on using the repository browser.