/// <summary>Compute static properties for orbit shape and speed</summary> public void ComputeStaticProperties() { orientation = Kepler.ComputeOrientation(argument, longitude, inclination); semiLatusRectum = Kepler.ComputeSemiLatusRectum(_periapsis, _eccentricity); semiMajorAxis = Kepler.ComputeSemiMajorAxis(_periapsis, _eccentricity); rate = Kepler.ComputeRate(_period, _limits.x * Deg2Rad, _limits.y * Deg2Rad); }
public void UpdateSimulation() { if (orbitDecay != 0) { orbit.periapsis += orbitDecay * Time.deltaTime * orbit.timeScale; if (orbit.periapsis <= 0) { //behaviour beyond this point is undefined, best not upset the Kraken ResetSimulation(); StopSimulation(); orbit.StopSimulation(); } else { orbit.period = Math.Sqrt( (periodOriginal * periodOriginal) * (orbit.periapsis * orbit.periapsis * orbit.periapsis) / (semiMajorAxisOriginal * semiMajorAxisOriginal * semiMajorAxisOriginal) ); } } if (apsidalPrecession != 0) { orbit.argument = Kepler.WrapAngle(orbit.argument - apsidalPrecession * Time.deltaTime * (float)orbit.timeScale, -180, 180); } }
/// <summary> /// Computes the position of a celestial body on it's orbit at a given time. /// </summary> /// <param name="time">Time offset relative to J2000 (1st January 2000) in years.</param> /// <returns>The position of the celestial body.</returns> public UnityEngine.Vector3 Position(float time) { var a = Elements.MajorRadius; var lambda = Elements.MeanLongitudeAtEpoch; var e = Elements.Eccentricity; var I = Elements.InclinationToElliptic / 180.0 * Math.PI; var omega = Elements.LongitudeOfPerihelion / 180.0 * Math.PI; var Omega = Elements.LongitudeOfAscendingNode / 180.0 * Math.PI; var T = Elements.OrbitalPeriod; var n = 2.0 * Math.PI / T; var theta = (lambda + omega) / n; var M = n * (time - theta); var E = Kepler.EccentricAnomaly(e, M); var Theta = 2.0 * Math.Atan(Math.Sqrt((1.0 + e) / (1.0 - e)) * Math.Tan(E / 2.0)); var r = a * (1.0 - e * Math.Cos(E)); var position = new UnityEngine.Vector3( Convert.ToSingle(r * (Math.Cos(Omega) * Math.Cos(omega + Theta) - Math.Sin(Omega) * Math.Sin(omega + Theta) * Math.Cos(I))), Convert.ToSingle(r * Math.Sin(omega + Theta) * Math.Sin(I)), Convert.ToSingle(r * (Math.Sin(Omega) * Math.Cos(omega + Theta) + Math.Cos(Omega) * Math.Sin(omega + Theta) * Math.Cos(I))) ); return(position); }
/// <summary>Compute dynamic properties that change over the anomaly</summary> /// <param name="M">The anomaly to evaluate properties at</param> public void ComputeDynamicProperties(double M) { eccentricAnomaly = Kepler.ComputeEccentricAnomaly(M, _eccentricity); trueAnomaly = Kepler.ComputeTrueAnomaly(eccentricAnomaly, _eccentricity); radius = Kepler.ComputeRadius(semiLatusRectum, _eccentricity, trueAnomaly); position = orientation * Kepler.ComputePosition(radius, trueAnomaly); velocity = orientation * Kepler.ComputeVelocity(_periapsis, radius, rate, eccentricAnomaly, trueAnomaly, _eccentricity); }
void OnDrawGizmosSelected() { //OnValidate should always be called before this, meaning appropriate values for properties are available //variables required Vector3[] path = new Vector3[51]; Vector3 periapsisV = orientation * Vector3.right * (float)_periapsis; Vector3 positionV = orientation * Kepler.ComputePosition(Kepler.ComputeRadius(semiLatusRectum, _eccentricity, trueAnomaly), trueAnomaly); //elliptical and circular //build list of vectors for path double step, lower, upper; double r; lower = Kepler.ComputeTrueAnomaly(Kepler.ComputeEccentricAnomaly(_limits.x * Deg2Rad, _eccentricity), _eccentricity); upper = Kepler.ComputeTrueAnomaly(Kepler.ComputeEccentricAnomaly(_limits.y * Deg2Rad, _eccentricity), _eccentricity); step = (upper - lower) / 50; for (int i = 0; i <= 50; i++) { r = Kepler.ComputeRadius(semiLatusRectum, _eccentricity, lower + i * step); path[i] = Kepler.ComputePosition(r, lower + i * step); } //Set the gizmos to draw in parent space Gizmos.matrix = (transform.parent)? transform.parent.localToWorldMatrix : Matrix4x4.identity; //draw the path of the orbit Gizmos.color = Color.cyan; for (int i = 0; i < 50; i++) { Gizmos.DrawLine(orientation * path[i], orientation * path[i + 1]); } //draw periapsis vector Gizmos.DrawLine(Vector3.zero, periapsisV); //draw position vector Gizmos.color = Color.blue; Gizmos.DrawLine(Vector3.zero, positionV); //draw velocity vector Gizmos.color = Color.magenta; Gizmos.DrawLine(positionV, positionV + velocity); }
void OnEnable() { if (orbit == null) { line.SetVertexCount(0); } else { double step, lower, upper, r; Matrix4x4 matrix = (transform.parent)? transform.parent.localToWorldMatrix : Matrix4x4.identity; line.SetVertexCount(segments + 1); upper = Kepler.ComputeTrueAnomaly(Kepler.ComputeEccentricAnomaly(orbit.limits.x * Deg2Rad, orbit.eccentricity), orbit.eccentricity); lower = Kepler.ComputeTrueAnomaly(Kepler.ComputeEccentricAnomaly(orbit.limits.y * Deg2Rad, orbit.eccentricity), orbit.eccentricity); step = (upper - lower) / segments; for (int i = 0; i < segments + 1; i++) { r = Kepler.ComputeRadius(orbit.semiLatusRectum, orbit.eccentricity, lower + step * i); line.SetPosition(i, matrix.MultiplyPoint(orbit.orientation * Kepler.ComputePosition(r, lower + step * i))); } } }
public void UpdateSimulation() { angle = Kepler.WrapAngle(angle + Time.deltaTime * rate * timeScale, 0, 2 * Math.PI); ComputeDynamicProperties(angle); transform.localRotation = rotation; }
public void ResetSimulation() { angle = Kepler.WrapAngle(meanAngle * Deg2Rad + startEpoch * rate, 0, 2 * Math.PI); }
/// <summary>Compute dynamic properties that change over the angle</summary> /// <param name="M">The angle to evaluate properties at</param> public void ComputeDynamicProperties(double angle) { rotation = Kepler.ComputeRotation(axis, angle / Deg2Rad); }
/// <summary>Computes static properties for rotational axis and speed</summary> public void ComputeStaticProperties() { axis = Kepler.ComputeAxis(_rightAscension, _declination); rate = Kepler.ComputeRate(_period, -Math.PI, Math.PI); }