Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

AstCoordinate.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // AstCoordinate
00004 //
00005 // Package: Ast (AstroUtil).
00006 //
00007 // S. Kasahara 05/03
00008 //
00009 // Purpose: Provide utility routines to convert between various astronomical
00010 //          coordinate sytems.
00011 //
00012 //          Horizon coordinates (altitude,azimuth) are defined as:
00013 //          altitude:  elevation above the horizon, measured from -90^o (nadir)
00014 //                     through 0^o (horizon) to +90^o (zenith).
00015 //          azimuth:  the angle in the horizon plane measured easterly from
00016 //                    north, i.e. 0^o is North, 90^o East, 180^o South,
00017 //                    270^o West.
00018 //
00019 //          Local Det. Coordinate direction cosines (dcosx,dcosy,dcosz) are 
00020 //          defined in the local coordinate system of a specified detector
00021 //          type (Detector::Detector_t):
00022 //          +z: horizontal component of the beam direction.
00023 //          +y: local vertical.
00024 //          +x: chosen to make coordinate system right-handed.
00025 //
00026 //          Ideal Det. Coordinate direction cosines (dcosx_ideal,dcosy_ideal,
00027 //          dcosz_ideal) are defined such that:
00028 //          +z: points North.
00029 //          +y: radius vector originating at center of earth.
00030 //          +x: points West.   
00031 //
00032 //          Geocentric Equatorial coordinates (hourangle, declination),
00033 //          are defined relative to the earth's equatorial plane.
00034 //          hourangle:  time since the object crossed the observer's meridian 
00035 //                      (the great circle passing through the observer's zenith
00036 //                       and the poles).  Measured from 0 to 360^o.
00037 //          declination: elevation above the equatorial plane, measured from
00038 //                       -90^o to 90^o.
00039 //
00040 //          Geocentric Celestial coordinates (right ascension,declination),
00041 //          are defined as in the equatorial system, but instead of rotating
00042 //          with the earth, they are fixed on the celestial sphere.
00043 //          right ascension: angle in the equatorial plane measured eastwards
00044 //                           from the rising of Aries. Measured from 0 - 360^o.
00045 //          declination: same as for Geocentric Equatorial coordinates.
00046 //
00047 //Panos, 10/04
00048 //          Geocentric Ecliptic coordinates (ecliptic latitude, beta, ecliptic 
00049 //          longitude, lamda), are defined relative to the ecliptic great circle.
00050 //          They are also fixed on the celestial sphere 
00051 //          latitude: elevation over the ecliptic (-90 to 90^o).
00052 //          longitude: angle in the ecliptic plane, measured eastwards from the 
00053 //          rising of Aries (one of two points where the equatorial and ecliptic
00054 //          circles cross).
00056 
00057 #include <math.h>
00058 #include "AstroUtil/Ast.h"
00059 #include "AstroUtil/AstCoordinate.h"
00060 #include "AstroUtil/AstTime.h"
00061 #include "Conventions/Mphysical.h"  // pi
00062 #include "MessageService/MsgService.h"
00063 
00064 CVSID("$Id: AstCoordinate.cxx,v 1.5 2005/12/13 15:57:30 rhatcher Exp $");
00065 
00066 // Definition of methods (alphabetical order)
00067 // ******************************************
00068 
00069 void AstUtil::LocalToIdeal( double dcosx, double dcosy, double dcosz, 
00070      Detector::Detector_t dettype, double& dcosx_ideal, 
00071      double& dcosy_ideal, double& dcosz_ideal ) {
00072   // Static method to convert direction cosines from local detector
00073   // coordinates to ideal detector coordinates.
00074 
00075   const double* rotmatrix = AstUtil::GetDetRotMatrixLocalToIdeal(dettype);
00076   if ( !rotmatrix ) {
00077     MSG("Ast",Msg::kWarning) 
00078       << "No rotation matrix available for requested det type " << dettype
00079       << ".\n No rotation from local to ideal coordinates will be applied." 
00080       << endl;
00081     dcosx_ideal = dcosx;
00082     dcosy_ideal = dcosy;
00083     dcosz_ideal = dcosz;
00084     return;
00085   }
00086 
00087   dcosx_ideal = rotmatrix[0]*dcosx
00088               + rotmatrix[1]*dcosy
00089               + rotmatrix[2]*dcosz;
00090   dcosy_ideal = rotmatrix[3]*dcosx
00091               + rotmatrix[4]*dcosy
00092               + rotmatrix[5]*dcosz;
00093   dcosz_ideal = rotmatrix[6]*dcosx
00094               + rotmatrix[7]*dcosy
00095               + rotmatrix[8]*dcosz;
00096   return;
00097 
00098 }
00099 
00100 void AstUtil::IdealToLocal( double dcosx_ideal, double dcosy_ideal,
00101       double dcosz_ideal, Detector::Detector_t dettype,
00102       double& dcosx, double& dcosy, double& dcosz) {
00103   // Static method to convert direction cosines from ideal detector 
00104   // coordinates to local detector coordinates.
00105 
00106   const double* rotmatrix = AstUtil::GetDetRotMatrixIdealToLocal(dettype);
00107   if ( !rotmatrix ) {
00108     MSG("Ast",Msg::kWarning) 
00109       << "No rotation matrix available for requested det type " << dettype
00110       << ".\n No rotation from ideal to local coordinates  will be applied." 
00111       << endl;
00112     dcosx = dcosx_ideal;
00113     dcosy = dcosy_ideal;
00114     dcosz = dcosz_ideal;
00115     return;
00116   }
00117 
00118   dcosx = rotmatrix[0]*dcosx_ideal
00119         + rotmatrix[1]*dcosy_ideal
00120         + rotmatrix[2]*dcosz_ideal;
00121   dcosy = rotmatrix[3]*dcosx_ideal
00122         + rotmatrix[4]*dcosy_ideal
00123         + rotmatrix[5]*dcosz_ideal;
00124   dcosz = rotmatrix[6]*dcosx_ideal
00125         + rotmatrix[7]*dcosy_ideal
00126         + rotmatrix[8]*dcosz_ideal;
00127   return;
00128 
00129 }
00130 
00131 void AstUtil::LocalToHorizon(double dcosx,double dcosy,double dcosz, 
00132      Detector::Detector_t dettype, double& altitude, double& azimuth){
00133   // Static method to convert direction cosines to horizon coordinates
00134   // The direction cosines are local to the detector type specified by dettype.
00135 
00136 
00137   double dcosx_ideal,dcosy_ideal,dcosz_ideal;
00138 
00139   AstUtil::LocalToIdeal(dcosx,dcosy,dcosz,dettype,dcosx_ideal,
00140                          dcosy_ideal,dcosz_ideal);
00141   AstUtil::IdealToHorizon(dcosx_ideal,dcosy_ideal,dcosz_ideal,altitude,
00142                              azimuth);
00143 
00144 }
00145 
00146 void AstUtil::IdealToHorizon(double dcosx_ideal,double dcosy_ideal,
00147                  double dcosz_ideal,double& altitude, double& azimuth){
00148   // Static method to convert ideal coordinate system direction cosines to 
00149   // horizon coordinates.
00150 
00151   double zenith = acos(dcosy_ideal)*180./Mphysical::pi;
00152   altitude = 90. - zenith;
00153   azimuth = 180.*atan2(-dcosx_ideal,dcosz_ideal)/Mphysical::pi;
00154   if ( azimuth < 0. ) azimuth += 360.;
00155 
00156 }
00157 
00158 void AstUtil::HorizonToIdeal(double altitude, double azimuth,
00159     double& dcosx_ideal, double& dcosy_ideal, double& dcosz_ideal) {
00160   // Static method to convert horizon coordinates to ideal detector
00161   // coordinates.
00162   double zenrad = (90. - altitude)*Mphysical::pi/180.; 
00163   double azirad = azimuth*Mphysical::pi/180.;
00164   dcosy_ideal =  cos(zenrad);
00165   dcosx_ideal = -sin(zenrad)*sin(azirad);
00166   dcosz_ideal =  sin(zenrad)*cos(azirad);
00167   return;
00168 
00169 }
00170 
00171 void AstUtil::HorizonToLocal(double altitude, double azimuth,
00172           Detector::Detector_t dettype, double& dcosx, double& dcosy, 
00173           double& dcosz) {
00174   // Static method to convert horizon coordinates to direction cosines
00175 
00176   double dcosx_ideal,dcosy_ideal,dcosz_ideal;
00177   AstUtil::HorizonToIdeal(altitude,azimuth,dcosx_ideal,dcosy_ideal,
00178                                                        dcosz_ideal);
00179   AstUtil::IdealToLocal(dcosx_ideal,dcosy_ideal,dcosz_ideal,dettype,
00180                         dcosx,dcosy,dcosz);
00181   return;
00182 }
00183 
00184 void AstUtil::HorizonToEquatorial(double altitude, double azimuth, 
00185               double latitude, double& hourangle, double& declination) {
00186   // Static method to convert from horizon to equatorial coordinates.
00187   // From Practical Ephemeris Calculations by O. Montenbruck:
00188   // 1)sin(dec)         = sin(lat)*sin(alt) + cos(lat)*cos(alt)*cos(azi)
00189   // 2)cos(dec)*sin(ha) = -cos(alt)*sin(azi)
00190   // 3)cos(dec)*cos(ha) = cos(lat)*sin(alt)-sin(lat)*cos(alt)*cos(azi)
00191   // This implementation is adapted from an M. Thomson Soudan2 fortran
00192   // routine.
00193 
00194   double latrad = latitude*Mphysical::pi/180.;
00195   double altrad = altitude*Mphysical::pi/180.;
00196   double azirad = azimuth*Mphysical::pi/180.;
00197 
00198   double sinlat = sin(latrad);
00199   double sinalt = sin(altrad);
00200   double sinazi = sin(azirad);
00201   double coslat = cos(latrad);
00202   double cosalt = cos(altrad);
00203   double cosazi = cos(azirad);
00204 
00205   // solve equation 1 to determine declination
00206   double sindec = sinalt*sinlat + cosalt*cosazi*coslat;
00207   if ( sindec >= 1 ) declination = Mphysical::pi/2.;
00208   else if ( sindec <= -1 ) declination = -Mphysical::pi/2.;
00209   else declination = asin(sindec);
00210 
00211   // solve equation 2 to determine hourangle in range -pi/2 to pi/2
00212   double du = 90.0001*Mphysical::pi/180.;
00213   double dl = 89.9999*Mphysical::pi/180.;
00214   if ( fabs(declination) > dl && fabs(declination) < du ) {
00215     hourangle = 0.;
00216   }
00217   else {
00218    double sinhourangle = -cosalt*sinazi/cos(declination);
00219    if ( sinhourangle >= 1 ) hourangle = Mphysical::pi/2.;
00220    else if ( sinhourangle <= -1 ) hourangle = -Mphysical::pi/2.;
00221    else hourangle = asin(sinhourangle);
00222   }
00223 
00224   // use 3rd equation to fully determine hourangle
00225   double lhs = cos(declination)*cos(hourangle);
00226   double rhs = sinalt*coslat - cosalt*cosazi*sinlat;
00227 
00228   double prod = lhs*rhs;
00229   if ( prod != fabs(prod) ) {
00230     if ( hourangle > 0. ) hourangle = Mphysical::pi - hourangle;
00231     else hourangle = -Mphysical::pi - hourangle;
00232   }
00233 
00234   if ( hourangle < 0. ) hourangle += 2.*Mphysical::pi;
00235 
00236   hourangle   = hourangle*180./Mphysical::pi; // degrees
00237   declination = declination*180./Mphysical::pi; // degrees
00238 
00239   return;
00240 
00241 }
00242 
00243 void AstUtil::EquatorialToHorizon(double hourangle,double declination, 
00244     double latitude, double& altitude, double& azimuth) {
00245   // Static method to convert from equatorial to horizon coordinates
00246   // From Practical Ephemeris Calculations by O. Montenbruck:
00247   // 1)sin(alt)          =  sin(lat)*sin(dec) + cos(lat)*cos(dec)*cos(ha)
00248   // 2)cos(alt)*sin(azi) = -cos(dec)*sin(ha)
00249   // 3)cos(alt)*cos(azi) =  cos(lat)*sin(dec) - sin(lat)*cos(dec)*cos(ha)
00250   // This implementation is adapted from an M. Thomson Soudan2 fortran
00251   // routine.
00252 
00253   double latrad = latitude*Mphysical::pi/180.;
00254   double harad  = hourangle*Mphysical::pi/180.;
00255   double decrad = declination*Mphysical::pi/180.;
00256 
00257   double sinlat = sin(latrad);
00258   double sinha  = sin(harad);
00259   double sindec = sin(decrad);
00260   double coslat = cos(latrad);
00261   double cosha  = cos(harad);
00262   double cosdec = cos(decrad);
00263 
00264   // Solve equation 1 for altitude
00265   double sinalt = sindec*sinlat + cosdec*cosha*coslat;
00266   if ( sinalt >= 1 ) altitude = Mphysical::pi/2.;
00267   else if ( sinalt <= -1 ) altitude = -Mphysical::pi/2.;
00268   else altitude = asin(sinalt);
00269 
00270   // Solve equation 2 to determine azimuth in range -pi/2 to pi/2.
00271   double du = 90.0001*Mphysical::pi/180.;
00272   double dl = 89.9999*Mphysical::pi/180.;
00273   if (fabs(altitude) > dl && fabs(altitude) < du ) {
00274     azimuth = 0;
00275   }
00276   else {
00277     double sinazi = -cosdec*sinha/cos(altitude);
00278     if ( sinazi >= 1 ) azimuth = Mphysical::pi/2.;
00279     else if (sinazi <= -1 ) azimuth = -Mphysical::pi/2.; 
00280     else azimuth = asin(sinazi);
00281   }
00282 
00283   // Use 3rd equation to fully determine azimuth
00284   double lhs = cos(altitude)*cos(azimuth);
00285   double rhs = sindec*coslat - cosdec*cosha*sinlat;
00286 
00287   double prod = lhs*rhs;
00288   if ( prod != fabs(prod) ) {
00289     if ( azimuth > 0. ) azimuth = Mphysical::pi - azimuth;
00290     else azimuth = -Mphysical::pi - azimuth;
00291   }
00292 
00293   if ( azimuth < 0. ) azimuth += 2.*Mphysical::pi;
00294 
00295   altitude = altitude*180./Mphysical::pi;  // degrees
00296   azimuth  = azimuth*180./Mphysical::pi;   // degrees
00297 
00298   return;
00299 
00300 }
00301 
00302 void AstUtil::CelestialToEquatorial(double ra, double gst,
00303                           double longitude,double& hourangle) {
00304   // Static method to convert from celestial to equatorial coordinates
00305 
00306   double lst;
00307   AstUtil::GSTToLST(gst,longitude,lst);
00308   lst *= 15.; // convert from hours to degrees
00309   hourangle = lst - ra;
00310   if ( hourangle < 0. ) hourangle += 360.;
00311  
00312   return;
00313 
00314 }
00315 
00316 void AstUtil::EquatorialToCelestial(double hourangle, double gst,
00317                                     double longitude, double& ra) {
00318   // Static method to convert from equatorial to celestial coordinates
00319 
00320   double lst; 
00321   AstUtil::GSTToLST(gst,longitude,lst);
00322   lst *= 15.; // convert from hours to degrees
00323   ra = lst - hourangle; // in degrees
00324   if ( ra < 0. ) ra += 360.;
00325 
00326   return;
00327 }
00328 
00329 void AstUtil::CelestialToEcliptic(double declination, double ra,
00330                 double& beta, double& lamda)
00331 { // Static method to convert from celestial to ecliptic coordinates
00332 
00333     const double epsilon  = 23.43;
00334     
00335     double sindelta = sin(declination);
00336     double sinalpha = sin(ra);
00337     double cosdelta = cos(declination);
00338     double cosalpha = cos(ra);
00339     double cosbeta  = cos(beta);
00340     
00341     //We will need both trigonometric numbers of epsilon, the constant angle between
00342     //the ecliptic and the celestial equator great circles. 
00343     const double Alpha = cos(Mphysical::pi*epsilon/180.);
00344     const double Beta  = sin(Mphysical::pi*epsilon/180.);
00345     
00346     beta  =  asin(sindelta*Alpha-cosdelta*Beta*sinalpha);
00347     if (cosbeta!=0){
00348         lamda =  acos(cosalpha*cosdelta/cosbeta); 
00349     } else { //the point lies on pole of ecliptic, and lamda has no meaning
00350         lamda = 0;
00351     }
00352     if (lamda < 0.) lamda += 360.;
00353     return;
00354 }
00355 
00356 
00357 void AstUtil::EclipticToCelestial(double beta, double lamda,
00358                 double& declination, double& ra)
00359 { // Static method to convert from ecliptic to celestial coordinates
00360 
00361     const double epsilon  = 23.43;
00362     
00363     double sinlamda = sin(lamda);
00364     double coslamda = cos(lamda);
00365     double cosbeta  = cos(beta);
00366     double sinbeta  = sin(beta);
00367     double cosdelta = cos(declination);
00368     
00369     //We will need both trigonometric numbers of epsilon, the constant angle between
00370     //the ecliptic and the celestial equator great circles. 
00371     const double Alpha = cos(Mphysical::pi*epsilon/180.);
00372     const double Beta  = sin(Mphysical::pi*epsilon/180.);
00373     
00374     declination  =  asin(sinbeta*Alpha+cosbeta*Beta*sinlamda);
00375     if (cosdelta!=0){
00376         ra =  acos(coslamda*cosbeta/cosdelta); 
00377     } else { //the point lies on pole of equator, and ra has no meaning
00378         ra = 0;
00379     }
00380     if (ra <0.) ra += 360.;
00381     return;
00382 }

Generated on Thu Nov 1 11:49:28 2007 for loon by  doxygen 1.3.9.1