/* converts from polar coordinates of ecliptic of date
 *          to   cartesian coordinates of equator 2000
 * tjd		date
 * x 		array of position
 */
static void ecldat_equ2000(double tjd, double *xpm) {
  /* cartesian */
  swi_polcart(xpm, xpm);
  /* equatorial */
  swi_coortrf2(xpm, xpm, -swed.oec.seps, swed.oec.ceps);
  /* j2000 */
  swi_precess(xpm, tjd, J_TO_J2000);/**/
}
Exemple #2
0
/* computes a planet from osculating elements *
 * tjd		julian day
 * ipl		body number
 * ipli 	body number in planetary data structure
 * iflag	flags
 */
int swi_osc_el_plan(double tjd, double *xp, int ipl, int ipli, double *xearth, double *xsun, char *serr)
{
  double pqr[9], x[6];
  double eps, K, fac, rho, cose, sine;
  double alpha, beta, zeta, sigma, M2, Msgn, M_180_or_0;
  double tjd0, tequ, mano, sema, ecce, parg, node, incl, dmot;
  double cosnode, sinnode, cosincl, sinincl, cosparg, sinparg;
  double M, E;
  struct plan_data *pedp = &swed.pldat[SEI_EARTH];
  struct plan_data *pdp = &swed.pldat[ipli];
  int32 fict_ifl = 0;
  int i;
  /* orbital elements, either from file or, if file not found,
   * from above built-in set  
   */
  if (read_elements_file(ipl, tjd, &tjd0, &tequ, 
       &mano, &sema, &ecce, &parg, &node, &incl, 
       NULL, &fict_ifl, serr) == ERR)
    return ERR;
  dmot = 0.9856076686 * DEGTORAD / sema / sqrt(sema);	/* daily motion */
  if (fict_ifl & FICT_GEO)
    dmot /= sqrt(SUN_EARTH_MRAT);
  cosnode = cos(node);
  sinnode = sin(node);
  cosincl = cos(incl);
  sinincl = sin(incl); 
  cosparg = cos(parg);
  sinparg = sin(parg);
  /* Gaussian vector */
  pqr[0] = cosparg * cosnode - sinparg * cosincl * sinnode;
  pqr[1] = -sinparg * cosnode - cosparg * cosincl * sinnode;
  pqr[2] = sinincl * sinnode;
  pqr[3] = cosparg * sinnode + sinparg * cosincl * cosnode;
  pqr[4] = -sinparg * sinnode + cosparg * cosincl * cosnode;
  pqr[5] = -sinincl * cosnode;
  pqr[6] = sinparg * sinincl;
  pqr[7] = cosparg * sinincl;
  pqr[8] = cosincl;
  /* Kepler problem */
  E = M = swi_mod2PI(mano + (tjd - tjd0) * dmot); /* mean anomaly of date */
  /* better E for very high eccentricity and small M */
  if (ecce > 0.975) {
    M2 = M * RADTODEG;
    if (M2 > 150 && M2 < 210) {
      M2 -= 180;
      M_180_or_0 = 180;
    } else
      M_180_or_0 = 0;
    if (M2 > 330) 
      M2 -= 360;
    if (M2 < 0) {
      M2 = -M2;
      Msgn = -1;
    } else
      Msgn = 1;
    if (M2 < 30) {
      M2 *= DEGTORAD;
      alpha = (1 - ecce) / (4 * ecce + 0.5);
      beta = M2 / (8 * ecce + 1);
      zeta = pow(beta + sqrt(beta * beta + alpha * alpha), 1/3);
      sigma = zeta - alpha / 2;
      sigma = sigma - 0.078 * sigma * sigma * sigma * sigma * sigma / (1 + ecce);
      E = Msgn * (M2 + ecce * (3 * sigma - 4 * sigma * sigma * sigma))
			+ M_180_or_0;
    }
  }
  E = swi_kepler(E, M, ecce);
  /* position and speed, referred to orbital plane */
  if (fict_ifl & FICT_GEO)
    K = KGAUSS_GEO / sqrt(sema);
  else
    K = KGAUSS / sqrt(sema);
  cose = cos(E);
  sine = sin(E);
  fac = sqrt((1 - ecce) * (1 + ecce));
  rho = 1 - ecce * cose;
  x[0] = sema * (cose - ecce);
  x[1] = sema * fac * sine;
  x[3] = -K * sine / rho;
  x[4] = K * fac * cose / rho;
  /* transformation to ecliptic */
  xp[0] = pqr[0] * x[0] + pqr[1] * x[1];
  xp[1] = pqr[3] * x[0] + pqr[4] * x[1];
  xp[2] = pqr[6] * x[0] + pqr[7] * x[1];
  xp[3] = pqr[0] * x[3] + pqr[1] * x[4];
  xp[4] = pqr[3] * x[3] + pqr[4] * x[4];
  xp[5] = pqr[6] * x[3] + pqr[7] * x[4];
  /* transformation to equator */
  eps = swi_epsiln(tequ);
  swi_coortrf(xp, xp, -eps);
  swi_coortrf(xp+3, xp+3, -eps);
  /* precess to J2000 */
  if (tequ != J2000) {
    swi_precess(xp, tequ, J_TO_J2000);
    swi_precess(xp+3, tequ, J_TO_J2000);
  }
  /* to solar system barycentre */
  if (fict_ifl & FICT_GEO) {
    for (i = 0; i <= 5; i++) {
      xp[i] += xearth[i];
    }
  } else {
	for (i = 0; i <= 5; i++) {
	  xp[i] += xsun[i];
	}
  }
  if (pdp->x == xp) {
    pdp->teval = tjd;	/* for precession! */
    pdp->iephe = pedp->iephe;
  }
  return OK;
}
Exemple #3
0
/* Adjust position from Earth-Moon barycenter to Earth
 *
 * J = Julian day number
 * xemb = rectangular equatorial coordinates of Earth
 */
