// Copyright 2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.android.stardroid.provider.ephemeris;
import android.util.Log;
import com.google.android.stardroid.util.Geometry;
import com.google.android.stardroid.util.MathUtil;
import com.google.android.stardroid.util.MiscUtil;
/**
* This class wraps the six parameters which define the path an object takes as
* it orbits the sun.
*
* The equations come from JPL's Solar System Dynamics site:
* http://ssd.jpl.nasa.gov/?planet_pos
*
* The original source for the calculations is based on the approximations described in:
* Van Flandern T. C., Pulkkinen, K. F. (1979): "Low-Precision Formulae for
* Planetary Positions", 1979, Astrophysical Journal Supplement Series, Vol. 41,
* pp. 391-411.
*
*
* @author Kevin Serafini
* @author Brent Bryan
*/
public class OrbitalElements {
private static String TAG = MiscUtil.getTag(OrbitalElements.class);
// calculation error
private final static float EPSILON = 1.0e-6f;
public final float distance; // Mean distance (AU)
public final float eccentricity; // Eccentricity of orbit
public final float inclination; // Inclination of orbit (AngleUtils.RADIANS)
public final float ascendingNode; // Longitude of ascending node (AngleUtils.RADIANS)
public final float perihelion; // Longitude of perihelion (AngleUtils.RADIANS)
public final float meanLongitude; // Mean longitude (AngleUtils.RADIANS)
public OrbitalElements(float d, float e, float i, float a, float p, float l) {
this.distance = d;
this.eccentricity = e;
this.inclination = i;
this.ascendingNode = a;
this.perihelion = p;
this.meanLongitude = l;
}
public float getAnomaly() {
return calculateTrueAnomaly(meanLongitude - perihelion, eccentricity);
}
// compute the true anomaly from mean anomaly using iteration
// m - mean anomaly in radians
// e - orbit eccentricity
// Return value is in radians.
private static float calculateTrueAnomaly(float m, float e) {
// initial approximation of eccentric anomaly
float e0 = m + e * MathUtil.sin(m) * (1.0f + e * MathUtil.cos(m));
float e1;
// iterate to improve accuracy
int counter = 0;
do {
e1 = e0;
e0 = e1 - (e1 - e * MathUtil.sin(e1) - m) / (1.0f - e * MathUtil.cos(e1));
if (counter++ > 100) {
Log.d(TAG, "Failed to converge! Exiting.");
Log.d(TAG, "e1 = " + e1 + ", e0 = " + e0);
Log.d(TAG, "diff = " + MathUtil.abs(e0 - e1));
break;
}
} while (MathUtil.abs(e0 - e1) > EPSILON);
// convert eccentric anomaly to true anomaly
float v =
2f * MathUtil.atan(MathUtil.sqrt((1 + e) / (1 - e))
* MathUtil.tan(0.5f * e0));
return Geometry.mod2pi(v);
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("Mean Distance: " + distance + " (AU)\n");
sb.append("Eccentricity: " + eccentricity + "\n");
sb.append("Inclination: " + inclination + " (AngleUtils.RADIANS)\n");
sb.append("Ascending Node: " + ascendingNode + " (AngleUtils.RADIANS)\n");
sb.append("Perihelion: " + perihelion + " (AngleUtils.RADIANS)\n");
sb.append("Mean Longitude: " + meanLongitude + " (AngleUtils.RADIANS)\n");
return sb.toString();
}
}