JEphem Informatic Trail JEphem source code SwissEphemeris.java
//*********************************************************************************
// class jephem.astro.solarsystem.SwissEphemeris
// Software released under the General Public License (version 2 or later), available at
// http://www.gnu.org/copyleft/gpl.html
//*********************************************************************************
package jephem.astro.solarsystem;

import swisseph.*;

import jephem.GlobalVar;

import jephem.astro.Body;
import jephem.astro.solarsystem.SolarSystemConstants;
import jephem.astro.AstroException;
//import jephem.astro.solarsystem.ComputationException;
import jephem.astro.spacetime.SpaceConstants;
import jephem.astro.spacetime.TimeConstants;
import jephem.astro.spacetime.Units;
import jephem.astro.spacetime.UnitsConstants;

import tig.GeneralConstants;

/******************************************************************************
Class serving to interface JEphem and the java port of SwissEphemeris.
@author Thierry Graff
@history feb 02 2002 : creation.

@todo To be able to get an ComputationException from calcBodyCoords, class SwissEphe should be modified.
*********************************************************************************/
public abstract class SwissEphemeris
  implements GeneralConstants, SolarSystemConstants, SpaceConstants, UnitsConstants{

  //=================================================================================
  //                                      CLASS VARIABLES
  //=================================================================================
  /** path to SwissEphemeris data. */
  private static String _dataPath;

  /** The only SwissEphemeris used to perform the computations. */
  private static SwissEph _se;

  //=================================================================================
  //                                      CONSTANTS
  //=================================================================================

  /** Path to SwissEphemeris data, relative to JEphem/data. */
  private static final String PATH_TO_SWISS = "astro" + FS + "swissEphem" + FS;

  //=================================================================================
  //                                      PUBLIC METHODS
  //=================================================================================

  //***************** calcBodyCoords *******************************
  /** Computation of body coordinates, using Swiss Ephemeris. The results are stored in 'bodies'.
  @post Elements of 'bodies' are respect the parameters (fram, sphereCart, units...).
  */
  public static void calcBodyCoords(double  jd,
                                    Body[]  bodies,
                                    int     frame,
                                    int     sphereCart,
                                    double  precision,
                                    boolean velocities,
                                    int[]   units
                                  ) throws AstroException{
    //traceCalcBodyCoordsParameters(jd, bodies, frame, sphereCart, precision, velocities, units);
    if (_dataPath == null){
      throw new AstroException("Before Using SwissEphemeris, you must indicate where data are located with setDataPath()");
    }
    if (_se == null){
      //System.out.println("SwissEphemeris.calcBodyCoords() - build swiwsseph : " + _dataPath);
      _se = new SwissEph(_dataPath);
    }

    int iPlanet; // 'planet' = moving body
    int flag;
    StringBuffer err;
    double[] res = new double[6];

    for(int iBody = 0; iBody < bodies.length; iBody++){
      // build iPlanet
      iPlanet = getPlanetIndex(bodies[iBody].getIndex());
      // build flag
      flag = SweConst.SEFLG_SWIEPH;
      if(sphereCart == CARTESIAN) flag += SweConst.SEFLG_XYZ;
      if(velocities) flag += SweConst.SEFLG_SPEED;
      if(frame == FRAME_THEORY){
        //flag += SweConst.SEFLG_BARYCTR;
        flag += SweConst.SEFLG_HELCTR;
        flag += SweConst.SEFLG_J2000;
        flag += SweConst.SEFLG_NOABERR;
        flag += SweConst.SEFLG_NOGDEFL;
        flag += SweConst.SEFLG_NONUT;
        flag += SweConst.SEFLG_TRUEPOS;
      }
      else if(frame == FRAME_EC_HELIO_GEOMETRIC){
        flag += SweConst.SEFLG_TRUEPOS;
        flag += SweConst.SEFLG_HELCTR;
      }
      else if(frame == FRAME_EQUATORIAL){
        flag += SweConst.SEFLG_EQUATORIAL;
      }
      //else if(frame == FRAME_ECLIPTIC) // nothing to do, default result

      // call swiss ephemeris
      err = new StringBuffer(); //err.delete(0, err.length() - 1);
      _se.swe_calc_ut(jd, iPlanet, flag, res, err);
      //System.out.println("values from swisseph : " + tig.Strings.doubleArrayToString(res));

      // fill bodies
      if (sphereCart == CARTESIAN){
        bodies[iBody].setPositionCoords(res[0], res[1], res[2]);
        bodies[iBody].setPositionUnits(UNITGROUP_AU_AU_AU);
        if (velocities){
          bodies[iBody].setVelocityCoords(res[3], res[4], res[5]);
          bodies[iBody].setVelocityUnits(UNITGROUP_AUD_AUD_AUD);
        }
      }
      else{ // SPHERICAL
        bodies[iBody].setPositionCoords(res[2], res[0], res[1]);
        bodies[iBody].setPositionUnits(new int[]{DISTANCE_UNIT_AU,
                                                 ANGULAR_UNIT_DEG,
                                                 ANGULAR_UNIT_DEG});
        if (velocities){
          bodies[iBody].setVelocityCoords(res[5], res[3], res[4]);
          bodies[iBody].setVelocityUnits(new int[]{LINEAR_SPEED_UNIT_AU_PER_D,
                                                   ANGULAR_SPEED_UNIT_DEG_PER_DAY,
                                                   ANGULAR_SPEED_UNIT_DEG_PER_DAY});
        }
      }
      bodies[iBody].setFrame(frame);
      bodies[iBody].setCoordinateExpression(sphereCart);

      // Convert pos units
      bodies[iBody].setPositionCoords(Units.convertUnits(
              bodies[iBody].getPositionCoords(),
              bodies[iBody].getPositionUnits(),
              new int[]{units[0], units[1], units[2]}
      ));
      bodies[iBody].setPositionUnits(new int[]{units[0], units[1], units[2]});

      // Convert vel units
      if (velocities){
        bodies[iBody].setVelocityCoords(Units.convertUnits(
                bodies[iBody].getVelocityCoords(),
                bodies[iBody].getVelocityUnits(),
                new int[]{units[3], units[4], units[5]}
        ));
      bodies[iBody].setVelocityUnits(new int[]{units[3], units[4], units[5]});
      }

      // handle error returned from swiss eph.
      if (err.length() != 0)
        throw new AstroException("Error coming from SwissEphemeris : " + LS + err.toString());
    }// end for iBody
  }// end calcBodyCoords()

  //**************************** setDataPath *****************************************
  /** Sets the path to data ; SwissEphem data are in <dataPath>/astro/swissEphem. */
  public static void setDataPath(String dataPath){
    //System.out.println("SwissEphemeris.setDataPath() : " + dataPath);
    _dataPath = dataPath;
  }// end

  //=================================================================================
  //                                      PRIVATE METHODS
  //=================================================================================

  /** Converts a JEphem body index to a SwissEphemeris planet index. */
  private static int getPlanetIndex(int iBody){
    switch(iBody){
      case SUN :        return SweConst.SE_SUN;
      case MOON :       return SweConst.SE_MOON;
      case MERCURY :    return SweConst.SE_MERCURY;
      case VENUS :      return SweConst.SE_VENUS;
      case EARTH :      return SweConst.SE_EARTH;
      case MARS :       return SweConst.SE_MARS;
      case JUPITER :    return SweConst.SE_JUPITER;
      case SATURN :     return SweConst.SE_SATURN;
      case URANUS :     return SweConst.SE_URANUS;
      case NEPTUNE :    return SweConst.SE_NEPTUNE;
      case PLUTO :      return SweConst.SE_PLUTO;
      default :         return NO_SPECIF; // I checked that no swiss eph planet index are = -1.
    }
  }// end getPlanetIndex


  //=================================================================================
  //=================================================================================
  //                                      TESTS
  //=================================================================================
  //=================================================================================

/*
  // **************** For tests only ****************
  public static void main(String[] args){
    // no complete argument checking
    if(args[0].equalsIgnoreCase("testUnitType"))
      testUnitType();
    else if(args[0].equalsIgnoreCase("testConversion"))
      testConversion(args[1]);
    else if(args[0].equalsIgnoreCase("testGetUnitLabel"))
      testGetUnitLabel(args[1]);
    else
      System.out.println("first argument must be 'testUnitType' or 'testConversion' " +
      "or 'testGetUnitLabel'");
  }// end main
*/
  // **************** For tests only ****************
  private static void traceCalcBodyCoordsParameters(double  jd,
                                                   Body[]  bodies,
                                                   int     frame,
                                                   int     sphereCart,
                                                   double  precision,
                                                   boolean velocities,
                                                   int[]   units
                                  ){
    System.out.println("========== SwissEphemeris.traceCalcBodyCoordsParameters() ====================");
    int[] bodyIndices = new int[bodies.length];
    for (int i = 0; i < bodies.length; i++) bodyIndices[i] = bodies[i].getIndex();
    System.out.println("bodies : " + tig.Strings.intArrayToString(bodyIndices));
    System.out.println("frame : " + frame);
    System.out.println("sphereCart : " + sphereCart);
    System.out.println("precision : " + precision);
    System.out.println("velocities : " + velocities);
    System.out.println("units : " + tig.Strings.intArrayToString(units));
  }//end traceCalcBodyCoordsParameters

}// end class SwissEphemeris