Skip to content
Snippets Groups Projects
xastropack.cc 13.3 KiB
Newer Older
#include <math.h>
#include <stdio.h>
#include "xastropack.h"

cmv's avatar
cmv committed
/*!
  \defgroup XAstroPack XAstroPack module
  This module contains simple programs to perform various
  astronomical computation (based on the libastro of Xephem).

  \verbatim
// TEMPS: modified Julian date (mjd) (number of days elapsed since 1900 jan 0.5)
//        jour [1,31] (dy)
//        mois [1,12] (mn)
//        annee       (yr)
//        universal time [0,24[ (utc)
//        Greenwich mean siderial [0,24[ (gst)
//        Greenwich mean siderial at 0h UT [0,24[ (gst0)
// EQUATORIALE: ascension droite en heures [0,24[ (ra)
//              declinaison en degres [-90,90]    (dec)
cmv's avatar
cmv committed
//              angle horaire en heures [-12,12] (-12=12) (ha) 
//              temps sideral du lieu: tsid=ha+ra (ou lst)
// GALACTIQUE: longitude en degres [0,360[  (glng)
//             latitude en degres [-90,90]  (glat)
// HORIZONTAL: azimuth en degres [0,360[   (az)
//                 (angle round to the east from north+)
//             altitude en degres [-90,90] (alt)
// ECLIPTIQUE: lontitude ecliptique en degres [0,360[ (eclng)
//                 (angle round counter clockwise from the vernal equinoxe)
//             latitude ecliptique en degres [-90,90] (eclat)
// GEOGRAPHIE: longitude en degres ]-180,180]        (geolng)
//                 (angle + vers l'ouest, - vers l'est)
//             latitude en degres [-90,90] (north>0) (geolat)
cmv's avatar
cmv committed
  \endverbatim
*/
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief gmst0() - return Greenwich Mean Sidereal Time at 0h UT
\param mjd0 = date at 0h UT in julian days since MJD0
cmv's avatar
cmv committed
*/                                                                             
double GST0(double mjd0)
cmv's avatar
cmv committed
/* Copie depuis le code de Xephem (utc_gst.c) car pas prototype*/
{
 double T, x;
 T = ((int)(mjd0 - 0.5) + 0.5 - J2000)/36525.0;
 x = 24110.54841 +
     (8640184.812866 + (0.093104 - 6.2e-6 * T) * T) * T;
 x /= 3600.0;
 range(&x, 24.0);
 return (x);
}

cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief return local sidereal time from modified julian day and longitude
\warning nutation or obliquity correction are taken into account.
*/                                                                             
double LSTfrMJD(double mjd,double geolng)
{
  double eps,lst,deps,dpsi;
  utc_gst(mjd_day(mjd),mjd_hr(mjd),&lst);
  lst += deghr(geolng);
cmv's avatar
cmv committed
  obliquity(mjd,&eps);
  nutation(mjd,&deps,&dpsi);
  lst += radhr(dpsi*cos(eps+deps));
  InRange(&lst,24.);
cmv's avatar
cmv committed
  return lst;
}

cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief Give a time in h:mn:s from a decimal hour
\verbatim
cmv's avatar
cmv committed
// OUTPUT: h mn s   (h,mn,s >=< 0)
// REMARQUE: si hd<0 alors h<0 ET mn<0 ET s<0
// EX: 12.51 -> h=12  mn=30  s=10 ; 
//    -12.51 -> h=-12 mn=-30 s=-10 ; 
cmv's avatar
cmv committed
\endverbatim
*/                                                                             
void HMSfrHdec(double hd,int *h,int *mn,double *s)
{
 int sgn=1;
 if(hd<0.) {sgn=-1; hd*=-1.;}
 *h  = int(hd);
 *mn = int((hd-(double)(*h))*60.);
 *s  = (hd - (double)(*h) - (double)(*mn)/60.)*3600.;
 // pb precision
 if(*s<0.) *s = 0.;
 if(*s>60. || *s==60.) {*s-=60.; *mn+=1;} // s=double attention comparaison
 if(*mn<0) *mn = 0;
 if(*mn>=60) {*mn-=60; *h+=1;}
cmv's avatar
cmv committed
 *h *= sgn; *mn *= sgn; *s *= (double)sgn;
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief Give a decimal hour from a time in h:mn:s
\verbatim
cmv's avatar
cmv committed
// INPUT: h , mn , s  (h,mn,s >=< 0)
// RETURN:  en heures decimales
// REMARQUE: pour avoir hd=-12.51 <- h=-12 mn=-30 s=-10
cmv's avatar
cmv committed
\endverbatim
*/                                                                             
double HdecfrHMS(int h,int mn,double s)
cmv's avatar
cmv committed
 return ((double)h + (double)mn/60. + s/3600.);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief Give a time string from a time in h:mn:s
\verbatim
cmv's avatar
cmv committed
// INPUT: h , mn , s   (h,mn,s >=< 0)
// RETURN: string h:mn:s
cmv's avatar
cmv committed
\endverbatim
*/                                                                             
string ToStringHMS(int h,int mn,double s)
cmv's avatar
cmv committed
 double hd = HdecfrHMS(h,mn,s); // put in range
 HMSfrHdec(hd,&h,&mn,&s);
cmv's avatar
cmv committed
 if(hd<0.)
   sprintf(str,"-%d:%d:%.3f",-h,-mn,-s);
 else
   sprintf(str,"%d:%d:%.3f",h,mn,s);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief Give a time string from a decimal hour
*/                                                                             
string ToStringHdec(double hd)
{
 int h,mn; double s;
cmv's avatar
cmv committed
 HMSfrHdec(hd,&h,&mn,&s);
/*! \ingroup XAstroPack
\brief Compute precession between 2 dates.
*/                                                                             
void Precess(double mjd1,double mjd2,double ra1,double dec1,double *ra2,double *dec2)
{
 ra1  = hrrad(ra1);   // radians
 dec1 = degrad(dec1);  // radians
 precess(mjd1,mjd2,&ra1,&dec1);
 *ra2 = radhr(ra1); InRange(ra2,24.);
 *dec2 = raddeg(dec1);
}

cmv's avatar
cmv committed
/*! \ingroup XAstroPack
cmv's avatar
cmv committed
\brief Convert equatorial coordinates for the given epoch into galactic coordinates
cmv's avatar
cmv committed
*/                                                                             
void EqtoGal(double mjd,double ra,double dec, double *glng,double *glat)
// Coordonnees equatoriales -> Coordonnees galactiques
{
 ra  = hrrad(ra);   // radians
 dec = degrad(dec);  // radians
 eq_gal(mjd,ra,dec,glat,glng);
 // Vraiment bizarre, sur Linux-g++ glng>=360 ne comprend pas glng==360 ! (CMV)
 *glng = raddeg(*glng); InRange(glng,360.);
 *glat = raddeg(*glat);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
cmv's avatar
cmv committed
\brief Convert galactic coordinates into equatorial coordinates at the given epoch
cmv's avatar
cmv committed
*/                                                                             
void GaltoEq(double mjd,double glng,double glat,double *ra,double *dec)
// Coordonnees galactiques -> Coordonnees equatoriales
{
 glng = degrad(glng);  // radians
 glat = degrad(glat);  // radians
 gal_eq (mjd,glat,glng,ra,dec);
 *ra = radhr(*ra); InRange(ra,24.);
 *dec = raddeg(*dec);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
cmv's avatar
cmv committed
\brief Convert equatorial coordinates (with hour angle instead of right ascension) into horizontal coordinates.
cmv's avatar
cmv committed
*/                                                                             
cmv's avatar
cmv committed
void EqHtoHor(double geolat,double ha,double dec,double *az,double *alt)
// Coordonnees equatoriales -> Coordonnees horizontales
{
 geolat = degrad(geolat);  // radians
 ha  = hrrad(ha);   // radians
 dec = degrad(dec);  // radians
 hadec_aa (geolat,ha,dec,alt,az);
 *alt = raddeg(*alt);
 *az  = raddeg(*az); InRange(az,360.);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
cmv's avatar
cmv committed
 Convert horizontal coordinates into equatorial coordinates (with hour angle instead of right ascension).
cmv's avatar
cmv committed
*/                                                                             
cmv's avatar
cmv committed
void HortoEqH(double geolat,double az,double alt,double *ha,double *dec)
// Coordonnees horizontales -> Coordonnees equatoriales
{
 geolat = degrad(geolat);  // radians
 alt = degrad(alt);  // radians
 az  = degrad(az);  // radians
 aa_hadec (geolat,alt,az,ha,dec);
 *ha = radhr(*ha); InRange(ha,24.,12.);
 *dec = raddeg(*dec);
cmv's avatar
cmv committed
}

/*! \ingroup XAstroPack
\brief Convert equatorial coordinates into horizontal coordinates.
*/                                                                             
void EqtoHor(double geolat,double lst,double ra,double dec,double *az,double *alt)
// Coordonnees equatoriales -> Coordonnees horizontales
{
 double ha = lst - ra; InRange(&ha,24.,12.);
 geolat = degrad(geolat);  // radians
 ha = hrrad(ha);   // radians
 dec = degrad(dec);  // radians
cmv's avatar
cmv committed
 hadec_aa (geolat,ha,dec,alt,az);
 *alt = raddeg(*alt);
 *az  = raddeg(*az); InRange(az,360.);
cmv's avatar
cmv committed
}

/*! \ingroup XAstroPack
 Convert horizontal coordinates into equatorial coordinates.
*/                                                                             
void HortoEq(double geolat,double lst,double az,double alt,double *ra,double *dec)
// Coordonnees horizontales -> Coordonnees equatoriales
{
 double ha;
 geolat = degrad(geolat);  // radians
 alt = degrad(alt);  // radians
 az  = degrad(az);  // radians
cmv's avatar
cmv committed
 aa_hadec (geolat,alt,az,&ha,dec);
 *ra = lst - radhr(ha); InRange(ra,24.);
 *dec = raddeg(*dec);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
cmv's avatar
cmv committed
\brief Convert equatorial coordinates into geocentric ecliptic coordinates given the modified Julian date.
\warning Correction for the effect on the angle of the obliquity due to nutation is not included.
cmv's avatar
cmv committed
*/                                                                             
// Attention, j'ai modifie eq_ecl.c pour proteger NaN
// dans ecleq_aux :
// *q = (sy*ceps)-(cy*seps*sx*sw);
// if(*q<-1.) *q = -PI/2.; else if(*q>1.) *q = PI/2.; else *q = asin(*q);
void EqtoEcl(double mjd,double ra,double dec,double *eclng,double *eclat)
// Coordonnees equatoriales -> Coordonnees ecliptiques
{
 ra = hrrad(ra);   // radians
 dec = degrad(dec);  // radians
 eq_ecl(mjd,ra,dec,eclat,eclng);
 *eclng = raddeg(*eclng); InRange(eclng,360.);
 *eclat = raddeg(*eclat);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
cmv's avatar
cmv committed
\brief Convert geocentric ecliptic coordinates into equatorial coordinates given the modified Julian date.
\warning Correction for the effect on the angle of the obliquity due to nutation is not included.
cmv's avatar
cmv committed
*/                                                                             
void EcltoEq(double mjd,double eclng,double eclat,double *ra,double *dec)
// Coordonnees ecliptiques -> Coordonnees equatoriales
{
 eclat = degrad(eclat);  // radians
 eclng = degrad(eclng);  // radians
 ecl_eq(mjd,eclat,eclng,ra,dec); 
 *ra = radhr(*ra); InRange(ra,24.);
 *dec = raddeg(*dec);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief Give Sun position
\verbatim
 given the modified JD, mjd, return the true geocentric ecliptic longitude
 of the sun for the mean equinox of the date, *eclsn, in degres, the
 sun-earth distance, *rsn, in AU, and the latitude *ecbsn, in degres
cmv's avatar
cmv committed
 (since this is always <= 1.2 arcseconds, in can be neglected by
 calling with ecbsn = NULL).
 - REMARQUE:
 * if the APPARENT ecliptic longitude is required, correct the longitude for
 *   nutation to the true equinox of date and for aberration (light travel time,
 *   approximately  -9.27e7/186000/(3600*24*365)*2*pi = -9.93e-5 radians).
cmv's avatar
cmv committed
\endverbatim
*/
void SunPos(double mjd,double *eclsn,double *ecbsn,double *rsn)
 sunpos(mjd,eclsn,rsn,ecbsn);
 *eclsn = raddeg(*eclsn); InRange(eclsn,360.);
 if(ecbsn!=NULL) *ecbsn = raddeg(*ecbsn);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief Give Moon position
\verbatim
 given the mjd, find the geocentric ecliptic longitude, lam, and latitude,
 bet, and geocentric distance, rho in a.u. for the moon.  also return
 the sun's mean anomaly, *msp, and the moon's mean anomaly, *mdp. 
 (for the mean equinox)
\endverbatim
*/
void MoonPos(double mjd,double *eclmn,double *ecbmn,double *rho)
  double msp,mdp;
  moon(mjd,eclmn,ecbmn,rho,&msp,&mdp);
 *eclmn = raddeg(*eclmn); InRange(eclmn,360.);
 *ecbmn = raddeg(*ecbmn);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief Give planet position
\verbatim
 * given a modified Julian date, mjd, and a planet, p, find:
 *   sunecl: heliocentric longitude, 
 *   sunecb: heliocentric latitude,
 *   sundist:  distance from the sun to the planet, 
 *   geodist: distance from the Earth to the planet,
 *         none corrected for light time, ie, they are the true values for the
 *         given instant.
 *   geoecl:  geocentric ecliptic longitude, 
 *   geoecb:  geocentric ecliptic latitude,
 *         each corrected for light time, ie, they are the apparent values as
 *	   seen from the center of the Earth for the given instant.
 *   diamang:  angular diameter in arcsec at 1 AU, 
 *   mag:  visual magnitude when 1 AU from sun and earth at 0 phase angle.
cmv's avatar
cmv committed
 *   (for the mean equinox)
 * all angles are in degres, all distances in AU.
 *
 * corrections for nutation and abberation must be made by the caller. The RA 
 *   and DEC calculated from the fully-corrected ecliptic coordinates are then
 *   the apparent geocentric coordinates. Further corrections can be made, if
 *   required, for atmospheric refraction and geocentric parallax.
cmv's avatar
cmv committed
 \endverbatim
*/
void PlanetPos(double mjd,int numplan,double *sunecl,double *sunecb,double *sundist
              ,double *geodist,double *geoecl,double *geoecb
              ,double *diamang,double *mag)
 plans(mjd,numplan,sunecl,sunecb,sundist,geodist,geoecl,geoecb,diamang,mag);
 *geoecl = raddeg(*geoecl); InRange(geoecl,360.);
 *geoecb = raddeg(*geoecb);
 *sunecl = raddeg(*sunecl); InRange(sunecl,360.);
 *sunecb = raddeg(*sunecb);
cmv's avatar
cmv committed
/*! \ingroup XAstroPack
\brief Given a coordinate type "typ", convert to standard for astropack
\verbatim
// Return : 0 = OK
cmv's avatar
cmv committed
//          1 = Unknown type of coordinates
//          2 = bad range for coord1
//          4 = bad range for coord2
//          6 = bad range for coord1 et coord2
\endverbatim
*/
int  CoordConvertToStd(TypAstroCoord typ,double& coord1,double& coord2)
{
  int rc = 0;

  // ---- Equatoriales alpha,delta
  //    - standard = [0,24[ , [-90,90]
  if(typ&TypCoordEq) {
    if(typ&TypCoordDD) {
      coord1 = deghr(coord1);
    } else if(typ&TypCoordRR) {
      coord1 = radhr(coord1);
      coord2 = raddeg(coord2);
    }
    if(coord1==24.) coord1 = 0.;
    if(coord1<0.   || coord1>=24.) rc+= 2;
    if(coord2<-90. || coord2>90. ) rc+= 4;

  // ---- Galactiques gLong, gLat
  // ---- Horizontales azimuth,altitude
  // ---- Ecliptiques EclLong,EclLat
  //    - standard = [0,360[ , [-90,90]
  } else if( typ&TypCoordGal || typ&TypCoordHor || typ&TypCoordEcl) {
    if(typ&TypCoordHD) {
      coord1 = hrdeg(coord1);
    } else if(typ&TypCoordRR) {
      coord1 = raddeg(coord1);
      coord2 = raddeg(coord2);
    }
    if(coord1==360.) coord1 = 0.;
    if(coord1<0.   || coord1>=360.) rc+= 2;
    if(coord2<-90. || coord2>90. )  rc+= 4;

  } else {          // Coordonnees non-connues
    rc= 1;
  }

  return rc;
}