/*****************************************************************************\
* PlanetData
\*****************************************************************************/
package com.mhuss.AstroLib;
//import android.util.Log;
/**
* This class handles planetary motion calculations and conversions.
*/
public class PlanetData {
public static final double AU = 149597870.691; // 1 AU km
/**
* Default constructor.
*/
public PlanetData() { m_planet = Planets.NAP; m_initComplete=false; }
/**
* Explicit (all parameters) constructor.
*
* @param planet Planet number (from Planets class)
* @param jd Julian day number
* @param oi Observer location
*/
public PlanetData( int planet, double jd, double deltaT, ObsInfo oi ) {
calc( planet, jd, deltaT, oi );
}
public PlanetData( int planet, double jd, ObsInfo oi ) {
calc( planet, jd, oi );
}
/**
* This calculates all LocationElements, then returns the longitude.
*
* Longitude is split out because it gets used most often.
*
* @param planet Planet number (from Planets class)
* @param jd Julian day number
* @param oi Observer location
*/
public double calcLon( int planet, double jd, ObsInfo oi ) {
if ( Planets.SUN == planet )
planet = Planets.EARTH;
// What we _really_ want is the location of the sun as seen from
// the earth (geocentric view). VSOP gives us the opposite, but
// this will be corrected below.
m_jd = jd;
m_planet = planet;
m_centuries = AstroOps.toMillenia( jd );
m_polarLEs = new LocationElements();
// choose appropriate method, based on planet
//
if( Planets.LUNA == planet ) {
Lunar luna = new Lunar();
try {
luna.calcAllLEs( m_polarLEs, m_centuries );
m_polarLEs.setRadius(m_polarLEs.getRadius()/AU); // Convert from km to AU
} catch (NoInitException ni) {}
}
else if( Planets.PLUTO == planet ) {
double [] lbr = new double [3];
Pluto2.ln_get_pluto_helio_coords (jd, lbr);
m_polarLEs.setLongitude(lbr[0]);
m_polarLEs.setLatitude(lbr[1]);
m_polarLEs.setRadius(lbr[2]);
//Pluto.calcAllLEs( m_polarLEs, m_centuries );
}
else {
Vsop.calcAllLEs( m_polarLEs, m_centuries, planet );
if ( Planets.EARTH == planet ) {
/*
* What we _really_ want is the location of the sun as seen from
* the earth (geocentric view). VSOP gives us the opposite
* (heliocentric) view, i.e., the earth as seen from the sun.
* To work around this, we add PI to the longitude (rotate 180 degrees)
* and negate the latitude.
*/
m_polarLEs.setLongitude( m_polarLEs.getLongitude() + Math.PI );
m_polarLEs.setLatitude( m_polarLEs.getLatitude() * -1D );
}
}
return m_polarLEs.getLongitude();
}
/**
* Calculate the data for a given planet, julian day, and location.
*
* This function must be called (directly or via constructor) before
* calling any of the other functions in this class.
*
* @param planet Planet number (from Planets class)
* @param jd Julian day number
* @param oi Observer location
*/
public void calc( int planet, double jd, double deltaT, ObsInfo oi ) {
calc (planet, jd, deltaT, oi, true, true);
}
// assumes deltaT = 0.0 for low precision purpose. (=> error in hour angle, if JD = TDT)
public void calc( int planet, double jd, ObsInfo oi ) {
calc (planet, jd, 0.0, oi, false, false);
}
/**
* Calculate the data for a given planet, julian day, and location.
*
* This function must be called (directly or via constructor) before
* calling any of the other functions in this class.
*
* @param planet Planet number (from Planets class)
* @param jd Julian day number (tdt)
* @param deltaT (in Days)
* @param oi Observer location
* @param topoc_Corr correct topocentric
* @param lightT_Corr correct light time
*/
public void calc( int planet, double jd, double deltaT, ObsInfo oi, boolean topoc_Corr, boolean lightT_Corr) {
// There's a lot of calculating here, but one we need most often
// is the last one (AltAzLoc), which depends on all the previous
// calculations
//
double localSiderealTime =
AstroOps.greenwichSiderealTime(jd-deltaT) + oi.getLongitudeRad(); // UTC required !
double obliquity = AstroOps.meanObliquity( m_centuries );
// Two pass iteration for light time correction (added by W. Strickling)
// needs planetary heliocentric position at jd -lightTimeCorrection
// seen from earth's heliocentric position at jd
// NOT FOR SOLAR POSITION!
double tmpVec[] = new double[MathOps.VECTOR_SIZE]; // buffers planet's xyz position, subject to transformations
double tmpVec2[] = new double[MathOps.VECTOR_SIZE]; // buffers Earth's xyz position
double lightTimeCorrection = 0; // in days
int passNo = 1;
if (! lightT_Corr) passNo = 2; // already last pass, if no light time correction required
do {
// Log.d ("PlanetData", "Pass " +passNo +", LightTimeCorrection (min):"+ lightTimeCorrection *24.*60. );
calcLon( planet, jd -lightTimeCorrection, oi ); // Heliocentric planetary coordinates
// Conversion to cartesian into tmpVec
MathOps.polarToCartesian( tmpVec, m_polarLEs.getLongitude(),
m_polarLEs.getLatitude(),
m_polarLEs.getRadius());
// Modification by Strickling:
// conversion Heliozentric to geocentric position
// calculate earth's position and convert tmpVec to geocentric
g_polarLEs = new LocationElements(); // for buffering earth's position
// if ((planet >= Planets.MERCURY) && (planet <= Planets.LUNA) && (planet != Planets.EARTH))
if (planet != Planets.EARTH && planet != Planets.SUN)
{
if (passNo ==1 || ! lightT_Corr) { // Earth position does not change, calc only first time
// Calculate heliocentric coordinates of the Earth (g_polarLEs)
Vsop.calcAllLEs( g_polarLEs, m_centuries, Planets.EARTH );
MathOps.polarToCartesian( tmpVec2, g_polarLEs.getLongitude(),
g_polarLEs.getLatitude(),
g_polarLEs.getRadius());
}
}
// tmpVec = Helicoentric planet position or geocentric lunar position
// tmpVec2 = Helicoentric position of the Earth
if (planet != Planets.LUNA && planet != Planets.EARTH && planet != Planets.SUN){
// Planets: Change tmpVec from heliocentric to geocentric
tmpVec [0] -= tmpVec2 [0];
tmpVec [1] -= tmpVec2 [1];
tmpVec [2] -= tmpVec2 [2];
}
// reduce geocentric equatorial position tmpVec cartesian coordinates to topocentric
if (planet == Planets.LUNA || planet == Planets.EARTH || planet == Planets.SUN)
{passNo = 2;} // no light time correction for sun and moon
// Topocentric reduction in passNo 2
if (passNo == 2) { // only in second pass of for Moon and Sun
if (topoc_Corr) TopocReductionEcl (tmpVec, localSiderealTime, oi.getLatitudeRad(), obliquity);
// MOON: Calculate heliocentric position of the moon, for physical ephemeris, magnitude etc
if (planet == Planets.LUNA){
tmpVec2 [0] += tmpVec [0];
tmpVec2 [1] += tmpVec [1];
tmpVec2 [2] += tmpVec [2];
double tmpVec3[] = new double[MathOps.VECTOR_SIZE];
MathOps.cartesianToPolar(tmpVec2, tmpVec3);
m_polarLEs = new LocationElements (tmpVec3);
}
}
// Calc lightTimeCorrection in days for passNo 2
else { // passNo == 1
final double LIGHTSPEED = 299792.458; // km/s
lightTimeCorrection = Math.sqrt(
tmpVec [0]*tmpVec [0] +tmpVec [1]*tmpVec [1] +tmpVec [2]*tmpVec [2])
* AU /(LIGHTSPEED *86400.0);
}
passNo ++;
} while (passNo <= 2); // end of Light time correction passes
// end Strickling modification
m_eclipticLEs = new LocationElements(tmpVec);
// At this point, eclipticLE is a unit vector in ecliptic
// coords of date. Rotate it by 'obliquity' to get
// a vector in equatorial coords of date:
//
MathOps.rotateVector( tmpVec, obliquity, 0 );
//TopocReductionEqu (tmpVec, localSiderealTime, oi.getLatitudeRad());
m_equatorialLEs = new LocationElements(tmpVec); // Cartesian!!
// extract RA/Dec from equatorial coords of date
//
m_rightAscension = Math.atan2(
m_equatorialLEs.getY(), m_equatorialLEs.getX() );
// m_declination = Math.asin( m_equatorialLEs.getZ() );
m_declination = Math.atan2( m_equatorialLEs.getZ(),
Math.sqrt(m_equatorialLEs.getX()* m_equatorialLEs.getX() +
m_equatorialLEs.getY()*m_equatorialLEs.getY())); // Correction by Strickling
// The following two rotations take us from a vector in
// equatorial coords of date to an alt/az vector:
//
MathOps.rotateVector( tmpVec, -localSiderealTime, 2 );
//Strickling Change Z To X and Y to -Y
m_hourAngle = Math.atan2( -tmpVec[LocationElements.Y], tmpVec[LocationElements.X] );
MathOps.rotateVector( tmpVec, oi.getLatitudeRad() - Astro.PI_OVER_TWO, 1);
m_altAzLEs = new LocationElements(tmpVec); // Cartesian!!
m_initComplete=true;
} //calc
/** Reduces cartesian equatorial coordinates from geocentric to topocentric
*
* @param cartVec equatorial
* @param localSiderealTime in radians
* @param latRad Latitude in radians
*/
static void TopocReductionEqu (double cartVec [], // cartesian coordinates in AU
double localSiderealTime, double latRad) {
final double AE = 149597870.691; // km
final double R_EARTH = 6368; // km mean Radius
double tmpVec2[] = new double[MathOps.VECTOR_SIZE];
MathOps.polarToCartesian (tmpVec2, localSiderealTime, latRad, R_EARTH/AE);
cartVec [0] -= tmpVec2 [0];
cartVec [1] -= tmpVec2 [1];
cartVec [2] -= tmpVec2 [2];
// Log.d ("TopRed", "TopRed " +localSiderealTime +" " +Math.atan2(tmpVec2 [0], tmpVec2 [1]));
} //TopocReduction **************************************
/** Reduces cartesian ecliptical coordinates from geocentric to topocentric
*
* @param cartVec equatorial
* @param localSiderealTime in radians
* @param latRad Latitude in radians
*/
protected static void TopocReductionEcl (double cartVec [], // cartesian coordinates in AU
double localSiderealTime, double latRad, double obliquity) {
final double AE = 149597870.691; // km
final double R_EARTH = 6368; // km mean Radius
double tmpVec2[] = new double[MathOps.VECTOR_SIZE];
MathOps.polarToCartesian (tmpVec2, localSiderealTime, latRad, R_EARTH/AE);
MathOps.rotateVector( tmpVec2, -obliquity, 0 );
cartVec [0] -= tmpVec2 [0];
cartVec [1] -= tmpVec2 [1];
cartVec [2] -= tmpVec2 [2];
} //TopocReduction **************************************
/**
* Get the Planets number.
*
* Example: Planets.MERCURY
*/
public int planet() { return m_planet; }
/**
* Get the Julian day number.
*/
public double jd() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_jd;
}
/**
* Get the hour angle.
*/
public double hourAngle() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_hourAngle;
}
/**
* Get the polar latitude. (Heliocentric polar coordinates)
*/
public double getPolarLat() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_polarLEs.getLatitude();
}
/**
* Get the polar longitude. (Heliocentric polar coordinates)
*/
public double getPolarLon() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_polarLEs.getLongitude();
}
/**
* Get the polar radius. (Distance to sun)
*/
public double getPolarRadius() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_polarLEs.getRadius();
}
/**
* Get the Solar ecliptic latitude in radians
* (Geocentric ecliptical coordinates of the Sun, usually close to zero)
*/
public double getSolarLat() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
if (g_polarLEs.getRadius() == -1) Vsop.calcAllLEs( g_polarLEs, m_centuries, Planets.EARTH );
return -g_polarLEs.getLatitude();
}
/**
* Get the geocentric ecliptic longitude of the Sun in radians
*/
public double getSolarLon() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
if (g_polarLEs.getRadius() == -1) Vsop.calcAllLEs( g_polarLEs, m_centuries, Planets.EARTH );
return g_polarLEs.getLongitude() +Math.PI;
}
/**
* Get the solar radius of the Earth. (Distance Earth to Sun)
*/
public double getSolarRadius() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
if (g_polarLEs.getRadius() == -1) Vsop.calcAllLEs( g_polarLEs, m_centuries, Planets.EARTH );
return g_polarLEs.getRadius();
}
/**
* Get the geocentric ecliptic cartesian Coords x, y, z. Add. by Strickling
*/
public LocationElements getEclipticXYZ() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
// Add by Strickling
return m_eclipticLEs;
}
/**
* Get the ecliptic latitude. Mod. by Strickling, geocentric polar coordinates
*/
public double getEclipticLat() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
// Modification by Strickling, Here is polar conversion needed!
// return m_eclipticLEs.getLatitude();
return Math.atan2 (m_eclipticLEs.getZ(), Math.sqrt(m_eclipticLEs.getX()* m_eclipticLEs.getX() +
m_eclipticLEs.getY()*m_eclipticLEs.getY()));
}
/**
* Get the ecliptic longitude. Mod. by Strickling, geocentric polar coordinates in radians
*/
public double getEclipticLon() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
// Modification by Strickling, Here is polar conversion needed!
// return m_eclipticLEs.getLongitude();
return Math.atan2(m_eclipticLEs.getY(), m_eclipticLEs.getX());
}
/**
* Get the ecliptic radius. Mod. by Strickling, Distance to Earth
*/
public double getEclipticRadius() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
// Modification by Strickling, Here is polar conversion needed!
// return m_eclipticLEs.getRadius();
return Math.sqrt( m_eclipticLEs.getX()* m_eclipticLEs.getX()
+m_eclipticLEs.getY()* m_eclipticLEs.getY()
+m_eclipticLEs.getZ()* m_eclipticLEs.getZ());
}
/**
* Get the equatorial latitude (y). Cartesian Coord-System
*/
public double getEquatorialLat() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_equatorialLEs.getLatitude();
}
/**
* Get the equatorial longitude (x). Cartesian Coord-System
*/
public double getEquatorialLon() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_equatorialLEs.getLongitude();
}
/**
* Get the equatorial radius (z). Cartesian Coord-System
*/
public double getEquatorialRadius() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_equatorialLEs.getRadius();
}
/**
* Get the Alt-Az latitude. (Converted into polar coordinates)
*/
public double getAltAzLat() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
// Modification by Strickling, Here is polar conversion needed!
// return m_altAzLEs.getLatitude();
return Math.atan2 (m_altAzLEs.getZ(), Math.sqrt(m_altAzLEs.getX()* m_altAzLEs.getX() +
m_altAzLEs.getY()*m_altAzLEs.getY()));
}
/**
* Get the Alt-Az longitude. Radians, south is 0 deg (Converted into polar coordinates)
*/
public double getAltAzLon() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
// Modification by Strickling, Here is polar conversion needed!
// return m_altAzLEs.getLongitude();
return Math.atan2(m_altAzLEs.getY(), m_altAzLEs.getX());
}
/**
* Get the Alt-Az radius. (Converted into polar coordinates)
*/
public double getAltAzRadius() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
// Modification by Strickling, Here is polar conversion needed!
// return m_altAzLEs.getRadius();
return Math.sqrt( m_altAzLEs.getX()* m_altAzLEs.getX()
+m_altAzLEs.getY()* m_altAzLEs.getY()
+m_altAzLEs.getZ()* m_altAzLEs.getZ());
}
/**
* Get the right ascension in radians.
*/
public double getRightAscension() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_rightAscension;
}
/**
* Get the declination in radians.
*/
public double getDeclination() throws NoInitException {
if ( !m_initComplete )
throw new NoInitException( NoInit );
return m_declination;
}
// instance data
protected boolean m_initComplete;
protected int m_planet;
protected double m_jd;
protected double m_centuries;
protected double m_hourAngle;
protected double m_rightAscension;
protected double m_declination;
protected LocationElements g_polarLEs; // Polar Coord-System Elemts of Earth Variable inserted by Strickling
protected LocationElements m_polarLEs; // Polar Coord-System Heliocentric
protected LocationElements m_eclipticLEs; // Cartesian Coord-System
protected LocationElements m_equatorialLEs; // Cartesian Coord-System
protected LocationElements m_altAzLEs; // Cartesian Coord-System
private final static String NoInit = "Call PlanetData.calc() first.";
}
Ads help maintain this website.