static void embofs_mosh(double tjd, double *xemb) 
{
  double T, M, a, L, B, p;
  double smp, cmp, s2mp, c2mp, s2d, c2d, sf, cf;
  double s2f, sx, cx, xyz[6];
  double seps = swed.oec.seps;
  double ceps = swed.oec.ceps;
  int i;
  /* Short series for position of the Moon
   */
  T = (tjd-J1900)/36525.0;
  /* Mean anomaly of moon (MP) */
  a = swe_degnorm(((1.44e-5*T + 0.009192)*T + 477198.8491)*T + 296.104608);
  a *= DEGTORAD;
  smp = sin(a);
  cmp = cos(a);
  s2mp = 2.0*smp*cmp;		/* sin(2MP) */
  c2mp = cmp*cmp - smp*smp;	/* cos(2MP) */
  /* Mean elongation of moon (D) */
  a = swe_degnorm(((1.9e-6*T - 0.001436)*T + 445267.1142)*T + 350.737486);
  a  = 2.0 * DEGTORAD * a;
  s2d = sin(a);
  c2d = cos(a);
  /* Mean distance of moon from its ascending node (F) */
  a = swe_degnorm((( -3.e-7*T - 0.003211)*T + 483202.0251)*T + 11.250889);
  a  *= DEGTORAD;
  sf = sin(a);
  cf = cos(a);
  s2f = 2.0*sf*cf;	/* sin(2F) */
  sx = s2d*cmp - c2d*smp;	/* sin(2D - MP) */
  cx = c2d*cmp + s2d*smp;	/* cos(2D - MP) */
  /* Mean longitude of moon (LP) */
  L = ((1.9e-6*T - 0.001133)*T + 481267.8831)*T + 270.434164;
  /* Mean anomaly of sun (M) */
  M = swe_degnorm((( -3.3e-6*T - 1.50e-4)*T + 35999.0498)*T + 358.475833);
  /* Ecliptic longitude of the moon */
  L =	L
	+ 6.288750*smp
	+ 1.274018*sx
	+ 0.658309*s2d
	+ 0.213616*s2mp
	- 0.185596*sin( DEGTORAD * M )
	- 0.114336*s2f;
  /* Ecliptic latitude of the moon */
  a = smp*cf;
  sx = cmp*sf;
  B =	  5.128189*sf
	+ 0.280606*(a+sx)		/* sin(MP+F) */
	+ 0.277693*(a-sx)		/* sin(MP-F) */
	+ 0.173238*(s2d*cf - c2d*sf);	/* sin(2D-F) */
  B *= DEGTORAD;
  /* Parallax of the moon */
  p =	 0.950724
	+0.051818*cmp
	+0.009531*cx
	+0.007843*c2d
	+0.002824*c2mp;
  p *= DEGTORAD;
  /* Elongation of Moon from Sun
   */
  L = swe_degnorm(L);
  L *= DEGTORAD;
  /* Distance in au */
  a = 4.263523e-5/sin(p);
  /* Convert to rectangular ecliptic coordinates */
  xyz[0] = L;
  xyz[1] = B;
  xyz[2] = a;
  swi_polcart(xyz, xyz);
  /* Convert to equatorial */
  swi_coortrf2(xyz, xyz, -seps, ceps);
  /* Precess to equinox of J2000.0 */
  swi_precess(xyz, tjd, J_TO_J2000);/**/
  /* now emb -> earth */
  for (i = 0; i <= 2; i++)
    xemb[i] -= xyz[i] / (EARTH_MOON_MRAT + 1.0);
}
Exemple #4
0
int swe_sx_nod_aps(double tjd_et, int ind, int iflag,
                   int  method,
                   double *xnasc, double *xndsc,
                   double *xperi, double *xaphe,
                   char *serr)
{
  int ij, i, j,ipl,fEquatorT,fUseJ2000T;
  int32 iplx;
  int32 ipli;
  int istart, iend;
  int32 iflJ2000;
  double plm;
  double t = (tjd_et - J2000) / 36525, dt;
  double x[6], xx[24], *xp, xobs[6], x2000[6];
  double xpos[3][6], xnorm[6];
  double xposm[6];
  double xn[3][6], xs[3][6];
  double xq[3][6], xa[3][6];
  double xobs2[6], x2[6];
  double *xna, *xnd, *xpe, *xap;
  double incl, sema, ecce, parg, ea, vincl, vsema, vecce, pargx, eax;
  struct plan_data *pedp = &swed.pldat[SEI_EARTH];
  struct plan_data *psbdp = &swed.pldat[SEI_SUNBARY];
  struct plan_data pldat;
  double *xsun = psbdp->x;
  double *xear = pedp->x;
  double *ep;
  double Gmsm, dzmin;
  double rxy, rxyz, fac, sgn;
  double sinnode, cosnode, sinincl, cosincl, sinu, cosu, sinE, cosE, cosE2;
  double uu, ny, ny2, c2, v2, pp, ro, ro2, rn, rn2;
  struct epsilon *oe;
  AS_BOOL is_true_nodaps = FALSE;
  AS_BOOL do_aberr = !(iflag & (SEFLG_TRUEPOS | SEFLG_NOABERR));
  AS_BOOL do_defl = !(iflag & SEFLG_TRUEPOS) && !(iflag & SEFLG_NOGDEFL);
  AS_BOOL do_focal_point = method & SE_NODBIT_FOPOINT;
  AS_BOOL ellipse_is_bary = FALSE;
  int32 iflg0;
  /* function calls for Pluto with asteroid number 134340
   * are treated as calls for Pluto as main body SE_PLUTO */
  ipl = AlToSweObj(ind);
  if (ipl == SE_WHITE_MOON)
    ipl = SE_AST_OFFSET+MaxNumberedAsteroid;
  if (ipl == SE_AST_OFFSET + 134340)
    ipl = SE_PLUTO;
  xna = xx;
  xnd = xx+6;
  xpe = xx+12;
  xap = xx+18;
  xpos[0][0] = 0; /* to shut up mint */
  /* to get control over the save area: */
  swi_force_app_pos_etc();
  method %= SE_NODBIT_FOPOINT;
  ipli = ipl;
  if (ipl == SE_SUN)
    ipli = SE_EARTH;
  if (ipl == SE_MOON)
    {
      do_defl = FALSE;
      if (!(iflag & SEFLG_HELCTR))
        do_aberr = FALSE;
    }
  iflg0 = (iflag & (SEFLG_EPHMASK|SEFLG_NONUT)) | SEFLG_SPEED | SEFLG_TRUEPOS;
  if (ipli != SE_MOON)
    iflg0 |= SEFLG_HELCTR;
  if (ipl == SE_MEAN_NODE || ipl == SE_TRUE_NODE ||
      ipl == SE_MEAN_APOG || ipl == SE_OSCU_APOG ||
      ipl < 0 ||
      (ipl >= SE_NPLANETS && ipl <= SE_AST_OFFSET))
    {
      /*(ipl >= SE_FICT_OFFSET && ipl - SE_FICT_OFFSET < SE_NFICT_ELEM)) */
      if (serr != NULL)
        sprintf(serr, "nodes/apsides for planet %5.0f are not implemented", (double) ipl);
      if (xnasc != NULL)
        for (i = 0; i <= 5; i++)
          xnasc[i] = 0;
      if (xndsc != NULL)
        for (i = 0; i <= 5; i++)
          xndsc[i] = 0;
      if (xaphe != NULL)
        for (i = 0; i <= 5; i++)
          xaphe[i] = 0;
      if (xperi != NULL)
        for (i = 0; i <= 5; i++)
          xperi[i] = 0;
      return ERR;
    }
  for (i = 0; i < 24; i++)
    xx[i] = 0;
  /***************************************
   * mean nodes and apsides
   ***************************************/
  /* mean points only for Sun - Neptune */
  if ((method == 0 || (method & SE_NODBIT_MEAN)) &&
      ((ipl >= SE_SUN && ipl <= SE_NEPTUNE) || ipl == SE_EARTH))
    {
      if (ipl == SE_MOON)
        {
          swi_mean_lunar_elements(tjd_et, &xna[0], &xna[3], &xpe[0], &xpe[3]);
          incl = MOON_MEAN_INCL;
          vincl = 0;
          ecce = MOON_MEAN_ECC;
          vecce = 0;
          sema = MOON_MEAN_DIST / AUNIT;
          vsema = 0;
        }
      else
        {
          iplx = ipl_to_elem[ipl];
          ep = el_incl[iplx];
          incl = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
          vincl = ep[1] / 36525;
          ep = el_sema[iplx];
          sema = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
          vsema = ep[1] / 36525;
          ep = el_ecce[iplx];
          ecce = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
          vecce = ep[1] / 36525;
          ep = el_node[iplx];
          /* ascending node */
          xna[0] = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
          xna[3] = ep[1] / 36525;
          /* perihelion */
          ep = el_peri[iplx];
          xpe[0] = ep[0] + ep[1] * t + ep[2] * t * t + ep[3] * t * t * t;
          xpe[3] = ep[1] / 36525;
        }
      /* descending node */
      xnd[0] = swe_degnorm(xna[0] + 180);
      xnd[3] = xna[3];
      /* angular distance of perihelion from node */
      parg = xpe[0] = swe_degnorm(xpe[0] - xna[0]);
      pargx = xpe[3] = swe_degnorm(xpe[0] + xpe[3]  - xna[3]);
      /* transform from orbital plane to mean ecliptic of date */
      swe_cotrans(xpe, xpe, -incl);
      /* xpe+3 is aux. position, not speed!!! */
      swe_cotrans(xpe+3, xpe+3, -incl-vincl);
      /* add node again */
      xpe[0] = swe_degnorm(xpe[0] + xna[0]);
      /* xpe+3 is aux. position, not speed!!! */
      xpe[3] = swe_degnorm(xpe[3] + xna[0] + xna[3]);
      /* speed */
      xpe[3] = swe_degnorm(xpe[3] - xpe[0]);
      /* heliocentric distance of perihelion and aphelion */
      xpe[2] = sema * (1 - ecce);
      xpe[5] = (sema + vsema) * (1 - ecce - vecce) - xpe[2];
      /* aphelion */
      xap[0] = swe_degnorm(xpe[0] + 180);
      xap[1] = -xpe[1];
      xap[3] = xpe[3];
      xap[4] = -xpe[4];
      if (do_focal_point)
        {
          xap[2] = sema * ecce * 2;
          xap[5] = (sema + vsema) * (ecce + vecce) * 2 - xap[2];
        }
      else
        {
          xap[2] = sema * (1 + ecce);
          xap[5] = (sema + vsema) * (1 + ecce + vecce) - xap[2];
        }
      /* heliocentric distance of nodes */
      ea = atan(tan(-parg * DEGTORAD / 2) * sqrt((1-ecce)/(1+ecce))) * 2;
      eax = atan(tan(-pargx * DEGTORAD / 2) * sqrt((1-ecce-vecce)/(1+ecce+vecce))) * 2;
      xna[2] = sema * (cos(ea) - ecce) / cos(parg * DEGTORAD);
      xna[5] = (sema+vsema) * (cos(eax) - ecce - vecce) / cos(pargx * DEGTORAD);
      xna[5] -= xna[2];
      ea = atan(tan((180 - parg) * DEGTORAD / 2) * sqrt((1-ecce)/(1+ecce))) * 2;
      eax = atan(tan((180 - pargx) * DEGTORAD / 2) * sqrt((1-ecce-vecce)/(1+ecce+vecce))) * 2;
      xnd[2] = sema * (cos(ea) - ecce) / cos((180 - parg) * DEGTORAD);
      xnd[5] = (sema+vsema) * (cos(eax) - ecce - vecce) / cos((180 - pargx) * DEGTORAD);
      xnd[5] -= xnd[2];
      /* no light-time correction because speed is extremely small */
      for (i = 0, xp = xx; i < 4; i++, xp += 6)
        {
          /* to cartesian coordinates */
          xp[0] *= DEGTORAD;
          xp[1] *= DEGTORAD;
          xp[3] *= DEGTORAD;
          xp[4] *= DEGTORAD;
          swi_polcart_sp(xp, xp);
        }
      /***************************************
       * "true" or osculating nodes and apsides
       ***************************************/
    } else {
      /* first, we need a heliocentric distance of the planet */
      if (swe_calc(tjd_et, ipli, iflg0, x, serr) == ERR)
        {
          if (FRiyalNumbered(tjd_et,ind,fTrue))
            {
              x[0]=planet[ind];
              x[1]=planetalt[ind];
              x[2]=planetdis[ind];
              x[3]=ret[ind];
              x[4]=altret[ind];
              x[5]=disret[ind];
            }
          else return ERR;
        }
      iflJ2000 = (iflag & SEFLG_EPHMASK)|SEFLG_J2000|SEFLG_EQUATORIAL|SEFLG_XYZ|SEFLG_TRUEPOS|SEFLG_NONUT|SEFLG_SPEED;
      ellipse_is_bary = FALSE;
      if (ipli != SE_MOON)
        {
          if ((method & SE_NODBIT_OSCU_BAR) && x[2] > 6)
            {
              iflJ2000 |= SEFLG_BARYCTR; /* only planets beyond Jupiter */
              ellipse_is_bary = TRUE;
            }
          else
            {
              iflJ2000 |= SEFLG_HELCTR;
            }
        }
      /* we need three positions and three speeds
       * for three nodes/apsides. from the three node positions,
       * the speed of the node will be computed. */
      if (ipli == SE_MOON)
        {
          dt = NODE_CALC_INTV;
          dzmin = 1e-15;
          Gmsm = GEOGCONST * (1 + 1 / EARTH_MOON_MRAT) /AUNIT/AUNIT/AUNIT*86400.0*86400.0;
        }
      else
        {
          if ((ipli >= SE_MERCURY && ipli <= SE_PLUTO) || ipli == SE_EARTH)
            plm = 1 / plmass[ipl_to_elem[ipl]];
          else
            plm = 0;
          dt = NODE_CALC_INTV * 10 * x[2];
          dzmin = 1e-15 * dt / NODE_CALC_INTV;
          Gmsm = HELGRAVCONST * (1 + plm) /AUNIT/AUNIT/AUNIT*86400.0*86400.0;
        }
      if (iflag & SEFLG_SPEED)
        {
          istart = 0;
          iend = 2;
        }
      else
        {
          istart = iend = 0;
          dt = 0;
        }
      for (i = istart, t = tjd_et - dt; i <= iend; i++, t += dt)
        {
          if (istart == iend)
            t = tjd_et;
          if (swe_calc(t, ipli, iflJ2000, xpos[i], serr) == ERR)
            {
              fUseJ2000T=fUseJ2000;
              fEquatorT=us.fEquator;
              fUseJ2000=fTrue;
              us.fEquator=fTrue;
              if (FRiyalNumbered(t,ind,fTrue))
                {
                  xpos[i][0]=spacex[ind];
                  xpos[i][1]=spacey[ind];
                  xpos[i][2]=spacez[ind];
                  xpos[i][3]=spacedx[ind];
                  xpos[i][4]=spacedy[ind];
                  xpos[i][5]=spacedz[ind];
              fUseJ2000=fUseJ2000T;
              us.fEquator=fEquatorT;
                }
              else return ERR;
            }
          /* the EMB is used instead of the earth */
          if (ipli == SE_EARTH)
            {
              if (swe_calc(t, SE_MOON, iflJ2000 & ~(SEFLG_BARYCTR|SEFLG_HELCTR), xposm, serr) == ERR)
                return ERR;
              for (j = 0; j <= 2; j++)
                xpos[i][j] += xposm[j] / (EARTH_MOON_MRAT + 1.0);
            }
          swi_plan_for_osc_elem(iflg0, t, xpos[i]);
        }
      for (i = istart; i <= iend; i++)
        {
          if (fabs(xpos[i][5]) < dzmin)
            xpos[i][5] = dzmin;
          fac = xpos[i][2] / xpos[i][5];
          sgn = xpos[i][5] / fabs(xpos[i][5]);
          for (j = 0; j <= 2; j++)
            {
              xn[i][j] = (xpos[i][j] - fac * xpos[i][j+3]) * sgn;
              xs[i][j] = -xn[i][j];
            }
        }
      for (i = istart; i <= iend; i++)
        {
          /* node */
          rxy =  sqrt(xn[i][0] * xn[i][0] + xn[i][1] * xn[i][1]);
          cosnode = xn[i][0] / rxy;
          sinnode = xn[i][1] / rxy;
          /* inclination */
          swi_cross_prod(xpos[i], xpos[i]+3, xnorm);
          rxy =  xnorm[0] * xnorm[0] + xnorm[1] * xnorm[1];
          c2 = (rxy + xnorm[2] * xnorm[2]);
          rxyz = sqrt(c2);
          rxy = sqrt(rxy);
          sinincl = rxy / rxyz;
          cosincl = sqrt(1 - sinincl * sinincl);
          if (xnorm[2] < 0) cosincl = -cosincl; /* retrograde asteroid, e.g. 20461 Dioretsa */
          /* argument of latitude */
          cosu = xpos[i][0] * cosnode + xpos[i][1] * sinnode;
          sinu = xpos[i][2] / sinincl;
          uu = atan2(sinu, cosu);
          /* semi-axis */
          rxyz = sqrt(square_sum(xpos[i]));
          v2 = square_sum((xpos[i]+3));
          sema = 1 / (2 / rxyz - v2 / Gmsm);
          /* eccentricity */
          pp = c2 / Gmsm;
          ecce = sqrt(1 - pp / sema);
          /* eccentric anomaly */
          cosE = 1 / ecce * (1 - rxyz / sema);
          sinE = 1 / ecce / sqrt(sema * Gmsm) * dot_prod(xpos[i], (xpos[i]+3));
          /* true anomaly */
          ny = 2 * atan(sqrt((1+ecce)/(1-ecce)) * sinE / (1 + cosE));
          /* distance of perihelion from ascending node */
          xq[i][0] = swi_mod2PI(uu - ny);
          xq[i][1] = 0;			/* latitude */
          xq[i][2] = sema * (1 - ecce);	/* distance of perihelion */
          /* transformation to ecliptic coordinates */
          swi_polcart(xq[i], xq[i]);
          swi_coortrf2(xq[i], xq[i], -sinincl, cosincl);
          swi_cartpol(xq[i], xq[i]);
          /* adding node, we get perihelion in ecl. coord. */
          xq[i][0] += atan2(sinnode, cosnode);
          xa[i][0] = swi_mod2PI(xq[i][0] + PI);
          xa[i][1] = -xq[i][1];
          if (do_focal_point)
            {
              xa[i][2] = sema * ecce * 2;	/* distance of aphelion */
            }
          else
            {
              xa[i][2] = sema * (1 + ecce);	/* distance of aphelion */
            }
          swi_polcart(xq[i], xq[i]);
          swi_polcart(xa[i], xa[i]);
          /* new distance of node from orbital ellipse:
           * true anomaly of node: */
          ny = swi_mod2PI(ny - uu);
          ny2 = swi_mod2PI(ny + PI);
          /* eccentric anomaly */
          cosE = cos(2 * atan(tan(ny / 2) / sqrt((1+ecce) / (1-ecce))));
          cosE2 = cos(2 * atan(tan(ny2 / 2) / sqrt((1+ecce) / (1-ecce))));
          /* new distance */
          rn = sema * (1 - ecce * cosE);
          rn2 = sema * (1 - ecce * cosE2);
          /* old node distance */
          ro = sqrt(square_sum(xn[i]));
          ro2 = sqrt(square_sum(xs[i]));
          /* correct length of position vector */
          for (j = 0; j <= 2; j++)
            {
              xn[i][j] *= rn / ro;
              xs[i][j] *= rn2 / ro2;
            }
        }
      for (i = 0; i <= 2; i++)
        {
          if (iflag & SEFLG_SPEED)
            {
              xpe[i] = xq[1][i];
              xpe[i+3] = (xq[2][i] - xq[0][i]) / dt / 2;
              xap[i] = xa[1][i];
              xap[i+3] = (xa[2][i] - xa[0][i]) / dt / 2;
              xna[i] = xn[1][i];
              xna[i+3] = (xn[2][i] - xn[0][i]) / dt / 2;
              xnd[i] = xs[1][i];
              xnd[i+3] = (xs[2][i] - xs[0][i]) / dt / 2;
            }
          else
            {
              xpe[i] = xq[0][i];
              xpe[i+3] = 0;
              xap[i] = xa[0][i];
              xap[i+3] = 0;
              xna[i] = xn[0][i];
              xna[i+3] = 0;
              xnd[i] = xs[0][i];
              xnd[i+3] = 0;
            }
        }
      is_true_nodaps = TRUE;
    }
  /* to set the variables required in the save area,
   * i.e. ecliptic, nutation, barycentric sun, earth
   * we compute the planet */
  if (ipli == SE_MOON && (iflag & (SEFLG_HELCTR | SEFLG_BARYCTR)))
    {
      swi_force_app_pos_etc();
      if (swe_calc(tjd_et, SE_SUN, iflg0, x, serr) == ERR)
        return ERR;
      } else {
          if (swe_calc(tjd_et, ipli, iflg0 | (iflag & SEFLG_TOPOCTR), x, serr) == ERR)
            {
              if (FRiyalNumbered(tjd_et,ind,iflg0 && SEFLG_HELCTR))
                {
                  x[0]=planet[ind];
                  x[1]=planetalt[ind];
                  x[2]=planetdis[ind];
                  x[3]=ret[ind];
                  x[4]=altret[ind];
                  x[5]=disret[ind];
                }
              else return ERR;
            }
            }
          /***********************
           * position of observer
           ***********************/
          if (iflag & SEFLG_TOPOCTR)
            {
              /* geocentric position of observer */
              if (swi_get_observer(tjd_et, iflag, FALSE, xobs, serr) != OK)
                return ERR;
              /*for (i = 0; i <= 5; i++)
                xobs[i] = swed.topd.xobs[i];*/
            }
          else
            {
              for (i = 0; i <= 5; i++)
                xobs[i] = 0;
            }
          if (iflag & (SEFLG_HELCTR | SEFLG_BARYCTR))
            {
              if ((iflag & SEFLG_HELCTR) && !(iflag & SEFLG_MOSEPH))
                for (i = 0; i <= 5; i++)
                  xobs[i] = xsun[i];
            }
          else if (ipl == SE_SUN && !(iflag & SEFLG_MOSEPH))
            {
              for (i = 0; i <= 5; i++)
                xobs[i] = xsun[i];
            }
          else
            {
              /* barycentric position of observer */
              for (i = 0; i <= 5; i++)
                xobs[i] += xear[i];
            }
          /* ecliptic obliqity */
          if (iflag & SEFLG_J2000)
            oe = &swed.oec2000;
          else
            oe = &swed.oec;
          /*************************************************
           * conversions shared by mean and osculating points
           *************************************************/
          for (ij = 0, xp = xx; ij < 4; ij++, xp += 6)
            {
              /* no nodes for earth */
              if (ipli == SE_EARTH && ij <= 1)
                {
                  for (i = 0; i <= 5; i++)
                    xp[i] = 0;
                  continue;
                }
              /*********************
               * to equator
               *********************/
              if (is_true_nodaps && !(iflag & SEFLG_NONUT))
                {
                  swi_coortrf2(xp, xp, -swed.nut.snut, swed.nut.cnut);
                  if (iflag & SEFLG_SPEED)
                    swi_coortrf2(xp+3, xp+3, -swed.nut.snut, swed.nut.cnut);
                }
              swi_coortrf2(xp, xp, -oe->seps, oe->ceps);
              swi_coortrf2(xp+3, xp+3, -oe->seps, oe->ceps);
              if (is_true_nodaps)
                {
                  /****************************
                   * to mean ecliptic of date
                   ****************************/
                  if (!(iflag & SEFLG_NONUT))
                    swi_nutate(xp, iflag, TRUE);
                }
              /*********************
               * to J2000
               *********************/
              swi_precess(xp, tjd_et, J_TO_J2000);
              if (iflag & SEFLG_SPEED)
                swi_precess_speed(xp, tjd_et, J_TO_J2000);
              /*********************
               * to barycenter
               *********************/
              if (ipli == SE_MOON)
                {
                  for (i = 0; i <= 5; i++)
                    xp[i] += xear[i];
                }
              else
                {
                  if (!(iflag & SEFLG_MOSEPH) && !ellipse_is_bary)
                    for (j = 0; j <= 5; j++)
                      xp[j] += xsun[j];
                }
              /*********************
               * to correct center
               *********************/
              for (j = 0; j <= 5; j++)
                xp[j] -= xobs[j];
              /* geocentric perigee/apogee of sun */
              if (ipl == SE_SUN && !(iflag & (SEFLG_HELCTR | SEFLG_BARYCTR)))
                for (j = 0; j <= 5; j++)
                  xp[j] = -xp[j];
              /*********************
               * light deflection
               *********************/
              dt = sqrt(square_sum(xp)) * AUNIT / CLIGHT / 86400.0;
              if (do_defl)
                swi_deflect_light(xp, dt, iflag);
              /*********************
               * aberration
               *********************/
              if (do_aberr)
                {
                  swi_aberr_light(xp, xobs, iflag);
                  /*
                   * Apparent speed is also influenced by
                   * the difference of speed of the earth between t and t-dt.
                   * Neglecting this would result in an error of several 0.1"
                   */
                  if (iflag & SEFLG_SPEED)
                    {
                      /* get barycentric sun and earth for t-dt into save area */
                      if (swe_calc(tjd_et - dt, ipli, iflg0 | (iflag & SEFLG_TOPOCTR), x2, serr) == ERR)
        {
          if (FRiyalNumbered(tjd_et-dt,ind,iflg0 && SEFLG_HELCTR))
            {
              x2[0]=planet[ind];
              x2[1]=planetalt[ind];
              x2[2]=planetdis[ind];
              x2[3]=ret[ind];
              x2[4]=altret[ind];
              x2[5]=disret[ind];
            }
          else return ERR;
        }
                      if (iflag & SEFLG_TOPOCTR)
                        {
                          /* geocentric position of observer */
                          /* if (swi_get_observer(tjd_et - dt, iflag, FALSE, xobs, serr) != OK)
                            return ERR;*/
                          for (i = 0; i <= 5; i++)
                            xobs2[i] = swed.topd.xobs[i];
                        }
                      else
                        {
                          for (i = 0; i <= 5; i++)
                            xobs2[i] = 0;
                        }
                      if (iflag & (SEFLG_HELCTR | SEFLG_BARYCTR))
                        {
                          if ((iflag & SEFLG_HELCTR) && !(iflag & SEFLG_MOSEPH))
                            for (i = 0; i <= 5; i++)
                              xobs2[i] = xsun[i];
                        }
                      else if (ipl == SE_SUN && !(iflag & SEFLG_MOSEPH))
                        {
                          for (i = 0; i <= 5; i++)
                            xobs2[i] = xsun[i];
                        }
                      else
                        {
                          /* barycentric position of observer */
                          for (i = 0; i <= 5; i++)
                            xobs2[i] += xear[i];
                        }
                      for (i = 3; i <= 5; i++)
                        xp[i] += xobs[i] - xobs2[i];
                      /* The above call of swe_calc() has destroyed the
                       * parts of the save area
                       * (i.e. bary sun, earth nutation matrix!).
                       * to restore it:
                       */
                      if (swe_calc(tjd_et, SE_SUN, iflg0 | (iflag & SEFLG_TOPOCTR), x2, serr) == ERR)
                        return ERR;
                    }
                }
              /*********************
               * precession
               *********************/
              /* save J2000 coordinates; required for sidereal positions */
              for (j = 0; j <= 5; j++)
                x2000[j] = xp[j];
              if (!(iflag & SEFLG_J2000))
                {
                  swi_precess(xp, tjd_et, J2000_TO_J);
                  if (iflag & SEFLG_SPEED)
                    swi_precess_speed(xp, tjd_et, J2000_TO_J);
                }
              /*********************
               * nutation
               *********************/
              if (!(iflag & SEFLG_NONUT))
                swi_nutate(xp, iflag, FALSE);
              /* now we have equatorial cartesian coordinates; keep them */
              for (j = 0; j <= 5; j++)
                pldat.xreturn[18+j] = xp[j];
              /************************************************
               * transformation to ecliptic.                  *
               * with sidereal calc. this will be overwritten *
               * afterwards.                                  *
               ************************************************/
              swi_coortrf2(xp, xp, oe->seps, oe->ceps);
              if (iflag & SEFLG_SPEED)
                swi_coortrf2(xp+3, xp+3, oe->seps, oe->ceps);
              if (!(iflag & SEFLG_NONUT))
                {
                  swi_coortrf2(xp, xp, swed.nut.snut, swed.nut.cnut);
                  if (iflag & SEFLG_SPEED)
                    swi_coortrf2(xp+3, xp+3, swed.nut.snut, swed.nut.cnut);
                }
              /* now we have ecliptic cartesian coordinates */
              for (j = 0; j <= 5; j++)
                pldat.xreturn[6+j] = xp[j];
              /************************************
               * sidereal positions               *
               ************************************/
              if (iflag & SEFLG_SIDEREAL)
                {
                  /* project onto ecliptic t0 */
                  if (swed.sidd.sid_mode & SE_SIDBIT_ECL_T0)
                    {
                      if (swi_trop_ra2sid_lon(x2000, pldat.xreturn+6, pldat.xreturn+18, iflag, serr) != OK)
                        return ERR;
                      /* project onto solar system equator */
                    }
                  else if (swed.sidd.sid_mode & SE_SIDBIT_SSY_PLANE)
                    {
                      if (swi_trop_ra2sid_lon_sosy(x2000, pldat.xreturn+6, pldat.xreturn+18, iflag, serr) != OK)
                        return ERR;
                    }
                  else
                    {
                      /* traditional algorithm */
                      swi_cartpol_sp(pldat.xreturn+6, pldat.xreturn);
                      pldat.xreturn[0] -= swe_get_ayanamsa(tjd_et) * DEGTORAD;
                      swi_polcart_sp(pldat.xreturn, pldat.xreturn+6);
                    }
                }
              if ((iflag & SEFLG_XYZ) && (iflag & SEFLG_EQUATORIAL))
                {
                  for (j = 0; j <= 5; j++)
                    xp[j] = pldat.xreturn[18+j];
                  continue;
                }
              if (iflag & SEFLG_XYZ)
                {
                  for (j = 0; j <= 5; j++)
                    xp[j] = pldat.xreturn[6+j];
                  continue;
                }
              /************************************************
               * transformation to polar coordinates          *
               ************************************************/
              swi_cartpol_sp(pldat.xreturn+18, pldat.xreturn+12);
              swi_cartpol_sp(pldat.xreturn+6, pldat.xreturn);
              /**********************
               * radians to degrees *
               **********************/
              for (j = 0; j < 2; j++)
                {
                  pldat.xreturn[j] *= RADTODEG;		/* ecliptic */
                  pldat.xreturn[j+3] *= RADTODEG;
                  pldat.xreturn[j+12] *= RADTODEG;	/* equator */
                  pldat.xreturn[j+15] *= RADTODEG;
                }
              if (iflag & SEFLG_EQUATORIAL)
                {
                  for (j = 0; j <= 5; j++)
                    xp[j] = pldat.xreturn[12+j];
                  continue;
                }
              else
                {
                  for (j = 0; j <= 5; j++)
                    xp[j] = pldat.xreturn[j];
                  continue;
                }
            }
          for (i = 0; i <= 5; i++)
            {
              if (i > 2 && !(iflag & SEFLG_SPEED))
                xna[i] = xnd[i] = xpe[i] = xap[i] = 0;
              if (xnasc != NULL)
                xnasc[i] = xna[i];
              if (xndsc != NULL)
                xndsc[i] = xnd[i];
              if (xperi != NULL)
                xperi[i] = xpe[i];
              if (xaphe != NULL)
                xaphe[i] = xap[i];
            }
          return OK;
        }