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

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

Ticket #134: enabling the specification of precision for decToDMS. Also setting that precision to be 1/10th of the pixel width, rounded down to the nearest multiple of 10. RA gets one additional decimal place.

File size: 7.2 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, int decPrecision)
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  int precision=std::max(0,decPrecision);
121  if(type=="RA") precision++;
122
123  if((type=="RA")||(type=="GLON")){
124    if(type=="GLON")  degSize = 3; // longitude has three figures in degrees.
125    // Make these modulo 360.;
126    while (thisDec < 0.) { thisDec += 360.; }
127    while (thisDec >= 360.) { thisDec -= 360.; }
128    if(type=="RA") thisDec /= 15.;  // Convert to hours.
129  }
130  else if((type=="DEC")||(type=="GLAT")){
131    if(thisDec<0.) sign = "-";
132    else sign = "+";
133  }
134  else { // UNKNOWN TYPE -- DEFAULT TO RA.
135    std::cerr << "WARNING <decToDMS> : Unknown axis type ("
136              << type << "). Defaulting to using RA.\n";
137    while (thisDec < 0.) { thisDec += 360.; }
138    while (thisDec >= 360.) { thisDec -= 360.; }
139    thisDec /= 15.;
140  }
141 
142  dec_abs = fabs(thisDec);
143  deg = int(dec_abs);
144  min = int(fmod(dec_abs,1.)*60.);
145  sec = fmod(dec_abs,onemin)*3600.;
146  if(fabs(sec-60.)<1.e-10){ // to prevent rounding errors stuffing things up
147    sec=0.;
148    min++;
149  }
150  std::stringstream ss(std::stringstream::out);
151  ss.setf(std::ios::showpoint);
152  ss.setf(std::ios::fixed);
153  ss << sign;
154  ss << setw(degSize)<<setfill('0')<<deg<<":";
155  ss<<setw(2)<<setfill('0')<<min<<":";
156  if(precision>0)
157    ss<<setw(precision+3)<<setprecision(precision)<<sec;
158  else {
159    //ss.unsetf(std::ios::showpoint);
160    //    ss.unsetf(std::ios::fixed);
161    ss << setw(2) << int(sec);
162    //    ss<<setw(2)<<setfill('0')<<setprecision(precision)<<sec;
163  }
164  return ss.str();
165}
166
167
168double dmsToDec(std::string dms)
169{
170  /**
171   *  double dmsToDec(string)
172   *   Converts a std::string in the format +12:23:34.45 to a decimal angle in degrees.
173   *   Assumes the angle given is in degrees, so if passing RA as the argument,
174   *   need to multiply by 15 to get the result in degrees rather than hours.
175   *   The sign of the angle is preserved, if present.
176   */
177
178
179  bool isNeg = false;
180  if(dms[0]=='-') isNeg = true;
181
182  std::stringstream ss;
183  ss.str(dms);
184  std::string deg,min,sec;
185  getline(ss,deg,':');
186  getline(ss,min,':');
187  getline(ss,sec);
188  char *end;
189  double d = strtod(deg.c_str(),&end);
190  double m = strtod(min.c_str(),&end);
191  double s = strtod(sec.c_str(),&end); 
192
193  double dec = fabs(d) + m/60. + s/3600.;
194  if(isNeg) dec = dec * -1.;
195
196  return dec;
197
198}
199
200const long double degToRadian=M_PI/180.;
201 
202double angularSeparation(double &ra1, double &dec1, double &ra2, double &dec2)
203{
204  /**
205   * double angularSeparation(double &,double &,double &,double &);
206   *  Enter ra & dec for two positions.
207   *    (all positions in degrees)
208   *  Returns the angular separation in degrees.
209   */
210
211  long double dra = (ra1-ra2)*degToRadian;
212  long double d1 = dec1*degToRadian;
213  long double d2 = dec2*degToRadian;
214  long double angsep;
215  if((fabs(ra1-ra2) < 1./3600.)&&(fabs(dec1-dec2)<1./3600.))
216    return sqrt(dra*dra + (d1-d2)*(d1-d2)) / degToRadian;
217  else {
218    if(fabs(ra1-ra2) < 1./3600.)
219      angsep = cos(d1)*cos(d2) - dra*dra*cos(d1)*cos(d2)/2. + sin(d1)*sin(d2);
220    else
221      angsep = cos(dra)*cos(d1)*cos(d2) + sin(d1)*sin(d2);
222    double dangsep = acos(angsep) / degToRadian;
223    return dangsep;
224  }
225
226}
Note: See TracBrowser for help on using the repository browser.