// // Kerbal Engineer Redux // // Copyright (C) 2015 CYBUTEK // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // namespace KerbalEngineer.Flight.Readouts.Rendezvous { using System; using Extensions; using Helpers; public class RendezvousProcessor : IUpdatable, IUpdateRequest { private static readonly RendezvousProcessor instance = new RendezvousProcessor(); private Orbit originOrbit; private Orbit targetOrbit; /// /// Gets the target's altitude above its reference body. /// public static double AltitudeSeaLevel { get; private set; } /// /// Gets the angle from the origin position to the ascending node. /// public static double AngleToAscendingNode { get; private set; } /// /// Gets the angle from the origin position to the descending node. /// public static double AngleToDescendingNode { get; private set; } /// /// Gets the target's apoapsis above its reference body. /// public static double ApoapsisHeight { get; private set; } /// /// Gets the distance from the origin position to the target position. /// public static double Distance { get; private set; } /// /// Gets the current instance of the rendezvous processor. /// public static RendezvousProcessor Instance { get { return instance; } } /// /// Gets the difference in angle from the origin position to where it is most efficient to burn for an encounter. /// public static double InterceptAngle { get; private set; } /// /// Gets the orbital period of the target orbit. /// public static double OrbitalPeriod { get; private set; } /// /// Gets the target's periapsis above its reference body. /// public static double PeriapsisHeight { get; private set; } /// /// Gets the difference in angle from the origin position to the target position based on a common reference. /// public static double PhaseAngle { get; private set; } /// /// Gets the angular difference between the origin and target orbits. /// public static double RelativeInclination { get; private set; } /// /// Gets the relative orbital speed between the vessel and target. /// public static double RelativeSpeed { get; private set; } /// /// Gets the relative orbital velocity between the vessel and target. /// public static double RelativeVelocity { get; private set; } /// /// Gets the semi-major axis of the target orbit. /// public static double SemiMajorAxis { get; private set; } /// /// Gets the semi-minor axis of the target orbit. /// public static double SemiMinorAxis { get; private set; } /// /// Gets whether the details are ready to be shown. /// public static bool ShowDetails { get; private set; } /// /// Gets the target's time to apoapsis. /// public static double TimeToApoapsis { get; private set; } /// /// Gets the time it will take to reach the ascending node. /// public static double TimeToAscendingNode { get; private set; } /// /// Gets the time it will take to reach the descending node. /// public static double TimeToDescendingNode { get; private set; } /// /// Gets the target's time to periapsis. /// public static double TimeToPeriapsis { get; private set; } /// /// Gets and sets whether the updatable object should be updated. /// public bool UpdateRequested { get; set; } /// /// Request and update to calculate the details. /// public static void RequestUpdate() { instance.UpdateRequested = true; } /// /// Updates the details by recalculating if requested. /// public void Update() { if (FlightGlobals.fetch == null || FlightGlobals.fetch.VesselTarget == null || FlightGlobals.ActiveVessel == null || FlightGlobals.ActiveVessel.targetObject == null || FlightGlobals.ActiveVessel.targetObject.GetOrbit() == null || FlightGlobals.ship_orbit == null || FlightGlobals.ship_orbit.referenceBody == null) { ShowDetails = false; return; } ShowDetails = true; targetOrbit = FlightGlobals.fetch.VesselTarget.GetOrbit(); originOrbit = (FlightGlobals.ship_orbit.referenceBody == Planetarium.fetch.Sun || FlightGlobals.ship_orbit.referenceBody == FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody) ? FlightGlobals.ship_orbit : FlightGlobals.ship_orbit.referenceBody.orbit; RelativeInclination = originOrbit.GetRelativeInclination(targetOrbit); RelativeVelocity = FlightGlobals.ship_tgtSpeed; RelativeSpeed = FlightGlobals.ship_obtSpeed - targetOrbit.orbitalSpeed; PhaseAngle = originOrbit.GetPhaseAngle(targetOrbit); InterceptAngle = CalcInterceptAngle(); TimeToAscendingNode = originOrbit.GetTimeToVector(GetAscendingNode()); TimeToDescendingNode = originOrbit.GetTimeToVector(GetDescendingNode()); AngleToAscendingNode = originOrbit.GetAngleToVector(GetAscendingNode()); AngleToDescendingNode = originOrbit.GetAngleToVector(GetDescendingNode()); AltitudeSeaLevel = targetOrbit.altitude; ApoapsisHeight = targetOrbit.ApA; PeriapsisHeight = targetOrbit.PeA; TimeToApoapsis = targetOrbit.timeToAp; TimeToPeriapsis = targetOrbit.timeToPe; SemiMajorAxis = targetOrbit.semiMajorAxis; SemiMinorAxis = targetOrbit.semiMinorAxis; Distance = Vector3d.Distance(targetOrbit.pos, originOrbit.pos); OrbitalPeriod = targetOrbit.period; } private double CalcInterceptAngle() { double originRadius = (originOrbit.semiMinorAxis + originOrbit.semiMajorAxis) * 0.5; double targetRadius = (targetOrbit.semiMinorAxis + targetOrbit.semiMajorAxis) * 0.5; double angle = 180.0 * (1.0 - Math.Pow((originRadius + targetRadius) / (2.0 * targetRadius), 1.5)); angle = PhaseAngle - angle; return RelativeInclination < 90.0 ? AngleHelper.Clamp360(angle) : AngleHelper.Clamp360(360.0 - (180.0 - angle)); } private Vector3d GetAscendingNode() { return Vector3d.Cross(targetOrbit.GetOrbitNormal(), originOrbit.GetOrbitNormal()); } private Vector3d GetDescendingNode() { return Vector3d.Cross(originOrbit.GetOrbitNormal(), targetOrbit.GetOrbitNormal()); } } }