public static double HeadingForLaunchInclination(CelestialBody body, double inclinationDegrees, double latitudeDegrees, double orbVel) { double cosDesiredSurfaceAngle = Math.Cos(inclinationDegrees * MathExtensions.Deg2Rad) / Math.Cos(latitudeDegrees * MathExtensions.Deg2Rad); if (Math.Abs(cosDesiredSurfaceAngle) > 1.0) { //If inclination < latitude, we get this case: the desired inclination is impossible if (Math.Abs(MuUtils.ClampDegrees180(inclinationDegrees)) < 90) { return(90); } else { return(270); } } else { double betaFixed = Math.Asin(cosDesiredSurfaceAngle); double velLaunchSite = body.Radius * body.angularVelocity.magnitude * Math.Cos(latitudeDegrees * MathExtensions.Deg2Rad); double vx = orbVel * Math.Sin(betaFixed) - velLaunchSite; double vy = orbVel * Math.Cos(betaFixed); double angle = MathExtensions.Rad2Deg * Math.Atan(vx / vy); if (inclinationDegrees < 0) { angle = 180 - angle; } return(MuUtils.ClampDegrees360(angle)); } }
//Originally by Zool, revised by The_Duck //Converts a true anomaly into an eccentric anomaly. //For elliptical orbits this returns a value between 0 and 2pi //For hyperbolic orbits the returned value can be any number. //NOTE: For a hyperbolic orbit, if a true anomaly is requested that does not exist (a true anomaly //past the true anomaly of the asymptote) then an ArgumentException is thrown public static double GetEccentricAnomalyAtTrueAnomaly(this Orbit o, double trueAnomaly) { double e = o.eccentricity; trueAnomaly = MuUtils.ClampDegrees360(trueAnomaly); trueAnomaly = trueAnomaly * (Math.PI / 180); if (e < 1) //elliptical orbits { double cosE = (e + Math.Cos(trueAnomaly)) / (1 + e * Math.Cos(trueAnomaly)); double sinE = Math.Sqrt(1 - (cosE * cosE)); if (trueAnomaly > Math.PI) { sinE *= -1; } return(MuUtils.ClampRadiansTwoPi(Math.Atan2(sinE, cosE))); } else //hyperbolic orbits { double coshE = (e + Math.Cos(trueAnomaly)) / (1 + e * Math.Cos(trueAnomaly)); if (coshE < 1) { throw new ArgumentException("OrbitExtensions.GetEccentricAnomalyAtTrueAnomaly: True anomaly of " + trueAnomaly + " radians is not attained by orbit with eccentricity " + o.eccentricity); } double E = MuUtils.Acosh(coshE); if (trueAnomaly > Math.PI) { E *= -1; } return(E); } }
//Gives the true anomaly at which o crosses the equator going southwards, if o is east-moving, //or northwards, if o is west-moving. //The returned value is always between 0 and 360. public static double DescendingNodeEquatorialTrueAnomaly(this Orbit o) { return(MuUtils.ClampDegrees360(o.AscendingNodeEquatorialTrueAnomaly() + 180)); }
//Gives the true anomaly (in a's orbit) at which a crosses its descending node //with b's orbit. //The returned value is always between 0 and 360. public static double DescendingNodeTrueAnomaly(this Orbit a, Orbit b) { return(MuUtils.ClampDegrees360(a.AscendingNodeTrueAnomaly(b) + 180)); }