Example #1
0
 public Int32 swe_nod_aps(double tjd_et, Int32 ipl, Int32 iflag,
                       Int32 method,
                       double[] xnasc, double[] xndsc,
                       double[] xperi, double[] xaphe,
                       ref string serr)
 {
     int ij, i, j;
     Int32 iplx;
     Int32 ipli;
     int istart, iend;
     Int32 iflJ2000;
     double plm;
     double t = (tjd_et - Sweph.J2000) / 36525, dt;
     double[] x = new double[6], xx = new double[24], xobs = new double[6], x2000 = new double[6];
     double[][] xpos = CreateArray<double>(3, 6); double[] xnorm = new double[6];
     double[] xposm = new double[6];
     double[][] xn = CreateArray<double>(3, 6), xs = CreateArray<double>(3, 6);
     double[][] xq = CreateArray<double>(3, 6), xa = CreateArray<double>(3, 6);
     double[] xobs2 = new double[6], x2 = new double[6];
     CPointer<double> xna, xnd, xpe, xap, xp;
     double incl, sema, ecce, parg, ea, vincl, vsema, vecce, pargx, eax;
     Sweph.plan_data pedp = SE.Sweph.swed.pldat[Sweph.SEI_EARTH];
     Sweph.plan_data psbdp = SE.Sweph.swed.pldat[Sweph.SEI_SUNBARY];
     Sweph.plan_data pldat = new Sweph.plan_data();
     CPointer<double> xsun = psbdp.x;
     CPointer<double> xear = pedp.x;
     CPointer<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;
     Sweph.epsilon oe;
     bool is_true_nodaps = false;
     bool do_aberr = 0 == (iflag & (SwissEph.SEFLG_TRUEPOS | SwissEph.SEFLG_NOABERR));
     bool do_defl = 0 == (iflag & SwissEph.SEFLG_TRUEPOS) && 0 == (iflag & SwissEph.SEFLG_NOGDEFL);
     bool do_focal_point = (method & SwissEph.SE_NODBIT_FOPOINT) != 0;
     bool ellipse_is_bary = false;
     Int32 iflg0;
     iflag &= ~(SwissEph.SEFLG_JPLHOR | SwissEph.SEFLG_JPLHOR_APPROX);
     /* function calls for Pluto with asteroid number 134340
      * are treated as calls for Pluto as main body SE_PLUTO */
     if (ipl == SwissEph.SE_AST_OFFSET + 134340)
         ipl = SwissEph.SE_PLUTO;
     xna = xx;
     xnd = xx.GetPointer(6);
     xpe = xx.GetPointer(12);
     xap = xx.GetPointer(18);
     xpos[0][0] = 0; /* to shut up mint */
     /* to get control over the save area: */
     SE.Sweph.swi_force_app_pos_etc();
     method %= SwissEph.SE_NODBIT_FOPOINT;
     ipli = ipl;
     if (ipl == SwissEph.SE_SUN)
         ipli = SwissEph.SE_EARTH;
     if (ipl == SwissEph.SE_MOON) {
         do_defl = false;
         if (0 == (iflag & SwissEph.SEFLG_HELCTR))
             do_aberr = false;
     }
     iflg0 = (iflag & (SEFLG_EPHMASK | SwissEph.SEFLG_NONUT)) | SwissEph.SEFLG_SPEED | SwissEph.SEFLG_TRUEPOS;
     if (ipli != SwissEph.SE_MOON)
         iflg0 |= SwissEph.SEFLG_HELCTR;
     if (ipl == SwissEph.SE_MEAN_NODE || ipl == SwissEph.SE_TRUE_NODE ||
         ipl == SwissEph.SE_MEAN_APOG || ipl == SwissEph.SE_OSCU_APOG ||
         ipl < 0 ||
         (ipl >= SwissEph.SE_NPLANETS && ipl <= SwissEph.SE_AST_OFFSET)) {
         /*(ipl >= SE_FICT_OFFSET && ipl - SE_FICT_OFFSET < SE_NFICT_ELEM)) */
         serr = C.sprintf("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 SwissEph.ERR;
     }
     for (i = 0; i < 24; i++)
         xx[i] = 0;
     /***************************************
      * mean nodes and apsides
      ***************************************/
     /* mean points only for Sun - Neptune */
     if ((method == 0 || (method & SwissEph.SE_NODBIT_MEAN) != 0) &&
           ((ipl >= SwissEph.SE_SUN && ipl <= SwissEph.SE_NEPTUNE) || ipl == SwissEph.SE_EARTH)) {
               if (ipl == SwissEph.SE_MOON) {
             double[] xdummy = new double[] { xna[0], xna[3], xpe[0], xpe[3] };
             SE.SwemMoon.swi_mean_lunar_elements(tjd_et, ref xdummy[0], ref xdummy[1], ref xdummy[2], ref xdummy[3]);
             xna[0] = xdummy[0]; xna[3] = xdummy[1]; xpe[0] = xdummy[2]; xpe[3] = xdummy[3];
             incl = Sweph.MOON_MEAN_INCL;
             vincl = 0;
             ecce = Sweph.MOON_MEAN_ECC;
             vecce = 0;
             sema = Sweph.MOON_MEAN_DIST / Sweph.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] = SE.swe_degnorm(xna[0] + 180);
         xnd[3] = xna[3];
         /* angular distance of perihelion from node */
         parg = xpe[0] = SE.swe_degnorm(xpe[0] - xna[0]);
         pargx = xpe[3] = SE.swe_degnorm(xpe[0] + xpe[3] - xna[3]);
         /* transform from orbital plane to mean ecliptic of date */
         SE.swe_cotrans(xpe, xpe, -incl);
         /* xpe+3 is aux. position, not speed!!! */
         SE.swe_cotrans(xpe + 3, xpe + 3, -incl - vincl);
         /* add node again */
         xpe[0] = SE.swe_degnorm(xpe[0] + xna[0]);
         /* xpe+3 is aux. position, not speed!!! */
         xpe[3] = SE.swe_degnorm(xpe[3] + xna[0] + xna[3]);
         /* speed */
         xpe[3] = SE.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] = SE.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 = Math.Atan(Math.Tan(-parg * SwissEph.DEGTORAD / 2) * Math.Sqrt((1 - ecce) / (1 + ecce))) * 2;
         eax = Math.Atan(Math.Tan(-pargx * SwissEph.DEGTORAD / 2) * Math.Sqrt((1 - ecce - vecce) / (1 + ecce + vecce))) * 2;
         xna[2] = sema * (Math.Cos(ea) - ecce) / Math.Cos(parg * SwissEph.DEGTORAD);
         xna[5] = (sema + vsema) * (Math.Cos(eax) - ecce - vecce) / Math.Cos(pargx * SwissEph.DEGTORAD);
         xna[5] -= xna[2];
         ea = Math.Atan(Math.Tan((180 - parg) * SwissEph.DEGTORAD / 2) * Math.Sqrt((1 - ecce) / (1 + ecce))) * 2;
         eax = Math.Atan(Math.Tan((180 - pargx) * SwissEph.DEGTORAD / 2) * Math.Sqrt((1 - ecce - vecce) / (1 + ecce + vecce))) * 2;
         xnd[2] = sema * (Math.Cos(ea) - ecce) / Math.Cos((180 - parg) * SwissEph.DEGTORAD);
         xnd[5] = (sema + vsema) * (Math.Cos(eax) - ecce - vecce) / Math.Cos((180 - pargx) * SwissEph.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] *= SwissEph.DEGTORAD;
             xp[1] *= SwissEph.DEGTORAD;
             xp[3] *= SwissEph.DEGTORAD;
             xp[4] *= SwissEph.DEGTORAD;
             SE.SwephLib.swi_polcart_sp(xp, xp);
         }
         /***************************************
          * "true" or osculating nodes and apsides
          ***************************************/
     } else {
         /* first, we need a heliocentric distance of the planet */
         if (SE.swe_calc(tjd_et, ipli, iflg0, x, ref serr) == SwissEph.ERR)
             return SwissEph.ERR;
         iflJ2000 = (iflag & SEFLG_EPHMASK) | SwissEph.SEFLG_J2000 | SwissEph.SEFLG_EQUATORIAL | SwissEph.SEFLG_XYZ | SwissEph.SEFLG_TRUEPOS | SwissEph.SEFLG_NONUT | SwissEph.SEFLG_SPEED;
         ellipse_is_bary = false;
         if (ipli != SwissEph.SE_MOON) {
             if ((method & SwissEph.SE_NODBIT_OSCU_BAR) != 0 && x[2] > 6) {
                 iflJ2000 |= SwissEph.SEFLG_BARYCTR; /* only planets beyond Jupiter */
                 ellipse_is_bary = true;
             } else {
                 iflJ2000 |= SwissEph.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 == SwissEph.SE_MOON) {
             dt = Sweph.NODE_CALC_INTV;
             dzmin = 1e-15;
             Gmsm = Sweph.GEOGCONST * (1 + 1 / Sweph.EARTH_MOON_MRAT) / Sweph.AUNIT / Sweph.AUNIT / Sweph.AUNIT * 86400.0 * 86400.0;
         } else {
             if ((ipli >= SwissEph.SE_MERCURY && ipli <= SwissEph.SE_PLUTO) || ipli == SwissEph.SE_EARTH)
                 plm = 1 / plmass[ipl_to_elem[ipl]];
             else
                 plm = 0;
             dt = Sweph.NODE_CALC_INTV * 10 * x[2];
             dzmin = 1e-15 * dt / Sweph.NODE_CALC_INTV;
             Gmsm = Sweph.HELGRAVCONST * (1 + plm) / Sweph.AUNIT / Sweph.AUNIT / Sweph.AUNIT * 86400.0 * 86400.0;
         }
         if ((iflag & SwissEph.SEFLG_SPEED) != 0) {
             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 (SE.swe_calc(t, ipli, iflJ2000, xpos[i], ref serr) == SwissEph.ERR)
                 return SwissEph.ERR;
             /* the EMB is used instead of the earth */
             if (ipli == SwissEph.SE_EARTH) {
                 if (SE.swe_calc(t, SwissEph.SE_MOON, iflJ2000 & ~(SwissEph.SEFLG_BARYCTR | SwissEph.SEFLG_HELCTR), xposm, ref serr) == SwissEph.ERR)
                     return SwissEph.ERR;
                 for (j = 0; j <= 2; j++)
                     xpos[i][j] += xposm[j] / (Sweph.EARTH_MOON_MRAT + 1.0);
             }
             SE.Sweph.swi_plan_for_osc_elem(iflg0, t, xpos[i]);
         }
         for (i = istart; i <= iend; i++) {
             if (Math.Abs(xpos[i][5]) < dzmin)
                 xpos[i][5] = dzmin;
             fac = xpos[i][2] / xpos[i][5];
             sgn = xpos[i][5] / Math.Abs(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 = Math.Sqrt(xn[i][0] * xn[i][0] + xn[i][1] * xn[i][1]);
             cosnode = xn[i][0] / rxy;
             sinnode = xn[i][1] / rxy;
             /* inclination */
             SE.SwephLib.swi_cross_prod(xpos[i], xpos[i].GetPointer(3), xnorm);
             rxy = xnorm[0] * xnorm[0] + xnorm[1] * xnorm[1];
             c2 = (rxy + xnorm[2] * xnorm[2]);
             rxyz = Math.Sqrt(c2);
             rxy = Math.Sqrt(rxy);
             sinincl = rxy / rxyz;
             cosincl = Math.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 = Math.Atan2(sinu, cosu);
             /* semi-axis */
             rxyz = Math.Sqrt(SE.Sweph.square_sum(xpos[i]));
             v2 = SE.Sweph.square_sum((xpos[i].GetPointer(3)));
             sema = 1 / (2 / rxyz - v2 / Gmsm);
             /* eccentricity */
             pp = c2 / Gmsm;
             ecce = Math.Sqrt(1 - pp / sema);
             /* eccentric anomaly */
             cosE = 1 / ecce * (1 - rxyz / sema);
             sinE = 1 / ecce / Math.Sqrt(sema * Gmsm) * SE.Sweph.dot_prod(xpos[i], (xpos[i].GetPointer(3)));
             /* true anomaly */
             ny = 2 * Math.Atan(Math.Sqrt((1 + ecce) / (1 - ecce)) * sinE / (1 + cosE));
             /* distance of perihelion from ascending node */
             xq[i][0] = SE.SwephLib.swi_mod2PI(uu - ny);
             xq[i][1] = 0;			/* latitude */
             xq[i][2] = sema * (1 - ecce);	/* distance of perihelion */
             /* transformation to ecliptic coordinates */
             SE.SwephLib.swi_polcart(xq[i], xq[i]);
             SE.SwephLib.swi_coortrf2(xq[i], xq[i], -sinincl, cosincl);
             SE.SwephLib.swi_cartpol(xq[i], xq[i]);
             /* adding node, we get perihelion in ecl. coord. */
             xq[i][0] += Math.Atan2(sinnode, cosnode);
             xa[i][0] = SE.SwephLib.swi_mod2PI(xq[i][0] + Math.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 */
             }
             SE.SwephLib.swi_polcart(xq[i], xq[i]);
             SE.SwephLib.swi_polcart(xa[i], xa[i]);
             /* new distance of node from orbital ellipse:
              * true anomaly of node: */
             ny = SE.SwephLib.swi_mod2PI(ny - uu);
             ny2 = SE.SwephLib.swi_mod2PI(ny + Math.PI);
             /* eccentric anomaly */
             cosE = Math.Cos(2 * Math.Atan(Math.Tan(ny / 2) / Math.Sqrt((1 + ecce) / (1 - ecce))));
             cosE2 = Math.Cos(2 * Math.Atan(Math.Tan(ny2 / 2) / Math.Sqrt((1 + ecce) / (1 - ecce))));
             /* new distance */
             rn = sema * (1 - ecce * cosE);
             rn2 = sema * (1 - ecce * cosE2);
             /* old node distance */
             ro = Math.Sqrt(SE.Sweph.square_sum(xn[i]));
             ro2 = Math.Sqrt(SE.Sweph.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 & SwissEph.SEFLG_SPEED) != 0) {
                 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 == SwissEph.SE_MOON && (iflag & (SwissEph.SEFLG_HELCTR | SwissEph.SEFLG_BARYCTR)) != 0) {
         SE.Sweph.swi_force_app_pos_etc();
         if (SE.swe_calc(tjd_et, SwissEph.SE_SUN, iflg0, x, ref serr) == SwissEph.ERR)
             return SwissEph.ERR;
     } else {
         if (SE.swe_calc(tjd_et, ipli, iflg0 | (iflag & SwissEph.SEFLG_TOPOCTR), x, ref serr) == SwissEph.ERR)
             return SwissEph.ERR;
     }
     /***********************
      * position of observer
      ***********************/
     if ((iflag & SwissEph.SEFLG_TOPOCTR) != 0) {
         /* geocentric position of observer */
         if (SE.Sweph.swi_get_observer(tjd_et, iflag, false, xobs, ref serr) != SwissEph.OK)
             return SwissEph.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 & (SwissEph.SEFLG_HELCTR | SwissEph.SEFLG_BARYCTR)) != Sweph.B1950) {
         if ((iflag & SwissEph.SEFLG_HELCTR) != 0 && 0 == (iflag & SwissEph.SEFLG_MOSEPH))
             for (i = 0; i <= 5; i++)
                 xobs[i] = xsun[i];
     } else if (ipl == SwissEph.SE_SUN && 0 == (iflag & SwissEph.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 & SwissEph.SEFLG_J2000) != 0)
         oe = SE.Sweph.swed.oec2000;
     else
         oe = SE.Sweph.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 == SwissEph.SE_EARTH && ij <= 1) {
             for (i = 0; i <= 5; i++)
                 xp[i] = 0;
             continue;
         }
         /*********************
          * to equator
          *********************/
         if (is_true_nodaps && 0 == (iflag & SwissEph.SEFLG_NONUT)) {
             SE.SwephLib.swi_coortrf2(xp, xp, -SE.Sweph.swed.nut.snut, SE.Sweph.swed.nut.cnut);
             if ((iflag & SwissEph.SEFLG_SPEED) != 0)
                 SE.SwephLib.swi_coortrf2(xp + 3, xp + 3, -SE.Sweph.swed.nut.snut, SE.Sweph.swed.nut.cnut);
         }
         SE.SwephLib.swi_coortrf2(xp, xp, -oe.seps, oe.ceps);
         SE.SwephLib.swi_coortrf2(xp + 3, xp + 3, -oe.seps, oe.ceps);
         if (is_true_nodaps) {
             /****************************
              * to mean ecliptic of date
              ****************************/
             if (0 == (iflag & SwissEph.SEFLG_NONUT))
                 SE.Sweph.swi_nutate(xp, iflag, true);
         }
         /*********************
          * to J2000
          *********************/
         SE.SwephLib.swi_precess(xp, tjd_et, iflag, Sweph.J_TO_J2000);
         if ((iflag & SwissEph.SEFLG_SPEED) != 0)
             SE.Sweph.swi_precess_speed(xp, tjd_et, iflag, Sweph.J_TO_J2000);
         /*********************
          * to barycenter
          *********************/
         if (ipli == SwissEph.SE_MOON) {
             for (i = 0; i <= 5; i++)
                 xp[i] += xear[i];
         } else {
             if (0 == (iflag & SwissEph.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 == SwissEph.SE_SUN && 0 == (iflag & (SwissEph.SEFLG_HELCTR | SwissEph.SEFLG_BARYCTR)))
             for (j = 0; j <= 5; j++)
                 xp[j] = -xp[j];
         /*********************
          * light deflection
          *********************/
         dt = Math.Sqrt(SE.Sweph.square_sum(xp)) * Sweph.AUNIT / Sweph.CLIGHT / 86400.0;
         if (do_defl)
             SE.Sweph.swi_deflect_light(xp, dt, iflag);
         /*********************
          * aberration
          *********************/
         if (do_aberr) {
             SE.Sweph.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 & SwissEph.SEFLG_SPEED) != 0) {
                 /* get barycentric sun and earth for t-dt into save area */
                 if (SE.swe_calc(tjd_et - dt, ipli, iflg0 | (iflag & SwissEph.SEFLG_TOPOCTR), x2, ref serr) == SwissEph.ERR)
                     return SwissEph.ERR;
                 if ((iflag & SwissEph.SEFLG_TOPOCTR) != 0) {
                     /* 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] = SE.Sweph.swed.topd.xobs[i];
                 } else {
                     for (i = 0; i <= 5; i++)
                         xobs2[i] = 0;
                 }
                 if ((iflag & (SwissEph.SEFLG_HELCTR | SwissEph.SEFLG_BARYCTR)) != 0) {
                     if ((iflag & SwissEph.SEFLG_HELCTR) != 0 && 0 == (iflag & SwissEph.SEFLG_MOSEPH))
                         for (i = 0; i <= 5; i++)
                             xobs2[i] = xsun[i];
                 } else if (ipl == SwissEph.SE_SUN && 0 == (iflag & SwissEph.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 (SE.swe_calc(tjd_et, SwissEph.SE_SUN, iflg0 | (iflag & SwissEph.SEFLG_TOPOCTR), x2, ref serr) == SwissEph.ERR)
                     return SwissEph.ERR;
             }
         }
         /*********************
          * precession
          *********************/
         /* save J2000 coordinates; required for sidereal positions */
         for (j = 0; j <= 5; j++)
             x2000[j] = xp[j];
         if (0 == (iflag & SwissEph.SEFLG_J2000)) {
             SE.SwephLib.swi_precess(xp, tjd_et, iflag, Sweph.J2000_TO_J);
             if ((iflag & SwissEph.SEFLG_SPEED) != 0)
                 SE.Sweph.swi_precess_speed(xp, tjd_et, iflag, Sweph.J2000_TO_J);
         }
         /*********************
          * nutation
          *********************/
         if (0 == (iflag & SwissEph.SEFLG_NONUT))
             SE.Sweph.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.                                  *
          ************************************************/
         SE.SwephLib.swi_coortrf2(xp, xp, oe.seps, oe.ceps);
         if ((iflag & SwissEph.SEFLG_SPEED) != 0)
             SE.SwephLib.swi_coortrf2(xp + 3, xp + 3, oe.seps, oe.ceps);
         if (0 == (iflag & SwissEph.SEFLG_NONUT)) {
             SE.SwephLib.swi_coortrf2(xp, xp, SE.Sweph.swed.nut.snut, SE.Sweph.swed.nut.cnut);
             if ((iflag & SwissEph.SEFLG_SPEED) != 0)
                 SE.SwephLib.swi_coortrf2(xp + 3, xp + 3, SE.Sweph.swed.nut.snut, SE.Sweph.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 & SwissEph.SEFLG_SIDEREAL) != 0) {
             /* project onto ecliptic t0 */
             if ((SE.Sweph.swed.sidd.sid_mode & SwissEph.SE_SIDBIT_ECL_T0) != 0) {
                 if (SE.Sweph.swi_trop_ra2sid_lon(x2000, pldat.xreturn.GetPointer(6), pldat.xreturn.GetPointer(18), iflag, ref serr) != SwissEph.OK)
                     return SwissEph.ERR;
                 /* project onto solar system equator */
             } else if ((SE.Sweph.swed.sidd.sid_mode & SwissEph.SE_SIDBIT_SSY_PLANE) != 0) {
                 if (SE.Sweph.swi_trop_ra2sid_lon_sosy(x2000, pldat.xreturn.GetPointer(6), pldat.xreturn.GetPointer(18), iflag, ref  serr) != SwissEph.OK)
                     return SwissEph.ERR;
             } else {
                 /* traditional algorithm */
                 SE.SwephLib.swi_cartpol_sp(pldat.xreturn.GetPointer(6), pldat.xreturn);
                 pldat.xreturn[0] -= SE.swe_get_ayanamsa(tjd_et) * SwissEph.DEGTORAD;
                 SE.SwephLib.swi_polcart_sp(pldat.xreturn, pldat.xreturn.GetPointer(6));
             }
         }
         if ((iflag & SwissEph.SEFLG_XYZ) != 0 && (iflag & SwissEph.SEFLG_EQUATORIAL) != 0) {
             for (j = 0; j <= 5; j++)
                 xp[j] = pldat.xreturn[18 + j];
             continue;
         }
         if ((iflag & SwissEph.SEFLG_XYZ) != 0) {
             for (j = 0; j <= 5; j++)
                 xp[j] = pldat.xreturn[6 + j];
             continue;
         }
         /************************************************
          * transformation to polar coordinates          *
          ************************************************/
         SE.SwephLib.swi_cartpol_sp(pldat.xreturn.GetPointer(18), pldat.xreturn.GetPointer(12));
         SE.SwephLib.swi_cartpol_sp(pldat.xreturn.GetPointer(6), pldat.xreturn);
         /**********************
          * radians to degrees *
          **********************/
         if ((iflag & SwissEph.SEFLG_RADIANS) == 0)
         {
             for (j = 0; j < 2; j++)
             {
                 pldat.xreturn[j] *= SwissEph.RADTODEG;		/* ecliptic */
                 pldat.xreturn[j + 3] *= SwissEph.RADTODEG;
                 pldat.xreturn[j + 12] *= SwissEph.RADTODEG;	/* equator */
                 pldat.xreturn[j + 15] *= SwissEph.RADTODEG;
             }
         }
         if ((iflag & SwissEph.SEFLG_EQUATORIAL) != 0) {
             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 && 0 == (iflag & SwissEph.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 SwissEph.OK;
 }
Example #2
0
        /* Moshier ephemeris.
         * computes heliocentric cartesian equatorial coordinates of
         * equinox 2000
         * for earth and a planet
         * tjd		julian day
         * ipli		internal SWEPH planet number
         * xp		array of 6 doubles for planet's position and speed
         * xe		                       earth's
         * serr		error string
         */
        public int swi_moshplan(double tjd, int ipli, bool do_save, CPointer <double> xpret, CPointer <double> xeret, ref string serr)
        {
            int  i;
            bool do_earth = false;

            double[] dx = new double[3], x2 = new double[3], xxe = new double[6], xxp = new double[6];
            double[] xp, xe;
            double   dt;
            string   s    = String.Empty;
            int      iplm = pnoint2msh[ipli];

            Sweph.plan_data pdp      = SE.Sweph.swed.pldat[ipli];
            Sweph.plan_data pedp     = SE.Sweph.swed.pldat[Sweph.SEI_EARTH];
            double          seps2000 = SE.Sweph.swed.oec2000.seps;
            double          ceps2000 = SE.Sweph.swed.oec2000.ceps;

            if (do_save)
            {
                xp = pdp.x;
                xe = pedp.x;
            }
            else
            {
                xp = xxp;
                xe = xxe;
            }
            if (do_save || ipli == Sweph.SEI_EARTH || xeret != null)
            {
                do_earth = true;
            }
            /* tjd beyond ephemeris limits, give some margin for spped at edge */
            if (tjd < Sweph.MOSHPLEPH_START - 0.3 || tjd > Sweph.MOSHPLEPH_END + 0.3)
            {
                s = C.sprintf("jd %f outside Moshier planet range %.2f .. %.2f ",
                              tjd, Sweph.MOSHPLEPH_START, Sweph.MOSHPLEPH_END);
                serr = (serr ?? String.Empty) + s;
                return(SwissEph.ERR);
            }
            /* earth, for geocentric position */
            if (do_earth)
            {
                if (tjd == pedp.teval &&
                    pedp.iephe == SwissEph.SEFLG_MOSEPH)
                {
                    xe = pedp.x;
                }
                else
                {
                    /* emb */
                    swi_moshplan2(tjd, pnoint2msh[Sweph.SEI_EMB], xe);     /* emb hel. ecl. 2000 polar */
                    SE.SwephLib.swi_polcart(xe, xe);                       /* to cartesian */
                    SE.SwephLib.swi_coortrf2(xe, xe, -seps2000, ceps2000); /* and equator 2000 */
                    embofs_mosh(tjd, xe);                                  /* emb -> earth */
                    if (do_save)
                    {
                        pedp.teval = tjd;
                        pedp.xflgs = -1;
                        pedp.iephe = SwissEph.SEFLG_MOSEPH;
                    }
                    /* one more position for speed. */
                    swi_moshplan2(tjd - Sweph.PLAN_SPEED_INTV, pnoint2msh[Sweph.SEI_EMB], x2);
                    SE.SwephLib.swi_polcart(x2, x2);
                    SE.SwephLib.swi_coortrf2(x2, x2, -seps2000, ceps2000);
                    embofs_mosh(tjd - Sweph.PLAN_SPEED_INTV, x2);/**/
                    for (i = 0; i <= 2; i++)
                    {
                        dx[i] = (xe[i] - x2[i]) / Sweph.PLAN_SPEED_INTV;
                    }
                    /* store speed */
                    for (i = 0; i <= 2; i++)
                    {
                        xe[i + 3] = dx[i];
                    }
                }
                if (xeret != null)
                {
                    for (i = 0; i <= 5; i++)
                    {
                        xeret[i] = xe[i];
                    }
                }
            }
            /* earth is the planet wanted */
            if (ipli == Sweph.SEI_EARTH)
            {
                xp = xe;
            }
            else
            {
                /* other planet */
                /* if planet has already been computed, return */
                if (tjd == pdp.teval && pdp.iephe == SwissEph.SEFLG_MOSEPH)
                {
                    xp = pdp.x;
                }
                else
                {
                    swi_moshplan2(tjd, iplm, xp);
                    SE.SwephLib.swi_polcart(xp, xp);
                    SE.SwephLib.swi_coortrf2(xp, xp, -seps2000, ceps2000);
                    if (do_save)
                    {
                        pdp.teval = tjd;/**/
                        pdp.xflgs = -1;
                        pdp.iephe = SwissEph.SEFLG_MOSEPH;
                    }

                    /* one more position for speed.
                     * the following dt gives good speed for light-time correction
                     */
                    //#if 0
                    //  for (i = 0; i <= 2; i++)
                    //dx[i] = xp[i] - pedp.x[i];
                    //  dt = LIGHTTIME_AUNIT * Math.Sqrt(square_sum(dx));
                    //#endif
                    dt = Sweph.PLAN_SPEED_INTV;
                    swi_moshplan2(tjd - dt, iplm, x2);
                    SE.SwephLib.swi_polcart(x2, x2);
                    SE.SwephLib.swi_coortrf2(x2, x2, -seps2000, ceps2000);
                    for (i = 0; i <= 2; i++)
                    {
                        dx[i] = (xp[i] - x2[i]) / dt;
                    }
                    /* store speed */
                    for (i = 0; i <= 2; i++)
                    {
                        xp[i + 3] = dx[i];
                    }
                }
                if (xpret != null)
                {
                    for (i = 0; i <= 5; i++)
                    {
                        xpret[i] = xp[i];
                    }
                }
            }
            return(SwissEph.OK);
        }

        /* Prepare lookup table of sin and cos ( i*Lj )
         * for required multiple angles
         */
        void plan_sscc(int k, double arg, int n)
        {
            double cu, su, cv, sv, s;
            int    i;

            su            = Math.Sin(arg);
            cu            = Math.Cos(arg);
            plan_ss[k, 0] = su;         /* sin(L) */
            plan_cc[k, 0] = cu;         /* cos(L) */
            sv            = 2.0 * su * cu;
            cv            = cu * cu - su * su;
            plan_ss[k, 1] = sv;         /* sin(2L) */
            plan_cc[k, 1] = cv;
            for (i = 2; i < n; i++)
            {
                s             = su * cv + cu * sv;
                cv            = cu * cv - su * sv;
                sv            = s;
                plan_ss[k, i] = sv;             /* sin( i+1 L ) */
                plan_cc[k, i] = cv;
            }
        }

        /* Adjust position from Earth-Moon barycenter to Earth
         *
         * J = Julian day number
         * xemb = rectangular equatorial coordinates of Earth
         */
        void embofs_mosh(double tjd, CPointer <double> xemb)
        {
            double T, M, a, L, B, p;
            double smp, cmp, s2mp, c2mp, s2d, c2d, sf, cf;
            double s2f, sx, cx; double[] xyz = new double[6];
            double seps = SE.Sweph.swed.oec.seps;
            double ceps = SE.Sweph.swed.oec.ceps;
            int    i;

            /* Short series for position of the Moon
             */
            T = (tjd - Sweph.J1900) / 36525.0;
            /* Mean anomaly of moon (MP) */
            a    = SE.swe_degnorm(((1.44e-5 * T + 0.009192) * T + 477198.8491) * T + 296.104608);
            a   *= SwissEph.DEGTORAD;
            smp  = Math.Sin(a);
            cmp  = Math.Cos(a);
            s2mp = 2.0 * smp * cmp;             /* sin(2MP) */
            c2mp = cmp * cmp - smp * smp;       /* cos(2MP) */
            /* Mean elongation of moon (D) */
            a   = SE.swe_degnorm(((1.9e-6 * T - 0.001436) * T + 445267.1142) * T + 350.737486);
            a   = 2.0 * SwissEph.DEGTORAD * a;
            s2d = Math.Sin(a);
            c2d = Math.Cos(a);
            /* Mean distance of moon from its ascending node (F) */
            a   = SE.swe_degnorm(((-3.0e-7 * T - 0.003211) * T + 483202.0251) * T + 11.250889);
            a  *= SwissEph.DEGTORAD;
            sf  = Math.Sin(a);
            cf  = Math.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 = SE.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 * Math.Sin(SwissEph.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 *= SwissEph.DEGTORAD;
            /* Parallax of the moon */
            p = 0.950724
                + 0.051818 * cmp
                + 0.009531 * cx
                + 0.007843 * c2d
                + 0.002824 * c2mp;
            p *= SwissEph.DEGTORAD;

            /* Elongation of Moon from Sun
             */
            L  = SE.swe_degnorm(L);
            L *= SwissEph.DEGTORAD;
            /* Distance in au */
            a = 4.263523e-5 / Math.Sin(p);
            /* Convert to rectangular ecliptic coordinates */
            xyz[0] = L;
            xyz[1] = B;
            xyz[2] = a;
            SE.SwephLib.swi_polcart(xyz, xyz);
            /* Convert to equatorial */
            SE.SwephLib.swi_coortrf2(xyz, xyz, -seps, ceps);
            /* Precess to equinox of J2000.0 */
            SE.SwephLib.swi_precess(xyz, tjd, 0, Sweph.J_TO_J2000);/**/
            /* now emb -> earth */
            for (i = 0; i <= 2; i++)
            {
                xemb[i] -= xyz[i] / (Sweph.EARTH_MOON_MRAT + 1.0);
            }
        }