/// <summary> /// Sets the true anomaly and updates all other anomalies. /// </summary> /// <param name="t">The t.</param> public void SetTrueAnomaly(double t) { if (!IsValidOrbit) { return; } t %= KeplerOrbitUtils.PI_2; if (Eccentricity < 1) { if (t < 0) { t += KeplerOrbitUtils.PI_2; } EccentricAnomaly = KeplerOrbitUtils.ConvertTrueToEccentricAnomaly(t, Eccentricity); MeanAnomaly = EccentricAnomaly - Eccentricity * Math.Sin(EccentricAnomaly); } else { EccentricAnomaly = KeplerOrbitUtils.ConvertTrueToEccentricAnomaly(t, Eccentricity); MeanAnomaly = Math.Sinh(EccentricAnomaly) * Eccentricity - EccentricAnomaly; } SetPositionByCurrentAnomaly(); SetVelocityByCurrentAnomaly(); }
/// <summary> /// Calculate eccentric anomaly in radians for point. /// </summary> /// <param name="point">Point in plane of elliptic shape.</param> /// <returns>Eccentric anomaly radians.</returns> public double GetEccentricAnomalyForPoint(Vector3d point) { var vector = point - Focus0; var trueAnomaly = Vector3d.Angle(vector, AxisMain) * KeplerOrbitUtils.Deg2Rad; if (KeplerOrbitUtils.DotProduct(vector, AxisSecondary) > 0) { trueAnomaly = KeplerOrbitUtils.PI_2 - trueAnomaly; } var result = KeplerOrbitUtils.ConvertTrueToEccentricAnomaly(trueAnomaly, Eccentricity); return(result); }
/// <summary> /// Gets the central position at true anomaly. /// </summary> /// <param name="trueAnomaly">The true anomaly.</param> /// <returns>Position relative to orbit center.</returns> /// <remarks> /// Note: central position is not same as focal position. /// </remarks> public Vector3d GetCentralPositionAtTrueAnomaly(double trueAnomaly) { double ecc = KeplerOrbitUtils.ConvertTrueToEccentricAnomaly(trueAnomaly, Eccentricity); return(GetCentralPositionAtEccentricAnomaly(ecc)); }
/// <summary> /// Calculates full orbit state from cartesian vectors: current body position, velocity, attractor mass, and gravConstant. /// </summary> public void CalculateOrbitStateFromOrbitalVectors() { MG = AttractorMass * GravConst; AttractorDistance = Position.magnitude; Vector3d angularMomentumVector = KeplerOrbitUtils.CrossProduct(Position, Velocity); OrbitNormal = angularMomentumVector.normalized; Vector3d eccVector; if (OrbitNormal.sqrMagnitude < 0.99) { OrbitNormal = KeplerOrbitUtils.CrossProduct(Position, EclipticUp).normalized; eccVector = new Vector3d(); } else { eccVector = KeplerOrbitUtils.CrossProduct(Velocity, angularMomentumVector) / MG - Position / AttractorDistance; } OrbitNormalDotEclipticNormal = KeplerOrbitUtils.DotProduct(OrbitNormal, EclipticNormal); FocalParameter = angularMomentumVector.sqrMagnitude / MG; Eccentricity = eccVector.magnitude; EnergyTotal = Velocity.sqrMagnitude - 2 * MG / AttractorDistance; SemiMinorAxisBasis = KeplerOrbitUtils.CrossProduct(angularMomentumVector, -eccVector).normalized; if (SemiMinorAxisBasis.sqrMagnitude < 0.99) { SemiMinorAxisBasis = KeplerOrbitUtils.CrossProduct(OrbitNormal, Position).normalized; } SemiMajorAxisBasis = KeplerOrbitUtils.CrossProduct(OrbitNormal, SemiMinorAxisBasis).normalized; if (Eccentricity < 1) { OrbitCompressionRatio = 1 - Eccentricity * Eccentricity; SemiMajorAxis = FocalParameter / OrbitCompressionRatio; SemiMinorAxis = SemiMajorAxis * Math.Sqrt(OrbitCompressionRatio); CenterPoint = -SemiMajorAxis * eccVector; Period = KeplerOrbitUtils.PI_2 * Math.Sqrt(Math.Pow(SemiMajorAxis, 3) / MG); Apoapsis = CenterPoint - SemiMajorAxisBasis * SemiMajorAxis; Periapsis = CenterPoint + SemiMajorAxisBasis * SemiMajorAxis; PeriapsisDistance = Periapsis.magnitude; ApoapsisDistance = Apoapsis.magnitude; TrueAnomaly = Vector3d.Angle(Position, SemiMajorAxisBasis) * KeplerOrbitUtils.Deg2Rad; if (KeplerOrbitUtils.DotProduct(KeplerOrbitUtils.CrossProduct(Position, -SemiMajorAxisBasis), OrbitNormal) < 0) { TrueAnomaly = KeplerOrbitUtils.PI_2 - TrueAnomaly; } EccentricAnomaly = KeplerOrbitUtils.ConvertTrueToEccentricAnomaly(TrueAnomaly, Eccentricity); MeanAnomaly = EccentricAnomaly - Eccentricity * Math.Sin(EccentricAnomaly); } else { OrbitCompressionRatio = Eccentricity * Eccentricity - 1; SemiMajorAxis = FocalParameter / OrbitCompressionRatio; SemiMinorAxis = SemiMajorAxis * Math.Sqrt(OrbitCompressionRatio); CenterPoint = SemiMajorAxis * eccVector; Period = double.PositiveInfinity; Apoapsis = new Vector3d(double.PositiveInfinity, double.PositiveInfinity, double.PositiveInfinity); Periapsis = CenterPoint - SemiMajorAxisBasis * (SemiMajorAxis); PeriapsisDistance = Periapsis.magnitude; ApoapsisDistance = double.PositiveInfinity; TrueAnomaly = Vector3d.Angle(Position, eccVector) * KeplerOrbitUtils.Deg2Rad; if (KeplerOrbitUtils.DotProduct(KeplerOrbitUtils.CrossProduct(Position, -SemiMajorAxisBasis), OrbitNormal) < 0) { TrueAnomaly = -TrueAnomaly; } EccentricAnomaly = KeplerOrbitUtils.ConvertTrueToEccentricAnomaly(TrueAnomaly, Eccentricity); MeanAnomaly = Math.Sinh(EccentricAnomaly) * Eccentricity - EccentricAnomaly; } }